Collaborator.tsx 6.6 KB

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