@steedos/service-core-objects 3.0.0-beta.9 → 3.0.0-beta.90

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.
Files changed (130) hide show
  1. package/main/default/client/{topic.client.js → css.client.js} +2 -1
  2. package/main/default/client/socket.client.js +118 -0
  3. package/main/default/objectTranslations/base.en/base.en.objectTranslation.yml +2 -0
  4. package/main/default/objectTranslations/base.zh-CN/base.zh-CN.objectTranslation.yml +2 -0
  5. package/main/default/objectTranslations/datasources.zh-CN/datasources.zh-CN.objectTranslation.yml +1 -1
  6. package/main/default/objectTranslations/instances.en/instances.en.objectTranslation.yml +45 -0
  7. package/main/default/objectTranslations/instances.zh-CN/instances.zh-CN.objectTranslation.yml +42 -0
  8. package/main/default/objectTranslations/license.en/license.en.objectTranslation.yml +1 -1
  9. package/main/default/objectTranslations/object_actions.zh-CN/object_actions.zh-CN.objectTranslation.yml +1 -1
  10. package/main/default/objectTranslations/object_fields.en/object_fields.en.objectTranslation.yml +1 -5
  11. package/main/default/objectTranslations/object_fields.zh-CN/object_fields.zh-CN.objectTranslation.yml +3 -3
  12. package/main/default/objectTranslations/object_functions.zh-CN/object_functions.zh-CN.objectTranslation.yml +1 -1
  13. package/main/default/objectTranslations/object_layouts.zh-CN/object_layouts.zh-CN.objectTranslation.yml +1 -1
  14. package/main/default/objectTranslations/object_listviews.en/object_listviews.en.objectTranslation.yml +3 -1
  15. package/main/default/objectTranslations/object_listviews.zh-CN/object_listviews.zh-CN.objectTranslation.yml +5 -3
  16. package/main/default/objectTranslations/objects.en/objects.en.objectTranslation.yml +23 -18
  17. package/main/default/objectTranslations/objects.zh-CN/objects.zh-CN.objectTranslation.yml +39 -25
  18. package/main/default/objectTranslations/operation_logs.en/operation_logs.en.objectTranslation.yml +66 -0
  19. package/main/default/objectTranslations/operation_logs.zh-CN/operation_logs.zh-CN.objectTranslation.yml +66 -0
  20. package/main/default/objects/_base/base.client.js +11 -10
  21. package/main/default/objects/_base/base.object.js +279 -105
  22. package/main/default/objects/_base/base.object.yml +8 -0
  23. package/main/default/objects/announcements.object.yml +68 -0
  24. package/main/default/objects/apps/apps.object.yml +25 -69
  25. package/main/default/objects/apps/buttons/disable.button.js +3 -1
  26. package/main/default/objects/apps/buttons/enable.button.js +3 -1
  27. package/main/default/objects/audit_records.object.yml +1 -1
  28. package/main/default/objects/cms_files/cms_files.object.yml +2 -1
  29. package/main/default/objects/favorites.object.yml +65 -0
  30. package/main/default/objects/keyvalue/keyvalue.object.yml +1 -0
  31. package/main/default/objects/logs/logs.object.yml +1 -0
  32. package/main/default/objects/object_fields/buttons/recomputeFormulaValues.button.js +6 -2
  33. package/main/default/objects/object_fields/buttons/recomputeSummaryValues.button.js +6 -2
  34. package/main/default/objects/object_fields/buttons/standard_new.button.js +1 -1
  35. package/main/default/objects/object_fields/fields/_name.field.yml +1 -0
  36. package/main/default/objects/object_fields/fields/auto_fill_mapping.$.to.field.yml +28 -13
  37. package/main/default/objects/object_fields/fields/name.field.yml +1 -0
  38. package/main/default/objects/object_fields/fields/options.field.yml +1 -0
  39. package/main/default/objects/object_fields/fields/summary_filters.$.field.field.yml +16 -9
  40. package/main/default/objects/object_fields/fields/summary_filters.$.operation.field.yml +26 -29
  41. package/main/default/objects/object_fields/listviews/all.listview.yml +3 -1
  42. package/main/default/objects/object_fields/listviews/customize.listview.yml +3 -1
  43. package/main/default/objects/object_functions/fields/script.field.yml +1 -1
  44. package/main/default/objects/object_listviews/buttons/customize.button.js +36 -30
  45. package/main/default/objects/object_listviews/buttons/showDesign.button.js +6 -6
  46. package/main/default/objects/object_listviews/fields/adaptor.field.yml +2 -2
  47. package/main/default/objects/object_listviews/fields/crudDataFilter.field.yml +10 -0
  48. package/main/default/objects/object_listviews/fields/enable_amis_schema.field.yml +1 -0
  49. package/main/default/objects/object_listviews/fields/extra_columns.field.yml +18 -0
  50. package/main/default/objects/object_listviews/fields/requestAdaptor.field.yml +2 -2
  51. package/main/default/objects/object_listviews/object_listviews.object.yml +1 -1
  52. package/main/default/objects/object_triggers/fields/handler.field.yml +1 -1
  53. package/main/default/objects/object_webhooks/fields/fields.field.yml +1 -1
  54. package/main/default/objects/object_webhooks/object_webhooks.object.yml +1 -0
  55. package/main/default/objects/objects/buttons/custom.button.js +6 -35
  56. package/main/default/objects/objects/buttons/custom.button.yml +85 -1
  57. package/main/default/objects/objects/buttons/delete_object.button.yml +5 -4
  58. package/main/default/objects/objects/buttons/design_fields_layout.button.yml +1 -1
  59. package/main/default/objects/objects/buttons/reset.button.yml +6 -5
  60. package/main/default/objects/objects/buttons/show_object.button.js +2 -29
  61. package/main/default/objects/objects/fields/compactLayouts.field.yml +2 -2
  62. package/main/default/objects/objects/fields/enable_audit.field.yml +5 -0
  63. package/main/default/objects/objects/fields/enable_chatter.field.yml +5 -4
  64. package/main/default/objects/objects/fields/enable_dataloader.field.yml +0 -1
  65. package/main/default/objects/objects/fields/enable_enhanced_lookup.field.yml +0 -4
  66. package/main/default/objects/objects/fields/enable_events.field.yml +2 -2
  67. package/main/default/objects/objects/fields/enable_files.field.yml +1 -1
  68. package/main/default/objects/objects/fields/enable_form_tabs.field.yml +1 -2
  69. package/main/default/objects/objects/fields/enable_inline_edit.field.yml +1 -1
  70. package/main/default/objects/objects/fields/enable_instances.field.yml +2 -2
  71. package/main/default/objects/objects/fields/enable_lock_detail.field.yml +0 -1
  72. package/main/default/objects/objects/fields/enable_notes.field.yml +2 -2
  73. package/main/default/objects/objects/fields/enable_tasks.field.yml +1 -1
  74. package/main/default/objects/objects/fields/enable_tree.field.yml +0 -1
  75. package/main/default/objects/objects/fields/field_groups.field.yml +1 -1
  76. package/main/default/objects/objects/fields/in_development.field.yml +0 -1
  77. package/main/default/objects/objects/fields/is_deleted.field.yml +1 -0
  78. package/main/default/objects/objects/fields/name.field.yml +1 -4
  79. package/main/default/objects/objects/fields/table_name.field.yml +0 -1
  80. package/main/default/objects/objects/listviews/all.listview.yml +4 -1
  81. package/main/default/objects/objects/listviews/customize.listview.yml +3 -1
  82. package/main/default/objects/objects/listviews/deleted.listview.yml +3 -1
  83. package/main/default/objects/objects/listviews/metadata.listview.yml +3 -1
  84. package/main/default/objects/objects/listviews/system.listview.yml +3 -1
  85. package/main/default/objects/objects/objects.object.yml +1 -1
  86. package/main/default/objects/permission_set.object.yml +0 -4
  87. package/main/default/objects/queue_import.object.yml +16 -1
  88. package/main/default/objects/roles.object.yml +1 -5
  89. package/main/default/objects/space_users/buttons/standard_edit.button.js +0 -1
  90. package/main/default/objects/space_users/fields/locale.field.yml +2 -1
  91. package/main/default/pages/cms_files_preview.page.amis.json +20 -1
  92. package/main/default/pages/object_detail.page.amis.json +17 -11
  93. package/main/default/pages/object_fields_form.page.amis.json +0 -11
  94. package/main/default/pages/object_validation_rules_form.page.amis.json +38 -0
  95. package/main/default/pages/object_validation_rules_form.page.yml +13 -0
  96. package/main/default/pages/object_webhooks_form.page.amis.json +1 -1
  97. package/main/default/pages/space_users_list.page.amis.json +2 -2
  98. package/main/default/routes/importRecords.router.js +87 -0
  99. package/main/default/routes/notifications.router.js +113 -0
  100. package/main/default/routes/object_fields_design.ejs +19 -8
  101. package/main/default/services/app-design.service.js +2 -1
  102. package/main/default/services/notifications.service.js +190 -0
  103. package/main/default/services/users.service.js +1 -1
  104. package/main/default/tabs/{admin_process_delegation_rules.tab.yml → admin_bull_dashboard.tab.yml} +9 -12
  105. package/main/default/translations/en.translation.yml +3 -2
  106. package/main/default/translations/zh-CN.translation.yml +3 -2
  107. package/main/default/triggers/objects_set_default_object_properties_trigger.trigger.yml +9 -6
  108. package/main/default/triggers/queue_import.trigger.js +16 -0
  109. package/package.json +4 -3
  110. package/package.service.js +3 -2
  111. package/public/platform.css +62 -0
  112. package/public/topic.css +17 -37
  113. package/main/default/objectTranslations/flow_positions.en/flow_positions.en.objectTranslation.yml +0 -19
  114. package/main/default/objectTranslations/flow_positions.zh-CN/flow_positions.zh-CN.objectTranslation.yml +0 -19
  115. package/main/default/objectTranslations/flow_roles.en/flow_roles.en.objectTranslation.yml +0 -11
  116. package/main/default/objectTranslations/flow_roles.zh-CN/flow_roles.zh-CN.objectTranslation.yml +0 -14
  117. package/main/default/objectTranslations/flows.en/flows.en.objectTranslation.yml +0 -317
  118. package/main/default/objectTranslations/flows.zh-CN/flows.zh-CN.objectTranslation.yml +0 -314
  119. package/main/default/objects/apps/buttons/amis_edit.button.yml +0 -39
  120. package/main/default/objects/apps/buttons/amis_new.button.yml +0 -43
  121. package/main/default/objects/flows/flows.object.yml +0 -1089
  122. package/main/default/objects/object_actions/buttons/customize.button.js +0 -33
  123. package/main/default/objects/object_actions/buttons/customize.button.yml +0 -3
  124. package/main/default/objects/object_listviews/buttons/copy.button.js +0 -58
  125. package/main/default/objects/object_listviews/buttons/copy.button.yml +0 -3
  126. package/main/default/objects/object_listviews/buttons/customize.button.yml +0 -3
  127. package/main/default/objects/objects/buttons/design_field_layout.button.js +0 -28
  128. package/main/default/objects/objects/buttons/design_field_layout.button.yml +0 -5
  129. package/main/default/objects/process_definition.object.yml +0 -323
  130. package/main/default/objects/space_users/fields/zoom.field.yml +0 -16
