@unicef-polymer/etools-form-builder 1.0.2 → 2.0.0-rc.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 (55) hide show
  1. package/dist/form-attachments-popup/form-attachments-popup.d.ts +10 -2
  2. package/dist/form-attachments-popup/form-attachments-popup.js +5 -0
  3. package/dist/form-attachments-popup/form-attachments-popup.tpl.d.ts +0 -5
  4. package/dist/form-attachments-popup/form-attachments-popup.tpl.js +0 -5
  5. package/dist/form-fields/abstract-field-base.class.d.ts +28 -0
  6. package/dist/form-fields/{base-field.js → abstract-field-base.class.js} +64 -38
  7. package/dist/form-fields/custom-elements.define.js +17 -5
  8. package/dist/form-fields/field-renderer-component.d.ts +20 -0
  9. package/dist/form-fields/field-renderer-component.js +245 -0
  10. package/dist/form-fields/index.d.ts +9 -5
  11. package/dist/form-fields/index.js +9 -5
  12. package/dist/form-fields/repeatable-fields/repeatable-attachment-field.d.ts +17 -0
  13. package/dist/form-fields/repeatable-fields/repeatable-attachment-field.js +198 -0
  14. package/dist/form-fields/repeatable-fields/repeatable-base-field.d.ts +20 -0
  15. package/dist/form-fields/repeatable-fields/repeatable-base-field.js +123 -0
  16. package/dist/form-fields/repeatable-fields/repeatable-number-field.d.ts +10 -0
  17. package/dist/form-fields/repeatable-fields/repeatable-number-field.js +56 -0
  18. package/dist/form-fields/repeatable-fields/repeatable-scale-field.d.ts +15 -0
  19. package/dist/form-fields/repeatable-fields/repeatable-scale-field.js +104 -0
  20. package/dist/form-fields/repeatable-fields/repeatable-text-field.d.ts +8 -0
  21. package/dist/form-fields/repeatable-fields/repeatable-text-field.js +43 -0
  22. package/dist/form-fields/single-fields/attachment-field.d.ts +16 -0
  23. package/dist/form-fields/single-fields/attachment-field.js +87 -0
  24. package/dist/form-fields/single-fields/base-field.d.ts +11 -0
  25. package/dist/form-fields/single-fields/base-field.js +57 -0
  26. package/dist/form-fields/single-fields/boolean-field.d.ts +8 -0
  27. package/dist/form-fields/single-fields/boolean-field.js +39 -0
  28. package/dist/form-fields/{number-field.d.ts → single-fields/number-field.d.ts} +1 -0
  29. package/dist/form-fields/{number-field.js → single-fields/number-field.js} +15 -2
  30. package/dist/form-fields/{scale-field.d.ts → single-fields/scale-field.d.ts} +4 -2
  31. package/dist/form-fields/{scale-field.js → single-fields/scale-field.js} +14 -2
  32. package/dist/form-fields/{text-field.d.ts → single-fields/text-field.d.ts} +0 -0
  33. package/dist/form-fields/{text-field.js → single-fields/text-field.js} +6 -1
  34. package/dist/form-groups/form-abstract-group.d.ts +12 -12
  35. package/dist/form-groups/form-abstract-group.js +133 -110
  36. package/dist/form-groups/form-card.d.ts +1 -0
  37. package/dist/form-groups/form-card.js +25 -0
  38. package/dist/form-groups/form-collapsed-card.d.ts +3 -1
  39. package/dist/form-groups/form-collapsed-card.js +24 -4
  40. package/dist/index.d.ts +1 -1
  41. package/dist/index.js +6 -1
  42. package/dist/lib/additional-components/confirmation-dialog.d.ts +16 -0
  43. package/dist/lib/additional-components/confirmation-dialog.js +61 -0
  44. package/dist/lib/additional-components/etools-fb-card.js +8 -1
  45. package/dist/lib/styles/attachments.styles.js +5 -2
  46. package/dist/lib/styles/form-builder-card.styles.js +8 -3
  47. package/dist/lib/styles/page-layout-styles.js +1 -1
  48. package/dist/lib/types/form-builder.interfaces.d.ts +2 -2
  49. package/dist/lib/types/form-builder.types.d.ts +8 -2
  50. package/dist/lib/utils/validations.helper.d.ts +3 -3
  51. package/dist/lib/utils/validations.helper.js +7 -7
  52. package/package.json +3 -2
  53. package/dist/form-fields/base-field.d.ts +0 -20
  54. package/dist/form-fields/wide-field.d.ts +0 -11
  55. package/dist/form-fields/wide-field.js +0 -51
