Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions app/components/editor/EditorWidgetSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,18 @@ function handleSave() {
</template>

<template v-if="widget.kind === 'clock'">
<UFormField label="Size">
<USelect
:model-value="(localOptions.size as string) || 'md'"
:items="[
{ label: 'Small', value: 'sm' },
{ label: 'Medium', value: 'md' },
{ label: 'Large', value: 'lg' },
{ label: 'Extra Large', value: 'xl' }
]"
@update:model-value="localOptions.size = $event"
/>
</UFormField>
<USwitch
:model-value="(localOptions.format24h as boolean)"
label="24-hour format"
Expand Down
5 changes: 4 additions & 1 deletion app/components/editor/IconBrowserCustom.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const emit = defineEmits<{

const open = defineModel<boolean>('open', { default: false })

const isMobile = useMediaQuery('(max-width: 768px)')

const toast = useToast()
const searchQuery = ref('')
const selectedIcon = ref('')
Expand Down Expand Up @@ -66,7 +68,8 @@ async function deleteIcon(filename: string) {
<template>
<UModal
v-model:open="open"
fullscreen
:fullscreen="isMobile"
:ui="{ content: 'sm:max-w-3xl sm:h-[80vh]' }"
title="Custom Icons"
>
<template #body>
Expand Down
5 changes: 4 additions & 1 deletion app/components/editor/IconBrowserIconify.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const emit = defineEmits<{

const open = defineModel<boolean>('open', { default: false })

const isMobile = useMediaQuery('(max-width: 768px)')

const searchQuery = ref('')
const activeCollection = ref('lucide')
const selectedIcon = ref('')
Expand Down Expand Up @@ -117,7 +119,8 @@ function confirm() {
<template>
<UModal
v-model:open="open"
fullscreen
:fullscreen="isMobile"
:ui="{ content: 'sm:max-w-4xl sm:h-[80vh]' }"
title="Browse Icons"
>
<template #body>
Expand Down
23 changes: 19 additions & 4 deletions app/components/plugins/HealthDot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,28 @@ const tooltip = computed(() => {
? `Offline (HTTP ${result.value.status})`
: 'Offline (unreachable)'
})

const showLatency = computed(() => Boolean(props.config.showLatency))

const latencyText = computed(() => {
if (!showLatency.value) return ''
if (result.value.loading) return ''
if (!result.value.online) return ''
return `${result.value.latency}ms`
})
</script>

<template>
<UTooltip :text="tooltip">
<span
class="block size-3 rounded-full ring-2 ring-white dark:ring-gray-900"
:class="dotColor"
/>
<div class="inline-flex items-center gap-1.5">
<span
class="block size-3 rounded-full ring-2 ring-white dark:ring-gray-900"
:class="dotColor"
/>
<span
v-if="latencyText"
class="text-xs font-medium text-muted tabular-nums"
>{{ latencyText }}</span>
</div>
</UTooltip>
</template>
10 changes: 10 additions & 0 deletions app/components/plugins/HealthDotSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ const intervalSeconds = computed({
get: () => (config.value.intervalSeconds as number) || 30,
set: (val: number) => { config.value = { ...config.value, intervalSeconds: val } }
})

const showLatency = computed({
get: () => Boolean(config.value.showLatency),
set: (val: boolean) => { config.value = { ...config.value, showLatency: val } }
})
</script>

<template>
Expand All @@ -33,5 +38,10 @@ const intervalSeconds = computed({
:step="10"
/>
</UFormField>
<USwitch
v-model="showLatency"
label="Show response time"
description="Display latency in ms next to the status dot"
/>
</div>
</template>
31 changes: 28 additions & 3 deletions app/components/widgets/ClockWidget.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,49 @@ const timeFormat = computed(() => {

const time = useDateFormat(now, timeFormat)
const date = useDateFormat(now, 'dddd, MMMM D, YYYY')

const timeSizeClass = computed(() => {
switch (props.options.size) {
case 'sm': return 'text-2xl'
case 'lg': return 'text-6xl'
case 'xl': return 'text-8xl'
default: return 'text-4xl'
}
})

const dateSizeClass = computed(() => {
switch (props.options.size) {
case 'sm': return 'text-sm'
case 'lg': return 'text-xl'
case 'xl': return 'text-2xl'
default: return 'text-base'
}
})
</script>

<template>
<ClientOnly>
<div class="text-center">
<p class="text-2xl font-mono font-bold tabular-nums">
<p
class="font-mono font-bold tabular-nums"
:class="timeSizeClass"
>
{{ time }}
</p>
<p
v-if="options.showDate"
class="text-sm text-dimmed mt-1"
class="text-dimmed mt-1"
:class="dateSizeClass"
>
{{ date }}
</p>
</div>
<template #fallback>
<div class="text-center">
<p class="text-2xl font-mono font-bold tabular-nums">
<p
class="font-mono font-bold tabular-nums"
:class="timeSizeClass"
>
&nbsp;
</p>
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/components/widgets/ServiceLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const linkAttrs = computed(() => {
<component
:is="isEditing ? 'div' : 'a'"
v-bind="linkAttrs"
class="flex items-center gap-3 min-w-0"
class="flex items-center gap-4 min-w-0"
>
<div
v-if="options.iconBackground"
Expand Down
3 changes: 2 additions & 1 deletion app/components/widgets/WidgetWrapper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ function pluginsAt(position: string) {
</div>
<div
v-if="pluginsAt('top-right').length"
class="absolute top-2 right-2 flex gap-1"
class="absolute top-2 flex gap-1"
:class="isEditing ? 'right-12' : 'right-2'"
>
<PluginSlot
v-for="p in pluginsAt('top-right')"
Expand Down
7 changes: 4 additions & 3 deletions app/composables/useWidgetRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ const widgetDefinitions: WidgetDefinition[] = [
icon: 'i-lucide-clock',
description: 'Shows current date and time',
defaultOptions: {
format24h: false,
showSeconds: true,
showDate: true
format24h: true,
showSeconds: false,
showDate: true,
size: 'md'
}
},
{
Expand Down
5 changes: 3 additions & 2 deletions app/plugins/health-check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ export default defineNuxtPlugin(() => {
id: 'health-check',
label: 'Health Check',
icon: 'i-lucide-activity',
defaultPosition: 'top-left',
defaultPosition: 'top-right',
defaultConfig: {
intervalSeconds: 30
intervalSeconds: 30,
showLatency: false
},
compatibleWith: ['service-link'],
component: HealthDot,
Expand Down
5 changes: 3 additions & 2 deletions server/plugins/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ const DEFAULT_BOARD: Board = {
kind: 'clock',
span: 1,
options: {
format24h: false,
format24h: true,
showSeconds: false,
showDate: true
showDate: true,
size: 'md'
},
plugins: {}
},
Expand Down
1 change: 1 addition & 0 deletions shared/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export interface ClockOptions {
format24h: boolean
showSeconds: boolean
showDate: boolean
size?: 'sm' | 'md' | 'lg' | 'xl'
timezone?: string
}

Expand Down
Loading