fixes in DeviceCertificats and DeviceTasks dialogs

This commit is contained in:
tdv
2025-12-04 15:08:28 +02:00
parent f8f099cccc
commit 50850897c0
15 changed files with 296 additions and 38 deletions

View File

@@ -18,7 +18,7 @@
"hls.js": "^1.6.13",
"leaflet": "^1.9.4",
"lucide-vue-next": "^0.525.0",
"reka-ui": "^2.5.0",
"reka-ui": "^2.6.1",
"tailwind-merge": "^3.3.1",
"tailwindcss": "^4.1.11",
"tw-animate-css": "^1.3.6",
@@ -2462,9 +2462,9 @@
"license": "MIT"
},
"node_modules/reka-ui": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.5.0.tgz",
"integrity": "sha512-81aMAmJeVCy2k0E6x7n1kypDY6aM1ldLis5+zcdV1/JtoAlSDck5OBsyLRJU9CfgbrQp1ImnRnBSmC4fZ2fkZQ==",
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.6.1.tgz",
"integrity": "sha512-XK7cJDQoNuGXfCNzBBo/81Yg/OgjPwvbabnlzXG2VsdSgNsT6iIkuPBPr+C0Shs+3bb0x0lbPvgQAhMSCKm5Ww==",
"license": "MIT",
"dependencies": {
"@floating-ui/dom": "^1.6.13",

View File

@@ -19,7 +19,7 @@
"hls.js": "^1.6.13",
"leaflet": "^1.9.4",
"lucide-vue-next": "^0.525.0",
"reka-ui": "^2.5.0",
"reka-ui": "^2.6.1",
"tailwind-merge": "^3.3.1",
"tailwindcss": "^4.1.11",
"tw-animate-css": "^1.3.6",

View File

@@ -9,22 +9,24 @@ export const buttonVariants = cva(
variants: {
variant: {
default:
"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
"bg-primary text-primary-foreground hover:bg-primary/90",
destructive:
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
outline:
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
secondary:
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost:
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2 has-[>svg]:px-3",
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
icon: "size-9",
"default": "h-9 px-4 py-2 has-[>svg]:px-3",
"sm": "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
"lg": "h-10 rounded-md px-6 has-[>svg]:px-4",
"icon": "size-9",
"icon-sm": "size-8",
"icon-lg": "size-10",
},
},
defaultVariants: {
@@ -33,5 +35,4 @@ export const buttonVariants = cva(
},
},
)
export type ButtonVariants = VariantProps<typeof buttonVariants>

View File

@@ -0,0 +1,26 @@
<script setup lang="ts">
import type { PaginationRootEmits, PaginationRootProps } from "reka-ui"
import type { HTMLAttributes } from "vue"
import { reactiveOmit } from "@vueuse/core"
import { PaginationRoot, useForwardPropsEmits } from "reka-ui"
import { cn } from "@/lib/utils"
const props = defineProps<PaginationRootProps & {
class?: HTMLAttributes["class"]
}>()
const emits = defineEmits<PaginationRootEmits>()
const delegatedProps = reactiveOmit(props, "class")
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>
<template>
<PaginationRoot
v-slot="slotProps"
data-slot="pagination"
v-bind="forwarded"
:class="cn('mx-auto flex w-full justify-center', props.class)"
>
<slot v-bind="slotProps" />
</PaginationRoot>
</template>

View File

@@ -0,0 +1,22 @@
<script setup lang="ts">
import type { PaginationListProps } from "reka-ui"
import type { HTMLAttributes } from "vue"
import { reactiveOmit } from "@vueuse/core"
import { PaginationList } from "reka-ui"
import { cn } from "@/lib/utils"
const props = defineProps<PaginationListProps & { class?: HTMLAttributes["class"] }>()
const delegatedProps = reactiveOmit(props, "class")
</script>
<template>
<PaginationList
v-slot="slotProps"
data-slot="pagination-content"
v-bind="delegatedProps"
:class="cn('flex flex-row items-center gap-1', props.class)"
>
<slot v-bind="slotProps" />
</PaginationList>
</template>

View File

@@ -0,0 +1,25 @@
<script setup lang="ts">
import type { PaginationEllipsisProps } from "reka-ui"
import type { HTMLAttributes } from "vue"
import { reactiveOmit } from "@vueuse/core"
import { MoreHorizontal } from "lucide-vue-next"
import { PaginationEllipsis } from "reka-ui"
import { cn } from "@/lib/utils"
const props = defineProps<PaginationEllipsisProps & { class?: HTMLAttributes["class"] }>()
const delegatedProps = reactiveOmit(props, "class")
</script>
<template>
<PaginationEllipsis
data-slot="pagination-ellipsis"
v-bind="delegatedProps"
:class="cn('flex size-9 items-center justify-center', props.class)"
>
<slot>
<MoreHorizontal class="size-4" />
<span class="sr-only">More pages</span>
</slot>
</PaginationEllipsis>
</template>

View File

@@ -0,0 +1,33 @@
<script setup lang="ts">
import type { PaginationFirstProps } from "reka-ui"
import type { HTMLAttributes } from "vue"
import type { ButtonVariants } from '@/components/ui/button'
import { reactiveOmit } from "@vueuse/core"
import { ChevronLeftIcon } from "lucide-vue-next"
import { PaginationFirst, useForwardProps } from "reka-ui"
import { cn } from "@/lib/utils"
import { buttonVariants } from '@/components/ui/button'
const props = withDefaults(defineProps<PaginationFirstProps & {
size?: ButtonVariants["size"]
class?: HTMLAttributes["class"]
}>(), {
size: "default",
})
const delegatedProps = reactiveOmit(props, "class", "size")
const forwarded = useForwardProps(delegatedProps)
</script>
<template>
<PaginationFirst
data-slot="pagination-first"
:class="cn(buttonVariants({ variant: 'ghost', size }), 'gap-1 px-2.5 sm:pr-2.5', props.class)"
v-bind="forwarded"
>
<slot>
<ChevronLeftIcon />
<span class="hidden sm:block">First</span>
</slot>
</PaginationFirst>
</template>

View File

@@ -0,0 +1,34 @@
<script setup lang="ts">
import type { PaginationListItemProps } from "reka-ui"
import type { HTMLAttributes } from "vue"
import type { ButtonVariants } from '@/components/ui/button'
import { reactiveOmit } from "@vueuse/core"
import { PaginationListItem } from "reka-ui"
import { cn } from "@/lib/utils"
import { buttonVariants } from '@/components/ui/button'
const props = withDefaults(defineProps<PaginationListItemProps & {
size?: ButtonVariants["size"]
class?: HTMLAttributes["class"]
isActive?: boolean
}>(), {
size: "icon",
})
const delegatedProps = reactiveOmit(props, "class", "size", "isActive")
</script>
<template>
<PaginationListItem
data-slot="pagination-item"
v-bind="delegatedProps"
:class="cn(
buttonVariants({
variant: isActive ? 'outline' : 'ghost',
size,
}),
props.class)"
>
<slot />
</PaginationListItem>
</template>

