Skip to content

Commit

Permalink
[2934] Fix the initial position of representations added into portals
Browse files Browse the repository at this point in the history
Bug: #2934
Signed-off-by: Pierre-Charles David <pierre-charles.david@obeo.fr>
  • Loading branch information
pcdavid committed Jan 18, 2024
1 parent e89e4d8 commit 39fc785
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 44 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ Now, for a multi-valued feature, the values are properly displayed and the delet
- https://github.com/eclipse-sirius/sirius-web/issues/2755[#2755] [diagram] Ensure that the unfolded tool section is always visible above the rest of the palette
- https://github.com/eclipse-sirius/sirius-web/issues/2786[#2786] [diagram] Fix an issue where resizing was clunky.
- https://github.com/eclipse-sirius/sirius-web/issues/2912[#2912] [diagram] Send all requested node descriptions to the frontend when requested.
- https://github.com/eclipse-sirius/sirius-web/issues/2934[#2934] [portal] Fix the initial position of representations added into portals

=== New Features

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@
*
* @author pcdavid
*/
public record AddPortalViewInput(UUID id, String editingContextId, String representationId, String viewRepresentationId) implements IPortalInput {
public record AddPortalViewInput(UUID id, String editingContextId, String representationId, String viewRepresentationId, int x, int y, int width, int height) implements IPortalInput {
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public void handle(One<IPayload> payloadSink, Many<ChangeDescription> changeDesc
} else if (portalServices.referencesRepresentation(context.getCurrentPortal(), addPortalViewInput.viewRepresentationId())) {
payload = new ErrorPayload(portalInput.id(), "The representation is already included in the portal");
} else {
var newPortal = portalServices.addView(context.getCurrentPortal(), addPortalViewInput.viewRepresentationId());
var newPortal = portalServices.addView(context.getCurrentPortal(), addPortalViewInput.viewRepresentationId(), addPortalViewInput.x(), addPortalViewInput.y(), addPortalViewInput.width(), addPortalViewInput.height());
context.setNextPortal(newPortal);
payload = new SuccessPayload(addPortalViewInput.id(), List.of());
changeDescription = new ChangeDescription(ChangeKind.SEMANTIC_CHANGE, context.getEditingContext().getId(), context.getInput());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,6 @@
* @author pcdavid
*/
public class PortalServices {

/**
* The id of the temporary item added to the layout before the actual view is added.
*/
private static final String DROP_ITEM = "drop-item";

public boolean referencesRepresentation(Portal portal, String representationId) {
return portal.getViews().stream().anyMatch(portalView -> Objects.equals(portalView.getRepresentationId(), representationId));
}
Expand Down Expand Up @@ -66,21 +60,12 @@ public Portal removeRepresentation(Portal portal, String representationId) {
return Portal.newPortal(portal).views(newViews).layoutData(newLayouts).build();
}

public Portal addView(Portal portal, String viewRepresentationId) {
PortalViewLayoutData initialLayout = portal.getLayoutData().stream()
.filter(layoutData -> layoutData.getPortalViewId().equals(DROP_ITEM))
.findFirst()
.orElseGet(() -> {
String id = this.getPortalViewId(portal, viewRepresentationId);
return PortalViewLayoutData.newPortalViewLayoutData(id).x(0).y(0).width(3).height(3).build();
});
return this.addView(portal, viewRepresentationId, initialLayout.getX(), initialLayout.getY(), initialLayout.getWidth(), initialLayout.getHeight());
}

public Portal addView(Portal portal, String viewRepresentationId, int x, int y, int width, int height) {
var newPortalViewId = this.getPortalViewId(portal, viewRepresentationId);

var newViews = new ArrayList<>(portal.getViews());
var newViews = portal.getViews().stream()
.filter(portalView -> !Objects.equals(portalView.getId(), newPortalViewId))
.collect(Collectors.toCollection(ArrayList::new));
newViews.add(PortalView.newPortalView(newPortalViewId).representationId(viewRepresentationId).build());

var newLayoutData = new ArrayList<>(portal.getLayoutData());
Expand Down Expand Up @@ -113,11 +98,8 @@ public Portal layout(Portal portal, List<PortalViewLayoutData> layoutData) {
.collect(Collectors.toMap(PortalViewLayoutData::getPortalViewId, Function.identity()));
List<PortalViewLayoutData> newLayoutData = portal.getLayoutData().stream()
.map(portalViewLayoutData -> updatedLayouts.getOrDefault(portalViewLayoutData.getPortalViewId(), portalViewLayoutData))
.filter(portalViewLayoutData -> valueViewIds.contains(portalViewLayoutData.getPortalViewId()) || portalViewLayoutData.getPortalViewId().equals(DROP_ITEM))
.filter(portalViewLayoutData -> valueViewIds.contains(portalViewLayoutData.getPortalViewId()))
.collect(Collectors.toCollection(ArrayList::new));
if (updatedLayouts.containsKey(DROP_ITEM)) {
newLayoutData.add(updatedLayouts.get(DROP_ITEM));
}
return Portal.newPortal(portal).layoutData(newLayoutData).build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ input AddPortalViewInput {
editingContextId: ID!
representationId: ID!
viewRepresentationId: ID!
x: Int!
y: Int!
width: Int!
height: Int!
}

union AddPortalViewPayload = SuccessPayload | ErrorPayload
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*******************************************************************************/
import { MutationResult, gql, useMutation } from '@apollo/client';
import { useMultiToast } from '@eclipse-sirius/sirius-components-core';
import { useEffect } from 'react';
import { useEffect, useState } from 'react';
import { GQLErrorPayload } from './usePortal.types';
import {
GQLAddPortalViewMutationData,
Expand Down Expand Up @@ -95,12 +95,16 @@ export const usePortalMutations = (editingContextId: string, portalId: string):
GQLAddPortalViewMutationVariables
>(addPortalViewMutation);

const addPortalView = (viewRepresentationId: string) => {
const addPortalView = (viewRepresentationId: string, x: number, y: number, width: number, height: number) => {
const input = {
id: crypto.randomUUID(),
editingContextId,
representationId: portalId,
viewRepresentationId,
x,
y,
width,
height,
};
rawAddPortalView({ variables: { input } });
};
Expand All @@ -124,6 +128,8 @@ export const usePortalMutations = (editingContextId: string, portalId: string):

useErrorReporting(rawRemovePortalViewResult, (data) => data?.removePortalView);

const [layoutsInProgress, setLayoutsInProgress] = useState<number>(0);

const [rawLayoutPortal, rawLayoutPortalResult] = useMutation<
GQLLayoutPortalViewMutationData,
GQLLayoutPortalViewMutationVariables
Expand All @@ -136,14 +142,22 @@ export const usePortalMutations = (editingContextId: string, portalId: string):
representationId: portalId,
layoutData,
};
setLayoutsInProgress((prevState) => prevState + 1);
rawLayoutPortal({ variables: { input } });
};

useEffect(() => {
if (!rawLayoutPortalResult.loading) {
setLayoutsInProgress((prevState) => prevState - 1);
}
}, [rawLayoutPortalResult.loading]);

useErrorReporting(rawLayoutPortalResult, (data) => data?.layoutPortalView);

return {
addPortalView,
removePortalView,
layoutPortal,
layoutInProgress: layoutsInProgress > 0,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
*******************************************************************************/

export interface UsePortalMutationsValue {
addPortalView: (viewRepresentationId: string) => void;
addPortalView: (viewRepresentationId: string, x: number, y: number, width: number, height: number) => void;
removePortalView: (portalViewId: string) => void;
layoutPortal: (layoutData: GQLLayoutPortalLayoutData[]) => void;
layoutInProgress: boolean;
}

// mutation addPortalView
Expand All @@ -27,6 +28,10 @@ export interface GQLAddPortalViewInput {
editingContextId: string;
representationId: string;
viewRepresentationId: string;
x: number;
y: number;
width: number;
height: number;
}

export interface GQLAddPortalViewMutationData {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
useMultiToast,
useSelection,
} from '@eclipse-sirius/sirius-components-core';
import { Typography } from '@material-ui/core';
import Typography from '@material-ui/core/Typography';
import { makeStyles, useTheme } from '@material-ui/core/styles';
import AddIcon from '@material-ui/icons/Add';
import { useCallback, useRef, useState } from 'react';
Expand Down Expand Up @@ -79,22 +79,25 @@ export const PortalRepresentation = ({
const { addErrorMessage } = useMultiToast();
const { selection, setSelection } = useSelection();
const { portal, complete, message } = usePortal(editingContextId, representationId);
const { addPortalView, removePortalView, layoutPortal } = usePortalMutations(editingContextId, representationId);
const { addPortalView, removePortalView, layoutPortal, layoutInProgress } = usePortalMutations(
editingContextId,
representationId
);
const [mode, setMode] = useState<PortalRepresentationMode>('edit');

const portalIncludesRepresentation = (representationId: string) => {
return portal?.views.find((view) => view?.representationMetadata?.id === representationId);
};

const handleDrop = (event: Event) => {
const handleDrop = (event: Event, item: LayoutItem) => {
event.preventDefault();
const droppedRepresentationId: string | null = getFirstDroppedElementId(event);
if (droppedRepresentationId === null) {
addErrorMessage('Invalid drop.');
} else if (portalIncludesRepresentation(droppedRepresentationId)) {
addErrorMessage('The representation is already present in this portal.');
} else {
addPortalView(droppedRepresentationId);
addPortalView(droppedRepresentationId, item.x, item.y, item.w, item.h);
}
};

Expand All @@ -103,14 +106,16 @@ export const PortalRepresentation = ({
};

const handleLayoutChange = (layout: Layout) => {
const newLayoutData: GQLLayoutPortalLayoutData[] = layout.map((layoutItem) => ({
portalViewId: layoutItem.i,
x: layoutItem.x,
y: layoutItem.y,
width: layoutItem.w,
height: layoutItem.h,
}));
layoutPortal(newLayoutData);
if (!layoutInProgress) {
const newLayoutData: GQLLayoutPortalLayoutData[] = layout.map((layoutItem) => ({
portalViewId: layoutItem.i,
x: layoutItem.x,
y: layoutItem.y,
width: layoutItem.w,
height: layoutItem.h,
}));
layoutPortal(newLayoutData);
}
};

/*
Expand Down Expand Up @@ -138,10 +143,9 @@ export const PortalRepresentation = ({
x: 0,
y: 0,
w: 10,
h: 10,
h: 20,
static: true,
}}>
{' '}
<AddIcon fontSize="large" />
<Typography variant="subtitle2" align="center">
Add representations by dropping them from the explorer
Expand Down Expand Up @@ -200,12 +204,13 @@ export const PortalRepresentation = ({
rowHeight={cellSize}
autoSize={true}
margin={[theme.spacing(1), theme.spacing(1)]}
compactType={null}
draggableHandle=".draggable"
isDroppable={mode === 'edit'}
allowOverlap={!(portal && portal.views.length > 0)}
droppingItem={{ i: 'drop-item', w: 4, h: 3 }}
onDrop={(_layout: Layout, _item: LayoutItem, event: Event) => {
handleDrop(event);
droppingItem={{ i: 'drop-item', w: 4, h: 6 }}
onDrop={(_layout: Layout, item: LayoutItem, event: Event) => {
handleDrop(event, item);
}}
onLayoutChange={handleLayoutChange}>
{items}
Expand Down

0 comments on commit 39fc785

Please sign in to comment.