diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index d85214804a..146f455f61 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -226,6 +226,8 @@ This will allow specifier to create images that fir perfectly in the project tem - https://github.com/eclipse-sirius/sirius-web/issues/4086[#4086] [form] Wrap widget returned by property section in a div with a specific classname - https://github.com/eclipse-sirius/sirius-web/issues/4088[#4088] [trees] Change tree item context menu entries internal management - https://github.com/eclipse-sirius/sirius-web/issues/4130[#4130] [sirius-web] The `sirius-web-application` package now exports `useExplorerSubscription` and `useRelatedElementsViewSubscription`. +- https://github.com/eclipse-sirius/sirius-web/issues/4086[#4086] [form] Wrap widget returned by property section in a div with a specific classname +- https://github.com/eclipse-sirius/sirius-web/issues/3533[#3553] [diagram] Add a dedicated component to handle diagram subscription == v2024.9.0 @@ -514,6 +516,7 @@ We cannot rely on the error message recaived from the backend since Cross Origin - https://github.com/eclipse-sirius/sirius-web/issues/3701[#3701] [domain] Add edge and node tools to domain diagram including creation tools as well as delete and direct edit tools. - https://github.com/eclipse-sirius/sirius-web/issues/3859[#3859] [view] Allow name duplication in ecore by grouping builders in dedicated packages + == v2024.5.0 === Shapes diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/representation/DiagramRepresentation.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/representation/DiagramRepresentation.tsx index f0811de6cb..061a974a22 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/representation/DiagramRepresentation.tsx +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/representation/DiagramRepresentation.tsx @@ -11,20 +11,12 @@ * Obeo - initial API and implementation *******************************************************************************/ -import { gql, OnDataOptions, useQuery, useSubscription } from '@apollo/client'; +import { gql, useQuery } from '@apollo/client'; import { RepresentationComponentProps, useMultiToast } from '@eclipse-sirius/sirius-components-core'; import { ReactFlowProvider } from '@xyflow/react'; import { memo, useEffect, useState } from 'react'; -import { DiagramContext } from '../contexts/DiagramContext'; import { DiagramDescriptionContext } from '../contexts/DiagramDescriptionContext'; -import { DialogContextProvider } from '../dialog/DialogContext'; -import { diagramEventSubscription } from '../graphql/subscription/diagramEventSubscription'; -import { - GQLDiagramEventPayload, - GQLDiagramRefreshedEventPayload, -} from '../graphql/subscription/diagramEventSubscription.types'; import { ConnectorContextProvider } from '../renderer/connector/ConnectorContext'; -import { DiagramRenderer } from '../renderer/DiagramRenderer'; import { DiagramDirectEditContextProvider } from '../renderer/direct-edit/DiagramDirectEditContext'; import { DropNodeContextProvider } from '../renderer/dropNode/DropNodeContext'; import { MarkerDefinitions } from '../renderer/edge/MarkerDefinitions'; @@ -37,12 +29,8 @@ import { GQLDiagramDescription, GQLDiagramDescriptionData, GQLDiagramDescriptionVariables, - GQLDiagramEventData, - GQLDiagramEventVariables, } from './DiagramRepresentation.types'; -import { StoreContextProvider } from './StoreContext'; - -const subscription = gql(diagramEventSubscription); +import { DiagramSubscriptionProvider } from './DiagramSubscriptionProvider'; export const getDiagramDescription = gql` query getDiagramDescription($editingContextId: ID!, $representationId: ID!) { @@ -75,38 +63,14 @@ export const getDiagramDescription = gql` } `; -const isDiagramRefreshedEventPayload = (payload: GQLDiagramEventPayload): payload is GQLDiagramRefreshedEventPayload => - payload.__typename === 'DiagramRefreshedEventPayload'; - export const DiagramRepresentation = memo( ({ editingContextId, representationId, readOnly }: RepresentationComponentProps) => { const [state, setState] = useState({ id: crypto.randomUUID(), - diagramRefreshedEventPayload: null, - payload: null, - complete: false, message: null, }); const { addErrorMessage } = useMultiToast(); - const variables: GQLDiagramEventVariables = { - input: { - id: state.id, - editingContextId, - diagramId: representationId, - }, - }; - - const onData = ({ data }: OnDataOptions) => { - if (data.data) { - const { diagramEvent } = data.data; - if (isDiagramRefreshedEventPayload(diagramEvent)) { - setState((prevState) => ({ ...prevState, diagramRefreshedEventPayload: diagramEvent })); - } - setState((prevState) => ({ ...prevState, payload: diagramEvent })); - } - }; - const { loading: diagramDescriptionLoading, data: diagramDescriptionData, @@ -116,7 +80,6 @@ export const DiagramRepresentation = memo( editingContextId, representationId, }, - skip: state.diagramRefreshedEventPayload === null, }); useEffect(() => { @@ -132,74 +95,40 @@ export const DiagramRepresentation = memo( } }, [diagramDescriptionLoading, diagramDescriptionData, diagramDescriptionError]); - const onComplete = () => { - setState((prevState) => ({ ...prevState, diagramRefreshedEventPayload: null, complete: true })); - }; - - const { error } = useSubscription(subscription, { - variables, - fetchPolicy: 'no-cache', - onData, - onComplete, - }); - const diagramDescription: GQLDiagramDescription | undefined = diagramDescriptionData?.viewer.editingContext.representation.description; if (state.message) { return
{state.message}
; } - if (error) { - return
{error.message}
; - } - if (state.complete) { - return
The representation is not available anymore
; - } - if (!state.diagramRefreshedEventPayload || !diagramDescription) { + + if (!diagramDescription) { return
; } return ( - - - - - - - - - -
- - - - - - -
-
-
-
-
-
-
-
-
-
+ + + + + + + + + + + + + + + + + +
); } diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/representation/DiagramRepresentation.types.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/representation/DiagramRepresentation.types.ts index 98224e5bed..30ff08eb3a 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/representation/DiagramRepresentation.types.ts +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/representation/DiagramRepresentation.types.ts @@ -12,16 +12,10 @@ *******************************************************************************/ import { GQLNodeDescription } from '../graphql/query/nodeDescriptionFragment.types'; -import { - GQLDiagramEventPayload, - GQLDiagramRefreshedEventPayload, -} from '../graphql/subscription/diagramEventSubscription.types'; +import { GQLDiagramEventPayload } from '../graphql/subscription/diagramEventSubscription.types'; export interface DiagramRepresentationState { id: string; - diagramRefreshedEventPayload: GQLDiagramRefreshedEventPayload | null; - payload: GQLDiagramEventPayload | null; - complete: boolean; message: string | null; } diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/representation/DiagramSubscriptionProvider.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/representation/DiagramSubscriptionProvider.tsx new file mode 100644 index 0000000000..20dc517485 --- /dev/null +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/representation/DiagramSubscriptionProvider.tsx @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2024 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +import LinearProgress from '@mui/material/LinearProgress'; +import Typography from '@mui/material/Typography'; +import { memo, useEffect, useState } from 'react'; +import { DiagramContext } from '../contexts/DiagramContext'; +import { + GQLDiagramEventPayload, + GQLDiagramRefreshedEventPayload, +} from '../graphql/subscription/diagramEventSubscription.types'; +import { DiagramRenderer } from '../renderer/DiagramRenderer'; +import { DiagramSubscriptionProviderProps, DiagramSubscriptionState } from './DiagramSubscriptionProvider.types'; +import { StoreContextProvider } from './StoreContext'; +import { useDiagramSubscription } from './useDiagramSubscription'; + +const isDiagramRefreshedEventPayload = ( + payload: GQLDiagramEventPayload | null +): payload is GQLDiagramRefreshedEventPayload => !!payload && payload.__typename === 'DiagramRefreshedEventPayload'; + +export const DiagramSubscriptionProvider = memo( + ({ diagramId, editingContextId, readOnly }: DiagramSubscriptionProviderProps) => { + const [state, setState] = useState({ + id: crypto.randomUUID(), + diagramRefreshedEventPayload: null, + complete: false, + message: '', + }); + + const { complete, payload } = useDiagramSubscription(editingContextId, diagramId); + + useEffect(() => { + if (isDiagramRefreshedEventPayload(payload)) { + setState((prevState) => ({ ...prevState, diagramRefreshedEventPayload: payload })); + } + }, [payload]); + + if (complete) { + return ( +
+ The representation is not available anymore +
+ ); + } + + if (!state.diagramRefreshedEventPayload) { + return ; + } + + return ( + + +
+ +
+
+
+ ); + } +); diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/representation/DiagramSubscriptionProvider.types.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/representation/DiagramSubscriptionProvider.types.ts new file mode 100644 index 0000000000..5896db7323 --- /dev/null +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/representation/DiagramSubscriptionProvider.types.ts @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2024 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +import { GQLDiagramRefreshedEventPayload } from '../graphql/subscription/diagramEventSubscription.types'; + +export type DiagramSubscriptionContextValue = { + diagramRefreshedEventPayload: GQLDiagramRefreshedEventPayload | null; + refreshEventPayloadId: string; +}; + +export type DiagramSubscriptionState = { + id: string; + diagramRefreshedEventPayload: GQLDiagramRefreshedEventPayload | null; + complete: boolean; + message: string; +}; + +export interface DiagramSubscriptionProviderProps { + editingContextId: string; + diagramId: string; + readOnly: boolean; +} diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/representation/useDiagramSubscription.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/representation/useDiagramSubscription.tsx new file mode 100644 index 0000000000..3b457d985d --- /dev/null +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/representation/useDiagramSubscription.tsx @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2024 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +import { gql, useSubscription } from '@apollo/client'; +import { useMultiToast } from '@eclipse-sirius/sirius-components-core'; +import { useEffect, useState } from 'react'; +import { diagramEventSubscription } from '../graphql/subscription/diagramEventSubscription'; +import { + GQLDiagramEventSubscription, + GQLDiagramEventVariables, + UseDiagramSubscriptionState, + UseDiagramSubscriptionValue, +} from './useDiagramSubscription.types'; + +export const useDiagramSubscription = (editingContextId: string, diagramId: string): UseDiagramSubscriptionValue => { + const [state, setState] = useState({ + id: crypto.randomUUID(), + complete: false, + payload: null, + }); + + const variables: GQLDiagramEventVariables = { + input: { + id: state.id, + editingContextId, + diagramId, + }, + }; + + const onComplete = () => { + setState((prevState) => ({ ...prevState, diagramRefreshedEventPayload: null, complete: true })); + }; + + const { error, loading, data } = useSubscription( + gql(diagramEventSubscription), + { + variables, + fetchPolicy: 'no-cache', + onComplete, + } + ); + + const { addErrorMessage } = useMultiToast(); + useEffect(() => { + if (error) { + addErrorMessage('An unexpected error has occurred, please refresh the page'); + } + }, [error]); + + return { + loading, + payload: data?.diagramEvent ?? null, + complete: state.complete, + }; +}; diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/representation/useDiagramSubscription.types.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/representation/useDiagramSubscription.types.ts new file mode 100644 index 0000000000..ab8be76c53 --- /dev/null +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/representation/useDiagramSubscription.types.ts @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2024 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +import { GQLDiagramEventPayload } from '../graphql/subscription/diagramEventSubscription.types'; +export interface UseDiagramSubscriptionValue { + loading: boolean; + payload: GQLDiagramEventPayload | null; + complete: boolean; +} + +export interface UseDiagramSubscriptionState { + id: string; + complete: boolean; + payload: GQLDiagramEventPayload | null; +} + +export interface GQLDiagramEventInput { + id: string; + editingContextId: string; + diagramId: string; +} + +export interface GQLDiagramEventVariables { + input: GQLDiagramEventInput; +} + +export interface GQLDiagramEventSubscription { + diagramEvent: GQLDiagramEventPayload; +}