@@ -66,8 +66,4 @@ permission_set:
66
66
  allowEdit: true
67
67
  allowRead: true
68
68
  modifyAllRecords: true
69
- viewAllRecords: true
70
- actions:
71
- customize:
72
- label: Customize
73
- on: record
69
+ viewAllRecords: true
@@ -7,7 +7,6 @@
7
7
  */
8
8
  module.exports = {
9
9
  standard_editVisible: function (object_name, record_id, record_permissions, data) {
10
- console.log('standard_editVisible===>')
11
10
  var allowEdit = Steedos.Object.base.actions.standard_edit.visible.apply(this, arguments);
12
11
  if (!allowEdit) {
13
12
  // permissions配置没有权限则不给权限
@@ -13,5 +13,6 @@ options:
13
13
  value: en-us
14
14
  - label: 日本語
15
15
  value: ja
16
- defaultValue: 'zh-cn'
16
+ amis:
17
+ value: "${locale ? locale : (window:Builder.settings.default_language == 'zh-CN' ? 'zh-cn' : (window:Builder.settings.default_language ? (window:Builder.settings.default_language === 'en' ? 'en-us' : window:Builder.settings.default_language) : 'zh-cn'))}"
17
18
  sort_no: 280
@@ -134,7 +134,7 @@
134
134
  "id": "u:5d4e7e3f6ecc"
135
135
  },
136
136
  {
137
- "title": "相关",
137
+ "title": "历史版本",
138
138
  "body": [
139
139
  {
140
140
  "type": "steedos-object-related-lists",
@@ -147,6 +147,25 @@
147
147
  ],
148
148
  "className": "px-0 pt-4",
149
149
  "id": "u:f2f42d8195ab"
150
+ },
151
+ {
152
+ "title": "评论",
153
+ "body": [
154
+ {
155
+ "type": "rooms-provider",
156
+ "baseUrl": "${context.rootUrl}",
157
+ "body": [
158
+ {
159
+ "type": "rooms-comments",
160
+ "className": "flex flex-col gap-3",
161
+ "roomId": "objects:${objectName}:${recordId}"
162
+ }
163
+ ]
164
+ }
165
+ ],
166
+ "className": "px-0 pt-4",
167
+ "id": "u:f2f42d8195ab",
168
+ "visibleOn": "${uiSchema.enable_chatter}"
150
169
  }
151
170
  ],
152
171
  "id": "u:560caa275d48"
@@ -173,6 +173,22 @@
173
173
  "recordId": "${recordId}",
174
174
  "relatedObjectApiName": "object_functions",
175
175
  "relatedKey": "objectApiName",
176
+ "perPage": 20,
177
+ "id": "u:e0aff125ad0f"
178
+ }
179
+ ],
180
+ "id": "u:13fd52c4e905"
181
+ },
182
+ {
183
+ "title": "${'objects_amis_queue_import' | t}",
184
+ "id": "u:b36e7189917a",
185
+ "body": [
186
+ {
187
+ "type": "steedos-object-related-listview",
188
+ "objectApiName": "objects",
189
+ "recordId": "${recordId}",
190
+ "relatedObjectApiName": "queue_import",
191
+ "relatedKey": "object_name",
176
192
  "perPage": 20
177
193
  }
178
194
  ]
@@ -180,7 +196,7 @@
180
196
  ],
