@steedos/standard-object-database 2.7.0 → 2.7.1-beta.10

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 (35) hide show
  1. package/main/default/objectTranslations/object_webhooks.en/object_webhooks.en.objectTranslation.yml +46 -0
  2. package/main/default/objectTranslations/object_webhooks.zh-CN/object_webhooks.zh-CN.objectTranslation.yml +48 -0
  3. package/main/default/objectTranslations/objects.en/objects.en.objectTranslation.yml +4 -0
  4. package/main/default/objectTranslations/objects.zh-CN/objects.zh-CN.objectTranslation.yml +4 -0
  5. package/main/default/objects/object_fields/fields/auto_fill_mapping.$.from.field.yml +8 -6
  6. package/main/default/objects/object_fields/fields/auto_fill_mapping.$.to.field.yml +13 -0
  7. package/main/default/objects/object_fields/fields/auto_fill_mapping.field.yml +1 -1
  8. package/main/default/objects/object_fields/fields/is_name.field.yml +1 -0
  9. package/main/default/objects/object_fields/fields/sortable.field.yml +0 -1
  10. package/main/default/objects/object_webhooks/fields/active.field.yml +5 -0
  11. package/main/default/objects/object_webhooks/fields/condition.field.yml +6 -0
  12. package/main/default/objects/object_webhooks/fields/content_type.field.yml +5 -0
  13. package/main/default/objects/object_webhooks/fields/event.field.yml +15 -0
  14. package/main/default/objects/object_webhooks/fields/execute_when.field.yml +12 -0
  15. package/main/default/objects/object_webhooks/fields/fields.field.yml +28 -0
  16. package/main/default/objects/object_webhooks/fields/name.field.yml +5 -0
  17. package/main/default/objects/object_webhooks/fields/object_name.field.yml +8 -0
  18. package/main/default/objects/object_webhooks/fields/payload_url.field.yml +7 -0
  19. package/main/default/objects/object_webhooks/listviews/all.listview.yml +9 -0
  20. package/main/default/objects/object_webhooks/object_webhooks.object.yml +5 -0
  21. package/main/default/objects/object_webhooks/permissions/admin.permission.yml +7 -0
  22. package/main/default/objects/object_webhooks/permissions/user.permission.yml +7 -0
  23. package/main/default/objects/objects/fields/enable_form_tabs.field.yml +6 -0
  24. package/main/default/pages/design_field_layout.page.amis.json +285 -215
  25. package/main/default/pages/object_fields_form.page.amis.json +38 -10
  26. package/main/default/pages/object_webhooks_form.page.amis.json +51 -0
  27. package/main/default/pages/object_webhooks_form.page.yml +12 -0
  28. package/main/default/server/object_fields.object.js +4 -2
  29. package/main/default/services/object_webhooks.service.js +141 -0
  30. package/main/default/triggers/datasources.trigger.js +4 -2
  31. package/main/default/triggers/object_actions.trigger.js +6 -4
  32. package/main/default/triggers/object_fields.trigger.js +3 -25
  33. package/main/default/triggers/object_validation_rules.trigger.js +4 -5
  34. package/package.json +8 -4
  35. package/package.service.js +3 -2
@@ -143,15 +143,18 @@
143
143
  "amis": {
144
144
  "onEvent": {
145
145
  "change": {
146
- "actions": [{
147
- "actionType": "setValue",
148
- "args": {
149
- "value": {
150
- "defaultValue": null
151
- }
152
- },
153
- "componentId": "steedos_object_fields_form"
154
- }]
146
+ "actions": [
147
+ {
148
+ "actionType": "setValue",
149
+ "args": {
150
+ "value": {
151
+ "defaultValue": null,
152
+ "sortable": "${ARRAYSOME(allowSort, item => item === event.data.value)}"
153
+ }
154
+ },
155
+ "componentId": "steedos_object_fields_form"
156
+ }
157
+ ]
155
158
  }
156
159
  },
157
160
  "disabledOn": "${is_system == true}",
@@ -197,8 +200,33 @@
197
200
  "tabsMode": "line"
198
201
  }],
