@steedos/service-metadata-apps 3.0.0-beta.8 → 3.0.0-beta.80

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,81 +1,110 @@
1
1
  import { getServiceAppConfig, METADATA_TYPE, refreshApp } from ".";
2
2
  import _ = require("lodash");
3
- import { translationApp, translationObjectLabel, translationTabLabel } from '@steedos/i18n';
4
- import { getAssignedApps, getObject as _getObject, absoluteUrl } from "@steedos/objectql";
5
- import { getNotLicensedTabNames } from "./getNotLicensedTabNames"
3
+ import { defaultsDeep } from "@steedos/utils";
4
+ import {
5
+ translationApp,
6
+ translationObjectLabel,
7
+ translationTabLabel,
8
+ } from "@steedos/i18n";
9
+ import {
10
+ getAssignedApps,
11
+ getObject as _getObject,
12
+ absoluteUrl,
13
+ } from "@steedos/objectql";
14
+ import { getNotLicensedTabNames } from "./getNotLicensedTabNames";
6
15
 
7
16
  function cacherKey(appApiName: string): string {
8
- return `$steedos.#${METADATA_TYPE}.${appApiName}`
17
+ return `$steedos.#${METADATA_TYPE}.${appApiName}`;
9
18
  }
10
19
 
11
20
  async function registerApp(ctx, appApiName, data, meta) {
12
- return await ctx.broker.call('metadata.add', { key: cacherKey(appApiName), data: data }, { meta: meta });
21
+ return await ctx.broker.call(
22
+ "metadata.add",
23
+ { key: cacherKey(appApiName), data: data },
24
+ { meta: meta },
25
+ );
13
26
  }
14
27
 
