diff --git a/web/public/locales/en/translation.json b/web/public/locales/en/translation.json
index 1c42584cc9..c57b49722c 100644
--- a/web/public/locales/en/translation.json
+++ b/web/public/locales/en/translation.json
@@ -139,7 +139,9 @@
"DeleteApp": "delete apps",
"DeleteTip": "The current operation will permanently delete applications, including functions, data, cloud storage, etc. related data related to the application. After deleting, will not be able to cancel ,please enter {{appId}} confirm",
"Duration": "Duration",
- "Spec": "Spec"
+ "Spec": "Spec",
+ "WelcomeTo": "Welcome to",
+ "LAF": "the LAF cloud development platform!"
},
"SpecItem": {
"cpu": "CPU",
@@ -204,7 +206,9 @@
"CostTrend": "Cost Trend",
"Balance": "Balance",
"Pause": "Pause",
- "AppMonitor": "Application Monitor"
+ "AppMonitor": "App Monitoring",
+ "PauseTips": "Are you sure you want to pause this application?",
+ "RestartTips": "Are you sure you want to restart this application?"
},
"StoragePanel": {
"All": "Total Capacity",
@@ -558,7 +562,12 @@
"Email": "Email",
"ChangeEmail": "Change Email",
"SmsNumber": "Verification Code",
- "ChangeEmailSuccess": "Change Email Success"
+ "ChangeEmailSuccess": "Change Email Success",
+ "GotoAuth": "Go to Authenticate",
+ "NoAuth": "Not Real-name Verified",
+ "WarnTips": "You have not yet completed real-name authentication.",
+ "PleaseBindPhone": "Please bind your mobile number first",
+ "VerifiedIdentity": "Verified Identity"
},
"Reset": "Reset",
"SettingModal": {
@@ -612,6 +621,7 @@
"Quit": "Quit"
},
"Collaborative": "Collaborative",
+ "CreateApp": "New Application",
"Used": "Used",
"Remaining": "Remaining",
"Pod": "Pod"
diff --git a/web/public/locales/zh-CN/translation.json b/web/public/locales/zh-CN/translation.json
index c8ac5fced8..08a8f4e92c 100644
--- a/web/public/locales/zh-CN/translation.json
+++ b/web/public/locales/zh-CN/translation.json
@@ -139,7 +139,9 @@
"DeleteApp": "删除 APP",
"DeleteTip": "当前操作将会永久删除应用, 包括函数、数据、云存储等与应用相关的数据, 删除后将无法撤消, 请输入 {{appId}} 后确认",
"Duration": "购买时长",
- "Spec": "规格"
+ "Spec": "规格",
+ "WelcomeTo": "欢迎来到 ",
+ "LAF": " LAF 云开发平台!"
},
"SpecItem": {
"cpu": "CPU",
@@ -204,7 +206,9 @@
"CostTrend": "成本趋势",
"Balance": "余额",
"Pause": "暂停应用",
- "AppMonitor": "资源监控"
+ "AppMonitor": "资源监控",
+ "PauseTips": "确定要暂停此应用吗?",
+ "RestartTips": "确定要重启此应用吗?"
},
"StoragePanel": {
"All": "总容量",
@@ -558,7 +562,12 @@
"Email": "邮箱",
"ChangeEmail": "更改邮箱",
"SmsNumber": "验证码",
- "ChangeEmailSuccess": "修改邮箱成功"
+ "ChangeEmailSuccess": "修改邮箱成功",
+ "GotoAuth": "去认证",
+ "NoAuth": "未实名",
+ "WarnTips": "您尚未实名认证",
+ "PleaseBindPhone": "请先绑定手机号",
+ "VerifiedIdentity": "已实名"
},
"Reset": "重置",
"SettingModal": {
@@ -612,6 +621,7 @@
"Quit": "退出"
},
"Collaborative": "协作",
+ "CreateApp": "新建应用",
"Used": "已使用",
"Remaining": "剩余",
"Pod": "实例"
diff --git a/web/public/locales/zh/translation.json b/web/public/locales/zh/translation.json
index 9fbc344c29..7b71a99df4 100644
--- a/web/public/locales/zh/translation.json
+++ b/web/public/locales/zh/translation.json
@@ -139,7 +139,9 @@
"DeleteApp": "删除 APP",
"DeleteTip": "当前操作将会永久删除应用, 包括函数、数据、云存储等与应用相关的数据, 删除后将无法撤消, 请输入 {{appId}} 后确认",
"Duration": "购买时长",
- "Spec": "规格"
+ "Spec": "规格",
+ "WelcomeTo": "欢迎来到 ",
+ "LAF": " LAF 云开发平台!"
},
"SpecItem": {
"cpu": "CPU",
@@ -204,7 +206,9 @@
"CostTrend": "成本趋势",
"Balance": "余额",
"Pause": "暂停应用",
- "AppMonitor": "资源监控"
+ "AppMonitor": "资源监控",
+ "PauseTips": "确定要暂停此应用吗?",
+ "RestartTips": "确定要重启此应用吗?"
},
"StoragePanel": {
"All": "总容量",
@@ -558,7 +562,12 @@
"Email": "邮箱",
"ChangeEmail": "更改邮箱",
"SmsNumber": "验证码",
- "ChangeEmailSuccess": "修改邮箱成功"
+ "ChangeEmailSuccess": "修改邮箱成功",
+ "GotoAuth": "去认证",
+ "NoAuth": "未实名",
+ "WarnTips": "您尚未实名认证",
+ "PleaseBindPhone": "请先绑定手机号",
+ "VerifiedIdentity": "已实名"
},
"Reset": "重置",
"SettingModal": {
@@ -612,6 +621,7 @@
"Quit": "退出"
},
"Collaborative": "协作",
+ "CreateApp": "新建应用",
"Used": "已使用",
"Remaining": "剩余",
"Pod": "实例"
diff --git a/web/src/apis/v1/api-auto.d.ts b/web/src/apis/v1/api-auto.d.ts
index 701d58eea6..d791aaf727 100644
--- a/web/src/apis/v1/api-auto.d.ts
+++ b/web/src/apis/v1/api-auto.d.ts
@@ -507,6 +507,7 @@ declare namespace Definitions {
name?: string;
createdAt?: string;
updatedAt?: string;
+ idVerified?: { isVerified?: boolean };
};
export type CreateDependencyDto = {
diff --git a/web/src/layouts/Basic/RealNameWarn.tsx b/web/src/layouts/Basic/RealNameWarn.tsx
new file mode 100644
index 0000000000..20ee4a155a
--- /dev/null
+++ b/web/src/layouts/Basic/RealNameWarn.tsx
@@ -0,0 +1,48 @@
+import React, { useState } from "react";
+import { useTranslation } from "react-i18next";
+import { WarningTwoIcon } from "@chakra-ui/icons";
+
+import SettingModal from "@/pages/app/setting";
+import useTabMatch from "@/pages/app/setting/UserSetting/useTabMatch";
+import useGlobalStore from "@/pages/globalStore";
+import useSiteSettingStore from "@/pages/siteSetting";
+
+export default function Warn() {
+ const { t } = useTranslation();
+ const { userInfo, showError } = useGlobalStore((state) => state);
+ const [openModal, setOpenModal] = useState(false);
+ const { siteSettings } = useSiteSettingStore((state) => state);
+
+ return (
+
+
+
+ {siteSettings.id_verify?.metadata.message}
+
+
{
+ if (userInfo?.phone) {
+ const w = window.open("about:blank");
+ w!.location.href = `${
+ siteSettings.id_verify?.metadata.authenticateSite
+ }?token=${localStorage.getItem("token")}`;
+ } else {
+ showError(t("UserInfo.PleaseBindPhone"));
+ setOpenModal(true);
+ }
+ }}
+ >
+ {t("UserInfo.GotoAuth")}
+
+
+
+
+ );
+}
diff --git a/web/src/layouts/Basic.tsx b/web/src/layouts/Basic/index.tsx
similarity index 61%
rename from web/src/layouts/Basic.tsx
rename to web/src/layouts/Basic/index.tsx
index 689aec1f57..0ee353794e 100644
--- a/web/src/layouts/Basic.tsx
+++ b/web/src/layouts/Basic/index.tsx
@@ -3,25 +3,33 @@ import { AiFillHeart } from "react-icons/ai";
import { Outlet } from "react-router-dom";
import { Center, Spinner } from "@chakra-ui/react";
+import Warn from "./RealNameWarn";
+
import Header from "@/layouts/Header";
import useGlobalStore from "@/pages/globalStore";
+import useSiteSettingStore from "@/pages/siteSetting";
export default function BasicLayout() {
- const { init, loading } = useGlobalStore((state) => state);
+ const { init, loading, userInfo } = useGlobalStore((state) => state);
+ const { siteSettings } = useSiteSettingStore((state) => state);
+
useEffect(() => {
init();
}, [init]);
-
return (
{loading ? (
-
+
) : (
-
+ <>
+ {siteSettings.id_verify?.value === "on" &&
+ !userInfo?.profile?.idVerified?.isVerified && }
+
+ >
)}
diff --git a/web/src/pages/app/setting/UserInfo/AuthDetail/index.tsx b/web/src/pages/app/setting/UserInfo/AuthDetail/index.tsx
deleted file mode 100644
index aa08bf9dd2..0000000000
--- a/web/src/pages/app/setting/UserInfo/AuthDetail/index.tsx
+++ /dev/null
@@ -1,124 +0,0 @@
-import { Controller, useForm } from "react-hook-form";
-import { ChevronLeftIcon } from "@chakra-ui/icons";
-import {
- Box,
- Button,
- FormControl,
- FormErrorMessage,
- Input,
- InputGroup,
- InputRightElement,
- VStack,
-} from "@chakra-ui/react";
-import { t } from "i18next";
-
-import { SendSmsCodeButton } from "@/components/SendSmsCodeButton";
-import SmsCodeInput from "@/components/SmsCodeInput";
-
-export default function AuthDetail(props: { handleBack: () => void }) {
- type FormData = {
- tel: string;
- code: string;
- name: string;
- id: string;
- };
- const {
- register,
- handleSubmit,
- getValues,
- control,
- formState: { errors },
- } = useForm
();
-
- const { handleBack } = props;
- const onSubmit = async (data: any) => {};
-
- return (
- <>
- handleBack()}
- className="absolute left-[280px] flex cursor-pointer items-center"
- >
- {t("Back")}
-
-
- {t("SettingPanel.Auth")}
-
-
- {t("SettingPanel.Tel")}
-
-
-
-
-
-
- {/*
- {errors?.tel && errors?.tel?.message}
- */}
-
-
- {t("SettingPanel.Code")}:
- (
-
-
-
- )}
- />
- {/*
- {errors?.code && errors?.code?.message}
- */}
-
-
- {t("SettingPanel.Name")}:
-
- {/*
- {errors?.name && errors?.name?.message}
- */}
-
-
- {t("SettingPanel.ID")}:
-
-
- {errors?.id && errors?.id?.message}
-
-
-
-
-
- >
- );
-}
diff --git a/web/src/pages/app/setting/UserInfo/index.tsx b/web/src/pages/app/setting/UserInfo/index.tsx
index fbe12f821a..c4b4e9be8b 100644
--- a/web/src/pages/app/setting/UserInfo/index.tsx
+++ b/web/src/pages/app/setting/UserInfo/index.tsx
@@ -1,5 +1,6 @@
import { useRef, useState } from "react";
-import { ChevronRightIcon, EditIcon } from "@chakra-ui/icons";
+import { useNavigate } from "react-router-dom";
+import { CheckCircleIcon, ChevronRightIcon, EditIcon, InfoOutlineIcon } from "@chakra-ui/icons";
import { Avatar, Box, Divider, useColorMode } from "@chakra-ui/react";
import clsx from "clsx";
import { t } from "i18next";
@@ -12,20 +13,21 @@ import EmailEditor from "./Mods/EmailEditor";
import PasswordEditor from "./Mods/PasswordEditor";
import PhoneEditor from "./Mods/PhoneEditor";
import UsernameEditor from "./Mods/UsernameEditor";
-import AuthDetail from "./AuthDetail";
import "react-image-crop/dist/ReactCrop.css";
import useGlobalStore from "@/pages/globalStore";
+import useSiteSettingStore from "@/pages/siteSetting";
export default function UserInfo() {
const [showItem, setShowItem] = useState("");
const [selectedImage, setSelectedImage] = useState(null);
- const { userInfo, avatarUpdatedAt } = useGlobalStore((state) => state);
-
+ const { userInfo, avatarUpdatedAt, showError } = useGlobalStore((state) => state);
const fileInputRef = useRef(null);
const { colorMode } = useColorMode();
const darkMode = colorMode === "dark";
+ const navigate = useNavigate();
+ const { siteSettings } = useSiteSettingStore((state) => state);
const handleClick = () => {
if (fileInputRef.current) {
@@ -112,8 +114,50 @@ export default function UserInfo() {
-
-
+
+ {siteSettings.id_verify?.value === "on" && (
+
+
+ {t("SettingPanel.Auth")}
+ {!userInfo?.profile?.idVerified?.isVerified && (
+
+ )}
+
+
+
+ {userInfo?.profile?.idVerified?.isVerified
+ ? userInfo?.profile?.name
+ : t("UserInfo.NoAuth")}
+
+ {!userInfo?.profile?.idVerified?.isVerified ? (
+ {
+ if (userInfo?.phone) {
+ navigate("/auth/real-name");
+ } else {
+ showError(t("UserInfo.PleaseBindPhone"));
+ setShowItem("phone");
+ }
+ }}
+ >
+ {t("UserInfo.GotoAuth")}
+
+ ) : (
+
+ {t("UserInfo.VerifiedIdentity")}
+
+
+ )}
+
+
+ )}
+
{t("SettingPanel.Tel")}
@@ -155,7 +199,6 @@ export default function UserInfo() {
{showItem === "avatar" &&
}
{showItem === "username" &&
}
{showItem === "password" &&
}
- {showItem === "auth" &&
}
{showItem === "phone" &&
}
{showItem === "email" &&
}
diff --git a/web/src/pages/app/setting/UserSetting/index.tsx b/web/src/pages/app/setting/UserSetting/index.tsx
index 356a608772..70064b3c41 100644
--- a/web/src/pages/app/setting/UserSetting/index.tsx
+++ b/web/src/pages/app/setting/UserSetting/index.tsx
@@ -1,4 +1,3 @@
-import { useTranslation } from "react-i18next";
import { ChevronRightIcon } from "@chakra-ui/icons";
import {
Avatar,
@@ -11,36 +10,24 @@ import {
VStack,
} from "@chakra-ui/react";
import clsx from "clsx";
+import { t } from "i18next";
import {
BillingIcon,
- CardIcon,
- ChargeIcon,
ContactIcon,
- CostIcon,
DiscordIcon,
ExitIcon,
GroupIcon,
- InviteIcon,
- PATIcon,
- StandardIcon,
UserIcon,
WechatIcon,
} from "@/components/CommonIcon";
+import useTabMatch from "./useTabMatch";
+
import UserBalance from "@/layouts/Header/UserBalance";
import SettingModal, { TabKeys } from "@/pages/app/setting";
-import BillingDetails from "@/pages/app/setting/BillingDetails";
-import CardRedemption from "@/pages/app/setting/CardRedemption";
-import PATList from "@/pages/app/setting/PATList";
-import PricingStandards from "@/pages/app/setting/PricingStandards";
-import RechargeHistory from "@/pages/app/setting/RechargeHistory";
-import Usage from "@/pages/app/setting/Usage";
-import UserInfo from "@/pages/app/setting/UserInfo";
-import UserInvite from "@/pages/app/setting/UserInvite";
export default function UserSetting(props: { name: string; avatar?: string; width: string }) {
- const { t } = useTranslation();
const darkMode = useColorMode().colorMode === "dark";
return (
@@ -97,26 +84,7 @@ export default function UserSetting(props: { name: string; avatar?: string; widt
>
,
- icon:
,
- },
- {
- key: TabKeys.UserInvite,
- name: String(t("SettingPanel.UserInvite")),
- component:
,
- icon:
,
- },
- {
- key: TabKeys.PAT,
- name: t("Personal Access Token"),
- component:
,
- icon:
,
- },
- ]}
+ tabMatch={useTabMatch("user")}
headerTitle={t("SettingPanel.UserCenter")}
currentTab={TabKeys.UserInfo}
>
@@ -136,38 +104,7 @@ export default function UserSetting(props: { name: string; avatar?: string; widt
,
- icon:
,
- },
- {
- key: TabKeys.CardRedemption,
- name: String(t("SettingPanel.CardRedemption")),
- component:
,
- icon:
,
- },
- {
- key: TabKeys.BillingDetails,
- name: String(t("SettingPanel.BillingDetails")),
- component:
,
- icon:
,
- },
- {
- key: TabKeys.RechargeHistory,
- name: String(t("SettingPanel.RechargeHistory")),
- component:
,
- icon:
,
- },
- {
- key: TabKeys.PricingStandards,
- name: String(t("SettingPanel.PricingStandards")),
- component:
,
- icon:
,
- },
- ]}
+ tabMatch={useTabMatch("usage")}
headerTitle={t("SettingPanel.Usage")}
currentTab={TabKeys.CostOverview}
>
diff --git a/web/src/pages/app/setting/UserSetting/useTabMatch.tsx b/web/src/pages/app/setting/UserSetting/useTabMatch.tsx
new file mode 100644
index 0000000000..a80777b214
--- /dev/null
+++ b/web/src/pages/app/setting/UserSetting/useTabMatch.tsx
@@ -0,0 +1,86 @@
+import { useTranslation } from "react-i18next";
+
+import {
+ BillingIcon,
+ CardIcon,
+ ChargeIcon,
+ CostIcon,
+ InviteIcon,
+ PATIcon,
+ StandardIcon,
+ UserIcon,
+} from "@/components/CommonIcon";
+
+import { TabKeys } from "@/pages/app/setting";
+import BillingDetails from "@/pages/app/setting/BillingDetails";
+import CardRedemption from "@/pages/app/setting/CardRedemption";
+import PATList from "@/pages/app/setting/PATList";
+import PricingStandards from "@/pages/app/setting/PricingStandards";
+import RechargeHistory from "@/pages/app/setting/RechargeHistory";
+import Usage from "@/pages/app/setting/Usage";
+import UserInfo from "@/pages/app/setting/UserInfo";
+import UserInvite from "@/pages/app/setting/UserInvite";
+
+export default function useTabMatch(type: string) {
+ const { t } = useTranslation();
+
+ const User_TabMatch = [
+ {
+ key: TabKeys.UserInfo,
+ name: t("SettingPanel.UserInfo"),
+ component:
,
+ icon:
,
+ },
+ {
+ key: TabKeys.UserInvite,
+ name: t("SettingPanel.UserInvite"),
+ component:
,
+ icon:
,
+ },
+ {
+ key: TabKeys.PAT,
+ name: t("Personal Access Token"),
+ component:
,
+ icon:
,
+ },
+ ];
+
+ const Usage_TabMatch = [
+ {
+ key: TabKeys.CostOverview,
+ name: String(t("SettingPanel.CostOverview")),
+ component:
,
+ icon:
,
+ },
+ {
+ key: TabKeys.CardRedemption,
+ name: String(t("SettingPanel.CardRedemption")),
+ component:
,
+ icon:
,
+ },
+ {
+ key: TabKeys.BillingDetails,
+ name: String(t("SettingPanel.BillingDetails")),
+ component:
,
+ icon:
,
+ },
+ {
+ key: TabKeys.RechargeHistory,
+ name: String(t("SettingPanel.RechargeHistory")),
+ component:
,
+ icon:
,
+ },
+ {
+ key: TabKeys.PricingStandards,
+ name: String(t("SettingPanel.PricingStandards")),
+ component:
,
+ icon:
,
+ },
+ ];
+
+ if (type === "user") {
+ return User_TabMatch;
+ } else if (type === "usage") {
+ return Usage_TabMatch;
+ }
+}
diff --git a/web/src/pages/app/setting/index.tsx b/web/src/pages/app/setting/index.tsx
index 50d355913a..fc13ba1b57 100644
--- a/web/src/pages/app/setting/index.tsx
+++ b/web/src/pages/app/setting/index.tsx
@@ -1,4 +1,4 @@
-import { useState } from "react";
+import { useEffect, useState } from "react";
import React from "react";
import {
Box,
@@ -38,28 +38,40 @@ export const TabKeys = {
const SettingModal = (props: {
headerTitle: string;
- children: React.ReactElement;
+ children?: React.ReactElement;
setApp?: TApplicationDetail;
tabMatch?: TTabItem[];
currentTab: string;
+ openModal?: boolean;
+ setOpenModal?: (open: boolean) => void;
}) => {
- const { headerTitle, children, setApp, tabMatch = [] } = props;
+ const { headerTitle, children, setApp, tabMatch = [], openModal, setOpenModal } = props;
const { isOpen, onOpen, onClose } = useDisclosure();
const currentIndex = tabMatch.findIndex((tab) => tab.key === props.currentTab);
const [item, setItem] = useState
(tabMatch[currentIndex]);
const { setCurrentApp } = useGlobalStore((state) => state);
const borderColor = useColorModeValue("lafWhite.600", "lafDark.600");
const darkMode = useColorMode().colorMode === "dark";
+
+ useEffect(() => {
+ if (!children && openModal && setOpenModal) {
+ onOpen();
+ setOpenModal(false);
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [openModal]);
+
return (
<>
- {React.cloneElement(children, {
- onClick: () => {
- if (setApp) {
- setCurrentApp(setApp);
- }
- onOpen();
- },
- })}
+ {children &&
+ React.cloneElement(children, {
+ onClick: () => {
+ if (setApp) {
+ setCurrentApp(setApp);
+ }
+ onOpen();
+ },
+ })}
diff --git a/web/src/pages/home/mods/CreateAppModal/index.tsx b/web/src/pages/home/mods/CreateAppModal/index.tsx
index 18b7fb5dbe..4e4bb0c43e 100644
--- a/web/src/pages/home/mods/CreateAppModal/index.tsx
+++ b/web/src/pages/home/mods/CreateAppModal/index.tsx
@@ -52,7 +52,7 @@ const CreateAppModal = (props: {
const { application, type, isCurrentApp } = props;
- const title = type === "edit" ? t("Edit") : type === "change" ? t("Change") : t("Create");
+ const title = type === "edit" ? t("Edit") : type === "change" ? t("Change") : t("CreateApp");
const { runtimes = [], regions = [] } = useGlobalStore();
diff --git a/web/src/pages/home/mods/Empty/index.tsx b/web/src/pages/home/mods/Empty/index.tsx
index e6634726cf..428d68738f 100644
--- a/web/src/pages/home/mods/Empty/index.tsx
+++ b/web/src/pages/home/mods/Empty/index.tsx
@@ -31,12 +31,12 @@ function Empty() {
return (
-
- {t("HomePanel.Hello")} 👋 ,{" "}
- {hidePhoneNumber(userInfo?.profile?.name || userInfo?.username || "")} ,
- {t("HomePanel.Welcome")}
+
+ {t("HomePanel.Hello")} 👋 , {hidePhoneNumber(userInfo?.username || "")} ,
+ {t("HomePanel.WelcomeTo")}
+ {t("HomePanel.LAF")}
-
{t("HomePanel.Introduction")}
+
{t("HomePanel.Introduction")}
{messageList.map((item, index) => {
return (
@@ -44,6 +44,7 @@ function Empty() {
key={index}
className={clsx("flex items-center pl-9 text-xl font-medium", styles.emptyItem, {
"bg-lafDark-300": darkMode,
+ "bg-lafWhite-100": !darkMode,
})}
>
{item}
@@ -51,7 +52,7 @@ function Empty() {
);
})}
-
{t("HomePanel.Use")}
+
{t("HomePanel.Use")}
}
>
- {t("Create")}
+ {t("CreateApp")}
diff --git a/web/src/pages/home/mods/List/index.tsx b/web/src/pages/home/mods/List/index.tsx
index 8be71c3532..922f5c2bbf 100644
--- a/web/src/pages/home/mods/List/index.tsx
+++ b/web/src/pages/home/mods/List/index.tsx
@@ -18,6 +18,7 @@ import {
} from "@chakra-ui/react";
import { useMutation, useQueryClient } from "@tanstack/react-query";
+import ConfirmButton from "@/components/ConfirmButton";
import CopyText from "@/components/CopyText";
import FileTypeIcon from "@/components/FileTypeIcon";
import IconWrap from "@/components/IconWrap";
@@ -77,7 +78,7 @@ function List(props: { appList: TApplicationItem[] }) {
}>
- {t("Create")}
+ {t("CreateApp")}
@@ -169,51 +170,79 @@ function List(props: { appList: TApplicationItem[] }) {
-
-
- {item.phase === APP_PHASE_STATUS.Started && (
+ {item.phase === APP_STATUS.Stopped ? (
+ ) : (
+ {
+ event?.preventDefault();
+ const res = await updateAppStateMutation.mutateAsync({
+ appid: item.appid,
+ state: APP_STATUS.Restarting,
+ });
+ if (!res.error) {
+ queryClient.setQueryData(APP_LIST_QUERY_KEY, (old: any) => {
+ return {
+ ...old,
+ data: old.data.map((app: any) => {
+ if (app.appid === item.appid) {
+ return {
+ ...app,
+ phase: APP_STATUS.Restarting,
+ };
+ }
+ return app;
+ }),
+ };
+ });
+ }
+ }}
+ >
+
+
+ )}
+
+ {item.phase === APP_PHASE_STATUS.Started && (
+ {
event?.preventDefault();
const res = await updateAppStateMutation.mutateAsync({
appid: item.appid,
@@ -237,10 +266,10 @@ function List(props: { appList: TApplicationItem[] }) {
}
}}
>
-
+
-
+
+
)}