Skip to content

Commit

Permalink
feat(web): support plugin block property (#1029)
Browse files Browse the repository at this point in the history
  • Loading branch information
airslice authored Jun 26, 2024
1 parent 37908a0 commit c07a2a2
Show file tree
Hide file tree
Showing 13 changed files with 93 additions and 21 deletions.
2 changes: 2 additions & 0 deletions web/src/beta/features/Editor/Visualizer/convert-infobox.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { InfoboxBlock } from "@reearth/beta/features/Visualizer/Crust/Infobox/types";
import type { Layer } from "@reearth/core";
import { NLSInfobox } from "@reearth/services/api/layersApi/utils";
import { convert } from "@reearth/services/api/propertyApi/utils";

import { processProperty as processNewProperty } from "./processNewProperty";

Expand All @@ -22,6 +23,7 @@ export default (
extensionId: b.extensionId,
property: processNewProperty(undefined, b.property),
propertyId: b.propertyId, // required by onBlockChange
pluginBlockPropertyItems: convert(b.property),
})),
};
};
2 changes: 2 additions & 0 deletions web/src/beta/features/Editor/Visualizer/convert-story.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
StoryBlock,
StoryPage,
} from "@reearth/beta/features/Visualizer/Crust/StoryPanel/types";
import { convert } from "@reearth/services/api/propertyApi/utils";
import { Scene } from "@reearth/services/api/sceneApi";
import { StoryPage as GqlStoryPage, StoryBlock as GqlStoryBlock } from "@reearth/services/gql";

Expand Down Expand Up @@ -38,6 +39,7 @@ export const convertStory = (scene?: Scene, storyId?: string): Story | undefined
name: installedBlockNames?.[b.extensionId] ?? "Story Block",
propertyId: b.property?.id,
property: processProperty(undefined, b.property),
pluginBlockPropertyItems: convert(b.property),
}));

return {
Expand Down
12 changes: 11 additions & 1 deletion web/src/beta/features/Visualizer/Crust/Infobox/Block/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,17 @@ const InfoboxBlockComponent = ({ renderBlock, onRemove, ...props }: Props): JSX.
return Builtin ? (
<Builtin {...props} minHeight={120} onRemove={onRemove ? handleRemove : undefined} />
) : props.block ? (
<BlockWrapper {...props} minHeight={120} onRemove={onRemove ? handleRemove : undefined}>
<BlockWrapper
{...props}
minHeight={120}
isPluginBlock
name={props.block.name}
isEditable={props.isEditable}
isSelected={props.isSelected}
property={props.block.property}
propertyId={props.block.propertyId}
pluginBlockPropertyItems={props.block.pluginBlockPropertyItems}
onRemove={onRemove ? handleRemove : undefined}>
{renderBlock?.({ block: props.block, layer: props.layer, onClick: props.onClick })}
</BlockWrapper>
) : null;
Expand Down
2 changes: 2 additions & 0 deletions web/src/beta/features/Visualizer/Crust/Infobox/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Layer, Spacing } from "@reearth/core";
import { Item } from "@reearth/services/api/propertyApi/utils";

