feat: add exact retention help contexts

This commit is contained in:
2026-08-17 17:41:45 +02:00
parent 887e9beb9e
commit ff88142471
15 changed files with 85 additions and 31 deletions
+2 -1
View File
@@ -7,12 +7,13 @@ export type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & PlatformInte
disabledReason?: ReactNode;
};
export default function Button({ variant = "secondary", className = "", disabledReason, disabled, interfaceId, helpContextId, helpTopicId, children, ...props }: ButtonProps) {
export default function Button({ variant = "secondary", className = "", disabledReason, disabled, interfaceId, helpContextId, helpModuleId, helpTopicId, children, ...props }: ButtonProps) {
const button = (
<button
data-help-scope="action"
data-interface-id={interfaceId}
data-help-context-id={helpContextId}
data-help-module-id={helpModuleId}
data-help-topic-id={helpTopicId}
data-help-key={typeof children === "string" ? children : undefined}
className={`btn btn-${variant} ${className}`}
+2 -1
View File
@@ -39,7 +39,7 @@ function writeCollapseState(storageKey: string | null, collapsed: boolean): void
// localStorage may be unavailable in private or restricted contexts.
}}
export default function Card({ title, children, actions, collapsible = false, collapseKey, persistCollapse = true, interfaceId, helpContextId, helpTopicId }: CardProps) {
export default function Card({ title, children, actions, collapsible = false, collapseKey, persistCollapse = true, interfaceId, helpContextId, helpModuleId, helpTopicId }: CardProps) {
const { translateText } = usePlatformLanguage();
const storageKey = resolveCollapseStorageKey(collapsible, persistCollapse, collapseKey, title);
const [collapseState, setCollapseState] = useState(() => ({ storageKey, collapsed: readCollapseState(storageKey) }));
@@ -65,6 +65,7 @@ export default function Card({ title, children, actions, collapsible = false, co
data-help-scope="interface"
data-interface-id={interfaceId}
data-help-context-id={helpContextId}
data-help-module-id={helpModuleId}
data-help-topic-id={helpTopicId}
data-help-key={typeof title === "string" ? title : undefined}
>
+11 -2
View File
@@ -1,10 +1,11 @@
import Button from "./Button";
import Dialog from "./Dialog";
import { usePlatformLanguage } from "../i18n/LanguageContext";
import type { PlatformInterfaceIdentityProps } from "../types";
export type ConfirmDialogTone = "default" | "danger";
export type ConfirmDialogProps = {
export type ConfirmDialogProps = PlatformInterfaceIdentityProps & {
open: boolean;
title: string;
message: string;
@@ -24,6 +25,10 @@ export default function ConfirmDialog({
cancelLabel = "i18n:govoplan-core.cancel.77dfd213",
tone = "default",
busy = false,
interfaceId,
helpContextId,
helpModuleId,
helpTopicId,
onConfirm,
onCancel
}: ConfirmDialogProps) {
@@ -38,11 +43,15 @@ export default function ConfirmDialog({
closeOnBackdrop={!busy}
closeDisabled={busy}
showCloseButton
interfaceId={interfaceId}
helpContextId={helpContextId}
helpModuleId={helpModuleId}
helpTopicId={helpTopicId}
onClose={onCancel}
footer={
<>
<Button onClick={onCancel} disabled={busy}>{translateText(cancelLabel)}</Button>
<Button variant={tone === "danger" ? "danger" : "primary"} onClick={onConfirm} disabled={busy}>{busy ? translateText("i18n:govoplan-core.working.13b7bfca") : translateText(confirmLabel)}</Button>
<Button helpContextId={helpContextId} helpModuleId={helpModuleId} helpTopicId={helpTopicId} variant={tone === "danger" ? "danger" : "primary"} onClick={onConfirm} disabled={busy}>{busy ? translateText("i18n:govoplan-core.working.13b7bfca") : translateText(confirmLabel)}</Button>
</>
}>
+6 -3
View File
@@ -50,7 +50,7 @@ function combineDateTime(date: string, time: string): string {
return `${date || dateString(new Date())}T${time || "00:00"}`;
}
export function DateField({ value, onChange, min, max, disabled, className = "", placeholder = "i18n:govoplan-core.yyyy_mm_dd.d3f8f7b8", interfaceId, helpContextId, helpTopicId, ...props }: BaseProps) {
export function DateField({ value, onChange, min, max, disabled, className = "", placeholder = "i18n:govoplan-core.yyyy_mm_dd.d3f8f7b8", interfaceId, helpContextId, helpModuleId, helpTopicId, ...props }: BaseProps) {
const selectedDate = parseDate(value);
const [open, setOpen] = useState(false);
const [visibleMonth, setVisibleMonth] = useState<Date>(() => selectedDate ?? new Date());
@@ -100,6 +100,7 @@ export function DateField({ value, onChange, min, max, disabled, className = "",
data-help-scope="field"
data-interface-id={interfaceId}
data-help-context-id={helpContextId}
data-help-module-id={helpModuleId}
data-help-topic-id={helpTopicId}
data-help-key={props["aria-label"] ?? placeholder}
>
@@ -154,7 +155,7 @@ export function DateField({ value, onChange, min, max, disabled, className = "",
}
export function TimeField({ value, onChange, min, max, className = "", placeholder = "i18n:govoplan-core.hh_mm.a4c7ee9b", interfaceId, helpContextId, helpTopicId, ...props }: BaseProps) {
export function TimeField({ value, onChange, min, max, className = "", placeholder = "i18n:govoplan-core.hh_mm.a4c7ee9b", interfaceId, helpContextId, helpModuleId, helpTopicId, ...props }: BaseProps) {
const inputRef = useRef<HTMLInputElement | null>(null);
useEffect(() => {
const input = inputRef.current;
@@ -172,6 +173,7 @@ export function TimeField({ value, onChange, min, max, className = "", placehold
data-help-scope="field"
data-interface-id={interfaceId}
data-help-context-id={helpContextId}
data-help-module-id={helpModuleId}
data-help-topic-id={helpTopicId}
data-help-key={props["aria-label"] ?? placeholder}
>
@@ -190,7 +192,7 @@ export function TimeField({ value, onChange, min, max, className = "", placehold
}
export function DateTimeField({ value, onChange, min, max, disabled, className = "", interfaceId, helpContextId, helpTopicId, ...props }: BaseProps) {
export function DateTimeField({ value, onChange, min, max, disabled, className = "", interfaceId, helpContextId, helpModuleId, helpTopicId, ...props }: BaseProps) {
const parts = datePartsFromDateTime(value);
const minParts = datePartsFromDateTime(min || "");
const maxParts = datePartsFromDateTime(max || "");
@@ -209,6 +211,7 @@ export function DateTimeField({ value, onChange, min, max, disabled, className =
data-help-scope="field"
data-interface-id={interfaceId}
data-help-context-id={helpContextId}
data-help-module-id={helpModuleId}
data-help-topic-id={helpTopicId}
data-help-key={props["aria-label"]}
>
+2
View File
@@ -60,6 +60,7 @@ export default function Dialog({
backdropStyle,
interfaceId,
helpContextId,
helpModuleId,
helpTopicId
}: DialogProps) {
const titleId = useId();
@@ -141,6 +142,7 @@ export default function Dialog({
data-help-scope="dialog"
data-interface-id={interfaceId}
data-help-context-id={helpContextId}
data-help-module-id={helpModuleId}
data-help-topic-id={helpTopicId}
data-help-key={typeof title === "string" ? title : undefined}
aria-labelledby={titleId}
+2 -1
View File
@@ -12,7 +12,7 @@ type FormFieldProps = PlatformInterfaceIdentityProps & {
children: ReactNode;
};
export default function FormField({ label, help, documentation, children, interfaceId, helpContextId, helpTopicId }: FormFieldProps) {
export default function FormField({ label, help, documentation, children, interfaceId, helpContextId, helpModuleId, helpTopicId }: FormFieldProps) {
const { translateText } = usePlatformLanguage();
const renderedLabel = typeof label === "string" ? translateText(label) : label;
return (
@@ -21,6 +21,7 @@ export default function FormField({ label, help, documentation, children, interf
data-help-scope="field"
data-interface-id={interfaceId}
data-help-context-id={helpContextId ?? documentation?.contextId}
data-help-module-id={helpModuleId}
data-help-topic-id={helpTopicId ?? documentation?.topicId}
data-help-documentation-type={documentation?.documentationType}
data-help-key={typeof label === "string" ? label : undefined}
@@ -99,6 +99,7 @@ export default function SearchableSelect({
className = "",
interfaceId,
helpContextId,
helpModuleId,
helpTopicId
}: SearchableSelectProps) {
const { translateText } = usePlatformLanguage();
@@ -301,6 +302,7 @@ export default function SearchableSelect({
data-help-scope="field"
data-interface-id={interfaceId}
data-help-context-id={helpContextId}
data-help-module-id={helpModuleId}
data-help-topic-id={helpTopicId}
data-help-key={ariaLabel}
onBlur={closeOnFocusLeave}
+2 -1
View File
@@ -14,7 +14,7 @@ type ToggleSwitchProps = PlatformInterfaceIdentityProps & {
help?: ReactNode;
};
export default function ToggleSwitch({ label, activeLabel, inactiveLabel, checked, onChange, disabled = false, help, interfaceId, helpContextId, helpTopicId }: ToggleSwitchProps) {
export default function ToggleSwitch({ label, activeLabel, inactiveLabel, checked, onChange, disabled = false, help, interfaceId, helpContextId, helpModuleId, helpTopicId }: ToggleSwitchProps) {
const { translateText } = usePlatformLanguage();
const hasStateLabels = activeLabel !== undefined || inactiveLabel !== undefined;
const renderedLabel = typeof label === "string" ? translateText(label) : label;
@@ -27,6 +27,7 @@ export default function ToggleSwitch({ label, activeLabel, inactiveLabel, checke
data-help-scope="field"
data-interface-id={interfaceId}
data-help-context-id={helpContextId}
data-help-module-id={helpModuleId}
data-help-topic-id={helpTopicId}
data-help-key={typeof label === "string" ? label : undefined}
>
@@ -29,6 +29,7 @@ export default function AdminPageLayout({
className = "",
interfaceId,
helpContextId,
helpModuleId,
helpTopicId
}: Props) {
const { translateText } = usePlatformLanguage();
@@ -38,6 +39,7 @@ export default function AdminPageLayout({
data-help-scope="page"
data-interface-id={interfaceId}
data-help-context-id={helpContextId}
data-help-module-id={helpModuleId}
data-help-topic-id={helpTopicId}
data-help-documentation-type="admin"
data-help-key={title}
@@ -47,6 +47,7 @@ export default function EmailAddressInput({
showAddButton,
interfaceId,
helpContextId,
helpModuleId,
helpTopicId
}: EmailAddressInputProps) {
const { translateText } = usePlatformLanguage();
@@ -208,6 +209,7 @@ export default function EmailAddressInput({
data-help-scope="field"
data-interface-id={interfaceId}
data-help-context-id={helpContextId}
data-help-module-id={helpModuleId}
data-help-topic-id={helpTopicId}
data-help-key={emailPlaceholder}
>