@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,273 @@
1
+ .Vlt-form__element--big .Vlt-input input:placeholder-shown:not(:focus) ~ label.Vlt-truncate {
2
+ font-size: 1.6rem;
3
+ margin-top: -0.8rem;
4
+ top: 50%;
5
+ }
6
+
7
+ .Vlt-form__element--big {
8
+ ::ng-deep .search-scope vgip-meta-field .Vlt-input input.main.standalone {
9
+ border-right: 0;
10
+ text-overflow: ellipsis;
11
+ white-space: nowrap;
12
+ overflow: hidden;
13
+ }
14
+ &:hover, &.active {
15
+ .items-container, .main, .Vlt-composite__append button, ::ng-deep .search-scope vgip-meta-field .Vlt-input input.main.standalone {
16
+ border-color: var(--vgip-meta-input-active-border-color);
17
+ }
18
+ }
19
+ &.Vlt-form__element--error {
20
+ .items-container, .main, .Vlt-composite__append button, ::ng-deep .search-scope vgip-meta-field .Vlt-input input.main.standalone {
21
+ border-color: #f25a6b;
22
+ }
23
+ }
24
+ &.multiple {
25
+ .Vlt-composite.Vlt-dropdown {
26
+ margin-top: 3px;
27
+ }
28
+ &:hover:not(.Vlt-form__element--error), &.active:not(.Vlt-form__element--error) {
29
+ .items-container, .main, .Vlt-composite__append button, ::ng-deep .search-scope vgip-meta-field .Vlt-input input.main.standalone {
30
+ border-color: var(--vgip-meta-input-active-border-color);
31
+ }
32
+ }
33
+ .items-container {
34
+ background-color: var(--vgip-meta-input-bg-color);
35
+ border: 1px solid var(--vgip-meta-input-border-color);
36
+ border-bottom: 0;
37
+ border-top-left-radius: 6px;
38
+ border-top-right-radius: 6px;
39
+ // &.creatable {
40
+ // margin-right: 62px;
41
+ // }
42
+ .badges-container {
43
+ overflow: auto;
44
+ // max-height: 140px;
45
+ padding: 6px 4px 3px 6px;
46
+ .Vlt-badge {
47
+ margin-bottom: 3px;
48
+ margin-left: 0;
49
+ margin-right: 3px;
50
+ overflow: hidden;
51
+ max-width: 100%;
52
+ position: relative;
53
+ padding-right: 30px;
54
+ &.grid {
55
+ display: grid;
56
+ }
57
+ }
58
+ }
59
+ }
60
+ &:not(.has-value) .items-container {
61
+ border: 0;
62
+ }
63
+ &.has-value {
64
+ .main, .Vlt-composite__append button, ::ng-deep .search-scope vgip-meta-field .Vlt-input input.main.standalone {
65
+ &:not(.Vlt-btn--icon) {
66
+ border-top: 0;
67
+ }
68
+ border-top-left-radius: 0;
69
+ border-top-right-radius: 0;
70
+ height: 48px;
71
+ }
72
+ .Vlt-composite__prepend ::ng-deep .search-scope vgip-meta-field .Vlt-input input.main.standalone {
73
+ border-top-right-radius: 6px;
74
+ }
75
+ .Vlt-composite__append button {
76
+ border-top-left-radius: 6px;
77
+ border-top: 0;
78
+ }
79
+ }
80
+ }
81
+ }
82
+
83
+ .Vlt-composite__prepend {
84
+ z-index: initial;
85
+ }
86
+ .Vlt-composite__prepend--icon {
87
+ top: 0;
88
+ padding-top: 15px;
89
+ left: 3px;
90
+ }
91
+ .Vlt-input.has-append-button {
92
+ .Vlt-composite__append.right-actions {
93
+ right: 0;
94
+ .Vlt-composite__append--icon:last-child {
95
+ width: 36px;
96
+ }
97
+ }
98
+ }
99
+ .Vlt-composite__append.right-actions {
100
+ position: absolute;
101
+ top: 5px;
102
+ right: 5px;
103
+ cursor: pointer;
104
+ .Vlt-composite__append--icon {
105
+ outline: none;
106
+ position: initial;
107
+ display: inline-block;
108
+ svg {
109
+ height: 14px;
110
+ width: 14px;
111
+ }
112
+ }
113
+ .Vlt-composite__append--icon:hover svg, .Vlt-composite__append--icon:focus svg {
114
+ fill: var(--vgip-meta-input-accent-color);
115
+ }
116
+ }
117
+
118
+ .vgip-disable .Vlt-composite__append{
119
+ cursor: not-allowed;
120
+ pointer-events: none;
121
+ }
122
+
123
+ .Vlt-composite__append--icon.preview {
124
+ bottom: initial;
125
+ padding: 0 2px;
126
+ }
127
+ .Vlt-composite__append button {
128
+ height: 48px;
129
+ padding-right: 16px;
130
+ background: var(--vgip-meta-input-bg-color);
131
+ border-color: var(--vgip-meta-input-border-color);
132
+ padding-left: 16px;
133
+ border-left: 0;
134
+ border-top-right-radius: 6px;
135
+ border-bottom-right-radius: 6px;
136
+ &:hover {
137
+ background: var(--vgip-meta-input-action-hover-bg-color);
138
+ }
139
+ svg {
140
+ margin: -2px 0 0 0;
141
+ fill: var(--vgip-meta-input-accent-color);
142
+ }
143
+ &:disabled {
144
+ opacity: 0.2;
145
+ }
146
+ }
147
+
148
+ .Vlt-input input {
149
+ padding-left: 38px;
150
+ text-overflow: ellipsis;
151
+ padding-right: 36px;
152
+ &.ext {
153
+ padding-right: 72px;
154
+ }
155
+ }
156
+ .Vlt-composite__wrapper.has-append-button {
157
+ input.main {
158
+ border-top-right-radius: 0;
159
+ border-bottom-right-radius: 0;
160
+ border-right: 0;
161
+ }
162
+ }
163
+ .Vlt-input input {
164
+ background: var(--vgip-meta-input-bg-color);
165
+ border-color: var(--vgip-meta-input-border-color);
166
+ font-weight: bold;
167
+ // &:hover, &:focus {
168
+ // border-color: #2c2d30;
169
+ // }
170
+ }
171
+
172
+ .Vlt-dropdown__panel {
173
+ max-width: 100%;
174
+ width: 100%;
175
+ min-width: 280px;
176
+ .Vlt-dropdown__link.smart {
177
+ font-weight: bold;
178
+ background: var(--vgip-meta-dropdown-bg-color);
179
+ &.hidden {
180
+ display: none;
181
+ }
182
+ }
183
+ .Vlt-dropdown__link.bold:after {
184
+ background-color: #e1e2e6;
185
+ content: '';
186
+ height: 1px;
187
+ left: 0;
188
+ position: absolute;
189
+ right: 0;
190
+ bottom: 0;
191
+ }
192
+ .Vlt-dropdown__link--selected {
193
+ background: rgba(44, 45, 48, 0.05);
194
+ }
195
+ .Vlt-dropdown__link > div {
196
+ flex: 1;
197
+ overflow: hidden;
198
+ white-space: nowrap;
199
+ text-overflow: ellipsis;
200
+ }
201
+ .Vlt-dropdown__link > svg {
202
+ // margin-left: -8px;
203
+ margin-right: 8px;
204
+ }
205
+ }
206
+
207
+ .vgip-meta-field-preview .Vlt-badge {
208
+ margin: 1px 3px 1px 0;
209
+ overflow: hidden;
210
+ max-width: 100%;
211
+ }
212
+
213
+ :host .search-scope {
214
+ width: 130px;
215
+ ::ng-deep .Vlt-form__element {
216
+ &.has-value .Vlt-select:after {
217
+ display: none;
218
+ }
219
+ .right-actions {
220
+ right: 12px;
221
+ }
222
+ label.Vlt-truncate {
223
+ padding-right: 48px;
224
+ }
225
+ }
226
+ .mobile-icon {
227
+ display: none;
228
+ }
229
+ @media only screen and (max-width: 575px) {
230
+ width: 60px;
231
+ &:not(.has-value) .mobile-icon {
232
+ display: block;
233
+ }
234
+ &.has-value {
235
+ .mobile-label {
236
+ display: block;
237
+ }
238
+ }
239
+ ::ng-deep .Vlt-form__element.Vlt-form__element--big {
240
+ .Vlt-composite__append {
241
+ display: none;
242
+ }
243
+ // &.has-value .Vlt-select:after {
244
+ // right: -7px;
245
+ // }
246
+ .Vlt-select:after {
247
+ margin-right: -7px;
248
+ }
249
+ // &:not(.has-value) label {
250
+ // display: none;
251
+ // }
252
+ label.Vlt-truncate {
253
+ visibility: hidden;
254
+ }
255
+ }
256
+ }
257
+ ::ng-deep vgip-meta-field {
258
+ .Vlt-input input.main.standalone {
259
+ padding-right: initial;
260
+ background: var(--vgip-meta-input-accent-bg-color);
261
+ border-color: var(--vgip-meta-input-border-color);
262
+ }
263
+ .Vlt-form__element {
264
+ padding: 0;
265
+ .Vlt-dropdown__panel {
266
+ width: initial;
267
+ }
268
+ // &:not(.has-value) > .Vlt-input > .Vlt-select > label {
269
+ // margin-left: 26px;
270
+ // }
271
+ }
272
+ }
273
+ }
@@ -0,0 +1,44 @@
1
+ /*
2
+ * @Author: Alexander.Vangelov@vonage.com
3
+ * @Date: 2019-09-19 17:35:19
4
+ * @Last Modified by: Alexander.Vangelov@vonage.com
5
+ * @Last Modified time: 2022-01-19 08:53:45
6
+ */
7
+
8
+ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
9
+ import { RouterTestingModule } from '@angular/router/testing';
10
+ import { NgForm } from '@angular/forms';
11
+
12
+ import { MetaModule } from '..';
13
+
14
+ import { FieldReference } from '../fieldReference';
15
+
16
+ describe('FieldReference', () => {
17
+ let component: FieldReference;
18
+ let fixture: ComponentFixture<FieldReference>;
19
+
20
+ beforeEach(waitForAsync(() => {
21
+ TestBed.configureTestingModule({
22
+ declarations: [],
23
+ imports: [
24
+ MetaModule, RouterTestingModule
25
+ ],
26
+ providers: [
27
+ { provide: NgForm, useValue: new NgForm([], []) }
28
+ ]
29
+ })
30
+ .compileComponents();
31
+ }));
32
+
33
+ beforeEach(() => {
34
+ fixture = TestBed.createComponent(FieldReference);
35
+ component = fixture.componentInstance;
36
+ component.parent = {};
37
+ component.meta = { name: 'f1', reference: { type: 'Test' } };
38
+ fixture.detectChanges();
39
+ });
40
+
41
+ it('should create', () => {
42
+ expect(component).toBeTruthy();
43
+ });
44
+ });
@@ -0,0 +1,163 @@
1
+ <div class='vgip-meta-field-preview' *ngIf='preview && model && (!multiple || (multiple && model.length))'>
2
+ <div class='vgip-meta-field-label' [title]='meta.label || meta.name'>{{meta.label || meta.name}}</div>
3
+ <div *ngIf='!multiple' class='vgip-meta-field-value __gu' [ngClass]="{ 'has-external-link': externalLink || model.externalLink }">
4
+ <svg class="Vlt-icon Vlt-icon--smaller" style='margin-top: -3px;'>
5
+ <use attr.xlink:href="volta/volta-brand-icons.svg#{{integrationIcon}}" />
6
+ </svg>
7
+ {{model.label || model.id}} <span class='Vlt-grey'>({{model.type}})</span>
8
+ </div>
9
+ <div *ngIf='multiple' class='vgip-meta-field-value __gu'>
10
+ <span *ngFor='let m of (model || [])' class='Vlt-badge Vlt-badge--app'>
11
+ {{m.label || m.id || m}} <span class='Vlt-grey-dark' *ngIf='isPolymorphic'>({{m.type}})</span>
12
+ </span>
13
+ </div>
14
+ <a [href]='externalLink || model.externalLink' target='_blank' rel='noopener'
15
+ *ngIf='externalLink && (model && !multiple)' class="Vlt-composite__append--icon preview" aria-label='Open external'>
16
+ <div class="Vlt-composite__icon">
17
+ <svg>
18
+ <use xlink:href="volta/volta-icons.svg#Vlt-icon-open" />
19
+ </svg>
20
+ </div>
21
+ </a>
22
+ </div>
23
+ <div *ngIf='!preview' class="meta-field-reference Vlt-form__element Vlt-form__element--big"
24
+ [ngClass]="{ 'Vlt-form__element--error': (searchError && keyListenerActive) || (f.invalid && ((f | metaModel)._parent.submitted || (ft | metaModel ).touched)), 'multiple': multiple, 'has-value': model, active: keyListenerActive }">
25
+ <div *ngIf='multiple' class='items-container' [ngClass]='{ creatable: isCreatable }'>
26
+ <div *ngIf='model' class='badges-container keep-focus' (click)='focus()' style='width: 100%;'> <!-- eslint-disable-line -->
27
+ <div *ngFor='let item of model' class="Vlt-badge Vlt-badge--transparent Vlt-badge--app Vlt-badge--large keep-focus" [ngClass]="{ grid: (item.label || item.id || '').length > 56}">
28
+ <span class='Vlt-truncate'>{{item.label || item.id || item }} <span *ngIf='isPolymorphic' class='Vlt-grey-darker' style='font-weight: normal;'>({{item.type}})</span></span>
29
+ <button class="Vlt-badge__dismiss keep-focus" (click)='remove($event, item)' style='position: absolute; right: 12px; top: 8px;' aria-label='Remove'></button>
30
+ </div>
31
+ </div>
32
+ </div>
33
+ <div class="Vlt-composite">
34
+ <div class='dropdown-wrapper Vlt-dropdown' style='width: 100%; position: absolute; top: 48px;'>
35
+ <div class="Vlt-dropdown__panel">
36
+ <div *ngIf='searchError'>
37
+ <div class="Vlt-callout Vlt-callout--critical keep-focus">
38
+ <i></i>
39
+ <div class="Vlt-callout__content">{{searchError}}</div>
40
+ </div>
41
+ </div>
42
+ <div *ngIf='!searchError && (suggestions.length || searchResults)' [ngClass]="{ suggestions: !searchResults}"
43
+ class="Vlt-dropdown__panel__content Vlt-dropdown__panel__content--scroll-area" style='padding: 0;'>
44
+ <div class="Vlt-dropdown__block"></div>
45
+ <div *ngIf='!searchResults' class="Vlt-dropdown__scroll">
46
+ <a href='#' [ngClass]="{ 'Vlt-dropdown__link--selected': activeSuggestionIndex === i, smart: suggestion.smart }" (click)='onSuggestionSelect($event, suggestion)' *ngFor='let suggestion of suggestions; let i = index' class="Vlt-dropdown__link has-type">
47
+ <svg class='Vlt-icon Vlt-icon--small'><use attr.xlink:href="volta/volta-brand-icons.svg#{{integrationIcon}}"/></svg>
48
+ <div class='__gu' [title]='suggestion.label'>{{ suggestion.label }}</div>
49
+ <small class='Vlt-grey-dark' style='text-transform: capitalize;'>{{suggestion.type}}</small>
50
+ </a>
51
+ </div>
52
+ <div *ngIf='searchResults' class="Vlt-dropdown__scroll">
53
+ <div *ngIf='!searchResults.length' class='Vlt-dropdown__block'> No records matching '<b style='pointer-events: none;'>{{searchText}}</b>' were found.</div>
54
+ <a href='#' [ngClass]="{ 'Vlt-dropdown__link--selected': activeSuggestionIndex === i }" (click)='onSuggestionSelect($event, suggestion)' *ngFor='let suggestion of searchResults; let i = index' class="Vlt-dropdown__link has-type">
55
+ <svg class='Vlt-icon Vlt-icon--small'><use attr.xlink:href="volta/volta-brand-icons.svg#{{integrationIcon}}"/></svg>
56
+ <div class='__gu' [title]='suggestion.label'>{{ suggestion.label }}</div>
57
+ <small class='Vlt-grey-dark' style='text-transform: capitalize;'>{{suggestion.type}}</small>
58
+ </a>
59
+ </div>
60
+ <!-- <div *ngIf='searchResults' class="Vlt-dropdown__block" style='text-align: right; padding-top: 0;'>
61
+ <small>
62
+ {{ searchResults ? searchResults.length+' results' : 'Suggestions' }} <span style='font-style: italic; font-weight: normal;' *ngIf='searchResults'>~{{ model ? 'last search' : searchText}}</span>
63
+ </small>
64
+ </div> -->
65
+ <div class="Vlt-dropdown__block"></div>
66
+ </div>
67
+ </div>
68
+ </div>
69
+ <div class="Vlt-composite__prepend"
70
+ *ngIf='isPolymorphic && showTypes && (multiple || !model || (dropdownVisible && ((suggestions || searchResults || []).length || searchResourceType.resourceType)))'>
71
+ <div class="search-scope" [ngClass]="{ 'has-value': searchResourceType.resourceType }">
72
+ <vgip-meta-field class='shown' [meta]='searchResourceTypeMeta' [parent]='searchResourceType'
73
+ (onChange)='onSearchResourceTypeChanged($event)' (onLeave)='onBlur($event)'
74
+ [integrationCode]='integrationCode' theme='inherit'></vgip-meta-field>
75
+ <svg class='Vlt-icon Vlt-grey Vlt-icon--smaller visible-mobile mobile-icon'
76
+ style='position: absolute; top: 15px; left: 14px; pointer-events: none;'>
77
+ <use xlink:href="volta/volta-icons.svg#Vlt-icon-menu" />
78
+ </svg>
79
+ </div>
80
+ </div>
81
+ <div *ngIf='!(isPolymorphic && showTypes && (multiple || !model || dropdownVisible))'>
82
+ <!-- required by css -->
83
+ </div>
84
+ <div class="Vlt-composite__wrapper Vlt-input" style='overflow: hidden;'
85
+ [ngClass]="{ 'has-append-button': hasAppendButton && !disabled, 'vgip-disable': disabled }">
86
+ <label class='wrapper'>
87
+ <div class="Vlt-composite__prepend Vlt-composite__prepend--icon" style='top: 0; padding-top: 15px;'>
88
+ <div class="Vlt-composite__icon">
89
+ <svg *ngIf='isSearchable && (!model || multiple)' class='Vlt-grey'>
90
+ <use attr.xlink:href="volta/volta-icons.svg#Vlt-icon-{{ multiple ? 'stack' : 'search'}}" />
91
+ </svg>
92
+ <svg *ngIf='!isSearchable || (model && !multiple)'
93
+ [ngStyle]="{fill: integrationIcon === 'Brand-icon-vonage' ? 'var(--vgip-meta-input-color)' : ''}">
94
+ <use attr.xlink:href="volta/volta-brand-icons.svg#{{integrationIcon}}" />
95
+ </svg>
96
+ </div>
97
+ <div *ngIf='suggestions.length' class="Vlt-badge Vlt-badge--small Vlt-badge--purple"
98
+ style='padding: 0px 4px; position: absolute; top: 26px; left: 4px; pointer-events: none; min-width: 14px;'>
99
+ {{suggestions.length}}</div>
100
+ </div>
101
+ <input class='model' type='hidden' [required]='validations.required' [(ngModel)]='model' #f='ngModel' [name]='name' />
102
+ <input class='main' [readonly]='!isSearchable || (model && !multiple)' [ngModel]='searchText' #ft='ngModel' (ngModelChange)='onSearchTextChanged($event)' [ngModelOptions]="{standalone: true}" type="text" placeholder="{{ placeHolderLabel || ' ' }}" [ngClass]='{ ext: externalLink }' (click)='onActivated($event)' (focus)='onActivated($event)' (blur)='onBlur($event)' [disabled]='disabled' [title]="model ? model.label : ''"/>
103
+ <label class='Vlt-truncate hidden-mobile' style='padding-left: 25px; padding-right: 42px;'>{{ (multiple && isPolymorphic) ? '+Add ' : ((model || !isPolymorphic) ? meta.label : ( meta.searchLabel || 'Search')) }}<span *ngIf='validations.required' class='Vlt-red'>*</span>&nbsp;<span style='color: var(--vgip-meta-input-color); text-transform: capitalize;' *ngIf='model'>({{model.type || model.resourceType || model.length}})</span></label> <!-- eslint-disable-line @angular-eslint/template/label-has-associated-control-->
104
+ <label class='Vlt-truncate hidden-desktop' style='padding-left: 25px; padding-right: 42px;'>{{meta.label || meta.name}}<span *ngIf='validations.required' class='Vlt-red'>*</span>&nbsp;<span style='color: var(--vgip-meta-input-color); text-transform: capitalize;' *ngIf='model'>({{model.type || model.resourceType || model.length}})</span></label> <!-- eslint-disable-line @angular-eslint/template/label-has-associated-control-->
105
+ </label>
106
+ <div *ngIf='searching' class='search-progress'>
107
+ <div class="container">
108
+ <div class="bar Vlt-bg-purple"></div>
109
+ </div>
110
+ </div>
111
+ <div class='Vlt-composite__append right-actions'>
112
+ <!-- <div *ngIf='prevModel && !model' class="Vlt-composite__append--icon" (click)='revert()'>
113
+ <div class="Vlt-composite__icon">
114
+ <svg><use xlink:href="volta/volta-icons.svg#Vlt-icon-reply"/></svg>
115
+ </div>
116
+ </div> -->
117
+ <a href='#' *ngIf='model && !multiple' class="Vlt-composite__append--icon" (click)='removeSelection($event)'>
118
+ <div class="Vlt-composite__icon">
119
+ <svg>
120
+ <use xlink:href="volta/volta-icons.svg#Vlt-icon-cross" />
121
+ </svg>
122
+ </div>
123
+ </a>
124
+ <a [href]='externalLink || model.externalLink' target='_blank' rel='noopener' *ngIf='externalLink && (model && !multiple)' class="Vlt-composite__append--icon" aria-label='Open external'>
125
+ <div class="Vlt-composite__icon">
126
+ <svg>
127
+ <use xlink:href="volta/volta-icons.svg#Vlt-icon-open" />
128
+ </svg>
129
+ </div>
130
+ </a>
131
+ </div>
132
+ </div>
133
+ <!-- <span *ngIf='hasCreatables'>
134
+ <button type='button' *ngIf='!model || multiple' (click)='openResource()' class="Vlt-btn Vlt-btn--secondary Vlt-btn--icon Vlt-btn--large" style='margin-left: 12px;'>
135
+ <svg><use xlink:href="volta/volta-icons.svg#Vlt-icon-plus"/></svg>
136
+ </button>
137
+ <button type='button' *ngIf='model && !multiple' (click)='openResource(model)' class="Vlt-btn Vlt-btn--primary Vlt-btn--icon Vlt-btn--large" style='margin-left: 12px;'>
138
+ <svg><use xlink:href="volta/volta-icons.svg#Vlt-icon-edit"/></svg>
139
+ </button>
140
+ </span> -->
141
+ <div *ngIf='hasAppendButton && !disabled' class="Vlt-composite__append">
142
+ <button (focus)='onActivated($event)' (blur)='onBlur($event)' type='button' *ngIf='!model || multiple'
143
+ (click)='openResource()' class="Vlt-btn Vlt-btn--white Vlt-btn--icon" aria-label='Add new' [disabled]='delegate'>
144
+ <svg>
145
+ <use xlink:href="volta/volta-icons.svg#Vlt-icon-plus" />
146
+ </svg>
147
+ </button>
148
+ <button (focus)='onActivated($event)' (blur)='onBlur($event)' type='button' *ngIf='model && !multiple'
149
+ (click)='openResource(model)' class="Vlt-btn Vlt-btn--white Vlt-btn--icon" aria-label='Edit' [disabled]='delegate'>
150
+ <svg>
151
+ <use xlink:href="volta/volta-icons.svg#Vlt-icon-edit" />
152
+ </svg>
153
+ </button>
154
+ </div>
155
+ </div>
156
+ <small *ngIf='f.invalid && ((f | metaModel)._parent.submitted || ((ft | metaModel).touched && keyListenerActive))'
157
+ class="Vlt-form__element__error">
158
+ <span *ngIf="f.errors.required">Required</span>
159
+ <span *ngIf="f.errors.pattern">Should match '{{validations.pattern}}' pattern</span>
160
+ <span *ngIf="f.errors.custom">{{f.errors.custom}}&nbsp;</span>
161
+ </small>
162
+ <small *ngIf='meta.helpText || meta.hint' class="Vlt-form__element__hint">{{meta.helpText || meta.hint}}</small>
163
+ </div>
@@ -0,0 +1,98 @@
1
+ /*
2
+ * @Author: Alexander.Vangelov@vonage.com
3
+ * @Date: 2019-09-19 17:35:13
4
+ * @Last Modified by: Alexander.Vangelov@vonage.com
5
+ * @Last Modified time: 2020-03-26 17:15:50
6
+ */
7
+
8
+ import { Component, OnInit } from '@angular/core';
9
+ import { ControlContainer, NgForm } from '@angular/forms';
10
+
11
+ // import { QUILL_CONFIG_TOKEN, QuillConfig } from 'ngx-quill';
12
+
13
+ import { FieldAbstract } from '../fieldAbstract';
14
+ // import { tMetaField } from '../../../metaTypes/tMetaField'
15
+ import { templateBuilder } from '../common/utils/templateBuilder';
16
+ import { MetaContextService } from '../services/metaContext';
17
+
18
+ // export const quillConfig = {
19
+ // modules: {
20
+ // syntax: false,
21
+ // toolbar: [
22
+ // ['bold', 'italic', 'underline'],
23
+ // [{ list: 'bullet' }],
24
+ // [{ header: [1, 2, 3, 4, 5, 6, false] }],
25
+ // [{ font: [] }],
26
+ // [{ align: [] }]
27
+ // ]
28
+ // }
29
+ // };
30
+
31
+ @Component({
32
+ templateUrl: './view.html',
33
+ styleUrls: [
34
+ './style.scss',
35
+ './quill.scss'
36
+ ],
37
+ viewProviders: [
38
+ { provide: ControlContainer, useExisting: NgForm },
39
+ // { provide: QUILL_CONFIG_TOKEN, useValue: quillConfig }
40
+ ],
41
+ standalone: false
42
+ })
43
+ export class FieldRichtext extends FieldAbstract implements OnInit {
44
+ // @Input() meta: any;
45
+ active: boolean;
46
+ quillConfigModules = {
47
+ syntax: false,
48
+ toolbar: [
49
+ ['bold', 'italic', 'underline'],
50
+ [{ list: 'bullet' }],
51
+ [{ header: [1, 2, 3, 4, 5, 6, false] }],
52
+ [{ font: [] }],
53
+ [{ align: [] }]
54
+ ]
55
+ };
56
+
57
+ constructor( private metaContext: MetaContextService ) {
58
+ super();
59
+ }
60
+
61
+ static setup(instance, parent, meta) {
62
+ const d = meta.default || meta.defaultValue;
63
+ if (d && !parent[meta.name]) {
64
+ if (typeof(d) === 'string') {
65
+ parent[meta.name] = d;
66
+ } else {
67
+ parent[meta.name] = d.id || d.value;
68
+ }
69
+ }
70
+ }
71
+
72
+ ngOnInit() {
73
+ if (typeof(this.parent[this.meta.name]) === 'string') {
74
+ this.parent[this.meta.name] = templateBuilder(this.metaContext, this.parent[this.meta.name]);
75
+ }
76
+ // if (this.default && !this.model) {
77
+ // setTimeout(()=>{
78
+ // if (typeof(this.default) == 'string') {
79
+ // this.parent[this.meta.name] = this.default;
80
+ // } else {
81
+ // this.parent[this.meta.name] = this.default.id || this.default.value;
82
+ // }
83
+ // }, 0);
84
+ // }
85
+ }
86
+
87
+ onModelChangeLocal(value) {
88
+ if (!value && this.prevModel && this.isPersistedParent) {
89
+ value = '';
90
+ }
91
+ this.onModelChange(value);
92
+ }
93
+
94
+ textToSpeech() {
95
+ this.focus();
96
+ }
97
+
98
+ }
@@ -0,0 +1,6 @@
1
+ @use "sass:meta";
2
+ :host ::ng-deep {
3
+ @include meta.load-css('quill/dist/quill.core');
4
+ @include meta.load-css('quill/dist/quill.bubble');
5
+ @include meta.load-css('quill/dist/quill.snow');
6
+ }
@@ -0,0 +1,87 @@
1
+ .Vlt-composite__append--icon {
2
+ bottom: 7px;
3
+ right: 16px;
4
+ padding: 3px;
5
+ width: initial;
6
+ height: initial;
7
+ cursor: pointer;
8
+ &:hover svg {
9
+ fill: #2c2d30;
10
+ }
11
+ }
12
+
13
+ .Vlt-form__element {
14
+ &.Vlt-form__element--error {
15
+ ::ng-deep .Vlt-textarea {
16
+ .ql-toolbar.ql-snow {
17
+ border-color: #f25a6b;
18
+ }
19
+ .ql-container.ql-snow {
20
+ // background: #fde8eb;
21
+ border-color: #f25a6b;
22
+ }
23
+ }
24
+ }
25
+ ::ng-deep quill-editor {
26
+ display: initial;
27
+ }
28
+ ::ng-deep .Vlt-textarea {
29
+ em {
30
+ font-style: italic;
31
+ }
32
+ .ql-toolbar.ql-snow {
33
+ border: 1px solid var(--vgip-meta-input-border-color);
34
+ border-top-left-radius: 5px;
35
+ border-top-right-radius: 5px;
36
+ border-bottom: 0;
37
+ background: var(--vgip-meta-input-accent-bg-color);
38
+ padding: 11px 8px;
39
+ @media only screen and (max-width: 575px) {
40
+ .ql-formats {
41
+ margin-right: 8px;
42
+ zoom: 84%;
43
+ }
44
+ }
45
+ button, .ql-picker-label {
46
+ color: var(--vgip-meta-input-label-color);
47
+ .ql-stroke {
48
+ stroke: var(--vgip-meta-input-label-color);
49
+ }
50
+ &:hover {
51
+ color: var(--vgip-meta-input-accent-color);
52
+ stroke: var(--vgip-meta-input-accent-color);
53
+ .ql-stroke {
54
+ stroke: var(--vgip-meta-input-accent-color);
55
+ }
56
+ }
57
+ }
58
+ }
59
+ .ql-container.ql-snow {
60
+ border-bottom-left-radius: 5px;
61
+ border-bottom-right-radius: 5px;
62
+ min-height: 48px;
63
+ background: var(--vgip-meta-input-bg-color);
64
+ border-color: var(--vgip-meta-input-border-color);
65
+ .ql-editor {
66
+ color: var(--vgip-meta-input-color) !important;
67
+ h1, h2, h3, h4, h5, h6 {
68
+ color: inherit;
69
+ }
70
+ p {
71
+ color: inherit;
72
+ }
73
+ @media (hover:none) { // fix zooming on iOS
74
+ font-size: 16px;
75
+ }
76
+ }
77
+ }
78
+ &:hover, &:focus, &.active {
79
+ .ql-toolbar, .ql-container {
80
+ border-color: var(--vgip-meta-input-active-border-color);
81
+ }
82
+ }
83
+ .ql-editor:focus {
84
+ border-color: var(--vgip-meta-input-active-border-color) !important;
85
+ }
86
+ }
87
+ }