feat(frontend): Add manual calendar button + add shortcuts (#1866)

* feat(frontend): Add manual calendar button + add shotcuts

* feat(frontend): rework calendar

* feat(frontend): revert changes

* feat(frontend): Set default date

* fix compile

* feat(frontend): fix focus

---------

Co-authored-by: Ruben Fiszel <ruben@rubenfiszel.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
This commit is contained in:
Faton Ramadani
2023-07-13 15:58:11 +02:00
committed by GitHub
parent 9172c18391
commit 350673ed8e
4 changed files with 168 additions and 8 deletions
@@ -91,7 +91,7 @@
'border border-gray-300 bg-white hover:bg-gray-100 focus:bg-gray-100 text-gray-700 hover:text-gray-800 focus:text-gray-800 focus:ring-gray-300',
contained:
'bg-white border-gray-300 hover:bg-gray-100 focus:bg-gray-100 text-gray-700 focus:ring-gray-300',
divider: 'divide-x divide-gray-100'
divider: 'divide-x divide-gray-200'
}
}
@@ -24,7 +24,7 @@
}
</script>
<Menu let:open as="div" class="relative hover:z-50 flex w-full h-full">
<Menu let:open as="div" class="relative hover:z-50 flex w-full h-full ">
<span use:popperRef>
<MenuButton
class={twMerge('h-full w-full flex flex-row gap-2 items-center', hasPadding ? 'px-2' : '')}
@@ -0,0 +1,70 @@
<script lang="ts">
import { ArrowRight, Calendar } from 'lucide-svelte'
import { createEventDispatcher } from 'svelte'
import { fade } from 'svelte/transition'
import { Button, Popup } from '..'
export let date: string | undefined
export let label: string
const dispatch = createEventDispatcher()
let value = date
let button: HTMLButtonElement
let input: HTMLInputElement
$: if (date && input) {
input.value = new Date(date).toISOString().slice(0, 16)
}
function save() {
dispatch('change', value)
input.blur()
}
function close() {
const elem = document.activeElement as HTMLElement
if (elem.blur) {
elem.blur()
}
}
</script>
<button
bind:this={button}
title="Open calendar picker"
class="absolute bottom-1 right-1 top-1 py-1 min-w-min !px-2 items-center text-gray-800 bg-white border rounded center-center hover:bg-gray-50 transition-all cursor-pointer"
aria-label="Open calendar picker"
on:click={() => {
input.focus()
}}
>
<Calendar size={14} />
</button>
<Popup
ref={button}
options={{ placement: 'top-start' }}
transition={fade}
wrapperClasses="!z-[1002]"
outerClasses="rounded shadow-xl bg-white border p-3"
closeOn={[]}
>
<label class="block text-gray-900">
<div class="pb-1 text-sm text-gray-600">{label}</div>
<div class="flex w-full">
<input type="datetime-local" bind:value class="!w-auto grow" bind:this={input} />
<Button
size="xs"
color="dark"
buttonType="button"
btnClasses="!p-1 !w-[34px] !ml-1"
aria-label="Save ID"
on:click={() => {
save()
close()
}}
>
<ArrowRight size={18} />
</Button>
</div>
</label>
</Popup>
@@ -23,6 +23,8 @@
import { openStore } from '$lib/components/jobs/JobPreview.svelte'
import { setQuery } from '$lib/navigation'
import Tooltip from '$lib/components/Tooltip.svelte'
import { RefreshCcw } from 'lucide-svelte'
import CalendarPicker from '$lib/components/common/calendarPicker/CalendarPicker.svelte'
let jobs: Job[] | undefined
let error: Error | undefined
@@ -195,6 +197,46 @@
let argError = ''
let resultError = ''
const manualDates = [
{
label: 'Last 30 seconds',
setMinMax: () => {
minTs = new Date(new Date().getTime() - 30 * 1000).toISOString()
maxTs = new Date().toISOString()
}
},
{
label: 'Last minute',
setMinMax: () => {
minTs = new Date(new Date().getTime() - 60 * 1000).toISOString()
maxTs = new Date().toISOString()
}
},
{
label: 'Last 5 minutes',
setMinMax: () => {
minTs = new Date(new Date().getTime() - 5 * 60 * 1000).toISOString()
maxTs = new Date().toISOString()
}
},
{
label: 'Last 30 minutes',
setMinMax: () => {
minTs = new Date(new Date().getTime() - 30 * 60 * 1000).toISOString()
maxTs = new Date().toISOString()
}
},
{
label: 'Last 24 hours',
setMinMax: () => {
minTs = new Date(new Date().getTime() - 24 * 60 * 60 * 1000).toISOString()
maxTs = new Date().toISOString()
}
}
]
let selectedManualDate = 0
</script>
<CenteredPage>
@@ -251,15 +293,63 @@
}}
/>
</div>
<div class="flex flex-row gap-x-2 w-full mb-2 mt-4">
<div class="relative w-full"
><span class="text-xs absolute -top-4">min datetime</span>
<input type="text" value={minTs ?? 'zoom x axis to set min (drag with ctrl)'} disabled />
<div class="flex flex-row gap-x-2 w-full mb-2 mt-8">
<div class="relative w-full">
<div class="flex gap-1 relative w-full">
<span class="text-xs absolute -top-4">Min datetime</span>
<input
type="text"
value={minTs ?? 'zoom x axis to set min (drag with ctrl)'}
disabled
/>
<CalendarPicker
date={minTs}
label="Min datetimes"
on:change={async ({ detail }) => {
minTs = new Date(detail).toISOString()
jobs = await fetchJobs(maxTs, minTs)
}}
/>
</div>
</div>
<div class="relative w-full"
><span class="text-xs absolute -top-4">max datetime</span>
<div class="relative w-full">
<span class="text-xs absolute -top-4">Max datetime</span>
<input type="text" value={maxTs ?? 'zoom x axis to set max'} disabled />
<CalendarPicker
date={maxTs}
label="Max datetimes"
on:change={async ({ detail }) => {
maxTs = new Date(detail).toISOString()
jobs = await fetchJobs(maxTs, minTs)
}}
/>
</div>
<Button
color="light"
size="xs2"
wrapperClasses="border-gray-200 border rounded-md"
on:click={() => {
manualDates[selectedManualDate].setMinMax()
loadJobs()
}}
dropdownItems={[
...manualDates.map((d, i) => ({
label: d.label,
onClick: () => {
selectedManualDate = i
d.setMinMax()
loadJobs()
}
}))
]}
>
<div class="flex flex-row items-center gap-2">
<RefreshCcw size={14} />
{manualDates[selectedManualDate].label}
</div>
</Button>
</div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-2 mb-2 w-full flex-wrap">
<div>