@genesislcap/blank-app-seed 3.29.0 → 3.29.1-prerelease.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/.genx/configure.js +1 -1
  2. package/.genx/package.json +1 -1
  3. package/.genx/scripts/update-versions.js +58 -10
  4. package/.genx/templates/angular/route.hbs +0 -1
  5. package/.genx/templates/react/chart.hbs +6 -2
  6. package/.genx/templates/react/component/component.gridOptions.hbs +1 -1
  7. package/.genx/templates/react/component/component.hbs +26 -10
  8. package/.genx/templates/react/component/component.index.hbs +1 -1
  9. package/.genx/templates/react/entityManager.hbs +13 -9
  10. package/.genx/templates/react/form.hbs +6 -2
  11. package/.genx/templates/react/grid.hbs +8 -5
  12. package/.genx/templates/react/gridLayout.hbs +28 -28
  13. package/.genx/templates/react/horizontalLayout.hbs +5 -5
  14. package/.genx/templates/react/route.hbs +4 -18
  15. package/.genx/utils/formatRouteData.js +1 -1
  16. package/.genx/utils/generateTile.js +1 -0
  17. package/.genx/versions.json +3 -3
  18. package/.github/pull_request_template.md +1 -1
  19. package/.github/workflows/build.yml +3 -2
  20. package/.github/workflows/release.yml +1 -0
  21. package/.github/workflows/slack.yml +1 -1
  22. package/.github/workflows/upgrade.yml +32 -11
  23. package/.github/workflows/upgrade_main.yml +19 -0
  24. package/.github/workflows/upgrade_prerelease.yml +19 -0
  25. package/CHANGELOG.md +70 -0
  26. package/client-tmp/react/package.json +3 -0
  27. package/client-tmp/react/src/App.tsx +33 -6
  28. package/client-tmp/react/src/components/ErrorMessage/ErrorMessage.jsx +62 -0
  29. package/client-tmp/react/src/config.ts +1 -0
  30. package/client-tmp/react/src/guards/PermissionsGuard.tsx +37 -0
  31. package/client-tmp/react/src/pages/NotPermittedPage/NotPermittedPage.css +0 -0
  32. package/client-tmp/react/src/pages/NotPermittedPage/NotPermittedPage.jsx +13 -0
  33. package/client-tmp/react/src/share/foundation-login.ts +1 -1
  34. package/client-tmp/react/src/utils/fdc3.ts +32 -0
  35. package/client-tmp/react/src/utils/history.ts +1 -3
  36. package/client-tmp/react/src/utils/index.ts +3 -0
  37. package/client-tmp/react/src/utils/permissions.ts +7 -0
  38. package/package.json +1 -1
  39. /package/client-tmp/react/src/pages/{auth → AuthPage}/AuthPage.css +0 -0
  40. /package/client-tmp/react/src/pages/{auth → AuthPage}/AuthPage.jsx +0 -0