181
197
  "id": "u:6a3b45d7adcf",
182
198
  "tabsMode": "vertical",
183
- "className": "steedos-record-tabs bg-white m-4 border-y",
199
+ "className": "steedos-record-tabs bg-white m-4 border-none sm:shadow",
184
200
  "toolbarClassName": "",
185
201
  "linksClassName": "",
186
202
  "contentClassName": "bg-white",
@@ -206,16 +222,6 @@
206
222
  }
207
223
  }
208
224
  ],
209
- "data": {
210
- "objectName": "objects",
211
- "recordId": "space_users",
212
- "context": {
213
- "rootUrl": "http://127.0.0.1:5800",
214
- "tenantId": "hKdnwE55WcnWveYxS",
215
- "userId": "62ede4f62161e377e35de58c",
216
- "authToken": "b6475c5536a26d23d3db84e96536e08e82e1e726380cdd5cb09fc977e1d6e57c08fb23d7a1090006189d3d"
217
- }
218
- },
219
225
  "id": "page_objects_record_detail",
220
226
  "objectApiName": "${objectName}",
221
227
  "name": "page_objects_record_detail",
@@ -224,17 +224,6 @@
224
224
  "formula"
225
225
  ]
226
226
  },
227
- "onEvent": {
228
- "init": {
229
- "weight": 0,
230
- "actions": [
231
- {
232
- "actionType": "custom",
233
- "script": "//初始化时给外层dialog加上类名,使过滤组件popover正常显示\n$('.steedos-object-fields-form-page').closest('.amis-dialog-widget.antd-Modal').addClass('steedos-overflow-visible-dialog');"
234
- }
235
- ]
236
- }
237
- },
238
227
  "name": "object_fields_form",
