Skip to content

Commit

Permalink
feat(web): add function fetch button (#1163)
Browse files Browse the repository at this point in the history
* feat(web): request methods persistence

* feat(web): add function label select

* feat(web): add fetch button

* feat(web): add invitecode to homepage and login

* Revert "feat(web): add invitecode to homepage and login"

This reverts commit 69daa00.
  • Loading branch information
newfish-cmyk committed May 26, 2023
1 parent 7a5fe76 commit 77369e4
Show file tree
Hide file tree
Showing 12 changed files with 191 additions and 19 deletions.
5 changes: 4 additions & 1 deletion web/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"AddFunction": "New Function",
"Code": "Function Template",
"ConfirmDeploy": "Confirm Deploy",
"ConfirmFetch": "Confirm Fetch",
"CustomDependence": "Custom",
"CustomDependenceTip": "No custom dependencies yet",
"DeleteDependencyConfirm": "Are you sure you want to delete the npm package?",
Expand All @@ -86,6 +87,8 @@
"DependenceVersion": "Dependency Version",
"Deploy": "Deploy",
"DeploySuccess": "Deploy successfully",
"Fetch": "Fetch",
"FetchSuccess": "Fetch successfully",
"Description": "Function Description",
"EditFunction": "Edit Function",
"Function": "Function",
Expand Down Expand Up @@ -420,4 +423,4 @@
"LinkCopied": "Link Copied",
"create success": "create success",
"ServerStatus": "STATUS"
}
}
5 changes: 4 additions & 1 deletion web/public/locales/zh-CN/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"AddFunction": "添加函数",
"Code": "函数模板",
"ConfirmDeploy": "确认发布",
"ConfirmFetch": "确认同步",
"CustomDependence": "自定义依赖",
"CustomDependenceTip": "暂无自定义依赖",
"DeleteDependencyConfirm": "确认要删除该依赖吗?删除依赖后会立即重启应用。",
Expand All @@ -86,6 +87,8 @@
"DependenceVersion": "依赖版本",
"Deploy": "发布",
"DeploySuccess": "发布成功",
"Fetch": "同步",
"FetchSuccess": "同步成功",
"Description": "函数描述",
"EditFunction": "编辑函数",
"Function": "函数",
Expand Down Expand Up @@ -420,4 +423,4 @@
"LinkCopied": "链接复制成功",
"create success": "创建成功",
"ServerStatus": "服务状态"
}
}
5 changes: 4 additions & 1 deletion web/public/locales/zh/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"AddFunction": "添加函数",
"Code": "函数模板",
"ConfirmDeploy": "确认发布",
"ConfirmFetch": "确认同步",
"CustomDependence": "自定义依赖",
"CustomDependenceTip": "暂无自定义依赖",
"DeleteDependencyConfirm": "确认要删除该依赖吗?删除依赖后会立即重启应用。",
Expand All @@ -86,6 +87,8 @@
"DependenceVersion": "依赖版本",
"Deploy": "发布",
"DeploySuccess": "发布成功",
"Fetch": "同步",
"FetchSuccess": "同步成功",
"Description": "函数描述",
"EditFunction": "编辑函数",
"Function": "函数",
Expand Down Expand Up @@ -420,4 +423,4 @@
"LinkCopied": "链接复制成功",
"create success": "创建成功",
"ServerStatus": "服务状态"
}
}
24 changes: 22 additions & 2 deletions web/src/components/Editor/FunctionEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import "./userWorker";
import { AutoImportTypings } from "./typesResolve";

import useHotKey, { DEFAULT_SHORTCUTS } from "@/hooks/useHotKey";
import useFunctionStore from "@/pages/app/functions/store";
import useGlobalStore from "@/pages/globalStore";

const autoImportTypings = new AutoImportTypings();
Expand Down Expand Up @@ -90,6 +91,19 @@ const updateModel = (path: string, value: string, editorRef: any) => {
}
};

const updateFetchModel = (path: string, value: string, editorRef: any) => {
const newModel =
monaco.editor.getModel(monaco.Uri.parse(path)) ||
monaco.editor.createModel(value, "typescript", monaco.Uri.parse(path));

newModel.setValue(value);

if (editorRef.current?.getModel() !== newModel) {
editorRef.current?.setModel(newModel);
autoImportTypings.parse(editorRef.current?.getValue() || "");
}
};

