Skip to content

Commit

Permalink
[4376] Add current selection as a URL search parameter (WIP2)
Browse files Browse the repository at this point in the history
* When the workbench selection changes, the URL search parameters are
now automatically updated to encode the contents of the selection.
* Reversely, when resolving a URL with such search parameters, the
workbench selection is set to those specified elements.

Known limitations/bugs:
* Start from a (diagram) representation with a selection of elements in
the diagram. Select either the diagram representation in the 'Explorer'
view, or the diagram background. The selection gets set to the diagram
representation, but quickly evolves into an empty selection. This does
not occur when starting from a selection of elements that are not shown
in the diagram, or from an empty selection.
* When loading a URL with an opened representation and a selection of
elements, the selection is properly applied in the 'Explorer' view, but
not in the diagram.

Bug: eclipse-sirius#4376
Signed-off-by: Florent Latombe <[email protected]>
  • Loading branch information
flatombe committed Jan 23, 2025
1 parent c4886fc commit bf6f604
Showing 1 changed file with 62 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ import {
RepresentationMetadata,
Selection,
SelectionContextProvider,
SelectionEntry,
useData,
useSelection,
UseSelectionValue,
Workbench,
} from '@eclipse-sirius/sirius-components-core';
import { OmniboxContextEntry, OmniboxProvider } from '@eclipse-sirius/sirius-components-omnibox';
Expand Down Expand Up @@ -64,12 +67,64 @@ const useEditProjectViewStyles = makeStyles()((_) => ({
},
}));

function createSelectionFromUrlSearchParams(urlSearchParams: URLSearchParams): Selection {
if (urlSearchParams !== null && urlSearchParams.has('selection')) {
const urlSelectionContents: Array<string> = urlSearchParams.get('selection').split(',');
const selectionEntries: Array<SelectionEntry> = urlSelectionContents.map((urlSelectionElement) => {
const [projectElementId, projectElementKind] = urlSelectionElement.split(';');
return { id: projectElementId, kind: projectElementKind };
});
return { entries: selectionEntries };
} else {
return null;
}
}

function updateUrlSearchParamsWithSelection(setUrlSearchParams: SetURLSearchParams, selection: Selection) {
setUrlSearchParams((previousSearchParams: URLSearchParams) => {
if (selection?.entries.length > 0) {
const selectionValue: string = selection.entries
.map((selectionEntry) => `${selectionEntry.id};${selectionEntry.kind}`)
.join(',');
previousSearchParams.set('selection', selectionValue);
} else {
if (previousSearchParams.has('selection')) {
previousSearchParams.delete('selection');
}
}
return previousSearchParams;
});
}

function updateSelectionBasedOnUrlSearchParamsIfNeeded(
urlSearchParams: URLSearchParams,
currentSelection: Selection,
setSelection: (selection: Selection) => void
) {
if (urlSearchParams?.has('selection')) {
const urlSelection: Selection = createSelectionFromUrlSearchParams(urlSearchParams);
if (!areSelectionContentsEqual(urlSelection, currentSelection)) {
setSelection(createSelectionFromUrlSearchParams(urlSearchParams));
}
}
}

function areSelectionContentsEqual(left: Selection, right: Selection): boolean {
return (
left?.entries.length == right?.entries.length &&
left?.entries.every(
(element, index) => element.id === right?.entries[index].id && element.kind === right?.entries[index].kind
)
);
}

export const EditProjectView = () => {
const navigate = useNavigate();
const routeMatch = useResolvedPath('.');
const { projectId, representationId } = useParams<EditProjectViewParams>();
const { classes } = useEditProjectViewStyles();
const [urlSearchParams]: [URLSearchParams, SetURLSearchParams] = useSearchParams();
const [urlSearchParams, setUrlSearchParams]: [URLSearchParams, SetURLSearchParams] = useSearchParams();
const { selection, setSelection }: UseSelectionValue = useSelection();

const [{ value, context }, dispatch] =
useMachine<StateMachine<EditProjectViewContext, EditProjectViewStateSchema, EditProjectViewEvent>>(
Expand All @@ -92,7 +147,9 @@ export const EditProjectView = () => {
dispatch(selectRepresentationEvent);
};

const workbenchOnSelectionChanged = () => {};
const workbenchOnSelectionChanged = (selection: Selection) => {
updateUrlSearchParamsWithSelection(setUrlSearchParams, selection);
};

useEffect(() => {
let pathname: string = null;
Expand All @@ -117,6 +174,8 @@ export const EditProjectView = () => {
}
}, [value, projectId, routeMatch, history, context.representation, representationId, urlSearchParams]);

updateSelectionBasedOnUrlSearchParamsIfNeeded(urlSearchParams, selection, setSelection);

let content: React.ReactNode = null;

if (value === 'loading') {
Expand All @@ -130,16 +189,7 @@ export const EditProjectView = () => {
const { data: readOnlyPredicate } = useData(editProjectViewReadOnlyPredicateExtensionPoint);

if (value === 'loaded' && context.project) {
const initialSelection: Selection = {
entries: context.representation
? [
{
id: context.representation.id,
kind: context.representation.kind,
},
]
: [],
};
const initialSelection: Selection = createSelectionFromUrlSearchParams(urlSearchParams);

const readOnly = readOnlyPredicate(context.project);
const initialContextEntries: OmniboxContextEntry[] = [
Expand Down

0 comments on commit bf6f604

Please sign in to comment.