@genesislcap/blank-app-seed 2.7.0 → 2.9.0

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,5 +1,5 @@
1
1
  const versions = require('./versions.json');
2
- const { registerPartials, generateRoute, generateEmptyCsv, formatRouteData } = require('./utils');
2
+ const { registerPartials, generateRoute, generateEmptyCsv, formatRouteData, validateRoute } = require('./utils');
3
3
 
4
4
  /**
5
5
  * Signature is `async (data: inquirer.Answers, utils: SeedConfigurationUtils)`
@@ -14,15 +14,20 @@ module.exports = async (data, utils) => {
14
14
 
15
15
  registerPartials(utils);
16
16
 
17
- data.routes
18
- .forEach((route) => {
19
- if (!route.name) {
20
- console.warn('Invalid route - missing name', route);
21
- return;
22
- }
23
- const routeData = formatRouteData(route);
24
- generateRoute(routeData, utils);
25
- });
17
+ data.routes = data.routes
18
+ .filter(validateRoute)
19
+ .map(formatRouteData);
20
+
21
+ const FDC3EventHandlersEnabled = data.routes.find(route => route.FDC3EventHandlersEnabled);
22
+ const FDC3ListenersEnabled = data.ui?.fdc3?.channels?.length;
23
+ data.FDC3 = {
24
+ includeDependencies: !!(FDC3ListenersEnabled || FDC3EventHandlersEnabled),
25
+ channels: data.ui?.fdc3?.channels || []
26
+ };
27
+
28
+ data.routes.forEach(route => {
29
+ generateRoute(route, utils);
30
+ });
26
31
 
27
32
  data.csv
28
33
  .map(entity => ({
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesislcap/blank-app-seed-config",
3
3
  "description": "Genesis Blank App Seed Configuration",
4
- "version": "2.7.0",
4
+ "version": "2.9.0",
5
5
  "license": "Apache-2.0",
6
6
  "genxSeedConfig": {
7
7
  "exclude": [
@@ -1,16 +1,7 @@
1
1
  const {mavenArtifactVersionRegex} = require('./validators');
2
+ const {parseJSONArgument} = require('../utils');
2
3
 
3
- const parsecsv = (inputEntities) => {
4
- if (!inputEntities){
5
- return [];
6
- }
7
- try {
8
- return JSON.parse(inputEntities);
9
- } catch (error) {
10
- console.error("Error parsing `csv` parameter as JSON:", error.message);
11
- return [];
12
- }
13
- }
4
+ const parsecsv = parseJSONArgument('csv', []);
14
5
 
15
6
  module.exports = async (inquirer, prevAns = {}) => {
16
7
  const {
@@ -44,7 +35,7 @@ module.exports = async (inquirer, prevAns = {}) => {
44
35
  {
45
36
  name: 'csv',
46
37
  type: 'input',
47
- message: 'Generate empty CSV for entities? (config in json format)',
38
+ message: 'Generate empty CSV for entities? (config in JSON format)',
48
39
  when: !prevAns.csv,
49
40
  default: '[]'
50
41
  },
@@ -1,37 +1,38 @@
1
- const routesInto = () => console.log(`
1
+ const {parseJSONArgument} = require('../utils');
2
+
3
+ const defaultRoutes = [{ name: 'home' }];
4
+ const parseRoutes = parseJSONArgument('routes', defaultRoutes);
5
+ const routesIntro = () => console.log(`
2
6
  Pages to be added to the navigation header
3
7
  `);
4
8
 
5
- const defaultRoutes = '[{"name":"home"}]';
9
+ const defaultUI = {};
10
+ const parseUI = parseJSONArgument('ui', defaultUI);
6
11
 
7
12
  module.exports = async (inquirer, prevAns = {}) => {
8
- routesInto();
13
+ routesIntro();
9
14
  const {
10
15
  routes = prevAns.routes,
16
+ ui = prevAns.ui,
11
17
  } = await inquirer.prompt([
12
18
  {
13
19
  name: 'routes',
14
20
  type: 'input',
15
- message: 'Pages config in json format',
21
+ message: 'Pages config in JSON format',
16
22
  when: !prevAns.routes,
17
- default: defaultRoutes,
23
+ default: JSON.stringify(defaultRoutes),
24
+ },
25
+ {
26
+ name: 'ui',
27
+ type: 'input',
28
+ message: 'UI configuration in JSON format',
29
+ when: !prevAns.ui,
30
+ default: JSON.stringify(defaultUI),
18
31
  },
19
32
  ])
20
33
 
21
- let routesParsed;
22
- if (routes) {
23
- try {
24
- routesParsed = JSON.parse(routes);
25
- } catch (error) {
26
- console.error("Error parsing `routes` parameter as JSON:", error.message);
27
- console.log("Falling back to the default routes value");
28
- routesParsed = JSON.parse(defaultRoutes);
29
- }
30
- } else {
31
- routesParsed = JSON.parse(defaultRoutes);
32
- }
33
-
34
34
  return {
35
- routes: routesParsed,
35
+ routes: parseRoutes(routes),
36
+ ui: parseUI(ui),
36
37
  };
37
38
  };
package/.genx/prompts.js CHANGED
@@ -13,7 +13,7 @@ module.exports = async (inquirer, prevAns = {}) => {
13
13
 
14
14
  const {apiHost, enableSSO} = await apiPrompts(inquirer, prevAns)
15
15
  const {groupId, applicationVersion, enableDeployPlugin, csv} = await genesisServerPrompts(inquirer, prevAns);
16
- const {routes} = await uiPrompts(inquirer, prevAns);
16
+ const {routes, ui} = await uiPrompts(inquirer, prevAns);
17
17
 
18
18
  return {
19
19
  apiHost,
@@ -23,5 +23,6 @@ module.exports = async (inquirer, prevAns = {}) => {
23
23
  applicationVersion,
24
24
  enableDeployPlugin,
25
25
  csv,
26
+ ui,
26
27
  };
27
28
  };
@@ -22,6 +22,11 @@
22
22
  {{#if config.deleteEvent}}
23
23
  deleteEvent="{{ config.deleteEvent }}"
24
24
  {{/if}}
25
+ {{#if config.gridOptions}}
26
+ :gridOptions=${() => (
27
+ {{{config.gridOptions}}}
28
+ )}
29
+ {{/if}}
25
30
  {{#if config.snapshot}}
26
31
  :datasourceConfig=${() => ({isSnapshot: {{ config.snapshot }} })}
27
32
  {{/if}}
@@ -4,9 +4,9 @@
4
4
  {{#if config.snapshot}}
5
5
  isSnapshot="{{config.snapshot}}"
6
6
  {{/if}}
7
- {{#if config.deferredGridOptions}}
7
+ {{#if config.gridOptions}}
8
8
  :deferredGridOptions=${() => (
9
- {{{config.deferredGridOptions}}}
9
+ {{{config.gridOptions}}}
10
10
  )}
11
11
  {{/if}}
12
12
  >
@@ -1,4 +1,7 @@
1
1
  import { html } from '@microsoft/fast-element';
2
+ {{#if route.FDC3EventHandlersEnabled}}
3
+ import { sendEventOnChannel } from '../../utils';
4
+ {{/if}}
2
5
  import type { {{pascalCase route.name}} } from './{{kebabCase route.name}}';
3
6
 
4
7
  export const {{pascalCase route.name}}Template = html<{{pascalCase route.name}}>`
package/.genx/utils.js CHANGED
@@ -34,15 +34,48 @@ const formatJSONValue = (value) => {
34
34
  }
35
35
  }
36
36
 
37
+ const gridOptionsSerializer = (options, pad = ' ') => {
38
+ if (!options) {
39
+ return undefined;
40
+ }
41
+ try {
42
+ let output = `{\n`;
43
+ Object.keys(options).forEach((key) => {
44
+ const value = options[key];
45
+ if (value?.type === 'function') {
46
+ const args = value.arguments?.map(JSON.stringify).join(', ');
47
+ output += `${pad}${key}: ${value.name}(${args}),\n`;
48
+ } else {
49
+ output += `${pad}${key}: ${formatJSONValue(value)},\n`;
50
+ }
51
+ });
52
+ output += `${pad}}\n`;
53
+ return output;
54
+ } catch (e) {
55
+ return undefined;
56
+ }
57
+ };
58
+
59
+ const validateRoute = (route) => {
60
+ if (!route.name) {
61
+ console.warn('Invalid route - missing name', route);
62
+ }
63
+ return !!route.name;
64
+ }
65
+
37
66
  const formatRouteData = (route) => {
38
67
  const layoutKey = route?.layoutKey || `${route.name}_${Date.now()}`;
68
+
69
+ const FDC3ClickCategory = 'fdc3';
70
+ const FDC3EventHandlersEnabled = !!route.tiles?.find(t => t.config?.gridOptions?.onRowClicked?.category === FDC3ClickCategory);
71
+
39
72
  const tiles = route.tiles?.map(tile => ({
40
73
  ...tile,
41
74
  config: {
42
75
  ...(tile.config || {}),
76
+ gridOptions: gridOptionsSerializer(tile.config?.gridOptions),
43
77
  createFormUiSchema: formatJSONValue(tile.config?.createFormUiSchema),
44
78
  updateFormUiSchema: formatJSONValue(tile.config?.updateFormUiSchema),
45
- deferredGridOptions: formatJSONValue(tile.config?.deferredGridOptions),
46
79
  uischema: formatJSONValue(tile.config?.uischema),
47
80
  columns: formatJSONValue(tile.config?.columns)
48
81
  }
@@ -51,14 +84,30 @@ const formatRouteData = (route) => {
51
84
  return {
52
85
  ...route,
53
86
  layoutKey,
54
- tiles
87
+ tiles,
88
+ FDC3EventHandlersEnabled,
89
+ }
90
+ };
91
+
92
+ const parseJSONArgument = (name, defaultValue) =>
93
+ (value) => {
94
+ if (!value){
95
+ return defaultValue;
96
+ }
97
+ try {
98
+ return JSON.parse(value);
99
+ } catch (error) {
100
+ console.error(`Error parsing "${name}" parameter as JSON:`, error.message);
101
+ return defaultValue;
102
+ }
55
103
  }
56
- }
57
104
 
58
105
  module.exports = {
59
106
  makeDirectory,
60
107
  registerPartials,
61
108
  generateRoute,
109
+ validateRoute,
62
110
  generateEmptyCsv,
63
111
  formatRouteData,
112
+ parseJSONArgument,
64
113
  };
@@ -1,5 +1,5 @@
1
1
  {
2
- "UI": "14.167.2",
3
- "GSF": "7.1.16",
2
+ "UI": "14.170.0",
3
+ "GSF": "7.1.17",
4
4
  "Auth": "7.1.6"
5
5
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.9.0](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v2.8.0...v2.9.0) (2024-04-12)
4
+
5
+
6
+ ### Features
7
+
8
+ * FDC3 support GENC-224 (#180) ac35e42
9
+
10
+ ## [2.8.0](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v2.7.0...v2.8.0) (2024-04-11)
11
+
12
+
13
+ ### Features
14
+
15
+ * global foundation-ui error handling - overlays [skip-ci] [PSD-9](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/9) (#179) 4eff966
16
+
3
17
  ## [2.7.0](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v2.6.0...v2.7.0) (2024-04-10)
4
18
 
5
19
 
@@ -87,6 +87,9 @@
87
87
  "lint-staged": "^12.4.1"
88
88
  },
89
89
  "dependencies": {
90
+ {{#if FDC3.includeDependencies}}
91
+ "@finos/fdc3": "^1.2.0",
92
+ {{/if}}
90
93
  "@genesislcap/foundation-comms": "{{versions.UI}}",
91
94
  "@genesislcap/foundation-entity-management": "{{versions.UI}}",
92
95
  "@genesislcap/foundation-events": "{{versions.UI}}",
@@ -11,6 +11,9 @@ import * as Components from '../components';
11
11
  import { MainRouterConfig } from '../routes';
12
12
  import { Store, StoreEventDetailMap } from '../store';
13
13
  import designTokens from '../styles/design-tokens.json';
14
+ {{#if FDC3.channels.length}}
15
+ import { listenToChannel, onFDC3Ready } from '../utils';
16
+ {{/if}}
14
17
  import { MainStyles as styles } from './main.styles';
15
18
  import { DynamicTemplate as template, LoadingTemplate, MainTemplate } from './main.template';
16
19
 
@@ -44,6 +47,9 @@ export class MainApplication extends EventEmitter<StoreEventDetailMap>(FASTEleme
44
47
  this.readyStore();
45
48
  await this.loadPBCs();
46
49
  await this.loadRemotes();
50
+ {{#if FDC3.channels.length}}
51
+ onFDC3Ready(this.FDC3ReadyHandler);
52
+ {{/if}}
47
53
  DOM.queueUpdate(() => {
48
54
  configureDesignSystem(this.provider, designTokens);
49
55
  });
@@ -89,6 +95,18 @@ export class MainApplication extends EventEmitter<StoreEventDetailMap>(FASTEleme
89
95
  return this.ready ? MainTemplate : LoadingTemplate;
90
96
  }
91
97
 
98
+ {{#if FDC3.channels.length}}
99
+ FDC3ReadyHandler = () => {
100
+ {{#each FDC3.channels}}
101
+ listenToChannel('{{this.name}}', '{{this.type}}', (result) => {
102
+ console.log('Received FDC3 channel message on: {{this.name}} channel, type: {{this.type}}', result);
103
+ // TODO: Add your listener logic here
104
+ // E.g. open a modal or route to specific page: Route.path.push(`[Route name]`);
105
+ });
106
+ {{/each}}
107
+ };
108
+
109
+ {{/if}}
92
110
  private registerDIDependencies() {
93
111
  this.container.register(
94
112
  Registration.transient(DefaultRouteRecognizer, DefaultRouteRecognizer),
@@ -0,0 +1,62 @@
1
+ {{#if FDC3.includeDependencies}}
2
+ import { getOrCreateChannel, raiseIntent, addIntentListener } from '@finos/fdc3';
3
+ {{/if}}
4
+ export const isFDC3 = (): boolean => !!(window as any).fdc3;
5
+ {{#if FDC3.includeDependencies}}
6
+
7
+ export const onFDC3Ready = async (FDC3ReadyCb: () => any): Promise<void> => {
8
+ isFDC3()
9
+ ? await FDC3ReadyCb()
10
+ : window.addEventListener('fdc3Ready', async () => {
11
+ await FDC3ReadyCb();
12
+ });
13
+ };
14
+
15
+ export const sendMessageOnChannel = async (
16
+ channelName: string,
17
+ type: string,
18
+ payload: any,
19
+ ): Promise<void> => {
20
+ const channel = await getOrCreateChannel(channelName);
21
+
22
+ const m: any = {
23
+ type,
24
+ id: payload,
25
+ };
26
+
27
+ await channel.broadcast(m);
28
+ };
29
+
30
+ export const listenToChannel = async (
31
+ channelName: string,
32
+ type: string,
33
+ callback: (result: any) => void,
34
+ ): Promise<void> => {
35
+ const channel = await getOrCreateChannel(channelName);
36
+ channel.addContextListener(type, (result) => callback(result));
37
+ };
38
+
39
+ export const doRaiseIntent = async (intent: string, type: string, context: any): Promise<void> => {
40
+ const message = {
41
+ type,
42
+ id: context,
43
+ };
44
+
45
+ const result = await raiseIntent(intent, message);
46
+ };
47
+
48
+ export const listenForIntent = async (
49
+ intent: string,
50
+ callback: (result: any) => void,
51
+ ): Promise<void> => {
52
+ addIntentListener(intent, (result) => callback(result));
53
+ };
54
+
55
+ export const sendEventOnChannel = (channelName: string, type: string) => {
56
+ return async (e: any) => {
57
+ // check for ag-grid-specific events, fall back to standard events
58
+ const payload = e.data?.payload || e.detail;
59
+ sendMessageOnChannel(channelName, type, payload);
60
+ };
61
+ };
62
+ {{/if}}
@@ -1 +1,2 @@
1
+ export * from './fdc3';
1
2
  export * from './logger';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesislcap/blank-app-seed",
3
3
  "description": "Genesis Blank App Seed",
4
- "version": "2.7.0",
4
+ "version": "2.9.0",
5
5
  "license": "Apache-2.0",
6
6
  "scripts": {
7
7
  "release": "semantic-release"