@genesislcap/blank-app-seed 5.2.0-prerelease.7 → 5.2.0-prerelease.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesislcap/blank-app-seed-config",
3
3
  "description": "Genesis Blank App Seed Configuration",
4
- "version": "5.2.0-prerelease.7",
4
+ "version": "5.2.0-prerelease.8",
5
5
  "license": "Apache-2.0",
6
6
  "scripts": {
7
7
  "lint": "eslint .",
@@ -1,4 +1,4 @@
1
- import { CustomEvent } from "../../../utils/customEvents";
1
+ import { CustomEventHandler } from "../../../utils/customEvents";
2
2
 
3
3
  {{#each tile.config.customEvents}}
4
4
  {{#if this.hasForm}}
@@ -14,7 +14,7 @@ export const customEventFormSchemas = {
14
14
  {{/each}}
15
15
  };
16
16
 
17
- export const customEvents: CustomEvent[] = [
17
+ export const customEvents: CustomEventHandler[] = [
18
18
  {{#each tile.config.customEvents}}
19
19
  {
20
20
  baseEvent: '{{this.baseEvent}}',
@@ -29,4 +29,4 @@ export const customEvents: CustomEvent[] = [
29
29
  defaultValues: {{{this.defaultValues}}},
30
30
  },
31
31
  {{/each}}
32
- ];
32
+ ];
@@ -1,10 +1,16 @@
1
1
  {{#if tile.config.permissions.viewRight~}}
2
2
  import { getUser } from '@genesislcap/foundation-user';
3
- import { getViewUpdateRightComponent } from '../../../utils';
3
+ {{#if tile.config.customEvents}}
4
+ import { customEvent } from '@genesislcap/foundation-events';
5
+ {{/if}}
6
+ import { getViewUpdateRightComponent{{#if tile.config.customEvents}}, submitFailureNotification{{/if}} } from '../../../utils';
4
7
  import ErrorMessage from '../../../components/ErrorMessage/ErrorMessage';
5
8
  {{else if tile.config.permissions.updateRight~}}
6
9
  import { getUser } from '@genesislcap/foundation-user';
7
- import { getViewUpdateRightComponent } from '../../../utils';
10
+ {{#if tile.config.customEvents}}
11
+ import { customEvent } from '@genesislcap/foundation-events';
12
+ {{/if}}
13
+ import { getViewUpdateRightComponent{{#if tile.config.customEvents}}, submitFailureNotification{{/if}} } from '../../../utils';
8
14
  import ErrorMessage from '../../../components/ErrorMessage/ErrorMessage';
9
15
  {{/if}}
10
16
  {{#if tile.config.customEvents}}
@@ -15,7 +21,7 @@ import type { ActionRendererParams } from '@genesislcap/rapid-grid-pro';
15
21
  import { RapidAgActionRenderer } from '@genesislcap/rapid-grid-pro';
16
22
  import { Modal } from '@genesislcap/rapid-design-system';
17
23
  import { customEvents, customEventFormSchemas } from './{{pascalCase tile.title}}EventsConfig';
18
- import { useCustomEvent, type CustomEvent, type CustomEventState } from '../../../utils/customEvents';
24
+ import { useCustomEvent, type CustomEventHandler, type CustomEventState } from '../../../utils/customEvents';
19
25
  {{/if}}
20
26
  {{#if tile.config.createFormUiSchema~}}
21
27
  import { createFormSchema as createFormSchemaTile } from './{{pascalCase tile.title}}CreateFormSchema';
@@ -38,7 +44,7 @@ import './{{pascalCase tile.title}}Component.css';
38
44
  {{#ifAny tile.metadata.comment tile.metadata.todo}}
39
45
  /**
40
46
  {{~#if tile.metadata.comment}}{{{ tile.metadata.comment }}}{{/if}}
41
- {{~#if tile.metadata.todo}}{{#if tile.metadata.comment}}
47
+ {{~#if tile.metadata.todo}}{{#if tile.metadata.comment}}
42
48
  *{{/if}}
43
49
  * TODO: {{{ tile.metadata.todo }}}{{/if}}
44
50
  */
@@ -168,7 +174,7 @@ export const {{pascalCase tile.componentName}}: React.FC = () => {
168
174
 
169
175
  const renderFormModal = () => {
170
176
  if (!activeCustomEvent) return null;
171
-
177
+
172
178
  return createPortal(
173
179
  <rapid-modal
174
180
  ref={customEventModalRef}
@@ -180,6 +186,8 @@ export const {{pascalCase tile.componentName}}: React.FC = () => {
180
186
  uischema={getCustomEventUiSchema()}
181
187
  data={customEventFormData}
182
188
  onsubmit-success={handleCustomEventSubmit}
189
+ onsubmit={submitFailureNotification}
190
+ onsubmit-failure={submitFailureNotification}
183
191
  ></foundation-form>
184
192
  </rapid-modal>,
185
193
  document.querySelector('rapid-design-system-provider')!
@@ -190,4 +198,4 @@ export const {{pascalCase tile.componentName}}: React.FC = () => {
190
198
  return (
191
199
  {{> (lookup tile 'type') tile}}
192
200
  );
193
- };
201
+ };
@@ -1,4 +1,4 @@
1
- import { CustomEvent } from "../../../utils/customEvents";
1
+ import { CustomEventHandler } from "../../../utils/customEvents";
2
2
 
3
3
  {{#each tile.config.customEvents}}
4
4
  {{#if this.hasForm}}
@@ -14,7 +14,7 @@ export const customEventFormSchemas = {
14
14
  {{/each}}
15
15
  };
16
16
 
17
- export const customEvents: CustomEvent[] = [
17
+ export const customEvents: CustomEventHandler[] = [
18
18
  {{#each tile.config.customEvents}}
19
19
  {
20
20
  baseEvent: '{{this.baseEvent}}',
@@ -12,7 +12,7 @@ import type { ActionRendererParams } from '@genesislcap/rapid-grid-pro';
12
12
  import { RapidAgActionRenderer } from '@genesislcap/rapid-grid-pro';
13
13
  import { Modal } from '@genesislcap/rapid-design-system';
14
14
  import { customEvents, customEventFormSchemas } from './{{kebabCase tile.title}}.events.config';
15
- import { handleFormCustomEvent, handleNonFormCustomEvent, showCustomEventConfirmation, type CustomEvent, type CustomEventState } from '../../../utils/customEvents';
15
+ import { handleFormCustomEvent, handleNonFormCustomEvent, showCustomEventConfirmation, type CustomEventHandler, type CustomEventState } from '../../../utils/customEvents';
16
16
  {{/if}}
17
17
 
18
18
  {{#ifAny tile.metadata.comment tile.metadata.todo}}
@@ -35,7 +35,7 @@ export class {{pascalCase tile.componentName}} extends GenesisElement {
35
35
 
36
36
  {{#if tile.config.customEvents}}
37
37
  customEventModal: Modal;
38
- @observable customEvents: CustomEvent[] = customEvents;
38
+ @observable customEvents: CustomEventHandler[] = customEvents;
39
39
  @observable activeCustomEvent: CustomEventState | null = null;
40
40
  @observable customEventFormData: Record<string, any> = {};
41
41
 
@@ -1,5 +1,8 @@
1
1
  import { html, when, whenElse, ref, repeat } from '@genesislcap/web-core';
2
- import { getViewUpdateRightComponent } from '../../../utils';
2
+ {{#if tile.config.customEvents}}
3
+ import { customEvent } from '@genesislcap/foundation-events';
4
+ {{/if}}
5
+ import { getViewUpdateRightComponent{{#if tile.config.customEvents}}, submitFailureNotification{{/if}} } from '../../../utils';
3
6
  import type { {{pascalCase tile.componentName}} } from './{{kebabCase tile.title}}';
4
7
  {{#if tile.config.createFormUiSchema}}
5
8
  import { createFormSchema } from './{{kebabCase tile.title}}.create.form.schema';
@@ -64,6 +64,8 @@ ${whenElse(
64
64
  :uischema=${(x) => x.getCustomEventUiSchema()}
65
65
  :data=${(x) => x.customEventFormData}
66
66
  @submit-success=${(x) => x.handleCustomEventSubmit()}
67
+ @submit=${(_, c) => submitFailureNotification(customEvent(c))}
68
+ @submit-failure=${(_, c) => submitFailureNotification(customEvent(c))}
67
69
  ></foundation-form>
68
70
  `,
69
71
  )}
@@ -73,4 +75,4 @@ ${whenElse(
73
75
  html`
74
76
  <not-permitted-component></not-permitted-component>
75
77
  `,
76
- )}
78
+ )}
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.2.0-prerelease.8](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v5.2.0-prerelease.7...v5.2.0-prerelease.8) (2025-07-01)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * show server errors in form GENC-1116 (#479) 3cc189f
9
+
3
10
  ## [5.2.0-prerelease.7](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v5.2.0-prerelease.6...v5.2.0-prerelease.7) (2025-07-01)
4
11
 
5
12
 
@@ -1,12 +1,20 @@
1
1
  import { getConnect } from '@genesislcap/foundation-comms';
2
- import { showNotificationDialog } from '@genesislcap/foundation-notifications';
2
+ import { showNotification, showNotificationDialog } from '@genesislcap/foundation-notifications';
3
3
 
4
4
  interface ConfirmSubmit {
5
5
  state: 'enabled' | 'disabled';
6
6
  message: string;
7
7
  }
8
8
 
9
- export interface CustomEvent {
9
+ interface CustomEventError {
10
+ errors: {
11
+ message?: string;
12
+ CODE: string;
13
+ TEXT: string;
14
+ }[];
15
+ }
16
+
17
+ export interface CustomEventHandler {
10
18
  baseEvent: string;
11
19
  name: string;
12
20
  hasForm: boolean;
@@ -50,20 +58,36 @@ export const mapDefaultValues = (
50
58
  );
51
59
 
52
60
  export const executeCustomEvent = async (
53
- customEvent: CustomEvent,
61
+ customEventHandler: CustomEventHandler,
54
62
  rowData: any
55
63
  ): Promise<void> => {
56
- const payload = customEvent.defaultValues
57
- ? mapDefaultValues(customEvent.defaultValues, rowData)
64
+ const payload = customEventHandler.defaultValues
65
+ ? mapDefaultValues(customEventHandler.defaultValues, rowData)
58
66
  : {};
59
67
 
60
- await getConnect().commitEvent(`EVENT_${customEvent.baseEvent}`, {
61
- DETAILS: payload,
62
- });
68
+ const res = await getConnect().commitEvent(
69
+ `EVENT_${customEventHandler.baseEvent}`,
70
+ { DETAILS: payload }
71
+ );
72
+
73
+ if (res.MESSAGE_TYPE === 'EVENT_NACK') {
74
+ const err: CustomEventError = {
75
+ errors:
76
+ res?.ERROR?.map((e) => ({
77
+ TEXT: e.TEXT,
78
+ CODE: e.STATUS_CODE ?? '0 Unknown Error',
79
+ message:
80
+ 'PATH' in e && typeof e.PATH === 'string' && 'FIELD' in e && typeof e.FIELD === 'string'
81
+ ? e.TEXT.replace(e.PATH, e.FIELD)
82
+ : undefined,
83
+ })) ?? [],
84
+ };
85
+ submitFailureNotification(new CustomEvent('Error', { detail: err }));
86
+ }
63
87
  };
64
88
 
65
89
  export const showCustomEventConfirmation = (
66
- customEvent: CustomEvent,
90
+ customEvent: CustomEventHandler,
67
91
  onConfirm: () => Promise<void>
68
92
  ): void => {
69
93
  showNotificationDialog(
@@ -87,9 +111,43 @@ export const showCustomEventConfirmation = (
87
111
  );
88
112
  };
89
113
 
114
+ export const submitFailureNotification = (e: CustomEvent<CustomEventError>) => {
115
+ e.detail.errors.forEach((submitFailureError) => {
116
+ if (submitFailureError.CODE === 'OPTIMISTIC_CONCURRENCY_ERROR') {
117
+ showNotification(
118
+ {
119
+ title: 'Warning',
120
+ body: "You're editing an old revision. Please close the form and try editing again",
121
+ config: {
122
+ snackbar: {
123
+ type: 'error',
124
+ },
125
+ },
126
+ },
127
+ 'rapid',
128
+ );
129
+ } else {
130
+ showNotification(
131
+ {
132
+ title: 'Error submitting form',
133
+ body:
134
+ submitFailureError.message ??
135
+ (submitFailureError.CODE + ': ' + submitFailureError.TEXT).toString(),
136
+ config: {
137
+ snackbar: {
138
+ type: 'error',
139
+ },
140
+ },
141
+ },
142
+ 'rapid',
143
+ );
144
+ }
145
+ });
146
+ };
147
+
90
148
  export const useCustomEvent =
91
149
  (
92
- customEvent: CustomEvent,
150
+ customEvent: CustomEventHandler,
93
151
  rowData: any,
94
152
  setFormData: (data: Record<string, any>) => void,
95
153
  setActiveEvent: (event: CustomEventState | null) => void
@@ -1,5 +1,6 @@
1
+ export * from './customEvents';
1
2
  export * from './fdc3';
3
+ export * from './getLayoutNameByRoute';
2
4
  export * from './layout';
3
5
  export * from './permissions';
4
6
  export * from './setApiHost';
5
- export * from './getLayoutNameByRoute';
@@ -1,12 +1,20 @@
1
1
  import { Connect } from '@genesislcap/foundation-comms';
2
- import { showNotificationDialog } from '@genesislcap/foundation-notifications';
2
+ import { showNotification, showNotificationDialog } from '@genesislcap/foundation-notifications';
3
3
 
4
4
  interface ConfirmSubmit {
5
5
  state: 'enabled' | 'disabled';
6
6
  message: string;
7
7
  }
8
8
 
9
- export interface CustomEvent {
9
+ interface CustomEventError {
10
+ errors: {
11
+ message?: string;
12
+ CODE: string;
13
+ TEXT: string;
14
+ }[];
15
+ }
16
+
17
+ export interface CustomEventHandler {
10
18
  baseEvent: string;
11
19
  name: string;
12
20
  hasForm: boolean;
@@ -45,20 +53,35 @@ export const mapDefaultValues = (defaultValues: DefaultValues, rowData: any): Re
45
53
 
46
54
  export const executeCustomEvent = async (
47
55
  connect: Connect,
48
- customEvent: CustomEvent,
56
+ customEvent: CustomEventHandler,
49
57
  rowData: any,
50
58
  ): Promise<void> => {
51
59
  const payload = customEvent.defaultValues
52
60
  ? mapDefaultValues(customEvent.defaultValues, rowData)
53
61
  : {};
54
62
 
55
- await connect.commitEvent(`EVENT_${customEvent.baseEvent}`, {
63
+ const res = await connect.commitEvent(`EVENT_${customEvent.baseEvent}`, {
56
64
  DETAILS: payload,
57
65
  });
66
+
67
+ if (res.MESSAGE_TYPE === 'EVENT_NACK') {
68
+ const err: CustomEventError = {
69
+ errors:
70
+ res?.ERROR?.map((e) => ({
71
+ TEXT: e.TEXT,
72
+ CODE: e.STATUS_CODE ?? '0 Unknown Error',
73
+ message:
74
+ 'PATH' in e && typeof e.PATH === 'string' && 'FIELD' in e && typeof e.FIELD === 'string'
75
+ ? e.TEXT.replace(e.PATH, e.FIELD)
76
+ : undefined,
77
+ })) ?? [],
78
+ };
79
+ submitFailureNotification(new CustomEvent('Error', { detail: err }));
80
+ }
58
81
  };
59
82
 
60
83
  export const showCustomEventConfirmation = (
61
- customEvent: CustomEvent,
84
+ customEvent: CustomEventHandler,
62
85
  onConfirm: () => Promise<void>,
63
86
  ): void => {
64
87
  showNotificationDialog(
@@ -82,8 +105,42 @@ export const showCustomEventConfirmation = (
82
105
  );
83
106
  };
84
107
 
108
+ export const submitFailureNotification = (e: CustomEvent<CustomEventError>) => {
109
+ e.detail.errors.forEach((submitFailureError) => {
110
+ if (submitFailureError.CODE === 'OPTIMISTIC_CONCURRENCY_ERROR') {
111
+ showNotification(
112
+ {
113
+ title: 'Warning',
114
+ body: "You're editing an old revision. Please close the form and try editing again",
115
+ config: {
116
+ snackbar: {
117
+ type: 'error',
118
+ },
119
+ },
120
+ },
121
+ 'rapid',
122
+ );
123
+ } else {
124
+ showNotification(
125
+ {
126
+ title: 'Error submitting form',
127
+ body:
128
+ submitFailureError.message ??
129
+ (submitFailureError.CODE + ': ' + submitFailureError.TEXT).toString(),
130
+ config: {
131
+ snackbar: {
132
+ type: 'error',
133
+ },
134
+ },
135
+ },
136
+ 'rapid',
137
+ );
138
+ }
139
+ });
140
+ };
141
+
85
142
  export const handleFormCustomEvent = (
86
- customEvent: CustomEvent,
143
+ customEvent: CustomEventHandler,
87
144
  rowData: any,
88
145
  setFormData: (data: Record<string, any>) => void,
89
146
  setActiveEvent: (event: CustomEventState) => void,
@@ -99,7 +156,7 @@ export const handleFormCustomEvent = (
99
156
 
100
157
  export const handleNonFormCustomEvent = async (
101
158
  connect: Connect,
102
- customEvent: CustomEvent,
159
+ customEvent: CustomEventHandler,
103
160
  rowData: any,
104
161
  showConfirmation: (onConfirm: () => Promise<void>) => void,
105
162
  ): Promise<void> => {
@@ -1,3 +1,4 @@
1
+ export * from './customEvents';
1
2
  export * from './fdc3';
2
3
  export * from './layout';
3
4
  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": "5.2.0-prerelease.7",
4
+ "version": "5.2.0-prerelease.8",
5
5
  "license": "Apache-2.0",
6
6
  "scripts": {
7
7
  "release": "semantic-release"