View File

@@ -0,0 +1,33 @@
<script setup lang="ts">
import type { PaginationLastProps } from "reka-ui"
import type { HTMLAttributes } from "vue"
import type { ButtonVariants } from '@/components/ui/button'
import { reactiveOmit } from "@vueuse/core"
import { ChevronRightIcon } from "lucide-vue-next"
import { PaginationLast, useForwardProps } from "reka-ui"
import { cn } from "@/lib/utils"
import { buttonVariants } from '@/components/ui/button'
const props = withDefaults(defineProps<PaginationLastProps & {
size?: ButtonVariants["size"]
class?: HTMLAttributes["class"]
}>(), {
size: "default",
})
const delegatedProps = reactiveOmit(props, "class", "size")
const forwarded = useForwardProps(delegatedProps)
</script>
<template>
<PaginationLast
data-slot="pagination-last"
:class="cn(buttonVariants({ variant: 'ghost', size }), 'gap-1 px-2.5 sm:pr-2.5', props.class)"
v-bind="forwarded"
>
<slot>
<span class="hidden sm:block">Last</span>
<ChevronRightIcon />
</slot>
</PaginationLast>
</template>

View File

@@ -0,0 +1,33 @@
<script setup lang="ts">
import type { PaginationNextProps } from "reka-ui"
import type { HTMLAttributes } from "vue"
import type { ButtonVariants } from '@/components/ui/button'
import { reactiveOmit } from "@vueuse/core"
import { ChevronRightIcon } from "lucide-vue-next"
import { PaginationNext, useForwardProps } from "reka-ui"
import { cn } from "@/lib/utils"
import { buttonVariants } from '@/components/ui/button'
const props = withDefaults(defineProps<PaginationNextProps & {
size?: ButtonVariants["size"]
class?: HTMLAttributes["class"]
}>(), {
size: "default",
})
const delegatedProps = reactiveOmit(props, "class", "size")
const forwarded = useForwardProps(delegatedProps)
</script>
<template>
<PaginationNext
data-slot="pagination-next"
:class="cn(buttonVariants({ variant: 'ghost', size }), 'gap-1 px-2.5 sm:pr-2.5', props.class)"
v-bind="forwarded"
>
<slot>
<span class="hidden sm:block">Next</span>
<ChevronRightIcon />
</slot>
</PaginationNext>
</template>

