@iamproperty/components 7.6.4--beta7 → 7.6.4--beta8
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/assets/css/components/actionbar.component.css +1 -1
- package/assets/css/components/actionbar.component.css.map +1 -1
- package/assets/css/components/actionbar.global.css +1 -1
- package/assets/css/components/actionbar.global.css.map +1 -1
- package/assets/css/components/config.component.css +1 -0
- package/assets/css/components/config.component.css.map +1 -0
- package/assets/css/components/notification.css +1 -1
- package/assets/css/components/notification.css.map +1 -1
- package/assets/css/components/table-basic.global.css +1 -1
- package/assets/css/components/table-basic.global.css.map +1 -1
- package/assets/css/components/table.global.css +1 -1
- package/assets/css/components/table.global.css.map +1 -1
- package/assets/css/core.min.css +1 -1
- package/assets/css/core.min.css.map +1 -1
- package/assets/css/style.min.css +1 -1
- package/assets/css/style.min.css.map +1 -1
- package/assets/js/components/accordion/accordion.component.min.js +1 -1
- package/assets/js/components/actionbar/actionbar.component.js +7 -6
- package/assets/js/components/actionbar/actionbar.component.min.js +5 -5
- package/assets/js/components/actionbar/actionbar.component.min.js.map +1 -1
- package/assets/js/components/address-lookup/address-lookup.component.js +11 -1
- package/assets/js/components/address-lookup/address-lookup.component.min.js +3 -3
- package/assets/js/components/address-lookup/address-lookup.component.min.js.map +1 -1
- package/assets/js/components/advanced-select/advanced-select.component.min.js +1 -1
- package/assets/js/components/applied-filters/applied-filters.component.min.js +1 -1
- package/assets/js/components/barchart/barchart.component.min.js +1 -1
- package/assets/js/components/bento-grid/bento-grid.component.min.js +1 -1
- package/assets/js/components/calendar/calendar.component.min.js +1 -1
- package/assets/js/components/card/card.component.min.js +1 -1
- package/assets/js/components/carousel/carousel.component.min.js +1 -1
- package/assets/js/components/collapsible-side/collapsible-side.component.min.js +1 -1
- package/assets/js/components/config/config.component.js +532 -0
- package/assets/js/components/config/config.component.min.js +59 -0
- package/assets/js/components/config/config.component.min.js.map +1 -0
- package/assets/js/components/content/content.component.min.js +1 -1
- package/assets/js/components/darkmode/darkmode.component.min.js +1 -1
- package/assets/js/components/doughnutchart/doughnutchart.component.min.js +1 -1
- package/assets/js/components/fileupload/fileupload.component.min.js +1 -1
- package/assets/js/components/filter-card/filter-card.component.min.js +1 -1
- package/assets/js/components/filterlist/filterlist.component.min.js +1 -1
- package/assets/js/components/form/form.component.min.js +1 -1
- package/assets/js/components/header/header.component.min.js +1 -1
- package/assets/js/components/inline-edit/inline-edit.component.min.js +1 -1
- package/assets/js/components/input/input.component.min.js +1 -1
- package/assets/js/components/input-range/input-range.component.min.js +1 -1
- package/assets/js/components/marketing/marketing.component.min.js +1 -1
- package/assets/js/components/menu/menu.component.min.js +1 -1
- package/assets/js/components/milestone/milestone.component.min.js +1 -1
- package/assets/js/components/milestone-group/milestone-group.component.min.js +1 -1
- package/assets/js/components/modal/modal.component.min.js +1 -1
- package/assets/js/components/multi-step/multi-step.component.min.js +1 -1
- package/assets/js/components/multi-step-modal/multi-step-modal.component.min.js +1 -1
- package/assets/js/components/multiselect/multiselect.component.min.js +1 -1
- package/assets/js/components/nav/nav.component.min.js +1 -1
- package/assets/js/components/notification/notification.component.js +69 -30
- package/assets/js/components/notification/notification.component.min.js +5 -5
- package/assets/js/components/notification/notification.component.min.js.map +1 -1
- package/assets/js/components/pagination/pagination.component.min.js +1 -1
- package/assets/js/components/password/password.component.min.js +1 -1
- package/assets/js/components/popover/popover.component.min.js +1 -1
- package/assets/js/components/rank/rank.component.min.js +1 -1
- package/assets/js/components/rankings/rankings.component.min.js +1 -1
- package/assets/js/components/rating/rating.component.min.js +1 -1
- package/assets/js/components/record-card/record-card.component.min.js +1 -1
- package/assets/js/components/search/search.component.min.js +1 -1
- package/assets/js/components/slider/slider.component.min.js +1 -1
- package/assets/js/components/split-button/split-button.component.min.js +1 -1
- package/assets/js/components/std-address-lookup/std-address-lookup.component.min.js +4 -4
- package/assets/js/components/std-address-lookup/std-address-lookup.component.min.js.map +1 -1
- package/assets/js/components/table/table.component.min.js +2 -2
- package/assets/js/components/table-ajax/table-ajax.component.min.js +2 -2
- package/assets/js/components/table-basic/table-basic.component.min.js +2 -2
- package/assets/js/components/table-no-submit/table-no-submit.component.min.js +2 -2
- package/assets/js/components/table-submit/table-submit.component.min.js +2 -2
- package/assets/js/components/tabs/tabs.component.min.js +1 -1
- package/assets/js/components/tag/tag.component.min.js +1 -1
- package/assets/js/components/tooltip/tooltip.component.min.js +1 -1
- package/assets/js/components/video-card/video-card.component.min.js +1 -1
- package/assets/js/components/video-modal/video-modal.component.min.js +1 -1
- package/assets/js/components/word-count/word-count.component.min.js +1 -1
- package/assets/js/scripts.bundle.js +1 -1
- package/assets/js/scripts.bundle.min.js +1 -1
- package/assets/sass/components/actionbar.component.scss +13 -4
- package/assets/sass/components/actionbar.global.scss +8 -0
- package/assets/sass/components/config.component.scss +235 -0
- package/assets/sass/components/notification.scss +4 -14
- package/assets/sass/components/table-basic.global.scss +4 -4
- package/assets/sass/foundations/root.scss +0 -4
- package/assets/ts/components/actionbar/actionbar.component.ts +7 -6
- package/assets/ts/components/address-lookup/address-lookup.component.ts +16 -1
- package/assets/ts/components/config/config.component.ts +699 -0
- package/assets/ts/components/notification/notification.component.ts +98 -47
- package/assets/ts/components/std-address-lookup/std-address-lookup.component.ts +1 -0
- package/dist/components.es.js +28 -28
- package/dist/components.umd.js +273 -216
- package/package.json +1 -1
- package/src/components/Config/Config.vue +23 -0
|
@@ -0,0 +1,699 @@
|
|
|
1
|
+
import Cookies from '../../../../node_modules/js-cookie/dist/js.cookie.mjs';
|
|
2
|
+
import { trackComponent, trackComponentRegistered } from '../_global';
|
|
3
|
+
|
|
4
|
+
trackComponentRegistered('iam-config');
|
|
5
|
+
|
|
6
|
+
class iamConfig extends HTMLElement {
|
|
7
|
+
constructor() {
|
|
8
|
+
super();
|
|
9
|
+
this.attachShadow({ mode: 'open' });
|
|
10
|
+
|
|
11
|
+
const assetLocation = document.body.hasAttribute('data-assets-location')
|
|
12
|
+
? document.body.getAttribute('data-assets-location')
|
|
13
|
+
: '/assets';
|
|
14
|
+
|
|
15
|
+
const loadCSS = `@import "${assetLocation}/css/components/config.component.css";`;
|
|
16
|
+
|
|
17
|
+
const template = document.createElement('template');
|
|
18
|
+
|
|
19
|
+
template.innerHTML = /* HTML */ `
|
|
20
|
+
<style>
|
|
21
|
+
${loadCSS}
|
|
22
|
+
</style>
|
|
23
|
+
<div id="wrapper">
|
|
24
|
+
<div id="items">
|
|
25
|
+
<div id="buckets"></div>
|
|
26
|
+
<div id="any" data-bucket="any"></div>
|
|
27
|
+
</div>
|
|
28
|
+
<div class="admin-panel">
|
|
29
|
+
<button class="btn btn-action fa-plus" command="add-bucket">Add bucket</button>
|
|
30
|
+
<button class="btn btn-action fa-plus" command="add-item">Add ${this.getAttribute('data-item-name')??'item'}</button> <!-- Changes to open a model if we want to validate the add form first -->
|
|
31
|
+
|
|
32
|
+
</div>
|
|
33
|
+
<button id="save" class="btn btn-sm btn-primary fa-floppy-disk" >Save items</button>
|
|
34
|
+
</div>
|
|
35
|
+
`;
|
|
36
|
+
this.shadowRoot?.appendChild(template.content.cloneNode(true));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async importData(ajaxURL): void {
|
|
40
|
+
|
|
41
|
+
// Setup controller vars if not already set
|
|
42
|
+
if (!window.controller) window.controller = [];
|
|
43
|
+
|
|
44
|
+
// Abort if controller already present for this url
|
|
45
|
+
if (window.controller[ajaxURL]) window.controller[ajaxURL].abort();
|
|
46
|
+
|
|
47
|
+
// Create a new controller so it can be aborted if new fetch made
|
|
48
|
+
window.controller[ajaxURL] = new AbortController();
|
|
49
|
+
const { signal } = window.controller[ajaxURL];
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
return await fetch(ajaxURL, {
|
|
53
|
+
signal: signal,
|
|
54
|
+
method: 'get',
|
|
55
|
+
credentials: 'same-origin',
|
|
56
|
+
headers: new Headers({
|
|
57
|
+
'Content-Type': 'application/json',
|
|
58
|
+
Accept: 'application/json',
|
|
59
|
+
'X-Requested-With': 'XMLHttpRequest',
|
|
60
|
+
'X-XSRF-TOKEN': Cookies.get('XSRF-TOKEN'),
|
|
61
|
+
}),
|
|
62
|
+
})
|
|
63
|
+
.then((response) => response.json())
|
|
64
|
+
.then((response) => {
|
|
65
|
+
|
|
66
|
+
const returnData = response['data'] ? response['data'] : response;
|
|
67
|
+
|
|
68
|
+
return returnData;
|
|
69
|
+
});
|
|
70
|
+
} catch (error) {
|
|
71
|
+
//console.log(error);
|
|
72
|
+
return 'There has been a problem. Please try again in a few moments.';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
getBucketsData = (data): void => {
|
|
78
|
+
|
|
79
|
+
if(!data)
|
|
80
|
+
return [];
|
|
81
|
+
|
|
82
|
+
const buckets = [];
|
|
83
|
+
// TODO: check local storage first
|
|
84
|
+
data.forEach(bucket => {
|
|
85
|
+
|
|
86
|
+
if(typeof bucket.attributes?.criteria == "object" && Array.isArray(bucket.attributes?.criteria)){
|
|
87
|
+
|
|
88
|
+
buckets.push(bucket);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
return buckets;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
createBuckets = (buckets): void => {
|
|
96
|
+
|
|
97
|
+
console.log(buckets);
|
|
98
|
+
|
|
99
|
+
const bucketsContainer = this.shadowRoot.querySelector('#buckets'); // TODO: rename
|
|
100
|
+
|
|
101
|
+
if(!buckets)
|
|
102
|
+
return false;
|
|
103
|
+
|
|
104
|
+
buckets.forEach((bucket) => {
|
|
105
|
+
|
|
106
|
+
this.createBucket(bucket);
|
|
107
|
+
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
createBucket = (bucket): void => {
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
const bucketsContainer = this.shadowRoot.querySelector('#buckets'); // TODO: rename
|
|
117
|
+
|
|
118
|
+
const bucketElement = document.createElement('div');
|
|
119
|
+
bucketElement.innerHTML = this.addBucketHTML(bucket);
|
|
120
|
+
//bucketElement.setAttribute('data-bucket',bucket.id);
|
|
121
|
+
bucketElement.classList.add('bucket__wrapper');
|
|
122
|
+
|
|
123
|
+
bucketsContainer?.insertAdjacentElement('beforeend', bucketElement);
|
|
124
|
+
|
|
125
|
+
//this.addButtonEvents(bucketElement,true);
|
|
126
|
+
this.createEditBucketsEvents(bucketElement);
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
const criteriaContainer = bucketElement.querySelector('.criteria--container');
|
|
130
|
+
|
|
131
|
+
if(bucket.attributes){
|
|
132
|
+
bucket.attributes.criteria.forEach((criteria) => {
|
|
133
|
+
const criteriaForm = document.createElement('form');
|
|
134
|
+
criteriaForm.classList.add('criteria');
|
|
135
|
+
|
|
136
|
+
criteriaForm.innerHTML = this.addCriteriaHTML(criteria.attributes);
|
|
137
|
+
|
|
138
|
+
// TODO add to HTML
|
|
139
|
+
criteriaForm.querySelector('[name="attribute"]')?.value = criteria.attributes.attribute;
|
|
140
|
+
criteriaForm.querySelector('[name="rule"]')?.value = criteria.attributes.rule;
|
|
141
|
+
criteriaForm.querySelector('[name="match"]')?.value = criteria.attributes.match;
|
|
142
|
+
|
|
143
|
+
criteriaContainer?.appendChild(criteriaForm);
|
|
144
|
+
|
|
145
|
+
// TODO add buttons
|
|
146
|
+
// TODO add events
|
|
147
|
+
});
|
|
148
|
+
this.createForms(bucket.attributes.items, bucket.id);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
return bucketElement;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
addCriteriaHTML = (attributes): void => {
|
|
156
|
+
return /*HTML*/ `<label>
|
|
157
|
+
<span class="visually-hidden">Attribute</span>
|
|
158
|
+
${this.createCriteriaDropdown(attributes.attribute)}
|
|
159
|
+
</label>
|
|
160
|
+
<label>
|
|
161
|
+
<span class="visually-hidden">Rule</span>
|
|
162
|
+
<select name="rule" class="mt-0 select--sm">
|
|
163
|
+
<option value="set">is not empty</option>
|
|
164
|
+
<option value="empty">is empty</option>
|
|
165
|
+
<option value="equals">equals</option>
|
|
166
|
+
<option value="not">is not</option>
|
|
167
|
+
<option value="greater">greater than</option>
|
|
168
|
+
<option value="less">less than</option>
|
|
169
|
+
</select>
|
|
170
|
+
</label>
|
|
171
|
+
<label>
|
|
172
|
+
<span class="visually-hidden">Match</span>
|
|
173
|
+
<input type="text" name="match" class="mt-0 input--sm" /> <!-- TODO Add datalist or transform into select -->
|
|
174
|
+
</label>
|
|
175
|
+
<div class="btn__group">
|
|
176
|
+
<button class="btn btn-compact btn-sm mt-0 btn-secondary fa-plus" type="button" data-direction="add" title="Delete">Add</button>
|
|
177
|
+
<button class="btn btn-compact btn-sm mt-0 btn-secondary fa-trash" type="button" data-direction="delete" title="Delete">Delete</button>
|
|
178
|
+
</div>`;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
addBucketHTML = (bucket):void => {
|
|
182
|
+
|
|
183
|
+
return /*HTML*/ `<label>
|
|
184
|
+
<span class="visually-hidden">Name</span>
|
|
185
|
+
<input type="text" name="bucket" value="${bucket.attributes?.name ?? ''}"/>
|
|
186
|
+
</label>
|
|
187
|
+
<div class="btn__group text-end"><button class="btn btn-compact btn-sm mt-0 btn-secondary fa-pen-to-square" data-expand title="Expand to see more options">Edit</button>${this.buttonHTML}</div>
|
|
188
|
+
<div class="criteria--container">
|
|
189
|
+
</div>
|
|
190
|
+
<div data-bucket="${bucket.id ?? ''}" class="bucket">
|
|
191
|
+
</div>`;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
createCriteriaDropdown = (attribute):void => {
|
|
195
|
+
|
|
196
|
+
const form = this.querySelector('form');
|
|
197
|
+
|
|
198
|
+
const formData = new FormData(form);
|
|
199
|
+
const formDataObj = Object.fromEntries(formData.entries());
|
|
200
|
+
|
|
201
|
+
let optionsHtml = '';
|
|
202
|
+
Object.keys(formDataObj).forEach(function(key){
|
|
203
|
+
optionsHtml += `<option value="${key}" ${key == attribute ? ' selected="selected"' : ''}>${key}</option>`;
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
return `<select name="attributes[criteria]" class="mt-0 select--sm">
|
|
207
|
+
<option value=""></option>
|
|
208
|
+
${optionsHtml}
|
|
209
|
+
</select>`;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
createEditBucketsEvents = (bucket):Void => {
|
|
213
|
+
this.addButtonEvents(bucket,true);
|
|
214
|
+
const expandButton = bucket?.querySelector('[data-expand]');
|
|
215
|
+
|
|
216
|
+
expandButton?.addEventListener('click',() => {
|
|
217
|
+
|
|
218
|
+
bucket.classList.toggle('bucket--expanded');
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async importAttributeData(comonponent): void {
|
|
223
|
+
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
createForms = (data, bucketId = "any"):void => {
|
|
227
|
+
|
|
228
|
+
data.forEach(item => {
|
|
229
|
+
|
|
230
|
+
if(typeof item.attributes?.criteria == "undefined"){
|
|
231
|
+
|
|
232
|
+
const formElement = this.createForm(item, bucketId);
|
|
233
|
+
|
|
234
|
+
Object.keys(item.attributes).forEach(function(key){
|
|
235
|
+
|
|
236
|
+
if(formElement.querySelector(`[name="${key}"]`)){
|
|
237
|
+
|
|
238
|
+
const element = formElement.querySelector(`[name="${key}"]`);
|
|
239
|
+
|
|
240
|
+
if(element.matches('select[data-import]') && !element.querySelector(`option[value="${item.attributes[key]}"]`)){
|
|
241
|
+
const optionElement = document.createElement('option');
|
|
242
|
+
optionElement.value = item.attributes[key];
|
|
243
|
+
optionElement.innerHTML = item.attributes[key];
|
|
244
|
+
element.appendChild(optionElement);
|
|
245
|
+
}
|
|
246
|
+
element.value = item.attributes[key];
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
checkCriteria = (attributes, bucket):void => {
|
|
254
|
+
|
|
255
|
+
if(attributes[bucket])
|
|
256
|
+
return true;
|
|
257
|
+
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
checkBuckets = (attributes):any => {
|
|
262
|
+
|
|
263
|
+
const anyContainer = this.shadowRoot.querySelector('#any'); // TODO: rename
|
|
264
|
+
let container = anyContainer;
|
|
265
|
+
|
|
266
|
+
if(!this.hasAttribute('data-buckets'))
|
|
267
|
+
return container;
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
let buckets = [];
|
|
271
|
+
let addedToBucket = false;
|
|
272
|
+
|
|
273
|
+
// If data attribute set
|
|
274
|
+
buckets = this.getAttribute('data-buckets').split(',');
|
|
275
|
+
|
|
276
|
+
// TODO: If importing the config from a json file
|
|
277
|
+
|
|
278
|
+
buckets.forEach((bucket)=>{
|
|
279
|
+
|
|
280
|
+
const addToBucket = !addedToBucket ? this.checkCriteria(attributes, bucket) : false;
|
|
281
|
+
|
|
282
|
+
if(addToBucket){
|
|
283
|
+
addedToBucket = true;
|
|
284
|
+
container = this.shadowRoot.querySelector(`[data-bucket="${bucket}"]`);
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
return container;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
createForm = (item, bucketId = "any"):void => {
|
|
292
|
+
|
|
293
|
+
const anyContainer = this.shadowRoot.querySelector(`#items [data-bucket="${bucketId}"]`); // TODO: rename
|
|
294
|
+
//const bucketsContainer = this.shadowRoot.querySelector('#buckets'); // TODO: rename
|
|
295
|
+
//const container = this.checkBuckets(item.attributes); TODO: re-enable
|
|
296
|
+
const container = anyContainer;
|
|
297
|
+
|
|
298
|
+
const formElement = this.querySelector(`form`)?.cloneNode(true);
|
|
299
|
+
//formTemplate.setAttribute('id', item.id);
|
|
300
|
+
|
|
301
|
+
// TODO check if it matches a bucket
|
|
302
|
+
container?.insertAdjacentElement('beforeend',formElement);
|
|
303
|
+
//const formElement = container?.querySelector(`[id="${item.id}"]`);
|
|
304
|
+
formElement?.addEventListener('submit', (event) => {
|
|
305
|
+
|
|
306
|
+
event.preventDefault();
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
this.addButtons(formElement);
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
return formElement;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
getCurrentIds = ():void => {
|
|
316
|
+
|
|
317
|
+
const idsArr = [];
|
|
318
|
+
|
|
319
|
+
Array.from(this.shadowRoot?.querySelectorAll('#items form')).forEach((form) => {
|
|
320
|
+
idsArr.push(parseInt(form.getAttribute('id')));
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
return idsArr;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
generateId = ():any => {
|
|
327
|
+
|
|
328
|
+
return Math.max(...this.getCurrentIds()) + 1;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
addButtonEvents = (element, scrollIntoView:boolean = true):void => {
|
|
332
|
+
|
|
333
|
+
const upButton = element?.querySelector('[data-direction="up"]');
|
|
334
|
+
const downButton = element?.querySelector('[data-direction="down"]');
|
|
335
|
+
const deleteButton = element?.querySelector('[data-direction="delete"]');
|
|
336
|
+
|
|
337
|
+
upButton?.addEventListener('click',() => {
|
|
338
|
+
|
|
339
|
+
if(element?.previousElementSibling){
|
|
340
|
+
element?.parentNode.insertBefore(element, element.previousElementSibling);
|
|
341
|
+
|
|
342
|
+
if(scrollIntoView)
|
|
343
|
+
element?.scrollIntoView({ behavior: "instant", block: "center" });
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
downButton?.addEventListener('click',() => {
|
|
348
|
+
|
|
349
|
+
if(element.nextElementSibling){
|
|
350
|
+
element?.parentNode.insertBefore(element, element.nextElementSibling.nextElementSibling);
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
element?.parentNode.insertAdjacentElement('beforeend',element);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if(scrollIntoView)
|
|
357
|
+
element?.scrollIntoView({ behavior: "instant", block: "center" });
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
deleteButton?.addEventListener('click',() => {
|
|
361
|
+
|
|
362
|
+
element.remove();
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
addButtons = (form):void => {
|
|
367
|
+
|
|
368
|
+
form?.insertAdjacentHTML('beforeend',`<div class="btn__group">${this.buttonHTML}</div>`);
|
|
369
|
+
|
|
370
|
+
this.addButtonEvents(form);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
async connectedCallback(): void {
|
|
374
|
+
this.buttonHTML = /* HTML */`
|
|
375
|
+
<button class="btn btn-compact btn-sm mt-0 btn-secondary fa-trash" type="button" data-direction="delete" title="Delete">Delete</button>
|
|
376
|
+
<button class="btn btn-compact btn-sm mt-0 btn-secondary fa-chevron-down" type="button" data-direction="down" title="Move down">Down</button>
|
|
377
|
+
<button class="btn btn-compact btn-sm mt-0 btn-secondary fa-chevron-up" type="button" data-direction="up" title="Move up">Up</button>
|
|
378
|
+
`;
|
|
379
|
+
|
|
380
|
+
const dataImportUrl = this.getAttribute('data-import');
|
|
381
|
+
const getBucketsData = this.getBucketsData;
|
|
382
|
+
const createBuckets = this.createBuckets;
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
const createForms = this.createForms;
|
|
386
|
+
const createForm = this.createForm;
|
|
387
|
+
const itemsContainer = this.shadowRoot.querySelector('#items'); // TODO: rename
|
|
388
|
+
const anyContainer = this.shadowRoot.querySelector('#any'); // TODO: rename
|
|
389
|
+
const bucketsContainer = this.shadowRoot.querySelector('#buckets'); // TODO: rename
|
|
390
|
+
|
|
391
|
+
const editBuckets = this.shadowRoot.querySelector('#editBuckets'); // TODO: rename
|
|
392
|
+
|
|
393
|
+
const saveButton = this.shadowRoot.querySelector('#save');
|
|
394
|
+
const addButton = this.shadowRoot?.querySelector('[data-add-item]')
|
|
395
|
+
const addForm = this.shadowRoot?.querySelector('#addForm');
|
|
396
|
+
|
|
397
|
+
const editBucketsDialog = this.shadowRoot?.querySelector('#editBucketsDialog');
|
|
398
|
+
const editBucketsForm = this.shadowRoot?.querySelector('#editBucketsForm');
|
|
399
|
+
const editBucketsFormSubmit = this.shadowRoot?.querySelector('#editBucketsForm .btn-primary');
|
|
400
|
+
const addBucketButton = this?.shadowRoot.querySelector('[command="add-bucket"]');
|
|
401
|
+
const addItemButton = this?.shadowRoot.querySelector('[command="add-item"]');
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
const templateForm = this?.querySelector('form');
|
|
405
|
+
|
|
406
|
+
let editBucketsOriginalState = '';
|
|
407
|
+
|
|
408
|
+
let buckets = [];
|
|
409
|
+
|
|
410
|
+
// Prevent the template form from submitting anything
|
|
411
|
+
templateForm?.addEventListener('submit', (event) => {
|
|
412
|
+
|
|
413
|
+
event.preventDefault();
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
// TODO: add this to an on change event on the select
|
|
418
|
+
Array.from(this.querySelectorAll('select[data-import]')).forEach(async(select) =>{
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
const ajaxURL = select.getAttribute('data-import');
|
|
422
|
+
|
|
423
|
+
this.importData(ajaxURL).then(
|
|
424
|
+
(data) => {
|
|
425
|
+
if(typeof data == 'string')
|
|
426
|
+
return data;
|
|
427
|
+
|
|
428
|
+
data.forEach(item =>{
|
|
429
|
+
|
|
430
|
+
const optionElement = document.createElement('option');
|
|
431
|
+
optionElement.value = item.id;
|
|
432
|
+
optionElement.innerHTML = item.attributes.name;
|
|
433
|
+
select.appendChild(optionElement);
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
return true;
|
|
437
|
+
}
|
|
438
|
+
);
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
// #region import data
|
|
445
|
+
// TODO load from web storage if its newer
|
|
446
|
+
|
|
447
|
+
const storedData = localStorage.getItem(`config-${this.getAttribute('data-name')}`);
|
|
448
|
+
//const buckets = this.getBucketsData(); // TODO: load from local storage
|
|
449
|
+
|
|
450
|
+
if(storedData){
|
|
451
|
+
|
|
452
|
+
//createForms(JSON.parse(storedData), buckets);
|
|
453
|
+
}
|
|
454
|
+
else if(dataImportUrl){
|
|
455
|
+
|
|
456
|
+
const dataImport = await this.importData(dataImportUrl).then(
|
|
457
|
+
(data) => {
|
|
458
|
+
if(typeof data == 'string')
|
|
459
|
+
return data;
|
|
460
|
+
|
|
461
|
+
const buckets = getBucketsData(data);
|
|
462
|
+
|
|
463
|
+
if(buckets){
|
|
464
|
+
|
|
465
|
+
createBuckets(buckets);
|
|
466
|
+
}
|
|
467
|
+
createForms(data); // any bucket
|
|
468
|
+
|
|
469
|
+
return true;
|
|
470
|
+
}
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
// #endregion
|
|
474
|
+
|
|
475
|
+
// #region Add buckets to edit modal
|
|
476
|
+
/*
|
|
477
|
+
editBucketsForm?.addEventListener('submit', (event) => {
|
|
478
|
+
|
|
479
|
+
event.stopPropagation();
|
|
480
|
+
event.preventDefault();
|
|
481
|
+
|
|
482
|
+
if(event.submitter == editBucketsFormSubmit){
|
|
483
|
+
|
|
484
|
+
// Clear what is there already
|
|
485
|
+
//anyContainer?.innerHTML = '';
|
|
486
|
+
|
|
487
|
+
Array.from(itemsContainer?.querySelectorAll('form')).forEach((formElement:HTMLElement, index):void => {
|
|
488
|
+
|
|
489
|
+
anyContainer?.insertAdjacentElement('beforeend',formElement);
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
// Empty the buckets
|
|
493
|
+
bucketsContainer?.innerHTML = '';
|
|
494
|
+
|
|
495
|
+
// Load the new bucket data then recreate them
|
|
496
|
+
const buckets = [];
|
|
497
|
+
Array.from(editBuckets?.querySelectorAll('[data-bucket]')).forEach((editBucketElement:HTMLElement, index):void => {
|
|
498
|
+
|
|
499
|
+
bucketsContainer?.insertAdjacentHTML('beforeend',`<div class="bucket" data-bucket="${editBucketElement.getAttribute('data-bucket')}"></div>`);
|
|
500
|
+
|
|
501
|
+
const bucket = {}
|
|
502
|
+
|
|
503
|
+
bucket.id = editBucketElement.getAttribute('data-bucket');
|
|
504
|
+
bucket.attributes = {};
|
|
505
|
+
|
|
506
|
+
bucket.attributes.name = editBucketElement.querySelector('[name="bucket"]')?.value;
|
|
507
|
+
|
|
508
|
+
//const formData = new FormData(editBucketElement);
|
|
509
|
+
//const formDataObj = Object.fromEntries(formData.entries());
|
|
510
|
+
// TODO cycle through the criteria forms
|
|
511
|
+
|
|
512
|
+
buckets.push(bucket);
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
console.log(buckets);
|
|
517
|
+
// this.createBuckets(buckets); TODO: re-enable
|
|
518
|
+
|
|
519
|
+
/*
|
|
520
|
+
// Move items back into buckets
|
|
521
|
+
Array.from(itemsContainer?.querySelectorAll('form')).forEach((formElement:HTMLElement, index):void => {
|
|
522
|
+
|
|
523
|
+
const formData = new FormData(formElement);
|
|
524
|
+
const formDataObj = Object.fromEntries(formData.entries());
|
|
525
|
+
const newContainer = this.checkBuckets(formDataObj);
|
|
526
|
+
|
|
527
|
+
if(newContainer != anyContainer){
|
|
528
|
+
newContainer?.insertAdjacentElement('beforeend',formElement);
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
editBucketsOriginalState = editBuckets.innerHTML;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
editBucketsDialog?.close();
|
|
537
|
+
});
|
|
538
|
+
*/
|
|
539
|
+
/*
|
|
540
|
+
|
|
541
|
+
addBucketButton?.addEventListener('click', (event) => {
|
|
542
|
+
|
|
543
|
+
const editBucket = document.createElement('div');
|
|
544
|
+
editBucket.classList.add('bucket--edit');
|
|
545
|
+
editBucket.innerHTML = this.addBucketHTML();
|
|
546
|
+
|
|
547
|
+
editBuckets?.insertAdjacentElement('beforeend', editBucket)
|
|
548
|
+
|
|
549
|
+
this.addButtonEvents(editBucket,false);
|
|
550
|
+
const expandButton = editBucket?.querySelector('[data-expand]');
|
|
551
|
+
|
|
552
|
+
expandButton?.addEventListener('click',() => {
|
|
553
|
+
|
|
554
|
+
editBucket.classList.toggle('bucket--expanded');
|
|
555
|
+
});
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
*/
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
// #endregion
|
|
563
|
+
|
|
564
|
+
// #region add data
|
|
565
|
+
|
|
566
|
+
addItemButton?.addEventListener("click", (event) => {
|
|
567
|
+
|
|
568
|
+
const form = this.createForm({});
|
|
569
|
+
form?.scrollIntoView({ behavior: "instant", block: "center" });
|
|
570
|
+
// TODO scroll into view
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
addBucketButton?.addEventListener("click", (event) => {
|
|
574
|
+
|
|
575
|
+
const bucket = this.createBucket({});
|
|
576
|
+
bucket?.scrollIntoView({ behavior: "instant", block: "center" });
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
// #endregion
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
// #region update values
|
|
583
|
+
|
|
584
|
+
this.shadowRoot.addEventListener('change', (event) => {
|
|
585
|
+
|
|
586
|
+
const container = event.target.closest('[data-bucket]');
|
|
587
|
+
|
|
588
|
+
if(!container)
|
|
589
|
+
return false;
|
|
590
|
+
|
|
591
|
+
const attribute = event.target.name;
|
|
592
|
+
const value = event.target.value;
|
|
593
|
+
const attributes = {};
|
|
594
|
+
attributes[attribute] = value;
|
|
595
|
+
const newContainer = this.checkBuckets(attributes);
|
|
596
|
+
|
|
597
|
+
if(newContainer != container){
|
|
598
|
+
const form = event.target.closest(`form`);
|
|
599
|
+
// TODO a confirmation modal
|
|
600
|
+
newContainer?.insertAdjacentElement('beforeend',form);
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
form?.scrollIntoView({ behavior: "instant", block: "center" });
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
});
|
|
607
|
+
// #endregion
|
|
608
|
+
|
|
609
|
+
// #region save data
|
|
610
|
+
saveButton?.addEventListener('click', (event) => {
|
|
611
|
+
|
|
612
|
+
event.preventDefault();
|
|
613
|
+
|
|
614
|
+
// TODO validation
|
|
615
|
+
|
|
616
|
+
const entries = [];
|
|
617
|
+
|
|
618
|
+
// Save buckets data
|
|
619
|
+
Array.from(itemsContainer?.querySelectorAll('.bucket__wrapper')).forEach((bucketElement:HTMLElement, index):void => {
|
|
620
|
+
|
|
621
|
+
const bucket = {};
|
|
622
|
+
bucket.attributes = {};
|
|
623
|
+
bucket.id = bucketElement?.querySelector('[name="bucket"]').value;
|
|
624
|
+
bucket.type = 'bucket';
|
|
625
|
+
bucket.attributes.index = index;
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
const criteria = [];
|
|
629
|
+
// TODO populate criteria
|
|
630
|
+
Array.from(bucketElement?.querySelectorAll('.criteria--container form')).forEach((formElement:HTMLElement, criteriaIndex):void => {
|
|
631
|
+
|
|
632
|
+
const item = {};
|
|
633
|
+
//item.id = formElement.getAttribute('id');
|
|
634
|
+
item.type = 'criteria';
|
|
635
|
+
item.index = criteriaIndex;
|
|
636
|
+
const formData = new FormData(formElement);
|
|
637
|
+
const formDataObj = Object.fromEntries(formData.entries());
|
|
638
|
+
|
|
639
|
+
item.attributes = formDataObj;
|
|
640
|
+
|
|
641
|
+
criteria.push(item);
|
|
642
|
+
});
|
|
643
|
+
bucket.attributes.criteria = criteria;
|
|
644
|
+
|
|
645
|
+
const items = [];
|
|
646
|
+
Array.from(bucketElement?.querySelectorAll('[data-bucket] form')).forEach((formElement:HTMLElement, itemIndex):void => {
|
|
647
|
+
|
|
648
|
+
const item = {};
|
|
649
|
+
//item.id = formElement.getAttribute('id');
|
|
650
|
+
item.type = 'item';
|
|
651
|
+
item.index = itemIndex;
|
|
652
|
+
const formData = new FormData(formElement);
|
|
653
|
+
const formDataObj = Object.fromEntries(formData.entries());
|
|
654
|
+
|
|
655
|
+
item.attributes = formDataObj;
|
|
656
|
+
|
|
657
|
+
items.push(item);
|
|
658
|
+
});
|
|
659
|
+
bucket.attributes.items = items;
|
|
660
|
+
|
|
661
|
+
entries.push(bucket);
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
Array.from(itemsContainer?.querySelectorAll('[data-bucket="any"] form')).forEach((formElement:HTMLElement, index):void => {
|
|
666
|
+
|
|
667
|
+
const entry = {};
|
|
668
|
+
//entry.id = formElement.getAttribute('id');
|
|
669
|
+
entry.type = 'item';
|
|
670
|
+
entry.index = index;
|
|
671
|
+
const formData = new FormData(formElement);
|
|
672
|
+
const formDataObj = Object.fromEntries(formData.entries());
|
|
673
|
+
|
|
674
|
+
entry.attributes = formDataObj;
|
|
675
|
+
|
|
676
|
+
entries.push(entry);
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
const entriesJson = JSON.stringify(entries);
|
|
680
|
+
|
|
681
|
+
console.log(entries);
|
|
682
|
+
|
|
683
|
+
// TODO add toast message
|
|
684
|
+
// TODO save locally for now but when pushing to endpoint the web storage file should get deleted
|
|
685
|
+
|
|
686
|
+
//localStorage.setItem(`config-${this.getAttribute('data-name')}`, entriesJson);
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
//const bucketsJson = JSON.stringify(buckets);
|
|
691
|
+
|
|
692
|
+
//localStorage.setItem(`config-buckets-${this.getAttribute('data-name')}`, bucketsJson);
|
|
693
|
+
|
|
694
|
+
});
|
|
695
|
+
// #endregion
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
export default iamConfig;
|