function FunctionEditor(props: {
value: string;
className?: string;
Expand All @@ -116,6 +130,7 @@ function FunctionEditor(props: {
const monacoEl = useRef(null);

const globalStore = useGlobalStore((state) => state);
const { isFetchButtonClicked, setIsFetchButtonClicked } = useFunctionStore((state) => state);

useHotKey(
DEFAULT_SHORTCUTS.send_request,
Expand Down Expand Up @@ -161,9 +176,14 @@ function FunctionEditor(props: {

useEffect(() => {
if (monacoEl && editorRef.current) {
updateModel(path, value, editorRef);
if (isFetchButtonClicked) {
updateFetchModel(path, value, editorRef);
setIsFetchButtonClicked();
} else {
updateModel(path, value, editorRef);
}
}
}, [path, value]);
}, [path, value, isFetchButtonClicked, setIsFetchButtonClicked]);

useEffect(() => {
if (monacoEl && editorRef.current) {
Expand Down
48 changes: 44 additions & 4 deletions web/src/components/InputTag/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,37 @@
import { useState } from "react";
import { Input, Tag, TagCloseButton, TagLabel, useColorMode } from "@chakra-ui/react";
import { ChevronDownIcon } from "@chakra-ui/icons";
import {
Input,
Menu,
MenuButton,
MenuItem,
MenuList,
Tag,
TagCloseButton,
TagLabel,
useColorMode,
} from "@chakra-ui/react";
import clsx from "clsx";
import { t } from "i18next";

import { COLOR_MODE } from "@/constants";

export default function InputTag(props: { value: string[]; onChange: (value: string[]) => any }) {
const { value, onChange } = props;
export default function InputTag(props: {
value: string[];
onChange: (value: string[]) => any;
tagList: any;
}) {
const { value, onChange, tagList } = props;
const [inputV, setInputV] = useState("");
const { colorMode } = useColorMode();
const darkMode = colorMode === COLOR_MODE.dark;

const handleMenuItemClick = (tag: any) => {
if (!value.some((x) => x === tag.tagName)) {
onChange([...value, tag.tagName]);
}
};

const handleEnter = (e: any) => {
if (e.key === "Enter") {
e.preventDefault();
Expand All @@ -20,9 +42,11 @@ export default function InputTag(props: { value: string[]; onChange: (value: str
setInputV("");
}
};

const handleClose = (item: string) => {
onChange(value.filter((name) => name !== item));
};

return (
<div
className={clsx(
Expand All @@ -44,7 +68,7 @@ export default function InputTag(props: { value: string[]; onChange: (value: str
: null}
<Input
className="flex-1"
minWidth={{ base: "150px", md: "150px" }}
minWidth={{ base: "100px", md: "100px" }}
placeholder={String(t("CollectionPanel.CreateTagTip"))}
value={inputV}
onKeyDown={(e) => handleEnter(e)}
Expand All @@ -53,6 +77,22 @@ export default function InputTag(props: { value: string[]; onChange: (value: str
setInputV(e.target.value);
}}
/>
<Menu placement="bottom-end">
<MenuButton className="cursor-pointer">
<ChevronDownIcon boxSize={8} color="gray.400" />
</MenuButton>
<MenuList className="mt-1 max-h-72 overflow-y-auto">
{(tagList || []).map((tag: any) => (
<MenuItem
key={tag.tagName}
onClick={() => handleMenuItemClick(tag)}
className="p-2 text-lg"
>
{tag.tagName}
</MenuItem>
))}
</MenuList>
</Menu>
</div>
);
}
3 changes: 2 additions & 1 deletion web/src/pages/app/functions/mods/DebugPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export default function DebugPanel(props: { containerRef: any; showOverlay: bool

useEffect(() => {
if (currentFunction?.methods) {
setRunningMethod(currentFunction.methods[0]);
setRunningMethod(currentFunction.params?.runningMethod || currentFunction.methods[0]);
}
}, [setRunningMethod, currentFunction]);

Expand All @@ -89,6 +89,7 @@ export default function DebugPanel(props: { containerRef: any; showOverlay: bool
queryParams: queryParams,
bodyParams: bodyParams,
headerParams: headerParams,
runningMethod: runningMethod,
};

updateFunctionMutation.mutateAsync({
Expand Down
2 changes: 2 additions & 0 deletions web/src/pages/app/functions/mods/EditorPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { COLOR_MODE } from "@/constants";
import { useFunctionListQuery } from "../../service";
import useFunctionStore from "../../store";
import DeployButton from "../DeployButton";
import FetchButton from "../FetchButton";
import CreateModal from "../FunctionPanel/CreateModal";
import PromptModal from "../FunctionPanel/CreateModal/PromptModal";

Expand Down Expand Up @@ -58,6 +59,7 @@ function EditorPanel() {
<Input w={"240px"} size="sm" readOnly value={getFunctionUrl()} />
</CopyText>

<FetchButton />
<DeployButton />
</HStack>
</Panel.Header>
Expand Down
84 changes: 84 additions & 0 deletions web/src/pages/app/functions/mods/FetchButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import {
Button,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
useDisclosure,
} from "@chakra-ui/react";
import { t } from "i18next";

import CommonDiffEditor from "@/components/Editor/CommonDiffEditor";

import { useFunctionDetailQuery } from "../../service";
import useFunctionStore from "../../store";

import useFunctionCache from "@/hooks/useFunctionCache";
import useGlobalStore from "@/pages/globalStore";

export default function FetchButton() {
const functionCache = useFunctionCache();
const { isOpen, onOpen, onClose } = useDisclosure();
const store = useFunctionStore((state) => state);
const { currentFunction, updateFunctionCode, setIsFetchButtonClicked } = store;
const functionDetailQuery = useFunctionDetailQuery(store.currentFunction.name, {
enabled: isOpen,
});
const data = functionDetailQuery.data?.data?.source?.code;
const { showSuccess } = useGlobalStore((state) => state);

return (
<>
<Button
variant={"text"}
isLoading={functionDetailQuery.isFetching}
disabled={store.getFunctionUrl() === ""}
onClick={() => {
onOpen();
}}
>
{t("FunctionPanel.Fetch")}
</Button>

{isOpen && !functionDetailQuery.isFetching ? (
<Modal isOpen={isOpen} onClose={onClose} size="6xl" isCentered>
<ModalOverlay />
<ModalContent maxW={"80%"}>
<ModalHeader>Code Diff</ModalHeader>
<ModalCloseButton />
<ModalBody borderBottom={"1px"} borderBottomColor="gray.200">
<CommonDiffEditor
modified={data}
original={functionCache.getCache(
currentFunction?.id,
currentFunction?.source?.code,
)}
/>
</ModalBody>

<ModalFooter>
<Button variant="ghost" mr={3} onClick={onClose}>
{t("Cancel")}
</Button>
<Button
variant="primary"
onClick={() => {
updateFunctionCode(currentFunction, data || "");
functionCache.setCache(currentFunction!.id, data || "");
setIsFetchButtonClicked();
onClose();
showSuccess(t("FunctionPanel.FetchSuccess"));
}}
>
{t("FunctionPanel.ConfirmFetch")}
</Button>
</ModalFooter>
</ModalContent>
</Modal>
) : null}
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,17 @@ import useFunctionStore from "../../../store";
import { TMethod } from "@/apis/typing";
import useGlobalStore from "@/pages/globalStore";

const PromptModal = (props: { functionItem?: any; children?: React.ReactElement }) => {
const PromptModal = (props: {
functionItem?: any;
children?: React.ReactElement;
tagList?: any;
}) => {
const { isOpen, onOpen, onClose } = useDisclosure();
const store = useFunctionStore();
const { showSuccess } = useGlobalStore();
const { t } = useTranslation();

const { functionItem, children = null } = props;
const { functionItem, children = null, tagList } = props;
const isEdit = !!functionItem;

const CancelToken = axios.CancelToken;
Expand Down Expand Up @@ -164,7 +168,7 @@ const PromptModal = (props: { functionItem?: any; children?: React.ReactElement
name="tags"
control={control}
render={({ field: { onChange, value } }) => (
<InputTag value={value} onChange={onChange} />
<InputTag value={value} onChange={onChange} tagList={tagList} />
)}
/>
<FormErrorMessage>{errors.tags && errors.tags.message}</FormErrorMessage>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,16 @@ import functionTemplates from "./functionTemplates";
import { TMethod } from "@/apis/typing";
import useGlobalStore from "@/pages/globalStore";

const CreateModal = (props: { functionItem?: any; children?: React.ReactElement }) => {
const CreateModal = (props: {
functionItem?: any;
children?: React.ReactElement;
tagList?: any;
}) => {
const { isOpen, onOpen, onClose } = useDisclosure();
const store = useFunctionStore();
const { showSuccess } = useGlobalStore();

const { functionItem, children = null } = props;
const { functionItem, children = null, tagList } = props;
const isEdit = !!functionItem;

const defaultValues = {
Expand Down Expand Up @@ -136,7 +140,7 @@ const CreateModal = (props: { functionItem?: any; children?: React.ReactElement
name="tags"
control={control}
render={({ field: { onChange, value } }) => (
<InputTag value={value} onChange={onChange} />
<InputTag value={value} onChange={onChange} tagList={tagList} />
)}
/>
<FormErrorMessage>{errors.tags && errors.tags.message}</FormErrorMessage>
Expand Down
Loading

0 comments on commit 77369e4

Please sign in to comment.