export type Infobox<BP = any> = {
featureId?: string;
Expand All @@ -24,6 +25,7 @@ export type InfoboxBlock<P = any> = {
extensionId?: string;
property?: P;
propertyId?: string;
pluginBlockPropertyItems?: Item[];
};

export type InfoboxBlockProps<P = any> = {
Expand Down
12 changes: 10 additions & 2 deletions web/src/beta/features/Visualizer/Crust/Plugins/plugin_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import {
ScreenSpaceCameraControllerOptions,
} from "@reearth/core";

import { InfoboxBlock as Block } from "../Infobox/types";
import { InteractionModeType } from "../types";
import { Widget } from "../Widgets";

Expand Down Expand Up @@ -112,7 +111,7 @@ export type Reearth = {
>;
readonly layer?: LazyLayer;
readonly widget?: Widget;
readonly block?: Block;
readonly block?: CommonBlock;
readonly scene: Undefinable<Scene>;
readonly viewport?: Viewport;
readonly clientStorage: ClientStorage;
Expand All @@ -131,6 +130,15 @@ export type Reearth = {
) => void;
};

export type CommonBlock = {
id: string;
name?: string | null;
pluginId: string;
extensionId: string;
propertyId?: string;
property?: any;
};

export type Scene = {
readonly inEditor: boolean;
readonly built: boolean;
Expand Down
24 changes: 12 additions & 12 deletions web/src/beta/features/Visualizer/Crust/StoryPanel/Block/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { useCallback, type ComponentType, type ReactNode } from "react";

import type { CommonBlockProps, BlockProps } from "@reearth/beta/features/Visualizer/shared/types";
import type { Layer } from "@reearth/core";
import { styled } from "@reearth/services/theme";

import BlockWrapper from "../../../shared/components/BlockWrapper";
import { StoryBlock } from "../types";

import builtin, { isBuiltinStoryBlock } from "./builtin";
Expand Down Expand Up @@ -31,17 +31,17 @@ export default function StoryBlockComponent({
return Builtin ? (
<Builtin {...props} onRemove={onRemove ? handleRemove : undefined} />
) : props.block ? (
<Wrapper editable={props?.isEditable} onClick={props?.onClick} selected={props?.isSelected}>
<BlockWrapper
{...props}
isPluginBlock
name={props.block.name}
isEditable={props.isEditable}
isSelected={props.isSelected}
property={props.block.property}
propertyId={props.block.propertyId}
pluginBlockPropertyItems={props.block.pluginBlockPropertyItems}
onRemove={onRemove ? handleRemove : undefined}>
{renderBlock?.({ block: props.block, layer: props.layer, onClick: props.onClick })}
</Wrapper>
</BlockWrapper>
) : null;
}

const Wrapper = styled.div<{ editable?: boolean; selected?: boolean }>`
border: 1px solid
${({ selected, editable, theme }) => (editable && selected ? theme.select.main : "transparent")};
:hover {
${({ editable, theme }) => editable && `border-color: ${theme.outline.main}`};
}
`;
3 changes: 3 additions & 0 deletions web/src/beta/features/Visualizer/Crust/StoryPanel/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Item } from "@reearth/services/api/propertyApi/utils";

export type Position = "left" | "right";

export type Story = {
Expand Down Expand Up @@ -25,6 +27,7 @@ export type StoryBlock = {
extensionId: string;
propertyId?: string;
property?: any;
pluginBlockPropertyItems?: Item[];
};

export type Field<V = any> = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ const Wrapper = styled.div<{ isSelected?: boolean; position?: ActionPosition }>`
gap: 4px;
height: 24px;
position: absolute;
max-width: 100%;
${({ position }) =>
position === "left-top"
? `
Expand Down Expand Up @@ -210,6 +211,10 @@ const OptionWrapper = styled.div<{ showPointer?: boolean }>`

const OptionText = styled(Text)`
padding-right: 4px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
max-width: 150px;
`;

const OptionIcon = styled(Icon)<{ border?: boolean }>`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,18 @@ export default ({
};
}, [property?.panel, isEditable]);

const pluginBlockSettings = useMemo(() => {
return property;
}, [property]);

return {
title,
groupId,
editMode,
showSettings,
defaultSettings,
generalBlockSettings,
pluginBlockSettings,
disableSelection,
handleEditModeToggle,
handleSettingsToggle,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { ReactNode, createContext, memo } from "react";
import { ReactNode, createContext, memo, useCallback } from "react";

import PropertyItem from "@reearth/beta/components/fields/Property/PropertyItem";
import SidePanelSectionField from "@reearth/beta/components/SidePanelSectionField";
import { stopClickPropagation } from "@reearth/beta/utils/events";
import { FlyTo, useVisualizer } from "@reearth/core";
import { Item } from "@reearth/services/api/propertyApi/utils";
import { styled } from "@reearth/services/theme";

import Template from "../../../Crust/StoryPanel/Block/Template";
Expand All @@ -26,9 +30,11 @@ type Props = {
children?: ReactNode;
propertyId?: string;
property?: any;
pluginBlockPropertyItems?: Item[];
dndEnabled?: boolean;
settingsEnabled?: boolean;
minHeight?: number;
isPluginBlock?: boolean;
onClick?: () => void;
onClickAway?: () => void;
onRemove?: () => void;
Expand Down Expand Up @@ -63,9 +69,11 @@ const BlockWrapper: React.FC<Props> = ({
children,
propertyId,
property,
pluginBlockPropertyItems,
dndEnabled = true,
settingsEnabled = true,
minHeight,
isPluginBlock,
onClick,
onBlockDoubleClick,
onClickAway,
Expand All @@ -82,6 +90,7 @@ const BlockWrapper: React.FC<Props> = ({
showSettings,
defaultSettings,
generalBlockSettings,
pluginBlockSettings,
disableSelection,
handleEditModeToggle,
handleSettingsToggle,
Expand All @@ -96,6 +105,14 @@ const BlockWrapper: React.FC<Props> = ({
onBlockDoubleClick,
});

const visualizerRef = useVisualizer();
const handleFlyTo: FlyTo = useCallback(
(target, options) => {
visualizerRef.current?.engine.flyTo(target, options);
},
[visualizerRef],
);

return (
<BlockContext.Provider value={{ editMode }}>
<SelectableArea
Expand All @@ -106,7 +123,8 @@ const BlockWrapper: React.FC<Props> = ({
propertyId={propertyId}
dndEnabled={dndEnabled}
showSettings={showSettings}
contentSettings={generalBlockSettings}
contentSettings={isPluginBlock ? pluginBlockSettings : generalBlockSettings}
isPluginBlock={isPluginBlock}
editMode={editMode}
isEditable={isEditable}
hideHoverUI={disableSelection}
Expand All @@ -130,7 +148,7 @@ const BlockWrapper: React.FC<Props> = ({
{children ?? (isEditable && <Template icon={icon} height={minHeight} />)}
{!editMode && isEditable && <Overlay disableSelection={disableSelection} />}
</Block>
{editMode && groupId && propertyId && settingsEnabled && (
{editMode && groupId && propertyId && settingsEnabled && !isPluginBlock && (
<EditorPanel onClick={stopClickPropagation}>
{Object.keys(defaultSettings).map((fieldId, idx) => {
const field = defaultSettings[fieldId];
Expand All @@ -150,6 +168,15 @@ const BlockWrapper: React.FC<Props> = ({
})}
</EditorPanel>
)}
{editMode && propertyId && settingsEnabled && isPluginBlock && (
<EditorPanel onClick={stopClickPropagation}>
{pluginBlockPropertyItems?.map((i, idx) => (
<SidePanelSectionField title={i.title} key={idx}>
<PropertyItem key={i.id} propertyId={propertyId} item={i} onFlyTo={handleFlyTo} />
</SidePanelSectionField>
))}
</EditorPanel>
)}
</SelectableArea>
</BlockContext.Provider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Props = {
isSelected?: boolean;
editMode?: boolean;
contentSettings?: any;
isPluginBlock?: boolean;
setShowPadding: Dispatch<SetStateAction<boolean>>;
onRemove?: () => void;
onEditModeToggle?: (enable: boolean) => void;
Expand All @@ -24,6 +25,7 @@ export default ({
isSelected,
editMode,
contentSettings,
isPluginBlock,
setShowPadding,
onRemove,
onEditModeToggle,
Expand All @@ -41,7 +43,7 @@ export default ({

const popoverContent = useMemo(() => {
const menuItems: { name: string; icon: Icons; onClick: () => void }[] = [];
if (contentSettings) {
if (!isPluginBlock && contentSettings) {
menuItems.push({
name: settingsTitle,
icon: "padding",
Expand All @@ -56,7 +58,7 @@ export default ({
});
}
return menuItems;
}, [settingsTitle, contentSettings, t, setShowPadding, onRemove, handleRemove]);
}, [isPluginBlock, settingsTitle, contentSettings, t, setShowPadding, onRemove, handleRemove]);

const actionItems: ActionItem[] = useMemo(() => {
const menuItems: ActionItem[] = [
Expand All @@ -66,7 +68,7 @@ export default ({
},
];

if (onEditModeToggle && !!contentSettings) {
if (onEditModeToggle && !!contentSettings && Object.keys(contentSettings).length !== 0) {
menuItems.push({
icon: editMode ? "exit" : "storyBlockEdit",
hide: !isSelected,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type Props = {
editMode?: boolean;
propertyId?: string;
contentSettings?: any;
isPluginBlock?: boolean;
dndEnabled?: boolean;
position?: ActionPosition;
overrideGroupId?: string;
Expand Down Expand Up @@ -53,6 +54,7 @@ const ActionPanel: React.FC<Props> = ({
editMode,
dndEnabled,
contentSettings,
isPluginBlock,
setShowPadding,
onEditModeToggle,
onSettingsToggle,
Expand All @@ -65,6 +67,7 @@ const ActionPanel: React.FC<Props> = ({
isSelected,
editMode,
contentSettings,
isPluginBlock,
setShowPadding,
onEditModeToggle,
onSettingsToggle,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type Props = {
children: ReactNode;
propertyId?: string;
contentSettings?: any;
isPluginBlock?: boolean;
dndEnabled?: boolean;
showSettings?: boolean;
editMode?: boolean;
Expand Down Expand Up @@ -67,6 +68,7 @@ const SelectableArea: React.FC<Props> = ({
isEditable,
hideHoverUI,
contentSettings,
isPluginBlock,
overrideGroupId,
domId,
onEditModeToggle,
Expand Down Expand Up @@ -112,6 +114,7 @@ const SelectableArea: React.FC<Props> = ({
editMode={editMode}
propertyId={propertyId}
contentSettings={contentSettings}
isPluginBlock={isPluginBlock}
dndEnabled={dndEnabled}
position={position}
overrideGroupId={overrideGroupId}
Expand Down

0 comments on commit c07a2a2

Please sign in to comment.