@vgip/meta-ui 2.1.1 → 2.1.3

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 (118) hide show
  1. package/.eslintrc.json +57 -0
  2. package/karma.conf.js +35 -0
  3. package/ng-package.json +10 -0
  4. package/package.json +4 -16
  5. package/src/lib/common/fieldNormalizer/boolean.ts +11 -0
  6. package/src/lib/common/fieldNormalizer/datetime.ts +8 -0
  7. package/src/lib/common/fieldNormalizer/index.ts +171 -0
  8. package/src/lib/common/fieldNormalizer/number.ts +13 -0
  9. package/src/lib/common/fieldNormalizer/options.ts +48 -0
  10. package/src/lib/common/fieldNormalizer/radio.ts +29 -0
  11. package/src/lib/common/fieldNormalizer/reference.ts +32 -0
  12. package/src/lib/common/fieldNormalizer/richtext.ts +15 -0
  13. package/src/lib/common/fieldNormalizer/string.ts +23 -0
  14. package/src/lib/common/fieldNormalizer/text.ts +17 -0
  15. package/src/lib/common/fieldNormalizer/uniqueNameFilter.ts +21 -0
  16. package/src/lib/common/metaAutofocus.directive.ts +31 -0
  17. package/src/lib/common/metaContext.resolver.ts +25 -0
  18. package/src/lib/common/metaIcons.pipe.spec.ts +15 -0
  19. package/src/lib/common/metaIcons.pipe.ts +29 -0
  20. package/src/lib/common/metaModel.pipe.ts +19 -0
  21. package/src/lib/common/metaNormalizer.ts +366 -0
  22. package/src/lib/common/metaStripHtml.pipe.ts +18 -0
  23. package/src/lib/common/utils/colorThemes.ts +86 -0
  24. package/src/lib/common/utils/indexedDbStore/index.ts +244 -0
  25. package/src/lib/common/utils/indexedDbStore/indexedDbStore.spec.ts +149 -0
  26. package/src/lib/common/utils/relativeTimeBuilder.ts +49 -0
  27. package/src/lib/common/utils/resourceCardLabel.ts +25 -0
  28. package/src/lib/common/utils/smartProp.spec.ts +24 -0
  29. package/src/lib/common/utils/smartProp.ts +28 -0
  30. package/src/lib/common/utils/templateBuilder.ts +99 -0
  31. package/src/lib/field.scss +207 -0
  32. package/src/lib/fieldAbstract.ts +327 -0
  33. package/src/lib/fieldBoolean/index.ts +55 -0
  34. package/src/lib/fieldBoolean/style.scss +22 -0
  35. package/src/lib/fieldBoolean/test.spec.ts +43 -0
  36. package/src/lib/fieldBoolean/view.html +30 -0
  37. package/src/lib/fieldComposite/index.ts +86 -0
  38. package/src/lib/fieldComposite/style.scss +6 -0
  39. package/src/lib/fieldComposite/test.spec.ts +43 -0
  40. package/src/lib/fieldComposite/view.html +9 -0
  41. package/src/lib/fieldDatetime/index.ts +359 -0
  42. package/src/lib/fieldDatetime/style.scss +81 -0
  43. package/src/lib/fieldDatetime/test.spec.ts +43 -0
  44. package/src/lib/fieldDatetime/view.html +26 -0
  45. package/src/lib/fieldHidden/index.ts +15 -0
  46. package/src/lib/fieldHidden/view.html +0 -0
  47. package/src/lib/fieldInput/index.ts +477 -0
  48. package/src/lib/fieldInput/style.scss +128 -0
  49. package/src/lib/fieldInput/test.spec.ts +43 -0
  50. package/src/lib/fieldInput/view.html +81 -0
  51. package/src/lib/fieldList/index.ts +73 -0
  52. package/src/lib/fieldList/style.scss +26 -0
  53. package/src/lib/fieldList/test.spec.ts +43 -0
  54. package/src/lib/fieldList/view.html +25 -0
  55. package/src/lib/fieldRadio/index.ts +93 -0
  56. package/src/lib/fieldRadio/style.scss +32 -0
  57. package/src/lib/fieldRadio/test.spec.ts +43 -0
  58. package/src/lib/fieldRadio/view.html +24 -0
  59. package/src/lib/fieldReference/index.ts +871 -0
  60. package/src/lib/fieldReference/style.scss +273 -0
  61. package/src/lib/fieldReference/test.spec.ts +44 -0
  62. package/src/lib/fieldReference/view.html +163 -0
  63. package/src/lib/fieldRichtext/index.ts +98 -0
  64. package/src/lib/fieldRichtext/quill.scss +6 -0
  65. package/src/lib/fieldRichtext/style.scss +87 -0
  66. package/src/lib/fieldRichtext/test.spec.ts +43 -0
  67. package/src/lib/fieldRichtext/view.html +17 -0
  68. package/src/lib/fieldSelect/index.ts +597 -0
  69. package/src/lib/fieldSelect/style.scss +165 -0
  70. package/src/lib/fieldSelect/test.spec.ts +44 -0
  71. package/src/lib/fieldSelect/view.html +128 -0
  72. package/src/lib/fieldText/index.ts +86 -0
  73. package/src/lib/fieldText/style.scss +24 -0
  74. package/src/lib/fieldText/test.spec.ts +43 -0
  75. package/src/lib/fieldText/view.html +23 -0
  76. package/src/lib/fieldUnknown/index.ts +15 -0
  77. package/src/lib/fieldUnknown/test.spec.ts +34 -0
  78. package/src/lib/fieldUnknown/view.html +9 -0
  79. package/src/lib/index.ts +127 -0
  80. package/src/lib/layout/index.ts +255 -0
  81. package/src/lib/layout/style.scss +67 -0
  82. package/src/lib/layout/view.html +45 -0
  83. package/src/lib/metaField/index.ts +133 -0
  84. package/src/lib/metaField/test.spec.ts +32 -0
  85. package/src/lib/refDialog/index.ts +157 -0
  86. package/src/lib/refDialog/style.scss +154 -0
  87. package/src/lib/refDialog/view.html +24 -0
  88. package/src/lib/resource/index.ts +559 -0
  89. package/src/lib/resource/style.scss +132 -0
  90. package/src/lib/resource/view.html +70 -0
  91. package/src/lib/resourceCard/index.ts +44 -0
  92. package/src/lib/resourceCard/style.scss +7 -0
  93. package/src/lib/resourceCard/view.html +14 -0
  94. package/src/lib/services/metaContext/index.ts +61 -0
  95. package/src/lib/services/metaMsg/index.ts +84 -0
  96. package/src/lib/services/metaReference/index.ts +98 -0
  97. package/src/lib/services/metaResource/index.ts +163 -0
  98. package/src/lib/services/metaResource/metaHttpClient.ts +76 -0
  99. package/src/lib/services/metaResource/metaResource.spec.ts +24 -0
  100. package/src/lib/services/metaTracker/index.ts +38 -0
  101. package/src/lib/services/resourceDrafts/index.ts +81 -0
  102. package/src/lib/services/resourceDrafts/resourceDrafts.spec.ts +24 -0
  103. package/src/lib/styles.scss +13 -0
  104. package/src/public-api.ts +5 -0
  105. package/src/test.ts +17 -0
  106. package/tsconfig.lib.json +25 -0
  107. package/tsconfig.lib.prod.json +9 -0
  108. package/tsconfig.spec.json +17 -0
  109. package/vendor/volta3/scss/components/_accordions.scss +5 -1
  110. package/vendor/volta3/scss/components/_callouts.scss +6 -2
  111. package/vendor/volta3/scss/components/_card.scss +1 -1
  112. package/vendor/volta3/scss/components/_form-elements.scss +1 -1
  113. package/vendor/volta3/scss/components/_modals.scss +1 -1
  114. package/vendor/volta3/scss/components/_tables.scss +1 -1
  115. package/vendor/volta3/scss/lib/_variables.scss +1 -1
  116. package/fesm2022/vgip-meta-ui.mjs +0 -6076
  117. package/fesm2022/vgip-meta-ui.mjs.map +0 -1
  118. package/index.d.ts +0 -709