View File

@@ -0,0 +1,33 @@
<script setup lang="ts">
import type { PaginationPrevProps } from "reka-ui"
import type { HTMLAttributes } from "vue"
import type { ButtonVariants } from '@/components/ui/button'
import { reactiveOmit } from "@vueuse/core"
import { ChevronLeftIcon } from "lucide-vue-next"
import { PaginationPrev, useForwardProps } from "reka-ui"
import { cn } from "@/lib/utils"
import { buttonVariants } from '@/components/ui/button'
const props = withDefaults(defineProps<PaginationPrevProps & {
size?: ButtonVariants["size"]
class?: HTMLAttributes["class"]
}>(), {
size: "default",
})
const delegatedProps = reactiveOmit(props, "class", "size")
const forwarded = useForwardProps(delegatedProps)
</script>
<template>
<PaginationPrev
data-slot="pagination-previous"
:class="cn(buttonVariants({ variant: 'ghost', size }), 'gap-1 px-2.5 sm:pr-2.5', props.class)"
v-bind="forwarded"
>
<slot>
<ChevronLeftIcon />
<span class="hidden sm:block">Previous</span>
</slot>
</PaginationPrev>
</template>

View File

@@ -0,0 +1,8 @@
export { default as Pagination } from "./Pagination.vue"
export { default as PaginationContent } from "./PaginationContent.vue"
export { default as PaginationEllipsis } from "./PaginationEllipsis.vue"
export { default as PaginationFirst } from "./PaginationFirst.vue"
export { default as PaginationItem } from "./PaginationItem.vue"
export { default as PaginationLast } from "./PaginationLast.vue"
export { default as PaginationNext } from "./PaginationNext.vue"
export { default as PaginationPrevious } from "./PaginationPrevious.vue"

View File

@@ -102,7 +102,7 @@ function close() {
</DialogDescription>
</div>
<div class="flex gap-2">
<div class="flex gap-2 pt-8">
<Button variant="outline" :disabled="loading || !guid" @click="loadCerts">
{{ loading ? 'Loading' : 'Refresh' }}
</Button>
@@ -117,11 +117,13 @@ function close() {
</div>
<div v-else>
<div class="flex-1 min-h-0 pb-2">
<DataTableNoCheckboxScroll
:columns="columns"
:data="certs"
minTableWidth="min-w-[900px]"
/>
minTableWidth="min-w-[900px]" />
</div>
</div>
<DialogFooter>

View File

@@ -100,17 +100,22 @@ const task_columns: ColumnDef<TaskDto, any>[] = [
<template>
<Dialog :open="props.modelValue" @update:open="(v: boolean) => emit('update:modelValue', v)">
<DialogContent class="sm:min-w-[1200px] max-h-[80vh] p-0 flex flex-col">
<DialogHeader class="flex flex-row items-center justify-between gap-4">
<DialogContent class="sm:min-w-[1000px]">
<DialogHeader>
<div class="flex items-center justify-between">
<div>
<DialogTitle>Tasks</DialogTitle>
<DialogDescription>{{ props.device?.guid }}</DialogDescription>
<DialogDescription class="mt-1 break-all">
{{ props.device?.guid }}
</DialogDescription>
</div>
<div class="flex gap-2">
<div class="flex gap-2 pt-8">
<Button variant="outline" :disabled="loading || !props.device?.guid" @click="fetchTasks">
{{ loading ? 'Loading' : 'Refresh' }}
</Button>
</div>
</div>
</DialogHeader>
<div v-if="error" class="text-sm text-red-600 mb-3">{{ error }}</div>
@@ -120,8 +125,11 @@ const task_columns: ColumnDef<TaskDto, any>[] = [
</div>
<div v-else>
<!-- SCROLLABLE MIDDLE: flex-1 + min-h-0 so child can overflow -->
<div class="flex-1 min-h-0 px-6 pb-4">
<DataTableNoCheckboxScroll :columns="task_columns" :data="tasks" minTableWidth="min-w-[800px]" />
<div class="flex-1 min-h-0 pb-2">
<DataTableNoCheckboxScroll
:columns="task_columns"
:data="tasks"
minTableWidth="min-w-[900px]" />
</div>
</div>

View File

@@ -7,7 +7,7 @@
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*","src/types/**/*"]
"@/*": ["./src/*","src/types/*"]
}
}
}