Link contextual guidance to Docs
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { AlertTriangle, Info } from "lucide-react";
|
||||
import type { ReactNode } from "react";
|
||||
import AdvancedOptionsPanel from "./AdvancedOptionsPanel";
|
||||
import DocumentationHelpLink from "./help/DocumentationHelpLink";
|
||||
import type { DocumentationHelpReference } from "./help/documentationHelp";
|
||||
|
||||
export type ActionBlockerReason = {
|
||||
summary: ReactNode;
|
||||
@@ -23,6 +25,7 @@ type ActionBlockerHintProps = {
|
||||
tone?: "info" | "warning" | "danger";
|
||||
className?: string;
|
||||
labels?: ActionBlockerLabels;
|
||||
documentation?: DocumentationHelpReference;
|
||||
};
|
||||
|
||||
function joinClasses(...classes: Array<string | undefined | false>) {
|
||||
@@ -33,7 +36,8 @@ export default function ActionBlockerHint({
|
||||
reason,
|
||||
tone = "warning",
|
||||
className = "",
|
||||
labels = {}
|
||||
labels = {},
|
||||
documentation
|
||||
}: ActionBlockerHintProps) {
|
||||
const Icon = tone === "info" ? Info : AlertTriangle;
|
||||
const hasActionRows = Boolean(reason.requiredAction || reason.actor || reason.target);
|
||||
@@ -71,6 +75,7 @@ export default function ActionBlockerHint({
|
||||
<div>{reason.technicalDetails}</div>
|
||||
</AdvancedOptionsPanel>
|
||||
)}
|
||||
{documentation && <DocumentationHelpLink reference={documentation} />}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import type { ReactNode } from "react";
|
||||
import FieldLabel from "./help/FieldLabel";
|
||||
import type { DocumentationHelpReference } from "./help/documentationHelp";
|
||||
import { helpForFieldLabel } from "../utils/fieldHelp";
|
||||
import { usePlatformLanguage } from "../i18n/LanguageContext";
|
||||
|
||||
export default function FormField({ label, help, children }: { label: ReactNode; help?: ReactNode; children: ReactNode }) {
|
||||
export default function FormField({ label, help, documentation, children }: { label: ReactNode; help?: ReactNode; documentation?: DocumentationHelpReference; children: ReactNode }) {
|
||||
const { translateText } = usePlatformLanguage();
|
||||
const renderedLabel = typeof label === "string" ? translateText(label) : label;
|
||||
return (
|
||||
<label className="form-field">
|
||||
<FieldLabel className="form-label" help={help ?? helpForFieldLabel(label)}>{renderedLabel}</FieldLabel>
|
||||
<FieldLabel className="form-label" help={help ?? helpForFieldLabel(label)} documentation={documentation}>{renderedLabel}</FieldLabel>
|
||||
{children}
|
||||
</label>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import { BookOpen } from "lucide-react";
|
||||
import { createContext, useContext, type MouseEvent, type ReactNode } from "react";
|
||||
|
||||
import { usePlatformLanguage } from "../../i18n/LanguageContext";
|
||||
import {
|
||||
HOSTED_DOCUMENTATION_URL,
|
||||
documentationHelpHref,
|
||||
type DocumentationHelpReference
|
||||
} from "./documentationHelp";
|
||||
|
||||
export { documentationHelpHref } from "./documentationHelp";
|
||||
export type { DocumentationHelpReference } from "./documentationHelp";
|
||||
|
||||
const DocumentationHelpAvailabilityContext = createContext(false);
|
||||
|
||||
export function DocumentationHelpProvider({
|
||||
localDocsAvailable,
|
||||
children
|
||||
}: {
|
||||
localDocsAvailable: boolean;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<DocumentationHelpAvailabilityContext.Provider value={localDocsAvailable}>
|
||||
{children}
|
||||
</DocumentationHelpAvailabilityContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export default function DocumentationHelpLink({
|
||||
reference,
|
||||
label = "i18n:govoplan-core.open_user_documentation.084af515",
|
||||
className = ""
|
||||
}: {
|
||||
reference: DocumentationHelpReference;
|
||||
label?: string;
|
||||
className?: string;
|
||||
}) {
|
||||
const { translateText } = usePlatformLanguage();
|
||||
const localDocsAvailable = useContext(DocumentationHelpAvailabilityContext);
|
||||
const href = documentationHelpHref(
|
||||
reference,
|
||||
localDocsAvailable ? "/docs" : HOSTED_DOCUMENTATION_URL
|
||||
);
|
||||
if (!href) return null;
|
||||
|
||||
const translatedLabel = translateText(label);
|
||||
const stopLabelActivation = (event: MouseEvent<HTMLAnchorElement>) => event.stopPropagation();
|
||||
return (
|
||||
<a
|
||||
className={["documentation-help-link", className].filter(Boolean).join(" ")}
|
||||
href={href}
|
||||
aria-label={translatedLabel}
|
||||
title={translatedLabel}
|
||||
target={localDocsAvailable ? undefined : "_blank"}
|
||||
rel={localDocsAvailable ? undefined : "noreferrer"}
|
||||
onClick={stopLabelActivation}
|
||||
onMouseDown={stopLabelActivation}
|
||||
>
|
||||
<BookOpen size={13} aria-hidden="true" />
|
||||
</a>
|
||||
);
|
||||
}
|
||||
@@ -1,17 +1,21 @@
|
||||
import type { ReactNode } from "react";
|
||||
import DocumentationHelpLink from "./DocumentationHelpLink";
|
||||
import type { DocumentationHelpReference } from "./documentationHelp";
|
||||
import InlineHelp from "./InlineHelp";
|
||||
|
||||
type FieldLabelProps = {
|
||||
children: ReactNode;
|
||||
help?: ReactNode;
|
||||
documentation?: DocumentationHelpReference;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export default function FieldLabel({ children, help, className = "" }: FieldLabelProps) {
|
||||
export default function FieldLabel({ children, help, documentation, className = "" }: FieldLabelProps) {
|
||||
return (
|
||||
<span className={`field-label ${className}`.trim()}>
|
||||
<span className="field-label-text">{children}</span>
|
||||
{help && <InlineHelp>{help}</InlineHelp>}
|
||||
{documentation && <DocumentationHelpLink reference={documentation} />}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
export const HOSTED_DOCUMENTATION_URL = "https://govoplan.add-ideas.de/";
|
||||
|
||||
export type DocumentationHelpReference = {
|
||||
topicId?: string;
|
||||
contextId?: string;
|
||||
documentationType?: "user" | "admin";
|
||||
anchorId?: string;
|
||||
};
|
||||
|
||||
export function documentationHelpHref(
|
||||
reference: DocumentationHelpReference,
|
||||
baseUrl = "/docs"
|
||||
): string | null {
|
||||
const topicId = reference.topicId?.trim();
|
||||
const contextId = reference.contextId?.trim();
|
||||
if (!topicId && !contextId) return null;
|
||||
|
||||
const params = new URLSearchParams({
|
||||
type: reference.documentationType === "admin" ? "admin" : "user"
|
||||
});
|
||||
if (topicId) params.set("topic", topicId);
|
||||
else if (contextId) params.set("context", contextId);
|
||||
const anchorId = reference.anchorId?.trim();
|
||||
return `${baseUrl}?${params.toString()}${anchorId ? `#${encodeURIComponent(anchorId)}` : ""}`;
|
||||
}
|
||||
Reference in New Issue
Block a user