@nocobase/plugin-departments 2.1.0-alpha.19 → 2.1.0-alpha.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,23 +8,24 @@
8
8
  */
9
9
 
10
10
  module.exports = {
11
- "@nocobase/client": "2.1.0-alpha.19",
11
+ "@nocobase/client": "2.1.0-alpha.20",
12
12
  "react": "18.2.0",
13
13
  "@formily/react": "2.3.7",
14
14
  "@formily/core": "2.3.7",
15
- "@nocobase/utils": "2.1.0-alpha.19",
16
- "@nocobase/plugin-acl": "2.1.0-alpha.19",
15
+ "@nocobase/utils": "2.1.0-alpha.20",
16
+ "@nocobase/plugin-acl": "2.1.0-alpha.20",
17
17
  "react-i18next": "11.18.6",
18
- "@nocobase/database": "2.1.0-alpha.19",
18
+ "@nocobase/database": "2.1.0-alpha.20",
19
19
  "lodash": "4.18.1",
20
- "@nocobase/plugin-user-data-sync": "2.1.0-alpha.19",
21
- "@nocobase/cache": "2.1.0-alpha.19",
22
- "@nocobase/server": "2.1.0-alpha.19",
23
- "@nocobase/data-source-manager": "2.1.0-alpha.19",
24
- "@nocobase/plugin-error-handler": "2.1.0-alpha.19",
20
+ "@nocobase/plugin-user-data-sync": "2.1.0-alpha.20",
21
+ "@nocobase/cache": "2.1.0-alpha.20",
22
+ "@nocobase/server": "2.1.0-alpha.20",
23
+ "@nocobase/data-source-manager": "2.1.0-alpha.20",
24
+ "@nocobase/plugin-error-handler": "2.1.0-alpha.20",
25
+ "sequelize": "6.35.2",
25
26
  "antd": "5.24.2",
26
27
  "@ant-design/icons": "5.6.1",
27
28
  "@formily/shared": "2.3.7",
28
29
  "@emotion/css": "11.13.0",
29
- "@nocobase/actions": "2.1.0-alpha.19"
30
+ "@nocobase/actions": "2.1.0-alpha.20"
30
31
  };
@@ -29,73 +29,37 @@ __export(set_main_department_exports, {
29
29
  setMainDepartment: () => setMainDepartment
30
30
  });
31
31
  module.exports = __toCommonJS(set_main_department_exports);
