@genesislcap/blank-app-seed 3.29.1-prerelease.1 → 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 (39) hide show
  1. package/.genx/configure.js +1 -1
  2. package/.genx/package.json +1 -1
  3. package/.genx/scripts/update-versions.js +45 -15
  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 +6 -1
  23. package/.github/workflows/upgrade_prerelease.yml +1 -0
  24. package/CHANGELOG.md +63 -0
  25. package/client-tmp/react/package.json +3 -0
  26. package/client-tmp/react/src/App.tsx +33 -6
  27. package/client-tmp/react/src/components/ErrorMessage/ErrorMessage.jsx +62 -0
  28. package/client-tmp/react/src/config.ts +1 -0
  29. package/client-tmp/react/src/guards/PermissionsGuard.tsx +37 -0
  30. package/client-tmp/react/src/pages/NotPermittedPage/NotPermittedPage.css +0 -0
  31. package/client-tmp/react/src/pages/NotPermittedPage/NotPermittedPage.jsx +13 -0
  32. package/client-tmp/react/src/share/foundation-login.ts +1 -1
  33. package/client-tmp/react/src/utils/fdc3.ts +32 -0
  34. package/client-tmp/react/src/utils/history.ts +1 -3
  35. package/client-tmp/react/src/utils/index.ts +3 -0
  36. package/client-tmp/react/src/utils/permissions.ts +7 -0
  37. package/package.json +1 -1
  38. /package/client-tmp/react/src/pages/{auth → AuthPage}/AuthPage.css +0 -0
  39. /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.1-prerelease.1",
4
+ "version": "3.29.1-prerelease.10",
5
5
  "license": "Apache-2.0",
6
6
  "scripts": {
7
7
  "lint": "eslint .",
@@ -4,23 +4,30 @@ const { resolve } = require('node:path');
4
4
  const current = require('../versions.json');
5
5
 
6
6
  const args = process.argv.slice(2);
7
- const patchOnly = args.indexOf("--patch-only") >= 0;
8
- const dryRun = args.indexOf("--dry-run") >= 0;
9
7
 
10
- const VERSION_REGEX = /\d+$/;
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");
11
13
 
12
- const jfrogVersionMatcher = patchOnly ? current.GSF.replace(VERSION_REGEX, '*') : undefined;
14
+ const VERSION_REGEX = /\d+$/;
15
+ const JFROG_BASE_EXCLUSIONS = '*-SNAPSHOT*;*maven-metadata*;*test*;*TEST*';
13
16
 
14
- const npmVersionMatcher = patchOnly ? current.UI.replace(VERSION_REGEX, 'x') : 'latest';
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' };
15
20
 
16
- console.log('Running with: ', {patchOnly, dryRun, npmVersionMatcher, jfrogVersionMatcher})
21
+ console.log('Running with: ', { patchOnly, skipServer, dryRun, npmVersionMatcher, jfrogVersionMatcher, jfrogExclusionsMatcher });
17
22
 
18
- const run = (command) =>
19
- execSync(command, {
23
+ const run = (command) => {
24
+ console.debug('running:', command);
25
+ return execSync(command, {
20
26
  stdio: ['pipe', 'pipe', 'ignore'],
21
27
  })
22
28
  .toString('utf8')
23
29
  .trim();
30
+ };
24
31
 
25
32
  const writeJSON = (json, path) => {
26
33
  const data = JSON.stringify(json, null, 2) + '\n';
@@ -32,15 +39,38 @@ const writeJSON = (json, path) => {
32
39
  }
33
40
  };
34
41
 
35
- const UI = run(`npm info @genesislcap/foundation-ui@${npmVersionMatcher} version`);
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`;
36
62
 
37
- const GSF = run(
38
- `jf rt s "libs-release-client/global/genesis/genesis-distribution/${jfrogVersionMatcher ?? ''}" --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`,
39
- );
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
+ };
40
73
 
41
- const Auth = run(
42
- `jf rt s "libs-release-client/global/genesis/auth-distribution/${jfrogVersionMatcher ?? ''}" --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`,
43
- );
44
74
  const latest = { UI, GSF, Auth };
45
75
 
46
76
  console.log('Current:', current);
@@ -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.4",
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:
@@ -11,6 +11,10 @@ on:
11
11
  type: boolean
12
12
  required: false
13
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
14
18
  secrets:
15
19
  GH_USER_TOKEN:
16
20
  required: true
@@ -26,6 +30,7 @@ jobs:
26
30
  env:
27
31
  BRANCH: ${{ inputs.branch }}
28
32
  PATCH_ARG: ${{ inputs.patch-only && '--patch-only' || '' }}
33
+ SKIP_SERVER_ARG: ${{ inputs.skip-server && '--skip-server' || '' }}
29
34
  steps:
30
35
  - uses: actions/checkout@v4
31
36
  with:
@@ -47,7 +52,7 @@ jobs:
47
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
48
53
 
49
54
  - name: Update to latest versions if available
50
- run: node .genx/scripts/update-versions ${PATCH_ARG}
55
+ run: node .genx/scripts/update-versions ${PATCH_ARG} ${SKIP_SERVER_ARG}
51
56
 
52
57
  - name: Check for changes
53
58
  id: versions
@@ -12,6 +12,7 @@ jobs:
12
12
  uses: ./.github/workflows/upgrade.yml
13
13
  with:
14
14
  branch: prerelease
15
+ skip-server: true
15
16
  secrets:
16
17
  GH_USER_TOKEN: ${{ secrets.GH_USER_TOKEN }}
17
18
  JFROG_LIBS_RELEASE_CLIENT_RO_USER: ${{ secrets.JFROG_LIBS_RELEASE_CLIENT_RO_USER }}
package/CHANGELOG.md CHANGED
@@ -1,5 +1,68 @@
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
+
3
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)
4
67
 
5
68
 
@@ -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.1-prerelease.1",
4
+ "version": "3.29.1-prerelease.10",
5
5
  "license": "Apache-2.0",
6
6
  "scripts": {
7
7
  "release": "semantic-release"