diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/project/dto/NatureDTO.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/project/dto/NatureDTO.java new file mode 100644 index 00000000000..a20fe5a7beb --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/project/dto/NatureDTO.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +package org.eclipse.sirius.web.application.project.dto; + +import jakarta.validation.constraints.NotNull; + +/** + * DTO used to represent the nature of a project. + * + * @author sbegaudeau + */ +public record NatureDTO(@NotNull String name) { +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/project/dto/ProjectDTO.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/project/dto/ProjectDTO.java index 7561b8bc824..76e1fe2508a 100644 --- a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/project/dto/ProjectDTO.java +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/project/dto/ProjectDTO.java @@ -12,6 +12,7 @@ *******************************************************************************/ package org.eclipse.sirius.web.application.project.dto; +import java.util.List; import java.util.UUID; import jakarta.validation.constraints.NotNull; @@ -23,5 +24,6 @@ */ public record ProjectDTO( @NotNull UUID id, - @NotNull String name) { + @NotNull String name, + @NotNull List natures) { } diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/project/services/ProjectMapper.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/project/services/ProjectMapper.java index a72de83694e..825c3898072 100644 --- a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/project/services/ProjectMapper.java +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/project/services/ProjectMapper.java @@ -12,6 +12,7 @@ *******************************************************************************/ package org.eclipse.sirius.web.application.project.services; +import org.eclipse.sirius.web.application.project.dto.NatureDTO; import org.eclipse.sirius.web.application.project.services.api.IProjectMapper; import org.eclipse.sirius.web.domain.boundedcontexts.project.Project; import org.eclipse.sirius.web.application.project.dto.ProjectDTO; @@ -26,6 +27,9 @@ public class ProjectMapper implements IProjectMapper { @Override public ProjectDTO toDTO(Project project) { - return new ProjectDTO(project.getId(), project.getName()); + var natures = project.getNatures().stream() + .map(nature -> new NatureDTO(nature.name())) + .toList(); + return new ProjectDTO(project.getId(), project.getName(), natures); } } diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/resources/schema/siriusweb.graphqls b/packages/sirius-web/backend/sirius-web-application/src/main/resources/schema/siriusweb.graphqls index d9e6f3d3d7d..76fd8d6953b 100644 --- a/packages/sirius-web/backend/sirius-web-application/src/main/resources/schema/siriusweb.graphqls +++ b/packages/sirius-web/backend/sirius-web-application/src/main/resources/schema/siriusweb.graphqls @@ -17,6 +17,11 @@ type Project { id: ID! name: String! currentEditingContext: EditingContext! + natures: [Nature!]! +} + +type Nature { + name: String! } type ViewerProjectTemplatesConnection { diff --git a/packages/sirius-web/backend/sirius-web-graphql/src/main/resources/schema/siriusweb.graphqls b/packages/sirius-web/backend/sirius-web-graphql/src/main/resources/schema/siriusweb.graphqls index b1e245b86f3..10696f8861f 100644 --- a/packages/sirius-web/backend/sirius-web-graphql/src/main/resources/schema/siriusweb.graphqls +++ b/packages/sirius-web/backend/sirius-web-graphql/src/main/resources/schema/siriusweb.graphqls @@ -18,6 +18,11 @@ type Project { name: String! currentEditingContext: EditingContext! images: [ImageMetadata!]! + natures: [Nature!]! +} + +type Nature { + name: String! } extend type Subscription { diff --git a/packages/sirius-web/backend/sirius-web-services-api/src/main/java/org/eclipse/sirius/web/services/api/projects/Project.java b/packages/sirius-web/backend/sirius-web-services-api/src/main/java/org/eclipse/sirius/web/services/api/projects/Project.java index 1f168387f1a..b7d3adad3a0 100644 --- a/packages/sirius-web/backend/sirius-web-services-api/src/main/java/org/eclipse/sirius/web/services/api/projects/Project.java +++ b/packages/sirius-web/backend/sirius-web-services-api/src/main/java/org/eclipse/sirius/web/services/api/projects/Project.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019, 2023 Obeo. + * Copyright (c) 2019, 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 @@ -13,6 +13,7 @@ package org.eclipse.sirius.web.services.api.projects; import java.text.MessageFormat; +import java.util.List; import java.util.Objects; import java.util.UUID; @@ -26,9 +27,12 @@ public class Project { private final String name; - public Project(UUID id, String name) { + private final List natures; + + public Project(UUID id, String name, List natures) { this.id = Objects.requireNonNull(id); this.name = Objects.requireNonNull(name); + this.natures = Objects.requireNonNull(natures); } public UUID getId() { @@ -39,6 +43,10 @@ public String getName() { return this.name; } + public List getNatures() { + return this.natures; + } + @Override public String toString() { String pattern = "{0} '{'id: {1}, name: {2}'}'"; diff --git a/packages/sirius-web/backend/sirius-web-services/src/main/java/org/eclipse/sirius/web/services/documents/DocumentMapper.java b/packages/sirius-web/backend/sirius-web-services/src/main/java/org/eclipse/sirius/web/services/documents/DocumentMapper.java index d51c9462c5f..bec398865bf 100644 --- a/packages/sirius-web/backend/sirius-web-services/src/main/java/org/eclipse/sirius/web/services/documents/DocumentMapper.java +++ b/packages/sirius-web/backend/sirius-web-services/src/main/java/org/eclipse/sirius/web/services/documents/DocumentMapper.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019, 2023 Obeo. + * Copyright (c) 2019, 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 @@ -12,6 +12,8 @@ *******************************************************************************/ package org.eclipse.sirius.web.services.documents; +import java.util.List; + import org.eclipse.sirius.web.persistence.entities.DocumentEntity; import org.eclipse.sirius.web.persistence.entities.ProjectEntity; import org.eclipse.sirius.web.services.api.document.Document; @@ -26,7 +28,7 @@ public class DocumentMapper { public Document toDTO(DocumentEntity documentEntity) { ProjectEntity projectEntity = documentEntity.getProject(); - Project project = new Project(projectEntity.getId(), projectEntity.getName()); + Project project = new Project(projectEntity.getId(), projectEntity.getName(), List.of()); return new Document(documentEntity.getId(), project, documentEntity.getName(), documentEntity.getContent()); } } diff --git a/packages/sirius-web/backend/sirius-web-services/src/main/java/org/eclipse/sirius/web/services/projects/ProjectMapper.java b/packages/sirius-web/backend/sirius-web-services/src/main/java/org/eclipse/sirius/web/services/projects/ProjectMapper.java index eb982634060..1d6eeb99a07 100644 --- a/packages/sirius-web/backend/sirius-web-services/src/main/java/org/eclipse/sirius/web/services/projects/ProjectMapper.java +++ b/packages/sirius-web/backend/sirius-web-services/src/main/java/org/eclipse/sirius/web/services/projects/ProjectMapper.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019, 2023 Obeo. + * Copyright (c) 2019, 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 @@ -12,6 +12,8 @@ *******************************************************************************/ package org.eclipse.sirius.web.services.projects; +import java.util.List; + import org.eclipse.sirius.web.persistence.entities.ProjectEntity; import org.eclipse.sirius.web.services.api.projects.Project; @@ -22,6 +24,6 @@ */ public class ProjectMapper { public Project toDTO(ProjectEntity projectEntity) { - return new Project(projectEntity.getId(), projectEntity.getName()); + return new Project(projectEntity.getId(), projectEntity.getName(), List.of()); } } diff --git a/packages/sirius-web/frontend/sirius-web-application/src/index.ts b/packages/sirius-web/frontend/sirius-web-application/src/index.ts index b3d2389eaf6..0debc3a29e9 100644 --- a/packages/sirius-web/frontend/sirius-web-application/src/index.ts +++ b/packages/sirius-web/frontend/sirius-web-application/src/index.ts @@ -42,6 +42,9 @@ export { export { routerExtensionPoint } from './router/RouterExtensionPoints'; export { type EditProjectNavbarSubtitleProps } from './views/edit-project/EditProjectNavbar/EditProjectNavbar.types'; export { editProjectNavbarSubtitleExtensionPoint } from './views/edit-project/EditProjectNavbar/EditProjectNavbarExtensionPoints'; +export { useCurrentProject } from './views/edit-project/useCurrentProject'; +export type { UseCurrentProjectValue } from './views/edit-project/useCurrentProject.types'; +export type { GQLProject } from './views/edit-project/useProjectAndRepresentationMetadata.types'; export { type CreateProjectAreaCardProps } from './views/project-browser/create-projects-area/CreateProjectArea.types'; export { createProjectAreaCardExtensionPoint } from './views/project-browser/create-projects-area/CreateProjectAreaExtensionPoints'; export { projectActionButtonMenuItemExtensionPoint } from './views/project-browser/list-projects-area/ProjectActionButtonExtensionPoints'; diff --git a/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/EditProjectNavbar/EditProjectNavbar.types.ts b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/EditProjectNavbar/EditProjectNavbar.types.ts index 542a858fd9e..b828053ed7c 100644 --- a/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/EditProjectNavbar/EditProjectNavbar.types.ts +++ b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/EditProjectNavbar/EditProjectNavbar.types.ts @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021, 2023 Obeo. + * Copyright (c) 2021, 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 @@ -10,11 +10,10 @@ * Contributors: * Obeo - initial API and implementation *******************************************************************************/ - -import { Project } from '../EditProjectView.types'; +import { GQLProject } from '../useProjectAndRepresentationMetadata.types'; export interface EditProjectNavbarProps { - project: Project; + project: GQLProject; } export interface EditProjectNavbarSubtitleProps {} diff --git a/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/EditProjectView.tsx b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/EditProjectView.tsx index 1daeec63953..edd81471b9c 100644 --- a/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/EditProjectView.tsx +++ b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/EditProjectView.tsx @@ -10,12 +10,10 @@ * Contributors: * Obeo - initial API and implementation *******************************************************************************/ -import { gql, useQuery } from '@apollo/client'; import { RepresentationMetadata, Selection, SelectionContextProvider, - Toast, Workbench, } from '@eclipse-sirius/sirius-components-core'; import { @@ -36,48 +34,26 @@ import { import Grid from '@material-ui/core/Grid'; import Typography from '@material-ui/core/Typography'; import { makeStyles } from '@material-ui/core/styles'; -import { useMachine } from '@xstate/react'; -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; import { generatePath, useHistory, useParams, useRouteMatch } from 'react-router-dom'; import { useNodes } from 'reactflow'; import { NavigationBar } from '../../navigationBar/NavigationBar'; import { DiagramTreeItemContextMenuContribution } from './DiagramTreeItemContextMenuContribution'; import { DocumentTreeItemContextMenuContribution } from './DocumentTreeItemContextMenuContribution'; import { EditProjectNavbar } from './EditProjectNavbar/EditProjectNavbar'; -import { EditProjectViewParams, GQLGetProjectQueryData, GQLGetProjectQueryVariables } from './EditProjectView.types'; import { - EditProjectViewContext, - EditProjectViewEvent, - HandleFetchedProjectEvent, - HideToastEvent, - SchemaValue, - SelectRepresentationEvent, - ShowToastEvent, - editProjectViewMachine, -} from './EditProjectViewMachine'; + DiagramPaletteToolProviderProps, + EditProjectViewParams, + EditProjectViewState, + TreeItemContexMenuProviderProps, + TreeToolBarProviderProps, +} from './EditProjectView.types'; import { ObjectTreeItemContextMenuContribution } from './ObjectTreeItemContextMenuContribution'; +import { ProjectContext } from './ProjectContext'; import { PapayaOperationActivityLabelDetailToolContribution } from './ToolContributions/PapayaOperationActivityLabelDetailToolContribution'; import { NewDocumentModalContribution } from './TreeToolBarContributions/NewDocumentModalContribution'; import { UploadDocumentModalContribution } from './TreeToolBarContributions/UploadDocumentModalContribution'; - -const getProjectQuery = gql` - query getRepresentation($projectId: ID!, $representationId: ID!, $includeRepresentation: Boolean!) { - viewer { - project(projectId: $projectId) { - id - name - currentEditingContext { - id - representation(representationId: $representationId) @include(if: $includeRepresentation) { - id - label - kind - } - } - } - } - } -`; +import { useProjectAndRepresentationMetadata } from './useProjectAndRepresentationMetadata'; const useEditProjectViewStyles = makeStyles((_) => ({ editProjectView: { @@ -94,161 +70,159 @@ export const EditProjectView = () => { const routeMatch = useRouteMatch(); const { projectId, representationId } = useParams(); const classes = useEditProjectViewStyles(); - const [{ value, context }, dispatch] = useMachine( - editProjectViewMachine - ); - const { toast, editProjectView } = value as SchemaValue; - const { project, representation, message } = context; - const { loading, data, error } = useQuery(getProjectQuery, { - variables: { - projectId, - representationId: representationId ?? '', - includeRepresentation: !!representationId, - }, + const [state, setState] = useState({ + project: null, + representationSelected: null, }); + + const { loading, data } = useProjectAndRepresentationMetadata( + projectId, + representationId, + projectId === state.project?.id + ); useEffect(() => { - if (!loading) { - if (error) { - const showToastEvent: ShowToastEvent = { - type: 'SHOW_TOAST', - message: 'An unexpected error has occurred, please refresh the page', - }; - dispatch(showToastEvent); - } - if (data) { - const fetchProjectEvent: HandleFetchedProjectEvent = { type: 'HANDLE_FETCHED_PROJECT', data }; - dispatch(fetchProjectEvent); + if (data) { + const { project } = data.viewer; + if (project && project.id !== projectId) { + const { representation } = project.currentEditingContext; + const representationSelected: RepresentationMetadata | null = representation + ? { id: representation.id, label: representation.label, kind: representation.kind } + : null; + setState((prevState) => ({ ...prevState, project, representationSelected })); } } - }, [loading, data, error, dispatch]); + }, [data]); + + const onRepresentationSelected = (representationMetadata: RepresentationMetadata) => + setState((prevState) => ({ ...prevState, representationSelected: representationMetadata })); useEffect(() => { - if (representation && representation.id !== representationId) { - const pathname = generatePath(routeMatch.path, { projectId, representationId: representation.id }); + if (state.project && state.representationSelected && state.representationSelected.id !== representationId) { + const pathname = generatePath(routeMatch.path, { projectId, representationId: state.representationSelected.id }); history.push({ pathname }); - } else if (editProjectView === 'loaded' && representation === null && representationId) { + } else if (state.project && state.representationSelected === null && representationId) { const pathname = generatePath(routeMatch.path, { projectId, representationId: null }); history.push({ pathname }); } - }, [editProjectView, projectId, routeMatch, history, representation, representationId]); - - let initialSelection: Selection = null; - if (representation) { - initialSelection = { - entries: [ - { - id: representation?.id, - label: representation?.label, - kind: representation?.kind, - }, - ], - }; - } - - let main = null; - if (editProjectView === 'loaded' && project) { - const onRepresentationSelected = (representationSelected: RepresentationMetadata) => { - const selectRepresentationEvent: SelectRepresentationEvent = { - type: 'SELECT_REPRESENTATION', - representation: representationSelected, - }; - dispatch(selectRepresentationEvent); - }; - - const treeItemContextMenuContributions: TreeItemContextMenuContextValue = [ - - treeId.startsWith('explorer://') && item.kind.startsWith('siriusWeb://document') - } - component={DocumentTreeItemContextMenuContribution} - />, - - treeId.startsWith('explorer://') && item.kind.startsWith('siriusComponents://semantic') - } - component={ObjectTreeItemContextMenuContribution} - />, - - treeId.startsWith('explorer://') && item.kind === 'siriusComponents://representation?type=Diagram' - } - component={DiagramTreeItemContextMenuContribution} - />, - ]; + }, [state.project, state.representationSelected, routeMatch, history, projectId, representationId]); - const treeToolBarContributions: TreeToolBarContextValue = [ - , - , - ]; - const diagramPaletteToolContributions: DiagramPaletteToolContextValue = [ - { - const nodes = useNodes(); - const targetedNode = nodes.find((node) => node.id === diagramElementId); - if (targetedNode) { - return ( - targetedNode.data.targetObjectKind === - 'siriusComponents://semantic?domain=papaya_operational_analysis&entity=OperationalActivity' - ); - } - return false; - }} - component={PapayaOperationActivityLabelDetailToolContribution} - />, - ]; - - main = ( - - - - - - - - ); - } else if (editProjectView === 'missing') { - main = ( - - - The project does not exist - - + if (loading && state.project === null) { + return ( +
+ +
); } - let navbar = null; - if (editProjectView === 'missing' || editProjectView === 'loading') { - navbar = ; - } else if (editProjectView === 'loaded') { - navbar = ; - } - - if (editProjectView !== 'loaded') { + if (data && !data.viewer.project) { return (
- {navbar} - {main} + + + + The project does not exist + +
); } + const { project } = data.viewer; + const { representation } = project.currentEditingContext; + const initialSelection: Selection = { + entries: representation + ? [ + { + id: representation.id, + label: representation.label, + kind: representation.kind, + }, + ] + : [], + }; + return ( - -
- {navbar} - {main} -
- dispatch({ type: 'HIDE_TOAST' } as HideToastEvent)} - /> -
+ + +
+ + + + + + + + +
+
+
+ ); +}; + +const TreeItemContexMenuProvider = ({ children }: TreeItemContexMenuProviderProps) => { + const treeItemContextMenuContributions: TreeItemContextMenuContextValue = [ + + treeId.startsWith('explorer://') && item.kind.startsWith('siriusWeb://document') + } + component={DocumentTreeItemContextMenuContribution} + />, + + treeId.startsWith('explorer://') && item.kind.startsWith('siriusComponents://semantic') + } + component={ObjectTreeItemContextMenuContribution} + />, + + treeId.startsWith('explorer://') && item.kind === 'siriusComponents://representation?type=Diagram' + } + component={DiagramTreeItemContextMenuContribution} + />, + ]; + + return ( + + {children} + + ); +}; + +const TreeToolBarProvider = ({ children }: TreeToolBarProviderProps) => { + const treeToolBarContributions: TreeToolBarContextValue = [ + , + , + ]; + + return {children}; +}; + +const DiagramPaletteToolProvider = ({ children }: DiagramPaletteToolProviderProps) => { + const diagramPaletteToolContributions: DiagramPaletteToolContextValue = [ + { + const nodes = useNodes(); + const targetedNode = nodes.find((node) => node.id === diagramElementId); + if (targetedNode) { + return ( + targetedNode.data.targetObjectKind === + 'siriusComponents://semantic?domain=papaya_operational_analysis&entity=OperationalActivity' + ); + } + return false; + }} + component={PapayaOperationActivityLabelDetailToolContribution} + />, + ]; + return ( + + {children} + ); }; diff --git a/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/EditProjectView.types.ts b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/EditProjectView.types.ts index dc52a97a55d..b3665db1c99 100644 --- a/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/EditProjectView.types.ts +++ b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/EditProjectView.types.ts @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021, 2023 Obeo and others. + * Copyright (c) 2021, 2024 Obeo and others. * 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 @@ -11,48 +11,27 @@ * Obeo - initial API and implementation *******************************************************************************/ -export type EditingContext = { - id: string; -}; +import { RepresentationMetadata } from '@eclipse-sirius/sirius-components-core'; +import { GQLProject } from './useProjectAndRepresentationMetadata.types'; -export type Project = { - id: string; - name: string; - currentEditingContext: EditingContext; -}; - -export type GQLRepresentationMetadata = { - id: string; - label: string; - kind: string; -}; - -export type GQLEditingContext = { - id: string; - representation: GQLRepresentationMetadata | undefined; -}; - -export type GQLProject = { - id: string; - name: string; - currentEditingContext: GQLEditingContext; -}; +export interface EditProjectViewParams { + projectId: string; + representationId: string; +} -export type GQLViewer = { - project: GQLProject; -}; +export interface EditProjectViewState { + project: GQLProject | null; + representationSelected: RepresentationMetadata | null; +} -export type GQLGetProjectQueryData = { - viewer: GQLViewer; -}; +export interface TreeItemContexMenuProviderProps { + children: React.ReactNode; +} -export type GQLGetProjectQueryVariables = { - projectId: string; - representationId: string; - includeRepresentation: boolean; -}; +export interface TreeToolBarProviderProps { + children: React.ReactNode; +} -export interface EditProjectViewParams { - projectId: string; - representationId: string; +export interface DiagramPaletteToolProviderProps { + children: React.ReactNode; } diff --git a/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/EditProjectViewMachine.ts b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/EditProjectViewMachine.ts deleted file mode 100644 index 7cfda0f6951..00000000000 --- a/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/EditProjectViewMachine.ts +++ /dev/null @@ -1,157 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2021, 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 { RepresentationMetadata } from '@eclipse-sirius/sirius-components-core'; -import { Machine, assign } from 'xstate'; -import { GQLGetProjectQueryData, Project } from './EditProjectView.types'; - -export interface EditProjectViewStateSchema { - states: { - toast: { - states: { - visible: {}; - hidden: {}; - }; - }; - editProjectView: { - states: { - loading: {}; - loaded: {}; - missing: {}; - }; - }; - }; -} - -export type SchemaValue = { - toast: 'visible' | 'hidden'; - editProjectView: 'loading' | 'loaded' | 'missing'; -}; - -export interface EditProjectViewContext { - project: Project | null; - representation: RepresentationMetadata | null; - message: string | null; -} - -export type ShowToastEvent = { type: 'SHOW_TOAST'; message: string }; -export type HideToastEvent = { type: 'HIDE_TOAST' }; -export type HandleFetchedProjectEvent = { type: 'HANDLE_FETCHED_PROJECT'; data: GQLGetProjectQueryData }; -export type SelectRepresentationEvent = { type: 'SELECT_REPRESENTATION'; representation: RepresentationMetadata }; -export type EditProjectViewEvent = - | HandleFetchedProjectEvent - | SelectRepresentationEvent - | ShowToastEvent - | HideToastEvent; - -export const editProjectViewMachine = Machine( - { - type: 'parallel', - context: { - project: null, - representation: null, - message: null, - }, - states: { - toast: { - initial: 'hidden', - states: { - hidden: { - on: { - SHOW_TOAST: { - target: 'visible', - actions: 'setMessage', - }, - }, - }, - visible: { - on: { - HIDE_TOAST: { - target: 'hidden', - actions: 'clearMessage', - }, - }, - }, - }, - }, - editProjectView: { - initial: 'loading', - states: { - loading: { - on: { - HANDLE_FETCHED_PROJECT: [ - { - cond: 'isMissing', - target: 'missing', - }, - { - target: 'loaded', - actions: 'updateProject', - }, - ], - }, - }, - loaded: { - type: 'final', - on: { - SELECT_REPRESENTATION: { - target: 'loaded', - actions: 'selectRepresentation', - }, - }, - }, - missing: { - type: 'final', - }, - }, - }, - }, - }, - { - guards: { - isMissing: (_, event) => { - const { data } = event as HandleFetchedProjectEvent; - return !data.viewer.project; - }, - }, - actions: { - updateProject: assign((_, event) => { - const { data } = event as HandleFetchedProjectEvent; - const { project: gQLProject } = data.viewer; - const { id, name, currentEditingContext } = gQLProject; - const project = { id, name, currentEditingContext: { id: currentEditingContext.id } }; - - let representation: RepresentationMetadata | null = null; - if (gQLProject.currentEditingContext.representation) { - representation = { - id: gQLProject.currentEditingContext.representation.id, - label: gQLProject.currentEditingContext.representation.label, - kind: gQLProject.currentEditingContext.representation.kind, - }; - } - - return { project, representation }; - }), - selectRepresentation: assign((_, event) => { - const { representation } = event as SelectRepresentationEvent; - return { representation }; - }), - setMessage: assign((_, event) => { - const { message } = event as ShowToastEvent; - return { message }; - }), - clearMessage: assign((_) => { - return { message: null }; - }), - }, - } -); diff --git a/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/ProjectContext.tsx b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/ProjectContext.tsx new file mode 100644 index 00000000000..a4180a9c82c --- /dev/null +++ b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/ProjectContext.tsx @@ -0,0 +1,29 @@ +/******************************************************************************* + * 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 React from 'react'; +import { ProjectContextValue } from './ProjectContext.types'; + +const value: ProjectContextValue = { + project: { + id: '', + name: '', + natures: [], + currentEditingContext: { + id: '', + representation: null, + }, + }, +}; + +export const ProjectContext = React.createContext(value); diff --git a/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/ProjectContext.types.ts b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/ProjectContext.types.ts new file mode 100644 index 00000000000..aab3f330115 --- /dev/null +++ b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/ProjectContext.types.ts @@ -0,0 +1,17 @@ +/******************************************************************************* + * 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 { GQLProject } from './useProjectAndRepresentationMetadata.types'; + +export interface ProjectContextValue { + project: GQLProject; +} diff --git a/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/useCurrentProject.ts b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/useCurrentProject.ts new file mode 100644 index 00000000000..001f5c4fe0c --- /dev/null +++ b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/useCurrentProject.ts @@ -0,0 +1,22 @@ +/******************************************************************************* + * 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 { useContext } from 'react'; +import { ProjectContext } from './ProjectContext'; +import { ProjectContextValue } from './ProjectContext.types'; +import { UseCurrentProjectValue } from './useCurrentProject.types'; + +export const useCurrentProject = (): UseCurrentProjectValue => { + const { project } = useContext(ProjectContext); + + return { project }; +}; diff --git a/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/useCurrentProject.types.ts b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/useCurrentProject.types.ts new file mode 100644 index 00000000000..34a132d7265 --- /dev/null +++ b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/useCurrentProject.types.ts @@ -0,0 +1,18 @@ +/******************************************************************************* + * 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 { GQLProject } from './useProjectAndRepresentationMetadata.types'; + +export interface UseCurrentProjectValue { + project: GQLProject; +} diff --git a/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/useProjectAndRepresentationMetadata.ts b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/useProjectAndRepresentationMetadata.ts new file mode 100644 index 00000000000..d0583221406 --- /dev/null +++ b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/useProjectAndRepresentationMetadata.ts @@ -0,0 +1,73 @@ +/******************************************************************************* + * 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, useQuery } from '@apollo/client'; +import { useMultiToast } from '@eclipse-sirius/sirius-components-core'; +import { useEffect } from 'react'; +import { + GQLGetProjectAndRepresentationMetadataQueryData, + GQLGetProjectAndRepresentationMetadataQueryVariables, + UseProjectAndRepresentationMetadataValue, +} from './useProjectAndRepresentationMetadata.types'; + +const getProjectQuery = gql` + query getRepresentation($projectId: ID!, $representationId: ID!, $includeRepresentation: Boolean!) { + viewer { + project(projectId: $projectId) { + id + name + natures { + name + } + currentEditingContext { + id + representation(representationId: $representationId) @include(if: $includeRepresentation) { + id + label + kind + } + } + } + } + } +`; + +export const useProjectAndRepresentationMetadata = ( + projectId: string, + representationId: string | null, + skip: boolean = false +): UseProjectAndRepresentationMetadataValue => { + const { loading, data, error } = useQuery< + GQLGetProjectAndRepresentationMetadataQueryData, + GQLGetProjectAndRepresentationMetadataQueryVariables + >(getProjectQuery, { + variables: { + projectId, + representationId: representationId ?? '', + includeRepresentation: !!representationId, + }, + skip, + }); + + const { addErrorMessage } = useMultiToast(); + useEffect(() => { + if (error) { + addErrorMessage(error.message); + } + }, [error]); + + return { + data: data ?? null, + loading, + }; +}; diff --git a/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/useProjectAndRepresentationMetadata.types.ts b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/useProjectAndRepresentationMetadata.types.ts new file mode 100644 index 00000000000..18255edd232 --- /dev/null +++ b/packages/sirius-web/frontend/sirius-web-application/src/views/edit-project/useProjectAndRepresentationMetadata.types.ts @@ -0,0 +1,53 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +export interface UseProjectAndRepresentationMetadataValue { + data: GQLGetProjectAndRepresentationMetadataQueryData | null; + loading: boolean; +} + +export interface GQLGetProjectAndRepresentationMetadataQueryVariables { + projectId: string; + representationId: string; + includeRepresentation: boolean; +} + +export interface GQLGetProjectAndRepresentationMetadataQueryData { + viewer: GQLViewer; +} + +export interface GQLViewer { + project: GQLProject | null; +} + +export interface GQLProject { + id: string; + name: string; + natures: GQLNature[]; + currentEditingContext: GQLEditingContext; +} + +export interface GQLNature { + name: string; +} + +export interface GQLEditingContext { + id: string; + representation: GQLRepresentationMetadata | undefined; +} + +export type GQLRepresentationMetadata = { + id: string; + label: string; + kind: string; +};