Skip to content

Commit

Permalink
chore(web): add widget and align system update functionality (#604)
Browse files Browse the repository at this point in the history
  • Loading branch information
KaWaite authored Jul 31, 2023
1 parent 54354b8 commit 0738b7e
Show file tree
Hide file tree
Showing 11 changed files with 246 additions and 20 deletions.
3 changes: 3 additions & 0 deletions web/src/beta/components/Icon/Icons/plugin.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions web/src/beta/components/Icon/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ import NavigatorAngle from "./Icons/navigatorAngle.svg";
import Compass from "./Icons/compass.svg";
import CompassFocus from "./Icons/compassFocus.svg";
import House from "./Icons/house.svg";
import Plugin from "./Icons/plugin.svg";

// Logos
import Logo from "./Icons/reearthLogo.svg";
Expand Down Expand Up @@ -152,4 +153,5 @@ export default {
compass: Compass,
compassFocus: CompassFocus,
house: House,
plugin: Plugin,
};
19 changes: 8 additions & 11 deletions web/src/beta/features/Editor/Visualizer/CanvasArea/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useMemo, useEffect, useCallback, useState } from "react";
import type { Alignment, Location } from "@reearth/beta/lib/core/Crust";
import type { LatLng, Tag, ValueTypes, ComputedLayer } from "@reearth/beta/lib/core/mantle";
import type { Layer, LayerSelectionReason, Cluster } from "@reearth/beta/lib/core/Map";
import { useSceneFetcher } from "@reearth/services/api";
import { useSceneFetcher, useWidgetsFetcher } from "@reearth/services/api";
import { config } from "@reearth/services/config";
import {
useSceneMode,
Expand All @@ -20,6 +20,7 @@ import { convertWidgets } from "./convert";
import { BlockType } from "./type";

export default ({ sceneId, isBuilt }: { sceneId?: string; isBuilt?: boolean }) => {
const { useUpdateWidget, useUpdateWidgetAlignSystem } = useWidgetsFetcher();
const { useSceneQuery } = useSceneFetcher();
const { scene } = useSceneQuery({ sceneId });

Expand Down Expand Up @@ -173,21 +174,17 @@ export default ({ sceneId, isBuilt }: { sceneId?: string; isBuilt?: boolean }) =
);

const onWidgetUpdate = useCallback(
async (_id: string, _update: { location?: Location; extended?: boolean; index?: number }) => {
if (!sceneId) return;

console.log("Widget has been updated!");
async (id: string, update: { location?: Location; extended?: boolean; index?: number }) => {
await useUpdateWidget(id, update, sceneId);
},
[sceneId],
[sceneId, useUpdateWidget],
);

const onWidgetAlignSystemUpdate = useCallback(
async (_location: Location, _align: Alignment) => {
if (!sceneId) return;

console.log("WAS has been updated!");
async (location: Location, align: Alignment) => {
await useUpdateWidgetAlignSystem(location, align, sceneId);
},
[sceneId],
[sceneId, useUpdateWidgetAlignSystem],
);

const engineMeta = useMemo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ const Settings: React.FC<Props> = ({ widgetPropertyId, propertyItems }) => {
const value = !isList ? i.fields.find(f => f.id === sf.id)?.value : sf.defaultValue;
return sf.type === "string" ? (
sf.ui === "color" ? (
<p>Color field</p>
<p key={sf.id}>Color field</p>
) : sf.ui === "selection" || sf.choices ? (
<p>Selection or choices field</p>
<p key={sf.id}>Selection or choices field</p>
) : sf.ui === "buttons" ? (
<p>Button radio field</p>
<p key={sf.id}>Button radio field</p>
) : (
<TextInput
key={sf.id}
Expand Down
115 changes: 112 additions & 3 deletions web/src/services/api/widgetsApi/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
import { useMutation, useQuery } from "@apollo/client";
import { useCallback, useMemo } from "react";

import { SceneWidget } from "@reearth/services/gql";
import {
SceneWidget,
WidgetAreaAlign,
WidgetAreaType,
WidgetSectionType,
WidgetZoneType,
} from "@reearth/services/gql";
import { GET_SCENE } from "@reearth/services/gql/queries/scene";
import { ADD_WIDGET, REMOVE_WIDGET } from "@reearth/services/gql/queries/widget";
import {
ADD_WIDGET,
REMOVE_WIDGET,
UPDATE_WIDGET,
UPDATE_WIDGET_ALIGN_SYSTEM,
} from "@reearth/services/gql/queries/widget";
import { useT } from "@reearth/services/i18n";
import { useNotification } from "@reearth/services/state";

Expand Down Expand Up @@ -96,17 +107,70 @@ export default () => {
[addWidgetMutation, setNotification, t],
);

const [updateWidget] = useMutation(UPDATE_WIDGET, { refetchQueries: ["GetScene"] });

const useUpdateWidget = useCallback(
async (
id: string,
update: { location?: WidgetLocation; extended?: boolean; index?: number },
sceneId?: string,
) => {
if (!sceneId) {
console.log("GraphQL: Failed to update widget because there is no sceneId provided");
setNotification({ type: "error", text: t("Failed to update widget.") });
return {
status: "error",
};
}

const { data, errors } = await updateWidget({
variables: {
sceneId,
widgetId: id,
enabled: true,
location: update.location
? {
zone: update.location.zone?.toUpperCase() as WidgetZoneType,
section: update.location.section?.toUpperCase() as WidgetSectionType,
area: update.location.area?.toUpperCase() as WidgetAreaType,
}
: undefined,
extended: update.extended,
index: update.index,
},
});

if (errors || !data?.updateWidget) {
console.log("GraphQL: Failed to update widget", errors);
setNotification({ type: "error", text: t("Failed to update widget.") });

return { status: "error" };
}

return {
data: data.updateWidget.scene.widgets,
status: "success",
};
},
[updateWidget, setNotification, t],
);

const [removeWidget] = useMutation(REMOVE_WIDGET, { refetchQueries: ["GetScene"] });

const useRemoveWidget = useCallback(
async (
sceneId?: string,
widgetId?: string,
): Promise<MutationReturn<Partial<SceneWidget>[]>> => {
if (!sceneId || !widgetId)
if (!sceneId || !widgetId) {
console.log(
"GraphQL: Failed to remove widget because there is either no sceneId or widgetId provided",
);
setNotification({ type: "error", text: t("Failed to update widget.") });
return {
status: "error",
};
}

const { data, errors } = await removeWidget({
variables: { sceneId: sceneId ?? "", widgetId },
Expand All @@ -127,10 +191,55 @@ export default () => {
[removeWidget, setNotification, t],
);

const [updateWidgetAlignSystem] = useMutation(UPDATE_WIDGET_ALIGN_SYSTEM, {
refetchQueries: ["GetScene"],
});

const useUpdateWidgetAlignSystem = useCallback(
async (location: WidgetLocation, align: WidgetAlignment, sceneId?: string) => {
if (!sceneId) {
console.log(
"GraphQL: Failed to update the widget align system because there is no sceneId provided",
);
setNotification({ type: "error", text: t("Failed to update widget alignment.") });
return {
status: "error",
};
}

const { data, errors } = await updateWidgetAlignSystem({
variables: {
sceneId,
location: {
zone: location.zone.toUpperCase() as WidgetZoneType,
section: location.section.toUpperCase() as WidgetSectionType,
area: location.area.toUpperCase() as WidgetAreaType,
},
align: align?.toUpperCase() as WidgetAreaAlign,
},
});

if (errors || !data?.updateWidgetAlignSystem) {
console.log("GraphQL: Failed to update the widget align system", errors);
setNotification({ type: "error", text: t("Failed to update the widget align system.") });

return { status: "error" };
}

return {
data: data.updateWidgetAlignSystem.scene.widgetAlignSystem,
status: "success",
};
},
[updateWidgetAlignSystem, setNotification, t],
);

return {
useInstallableWidgetsQuery,
useInstalledWidgetsQuery,
useAddWidget,
useUpdateWidget,
useUpdateWidgetAlignSystem,
useRemoveWidget,
};
};
2 changes: 1 addition & 1 deletion web/src/services/api/widgetsApi/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const getInstallableWidgets = (rawScene?: GetSceneQuery) => {
undefined,
};
})
.filter((w): w is InstallableWidget => !!w);
.filter((w): w is InstallableWidget => !!w && !w.title.includes("legacy"));
})
.reduce<InstallableWidget[]>((a, b) => (b ? [...a, ...b] : a), []);
};
Expand Down
10 changes: 10 additions & 0 deletions web/src/services/gql/__gen__/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ const documents = {
"\n mutation UpdateMe(\n $name: String\n $email: String\n $lang: Lang\n $theme: Theme\n $password: String\n $passwordConfirmation: String\n ) {\n updateMe(\n input: {\n name: $name\n email: $email\n lang: $lang\n theme: $theme\n password: $password\n passwordConfirmation: $passwordConfirmation\n }\n ) {\n me {\n id\n name\n email\n lang\n theme\n myTeam {\n id\n name\n }\n }\n }\n }\n": types.UpdateMeDocument,
"\n mutation DeleteMe($userId: ID!) {\n deleteMe(input: { userId: $userId }) {\n userId\n }\n }\n": types.DeleteMeDocument,
" mutation AddWidget($sceneId: ID!, $pluginId: ID!, $extensionId: ID!, $lang: Lang) {\n addWidget(\n input: {sceneId: $sceneId, pluginId: $pluginId, extensionId: $extensionId}\n ) {\n scene {\n id\n widgets {\n id\n enabled\n pluginId\n extensionId\n propertyId\n property {\n id\n ...PropertyFragment\n }\n }\n }\n sceneWidget {\n id\n enabled\n pluginId\n extensionId\n }\n }\n }": types.AddWidgetDocument,
"\n mutation UpdateWidget(\n $sceneId: ID!\n $widgetId: ID!\n $enabled: Boolean\n $location: WidgetLocationInput\n $extended: Boolean\n $index: Int\n ) {\n updateWidget(\n input: {\n sceneId: $sceneId\n widgetId: $widgetId\n enabled: $enabled\n location: $location\n extended: $extended\n index: $index\n }\n ) {\n scene {\n id\n widgets {\n id\n enabled\n extended\n pluginId\n extensionId\n propertyId\n }\n }\n }\n }\n": types.UpdateWidgetDocument,
"\n mutation RemoveWidget($sceneId: ID!, $widgetId: ID!) {\n removeWidget(input: { sceneId: $sceneId, widgetId: $widgetId }) {\n scene {\n id\n widgets {\n id\n enabled\n pluginId\n extensionId\n propertyId\n }\n }\n }\n }\n": types.RemoveWidgetDocument,
"\n mutation UpdateWidgetAlignSystem(\n $sceneId: ID!\n $location: WidgetLocationInput!\n $align: WidgetAreaAlign\n $padding: WidgetAreaPaddingInput\n $gap: Int\n $centered: Boolean\n $background: String\n ) {\n updateWidgetAlignSystem(\n input: {\n sceneId: $sceneId\n location: $location\n align: $align\n padding: $padding\n gap: $gap\n centered: $centered\n background: $background\n }\n ) {\n scene {\n id\n widgets {\n id\n enabled\n pluginId\n extensionId\n propertyId\n }\n widgetAlignSystem {\n ...WidgetAlignSystemFragment\n }\n }\n }\n }\n": types.UpdateWidgetAlignSystemDocument,
"\n mutation CreateWorkspace($name: String!) {\n createTeam(input: { name: $name }) {\n team {\n id\n name\n members {\n user {\n id\n name\n email\n }\n userId\n role\n }\n personal\n policyId\n policy {\n id\n name\n projectCount\n memberCount\n publishedProjectCount\n layerCount\n assetStorageSize\n datasetSchemaCount\n datasetCount\n }\n }\n }\n }\n": types.CreateWorkspaceDocument,
};

Expand Down Expand Up @@ -166,10 +168,18 @@ export function gql(source: "\n mutation DeleteMe($userId: ID!) {\n deleteMe
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function gql(source: " mutation AddWidget($sceneId: ID!, $pluginId: ID!, $extensionId: ID!, $lang: Lang) {\n addWidget(\n input: {sceneId: $sceneId, pluginId: $pluginId, extensionId: $extensionId}\n ) {\n scene {\n id\n widgets {\n id\n enabled\n pluginId\n extensionId\n propertyId\n property {\n id\n ...PropertyFragment\n }\n }\n }\n sceneWidget {\n id\n enabled\n pluginId\n extensionId\n }\n }\n }"): (typeof documents)[" mutation AddWidget($sceneId: ID!, $pluginId: ID!, $extensionId: ID!, $lang: Lang) {\n addWidget(\n input: {sceneId: $sceneId, pluginId: $pluginId, extensionId: $extensionId}\n ) {\n scene {\n id\n widgets {\n id\n enabled\n pluginId\n extensionId\n propertyId\n property {\n id\n ...PropertyFragment\n }\n }\n }\n sceneWidget {\n id\n enabled\n pluginId\n extensionId\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 UpdateWidget(\n $sceneId: ID!\n $widgetId: ID!\n $enabled: Boolean\n $location: WidgetLocationInput\n $extended: Boolean\n $index: Int\n ) {\n updateWidget(\n input: {\n sceneId: $sceneId\n widgetId: $widgetId\n enabled: $enabled\n location: $location\n extended: $extended\n index: $index\n }\n ) {\n scene {\n id\n widgets {\n id\n enabled\n extended\n pluginId\n extensionId\n propertyId\n }\n }\n }\n }\n"): (typeof documents)["\n mutation UpdateWidget(\n $sceneId: ID!\n $widgetId: ID!\n $enabled: Boolean\n $location: WidgetLocationInput\n $extended: Boolean\n $index: Int\n ) {\n updateWidget(\n input: {\n sceneId: $sceneId\n widgetId: $widgetId\n enabled: $enabled\n location: $location\n extended: $extended\n index: $index\n }\n ) {\n scene {\n id\n widgets {\n id\n enabled\n extended\n pluginId\n extensionId\n propertyId\n }\n }\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 RemoveWidget($sceneId: ID!, $widgetId: ID!) {\n removeWidget(input: { sceneId: $sceneId, widgetId: $widgetId }) {\n scene {\n id\n widgets {\n id\n enabled\n pluginId\n extensionId\n propertyId\n }\n }\n }\n }\n"): (typeof documents)["\n mutation RemoveWidget($sceneId: ID!, $widgetId: ID!) {\n removeWidget(input: { sceneId: $sceneId, widgetId: $widgetId }) {\n scene {\n id\n widgets {\n id\n enabled\n pluginId\n extensionId\n propertyId\n }\n }\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 UpdateWidgetAlignSystem(\n $sceneId: ID!\n $location: WidgetLocationInput!\n $align: WidgetAreaAlign\n $padding: WidgetAreaPaddingInput\n $gap: Int\n $centered: Boolean\n $background: String\n ) {\n updateWidgetAlignSystem(\n input: {\n sceneId: $sceneId\n location: $location\n align: $align\n padding: $padding\n gap: $gap\n centered: $centered\n background: $background\n }\n ) {\n scene {\n id\n widgets {\n id\n enabled\n pluginId\n extensionId\n propertyId\n }\n widgetAlignSystem {\n ...WidgetAlignSystemFragment\n }\n }\n }\n }\n"): (typeof documents)["\n mutation UpdateWidgetAlignSystem(\n $sceneId: ID!\n $location: WidgetLocationInput!\n $align: WidgetAreaAlign\n $padding: WidgetAreaPaddingInput\n $gap: Int\n $centered: Boolean\n $background: String\n ) {\n updateWidgetAlignSystem(\n input: {\n sceneId: $sceneId\n location: $location\n align: $align\n padding: $padding\n gap: $gap\n centered: $centered\n background: $background\n }\n ) {\n scene {\n id\n widgets {\n id\n enabled\n pluginId\n extensionId\n propertyId\n }\n widgetAlignSystem {\n ...WidgetAlignSystemFragment\n }\n }\n }\n }\n"];
/**
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
Expand Down
Loading

0 comments on commit 0738b7e

Please sign in to comment.