239
228
  "className": "steedos-object-fields-form-page",
240
229
  "id": "steedos_object_fields_service"
@@ -0,0 +1,38 @@
1
+ {
2
+ "type": "service",
3
+ "body": [
4
+ {
5
+ "type": "steedos-object-form",
6
+ "label": "对象表单",
7
+ "objectApiName": "object_validation_rules",
8
+ "recordId": "${recordId}",
9
+ "className": "",
10
+ "id": "u:b3d626885b90",
11
+ "enableTabs": false,
12
+ "mode": "edit",
13
+ "layout": "normal",
14
+ "tabsMode": "",
15
+ "fieldsExtend": {
16
+ "error_condition_formula": {
17
+ "amis": {
18
+ "type": "service",
19
+ "schemaApi": {
20
+ "method": "get",
21
+ "url": "${context.rootUrl}/service/api/amis-metadata-objects/objects/${object_name}/fields/options",
22
+ "cache": 30000,
23
+ "adaptor": "const field = context.uiSchema.fields.error_condition_formula; const variables = SteedosUI.getFormulaVariables(payload.data.options); \n var fieldSchema={label: field.label, type:'input-formula', name: 'error_condition_formula', 'evalMode': false, variableMode: 'tabs', variables: variables, labelRemark: field.inlineHelpText, description: field.description } \n return {...payload, data:fieldSchema};",
24
+ "trackExpression": "${object_name}",
25
+ "sendOn": "${object_name}"
26
+ },
27
+ "dsType": "api",
28
+ "id": "u:508198dbfac7"
29
+ }
30
+ }
31
+ }
32
+ }
33
+ ],
34
+ "data": {},
35
+ "name": "page_object_validation_rules_form",
36
+ "id": "u:5f4f07272db7",
37
+ "dsType": "api"
38
+ }
@@ -0,0 +1,13 @@
1
+ name: object_validation_rules_form
2
+ is_active: true
3
+ label: 对象验证规则表单
4
+ locked: false
5
+ object_name: object_validation_rules
6
+ pageAssignments:
7
+ - type: orgDefault
8
+ page: object_validation_rules_form
9
+ desktop: true
10
+ mobile: true
11
+ render_engine: amis
12
+ type: form
13
+ widgets: []
@@ -16,7 +16,7 @@
16
16
  "method": "get",
