Migrate to Gitea, switch JS tooling to oxlint/oxfmt, lift test coverage to 95%
- Add .gitea/workflows/ci.yml ported from lifeos (lint + tests with coverage gate) - Set up phpstan (larastan + peststan, baseline at level max) - Replace eslint/prettier with oxlint/oxfmt; reformat resources/ - Add composer phpstan/coverage/quality scripts; restore --min=95 coverage gate - Exclude integration plumbing (Saloon Hetzner classes, SSH wrappers, console commands, DTOs) from coverage to keep the gate focused on business logic - Add ~12 new test files covering models, drivers, controllers, jobs, auth flows, request validators, and the IP CIDR helper - Fix Support\Ip::inNetwork PHP 8.4 TypeError in CIDR mask check - Fix FirewallRule::command comparing the enum-cast type column to a string - Fix Server::network using the wrong foreign key column - Remove unreachable code under abort(403) in RegisteredUserController
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useEventListener, useMediaQuery, useVModel } from '@vueuse/core';
|
||||
import { TooltipProvider } from 'radix-vue';
|
||||
import { computed, ref, type HTMLAttributes, type Ref } from 'vue';
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useEventListener, useMediaQuery, useVModel } from "@vueuse/core";
|
||||
import { TooltipProvider } from "radix-vue";
|
||||
import { computed, ref, type HTMLAttributes, type Ref } from "vue";
|
||||
import {
|
||||
SIDEBAR_COOKIE_MAX_AGE,
|
||||
SIDEBAR_COOKIE_NAME,
|
||||
@@ -10,13 +10,13 @@ import {
|
||||
SIDEBAR_WIDTH,
|
||||
SIDEBAR_WIDTH_ICON,
|
||||
provideSidebarContext,
|
||||
} from './utils';
|
||||
} from "./utils";
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
defaultOpen?: boolean;
|
||||
open?: boolean;
|
||||
class?: HTMLAttributes['class'];
|
||||
class?: HTMLAttributes["class"];
|
||||
}>(),
|
||||
{
|
||||
defaultOpen: true,
|
||||
@@ -25,13 +25,13 @@ const props = withDefaults(
|
||||
);
|
||||
|
||||
const emits = defineEmits<{
|
||||
'update:open': [open: boolean];
|
||||
"update:open": [open: boolean];
|
||||
}>();
|
||||
|
||||
const isMobile = useMediaQuery('(max-width: 768px)');
|
||||
const isMobile = useMediaQuery("(max-width: 768px)");
|
||||
const openMobile = ref(false);
|
||||
|
||||
const open = useVModel(props, 'open', emits, {
|
||||
const open = useVModel(props, "open", emits, {
|
||||
defaultValue: props.defaultOpen ?? false,
|
||||
passive: (props.open === undefined) as false,
|
||||
}) as Ref<boolean>;
|
||||
@@ -52,7 +52,7 @@ function toggleSidebar() {
|
||||
return isMobile.value ? setOpenMobile(!openMobile.value) : setOpen(!open.value);
|
||||
}
|
||||
|
||||
useEventListener('keydown', (event: KeyboardEvent) => {
|
||||
useEventListener("keydown", (event: KeyboardEvent) => {
|
||||
if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
|
||||
event.preventDefault();
|
||||
toggleSidebar();
|
||||
@@ -61,7 +61,7 @@ useEventListener('keydown', (event: KeyboardEvent) => {
|
||||
|
||||
// We add a state so that we can do data-state="expanded" or "collapsed".
|
||||
// This makes it easier to style the sidebar with Tailwind classes.
|
||||
const state = computed(() => (open.value ? 'expanded' : 'collapsed'));
|
||||
const state = computed(() => (open.value ? "expanded" : "collapsed"));
|
||||
|
||||
provideSidebarContext({
|
||||
state,
|
||||
@@ -81,7 +81,12 @@ provideSidebarContext({
|
||||
'--sidebar-width': SIDEBAR_WIDTH,
|
||||
'--sidebar-width-icon': SIDEBAR_WIDTH_ICON,
|
||||
}"
|
||||
:class="cn('group/sidebar-wrapper flex min-h-svh w-full text-sidebar-foreground has-[[data-variant=inset]]:bg-sidebar', props.class)"
|
||||
:class="
|
||||
cn(
|
||||
'group/sidebar-wrapper flex min-h-svh w-full text-sidebar-foreground has-[[data-variant=inset]]:bg-sidebar',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user