@@ -16,7 +16,7 @@ module.exports = async (data, utils) => {
16
16
  // populate additional data fields
17
17
  data.pkgName = data.appName.replace(/[\W_]/g, '').toLowerCase();
18
18
  data.rootElement = `${data.pkgName}-root`;
19
- data.localGenId = data.appName.toUpperCase().replace('-', '_');
19
+ data.localGenId = data.appName.toUpperCase().replace(/-/g, '_');
20
20
  data.applicationVersionWeb = data.applicationVersion.split('-').shift();
21
21
  data.versions = versions;
22
22
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesislcap/blank-app-seed-config",
3
3
  "description": "Genesis Blank App Seed Configuration",
4
- "version": "3.29.0",
4
+ "version": "3.29.1-prerelease.10",
5
5
  "license": "Apache-2.0",
6
6
  "scripts": {
7
7
  "lint": "eslint .",
@@ -3,12 +3,31 @@ const { writeFileSync } = require('node:fs');
3
3
  const { resolve } = require('node:path');
4
4
  const current = require('../versions.json');
5
5
 
6
- const run = (command) =>
7
- execSync(command, {
6
+ const args = process.argv.slice(2);
7
+
8
+ const argDefined = (name) => args.indexOf(name) >= 0;
9
+
10
+ const patchOnly = argDefined("--patch-only");
11
+ const dryRun = argDefined("--dry-run");
12
+ const skipServer = argDefined("--skip-server");
13
+
14
+ const VERSION_REGEX = /\d+$/;
15
+ const JFROG_BASE_EXCLUSIONS = '*-SNAPSHOT*;*maven-metadata*;*test*;*TEST*';
16
+
17
+ const { jfrogVersionMatcher, jfrogExclusionsMatcher, npmVersionMatcher } = patchOnly
18
+ ? { jfrogVersionMatcher: current.GSF.replace(VERSION_REGEX, '*'), jfrogExclusionsMatcher: `*-beta*;*-RC*;${JFROG_BASE_EXCLUSIONS}`, npmVersionMatcher: current.UI.replace(VERSION_REGEX, 'x') }
19
+ : { jfrogVersionMatcher: undefined, jfrogExclusionsMatcher: JFROG_BASE_EXCLUSIONS, npmVersionMatcher: 'latest' };
20
+
21
+ console.log('Running with: ', { patchOnly, skipServer, dryRun, npmVersionMatcher, jfrogVersionMatcher, jfrogExclusionsMatcher });
22
+
23
+ const run = (command) => {
24
+ console.debug('running:', command);
25
+ return execSync(command, {
8
26
  stdio: ['pipe', 'pipe', 'ignore'],
9
27
  })
10
28
  .toString('utf8')
11
29
  .trim();
30
+ };
12
31
 
13
32
  const writeJSON = (json, path) => {
14
33
  const data = JSON.stringify(json, null, 2) + '\n';
@@ -20,13 +39,38 @@ const writeJSON = (json, path) => {
20
39
  }
21
40
  };
22
41
 
23
- const UI = run('npm info @genesislcap/foundation-ui@latest version');
24
- const GSF = run(
25
- `jf rt s "libs-release-client/global/genesis/genesis-distribution/" --exclusions="*-RC*;*-SNAPSHOT*;*maven-metadata*;*test*;*TEST*" | grep path | tr -s ' ' | sed 's/"path": //g' | awk -F'/' '{print $(NF-1)}' | sort -V | tail -n 1`,
26
- );
27
- const Auth = run(
28
- `jf rt s "libs-release-client/global/genesis/auth-distribution/" --exclusions="*-RC*;*-SNAPSHOT*;*maven-metadata*;*test*;*TEST*" | grep path | tr -s ' ' | sed 's/"path": //g' | awk -F'/' '{print $(NF-1)}' | sort -V | tail -n 1`,
29
- );
42
+ /**
43
+ * NPM Info returns a string if there's only one version in the channel;, otherwise it returns a valid json array,
44
+ * where the most recent version will be the last value;
45
+ * @param {*} output
46
+ * @returns
47
+ */
48
+ const parseNpmInfo = (output) => {
49
+ try {
50
+ const versions = JSON.parse(output);
51
+ return Array.isArray(versions) ? versions[versions.length-1] : versions;
52
+ } catch (err) {
53
+ return output;
54
+ }
55
+ }
56
+
57
+ const npmInfo = run(`npm info @genesislcap/foundation-ui@${npmVersionMatcher} version --json`);
58
+ console.debug('Npm raw output:', npmInfo);
59
+ const UI = parseNpmInfo(npmInfo);
60
+
61
+ const serverOsCommandPipeline = `grep path | tr -s ' ' | sed 's/"path": //g' | awk -F'/' '{print $(NF-1)}' | sort -V | tail -n 1`;
62
+
63
+ const { GSF, Auth } = skipServer
64
+ ? { GSF: current.GSF, Auth: current.Auth }
65
+ : {
66
+ GSF: run(
67
+ `jf rt s "libs-release-client/global/genesis/genesis-distribution/${jfrogVersionMatcher ?? ''}" --exclusions="${jfrogExclusionsMatcher}" | ${serverOsCommandPipeline}`
68
+ ),
69
+ Auth: run(
70
+ `jf rt s "libs-release-client/global/genesis/auth-distribution/${jfrogVersionMatcher ?? ''}" --exclusions="${jfrogExclusionsMatcher}" | ${serverOsCommandPipeline}`,
71
+ )
72
+ };
73
+
30
74
  const latest = { UI, GSF, Auth };
31
75
 
32
76
  console.log('Current:', current);
@@ -35,7 +79,11 @@ console.log('Latest:', latest);
35
79
  if (current.UI !== UI || current.GSF !== GSF || current.Auth !== Auth) {
36
80
  console.log('Newer versions available');
37
81
  const path = resolve(__dirname, '../versions.json');
38
- writeJSON(latest, path);
82
+ if (!dryRun) {
83
+ writeJSON(latest, path);
84
+ } else {
85
+ console.log('Dry run execution, versions will not be written.')
86
+ }
39
87
  } else {
40
88
  console.log('No newer versions available');
41
89
  }
@@ -5,7 +5,6 @@ import { {{pascalCase this.componentName}} } from './{{kebabCase this.title}}-{{
5
5
  {{/each}}
6
6
  import { environment } from '../../../environments/environment';
7
7
 
8
-
9
8
  @Component({
10
9
  selector: 'app-{{kebabCase route.name}}',
11
10
  standalone: true,
@@ -1,9 +1,13 @@
1
+ {{#if config.permissions.viewRight}}hasUserPermission('{{config.permissions.viewRight}}') ? ({{/if}}
1
2
  <rapid-g2plot-chart
2
3
  type="{{ config.type }}"
3
- config={tile{{ config.index }}.chartConfig}
4
+ config={chartConfig}
4
5
  >
5
6
  <chart-datasource
6
7
  resourceName="{{ config.resourceName }}"
7
8
  server-fields="{{ config.xField }} {{ config.yField }}"
8
9
  ></chart-datasource>
9
- </rapid-g2plot-chart>
10
+ </rapid-g2plot-chart>{{#if config.permissions.viewRight}}
11
+ ) : (
12
+ <ErrorMessage elementType="h3" message="You do not have access to view this component." />
13
+ ){{/if}}
@@ -6,4 +6,4 @@ import { sendEventOnChannel } from '../../../utils';
6
6
 
7
7
  {{#if tile.config.gridOptions}}
8
8
  export const gridOptions: GridOptionsConfig = {{{ tile.config.gridOptions }}}
9
- {{/if}}
9
+ {{/if}}
@@ -1,11 +1,13 @@
1
- import { Component, Input, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
2
- import { CommonModule } from '@angular/common';
1
+
2
+ {{#if tile.config.permissions.viewRight}}
3
3
  import { getUser } from '@genesislcap/foundation-user';
4
- import { ErrorMessageComponent } from '../../../components/error-message/error-message.component';
5
4
  import { getViewUpdateRightComponent } from '../../../utils';
6
- {{#if tile.config.gridOptions}}
7
- import { GridOptionsConfig } from "@genesislcap/rapid-grid-pro";
8
- {{/if}}
5
+ import ErrorMessage from '../../../components/ErrorMessage/ErrorMessage';
6
+ {{else}}{{#if tile.config.permissions.updateRight}}
7
+ import { getViewUpdateRightComponent } from '../../../utils';
8
+ import { getUser } from '@genesislcap/foundation-user';
9
+ import ErrorMessage from '../../../components/ErrorMessage/ErrorMessage';
10
+ {{/if}}{{/if}}
9
11
  {{#if tile.config.createFormUiSchema}}
10
12
  import { createFormSchema } from './{{kebabCase tile.title}}.create.form.schema';
11
13
  {{/if}}
@@ -19,14 +21,28 @@ import { updateFormSchema } from './{{kebabCase tile.title}}.update.form.schema'
19
21
  import { columnDefs } from './{{kebabCase tile.title}}.column.defs';
20
22
  {{/if}}
21
23
  {{#if tile.config.gridOptions}}
22
- import { gridOptions } from './{{kebabCase tile.title}}.gridOptions';
24
+ import { gridOptions as tileGridOptions } from './{{kebabCase tile.title}}.gridOptions';
23
25
  {{/if}}
24
26
  import './{{kebabCase tile.title}}.component.css';
25
27
 
26
- const {{pascalCase tile.componentName}} = () => {
28
+ export const {{pascalCase tile.componentName}} = () => { {{#if tile.config.permissions.viewRight}}
29
+ const hasUserPermission = (permissionCode) => getViewUpdateRightComponent(getUser(), permissionCode);{{else}}{{#if tile.config.permissions.updateRight}}
30
+ const hasUserPermission = (permissionCode) => getViewUpdateRightComponent(getUser(), permissionCode);{{/if}}{{/if}}{{#if tile.config.createFormUiSchema}}
31
+ const createFormSchema = createFormSchema;{{/if}}{{#if tile.config.uischema}}
32
+ const uischema = createFormSchema;{{/if}}{{#if tile.config.updateFormUiSchema}}
33
+ const updateFormSchema = updateFormSchema;{{/if}}{{#if tile.config.columns}}
34
+ const columnDefs = columnDefs;{{/if}}{{#if tile.config.gridOptions}}
35
+ const gridOptions = tileGridOptions;{{/if}}{{#if tile.config.reqrep}}
36
+ const reqrep = { pollingInterval: 5000 };{{/if}}{{#if tile.config.type}}
37
+ const chartConfig = { {{#ifEquals tile.config.type 'pie'}}
38
+ "radius": 0.75,
39
+ "angleField": "value",
40
+ "colorField": "groupBy",{{else}}
41
+ "xField": "groupBy",
42
+ "yField": "value",{{/ifEquals}}
43
+ };{{/if}}
44
+
27
45
  return (
28
46
  {{> (lookup tile 'type') tile}}
29
47
  );
30
48
  };
31
-
32
- export default {{pascalCase tile.componentName}};
@@ -1 +1 @@
1
- export * from './{{kebabCase tile.title}}.component';
1
+ export * from './{{kebabCase tile.title}}.component.jsx';
@@ -1,3 +1,4 @@
1
+ {{#if config.permissions.viewRight}}hasUserPermission('{{config.permissions.viewRight}}') ? ({{/if}}
1
2
  <entity-management
2
3
  design-system-prefix="rapid"
3
4
  enable-row-flashing
@@ -7,31 +8,31 @@
7
8
  {{/if}}
8
9
  resourceName="{{ config.resourceName }}"
9
10
  {{#if config.createEvent}}
10
- createEvent="{{ config.createEvent }}"
11
+ createEvent={hasUserPermission('{{config.permissions.updateRight}}') ? '{{ config.createEvent }}' : undefined}
11
12
  {{#if config.createFormUiSchema}}
12
- createFormUiSchema={tile{{ config.index }}.createFormUiSchema}
13
+ createFormUiSchema={createFormSchema}
13
14
  {{/if}}
14
15
  {{/if}}
15
16
  {{#if config.updateEvent}}
16
- updateEvent="{{ config.updateEvent }}"
17
+ updateEvent={hasUserPermission('{{config.permissions.updateRight}}') ? '{{ config.updateEvent }}' : undefined}
17
18
  {{#if config.updateFormUiSchema}}
18
- updateFormUiSchema={tile{{ config.index }}.updateFormUiSchema}
19
+ updateFormUiSchema={updateFormSchema}
19
20
  {{/if}}
20
21
  {{/if}}
21
22
  {{#if config.deleteEvent}}
22
- deleteEvent="{{ config.deleteEvent }}"
23
+ deleteEvent={hasUserPermission('{{config.permissions.updateRight}}') ? '{{ config.deleteEvent }}' : undefined}
23
24
  {{/if}}
24
25
  {{#if config.gridOptions}}
25
- gridOptions={{{ config.gridOptions }}}
26
+ gridOptions={gridOptions}
26
27
  {{/if}}
27
28
  {{#if config.snapshot}}
28
29
  datasourceConfig={ isSnapshot: {{ config.snapshot }} }
29
30
  {{/if}}
30
31
  {{#if config.reqrep}}
31
- datasourceConfig={tile{{ config.index }}.reqrep}
32
+ datasourceConfig={reqrep}
32
33
  {{/if}}
33
34
  {{#if config.columns}}
34
- columns={tile{{ config.index }}.columns}
35
+ columns={columnDefs}
35
36
  {{/if}}
36
37
  {{#if config.modalPosition}}
37
38
  modal-position="{{ config.modalPosition }}"
@@ -42,4 +43,7 @@
42
43
  {{#if config.enableSearchBar}}
43
44
  enable-search-bar
44
45
  {{/if}}
45
- ></entity-management>
46
+ ></entity-management>{{#if config.permissions.viewRight}}
47
+ ) : (
48
+ <ErrorMessage elementType="h3" message="You do not have access to view this component." />
49
+ ){{/if}}
@@ -1,8 +1,12 @@
1
+ {{#if config.permissions.updateRight}}hasUserPermission('{{config.permissions.updateRight}}') ? ({{/if}}
1
2
  <foundation-form
2
3
  design-system-prefix="rapid"
3
4
  resourceName="{{config.resourceName}}"
4
5
  {{#if config.uischema}}
5
- uischema={tile{{ config.index }}.uischema}
6
+ uischema={uischema}
6
7
  {{/if}}
7
8
  >
8
- </foundation-form>
9
+ </foundation-form>{{#if config.permissions.updateRight}}
10
+ ) : (
11
+ <ErrorMessage elementType="h3" message="You do not have access to view this component." />
12
+ ){{/if}}
@@ -1,3 +1,4 @@
1
+ {{#if config.permissions.viewRight}}hasUserPermission('{{config.permissions.viewRight}}') ? ({{/if}}
1
2
  <rapid-grid-pro
2
3
  enable-row-flashing
3
4
  enable-cell-flashing
@@ -8,11 +9,13 @@
8
9
  isSnapshot="{{config.snapshot}}"
9
10
  {{/if}}
10
11
  {{#if config.reqrep}}
11
- datasourceConfig={tile{{ config.index }}.reqrep}
12
+ datasourceConfig="reqrep"
12
13
  {{/if}}
13
14
  {{#if config.gridOptions}}
14
- deferredGridOptions={tile{{ config.index }}.gridOptions}
15
+ deferredGridOptions=\{{ onRowClicked: gridOptions?.onRowClicked }}
15
16
  {{/if}}
16
- >
17
- </grid-pro-genesis-datasource>
18
- </rapid-grid-pro>
17
+ ></grid-pro-genesis-datasource>
18
+ </rapid-grid-pro>{{#if config.permissions.viewRight}}
19
+ ) : (
20
+ <ErrorMessage elementType="h3" message="You do not have access to view this component." />
21
+ ){{/if}}
@@ -1,30 +1,30 @@
1
1
  <rapid-layout-region type="horizontal">
2
- <rapid-layout-region type="vertical">
3
- {{#each route.tiles}}
4
- {{#ifEquals @index 0}}
5
- <rapid-layout-item title="{{../title}}">
6
- {{> (lookup ../this 'type') ../this}}
7
- </rapid-layout-item>
8
- {{/ifEquals}}
9
- {{#ifEquals @index 1}}
10
- <rapid-layout-item title="{{../title}}">
11
- {{> (lookup ../this 'type') ../this}}
12
- </rapid-layout-item>
13
- {{/ifEquals}}
14
- {{/each}}
15
- </rapid-layout-region>
16
- <rapid-layout-region type="vertical">
17
- {{#each route.tiles}}
18
- {{#ifEquals @index 2}}
19
- <rapid-layout-item title="{{../title}}">
20
- {{> (lookup ../this 'type') ../this}}
21
- </rapid-layout-item>
22
- {{/ifEquals}}
23
- {{#ifEquals @index 3}}
24
- <rapid-layout-item title="{{../title}}">
25
- {{> (lookup ../this 'type') ../this}}
26
- </rapid-layout-item>
27
- {{/ifEquals}}
28
- {{/each}}
29
- </rapid-layout-region>
2
+ <rapid-layout-region type="vertical">
3
+ {{#each route.tiles}}
4
+ {{#ifEquals @index 0}}
5
+ <rapid-layout-item title="{{../title}}">
6
+ <{{pascalCase ../componentName}}></{{pascalCase ../componentName}}>
7
+ </rapid-layout-item>
8
+ {{/ifEquals}}
9
+ {{#ifEquals @index 1}}
10
+ <rapid-layout-item title="{{../title}}">
11
+ <{{pascalCase ../componentName}}></{{pascalCase ../componentName}}>
12
+ </rapid-layout-item>
13
+ {{/ifEquals}}
14
+ {{/each}}
15
+ </rapid-layout-region>
16
+ <rapid-layout-region type="vertical">
17
+ {{#each route.tiles}}
18
+ {{#ifEquals @index 2}}
19
+ <rapid-layout-item title="{{../title}}">
20
+ <{{pascalCase ../componentName}}></{{pascalCase ../componentName}}>
21
+ </rapid-layout-item>
22
+ {{/ifEquals}}
23
+ {{#ifEquals @index 3}}
24
+ <rapid-layout-item title="{{../title}}">
25
+ <{{pascalCase ../componentName}}></{{pascalCase ../componentName}}>
26
+ </rapid-layout-item>
27
+ {{/ifEquals}}
28
+ {{/each}}
29
+ </rapid-layout-region>
30
30
  </rapid-layout-region>
@@ -1,7 +1,7 @@
1
1
  <rapid-layout-region>
2
- {{#each route.tiles}}
3
- <rapid-layout-item title="{{this.title}}">
4
- {{> (lookup . 'type') }}
5
- </rapid-layout-item>
6
- {{/each}}
2
+ {{#each route.tiles}}
3
+ <rapid-layout-item title="{{this.title}}">
4
+ <{{pascalCase this.componentName}}></{{pascalCase this.componentName}}>
5
+ </rapid-layout-item>
6
+ {{/each}}
7
7
  </rapid-layout-region>
@@ -1,28 +1,14 @@
1
1
  import './{{pascalCase route.name}}.css';
2
+ {{#each route.tiles}}
3
+ import { {{pascalCase this.componentName}} } from './{{kebabCase this.title}}-{{this.componentType}}';
4
+ {{/each}}
2
5
 
3
6
  const {{pascalCase route.name}} = () => {
4
- {{#each route.tiles}}
5
- const tile{{this.config.index}} = { {{#if this.config.createFormUiSchema}}
6
- "createFormUiSchema": {{{ this.config.createFormUiSchema }}},{{/if}}{{#if this.config.updateFormUiSchema}}
7
- "updateFormUiSchema": {{{ this.config.updateFormUiSchema }}},{{/if}}{{#if this.config.uischema}}
8
- "uischema": {{{ this.config.uischema }}},{{/if}}{{#if this.config.gridOptions}}
9
- "gridOptions": {{{ this.config.gridOptions }}},{{/if}}{{#if this.config.reqrep}}
10
- "reqrep": {{{ this.config.reqrep }}},{{/if}}{{#if this.config.columns}}
11
- "columns": {{{ this.config.columns }}},{{/if}}{{#if this.config.type}}
12
- "chartConfig": { {{#ifEquals this.config.type 'pie'}}
13
- "radius": 0.75,
14
- "angleField": "value",
15
- "colorField": "groupBy",{{else}}
16
- "xField": "groupBy",
17
- "yField": "value",{{/ifEquals}}
18
- },{{/if}}
19
- };
20
- {{/each}}
21
7
 
22
8
  return (
23
9
  <section className="{{kebabCase route.name}}-page">
24
10
  {{#if route.tiles}}
25
- <rapid-layout auto-save-key="{{route.layoutKey}}">
11
+ <rapid-layout auto-save-key={process.env.NODE_ENV === 'production' ? "{{route.layoutKey}}" : null}>
26
12
  {{> (lookup ./route 'layoutType') }}
27
13
  </rapid-layout>
28
14
  {{else}}
@@ -37,7 +37,7 @@ const formatRouteData = (framework, route) => {
37
37
  ...config,
38
38
  index,
39
39
  gridOptions: gridOptionsSerializer(gridOptions),
40
- useOnlyTemplateCols: !!gridOptions?.columnDefs,
40
+ useOnlyTemplateCols: !!gridOptions?.columns,
41
41
  createFormUiSchema: formatJSONValue(createFormUiSchema),
42
42
  updateFormUiSchema: formatJSONValue(updateFormUiSchema),
43
43
  uischema: formatJSONValue(uischema),
@@ -44,6 +44,7 @@ const getPathByFramework = {
44
44
  },
45
45
  [FRAMEWORK_REACT_ALIAS]: {
46
46
  ...defaultPathGetters,
47
+ index: (componentPath) => `${componentPath}/index.js`,
47
48
  clientSrcPath: `../../client/src/pages`,
48
49
  route: (clientSrcPath, tile, routeName) =>
49
50
  `${clientSrcPath}/${routeName}/${tile.name}-${tile.componentType}`,
@@ -1,5 +1,5 @@
1
1
  {
2
- "UI": "14.200.0",
3
- "GSF": "8.2.3",
4
- "Auth": "8.2.1"
2
+ "UI": "14.201.0",
3
+ "GSF": "8.3.0-beta4",
4
+ "Auth": "8.3.0-beta4"
5
5
  }
@@ -36,7 +36,7 @@ rm -rf blankappseedtest && npx -y @genesislcap/genx@latest init blankappseedtest
36
36
  ### Route and CSV parameter handling test
37
37
 
38
38
  ```
39
- rm -rf blankappseedtest && npx -y @genesislcap/genx@latest init blankappseedtest --ref %YOUR-BRANCH-NAME% --no-npm -x --routes '[{"name":"Home","tiles":[{"title":"Entity manager","type":"entity-manager","config":{ "modalPosition": "centre", "sizeColumnsToFit": true, "enableSearchBar": true, "resourceName":"ALL_POSITIONS","title":"My Positions","updateEvent":"EVENT_COUNTERPARTY_MODIFY","deleteEvent":"EVENT_COUNTERPARTY_DELETE","createEvent":"EVENT_COUNTERPARTY_INSERT", "createFormUiSchema": {"type":"VerticalLayout","elements":[{"type":"Control","label":"Inline create schema - main contact","scope":"#/properties/MAIN_CONTACT"},{"type":"Control","label":"Issuer Name - Local Schema","scope":"#/properties/ISSUER_NAME","options":{"readonly":true}},{"type":"Control","label":"Price","scope":"#/properties/PRICE"},{"type":"Control","scope":"#/properties/COUNTERPARTY","options":{"allOptionsResourceName":"ALL_COUNTERPARTYS","valueField":"COUNTERPARTY_ID","labelField":"COUNTERPARTY_ID"}},{"type":"Control","label":"Password","scope":"#/properties/PASSWORD","options":{"isPassword":true}},{"type":"Control","label":"Password","scope":"#/properties/PASSWORD","options":{"textarea":true}}]}, "updateFormUiSchema": {"type":"VerticalLayout","elements":[{"type":"Control","label":"Inline update schema - main contact","scope":"#/properties/MAIN_CONTACT"},{"type":"Control","label":"Issuer Name - Local Schema","scope":"#/properties/ISSUER_NAME","options":{"readonly":true}},{"type":"Control","label":"Price","scope":"#/properties/PRICE"},{"type":"Control","scope":"#/properties/COUNTERPARTY","options":{"allOptionsResourceName":"ALL_COUNTERPARTYS","valueField":"COUNTERPARTY_ID","labelField":"COUNTERPARTY_ID"}},{"type":"Control","label":"Password","scope":"#/properties/PASSWORD","options":{"isPassword":true}},{"type":"Control","label":"Password","scope":"#/properties/PASSWORD","options":{"textarea":true}}]}, "columns": [{"field":"INSTRUMENT_NAME","headerName":"Instrument Name"},{"field":"VALUE","headerName":"Inline coldef - VALUE"},{"field":"QUANTITY","headerName":"Quantity"},{"field":"PNL","headerName":"PNL"}] }},{"title":"Grid","type":"grid-pro","config":{"resourceName":"ALL_TRADES", "gridOptions": {"columnDefs":[{"field":"INSTRUMENT_NAME","headerName":"Instrument Name"},{"field":"VALUE","headerName":"Inline coldef - VALUE"},{"field":"QUANTITY","headerName":"Quantity"},{"field":"PNL","headerName":"PNL"}]} }},{"title":"Form","type":"smart-form","config":{"resourceName":"EVENT_COUNTERPARTY_INSERT", "uischema": {"type":"VerticalLayout","elements":[{"type":"Control","label":"Inline form schema - main contact","scope":"#/properties/MAIN_CONTACT"},{"type":"Control","label":"Issuer Name - Local Schema","scope":"#/properties/ISSUER_NAME","options":{"readonly":true}},{"type":"Control","label":"Price","scope":"#/properties/PRICE"},{"type":"Control","scope":"#/properties/COUNTERPARTY","options":{"allOptionsResourceName":"ALL_COUNTERPARTYS","valueField":"COUNTERPARTY_ID","labelField":"COUNTERPARTY_ID"}},{"type":"Control","label":"Password","scope":"#/properties/PASSWORD","options":{"isPassword":true}},{"type":"Control","label":"Password","scope":"#/properties/PASSWORD","options":{"textarea":true}}]} }}]}, {"name":"Realtime Dashboard","tiles":[{"title":"Entity manager tile","type":"entity-manager","config":{"resourceName":"ALL_COUNTERPARTYS","title":"Counterparty Management","updateEvent":"EVENT_COUNTERPARTY_MODIFY","deleteEvent":"EVENT_COUNTERPARTY_DELETE","createEvent":"EVENT_COUNTERPARTY_INSERT"}},{"title":"Form tile","type":"smart-form","config":{"resourceName":"EVENT_COUNTERPARTY_INSERT"}}]},{"name":"Analytics","tiles":[{"title":"Grid Tile","type":"grid-pro","config":{"resourceName":"ALL_POSITIONS"}},{"title":"Charts Tile 1","type":"chart","config":{"type":"line","resourceName":"ALL_POSITIONS","xField":"INSTRUMENT_NAME","yField":"VALUE"}},{"title":"Charts Tile 2","type":"chart","config":{"type":"pie","resourceName":"ALL_POSITIONS","xField":"INSTRUMENT_NAME","yField":"VALUE"}},{"title":"Charts Tile 3","type":"chart","config":{"type":"column","resourceName":"ALL_POSITIONS","xField":"INSTRUMENT_ID","yField":"VALUE"}}]}]' --csv '[{"name": "trade", "fields": ["a", "B"]}, {"name": "position", "fields": ["id", "TYPE"]} ]' --apiHost 'wss://public-foundation.genesislab.global/gwf/' --no-shell && cd blankappseedtest/client && npm run bootstrap && npm run dev
39
+ rm -rf blankappseedtest && npx -y @genesislcap/genx@latest init blankappseedtest --ref %YOUR-BRANCH-NAME% --no-npm -x --routes '[{"name":"Home","tiles":[{"title":"Entity manager","type":"entity-manager","config":{ "modalPosition": "centre", "sizeColumnsToFit": true, "enableSearchBar": true, "resourceName":"ALL_POSITIONS","title":"My Positions","updateEvent":"EVENT_COUNTERPARTY_MODIFY","deleteEvent":"EVENT_COUNTERPARTY_DELETE","createEvent":"EVENT_COUNTERPARTY_INSERT", "createFormUiSchema": {"type":"VerticalLayout","elements":[{"type":"Control","label":"Inline create schema - main contact","scope":"#/properties/MAIN_CONTACT"},{"type":"Control","label":"Issuer Name - Local Schema","scope":"#/properties/ISSUER_NAME","options":{"readonly":true}},{"type":"Control","label":"Price","scope":"#/properties/PRICE"},{"type":"Control","scope":"#/properties/COUNTERPARTY","options":{"allOptionsResourceName":"ALL_COUNTERPARTYS","valueField":"COUNTERPARTY_ID","labelField":"COUNTERPARTY_ID"}},{"type":"Control","label":"Password","scope":"#/properties/PASSWORD","options":{"isPassword":true}},{"type":"Control","label":"Password","scope":"#/properties/PASSWORD","options":{"textarea":true}}]}, "updateFormUiSchema": {"type":"VerticalLayout","elements":[{"type":"Control","label":"Inline update schema - main contact","scope":"#/properties/MAIN_CONTACT"},{"type":"Control","label":"Issuer Name - Local Schema","scope":"#/properties/ISSUER_NAME","options":{"readonly":true}},{"type":"Control","label":"Price","scope":"#/properties/PRICE"},{"type":"Control","scope":"#/properties/COUNTERPARTY","options":{"allOptionsResourceName":"ALL_COUNTERPARTYS","valueField":"COUNTERPARTY_ID","labelField":"COUNTERPARTY_ID"}},{"type":"Control","label":"Password","scope":"#/properties/PASSWORD","options":{"isPassword":true}},{"type":"Control","label":"Password","scope":"#/properties/PASSWORD","options":{"textarea":true}}]}, "columns": [{"field":"INSTRUMENT_NAME","headerName":"Instrument Name"},{"field":"VALUE","headerName":"Inline coldef - VALUE"},{"field":"QUANTITY","headerName":"Quantity"},{"field":"PNL","headerName":"PNL"}] }},{"title":"Grid","type":"grid-pro","config":{"resourceName":"ALL_TRADES", "gridOptions": {"columns":[{"field":"INSTRUMENT_NAME","headerName":"Instrument Name"},{"field":"VALUE","headerName":"Inline coldef - VALUE"},{"field":"QUANTITY","headerName":"Quantity"},{"field":"PNL","headerName":"PNL"}]} }},{"title":"Form","type":"smart-form","config":{"resourceName":"EVENT_COUNTERPARTY_INSERT", "uischema": {"type":"VerticalLayout","elements":[{"type":"Control","label":"Inline form schema - main contact","scope":"#/properties/MAIN_CONTACT"},{"type":"Control","label":"Issuer Name - Local Schema","scope":"#/properties/ISSUER_NAME","options":{"readonly":true}},{"type":"Control","label":"Price","scope":"#/properties/PRICE"},{"type":"Control","scope":"#/properties/COUNTERPARTY","options":{"allOptionsResourceName":"ALL_COUNTERPARTYS","valueField":"COUNTERPARTY_ID","labelField":"COUNTERPARTY_ID"}},{"type":"Control","label":"Password","scope":"#/properties/PASSWORD","options":{"isPassword":true}},{"type":"Control","label":"Password","scope":"#/properties/PASSWORD","options":{"textarea":true}}]} }}]}, {"name":"Realtime Dashboard","tiles":[{"title":"Entity manager tile","type":"entity-manager","config":{"resourceName":"ALL_COUNTERPARTYS","title":"Counterparty Management","updateEvent":"EVENT_COUNTERPARTY_MODIFY","deleteEvent":"EVENT_COUNTERPARTY_DELETE","createEvent":"EVENT_COUNTERPARTY_INSERT"}},{"title":"Form tile","type":"smart-form","config":{"resourceName":"EVENT_COUNTERPARTY_INSERT"}}]},{"name":"Analytics","tiles":[{"title":"Grid Tile","type":"grid-pro","config":{"resourceName":"ALL_POSITIONS"}},{"title":"Charts Tile 1","type":"chart","config":{"type":"line","resourceName":"ALL_POSITIONS","xField":"INSTRUMENT_NAME","yField":"VALUE"}},{"title":"Charts Tile 2","type":"chart","config":{"type":"pie","resourceName":"ALL_POSITIONS","xField":"INSTRUMENT_NAME","yField":"VALUE"}},{"title":"Charts Tile 3","type":"chart","config":{"type":"column","resourceName":"ALL_POSITIONS","xField":"INSTRUMENT_ID","yField":"VALUE"}}]}]' --csv '[{"name": "trade", "fields": ["a", "B"]}, {"name": "position", "fields": ["id", "TYPE"]} ]' --apiHost 'wss://public-foundation.genesislab.global/gwf/' --no-shell && cd blankappseedtest/client && npm run bootstrap && npm run dev
40
40
  ```
41
41
 
42
42
  ✅ &nbsp; **Checklist**
@@ -15,6 +15,7 @@ jobs:
15
15
  genesisArtifactoryUser: ${{ secrets.JFROG_LIBS_RELEASE_CLIENT_RO_USER }}
16
16
  genesisArtifactoryPassword: ${{ secrets.JFROG_LIBS_RELEASE_CLIENT_RO_KEY }}
17
17
  USE_DOCKER: 1
18
+ GRADLE_PARAMS: ${{ github.base_ref == 'prerelease' && '-PuseDevRepo=true' || '' }}
18
19
  runs-on: ubuntu-latest
19
20
  steps:
20
21
  - uses: actions/checkout@v4
@@ -46,7 +47,7 @@ jobs:
46
47
 
47
48
  - name: Build sample app
48
49
  working-directory: /tmp/testapp
49
- run: ./gradlew build --info
50
+ run: ./gradlew ${GRADLE_PARAMS} build --info
50
51
 
51
52
  - name: Lint UI
52
53
  working-directory: /tmp/testapp/client
@@ -62,7 +63,7 @@ jobs:
62
63
 
63
64
  - name: Create Server Dockerfile
64
65
  working-directory: /tmp/testapp
65
- run: ./gradlew :server:testapp-app:createDockerfile --info
66
+ run: ./gradlew ${GRADLE_PARAMS} :server:testapp-app:createDockerfile --info
66
67
 
67
68
  - name: Build Docker images
68
69
  working-directory: /tmp/testapp
@@ -1,6 +1,7 @@
1
1
  name: Release
2
2
 
3
3
  on:
4
+ workflow_dispatch:
4
5
  push:
5
6
  branches: [main, prerelease]
6
7
 
@@ -2,7 +2,7 @@ name: Slack PR notification
2
2
 
3
3
  on:
4
4
  pull_request:
5
- branches: [main]
5
+ branches: [main, prerelease]
6
6
  types: [opened, reopened]
7
7
 
8
8
  jobs:
@@ -1,17 +1,40 @@
1
- name: Upgrade
1
+ name: Ω Workflow - Upgrade dependencies
2
2
 
3
3
  on:
4
- workflow_dispatch: # Manual
5
- schedule:
6
- - cron: '0 9 * * 1' # Mondays 9AM UTC
4
+ workflow_call:
5
+ inputs:
6
+ branch:
7
+ type: string
8
+ required: true
9
+ description: The branch that will be upgraded
10
+ patch-only:
11
+ type: boolean
12
+ required: false
13
+ description: Only update if there are newer patch versions
14
+ skip-server:
15
+ type: boolean
16
+ required: false
17
+ description: Skip updating server dependencies
18
+ secrets:
19
+ GH_USER_TOKEN:
20
+ required: true
21
+ JFROG_LIBS_RELEASE_CLIENT_RO_USER:
22
+ required: true
23
+ JFROG_LIBS_RELEASE_CLIENT_RO_KEY:
24
+ required: true
7
25
 
8
26
  jobs:
9
27
  upgrade:
10
28
  runs-on: ubuntu-latest
11
29
  environment: deploy
30
+ env:
31
+ BRANCH: ${{ inputs.branch }}
32
+ PATCH_ARG: ${{ inputs.patch-only && '--patch-only' || '' }}
33
+ SKIP_SERVER_ARG: ${{ inputs.skip-server && '--skip-server' || '' }}
12
34
  steps:
13
35
  - uses: actions/checkout@v4
14
36
  with:
37
+ ref: ${{ inputs.branch }}
15
38
  token: ${{secrets.GH_USER_TOKEN}}
16
39
 
17
40
  - name: Set up Node
@@ -29,7 +52,7 @@ jobs:
29
52
  jfrog config add --artifactory-url="https://genesisglobal.jfrog.io/artifactory" --user="${{ secrets.JFROG_LIBS_RELEASE_CLIENT_RO_USER }}" --password="${{ secrets.JFROG_LIBS_RELEASE_CLIENT_RO_KEY }}" --interactive=false
30
53
 
31
54
  - name: Update to latest versions if available
32
- run: node .genx/scripts/update-versions
55
+ run: node .genx/scripts/update-versions ${PATCH_ARG} ${SKIP_SERVER_ARG}
33
56
 
34
57
  - name: Check for changes
35
58
  id: versions
@@ -39,10 +62,10 @@ jobs:
39
62
  if: steps.versions.outputs.CHANGED
40
63
  run: |
41
64
  git config --global user.email "ci@genesis.global" && git config --global user.name "CI"
42
- git checkout -b chore-dep-update
65
+ git checkout -b chore-dep-update-${BRANCH}
43
66
  git add --all
44
67
  git commit -m "fix: automated dependency version update [skip-ci] PSD-9"
45
- git push -f --set-upstream origin chore-dep-update
68
+ git push -f --set-upstream origin chore-dep-update-${BRANCH}
46
69
 
47
70
  - name: Raise PR
48
71
  if: steps.versions.outputs.CHANGED
@@ -64,8 +87,8 @@ jobs:
64
87
  repo = process.env.REPO,
65
88
  title = 'fix: automated dependency version update [skip-ci] PSD-9',
66
89
  body = 'Automated PR',
67
- head = 'chore-dep-update',
68
- base = 'main';
90
+ head = 'chore-dep-update-${{inputs.branch}}',
91
+ base = '${{inputs.branch}}';
69
92
 
70
93
  (async () => {
71
94
  const response = await octokit.request(
@@ -75,5 +98,3 @@ jobs:
75
98
  EOT
76
99
 
77
100
  node /tmp/create-pr/index
78
-
79
-
@@ -0,0 +1,19 @@
1
+ name: Upgrade main
2
+
3
+ on:
4
+ workflow_dispatch: # Manual
5
+ schedule:
6
+ - cron: '0 8 * * 1-5' # Weekdays 8AM UTC
7
+
8
+ concurrency: upgrade-main
9
+
10
+ jobs:
11
+ upgrade:
12
+ uses: ./.github/workflows/upgrade.yml
13
+ with:
14
+ branch: main
15
+ patch-only: true
16
+ secrets:
17
+ GH_USER_TOKEN: ${{ secrets.GH_USER_TOKEN }}
18
+ JFROG_LIBS_RELEASE_CLIENT_RO_USER: ${{ secrets.JFROG_LIBS_RELEASE_CLIENT_RO_USER }}
19
+ JFROG_LIBS_RELEASE_CLIENT_RO_KEY: ${{ secrets.JFROG_LIBS_RELEASE_CLIENT_RO_KEY }}
@@ -0,0 +1,19 @@
1
+ name: Upgrade prerelease
2
+
3
+ on:
4
+ workflow_dispatch: # Manual
5
+ schedule:
6
+ - cron: '0 8 * * 1-5' # Weekdays 8AM UTC
7
+
8
+ concurrency: upgrade-prerelease
9
+
10
+ jobs:
11
+ upgrade:
12
+ uses: ./.github/workflows/upgrade.yml
13
+ with:
14
+ branch: prerelease
15
+ skip-server: true
16
+ secrets:
17
+ GH_USER_TOKEN: ${{ secrets.GH_USER_TOKEN }}
18
+ JFROG_LIBS_RELEASE_CLIENT_RO_USER: ${{ secrets.JFROG_LIBS_RELEASE_CLIENT_RO_USER }}
19
+ JFROG_LIBS_RELEASE_CLIENT_RO_KEY: ${{ secrets.JFROG_LIBS_RELEASE_CLIENT_RO_KEY }}
package/CHANGELOG.md CHANGED
@@ -1,5 +1,75 @@
1
1
  # Changelog
2
2
 
3
+ ## [3.29.1-prerelease.10](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.29.1-prerelease.9...v3.29.1-prerelease.10) (2024-08-23)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * updating server version information for Auth [PSD-0](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/0) 940ebbc
9
+
10
+ ## [3.29.1-prerelease.9](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.29.1-prerelease.8...v3.29.1-prerelease.9) (2024-08-23)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * updating server version information for GSF [PSD-0](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/0) fea6c6f
16
+
17
+ ## [3.29.1-prerelease.8](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.29.1-prerelease.7...v3.29.1-prerelease.8) (2024-08-23)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * updating server version information for GSF [PSD-0](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/0) 0fbf0b3
23
+
24
+ ## [3.29.1-prerelease.7](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.29.1-prerelease.6...v3.29.1-prerelease.7) (2024-08-20)
25
+
26
+
27
+ ### Bug Fixes
28
+
29
+ * automated dependency version update [skip-ci] [PSD-9](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/9) (#321) b5d9dd9
30
+
31
+ ## [3.29.1-prerelease.6](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.29.1-prerelease.5...v3.29.1-prerelease.6) (2024-08-20)
32
+
33
+
34
+ ### Bug Fixes
35
+
36
+ * updating server version information for GSF [PSD-0](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/0) f18c4cf
37
+
38
+ ## [3.29.1-prerelease.5](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.29.1-prerelease.4...v3.29.1-prerelease.5) (2024-08-16)
39
+
40
+
41
+ ### Bug Fixes
42
+
43
+ * updating server version information for GSF [PSD-0](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/0) a2c959c
44
+
45
+ ## [3.29.1-prerelease.4](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.29.1-prerelease.3...v3.29.1-prerelease.4) (2024-08-16)
46
+
47
+
48
+ ### Bug Fixes
49
+
50
+ * updating server version information for GSF [PSD-0](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/0) 872539b
51
+
52
+ ## [3.29.1-prerelease.3](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.29.1-prerelease.2...v3.29.1-prerelease.3) (2024-08-15)
53
+
54
+
55
+ ### Bug Fixes
56
+
57
+ * useonlytemplatecols not enabled from create GENC-703 (#316) 93c9e9f
58
+
59
+ ## [3.29.1-prerelease.2](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.29.1-prerelease.1...v3.29.1-prerelease.2) (2024-08-15)
60
+
61
+
62
+ ### Bug Fixes
63
+
64
+ * handling multiple hyphens when generating DB namespace PA-1361 (#317) ceda4bb
65
+
66
+ ## [3.29.1-prerelease.1](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.29.0...v3.29.1-prerelease.1) (2024-08-14)
67
+
68
+
69
+ ### Bug Fixes
70
+
71
+ * automated dependency version update [skip-ci] [PSD-9](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/9) (#314) 5070baa
72
+
3
73
  ## [3.29.0](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.28.6...v3.29.0) (2024-08-13)
4
74
 
5
75
 
@@ -19,6 +19,9 @@
19
19
  "@ag-grid-enterprise/core": "29.2.0",
20
20
  "@ag-grid-enterprise/row-grouping": "29.2.0",
21
21
  "@ag-grid-enterprise/server-side-row-model": "29.2.0",
22
+ {{#if FDC3.includeDependencies}}
23
+ "@genesislcap/foundation-fdc3": "{{versions.UI}}",
24
+ {{/if}}
22
25
  "@genesislcap/foundation-comms": "{{versions.UI}}",
23
26
  "@genesislcap/foundation-login": "{{versions.UI}}",
24
27
  "@genesislcap/foundation-entity-management": "{{versions.UI}}",
@@ -1,36 +1,61 @@
1
- import React from 'react';
1
+ import { useEffect } from 'react';
2
2
  import {
3
3
  unstable_HistoryRouter as HistoryRouter,
4
4
  Routes,
5
5
  Route,
6
6
  useLocation,
7
7
  } from 'react-router-dom';
8
- import history from './utils/history';
8
+ import { history } from './utils/history';
9
9
  import LayoutWrapper from './layouts/LayoutWrapper';
10
- import { routeLayouts } from './config';
10
+ import { AUTH_PATH, NOT_PERMITTED_PATH, routeLayouts } from './config';
11
11
  import AuthGuard from './guards/AuthGuard';
12
+ import PermissionsGuard from './guards/PermissionsGuard';
12
13
  import { AuthProvider } from './store/AuthContext';
13
14
  // Pages Components
14
- import AuthPage from './pages/auth/AuthPage';
15
+ import AuthPage from './pages/AuthPage/AuthPage';
16
+ import NotPermittedPage from './pages/NotPermittedPage/NotPermittedPage';
15
17
  {{#each routes}}
16
18
  import {{pascalCase this.name}} from './pages/{{kebabCase this.name}}/{{pascalCase this.name}}';
17
19
  {{/each}}
20
+ {{#if FDC3.channels.length}}
21
+ import { listenToChannel, onFDC3Ready } from './utils';
22
+ {{/if}}
18
23
  // Genesis Components
19
24
  import './share/genesis-components';
20
25
 
21
26
  const LayoutWithLocation = () => {
22
27
  const location = useLocation();
23
28
  const layout = routeLayouts[location.pathname] || 'default';
29
+ {{#if FDC3.channels.length}}
30
+ useEffect(() => {
31
+ {{#each FDC3.channels}}
32
+ listenToChannel('{{this.name}}', '{{this.type}}', (result) => {
33
+ console.log('Received FDC3 channel message on: {{this.name}} channel, type: {{this.type}}', result);
34
+ // TODO: Add your listener logic here
35
+ // E.g. open a modal or route to specific page: Route.path.push(`[Route name]`);
36
+ });
37
+ {{/each}}
38
+
39
+ return () => {
40
+ console.log('Component is being unmounted');
41
+ };
42
+ }, []);
43
+ {{/if}}
24
44
 
25
45
  let pageComponent;
46
+ let permissionCode = '{{this.permissions.viewRight}}';
26
47
 
27
48
  switch (location.pathname) {
28
- case '/auth':
49
+ case `/${AUTH_PATH}`:
29
50
  pageComponent = <AuthPage />;
30
51
  break;
52
+ case `/${NOT_PERMITTED_PATH}`:
53
+ pageComponent = <NotPermittedPage />;
54
+ break;
31
55
  {{#each routes}}
32
56
  case '/{{kebabCase this.name}}':
33
57
  pageComponent = <{{pascalCase this.name}} />;
58
+ permissionCode = '{{this.permissions.viewRight}}';
34
59
  break;
35
60
  {{/each}}
36
61
  default:
@@ -45,7 +70,9 @@ const LayoutWithLocation = () => {
45
70
  } else {
46
71
  return (
47
72
  <AuthGuard>
48
- <LayoutWrapper layout={layout}>{pageComponent}</LayoutWrapper>
73
+ <PermissionsGuard permissionCode={permissionCode}>
74
+ <LayoutWrapper layout={layout}>{pageComponent}</LayoutWrapper>
75
+ </PermissionsGuard>
49
76
  </AuthGuard>
50
77
  );
51
78
  }
@@ -0,0 +1,62 @@
1
+ import React from 'react';
2
+
3
+ const styles = {
4
+ errorMessageWrapper: {
5
+ display: 'flex',
6
+ flexDirection: 'column',
7
+ justifyContent: 'center',
8
+ alignItems: 'center',
9
+ height: '100%',
10
+ width: '100%',
11
+ },
12
+ errorMessage: {
13
+ color: 'var(--neutral-foreground-rest)',
14
+ backgroundColor: 'var(--neutral-layer-4)',
15
+ borderColor: 'var(--error-color)',
16
+ borderRadius: '7px',
17
+ borderStyle: 'solid',
18
+ borderWidth: '4px',
19
+ padding: '5px',
20
+ margin: '15px',
21
+ textAlign: 'center',
22
+ width: 'fit-content',
23
+ alignSelf: 'center',
24
+ height: 'auto',
25
+ maxHeight: '100%'
26
+ },
27
+ };
28
+
29
+ const ErrorMessage = ({ elementType = 'div', message = '' }) => {
30
+ const ElementType = elementType;
31
+
32
+ return (
33
+ <section style={styles.errorMessageWrapper}>
34
+ <div style={styles.errorMessage}>
35
+ {(() => {
36
+ switch (ElementType) {
37
+ case 'h1':
38
+ return <h1>{message}</h1>;
39
+ case 'h2':
40
+ return <h2>{message}</h2>;
41
+ case 'h3':
42
+ return <h3>{message}</h3>;
43
+ case 'h4':
44
+ return <h4>{message}</h4>;
45
+ case 'h5':
46
+ return <h5>{message}</h5>;
47
+ case 'h6':
48
+ return <h6>{message}</h6>;
49
+ case 'p':
50
+ return <p>{message}</p>;
51
+ case 'span':
52
+ return <span>{message}</span>;
53
+ default:
54
+ return <div>{message}</div>;
55
+ }
56
+ })()}
57
+ </div>
58
+ </section>
59
+ );
60
+ };
61
+
62
+ export default ErrorMessage;
@@ -9,6 +9,7 @@ export const routeLayouts: RouteLayouts = {
9
9
  import type { MainMenu } from './types/menu';
10
10
 
11
11
  export const AUTH_PATH = 'auth';
12
+ export const NOT_PERMITTED_PATH = 'not-permitted';
12
13
 
13
14
  export const API_DATA = {
14
15
  URL: '',
@@ -0,0 +1,37 @@
1
+ import { useEffect, useState, ReactNode } from 'react';
2
+ import { useNavigate } from 'react-router-dom';
3
+ import { getUser } from '@genesislcap/foundation-user';
4
+ import { NOT_PERMITTED_PATH } from '../config';
5
+
6
+ interface PermissionsGuardProps {
7
+ children: ReactNode;
8
+ permissionCode?: string;
9
+ }
10
+
11
+ const PermissionsGuard: React.FC<PermissionsGuardProps> = ({ children, permissionCode }: PermissionsGuardProps) => {
12
+ const navigate = useNavigate();
13
+ const [isAuthorized, setIsAuthorized] = useState(false);
14
+ const [isLoading, setIsLoading] = useState(true);
15
+
16
+ useEffect(() => {
17
+ const checkPermission = async () => {
18
+ const user = getUser();
19
+ if (permissionCode && !user.hasPermission(permissionCode)) {
20
+ navigate(`/${NOT_PERMITTED_PATH}`);
21
+ } else {
22
+ setIsAuthorized(true);
23
+ }
24
+ setIsLoading(false);
25
+ };
26
+
27
+ checkPermission();
28
+ }, [navigate, permissionCode]);
29
+
30
+ if (isLoading) {
31
+ return <div>Loading...</div>; // Or some loading component
32
+ }
33
+
34
+ return isAuthorized ? <>{children}</> : null;
35
+ };
36
+
37
+ export default PermissionsGuard;
@@ -0,0 +1,13 @@
1
+ import ErrorMessage from '../../components/ErrorMessage/ErrorMessage';
2
+ import './NotPermittedPage.css';
3
+
4
+ const NotPermittedPage = () => {
5
+ return (
6
+ <ErrorMessage
7
+ elementType="h1"
8
+ message="You do not have permission to access this part of the application, please contact your administrator."
9
+ ></ErrorMessage>
10
+ );
11
+ };
12
+
13
+ export default NotPermittedPage;
@@ -1,7 +1,7 @@
1
1
  import {configure, define} from '@genesislcap/foundation-login';
2
2
  import { AUTH_PATH } from '../config';
3
3
  import { DI } from '@microsoft/fast-foundation';
4
- import history from '../utils/history';
4
+ import { history } from '../utils/history';
5
5
 
6
6
  /**
7
7
  * Configure the micro frontend
@@ -0,0 +1,32 @@
1
+ {{#if FDC3.includeDependencies}}
2
+ import { DefaultFDC3 } from '@genesislcap/foundation-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 listenToChannel = async (
16
+ channelName: string,
17
+ type: string,
18
+ callback: (result: any) => void,
19
+ ): Promise<void> => {
20
+ const fdc3Service = new DefaultFDC3();
21
+ fdc3Service.addChannelListener(channelName, type, callback);
22
+ };
23
+
24
+ export const sendEventOnChannel = (channelName: string, type: string) => {
25
+ return async (e: any) => {
26
+ const fdc3Service = new DefaultFDC3();
27
+ // check for ag-grid-specific events, fall back to standard events
28
+ const payload = e.data || e.detail;
29
+ await fdc3Service.broadcastOnChannel(channelName, type, payload);
30
+ };
31
+ };
32
+ {{/if}}
@@ -1,5 +1,3 @@
1
1
  import { createBrowserHistory } from 'history';
2
2
 
3
- const history = createBrowserHistory();
4
-
5
- export default history;
3
+ export const history = createBrowserHistory();
@@ -0,0 +1,3 @@
1
+ export * from './history';
2
+ export * from './fdc3';
3
+ export * from './permissions';
@@ -0,0 +1,7 @@
1
+ import { User } from '@genesislcap/foundation-user';
2
+
3
+ export const getViewUpdateRightComponent = (
4
+ user: User,
5
+ right: string,
6
+ event: string | boolean = true,
7
+ ) => (!right || user.hasPermission(right) ? event : '');
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": "3.29.0",
4
+ "version": "3.29.1-prerelease.10",
5
5
  "license": "Apache-2.0",
6
6
  "scripts": {
7
7
  "release": "semantic-release"