@steedos/service-object-graphql 3.0.0-beta.2 → 3.0.0-beta.8

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.
@@ -1,836 +1,998 @@
1
1
  import _ = require("underscore");
2
- import { translationObject } from '@steedos/i18n';
3
- import moment = require('moment');
4
- import { getSteedosSchema, SteedosObjectTypeConfig, getUserLocale, absoluteUrl } from "@steedos/objectql";
5
- import { EXPAND_SUFFIX, DISPLAY_PREFIX, RELATED_PREFIX, GRAPHQL_ACTION_PREFIX, UI_PREFIX, PERMISSIONS_PREFIX, QUERY_DOCS_TOP } from "./consts";
2
+ import { translationObject } from "@steedos/i18n";
3
+ import moment = require("moment");
4
+ import {
5
+ getSteedosSchema,
6
+ SteedosObjectTypeConfig,
7
+ getUserLocale,
8
+ absoluteUrl,
9
+ } from "@steedos/objectql";
10
+ import {
11
+ EXPAND_SUFFIX,
12
+ DISPLAY_PREFIX,
13
+ RELATED_PREFIX,
14
+ GRAPHQL_ACTION_PREFIX,
15
+ UI_PREFIX,
16
+ PERMISSIONS_PREFIX,
17
+ QUERY_DOCS_TOP,
18
+ } from "./consts";
6
19
  import { getQueryFields } from "./getQueryFields";
7
20
  import {
8
- callObjectServiceAction,
9
- _getRelatedType,
10
- formatBasicFieldValue,
11
- formatFileSize,
12
- numberToString,
13
- getFileStorageName
14
- } from "./utils"
15
- import { sortBy, each, find } from 'lodash'
21
+ callObjectServiceAction,
22
+ _getRelatedType,
23
+ formatBasicFieldValue,
24
+ formatFileSize,
25
+ numberToString,
26
+ getFileStorageName,
27
+ } from "./utils";
28
+ import { sortBy, each, find } from "lodash";
16
29
  // import { LRUMap } from 'lru_map';
17
30
 
