mirror of
https://github.com/Litlyx/litlyx
synced 2025-12-10 07:48:37 +01:00
implementing snapshots
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
|
||||
import CreateSnapshot from './dialog/CreateSnapshot.vue';
|
||||
|
||||
export type Entry = {
|
||||
label: string,
|
||||
@@ -36,6 +36,17 @@ const snapshotsItems = computed(() => {
|
||||
return snapshots.value as any[];
|
||||
})
|
||||
|
||||
|
||||
const { openDialogEx } = useCustomDialog();
|
||||
|
||||
function openSnapshotDialog() {
|
||||
openDialogEx(CreateSnapshot, {
|
||||
width: "20rem",
|
||||
height: "16rem",
|
||||
closable: false
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -59,7 +70,16 @@ const snapshotsItems = computed(() => {
|
||||
|
||||
<div class="px-4 w-full flex-col">
|
||||
|
||||
<div class="poppins text-[.8rem] mb-2 px-2"> Snapshots </div>
|
||||
<div class="flex mb-2 px-2 items-center justify-between">
|
||||
<div class="poppins text-[.8rem]">
|
||||
Snapshots
|
||||
</div>
|
||||
<div @click="openSnapshotDialog()"
|
||||
class="poppins text-[.8rem] px-2 rounded-lg outline outline-[2px] outline-lyx-widget-lighter cursor-pointer hover:bg-lyx-widget-lighter">
|
||||
<i class="far fa-plus"></i>
|
||||
Add
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<USelectMenu class="w-full" v-model="snapshot" :options="snapshotsItems">
|
||||
<template #label>
|
||||
|
||||
63
dashboard/components/DatePicker.vue
Normal file
63
dashboard/components/DatePicker.vue
Normal file
@@ -0,0 +1,63 @@
|
||||
<script setup lang="ts">
|
||||
import { DatePicker as VCalendarDatePicker } from 'v-calendar'
|
||||
import type { DatePickerDate, DatePickerRangeObject } from 'v-calendar/dist/types/src/use/datePicker'
|
||||
import 'v-calendar/dist/style.css'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: [Date, Object] as PropType<DatePickerDate | DatePickerRangeObject | null>,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:model-value', 'close'])
|
||||
|
||||
const date = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (value) => {
|
||||
emit('update:model-value', value)
|
||||
emit('close')
|
||||
}
|
||||
})
|
||||
|
||||
const attrs = {
|
||||
transparent: true,
|
||||
borderless: true,
|
||||
color: 'primary',
|
||||
'is-dark': { selector: 'html', darkClass: 'dark' },
|
||||
'first-day-of-week': 2,
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCalendarDatePicker v-if="date && (typeof date === 'object')" v-model.range="date" :columns="2" v-bind="{ ...attrs, ...$attrs }" />
|
||||
<VCalendarDatePicker v-else v-model="date" v-bind="{ ...attrs, ...$attrs }" />
|
||||
</template>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--vc-gray-50: rgb(var(--color-gray-50));
|
||||
--vc-gray-100: rgb(var(--color-gray-100));
|
||||
--vc-gray-200: rgb(var(--color-gray-200));
|
||||
--vc-gray-300: rgb(var(--color-gray-300));
|
||||
--vc-gray-400: rgb(var(--color-gray-400));
|
||||
--vc-gray-500: rgb(var(--color-gray-500));
|
||||
--vc-gray-600: rgb(var(--color-gray-600));
|
||||
--vc-gray-700: rgb(var(--color-gray-700));
|
||||
--vc-gray-800: rgb(var(--color-gray-800));
|
||||
--vc-gray-900: rgb(var(--color-gray-900));
|
||||
}
|
||||
|
||||
.vc-primary {
|
||||
--vc-accent-50: rgb(var(--color-primary-50));
|
||||
--vc-accent-100: rgb(var(--color-primary-100));
|
||||
--vc-accent-200: rgb(var(--color-primary-200));
|
||||
--vc-accent-300: rgb(var(--color-primary-300));
|
||||
--vc-accent-400: rgb(var(--color-primary-400));
|
||||
--vc-accent-500: rgb(var(--color-primary-500));
|
||||
--vc-accent-600: rgb(var(--color-primary-600));
|
||||
--vc-accent-700: rgb(var(--color-primary-700));
|
||||
--vc-accent-800: rgb(var(--color-primary-800));
|
||||
--vc-accent-900: rgb(var(--color-primary-900));
|
||||
}
|
||||
</style>
|
||||
89
dashboard/components/dialog/CreateSnapshot.vue
Normal file
89
dashboard/components/dialog/CreateSnapshot.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<script lang="ts" setup>
|
||||
|
||||
const { closeDialog } = useCustomDialog();
|
||||
|
||||
import { sub, format, isSameDay, type Duration } from 'date-fns'
|
||||
|
||||
const ranges = [
|
||||
{ label: 'Last 7 days', duration: { days: 7 } },
|
||||
{ label: 'Last 14 days', duration: { days: 14 } },
|
||||
{ label: 'Last 30 days', duration: { days: 30 } },
|
||||
{ label: 'Last 3 months', duration: { months: 3 } },
|
||||
{ label: 'Last 6 months', duration: { months: 6 } },
|
||||
{ label: 'Last year', duration: { years: 1 } }
|
||||
]
|
||||
const selected = ref({ start: sub(new Date(), { days: 14 }), end: new Date() })
|
||||
|
||||
function isRangeSelected(duration: Duration) {
|
||||
return isSameDay(selected.value.start, sub(new Date(), duration)) && isSameDay(selected.value.end, new Date())
|
||||
}
|
||||
|
||||
function selectRange(duration: Duration) {
|
||||
selected.value = { start: sub(new Date(), duration), end: new Date() }
|
||||
}
|
||||
|
||||
const currentColor = ref<string>("");
|
||||
|
||||
const colorpicker = ref<HTMLInputElement | null>(null);
|
||||
|
||||
function showColorPicker() {
|
||||
colorpicker.value?.click();
|
||||
}
|
||||
|
||||
function onColorChange() {
|
||||
currentColor.value = colorpicker.value?.value || '#000000';
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full h-full flex flex-col">
|
||||
|
||||
<div class="poppins text-center">
|
||||
Create a snapshot
|
||||
</div>
|
||||
|
||||
<div class="mt-10 flex items-center gap-2">
|
||||
<div :style="`background-color: ${currentColor};`" @click="showColorPicker" class="w-6 h-6 rounded-full aspect-[1/1] relative">
|
||||
<input @input="onColorChange" ref="colorpicker" class="relative w-0 h-0 z-[-100]" type="color">
|
||||
</div>
|
||||
<div class="grow">
|
||||
<input placeholder="Snapshot name" class="px-4 py-2 w-full rounded-lg bg-lyx-widget-light" type="text">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 justify-center flex w-full">
|
||||
|
||||
<UPopover :popper="{ placement: 'bottom' }">
|
||||
<UButton icon="i-heroicons-calendar-days-20-solid">
|
||||
{{ selected.start.toLocaleDateString() }} - {{ selected.end.toLocaleDateString() }}
|
||||
</UButton>
|
||||
<template #panel="{ close }">
|
||||
<div class="flex items-center sm:divide-x divide-gray-200 dark:divide-gray-800">
|
||||
<div class="hidden sm:flex flex-col py-4">
|
||||
<UButton v-for="(range, index) in ranges" :key="index" :label="range.label" color="gray"
|
||||
variant="ghost" class="rounded-none px-6"
|
||||
:class="[isRangeSelected(range.duration) ? 'bg-gray-100 dark:bg-gray-800' : 'hover:bg-gray-50 dark:hover:bg-gray-800/50']"
|
||||
truncate @click="selectRange(range.duration)" />
|
||||
</div>
|
||||
|
||||
<DatePicker v-model="selected" @close="close" />
|
||||
</div>
|
||||
</template>
|
||||
</UPopover>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="grow"></div>
|
||||
<div class="flex items-center justify-around">
|
||||
<div @click="closeDialog()">
|
||||
Cancel
|
||||
</div>
|
||||
<div @click="closeDialog()">
|
||||
Confirm
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user