@@ -0,0 +1,127 @@
1
+ /*
2
+ * @Author: Alexander.Vangelov@vonage.com
3
+ * @Date: 2019-09-19 17:34:34
4
+ * @Last Modified by: Alexander.Vangelov@vonage.com
5
+ * @Last Modified time: 2021-02-09 16:57:29
6
+ */
7
+
8
+ import { NgModule, ModuleWithProviders } from '@angular/core';
9
+ import { CommonModule } from '@angular/common';
10
+ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
11
+ import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
12
+
13
+ import { QuillModule } from 'ngx-quill';
14
+
15
+ import { MetaRefDialog } from './refDialog';
16
+
17
+ import { MetaLayout } from './layout';
18
+
19
+ import { MetaResource } from './resource';
20
+
21
+ import { MetaResourceCard } from './resourceCard';
22
+
23
+ import { FieldUnknown } from './fieldUnknown';
24
+ import { FieldInput } from './fieldInput';
25
+ import { FieldText } from './fieldText';
26
+
27
+ import { FieldSelect } from './fieldSelect';
28
+
29
+ import { FieldReference } from './fieldReference';
30
+
31
+ import { FieldComposite } from './fieldComposite';
32
+
33
+ import { FieldBoolean } from './fieldBoolean';
34
+ import { FieldRadio } from './fieldRadio';
35
+
36
+ import { FieldList } from './fieldList';
37
+
38
+ import { FieldRichtext } from './fieldRichtext';
39
+ import { FieldDatetime } from './fieldDatetime';
40
+
41
+ import { FieldHidden } from './fieldHidden';
42
+
43
+ import { MetaIconsPipe } from './common/metaIcons.pipe';
44
+ import { MetaModelPipe } from './common/metaModel.pipe';
45
+ import { MetaStripHtmlPipe } from './common/metaStripHtml.pipe';
46
+ import { MetaAutofocusDirective } from './common/metaAutofocus.directive';
47
+ import { MetaContextService } from './services/metaContext';
48
+ import { MetaTrackerService } from './services/metaTracker';
49
+ import { ResourceDraftsService } from './services/resourceDrafts';
50
+ import { MetaMsgService } from './services/metaMsg';
51
+ import { MetaReferenceService } from './services/metaReference';
52
+ import { MetaResourceService } from './services/metaResource';
53
+ import { MetaHttpClient } from './services/metaResource/metaHttpClient';
54
+ import { relativeTimeBuilder } from './common/utils/relativeTimeBuilder';
55
+ import { MetaField, MetaFieldContentDirective } from './metaField';
56
+
57
+ export * from './common/utils/colorThemes';
58
+ export * from './common/metaNormalizer';
59
+
60
+ @NgModule({ declarations: [
61
+ MetaIconsPipe,
62
+ MetaModelPipe,
63
+ MetaStripHtmlPipe,
64
+ MetaField,
65
+ MetaRefDialog,
66
+ MetaFieldContentDirective,
67
+ MetaLayout,
68
+ MetaResource,
69
+ MetaResourceCard,
70
+ FieldUnknown,
71
+ FieldInput,
72
+ FieldText,
73
+ FieldSelect,
74
+ FieldReference,
75
+ FieldComposite,
76
+ FieldBoolean,
77
+ FieldRadio,
78
+ FieldList,
79
+ FieldRichtext,
80
+ FieldDatetime,
81
+ FieldHidden,
82
+ MetaAutofocusDirective
83
+ ],
84
+ exports: [
85
+ MetaIconsPipe,
86
+ MetaModelPipe,
87
+ MetaStripHtmlPipe,
88
+ MetaField,
89
+ MetaLayout,
90
+ MetaResource,
91
+ MetaResourceCard,
92
+ MetaAutofocusDirective
93
+ ], imports: [CommonModule,
94
+ FormsModule,
95
+ ReactiveFormsModule,
96
+ QuillModule.forRoot()
97
+ // QuillModule.forRoot({
98
+ // modules: {
99
+ // syntax: false,
100
+ // toolbar: [
101
+ // ['bold', 'italic', 'underline'],
102
+ // [{ list: 'bullet' }],
103
+ // [{ header: [1, 2, 3, 4, 5, 6, false] }],
104
+ // [{ font: [] }],
105
+ // [{ align: [] }]
106
+ // ]
107
+ // }
108
+ // })
109
+ ], providers: [provideHttpClient(withInterceptorsFromDi())] })
110
+ export class MetaModule {
111
+ static withProviders(customProviders: any): ModuleWithProviders<MetaModule> {
112
+ return {
113
+ ngModule: MetaModule,
114
+ providers: customProviders
115
+ };
116
+ }
117
+ }
118
+
119
+ export {
120
+ MetaField, MetaFieldContentDirective, MetaRefDialog, MetaResourceCard,
121
+ MetaIconsPipe, MetaModelPipe, MetaStripHtmlPipe, MetaAutofocusDirective,
122
+ FieldUnknown, FieldInput, FieldText, FieldSelect, MetaLayout, MetaResource,
123
+ FieldBoolean, FieldRadio, FieldList, FieldComposite, FieldReference, FieldHidden,
124
+ FieldRichtext, FieldDatetime, MetaContextService, MetaTrackerService, ResourceDraftsService,
125
+ MetaMsgService, MetaReferenceService, MetaResourceService, MetaHttpClient,
126
+ relativeTimeBuilder
127
+ };
@@ -0,0 +1,255 @@
1
+ import {
2
+ AfterContentChecked,
3
+ ChangeDetectorRef,
4
+ Component,
5
+ ElementRef,
6
+ Input,
7
+ OnChanges,
8
+ OnInit,
9
+ DoCheck,
10
+ ViewContainerRef,
11
+ } from "@angular/core";
12
+ import { Subject } from "rxjs";
13
+ import { resourceCardLabel } from "../common/utils/resourceCardLabel";
14
+ import { MetaResourceService } from "../services/metaResource";
15
+ import { MetaReferenceService } from "../services/metaReference";
16
+ import { debounceTime, distinctUntilChanged } from "rxjs/operators";
17
+ import { metaDark, metaLight } from "../common/utils/colorThemes";
18
+ import { MetaMsgService } from "../services/metaMsg";
19
+ import { MetaContextService } from "../services/metaContext";
20
+
21
+ @Component({
22
+ selector: "vgip-meta-layout",
23
+ templateUrl: "./view.html",
24
+ styleUrls: ["./style.scss"],
25
+ standalone: false
26
+ })
27
+ export class MetaLayout
28
+ implements OnInit, AfterContentChecked, OnChanges, DoCheck
29
+ {
30
+ @Input() meta: any;
31
+ @Input() resource: any;
32
+ @Input() integration: any;
33
+ @Input() type: any;
34
+ @Input() preview: boolean;
35
+ @Input() theme: string;
36
+ @Input() delegate: any;
37
+
38
+ optionalFields: any = {};
39
+ optionalFieldsCount: number;
40
+ showAll = false;
41
+ fieldsVisibilityChanged: Subject<string> = new Subject<string>();
42
+ parentForm: HTMLFormElement;
43
+ integrationCode: string;
44
+ resourceType: string;
45
+ childResourceCardLabel = resourceCardLabel;
46
+ overlayContainer: HTMLElement;
47
+
48
+ constructor(
49
+ private viewContainerRef: ViewContainerRef,
50
+ private ref: ChangeDetectorRef,
51
+ private el: ElementRef,
52
+ private metaResource: MetaResourceService,
53
+ private referenceService: MetaReferenceService,
54
+ private metaMsgService: MetaMsgService,
55
+ private metaContext: MetaContextService
56
+ ) {
57
+ // console.log('MetaLayout', this.meta);
58
+ this.overlayContainer = el.nativeElement;
59
+ }
60
+
61
+ get isPersistedResource() {
62
+ // eslint-disable-next-line no-underscore-dangle
63
+ return (
64
+ this.resource &&
65
+ this.resource._vgis &&
66
+ (this.resource._vgis.externalId || this.resource._vgis.id)
67
+ );
68
+ }
69
+
70
+ ngOnInit() {
71
+ this.integrationCode = this.meta.integrationCode || this.integration;
72
+ this.resourceType = this.meta.resourceType || this.type;
73
+ this.parentForm = this.el.nativeElement.closest("form");
74
+ this.configureOptionalSections();
75
+
76
+ this.fieldsVisibilityChanged
77
+ .pipe(debounceTime(100), distinctUntilChanged())
78
+ .subscribe(() => {
79
+ this.countOptionalFields();
80
+ });
81
+ setTimeout(() => {
82
+ this.countOptionalFields();
83
+ }, 0);
84
+
85
+ if (this.parentForm) {
86
+ this.parentForm.addEventListener("change", () => {
87
+ setTimeout(() => {
88
+ this.fieldsVisibilityChanged.next(JSON.stringify(this.resource));
89
+ this.countOptionalFields();
90
+ }, 0);
91
+ });
92
+ }
93
+
94
+ if (this.theme !== "inherit") {
95
+ this.applyTheme();
96
+ }
97
+ if (this.isPersistedResource && this.meta.children && this.preview) {
98
+ this.procChildrenExternalLinks();
99
+ }
100
+ }
101
+
102
+ ngDoCheck(): void {
103
+ this.countOptionalFields();
104
+ }
105
+
106
+ ngOnChanges(changes: any) {
107
+ if (changes.meta) {
108
+ this.configureOptionalSections();
109
+ setTimeout(() => {
110
+ this.countOptionalFields();
111
+ }, 0);
112
+ }
113
+ if (changes.theme) {
114
+ this.theme = changes.theme.currentValue;
115
+ this.applyTheme();
116
+ }
117
+ }
118
+
119
+ countOptionalFields() {
120
+ let count = 0;
121
+ const countSectionFields = (s) => {
122
+ for (const f of s.fields || []) {
123
+ if (f.fields?.length && !f.visible) {
124
+ countSectionFields(f);
125
+ } else {
126
+ if (f.$optional && !f.$hidden) {
127
+ count++;
128
+ }
129
+ }
130
+ }
131
+ };
132
+ for (const s of this.meta.sections) {
133
+ const notOptionalAny = s.fields?.find((f) => !f.$optional);
134
+ s.$optional = !notOptionalAny;
135
+ if (!s.visible) {
136
+ countSectionFields(s);
137
+ }
138
+ }
139
+ this.optionalFieldsCount = count;
140
+ }
141
+
142
+ configureOptionalSections() {
143
+ if (this.meta?.sections) {
144
+ for (const s of this.meta.sections) {
145
+ Object.defineProperty(s, "$optional", {
146
+ value: true,
147
+ writable: true,
148
+ configurable: true,
149
+ enumerable: false,
150
+ });
151
+ }
152
+ }
153
+ }
154
+
155
+ ngAfterContentChecked() {
156
+ this.ref.detectChanges();
157
+ }
158
+
159
+ toggleOptionalFields() {
160
+ this.showAll = !this.showAll;
161
+ this.ngAfterContentChecked();
162
+ }
163
+
164
+ private buildExternalLinkForChild(child) {
165
+ if (child?.externalId || child.id) {
166
+ this.metaMsgService.sendMessage(
167
+ this.integrationCode.toUpperCase(),
168
+ {
169
+ action: "buildExternalLink",
170
+ integrationCode: this.integrationCode.toLowerCase(), // don't know why but all workers are written expecting lowercase
171
+ ref: {
172
+ parentRefId: this.resource._vgis.externalId || this.resource._vgis.id,
173
+ parentResourceType: this.resource._vgis.resourceType,
174
+ ...child
175
+ },
176
+ profile: this.metaContext.profiles[ this.integrationCode.toUpperCase()]
177
+ },
178
+ (response) => {
179
+ if (!response.error) {
180
+ child.externalLink = response.externalLink;
181
+ } else {
182
+ console.warn(
183
+ "No external link support for",
184
+ this.integrationCode,
185
+ child.resourceType
186
+ );
187
+ }
188
+ }
189
+ );
190
+ }
191
+ }
192
+
193
+ private procChildrenExternalLinks() {
194
+ for (const child of this.meta.children) {
195
+ let childrenValue = this.resource[child.name];
196
+ Object.defineProperty(this.resource, child.name, {
197
+ set: (children) => {
198
+ childrenValue = children;
199
+ if (children instanceof Array) {
200
+ childrenValue = children;
201
+ for (const c in children) {
202
+ if (children[c]?._vgis && !children[c]._vgis.externalLink) { // some day BE will start providing it
203
+ this.buildExternalLinkForChild(children[c]._vgis);
204
+ }
205
+ }
206
+ }
207
+ },
208
+ get: () => childrenValue,
209
+ enumerable: true,
210
+ configurable: true
211
+ });
212
+ if (childrenValue) {
213
+ this.resource[child.name] = childrenValue;
214
+ }
215
+ }
216
+ }
217
+
218
+ async openChild(childResource, childModel?) {
219
+ const metaRefDialog = await import("../refDialog").then(
220
+ (m) => m.MetaRefDialog
221
+ );
222
+ childResource.reference.parent = this.resource._vgis; // eslint-disable-line no-underscore-dangle
223
+ const refDialogComponent =
224
+ this.viewContainerRef.createComponent(metaRefDialog);
225
+ this.referenceService
226
+ .openDialog(
227
+ refDialogComponent,
228
+ this.metaResource,
229
+ this.integrationCode,
230
+ childResource.reference,
231
+ childModel,
232
+ childModel && childResource.reference.editable === false // is preview mode
233
+ )
234
+ .subscribe((result: any) => {
235
+ if (result?.raw) {
236
+ if (!this.resource[childResource.name]) {
237
+ this.resource[childResource.name] = [];
238
+ }
239
+ if (childModel) {
240
+ Object.assign(childModel, result.raw);
241
+ } else {
242
+ this.buildExternalLinkForChild(result.raw._vgis);
243
+ this.resource[childResource.name].push(result.raw);
244
+ }
245
+ }
246
+ });
247
+ }
248
+
249
+ private applyTheme() {
250
+ const metaTheme = this.theme === "dark" ? metaDark : metaLight;
251
+ for (const key of Object.keys(metaTheme.properties)) {
252
+ this.el.nativeElement.style.setProperty(key, metaTheme.properties[key]);
253
+ }
254
+ }
255
+ }
@@ -0,0 +1,67 @@
1
+ vgip-meta-field {
2
+ display: none;
3
+ &.shown {
4
+ display: initial;
5
+ }
6
+ }
7
+
8
+ .Vlt-section__title {
9
+ // font-size: 12px;
10
+ line-height: 14px;
11
+ // font-weight: normal;
12
+ margin: 8px;
13
+ padding: 16px 16px 14px 3px;
14
+ // text-transform: uppercase;
15
+ margin-left: -1px;
16
+ margin-right: -1px;
17
+ margin-top: -9px;
18
+ background-color: var(--vgip-meta-resource-bg-color);
19
+ color: var(--vgip-meta-resource-color);
20
+ position: sticky;
21
+ top: -9px;
22
+ z-index: 3;
23
+ // box-shadow: 0px 1px 3px rgba(44, 45, 48, 0.1);
24
+ border-bottom: 1px solid var(--vgip-meta-separator-color);
25
+ }
26
+
27
+ .Vlt-section {
28
+ margin: 0;
29
+ padding-bottom: 8px;
30
+ display: none;
31
+ &.shown {
32
+ display: block;
33
+ }
34
+ }
35
+ .Vlt-btn.vlt-add-child:hover {
36
+ transform: scale(1.02);
37
+ }
38
+
39
+ .for-preview {
40
+ margin-top: -6px;
41
+ }
42
+
43
+ .Vlt-card {
44
+ margin-bottom: 16px;
45
+ padding: 16px;
46
+ .Vlt-btn-group.Vlt-btn-group--hover {
47
+ right: -8px;
48
+ }
49
+ }
50
+
51
+ button.more-button:focus {
52
+ font-weight: bold;
53
+ }
54
+
55
+ .centered {
56
+ text-align: center;
57
+ }
58
+
59
+ .Vlt-btn--link {
60
+ color: var(--vgip-meta-link-color);
61
+ &:hover {
62
+ color: var(--vgip-meta-link-hover-color);
63
+ }
64
+ svg {
65
+ fill: var(--vgip-meta-link-color);
66
+ }
67
+ }
@@ -0,0 +1,45 @@
1
+ <div *ngFor='let section of meta.sections' class='Vlt-section' [ngClass]="{ shown: showAll || section.visible || (!meta.oneTimeOptional && !section.$optional) || (meta.oneTimeOptional && !optionalFieldsCount) }">
2
+ <h5 *ngIf='section.label' class="Vlt-section__title">{{section.label}}</h5>
3
+ <div style='overflow: visible;' [ngClass]="{ 'for-preview': preview }">
4
+ <small *ngIf='section.description' class="Vlt-form__element__hint">{{section.description}}</small>
5
+ <div>
6
+ <ng-container *ngFor='let field of section.fields'>
7
+ <vgip-meta-field *ngIf='!field.$hidden && (showAll || section.visible || !field.$optional)' [meta]='field' [parent]='resource' [integrationCode]='integrationCode' [resourceType]='resourceType' [preview]='preview' [ngClass]="{ shown: !field.$invisible && (showAll || true) }" theme='inherit' [attr.data-theme]='theme' [delegate]='delegate'></vgip-meta-field>
8
+ </ng-container>
9
+ </div>
10
+ </div>
11
+ </div>
12
+ <div *ngIf='isPersistedResource && meta.children && preview'>
13
+ <div *ngFor='let child of meta.children'>
14
+ <h5 class='Vlt-children__title'>
15
+ <svg class="Vlt-icon"><use xlink:href="volta/volta-icons.svg#Vlt-icon-stack" /></svg>&nbsp;
16
+ {{child.label}} <span class='Vlt-grey'>({{(resource[child.name] || []).length}})</span>
17
+ </h5>
18
+ <div *ngFor="let c of resource[child.name]" style='position: relative;'>
19
+
20
+ <div class="Vlt-card Vlt-bg-white">
21
+ <div class="Vlt-card__content Vlt-btn-on-hover">
22
+ <h5>{{childResourceCardLabel(c)}}</h5>
23
+ <div style='font-size: 12px; line-height: 16px;'>
24
+ Created: <span class='Vlt-black'>{{c._vgis.createdDate | date:'mediumDate'}}</span>
25
+ Edited: <span class='Vlt-black'>{{c._vgis.modifiedDate | date:'medium'}}</span>
26
+ </div>
27
+ <div class="Vlt-badge Vlt-badge--app Vlt-badge--purple Vlt-badge--small">{{c._vgis.resourceType}}</div>
28
+ <div class="Vlt-btn-group Vlt-btn-group--hover">
29
+ <a *ngIf='c._vgis.externalLink' attr.href='{{c._vgis.externalLink}}' target='_blank' rel='noopener' rel='noopener' class="Vlt-btn Vlt-btn--tertiary Vlt-btn--icon" aria-label='Open external'><svg style='margin-left: 0; margin-right: 0;'><use xlink:href="volta/volta-icons.svg#Vlt-icon-open"/></svg></a>
30
+ <button type='button' (click)='openChild(child, c)' class="Vlt-btn Vlt-btn--tertiary Vlt-btn--icon"><svg style='margin-left: 0; margin-right: 0;'><use attr.xlink:href="volta/volta-icons.svg#Vlt-icon-{{ child.reference.editable ? 'edit' : 'eye-negative' }}"/></svg></button>
31
+ </div>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ <button style='width: 100%; margin-top: 0; max-width: 100%;' type='button' (click)='openChild(child)' class="Vlt-btn Vlt-btn--small Vlt-btn--secondary" [disabled]='child.creatable === false'>
36
+ <svg><use xlink:href="volta/volta-icons.svg#Vlt-icon-plus"/></svg>{{child.reference.label}}
37
+ </button>
38
+ </div>
39
+ </div>
40
+ <div *ngIf='!(meta.oneTimeOptional && showAll)' [ngClass]='{ centered: !meta.oneTimeOptional }'>
41
+ <button *ngIf='!preview && optionalFieldsCount' type='button' (click)='toggleOptionalFields()' class="Vlt-btn Vlt-btn--small Vlt-btn--link more-button" style='margin: 0; margin-bottom: 10px;'>
42
+ <svg><use attr.xlink:href="volta/volta-icons.svg#Vlt-icon-chevron-{{ showAll ? 'up' : 'down' }}"/></svg>
43
+ {{ showAll ? 'Hide' : 'Show' }} Optional Fields ({{optionalFieldsCount}})
44
+ </button>
45
+ </div>
@@ -0,0 +1,133 @@
1
+ import { Component, Directive, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild, ViewContainerRef } from '@angular/core';
2
+ import { FieldAbstract } from '../fieldAbstract';
3
+
4
+ const FMAP = async (fType) => {
5
+ switch (fType) {
6
+ case '':
7
+ case null:
8
+ case undefined:
9
+ case 'number':
10
+ // case 'datetime':
11
+ // case 'time':
12
+ // case 'date':
13
+ case 'string': { // eslint-disable-line no-fallthrough
14
+ // return FieldInput;
15
+ return import('../fieldInput').then(m => m.FieldInput);
16
+ }
17
+ case 'textarea':
18
+ case 'text': {
19
+ // return FieldText
20
+ return import('../fieldText').then(m => m.FieldText);
21
+ }
22
+ case 'select':
23
+ case 'options': {
24
+ // return FieldSelect
25
+ return import('../fieldSelect').then(m => m.FieldSelect);
26
+ }
27
+ case 'reference': {
28
+ // return FieldReference;
29
+ return import('../fieldReference').then(m => m.FieldReference);
30
+ }
31
+ case 'composite': {
32
+ // return FieldComposite;
33
+ return import('../fieldComposite').then(m => m.FieldComposite);
34
+ }
35
+ case 'boolean': {
36
+ // return FieldBoolean;
37
+ return import('../fieldBoolean').then(m => m.FieldBoolean);
38
+ }
39
+ case 'radio': {
40
+ // return FieldRadio;
41
+ return import('../fieldRadio').then(m => m.FieldRadio);
42
+ }
43
+ case 'list': {
44
+ // return FieldList;
45
+ return import('../fieldList').then(m => m.FieldList);
46
+ }
47
+ case 'richtext': {
48
+ // return FieldRichtext;
49
+ return import('../fieldRichtext').then(m => m.FieldRichtext);
50
+ }
51
+ case 'datetime':
52
+ case 'time':
53
+ case 'date': {
54
+ // return FieldDatetime;
55
+ return import('../fieldDatetime').then(m => m.FieldDatetime);
56
+ }
57
+ case 'hidden': {
58
+ return import('../fieldHidden').then(m => m.FieldHidden);
59
+ }
60
+ default: {
61
+ // return FieldUnknown;
62
+ return import('../fieldUnknown').then(m => m.FieldUnknown);
63
+ }
64
+ }
65
+ };
66
+
67
+ @Directive({
68
+ selector: '[metaFieldContent]',
69
+ standalone: false
70
+ })
71
+ export class MetaFieldContentDirective {
72
+ constructor(public viewContainerRef: ViewContainerRef) { }
73
+ }
74
+
75
+ @Component({
76
+ selector: 'vgip-meta-field',
77
+ template: '<ng-template metaFieldContent>Loading</ng-template>',
78
+ styleUrls: ['../field.scss'],
79
+ standalone: false
80
+ })
81
+ export class MetaField extends FieldAbstract implements OnInit {
82
+ @Input() meta: any;
83
+ @Input() parent: any;
84
+ @Input() integrationCode: any;
85
+ @Input() resourceType: any;
86
+ @Input() index: number;
87
+ @Input() scope: string;
88
+ @Input() preview: boolean;
89
+ @Input() theme: string;
90
+ @Input() overlayContainer: HTMLElement;
91
+ @Input() delegate: any;
92
+
93
+ // eslint-disable-next-line
94
+ @Output() onChange = new EventEmitter();
95
+ // eslint-disable-next-line
96
+ @Output() onLeave = new EventEmitter();
97
+
98
+ @ViewChild(MetaFieldContentDirective, { static: true }) fieldContent: MetaFieldContentDirective;
99
+
100
+ constructor(private el: ElementRef) {
101
+ super();
102
+ }
103
+
104
+ async ngOnInit() {
105
+ const component = await FMAP(this.meta.type);
106
+ this.fieldContent.viewContainerRef.clear();
107
+ const componentRef = this.fieldContent.viewContainerRef.createComponent(component);
108
+ const field: FieldAbstract = componentRef.instance;
109
+ if (component.setup) {
110
+ // console.log('setup', {a: this.el.nativeElement.parentNode.parentNode})
111
+ component.setup(field, this.parent, this.meta);
112
+ }
113
+ field.meta = this.meta;
114
+ field.parent = this.parent;
115
+ field.integrationCode = (this.integrationCode || '').toLowerCase();
116
+ field.resourceType = (this.resourceType || '');
117
+ field.index = this.index;
118
+ field.scope = this.scope;
119
+ field.elementRef = this.el;
120
+ field.onChange = this.onChange;
121
+ field.onLeave = this.onLeave;
122
+ field.preview = this.preview;
123
+ field.theme = this.theme;
124
+ field.overlayContainer = this.overlayContainer;
125
+ field.delegate = this.delegate;
126
+ Object.defineProperty(field.meta, 'unset', {
127
+ value: false,
128
+ writable: true,
129
+ configurable: true,
130
+ enumerable: false
131
+ });
132
+ }
133
+ }
@@ -0,0 +1,32 @@
1
+
2
+ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
3
+
4
+ import { MetaModule } from '..';
5
+ import { MetaField } from '.';
6
+
7
+ describe('MetaField', () => {
8
+ let component: MetaField;
9
+ let fixture: ComponentFixture<MetaField>;
10
+
11
+ beforeEach(waitForAsync(() => {
12
+ TestBed.configureTestingModule({
13
+ declarations: [],
14
+ imports: [
15
+ MetaModule
16
+ ]
17
+ })
18
+ .compileComponents();
19
+ }));
20
+
21
+ beforeEach(() => {
22
+ fixture = TestBed.createComponent(MetaField);
23
+ component = fixture.componentInstance;
24
+ component.parent = {};
25
+ component.meta = { type: 'dummy' };
26
+ fixture.detectChanges();
27
+ });
28
+
29
+ it('should create', () => {
30
+ expect(component).toBeTruthy();
31
+ });
32
+ });