199
202
  "data": {
200
- "context": {}
203
+ "context": {},
204
+ "allowSort": [
205
+ "text",
206
+ "select",
207
+ "date",
208
+ "datetime",
209
+ "time",
210
+ "number",
211
+ "currency",
212
+ "percent",
213
+ "autoumber",
214
+ "summary",
215
+ "formula"
216
+ ]
217
+ },
218
+ "onEvent": {
219
+ "init": {
220
+ "weight": 0,
221
+ "actions": [
222
+ {
223
+ "actionType": "custom",
224
+ "script": "//初始化时给外层dialog加上类名,使过滤组件popover正常显示\n$('.steedos-object-fields-form-page').closest('.amis-dialog-widget.antd-Modal').addClass('steedos-overflow-visible-dialog');"
225
+ }
226
+ ]
227
+ }
201
228
  },
202
229
  "name": "object_fields_form",
230
+ "className": "steedos-object-fields-form-page",
203
231
  "id": "steedos_object_fields_service"
204
232
  }
@@ -0,0 +1,51 @@
1
+ {
2
+ "type": "service",
3
+ "body": [{
4
+ "type": "steedos-object-form",
5
+ "label": "Object Webhook",
6
+ "objectApiName": "object_webhooks",
7
+ "recordId": "${recordId}",
8
+ "mode": "edit",
9
+ "layout": "horizontal",
10
+
11
+ "fieldsExtend": {
12
+ "condition": {
13
+ "amis": {
14
+ "type": "service",
15
+ "schemaApi": {
16
+ "method": "get",
17
+ "url": "/service/api/amis-metadata-objects/objects/${object_name}/fields/options",
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;",
20
+ "trackExpression": "${object_name}",
21
+ "sendOn": "${object_name}"
22
+ }
23
+ }
24
+ },
25
+ "execute_when":{
26
+ "amis": {
27
+ "type": "radios",
28
+ "inline": false
29
+ }
30
+ },
31
+ "event": {
32
+ "amis":{
33
+ "type": "radios",
34
+ "inline": false
35
+ }
36
+ }
37
+ },
38
+ "form": {
39
+ "id": "steedos_object_webhooks_form"
40
+ },
41
+ "id": "u:e17c57cce896",
42
+ "tabsMode": "line"
43
+ }],
44
+ "data": {
45
+ "context": {},
46
+ "visibleOnVariables": "",
47
+ "defaultValueVariables": ""
48
+ },
49
+ "name": "object_webhooks_form",
50
+ "id": "steedos_object_webhooks_service"
51
+ }
@@ -0,0 +1,12 @@
1
+ name: object_webhooks_form
2
+ is_active: true
3
+ label: 对象字段表单
4
+ object_name: object_webhooks
5
+ pageAssignments:
6
+ - type: orgDefault
7
+ page: object_webhooks_form
8
+ desktop: true
9
+ mobile: true
10
+ render_engine: amis
11
+ type: form
12
+ widgets: []
@@ -299,8 +299,10 @@ function allowChangeObject(){
299
299
  }
300
300
 
