diff --git a/web/public/locales/en/translation.json b/web/public/locales/en/translation.json index dc44410b1a..4316ee58b6 100644 --- a/web/public/locales/en/translation.json +++ b/web/public/locales/en/translation.json @@ -83,7 +83,7 @@ "Function": "Function", "FunctionList": "Function List", "FunctionName": "Function Name", - "FunctionNameTip": "The unique identifier of the function, such as", + "FunctionNameTip": "The unique identifier of the function, such as get-user", "InterfaceDebug": "Interface Debugging", "Methods": "Request Method", "Name": "Parameter Name", @@ -91,7 +91,8 @@ "Select": "chosen", "SystemDependence": "Built-In", "Value": "Value", - "isSupport": "Whether to support" + "isSupport": "Whether to support", + "FunctionNameRule": "Function names can only be in letters" }, "HomePanel": { "APP": "Android or iOS app", @@ -166,7 +167,8 @@ "SetTimeout": "timed task", "Time": "Creation/update time", "Trigger": "Trigger", - "Type": "Type" + "Type": "Type", + "CronHelp": "more examples" }, "NoData": "Currently no data" } diff --git a/web/public/locales/zh-CN/translation.json b/web/public/locales/zh-CN/translation.json index de17c9f77b..8bc9571304 100644 --- a/web/public/locales/zh-CN/translation.json +++ b/web/public/locales/zh-CN/translation.json @@ -59,7 +59,7 @@ "AddFunction": "添加函数", "EditFunction": "编辑函数", "FunctionName": "函数名", - "FunctionNameTip": "函数唯一标识, 如", + "FunctionNameTip": "函数唯一标识, 如 get-user", "Methods": "请求方法", "Description": "函数描述", "Code": "函数模板", @@ -79,7 +79,8 @@ "DependenceName": "依赖包名", "DependenceVersion": "依赖版本", "DependenceTip": "请输入依赖包名", - "Select": "已选择" + "Select": "已选择", + "FunctionNameRule": "函数名只能是英文" }, "TriggerPanel": { "Trigger": "触发器", @@ -90,11 +91,13 @@ "Function": "关联函数", "FunctionTip": "请选择关联的云函数", "Type": "类型", + "Cron": "表达式", "SetTimeout": "定时任务", - "Time": "创建/更新时间", + "Time": "更新时间", "Express": "表达式", "CornTip": "例:0/1 * * * * ?表示每 1 秒执行任务", - "DeleteConfirm": "确定删除该触发器吗" + "DeleteConfirm": "确定删除该触发器吗", + "CronHelp": "更多示例" }, "LogPanel": { "Log": "日志", diff --git a/web/public/locales/zh/translation.json b/web/public/locales/zh/translation.json index c0897b3c63..74c95cb7e3 100644 --- a/web/public/locales/zh/translation.json +++ b/web/public/locales/zh/translation.json @@ -83,7 +83,7 @@ "Function": "函数", "FunctionList": "函数列表", "FunctionName": "函数名", - "FunctionNameTip": "函数唯一标识, 如", + "FunctionNameTip": "函数唯一标识, 如 get-user", "InterfaceDebug": "接口调试", "Methods": "请求方法", "Name": "参数名", @@ -91,7 +91,8 @@ "Select": "已选择", "SystemDependence": "内置依赖", "Value": "值", - "isSupport": "是否支持" + "isSupport": "是否支持", + "FunctionNameRule": "函数名只能是英文" }, "HomePanel": { "APP": "Android or iOS 应用", @@ -166,7 +167,8 @@ "SetTimeout": "定时任务", "Time": "创建/更新时间", "Trigger": "触发器", - "Type": "类型" + "Type": "类型", + "CronHelp": "更多示例" }, "NoData": "当前无数据" } diff --git a/web/src/apis/typing.d.ts b/web/src/apis/typing.d.ts index e839a57f28..70f24d9bcd 100644 --- a/web/src/apis/typing.d.ts +++ b/web/src/apis/typing.d.ts @@ -198,12 +198,14 @@ export interface TFunction { desc: string; tags: any[]; websocket: boolean; - methods: string[]; + methods: TMethod[]; createdAt: string; updatedAt: string; createdBy: string; } +export type TMethod = "GET" | "POST" | "PUT" | "DELETE" | "HEAD" | "OPTIONS" | "PATCH"; + export interface Source { code: string; compiled: string; diff --git a/web/src/chakraTheme.ts b/web/src/chakraTheme.ts index d0fbf11a87..295f01fe4a 100644 --- a/web/src/chakraTheme.ts +++ b/web/src/chakraTheme.ts @@ -201,7 +201,16 @@ const Tabs = { const Table = { baseStyle: {}, variants: { - unstyled: { + simple: { + parts: ["th", "td"], + th: { + border: "none", + }, + td: { + border: "none", + }, + }, + border: { parts: ["th", "td"], th: { border: "1px solid #dddddd", @@ -212,7 +221,7 @@ const Table = { }, }, defaultProps: { - variant: "unstyled", + variant: "border", }, }; diff --git a/web/src/constants/index.ts b/web/src/constants/index.ts index 57b46909e0..86d43ed702 100644 --- a/web/src/constants/index.ts +++ b/web/src/constants/index.ts @@ -4,7 +4,6 @@ export const SmallNavHeight = 42; export const Pages = { function: "function", - trigger: "trigger", storage: "storage", database: "database", logs: "logs", @@ -24,6 +23,14 @@ export enum APP_STATUS { export const DEFAULT_REGION = "default"; +export enum SUPPORTED_METHODS { + GET = "GET", + POST = "POST", + PUT = "PUT", + PATCH = "PATCH", + DELETE = "DELETE", +} + export enum APP_PHASE_STATUS { Creating = "Creating", Started = "Started", diff --git a/web/src/pages/app/functions/mods/DebugPanel/index.tsx b/web/src/pages/app/functions/mods/DebugPanel/index.tsx index 5926b73853..0f30c77f0e 100644 --- a/web/src/pages/app/functions/mods/DebugPanel/index.tsx +++ b/web/src/pages/app/functions/mods/DebugPanel/index.tsx @@ -18,7 +18,7 @@ import { keyBy, mapValues } from "lodash"; import { Row } from "@/components/Grid"; import Panel from "@/components/Panel"; -import { Pages } from "@/constants"; +import { Pages, SUPPORTED_METHODS } from "@/constants"; import { useCompileMutation } from "../../service"; import useFunctionStore from "../../store"; @@ -27,6 +27,7 @@ import BodyParamsTab from "./BodyParamsTab"; import QueryParamsTab from "./QueryParamsTab"; import HeaderParamsTab from "./QueryParamsTab"; +import { TMethod } from "@/apis/typing"; import useFunctionCache from "@/hooks/useFunctionCache"; import useHotKey, { DEFAULT_SHORTCUTS } from "@/hooks/useHotKey"; import useGlobalStore from "@/pages/globalStore"; @@ -44,7 +45,7 @@ export default function DebugPanel() { const [runningResData, setRunningResData] = useState(); const [isLoading, setIsLoading] = useState(false); - const [runningMethod, setRunningMethod] = useState(""); + const [runningMethod, setRunningMethod] = useState(); const compileMutation = useCompileMutation(); @@ -126,7 +127,7 @@ export default function DebugPanel() { value={runningMethod} disabled={getFunctionUrl() === ""} onChange={(e) => { - setRunningMethod(e.target.value); + setRunningMethod(e.target.value as TMethod); }} > {currentFunction.methods?.map((item: string) => { @@ -158,12 +159,15 @@ export default function DebugPanel() { ({queryParams.length}) )} - - Body - {Object.keys(bodyParams).length > 0 && ( - ({Object.keys(bodyParams).length}) - )} - + {runningMethod === SUPPORTED_METHODS.POST && ( + + Body + {Object.keys(bodyParams).length > 0 && ( + ({Object.keys(bodyParams).length}) + )} + + )} + Headers {headerParams.length > 0 && ( @@ -187,13 +191,17 @@ export default function DebugPanel() { }} /> - - { - setBodyParams(values); - }} - /> - + + {runningMethod === SUPPORTED_METHODS.POST && ( + + { + setBodyParams(values); + }} + /> + + )} + { @@ -51,7 +54,7 @@ const CreateModal = (props: { functionItem?: any; children?: React.ReactElement name: string; description: string; websocket: boolean; - methods: string[]; + methods: TMethod[]; code: string; }; @@ -113,10 +116,13 @@ const CreateModal = (props: { functionItem?: any; children?: React.ReactElement {t("FunctionPanel.FunctionName")} @@ -131,11 +137,13 @@ const CreateModal = (props: { functionItem?: any; children?: React.ReactElement control={control} render={({ field: { ref, ...rest } }) => ( - GET - POST - HEAD - PATCH - DELETE + {Object.keys(SUPPORTED_METHODS).map((item) => { + return ( + + {item} + + ); + })} )} rules={{ diff --git a/web/src/pages/app/functions/mods/FunctionPanel/index.tsx b/web/src/pages/app/functions/mods/FunctionPanel/index.tsx index 4a11807ffb..91dd4eb24f 100644 --- a/web/src/pages/app/functions/mods/FunctionPanel/index.tsx +++ b/web/src/pages/app/functions/mods/FunctionPanel/index.tsx @@ -18,11 +18,11 @@ import { Pages } from "@/constants"; import { useDeleteFunctionMutation, useFunctionListQuery } from "../../service"; import useFunctionStore from "../../store"; +import TriggerModal from "../TriggerModal"; import CreateModal from "./CreateModal"; import { TFunction } from "@/apis/typing"; -import AddTriggerModal from "@/pages/app/trigger/AddTriggerModal"; import useGlobalStore from "@/pages/globalStore"; export default function FunctionList() { @@ -64,6 +64,11 @@ export default function FunctionList() { + + + + , @@ -102,11 +107,6 @@ export default function FunctionList() { {func?.name}
- - - - - diff --git a/web/src/pages/app/trigger/AddTriggerModal/index.tsx b/web/src/pages/app/functions/mods/TriggerModal/AddTriggerModal/index.tsx similarity index 80% rename from web/src/pages/app/trigger/AddTriggerModal/index.tsx rename to web/src/pages/app/functions/mods/TriggerModal/AddTriggerModal/index.tsx index c40be7d1f2..4bffedc0d7 100644 --- a/web/src/pages/app/trigger/AddTriggerModal/index.tsx +++ b/web/src/pages/app/functions/mods/TriggerModal/AddTriggerModal/index.tsx @@ -5,7 +5,9 @@ import { FormControl, FormErrorMessage, FormLabel, + HStack, Input, + Link, Modal, ModalBody, ModalCloseButton, @@ -24,6 +26,21 @@ import {} from "../service"; import { useFunctionListQuery } from "@/pages/app/functions/service"; +const CRON_TEMPLATE = [ + { + label: "每5分钟", + value: "*/5 * * * *", + }, + { + label: "每小时", + value: "0 * * * *", + }, + { + label: "每天上午8点", + value: "0 8 * * *", + }, +]; + const AddTriggerModal = (props: { children: React.ReactElement; targetFunc?: string }) => { type FormData = { desc: string; @@ -34,6 +51,7 @@ const AddTriggerModal = (props: { children: React.ReactElement; targetFunc?: str register, handleSubmit, setFocus, + setValue, reset, formState: { errors }, } = useForm(); @@ -110,7 +128,7 @@ const AddTriggerModal = (props: { children: React.ReactElement; targetFunc?: str - Cron {t("TriggerPanel.Express")} + Cron {t("TriggerPanel.Express")} {errors.cron && errors.cron.message} + + {CRON_TEMPLATE.map((item) => ( + { + setValue("cron", item.value); + }} + > + {item.label} + + ))} + + {t("TriggerPanel.CronHelp")} + + diff --git a/web/src/pages/app/functions/mods/TriggerModal/index.tsx b/web/src/pages/app/functions/mods/TriggerModal/index.tsx new file mode 100644 index 0000000000..4972a53f42 --- /dev/null +++ b/web/src/pages/app/functions/mods/TriggerModal/index.tsx @@ -0,0 +1,152 @@ +import { useState } from "react"; +import React from "react"; +import { AddIcon, DeleteIcon, Search2Icon } from "@chakra-ui/icons"; +import { + Button, + Center, + HStack, + Input, + InputGroup, + InputLeftElement, + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalHeader, + ModalOverlay, + Spinner, + Table, + TableContainer, + Tbody, + Td, + Th, + Thead, + Tr, + useDisclosure, +} from "@chakra-ui/react"; +import { t } from "i18next"; + +import ConfirmButton from "@/components/ConfirmButton"; +import IconWrap from "@/components/IconWrap"; +import { formatDate } from "@/utils/format"; + +import AddTriggerModal from "./AddTriggerModal"; +import { useDeleteTriggerMutation, useTriggerListQuery } from "./service"; + +export default function TriggerModal(props: { children: React.ReactElement }) { + const [searchKey, setSearchKey] = useState(""); + const triggerListQuery = useTriggerListQuery(() => {}); + const deleteTriggerMutation = useDeleteTriggerMutation(() => { + triggerListQuery.refetch(); + }); + + const { isOpen, onOpen, onClose } = useDisclosure(); + + return ( + <> + {React.cloneElement(props.children, { + onClick: () => { + onOpen(); + }, + })} + + + + + {t("TriggerPanel.Trigger")} + + +
+ + + + + } + /> + setSearchKey(e.target.value)} + /> + +
+
+ {triggerListQuery.isFetching ? ( +
+ +
+ ) : null} +
+ + + + + + + + + + + + + + {(triggerListQuery.data?.data || []) + .filter((item: any) => { + return item.desc.indexOf(searchKey) > -1; + }) + .map((item: any) => ( + + + + + + + + + ))} + +
+ {t("TriggerPanel.Name")} + {t("TriggerPanel.Function")}{t("TriggerPanel.Type")}{t("TriggerPanel.Cron")}{t("TriggerPanel.Time")} + {t("Operation")} +
+ {item.desc} + + {item.target} + + {t("TriggerPanel.SetTimeout")} + + {item.cron} + + {formatDate(item.updatedAt, "YYYY-MM-DD HH:mm")} + + + + deleteTriggerMutation.mutate({ id: item.id }) + } + headerText={String(t("Delete"))} + bodyText={t("TriggerPanel.DeleteConfirm")} + > + + + + + +
+
+
+
+
+
+
+ + ); +} diff --git a/web/src/pages/app/trigger/service.ts b/web/src/pages/app/functions/mods/TriggerModal/service.ts similarity index 100% rename from web/src/pages/app/trigger/service.ts rename to web/src/pages/app/functions/mods/TriggerModal/service.ts diff --git a/web/src/pages/app/index.tsx b/web/src/pages/app/index.tsx index 095d85a1b3..8c7f700412 100644 --- a/web/src/pages/app/index.tsx +++ b/web/src/pages/app/index.tsx @@ -7,7 +7,6 @@ import DatabasePage from "./database"; import FunctionPage from "./functions"; import LogsPage from "./logs"; import StoragePage from "./storages"; -import TriggerPage from "./trigger"; function AppDetail() { const { visitedViews, currentPageId } = useGlobalStore(); @@ -21,10 +20,6 @@ function AppDetail() { pageId: Pages.function, component: FunctionPage, }, - { - pageId: Pages.trigger, - component: TriggerPage, - }, { pageId: Pages.database, component: DatabasePage, diff --git a/web/src/pages/app/mods/SideBar/Icons.tsx b/web/src/pages/app/mods/SideBar/Icons.tsx new file mode 100644 index 0000000000..91a5f2ecee --- /dev/null +++ b/web/src/pages/app/mods/SideBar/Icons.tsx @@ -0,0 +1,94 @@ +import React from "react"; +import { Icon } from "@chakra-ui/react"; + +function Icons(props: { type: "function" | "database" | "storage" | "logs" | "setting" }) { + const { type } = props; + switch (type) { + case "function": + return ( + + + + ); + + case "database": + return ( + + + + ); + + case "storage": + return ( + + + + ); + + case "logs": + return ( + + + + + + + + + + + + ); + + case "setting": + return ( + + + + + + + + + + + ); + + default: + break; + } + return
Icons
; +} + +export default Icons; diff --git a/web/src/pages/app/mods/SideBar/index.module.scss b/web/src/pages/app/mods/SideBar/index.module.scss index 2ab785d5bd..d441ea8626 100644 --- a/web/src/pages/app/mods/SideBar/index.module.scss +++ b/web/src/pages/app/mods/SideBar/index.module.scss @@ -3,15 +3,19 @@ cursor: pointer; border-radius: 4px; height: 48px; + + svg { + fill: #9ca2a8; + } } .icon:hover, .icon.current { - background-color: #f0fff4; -} + background-color: #d3ecec; -.icon.current { - color: #38a169; + svg { + fill: #00a99d; + } } .icon.bottom { diff --git a/web/src/pages/app/mods/SideBar/index.tsx b/web/src/pages/app/mods/SideBar/index.tsx index 2087ec9e8a..caecf7c47d 100644 --- a/web/src/pages/app/mods/SideBar/index.tsx +++ b/web/src/pages/app/mods/SideBar/index.tsx @@ -2,17 +2,15 @@ * cloud functions SideBar menu ***************************/ -import { AiFillDatabase, AiOutlineFunction } from "react-icons/ai"; -import { GrCatalogOption, GrSettingsOption, GrStorage } from "react-icons/gr"; import { useNavigate, useParams } from "react-router-dom"; import { Center } from "@chakra-ui/react"; import clsx from "clsx"; import { t } from "i18next"; -import { TriggerIcon } from "@/components/CommonIcon"; -import IconWrap from "@/components/IconWrap"; import { Pages, SideBarWidth } from "@/constants/index"; +import Icons from "./Icons"; + import styles from "./index.module.scss"; import UserSetting from "@/layouts/Header/UserSetting"; @@ -32,43 +30,19 @@ export default function SideBar() { }, { pageId: Pages.function, - component: ( - - - - ), - }, - { - pageId: Pages.trigger, - component: ( - - - - ), + component: , }, { pageId: Pages.database, - component: ( - - - - ), + component: , }, { pageId: Pages.storage, - component: ( - - - - ), + component: , }, { pageId: Pages.logs, - component: ( - - - - ), + component: , }, ]; @@ -109,9 +83,9 @@ export default function SideBar() { }, ]} > - - - +
+ +
), }, diff --git a/web/src/pages/app/trigger/index.tsx b/web/src/pages/app/trigger/index.tsx deleted file mode 100644 index a18cfd645d..0000000000 --- a/web/src/pages/app/trigger/index.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import { useState } from "react"; -import { AddIcon, DeleteIcon, Search2Icon } from "@chakra-ui/icons"; -import { - Button, - Center, - Input, - InputGroup, - InputLeftElement, - Spinner, - Table, - TableContainer, - Tbody, - Td, - Th, - Thead, - Tr, -} from "@chakra-ui/react"; -import { t } from "i18next"; - -import ConfirmButton from "@/components/ConfirmButton"; -import Content from "@/components/Content"; -import IconWrap from "@/components/IconWrap"; -import Panel from "@/components/Panel"; -import { formatDate } from "@/utils/format"; - -import AddTriggerModal from "./AddTriggerModal"; -import { useDeleteTriggerMutation, useTriggerListQuery } from "./service"; - -export default function TriggerPage() { - const [searchKey, setSearchKey] = useState(""); - const triggerListQuery = useTriggerListQuery(() => {}); - const deleteTriggerMutation = useDeleteTriggerMutation(() => { - triggerListQuery.refetch(); - }); - - return ( - - - -
- - - - - } - /> - setSearchKey(e.target.value)} - /> - -
-
-
- {triggerListQuery.isFetching ? ( -
- -
- ) : null} -
- - - - - - - - - - - - - {(triggerListQuery.data?.data || []) - .filter((item: any) => { - return item.desc.indexOf(searchKey) > -1; - }) - .map((item: any) => { - return ( - - - - - - - - ); - })} - -
{t("TriggerPanel.Name")}{t("TriggerPanel.Function")}{t("TriggerPanel.Type")}{t("TriggerPanel.Time")}{t("Operation")}
- {item.desc} - - {item.target} - - {t("TriggerPanel.SetTimeout")} - - {formatDate(item.updatedAt, "YYYY-MM-DD HH:mm:ss")} - - deleteTriggerMutation.mutate({ id: item.id })} - headerText={String(t("Delete"))} - bodyText={t("TriggerPanel.DeleteConfirm")} - > - - - - -
-
-
-
-
-
- ); -} diff --git a/web/src/pages/home/mods/Empty/index.tsx b/web/src/pages/home/mods/Empty/index.tsx index bb6a0efc57..6136d2b753 100644 --- a/web/src/pages/home/mods/Empty/index.tsx +++ b/web/src/pages/home/mods/Empty/index.tsx @@ -7,6 +7,8 @@ import CreateAppModal from "../CreateAppModal"; import styles from "./index.module.scss"; +import useGlobalStore from "@/pages/globalStore"; + function Empty() { const messageList = [ t("HomePanel.WX"), @@ -16,11 +18,14 @@ function Empty() { t("HomePanel.Personal"), t("HomePanel.Explore"), ]; + + const { userInfo } = useGlobalStore(); + return (

- {t("HomePanel.Hello")} 👋 ,Violetjam,{t("HomePanel.Welcome")} + {t("HomePanel.Hello")} 👋 , {userInfo?.profile.name} , {t("HomePanel.Welcome")}

{t("HomePanel.Introduction")}

diff --git a/web/src/pages/home/mods/List/index.tsx b/web/src/pages/home/mods/List/index.tsx index 749080f2a4..2e5d5cee7e 100644 --- a/web/src/pages/home/mods/List/index.tsx +++ b/web/src/pages/home/mods/List/index.tsx @@ -122,14 +122,14 @@ function List(props: { appListQuery: any }) { - + - + {t("Edit")} - + - + {t("Delete")} diff --git a/web/src/utils/request.ts b/web/src/utils/request.ts index 0f7004b3b4..453e7344e3 100644 --- a/web/src/utils/request.ts +++ b/web/src/utils/request.ts @@ -50,7 +50,7 @@ request.interceptors.response.use( const { data } = error.response; if (data.statusCode === 401) { // eslint-disable-next-line no-restricted-globals - // (window as any).location.href = (import.meta.env.VITE_SERVER_URL + "/v1/login") as string; + (window as any).location.href = (import.meta.env.VITE_SERVER_URL + "/v1/login") as string; return; } toast({