32
+ var import_sync_user_main_department = require("../sync-user-main-department");
33
+ const normalizeIds = (values = []) => values.map((value) => typeof value === "object" && value ? value.id ?? value : value).filter((value) => value !== null && value !== void 0);
34
+ const syncUsersMainDepartment = async (ctx, userIds) => {
35
+ const uniqUserIds = [...new Set(normalizeIds(userIds))];
36
+ for (const userId of uniqUserIds) {
37
+ await (0, import_sync_user_main_department.syncUserMainDepartment)(ctx.db, userId, ctx.transaction);
38
+ }
39
+ };
32
40
  const setMainDepartment = async (ctx, next) => {
33
- var _a, _b;
34
- await next();
35
41
  const { associatedName, resourceName, associatedIndex, actionName, values, filterByTk } = ctx.action.params;
36
- if (associatedName === "departments" && resourceName === "members" && (values == null ? void 0 : values.length)) {
37
- const userRepo = ctx.db.getRepository("users");
42
+ let affectedDepartmentMemberUserIds = [];
43
+ if (associatedName === "departments" && resourceName === "members" && actionName === "set") {
38
44
  const throughRepo = ctx.db.getRepository("departmentsUsers");
39
- if (actionName === "add" || actionName === "set") {
40
- for (const userId of values) {
41
- const user = await userRepo.findOne({ filterByTk: userId, fields: ["id", "mainDepartmentId"] });
42
- if (!(user == null ? void 0 : user.mainDepartmentId)) {
43
- await userRepo.update({
44
- filterByTk: userId,
45
- values: { mainDepartmentId: associatedIndex }
46
- });
47
- }
48
- }
49
- return;
50
- }
51
- if (actionName === "remove") {
52
- for (const userId of values) {
53
- const user = await userRepo.findOne({ filterByTk: userId, fields: ["id", "mainDepartmentId"] });
54
- if ((user == null ? void 0 : user.mainDepartmentId) === Number(associatedIndex)) {
55
- const firstDept = await throughRepo.findOne({
56
- filter: { userId }
57
- });
58
- await userRepo.update({
59
- filterByTk: userId,
60
- values: { mainDepartmentId: firstDept ? firstDept.departmentId : null }
61
- });
62
- }
63
- }
64
- }
45
+ const currentMembers = await throughRepo.find({
46
+ fields: ["userId"],
47
+ filter: { departmentId: associatedIndex },
48
+ transaction: ctx.transaction
49
+ });
50
+ affectedDepartmentMemberUserIds = currentMembers.map((member) => {
51
+ var _a;
52
+ return ((_a = member.get) == null ? void 0 : _a.call(member, "userId")) ?? member.userId;
53
+ });
65
54
  }
66
- if (associatedName === "users" && resourceName === "departments" && ["add", "remove", "set"].includes(actionName)) {
67
- const userRepo = ctx.db.getRepository("users");
68
- const throughRepo = ctx.db.getRepository("departmentsUsers");
69
- const user = await userRepo.findOne({ filterByTk: associatedIndex, fields: ["id", "mainDepartmentId"] });
70
- let hasValidMain = false;
71
- if (user == null ? void 0 : user.mainDepartmentId) {
72
- const existingAssoc = await throughRepo.findOne({
73
- filter: { userId: associatedIndex, departmentId: user.mainDepartmentId }
74
- });
75
- hasValidMain = !!existingAssoc;
76
- }
77
- if (!hasValidMain) {
78
- const firstDept = await throughRepo.findOne({
79
- filter: { userId: associatedIndex }
80
- });
81
- await userRepo.update({
82
- filterByTk: associatedIndex,
83
- values: { mainDepartmentId: firstDept ? firstDept.departmentId : null }
84
- });
85
- }
55
+ await next();
56
+ if (associatedName === "departments" && resourceName === "members" && ["add", "remove", "set"].includes(actionName)) {
57
+ const affectedUserIds = actionName === "set" ? [...affectedDepartmentMemberUserIds, ...values || []] : values || [];
58
+ await syncUsersMainDepartment(ctx, affectedUserIds);
59
+ return;
86
60
  }
87
- if (resourceName === "users" && actionName === "update") {
88
- const userRepo = ctx.db.getRepository("users");
89
- const throughRepo = ctx.db.getRepository("departmentsUsers");
90
- const userId = associatedIndex ?? filterByTk ?? ((_b = (_a = ctx.body) == null ? void 0 : _a.data) == null ? void 0 : _b.id);
91
- if (!userId) return;
92
- const deptUsers = await throughRepo.find({ filter: { userId } });
93
- if (deptUsers.length === 1) {
94
- await userRepo.update({
95
- filterByTk: userId,
96
- values: { mainDepartmentId: deptUsers[0].departmentId }
97
- });
98
- }
61
+ if (associatedName === "users" && resourceName === "departments" && ["add", "remove", "set"].includes(actionName)) {
62
+ await syncUsersMainDepartment(ctx, [associatedIndex ?? filterByTk]);
99
63
  }
100
64
  };
101
65
  // Annotate the CommonJS export names for ESM import in node:
@@ -37,6 +37,7 @@ var import_users2 = require("./collections/users");
37
37
  var import_middlewares = require("./middlewares");
38
38
  var import_department = require("./models/department");
39
39
  var import_department_data_sync_resource = require("./department-data-sync-resource");
40
+ var import_sync_user_main_department = require("./sync-user-main-department");
40
41
  class PluginDepartmentsServer extends import_server.Plugin {
41
42
  afterAdd() {
42
43
  }
@@ -88,16 +89,22 @@ class PluginDepartmentsServer extends import_server.Plugin {
88
89
  this.app.resourceManager.use(import_middlewares.updateDepartmentIsLeaf);
89
90
  this.app.resourceManager.use(import_middlewares.resetUserDepartmentsCache);
90
91
  this.app.resourceManager.use(import_middlewares.setMainDepartment);
91
- this.app.db.on("departmentsUsers.afterSave", async (model) => {
92
+ this.app.db.on("departmentsUsers.afterSave", async (model, options) => {
92
93
  const cache = this.app.cache;
94
+ await (0, import_sync_user_main_department.syncUserMainDepartment)(this.app.db, model.get("userId"), options == null ? void 0 : options.transaction);
93
95
  await cache.del(`departments:${model.get("userId")}`);
94
96
  });
95
- this.app.db.on("departmentsUsers.afterDestroy", async (model) => {
97
+ this.app.db.on("departmentsUsers.afterDestroy", async (model, options) => {
96
98
  const cache = this.app.cache;
99
+ await (0, import_sync_user_main_department.syncUserMainDepartment)(this.app.db, model.get("userId"), options == null ? void 0 : options.transaction);
97
100
  await cache.del(`departments:${model.get("userId")}`);
98
101
  });
102
+ this.app.db.on("users.afterSaveWithAssociations", async (model, options) => {
103
+ await (0, import_sync_user_main_department.syncUserMainDepartment)(this.app.db, model.get("id"), options == null ? void 0 : options.transaction);
104
+ });
99
105
  this.app.db.on("users.beforeSave", async (model, options) => {
100
106
  var _a;
107
+ const submittedDepartments = (_a = options == null ? void 0 : options.values) == null ? void 0 : _a.departments;
101
108
  const mainDepartmentId = model.get("mainDepartmentId");
102
109
  if (!mainDepartmentId) {
103
110
  return;
@@ -116,7 +123,6 @@ class PluginDepartmentsServer extends import_server.Plugin {
116
123
  return;
117
124
  }
118
125
  }
119
- const submittedDepartments = (_a = options == null ? void 0 : options.values) == null ? void 0 : _a.departments;
120
126
  if (Array.isArray(submittedDepartments)) {
121
127
  const included = submittedDepartments.some((d) => {
122
128
  const id = typeof d === "object" ? d && (d.id ?? d) : d;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ /**
10
+ * This file is part of the NocoBase (R) project.
11
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
12
+ * Authors: NocoBase Team.
13
+ *
14
+ * This program is offered under a commercial license.
15
+ * For more information, see <https://www.nocobase.com/agreement>
16
+ */
17
+ import type { Database } from '@nocobase/database';
18
+ import type { Transaction } from 'sequelize';
19
+ export declare const syncUserMainDepartment: (db: Database, userId: number | string, transaction?: Transaction) => Promise<void>;
@@ -0,0 +1,74 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") {
20
+ for (let key of __getOwnPropNames(from))
21
+ if (!__hasOwnProp.call(to, key) && key !== except)
22
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
+ }
24
+ return to;
25
+ };
26
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
+ var sync_user_main_department_exports = {};
28
+ __export(sync_user_main_department_exports, {
29
+ syncUserMainDepartment: () => syncUserMainDepartment
30
+ });
31
+ module.exports = __toCommonJS(sync_user_main_department_exports);
32
+ const syncUserMainDepartment = async (db, userId, transaction) => {
33
+ if (!userId) {
34
+ return;
35
+ }
36
+ const userRepo = db.getRepository("users");
37
+ const throughRepo = db.getRepository("departmentsUsers");
38
+ const user = await userRepo.findOne({
39
+ filterByTk: userId,
40
+ fields: ["id", "mainDepartmentId"],
41
+ transaction
42
+ });
43
+ if (!user) {
44
+ return;
45
+ }
46
+ const currentMainDepartmentId = user.get("mainDepartmentId");
47
+ const currentMainDepartment = currentMainDepartmentId && await throughRepo.findOne({
48
+ filter: {
49
+ userId,
50
+ departmentId: currentMainDepartmentId
51
+ },
52
+ transaction
53
+ });
54
+ if (currentMainDepartment) {
55
+ return;
56
+ }
57
+ const firstDepartment = await throughRepo.findOne({
58
+ filter: { userId },
59
+ transaction
60
+ });
61
+ const nextMainDepartmentId = firstDepartment ? firstDepartment.get("departmentId") : null;
62
+ if (currentMainDepartmentId === nextMainDepartmentId) {
63
+ return;
64
+ }
65
+ await userRepo.update({
66
+ filterByTk: userId,
67
+ values: { mainDepartmentId: nextMainDepartmentId },
68
+ transaction
69
+ });
70
+ };
71
+ // Annotate the CommonJS export names for ESM import in node:
72
+ 0 && (module.exports = {
73
+ syncUserMainDepartment
74
+ });
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "description": "Organize users by departments, set hierarchical relationships, link roles to control permissions, and use departments as variables in workflows and expressions.",
7
7
  "description.ru-RU": "Организация пользователей по подразделениям, установление иерархических связей, привязка ролей для управления правами и использование подразделений в качестве переменных в рабочих процессах и выражениях.",
8
8
  "description.zh-CN": "以部门来组织用户,设定上下级关系,绑定角色控制权限,并支持作为变量用于工作流和表达式。",
9
- "version": "2.1.0-alpha.19",
9
+ "version": "2.1.0-alpha.20",
10
10
  "main": "dist/server/index.js",
11
11
  "peerDependencies": {
12
12
  "@nocobase/actions": "2.x",
@@ -20,6 +20,6 @@
20
20
  "keywords": [
21
21
  "Users & permissions"
22
22
  ],
23
- "gitHead": "3d13700360eac1c0f9dbf6a5f167ed396a294a3c",
23
+ "gitHead": "3d1535db6bf93ca23257faf474afee0d565f54c6",
24
24
  "license": "Apache-2.0"
25
25
  }