17
17
  "url": "/service/api/amis-metadata-objects/objects/${object_name}/fields/options",
18
18
  "cache": 30000,
19
- "adaptor": "const field = context.uiSchema.fields.condition; const visibleOnVariables = SteedosUI.getFormulaVariables(payload.data.options);\n const defaultValueVariables = [visibleOnVariables[1]];\n const variables = [];\n const varItem = {\n label: '对象字段',\n children: _.map(payload.data.options, (item)=>{\n return {\n label: item.label,\n value: item.value\n }\n })\n };\n variables.push(varItem);\n payload.data={label: field.label, type:'input-formula', name: 'condition', variables: variables, labelRemark: field.inlineHelpText, description: field.description } \n return payload;",
19
+ "adaptor": "const field = context.uiSchema.fields.condition; const variables = SteedosUI.getFormulaVariables(payload.data.options);\n var fieldSchema={label: field.label, type:'input-formula', name: 'condition', 'evalMode': false, variableMode: 'tabs', variables: variables, labelRemark: field.inlineHelpText, description: field.description } \n return {...payload, data:fieldSchema};",
20
20
  "trackExpression": "${object_name}",
21
21
  "sendOn": "${object_name}"
22
22
  }
@@ -19,7 +19,7 @@
19
19
  {
20
20
  "type": "input-tree",
21
21
  "id": "u:7fd77b7915b0",
22
- "className": "",
22
+ "className": "bg-none",
23
23
  "source": {
24
24
  "method": "post",
25
25
  "url": "${context.rootUrl}/graphql",
@@ -88,7 +88,7 @@
88
88
  {
89
89
  "type": "wrapper",
90
90
  "size": "none",
91
- "className": "flex-1 overflow-y-auto focus:outline-none lg:order-last w-96",
91
+ "className": "flex-1 focus:outline-none lg:order-last w-96",
92
92
  "body": [
93
93
  {
94
94
  "type": "steedos-object-listview",
@@ -0,0 +1,87 @@
1
+
2
+ const { requireAuthentication } = require('@steedos/auth');
3
+ const { importWithCmsFile } = require('@steedos/data-import/lib/index')
4
+ const express = require('express');
5
+ const router = express.Router();
6
+
7
+ const json2xls = require('json2xls');
8
+ const { getObject } = require('@steedos/objectql');
9
+ const _ = require('lodash');
10
+
11
+ const initiateImport = async function (req, res) {
12
+ try {
13
+ const userSession = req.user;
14
+ // const spaceId = userSession.spaceId;
15
+ let { importObjId, importObjectHistoryId } = req.body;
16
+ let fileId = null;
17
+ const isSpaceAdmin = req.user.is_space_admin;
18
+ //传入了importObjId参数,必须是工作区管理员权限
19
+ if (importObjId && !isSpaceAdmin) {
20
+ return res
21
+ .status(401)
22
+ .send({ status: "error", message: "Permission denied" });
23
+ }
24
+
25
+ if (importObjectHistoryId) {
26
+ const record = await getObject('queue_import_history').findOne(importObjectHistoryId);
27
+ if (!record) {
28
+ throw new Error(
29
+ `can not find queue_import_history record with given id "${importObjectHistoryId}"`
30
+ );
31
+ }
32
+ if (!record.file) {
33
+ throw new Error(`Upload excel file, please.`);
34
+ }
35
+ fileId = record.file
36
+ importObjId = record.queue_import
37
+ }
38
+
39
+ // if (!Steedos.hasFeature('metadata_api', spaceId)) {
40
+ // return res.status(403).send({ status: 'error', message: 'Please upgrade the platform license to Enterprise Edition' });
41
+ // }
42
+
43
+ try {
44
+ let result = await importWithCmsFile(importObjId, userSession, importObjectHistoryId, fileId);
45
+ return res.status(200).send({ status: "success", result });
46
+ } catch (error) {
47
+ console.log(error)
48
+ return res
49
+ .status(500)
50
+ .send({ status: "failed", message: error.message });
51
+ }
52
+ } catch (error) {
53
+ console.log(error)
54
+ return res.status(500).send({ status: "failed", error: error.message });
55
+ }
56
+ }
57
+
58
+ router.post('/api/data/initiateImport', requireAuthentication, initiateImport);
59
+
60
+ router.get('/api/data/download/template/:record_id', requireAuthentication, async function (req, res) {
61
+ try {
62
+ const { record_id } = req.params;
63
+ let queueImportDoc = await getObject("queue_import").findOne(record_id);
64
+ let fieldMaps = queueImportDoc.field_mappings;
65
+ if (_.isEmpty(fieldMaps)) {
66
+ return;
67
+ }
68
+ let json = {};
69
+ for (const fMap of fieldMaps) {
70
+ json[fMap.header] = null;
71
+ }
72
+ let xls = json2xls([json]);
73
+ res.writeHead(200, {
74
+ 'Content-Type': 'application/octet-stream',
75
+ 'Content-Disposition': 'attachment;filename=' + encodeURI(queueImportDoc.description + '.xlsx'),
76
+ 'Access-Control-Expose-Headers': 'Content-Disposition'
77
+ });
78
+ res.end(xls, 'binary');
79
+ } catch (error) {
80
+ console.error(error);
81
+ res.status(500).send({ error: error.message });
82
+ }
83
+
84
+ });
85
+
86
+ exports.default = router;
87
+
@@ -0,0 +1,113 @@
1
+ /*
2
+ * @Author: 殷亮辉 yinlianghui@hotoa.com
3
+ * @Date: 2025-05-27 14:51:49
4
+ * @LastEditors: 殷亮辉 yinlianghui@hotoa.com
5
+ * @LastEditTime: 2025-05-27 15:48:42
6
+ */
7
+ const { requireAuthentication } = require("@steedos/auth");
8
+ const { getSteedosSchema, getObject } = require("@steedos/objectql");
9
+ const express = require("express");
10
+ const router = express.Router();
11
+ const _ = require("lodash");
12
+
13
+ const util = {
14
+ /**
15
+ * Returns the object record Relative url
16
+ */
17
+ getObjectRecordRelativeUrl: (objectName, recordId, spaceId = null, options = {}) => {
18
+ let appId = '-';
19
+ if (options.appId) {
20
+ appId = options.appId;
21
+ }
22
+ let url = `/app/${appId}/${objectName}/view/${recordId}`;
23
+ if (objectName === "instances") {
24
+ url = `/api/workflow/instances/redirect/${recordId}`
25
+ }
26
+ return url;
27
+ }
28
+ }
29
+
30
+ router.get(
31
+ "/api/v4/notifications/:_id/read",
32
+ requireAuthentication,
33
+ async function (req, res) {
34
+ let { _id: record_id } = req.params;
35
+ let { rootUrl, appId } = req.query;
36
+ const userSession = req.user;
37
+ let req_async = _.has(req.query, 'async');
38
+ if (userSession.userId) {
39
+ let record = await getSteedosSchema().getObject("notifications").findOne(record_id, { fields: ['owner', 'is_read', 'related_to', 'space', 'url'] });
40
+ if (!record) {
41
+ // 跳转到通知记录界面会显示为404效果
42
+ let redirectUrl = util.getObjectRecordRelativeUrl("notifications", record_id);
43
+ if (req.get("X-Requested-With") === 'XMLHttpRequest') {
44
+ return res.status(200).send({
45
+ "status": 404,
46
+ "redirect": redirectUrl
47
+ });
48
+ } else {
49
+ return res.redirect(redirectUrl);
50
+ }
51
+ }
52
+ if (!record.related_to && !record.url) {
53
+ return res.status(401).send({
54
+ "error": "Validate Request -- Missing related_to or url",
55
+ "success": false
56
+ });
57
+ }
58
+ if (!record.is_read && record.owner === userSession.userId) {
59
+ // 没有权限时,只是不修改is_read值,但是允许跳转到相关记录查看
60
+ await getSteedosSchema().getObject('notifications').update(record_id, { 'is_read': true, modified: new Date() })
61
+ }
62
+ let redirectUrl = record.url ? record.url : util.getObjectRecordRelativeUrl(record.related_to.o, record.related_to.ids[0], record.space, {
63
+ rootUrl, appId
64
+ });
65
+ if (req_async) { // || req.get("X-Requested-With") === 'XMLHttpRequest'
66
+ return res.status(200).send({
67
+ "status": 200,
68
+ "redirect": redirectUrl
69
+ });
70
+ } else {
71
+ return res.redirect(redirectUrl);
72
+ }
73
+ }
74
+ return res.status(401).send({
75
+ "error": "Validate Request -- Missing X-Auth-Token",
76
+ "success": false
77
+ })
78
+ }
79
+ );
80
+
81
+ router.post(
82
+ "/api/v4/notifications/all/markReadAll",
83
+ requireAuthentication,
84
+ async function (req, res) {
85
+ let userSession = req.user;
86
+ let error;
87
+ let updatedCount = await getObject("notifications").directUpdateMany([
88
+ ["space", "=", userSession.spaceId],
89
+ ["owner", "=", userSession.userId],
90
+ [["is_read", "=", null], 'or', ["is_read", "=", false]]
91
+ ], {
92
+ is_read: true
93
+ }).catch((ex) => {
94
+ console.error(ex);
95
+ error = ex;
96
+ return 0;
97
+ });
98
+ if (error) {
99
+ res.status(500).send({
100
+ "error": error,
101
+ "success": false
102
+ });
103
+ }
104
+ else {
105
+ return res.send({
106
+ markedCount: updatedCount,
107
+ "success": true
108
+ });
109
+ }
110
+ }
111
+ );
112
+
113
+ exports.default = router;
@@ -1,10 +1,3 @@
1
- <!--
2
- * @Author: baozhoutao@steedos.com
3
- * @Date: 2022-06-02 17:45:15
4
- * @LastEditors: baozhoutao@steedos.com
5
- * @LastEditTime: 2024-10-17 12:02:21
6
- * @Description:
7
- -->
8
1
  <html>
9
2
  <head>
10
3
  <script src="/unpkg.com/@steedos-builder/fiddle@0.0.5/dist/builder-fiddle.umd.js"></script>
@@ -14,6 +7,11 @@
14
7
  <link href="/toast/toastr.min.css" rel="stylesheet" />
15
8
  <script src="/jquery.min.js" ></script>
16
9
  <script src="/toast/toastr.min.js"></script>
10
+ <script>
11
+ window._disabledFields = [
12
+ 'table'
13
+ ]
14
+ </script>
17
15
  <style>
18
16
  #toast-container.toast-bottom-center>div, #toast-container.toast-top-center>div {
19
17
  width: 450px;
@@ -115,6 +113,12 @@
115
113
  tenantId,
116
114
  authToken,
117
115
  },
116
+ global: {
117
+ userId: userId,
118
+ spaceId: tenantId,
119
+ user: <%- JSON.stringify(userSession) %>,
120
+ now: new Date(),
121
+ }
118
122
  },
119
123
  };
120
124
 
@@ -150,7 +154,12 @@
150
154
  schema.data.context.userId = userId;
151
155
  schema.data.context.authToken = authToken;
152
156
  schema.data.context.user = <%- JSON.stringify(userSession) %>;
153
-
157
+ schema.data.global = {
158
+ userId: userId,
159
+ spaceId: tenantId,
160
+ user: <%- JSON.stringify(userSession) %>,
161
+ now: new Date(),
162
+ }
154
163
  // if (objectName && pageType === "record") {
155
164
  // const record = await axios.get(
156
165
  // `${rootUrl}/api/v4/${objectName}?$orderby=modified&$top=1`,
@@ -185,11 +194,13 @@
185
194
  );
186
195
  if (schema.data && typeof schema.data.context === 'object' ) {
187
196
  delete schema.data.context
197
+ delete schema.data.global
188
198
  }
189
199
 
190
200
  try {
191
201
  delete schema.data.recordId;
192
202
  delete schema.data.objectName;
203
+ delete schema.data.global
193
204
  } catch (error) {
194
205
 
195
206
  }
@@ -76,7 +76,8 @@ module.exports = {
76
76
 
77
77
  return obj;
78
78
  } catch (error) {
79
- console.log(error)
79
+ console.log(error);
80
+ throw error
80
81
  }
81
82
  }
