visuddhinanda 2 лет назад
Родитель
Сommit
9bb40dc521

+ 0 - 115
dashboard/src/components/article/ArticleTplMaker.tsx

@@ -1,115 +0,0 @@
-import { useEffect, useState } from "react";
-import { Input, Modal, Select, Space, Typography } from "antd";
-
-import { TDisplayStyle } from "../template/Article";
-const { TextArea } = Input;
-const { Paragraph } = Typography;
-interface IWidget {
-  type?: string;
-  id?: string;
-  title?: string;
-  style?: TDisplayStyle;
-  trigger?: JSX.Element;
-  onSelect?: Function;
-  onCancel?: Function;
-}
-const ArticleTplMakerWidget = ({
-  type,
-  id,
-  title,
-  style = "modal",
-  trigger,
-  onSelect,
-  onCancel,
-}: IWidget) => {
-  const [isModalOpen, setIsModalOpen] = useState(false);
-  const [titleText, setTitleText] = useState(title);
-  const [styleText, setStyleText] = useState(style);
-  const [tplText, setTplText] = useState("");
-
-  const ids = id?.split("_");
-  const id1 = ids ? ids[0] : undefined;
-  const channels = ids
-    ? ids.length > 1
-      ? ids?.slice(1)
-      : undefined
-    : undefined;
-
-  const showModal = () => {
-    setIsModalOpen(true);
-  };
-
-  const handleOk = () => {
-    setIsModalOpen(false);
-  };
-
-  const handleCancel = () => {
-    setIsModalOpen(false);
-  };
-  useEffect(() => {
-    setTitleText(title);
-  }, [title]);
-  useEffect(() => {
-    let tplText = `{{article|
-type=${type}|
-id=${id1}|
-title=${titleText}|
-style=${styleText}`;
-    tplText += channels ? `channel=${channels}` : undefined;
-    tplText += "}}";
-
-    setTplText(tplText);
-  }, [titleText, styleText, type, id1, channels]);
-  return (
-    <>
-      <span onClick={showModal}>{trigger}</span>
-      <Modal
-        width={"80%"}
-        title="生成模版"
-        open={isModalOpen}
-        onOk={handleOk}
-        onCancel={handleCancel}
-      >
-        <Space direction="vertical" style={{ width: 500 }}>
-          <Space style={{ width: 500 }}>
-            {"标题:"}
-            <Input
-              width={400}
-              value={titleText}
-              placeholder="Basic usage"
-              onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                setTitleText(event.target.value);
-              }}
-            />
-          </Space>
-          <Space>
-            {"显示为:"}
-            <Select
-              defaultValue={style}
-              style={{ width: 120 }}
-              onChange={(value: string) => {
-                console.log(`selected ${value}`);
-                setStyleText(value as TDisplayStyle);
-              }}
-              options={[
-                { value: "modal", label: "对话框" },
-                { value: "card", label: "卡片" },
-              ]}
-            />
-          </Space>
-          <div>
-            <TextArea
-              value={tplText}
-              rows={4}
-              placeholder="maxLength is 6"
-              maxLength={6}
-            />
-            <Paragraph copyable={{ text: tplText }}>复制</Paragraph>
-          </div>
-        </Space>
-      </Modal>
-    </>
-  );
-};
-
-export default ArticleTplMakerWidget;

+ 194 - 0
dashboard/src/components/template/Builder/ArticleTpl.tsx

