feat: add View-scoped quick access presentation
This commit is contained in:
@@ -20,6 +20,8 @@ export type ViewRevision = {
|
||||
navigation_mode?: "grouped" | "flat";
|
||||
product_area_order?: string[];
|
||||
product_area_labels?: Record<string, string>;
|
||||
quick_access_recommended_tool_ids?: string[];
|
||||
quick_access_focused_tool_ids?: string[];
|
||||
};
|
||||
content_hash: string;
|
||||
created_by?: string | null;
|
||||
@@ -264,7 +266,9 @@ function presentationFromApi(
|
||||
return {
|
||||
navigationMode: value?.navigation_mode,
|
||||
productAreaOrder: value?.product_area_order ?? [],
|
||||
productAreaLabels: value?.product_area_labels ?? {}
|
||||
productAreaLabels: value?.product_area_labels ?? {},
|
||||
quickAccessRecommendedToolIds: value?.quick_access_recommended_tool_ids ?? [],
|
||||
quickAccessFocusedToolIds: value?.quick_access_focused_tool_ids ?? []
|
||||
};
|
||||
}
|
||||
|
||||
@@ -274,7 +278,9 @@ export function presentationToApi(
|
||||
return {
|
||||
navigation_mode: value.navigationMode ?? "grouped",
|
||||
product_area_order: value.productAreaOrder ?? [],
|
||||
product_area_labels: value.productAreaLabels ?? {}
|
||||
product_area_labels: value.productAreaLabels ?? {},
|
||||
quick_access_recommended_tool_ids: value.quickAccessRecommendedToolIds ?? [],
|
||||
quick_access_focused_tool_ids: value.quickAccessFocusedToolIds ?? []
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -771,6 +771,46 @@ export default function ViewsAdminPanel({
|
||||
/>
|
||||
)}
|
||||
|
||||
<section className="views-product-area-section">
|
||||
<div className="views-section-heading">
|
||||
<div>
|
||||
<h4>Quick Access focus</h4>
|
||||
<p className="muted small-note">
|
||||
Recommend or focus namespaced tool IDs for this View. The
|
||||
active account still needs the tool's permissions and visible surface.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<FormGrid columns={2} collapseAt="standard">
|
||||
<FormField label="Recommended tool IDs" help="Comma-separated, for example tasks.work, files.recent">
|
||||
<input
|
||||
value={(draft.presentation.quickAccessRecommendedToolIds ?? []).join(", ")}
|
||||
disabled={!definitionEditable || busy}
|
||||
onChange={(event) => setDraft({
|
||||
...draft,
|
||||
presentation: {
|
||||
...draft.presentation,
|
||||
quickAccessRecommendedToolIds: commaSeparatedToolIds(event.target.value)
|
||||
}
|
||||
})}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label="Focused tool IDs" help="When at least one listed tool is available, other Quick Access tools are hidden for this View.">
|
||||
<input
|
||||
value={(draft.presentation.quickAccessFocusedToolIds ?? []).join(", ")}
|
||||
disabled={!definitionEditable || busy}
|
||||
onChange={(event) => setDraft({
|
||||
...draft,
|
||||
presentation: {
|
||||
...draft.presentation,
|
||||
quickAccessFocusedToolIds: commaSeparatedToolIds(event.target.value)
|
||||
}
|
||||
})}
|
||||
/>
|
||||
</FormField>
|
||||
</FormGrid>
|
||||
</section>
|
||||
|
||||
<section className="views-surface-section">
|
||||
<div className="views-section-heading">
|
||||
<div>
|
||||
@@ -1839,7 +1879,9 @@ function defaultPresentation(areas: ViewProductArea[]): ViewPresentation {
|
||||
return {
|
||||
navigationMode: "grouped",
|
||||
productAreaOrder: areas.map((area) => area.id),
|
||||
productAreaLabels: {}
|
||||
productAreaLabels: {},
|
||||
quickAccessRecommendedToolIds: [],
|
||||
quickAccessFocusedToolIds: []
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1878,7 +1920,9 @@ function revisionPresentation(
|
||||
value?.product_area_order?.length
|
||||
? value.product_area_order
|
||||
: defaults.productAreaOrder,
|
||||
productAreaLabels: value?.product_area_labels ?? {}
|
||||
productAreaLabels: value?.product_area_labels ?? {},
|
||||
quickAccessRecommendedToolIds: value?.quick_access_recommended_tool_ids ?? [],
|
||||
quickAccessFocusedToolIds: value?.quick_access_focused_tool_ids ?? []
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1905,10 +1949,16 @@ function presentationKey(value: ViewPresentation): string {
|
||||
Object.entries(value.productAreaLabels ?? {})
|
||||
.filter(([, label]) => label.trim())
|
||||
.sort(([left], [right]) => left.localeCompare(right))
|
||||
)
|
||||
),
|
||||
quickAccessRecommendedToolIds: value.quickAccessRecommendedToolIds ?? [],
|
||||
quickAccessFocusedToolIds: value.quickAccessFocusedToolIds ?? []
|
||||
});
|
||||
}
|
||||
|
||||
function commaSeparatedToolIds(value: string): string[] {
|
||||
return [...new Set(value.split(",").map((item) => item.trim()).filter(Boolean))];
|
||||
}
|
||||
|
||||
|
||||
function assignmentDraftKey(draft: AssignmentDraft): string {
|
||||
return JSON.stringify({
|
||||
|
||||
Reference in New Issue
Block a user