refactor(webui): centralize Calendar icon actions

This commit is contained in:
2026-07-21 12:36:13 +02:00
parent 2d7d105ba3
commit 6ca1816c95
2 changed files with 38 additions and 83 deletions

View File

@@ -11,6 +11,7 @@ import {
"react";
import { CalendarDays, ChevronLeft, ChevronRight, Pencil, Plus, RefreshCw, Trash2 } from "lucide-react";
import {
AdminIconButton,
Button,
ColorPickerField,
DateField,
@@ -19,6 +20,7 @@ import {
LoadingFrame,
PasswordField,
SegmentedControl,
TableActionGroup,
TimeField,
ToggleSwitch,
hasScope,
@@ -684,31 +686,24 @@ export default function CalendarPage({ settings, auth }: {settings: ApiSettings;
<button type="button" className="calendar-list-name" onClick={() => setEventCalendarId(calendar.id)}>
{calendar.name}
</button>
<div className="calendar-list-actions">
{source && canSyncCalendars &&
<Button
type="button"
className={syncing ? "calendar-row-icon-button is-syncing" : "calendar-row-icon-button"}
title={syncing ? i18nMessage("i18n:govoplan-calendar.syncing_value.ca80b487", { value0: calendar.name }) : i18nMessage("i18n:govoplan-calendar.sync_value.72e4ba66", { value0: calendar.name })}
aria-label={syncing ? i18nMessage("i18n:govoplan-calendar.syncing_value.ca80b487", { value0: calendar.name }) : i18nMessage("i18n:govoplan-calendar.sync_value.72e4ba66", { value0: calendar.name })}
onClick={() => void handleSyncSource(source)}
disabled={saving || syncing}>
<RefreshCw size={15} className={syncing ? "calendar-sync-spin" : undefined} />
</Button>
}
{(canManageCalendars || canDeleteCalendars) &&
<Button
type="button"
className="calendar-row-icon-button"
title={i18nMessage("i18n:govoplan-calendar.edit_value.fad75899", { value0: calendar.name })}
aria-label={i18nMessage("i18n:govoplan-calendar.edit_value.fad75899", { value0: calendar.name })}
onClick={() => openCalendarEditor(calendar)}>
<Pencil size={15} />
</Button>
}
</div>
<TableActionGroup
className="calendar-list-actions"
actions={[
source && canSyncCalendars && {
id: "sync",
label: syncing ? i18nMessage("i18n:govoplan-calendar.syncing_value.ca80b487", { value0: calendar.name }) : i18nMessage("i18n:govoplan-calendar.sync_value.72e4ba66", { value0: calendar.name }),
icon: <RefreshCw size={15} className={syncing ? "calendar-sync-spin" : undefined} />,
onClick: () => void handleSyncSource(source),
disabled: saving || syncing
},
(canManageCalendars || canDeleteCalendars) && {
id: "edit",
label: i18nMessage("i18n:govoplan-calendar.edit_value.fad75899", { value0: calendar.name }),
icon: <Pencil size={15} />,
onClick: () => openCalendarEditor(calendar)
}
]}
/>
</div>);
})}
@@ -764,13 +759,19 @@ export default function CalendarPage({ settings, auth }: {settings: ApiSettings;
<div className="calendar-toolbar-center">
<div className="calendar-icon-group" aria-label="i18n:govoplan-calendar.calendar_navigation.7ba43cd2">
<Button type="button" className="calendar-icon-button" title="i18n:govoplan-calendar.previous.50f94286" aria-label="i18n:govoplan-calendar.previous.50f94286" onClick={() => moveFocus(-1)} disabled={mode === "continuous"}>
<ChevronLeft size={18} />
</Button>
<AdminIconButton
label="i18n:govoplan-calendar.previous.50f94286"
icon={<ChevronLeft size={18} />}
onClick={() => moveFocus(-1)}
disabled={mode === "continuous"}
/>
<Button type="button" onClick={handleToday}>i18n:govoplan-calendar.today.24345a14</Button>
<Button type="button" className="calendar-icon-button" title="i18n:govoplan-calendar.next.bc981983" aria-label="i18n:govoplan-calendar.next.bc981983" onClick={() => moveFocus(1)} disabled={mode === "continuous"}>
<ChevronRight size={18} />
</Button>
<AdminIconButton
label="i18n:govoplan-calendar.next.bc981983"
icon={<ChevronRight size={18} />}
onClick={() => moveFocus(1)}
disabled={mode === "continuous"}
/>
<div className="calendar-range-label">
<CalendarDays size={18} aria-hidden="true" />
<strong>{heading}</strong>
@@ -779,9 +780,11 @@ export default function CalendarPage({ settings, auth }: {settings: ApiSettings;
</div>
<div className="calendar-toolbar-right">
<Button type="button" className="calendar-icon-button" title="i18n:govoplan-calendar.refresh.56e3badc" aria-label="i18n:govoplan-calendar.refresh.56e3badc" onClick={() => void loadEvents()}>
<RefreshCw size={18} />
</Button>
<AdminIconButton
label="i18n:govoplan-calendar.refresh.56e3badc"
icon={<RefreshCw size={18} />}
onClick={() => void loadEvents()}
/>
{canWrite &&
<Button type="button" variant="primary" onClick={() => setEventDialog({ kind: "create" })} disabled={!targetCalendarId}>
<Plus size={17} /> i18n:govoplan-calendar.new.6403f2b7

View File

@@ -89,21 +89,6 @@
gap: 6px;
}
.calendar-icon-button.btn {
width: 36px;
min-width: 36px;
height: 36px;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0;
}
.calendar-icon-button.btn:disabled {
opacity: .42;
cursor: default;
}
.calendar-mode-switch {
flex: 0 1 520px;
grid-template-columns: repeat(5, minmax(0, 1fr));
@@ -250,40 +235,7 @@
}
.calendar-list-actions {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 2px;
min-width: 28px;
}
.calendar-row-icon-button.btn {
width: 28px;
min-width: 28px;
height: 28px;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0;
border-color: transparent;
background: transparent;
opacity: .72;
}
.calendar-row-icon-button.btn:hover,
.calendar-row-icon-button.btn:focus-visible {
border-color: var(--line-dark);
background: var(--surface);
opacity: 1;
}
.calendar-row-icon-button.btn.is-syncing,
.calendar-row-icon-button.btn.is-syncing:disabled {
border-color: var(--green);
background: var(--surface);
color: var(--green);
opacity: 1;
cursor: progress;
width: auto;
}
.calendar-sync-spin {