TaskStatusButton.tsx 5.0 KB

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