Skip to content

Commit

Permalink
feat(web): plugin playground/enable edit html with modal (#1236)
Browse files Browse the repository at this point in the history
Co-authored-by: lby <[email protected]>
  • Loading branch information
devshun and airslice authored Nov 21, 2024
1 parent 045742a commit 898a0bb
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 25 deletions.
60 changes: 60 additions & 0 deletions web/src/beta/features/PluginPlayground/Code/HtmlEditModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {
Button,
CodeInput,
Modal,
ModalPanel
} from "@reearth/beta/lib/reearth-ui";
import { styled } from "@reearth/services/theme";
import { FC, useState } from "react";

type Props = {
isOpened: boolean;
sourceCode: string;
onClose: () => void;
onSubmit: (value: string) => void;
};

const HtmlEditModal: FC<Props> = ({
isOpened,
onClose,
sourceCode,
onSubmit
}) => {
const [value, setValue] = useState(sourceCode);
return (
<Modal size="medium" visible={isOpened}>
<ModalPanel
title="HTML Editor"
onCancel={onClose}
actions={
<>
<Button title="Cancel" onClick={onClose} />
<Button
title="Submit"
appearance="primary"
onClick={() => {
onSubmit(value);
onClose();
}}
/>
</>
}
>
<CodeInputWrapper>
<CodeInput
language="html"
value={value}
onChange={(value) => setValue(value ?? "")}
/>
</CodeInputWrapper>
</ModalPanel>
</Modal>
);
};

const CodeInputWrapper = styled("div")(() => ({
height: "100%",
minHeight: "554px"
}));

export default HtmlEditModal;
74 changes: 49 additions & 25 deletions web/src/beta/features/PluginPlayground/Code/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { Button, CodeInput } from "@reearth/beta/lib/reearth-ui";
import { styled } from "@reearth/services/theme";
import { FC } from "react";
import { FC, useCallback, useMemo, useState } from "react";

import HtmlEditModal from "./HtmlEditModal";
import {
extractHtmlFromSourceCode,
getLanguageByFileExtension,
injectHtmlIntoSourceCode
} from "./utils";

type Props = {
fileTitle: string;
Expand All @@ -9,37 +16,54 @@ type Props = {
executeCode: () => void;
};

const getLanguageByFileExtension = (fileTitle: string) => {
const ext = fileTitle.split(".").pop();
switch (ext) {
case "js":
return "javascript";
case "yml":
case "yaml":
return "yaml";
default:
return "plaintext";
}
};

const Code: FC<Props> = ({
fileTitle,
sourceCode,
onChangeSourceCode,
executeCode
}) => {
const editableHtmlSourceCode = useMemo(
() => extractHtmlFromSourceCode(sourceCode),
[sourceCode]
);

const onSubmitHtmlEditor = useCallback(
(newHtml: string) => {
onChangeSourceCode(injectHtmlIntoSourceCode(newHtml, sourceCode));
},
[sourceCode, onChangeSourceCode]
);

const [isOpenedHtmlEditor, setIsOpenedHtmlEditor] = useState(false);

return (
<Wrapper>
<Header>
<Button icon="playRight" iconButton onClick={executeCode} />
<p>Widget</p>
</Header>
<CodeInput
language={getLanguageByFileExtension(fileTitle)}
value={sourceCode}
onChange={onChangeSourceCode}
/>
</Wrapper>
<>
<Wrapper>
<Header>
<Button icon="playRight" iconButton onClick={executeCode} />
<Button
icon="pencilSimple"
title="HTML Editor"
disabled={!editableHtmlSourceCode}
onClick={() => setIsOpenedHtmlEditor(true)}
/>
<p>Widget</p>
</Header>
<CodeInput
language={getLanguageByFileExtension(fileTitle)}
value={sourceCode}
onChange={onChangeSourceCode}
/>
</Wrapper>
{isOpenedHtmlEditor && (
<HtmlEditModal
isOpened={isOpenedHtmlEditor}
sourceCode={editableHtmlSourceCode ?? ""}
onClose={() => setIsOpenedHtmlEditor(false)}
onSubmit={onSubmitHtmlEditor}
/>
)}
</>
);
};

Expand Down
30 changes: 30 additions & 0 deletions web/src/beta/features/PluginPlayground/Code/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const REEARTH_HTML_INJECTION_PATTERN =
/reearth\.(ui|modal|popup)\.show\(\s*(['"`])([^]*?)\2\s*\);/;

export const extractHtmlFromSourceCode = (sourceCode: string) => {
const match = REEARTH_HTML_INJECTION_PATTERN.exec(sourceCode);
return match?.[3];
};

export const injectHtmlIntoSourceCode = (
htmlSourceCode: string,
sourceCode: string
) => {
return sourceCode.replace(
REEARTH_HTML_INJECTION_PATTERN,
(_, type) => `reearth.${type}.show(\`${htmlSourceCode}\`);`
);
};

export const getLanguageByFileExtension = (fileTitle: string) => {
const ext = fileTitle.split(".").pop();
switch (ext) {
case "js":
return "javascript";
case "yml":
case "yaml":
return "yaml";
default:
return "plaintext";
}
};

0 comments on commit 898a0bb

Please sign in to comment.