18
- export function getGraphqlActions(
19
- // objectConfig: SteedosObjectTypeConfig
31
+ export function getGraphqlActions() {
32
+ // objectConfig: SteedosObjectTypeConfig
33
+ let actions = {};
34
+ // let objName = objectConfig.name;
35
+
36
+ // actions[`${GRAPHQL_ACTION_PREFIX}${EXPAND_SUFFIX}_multiple`] = {
37
+ // handler: async function (ctx) {
38
+ // let { ids, objectName, referenceToField } = ctx.params;
39
+ // if (_.isEmpty(ids)) {
40
+ // return null;
41
+ // }
42
+ // let filters = [[referenceToField || "_id", "in", ids]];
43
+ // const selector: any = { filters: filters };
44
+ // let steedosSchema = getSteedosSchema();
45
+ // let obj = steedosSchema.getObject(objectName);
46
+
47
+ // const { resolveInfo } = ctx.meta;
48
+ // const fieldNames = getQueryFields(resolveInfo);
49
+ // if (!_.isEmpty(fieldNames)) {
50
+ // selector.fields = fieldNames;
51
+ // }
52
+
53
+ // return obj.find(selector);
54
+ // },
55
+ // };
56
+ actions[`${GRAPHQL_ACTION_PREFIX}${EXPAND_SUFFIX}`] = {
57
+ // params:{
58
+ // graphql: { dataLoaderOptions: { cacheMap: new LRUMap(1000) } },
59
+ // },
60
+ handler: async function (ctx) {
61
+ // console.log(`${GRAPHQL_ACTION_PREFIX}${EXPAND_SUFFIX} params`, ctx.params)
62
+ let { id, objectName, referenceToField } = ctx.params;
63
+ if (!id) {
64
+ return;
65
+ }
66
+ let steedosSchema = getSteedosSchema();
67
+ let obj = steedosSchema.getObject(objectName);
68
+ if (_.isString(id)) {
69
+ id = [id];
70
+ }
71
+ const selector: any = {
72
+ filters: [[referenceToField || "_id", "in", id]],
73
+ };
74
+ const spaceId = ctx.meta.spaceId || ctx.meta.user?.spaceId;
75
+ if (
76
+ referenceToField &&
77
+ referenceToField != "_id" &&
78
+ objectName != "users" &&
79
+ objectName != "spaces" &&
80
+ spaceId
81
+ ) {
82
+ selector.filters.push(["space", "=", spaceId]);
83
+ }
84
+ // const { resolveInfo } = ctx.meta;
85
+ // const fieldNames = getQueryFields(resolveInfo);
86
+ // if (!_.isEmpty(fieldNames)) {
87
+ // selector.fields = fieldNames;
88
+ // }
89
+
90
+ // return (await obj.find(selector))[0];
91
+ delete selector.fields;
92
+ const result = await obj.find(selector);
93
+
94
+ if (id.length > result.length) {
95
+ // const count = id.length - result.length;
96
+ // for (let index = 0; index < count; index++) {
97
+ // result.push({})
98
+ // }
99
+ each(id, (_id) => {
100
+ if (
101
+ !find(result, (doc) => {
102
+ return doc[referenceToField || "_id"] === _id;
103
+ })
104
+ ) {
105
+ result.push({ [referenceToField || "_id"]: _id });
106
+ }
107
+ });
108
+ }
109
+ // console.log(`result=====>`, JSON.stringify(selector), result)
110
+ if (_.isString(ctx.params.id)) {
111
+ return result[0];
112
+ }
113
+
114
+ // 使用 id 对象查询的结果result进行排序. 否则会导致dataloader缓存key与结果不匹配
115
+ return sortBy(result, (doc) => {
116
+ return id.indexOf(doc[referenceToField || "_id"]);
117
+ });
118
+ },
119
+ };
120
+
121
+ // if (
122
+ // [
123
+ // "cms_files",
124
+ // "tasks",
125
+ // "notes",
126
+ // "events",
127
+ // "audit_records",
128
+ // "instances",
129
+ // "approvals",
130
+ // ].includes(objName)
131
+ // ) {
132
+ actions[`${GRAPHQL_ACTION_PREFIX}${RELATED_PREFIX}_enabled`] = {
133
+ handler: async function (ctx) {
134
+ let params = ctx.params;
135
+ let { _parentId, _related_params } = params;
136
+ let { objectName, parentObjectName, foreignKey } = _related_params;
137
+ let userSession = ctx.meta.user;
138
+ let steedosSchema = getSteedosSchema();
139
+ let object = steedosSchema.getObject(objectName);
140
+ let filters = [];
141
+ filters = [
142
+ [`${foreignKey}.o`, "=", parentObjectName],
143
+ [`${foreignKey}.ids`, "=", _parentId],
144
+ ];
145
+ if (params.filters) {
146
+ filters.push(params.filters);
147
+ }
148
+ params.filters = filters;
149
+ return await object.find(params, userSession);
150
+ },
151
+ };
152
+ // }
153
+
154
+ actions[`${GRAPHQL_ACTION_PREFIX}${RELATED_PREFIX}`] = {
155
+ params: {
156
+ fields: { type: "array", items: "string", optional: true },
157
+ filters: [
158
+ { type: "array", optional: true },
159
+ { type: "string", optional: true },
160
+ ],
161
+ top: { type: "number", optional: true, default: QUERY_DOCS_TOP },
162
+ skip: { type: "number", optional: true },
163
+ sort: { type: "string", optional: true },
164
+ _parentId: { type: "string", optional: false },
165
+ _related_params: {
166
+ type: "object",
167
+ props: {
168
+ objectName: { type: "string", optional: false },
169
+ parentObjectName: { type: "string", optional: false },
170
+ fieldName: { type: "string", optional: false },
171
+ referenceToParentFieldName: { type: "string", optional: true },
172
+ },
173
+ },
174
+ },
175
+ handler: async function (ctx) {
176
+ let params = ctx.params;
177
+ let { _parentId, _related_params } = params;
178
+ let {
179
+ objectName,
180
+ parentObjectName,
181
+ fieldName,
182
+ referenceToParentFieldName,
183
+ } = _related_params;
184
+ let userSession = ctx.meta.user;
185
+ let steedosSchema = getSteedosSchema();
186
+ let object = steedosSchema.getObject(objectName);
187
+ let parentObj = steedosSchema.getObject(parentObjectName);
188
+ let parent = await parentObj.findOne(_parentId);
189
+ // 防止万一parent为空
190
+ if (!parent) {
191
+ return [];
192
+ }
193
+ let filters = [];
194
+ let _idValue = parent._id;
195
+ if (referenceToParentFieldName) {
196
+ _idValue = parent[referenceToParentFieldName];
197
+ }
198
+ filters = [[fieldName, "=", _idValue]];
199
+ if (params.filters) {
200
+ filters.push(params.filters);
201
+ }
202
+ params.filters = filters;
203
+
204
+ const { resolveInfo } = ctx.meta;
205
+ const fieldNames = getQueryFields(resolveInfo);
206
+ if (!_.isEmpty(fieldNames)) {
207
+ params.fields = fieldNames;
208
+ }
209
+ delete params._related_params;
210
+ delete params._parentId;
211
+ if (_.has(params, "top")) {
212
+ // 如果top小于1,不返回数据
213
+ if (params.top < 1) {
214
+ return [];
215
+ }
216
+ if (params.top > QUERY_DOCS_TOP) {
217
+ params.top = QUERY_DOCS_TOP; // 最多返回5000条数据
218
+ }
219
+ }
220
+ return await object.find(params, userSession);
221
+ },
222
+ };
223
+
224
+ actions[`${GRAPHQL_ACTION_PREFIX}${DISPLAY_PREFIX}`] = {
225
+ handler: async function (ctx) {
226
+ let params = ctx.params;
227
+ let { __objectName } = params;
228
+ let userSession = ctx.meta.user;
229
+ let selectFieldNames = [];
230
+ const { resolveInfo } = ctx.meta;
231
+ const fieldNames = getQueryFields(resolveInfo);
232
+ if (!_.isEmpty(fieldNames)) {
233
+ selectFieldNames = fieldNames;
234
+ }
235
+ let result = await translateToDisplay(
236
+ __objectName,
237
+ params,
238
+ userSession,
239
+ selectFieldNames,
240
+ );
241
+ return result;
242
+ },
243
+ };
244
+
245
+ // actions[`${GRAPHQL_ACTION_PREFIX}${UI_PREFIX}`] = {
246
+ // handler: async function (ctx) {
247
+ // let params = ctx.params;
248
+ // let { __objectName, __objectConfig } = params;
249
+ // let userSession = ctx.meta.user;
250
+ // let selectFieldNames = [];
251
+ // const { resolveInfo } = ctx.meta;
252
+ // const fieldNames = getQueryFields(resolveInfo);
253
+ // if (!_.isEmpty(fieldNames)) {
254
+ // selectFieldNames = fieldNames;
255
+ // }
256
+ // let result = await translateToUI(__objectConfig, params, userSession, selectFieldNames);
257
+
258
+ // return result;
259
+ // },
260
+ // };
261
+
262
+ actions[`${GRAPHQL_ACTION_PREFIX}${PERMISSIONS_PREFIX}`] = {
263
+ handler: async function (ctx) {
264
+ let params = ctx.params;
265
+ let { __objectName } = params;
266
+ let userSession = ctx.meta.user;
267
+ return await callObjectServiceAction(
268
+ `objectql.getRecordPermissionsById`,
269
+ userSession,
270
+ {
271
+ objectName: __objectName,
272
+ recordId: params._id,
273
+ },
274
+ );
275
+ },
276
+ };
277
+
278
+ return actions;
279
+ }
280
+
281
+ async function translateToDisplay(
282
+ objectName,
283
+ doc,
284
+ userSession: any,
285
+ selectorFieldNames,
20
286
  ) {
21
- let actions = {};
22
- // let objName = objectConfig.name;
23
-
24
- // actions[`${GRAPHQL_ACTION_PREFIX}${EXPAND_SUFFIX}_multiple`] = {
25
- // handler: async function (ctx) {
26
- // let { ids, objectName, referenceToField } = ctx.params;
27
- // if (_.isEmpty(ids)) {
28
- // return null;
29
- // }
30
- // let filters = [[referenceToField || "_id", "in", ids]];
31
- // const selector: any = { filters: filters };
32
- // let steedosSchema = getSteedosSchema();
33
- // let obj = steedosSchema.getObject(objectName);
34
-
35
- // const { resolveInfo } = ctx.meta;
36
- // const fieldNames = getQueryFields(resolveInfo);
37
- // if (!_.isEmpty(fieldNames)) {
38
- // selector.fields = fieldNames;
39
- // }
40
-
41
- // return obj.find(selector);
42
- // },
43
- // };
44
- actions[`${GRAPHQL_ACTION_PREFIX}${EXPAND_SUFFIX}`] = {
45
- // params:{
46
- // graphql: { dataLoaderOptions: { cacheMap: new LRUMap(1000) } },
47
- // },
48
- handler: async function (ctx) {
49
- // console.log(`${GRAPHQL_ACTION_PREFIX}${EXPAND_SUFFIX} params`, ctx.params)
50
- let { id, objectName, referenceToField } = ctx.params;
51
- if (!id) {
52
- return;
53
- }
54
- let steedosSchema = getSteedosSchema();
55
- let obj = steedosSchema.getObject(objectName);
56
- if(_.isString(id)){
57
- id = [id]
58
- }
59
- const selector: any = { filters: [[referenceToField || "_id", "in", id]] };
60
- const spaceId = ctx.meta.spaceId || ctx.meta.user?.spaceId;
61
- if(referenceToField && referenceToField != '_id' && objectName != 'users' && objectName != 'spaces' && spaceId){
62
- selector.filters.push(["space", "=", spaceId])
287
+ const lng = getUserLocale(userSession);
288
+ let steedosSchema = getSteedosSchema();
289
+ let object = steedosSchema.getObject(objectName);
290
+ let objConfig = await object.toConfig();
291
+ let fields = objConfig.fields;
292
+ // let _object = clone(objConfig);
293
+ translationObject(lng, objConfig.name, objConfig, true);
294
+
295
+ let utcOffset = userSession.utcOffset || 8;
296
+ async function _translateToDisplay(doc, selectorFieldNames) {
297
+ let displayObj = {};
298
+ for (const name of selectorFieldNames) {
299
+ if (Object.prototype.hasOwnProperty.call(fields, name)) {
300
+ const field = fields[name];
301
+ if (_.has(doc, name)) {
302
+ const fType = field.type;
303
+ if (fType == "text") {
304
+ displayObj[name] = doc[name] || "";
305
+ } else if (fType == "textarea") {
306
+ displayObj[name] = doc[name] || "";
307
+ } else if (fType == "html_text") {
308
+ displayObj[name] = doc[name] || "";
309
+ } else if (fType == "html") {
310
+ displayObj[name] = doc[name] || "";
311
+ } else if (fType == "color") {
312
+ displayObj[name] = doc[name] || "";
313
+ } else if (fType == "select") {
314
+ let label = "";
315
+ let map = {};
316
+ let value = doc[name];
317
+ let translatedField = getTranslatedFieldConfig(objConfig, name);
318
+ let translatedFieldOptions =
319
+ translatedField && translatedField.options;
320
+ _.forEach(translatedFieldOptions, function (o) {
321
+ map[o.value] = o.label;
322
+ });
323
+ if (field.multiple) {
324
+ let labels = [];
325
+ _.forEach(value, function (v) {
326
+ labels.push(map[v]);
327
+ });
328
+ label = labels.join(",");
329
+ } else {
330
+ label = map[value];
63
331
  }
64
- // const { resolveInfo } = ctx.meta;
65
- // const fieldNames = getQueryFields(resolveInfo);
66
- // if (!_.isEmpty(fieldNames)) {
67
- // selector.fields = fieldNames;
68
- // }
69
-
70
- // return (await obj.find(selector))[0];
71
- delete selector.fields;
72
- const result = await obj.find(selector);
73
-
74
- if(id.length > result.length){
75
- // const count = id.length - result.length;
76
- // for (let index = 0; index < count; index++) {
77
- // result.push({})
78
- // }
79
- each(id, (_id)=>{
80
- if(!find(result, (doc)=>{return doc[referenceToField || "_id"] === _id})){
81
- result.push({[referenceToField || "_id"]: _id})
82
- }
83
- })
332
+ displayObj[name] = label;
333
+ } else if (fType == "boolean") {
334
+ if (doc[name]) {
335
+ displayObj[name] = "√";
336
+ } else {
337
+ displayObj[name] = "";
84
338
  }
85
- // console.log(`result=====>`, JSON.stringify(selector), result)
86
- if(_.isString(ctx.params.id)){
87
- return result[0];
339
+ } else if (fType == "date") {
340
+ // 注意日期类型存的是utc0点,不需要执行utcOffset
341
+ displayObj[name] = doc[name]
342
+ ? moment.utc(doc[name]).format("YYYY-MM-DD")
343
+ : "";
344
+ } else if (fType == "datetime") {
345
+ displayObj[name] = doc[name]
346
+ ? moment(doc[name])
347
+ .utcOffset(utcOffset)
348
+ .format("YYYY-MM-DD HH:mm")
349
+ : "";
350
+ } else if (fType == "time") {
351
+ // 注意时间类型走的是utc时间,不需要执行utcOffset
352
+ displayObj[name] = doc[name]
353
+ ? moment.utc(doc[name]).format("HH:mm")
354
+ : "";
355
+ } else if (fType == "number") {
356
+ displayObj[name] = doc[name]
357
+ ? numberToString(
358
+ doc[name],
359
+ field.scale,
360
+ field.enable_thousands === false,
361
+ )
362
+ : "";
363
+ } else if (fType == "currency") {
364
+ displayObj[name] = doc[name]
365
+ ? numberToString(
366
+ doc[name],
367
+ field.scale,
368
+ field.enable_thousands === false,
369
+ )
370
+ : "";
371
+ } else if (fType == "percent") {
372
+ displayObj[name] = doc[name] ? `${doc[name] * 100}%` : "";
373
+ } else if (fType == "password") {
374
+ displayObj[name] = "";
375
+ if (_.isString(doc[name])) {
376
+ for (let i = 0; i < doc[name].length; i++) {
377
+ displayObj[name] += "*";
378
+ }
88
379
  }
380
+ } else if (fType == "lookup" && _.isString(field.reference_to)) {
381
+ let refTo = field.reference_to;
89
382
 
90
- // 使用 id 对象查询的结果result进行排序. 否则会导致dataloader缓存key与结果不匹配
91
- return sortBy(result, (doc)=>{
92
- return id.indexOf(doc[referenceToField || "_id"]);
93
- });
94
- },
95
- };
96
-
97
- // if (
98
- // [
99
- // "cms_files",
100
- // "tasks",
101
- // "notes",
102
- // "events",
103
- // "audit_records",
104
- // "instances",
105
- // "approvals",
106
- // ].includes(objName)
107
- // ) {
108
- actions[`${GRAPHQL_ACTION_PREFIX}${RELATED_PREFIX}_enabled`] = {
109
- handler: async function (ctx) {
110
- let params = ctx.params;
111
- let { _parentId, _related_params } = params;
112
- let { objectName, parentObjectName, foreignKey } = _related_params;
113
- let userSession = ctx.meta.user;
114
- let steedosSchema = getSteedosSchema();
115
- let object = steedosSchema.getObject(objectName);
116
- let filters = [];
117
- filters = [
118
- [`${foreignKey}.o`, "=", parentObjectName],
119
- [`${foreignKey}.ids`, "=", _parentId],
120
- ];
121
- if (params.filters) {
122
- filters.push(params.filters);
383
+ let refField = field.reference_to_field || "_id";
384
+
385
+ if (refTo === "users") {
386
+ refTo = "space_users";
387
+ refField = "user";
123
388
  }
124
- params.filters = filters;
125
- return await object.find(params, userSession);
126
- },
127
- };
128
- // }
129
-
130
- actions[`${GRAPHQL_ACTION_PREFIX}${RELATED_PREFIX}`] = {
131
- params: {
132
- fields: { type: 'array', items: "string", optional: true },
133
- filters: [{ type: 'array', optional: true }, { type: 'string', optional: true }],
134
- top: { type: 'number', optional: true, default: QUERY_DOCS_TOP },
135
- skip: { type: 'number', optional: true },
136
- sort: { type: 'string', optional: true },
137
- _parentId: { type: 'string', optional: false },
138
- _related_params: {
139
- type: 'object',
140
- props: {
141
- objectName: { type: "string", optional: false },
142
- parentObjectName: { type: "string", optional: false },
143
- fieldName: { type: "string", optional: false },
144
- referenceToParentFieldName: { type: "string", optional: true },
145
- }
389
+
390
+ let refValue = doc[name];
391
+ if (!refValue) {
392
+ continue;
146
393
  }
147
- },
148
- handler: async function (ctx) {
149
- let params = ctx.params;
150
- let { _parentId, _related_params } = params;
151
- let {
152
- objectName,
153
- parentObjectName,
154
- fieldName,
155
- referenceToParentFieldName,
156
- } = _related_params;
157
- let userSession = ctx.meta.user;
158
- let steedosSchema = getSteedosSchema();
159
- let object = steedosSchema.getObject(objectName);
160
- let parentObj = steedosSchema.getObject(parentObjectName);
161
- let parent = await parentObj.findOne(_parentId);
162
- // 防止万一parent为空
163
- if (!parent) {
164
- return []
394
+ let refObj = steedosSchema.getObject(refTo);
395
+ let nameFieldKey = await refObj.getNameFieldKey();
396
+ if (field.multiple) {
397
+ let refRecords = await refObj.find({
398
+ filters: [refField, "in", refValue],
399
+ fields: [nameFieldKey],
400
+ });
401
+ displayObj[name] = _.pluck(refRecords, nameFieldKey).join(",");
402
+ } else {
403
+ let refRecord = (
404
+ await refObj.find({
405
+ filters: [refField, "=", refValue],
406
+ fields: [nameFieldKey],
407
+ })
408
+ )[0];
409
+ if (refRecord) {
410
+ displayObj[name] = refRecord[nameFieldKey];
411
+ }
165
412
  }
166
- let filters = [];
167
- let _idValue = parent._id;
168
- if (referenceToParentFieldName) {
169
- _idValue = parent[referenceToParentFieldName];
413
+ } else if (
414
+ fType == "master_detail" &&
415
+ _.isString(field.reference_to)
416
+ ) {
417
+ let refTo = field.reference_to;
418
+ let refField = field.reference_to_field || "_id";
419
+
420
+ if (refTo === "users") {
421
+ refTo = "space_users";
422
+ refField = "user";
170
423
  }
171
- filters = [[fieldName, "=", _idValue]];
172
- if (params.filters) {
173
- filters.push(params.filters);
424
+ let refValue = doc[name];
425
+ if (!refValue) {
426
+ continue;
174
427
  }
175
- params.filters = filters;
176
-
177
- const { resolveInfo } = ctx.meta;
178
- const fieldNames = getQueryFields(resolveInfo);
179
- if (!_.isEmpty(fieldNames)) {
180
- params.fields = fieldNames;
428
+ let refObj = steedosSchema.getObject(refTo);
429
+ let nameFieldKey = await refObj.getNameFieldKey();
430
+ if (field.multiple) {
431
+ let refRecords = await refObj.find({
432
+ filters: [refField, "in", refValue],
433
+ fields: [nameFieldKey],
434
+ });
435
+ displayObj[name] = _.pluck(refRecords, nameFieldKey).join(",");
436
+ } else {
437
+ let refRecord = (
438
+ await refObj.find({
439
+ filters: [refField, "=", refValue],
440
+ fields: [nameFieldKey],
441
+ })
442
+ )[0];
443
+ if (refRecord) {
444
+ displayObj[name] = refRecord[nameFieldKey];
445
+ }
181
446
  }
182
- delete params._related_params;
183
- delete params._parentId;
184
- if (_.has(params, "top")) { // 如果top小于1,不返回数据
185
- if (params.top < 1) {
186
- return []
187
- }
188
- if (params.top > QUERY_DOCS_TOP) {
189
- params.top = QUERY_DOCS_TOP; // 最多返回5000条数据
190
- }
447
+ } else if (
448
+ (fType == "master_detail" || fType == "lookup") &&
449
+ field.reference_to &&
450
+ !_.isString(field.reference_to)
451
+ ) {
452
+ let refValue = doc[name];
453
+ if (!refValue) {
454
+ continue;
191
455
  }
192
- return await object.find(params, userSession);
193
- },
194
- };
195
-
196
- actions[`${GRAPHQL_ACTION_PREFIX}${DISPLAY_PREFIX}`] = {
197
- handler: async function (ctx) {
198
- let params = ctx.params;
199
- let { __objectName } = params;
200
- let userSession = ctx.meta.user;
201
- let selectFieldNames = [];
202
- const { resolveInfo } = ctx.meta;
203
- const fieldNames = getQueryFields(resolveInfo);
204
- if (!_.isEmpty(fieldNames)) {
205
- selectFieldNames = fieldNames;
456
+ let refTo = refValue.o;
457
+ let refValues = refValue.ids;
458
+ if (!refTo) {
459
+ continue;
206
460
  }
207
- let result = await translateToDisplay(__objectName, params, userSession, selectFieldNames);
208
- return result;
209
- },
210
- };
211
-
212
- // actions[`${GRAPHQL_ACTION_PREFIX}${UI_PREFIX}`] = {
213
- // handler: async function (ctx) {
214
- // let params = ctx.params;
215
- // let { __objectName, __objectConfig } = params;
216
- // let userSession = ctx.meta.user;
217
- // let selectFieldNames = [];
218
- // const { resolveInfo } = ctx.meta;
219
- // const fieldNames = getQueryFields(resolveInfo);
220
- // if (!_.isEmpty(fieldNames)) {
221
- // selectFieldNames = fieldNames;
222
- // }
223
- // let result = await translateToUI(__objectConfig, params, userSession, selectFieldNames);
224
-
225
- // return result;
226
- // },
227
- // };
228
-
229
- actions[`${GRAPHQL_ACTION_PREFIX}${PERMISSIONS_PREFIX}`] = {
230
- handler: async function (ctx) {
231
- let params = ctx.params;
232
- let { __objectName } = params;
233
- let userSession = ctx.meta.user;
234
- return await callObjectServiceAction(`objectql.getRecordPermissionsById`, userSession, {
235
- objectName: __objectName,
236
- recordId: params._id
461
+ let refObj = steedosSchema.getObject(refTo);
462
+ let nameFieldKey = await refObj.getNameFieldKey();
463
+ let refRecords = await refObj.find({
464
+ filters: [`_id`, "in", refValues],
465
+ fields: [nameFieldKey],
237
466
  });
238
- },
239
- };
240
-
241
- return actions;
242
- }
243
467
 
244
- async function translateToDisplay(objectName, doc, userSession: any, selectorFieldNames) {
245
- const lng = getUserLocale(userSession);
246
- let steedosSchema = getSteedosSchema();
247
- let object = steedosSchema.getObject(objectName);
248
- let objConfig = await object.toConfig();
249
- let fields = objConfig.fields;
250
- // let _object = clone(objConfig);
251
- translationObject(lng, objConfig.name, objConfig, true);
252
-
253
- let utcOffset = userSession.utcOffset || 8;
254
- async function _translateToDisplay(doc, selectorFieldNames) {
255
- let displayObj = {};
256
- for (const name of selectorFieldNames) {
257
- if (Object.prototype.hasOwnProperty.call(fields, name)) {
258
- const field = fields[name];
259
- if (_.has(doc, name)) {
260
- const fType = field.type;
261
- if (fType == "text") {
262
- displayObj[name] = doc[name] || "";
263
- } else if (fType == "textarea") {
264
- displayObj[name] = doc[name] || "";
265
- } else if (fType == "html_text") {
266
- displayObj[name] = doc[name] || "";
267
- } else if (fType == "html") {
268
- displayObj[name] = doc[name] || "";
269
- } else if (fType == "color") {
270
- displayObj[name] = doc[name] || "";
271
- } else if (fType == "select") {
272
- let label = "";
273
- let map = {};
274
- let value = doc[name];
275
- let translatedField = getTranslatedFieldConfig(objConfig, name);
276
- let translatedFieldOptions =
277
- translatedField && translatedField.options;
278
- _.forEach(translatedFieldOptions, function (o) {
279
- map[o.value] = o.label;
280
- });
281
- if (field.multiple) {
282
- let labels = [];
283
- _.forEach(value, function (v) {
284
- labels.push(map[v]);
285
- });
286
- label = labels.join(",");
287
- } else {
288
- label = map[value];
289
- }
290
- displayObj[name] = label;
291
- } else if (fType == "boolean") {
292
- if (doc[name]) {
293
- displayObj[name] = "√";
294
- } else {
295
- displayObj[name] = "";
296
- }
297
- } else if (fType == "date") {
298
- // 注意日期类型存的是utc0点,不需要执行utcOffset
299
- displayObj[name] = doc[name] ? moment.utc(doc[name])
300
- .format("YYYY-MM-DD") : '';
301
- } else if (fType == "datetime") {
302
- displayObj[name] = doc[name] ? moment(doc[name])
303
- .utcOffset(utcOffset)
304
- .format("YYYY-MM-DD HH:mm") : '';
305
- } else if (fType == "time") {
306
- // 注意时间类型走的是utc时间,不需要执行utcOffset
307
- displayObj[name] = doc[name] ? moment.utc(doc[name])
308
- .format("HH:mm") : '';
309
- } else if (fType == "number") {
310
- displayObj[name] = doc[name] ? numberToString(doc[name], field.scale, field.enable_thousands === false) : "";
311
- } else if (fType == "currency") {
312
- displayObj[name] = doc[name] ? numberToString(doc[name], field.scale, field.enable_thousands === false) : "";
313
- } else if (fType == "percent") {
314
- displayObj[name] = doc[name] ? `${doc[name] * 100}%` : "";
315
- } else if (fType == "password") {
316
- displayObj[name] = "";
317
- if (_.isString(doc[name])) {
318
- for (let i = 0; i < doc[name].length; i++) {
319
- displayObj[name] += "*";
320
- }
321
- }
322
- } else if (fType == "lookup" && _.isString(field.reference_to)) {
323
- let refTo = field.reference_to;
324
-
325
- let refField = field.reference_to_field || '_id';
326
-
327
- if (refTo === 'users') {
328
- refTo = 'space_users';
329
- refField = 'user'
330
- }
331
-
332
- let refValue = doc[name];
333
- if (!refValue) {
334
- continue;
335
- }
336
- let refObj = steedosSchema.getObject(refTo);
337
- let nameFieldKey = await refObj.getNameFieldKey();
338
- if (field.multiple) {
339
- let refRecords = await refObj.find({
340
- filters: [refField, "in", refValue],
341
- fields: [nameFieldKey],
342
- });
343
- displayObj[name] = _.pluck(refRecords, nameFieldKey).join(',')
344
- } else {
345
- let refRecord = (
346
- await refObj.find({
347
- filters: [refField, "=", refValue],
348
- fields: [nameFieldKey],
349
- })
350
- )[0];
351
- if (refRecord) {
352
- displayObj[name] = refRecord[nameFieldKey];
353
- }
354
- }
355
- } else if (fType == "master_detail" && _.isString(field.reference_to)) {
356
- let refTo = field.reference_to;
357
- let refField = field.reference_to_field || '_id';
358
-
359
- if (refTo === 'users') {
360
- refTo = 'space_users';
361
- refField = 'user'
362
- }
363
- let refValue = doc[name];
364
- if (!refValue) {
365
- continue;
366
- }
367
- let refObj = steedosSchema.getObject(refTo);
368
- let nameFieldKey = await refObj.getNameFieldKey();
369
- if (field.multiple) {
370
- let refRecords = await refObj.find({
371
- filters: [refField, "in", refValue],
372
- fields: [nameFieldKey],
373
- });
374
- displayObj[name] = _.pluck(refRecords, nameFieldKey).join(',')
375
- } else {
376
- let refRecord = (
377
- await refObj.find({
378
- filters: [refField, "=", refValue],
379
- fields: [nameFieldKey],
380
- })
381
- )[0];
382
- if (refRecord) {
383
- displayObj[name] = refRecord[nameFieldKey];
384
- }
385
- }
386
- } else if ((fType == "master_detail" || fType == "lookup") && field.reference_to && !_.isString(field.reference_to)) {
387
- let refValue = doc[name];
388
- if (!refValue) {
389
- continue;
390
- }
391
- let refTo = refValue.o;
392
- let refValues = refValue.ids;
393
- if (!refTo) {
394
- continue;
395
- }
396
- let refObj = steedosSchema.getObject(refTo);
397
- let nameFieldKey = await refObj.getNameFieldKey();
398
- let refRecords = await refObj.find({
399
- filters: [`_id`, "in", refValues],
400
- fields: [nameFieldKey]
401
- });
402
-
403
- displayObj[name] = _.pluck(refRecords, nameFieldKey).join(',')
404
- } else if (fType == "autonumber") {
405
- displayObj[name] = doc[name] || "";
406
- } else if (fType == "url") {
407
- displayObj[name] = doc[name] || "";
408
- } else if (fType == "email") {
409
- displayObj[name] = doc[name] || "";
410
- } else if (fType == "formula") {
411
- displayObj[name] = doc[name] || "";
412
- } else if (fType == "summary") {
413
- displayObj[name] = doc[name] || "";
414
- } else if (fType == "image" || fType == "file") {
415
- let fileLabel = "";
416
- let value = doc[name];
417
- if (!value) {
418
- continue;
419
- }
420
- // TODO: cfs_images_filerecord对象不存在,需要额外处理
421
- let fileObjectName = fType == "image" ? "cfs_images_filerecord" : "cfs_files_filerecord";
422
- let fileObject = steedosSchema.getObject(fileObjectName);
423
- const fileNameFieldKey = "original.name";
424
- if (field.multiple) {
425
- let fileRecords = await fileObject.find({
426
- filters: [`_id`, "in", value],
427
- fields: [fileNameFieldKey],
428
- });
429
- fileLabel = _.map(fileRecords, (fileRecord) => {
430
- return fileRecord.original?.name;
431
- }).join(",");
432
- } else {
433
- let fileRecord = (
434
- await fileObject.find({
435
- filters: [`_id`, "=", value],
436
- fields: [fileNameFieldKey],
437
- })
438
- )[0];
439
- if (fileRecord) {
440
- fileLabel = fileRecord["original"]["name"];
441
- }
442
- }
443
- displayObj[name] = fileLabel;
444
- }
445
- else {
446
- console.error(
447
- `Graphql Display: need to handle new field type ${field.type} for ${objectName}.`
448
- );
449
- displayObj[name] = doc[name] || "";
450
- }
451
- } else {
452
- displayObj[name] = ""; // 如果值为空,均返回空字符串
453
- }
468
+ displayObj[name] = _.pluck(refRecords, nameFieldKey).join(",");
469
+ } else if (fType == "autonumber") {
470
+ displayObj[name] = doc[name] || "";
471
+ } else if (fType == "url") {
472
+ displayObj[name] = doc[name] || "";
473
+ } else if (fType == "email") {
474
+ displayObj[name] = doc[name] || "";
475
+ } else if (fType == "formula") {
476
+ displayObj[name] = doc[name] || "";
477
+ } else if (fType == "summary") {
478
+ displayObj[name] = doc[name] || "";
479
+ } else if (fType == "image" || fType == "file") {
480
+ let fileLabel = "";
481
+ let value = doc[name];
482
+ if (!value) {
483
+ continue;
454
484
  }
485
+ // TODO: cfs_images_filerecord对象不存在,需要额外处理
486
+ let fileObjectName =
487
+ fType == "image"
488
+ ? "cfs_images_filerecord"
489
+ : "cfs_files_filerecord";
490
+ let fileObject = steedosSchema.getObject(fileObjectName);
491
+ const fileNameFieldKey = "original.name";
492
+ if (field.multiple) {
493
+ let fileRecords = await fileObject.find({
494
+ filters: [`_id`, "in", value],
495
+ fields: [fileNameFieldKey],
496
+ });
497
+ fileLabel = _.map(fileRecords, (fileRecord) => {
498
+ return fileRecord.original?.name;
499
+ }).join(",");
500
+ } else {
501
+ let fileRecord = (
502
+ await fileObject.find({
503
+ filters: [`_id`, "=", value],
504
+ fields: [fileNameFieldKey],
505
+ })
506
+ )[0];
507
+ if (fileRecord) {
508
+ fileLabel = fileRecord["original"]["name"];
509
+ }
510
+ }
511
+ displayObj[name] = fileLabel;
512
+ } else {
513
+ console.error(
514
+ `Graphql Display: need to handle new field type ${field.type} for ${objectName}.`,
515
+ );
516
+ displayObj[name] = doc[name] || "";
517
+ }
518
+ } else {
519
+ displayObj[name] = ""; // 如果值为空,均返回空字符串
455
520
  }
456
- return displayObj
521
+ }
457
522
  }
458
- let displayDoc = await _translateToDisplay(doc, selectorFieldNames)
459
- displayDoc['_id'] = doc._id;
460
- return displayDoc;
523
+ return displayObj;
524
+ }
525
+ let displayDoc = await _translateToDisplay(doc, selectorFieldNames);
526
+ displayDoc["_id"] = doc._id;
527
+ return displayDoc;
461
528
  }
462
529
 
530
+ const getObjectDisplayData = async (
531
+ graphqlServiceName,
532
+ objectName,
533
+ refFieldName,
534
+ referenceToFieldName,
535
+ objectDataLoaderHandler,
536
+ graphqlCtx,
537
+ ) => {
538
+ const actionName = `${graphqlServiceName}.${GRAPHQL_ACTION_PREFIX}${EXPAND_SUFFIX}`;
539
+ // console.log(`getObjectDisplayData===>actionName`, actionName, referenceToFieldName)
540
+ return await objectDataLoaderHandler(
541
+ actionName,
542
+ {
543
+ objectName: objectName,
544
+ referenceToField: referenceToFieldName,
545
+ },
546
+ {
547
+ [refFieldName]: "id",
548
+ },
549
+ graphqlCtx,
550
+ );
551
+ };
552
+
553
+ export async function translateToUI(
554
+ objConfig,
555
+ doc,
556
+ userSession: any,
557
+ selectorFieldNames,
558
+ graphqlCtx,
559
+ ) {
560
+ const lng = getUserLocale(userSession);
561
+ let steedosSchema = getSteedosSchema();
562
+ // let object = steedosSchema.getObject(objectName);
563
+ // let objConfig = await object.toConfig();
564
+ let fields = objConfig.fields;
565
+ // let _object = clone(objConfig);
566
+ translationObject(lng, objConfig.name, objConfig, true);
567
+ async function _translateToUI(doc, selectorFieldNames, parentDoc?) {
568
+ let displayObj = {};
569
+ for (const name of selectorFieldNames) {
570
+ if (Object.prototype.hasOwnProperty.call(fields, name)) {
571
+ const field = fields[name];
572
+ try {
573
+ if (_.has(doc, name)) {
574
+ const fType = field.type;
575
+ const dataType = field.data_type;
576
+ if (fType == "select") {
577
+ let label = "";
578
+ let map = {};
579
+ let value = doc[name];
580
+ let translatedField = getTranslatedFieldConfig(objConfig, name);
581
+ let translatedFieldOptions =
582
+ translatedField && translatedField.options;
583
+ _.forEach(translatedFieldOptions, function (o) {
584
+ map[o.value] = o.label;
585
+ });
586
+ if (field.multiple) {
587
+ let labels = [];
588
+ _.forEach(value, function (v) {
589
+ labels.push(map[v]);
590
+ });
591
+ label = labels.join(",");
592
+ } else {
593
+ label = map[value];
594
+ }
595
+ displayObj[name] = label;
596
+ } else if (
597
+ fType == "lookup" &&
598
+ (_.isString(field.reference_to) ||
599
+ (!_.has(field, "reference_to") &&
600
+ !_.has(field, "_reference_to")))
601
+ ) {
602
+ if (_.isString(field.reference_to)) {
603
+ let refTo = field.reference_to;
604
+
605
+ let refField = field.reference_to_field || "_id";
606
+
607
+ if (refTo === "users") {
608
+ refTo = "space_users";
609
+ refField = "user";
610
+ }
463
611
 
464
- const getObjectDisplayData = async (graphqlServiceName, objectName, refFieldName , referenceToFieldName, objectDataLoaderHandler, graphqlCtx) => {
465
- const actionName = `${graphqlServiceName}.${GRAPHQL_ACTION_PREFIX}${EXPAND_SUFFIX}`
466
- // console.log(`getObjectDisplayData===>actionName`, actionName, referenceToFieldName)
467
- return await objectDataLoaderHandler(actionName, {
468
- objectName: objectName,
469
- referenceToField: referenceToFieldName
470
- }, {
471
- [refFieldName]: 'id'
472
- }, graphqlCtx);
473
- }
474
-
475
- export async function translateToUI(objConfig, doc, userSession: any, selectorFieldNames, graphqlCtx) {
476
- const lng = getUserLocale(userSession);
477
- let steedosSchema = getSteedosSchema();
478
- // let object = steedosSchema.getObject(objectName);
479
- // let objConfig = await object.toConfig();
480
- let fields = objConfig.fields;
481
- // let _object = clone(objConfig);
482
- translationObject(lng, objConfig.name, objConfig, true);
483
- async function _translateToUI(doc, selectorFieldNames, parentDoc?) {
484
- let displayObj = {};
485
- for (const name of selectorFieldNames) {
486
- if (Object.prototype.hasOwnProperty.call(fields, name)) {
487
- const field = fields[name];
488
- try {
489
- if (_.has(doc, name)) {
490
- const fType = field.type;
491
- const dataType = field.data_type;
492
- if (fType == "select") {
493
- let label = "";
494
- let map = {};
495
- let value = doc[name];
496
- let translatedField = getTranslatedFieldConfig(objConfig, name);
497
- let translatedFieldOptions =
498
- translatedField && translatedField.options;
499
- _.forEach(translatedFieldOptions, function (o) {
500
- map[o.value] = o.label;
501
- });
502
- if (field.multiple) {
503
- let labels = [];
504
- _.forEach(value, function (v) {
505
- labels.push(map[v]);
506
- });
507
- label = labels.join(",");
508
- } else {
509
- label = map[value];
510
- }
511
- displayObj[name] = label;
512
- } else if (fType == "lookup" && (_.isString(field.reference_to) || (!_.has(field, 'reference_to') && !_.has(field, '_reference_to')))) {
513
- if (_.isString(field.reference_to)) {
514
- let refTo = field.reference_to;
515
-
516
- let refField = field.reference_to_field || '_id';
517
-
518
- if (refTo === 'users') {
519
- refTo = 'space_users';
520
- refField = 'user'
521
- }
522
-
523
- let refValue = doc[name];
524
- if (!refValue || _.isEmpty(refValue)) {
525
- continue;
526
- }
527
- let refObj = steedosSchema.getObject(refTo);
528
- let nameFieldKey = await refObj.getNameFieldKey();
529
- let objectDataLoader = refObj.enable_dataloader != false && process.env.STEEDOS_GRAPHQL_ENABLE_DATALOADER != 'false';
530
- if(objectDataLoader){
531
- const results = await getObjectDisplayData('api', refTo, name, refField, graphqlCtx.objectDataLoaderHandler, graphqlCtx);
532
- if(field.multiple){
533
- displayObj[name] = _.map(results, (item) => {
534
- return {
535
- objectName: refTo,
536
- value: item ? item._id : refValue,
537
- label: item ? item[nameFieldKey] : refValue
538
- }
539
- })
540
- }else{
541
- displayObj[name] = {
542
- objectName: refTo,
543
- value: results._id || refValue,
544
- label: results[nameFieldKey] || refValue
545
- };
546
- }
547
- }else{
548
-
549
- let refFilters = null;
550
-
551
- if (field.multiple) {
552
- refFilters = [refField, "in", refValue]
553
- } else {
554
- refFilters = [refField, "=", refValue]
555
- }
556
-
557
- // 判断如果是 reference_to = object_fields && reference_to_field = name, 则额外添加查询条件 object 查询条件;
558
- if (refTo === 'object_fields' && refField == 'name') {
559
- if(objConfig.name === 'objects'){
560
- refFilters = [['object', '=', parentDoc['name']], refFilters]
561
- }else{
562
- const refToObjectsField = _.find(fields, (_field) => {
563
- return _field.reference_to === 'objects'
564
- })
565
- if (refToObjectsField) {
566
- refFilters = [['object', '=', parentDoc[refToObjectsField.name]], refFilters]
567
- }
568
- }
569
-
570
- }
571
-
572
- // 判断如果是 reference_to = object_actions && reference_to_field = name, 则额外添加查询条件 object 查询条件;
573
- if (refTo === 'object_actions' && refField == 'name') {
574
- const refToObjectsField = _.find(fields, (_field) => {
575
- return _field.reference_to === 'objects'
576
- })
577
- if (refToObjectsField) {
578
- refFilters = [['object', '=', parentDoc[refToObjectsField.name]], refFilters]
579
- }
580
- }
581
-
582
- if (field.multiple) {
583
- let refRecords = await refObj.find({
584
- filters: refFilters,
585
- fields: [nameFieldKey],
586
- });
587
- displayObj[name] = _.map(refRecords, (item) => {
588
- return {
589
- objectName: refTo,
590
- value: item ? item._id : refValue,
591
- label: item ? item[nameFieldKey] : refValue
592
- }
593
- })
594
- } else {
595
- let refRecord = (
596
- await refObj.find({
597
- filters: refFilters,
598
- fields: [nameFieldKey],
599
- })
600
- )[0];
601
- if (refRecord) {
602
- displayObj[name] = {
603
- objectName: refTo,
604
- value: refRecord._id,
605
- label: refRecord[nameFieldKey]
606
- };
607
- } else {
608
- displayObj[name] = {
609
- objectName: refTo,
610
- value: refValue,
611
- label: refValue
612
- };
613
- }
614
- }
615
- }
616
- } else {
617
- let refValue = doc[name];
618
- if (!refValue) {
619
- continue;
620
- }
621
- if (field.multiple && _.isArray(refValue)) {
622
- _.each(refValue, (item) => {
623
- displayObj[name] = {
624
- value: item,
625
- label: item
626
- };
627
- })
628
- } else {
629
- displayObj[name] = {
630
- value: refValue,
631
- label: refValue
632
- };
633
- }
634
- }
635
-
636
- } else if (fType == "master_detail" && _.isString(field.reference_to)) {
637
- let refTo = field.reference_to;
638
- let refField = field.reference_to_field || '_id';
639
-
640
- if (refTo === 'users') {
641
- refTo = 'space_users';
642
- refField = 'user'
643
- }
644
- let refValue = doc[name];
645
- if (!refValue) {
646
- continue;
647
- }
648
- let refObj = steedosSchema.getObject(refTo);
649
- let nameFieldKey = await refObj.getNameFieldKey();
650
-
651
- let objectDataLoader = refObj.enable_dataloader != false && process.env.STEEDOS_GRAPHQL_ENABLE_DATALOADER != 'false';
652
-
653
- if(objectDataLoader){
654
- const results = await getObjectDisplayData('api', field.reference_to, name, refField, graphqlCtx.objectDataLoaderHandler, graphqlCtx);
655
- if(field.multiple){
656
- displayObj[name] = _.map(results, (item) => {
657
- return {
658
- objectName: refTo,
659
- value: item ? item._id : refValue,
660
- label: item ? item[nameFieldKey] : refValue
661
- }
662
- })
663
- }else{
664
- displayObj[name] = {
665
- objectName: refTo,
666
- value: results._id || refValue,
667
- label: results[nameFieldKey] || refValue
668
- };
669
- }
670
- }else{
671
- if (field.multiple) {
672
- let refRecords = await refObj.find({
673
- filters: [refField, "in", refValue],
674
- fields: [nameFieldKey],
675
- });
676
- displayObj[name] = _.map(refRecords, (item) => {
677
- return {
678
- objectName: refTo,
679
- value: item._id,
680
- label: item[nameFieldKey]
681
- }
682
- })
683
- } else {
684
- let refRecord = (
685
- await refObj.find({
686
- filters: [refField, "=", refValue],
687
- fields: [nameFieldKey],
688
- })
689
- )[0];
690
- if (refRecord) {
691
- displayObj[name] = {
692
- objectName: refTo,
693
- value: refRecord._id,
694
- label: refRecord[nameFieldKey]
695
- };
696
- }
697
- }
698
- }
699
- } else if ((fType == "master_detail" || fType == "lookup") && ((field.reference_to && !_.isString(field.reference_to)) || _.isString(field._reference_to))) {
700
- let refValue = doc[name];
701
- if (!refValue) {
702
- continue;
703
- }
704
- let refTo = refValue.o;
705
- let refValues = refValue.ids;
706
- if (!refTo) {
707
- continue;
708
- }
709
- let refObj = steedosSchema.getObject(refTo);
710
- let nameFieldKey = await refObj.getNameFieldKey();
711
- let refRecords = await refObj.find({
712
- filters: [`_id`, "in", refValues],
713
- fields: [nameFieldKey]
714
- });
715
-
716
- displayObj[name] = _.map(refRecords, (item) => {
717
- return {
718
- objectName: refTo,
719
- value: item._id,
720
- label: item[nameFieldKey]
721
- }
722
- })
723
- } else if (fType == "formula") {
724
- displayObj[name] = formatBasicFieldValue(field.data_type, field, doc[name], objConfig, userSession);
725
- } else if (fType == "summary") {
726
- displayObj[name] = formatBasicFieldValue(dataType, field, doc[name], objConfig, userSession);
727
- } else if (fType == "image" || fType == "file" || fType === 'avatar') {
728
- const optionsStr = fType == "file" ? '?download=1' : ''
729
- let fileValue: any = null;
730
- let value = doc[name];
731
- if (!value) {
732
- continue;
733
- }
734
- // TODO: cfs_images_filerecord对象不存在,需要额外处理
735
- let storageName = getFileStorageName(fType)
736
- let fileObjectName = `cfs_${storageName}_filerecord`;
737
- let fileObject = steedosSchema.getObject(fileObjectName);
738
- const fileNameFieldKey = "original.name";
739
- if (field.multiple) {
740
- let fileRecords = await fileObject.find({
741
- filters: [`_id`, "in", value],
742
- fields: ['_id', fileNameFieldKey, 'original.size', 'original.type'],
743
- });
744
- fileValue = _.map(fileRecords, (fileRecord) => {
745
- return {
746
- name: fileRecord.original?.name,
747
- url: absoluteUrl(`/api/files/${storageName}/${fileRecord._id}${optionsStr}`),
748
- size: fileRecord.original?.size,
749
- type: fileRecord.original?.type,
750
- };
751
- });
752
- } else {
753
- let fileRecord = (
754
- await fileObject.find({
755
- filters: [`_id`, "=", value],
756
- fields: ['_id', fileNameFieldKey, 'original.size', 'original.type'],
757
- })
758
- )[0];
759
- if (fileRecord) {
760
- fileValue = {
761
- name: fileRecord["original"]["name"],
762
- url: absoluteUrl(`/api/files/${storageName}/${value}${optionsStr}`),
763
- size: fileRecord.original?.size,
764
- type: fileRecord.original?.type
765
- };
766
- } else {
767
- fileValue = {
768
- url: value
769
- };
770
- }
771
- }
772
- displayObj[name] = fileValue;
773
- } else if (fType == "filesize") {
774
- displayObj[name] = formatFileSize(doc[name]);
775
- }
776
- else if (fType === 'object') {
777
- if (doc[name] && _.isObject(doc[name])) {
778
- const _doc = {}
779
- _.each(doc[name], function (v, k) {
780
- const newKey = `${name}.${k}`
781
- _doc[newKey] = v
782
- })
783
- const objectFieldDoc = await _translateToUI(_doc, Object.keys(_doc), doc)
784
- const objectDoc = {}
785
- _.each(objectFieldDoc, function (v, k) {
786
- const newKey = k.replace(`${name}.`, '')
787
- objectDoc[newKey] = v
788
- })
789
- displayObj[name] = objectDoc
790
- }
791
- }
792
- else if (fType === 'grid' || 'table' === fType) {
793
- if (doc[name] && _.isArray(doc[name])) {
794
- const gridDocs = []
795
- for (const gridDoc of doc[name]) {
796
- const _doc = {}
797
- _.each(gridDoc, function (v, k) {
798
- const newKey = `${name}.$.${k}`
799
- _doc[newKey] = v
800
- })
801
- const objectFieldDoc = await _translateToUI(_doc, Object.keys(_doc), doc)
802
- const objectDoc = {}
803
- _.each(objectFieldDoc, function (v, k) {
804
- const newKey = k.replace(`${name}.$.`, '')
805
- objectDoc[newKey] = v
806
- })
807
- gridDocs.push(objectDoc)
808
- }
809
-
810
- displayObj[name] = gridDocs
811
- }
812
- }
813
- else {
814
- displayObj[name] = formatBasicFieldValue(fType, field, doc[name], objConfig, userSession);
815
- }
612
+ let refValue = doc[name];
613
+ if (!refValue || _.isEmpty(refValue)) {
614
+ continue;
615
+ }
616
+ let refObj = steedosSchema.getObject(refTo);
617
+ let nameFieldKey = await refObj.getNameFieldKey();
618
+ let objectDataLoader =
619
+ refObj.enable_dataloader != false &&
620
+ process.env.STEEDOS_GRAPHQL_ENABLE_DATALOADER != "false";
621
+ if (objectDataLoader) {
622
+ const results = await getObjectDisplayData(
623
+ "api",
624
+ refTo,
625
+ name,
626
+ refField,
627
+ graphqlCtx.objectDataLoaderHandler,
628
+ graphqlCtx,
629
+ );
630
+ if (field.multiple) {
631
+ displayObj[name] = _.map(results, (item) => {
632
+ return {
633
+ objectName: refTo,
634
+ value: item ? item._id : refValue,
635
+ label: item ? item[nameFieldKey] : refValue,
636
+ };
637
+ });
638
+ } else {
639
+ displayObj[name] = {
640
+ objectName: refTo,
641
+ value: results._id || refValue,
642
+ label: results[nameFieldKey] || refValue,
643
+ };
644
+ }
645
+ } else {
646
+ let refFilters = null;
647
+
648
+ if (field.multiple) {
649
+ refFilters = [refField, "in", refValue];
650
+ } else {
651
+ refFilters = [refField, "=", refValue];
652
+ }
653
+
654
+ // 判断如果是 reference_to = object_fields && reference_to_field = name, 则额外添加查询条件 object 查询条件;
655
+ if (refTo === "object_fields" && refField == "name") {
656
+ if (objConfig.name === "objects") {
657
+ refFilters = [
658
+ ["object", "=", parentDoc["name"]],
659
+ refFilters,
660
+ ];
661
+ } else {
662
+ const refToObjectsField = _.find(fields, (_field) => {
663
+ return _field.reference_to === "objects";
664
+ });
665
+ if (refToObjectsField) {
666
+ refFilters = [
667
+ ["object", "=", parentDoc[refToObjectsField.name]],
668
+ refFilters,
669
+ ];
670
+ }
671
+ }
672
+ }
673
+
674
+ // 判断如果是 reference_to = object_actions && reference_to_field = name, 则额外添加查询条件 object 查询条件;
675
+ if (refTo === "object_actions" && refField == "name") {
676
+ const refToObjectsField = _.find(fields, (_field) => {
677
+ return _field.reference_to === "objects";
678
+ });
679
+ if (refToObjectsField) {
680
+ refFilters = [
681
+ ["object", "=", parentDoc[refToObjectsField.name]],
682
+ refFilters,
683
+ ];
816
684
  }
817
- else {
818
- displayObj[name] = ""; // 如果值为空,均返回空字符串
685
+ }
686
+
687
+ if (field.multiple) {
688
+ let refRecords = await refObj.find({
689
+ filters: refFilters,
690
+ fields: [nameFieldKey],
691
+ });
692
+ displayObj[name] = _.map(refRecords, (item) => {
693
+ return {
694
+ objectName: refTo,
695
+ value: item ? item._id : refValue,
696
+ label: item ? item[nameFieldKey] : refValue,
697
+ };
698
+ });
699
+ } else {
700
+ let refRecord = (
701
+ await refObj.find({
702
+ filters: refFilters,
703
+ fields: [nameFieldKey],
704
+ })
705
+ )[0];
706
+ if (refRecord) {
707
+ displayObj[name] = {
708
+ objectName: refTo,
709
+ value: refRecord._id,
710
+ label: refRecord[nameFieldKey],
711
+ };
712
+ } else {
713
+ displayObj[name] = {
714
+ objectName: refTo,
715
+ value: refValue,
716
+ label: refValue,
717
+ };
819
718
  }
820
- } catch (error) {
821
- displayObj[name] = doc[name];
822
- // console.warn(error)
719
+ }
720
+ }
721
+ } else {
722
+ let refValue = doc[name];
723
+ if (!refValue) {
724
+ continue;
725
+ }
726
+ if (field.multiple && _.isArray(refValue)) {
727
+ _.each(refValue, (item) => {
728
+ displayObj[name] = {
729
+ value: item,
730
+ label: item,
731
+ };
732
+ });
733
+ } else {
734
+ displayObj[name] = {
735
+ value: refValue,
736
+ label: refValue,
737
+ };
738
+ }
739
+ }
740
+ } else if (
741
+ fType == "master_detail" &&
742
+ _.isString(field.reference_to)
743
+ ) {
744
+ let refTo = field.reference_to;
745
+ let refField = field.reference_to_field || "_id";
746
+
747
+ if (refTo === "users") {
748
+ refTo = "space_users";
749
+ refField = "user";
750
+ }
751
+ let refValue = doc[name];
752
+ if (!refValue) {
753
+ continue;
754
+ }
755
+ let refObj = steedosSchema.getObject(refTo);
756
+ let nameFieldKey = await refObj.getNameFieldKey();
757
+
758
+ let objectDataLoader =
759
+ refObj.enable_dataloader != false &&
760
+ process.env.STEEDOS_GRAPHQL_ENABLE_DATALOADER != "false";
761
+
762
+ if (objectDataLoader) {
763
+ const results = await getObjectDisplayData(
764
+ "api",
765
+ field.reference_to,
766
+ name,
767
+ refField,
768
+ graphqlCtx.objectDataLoaderHandler,
769
+ graphqlCtx,
770
+ );
771
+ if (field.multiple) {
772
+ displayObj[name] = _.map(results, (item) => {
773
+ return {
774
+ objectName: refTo,
775
+ value: item ? item._id : refValue,
776
+ label: item ? item[nameFieldKey] : refValue,
777
+ };
778
+ });
779
+ } else {
780
+ displayObj[name] = {
781
+ objectName: refTo,
782
+ value: results._id || refValue,
783
+ label: results[nameFieldKey] || refValue,
784
+ };
823
785
  }
786
+ } else {
787
+ if (field.multiple) {
788
+ let refRecords = await refObj.find({
789
+ filters: [refField, "in", refValue],
790
+ fields: [nameFieldKey],
791
+ });
792
+ displayObj[name] = _.map(refRecords, (item) => {
793
+ return {
794
+ objectName: refTo,
795
+ value: item._id,
796
+ label: item[nameFieldKey],
797
+ };
798
+ });
799
+ } else {
800
+ let refRecord = (
801
+ await refObj.find({
802
+ filters: [refField, "=", refValue],
803
+ fields: [nameFieldKey],
804
+ })
805
+ )[0];
806
+ if (refRecord) {
807
+ displayObj[name] = {
808
+ objectName: refTo,
809
+ value: refRecord._id,
810
+ label: refRecord[nameFieldKey],
811
+ };
812
+ }
813
+ }
814
+ }
815
+ } else if (
816
+ (fType == "master_detail" || fType == "lookup") &&
817
+ ((field.reference_to && !_.isString(field.reference_to)) ||
818
+ _.isString(field._reference_to))
819
+ ) {
820
+ let refValue = doc[name];
821
+ if (!refValue) {
822
+ continue;
823
+ }
824
+ let refTo = refValue.o;
825
+ let refValues = refValue.ids;
826
+ if (!refTo) {
827
+ continue;
828
+ }
829
+ let refObj = steedosSchema.getObject(refTo);
830
+ let nameFieldKey = await refObj.getNameFieldKey();
831
+ let refRecords = await refObj.find({
832
+ filters: [`_id`, "in", refValues],
833
+ fields: [nameFieldKey],
834
+ });
835
+
836
+ displayObj[name] = _.map(refRecords, (item) => {
837
+ return {
838
+ objectName: refTo,
839
+ value: item._id,
840
+ label: item[nameFieldKey],
841
+ };
842
+ });
843
+ } else if (fType == "formula") {
844
+ displayObj[name] = formatBasicFieldValue(
845
+ field.data_type,
846
+ field,
847
+ doc[name],
848
+ objConfig,
849
+ userSession,
850
+ );
851
+ } else if (fType == "summary") {
852
+ displayObj[name] = formatBasicFieldValue(
853
+ dataType,
854
+ field,
855
+ doc[name],
856
+ objConfig,
857
+ userSession,
858
+ );
859
+ } else if (
860
+ fType == "image" ||
861
+ fType == "file" ||
862
+ fType === "avatar"
863
+ ) {
864
+ const optionsStr = fType == "file" ? "" : "";
865
+ let fileValue: any = null;
866
+ let value = doc[name];
867
+ if (!value) {
868
+ continue;
869
+ }
870
+ // TODO: cfs_images_filerecord对象不存在,需要额外处理
871
+ let storageName = getFileStorageName(fType);
872
+ let fileObjectName = `cfs_${storageName}_filerecord`;
873
+ let fileObject = steedosSchema.getObject(fileObjectName);
874
+ const fileNameFieldKey = "original.name";
875
+ if (field.multiple) {
876
+ let fileRecords = await fileObject.find({
877
+ filters: [`_id`, "in", value],
878
+ fields: [
879
+ "_id",
880
+ fileNameFieldKey,
881
+ "original.size",
882
+ "original.type",
883
+ ],
884
+ });
885
+ fileValue = _.map(fileRecords, (fileRecord) => {
886
+ const fName = fileRecord.original?.name;
887
+ return {
888
+ name: fName,
889
+ url: absoluteUrl(
890
+ `/api/v6/files/download/cfs.${storageName}.filerecord/${fileRecord._id}/${fName}${optionsStr}`,
891
+ ),
892
+ size: fileRecord.original?.size,
893
+ type: fileRecord.original?.type,
894
+ };
895
+ });
896
+ } else {
897
+ let fileRecord = (
898
+ await fileObject.find({
899
+ filters: [`_id`, "=", value],
900
+ fields: [
901
+ "_id",
902
+ fileNameFieldKey,
903
+ "original.size",
904
+ "original.type",
905
+ ],
906
+ })
907
+ )[0];
908
+ if (fileRecord) {
909
+ const fName = fileRecord["original"]["name"];
910
+ fileValue = {
911
+ name: fName,
912
+ url: absoluteUrl(
913
+ `/api/v6/files/download/cfs.${storageName}.filerecord/${value}/${fName}${optionsStr}`,
914
+ ),
915
+ size: fileRecord.original?.size,
916
+ type: fileRecord.original?.type,
917
+ };
918
+ } else {
919
+ fileValue = {
920
+ url: value,
921
+ };
922
+ }
923
+ }
924
+ displayObj[name] = fileValue;
925
+ } else if (fType == "filesize") {
926
+ displayObj[name] = formatFileSize(doc[name]);
927
+ } else if (fType === "object") {
928
+ if (doc[name] && _.isObject(doc[name])) {
929
+ const _doc = {};
930
+ _.each(doc[name], function (v, k) {
931
+ const newKey = `${name}.${k}`;
932
+ _doc[newKey] = v;
933
+ });
934
+ const objectFieldDoc = await _translateToUI(
935
+ _doc,
936
+ Object.keys(_doc),
937
+ doc,
938
+ );
939
+ const objectDoc = {};
940
+ _.each(objectFieldDoc, function (v, k) {
941
+ const newKey = k.replace(`${name}.`, "");
942
+ objectDoc[newKey] = v;
943
+ });
944
+ displayObj[name] = objectDoc;
945
+ }
946
+ } else if (fType === "grid" || "table" === fType) {
947
+ if (doc[name] && _.isArray(doc[name])) {
948
+ const gridDocs = [];
949
+ for (const gridDoc of doc[name]) {
950
+ const _doc = {};
951
+ _.each(gridDoc, function (v, k) {
952
+ const newKey = `${name}.$.${k}`;
953
+ _doc[newKey] = v;
954
+ });
955
+ const objectFieldDoc = await _translateToUI(
956
+ _doc,
957
+ Object.keys(_doc),
958
+ doc,
959
+ );
960
+ const objectDoc = {};
961
+ _.each(objectFieldDoc, function (v, k) {
962
+ const newKey = k.replace(`${name}.$.`, "");
963
+ objectDoc[newKey] = v;
964
+ });
965
+ gridDocs.push(objectDoc);
966
+ }
967
+
968
+ displayObj[name] = gridDocs;
969
+ }
970
+ } else {
971
+ displayObj[name] = formatBasicFieldValue(
972
+ fType,
973
+ field,
974
+ doc[name],
975
+ objConfig,
976
+ userSession,
977
+ );
824
978
  }
979
+ } else {
980
+ displayObj[name] = ""; // 如果值为空,均返回空字符串
981
+ }
982
+ } catch (error) {
983
+ displayObj[name] = doc[name];
984
+ // console.warn(error)
825
985
  }
826
- return displayObj
986
+ }
827
987
  }
988
+ return displayObj;
989
+ }
828
990
 
829
- let uiDoc = await _translateToUI(doc, selectorFieldNames, doc)
830
- uiDoc['_id'] = doc._id;
831
- return uiDoc;
991
+ let uiDoc = await _translateToUI(doc, selectorFieldNames, doc);
992
+ uiDoc["_id"] = doc._id;
993
+ return uiDoc;
832
994
  }
833
995
 
834
996
  function getTranslatedFieldConfig(translatedObject: any, name: string) {
835
- return translatedObject.fields[name.replace(/__label$/, "")];
836
- }
997
+ return translatedObject.fields[name.replace(/__label$/, "")];
998
+ }