TaskStatusButton.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. import type { DropdownButtonType } from "antd/lib/dropdown/dropdown-button";
  2. import {
  3. Button,
  4. Dropdown,
  5. type MenuProps,
  6. message,
  7. Popconfirm,
  8. type PopconfirmProps,
  9. } from "antd";
  10. import { useIntl } from "react-intl";
  11. import {
  12. CheckOutlined,
  13. LoadingOutlined,
  14. DownOutlined,
  15. } from "@ant-design/icons";
  16. import {
  17. type ITaskData,
  18. type ITaskListResponse,
  19. type ITaskUpdateRequest,
  20. StatusButtons,
  21. type TTaskStatus,
  22. } from "../../api/task";
  23. import { patch } from "../../request";
  24. import TaskStatus from "./TaskStatus";
  25. import { useState } from "react";
  26. import type { MenuItemType } from "antd/es/menu/interface";
  27. type IStatusMenu = MenuItemType & {
  28. key: TTaskStatus;
  29. };
  30. interface IWidget {
  31. type?: "button" | "tag";
  32. task?: ITaskData;
  33. buttonType?: DropdownButtonType;
  34. onChange?: (task: ITaskData[]) => void;
  35. }
  36. const TaskStatusButton = ({
  37. type = "button",
  38. task,
  39. buttonType = "primary",
  40. onChange,
  41. }: IWidget) => {
  42. const intl = useIntl();
  43. const [loading, setLoading] = useState(false);
  44. const setStatus = (setting: ITaskUpdateRequest) => {
  45. const url = `/api/v2/task-status/${setting.id}`;
  46. console.info("api request", url, setting);
  47. setLoading(true);
  48. patch<ITaskUpdateRequest, ITaskListResponse>(url, setting)
  49. .then((json) => {
  50. console.info("api response", json);
  51. if (json.ok) {
  52. message.success("Success");
  53. onChange?.(json.data.rows);
  54. } else {
  55. message.error(json.message);
  56. }
  57. })
  58. .finally(() => setLoading(false));
  59. };
  60. const handleMenuClick: MenuProps["onClick"] = (e) => {
  61. console.log("click", e);
  62. if (task?.id) {
  63. setStatus({
  64. id: task.id,
  65. status: e.key,
  66. studio_name: "",
  67. });
  68. }
  69. };
  70. const requested_restart_enable =
  71. task?.type === "instance" &&
  72. task.status === "running" &&
  73. task.pre_task &&
  74. task.pre_task?.length > 0;
  75. let menuEnable: TTaskStatus[] = [];
  76. switch (task?.status) {
  77. case "pending":
  78. menuEnable = ["published"];
  79. break;
  80. case "published":
  81. menuEnable = ["pending", "running"];
  82. break;
  83. case "running":
  84. menuEnable = [
  85. "done",
  86. "stop",
  87. "quit",
  88. requested_restart_enable ? "requested_restart" : "done",
  89. ];
  90. break;
  91. case "done":
  92. menuEnable = ["restarted"];
  93. break;
  94. case "restarted":
  95. menuEnable = ["done"];
  96. break;
  97. case "requested_restart":
  98. menuEnable = ["done"];
  99. break;
  100. case "queue":
  101. menuEnable = ["stop"];
  102. break;
  103. case "stop":
  104. menuEnable = ["restarted"];
  105. break;
  106. case "quit":
  107. menuEnable = ["published"];
  108. break;
  109. case "pause":
  110. menuEnable = ["restarted"];
  111. break;
  112. }
  113. const items: IStatusMenu[] = StatusButtons.map((item) => {
  114. return {
  115. key: item,
  116. label: intl.formatMessage({
  117. id: `buttons.task.status.change.to.${item}`,
  118. }),
  119. disabled:
  120. task?.type === "instance" && !menuEnable.includes(item as TTaskStatus),
  121. };
  122. });
  123. const menuProps = {
  124. items: items,
  125. onClick: handleMenuClick,
  126. };
  127. const confirm: PopconfirmProps["onConfirm"] = (e) => {
  128. console.log(e);
  129. if (task?.id) {
  130. setStatus({
  131. id: task.id,
  132. status: newStatus,
  133. studio_name: "",
  134. });
  135. }
  136. };
  137. let newStatus: TTaskStatus = "pending";
  138. switch (task?.status) {
  139. case "pending":
  140. newStatus = "published";
  141. break;
  142. case "published":
  143. newStatus = "running";
  144. break;
  145. case "running":
  146. newStatus = "done";
  147. break;
  148. case "done":
  149. newStatus = "restarted";
  150. break;
  151. case "restarted":
  152. newStatus = "done";
  153. break;
  154. case "requested_restart":
  155. newStatus = "done";
  156. break;
  157. default:
  158. break;
  159. }
  160. const buttonText = intl.formatMessage({
  161. id: `buttons.task.status.change.to.${newStatus}`,
  162. defaultMessage: "unknown",
  163. });
  164. return type === "button" ? (
  165. <Dropdown.Button
  166. type={buttonType}
  167. trigger={["click"]}
  168. icon={<DownOutlined />}
  169. menu={menuProps}
  170. buttonsRender={([, rightButton]) => {
  171. return [
  172. <Popconfirm
  173. title={intl.formatMessage(
  174. { id: "message.task.status.change" },
  175. { status: newStatus }
  176. )}
  177. onConfirm={confirm}
  178. okText="Yes"
  179. cancelText="No"
  180. >
  181. <Button
  182. type={buttonType}
  183. disabled={task?.type === "workflow"}
  184. icon={
  185. loading ? (
  186. <LoadingOutlined />
  187. ) : newStatus === "done" ? (
  188. <CheckOutlined />
  189. ) : (
  190. <></>
  191. )
  192. }
  193. >
  194. {buttonText}
  195. </Button>
  196. </Popconfirm>,
  197. rightButton,
  198. ];
  199. }}
  200. />
  201. ) : (
  202. <Dropdown placement="bottomLeft" menu={menuProps}>
  203. <span>{loading ? <LoadingOutlined /> : <TaskStatus task={task} />}</span>
  204. </Dropdown>
  205. );
  206. };
  207. export default TaskStatusButton;