@@ -0,0 +1,194 @@
+import { useEffect, useState } from "react";
+import { Divider, Input, Modal, Select, Space, Tabs, Typography } from "antd";
+
+import { ArticleCtl, TDisplayStyle } from "../Article";
+import { ArticleType } from "../../article/Article";
+import { useIntl } from "react-intl";
+const { TextArea } = Input;
+const { Paragraph } = Typography;
+
+interface IWidget {
+  type?: ArticleType;
+  id?: string;
+  title?: string;
+  style?: TDisplayStyle;
+  onSelect?: Function;
+  onCancel?: Function;
+}
+const ArticleTplWidget = ({
+  type,
+  id,
+  title = "title",
+  style = "modal",
+}: IWidget) => {
+  const intl = useIntl(); //i18n
+  const [titleText, setTitleText] = useState(title);
+  const [styleText, setStyleText] = useState(style);
+  const [typeText, setTypeText] = useState(type);
+  const [idText, setIdText] = useState(id);
+  const [tplText, setTplText] = useState("");
+
+  const ids = id?.split("_");
+  const id1 = ids ? ids[0] : undefined;
+  const channels = ids
+    ? ids.length > 1
+      ? ids?.slice(1)
+      : undefined
+    : undefined;
+
+  useEffect(() => {
+    setTitleText(title);
+  }, [title]);
+  useEffect(() => {
+    let tplText = `{{article|
+type=${typeText}|
+id=${idText}|
+title=${titleText}|
+style=${styleText}`;
+
+    tplText += channels ? `channel=${channels}` : "";
+    tplText += "}}";
+
+    setTplText(tplText);
+  }, [titleText, styleText, type, id1, channels, typeText, idText]);
+  return (
+    <>
+      <Space direction="vertical" style={{ width: 500 }}>
+        <Space style={{ width: 500 }}>
+          {"标题:"}
+          <Input
+            width={400}
+            value={titleText}
+            placeholder="Title"
+            onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
+              setTitleText(event.target.value);
+            }}
+          />
+        </Space>
+        <Space>
+          {"类别:"}
+          <Select
+            disabled={type ? true : false}
+            defaultValue={type}
+            style={{ width: 120 }}
+            onChange={(value: string) => {
+              console.log(`selected ${value}`);
+              setTypeText(value as ArticleType);
+            }}
+            options={["article", "chapter", "para"].map((item) => {
+              return { value: item, label: item };
+            })}
+          />
+        </Space>
+        <Space style={{ width: 500 }}>
+          {"id:"}
+          <Input
+            disabled={id ? true : false}
+            defaultValue={id}
+            width={400}
+            value={idText}
+            placeholder="Title"
+            onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
+              setIdText(event.target.value);
+            }}
+          />
+        </Space>
+        <Space>
+          {"显示为:"}
+          <Select
+            defaultValue={style}
+            style={{ width: 120 }}
+            onChange={(value: string) => {
+              console.log(`selected ${value}`);
+              setStyleText(value as TDisplayStyle);
+            }}
+            options={[
+              { value: "modal", label: "对话框" },
+              { value: "card", label: "卡片" },
+            ]}
+          />
+        </Space>
+        <Tabs
+          size="small"
+          defaultActiveKey="preview"
+          items={[
+            {
+              label: intl.formatMessage({
+                id: "buttons.preview",
+              }),
+              key: "preview",
+              children: (
+                <ArticleCtl
+                  type={typeText}
+                  id={idText}
+                  title={titleText}
+                  style={styleText}
+                />
+              ),
+            },
+            {
+              label: `Code`,
+              key: "code",
+              children: (
+                <TextArea
+                  value={tplText}
+                  rows={4}
+                  placeholder="maxLength is 6"
+                  maxLength={6}
+                />
+              ),
+            },
+          ]}
+        />
+        <Divider></Divider>
+        <Paragraph copyable={{ text: tplText }}>复制到剪贴板</Paragraph>
+      </Space>
+    </>
+  );
+};
+
+interface IModalWidget {
+  type?: ArticleType;
+  id?: string;
+  title?: string;
+  style?: TDisplayStyle;
+  trigger?: JSX.Element;
+}
+export const ArticleTplModal = ({
+  type,
+  id,
+  title,
+  style = "modal",
+  trigger,
+}: IModalWidget) => {
+  const [isModalOpen, setIsModalOpen] = useState(false);
+
+  const showModal = () => {
+    setIsModalOpen(true);
+  };
+
+  const handleOk = () => {
+    setIsModalOpen(false);
+  };
+
+  const handleCancel = () => {
+    setIsModalOpen(false);
+  };
+
+  return (
+    <>
+      <span onClick={showModal}>{trigger}</span>
+      <Modal
+        width={"80%"}
+        title="生成模版"
+        open={isModalOpen}
+        onOk={handleOk}
+        onCancel={handleCancel}
+      >
+        <ArticleTplWidget type={type} id={id} title={title} style={style} />
+      </Modal>
+    </>
+  );
+};
+
+export default ArticleTplWidget;

+ 74 - 0
dashboard/src/components/template/Builder/Builder.tsx

@@ -0,0 +1,74 @@
+import { useState } from "react";
+import { Col, Modal, Row, Tree } from "antd";
+import { Key } from "antd/lib/table/interface";
+import ArticleTpl from "./ArticleTpl";
+
+interface DataNode {
+  title: React.ReactNode;
+  key: string;
+  isLeaf?: boolean;
+  children?: DataNode[];
+}
+
+interface tplListNode {
+  name: string;
+  component?: React.ReactNode;
+}
+
+interface IWidget {
+  trigger?: React.ReactNode;
+}
+const TplBuilderWidget = ({ trigger }: IWidget) => {
+  const [isModalOpen, setIsModalOpen] = useState(false);
+  const [template, setTemplate] =
+    useState<React.ReactNode>("在左侧列表选择一个模版");
+
+  const tplList: tplListNode[] = [
+    { name: "article", component: <ArticleTpl /> },
+    { name: "note" },
+    { name: "term" },
+  ];
+  const treeData: DataNode[] = tplList.map((item) => {
+    return { title: item.name, key: item.name };
+  });
+
+  const showModal = () => {
+    setIsModalOpen(true);
+  };
+
+  const handleCancel = () => {
+    setIsModalOpen(false);
+  };
+
+  return (
+    <>
+      <span onClick={showModal}>{trigger}</span>
+      <Modal
+        width={"80%"}
+        footer={false}
+        title="template builder"
+        open={isModalOpen}
+        onCancel={handleCancel}
+      >
+        <Row>
+          <Col span={8}>
+            <Tree
+              treeData={treeData}
+              onSelect={(selectedKeys: Key[]) => {
+                if (selectedKeys.length > 0) {
+                  const tpl = tplList.find(
+                    (value) => value.name === selectedKeys[0]
+                  )?.component;
+                  setTemplate(tpl);
+                }
+              }}
+            />
+          </Col>
+          <Col span={16}>{template}</Col>
+        </Row>
+      </Modal>
+    </>
+  );
+};
+
+export default TplBuilderWidget;