From e58f8cc42a18bf412e8a8bedfdba09dc0e8d0ccc Mon Sep 17 00:00:00 2001
From: lby
Date: Mon, 19 Aug 2024 10:52:27 +0800
Subject: [PATCH 01/23] fix(web): disable link when id undefined (#1104)
---
web/src/beta/features/Navbar/LeftSection/index.tsx | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/web/src/beta/features/Navbar/LeftSection/index.tsx b/web/src/beta/features/Navbar/LeftSection/index.tsx
index 6da1c4484..de3c27cd3 100644
--- a/web/src/beta/features/Navbar/LeftSection/index.tsx
+++ b/web/src/beta/features/Navbar/LeftSection/index.tsx
@@ -50,11 +50,11 @@ const LeftSection: React.FC = ({
return (
-
+
{page !== "editor" && (
-
+
)}
@@ -79,10 +79,11 @@ const Wrapper = styled("div")(({ theme }) => ({
gap: theme.spacing.small,
}));
-const StyledLink = styled(Link)(({ theme }) => ({
+const StyledLink = styled(Link)<{ disabled?: boolean }>(({ theme, disabled }) => ({
display: "flex",
color: theme.content.main,
textDecoration: "none",
+ pointerEvents: disabled ? "none" : "all",
"&:hover": {
textDecoration: "none",
},
From 422db8776f334c141ea7229d8f5a907c1e334d4a Mon Sep 17 00:00:00 2001
From: lby
Date: Mon, 19 Aug 2024 16:44:36 +0800
Subject: [PATCH 02/23] feat(web): support delete sketch feature (#1105)
---
.../LayerInspector/FeatureInspector/index.tsx | 24 +++++++++++++++++-
.../InspectorPanel/LayerInspector/index.tsx | 9 ++++++-
.../Editor/Map/InspectorPanel/index.tsx | 2 ++
web/src/beta/features/Editor/Map/context.tsx | 3 ++-
web/src/beta/features/Editor/hooks/index.ts | 3 +++
.../beta/features/Editor/hooks/useSketch.ts | 19 +++++++++++++-
.../api/featureCollectionApi/index.ts | 25 ++++++++++++++++++-
web/src/services/gql/__gen__/gql.ts | 5 ++++
web/src/services/gql/__gen__/graphql.ts | 8 ++++++
.../services/gql/queries/featureCollection.ts | 8 ++++++
web/src/services/i18n/translations/en.yml | 6 +++--
web/src/services/i18n/translations/ja.yml | 6 +++--
12 files changed, 109 insertions(+), 9 deletions(-)
diff --git a/web/src/beta/features/Editor/Map/InspectorPanel/LayerInspector/FeatureInspector/index.tsx b/web/src/beta/features/Editor/Map/InspectorPanel/LayerInspector/FeatureInspector/index.tsx
index b52c8e67b..540e89d4e 100644
--- a/web/src/beta/features/Editor/Map/InspectorPanel/LayerInspector/FeatureInspector/index.tsx
+++ b/web/src/beta/features/Editor/Map/InspectorPanel/LayerInspector/FeatureInspector/index.tsx
@@ -3,7 +3,10 @@ import "react18-json-view/src/style.css";
import "react18-json-view/src/dark.css";
import JsonView from "react18-json-view";
-import { GeoJsonFeatureUpdateProps } from "@reearth/beta/features/Editor/hooks/useSketch";
+import {
+ GeoJsonFeatureDeleteProps,
+ GeoJsonFeatureUpdateProps,
+} from "@reearth/beta/features/Editor/hooks/useSketch";
import { Button, Collapse, Typography } from "@reearth/beta/lib/reearth-ui";
import { Geometry } from "@reearth/core";
import { NLSLayer, SketchFeature } from "@reearth/services/api/layersApi/utils";
@@ -21,6 +24,7 @@ type Props = {
layer?: NLSLayer;
sketchFeature?: SketchFeature;
onGeoJsonFeatureUpdate?: (inp: GeoJsonFeatureUpdateProps) => void;
+ onGeoJsonFeatureDelete?: (inp: GeoJsonFeatureDeleteProps) => void;
};
export type ValueProp = string | number | boolean | undefined;
@@ -36,6 +40,7 @@ const FeatureData: FC = ({
layer,
sketchFeature,
onGeoJsonFeatureUpdate,
+ onGeoJsonFeatureDelete,
}) => {
const t = useT();
const theme = useTheme();
@@ -87,6 +92,14 @@ const FeatureData: FC = ({
[theme.fonts.sizes.body],
);
+ const handleDeleteSketchFeature = useCallback(() => {
+ if (!layer?.id || !sketchFeature?.id) return;
+ onGeoJsonFeatureDelete?.({
+ layerId: layer.id,
+ featureId: sketchFeature.id,
+ });
+ }, [layer?.id, sketchFeature?.id, onGeoJsonFeatureDelete]);
+
return (
{!!layer?.isSketch && (
@@ -134,6 +147,15 @@ const FeatureData: FC = ({
+ {!!layer?.isSketch && sketchFeature?.id && (
+
+ )}
);
};
diff --git a/web/src/beta/features/Editor/Map/InspectorPanel/LayerInspector/index.tsx b/web/src/beta/features/Editor/Map/InspectorPanel/LayerInspector/index.tsx
index 38c335668..1802ed70a 100644
--- a/web/src/beta/features/Editor/Map/InspectorPanel/LayerInspector/index.tsx
+++ b/web/src/beta/features/Editor/Map/InspectorPanel/LayerInspector/index.tsx
@@ -1,7 +1,10 @@
import { FC, useCallback, useMemo, useState } from "react";
import { SelectedLayer } from "@reearth/beta/features/Editor/hooks/useLayers";
-import { GeoJsonFeatureUpdateProps } from "@reearth/beta/features/Editor/hooks/useSketch";
+import {
+ GeoJsonFeatureDeleteProps,
+ GeoJsonFeatureUpdateProps,
+} from "@reearth/beta/features/Editor/hooks/useSketch";
import { TabItem, Tabs } from "@reearth/beta/lib/reearth-ui";
import { NLSLayer } from "@reearth/services/api/layersApi/utils";
import { LayerStyle as LayerStyleType } from "@reearth/services/api/layerStyleApi/utils";
@@ -22,6 +25,7 @@ type Props = {
sceneId?: string;
onLayerConfigUpdate?: (inp: LayerConfigUpdateProps) => void;
onGeoJsonFeatureUpdate?: (inp: GeoJsonFeatureUpdateProps) => void;
+ onGeoJsonFeatureDelete?: (inp: GeoJsonFeatureDeleteProps) => void;
};
const InspectorTabs: FC = ({
@@ -31,6 +35,7 @@ const InspectorTabs: FC = ({
sceneId,
onLayerConfigUpdate,
onGeoJsonFeatureUpdate,
+ onGeoJsonFeatureDelete,
}) => {
const selectedFeature = useMemo(() => {
if (!selectedLayer?.computedFeature?.id) return;
@@ -79,6 +84,7 @@ const InspectorTabs: FC = ({
layer={selectedLayer?.layer}
sketchFeature={selectedSketchFeature}
onGeoJsonFeatureUpdate={onGeoJsonFeatureUpdate}
+ onGeoJsonFeatureDelete={onGeoJsonFeatureDelete}
/>
),
},
@@ -115,6 +121,7 @@ const InspectorTabs: FC = ({
sceneId,
onLayerConfigUpdate,
onGeoJsonFeatureUpdate,
+ onGeoJsonFeatureDelete,
],
);
diff --git a/web/src/beta/features/Editor/Map/InspectorPanel/index.tsx b/web/src/beta/features/Editor/Map/InspectorPanel/index.tsx
index e0f256b31..bb4308907 100644
--- a/web/src/beta/features/Editor/Map/InspectorPanel/index.tsx
+++ b/web/src/beta/features/Editor/Map/InspectorPanel/index.tsx
@@ -22,6 +22,7 @@ const InspectorPanel: FC = ({ areaRef, showCollapseArea }) => {
handleFlyTo,
handleLayerConfigUpdate,
handleGeoJsonFeatureUpdate,
+ handleGeoJsonFeatureDelete,
} = useMapPage();
const t = useT();
@@ -52,6 +53,7 @@ const InspectorPanel: FC = ({ areaRef, showCollapseArea }) => {
selectedLayer={selectedLayer}
onLayerConfigUpdate={handleLayerConfigUpdate}
onGeoJsonFeatureUpdate={handleGeoJsonFeatureUpdate}
+ onGeoJsonFeatureDelete={handleGeoJsonFeatureDelete}
/>
)}
diff --git a/web/src/beta/features/Editor/Map/context.tsx b/web/src/beta/features/Editor/Map/context.tsx
index bc7c6a97e..d6d40d009 100644
--- a/web/src/beta/features/Editor/Map/context.tsx
+++ b/web/src/beta/features/Editor/Map/context.tsx
@@ -20,7 +20,7 @@ import {
LayerStyleNameUpdateProps,
LayerStyleValueUpdateProps,
} from "../hooks/useLayerStyles";
-import { GeoJsonFeatureUpdateProps } from "../hooks/useSketch";
+import { GeoJsonFeatureDeleteProps, GeoJsonFeatureUpdateProps } from "../hooks/useSketch";
export interface MapPageContextType {
handleVisualizerResize?: (props: AreaSize) => void;
@@ -52,6 +52,7 @@ export interface MapPageContextType {
handleLayerStyleValueUpdate?: (inp: LayerStyleValueUpdateProps) => void;
handleLayerConfigUpdate?: (inp: LayerConfigUpdateProps) => void;
handleGeoJsonFeatureUpdate?: (inp: GeoJsonFeatureUpdateProps) => void;
+ handleGeoJsonFeatureDelete?: (inp: GeoJsonFeatureDeleteProps) => void;
handleLayerStyleAdd: (inp: LayerStyleAddProps) => void;
handleLayerStyleDelete: (id: string) => void;
handleLayerStyleNameUpdate: (inp: LayerStyleNameUpdateProps) => void;
diff --git a/web/src/beta/features/Editor/hooks/index.ts b/web/src/beta/features/Editor/hooks/index.ts
index c7e5b4818..33cf09877 100644
--- a/web/src/beta/features/Editor/hooks/index.ts
+++ b/web/src/beta/features/Editor/hooks/index.ts
@@ -61,6 +61,7 @@ export default ({ sceneId, projectId, tab }: Props) => {
handleSketchFeatureCreate,
sketchType,
handleGeoJsonFeatureUpdate,
+ handleGeoJsonFeatureDelete,
} = useSketch({
tab,
nlsLayers,
@@ -164,6 +165,7 @@ export default ({ sceneId, projectId, tab }: Props) => {
handleLayerStyleValueUpdate,
handleLayerConfigUpdate,
handleGeoJsonFeatureUpdate,
+ handleGeoJsonFeatureDelete,
handleLayerStyleAdd,
handleLayerStyleDelete,
handleLayerStyleNameUpdate,
@@ -198,6 +200,7 @@ export default ({ sceneId, projectId, tab }: Props) => {
handleLayerStyleValueUpdate,
handleLayerConfigUpdate,
handleGeoJsonFeatureUpdate,
+ handleGeoJsonFeatureDelete,
handleLayerStyleAdd,
handleLayerStyleDelete,
handleLayerStyleNameUpdate,
diff --git a/web/src/beta/features/Editor/hooks/useSketch.ts b/web/src/beta/features/Editor/hooks/useSketch.ts
index 756566ede..0a3efb7d0 100644
--- a/web/src/beta/features/Editor/hooks/useSketch.ts
+++ b/web/src/beta/features/Editor/hooks/useSketch.ts
@@ -29,6 +29,11 @@ export type GeoJsonFeatureUpdateProps = {
properties?: any;
};
+export type GeoJsonFeatureDeleteProps = {
+ layerId: string;
+ featureId: string;
+};
+
export default ({
tab,
nlsLayers,
@@ -50,7 +55,8 @@ export default ({
[visualizerRef],
);
- const { useAddGeoJsonFeature, useUpdateGeoJSONFeature } = useFeatureCollectionFetcher();
+ const { useAddGeoJsonFeature, useUpdateGeoJSONFeature, useDeleteGeoJSONFeature } =
+ useFeatureCollectionFetcher();
const handleSketchLayerAdd = useCallback(
async (inp: FeatureProps) => {
@@ -128,10 +134,21 @@ export default ({
[useUpdateGeoJSONFeature],
);
+ const handleGeoJsonFeatureDelete = useCallback(
+ async (inp: GeoJsonFeatureDeleteProps) => {
+ await useDeleteGeoJSONFeature({
+ layerId: inp.layerId,
+ featureId: inp.featureId,
+ });
+ },
+ [useDeleteGeoJSONFeature],
+ );
+
return {
sketchType,
handleSketchTypeChange,
handleSketchFeatureCreate,
handleGeoJsonFeatureUpdate,
+ handleGeoJsonFeatureDelete,
};
};
diff --git a/web/src/services/api/featureCollectionApi/index.ts b/web/src/services/api/featureCollectionApi/index.ts
index 5df0f93d0..5ac5ad105 100644
--- a/web/src/services/api/featureCollectionApi/index.ts
+++ b/web/src/services/api/featureCollectionApi/index.ts
@@ -5,12 +5,14 @@ import { MutationReturn } from "@reearth/services/api/types";
import {
AddGeoJsonFeatureInput,
AddGeoJsonFeatureMutation,
+ DeleteGeoJsonFeatureInput,
MutationAddGeoJsonFeatureArgs,
UpdateGeoJsonFeatureInput,
UpdateGeoJsonFeatureMutation,
} from "@reearth/services/gql/__gen__/graphql";
import {
ADD_GEOJSON_FEATURE,
+ DELETE_GEOJSON_FEATURE,
UPDATE_GEOJSON_FEATURE,
} from "@reearth/services/gql/queries/featureCollection";
import { useT } from "@reearth/services/i18n";
@@ -59,14 +61,35 @@ export default () => {
return { status: "error", errors };
}
- setNotification({ type: "success", text: t("Successfully updated a the layer!") });
+ setNotification({ type: "success", text: t("Successfully updated the layer!") });
return { data, status: "success" };
},
[updateGeoJsonFeatureMutation, setNotification, t],
);
+
+ const [deleteGeoJsonFeatureMutation] = useMutation(DELETE_GEOJSON_FEATURE, {
+ refetchQueries: ["GetScene"],
+ });
+
+ const useDeleteGeoJSONFeature = useCallback(
+ async (input: DeleteGeoJsonFeatureInput) => {
+ if (!input.layerId || !input.featureId) return { status: "error" };
+ const { data, errors } = await deleteGeoJsonFeatureMutation({ variables: { input } });
+ if (errors || !data?.deleteGeoJSONFeature) {
+ setNotification({ type: "error", text: t("Failed to delete the feature.") });
+ return { status: "error", errors };
+ }
+
+ setNotification({ type: "success", text: t("Successfully deleted the feature!") });
+ return { data, status: "success" };
+ },
+ [deleteGeoJsonFeatureMutation, t, setNotification],
+ );
+
return {
useAddGeoJsonFeature,
useUpdateGeoJSONFeature,
+ useDeleteGeoJSONFeature,
};
};
diff --git a/web/src/services/gql/__gen__/gql.ts b/web/src/services/gql/__gen__/gql.ts
index 0f8a156b8..c8a2a9102 100644
--- a/web/src/services/gql/__gen__/gql.ts
+++ b/web/src/services/gql/__gen__/gql.ts
@@ -32,6 +32,7 @@ const documents = {
"\n mutation RemoveAsset($assetId: ID!) {\n removeAsset(input: { assetId: $assetId }) {\n assetId\n }\n }\n": types.RemoveAssetDocument,
"\n mutation AddGeoJSONFeature($input: AddGeoJSONFeatureInput!) {\n addGeoJSONFeature(input: $input) {\n id\n\t\t type\n\t\t properties\n }\n }\n": types.AddGeoJsonFeatureDocument,
"\n mutation UpdateGeoJSONFeature($input: UpdateGeoJSONFeatureInput!) {\n updateGeoJSONFeature(input: $input) {\n id\n\t\t type\n\t\t properties\n }\n }\n": types.UpdateGeoJsonFeatureDocument,
+ "\n mutation DeleteGeoJSONFeature($input: DeleteGeoJSONFeatureInput!){\n deleteGeoJSONFeature(input: $input) {\n\t\t deletedFeatureId\n }\n }\n": types.DeleteGeoJsonFeatureDocument,
"\n mutation CreateNLSInfobox($input: CreateNLSInfoboxInput!) {\n createNLSInfobox(input: $input) {\n layer{\n id\n }\n }\n }\n": types.CreateNlsInfoboxDocument,
"\n mutation RemoveNLSInfobox($input: RemoveNLSInfoboxInput!) {\n removeNLSInfobox(input: $input) {\n layer {\n id\n }\n }\n }\n": types.RemoveNlsInfoboxDocument,
"\n mutation AddNLSInfoboxBlock($input: AddNLSInfoboxBlockInput!) {\n addNLSInfoboxBlock(input: $input) {\n layer {\n id\n }\n }\n }\n": types.AddNlsInfoboxBlockDocument,
@@ -177,6 +178,10 @@ export function gql(source: "\n mutation AddGeoJSONFeature($input: AddGeoJSONFe
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function gql(source: "\n mutation UpdateGeoJSONFeature($input: UpdateGeoJSONFeatureInput!) {\n updateGeoJSONFeature(input: $input) {\n id\n\t\t type\n\t\t properties\n }\n }\n"): (typeof documents)["\n mutation UpdateGeoJSONFeature($input: UpdateGeoJSONFeatureInput!) {\n updateGeoJSONFeature(input: $input) {\n id\n\t\t type\n\t\t properties\n }\n }\n"];
+/**
+ * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
+ */
+export function gql(source: "\n mutation DeleteGeoJSONFeature($input: DeleteGeoJSONFeatureInput!){\n deleteGeoJSONFeature(input: $input) {\n\t\t deletedFeatureId\n }\n }\n"): (typeof documents)["\n mutation DeleteGeoJSONFeature($input: DeleteGeoJSONFeatureInput!){\n deleteGeoJSONFeature(input: $input) {\n\t\t deletedFeatureId\n }\n }\n"];
/**
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
diff --git a/web/src/services/gql/__gen__/graphql.ts b/web/src/services/gql/__gen__/graphql.ts
index a72733a97..337a320ef 100644
--- a/web/src/services/gql/__gen__/graphql.ts
+++ b/web/src/services/gql/__gen__/graphql.ts
@@ -3194,6 +3194,13 @@ export type UpdateGeoJsonFeatureMutationVariables = Exact<{
export type UpdateGeoJsonFeatureMutation = { __typename?: 'Mutation', updateGeoJSONFeature: { __typename?: 'Feature', id: string, type: string, properties?: any | null } };
+export type DeleteGeoJsonFeatureMutationVariables = Exact<{
+ input: DeleteGeoJsonFeatureInput;
+}>;
+
+
+export type DeleteGeoJsonFeatureMutation = { __typename?: 'Mutation', deleteGeoJSONFeature: { __typename?: 'DeleteGeoJSONFeaturePayload', deletedFeatureId: string } };
+
export type CreateNlsInfoboxMutationVariables = Exact<{
input: CreateNlsInfoboxInput;
}>;
@@ -3686,6 +3693,7 @@ export const CreateAssetDocument = {"kind":"Document","definitions":[{"kind":"Op
export const RemoveAssetDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RemoveAsset"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"assetId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"removeAsset"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"assetId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"assetId"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assetId"}}]}}]}}]} as unknown as DocumentNode;
export const AddGeoJsonFeatureDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AddGeoJSONFeature"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"AddGeoJSONFeatureInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"addGeoJSONFeature"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"properties"}}]}}]}}]} as unknown as DocumentNode;
export const UpdateGeoJsonFeatureDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateGeoJSONFeature"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateGeoJSONFeatureInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateGeoJSONFeature"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"properties"}}]}}]}}]} as unknown as DocumentNode;
+export const DeleteGeoJsonFeatureDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteGeoJSONFeature"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DeleteGeoJSONFeatureInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteGeoJSONFeature"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deletedFeatureId"}}]}}]}}]} as unknown as DocumentNode;
export const CreateNlsInfoboxDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateNLSInfobox"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateNLSInfoboxInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createNLSInfobox"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"layer"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]} as unknown as DocumentNode;
export const RemoveNlsInfoboxDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RemoveNLSInfobox"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoveNLSInfoboxInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"removeNLSInfobox"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"layer"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]} as unknown as DocumentNode;
export const AddNlsInfoboxBlockDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AddNLSInfoboxBlock"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"AddNLSInfoboxBlockInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"addNLSInfoboxBlock"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"layer"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]} as unknown as DocumentNode;
diff --git a/web/src/services/gql/queries/featureCollection.ts b/web/src/services/gql/queries/featureCollection.ts
index 60b37f8c7..e6c5a62da 100644
--- a/web/src/services/gql/queries/featureCollection.ts
+++ b/web/src/services/gql/queries/featureCollection.ts
@@ -19,3 +19,11 @@ export const UPDATE_GEOJSON_FEATURE = gql(`
}
}
`);
+
+export const DELETE_GEOJSON_FEATURE = gql(`
+ mutation DeleteGeoJSONFeature($input: DeleteGeoJSONFeatureInput!){
+ deleteGeoJSONFeature(input: $input) {
+ deletedFeatureId
+ }
+ }
+`);
diff --git a/web/src/services/i18n/translations/en.yml b/web/src/services/i18n/translations/en.yml
index f56785dbd..24dca2fcb 100644
--- a/web/src/services/i18n/translations/en.yml
+++ b/web/src/services/i18n/translations/en.yml
@@ -116,6 +116,7 @@ Save & Apply: ''
No custom properties: ''
Geometry: ''
Properties: ''
+Delete Feature: ''
Enable Infobox: ''
Show infobox when the user clicks on a layer: ''
Layer Style: ''
@@ -310,14 +311,15 @@ One or more assets were successfully deleted.: ''
Failed to add layer.: ''
Successfully added a new layer: ''
Failed to update the layer.: ''
-Successfully updated a the layer!: ''
+Successfully updated the layer!: ''
+Failed to delete the feature.: ''
+Successfully deleted the feature!: ''
Failed to create block.: ''
Successfullly created a block!: ''
Failed to delete block.: ''
Block was successfully deleted.: ''
Failed to move block.: ''
Block was successfully moved.: ''
-Successfully updated the layer!: ''
Failed to remove the layer.: ''
Successfully removed the layer!: ''
Failed to update the custom property schema.: ''
diff --git a/web/src/services/i18n/translations/ja.yml b/web/src/services/i18n/translations/ja.yml
index 73135650c..fed7ab513 100644
--- a/web/src/services/i18n/translations/ja.yml
+++ b/web/src/services/i18n/translations/ja.yml
@@ -116,6 +116,7 @@ Save & Apply: ''
No custom properties: ''
Geometry: ジオメトリ
Properties: プロパティ
+Delete Feature: ''
Enable Infobox: インフォボックスを有効化
Show infobox when the user clicks on a layer: フェーチャーをクリックした際にインフォボックスを表示
Layer Style: レイヤースタイル
@@ -310,14 +311,15 @@ One or more assets were successfully deleted.: アセットが削除されまし
Failed to add layer.: レイヤーの追加に失敗しました。
Successfully added a new layer: 新しいレイヤーの追加に成功しました。
Failed to update the layer.: レイヤーのアップデートに失敗しました。
-Successfully updated a the layer!: レイヤーのアップデートに成功しました!
+Successfully updated the layer!: ''
+Failed to delete the feature.: ''
+Successfully deleted the feature!: ''
Failed to create block.: ブロックの作成に失敗しました。
Successfullly created a block!: ブロックの作成に成功しました!
Failed to delete block.: ブロックの削除に失敗しました。
Block was successfully deleted.: ブロックの削除に成功しました。
Failed to move block.: ブロックの移動に失敗しました。
Block was successfully moved.: ブロックの移動に成功しました。
-Successfully updated the layer!: ''
Failed to remove the layer.: レイヤーの削除に失敗しました。
Successfully removed the layer!: ''
Failed to update the custom property schema.: ''
From b9401d0e67d2deac5363ada9dfcc56ba294d2efb Mon Sep 17 00:00:00 2001
From: lby
Date: Tue, 20 Aug 2024 15:26:28 +0800
Subject: [PATCH 03/23] refactor(web): evict project cache after delete project
(#1103)
---
web/src/services/api/projectApi.ts | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/web/src/services/api/projectApi.ts b/web/src/services/api/projectApi.ts
index 8c85738d0..0af5103fc 100644
--- a/web/src/services/api/projectApi.ts
+++ b/web/src/services/api/projectApi.ts
@@ -1,4 +1,4 @@
-import { useLazyQuery, useMutation, useQuery } from "@apollo/client";
+import { useApolloClient, useLazyQuery, useMutation, useQuery } from "@apollo/client";
import { useCallback, useMemo } from "react";
import { type PublishStatus } from "@reearth/beta/features/Editor/Publish/PublishToolsPanel/PublishModal/hooks";
@@ -39,6 +39,7 @@ export type Project = ProjectPayload["project"];
export default () => {
const t = useT();
const [, setNotification] = useNotification();
+ const apolloCache = useApolloClient().cache;
const useProjectQuery = useCallback((projectId?: string) => {
const { data, ...rest } = useQuery(GET_PROJECT, {
@@ -251,10 +252,12 @@ export default () => {
return { status: "error" };
}
+ apolloCache.evict({ fieldName: "projects" });
+
setNotification({ type: "success", text: t("Successfully delete project!") });
return { status: "success" };
},
- [deleteProjectMutation, t, setNotification],
+ [apolloCache, deleteProjectMutation, t, setNotification],
);
const [updateProjectBasicAuthMutation] = useMutation(UPDATE_PROJECT_BASIC_AUTH, {
From 9849751346c1365e42650c9f8ac2614b9e7da5b6 Mon Sep 17 00:00:00 2001
From: lby
Date: Tue, 20 Aug 2024 17:16:33 +0800
Subject: [PATCH 04/23] chore(web): upgrade vite plugin cesium (#1106)
---
web/package.json | 4 ++--
web/vite.config.ts | 20 +++++++++++++++++++-
web/yarn.lock | 32 ++++++++++++++++----------------
3 files changed, 37 insertions(+), 19 deletions(-)
diff --git a/web/package.json b/web/package.json
index ed35ae05c..637db38ae 100644
--- a/web/package.json
+++ b/web/package.json
@@ -89,7 +89,7 @@
"typescript": "5.0.4",
"typescript-styled-plugin": "0.18.3",
"vite": "5.3.5",
- "vite-plugin-cesium": "1.2.22",
+ "vite-plugin-cesium": "1.2.23",
"vite-plugin-svgr": "4.2.0",
"vite-tsconfig-paths": "4.2.1",
"vitest": "1.6.0",
@@ -106,7 +106,7 @@
"@lexical/react": "0.12.2",
"@monaco-editor/react": "4.6.0",
"@popperjs/core": "2.11.8",
- "@reearth/core": "0.0.7-alpha.6",
+ "@reearth/core": "0.0.7-alpha.11",
"@rot1024/use-transition": "1.0.0",
"@sentry/browser": "7.77.0",
"@seznam/compose-react-refs": "1.0.6",
diff --git a/web/vite.config.ts b/web/vite.config.ts
index 00a753663..517cf0497 100644
--- a/web/vite.config.ts
+++ b/web/vite.config.ts
@@ -26,9 +26,27 @@ try {
// noop
}
+let cesiumVersion = "";
+try {
+ const cesiumPackageJson = JSON.parse(
+ readFileSync(resolve(__dirname, "node_modules", "cesium", "package.json"), "utf-8"),
+ );
+ cesiumVersion = cesiumPackageJson.version;
+} catch {
+ // noop
+}
+
export default defineConfig({
envPrefix: "REEARTH_WEB_",
- plugins: [svgr(), react(), yaml(), cesium(), serverHeaders(), config(), tsconfigPaths()],
+ plugins: [
+ svgr(),
+ react(),
+ yaml(),
+ cesium({ cesiumBaseUrl: cesiumVersion ? `cesium-${cesiumVersion}/` : undefined }),
+ serverHeaders(),
+ config(),
+ tsconfigPaths(),
+ ],
// https://github.com/storybookjs/storybook/issues/25256
assetsInclude: ["/sb-preview/runtime.js"],
define: {
diff --git a/web/yarn.lock b/web/yarn.lock
index 878543687..afef5f4a9 100644
--- a/web/yarn.lock
+++ b/web/yarn.lock
@@ -8036,9 +8036,9 @@ __metadata:
languageName: node
linkType: hard
-"@reearth/core@npm:0.0.7-alpha.6":
- version: 0.0.7-alpha.6
- resolution: "@reearth/core@npm:0.0.7-alpha.6"
+"@reearth/core@npm:0.0.7-alpha.11":
+ version: 0.0.7-alpha.11
+ resolution: "@reearth/core@npm:0.0.7-alpha.11"
dependencies:
"@reearth/cesium-mvt-imagery-provider": "npm:1.5.4"
"@rot1024/use-transition": "npm:1.0.0"
@@ -8069,7 +8069,7 @@ __metadata:
react-error-boundary: "npm:4.0.11"
react-nl2br: "npm:1.0.4"
react-use: "npm:17.5.0"
- resium: "npm:^1.18.0"
+ resium: "npm:1.18.1"
suspend-react: "npm:0.1.3"
tiny-invariant: "npm:1.3.3"
use-callback-ref: "npm:1.3.2"
@@ -8077,10 +8077,10 @@ __metadata:
uuid: "npm:9.0.1"
xstate: "npm:4.38.2"
peerDependencies:
- cesium: 1.x
+ cesium: 1.118.x
react: ^18.2.0
react-dom: ^18.2.0
- checksum: 10c0/b8785d9a72076cdd0470d473ae9abd33107f2f8cf4f51dd6d233b8fa68870387c8aa2ddf8152d0405a6ea5a240fde747860ebc92aa04685b0f31d91123839a2e
+ checksum: 10c0/9efc7b5ef280d89ef4f039d82fa07fbf97c54cfcb321ecf9337e251f77a40313bd027554188f86089a314d3ca0084696358aee136c58fc66c8924a3e42d7f461
languageName: node
linkType: hard
@@ -8107,7 +8107,7 @@ __metadata:
"@monaco-editor/react": "npm:4.6.0"
"@playwright/test": "npm:1.39.0"
"@popperjs/core": "npm:2.11.8"
- "@reearth/core": "npm:0.0.7-alpha.6"
+ "@reearth/core": "npm:0.0.7-alpha.11"
"@rollup/plugin-yaml": "npm:4.1.2"
"@rot1024/use-transition": "npm:1.0.0"
"@sentry/browser": "npm:7.77.0"
@@ -8207,7 +8207,7 @@ __metadata:
use-file-input: "npm:1.0.0"
uuid: "npm:9.0.1"
vite: "npm:5.3.5"
- vite-plugin-cesium: "npm:1.2.22"
+ vite-plugin-cesium: "npm:1.2.23"
vite-plugin-svgr: "npm:4.2.0"
vite-tsconfig-paths: "npm:4.2.1"
vitest: "npm:1.6.0"
@@ -23770,14 +23770,14 @@ __metadata:
languageName: node
linkType: hard
-"resium@npm:^1.18.0":
- version: 1.18.0
- resolution: "resium@npm:1.18.0"
+"resium@npm:1.18.1":
+ version: 1.18.1
+ resolution: "resium@npm:1.18.1"
peerDependencies:
cesium: 1.x
react: ">=18.2.0"
react-dom: ">=18.2.0"
- checksum: 10c0/c4693e4aae6002eca35bce9c5d81df3d013784f2344d5a8b76fb7213acf23b16a7c96e751bf9951ee5ca2bec8fca879f86dc12fad03d5b1f675bdde249b06b77
+ checksum: 10c0/52e29361e3f59469125293d203e8c68baea499338c5bb93d642225817ddafdb30d8874baabbf124a9fea6f3daa8ac13bec71db6d466d5d2c90d103ee1d78ea5f
languageName: node
linkType: hard
@@ -26712,9 +26712,9 @@ __metadata:
languageName: node
linkType: hard
-"vite-plugin-cesium@npm:1.2.22":
- version: 1.2.22
- resolution: "vite-plugin-cesium@npm:1.2.22"
+"vite-plugin-cesium@npm:1.2.23":
+ version: 1.2.23
+ resolution: "vite-plugin-cesium@npm:1.2.23"
dependencies:
fs-extra: "npm:^9.1.0"
rollup-plugin-external-globals: "npm:^0.6.1"
@@ -26722,7 +26722,7 @@ __metadata:
peerDependencies:
cesium: ^1.95.0
vite: ">=2.7.1"
- checksum: 10c0/3c660d45a72908e6293f0ebf86668fad235fa1cd355f9e5e95fb5584cf9ffac2e2fa54c4cbfb74817624ffab210233595f0bdf8378aa4869beb4c234bffdba04
+ checksum: 10c0/5e14c4135d39ce7e84ad12c8315410b4a4f43fc306877687397bf2ccbf783f4388f87619ce2d9374696b1205ffa86e5f3c23820d3214350f1aab5cf097ea44d7
languageName: node
linkType: hard
From bdf32d6022d99a4637393c8f7fb10e5c3212b386 Mon Sep 17 00:00:00 2001
From: Beatrice Mkumbo
Date: Thu, 22 Aug 2024 09:07:44 +0300
Subject: [PATCH 05/23] fix(web): camera duration bug (#1107)
Co-authored-by: airslice
---
.../Editor/Story/PagesPanel/PageItem.tsx | 1 -
.../StoryPanel/Block/builtin/Title/index.tsx | 16 +++++++---
.../PageIndicator/IndicatorSection.tsx | 13 ++------
.../Visualizer/Crust/StoryPanel/hooks.ts | 8 ++---
.../beta/ui/components/EntryItem/index.tsx | 3 +-
web/src/beta/ui/fields/CamersField/index.tsx | 12 ++------
web/src/beta/ui/fields/QuartetInputField.tsx | 30 ++++++++++++-------
web/src/beta/ui/fields/TripletInputField.tsx | 26 +++++++++-------
web/src/beta/ui/fields/TwinInputField.tsx | 27 ++++++++++-------
9 files changed, 74 insertions(+), 62 deletions(-)
diff --git a/web/src/beta/features/Editor/Story/PagesPanel/PageItem.tsx b/web/src/beta/features/Editor/Story/PagesPanel/PageItem.tsx
index 8160ddabb..0f3670d70 100644
--- a/web/src/beta/features/Editor/Story/PagesPanel/PageItem.tsx
+++ b/web/src/beta/features/Editor/Story/PagesPanel/PageItem.tsx
@@ -133,5 +133,4 @@ const TitleWrapper = styled("div")(({ theme }) => ({
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
- maxWidth: "240px",
}));
diff --git a/web/src/beta/features/Visualizer/Crust/StoryPanel/Block/builtin/Title/index.tsx b/web/src/beta/features/Visualizer/Crust/StoryPanel/Block/builtin/Title/index.tsx
index 8030d0fe3..5d5a9abec 100644
--- a/web/src/beta/features/Visualizer/Crust/StoryPanel/Block/builtin/Title/index.tsx
+++ b/web/src/beta/features/Visualizer/Crust/StoryPanel/Block/builtin/Title/index.tsx
@@ -2,11 +2,10 @@ import { FC, useMemo } from "react";
import BlockWrapper from "@reearth/beta/features/Visualizer/shared/components/BlockWrapper";
import { CommonBlockProps as BlockProps } from "@reearth/beta/features/Visualizer/shared/types";
-import { Typography } from "@reearth/beta/lib/reearth-ui";
import { isEmptyString } from "@reearth/beta/utils/util";
import { ValueTypes } from "@reearth/beta/utils/value";
import { useT } from "@reearth/services/i18n";
-import { useTheme } from "@reearth/services/theme";
+import { styled, useTheme } from "@reearth/services/theme";
import { StoryBlock } from "../../../types";
@@ -38,11 +37,20 @@ const TitleBlock: FC> = ({ block, isSelected, ...props })
property={property}
dndEnabled={false}
{...props}>
-
+
{hasEmptySpace || !title ? t("Untitled") : title}
-
+
);
};
export default TitleBlock;
+
+const TitleWrapper = styled("div")<{ color?: string }>(({ color, theme }) => ({
+ color: color,
+ fontSize: theme.fonts.sizes.h2,
+ fontWeight: theme.fonts.weight.regular,
+ overflow: "hidden",
+ textOverflow: "ellipsis",
+ wordBreak: "break-word",
+}));
diff --git a/web/src/beta/features/Visualizer/Crust/StoryPanel/PageIndicator/IndicatorSection.tsx b/web/src/beta/features/Visualizer/Crust/StoryPanel/PageIndicator/IndicatorSection.tsx
index d37abd1f6..fdc9e32a3 100644
--- a/web/src/beta/features/Visualizer/Crust/StoryPanel/PageIndicator/IndicatorSection.tsx
+++ b/web/src/beta/features/Visualizer/Crust/StoryPanel/PageIndicator/IndicatorSection.tsx
@@ -1,4 +1,4 @@
-import { FC, useCallback, useMemo, useState } from "react";
+import { FC, useCallback, useMemo } from "react";
import { Popup } from "@reearth/beta/lib/reearth-ui";
import { styled } from "@reearth/services/theme";
@@ -11,14 +11,8 @@ type Props = {
};
const IndicatorSection: FC = ({ pageNumber, currentPageNumber, title, onPageChange }) => {
- const [isHovered, setIsHovered] = useState(false);
-
- const handleMouseEnter = useCallback(() => setIsHovered(true), []);
- const handleMouseOut = useCallback(() => setIsHovered(false), []);
-
const handleClick = useCallback(() => {
onPageChange(pageNumber);
- setIsHovered(false);
}, [pageNumber, onPageChange]);
const isHighlighted = useMemo(
@@ -33,12 +27,10 @@ const IndicatorSection: FC = ({ pageNumber, currentPageNumber, title, onP
}
- open={isHovered}
+ triggerOnHover
placement="bottom"
extendTriggerWidth>
@@ -72,4 +64,5 @@ const TitleWrapper = styled("div")(({ theme }) => ({
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
+ cursor: "default",
}));
diff --git a/web/src/beta/features/Visualizer/Crust/StoryPanel/hooks.ts b/web/src/beta/features/Visualizer/Crust/StoryPanel/hooks.ts
index e63670c06..c935611c3 100644
--- a/web/src/beta/features/Visualizer/Crust/StoryPanel/hooks.ts
+++ b/web/src/beta/features/Visualizer/Crust/StoryPanel/hooks.ts
@@ -129,12 +129,12 @@ export default (
}
handlePageTime(newPage);
-
const cameraAnimation = newPage.property?.cameraAnimation;
- const destination = cameraAnimation?.cameraPosition?.value;
+
+ const destination = cameraAnimation?.cameraPosition;
if (!destination) return;
- const duration = cameraAnimation?.cameraDuration?.value ?? DEFAULT_STORY_PAGE_DURATION;
+ const duration = cameraAnimation?.cameraDuration ?? DEFAULT_STORY_PAGE_DURATION;
visualizer.current?.engine.flyTo({ ...destination }, { duration });
},
@@ -148,7 +148,7 @@ export default (
const currentIndex = pages.findIndex(p => p.id === currentPageId);
return {
currentPage: currentIndex + 1,
- pageTitles: pages.map(p => p.property?.title?.title?.value),
+ pageTitles: pages.map(p => p.property?.title?.title),
maxPage: pages.length,
onPageChange: (pageIndex: number) => handleCurrentPageChange(pages[pageIndex - 1]?.id),
};
diff --git a/web/src/beta/ui/components/EntryItem/index.tsx b/web/src/beta/ui/components/EntryItem/index.tsx
index 941597651..ef0678f9c 100644
--- a/web/src/beta/ui/components/EntryItem/index.tsx
+++ b/web/src/beta/ui/components/EntryItem/index.tsx
@@ -101,7 +101,8 @@ const Wrapper = styled("div")<{
borderRadius: theme.radius.small,
backgroundColor: "transparent",
minHeight: 28,
- width: "100%",
+ flex: 1,
+ minWidth: 0,
cursor: "pointer",
...(hovered && {
backgroundColor: theme.bg[1],
diff --git a/web/src/beta/ui/fields/CamersField/index.tsx b/web/src/beta/ui/fields/CamersField/index.tsx
index d420ee405..9a05cb0e5 100644
--- a/web/src/beta/ui/fields/CamersField/index.tsx
+++ b/web/src/beta/ui/fields/CamersField/index.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useState, FC, useEffect } from "react";
+import { useCallback, useState, FC } from "react";
import { useCurrentCamera } from "@reearth/beta/features/Editor/atoms";
import { Button, ButtonProps, Popup, TextInput } from "@reearth/beta/lib/reearth-ui";
@@ -39,7 +39,7 @@ const CameraField: FC = ({
const theme = useTheme();
const t = useT();
const [open, setOpen] = useState<"editor" | "capture" | null>(null);
- const [currentCamera, setCurrentCamera] = useCurrentCamera();
+ const [currentCamera] = useCurrentCamera();
const handleClick = useCallback(
(panel: "editor" | "capture") => setOpen(current => (current === panel ? null : panel)),
@@ -58,13 +58,12 @@ const CameraField: FC = ({
const handleFlyto = useCallback(
(c?: Partial) => {
- if (!value) return;
const dest = c ?? currentCamera;
if (dest) {
onFlyTo?.(dest);
}
},
- [currentCamera, onFlyTo, value],
+ [currentCamera, onFlyTo],
);
const handleCameraSettingDelete = useCallback(() => {
@@ -72,11 +71,6 @@ const CameraField: FC = ({
handleSave();
}, [value, handleSave]);
- useEffect(() => {
- if (!value) return;
- setCurrentCamera(value);
- }, [setCurrentCamera, value]);
-
const ZoomToPosition: FC = () => (
+
+
+
+