15
28
  async function getSpaceApp(ctx: any, appApiName: string) {
16
- const allApps = await getAllApps(ctx);
17
- const userSession = ctx.meta.user;
18
- const spaceId = userSession.spaceId;
19
- const userApps = _.filter(allApps, function (metadataConfig) {
29
+ const allApps = await getAllApps(ctx);
30
+ const userSession = ctx.meta.user;
31
+ const spaceId = userSession.spaceId;
32
+ const userApps = _.filter(allApps, function (metadataConfig) {
33
+ const config = metadataConfig.metadata;
34
+ //只判断是否启用
35
+ if (!config.visible) {
36
+ return false;
37
+ }
38
+ if (_.has(config, "space") && config.space) {
39
+ return config.space === spaceId;
40
+ }
41
+ if (
42
+ !_.isEmpty(config.tabs) ||
43
+ !_.isEmpty(config.objects) ||
44
+ !_.isEmpty(config.mobile_objects)
45
+ ) {
46
+ return true;
47
+ }
48
+ return true;
49
+ });
50
+
51
+ return _.find(userApps, function (metadataConfig) {
52
+ const config = metadataConfig.metadata;
53
+ return config.space && config.code === appApiName;
54
+ });
55
+ }
56
+
57
+ async function get(ctx: any) {
58
+ const spaceAppMetadataConfig = await getSpaceApp(ctx, ctx.params.appApiName);
59
+ if (spaceAppMetadataConfig) {
60
+ return spaceAppMetadataConfig;
61
+ } else {
62
+ const metadataConfig = await ctx.broker.call(
63
+ "metadata.get",
64
+ { key: cacherKey(ctx.params.appApiName) },
65
+ { meta: ctx.meta },
66
+ );
67
+ if (metadataConfig) {
68
+ return metadataConfig;
69
+ } else {
70
+ const allApps = await getAllApps(ctx);
71
+ const userSession = ctx.meta.user;
72
+ const spaceId = userSession.spaceId;
73
+ const userApps = _.filter(allApps, function (metadataConfig) {
20
74
  const config = metadataConfig.metadata;
21
75
  //只判断是否启用
22
76
  if (!config.visible) {
23
- return false;
77
+ return false;
24
78
  }
25
- if (_.has(config, 'space') && config.space) {
26
- return config.space === spaceId;
79
+ if (_.has(config, "space") && config.space) {
80
+ return config.space === spaceId;
27
81
  }
28
- if (!_.isEmpty(config.tabs) || !_.isEmpty(config.objects) || !_.isEmpty(config.mobile_objects)) {
29
- return true;
82
+ if (
83
+ !_.isEmpty(config.tabs) ||
84
+ !_.isEmpty(config.objects) ||
85
+ !_.isEmpty(config.mobile_objects)
86
+ ) {
87
+ return true;
30
88
  }
31
89
  return true;
32
- });
33
-
34
- return _.find(userApps, function (metadataConfig) {
35
- const config = metadataConfig.metadata;
36
- return config.space && config.code === appApiName
37
- })
38
- }
39
-
40
- async function get(ctx: any) {
41
- const spaceAppMetadataConfig = await getSpaceApp(ctx, ctx.params.appApiName)
42
- if (spaceAppMetadataConfig) {
43
- return spaceAppMetadataConfig;
44
- } else {
45
- const metadataConfig = await ctx.broker.call('metadata.get', { key: cacherKey(ctx.params.appApiName) }, { meta: ctx.meta });
46
- if (metadataConfig) {
47
- return metadataConfig;
48
- } else {
49
- const allApps = await getAllApps(ctx);
50
- const userSession = ctx.meta.user;
51
- const spaceId = userSession.spaceId;
52
- const userApps = _.filter(allApps, function (metadataConfig) {
53
- const config = metadataConfig.metadata;
54
- //只判断是否启用
55
- if (!config.visible) {
56
- return false;
57
- }
58
- if (_.has(config, 'space') && config.space) {
59
- return config.space === spaceId;
60
- }
61
- if (!_.isEmpty(config.tabs) || !_.isEmpty(config.objects) || !_.isEmpty(config.mobile_objects)) {
62
- return true;
63
- }
64
- return true;
65
- })
66
- if (ctx.params.appApiName === '-') {
67
- return _.first(_.sortBy(userApps, ['metadata.sort']));
68
- }
69
- return _.find(userApps, function (metadataConfig) {
70
- const app = metadataConfig.metadata;
71
- return app.code === ctx.params.appApiName
72
- })
73
- }
90
+ });
91
+ if (ctx.params.appApiName === "-") {
92
+ return _.first(_.sortBy(userApps, ["metadata.sort"]));
93
+ }
94
+ return _.find(userApps, function (metadataConfig) {
95
+ const app = metadataConfig.metadata;
96
+ return app.code === ctx.params.appApiName;
97
+ });
74
98
  }
99
+ }
75
100
  }
76
101
 
77
102
  async function getAllApps(ctx: any) {
78
- return await ctx.broker.call('metadata.filter', { key: cacherKey("*") }, { meta: ctx.meta })
103
+ return await ctx.broker.call(
104
+ "metadata.filter",
105
+ { key: cacherKey("*") },
106
+ { meta: ctx.meta },
107
+ );
79
108
  }
80
109
 
81
110
  // async function getObject(ctx: any, objectApiName: string){
@@ -83,32 +112,32 @@ async function getAllApps(ctx: any) {
83
112
  // }
84
113
 
85
114
  async function getAllTabs(ctx: any) {
86
- return await ctx.broker.call('tabs.getAll');
115
+ return await ctx.broker.call("tabs.getAll");
87
116
  }
88
117
 
89
118
  async function getContext(ctx: any) {
90
- const userSession = ctx.meta.user;
91
- const allTabs = await getAllTabs(ctx);
92
- if(userSession.is_space_admin){
93
- return {
94
- tabs: allTabs,
95
- hiddenTabNames: []
96
- }
97
- }
98
- // const allObject = await getSteedosSchema().getAllObject()
99
- let hiddenTabNames = await getHiddenTabNames(ctx, allTabs)
100
- const notLicensedTabNames = await getNotLicensedTabNames(ctx, allTabs)
101
- hiddenTabNames = hiddenTabNames.concat(notLicensedTabNames)
119
+ const userSession = ctx.meta.user;
120
+ const allTabs = await getAllTabs(ctx);
121
+ if (userSession.is_space_admin) {
102
122
  return {
103
- tabs: allTabs,
104
- // objects: allObject,
105
- hiddenTabNames: hiddenTabNames
106
- }
123
+ tabs: allTabs,
124
+ hiddenTabNames: [],
125
+ };
126
+ }
127
+ // const allObject = await getSteedosSchema().getAllObject()
128
+ let hiddenTabNames = await getHiddenTabNames(ctx, allTabs);
129
+ const notLicensedTabNames = await getNotLicensedTabNames(ctx, allTabs);
130
+ hiddenTabNames = hiddenTabNames.concat(notLicensedTabNames);
131
+ return {
132
+ tabs: allTabs,
133
+ // objects: allObject,
134
+ hiddenTabNames: hiddenTabNames,
135
+ };
107
136
  }
108
137
 
109
138
  async function getTab(ctx: any, tabApiName: string) {
110
- const metadataConfig = await ctx.broker.call('tabs.get', { tabApiName });
111
- return metadataConfig?.metadata;
139
+ const metadataConfig = await ctx.broker.call("tabs.get", { tabApiName });
140
+ return metadataConfig?.metadata;
112
141
  }
113
142
 
114
143
  // async function getChildren(ctx: any, tabApiName: string){
@@ -116,470 +145,623 @@ async function getTab(ctx: any, tabApiName: string) {
116
145
  // }
117
146
 
118
147
  function getTabChildren(context: any, tabApiName: string) {
119
- if (context) {
120
- const { tabs } = context;
121
- return _.filter(tabs, function (tab) {
122
- return tab?.metadata.parent === tabApiName
123
- })
124
- }
148
+ if (context) {
149
+ const { tabs } = context;
150
+ return _.filter(tabs, function (tab) {
151
+ return tab?.metadata.parent === tabApiName;
152
+ });
153
+ }
125
154
  }
126
155
 
127
156
  /**
128
157
  * 判断tab是否符合mobile配置
129
- * @param tab
158
+ * @param tab
130
159
  * @param mobile 是否是在移动设备上显示tab
131
- * @returns
160
+ * @returns
132
161
  */
133
162
  function checkTabMobile(tab, mobile) {
134
- let isChecked = false;
135
- if (mobile === true || mobile === "true") {
136
- isChecked = tab.mobile !== false;
137
- }
138
- else {
139
- isChecked = tab.desktop !== false;
140
- }
141
- return isChecked;
163
+ let isChecked = false;
164
+ if (mobile === true || mobile === "true") {
165
+ isChecked = tab.mobile !== false;
166
+ } else {
167
+ isChecked = tab.desktop !== false;
168
+ }
169
+ return isChecked;
142
170
  }
143
171
  function checkAppMobile(app, mobile) {
144
- let isChecked = false;
145
- // 手机端访问
146
- if (mobile === true || mobile === "true") {
147
- isChecked = app.mobile === true;
148
- }
149
- else {
150
- // 桌面端访问
151
- isChecked = app.is_creator === true
152
- }
153
- return isChecked;
172
+ let isChecked = false;
173
+ // 手机端访问
174
+ if (mobile === true || mobile === "true") {
175
+ isChecked = app.mobile === true;
176
+ } else {
177
+ // 桌面端访问
178
+ isChecked = app.is_creator === true;
179
+ }
180
+ return isChecked;
154
181
  }
155
182
 
156
183
  /**
157
184
  * 根据选项卡权限的配置决定选项卡是否可见,默认可见,关闭的和隐藏的选项卡不可见
158
- * @param ctx
185
+ * @param ctx
159
186
  * @return ['tabName', ...]
160
187
  */
161
188
  async function getHiddenTabNames(ctx, allTabs) {
162
- const userSession = ctx.meta.user
163
- if (!userSession) {
164
- throw new Error('no permission.')
189
+ const userSession = ctx.meta.user;
190
+ if (!userSession) {
191
+ throw new Error("no permission.");
192
+ }
193
+ const hiddenTabNames = [];
194
+ const permissionTabs = await getPermissionTabs(ctx, userSession);
195
+ const showTabNames = []; // 同一个选项卡在不同权限集中的权限叠加,如有一个是默认打开的则选项卡默认打开
196
+ for (const permissionTab of permissionTabs) {
197
+ if (permissionTab.permission === "on") {
198
+ showTabNames.push(permissionTab.tab);
165
199
  }
166
- const hiddenTabNames = []
167
- const permissionTabs = await getPermissionTabs(ctx, userSession)
168
- const showTabNames = [] // 同一个选项卡在不同权限集中的权限叠加,如有一个是默认打开的则选项卡默认打开
169
- for (const permissionTab of permissionTabs) {
170
- if (permissionTab.permission === 'on') {
171
- showTabNames.push(permissionTab.tab)
172
- }
173
- }
174
- for (const permissionTab of permissionTabs) {
175
- if ((permissionTab.permission === 'off' || permissionTab.permission === 'hidden') && !showTabNames.includes(permissionTab.tab)) {
176
- hiddenTabNames.push(permissionTab.tab)
177
- }
200
+ }
201
+ for (const permissionTab of permissionTabs) {
202
+ if (
203
+ (permissionTab.permission === "off" ||
204
+ permissionTab.permission === "hidden") &&
205
+ !showTabNames.includes(permissionTab.tab)
206
+ ) {
207
+ hiddenTabNames.push(permissionTab.tab);
178
208
  }
209
+ }
179
210
 
180
- // .tab.yml中配置了hidden:true
181
- for (const config of allTabs) {
182
- if (config.metadata && config.metadata.hidden) {
183
- hiddenTabNames.push(config.metadata.name)
184
- }
211
+ // .tab.yml中配置了hidden:true
212
+ for (const config of allTabs) {
213
+ if (config.metadata && config.metadata.hidden) {
214
+ hiddenTabNames.push(config.metadata.name);
185
215
  }
216
+ }
186
217
 
187
- return hiddenTabNames
218
+ return hiddenTabNames;
188
219
  }
189
220
 
190
- async function getPermissionTabs(ctx, userSession): Promise<any[]>{
191
- const { roles, spaceId } = userSession
192
- const permissionTabs = []
193
- for (const role of roles) {
194
- const pattern = `${role}_*`
195
- const filterResult = await ctx.broker.call('permission_tabs.filter', {
196
- pattern: pattern,
197
- }, {
198
- user: { spaceId: spaceId }
199
- });
200
- for (const ptConfig of filterResult) {
201
- if (ptConfig.metadata.permission_set === role && (!_.has(ptConfig.metadata, 'space') || ptConfig.metadata.space === spaceId)) {
202
- permissionTabs.push(ptConfig.metadata)
203
- }
204
- }
221
+ async function getPermissionTabs(ctx, userSession): Promise<any[]> {
222
+ const { roles, spaceId } = userSession;
223
+ const permissionTabs = [];
224
+ for (const role of roles) {
225
+ const pattern = `${role}_*`;
226
+ const filterResult = await ctx.broker.call(
227
+ "permission_tabs.filter",
228
+ {
229
+ pattern: pattern,
230
+ },
231
+ {
232
+ user: { spaceId: spaceId },
233
+ },
234
+ );
235
+ for (const ptConfig of filterResult) {
236
+ if (
237
+ ptConfig.metadata.permission_set === role &&
238
+ (!_.has(ptConfig.metadata, "space") ||
239
+ ptConfig.metadata.space === spaceId)
240
+ ) {
241
+ permissionTabs.push(ptConfig.metadata);
242
+ }
205
243
  }
206
- return permissionTabs
244
+ }
245
+ return permissionTabs;
207
246
  }
208
247
 
248
+ async function tabMenus(
249
+ ctx: any,
250
+ appPath,
251
+ tabApiName,
252
+ menu,
253
+ mobile,
254
+ userSession,
255
+ context,
256
+ props: any = {},
257
+ ) {
258
+ try {
259
+ // const objectsConfigs = context.objects;
260
+ const tab = await getTab(ctx, tabApiName);
261
+ if (props.group) {
262
+ props.group =
263
+ _.find(menu.tab_groups, { id: props.group })?.group_name || props.group;
264
+ }
209
265
 
210
- async function tabMenus(ctx: any, appPath, tabApiName, menu, mobile, userSession, context, props:any = {}) {
211
- try {
212
- // const objectsConfigs = context.objects;
213
- const tab = await getTab(ctx, tabApiName);
214
- if(props.group){
215
- props.group = _.find(menu.tab_groups, { id: props.group })?.group_name || props.group;
216
- }
266
+ if (tabApiName) {
267
+ props.tabApiName = tabApiName;
268
+ }
217
269
 
218
- if(tabApiName){
219
- props.tabApiName = tabApiName;
270
+ if (tab) {
271
+ const isMobileChecked = checkTabMobile(tab, mobile);
272
+ if (!isMobileChecked) {
273
+ return;
274
+ }
275
+ const tabChildren = getTabChildren(context, tabApiName);
276
+
277
+ if (tabChildren && tabChildren.length > 0) {
278
+ const tabMenu = {
279
+ id: tab.name,
280
+ icon: tab.icon,
281
+ name: `${tab.label}`,
282
+ children: [],
283
+ ...props,
284
+ };
285
+ for (const { metadata: tabChild } of tabChildren) {
286
+ if (tabChild && tabChild.apiName) {
287
+ await tabMenus(
288
+ ctx,
289
+ appPath,
290
+ tabChild.apiName,
291
+ tabMenu,
292
+ mobile,
293
+ userSession,
294
+ context,
295
+ );
296
+ }
220
297
  }
221
-
222
- if (tab) {
223
- const isMobileChecked = checkTabMobile(tab, mobile)
224
- if (!isMobileChecked) {
225
- return;
226
- }
227
- const tabChildren = getTabChildren(context, tabApiName);
228
-
229
- if (tabChildren && tabChildren.length > 0) {
230
- const tabMenu = {
231
- id: tab.name,
232
- icon: tab.icon,
233
- name: `${tab.label}`,
234
- children: [],
235
- ...props
236
- };
237
- for (const { metadata: tabChild } of tabChildren) {
238
- if (tabChild && tabChild.apiName) {
239
- await tabMenus(ctx, appPath, tabChild.apiName, tabMenu, mobile, userSession, context);
240
- }
241
- }
242
- menu.children.push(tabMenu);
243
- } else {
244
- if (tab.type === 'object') {
245
- const allowRead = await objectAllowRead(tab.object, userSession);
246
- if (!allowRead) {
247
- return;
248
- }
249
- // const objectMetadata = await getObject(ctx, tab.object);
250
- // const objectMetadata = _.find(objectsConfigs, (config) => {
251
- // return config && config.metadata.name === tab.object
252
- // });
253
- const objectConfig = await _getObject(tab.object).getConfig()
254
- if (objectConfig) {
255
- // const objectConfig = objectMetadata.metadata;
256
- const objectLabel = translationObjectLabel(userSession.language, objectConfig.name, objectConfig.label || objectConfig.name)
257
- menu.children.push(
258
- {
259
- id: objectConfig.name,
260
- type: tab.type,
261
- icon: objectConfig.icon,
262
- path: `${appPath}/${objectConfig.name}`,
263
- name: `${objectLabel}`,
264
- ...props
265
- }
266
- )
267
- }
268
- }
269
- if (tab.type === 'url') {
270
- tab.label = translationTabLabel(userSession.language, tab.name, tab.label || tab.name);
271
- let urlMenu: any = {
272
- id: `${tab.name}`,
273
- type: tab.type,
274
- icon: tab.icon,
275
- path: `${tab.url}`,
276
- name: `${tab.label}`,
277
- ...props
278
- };
279
- if (tab.is_new_window) {
280
- urlMenu.target = '_blank'
281
- }else if(tab.is_use_iframe){
282
- urlMenu.is_use_iframe = true;
283
- urlMenu.path = `${appPath}/tab_iframe/${tab.name}/?url=${tab.url}`
284
- }
285
- menu.children.push(
286
- urlMenu
287
- )
288
- }
289
- if (tab.type === 'page') {
290
- tab.label = translationTabLabel(userSession.language, tab.name, tab.label || tab.name);
291
- menu.children.push(
292
- {
293
- id: `${tab.name}`,
294
- icon: tab.icon,
295
- type: tab.type,
296
- page: tab.page,
297
- path: `${appPath}/${tab.type}/${tab.page}`,
298
- name: `${tab.label}`,
299
- ...props
300
- }
301
- )
302
- }
303
- }
298
+ menu.children.push(tabMenu);
299
+ } else {
300
+ if (tab.type === "object") {
301
+ const allowRead = await objectAllowRead(tab.object, userSession);
302
+ if (!allowRead) {
303
+ return;
304
+ }
305
+ // const objectMetadata = await getObject(ctx, tab.object);
306
+ // const objectMetadata = _.find(objectsConfigs, (config) => {
307
+ // return config && config.metadata.name === tab.object
308
+ // });
309
+ const objectConfig = await _getObject(tab.object).getConfig();
310
+ if (objectConfig) {
311
+ // const objectConfig = objectMetadata.metadata;
312
+ const objectLabel = translationObjectLabel(
313
+ userSession.language,
314
+ objectConfig.name,
315
+ objectConfig.label || objectConfig.name,
316
+ );
317
+ menu.children.push({
318
+ id: objectConfig.name,
319
+ type: tab.type,
320
+ icon: objectConfig.icon,
321
+ path: `${appPath}/${objectConfig.name}`,
322
+ name: `${objectLabel}`,
323
+ ...props,
324
+ });
325
+ }
304
326
  }
305
- } catch (error) {
306
- ctx.broker.logger.info(error.message);
327
+ if (tab.type === "url") {
328
+ tab.label = translationTabLabel(
329
+ userSession.language,
330
+ tab.name,
331
+ tab.label || tab.name,
332
+ );
333
+ let urlMenu: any = {
334
+ id: `${tab.name}`,
335
+ type: tab.type,
336
+ icon: tab.icon,
337
+ path: `${tab.url}`,
338
+ name: `${tab.label}`,
339
+ ...props,
340
+ };
341
+ if (tab.is_new_window) {
342
+ urlMenu.target = "_blank";
343
+ } else if (tab.is_use_iframe) {
344
+ urlMenu.is_use_iframe = true;
345
+ urlMenu.path = `${appPath}/tab_iframe/${tab.name}/?url=${encodeURIComponent(tab.url)}`;
346
+ }
347
+ menu.children.push(urlMenu);
348
+ }
349
+ if (tab.type === "page") {
350
+ tab.label = translationTabLabel(
351
+ userSession.language,
352
+ tab.name,
353
+ tab.label || tab.name,
354
+ );
355
+ menu.children.push({
356
+ id: `${tab.name}`,
357
+ icon: tab.icon,
358
+ type: tab.type,
359
+ page: tab.page,
360
+ path: `${appPath}/${tab.type}/${tab.page}`,
361
+ name: `${tab.label}`,
362
+ ...props,
363
+ });
364
+ }
365
+ if (tab.type === "analytics_dashboard") {
366
+ const url = `/analytics/embed/dashboard/${tab.analytics_dashboard}?titled=false&bordered=false`;
367
+ tab.label = translationTabLabel(
368
+ userSession.language,
369
+ tab.name,
370
+ tab.label || tab.name,
371
+ );
372
+ let urlMenu: any = {
373
+ id: `${tab.name}`,
374
+ type: tab.type,
375
+ icon: tab.icon,
376
+ path: `${url}`,
377
+ name: `${tab.label}`,
378
+ ...props,
379
+ };
380
+ if (tab.is_new_window) {
381
+ urlMenu.target = "_blank";
382
+ } else {
383
+ urlMenu.is_use_iframe = true;
384
+ urlMenu.path = `${appPath}/tab_iframe/${tab.name}/?url=${url}`;
385
+ }
386
+ menu.children.push(urlMenu);
387
+ }
388
+ }
307
389
  }
390
+ } catch (error) {
391
+ ctx.broker.logger.info(error.message);
392
+ }
308
393
  }
309
394
  async function objectAllowRead(objectApiName: string, userSession) {
310
- return await _getObject(objectApiName).allowRead(userSession);
395
+ return await _getObject(objectApiName).allowRead(userSession);
311
396
  }
312
397
 
313
398
  async function transformAppToMenus(ctx, app, mobile, userSession, context) {
314
- if (!app.code && !app._id) {
315
- return;
316
- }
317
-
318
- const isAppShow = checkAppMobile(app, mobile);
319
- if (!isAppShow) {
320
- return;
321
- }
322
-
323
- if (!app.code) {
324
- app.code = app._id;
399
+ if (!app.code && !app._id) {
400
+ return;
401
+ }
402
+
403
+ const isAppShow = checkAppMobile(app, mobile);
404
+ if (!isAppShow) {
405
+ return;
406
+ }
407
+
408
+ if (!app.code) {
409
+ app.code = app._id;
410
+ }
411
+ translationApp(userSession.language, app.code, app);
412
+ var appPath = `/app/${app.code}`;
413
+ if (app.url) {
414
+ if (/^http(s?):\/\//.test(app.url)) {
415
+ if (app.secret) {
416
+ appPath = absoluteUrl("/api/external/app/" + (app._id || app.code));
417
+ } else {
418
+ appPath = app.url;
419
+ }
420
+ } else {
421
+ appPath = app.url;
325
422
  }
326
- translationApp(userSession.language, app.code, app);
327
- var appPath = `/app/${app.code}`
328
- if(app.url){
329
- if(/^http(s?):\/\//.test(app.url)){
330
- if(app.secret){
331
- appPath = absoluteUrl("/api/external/app/" + (app._id || app.code))
332
- }else{
333
- appPath = app.url
334
- }
335
- }else{
336
- appPath = app.url
423
+ }
424
+ const menu: any = {
425
+ id: app.code,
426
+ path: appPath,
427
+ name: `${app.label || app.name}`,
428
+ icon: app.icon_slds,
429
+ showSidebar: app.showSidebar,
430
+ description: app.description,
431
+ children: [],
432
+ blank: app.is_new_window,
433
+ on_click: app.on_click,
434
+ isExternalUrl: !!app.url,
435
+ tab_groups: app.tab_groups,
436
+ is_hide_mobile_menu: app.is_hide_mobile_menu,
437
+ visible_on: app.visible_on || "${true}",
438
+ };
439
+ if (app.enable_nav_schema && app.nav_schema && !mobile) {
440
+ menu.nav_schema = _.isString(app.nav_schema)
441
+ ? JSON.parse(app.nav_schema)
442
+ : app.nav_schema;
443
+ }
444
+
445
+ const hiddenTabNames = context.hiddenTabNames || [];
446
+ if (app.tab_items) {
447
+ // app.tab_items is array
448
+ if (_.isArray(app.tab_items)) {
449
+ for (const item of app.tab_items) {
450
+ try {
451
+ if (hiddenTabNames.includes(item.tab_name)) continue;
452
+ await tabMenus(
453
+ ctx,
454
+ appPath,
455
+ item.tab_name,
456
+ menu,
457
+ mobile,
458
+ userSession,
459
+ context,
460
+ item,
461
+ );
462
+ } catch (error) {
463
+ ctx.broker.logger.info(error.message);
464
+ }
465
+ }
466
+ } else {
467
+ for (const tabApiName in app.tab_items) {
468
+ try {
469
+ if (hiddenTabNames.includes(tabApiName)) continue;
470
+ const props = app.tab_items[tabApiName];
471
+ await tabMenus(
472
+ ctx,
473
+ appPath,
474
+ tabApiName,
475
+ menu,
476
+ mobile,
477
+ userSession,
478
+ context,
479
+ props,
480
+ );
481
+ } catch (error) {
482
+ ctx.broker.logger.info(error.message);
337
483
  }
484
+ }
338
485
  }
339
- const menu: any = {
340
- id: app.code,
341
- path: appPath,
342
- name: `${app.label || app.name}`,
343
- icon: app.icon_slds,
344
- showSidebar: app.showSidebar,
345
- description: app.description,
346
- children: [],
347
- blank: app.is_new_window,
348
- on_click: app.on_click,
349
- isExternalUrl: !!app.url,
350
- tab_groups: app.tab_groups,
351
- is_hide_mobile_menu: app.is_hide_mobile_menu,
352
- visible_on: app.visible_on || "${true}"
486
+ } else if (_.isArray(app.tabs)) {
487
+ for (const tabApiName of app.tabs) {
488
+ try {
489
+ if (hiddenTabNames.includes(tabApiName)) continue;
490
+ await tabMenus(
491
+ ctx,
492
+ appPath,
493
+ tabApiName,
494
+ menu,
495
+ mobile,
496
+ userSession,
497
+ context,
498
+ );
499
+ } catch (error) {
500
+ ctx.broker.logger.info(error.message);
501
+ }
353
502
  }
354
- if(app.enable_nav_schema && app.nav_schema && !mobile){
355
- menu.nav_schema = _.isString(app.nav_schema) ? JSON.parse(app.nav_schema) : app.nav_schema
503
+ }
504
+ const objects = mobile ? app.mobile_objects : app.objects;
505
+ // const objectsConfigs = context.objects;
506
+ if (_.isArray(objects)) {
507
+ const getChildrenPromises = [];
508
+ for (const objectApiName of objects) {
509
+ getChildrenPromises.push(
510
+ getMenuChildren({
511
+ objectApiName,
512
+ userSession,
513
+ ctx,
514
+ appPath,
515
+ app,
516
+ }),
517
+ );
356
518
  }
357
-
358
- const hiddenTabNames = context.hiddenTabNames || []
359
- if (app.tab_items) {
360
- // app.tab_items is array
361
- if (_.isArray(app.tab_items)) {
362
- for (const item of app.tab_items) {
363
- try {
364
- if (hiddenTabNames.includes(item.tab_name)) continue;
365
- await tabMenus(ctx, appPath, item.tab_name, menu, mobile, userSession, context, item)
366
- } catch (error) {
367
- ctx.broker.logger.info(error.message);
368
- }
369
- }
370
- } else {
371
- for (const tabApiName in app.tab_items) {
372
- try {
373
- if (hiddenTabNames.includes(tabApiName)) continue;
374
- const props = app.tab_items[tabApiName]
375
- await tabMenus(ctx, appPath, tabApiName, menu, mobile, userSession, context, props)
376
- } catch (error) {
377
- ctx.broker.logger.info(error.message);
378
- }
379
- }
380
- }
381
- } else if (_.isArray(app.tabs)) {
382
- for (const tabApiName of app.tabs) {
383
- try {
384
- if (hiddenTabNames.includes(tabApiName)) continue;
385
- await tabMenus(ctx, appPath, tabApiName, menu, mobile, userSession, context)
386
- } catch (error) {
387
- ctx.broker.logger.info(error.message);
388
- }
389
- }
519
+ const children = await Promise.all(getChildrenPromises);
520
+ for (const child of children) {
521
+ if (child) {
522
+ menu.children.push(child);
523
+ }
390
524
  }
391
- const objects = mobile ? app.mobile_objects : app.objects
392
- // const objectsConfigs = context.objects;
393
- if (_.isArray(objects)) {
394
- const getChildrenPromises = []
395
- for (const objectApiName of objects) {
396
- getChildrenPromises.push(getMenuChildren({
397
- objectApiName, userSession, ctx, appPath, app
398
- }))
399
- }
400
- const children = await Promise.all(getChildrenPromises)
401
- for (const child of children) {
402
- if (child) {
403
- menu.children.push(child)
404
- }
405
- }
406
- }
407
-
408
- return menu;
525
+ }
526
+
527
+ return menu;
409
528
  }
410
529
 
411
- async function getMenuChildren({ objectApiName, userSession, ctx, appPath, app }) {
412
- try {
413
- const objectConfig = await _getObject(objectApiName).getConfig()
414
- if (!objectConfig) {
415
- ctx.broker.logger.error(`${objectApiName} is not found in the objects of app ${app.code} `)
416
- return
417
- }
418
- const allowRead = await objectAllowRead(objectApiName, userSession);
419
- if (!allowRead) {
420
- return
421
- }
422
- if (objectConfig) {
423
- // const objectConfig = objectMetadata.metadata;
424
- const objectLabel = translationObjectLabel(userSession.language, objectConfig.name, objectConfig.label || objectConfig.name)
425
- return {
426
- id: objectConfig.name,
427
- icon: objectConfig.icon,
428
- path: `${appPath}/${objectConfig.name}`,
429
- name: `${objectLabel}`
430
- }
431
- }
432
- } catch (error) {
433
- ctx.broker.logger.error(error);
530
+ async function getMenuChildren({
531
+ objectApiName,
532
+ userSession,
533
+ ctx,
534
+ appPath,
535
+ app,
536
+ }) {
537
+ try {
538
+ const objectConfig = await _getObject(objectApiName).getConfig();
539
+ if (!objectConfig) {
540
+ ctx.broker.logger.error(
541
+ `${objectApiName} is not found in the objects of app ${app.code} `,
542
+ );
543
+ return;
434
544
  }
545
+ const allowRead = await objectAllowRead(objectApiName, userSession);
546
+ if (!allowRead) {
547
+ return;
548
+ }
549
+ if (objectConfig) {
550
+ // const objectConfig = objectMetadata.metadata;
551
+ const objectLabel = translationObjectLabel(
552
+ userSession.language,
553
+ objectConfig.name,
554
+ objectConfig.label || objectConfig.name,
555
+ );
556
+ return {
557
+ id: objectConfig.name,
558
+ icon: objectConfig.icon,
559
+ path: `${appPath}/${objectConfig.name}`,
560
+ name: `${objectLabel}`,
561
+ };
562
+ }
563
+ } catch (error) {
564
+ ctx.broker.logger.error(error);
565
+ }
435
566
  }
436
567
 
437
568
  async function getAppsMenus(ctx) {
438
- const userSession = ctx.meta.user;
439
- if (!userSession) {
440
- throw new Error('no permission.')
441
- }
442
- let assigned_apps = await getAssignedApps(userSession);
443
- let mobile = ctx.params.mobile;
444
- if (typeof mobile !== 'boolean') {
445
- mobile = mobile === "true" ? true : false;
446
- }
447
- const spaceId = userSession.spaceId;
448
- const metadataApps = await getAllApps(ctx);
449
- const context = await getContext(ctx)
450
- const allApps = _.map(metadataApps, 'metadata');
451
- if (assigned_apps && assigned_apps.length) {
452
- assigned_apps = _.filter(allApps, (item) => { return assigned_apps.includes(item.code) });
453
- } else {
454
- assigned_apps = allApps;
569
+ const userSession = ctx.meta.user;
570
+ if (!userSession) {
571
+ throw new Error("no permission.");
572
+ }
573
+ let assigned_apps = await getAssignedApps(userSession);
574
+ let mobile = ctx.params.mobile;
575
+ if (typeof mobile !== "boolean") {
576
+ mobile = mobile === "true" ? true : false;
577
+ }
578
+ const spaceId = userSession.spaceId;
579
+ const metadataApps = await getAllApps(ctx);
580
+ const context = await getContext(ctx);
581
+ const allApps = _.map(metadataApps, "metadata");
582
+ if (assigned_apps && assigned_apps.length) {
583
+ assigned_apps = _.filter(allApps, (item) => {
584
+ return assigned_apps.includes(item.code);
585
+ });
586
+ } else {
587
+ assigned_apps = allApps;
588
+ }
589
+ const _userApps = _.filter(assigned_apps, function (config) {
590
+ if (!config.visible) {
591
+ return false;
455
592
  }
456
- const _userApps = _.filter(assigned_apps, function (config) {
457
- if (!config.visible) {
458
- return false;
459
- }
460
593
 
461
- if (config._id === config.code) {
462
- let dbApp = _.find(assigned_apps, (item) => {
463
- return item.code === config.code && item._id != item.code && item.space === spaceId;
464
- });
465
- if (dbApp) {
466
- return dbApp.visible
467
- }
468
- }
594
+ if (config._id === config.code) {
595
+ let dbApp = _.find(assigned_apps, (item) => {
596
+ return (
597
+ item.code === config.code &&
598
+ item._id != item.code &&
599
+ item.space === spaceId
600
+ );
601
+ });
602
+ if (dbApp) {
603
+ return dbApp.visible;
604
+ }
605
+ }
469
606
 
470
- if (_.has(config, 'space') && config.space) {
471
- return config.space === spaceId;
472
- }
473
- return true;
474
- })
475
- const menus = [];
607
+ if (_.has(config, "space") && config.space) {
608
+ return config.space === spaceId;
609
+ }
610
+ return true;
611
+ });
612
+ const menus = [];
476
613
 
477
- let userApps = [];
478
- _.each(_.sortBy(_userApps, ['sort']), function (app) {
479
- if (!app.code) {
480
- app.code = app._id;
481
- }
482
- const _appIndex = _.findIndex(userApps, function (item) { return item.code === app.code });
483
- if (_appIndex < 0) {
484
- userApps.push(app)
485
- } else {
486
- const _app = userApps[_appIndex];
487
- if (!_app.space && app.space) {
488
- userApps[_appIndex] = app;
489
- }
490
- }
491
- })
492
- for (const app of _.sortBy(userApps, ['sort'])) {
493
- const menu = await transformAppToMenus(ctx, app, mobile, userSession, context);
494
- if (menu) {
495
- menus.push(menu);
496
- }
614
+ let userApps = [];
615
+ _.each(_.sortBy(_userApps, ["sort"]), function (app) {
616
+ if (!app.code) {
617
+ app.code = app._id;
497
618
  }
498
- // if (!mobile) {
499
- // const setupApp = {
500
- // code: 'admin',
501
- // name: '设置',
502
- // icon_slds: 'settings',
503
- // description: '管理员设置公司、人员、权限等。',
504
- // children: [],
505
- // mobile: true,
506
- // is_creator: true,
507
- // }
508
- // const menu = await transformAppToMenus(ctx, setupApp, mobile, userSession, context);
509
- // menus.push(menu);
510
- // }
511
- return menus;
619
+ const _appIndex = _.findIndex(userApps, function (item) {
620
+ return item.code === app.code;
621
+ });
622
+ if (_appIndex < 0) {
623
+ userApps.push(app);
624
+ } else {
625
+ const _app = userApps[_appIndex];
626
+ if (!_app.space && app.space) {
627
+ userApps[_appIndex] = app;
628
+ }
629
+ }
630
+ });
631
+ for (const app of _.sortBy(userApps, ["sort"])) {
632
+ const menu = await transformAppToMenus(
633
+ ctx,
634
+ app,
635
+ mobile,
636
+ userSession,
637
+ context,
638
+ );
639
+ if (menu) {
640
+ menus.push(menu);
641
+ }
642
+ }
643
+ // if (!mobile) {
644
+ // const setupApp = {
645
+ // code: 'admin',
646
+ // name: '设置',
647
+ // icon_slds: 'settings',
648
+ // description: '管理员设置公司、人员、权限等。',
649
+ // children: [],
650
+ // mobile: true,
651
+ // is_creator: true,
652
+ // }
653
+ // const menu = await transformAppToMenus(ctx, setupApp, mobile, userSession, context);
654
+ // menus.push(menu);
655
+ // }
656
+ return menus;
512
657
  }
513
658
 
514
659
  async function getAppMenus(ctx) {
515
- const userSession = ctx.meta.user;
516
- const { mobile } = ctx.params;
517
- if (!userSession) {
518
- throw new Error('no permission.')
660
+ const userSession = ctx.meta.user;
661
+ const { mobile } = ctx.params;
662
+ if (!userSession) {
663
+ throw new Error("no permission.");
664
+ }
665
+ const spaceId = userSession.spaceId;
666
+ const metadataConf = await get(ctx);
667
+ if (metadataConf) {
668
+ const appConfig = metadataConf.metadata;
669
+ if (
670
+ _.has(appConfig, "space") &&
671
+ appConfig.space &&
672
+ appConfig.space != spaceId
673
+ ) {
674
+ return;
519
675
  }
520
- const spaceId = userSession.spaceId;
521
- const metadataConf = await get(ctx);
522
- if (metadataConf) {
523
- const appConfig = metadataConf.metadata;
524
- if (_.has(appConfig, 'space') && appConfig.space && appConfig.space != spaceId) {
525
- return;
526
- }
527
- const context = await getContext(ctx)
528
- const appMenus = await transformAppToMenus(ctx, appConfig, mobile, userSession, context);
529
-
530
- if (userSession.is_space_admin && appConfig._id && appConfig.code && appConfig._id != appConfig.code) {
531
- appMenus.allowEditApp = true;
532
- }
533
-
534
- return appMenus;
676
+ const context = await getContext(ctx);
677
+ const appMenus = await transformAppToMenus(
678
+ ctx,
679
+ appConfig,
680
+ mobile,
681
+ userSession,
682
+ context,
683
+ );
684
+
685
+ if (
686
+ userSession.is_space_admin &&
687
+ appConfig._id &&
688
+ appConfig.code &&
689
+ appConfig._id != appConfig.code
690
+ ) {
691
+ appMenus.allowEditApp = true;
535
692
  }
536
693
 
694
+ return appMenus;
695
+ }
537
696
  }
538
697
 
539
698
  export const ActionHandlers = {
540
- async get(ctx: any): Promise<any> {
541
- return await ctx.broker.call('metadata.get', { key: cacherKey(ctx.params.appApiName) }, { meta: ctx.meta })
542
- },
543
- async getAll(ctx: any): Promise<any> {
544
- return await getAllApps(ctx);
545
- },
546
- async getMenus(ctx: any): Promise<any> {
547
- const menus = await getAppsMenus(ctx);
548
- return menus;
549
- },
550
- async getAppMenus(ctx: any): Promise<any> {
551
- return await getAppMenus(ctx);
552
- },
553
- async add(ctx: any): Promise<boolean> {
554
- let config = ctx.params.data;
555
- const serviceName = ctx.meta.metadataServiceName
556
- const metadataApiName = ctx.params.appApiName;
557
- const metadataConfig = await getServiceAppConfig(ctx, serviceName, metadataApiName)
558
- if (metadataConfig && metadataConfig.metadata) {
559
- config = _.defaultsDeep(config, metadataConfig.metadata);
560
- }
561
- await ctx.broker.call('metadata.addServiceMetadata', { key: cacherKey(metadataApiName), data: config }, { meta: Object.assign({}, ctx.meta, { metadataType: METADATA_TYPE, metadataApiName: metadataApiName }) })
699
+ async get(ctx: any): Promise<any> {
700
+ return await ctx.broker.call(
701
+ "metadata.get",
702
+ { key: cacherKey(ctx.params.appApiName) },
703
+ { meta: ctx.meta },
704
+ );
705
+ },
706
+ async getAll(ctx: any): Promise<any> {
707
+ return await getAllApps(ctx);
708
+ },
709
+ async getMenus(ctx: any): Promise<any> {
710
+ const menus = await getAppsMenus(ctx);
711
+ return menus;
712
+ },
713
+ async getAppMenus(ctx: any): Promise<any> {
714
+ return await getAppMenus(ctx);
715
+ },
716
+ async add(ctx: any): Promise<boolean> {
717
+ let config = ctx.params.data;
718
+ const serviceName = ctx.meta.metadataServiceName;
719
+ const metadataApiName = ctx.params.appApiName;
720
+ const metadataConfig = await getServiceAppConfig(
721
+ ctx,
722
+ serviceName,
723
+ metadataApiName,
724
+ );
725
+ if (metadataConfig && metadataConfig.metadata) {
726
+ config = defaultsDeep(config, metadataConfig.metadata);
727
+ }
728
+ await ctx.broker.call(
729
+ "metadata.addServiceMetadata",
730
+ { key: cacherKey(metadataApiName), data: config },
731
+ {
732
+ meta: Object.assign({}, ctx.meta, {
733
+ metadataType: METADATA_TYPE,
734
+ metadataApiName: metadataApiName,
735
+ }),
736
+ },
737
+ );
738
+ const appConfig = await refreshApp(ctx, metadataApiName);
739
+ return await registerApp(ctx, metadataApiName, appConfig, ctx.meta);
740
+ },
741
+ async delete(ctx: any): Promise<boolean> {
742
+ return await ctx.broker.call(
743
+ "metadata.delete",
744
+ { key: cacherKey(ctx.params.appApiName) },
745
+ { meta: ctx.meta },
746
+ );
747
+ },
748
+ async verify(ctx: any): Promise<boolean> {
749
+ console.log("verify");
750
+ return true;
751
+ },
752
+ async refresh(ctx) {
753
+ const { isClear, metadataApiNames } = ctx.params;
754
+ if (isClear) {
755
+ for (const metadataApiName of metadataApiNames) {
562
756
  const appConfig = await refreshApp(ctx, metadataApiName);
563
- return await registerApp(ctx, metadataApiName, appConfig, ctx.meta)
564
- },
565
- async delete(ctx: any): Promise<boolean> {
566
- return await ctx.broker.call('metadata.delete', { key: cacherKey(ctx.params.appApiName) }, { meta: ctx.meta })
567
- },
568
- async verify(ctx: any): Promise<boolean> {
569
- console.log("verify");
570
- return true;
571
- },
572
- async refresh(ctx) {
573
- const { isClear, metadataApiNames } = ctx.params
574
- if (isClear) {
575
- for (const metadataApiName of metadataApiNames) {
576
- const appConfig = await refreshApp(ctx, metadataApiName);
577
- if (!appConfig) {
578
- await ctx.broker.call('metadata.delete', { key: cacherKey(metadataApiName) })
579
- } else {
580
- await registerApp(ctx, metadataApiName, appConfig, {});
581
- }
582
- }
757
+ if (!appConfig) {
758
+ await ctx.broker.call("metadata.delete", {
759
+ key: cacherKey(metadataApiName),
760
+ });
761
+ } else {
762
+ await registerApp(ctx, metadataApiName, appConfig, {});
583
763
  }
764
+ }
584
765
  }
585
- }
766
+ },
767
+ };