refactor(webui): use Core date-time formatting
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
|||||||
DismissibleAlert,
|
DismissibleAlert,
|
||||||
ExplorerTree,
|
ExplorerTree,
|
||||||
fetchAuthGroups,
|
fetchAuthGroups,
|
||||||
|
formatDateTime,
|
||||||
FormField,
|
FormField,
|
||||||
LoadingFrame,
|
LoadingFrame,
|
||||||
PasswordField,
|
PasswordField,
|
||||||
@@ -19,7 +20,8 @@ import {
|
|||||||
hasScope,
|
hasScope,
|
||||||
type ApiSettings,
|
type ApiSettings,
|
||||||
type AuthInfo,
|
type AuthInfo,
|
||||||
type AuthUpdate
|
type AuthUpdate,
|
||||||
|
type FormatDateTimeOptions
|
||||||
} from "@govoplan/core-webui";
|
} from "@govoplan/core-webui";
|
||||||
import {
|
import {
|
||||||
createAddressBook,
|
createAddressBook,
|
||||||
@@ -291,14 +293,17 @@ function syncSourceLabel(source: AddressSyncSource): string {
|
|||||||
return source.display_name || source.external_address_book_ref || source.connector_type;
|
return source.display_name || source.external_address_book_ref || source.connector_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatDateTime(value?: string | null): string {
|
const ADDRESS_DATE_TIME_OPTIONS: FormatDateTimeOptions = {
|
||||||
if (!value) return "Never";
|
fallback: "Never",
|
||||||
try {
|
year: undefined,
|
||||||
return new Intl.DateTimeFormat(undefined, { dateStyle: "short", timeStyle: "short" }).format(new Date(value));
|
month: undefined,
|
||||||
} catch {
|
day: undefined,
|
||||||
return value;
|
hour: undefined,
|
||||||
}
|
minute: undefined,
|
||||||
}
|
timeZoneName: undefined,
|
||||||
|
dateStyle: "short",
|
||||||
|
timeStyle: "short"
|
||||||
|
};
|
||||||
|
|
||||||
function planSummary(plan: AddressSyncPlan | null): string {
|
function planSummary(plan: AddressSyncPlan | null): string {
|
||||||
if (!plan) return "No preview loaded.";
|
if (!plan) return "No preview loaded.";
|
||||||
@@ -1740,7 +1745,7 @@ export default function AddressBookPage({ settings, auth, onAuthChange }: Props)
|
|||||||
{selectedBookSyncSources.map((source) => (
|
{selectedBookSyncSources.map((source) => (
|
||||||
<p key={source.id}>
|
<p key={source.id}>
|
||||||
{syncSourceLabel(source)} · {source.connector_type} · {source.status}
|
{syncSourceLabel(source)} · {source.connector_type} · {source.status}
|
||||||
{source.last_success_at ? ` · last success ${formatDateTime(source.last_success_at)}` : ""}
|
{source.last_success_at ? ` · last success ${formatDateTime(source.last_success_at, ADDRESS_DATE_TIME_OPTIONS)}` : ""}
|
||||||
{source.last_error ? ` · ${source.last_error}` : ""}
|
{source.last_error ? ` · ${source.last_error}` : ""}
|
||||||
</p>
|
</p>
|
||||||
))}
|
))}
|
||||||
@@ -2314,7 +2319,7 @@ export default function AddressBookPage({ settings, auth, onAuthChange }: Props)
|
|||||||
<StatusBadge status={syncInspector.source.status} />
|
<StatusBadge status={syncInspector.source.status} />
|
||||||
{syncInspector.source.read_only && <StatusBadge status="read-only" />}
|
{syncInspector.source.read_only && <StatusBadge status="read-only" />}
|
||||||
</div>
|
</div>
|
||||||
<p className="muted">Last attempt: {formatDateTime(syncInspector.source.last_attempted_at)} · Last success: {formatDateTime(syncInspector.source.last_success_at)}</p>
|
<p className="muted">Last attempt: {formatDateTime(syncInspector.source.last_attempted_at, ADDRESS_DATE_TIME_OPTIONS)} · Last success: {formatDateTime(syncInspector.source.last_success_at, ADDRESS_DATE_TIME_OPTIONS)}</p>
|
||||||
{syncInspector.source.last_error && <DismissibleAlert tone="danger" resetKey={syncInspector.source.last_error}>{syncInspector.source.last_error}</DismissibleAlert>}
|
{syncInspector.source.last_error && <DismissibleAlert tone="danger" resetKey={syncInspector.source.last_error}>{syncInspector.source.last_error}</DismissibleAlert>}
|
||||||
<div className="button-row compact-actions">
|
<div className="button-row compact-actions">
|
||||||
<Button
|
<Button
|
||||||
@@ -2383,7 +2388,7 @@ export default function AddressBookPage({ settings, auth, onAuthChange }: Props)
|
|||||||
<div className="address-sync-record-list">
|
<div className="address-sync-record-list">
|
||||||
{syncTombstones.slice(0, 20).map((tombstone) => (
|
{syncTombstones.slice(0, 20).map((tombstone) => (
|
||||||
<div className="address-sync-record-row" key={tombstone.id}>
|
<div className="address-sync-record-row" key={tombstone.id}>
|
||||||
<span><strong>{tombstone.remote_uid || tombstone.resource_href || tombstone.contact_id}</strong><small>{formatDateTime(tombstone.synced_at || tombstone.remote_deleted_at || tombstone.local_deleted_at)}</small></span>
|
<span><strong>{tombstone.remote_uid || tombstone.resource_href || tombstone.contact_id}</strong><small>{formatDateTime(tombstone.synced_at || tombstone.remote_deleted_at || tombstone.local_deleted_at, ADDRESS_DATE_TIME_OPTIONS)}</small></span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user