TaskStatusButton.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. import { DropdownButtonType } from "antd/lib/dropdown/dropdown-button";
  2. import {
  3. Button,
  4. Dropdown,
  5. MenuProps,
  6. message,
  7. Popconfirm,
  8. 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. ITaskData,
  18. ITaskListResponse,
  19. ITaskUpdateRequest,
  20. StatusButtons,
  21. 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. 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. }
  107. const items: IStatusMenu[] = StatusButtons.map((item) => {
  108. return {
  109. key: item,
  110. label: intl.formatMessage({
  111. id: `buttons.task.status.change.to.${item}`,
  112. }),
  113. disabled:
  114. task?.type === "instance" && !menuEnable.includes(item as TTaskStatus),
  115. };
  116. });
  117. const menuProps = {
  118. items: items,
  119. onClick: handleMenuClick,
  120. };
  121. const confirm: PopconfirmProps["onConfirm"] = (e) => {
  122. console.log(e);
  123. if (task?.id) {
  124. setStatus({
  125. id: task.id,
  126. status: newStatus,
  127. studio_name: "",
  128. });
  129. }
  130. };
  131. let newStatus: TTaskStatus = "pending";
  132. switch (task?.status) {
  133. case "pending":
  134. newStatus = "published";
  135. break;
  136. case "published":
  137. newStatus = "running";
  138. break;
  139. case "running":
  140. newStatus = "done";
  141. break;
  142. case "done":
  143. newStatus = "restarted";
  144. break;
  145. case "restarted":
  146. newStatus = "done";
  147. break;
  148. case "requested_restart":
  149. newStatus = "done";
  150. break;
  151. default:
  152. break;
  153. }
  154. let buttonText = intl.formatMessage({
  155. id: `buttons.task.status.change.to.${newStatus}`,
  156. defaultMessage: "unknown",
  157. });
  158. return type === "button" ? (
  159. <Dropdown.Button
  160. type={buttonType}
  161. trigger={["click"]}
  162. icon={<DownOutlined />}
  163. menu={menuProps}
  164. buttonsRender={([leftButton, rightButton]) => {
  165. return [
  166. <Popconfirm
  167. title={intl.formatMessage(
  168. { id: "message.task.status.change" },
  169. { status: newStatus }
  170. )}
  171. onConfirm={confirm}
  172. okText="Yes"
  173. cancelText="No"
  174. >
  175. <Button
  176. type={buttonType}
  177. disabled={task?.type === "workflow"}
  178. icon={
  179. loading ? (
  180. <LoadingOutlined />
  181. ) : newStatus === "done" ? (
  182. <CheckOutlined />
  183. ) : (
  184. <></>
  185. )
  186. }
  187. >
  188. {buttonText}
  189. </Button>
  190. </Popconfirm>,
  191. rightButton,
  192. ];
  193. }}
  194. />
  195. ) : (
  196. <Dropdown placement="bottomLeft" menu={menuProps}>
  197. <span>{loading ? <LoadingOutlined /> : <TaskStatus task={task} />}</span>
  198. </Dropdown>
  199. );
  200. };
  201. export default TaskStatusButton;