mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-21 16:02:28 +00:00
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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user