Skip to content

Commit

Permalink
[1667] Make the contextual palette self contained
Browse files Browse the repository at this point in the history
Bug: #1667
Signed-off-by: Axel RICHARD <axel.richard@obeo.fr>
  • Loading branch information
AxelRICHARD authored and sbegaudeau committed Mar 8, 2023
1 parent e8151f2 commit dfbd9c4
Show file tree
Hide file tree
Showing 10 changed files with 663 additions and 311 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ This will allow us to easily compare the current layout algorithm and the new on
- https://github.com/eclipse-sirius/sirius-components/issues/1565[1565] [view] The definition of the View DSL now uses richer data types for most attributes.
This has no visible effect at the moment, but will allow better documentation, validation and configuration later.
- [studio] Add a project template for the Papaya domains and view
- https://github.com/eclipse-sirius/sirius-components/issues/1667[#1667] [diagram] Make the contextual palette self contained

== v2023.3.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,36 @@
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
import { gql, useQuery } from '@apollo/client';
import { ApolloError, gql, useMutation, useQuery } from '@apollo/client';
import IconButton from '@material-ui/core/IconButton';
import Snackbar from '@material-ui/core/Snackbar';
import { makeStyles } from '@material-ui/core/styles';
import CloseIcon from '@material-ui/icons/Close';
import { useMachine } from '@xstate/react';
import { useEffect } from 'react';
import { GQLCollapsingState, GQLDeletionPolicy } from '../representation/DiagramRepresentation.types';
import { Diagram } from '../sprotty/Diagram.types';
import { useCallback, useEffect } from 'react';
import { EditLabelAction, isWithEditableLabel, SModelElement } from 'sprotty';
import { v4 as uuid } from 'uuid';
import { GQLDeletionPolicy } from '../representation/DiagramRepresentation.types';
import { BorderNode, Diagram, Edge, Node, ViewModifier } from '../sprotty/Diagram.types';
import { HIDE_CONTEXTUAL_TOOLBAR_ACTION } from '../sprotty/DiagramServer';
import {
ContextualPaletteProps,
ContextualPaletteStyleProps,
GQLCollapsingState,
GQLErrorPayload,
GQLFadeDiagramElementData,
GQLFadeDiagramElementInput,
GQLFadeDiagramElementVariables,
GQLGetToolSectionsData,
GQLGetToolSectionsVariables,
GQLHideDiagramElementData,
GQLHideDiagramElementInput,
GQLHideDiagramElementVariables,
GQLTool,
GQLToolSection,
GQLUpdateCollapsingStateData,
GQLUpdateCollapsingStateInput,
GQLUpdateCollapsingStateVariables,
} from './ContextualPalette.types';
import {
ContextualPaletteContext,
Expand Down Expand Up @@ -86,6 +100,48 @@ export const getToolSectionsQuery = gql`
}
`;

const hideDiagramElementMutation = gql`
mutation hideDiagramElement($input: HideDiagramElementInput!) {
hideDiagramElement(input: $input) {
__typename
... on SuccessPayload {
id
}
... on ErrorPayload {
message
}
}
}
`;

const fadeDiagramElementMutation = gql`
mutation fadeDiagramElement($input: FadeDiagramElementInput!) {
fadeDiagramElement(input: $input) {
__typename
... on SuccessPayload {
id
}
... on ErrorPayload {
message
}
}
}
`;

const updateCollapsingStateMutation = gql`
mutation updateCollapsingState($input: UpdateCollapsingStateInput!) {
updateCollapsingState(input: $input) {
__typename
... on SuccessPayload {
id
}
... on ErrorPayload {
message
}
}
}
`;

const connectorTool = {
id: 'connector',
type: 'connector',
Expand Down Expand Up @@ -161,14 +217,12 @@ export const ContextualPalette = ({
editingContextId,
representationId,
diagramElement,
diagramServer,
renameable,
invokeTool,
invokeConnectorTool,
invokeLabelEdit,
invokeDelete,
invokeClose,
invokeHide,
invokeFade,
updateCollapsingState,
}: ContextualPaletteProps) => {
const [{ value, context }, dispatch] = useMachine<ContextualPaletteContext, ContextualPaletteEvent>(
contextualPaletteMachine
Expand Down Expand Up @@ -209,6 +263,99 @@ export const ContextualPalette = ({
toolSection.tools.some((tool) => tool.__typename === 'SingleClickOnTwoDiagramElementsTool')
);

let invokeLabelEdit;
if (renameable && isWithEditableLabel(diagramElement)) {
invokeLabelEdit = () =>
diagramServer.actionDispatcher.dispatchAll([
{ kind: HIDE_CONTEXTUAL_TOOLBAR_ACTION },
EditLabelAction.create(diagramElement.editableLabel.id),
]);
}

const [
hideElementMutation,
{ loading: hideDiagramElementLoading, data: hideDiagramElementData, error: hideDiagramElementError },
] = useMutation<GQLHideDiagramElementData, GQLHideDiagramElementVariables>(hideDiagramElementMutation);

const hideElements = useCallback(
(diagramElements: SModelElement[]): void => {
const elements: Array<Edge | Node | BorderNode> = diagramElements
.filter((elem) => elem instanceof Edge || elem instanceof Node || elem instanceof BorderNode)
.map((elem) => elem as Edge | Node | BorderNode);
const elementIds = elements.map((elt) => elt.id);
// If at least one selected element is not hidden, we hide all selected elements
const hide = elements.some((elem) => elem.state !== ViewModifier.Hidden);

const input: GQLHideDiagramElementInput = {
id: uuid(),
editingContextId,
representationId,
elementIds,
hide,
};
hideElementMutation({ variables: { input } });
invokeClose();
},
[editingContextId, representationId, hideElementMutation, invokeClose]
);

const [
fadeElementMutation,
{ loading: fadeDiagramElementLoading, data: fadeDiagramElementData, error: fadeDiagramElementError },
] = useMutation<GQLFadeDiagramElementData, GQLFadeDiagramElementVariables>(fadeDiagramElementMutation);

const fadeElements = useCallback(
(diagramElements: SModelElement[]): void => {
const elements: Array<Edge | Node | BorderNode> = diagramElements
.filter((elem) => elem instanceof Edge || elem instanceof Node || elem instanceof BorderNode)
.map((elem) => elem as Edge | Node | BorderNode);
const elementIds = elements.map((elt) => elt.id);
// If at least one selected element is not hidden, we fade all selected elements
const fade = elements.some((elem) => elem.state !== ViewModifier.Hidden);

const input: GQLFadeDiagramElementInput = {
id: uuid(),
editingContextId,
representationId,
elementIds,
fade,
};
fadeElementMutation({ variables: { input } });
invokeClose();
},
[editingContextId, representationId, fadeElementMutation, invokeClose]
);

const invokeHide = () => hideElements([diagramElement]);
const invokeFade = () => fadeElements([diagramElement]);

const [
collapseExpandMutation,
{
loading: collapseExpandDiagramElementLoading,
data: collapseExpandDiagramElementData,
error: collapseExpandDiagramElementError,
},
] = useMutation<GQLUpdateCollapsingStateData, GQLUpdateCollapsingStateVariables>(updateCollapsingStateMutation);

const collapseExpandElement = useCallback(
(nodeId: string, collapsingState: GQLCollapsingState) => {
const input: GQLUpdateCollapsingStateInput = {
id: uuid(),
editingContextId,
representationId,
diagramElementId: nodeId,
collapsingState,
};
collapseExpandMutation({ variables: { input } });
invokeClose();
},
[editingContextId, representationId, collapseExpandMutation]
);

const updateCollapsingState = (collapsingState: GQLCollapsingState) =>
collapseExpandElement(diagramElement.id, collapsingState);

let toolSectionsCount = toolSections.length + 1;
if (atLeastOneSingleClickOnTwoDiagramElementsTool) {
toolSectionsCount = toolSectionsCount + 1;
Expand All @@ -217,6 +364,57 @@ export const ContextualPalette = ({
toolSectionsCount = toolSectionsCount + 1;
}

const isErrorPayload = (payload): payload is GQLErrorPayload => payload.__typename === 'ErrorPayload';

const handleError = useCallback(
(loading: boolean, data, error: ApolloError) => {
if (!loading) {
if (error) {
const showToastEvent: ShowToastEvent = {
type: 'SHOW_TOAST',
message: 'An error has occurred while executing this action, please contact the server administrator',
};
dispatch(showToastEvent);
}
if (data) {
const keys = Object.keys(data);
if (keys.length > 0) {
const firstKey = keys[0];
const firstField = data[firstKey];
if (isErrorPayload(firstField)) {
const { message } = firstField;
const showToastEvent: ShowToastEvent = {
type: 'SHOW_TOAST',
message,
};
dispatch(showToastEvent);
}
}
}
}
},
[dispatch]
);

useEffect(() => {
handleError(hideDiagramElementLoading, hideDiagramElementData, hideDiagramElementError);
}, [hideDiagramElementLoading, hideDiagramElementData, hideDiagramElementError, handleError]);
useEffect(() => {
handleError(fadeDiagramElementLoading, fadeDiagramElementData, fadeDiagramElementError);
}, [fadeDiagramElementLoading, fadeDiagramElementData, fadeDiagramElementError, handleError]);
useEffect(() => {
handleError(
collapseExpandDiagramElementLoading,
collapseExpandDiagramElementData,
collapseExpandDiagramElementError
);
}, [
collapseExpandDiagramElementLoading,
collapseExpandDiagramElementData,
collapseExpandDiagramElementError,
handleError,
]);

const props: ContextualPaletteStyleProps = { toolSectionsCount };
const classes = useContextualPaletteStyle(props);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,19 @@
* Obeo - initial API and implementation
*******************************************************************************/
import { SModelElement } from 'sprotty';
import { GQLCollapsingState, GQLDeletionPolicy } from '../representation/DiagramRepresentation.types';
import { GQLDeletionPolicy } from '../representation/DiagramRepresentation.types';
import { DiagramServer } from '../sprotty/DiagramServer';

export interface ContextualPaletteProps {
editingContextId: string;
representationId: string;
diagramElement: SModelElement;
diagramServer: DiagramServer;
renameable: boolean;
invokeTool: (tool: GQLTool) => void;
invokeConnectorTool: (toolSections: GQLToolSection[]) => void;
invokeLabelEdit: () => void | null;
invokeDelete: (deletionPolicy: GQLDeletionPolicy) => void | null;
invokeClose: () => void;
invokeHide: () => void;
invokeFade: () => void;
updateCollapsingState: (collapsingState: GQLCollapsingState) => void;
}

export interface ContextualPaletteStyleProps {
Expand Down Expand Up @@ -95,3 +94,72 @@ export interface GQLSingleClickOnTwoDiagramElementsCandidate {
export interface GQLNodeDescription {
id: string;
}

export interface GQLHideDiagramElementInput {
id: string;
editingContextId: string;
representationId: string;
elementIds: string[];
hide: boolean;
}

export interface GQLHideDiagramElementVariables {
input: GQLHideDiagramElementInput;
}

export interface GQLHideDiagramElementPayload {
__typename: string;
}
export interface GQLHideDiagramElementData {
hideDiagramElement: GQLHideDiagramElementPayload;
}

export interface GQLFadeDiagramElementInput {
id: string;
editingContextId: string;
representationId: string;
elementIds: string[];
fade: boolean;
}

export interface GQLFadeDiagramElementVariables {
input: GQLFadeDiagramElementInput;
}

export interface GQLFadeDiagramElementPayload {
__typename: string;
}
export interface GQLFadeDiagramElementData {
fadeDiagramElement: GQLFadeDiagramElementPayload;
}
export enum GQLCollapsingState {
EXPANDED = 'EXPANDED',
COLLAPSED = 'COLLAPSED',
}

export interface GQLUpdateCollapsingStateVariables {
input: GQLUpdateCollapsingStateInput;
}

export interface GQLUpdateCollapsingStateInput {
id: string;
editingContextId: string;
representationId: string;
diagramElementId: string;
collapsingState: GQLCollapsingState;
}

export interface GQLUpdateCollapsingStateData {
collapseExpandDiagramElement: GQLUpdateCollapsingStatePayload;
}

export interface GQLUpdateCollapsingStatePayload {
__typename: string;
}

export interface GQLErrorPayload
extends GQLFadeDiagramElementPayload,
GQLHideDiagramElementPayload,
GQLUpdateCollapsingStatePayload {
message: string;
}

0 comments on commit dfbd9c4

Please sign in to comment.