82
83
  },
@@ -0,0 +1,190 @@
1
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
2
+ const _ = require("lodash");
3
+ const objectql = require('@steedos/objectql');
4
+
5
+ module.exports = {
6
+ name: 'notifications',
7
+ namespace: "steedos",
8
+ mixins: [],
9
+ /**
10
+ * Settings
11
+ */
12
+ settings: {
13
+
14
+ },
15
+
16
+ /**
17
+ * Dependencies
18
+ */
19
+ dependencies: [],
20
+
21
+ /**
22
+ * Actions
23
+ */
24
+ actions: {
25
+ /**
26
+ * @api {post} add 发送通知
27
+ * @apiName add
28
+ * @apiGroup notifications.service.js
29
+ * @apiParam {Object} message 消息主体
30
+ * @apiParam {String} message[name] 消息标题
31
+ * @apiParam {String} message[body] 消息内容
32
+ * @apiParam {String} message[related_to] 关联记录
33
+ * @apiParam {String} message[related_name] 关联名称
34
+ * @apiParam {String} message[from] 发送者ID,选填
35
+ * @apiParam {String} message[space] 工作区ID
36
+ * @apiParam {String} from 发送者ID
37
+ * @apiParam {String[]} to 接受者ID
38
+ */
39
+ add: {
40
+ params: {
41
+ message: {
42
+ type: "object",
43
+ props: {
44
+ name: { type: "string" },
45
+ body: { type: "string" },
46
+ related_to: {
47
+ type: "object",
48
+ props: {
49
+ o: { type: "string" },
50
+ ids: { type: "array", items: "string" },
51
+ }
52
+ },
53
+ related_name: { type: "string", optional: true },
54
+ from: { type: "string", optional: true },
55
+ space: { type: "string" },
56
+ }
57
+ },
58
+ from: { type: "string" },
59
+ to: {
60
+ type: "multi",
61
+ rules: [
62
+ { type: "string" },
63
+ { type: "array", items: "string" }
64
+ ]
65
+ },
66
+ },
67
+ async handler(ctx) {
68
+ let { from, to, message } = ctx.params;
69
+ this.broker.emit('notifications.add', {from, to, message})
70
+
71
+
72
+ let notifications_ids = [];
73
+ if(!_.isArray(to) && _.isString(to)){
74
+ to = [to]
75
+ }
76
+
77
+ if (_.isEmpty(to)) {
78
+ return
79
+ }
80
+ let now = new Date();
81
+ const datasource = objectql.getDataSource('default');
82
+ const adapter = datasource.adapter
83
+ await adapter.connect()
84
+ const collection = adapter.collection('notifications');
85
+ let bulk = collection.initializeUnorderedBulkOp();
86
+
87
+ let doc = Object.assign({
88
+ created: now,
89
+ modified: now,
90
+ created_by: from,
91
+ modified_by: from
92
+ }, message)
93
+
94
+ for (const userId of to) {
95
+ let notifications_id = await objectql.getObject('notifications')._makeNewID();
96
+ bulk.insert(Object.assign({}, doc, {_id: notifications_id, owner: userId}));
97
+ notifications_ids.push(notifications_id)
98
+ }
99
+
100
+ bulk.execute().catch(function (error) {
101
+ console.error("通知数据插入失败,错误信息:", error);
102
+ });
103
+
104
+ try {
105
+ this.broker.emit(`notifications.hasBeenSent`, {
106
+ ids: notifications_ids
107
+ });
108
+ await ctx.broker.call('b6-microservice.broadcast', {name: '$notification.users', data: {tenantId: message.space, users: to, message: {name: message.name, body: message.body}}})
109
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
110
+ } catch (e) { console.log(e) }
111
+ }
112
+ },
113
+ /**
114
+ * @api {post} remove 删除通知
115
+ * @apiName remove
116
+ * @apiGroup notifications.service.js
117
+ * @apiParam {Object} doc 消息主体
118
+ * @apiParam {String} doc[_id] 消息ID
119
+ * @apiParam {String[]} assignees 接受者ID
120
+ * @apiParam {String} objectName 关联对象名称
121
+ */
122
+ remove: {
123
+ params: {
124
+ doc: {
125
+ type: "object",
126
+ props: {
127
+ _id: { type: "string" },
128
+ }
129
+ },
130
+ assignees: {
131
+ type: "array", items: "string"
132
+ },
133
+ objectName: { type: "string" },
134
+ },
135
+ async handler(ctx) {
136
+ const { doc, assignees, objectName } = ctx.params;
137
+ const datasource = objectql.getDataSource('default');
138
+ const adapter = datasource.adapter
139
+ await adapter.connect()
140
+ const collection = adapter.collection('notifications');
141
+ let bulk = collection.initializeUnorderedBulkOp();
142
+ assignees.forEach(function (assignee) {
143
+ bulk.find({
144
+ "related_to.o": objectName,
145
+ "related_to.ids": doc._id,
146
+ owner: assignee
147
+ }).remove();
148
+ });
149
+ return bulk.execute().catch(function (error) {
150
+ console.error("通知数据删除失败,错误信息:", error);
151
+ });
152
+ }
153
+ },
154
+ },
155
+
156
+ /**
157
+ * Events
158
+ */
159
+ events: {
160
+
161
+ },
162
+
163
+ /**
164
+ * Methods
165
+ */
166
+ methods: {
167
+
168
+ },
169
+
170
+ /**
171
+ * Service created lifecycle event handler
172
+ */
173
+ created() {
174
+
175
+ },
176
+
177
+ /**
178
+ * Service started lifecycle event handler
179
+ */
180
+ async started() {
181
+ this.broker.logger.info('[service][notifications]===>', 'started')
182
+ },
183
+
184
+ /**
185
+ * Service stopped lifecycle event handler
186
+ */
187
+ async stopped() {
188
+
189
+ }
190
+ };