Rework to use marbas and authentik instead of poketbase (#1)

Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
2024-05-17 23:00:52 +02:00
parent 9fb78329cc
commit 717eaa6ed8
47 changed files with 2306 additions and 1049 deletions

View File

@@ -0,0 +1,59 @@
<script setup lang="ts">
import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/vue/24/outline';
import { vOnClickOutside } from '@vueuse/components';
import { useEventListener } from '@vueuse/core';
import { ref } from 'vue';
const isOpen = ref(false);
useEventListener('keyup', e => {
if (e.key === 'Escape') {
isOpen.value = false;
}
});
</script>
<template>
<div class="dropdown" :class="{'dropdown-open': isOpen, 'dropdown-close': !isOpen}" v-on-click-outside="() => isOpen = false">
<button @click="isOpen = !isOpen">
<slot name="button" />
<Transition name="flip">
<ChevronDownIcon v-if="!isOpen" class="chevron" />
<ChevronUpIcon v-else class="chevron" />
</Transition>
</button>
<Transition name="fade">
<div v-if="isOpen" class="relative">
<div class="z-10 divide-y rounded-b-md absolute">
<slot />
</div>
</div>
</Transition>
</div>
</template>
<style scoped lang="postcss">
.chevron {
@apply w-4 h-4 ms-1;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
.fade-enter-active, .fade-leave-active {
@apply transition-opacity;
}
.flip-enter-from, .flip-leave-to {
transform: rotate(180deg);
}
.flip-enter-active {
@apply transition-transform;
}
.flip-leave-active {
display: none;
}
</style>

View File

@@ -54,7 +54,7 @@ useEventListener('keyup', e => {
}
.fade-enter-active, .fade-leave-active {
transition: opacity 100ms ease-out;
@apply transition-opacity;
}
</style>

View File

@@ -1,4 +1,5 @@
export { default as ClipboardButton } from './ClipboardButton.vue';
export { default as Dropdown } from './Dropdown.vue';
export { default as LoadingSpinner } from './LoadingSpinner.vue';
export { default as Modal } from './Modal.vue';
export { default as SliderCheckbox } from './SliderCheckbox.vue';

View File

@@ -35,7 +35,7 @@ th {
@apply relative h-8 pe-3;
}
span.asc, span.desc {
@apply absolute end-1 cursor-pointer text-xs;
@apply absolute end-1 cursor-pointer text-xs transition-opacity;
}
span.asc {
@apply top-0.5;

View File

@@ -0,0 +1,44 @@
import { describe, expect, test } from 'vitest'
import { ref } from 'vue'
import { useSort } from './sort'
describe('useSort', () => {
const array = ref([{ key1: 'b', key2: 'a' }, { key1: 'a', key2: 'b' }])
test('Returns expected properties with default options', () => {
const { sortedArray, headerProps, showColumn } = useSort(array)
expect(sortedArray).toBeDefined()
expect(headerProps).toBeDefined()
expect(showColumn).toBeDefined()
})
test('Returns expected properties with custom options', () => {
const { sortedArray, headerProps, showColumn } = useSort(array, { defaultSortKey: 'key1', defaultSortDirection: 'asc' })
expect(sortedArray.value[0].key1).toBe('a')
expect(headerProps.value.currentSortKey).toBe('key1')
expect(headerProps.value.sortDirection).toBe('asc')
expect(showColumn('key1')).toBe(true)
})
test('Sorts array in ascending order', () => {
const { sortedArray, headerProps } = useSort(array, { defaultSortKey: 'key1', defaultSortDirection: 'asc' })
headerProps.value.onSort('key1', 'asc')
expect(sortedArray.value[0].key1).toBe('a')
})
test('Sorts array in descending order', () => {
const { sortedArray, headerProps } = useSort(array, { defaultSortKey: 'key1', defaultSortDirection: 'desc' })
headerProps.value.onSort('key1', 'desc')
expect(sortedArray.value[0].key1).toBe('b')
})
test('Hides ignored columns', () => {
const { showColumn } = useSort(array, { ignoredColums: ['key1'] })
expect(showColumn('key1')).toBe(false)
})
})

View File

@@ -16,7 +16,8 @@ export const useSort = <T>(array: MaybeRefOrGetter<T[]>, options?: UseSortOption
};
const showColumn = (sortKey: string) => !toValue(options?.ignoredColums)?.includes(sortKey);
const headerProps = computed(() => ({
onSort: sortBy, showColumn,
onSort: sortBy,
showColumn,
currentSortKey: sortKey.value,
sortDirection: sortDirection.value
}));