@@ -5,10 +5,9 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { LitElement, property, html, css } from 'lit-element';
8
- import '../form-fields/text-field';
9
- import '../form-fields/number-field';
10
- import '../form-fields/scale-field';
11
- import '../form-fields/wide-field';
8
+ import '../form-fields/single-fields/text-field';
9
+ import '../form-fields/single-fields/number-field';
10
+ import '../form-fields/single-fields/scale-field';
12
11
  import '@polymer/paper-input/paper-textarea';
13
12
  import { SharedStyles } from '../lib/styles/shared-styles';
14
13
  import { pageLayoutStyles } from '../lib/styles/page-layout-styles';
@@ -18,6 +17,8 @@ import { FlexLayoutClasses } from '../lib/styles/flex-layout-classes';
18
17
  import { FormBuilderCardStyles } from '..';
19
18
  import { fireEvent } from '../lib/utils/fire-custom-event';
20
19
  import { clone } from 'ramda';
20
+ import { live } from 'lit-html/directives/live';
21
+ import { openDialog } from '../lib/utils/dialog';
21
22
  export var FieldTypes;
22
23
  (function (FieldTypes) {
23
24
  FieldTypes["FILE_TYPE"] = "file";
@@ -41,7 +42,7 @@ export class FormAbstractGroup extends LitElement {
41
42
  constructor() {
42
43
  super(...arguments);
43
44
  this.parentGroupName = '';
44
- this.readonly = true;
45
+ this.readonly = false;
45
46
  this._errors = {};
46
47
  this._value = {};
47
48
  this.computedPath = [];
@@ -87,120 +88,68 @@ export class FormAbstractGroup extends LitElement {
87
88
  return this.renderField(child);
88
89
  case 'group':
89
90
  return this.renderGroup(child);
91
+ case 'information':
92
+ return this.renderInformation(child);
90
93
  default:
91
94
  console.warn(`FormBuilderGroup: Unknown group type ${type}. Please, specify rendering method`);
92
95
  return html ``;
93
96
  }
94
97
  }
95
98
  renderField(blueprintField) {
96
- const isWide = blueprintField.styling.includes(StructureTypes.WIDE);
97
- const isAdditional = blueprintField.styling.includes(StructureTypes.ADDITIONAL);
98
- if (isWide) {
99
- return html `
100
- <div class="${isAdditional ? 'additional-field' : ''}">${this.renderWideField(blueprintField)}</div>
101
- `;
102
- }
103
- else {
104
- return html `
105
- <div class="${isAdditional ? 'additional-field finding-container' : 'finding-container'}">
106
- ${this.renderStandardField(blueprintField)}
107
- </div>
108
- `;
109
- }
110
- }
111
- renderWideField({ name, label, placeholder, required, validations }) {
99
+ var _a;
112
100
  return html `
113
- <wide-field
114
- ?is-readonly="${this.readonly}"
115
- ?required="${required}"
116
- .value="${this.value && this.value[name]}"
117
- label="${label}"
118
- placeholder="${placeholder}"
119
- .validators="${validations.map((validation) => this.metadata.validations[validation])}"
120
- .errorMessage="${this.getErrorMessage(name)}"
121
- @value-changed="${(event) => this.valueChanged(event, name)}"
122
- @error-changed="${(event) => this.errorChanged(event, name)}"
123
- ></wide-field>
101
+ <field-renderer
102
+ .field="${blueprintField}"
103
+ ?readonly="${live(this.readonly)}"
104
+ .value="${this.value && this.value[blueprintField.name]}"
105
+ .validations="${blueprintField.validations.map((validation) => this.metadata.validations[validation])}"
106
+ .errorMessage="${this.getErrorMessage(blueprintField.name)}"
107
+ .options="${((_a = this.metadata.options[blueprintField.options_key || '']) === null || _a === void 0 ? void 0 : _a.values) || []}"
108
+ .computedPath="${this.computedPath.concat(this.groupStructure.name === 'root' ? [blueprintField.name] : [this.groupStructure.name, blueprintField.name])}"
109
+ @value-changed="${(event) => this.valueChanged(event, blueprintField.name)}"
110
+ @error-changed="${(event) => this.errorChanged(event, blueprintField.name)}"
111
+ ></field-renderer>
124
112
  `;
125
113
  }
126
- renderStandardField({ input_type, name, label, help_text, options_key, required, validations }) {
127
- var _a;
128
- switch (input_type) {
129
- case FieldTypes.TEXT_TYPE:
130
- return html `
131
- <text-field
132
- ?is-readonly="${this.readonly}"
133
- ?required="${required}"
134
- .value="${this.value && this.value[name]}"
135
- .validators="${validations.map((validation) => this.metadata.validations[validation])}"
136
- .errorMessage="${this.getErrorMessage(name)}"
137
- @value-changed="${(event) => this.valueChanged(event, name)}"
138
- @error-changed="${(event) => this.errorChanged(event, name)}"
139
- >
140
- ${this.renderFieldLabel(label, help_text)}
141
- </text-field>
142
- `;
143
- case FieldTypes.NUMBER_TYPE:
144
- case FieldTypes.NUMBER_FLOAT_TYPE:
145
- case FieldTypes.NUMBER_INTEGER_TYPE:
146
- return html `
147
- <number-field
148
- ?is-readonly="${this.readonly}"
149
- ?required="${required}"
150
- .value="${this.value && this.value[name]}"
151
- .validators="${validations.map((validation) => this.metadata.validations[validation])}"
152
- .errorMessage="${this.getErrorMessage(name)}"
153
- @value-changed="${(event) => this.valueChanged(event, name)}"
154
- @error-changed="${(event) => this.errorChanged(event, name)}"
155
- >
156
- ${this.renderFieldLabel(label, help_text)}
157
- </number-field>
158
- `;
159
- case FieldTypes.BOOL_TYPE:
160
- case FieldTypes.SCALE_TYPE:
161
- return html `
162
- <scale-field
163
- .options="${((_a = this.metadata.options[options_key || '']) === null || _a === void 0 ? void 0 : _a.values) || []}"
164
- ?is-readonly="${this.readonly}"
165
- ?required="${required}"
166
- .value="${this.value && this.value[name]}"
167
- .validators="${validations.map((validation) => this.metadata.validations[validation])}"
168
- .errorMessage="${this.getErrorMessage(name)}"
169
- @value-changed="${(event) => this.valueChanged(event, name)}"
170
- @error-changed="${(event) => this.errorChanged(event, name)}"
171
- >
172
- ${this.renderFieldLabel(label, help_text)}
173
- </scale-field>
174
- `;
175
- default:
176
- console.warn(`FormBuilderGroup: Unknown field type: ${input_type}`);
177
- return html ``;
178
- }
114
+ renderInformation(information) {
115
+ return html `<section class="elevation page-content" elevation="1">${information.text}</section>`;
179
116
  }
180
- renderFieldLabel(label, helperText) {
117
+ renderGroup(groupStructure) {
118
+ if (!groupStructure.repeatable) {
119
+ return this.getGroupTemplate(groupStructure);
120
+ }
121
+ const value = (this.value && this.value[groupStructure.name]) || [{}];
181
122
  return html `
182
- <div class="layout vertical question-container">
183
- <div class="question-text">${label}</div>
184
- <div class="question-details">${helperText}</div>
185
- </div>
123
+ ${value.map((_, index) => this.getGroupTemplate(groupStructure, index))}
124
+ <paper-button class="add-group save-button" @click="${() => this.addGroup(groupStructure.name)}">
125
+ Add ${!groupStructure.title || groupStructure.title.length > 15 ? 'group' : groupStructure.title}
126
+ </paper-button>
186
127
  `;
187
128
  }
188
- renderGroup(groupStructure) {
129
+ getGroupTemplate(groupStructure, index) {
189
130
  const isAbstract = groupStructure.styling.includes(StructureTypes.ABSTRACT);
190
131
  const isCard = groupStructure.styling.includes(StructureTypes.CARD);
191
132
  const isCollapsed = groupStructure.styling.includes(StructureTypes.COLLAPSED);
133
+ let value = this.value && this.value[groupStructure.name];
134
+ if (typeof index === 'number') {
135
+ value = value && value[index];
136
+ }
137
+ let errors = this._errors[groupStructure.name];
138
+ if (typeof index === 'number') {
139
+ errors = errors && errors[index];
140
+ }
192
141
  if (isAbstract) {
193
142
  return html `
194
143
  <form-abstract-group
195
144
  .groupStructure="${groupStructure}"
196
- .value="${this.value && this.value[groupStructure.name]}"
145
+ .value="${value}"
197
146
  .metadata="${this.metadata}"
198
147
  .parentGroupName="${this.groupStructure.name}"
199
148
  .computedPath="${this.computedPath.concat(this.groupStructure.name === 'root' ? [] : [this.groupStructure.name])}"
200
149
  .readonly="${this.readonly}"
201
- .errors="${this._errors[groupStructure.name] || null}"
202
- @value-changed="${(event) => this.valueChanged(event, groupStructure.name)}"
203
- @error-changed="${(event) => this.errorChanged(event, groupStructure.name)}"
150
+ .errors="${errors || null}"
151
+ @value-changed="${(event) => this.valueChanged(event, groupStructure.name, index)}"
152
+ @error-changed="${(event) => this.errorChanged(event, groupStructure.name, index)}"
204
153
  ></form-abstract-group>
205
154
  `;
206
155
  }
@@ -208,14 +157,15 @@ export class FormAbstractGroup extends LitElement {
208
157
  return html `
209
158
  <form-collapsed-card
210
159
  .groupStructure="${groupStructure}"
211
- .value="${this.value && this.value[groupStructure.name]}"
160
+ .value="${value}"
212
161
  .metadata="${this.metadata}"
213
162
  .parentGroupName="${this.groupStructure.name}"
214
163
  .computedPath="${this.computedPath.concat(this.groupStructure.name === 'root' ? [] : [this.groupStructure.name])}"
215
164
  .readonly="${this.readonly}"
216
- .errors="${this._errors[groupStructure.name] || null}"
217
- @value-changed="${(event) => this.valueChanged(event, groupStructure.name)}"
218
- @error-changed="${(event) => this.errorChanged(event, groupStructure.name)}"
165
+ .errors="${errors || null}"
166
+ @remove-group="${() => this.removeGroup(groupStructure, index)}"
167
+ @value-changed="${(event) => this.valueChanged(event, groupStructure.name, index)}"
168
+ @error-changed="${(event) => this.errorChanged(event, groupStructure.name, index)}"
219
169
  ></form-collapsed-card>
220
170
  `;
221
171
  }
@@ -223,14 +173,15 @@ export class FormAbstractGroup extends LitElement {
223
173
  return html `
224
174
  <form-card
225
175
  .groupStructure="${groupStructure}"
226
- .value="${this.value && this.value[groupStructure.name]}"
176
+ .value="${value}"
227
177
  .metadata="${this.metadata}"
228
178
  .parentGroupName="${this.groupStructure.name}"
229
179
  .computedPath="${this.computedPath.concat(this.groupStructure.name === 'root' ? [] : [this.groupStructure.name])}"
230
180
  .readonly="${this.readonly}"
231
- .errors="${this._errors[groupStructure.name] || null}"
232
- @value-changed="${(event) => this.valueChanged(event, groupStructure.name)}"
233
- @error-changed="${(event) => this.errorChanged(event, groupStructure.name)}"
181
+ .errors="${errors || null}"
182
+ @remove-group="${() => this.removeGroup(groupStructure, index)}"
183
+ @value-changed="${(event) => this.valueChanged(event, groupStructure.name, index)}"
184
+ @error-changed="${(event) => this.errorChanged(event, groupStructure.name, index)}"
234
185
  ></form-card>
235
186
  `;
236
187
  }
@@ -239,18 +190,33 @@ export class FormAbstractGroup extends LitElement {
239
190
  return html ``;
240
191
  }
241
192
  }
242
- valueChanged(event, name) {
193
+ valueChanged(event, name, index) {
243
194
  if (!this.value) {
244
195
  this.value = {};
245
196
  }
246
- this.value[name] = event.detail.value;
247
- event.stopPropagation();
197
+ if (typeof index === 'number') {
198
+ const value = this.value[name] || [];
199
+ value[index] = event.detail.value;
200
+ this.value[name] = value;
201
+ }
202
+ else {
203
+ this.value[name] = event.detail.value;
204
+ }
205
+ if (event.stopPropagation) {
206
+ event.stopPropagation();
207
+ }
248
208
  fireEvent(this, 'value-changed', { value: this.value });
249
209
  this.requestUpdate();
250
210
  }
251
- errorChanged(event, name) {
211
+ errorChanged(event, name, index) {
252
212
  const errorMessage = event.detail.error;
253
- if (errorMessage) {
213
+ if (typeof index === 'number') {
214
+ const errors = this._errors[name] || (this.value && new Array(this.value[name].length).fill(null)) || [];
215
+ errors.splice(index, 1, errorMessage);
216
+ const hasErrors = errors.some((error) => error !== null);
217
+ this._errors[name] = hasErrors ? errors : null;
218
+ }
219
+ else if (errorMessage) {
254
220
  this._errors[name] = errorMessage;
255
221
  }
256
222
  else {
@@ -260,6 +226,30 @@ export class FormAbstractGroup extends LitElement {
260
226
  const errors = Object.keys(this._errors).length ? this._errors : null;
261
227
  fireEvent(this, 'error-changed', { error: errors });
262
228
  }
229
+ addGroup(name) {
230
+ const value = this.value[name] || [];
231
+ value.push({});
232
+ this.valueChanged({ detail: { value } }, name);
233
+ }
234
+ removeGroup(group, index) {
235
+ if (typeof index !== 'number') {
236
+ return;
237
+ }
238
+ const value = (this.value && this.value[group.name]) || [];
239
+ if (group.required && value.length < 2) {
240
+ openDialog({
241
+ dialog: 'confirmation-popup',
242
+ dialogData: {
243
+ text: `Group is required. At least one group must exist`,
244
+ hideConfirmBtn: true,
245
+ dialogTitle: ''
246
+ }
247
+ });
248
+ return;
249
+ }
250
+ value.splice(index, 1);
251
+ this.valueChanged({ detail: { value } }, group.name);
252
+ }
263
253
  getErrorMessage(fieldName) {
264
254
  const error = this._errors && this._errors[fieldName];
265
255
  return Array.isArray(error) ? error[0] : error || null;
@@ -274,12 +264,41 @@ export class FormAbstractGroup extends LitElement {
274
264
  FlexLayoutClasses,
275
265
  FormBuilderCardStyles,
276
266
  css `
267
+ :host {
268
+ display: flex;
269
+ flex-direction: column;
270
+ }
271
+ .add-group {
272
+ align-self: flex-end;
273
+ margin-right: 23px;
274
+ margin-top: 20px;
275
+ box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12),
276
+ 0 2px 4px -1px rgba(0, 0, 0, 0.4);
277
+ }
278
+ .card-header {
279
+ display: flex;
280
+ align-items: center;
281
+ justify-content: space-between;
282
+ }
283
+ .card-header .remove-group {
284
+ display: flex;
285
+ align-items: center;
286
+ justify-content: flex-end;
287
+ padding: 0 10px 8px;
288
+ cursor: pointer;
289
+ width: min-content;
290
+ white-space: nowrap;
291
+ }
292
+ .card-header .title {
293
+ padding: 0 24px 8px;
294
+ font-size: 18px;
295
+ font-weight: bold;
296
+ }
277
297
  .save-button {
278
298
  margin-top: 8px;
279
299
  color: var(--primary-background-color);
280
300
  background-color: var(--primary-color);
281
301
  }
282
-
283
302
  .information-source {
284
303
  padding: 0.5% 2% 0.5% 1%;
285
304
  }
@@ -302,6 +321,10 @@ export class FormAbstractGroup extends LitElement {
302
321
  .attachments-warning {
303
322
  color: red;
304
323
  }
324
+ paper-icon-button[icon='close'] {
325
+ cursor: pointer;
326
+ color: var(--primary-text-color);
327
+ }
305
328
  `
306
329
  ];
307
330
  }
@@ -316,7 +339,7 @@ __decorate([
316
339
  property({ type: String })
317
340
  ], FormAbstractGroup.prototype, "parentGroupName", void 0);
318
341
  __decorate([
319
- property({ type: Boolean, attribute: 'readonly', reflect: true })
342
+ property({ type: Boolean, attribute: 'readonly' })
320
343
  ], FormAbstractGroup.prototype, "readonly", void 0);
321
344
  __decorate([
322
345
  property()
@@ -28,4 +28,5 @@ export declare class FormCard extends FormAbstractGroup implements IFormBuilderC
28
28
  */
29
29
  valueChanged(event: CustomEvent, name: string): void;
30
30
  saveChanges(): void;
31
+ confirmRemove(groupName: string): void;
31
32
  }
@@ -9,6 +9,7 @@ import { fireEvent } from '../lib/utils/fire-custom-event';
9
9
  import { clone, equals } from 'ramda';
10
10
  import { FormAbstractGroup } from './form-abstract-group';
11
11
  import '@polymer/iron-collapse';
12
+ import { openDialog } from '../lib/utils/dialog';
12
13
  export class FormCard extends FormAbstractGroup {
13
14
  constructor() {
14
15
  super(...arguments);
@@ -40,6 +41,18 @@ export class FormCard extends FormAbstractGroup {
40
41
  render() {
41
42
  return html `
42
43
  <section class="elevation page-content card-container form-card" elevation="1">
44
+ <div class="card-header">
45
+ <div class="title">${this.groupStructure.title}</div>
46
+ <div
47
+ class="remove-group"
48
+ ?hidden="${!this.groupStructure.repeatable}"
49
+ @click="${() => this.confirmRemove(this.groupStructure.title || 'this group')}"
50
+ >
51
+ Remove
52
+ ${!this.groupStructure.title || this.groupStructure.title.length > 15 ? 'group' : this.groupStructure.title}
53
+ <paper-icon-button icon="delete" class="attachments-warning"></paper-icon-button>
54
+ </div>
55
+ </div>
43
56
  ${super.render()}
44
57
 
45
58
  <iron-collapse ?opened="${this.showSaveButton}">
@@ -70,6 +83,18 @@ export class FormCard extends FormAbstractGroup {
70
83
  fireEvent(this, 'value-changed', { value: this.value });
71
84
  this.showSaveButton = false;
72
85
  }
86
+ confirmRemove(groupName) {
87
+ openDialog({
88
+ dialog: 'confirmation-popup',
89
+ dialogData: {
90
+ text: `Are you sure you want to delete ${groupName}`
91
+ }
92
+ }).then((response) => {
93
+ if (response.confirmed) {
94
+ fireEvent(this, 'remove-group');
95
+ }
96
+ });
97
+ }
73
98
  }
74
99
  __decorate([
75
100
  property()
@@ -3,6 +3,7 @@ import { IFormBuilderCard, IFormBuilderCollapsedCard } from '../lib/types/form-b
3
3
  import { FormAbstractGroup } from './form-abstract-group';
4
4
  import '../lib/additional-components/etools-fb-card';
5
5
  import { GenericObject } from '../lib/types/global.types';
6
+ import '../lib/additional-components/confirmation-dialog';
6
7
  export declare class FormCollapsedCard extends FormAbstractGroup implements IFormBuilderCollapsedCard, IFormBuilderCard {
7
8
  /**
8
9
  * Overrides readonly property
@@ -38,7 +39,7 @@ export declare class FormCollapsedCard extends FormAbstractGroup implements IFor
38
39
  * Filters StructureTypes.ATTACHMENTS_BUTTON type. It will be rendered as button,
39
40
  * allows parent renderChild method to render other types
40
41
  */
41
- renderGroupChildren(): TemplateResult[];
42
+ renderGroupChildren(): (TemplateResult | TemplateResult[])[];
42
43
  /**
43
44
  * Generate open Attachments popup button.
44
45
  * It is hidden if tab is readonly and no attachments uploaded
@@ -64,5 +65,6 @@ export declare class FormCollapsedCard extends FormAbstractGroup implements IFor
64
65
  * In this case it will take only attachments changes and ignore other changes that may happen during card edit
65
66
  */
66
67
  openAttachmentsPopup(): void;
68
+ confirmRemove(groupName: string): void;
67
69
  protected getAttachmentsBtnText(attachmentsCount?: number): string;
68
70
  }
@@ -10,6 +10,7 @@ import { fireEvent } from '../lib/utils/fire-custom-event';
10
10
  import { openDialog } from '../lib/utils/dialog';
11
11
  import { FormAbstractGroup, StructureTypes } from './form-abstract-group';
12
12
  import '../lib/additional-components/etools-fb-card';
13
+ import '../lib/additional-components/confirmation-dialog';
13
14
  const PARTNER_KEY = 'partner';
14
15
  const OUTPUT_KEY = 'output';
15
16
  const INTERVENTION_KEY = 'intervention';
@@ -72,7 +73,7 @@ export class FormCollapsedCard extends FormAbstractGroup {
72
73
  return html `
73
74
  <section class="elevation page-content card-container" elevation="1">
74
75
  <etools-fb-card
75
- card-title="${this.retrieveTitle(this.parentGroupName) + ': ' + this.groupStructure.title}"
76
+ card-title="${this.retrieveTitle(this.parentGroupName) + this.groupStructure.title}"
76
77
  is-collapsible
77
78
  ?is-editable="${!this._readonly}"
78
79
  ?edit="${this.isEditMode}"
@@ -82,6 +83,13 @@ export class FormCollapsedCard extends FormAbstractGroup {
82
83
  >
83
84
  <!-- Open Attachments popup button -->
84
85
  <div slot="actions" class="layout horizontal center">${this.getAdditionalButtons()}</div>
86
+ <div slot="postfix" class="layout horizontal center" ?hidden="${!this.groupStructure.repeatable}">
87
+ <paper-icon-button
88
+ icon="close"
89
+ class="attachments-warning"
90
+ @click="${() => this.confirmRemove(this.groupStructure.title || 'this group')}"
91
+ ></paper-icon-button>
92
+ </div>
85
93
  <div slot="content">${this.renderGroupChildren()}</div>
86
94
  </etools-fb-card>
87
95
  </section>
@@ -117,11 +125,11 @@ export class FormCollapsedCard extends FormAbstractGroup {
117
125
  retrieveTitle(target) {
118
126
  switch (target) {
119
127
  case PARTNER_KEY:
120
- return `Partner`;
128
+ return `Partner: `;
121
129
  case OUTPUT_KEY:
122
- return `Output`;
130
+ return `Output: `;
123
131
  case INTERVENTION_KEY:
124
- return `PD/SSFA`;
132
+ return `PD/SSFA: `;
125
133
  default:
126
134
  return '';
127
135
  }
@@ -206,6 +214,18 @@ export class FormCollapsedCard extends FormAbstractGroup {
206
214
  this.requestUpdate();
207
215
  });
208
216
  }
217
+ confirmRemove(groupName) {
218
+ openDialog({
219
+ dialog: 'confirmation-popup',
220
+ dialogData: {
221
+ text: `Are you sure you want to delete ${groupName}`
222
+ }
223
+ }).then((response) => {
224
+ if (response.confirmed) {
225
+ fireEvent(this, 'remove-group');
226
+ }
227
+ });
228
+ }
209
229
  getAttachmentsBtnText(attachmentsCount = 0) {
210
230
  if (attachmentsCount === 1) {
211
231
  return `${attachmentsCount} File`;
package/dist/index.d.ts CHANGED
@@ -11,4 +11,4 @@ import './form-groups/custom-elements.define';
11
11
  * Form field elements
12
12
  */
13
13
  import './form-fields/custom-elements.define';
14
- export * from './form-fields/base-field';
14
+ export * from './form-fields/single-fields/base-field';
package/dist/index.js CHANGED
@@ -11,9 +11,14 @@ import './form-groups/custom-elements.define';
11
11
  * Form field elements
12
12
  */
13
13
  import './form-fields/custom-elements.define';
14
- export * from './form-fields/base-field';
14
+ export * from './form-fields/single-fields/base-field';
15
15
  /**
16
16
  * Attachments Popup
17
17
  */
18
18
  import { FormAttachmentsPopup } from './form-attachments-popup';
19
19
  window.customElements.define('form-attachments-popup', FormAttachmentsPopup);
20
+ /**
21
+ * Confirmation Popup
22
+ */
23
+ import { ConfirmationDialog } from './lib/additional-components/confirmation-dialog';
24
+ window.customElements.define('confirmation-popup', ConfirmationDialog);
@@ -0,0 +1,16 @@
1
+ import { LitElement, CSSResultArray } from 'lit-element';
2
+ export declare class ConfirmationDialog extends LitElement {
3
+ dialogOpened: boolean;
4
+ text: string;
5
+ dialogTitle: string;
6
+ hideConfirmBtn: boolean;
7
+ set dialogData({ text, dialogTitle, hideConfirmBtn }: {
8
+ text: string;
9
+ dialogTitle: string;
10
+ hideConfirmBtn: boolean;
11
+ });
12
+ render(): unknown;
13
+ onClose(): void;
14
+ confirm(): void;
15
+ static get styles(): CSSResultArray;
16
+ }
@@ -0,0 +1,61 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { LitElement, property, html, css } from 'lit-element';
8
+ import { fireEvent } from '../utils/fire-custom-event';
9
+ export class ConfirmationDialog extends LitElement {
10
+ constructor() {
11
+ super(...arguments);
12
+ this.dialogOpened = true;
13
+ this.text = '';
14
+ this.dialogTitle = '';
15
+ this.hideConfirmBtn = false;
16
+ }
17
+ set dialogData({ text, dialogTitle = 'Are you', hideConfirmBtn = false }) {
18
+ this.text = text;
19
+ this.dialogTitle = dialogTitle;
20
+ this.hideConfirmBtn = hideConfirmBtn;
21
+ this.requestUpdate();
22
+ }
23
+ render() {
24
+ return html `
25
+ <etools-dialog
26
+ id="confirmation-dialog"
27
+ size="md"
28
+ no-padding
29
+ keep-dialog-open
30
+ ?hide-confirm-btn="${this.hideConfirmBtn}"
31
+ cancel-btn-text="${this.hideConfirmBtn ? 'Ok' : 'Cancel'}"
32
+ ?opened="${this.dialogOpened}"
33
+ theme="confirmation"
34
+ dialog-title="${this.dialogTitle}"
35
+ @close="${this.onClose}"
36
+ @confirm-btn-clicked="${() => this.confirm()}"
37
+ >
38
+ <div class="confirmation-message">${this.text}</div>
39
+ </etools-dialog>
40
+ `;
41
+ }
42
+ onClose() {
43
+ fireEvent(this, 'response', { confirmed: false });
44
+ }
45
+ confirm() {
46
+ fireEvent(this, 'response', { confirmed: true });
47
+ }
48
+ static get styles() {
49
+ // language=CSS
50
+ return [
51
+ css `
52
+ .confirmation-message {
53
+ padding-left: 24px;
54
+ }
55
+ `
56
+ ];
57
+ }
58
+ }
59
+ __decorate([
60
+ property()
61
+ ], ConfirmationDialog.prototype, "dialogOpened", void 0);
@@ -83,6 +83,9 @@ let EtoolsFbCard = class EtoolsFbCard extends LitElement {
83
83
  display: flex;
84
84
  flex-basis: auto;
85
85
  }
86
+ .flex-header__postfix {
87
+ order: 3;
88
+ }
86
89
  .flex-header__edit {
87
90
  order: 2;
88
91
  }
@@ -111,6 +114,9 @@ let EtoolsFbCard = class EtoolsFbCard extends LitElement {
111
114
  border-top: 1px solid lightgrey;
112
115
  justify-content: flex-end;
113
116
  }
117
+ .flex-header__postfix {
118
+ order: 3;
119
+ }
114
120
  .flex-header__edit {
115
121
  order: 1;
116
122
  flex-basis: 20%;
@@ -151,6 +157,7 @@ let EtoolsFbCard = class EtoolsFbCard extends LitElement {
151
157
  `
152
158
  : ''}
153
159
  <div class="flex-header__title">${this.cardTitle}</div>
160
+ <div class="flex-header__actions"><slot name="actions"></slot></div>
154
161
  <div class="layout horizontal center flex-header__edit">
155
162
  ${this.isEditable
156
163
  ? html `
@@ -164,7 +171,7 @@ let EtoolsFbCard = class EtoolsFbCard extends LitElement {
164
171
  `
165
172
  : ''}
166
173
  </div>
167
- <div class="flex-header__actions"><slot name="actions"></slot></div>
174
+ <div class="flex-header__postfix"><slot name="postfix"></slot></div>
168
175
  </header>
169
176
  <iron-collapse ?opened="${!this.collapsed}">
170
177
  <section class="card-content-block">
@@ -11,11 +11,14 @@ export const AttachmentsStyles = css `
11
11
  display: flex;
12
12
  align-items: center;
13
13
  border-bottom: 1px solid var(--secondary-text-color, rgba(0, 0, 0, 0.54));
14
- margin: 0 14px;
14
+ margin: 0 14px 0 0;
15
15
  min-width: 145px;
16
16
  overflow-wrap: break-word;
17
17
  font-size: 16px;
18
18
  }
19
+ :host([is-readonly]) .filename-container {
20
+ border-bottom-color: transparent;
21
+ }
19
22
  .filename {
20
23
  overflow: hidden;
21
24
  text-overflow: ellipsis;
@@ -63,7 +66,7 @@ export const AttachmentsStyles = css `
63
66
  margin-top: 15px;
64
67
  }
65
68
  etools-upload-multi.with-padding {
66
- padding: 12px 9px;
69
+ padding: 12px 9px 12px 0;
67
70
  box-sizing: border-box;
68
71
  }
69
72
  `;