Support deep links into organization editor
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { useCallback, useEffect, useMemo, useState, type FormEvent } from "react";
|
import { useCallback, useEffect, useMemo, useRef, useState, type FormEvent } from "react";
|
||||||
import { Edit3, Plus, RefreshCw, Save, XCircle } from "lucide-react";
|
import { Edit3, Plus, RefreshCw, Save, XCircle } from "lucide-react";
|
||||||
import {
|
import {
|
||||||
ApiError,
|
ApiError,
|
||||||
@@ -118,6 +118,26 @@ type ActiveItem = {
|
|||||||
is_active: boolean;
|
is_active: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type OrganizationsInitialQuery = {
|
||||||
|
section: OrganizationSection | "";
|
||||||
|
unitId: string;
|
||||||
|
functionId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
function organizationSectionFromQuery(value: string | null): OrganizationSection | "" {
|
||||||
|
return value === "model" || value === "units" || value === "relations" || value === "functions" ? value : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function organizationsInitialQuery(): OrganizationsInitialQuery {
|
||||||
|
if (typeof window === "undefined") return { section: "", unitId: "", functionId: "" };
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
return {
|
||||||
|
section: organizationSectionFromQuery(params.get("section")),
|
||||||
|
unitId: params.get("unit_id") || "",
|
||||||
|
functionId: params.get("function_id") || ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const EMPTY_MODEL: OrganizationModel = {
|
const EMPTY_MODEL: OrganizationModel = {
|
||||||
unit_types: [],
|
unit_types: [],
|
||||||
structures: [],
|
structures: [],
|
||||||
@@ -345,7 +365,10 @@ export default function OrganizationsPage({
|
|||||||
}: OrganizationsPageProps) {
|
}: OrganizationsPageProps) {
|
||||||
const sectionSet = useMemo(() => new Set(availableSections.length ? availableSections : ALL_SECTIONS), [availableSections]);
|
const sectionSet = useMemo(() => new Set(availableSections.length ? availableSections : ALL_SECTIONS), [availableSections]);
|
||||||
const firstAvailableSection = availableSections.find((section) => sectionSet.has(section)) ?? "model";
|
const firstAvailableSection = availableSections.find((section) => sectionSet.has(section)) ?? "model";
|
||||||
const [active, setActive] = useState<OrganizationSection>(sectionSet.has(initialSection) ? initialSection : firstAvailableSection);
|
const initialQuery = useMemo(() => organizationsInitialQuery(), []);
|
||||||
|
const requestedInitialSection = initialQuery.section && sectionSet.has(initialQuery.section) ? initialQuery.section : initialSection;
|
||||||
|
const [active, setActive] = useState<OrganizationSection>(sectionSet.has(requestedInitialSection) ? requestedInitialSection : firstAvailableSection);
|
||||||
|
const appliedInitialQueryRef = useRef(false);
|
||||||
const visibleSectionGroups = useMemo(() => sectionGroupsFor(sectionSet), [sectionSet]);
|
const visibleSectionGroups = useMemo(() => sectionGroupsFor(sectionSet), [sectionSet]);
|
||||||
const [model, setModel] = useState<OrganizationModel>(EMPTY_MODEL);
|
const [model, setModel] = useState<OrganizationModel>(EMPTY_MODEL);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
@@ -784,6 +807,30 @@ export default function OrganizationsPage({
|
|||||||
setActive("functions");
|
setActive("functions");
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (appliedInitialQueryRef.current || loading) return;
|
||||||
|
if (initialQuery.functionId) {
|
||||||
|
const item = functionById.get(initialQuery.functionId);
|
||||||
|
if (item) {
|
||||||
|
appliedInitialQueryRef.current = true;
|
||||||
|
editFunction(item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (initialQuery.unitId) {
|
||||||
|
const item = unitById.get(initialQuery.unitId);
|
||||||
|
if (item) {
|
||||||
|
appliedInitialQueryRef.current = true;
|
||||||
|
editUnit(item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (initialQuery.section && sectionSet.has(initialQuery.section)) {
|
||||||
|
appliedInitialQueryRef.current = true;
|
||||||
|
setActive(initialQuery.section);
|
||||||
|
}
|
||||||
|
}, [editFunction, editUnit, functionById, initialQuery, loading, sectionSet, unitById]);
|
||||||
|
|
||||||
const unitTypeColumns: DataGridColumn<OrganizationUnitTypeItem>[] = [
|
const unitTypeColumns: DataGridColumn<OrganizationUnitTypeItem>[] = [
|
||||||
{ id: "name", header: "i18n:govoplan-organizations.name.709a2322", minWidth: 180, sortable: true, filterable: true, value: (row) => row.name },
|
{ id: "name", header: "i18n:govoplan-organizations.name.709a2322", minWidth: 180, sortable: true, filterable: true, value: (row) => row.name },
|
||||||
{ id: "slug", header: "i18n:govoplan-organizations.slug.094da9b9", width: 160, sortable: true, filterable: true, value: (row) => row.slug },
|
{ id: "slug", header: "i18n:govoplan-organizations.slug.094da9b9", width: 160, sortable: true, filterable: true, value: (row) => row.slug },
|
||||||
|
|||||||
Reference in New Issue
Block a user