301
301
  function checkNameField(nameField){
302
- if(["text", "textarea", "autonumber", "date", "datetime", "time", "formula"].indexOf(nameField.type) < 0){
303
- throw new Error("只有文本、长文本、自动编号、日期、日期时间、时间、公式这些类型的字段可以被设置为名称字段");
302
+ if(["text", "textarea", "autonumber", "date", "datetime", "time", "formula", "lookup"].indexOf(nameField.type) < 0){
303
+ throw new Error("只有文本、长文本、自动编号、日期、日期时间、时间、公式、相关表这些类型的字段可以被设置为名称字段");
304
+ } else if(nameField.type == "lookup" && nameField.multiple) {
305
+ throw new Error("多选的相关表字段不可以被设置为名称字段");
304
306
  }
305
307
  }
306
308
 
@@ -0,0 +1,141 @@
1
+ /*
2
+ * @Author: baozhoutao@steedos.com
3
+ * @Date: 2024-04-23 14:35:03
4
+ * @LastEditors: baozhoutao@steedos.com
5
+ * @LastEditTime: 2024-05-06 11:45:46
6
+ * @Description:
7
+ */
8
+
9
+ const BullMqMixin = require('moleculer-bullmq');
10
+ const axios = require('axios');
11
+ const { evaluate } = require("amis-formula")
12
+ const serviceObjectMixin = require('@steedos/service-object-mixin');
13
+
14
+ module.exports = {
15
+ name: "object_webhooks",
16
+ mixins: [serviceObjectMixin, BullMqMixin],
17
+ settings: {
18
+ bullmq: {
19
+ client: process.env.QUEUE_BACKEND,
20
+ worker: { concurrency: 50 }
21
+ }
22
+ },
23
+ events: {
24
+ "*.inserted": async function(ctx){
25
+ const { objectApiName, id, spaceId, userId } = ctx.params;
26
+ if(ctx.eventName != `@${objectApiName}.inserted`){
27
+ return
28
+ }
29
+ if(objectApiName && id && spaceId){
30
+ await this.addQueue(ctx, objectApiName, "create", id, spaceId, userId)
31
+ }
32
+ },
33
+ "*.updated": async function(ctx){
34
+ const { objectApiName, id, spaceId, userId, previousDoc } = ctx.params;
35
+ if(ctx.eventName != `@${objectApiName}.updated`){
36
+ return
37
+ }
38
+ if(objectApiName && id && spaceId){
39
+ await this.addQueue(ctx, objectApiName, "update", id, spaceId, userId, previousDoc)
40
+ }
41
+ },
42
+ "*.deleted": async function(ctx){
43
+ const { objectApiName, id, spaceId, userId, previousDoc } = ctx.params;
44
+ if(ctx.eventName != `@${objectApiName}.deleted`){
45
+ return
46
+ }
47
+ if(objectApiName && id){
48
+ await this.addQueue(ctx, objectApiName, "delete", id, spaceId, userId, previousDoc)
49
+ }
50
+ }
51
+ },
52
+ actions: {
53
+ send: {
54
+ queue: true,
55
+ async handler(ctx) {
56
+ const { url, data } = ctx.params
57
+ const result = await axios.post(url, data);
58
+ ctx.locals.job.updateProgress(100)
59
+ return result.data;
60
+ }
61
+ }
62
+ },
63
+ methods: {
64
+
65
+ async addQueue(ctx, objectName, actionName, recordId, spaceId, userId, previousDoc){
66
+ const hooks = await this.getObjectWebhooks(objectName, spaceId)
67
+ if(hooks.length === 0) return
68
+
69
+ let newDoc;
70
+ if(recordId && (actionName === 'update' || actionName === 'create')){
71
+ newDoc = await this.getObject(objectName).findOne(recordId)
72
+ }
73
+ let sender;
74
+ let space;
75
+ if(userId && spaceId){
76
+ const userSession = await ctx.call('@steedos/service-accounts.getUserSession', {userId, spaceId})
77
+ if(userSession){
78
+ sender = {
79
+ _id: userSession.userId,
80
+ username: userSession.username,
81
+ name: userSession.name,
82
+ email: userSession.email
83
+ }
84
+
85
+ space = {
86
+ _id: userSession.space._id,
87
+ name: userSession.space.name
88
+ }
89
+ }
90
+ }
91
+
92
+ for (const hook of hooks) {
93
+
94
+ if(hook.event != 'createAndUpdate' && hook.event != actionName){
95
+ continue;
96
+ }
97
+
98
+ if(hook.event == 'createAndUpdate' && actionName != 'create' && actionName != 'update'){
99
+ continue;
100
+ }
101
+
102
+ const { execute_when, condition } = hook;
103
+
104
+ if(hook.event == 'createAndUpdate' && actionName == 'create' && execute_when == 'trueOnChangeOnly'){
105
+ continue;
106
+ }
107
+
108
+ if(condition){
109
+
110
+ if(actionName == 'update' && execute_when === 'trueOnChangeOnly'){
111
+ const oldResult = evaluate(condition, previousDoc);
112
+ if(oldResult){
113
+ continue;
114
+ }
115
+ }
116
+
117
+ const result = evaluate(condition, newDoc);
118
+ if(!result){
119
+ continue;
120
+ }
121
+ }
122
+ let data = newDoc || previousDoc;
123
+ if(hook.fields && hook.fields.length > 0){
124
+ data = _.map(data, hook.fields)
125
+ }
126
+ await this.queue(ctx, 'object_webhooks', 'send', { url: hook.payload_url, data: {
127
+ action: actionName,
128
+ object_name: objectName,
129
+ doc: data,
130
+ sender: sender,
131
+ space: space
132
+ }, space: spaceId, user: userId }, { priority: 10 })
133
+ }
134
+ },
135
+ async getObjectWebhooks(objectName, spaceId){
136
+ const SERVICE_NAME = 'metadata-cachers-service'
137
+ const hooks = await global.broker.call(`${SERVICE_NAME}.find`, {metadataName: 'object_webhooks', filters: ['object_name', '=', objectName], spaceId});
138
+ return hooks;
139
+ }
140
+ }
141
+ }
@@ -7,6 +7,7 @@ const InternalData = require('@steedos/standard-objects').internalData;
7
7
  const objectql = require('@steedos/objectql');
8
8
  const auth = require('@steedos/auth');
9
9
  const _ = require('underscore');
10
+ const clone = require('clone');
10
11
  //由于新版lookup 组件限制。需编写trigger处理在只读页面不显示已选中项的问题
11
12
  //由于lookup组件强依赖_id 字段,所以必须返回_id
12
13
 
@@ -35,14 +36,15 @@ module.exports = {
35
36
  dataList.push({_id: 'meteor', name: 'meteor', label: TAPi18n.__(`objects_field_datasource_meteor`, {}, lng), ...BASERECORD})
36
37
  }
37
38
  if (!_.isEmpty(dataList)) {
39
+ const cloneValues = clone(this.data.values, false);
38
40
  dataList.forEach((doc) => {
39
41
  if (!_.find(this.data.values, (value) => {
40
42
  return value.name === doc.name
41
43
  })) {
42
- this.data.values.push(doc);
44
+ cloneValues.push(doc);
43
45
  }
44
46
  })
45
- const records = objectql.getSteedosSchema().metadataDriver.find(this.data.values, this.query, spaceId);
47
+ const records = objectql.getSteedosSchema().metadataDriver.find(cloneValues, this.query, spaceId);
46
48
  if (records.length > 0) {
47
49
  this.data.values = records;
48
50
  } else {
@@ -1,13 +1,14 @@
1
1
  /*
2
2
  * @Author: sunhaolin@hotoa.com
3
3
  * @Date: 2022-05-28 11:07:57
4
- * @LastEditors: baozhoutao@steedos.com
5
- * @LastEditTime: 2024-03-20 16:00:17
4
+ * @LastEditors: 孙浩林 sunhaolin@steedos.com
5
+ * @LastEditTime: 2024-05-11 13:57:23
6
6
  * @Description:
7
7
  */
8
8
  const InternalData = require('@steedos/standard-objects').internalData;
9
9
  const objectql = require('@steedos/objectql');
10
10
  const auth = require("@steedos/auth");
11
+ const clone = require('clone');
11
12
  const sleep = async (ms) => new Promise(resolve => setTimeout(resolve, ms));
12
13
  module.exports = {
13
14
  beforeInsert: async function(){
@@ -35,14 +36,15 @@ module.exports = {
35
36
  if(objectName){
36
37
  let dataList = await InternalData.getObjectActions(objectName, this.userId);
37
38
  if (!_.isEmpty(dataList)) {
39
+ const cloneValues = clone(this.data.values, false);
38
40
  dataList.forEach((doc) => {
39
41
  if (!_.find(this.data.values, (value) => {
40
42
  return value.name === doc.name
41
43
  })) {
42
- this.data.values.push(Object.assign({_id: `${objectName}.${doc.name}`}, doc));
44
+ cloneValues.push(Object.assign({_id: `${objectName}.${doc.name}`}, doc));
43
45
  }
44
46
  })
45
- const records = objectql.getSteedosSchema().metadataDriver.find(this.data.values, this.query, spaceId);
47
+ const records = objectql.getSteedosSchema().metadataDriver.find(cloneValues, this.query, spaceId);
46
48
  if (records.length > 0) {
47
49
  this.data.values = records;
48
50
  } else {
@@ -231,15 +231,16 @@ module.exports = {
231
231
  if(objectName){
232
232
  let fields = await InternalData.getObjectFields(objectName, this.userId, filters.name ? true : false);
233
233
  if(fields){
234
+ const cloneValues = clone(this.data.values, false);
234
235
  _.each(fields, (field)=>{
235
236
  if(!_.find(this.data.values, (item)=>{
236
237
  return item.object == field.object && item.name == field.name
237
238
  })){
238
- this.data.values.push(Object.assign({_id: `${objectName}.${field.name}`}, field))
239
+ cloneValues.push(Object.assign({_id: `${objectName}.${field.name}`}, field))
239
240
  }
240
241
  })
241
242
  // this.data.values = this.data.values.concat(fields)
242
- this.data.values = objectql.getSteedosSchema().metadataDriver.find(this.data.values, this.query, this.spaceId);
243
+ this.data.values = objectql.getSteedosSchema().metadataDriver.find(cloneValues, this.query, this.spaceId);
243
244
  }
244
245
  }
245
246
 
@@ -282,29 +283,6 @@ module.exports = {
282
283
  }
283
284
 
284
285
 
285
- },
286
- beforeAggregate: async function(){
287
- const { query } = this;
288
- if(query.fields && _.isArray(query.fields) && !_.include(query.fields, 'object')){
289
- query.fields.push('object')
290
- }
291
- },
292
- afterAggregate: async function(){
293
- let filters = InternalData.parserFilters(this.query.filters);
294
- let objectName = filters.object;
295
- if(!objectName && filters._id && filters._id.indexOf(".") > -1){
296
- objectName = filters._id.split('.')[0];
297
- }
298
- if(objectName){
299
- let fields = await InternalData.getObjectFields(objectName, this.userId, true);
300
- if(fields){
301
- _.each(fields, (field)=>{
302
- this.data.values.push(Object.assign({_id: `${objectName}.${field.name}`}, field))
303
- })
304
- // this.data.values = this.data.values.concat(fields)
305
- this.data.values = objectql.getSteedosSchema().metadataDriver.find(this.data.values, this.query, this.spaceId);
306
- }
307
- }
308
286
  },
309
287
  afterCount: async function(){
310
288
  let result = await objectql.getObject('object_fields').find(this.query, await auth.getSessionByUserId(this.userId, this.spaceId))
@@ -8,26 +8,25 @@ const util = require('@steedos/standard-objects').util;
8
8
  const objectql = require("@steedos/objectql");
9
9
  const register = require('@steedos/metadata-registrar')
10
10
  const auth = require('@steedos/auth');
11
+ const clone = require('clone');
11
12
 
12
13
  module.exports = {
13
14
  beforeFind: async function(){
14
15
  delete this.query.fields;
15
16
  },
16
- beforeAggregate: async function(){
17
- delete this.query.fields;
18
- },
19
17
  afterFind: async function(){
20
18
  const { spaceId } = this;
21
19
  let dataList = await register.getAllObjectValidationRules();
22
20
  if (!_.isEmpty(dataList)) {
21
+ const cloneValues = clone(this.data.values, false);
23
22
  dataList.forEach((doc) => {
24
23
  if (!_.find(this.data.values, (value) => {
25
24
  return value.name === doc.name
26
25
  })) {
27
- this.data.values.push(doc);
26
+ cloneValues.push(doc);
28
27
  }
29
28
  })
30
- const records = objectql.getSteedosSchema().metadataDriver.find(this.data.values, this.query, spaceId);
29
+ const records = objectql.getSteedosSchema().metadataDriver.find(cloneValues, this.query, spaceId);
31
30
  if (records.length > 0) {
32
31
  this.data.values = records;
33
32
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steedos/standard-object-database",
3
- "version": "2.7.0",
3
+ "version": "2.7.1-beta.10",
4
4
  "main": "package.service.js",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -12,10 +12,14 @@
12
12
  "description": "steedos package",
13
13
  "dependencies": {
14
14
  "@steedos-widgets/amis-lib": "^1.0.22",
15
- "@steedos/metadata-core": "2.7.0",
16
- "@steedos/standard-objects": "2.7.0"
15
+ "@steedos/metadata-core": "2.7.1-beta.10",
16
+ "@steedos/service-object-mixin": "2.7.1-beta.10",
17
+ "@steedos/standard-objects": "2.7.1-beta.10",
18
+ "amis-formula": "~6.3.0",
19
+ "clone": "^2.1.2",
20
+ "moleculer-bullmq": "3.0.0"
17
21
  },
18
22
  "repository": {},
19
23
  "license": "MIT",
20
- "gitHead": "2f1586ea4f8af5b93753878e96f1f48adbef31a7"
24
+ "gitHead": "ebcec3b98499655769a965cf548456f280f0df18"
21
25
  }
@@ -166,8 +166,9 @@ module.exports = {
166
166
  const dbRecord = await object.directFind({filters: ['_id','=',id]});
167
167
  if(dbRecord.length === 0){
168
168
  // const newId = await object._makeNewID();
169
- const objectConfig = await object.toConfig();
170
- let field_groups = objectConfig.field_groups || null;
169
+ const curentObject = await this.getObject(name);
170
+ const curentObjectConfig = await curentObject.toConfig();
171
+ let field_groups = curentObjectConfig.field_groups || null;
171
172
 
172
173
  const now = new Date();
173
174
  await object.directInsert(Object.assign({}, data, {