@genesislcap/pbc-reporting-ui 14.396.3 → 14.397.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dts/new/main/edit-config/col-filters/col-filters-grid.helpers.d.ts.map +1 -1
- package/dist/dts/new/main/edit-config/datasource-config/datasource-config-item.d.ts +6 -2
- package/dist/dts/new/main/edit-config/datasource-config/datasource-config-item.d.ts.map +1 -1
- package/dist/dts/new/main/edit-config/datasource-config/datasource-config-item.styles.d.ts.map +1 -1
- package/dist/dts/new/main/edit-config/datasource-config/datasource-config-item.template.d.ts.map +1 -1
- package/dist/dts/new/main/edit-config/datasource-config/datasources-config-container.helpers.d.ts.map +1 -1
- package/dist/dts/new/main/edit-config/datasource-config/datasources-config-container.template.d.ts.map +1 -1
- package/dist/dts/new/main/edit-config/shared/datasource-data-base-component.helpers.ts.d.ts.map +1 -1
- package/dist/dts/new/store/slices/datasources-config.d.ts +20 -6
- package/dist/dts/new/store/slices/datasources-config.d.ts.map +1 -1
- package/dist/dts/new/store/slices/types.d.ts +19 -2
- package/dist/dts/new/store/slices/types.d.ts.map +1 -1
- package/dist/dts/new/store/store.d.ts +133 -35
- package/dist/dts/new/store/store.d.ts.map +1 -1
- package/dist/dts/new/types/misc.d.ts +4 -2
- package/dist/dts/new/types/misc.d.ts.map +1 -1
- package/dist/dts/new/utils/alias-generator.d.ts +8 -0
- package/dist/dts/new/utils/alias-generator.d.ts.map +1 -0
- package/dist/dts/new/utils/alias-generator.test.d.ts +2 -0
- package/dist/dts/new/utils/alias-generator.test.d.ts.map +1 -0
- package/dist/dts/new/utils/index.d.ts +1 -0
- package/dist/dts/new/utils/index.d.ts.map +1 -1
- package/dist/dts/new/utils/tooltip.d.ts +3 -0
- package/dist/dts/new/utils/tooltip.d.ts.map +1 -1
- package/dist/dts/new/utils/transformers.d.ts +1 -1
- package/dist/dts/new/utils/transformers.d.ts.map +1 -1
- package/dist/esm/new/main/edit-config/col-filters/col-filters-grid.helpers.js +3 -1
- package/dist/esm/new/main/edit-config/col-filters/col-filters-grid.helpers.test.js +71 -6
- package/dist/esm/new/main/edit-config/col-rename-alias/col-rename-alias-grid.helpers.test.js +32 -4
- package/dist/esm/new/main/edit-config/data-transforms-derived-fields/data-transforms.helpers.test.js +10 -2
- package/dist/esm/new/main/edit-config/datasource-config/datasource-config-item.js +100 -10
- package/dist/esm/new/main/edit-config/datasource-config/datasource-config-item.styles.js +6 -0
- package/dist/esm/new/main/edit-config/datasource-config/datasource-config-item.template.js +38 -3
- package/dist/esm/new/main/edit-config/datasource-config/datasources-config-container.helpers.js +11 -7
- package/dist/esm/new/main/edit-config/datasource-config/datasources-config-container.helpers.test.js +29 -22
- package/dist/esm/new/main/edit-config/datasource-config/datasources-config-container.template.js +3 -0
- package/dist/esm/new/main/edit-config/shared/datasource-data-base-component.helpers.ts.js +16 -8
- package/dist/esm/new/main/edit-config/shared/datasource-data-base-component.test.js +13 -2
- package/dist/esm/new/main/edit-config/tabbed-datasource-container/tabbed-datasource-container.template.js +1 -1
- package/dist/esm/new/store/slices/datasources-config.js +50 -11
- package/dist/esm/new/store/slices/types.js +1 -0
- package/dist/esm/new/utils/alias-generator.js +16 -0
- package/dist/esm/new/utils/alias-generator.test.js +36 -0
- package/dist/esm/new/utils/index.js +1 -0
- package/dist/esm/new/utils/tooltip.js +16 -0
- package/dist/esm/new/utils/transformers.js +20 -6
- package/dist/esm/new/utils/transformers.test.js +61 -11
- package/dist/esm/new/utils/validators.test.js +35 -21
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +22 -22
- package/src/new/main/edit-config/col-filters/col-filters-grid.helpers.test.ts +76 -6
- package/src/new/main/edit-config/col-filters/col-filters-grid.helpers.ts +4 -1
- package/src/new/main/edit-config/col-rename-alias/col-rename-alias-grid.helpers.test.ts +32 -4
- package/src/new/main/edit-config/data-transforms-derived-fields/data-transforms.helpers.test.ts +10 -2
- package/src/new/main/edit-config/datasource-config/datasource-config-item.styles.ts +6 -0
- package/src/new/main/edit-config/datasource-config/datasource-config-item.template.ts +62 -3
- package/src/new/main/edit-config/datasource-config/datasource-config-item.ts +107 -8
- package/src/new/main/edit-config/datasource-config/datasources-config-container.helpers.test.ts +32 -23
- package/src/new/main/edit-config/datasource-config/datasources-config-container.helpers.ts +18 -10
- package/src/new/main/edit-config/datasource-config/datasources-config-container.template.ts +6 -0
- package/src/new/main/edit-config/shared/datasource-data-base-component.helpers.ts.ts +21 -11
- package/src/new/main/edit-config/shared/datasource-data-base-component.test.ts +14 -2
- package/src/new/main/edit-config/tabbed-datasource-container/tabbed-datasource-container.template.ts +1 -1
- package/src/new/store/slices/datasources-config.ts +71 -16
- package/src/new/store/slices/types.ts +22 -4
- package/src/new/types/misc.ts +9 -2
- package/src/new/utils/alias-generator.test.ts +44 -0
- package/src/new/utils/alias-generator.ts +18 -0
- package/src/new/utils/index.ts +1 -0
- package/src/new/utils/tooltip.ts +19 -0
- package/src/new/utils/transformers.test.ts +73 -11
- package/src/new/utils/transformers.ts +30 -6
- package/src/new/utils/validators.test.ts +35 -21
|
@@ -28,6 +28,8 @@ LookupColumnRename('should return original data when no rename is found', () =>
|
|
|
28
28
|
INPUT_TYPE: 'REQ_REP' as const,
|
|
29
29
|
OUTPUT_TYPE: 'TABLE' as const,
|
|
30
30
|
TRANSFORMER_CONFIGURATION: { COLUMN_RENAMES: {} },
|
|
31
|
+
GROUPING_STRATEGY: 'NONE',
|
|
32
|
+
GROUP_KEY: null,
|
|
31
33
|
});
|
|
32
34
|
|
|
33
35
|
const result = lookupColumnRename(mockData);
|
|
@@ -56,6 +58,8 @@ LookupColumnRename('should return data with renamed display name when rename exi
|
|
|
56
58
|
[originalColumn]: newDisplayName,
|
|
57
59
|
},
|
|
58
60
|
},
|
|
61
|
+
GROUPING_STRATEGY: 'NONE',
|
|
62
|
+
GROUP_KEY: null,
|
|
59
63
|
});
|
|
60
64
|
|
|
61
65
|
const result = lookupColumnRename(mockData);
|
|
@@ -81,6 +85,8 @@ LookupColumnRename('should handle undefined COLUMN_RENAMES', () => {
|
|
|
81
85
|
INPUT_TYPE: 'REQ_REP' as const,
|
|
82
86
|
OUTPUT_TYPE: 'TABLE' as const,
|
|
83
87
|
TRANSFORMER_CONFIGURATION: {},
|
|
88
|
+
GROUPING_STRATEGY: 'NONE',
|
|
89
|
+
GROUP_KEY: null,
|
|
84
90
|
});
|
|
85
91
|
|
|
86
92
|
const result = lookupColumnRename(mockData);
|
|
@@ -101,13 +107,24 @@ DisplayNameOnChangeHandler('calls setColumnRename with correct parameters when v
|
|
|
101
107
|
const callback = sinon.spy();
|
|
102
108
|
const handler = displayNameOnChangeHandler(callback);
|
|
103
109
|
const mockData = {
|
|
104
|
-
[GridColumnNames.Datasource]: '
|
|
110
|
+
[GridColumnNames.Datasource]: 'testAlias (Snapshot)',
|
|
105
111
|
[GridColumnNames.ColumnName]: 'originalColumn',
|
|
106
112
|
[GridColumnNames.DisplayName]: 'Original Display',
|
|
107
113
|
[GridColumnNames.Type]: 'STRING',
|
|
108
114
|
} as ColumnRenameAliasRowData;
|
|
109
115
|
|
|
110
116
|
const setColumnRenameStub = sinon.stub(actions.datasourceConfig, 'setColumnRename');
|
|
117
|
+
sinon.stub(selectors.datasourceConfig, 'getAllConfigSet').returns({
|
|
118
|
+
REQ_REP_testSource_testAlias: {
|
|
119
|
+
KEY: 'testAlias',
|
|
120
|
+
NAME: 'testSource',
|
|
121
|
+
INPUT_TYPE: 'REQ_REP',
|
|
122
|
+
OUTPUT_TYPE: 'TABLE',
|
|
123
|
+
TRANSFORMER_CONFIGURATION: {},
|
|
124
|
+
GROUPING_STRATEGY: 'NONE',
|
|
125
|
+
GROUP_KEY: null,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
111
128
|
|
|
112
129
|
handler('newColumn', { data: mockData } as ICellRendererParams<ColumnRenameAliasRowData>);
|
|
113
130
|
|
|
@@ -115,7 +132,7 @@ DisplayNameOnChangeHandler('calls setColumnRename with correct parameters when v
|
|
|
115
132
|
|
|
116
133
|
// Check each property individually instead of using deepEqual
|
|
117
134
|
const firstCallArg = setColumnRenameStub.firstCall.args[0];
|
|
118
|
-
assert.equal(firstCallArg.key, '
|
|
135
|
+
assert.equal(firstCallArg.key, 'REQ_REP_testSource_testAlias');
|
|
119
136
|
assert.equal(firstCallArg.columnFrom, 'originalColumn');
|
|
120
137
|
assert.equal(firstCallArg.columnTo, 'newColumn');
|
|
121
138
|
|
|
@@ -126,13 +143,24 @@ DisplayNameOnChangeHandler('removes prohibited characters and calls callback', (
|
|
|
126
143
|
const callback = sinon.spy();
|
|
127
144
|
const handler = displayNameOnChangeHandler(callback);
|
|
128
145
|
const mockData = {
|
|
129
|
-
[GridColumnNames.Datasource]: '
|
|
146
|
+
[GridColumnNames.Datasource]: 'testAlias (Snapshot)',
|
|
130
147
|
[GridColumnNames.ColumnName]: 'originalColumn',
|
|
131
148
|
[GridColumnNames.DisplayName]: 'Original Display',
|
|
132
149
|
[GridColumnNames.Type]: 'STRING',
|
|
133
150
|
} as ColumnRenameAliasRowData;
|
|
134
151
|
|
|
135
152
|
const setColumnRenameStub = sinon.stub(actions.datasourceConfig, 'setColumnRename');
|
|
153
|
+
sinon.stub(selectors.datasourceConfig, 'getAllConfigSet').returns({
|
|
154
|
+
REQ_REP_testSource_testAlias: {
|
|
155
|
+
KEY: 'testAlias',
|
|
156
|
+
NAME: 'testSource',
|
|
157
|
+
INPUT_TYPE: 'REQ_REP',
|
|
158
|
+
OUTPUT_TYPE: 'TABLE',
|
|
159
|
+
TRANSFORMER_CONFIGURATION: {},
|
|
160
|
+
GROUPING_STRATEGY: 'NONE',
|
|
161
|
+
GROUP_KEY: null,
|
|
162
|
+
},
|
|
163
|
+
});
|
|
136
164
|
|
|
137
165
|
handler('new@Column-=+test', { data: mockData } as ICellRendererParams<ColumnRenameAliasRowData>);
|
|
138
166
|
|
|
@@ -140,7 +168,7 @@ DisplayNameOnChangeHandler('removes prohibited characters and calls callback', (
|
|
|
140
168
|
|
|
141
169
|
// Check each property individually instead of using deepEqual
|
|
142
170
|
const firstCallArg = setColumnRenameStub.firstCall.args[0];
|
|
143
|
-
assert.equal(firstCallArg.key, '
|
|
171
|
+
assert.equal(firstCallArg.key, 'REQ_REP_testSource_testAlias');
|
|
144
172
|
assert.equal(firstCallArg.columnFrom, 'originalColumn');
|
|
145
173
|
assert.equal(firstCallArg.columnTo, 'newColumntest');
|
|
146
174
|
|
package/src/new/main/edit-config/data-transforms-derived-fields/data-transforms.helpers.test.ts
CHANGED
|
@@ -49,6 +49,8 @@ LookupColumnFormat('should return empty string when no format is found', () => {
|
|
|
49
49
|
INPUT_TYPE: 'REQ_REP' as const,
|
|
50
50
|
OUTPUT_TYPE: 'TABLE' as const,
|
|
51
51
|
TRANSFORMER_CONFIGURATION: { COLUMN_FORMATS: {} },
|
|
52
|
+
GROUPING_STRATEGY: 'NONE',
|
|
53
|
+
GROUP_KEY: null,
|
|
52
54
|
});
|
|
53
55
|
|
|
54
56
|
const result = lookupColumnFormat(mockData);
|
|
@@ -77,6 +79,8 @@ LookupColumnFormat('should return data with format when format exists', () => {
|
|
|
77
79
|
[originalColumn]: newFormat,
|
|
78
80
|
},
|
|
79
81
|
},
|
|
82
|
+
GROUPING_STRATEGY: 'NONE',
|
|
83
|
+
GROUP_KEY: null,
|
|
80
84
|
});
|
|
81
85
|
|
|
82
86
|
const result = lookupColumnFormat(mockData);
|
|
@@ -102,6 +106,8 @@ LookupColumnFormat('should handle undefined COLUMN_FORMATS', () => {
|
|
|
102
106
|
INPUT_TYPE: 'REQ_REP' as const,
|
|
103
107
|
OUTPUT_TYPE: 'TABLE' as const,
|
|
104
108
|
TRANSFORMER_CONFIGURATION: {},
|
|
109
|
+
GROUPING_STRATEGY: 'NONE',
|
|
110
|
+
GROUP_KEY: null,
|
|
105
111
|
});
|
|
106
112
|
|
|
107
113
|
const result = lookupColumnFormat(mockData);
|
|
@@ -128,6 +134,8 @@ LookupColumnFormat('should return existing format when format exists', () => {
|
|
|
128
134
|
numericColumn: '#.##',
|
|
129
135
|
},
|
|
130
136
|
},
|
|
137
|
+
GROUPING_STRATEGY: 'NONE',
|
|
138
|
+
GROUP_KEY: null,
|
|
131
139
|
});
|
|
132
140
|
|
|
133
141
|
const result = lookupColumnFormat(mockData);
|
|
@@ -468,7 +476,7 @@ ValueExprCellRendereronChange.before.each(() => {
|
|
|
468
476
|
});
|
|
469
477
|
|
|
470
478
|
ValueExprCellRendereronChange('should call setColumnTransform when model exists', () => {
|
|
471
|
-
const datasourceKey = '
|
|
479
|
+
const datasourceKey = 'REQ_REP_RESOURCE_ALIAS';
|
|
472
480
|
const columnName = 'testColumn';
|
|
473
481
|
|
|
474
482
|
// Using type assertions to match the expected type
|
|
@@ -518,7 +526,7 @@ ValueExprCellRendereronChange('should call setColumnTransform when model exists'
|
|
|
518
526
|
});
|
|
519
527
|
|
|
520
528
|
ValueExprCellRendereronChange('should call deleteColumnTransform when model is null', () => {
|
|
521
|
-
const datasourceKey = '
|
|
529
|
+
const datasourceKey = 'REQ_REP_RESOURCE_ALIAS';
|
|
522
530
|
const columnName = 'testColumn';
|
|
523
531
|
|
|
524
532
|
const mockParams = {
|
|
@@ -9,6 +9,12 @@ export const styles = css`
|
|
|
9
9
|
gap: calc(var(--design-unit) * 2px);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
div.split {
|
|
13
|
+
display: grid;
|
|
14
|
+
grid-template-columns: 1fr 1fr;
|
|
15
|
+
gap: calc(var(--design-unit) * 2px);
|
|
16
|
+
}
|
|
17
|
+
|
|
12
18
|
rapid-combobox.datasource {
|
|
13
19
|
margin-bottom: calc(var(--design-unit) * 2px);
|
|
14
20
|
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { Combobox } from '@genesislcap/foundation-ui';
|
|
2
2
|
import { classNames, html, repeat, when, whenElse } from '@genesislcap/web-core';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
datasourceGroupingStrategies,
|
|
5
|
+
DatasourceGroupingStrategy,
|
|
6
|
+
datasourceOutputs,
|
|
7
|
+
DatasourceOutputTypes,
|
|
8
|
+
selectors,
|
|
9
|
+
} from '../../../store';
|
|
4
10
|
import { datasourceInputForDisplay, TOOLTIP, tooltip } from '../../../utils';
|
|
5
11
|
import type { DatasourceConfigItem } from './datasource-config-item';
|
|
6
12
|
import { DatasourceChoice } from './types';
|
|
@@ -10,11 +16,52 @@ const datasourceAlias = html<DatasourceConfigItem>`
|
|
|
10
16
|
<p class="label">Name${tooltip(TOOLTIP.DATASOURCES_NAME)}</p>
|
|
11
17
|
<rapid-text-field
|
|
12
18
|
value=${(x) => selectors.datasourceConfig.getDatasource(x.datasourceName!).KEY}
|
|
13
|
-
@change=${(x, ctx) =>
|
|
19
|
+
@change=${(x, ctx) =>
|
|
20
|
+
x.updateKeyHandler((<HTMLInputElement>ctx.event.target).value, ctx.event)}
|
|
14
21
|
></rapid-text-field>
|
|
15
22
|
</div>
|
|
16
23
|
`;
|
|
17
24
|
|
|
25
|
+
const groupingType = html<DatasourceConfigItem>`
|
|
26
|
+
<div class="split">
|
|
27
|
+
<div>
|
|
28
|
+
<p class="label">Grouping Strategy${tooltip(TOOLTIP.DATASOURCES_GROUPING_STRATEGY)}</p>
|
|
29
|
+
<rapid-select
|
|
30
|
+
:value=${(x) =>
|
|
31
|
+
selectors.datasourceConfig.getDatasource(x.datasourceName!).GROUPING_STRATEGY}
|
|
32
|
+
@change=${(x, ctx) =>
|
|
33
|
+
x.updateGroupingStrategyHandler(
|
|
34
|
+
(<HTMLSelectElement>ctx.event.target).value as DatasourceGroupingStrategy,
|
|
35
|
+
)}
|
|
36
|
+
>
|
|
37
|
+
${repeat(
|
|
38
|
+
() => datasourceGroupingStrategies,
|
|
39
|
+
html<string>`
|
|
40
|
+
<rapid-option>${(x) => x}</rapid-option>
|
|
41
|
+
`,
|
|
42
|
+
)}
|
|
43
|
+
</rapid-select>
|
|
44
|
+
</div>
|
|
45
|
+
<div>
|
|
46
|
+
<p class="label">Grouping Key${tooltip(TOOLTIP.DATASOURCES_GROUPING_KEY)}</p>
|
|
47
|
+
<rapid-select
|
|
48
|
+
:value=${(x) => selectors.datasourceConfig.getDatasource(x.datasourceName!).GROUP_KEY}
|
|
49
|
+
@change=${(x, ctx) =>
|
|
50
|
+
x.updateGroupingByHandler((<HTMLSelectElement>ctx.event.target).value)}
|
|
51
|
+
?disabled=${(x) =>
|
|
52
|
+
selectors.datasourceConfig.getDatasource(x.datasourceName!).GROUPING_STRATEGY === 'NONE'}
|
|
53
|
+
>
|
|
54
|
+
${repeat(
|
|
55
|
+
(x) => x.groupingByFieldsNames ?? [],
|
|
56
|
+
html<string>`
|
|
57
|
+
<rapid-option>${(x) => x}</rapid-option>
|
|
58
|
+
`,
|
|
59
|
+
)}
|
|
60
|
+
</rapid-select>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
`;
|
|
64
|
+
|
|
18
65
|
const processType = html<DatasourceConfigItem>`
|
|
19
66
|
<div>
|
|
20
67
|
<p class="label">Type${tooltip(TOOLTIP.DATASOURCES_TYPE)}</p>
|
|
@@ -46,6 +93,9 @@ const closeButton = html<DatasourceConfigItem>`
|
|
|
46
93
|
const component = html<DatasourceConfigItem>`
|
|
47
94
|
${when((x) => x.canRemove, closeButton)}
|
|
48
95
|
<div class="container">
|
|
96
|
+
<div class="${() => classNames(['split', Boolean(selectors.baseConfig.getConfig().DOCUMENT_TEMPLATE_ID)])}">
|
|
97
|
+
<div>
|
|
98
|
+
<p class="label">Datasource${tooltip(TOOLTIP.DATASOURCES_DATASOURCE)}</p>
|
|
49
99
|
<rapid-combobox
|
|
50
100
|
class="datasource ${(x) => classNames(['error', x.error !== 'none'])}"
|
|
51
101
|
autocomplete="both"
|
|
@@ -66,7 +116,16 @@ const component = html<DatasourceConfigItem>`
|
|
|
66
116
|
`,
|
|
67
117
|
)}
|
|
68
118
|
</rapid-combobox>
|
|
69
|
-
|
|
119
|
+
</div>
|
|
120
|
+
${when(
|
|
121
|
+
(_) =>
|
|
122
|
+
Boolean(selectors.baseConfig.getConfig().DOCUMENT_TEMPLATE_ID) ||
|
|
123
|
+
selectors.baseConfig.getConfig().OUTPUT_FORMAT !== 'CSV',
|
|
124
|
+
datasourceAlias,
|
|
125
|
+
)}
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
${when((_) => Boolean(selectors.baseConfig.getConfig().DOCUMENT_TEMPLATE_ID), groupingType)}
|
|
70
129
|
<!-- ${when((_) => selectors.baseConfig.getConfig().OUTPUT_FORMAT === 'CSV', processType)} -->
|
|
71
130
|
</div>
|
|
72
131
|
`;
|
|
@@ -3,14 +3,17 @@ import { Combobox } from '@genesislcap/foundation-ui';
|
|
|
3
3
|
import { attr, customElement, GenesisElement, observable } from '@genesislcap/web-core';
|
|
4
4
|
import {
|
|
5
5
|
actions,
|
|
6
|
+
DatasourceGroupingStrategy,
|
|
6
7
|
DatasourceInputTypes,
|
|
7
8
|
DatasourceName,
|
|
8
9
|
DatasourceOutputTypes,
|
|
10
|
+
selectors,
|
|
9
11
|
} from '../../../store';
|
|
10
12
|
import { Display } from '../../../types';
|
|
11
13
|
import {
|
|
12
14
|
buildDatasourceName,
|
|
13
15
|
datasourceInputFromDisplay,
|
|
16
|
+
generateUniqueAlias,
|
|
14
17
|
getDatasourceSchema,
|
|
15
18
|
showNotificationToast,
|
|
16
19
|
} from '../../../utils';
|
|
@@ -30,11 +33,23 @@ export class DatasourceConfigItem extends GenesisElement {
|
|
|
30
33
|
|
|
31
34
|
@observable datasourceName: DatasourceName | null = null;
|
|
32
35
|
@observable datasourceChoices: DatasourceChoice[] | null = null;
|
|
36
|
+
@observable groupingByFieldsNames: string[] | null = null;
|
|
33
37
|
@attr({ mode: 'boolean', attribute: 'can-remove' }) canRemove: boolean = false;
|
|
34
38
|
|
|
35
39
|
@attr position: 'below' | 'above' = 'below';
|
|
36
40
|
@attr error: 'none' | 'invalid-datasource' | 'unknown' = 'none';
|
|
37
41
|
|
|
42
|
+
async connectedCallback(): Promise<void> {
|
|
43
|
+
super.connectedCallback();
|
|
44
|
+
try {
|
|
45
|
+
const datasource = selectors.datasourceConfig.getDatasource(this.datasourceName);
|
|
46
|
+
const schema = await this.getSchema(datasource.NAME);
|
|
47
|
+
this.groupingByFieldsNames = Object.keys(schema.properties);
|
|
48
|
+
} catch (e) {
|
|
49
|
+
console.error(e);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
38
53
|
deleteDatasourceHandler() {
|
|
39
54
|
if (!this.canRemove) throw new Error('Trying to remove final datasource!');
|
|
40
55
|
if (!this.datasourceName) throw new Error('deleteDatasourceHandler - Datasource key unset!');
|
|
@@ -43,13 +58,31 @@ export class DatasourceConfigItem extends GenesisElement {
|
|
|
43
58
|
});
|
|
44
59
|
}
|
|
45
60
|
|
|
46
|
-
updateKeyHandler(
|
|
61
|
+
updateKeyHandler(newName: string, event?: Event) {
|
|
47
62
|
if (!this.datasourceName) {
|
|
48
63
|
throw new Error('updateKeyHandler - datasourceName unset');
|
|
49
64
|
}
|
|
50
|
-
|
|
65
|
+
|
|
66
|
+
const allDatasources = selectors.datasourceConfig.getAllConfigSet();
|
|
67
|
+
const nameExists = Object.entries(allDatasources)
|
|
68
|
+
.filter(([key]) => key !== this.datasourceName)
|
|
69
|
+
.some(([, ds]) => ds.KEY.toLowerCase() === newName.toLowerCase());
|
|
70
|
+
|
|
71
|
+
if (nameExists) {
|
|
72
|
+
showNotificationToast({
|
|
73
|
+
title: 'Reporting Config',
|
|
74
|
+
body: `Name '${newName}' is already in use by another datasource.`,
|
|
75
|
+
toast: { type: 'error' as any },
|
|
76
|
+
});
|
|
77
|
+
if (event) {
|
|
78
|
+
(event.target as HTMLInputElement).value = allDatasources[this.datasourceName].KEY;
|
|
79
|
+
}
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
actions.datasourceConfig.renameDatasource({
|
|
51
84
|
key: this.datasourceName,
|
|
52
|
-
|
|
85
|
+
newName,
|
|
53
86
|
});
|
|
54
87
|
}
|
|
55
88
|
|
|
@@ -63,6 +96,45 @@ export class DatasourceConfigItem extends GenesisElement {
|
|
|
63
96
|
});
|
|
64
97
|
}
|
|
65
98
|
|
|
99
|
+
async updateGroupingStrategyHandler(value: DatasourceGroupingStrategy) {
|
|
100
|
+
try {
|
|
101
|
+
if (value === 'NONE') {
|
|
102
|
+
actions.datasourceConfig.deleteGrouping({ key: this.datasourceName });
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const dsResource = selectors.datasourceConfig.getDatasource(this.datasourceName).NAME;
|
|
107
|
+
const schema = await this.getSchema(dsResource);
|
|
108
|
+
if (!schema.properties) throw new Error(`schema properties for ${dsResource} undefined`);
|
|
109
|
+
|
|
110
|
+
const fields = Object.keys(schema.properties);
|
|
111
|
+
actions.datasourceConfig.setGrouping({
|
|
112
|
+
key: this.datasourceName,
|
|
113
|
+
grouping: { GROUPING_STRATEGY: value, GROUP_KEY: fields[0] },
|
|
114
|
+
});
|
|
115
|
+
this.groupingByFieldsNames = Object.keys(schema.properties);
|
|
116
|
+
} catch (e) {
|
|
117
|
+
const errorMsg = e instanceof Error ? `\n\n${e.message}` : '';
|
|
118
|
+
showNotificationToast({
|
|
119
|
+
title: 'Reporting Config',
|
|
120
|
+
body: `Error fetching field data for datasource ${this.datasourceName}.${errorMsg}`,
|
|
121
|
+
toast: { type: 'critical' as any },
|
|
122
|
+
});
|
|
123
|
+
this.error = 'unknown';
|
|
124
|
+
console.error(e);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
updateGroupingByHandler(value: string) {
|
|
129
|
+
const datasource = selectors.datasourceConfig.getDatasource(this.datasourceName);
|
|
130
|
+
if (datasource.GROUPING_STRATEGY === 'NONE')
|
|
131
|
+
throw new Error('Cannot set group by field when GROUPING_STRATEGY is NONE');
|
|
132
|
+
actions.datasourceConfig.setGrouping({
|
|
133
|
+
key: this.datasourceName,
|
|
134
|
+
grouping: { GROUPING_STRATEGY: datasource.GROUPING_STRATEGY, GROUP_KEY: value },
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
66
138
|
async updateDatasourceSourceHandler(selectedOption: Combobox) {
|
|
67
139
|
try {
|
|
68
140
|
if ((selectedOption?.selectedOptions ?? []).filter((x) => x).length === 0) {
|
|
@@ -72,7 +144,7 @@ export class DatasourceConfigItem extends GenesisElement {
|
|
|
72
144
|
return;
|
|
73
145
|
}
|
|
74
146
|
const option = selectedOption.selectedOptions[0];
|
|
75
|
-
const
|
|
147
|
+
const RESOURCE_NAME = option.value;
|
|
76
148
|
const dataAttr = <Display.DatasourceInputTypes | null>(
|
|
77
149
|
option.getAttribute('data-bubble-content')
|
|
78
150
|
);
|
|
@@ -83,22 +155,49 @@ export class DatasourceConfigItem extends GenesisElement {
|
|
|
83
155
|
throw new Error('updateKeyHandler - datasourceName or INPUT_TYPE null');
|
|
84
156
|
}
|
|
85
157
|
|
|
86
|
-
const schema = await this.getSchema(
|
|
87
|
-
if (!schema.properties) throw new Error(`schema properties for ${
|
|
158
|
+
const schema = await this.getSchema(RESOURCE_NAME);
|
|
159
|
+
if (!schema.properties) throw new Error(`schema properties for ${RESOURCE_NAME} undefined`);
|
|
88
160
|
|
|
89
161
|
const fields = Object.keys(schema.properties);
|
|
90
162
|
|
|
163
|
+
// Check for duplicate aliases
|
|
164
|
+
const allDatasources = selectors.datasourceConfig.getAllConfigSet();
|
|
165
|
+
const existingAliases = new Set(
|
|
166
|
+
Object.entries(allDatasources)
|
|
167
|
+
.filter(([key]) => key !== this.datasourceName)
|
|
168
|
+
.map(([, ds]) => ds.KEY),
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
const uniqueAlias = generateUniqueAlias(RESOURCE_NAME, existingAliases);
|
|
172
|
+
|
|
173
|
+
// Preserve index
|
|
174
|
+
const originalIndex = Object.keys(allDatasources).indexOf(this.datasourceName);
|
|
175
|
+
|
|
91
176
|
actions.datasourceConfig.deleteDatasource({ key: this.datasourceName });
|
|
92
177
|
actions.datasourceConfig.initDatasourceConfiguration({
|
|
93
178
|
base: {
|
|
94
|
-
KEY,
|
|
179
|
+
KEY: uniqueAlias,
|
|
180
|
+
NAME: RESOURCE_NAME,
|
|
95
181
|
INPUT_TYPE: INPUT_TYPE as DatasourceInputTypes,
|
|
96
182
|
},
|
|
97
183
|
fields,
|
|
98
184
|
});
|
|
99
|
-
const datasourceName = buildDatasourceName(
|
|
185
|
+
const datasourceName = buildDatasourceName(
|
|
186
|
+
uniqueAlias,
|
|
187
|
+
RESOURCE_NAME,
|
|
188
|
+
INPUT_TYPE as DatasourceInputTypes,
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
if (originalIndex !== -1) {
|
|
192
|
+
actions.datasourceConfig.reorderDatasource({
|
|
193
|
+
key: datasourceName,
|
|
194
|
+
newIndex: originalIndex,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
100
198
|
setDefaultFormatsForDatasource(datasourceName, schema);
|
|
101
199
|
this.error = 'none';
|
|
200
|
+
this.groupingByFieldsNames = Object.keys(schema.properties);
|
|
102
201
|
} catch (e: unknown) {
|
|
103
202
|
const errorMsg = e instanceof Error ? `\n\n${e.message}` : '';
|
|
104
203
|
showNotificationToast({
|
package/src/new/main/edit-config/datasource-config/datasources-config-container.helpers.test.ts
CHANGED
|
@@ -190,15 +190,17 @@ CreateNewDatasourceConfig.before.each(() => {
|
|
|
190
190
|
});
|
|
191
191
|
|
|
192
192
|
CreateNewDatasourceConfig('should exit when no valid datasources are available', async () => {
|
|
193
|
-
const mockChoices = [{ name: '
|
|
193
|
+
const mockChoices = [{ name: 'testSource', inputType: 'REQ_REP' as DatasourceInputTypes }];
|
|
194
194
|
|
|
195
195
|
const getAllConfigSetStub = sinon.stub(selectors.datasourceConfig, 'getAllConfigSet').returns({
|
|
196
|
-
|
|
197
|
-
KEY: '
|
|
198
|
-
NAME: '
|
|
196
|
+
REQ_REP_testSource_testSource: {
|
|
197
|
+
KEY: 'testSource',
|
|
198
|
+
NAME: 'testSource',
|
|
199
199
|
INPUT_TYPE: 'REQ_REP' as const,
|
|
200
200
|
OUTPUT_TYPE: 'TABLE' as const,
|
|
201
201
|
TRANSFORMER_CONFIGURATION: { INCLUDE_COLUMNS: [] },
|
|
202
|
+
GROUPING_STRATEGY: 'NONE',
|
|
203
|
+
GROUP_KEY: null,
|
|
202
204
|
},
|
|
203
205
|
});
|
|
204
206
|
|
|
@@ -215,15 +217,17 @@ CreateNewDatasourceConfig('should exit when no valid datasources are available',
|
|
|
215
217
|
CreateNewDatasourceConfig(
|
|
216
218
|
'should exit when trying to add multiple datasources with CSV format',
|
|
217
219
|
async () => {
|
|
218
|
-
const mockChoices = [{ name: '
|
|
220
|
+
const mockChoices = [{ name: 'testSource', inputType: 'REQ_REP' as DatasourceInputTypes }];
|
|
219
221
|
|
|
220
222
|
const getAllConfigSetStub = sinon.stub(selectors.datasourceConfig, 'getAllConfigSet').returns({
|
|
221
|
-
|
|
222
|
-
KEY: '
|
|
223
|
-
NAME: '
|
|
223
|
+
REQ_REP_existingSource_existingAlias: {
|
|
224
|
+
KEY: 'existingAlias',
|
|
225
|
+
NAME: 'existingSource',
|
|
224
226
|
INPUT_TYPE: 'REQ_REP' as const,
|
|
225
227
|
OUTPUT_TYPE: 'TABLE' as const,
|
|
226
228
|
TRANSFORMER_CONFIGURATION: { INCLUDE_COLUMNS: [] },
|
|
229
|
+
GROUPING_STRATEGY: 'NONE' as const,
|
|
230
|
+
GROUP_KEY: null,
|
|
227
231
|
},
|
|
228
232
|
});
|
|
229
233
|
|
|
@@ -238,7 +242,7 @@ CreateNewDatasourceConfig(
|
|
|
238
242
|
|
|
239
243
|
await createNewDatasourceConfig(getSchemaStub)(mockChoices);
|
|
240
244
|
|
|
241
|
-
assert.equal(getAllConfigSetStub.callCount,
|
|
245
|
+
assert.equal(getAllConfigSetStub.callCount, 1, 'getAllConfigSetStub should be called once');
|
|
242
246
|
assert.equal(getConfigStub.callCount, 1, 'getConfigStub should be called once');
|
|
243
247
|
// assert.ok(loggerStub.calledWith('Cannot add multiple datasources when using csv file without a template'));
|
|
244
248
|
if (loggerStub.args.length > 0) {
|
|
@@ -256,15 +260,17 @@ CreateNewDatasourceConfig(
|
|
|
256
260
|
CreateNewDatasourceConfig(
|
|
257
261
|
'should allow adding multiple datasources with CSV format IF template is selected',
|
|
258
262
|
async () => {
|
|
259
|
-
const mockChoices = [{ name: '
|
|
263
|
+
const mockChoices = [{ name: 'testSource', inputType: 'REQ_REP' as DatasourceInputTypes }];
|
|
260
264
|
|
|
261
265
|
const getAllConfigSetStub = sinon.stub(selectors.datasourceConfig, 'getAllConfigSet').returns({
|
|
262
|
-
|
|
263
|
-
KEY: '
|
|
264
|
-
NAME: '
|
|
266
|
+
REQ_REP_existingSource_existingAlias: {
|
|
267
|
+
KEY: 'existingAlias',
|
|
268
|
+
NAME: 'existingSource',
|
|
265
269
|
INPUT_TYPE: 'REQ_REP' as const,
|
|
266
270
|
OUTPUT_TYPE: 'TABLE' as const,
|
|
267
271
|
TRANSFORMER_CONFIGURATION: { INCLUDE_COLUMNS: [] },
|
|
272
|
+
GROUPING_STRATEGY: 'NONE' as const,
|
|
273
|
+
GROUP_KEY: null,
|
|
268
274
|
},
|
|
269
275
|
});
|
|
270
276
|
|
|
@@ -287,14 +293,14 @@ CreateNewDatasourceConfig(
|
|
|
287
293
|
|
|
288
294
|
await createNewDatasourceConfig(getSchemaStub)(mockChoices);
|
|
289
295
|
|
|
290
|
-
assert.ok(getAllConfigSetStub.
|
|
296
|
+
assert.ok(getAllConfigSetStub.calledOnce);
|
|
291
297
|
assert.ok(getSchemaStub.calledOnce);
|
|
292
298
|
assert.ok(initConfigStub.called);
|
|
293
299
|
},
|
|
294
300
|
);
|
|
295
301
|
|
|
296
302
|
CreateNewDatasourceConfig('should successfully create new datasource configuration', async () => {
|
|
297
|
-
const mockChoices = [{ name: '
|
|
303
|
+
const mockChoices = [{ name: 'testSource', inputType: 'REQ_REP' as DatasourceInputTypes }];
|
|
298
304
|
|
|
299
305
|
const getAllConfigSetStub = sinon.stub(selectors.datasourceConfig, 'getAllConfigSet').returns({});
|
|
300
306
|
|
|
@@ -316,16 +322,19 @@ CreateNewDatasourceConfig('should successfully create new datasource configurati
|
|
|
316
322
|
|
|
317
323
|
await createNewDatasourceConfig(getSchemaStub)(mockChoices);
|
|
318
324
|
|
|
319
|
-
assert.ok(getAllConfigSetStub.
|
|
325
|
+
assert.ok(getAllConfigSetStub.calledOnce);
|
|
320
326
|
assert.ok(getSchemaStub.calledOnce);
|
|
321
327
|
assert.ok(
|
|
322
|
-
initConfigStub.calledWith(
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
328
|
+
initConfigStub.calledWith(
|
|
329
|
+
sinon.match({
|
|
330
|
+
base: sinon.match({
|
|
331
|
+
KEY: 'testSource',
|
|
332
|
+
NAME: 'testSource',
|
|
333
|
+
INPUT_TYPE: 'REQ_REP',
|
|
334
|
+
}),
|
|
335
|
+
fields: sinon.match.array.deepEquals(['field1', 'field2']),
|
|
336
|
+
}),
|
|
337
|
+
),
|
|
329
338
|
);
|
|
330
339
|
});
|
|
331
340
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Connect, logger } from '@genesislcap/foundation-comms';
|
|
2
2
|
import { actions, selectors } from '../../../store';
|
|
3
3
|
import { Genesis } from '../../../types';
|
|
4
|
-
import { buildDatasourceName } from '../../../utils';
|
|
4
|
+
import { buildDatasourceName, generateUniqueAlias } from '../../../utils';
|
|
5
5
|
import { setDefaultFormatsForDatasource } from '../data-transforms-derived-fields/data-transforms.helpers';
|
|
6
6
|
import { DatasourceChoice } from './types';
|
|
7
7
|
|
|
@@ -10,21 +10,19 @@ export type GetGenesisSchema = (resource: string) => Promise<Genesis.JSONSchema7
|
|
|
10
10
|
export const createNewDatasourceConfig =
|
|
11
11
|
(getSchema: GetGenesisSchema) =>
|
|
12
12
|
async (choices: DatasourceChoice[]): Promise<void> => {
|
|
13
|
+
const allDatasources = selectors.datasourceConfig.getAllConfigSet();
|
|
13
14
|
const validDatasources =
|
|
14
15
|
choices.filter(
|
|
15
|
-
(ds) =>
|
|
16
|
-
!(
|
|
17
|
-
buildDatasourceName(ds.name, ds.inputType) in
|
|
18
|
-
selectors.datasourceConfig.getAllConfigSet()
|
|
19
|
-
),
|
|
16
|
+
(ds) => !(buildDatasourceName(ds.name, ds.name, ds.inputType) in allDatasources),
|
|
20
17
|
) ?? [];
|
|
18
|
+
|
|
21
19
|
if (validDatasources?.length < 1) {
|
|
22
20
|
logger.error('No datasources available to create new config from');
|
|
23
21
|
return;
|
|
24
22
|
}
|
|
25
23
|
const baseConfig = selectors.baseConfig.getConfig();
|
|
26
24
|
if (
|
|
27
|
-
Object.keys(
|
|
25
|
+
Object.keys(allDatasources).length > 0 &&
|
|
28
26
|
baseConfig.OUTPUT_FORMAT === 'CSV' &&
|
|
29
27
|
!baseConfig.DOCUMENT_TEMPLATE_ID
|
|
30
28
|
) {
|
|
@@ -32,13 +30,23 @@ export const createNewDatasourceConfig =
|
|
|
32
30
|
return;
|
|
33
31
|
}
|
|
34
32
|
|
|
35
|
-
const {
|
|
33
|
+
const {
|
|
34
|
+
KEY: RESOURCE_NAME,
|
|
35
|
+
INPUT_TYPE,
|
|
36
|
+
schema,
|
|
37
|
+
} = await findFirstValidDatasource(getSchema)(validDatasources);
|
|
38
|
+
|
|
39
|
+
// Check for duplicate aliases
|
|
40
|
+
const existingAliases = new Set(Object.values(allDatasources).map((ds) => ds.KEY));
|
|
41
|
+
|
|
42
|
+
const uniqueAlias = generateUniqueAlias(RESOURCE_NAME, existingAliases);
|
|
36
43
|
|
|
37
|
-
const datasourceName = buildDatasourceName(
|
|
44
|
+
const datasourceName = buildDatasourceName(uniqueAlias, RESOURCE_NAME, INPUT_TYPE);
|
|
38
45
|
|
|
39
46
|
actions.datasourceConfig.initDatasourceConfiguration({
|
|
40
47
|
base: {
|
|
41
|
-
KEY,
|
|
48
|
+
KEY: uniqueAlias,
|
|
49
|
+
NAME: RESOURCE_NAME,
|
|
42
50
|
INPUT_TYPE,
|
|
43
51
|
},
|
|
44
52
|
fields: Object.keys(schema.properties!), // Properties is valid as we check in findFirstValidDatasource
|
|
@@ -37,6 +37,12 @@ const container = html<DatasourcesConfigContainer>`
|
|
|
37
37
|
${repeat(
|
|
38
38
|
(_) => Object.keys(selectors.datasourceConfig.getAllConfigSet()),
|
|
39
39
|
html<string, DatasourcesConfigContainer>`
|
|
40
|
+
${when(
|
|
41
|
+
(_, ctx) => !ctx.isFirst,
|
|
42
|
+
html`
|
|
43
|
+
<rapid-divider></rapid-divider>
|
|
44
|
+
`,
|
|
45
|
+
)}
|
|
40
46
|
<datasource-config-item
|
|
41
47
|
:datasourceName=${(x) => x}
|
|
42
48
|
:datasourceChoices=${(_, c) => c.parent.datasourceChoices}
|