Skip to content
This repository has been archived by the owner on Apr 24, 2024. It is now read-only.

Use Groups instead of Layers (again). #1224

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Syntax: `- short text describing the change _(Your Name)_`
- Add notes to plantings in backend #1156 _(Jannis Adamek)_
- Fix seed routes and add naming convention guideline _(Daniel Steinkogler)_
- Enable automatic image scaling in base layer _(Moritz)_
- _()_
- Use Konva Groups instead of Layers _(Moritz)_
- Add [guideline](guidelines/frontend-keyhandling.md) and [decisions](decisions/frontend_keyhandling.md) for key handling) _(Daniel Steinkogler)_
- _()_
- Fix ref warning in PlantLabel, center labels as intended _(Paul)_
Expand Down
51 changes: 27 additions & 24 deletions frontend/src/features/map_planning/components/EditorMap.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import i18next from 'i18next';
import Konva from 'konva';
import { useCallback, useContext, useEffect, useState } from 'react';
import React, { useCallback, useContext, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Layer } from 'react-konva';
import { ShepherdTourContext } from 'react-shepherd';
import { toast } from 'react-toastify';
import { GainedBlossomsDto, LayerDto, LayerType } from '@/api_types/definitions';
Expand All @@ -14,6 +15,9 @@ import {
} from '@/config/keybindings';
import { FrontendOnlyLayerType } from '@/features/map_planning/layers/_frontend_only';
import { GridLayer } from '@/features/map_planning/layers/_frontend_only/grid/GridLayer';
import DrawingLayer from '@/features/map_planning/layers/drawing/DrawingLayer';
import { DrawingLayerLeftToolbar } from '@/features/map_planning/layers/drawing/DrawingLayerLeftToolbar';
import DrawingLayerRightToolbar from '@/features/map_planning/layers/drawing/DrawingLayerRightToolbar';
import { CombinedLayerType } from '@/features/map_planning/store/MapStoreTypes';
import { StageListenerRegister } from '@/features/map_planning/types/layer-config';
import { useKeyHandlers } from '@/hooks/useKeyHandlers';
Expand All @@ -27,9 +31,6 @@ import { gainBlossom } from '../api/gainBlossom';
import { useCompleteTour, useReenableTour } from '../hooks/tourHookApi';
import BaseLayer from '../layers/base/BaseLayer';
import BaseLayerRightToolbar from '../layers/base/components/BaseLayerRightToolbar';
import DrawingLayer from '../layers/drawing/DrawingLayer';
import { DrawingLayerLeftToolbar } from '../layers/drawing/DrawingLayerLeftToolbar';
import DrawingLayerRightToolbar from '../layers/drawing/DrawingLayerRightToolbar';
import PlantsLayer from '../layers/plant/PlantsLayer';
import { PlantLayerLeftToolbar } from '../layers/plant/components/PlantLayerLeftToolbar';
import { PlantLayerRightToolbar } from '../layers/plant/components/PlantLayerRightToolbar';
Expand Down Expand Up @@ -331,26 +332,28 @@ export const EditorMap = ({ layers }: MapProps) => {
}}
selectable={isShapeSelectionEnabled}
>
<BaseLayer
stageListenerRegister={baseStageListenerRegister}
opacity={layersState.base.opacity}
visible={layersState.base.visible}
listening={getSelectedLayerType() === LayerType.Base}
/>
<DrawingLayer
visible={layersState.drawing.visible}
opacity={layersState.drawing.opacity}
listening={getSelectedLayerType() === LayerType.Drawing}
></DrawingLayer>
<PlantsLayer
visible={layersState.plants.visible}
opacity={layersState.plants.opacity}
listening={getSelectedLayerType() === LayerType.Plants}
></PlantsLayer>
<GridLayer
visible={layersState.grid.visible}
opacity={layersState.grid.opacity}
></GridLayer>
<Layer listening={true}>
<BaseLayer
stageListenerRegister={baseStageListenerRegister}
opacity={layersState.base.opacity}
visible={layersState.base.visible}
listening={getSelectedLayerType() === LayerType.Base}
/>
<DrawingLayer
visible={layersState.drawing.visible}
opacity={layersState.drawing.opacity}
listening={getSelectedLayerType() === LayerType.Drawing}
></DrawingLayer>
<PlantsLayer
visible={layersState.plants.visible}
opacity={layersState.plants.opacity}
listening={getSelectedLayerType() === LayerType.Plants}
></PlantsLayer>
<GridLayer
visible={layersState.grid.visible}
opacity={layersState.grid.opacity}
></GridLayer>
</Layer>
</BaseStage>
<div>
<TimelineDatePicker
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Konva from 'konva/cmj';
import { Layer } from 'react-konva';
import { Group } from 'react-konva';
import { Grid } from '@/features/map_planning/layers/_frontend_only/grid/groups/Grid';
import { YardStick } from '@/features/map_planning/layers/_frontend_only/grid/groups/YardStick';
import useMapStore from '@/features/map_planning/store/MapStore';
Expand All @@ -8,9 +8,9 @@ export const GridLayer = (props: Konva.LayerConfig) => {
const viewRect = useMapStore((state) => state.untrackedState.editorViewRect);

return (
<Layer listening={false} visible={props.visible} opacity={props.opacity}>
<Group listening={false} visible={props.visible} opacity={props.opacity}>
<Grid x={viewRect.x} y={viewRect.y} width={viewRect.width} height={viewRect.height} />
<YardStick x={viewRect.x} y={viewRect.y} width={viewRect.width} height={viewRect.height} />
</Layer>
</Group>
);
};
6 changes: 3 additions & 3 deletions frontend/src/features/map_planning/layers/base/BaseLayer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useCallback, useEffect, useState } from 'react';
import { Circle, Group, Layer, Line } from 'react-konva';
import { Circle, Group, Line } from 'react-konva';
import { NextcloudKonvaImage } from '@/features/map_planning/components/image/NextcloudKonvaImage';
import { MapGeometryEditor } from '@/features/map_planning/layers/base/components/MapGeometryEditor';
import useMapStore from '@/features/map_planning/store/MapStore';
Expand Down Expand Up @@ -62,7 +62,7 @@ const BaseLayer = (props: BaseLayerProps) => {
const scale = MAP_PIXELS_PER_METER / pixelsPerMeter;

return (
<Layer {...layerProps} draggable={true}>
<Group {...layerProps} draggable={true}>
<Group listening={false}>
{cleanImagePath && (
<NextcloudKonvaImage
Expand Down Expand Up @@ -97,7 +97,7 @@ const BaseLayer = (props: BaseLayerProps) => {
/>
</Group>
<MapGeometryEditor {...props} />
</Layer>
</Group>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { LayerConfig } from 'konva/lib/Layer';
import { KonvaEventListener, KonvaEventObject } from 'konva/lib/Node';
import { Vector2d } from 'konva/lib/types';
import { useCallback, useEffect, useRef, useState } from 'react';
import { Ellipse, Layer, Line, Rect } from 'react-konva';
import { Ellipse, Group, Line, Rect } from 'react-konva';
import * as uuid from 'uuid';
import { DrawingDto, DrawingShapeType, LayerType } from '@/api_types/definitions';
import {
Expand Down Expand Up @@ -688,7 +688,7 @@ function DrawingLayer(props: DrawingLayerProps) {

return (
<>
<Layer {...layerProps} name={`${LayerType.Drawing}`}>
<Group {...layerProps} name={`${LayerType.Drawing}`}>
{bezierLines.map((bezierLine, i) => (
<BezierPolygon
key={`bezier-line-${i}`}
Expand Down Expand Up @@ -855,7 +855,7 @@ function DrawingLayer(props: DrawingLayerProps) {
fillEnabled={previewEllipse.fillEnabled}
/>
)}
</Layer>
</Group>
</>
);
}
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/features/map_planning/layers/plant/PlantsLayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { t } from 'i18next';
import Konva from 'konva';
import { KonvaEventListener, KonvaEventObject, Node } from 'konva/lib/Node';
import { useCallback, useEffect, useRef } from 'react';
import { Layer } from 'react-konva';
import { Group } from 'react-konva';
import * as uuid from 'uuid';
import {
LayerType,
Expand Down Expand Up @@ -339,15 +339,15 @@ function PlantsLayer(props: PlantsLayerProps) {
return (
<>
<PlantLayerRelationsOverlay />
<Layer {...props} ref={layerRef} name={`${LayerType.Plants}`}>
<Group {...props} ref={layerRef} name={`${LayerType.Plants}`}>
{plantings.map((planting) => (
<Planting planting={planting} key={planting.id} />
))}
</Layer>
<Layer listening={false}>
</Group>
<Group listening={false}>
<PlantCursor />
<AreaOfPlantingsIndicator />
</Layer>
</Group>
</>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Konva from 'konva';
import { useEffect, useMemo, useState } from 'react';
import { Layer, Line } from 'react-konva';
import { Group, Line } from 'react-konva';
import { LayerType, RelationType } from '@/api_types/definitions';
import useMapStore from '@/features/map_planning/store/MapStore';
import { useRelations } from '../hooks/relationsHookApi';
Expand Down Expand Up @@ -62,15 +62,21 @@ export function PlantLayerRelationsOverlay() {
const layers = stage?.children;

const visiblePlantingNodes = useMemo(() => {
return layers
?.filter((l) => l.name() === LayerType.Plants)
.flatMap((l) => l.children ?? [])
.filter((s) => s.attrs.plantId && s.isClientRectOnScreen())
.filter((s) => relations?.has(s.attrs.plantId));
return (
layers
?.flatMap((l) => l.children ?? [])
.filter((l) => l.name() === LayerType.Plants)
// @ts-expect-error Typescript can't tell that all direct children layer must have children themselves
.filter((group) => group['children'] !== undefined)
// @ts-expect-error Typescript can't tell that all direct children layer must have children themselves
.flatMap((group) => group?.children)
.filter((s) => s.attrs.plantId && s.isClientRectOnScreen())
.filter((s) => relations?.has(s.attrs.plantId))
);
}, [relations, layers]);

return (
<Layer listening={false}>
<Group listening={false}>
{!areRelationsLoading && lineEnd && visiblePlantingNodes
? visiblePlantingNodes.map((node) => {
const relation = relations?.get(node.attrs.plantId)?.relation;
Expand All @@ -88,7 +94,7 @@ export function PlantLayerRelationsOverlay() {
);
})
: null}
</Layer>
</Group>
);
}

Expand Down
8 changes: 7 additions & 1 deletion frontend/src/features/map_planning/utils/ShapesSelection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,15 @@ export const selectIntersectingShapes = (

// we don't always have to look for them, we can store them
const allShapes = stageRef.current.children
//filter out layers which are not selected
// only layers
?.filter((layer) => layer.attrs.listening)
.flatMap((layer) => layer.children)
.filter((group) => !!group)
.filter((group) => group?.attrs.listening)
// @ts-expect-error Typescript can't tell that all direct children layer must have children themselves
.filter((group) => group['children'] !== undefined)
// @ts-expect-error Typescript can't tell that all direct children layer must have children themselves
.flatMap((group) => group?.children)
.filter((shape) => {
// To exclude Konva's transformer, check if node contains children.
// 'listening' is explicitly checked for '!== false' because
Expand Down