@openmfp/webcomponents 0.6.1 → 0.6.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.
- package/mfp-wc-dashboard.js +153 -0
- package/mfp-webcomponents.js +573 -0
- package/package.json +14 -68
- package/.github/workflows/pipeline.yaml +0 -41
- package/.storybook/main.ts +0 -34
- package/.storybook/preview.ts +0 -29
- package/.storybook/tsconfig.json +0 -11
- package/AGENTS.md +0 -153
- package/CODEOWNERS +0 -6
- package/CONTRIBUTING.md +0 -95
- package/LICENSE +0 -201
- package/LICENSES/Apache-2.0.txt +0 -73
- package/README.md +0 -91
- package/REUSE.toml +0 -9
- package/angular.json +0 -157
- package/docs/dashboard.md +0 -358
- package/docs/declarative-form.md +0 -178
- package/docs/declarative-table-card.md +0 -235
- package/docs/declarative-table.md +0 -315
- package/eslint.config.js +0 -41
- package/projects/ngx/cards/favorites/favorites.component.html +0 -12
- package/projects/ngx/cards/favorites/favorites.component.scss +0 -50
- package/projects/ngx/cards/favorites/favorites.component.ts +0 -19
- package/projects/ngx/cards/public-api.ts +0 -4
- package/projects/ngx/cards/service-status/service-status-card.component.html +0 -15
- package/projects/ngx/cards/service-status/service-status-card.component.scss +0 -87
- package/projects/ngx/cards/service-status/service-status-card.component.ts +0 -36
- package/projects/ngx/cards/stories/visited-service-card.stories.ts +0 -149
- package/projects/ngx/cards/visited-service-card/visited-service-card.component.html +0 -17
- package/projects/ngx/cards/visited-service-card/visited-service-card.component.scss +0 -34
- package/projects/ngx/cards/visited-service-card/visited-service-card.component.ts +0 -22
- package/projects/ngx/cards/whats-new/whats-new.component.html +0 -10
- package/projects/ngx/cards/whats-new/whats-new.component.scss +0 -25
- package/projects/ngx/cards/whats-new/whats-new.component.ts +0 -46
- package/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.html +0 -28
- package/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.scss +0 -44
- package/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.spec.ts +0 -85
- package/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.ts +0 -58
- package/projects/ngx/declarative-ui/dashboard/card/dashboard-card.component.html +0 -29
- package/projects/ngx/declarative-ui/dashboard/card/dashboard-card.component.scss +0 -63
- package/projects/ngx/declarative-ui/dashboard/card/dashboard-card.component.spec.ts +0 -255
- package/projects/ngx/declarative-ui/dashboard/card/dashboard-card.component.ts +0 -75
- package/projects/ngx/declarative-ui/dashboard/card/utils/dashboard-card-registry.spec.ts +0 -76
- package/projects/ngx/declarative-ui/dashboard/card/utils/dashboard-card-registry.ts +0 -109
- package/projects/ngx/declarative-ui/dashboard/card/utils/index.ts +0 -4
- package/projects/ngx/declarative-ui/dashboard/card/utils/mount-angular-card.spec.ts +0 -141
- package/projects/ngx/declarative-ui/dashboard/card/utils/mount-angular-card.ts +0 -44
- package/projects/ngx/declarative-ui/dashboard/card/utils/mount-sap-card.spec.ts +0 -142
- package/projects/ngx/declarative-ui/dashboard/card/utils/mount-sap-card.ts +0 -52
- package/projects/ngx/declarative-ui/dashboard/card/utils/mount-wc-card.spec.ts +0 -107
- package/projects/ngx/declarative-ui/dashboard/card/utils/mount-wc-card.ts +0 -22
- package/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.html +0 -134
- package/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.scss +0 -88
- package/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.spec.ts +0 -354
- package/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.ts +0 -238
- package/projects/ngx/declarative-ui/dashboard/dashboard/index.ts +0 -1
- package/projects/ngx/declarative-ui/dashboard/index.ts +0 -5
- package/projects/ngx/declarative-ui/dashboard/models/constants.ts +0 -2
- package/projects/ngx/declarative-ui/dashboard/models/dashboard.model.ts +0 -50
- package/projects/ngx/declarative-ui/dashboard/models/index.ts +0 -1
- package/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.html +0 -28
- package/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.scss +0 -85
- package/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.spec.ts +0 -104
- package/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.ts +0 -23
- package/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.html +0 -62
- package/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.scss +0 -12
- package/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.spec.ts +0 -301
- package/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.ts +0 -166
- package/projects/ngx/declarative-ui/form/declarative-form/index.ts +0 -1
- package/projects/ngx/declarative-ui/form/index.ts +0 -2
- package/projects/ngx/declarative-ui/form/models/form-field-definition.ts +0 -15
- package/projects/ngx/declarative-ui/form/models/index.ts +0 -1
- package/projects/ngx/declarative-ui/form/utils/set-property-by-path.ts +0 -30
- package/projects/ngx/declarative-ui/models/index.ts +0 -2
- package/projects/ngx/declarative-ui/models/resource.ts +0 -5
- package/projects/ngx/declarative-ui/models/ui-definition.ts +0 -95
- package/projects/ngx/declarative-ui/public-api.ts +0 -4
- package/projects/ngx/declarative-ui/stories/add-card-dialog.stories.ts +0 -91
- package/projects/ngx/declarative-ui/stories/background-lightblue.png +0 -0
- package/projects/ngx/declarative-ui/stories/dashboard.cards.ts +0 -107
- package/projects/ngx/declarative-ui/stories/dashboard.stories.ts +0 -296
- package/projects/ngx/declarative-ui/stories/declarative-form.stories.ts +0 -149
- package/projects/ngx/declarative-ui/stories/declarative-table-card.stories.ts +0 -358
- package/projects/ngx/declarative-ui/stories/declarative-table.stories.ts +0 -363
- package/projects/ngx/declarative-ui/stories/pods-table.config.ts +0 -188
- package/projects/ngx/declarative-ui/table/declarative-table/declarative-table.component.html +0 -138
- package/projects/ngx/declarative-ui/table/declarative-table/declarative-table.component.scss +0 -21
- package/projects/ngx/declarative-ui/table/declarative-table/declarative-table.component.spec.ts +0 -345
- package/projects/ngx/declarative-ui/table/declarative-table/declarative-table.component.ts +0 -61
- package/projects/ngx/declarative-ui/table/declarative-table/index.ts +0 -1
- package/projects/ngx/declarative-ui/table/index.ts +0 -2
- package/projects/ngx/declarative-ui/table/models/index.ts +0 -14
- package/projects/ngx/declarative-ui/table/models/table.model.ts +0 -17
- package/projects/ngx/declarative-ui/table/utils/cssRules.engine.spec.ts +0 -146
- package/projects/ngx/declarative-ui/table/utils/cssRules.engine.ts +0 -69
- package/projects/ngx/declarative-ui/table/utils/field-definition.utils.spec.ts +0 -70
- package/projects/ngx/declarative-ui/table/utils/field-definition.utils.ts +0 -13
- package/projects/ngx/declarative-ui/table/utils/proccess-fields.spec.ts +0 -511
- package/projects/ngx/declarative-ui/table/utils/proccess-fields.ts +0 -71
- package/projects/ngx/declarative-ui/table/utils/resource-field-by-path.spec.ts +0 -372
- package/projects/ngx/declarative-ui/table/utils/resource-field-by-path.ts +0 -98
- package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-cell.constants.ts +0 -5
- package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.html +0 -1
- package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.scss +0 -0
- package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.spec.ts +0 -119
- package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.ts +0 -35
- package/projects/ngx/declarative-ui/table/value-cell/link-value/link-value.component.html +0 -7
- package/projects/ngx/declarative-ui/table/value-cell/link-value/link-value.component.scss +0 -0
- package/projects/ngx/declarative-ui/table/value-cell/link-value/link-value.component.spec.ts +0 -114
- package/projects/ngx/declarative-ui/table/value-cell/link-value/link-value.component.ts +0 -19
- package/projects/ngx/declarative-ui/table/value-cell/secret-value/secret-value.component.html +0 -7
- package/projects/ngx/declarative-ui/table/value-cell/secret-value/secret-value.component.scss +0 -10
- package/projects/ngx/declarative-ui/table/value-cell/secret-value/secret-value.component.spec.ts +0 -188
- package/projects/ngx/declarative-ui/table/value-cell/secret-value/secret-value.component.ts +0 -16
- package/projects/ngx/declarative-ui/table/value-cell/value-cell.component.html +0 -59
- package/projects/ngx/declarative-ui/table/value-cell/value-cell.component.scss +0 -33
- package/projects/ngx/declarative-ui/table/value-cell/value-cell.component.spec.ts +0 -316
- package/projects/ngx/declarative-ui/table/value-cell/value-cell.component.ts +0 -115
- package/projects/ngx/declarative-ui/table-card/declarative-table-card.component.html +0 -156
- package/projects/ngx/declarative-ui/table-card/declarative-table-card.component.scss +0 -123
- package/projects/ngx/declarative-ui/table-card/declarative-table-card.component.spec.ts +0 -786
- package/projects/ngx/declarative-ui/table-card/declarative-table-card.component.ts +0 -286
- package/projects/ngx/declarative-ui/table-card/index.ts +0 -2
- package/projects/ngx/declarative-ui/table-card/models/configs.ts +0 -46
- package/projects/ngx/declarative-ui/tsconfig.lib.json +0 -11
- package/projects/ngx/declarative-ui/tsconfig.lib.prod.json +0 -9
- package/projects/ngx/declarative-ui/tsconfig.spec.json +0 -9
- package/projects/ngx/ng-package.json +0 -8
- package/projects/ngx/package.json +0 -22
- package/projects/ngx/public-api.ts +0 -2
- package/projects/ngx/tsconfig.lib.json +0 -11
- package/projects/ngx/tsconfig.lib.prod.json +0 -9
- package/projects/webcomponents/main.ts +0 -92
- package/projects/webcomponents/tsconfig.app.json +0 -9
- package/projects/webcomponents-dashboard/main.ts +0 -15
- package/projects/webcomponents-dashboard/tsconfig.app.json +0 -9
- package/renovate.json +0 -6
- package/scripts/bundle-wc.mjs +0 -79
- package/tsconfig.json +0 -37
- package/tsconfig.spec.json +0 -8
- package/tsconfig.storybook.json +0 -16
- package/vitest.config.ts +0 -26
|
@@ -1,372 +0,0 @@
|
|
|
1
|
-
import { GenericResource, PropertyField, TransformType } from '../../models';
|
|
2
|
-
import {
|
|
3
|
-
decodeBase64,
|
|
4
|
-
encodeBase64,
|
|
5
|
-
getResourceValueByJsonPath,
|
|
6
|
-
} from './resource-field-by-path';
|
|
7
|
-
|
|
8
|
-
const mockResource = {
|
|
9
|
-
id: 'mock-1',
|
|
10
|
-
metadata: { name: 'test-resource' },
|
|
11
|
-
spec: { value: 'test-value', nested: { field: 'nested-value' } },
|
|
12
|
-
} satisfies GenericResource;
|
|
13
|
-
|
|
14
|
-
describe('getResourceValueByJsonPath', () => {
|
|
15
|
-
it('should return undefined when no property or jsonPathExpression is provided', () => {
|
|
16
|
-
const result = getResourceValueByJsonPath(mockResource, {});
|
|
17
|
-
expect(result).toBeUndefined();
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should return undefined and log error when property is an array', () => {
|
|
21
|
-
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {
|
|
22
|
-
/* noop */
|
|
23
|
-
});
|
|
24
|
-
const result = getResourceValueByJsonPath(mockResource, {
|
|
25
|
-
property: ['path1', 'path2'],
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
expect(result).toBeUndefined();
|
|
29
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
30
|
-
expect.stringContaining('Property defined as an array'),
|
|
31
|
-
);
|
|
32
|
-
consoleSpy.mockRestore();
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('should query resource using jsonPathExpression', () => {
|
|
36
|
-
const result = getResourceValueByJsonPath(mockResource, {
|
|
37
|
-
jsonPathExpression: 'spec.value',
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
expect(result).toBe('test-value');
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('should query resource using jsonPathExpression when "$." is already provided', () => {
|
|
44
|
-
const result = getResourceValueByJsonPath(mockResource, {
|
|
45
|
-
jsonPathExpression: '$.spec.value',
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
expect(result).toBe('test-value');
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('should query resource using property', () => {
|
|
52
|
-
const result = getResourceValueByJsonPath(mockResource, {
|
|
53
|
-
property: 'metadata.name',
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
expect(result).toBe('test-resource');
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('should return undefined when query result is empty', () => {
|
|
60
|
-
const result = getResourceValueByJsonPath(mockResource, {
|
|
61
|
-
property: 'nonexistent',
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
expect(result).toBeUndefined();
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('should apply propertyField transform when provided', () => {
|
|
68
|
-
const resource = {
|
|
69
|
-
spec: { data: { key1: 'value1', key2: 'value2' } },
|
|
70
|
-
} as unknown as GenericResource;
|
|
71
|
-
|
|
72
|
-
const propertyField: PropertyField = {
|
|
73
|
-
key: 'key1',
|
|
74
|
-
transform: ['uppercase'],
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const result = getResourceValueByJsonPath(resource, {
|
|
78
|
-
property: 'spec.data',
|
|
79
|
-
propertyField,
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
expect(result).toBe('VALUE1');
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it('should handle none existing transform', () => {
|
|
86
|
-
const resource = {
|
|
87
|
-
spec: { data: { text: 'hello world' } },
|
|
88
|
-
} as unknown as GenericResource;
|
|
89
|
-
|
|
90
|
-
const result = getResourceValueByJsonPath(resource, {
|
|
91
|
-
property: 'spec.data',
|
|
92
|
-
propertyField: { key: 'text', transform: ['notknown' as TransformType] },
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
expect(result).toBe('hello world');
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it('should handle uppercase transform', () => {
|
|
99
|
-
const resource = {
|
|
100
|
-
spec: { data: { text: 'hello world' } },
|
|
101
|
-
} as unknown as GenericResource;
|
|
102
|
-
|
|
103
|
-
const result = getResourceValueByJsonPath(resource, {
|
|
104
|
-
property: 'spec.data',
|
|
105
|
-
propertyField: { key: 'text', transform: ['uppercase'] },
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
expect(result).toBe('HELLO WORLD');
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('should handle lowercase transform', () => {
|
|
112
|
-
const resource = {
|
|
113
|
-
spec: { data: { text: 'HELLO WORLD' } },
|
|
114
|
-
} as unknown as GenericResource;
|
|
115
|
-
|
|
116
|
-
const result = getResourceValueByJsonPath(resource, {
|
|
117
|
-
property: 'spec.data',
|
|
118
|
-
propertyField: { key: 'text', transform: ['lowercase'] },
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
expect(result).toBe('hello world');
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it('should handle capitalize transform', () => {
|
|
125
|
-
const resource = {
|
|
126
|
-
spec: { data: { text: 'hello' } },
|
|
127
|
-
} as unknown as GenericResource;
|
|
128
|
-
|
|
129
|
-
const result = getResourceValueByJsonPath(resource, {
|
|
130
|
-
property: 'spec.data',
|
|
131
|
-
propertyField: { key: 'text', transform: ['capitalize'] },
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
expect(result).toBe('Hello');
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('should handle multiple transforms', () => {
|
|
138
|
-
const resource = {
|
|
139
|
-
spec: { data: { text: 'HELLO WORLD' } },
|
|
140
|
-
} as unknown as GenericResource;
|
|
141
|
-
|
|
142
|
-
const result = getResourceValueByJsonPath(resource, {
|
|
143
|
-
property: 'spec.data',
|
|
144
|
-
propertyField: { key: 'text', transform: ['lowercase', 'capitalize'] },
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
expect(result).toBe('Hello world');
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it('should handle encode transform', () => {
|
|
151
|
-
const resource = {
|
|
152
|
-
spec: { data: { text: 'test' } },
|
|
153
|
-
} as unknown as GenericResource;
|
|
154
|
-
|
|
155
|
-
const result = getResourceValueByJsonPath(resource, {
|
|
156
|
-
property: 'spec.data',
|
|
157
|
-
propertyField: { key: 'text', transform: ['encode'] },
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
expect(result).toBe(encodeBase64('test'));
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it('should return original value when encode transform fails', () => {
|
|
164
|
-
vi.spyOn(globalThis, 'btoa').mockImplementation(() => {
|
|
165
|
-
throw new Error('btoa error');
|
|
166
|
-
});
|
|
167
|
-
vi.spyOn(console, 'error').mockImplementation(() => {
|
|
168
|
-
/* noop */
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
const resource = {
|
|
172
|
-
spec: { data: { text: 'test-value' } },
|
|
173
|
-
} as unknown as GenericResource;
|
|
174
|
-
|
|
175
|
-
const result = getResourceValueByJsonPath(resource, {
|
|
176
|
-
property: 'spec.data',
|
|
177
|
-
propertyField: { key: 'text', transform: ['encode'] },
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
expect(result).toBe('test-value');
|
|
181
|
-
vi.restoreAllMocks();
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
it('should handle decode transform', () => {
|
|
185
|
-
const encoded = encodeBase64('test');
|
|
186
|
-
const resource = {
|
|
187
|
-
spec: { data: { text: encoded } },
|
|
188
|
-
} as unknown as GenericResource;
|
|
189
|
-
|
|
190
|
-
const result = getResourceValueByJsonPath(resource, {
|
|
191
|
-
property: 'spec.data',
|
|
192
|
-
propertyField: { key: 'text', transform: ['decode'] },
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
expect(result).toBe('test');
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
it('should return original value when transform fails', () => {
|
|
199
|
-
const resource = {
|
|
200
|
-
spec: { data: { text: 'invalid-base64!!!' } },
|
|
201
|
-
} as unknown as GenericResource;
|
|
202
|
-
|
|
203
|
-
const result = getResourceValueByJsonPath(resource, {
|
|
204
|
-
property: 'spec.data',
|
|
205
|
-
propertyField: { key: 'text', transform: ['decode'] },
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
expect(result).toBe('invalid-base64!!!');
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
it('should handle null value in transform', () => {
|
|
212
|
-
const resource = {
|
|
213
|
-
spec: { data: { text: null } },
|
|
214
|
-
} as unknown as GenericResource;
|
|
215
|
-
|
|
216
|
-
const result = getResourceValueByJsonPath(resource, {
|
|
217
|
-
property: 'spec.data',
|
|
218
|
-
propertyField: { key: 'text', transform: ['uppercase'] },
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
expect(result).toBeNull();
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
it('should handle undefined value in transform', () => {
|
|
225
|
-
const resource = {
|
|
226
|
-
spec: { data: { text: undefined } },
|
|
227
|
-
} as unknown as GenericResource;
|
|
228
|
-
|
|
229
|
-
const result = getResourceValueByJsonPath(resource, {
|
|
230
|
-
property: 'spec.data',
|
|
231
|
-
propertyField: { key: 'text', transform: ['uppercase'] },
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
expect(result).toBeUndefined();
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
it('should return value when no transform is provided', () => {
|
|
238
|
-
const resource = {
|
|
239
|
-
spec: { data: { text: 'no-transform' } },
|
|
240
|
-
} as unknown as GenericResource;
|
|
241
|
-
|
|
242
|
-
const result = getResourceValueByJsonPath(resource, {
|
|
243
|
-
property: 'spec.data',
|
|
244
|
-
propertyField: { key: 'text' },
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
expect(result).toBe('no-transform');
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it('should return value when transform is empty array', () => {
|
|
251
|
-
const resource = {
|
|
252
|
-
spec: { data: { text: 'empty-transform' } },
|
|
253
|
-
} as unknown as GenericResource;
|
|
254
|
-
|
|
255
|
-
const result = getResourceValueByJsonPath(resource, {
|
|
256
|
-
property: 'spec.data',
|
|
257
|
-
propertyField: { key: 'text', transform: [] },
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
expect(result).toBe('empty-transform');
|
|
261
|
-
});
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
describe('encodeBase64', () => {
|
|
265
|
-
it('should encode simple ASCII string', () => {
|
|
266
|
-
const result = encodeBase64('hello');
|
|
267
|
-
expect(result).toBe('aGVsbG8=');
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
it('should encode UTF-8 string with special characters', () => {
|
|
271
|
-
const result = encodeBase64('Hello, 世界');
|
|
272
|
-
expect(decodeBase64(result)).toBe('Hello, 世界');
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
it('should encode emojis', () => {
|
|
276
|
-
const result = encodeBase64('👍🎉');
|
|
277
|
-
expect(decodeBase64(result)).toBe('👍🎉');
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
it('should encode empty string', () => {
|
|
281
|
-
const result = encodeBase64('');
|
|
282
|
-
expect(result).toBe('');
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
it('should throw error when encoding fails', () => {
|
|
286
|
-
vi.spyOn(globalThis, 'btoa').mockImplementation(() => {
|
|
287
|
-
throw new Error('btoa error');
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
expect(() => encodeBase64('test')).toThrow(
|
|
291
|
-
'Failed to encode string to Base64',
|
|
292
|
-
);
|
|
293
|
-
vi.restoreAllMocks();
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
it('should log error when encoding fails', () => {
|
|
297
|
-
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {
|
|
298
|
-
/* noop */
|
|
299
|
-
});
|
|
300
|
-
vi.spyOn(globalThis, 'btoa').mockImplementation(() => {
|
|
301
|
-
throw new Error('btoa error');
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
try {
|
|
305
|
-
encodeBase64('test');
|
|
306
|
-
} catch {
|
|
307
|
-
/* expected to throw */
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
311
|
-
'Base64 encoding failed:',
|
|
312
|
-
expect.any(Error),
|
|
313
|
-
);
|
|
314
|
-
vi.restoreAllMocks();
|
|
315
|
-
});
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
describe('decodeBase64', () => {
|
|
319
|
-
it('should decode simple ASCII string', () => {
|
|
320
|
-
const result = decodeBase64('aGVsbG8=');
|
|
321
|
-
expect(result).toBe('hello');
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
it('should decode UTF-8 string with special characters', () => {
|
|
325
|
-
const encoded = encodeBase64('Hello, 世界');
|
|
326
|
-
const result = decodeBase64(encoded);
|
|
327
|
-
expect(result).toBe('Hello, 世界');
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
it('should decode emojis', () => {
|
|
331
|
-
const encoded = encodeBase64('👍🎉');
|
|
332
|
-
const result = decodeBase64(encoded);
|
|
333
|
-
expect(result).toBe('👍🎉');
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
it('should decode empty string', () => {
|
|
337
|
-
const result = decodeBase64('');
|
|
338
|
-
expect(result).toBe('');
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
it('should throw error for invalid base64', () => {
|
|
342
|
-
expect(() => decodeBase64('invalid!!!')).toThrow(
|
|
343
|
-
'Failed to decode Base64 string',
|
|
344
|
-
);
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
it('should log error when decoding fails', () => {
|
|
348
|
-
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {
|
|
349
|
-
/* noop */
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
try {
|
|
353
|
-
decodeBase64('invalid!!!');
|
|
354
|
-
} catch {
|
|
355
|
-
/* expected to throw */
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
359
|
-
'Base64 decoding failed:',
|
|
360
|
-
expect.any(Error),
|
|
361
|
-
);
|
|
362
|
-
|
|
363
|
-
consoleSpy.mockRestore();
|
|
364
|
-
});
|
|
365
|
-
|
|
366
|
-
it('should handle round-trip encoding and decoding', () => {
|
|
367
|
-
const original = 'Test string with 特殊字符 and emojis 🚀';
|
|
368
|
-
const encoded = encodeBase64(original);
|
|
369
|
-
const decoded = decodeBase64(encoded);
|
|
370
|
-
expect(decoded).toBe(original);
|
|
371
|
-
});
|
|
372
|
-
});
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { PropertyField, TransformType } from '../../models';
|
|
2
|
-
import jsonpath from 'jsonpath';
|
|
3
|
-
|
|
4
|
-
export const getResourceValueByJsonPath = <T>(
|
|
5
|
-
resource: T,
|
|
6
|
-
field: {
|
|
7
|
-
jsonPathExpression?: string;
|
|
8
|
-
property?: string | string[];
|
|
9
|
-
propertyField?: PropertyField;
|
|
10
|
-
},
|
|
11
|
-
) => {
|
|
12
|
-
const property = field.jsonPathExpression || field.property;
|
|
13
|
-
if (!property) {
|
|
14
|
-
return undefined;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if (property instanceof Array) {
|
|
18
|
-
console.error(
|
|
19
|
-
`Property defined as an array: ${JSON.stringify(property)}, provide "jsonPathExpression" field to properly ready resource value`,
|
|
20
|
-
);
|
|
21
|
-
return undefined;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const prefix = property.startsWith('$.') ? '' : '$.';
|
|
25
|
-
const queryResult = jsonpath.query(resource, `${prefix}${property}`);
|
|
26
|
-
const value = queryResult.length ? queryResult[0] : undefined;
|
|
27
|
-
|
|
28
|
-
if (value && field.propertyField) {
|
|
29
|
-
return executeTransform(
|
|
30
|
-
value[field.propertyField.key],
|
|
31
|
-
field.propertyField.transform,
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return value;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const executeTransform = (
|
|
39
|
-
value: string | undefined,
|
|
40
|
-
transform: TransformType[] | undefined,
|
|
41
|
-
): string | undefined => {
|
|
42
|
-
if (value == null || transform == null || !transform.length) return value;
|
|
43
|
-
|
|
44
|
-
return transform.reduce((acc, t) => {
|
|
45
|
-
if (acc == null) return acc;
|
|
46
|
-
|
|
47
|
-
switch (t) {
|
|
48
|
-
case 'uppercase':
|
|
49
|
-
return acc.toUpperCase();
|
|
50
|
-
case 'lowercase':
|
|
51
|
-
return acc.toLowerCase();
|
|
52
|
-
case 'capitalize': {
|
|
53
|
-
const str = String(acc);
|
|
54
|
-
return str.length ? str.charAt(0).toUpperCase() + str.slice(1) : str;
|
|
55
|
-
}
|
|
56
|
-
case 'decode': {
|
|
57
|
-
try {
|
|
58
|
-
return decodeBase64(acc);
|
|
59
|
-
} catch {
|
|
60
|
-
return acc;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
case 'encode': {
|
|
64
|
-
try {
|
|
65
|
-
return encodeBase64(acc);
|
|
66
|
-
} catch {
|
|
67
|
-
return acc;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
default:
|
|
71
|
-
return acc;
|
|
72
|
-
}
|
|
73
|
-
}, value);
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
export const encodeBase64 = (str: string): string => {
|
|
77
|
-
try {
|
|
78
|
-
const utf8Bytes = new TextEncoder().encode(str);
|
|
79
|
-
const binaryString = Array.from(utf8Bytes, (byte) =>
|
|
80
|
-
String.fromCharCode(byte),
|
|
81
|
-
).join('');
|
|
82
|
-
return btoa(binaryString);
|
|
83
|
-
} catch (error) {
|
|
84
|
-
console.error('Base64 encoding failed:', error);
|
|
85
|
-
throw new Error('Failed to encode string to Base64');
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
export const decodeBase64 = (base64: string): string => {
|
|
90
|
-
try {
|
|
91
|
-
const binaryString = atob(base64);
|
|
92
|
-
const bytes = Uint8Array.from(binaryString, (char) => char.charCodeAt(0));
|
|
93
|
-
return new TextDecoder().decode(bytes);
|
|
94
|
-
} catch (error) {
|
|
95
|
-
console.error('Base64 decoding failed:', error);
|
|
96
|
-
throw new Error('Failed to decode Base64 string');
|
|
97
|
-
}
|
|
98
|
-
};
|
package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.html
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<ui5-icon [attr.test-id]="testId()" [design]="iconDesign()" [name]="iconName()" />
|
package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.scss
DELETED
|
File without changes
|
package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.spec.ts
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ICON_DESIGN_NEGATIVE,
|
|
3
|
-
ICON_DESIGN_POSITIVE,
|
|
4
|
-
ICON_NAME_NEGATIVE,
|
|
5
|
-
ICON_NAME_POSITIVE,
|
|
6
|
-
} from './boolean-cell.constants';
|
|
7
|
-
import { BooleanValue } from './boolean-value.component';
|
|
8
|
-
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
9
|
-
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
10
|
-
|
|
11
|
-
describe('BooleanValueComponent', () => {
|
|
12
|
-
let component: BooleanValue;
|
|
13
|
-
let fixture: ComponentFixture<BooleanValue>;
|
|
14
|
-
|
|
15
|
-
const makeComponent = (boolValue: boolean) => {
|
|
16
|
-
fixture = TestBed.createComponent(BooleanValue);
|
|
17
|
-
component = fixture.componentInstance;
|
|
18
|
-
|
|
19
|
-
fixture.componentRef.setInput('boolValue', boolValue);
|
|
20
|
-
|
|
21
|
-
fixture.detectChanges();
|
|
22
|
-
|
|
23
|
-
return { component, fixture };
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
beforeEach(() => {
|
|
27
|
-
TestBed.configureTestingModule({
|
|
28
|
-
imports: [BooleanValue],
|
|
29
|
-
}).overrideComponent(BooleanValue, {
|
|
30
|
-
set: {
|
|
31
|
-
imports: [],
|
|
32
|
-
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
33
|
-
},
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('should create', () => {
|
|
38
|
-
const { component } = makeComponent(true);
|
|
39
|
-
expect(component).toBeTruthy();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('should set positive icon design and name for true value', () => {
|
|
43
|
-
const { component } = makeComponent(true);
|
|
44
|
-
|
|
45
|
-
expect(component.iconDesign()).toBe(ICON_DESIGN_POSITIVE);
|
|
46
|
-
expect(component.iconName()).toBe(ICON_NAME_POSITIVE);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('should set negative icon design and name for false value', () => {
|
|
50
|
-
const { component } = makeComponent(false);
|
|
51
|
-
|
|
52
|
-
expect(component.iconDesign()).toBe(ICON_DESIGN_NEGATIVE);
|
|
53
|
-
expect(component.iconName()).toBe(ICON_NAME_NEGATIVE);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('should render ui5-icon for true value', () => {
|
|
57
|
-
const { fixture } = makeComponent(true);
|
|
58
|
-
const compiled = fixture.nativeElement;
|
|
59
|
-
const iconElement = compiled.querySelector('ui5-icon');
|
|
60
|
-
|
|
61
|
-
expect(iconElement).toBeTruthy();
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('should render ui5-icon for false value', () => {
|
|
65
|
-
const { fixture } = makeComponent(false);
|
|
66
|
-
const compiled = fixture.nativeElement;
|
|
67
|
-
const iconElement = compiled.querySelector('ui5-icon');
|
|
68
|
-
|
|
69
|
-
expect(iconElement).toBeTruthy();
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('should update icon when boolValue changes from true to false', () => {
|
|
73
|
-
const { component, fixture } = makeComponent(true);
|
|
74
|
-
|
|
75
|
-
expect(component.iconDesign()).toBe(ICON_DESIGN_POSITIVE);
|
|
76
|
-
expect(component.iconName()).toBe(ICON_NAME_POSITIVE);
|
|
77
|
-
|
|
78
|
-
fixture.componentRef.setInput('boolValue', false);
|
|
79
|
-
fixture.detectChanges();
|
|
80
|
-
|
|
81
|
-
expect(component.iconDesign()).toBe(ICON_DESIGN_NEGATIVE);
|
|
82
|
-
expect(component.iconName()).toBe(ICON_NAME_NEGATIVE);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it('should update icon when boolValue changes from false to true', () => {
|
|
86
|
-
const { component, fixture } = makeComponent(false);
|
|
87
|
-
|
|
88
|
-
expect(component.iconDesign()).toBe(ICON_DESIGN_NEGATIVE);
|
|
89
|
-
expect(component.iconName()).toBe(ICON_NAME_NEGATIVE);
|
|
90
|
-
|
|
91
|
-
fixture.componentRef.setInput('boolValue', true);
|
|
92
|
-
fixture.detectChanges();
|
|
93
|
-
|
|
94
|
-
expect(component.iconDesign()).toBe(ICON_DESIGN_POSITIVE);
|
|
95
|
-
expect(component.iconName()).toBe(ICON_NAME_POSITIVE);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it('should have required boolValue input', () => {
|
|
99
|
-
const { component } = makeComponent(true);
|
|
100
|
-
expect(component.boolValue()).toBe(true);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it('should have default testId', () => {
|
|
104
|
-
const { component } = makeComponent(true);
|
|
105
|
-
expect(component.testId()).toBe('boolean-value-icon');
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it('should accept custom testId', () => {
|
|
109
|
-
fixture = TestBed.createComponent(BooleanValue);
|
|
110
|
-
component = fixture.componentInstance;
|
|
111
|
-
|
|
112
|
-
fixture.componentRef.setInput('boolValue', true);
|
|
113
|
-
fixture.componentRef.setInput('testId', 'custom-test-id');
|
|
114
|
-
|
|
115
|
-
fixture.detectChanges();
|
|
116
|
-
|
|
117
|
-
expect(component.testId()).toBe('custom-test-id');
|
|
118
|
-
});
|
|
119
|
-
});
|
package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ICON_DESIGN_NEGATIVE,
|
|
3
|
-
ICON_DESIGN_POSITIVE,
|
|
4
|
-
ICON_NAME_NEGATIVE,
|
|
5
|
-
ICON_NAME_POSITIVE,
|
|
6
|
-
} from './boolean-cell.constants';
|
|
7
|
-
import {
|
|
8
|
-
CUSTOM_ELEMENTS_SCHEMA,
|
|
9
|
-
ChangeDetectionStrategy,
|
|
10
|
-
Component,
|
|
11
|
-
computed,
|
|
12
|
-
input,
|
|
13
|
-
} from '@angular/core';
|
|
14
|
-
import { Icon } from '@fundamental-ngx/ui5-webcomponents/icon';
|
|
15
|
-
|
|
16
|
-
export type IconDesignType = typeof ICON_DESIGN_POSITIVE | typeof ICON_DESIGN_NEGATIVE;
|
|
17
|
-
|
|
18
|
-
@Component({
|
|
19
|
-
selector: 'mfp-boolean-value',
|
|
20
|
-
imports: [Icon],
|
|
21
|
-
templateUrl: './boolean-value.component.html',
|
|
22
|
-
styleUrl: './boolean-value.component.scss',
|
|
23
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
24
|
-
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
|
25
|
-
})
|
|
26
|
-
export class BooleanValue {
|
|
27
|
-
boolValue = input.required<boolean>();
|
|
28
|
-
testId = input<string>('boolean-value-icon');
|
|
29
|
-
iconDesign = computed<IconDesignType>(() => {
|
|
30
|
-
return this.boolValue() ? ICON_DESIGN_POSITIVE : ICON_DESIGN_NEGATIVE;
|
|
31
|
-
});
|
|
32
|
-
iconName = computed<string>(() => {
|
|
33
|
-
return this.boolValue() ? ICON_NAME_POSITIVE : ICON_NAME_NEGATIVE;
|
|
34
|
-
});
|
|
35
|
-
}
|
|
File without changes
|