Skip to content

Commit

Permalink
[4376] Add current selection as a URL search parameter
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 (id
and kind).
* Reversely, when resolving a URL with such search parameters, the
workbench selection is set to those specified elements.

Bug: eclipse-sirius#4376
Signed-off-by: Florent Latombe <[email protected]>
  • Loading branch information
flatombe committed Jan 24, 2025
1 parent c4886fc commit 45b3287
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 13 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ The new endpoints are:
** getBranchById (`GET /api/rest/projects/{projectId}/branches/{branchId}`): Get the branch represented by its Id for the given project. There is only one branch per project in Sirius Web for now, and its Id is the same as the project Id. It represents the current state of the project, without taking care of data created/updated/deleted since the creation of the project.
** deleteBranch (`DELETE /api/rest/projects/{projectId}/branches/{branchId}`): Delete the branch with the given Id in the given project. There is only one branch per project in Sirius Web for now, so the default implementation of this method does nothing.
- https://github.com/eclipse-sirius/sirius-web/issues/4440[#4440] [sirius-web] Add the representation description name in details view

- https://github.com/eclipse-sirius/sirius-web/issues/4376[#4376] [sirius-web] Add current workbench selection to the URL. Reversely, when resolving a URL, the specified elements automatically get selected.

=== Improvements

Expand Down
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 45b3287

Please sign in to comment.