Collaborator.tsx 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. import { useIntl } from "react-intl";
  2. import { useEffect, useRef, useState } from "react";
  3. import { ActionType, ProList } from "@ant-design/pro-components";
  4. import { Tag, Button, Popconfirm, Space, Badge, message, Dropdown } from "antd";
  5. import { UserOutlined, TeamOutlined } from "@ant-design/icons";
  6. import { delete_, get, put } from "../../request";
  7. import {
  8. IShareDeleteResponse,
  9. IShareListResponse,
  10. IShareRequest,
  11. IShareResponse,
  12. IShareUpdateRequest,
  13. } from "../api/Share";
  14. import { IUser } from "../auth/User";
  15. import { TRole } from "../api/Auth";
  16. import Group, { IGroup } from "../group/Group";
  17. import UserName from "../auth/UserName";
  18. interface ICollaborator {
  19. sn?: number;
  20. id?: string;
  21. resId: string;
  22. resType: string;
  23. power?: number;
  24. user?: IUser;
  25. group?: IGroup;
  26. role?: TRole;
  27. }
  28. interface IWidget {
  29. resId?: string;
  30. load?: boolean;
  31. onReload?: Function;
  32. }
  33. const Widget = ({ resId, load = false, onReload }: IWidget) => {
  34. const intl = useIntl(); //i18n
  35. const [canDelete, setCanDelete] = useState(false);
  36. const [memberCount, setMemberCount] = useState<number>();
  37. useEffect(() => {
  38. if (load) {
  39. ref.current?.reload();
  40. if (typeof onReload !== "undefined") {
  41. onReload();
  42. }
  43. }
  44. }, [load, onReload]);
  45. const ref = useRef<ActionType>();
  46. const roleList: TRole[] = ["editor", "reader"];
  47. return (
  48. <ProList<ICollaborator>
  49. rowKey="id"
  50. actionRef={ref}
  51. headerTitle={
  52. <Space>
  53. {intl.formatMessage({ id: "labels.collaborators" })}
  54. <Badge color="geekblue" count={memberCount} />
  55. </Space>
  56. }
  57. showActions="hover"
  58. request={async (params = {}, sorter, filter) => {
  59. // TODO
  60. console.log(params, sorter, filter);
  61. let url = `/v2/share?view=res&id=${resId}`;
  62. const offset =
  63. ((params.current ? params.current : 1) - 1) *
  64. (params.pageSize ? params.pageSize : 20);
  65. url += `&limit=${params.pageSize}&offset=${offset}`;
  66. if (typeof params.keyword !== "undefined") {
  67. url += "&search=" + (params.keyword ? params.keyword : "");
  68. }
  69. const res = await get<IShareListResponse>(url);
  70. if (res.ok) {
  71. console.log(res.data);
  72. setMemberCount(res.data.count);
  73. switch (res.data.role) {
  74. case "owner":
  75. setCanDelete(true);
  76. break;
  77. case "manager":
  78. setCanDelete(true);
  79. break;
  80. }
  81. const items: ICollaborator[] = res.data.rows.map((item, id) => {
  82. let member: ICollaborator = {
  83. sn: id + 1,
  84. id: item.id,
  85. resId: item.res_id,
  86. resType: item.res_type,
  87. power: item.power,
  88. user: item.user,
  89. group: item.group,
  90. role: item.role,
  91. };
  92. return member;
  93. });
  94. console.log(items);
  95. return {
  96. total: res.data.count,
  97. succcess: true,
  98. data: items,
  99. };
  100. } else {
  101. console.error(res.message);
  102. return {
  103. total: 0,
  104. succcess: false,
  105. data: [],
  106. };
  107. }
  108. }}
  109. pagination={{
  110. showQuickJumper: true,
  111. showSizeChanger: true,
  112. }}
  113. metas={{
  114. title: {
  115. render: (text, row, index, action) => {
  116. return row.user ? (
  117. <UserName {...row.user} key={index} />
  118. ) : (
  119. <Group group={row.group} key={index} />
  120. );
  121. },
  122. },
  123. avatar: {
  124. render: (text, row, index, action) => {
  125. return row.user ? (
  126. <UserOutlined key={index} />
  127. ) : (
  128. <TeamOutlined key={index} />
  129. );
  130. },
  131. },
  132. subTitle: {
  133. render: (text, row, index, action) => {
  134. let right = "";
  135. switch (row.power) {
  136. case 10:
  137. right = intl.formatMessage({ id: "auth.role.reader" });
  138. break;
  139. case 20:
  140. right = intl.formatMessage({ id: "auth.role.editor" });
  141. break;
  142. case 30:
  143. right = intl.formatMessage({ id: "auth.role.manager" });
  144. break;
  145. default:
  146. break;
  147. }
  148. return (
  149. <Dropdown
  150. key={index}
  151. trigger={["click"]}
  152. menu={{
  153. items: roleList.map((item) => {
  154. return {
  155. key: item,
  156. label: intl.formatMessage({ id: "auth.role." + item }),
  157. };
  158. }),
  159. onClick: (e) => {
  160. put<IShareUpdateRequest, IShareResponse>(
  161. `/v2/share/${row.id}`,
  162. {
  163. role: e.key as TRole,
  164. }
  165. ).then((json) => {
  166. console.log(json);
  167. if (json.ok) {
  168. ref.current?.reload();
  169. }
  170. });
  171. },
  172. }}
  173. >
  174. <Tag key={index}>{right}</Tag>
  175. </Dropdown>
  176. );
  177. },
  178. },
  179. actions: {
  180. render: (text, row, index, action) => [
  181. canDelete ? (
  182. <Popconfirm
  183. key={index}
  184. placement="bottomLeft"
  185. title={intl.formatMessage({
  186. id: "forms.message.member.delete",
  187. })}
  188. onConfirm={(e?: React.MouseEvent<HTMLElement, MouseEvent>) => {
  189. console.log("delete", row.id);
  190. delete_<IShareDeleteResponse>("/v2/share/" + row.id)
  191. .then((json) => {
  192. if (json.ok) {
  193. message.success("delete ok");
  194. ref.current?.reload();
  195. } else {
  196. message.error(json.message);
  197. }
  198. })
  199. .catch((e) => {
  200. message.error(e);
  201. });
  202. }}
  203. okText={intl.formatMessage({ id: "buttons.ok" })}
  204. cancelText={intl.formatMessage({ id: "buttons.cancel" })}
  205. >
  206. <Button size="small" type="link" danger key="link">
  207. {intl.formatMessage({ id: "buttons.remove" })}
  208. </Button>
  209. </Popconfirm>
  210. ) : undefined,
  211. ],
  212. },
  213. }}
  214. />
  215. );
  216. };
  217. export default Widget;