@dile/crud 2.5.4 → 2.5.6

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.
@@ -219,6 +219,9 @@ export class DileCrudActions extends DileI18nMixin(LitElement) {
219
219
 
220
220
  doErrorAction(e) {
221
221
  this.loading = false;
222
+ if (this.confirmElement) {
223
+ this.confirmElement.resetProcessing();
224
+ }
222
225
  this.responseAdapter.setResponse(e.detail);
223
226
  this.selectedActionForm.showErrors(e.detail.errors);
224
227
  this.dispatchEvent(new CustomEvent('crud-action-error', {
@@ -238,6 +241,9 @@ export class DileCrudActions extends DileI18nMixin(LitElement) {
238
241
 
239
242
  cancelAction() {
240
243
  this.loading = false;
244
+ if (this.confirmElement) {
245
+ this.confirmElement.resetProcessing();
246
+ }
241
247
  this.selectedActionForm.clearErrors();
242
248
  this.selectedActionForm.resetData();
243
249
  }
@@ -0,0 +1,93 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import { CrudConfigBuilder } from '../../lib/CrudConfigBuilder.js';
3
+ import './crud.js';
4
+
5
+ describe('dile-crud initial filters', () => {
6
+ afterEach(() => {
7
+ document.body.innerHTML = '';
8
+ });
9
+
10
+ it('syncs active filters from config into the list and form on first render', async () => {
11
+ const config = new CrudConfigBuilder('https://example.test/api/countries', {
12
+ customization: {
13
+ disableInsert: true,
14
+ disableHelp: true,
15
+ disableKeywordSearch: true,
16
+ disableSort: true,
17
+ disableFilter: false,
18
+ disablePagination: true,
19
+ hideCheckboxSelection: true,
20
+ },
21
+ availableFilters: [
22
+ {
23
+ name: 'continent',
24
+ label: 'Continent',
25
+ active: true,
26
+ value: 'Europe',
27
+ type: 'select',
28
+ options: [
29
+ { value: 'Europe', label: 'Europe' },
30
+ { value: 'Asia', label: 'Asia' },
31
+ ],
32
+ },
33
+ ],
34
+ }).getConfig();
35
+
36
+ const el = document.createElement('dile-crud');
37
+ el.config = config;
38
+ document.body.appendChild(el);
39
+ await el.updateComplete;
40
+ await Promise.resolve();
41
+
42
+ expect(el.config.availableFilters[0].active).toBe(true);
43
+ expect(el.config.availableFilters[0].value).toBe('Europe');
44
+ expect(el.listElement.filters).toHaveLength(1);
45
+ expect(el.listElement.filters[0].name).toBe('continent');
46
+ expect(el.listElement.filters[0].value).toBe('Europe');
47
+
48
+ const form = el.shadowRoot.querySelector('dile-crud-filters');
49
+ expect(form.filters[0].active).toBe(true);
50
+ expect(form.filters[0].value).toBe('Europe');
51
+ });
52
+
53
+ it('removes an active initial filter when the chip close icon is clicked', async () => {
54
+ const config = new CrudConfigBuilder('https://example.test/api/countries', {
55
+ customization: {
56
+ disableInsert: true,
57
+ disableHelp: true,
58
+ disableKeywordSearch: true,
59
+ disableSort: true,
60
+ disableFilter: false,
61
+ disablePagination: true,
62
+ hideCheckboxSelection: true,
63
+ },
64
+ availableFilters: [
65
+ {
66
+ name: 'continent',
67
+ label: 'Continent',
68
+ active: true,
69
+ value: 'Europe',
70
+ type: 'select',
71
+ options: [
72
+ { value: 'Europe', label: 'Europe' },
73
+ { value: 'Asia', label: 'Asia' },
74
+ ],
75
+ },
76
+ ],
77
+ }).getConfig();
78
+
79
+ const el = document.createElement('dile-crud');
80
+ el.config = config;
81
+ document.body.appendChild(el);
82
+ await el.updateComplete;
83
+ await Promise.resolve();
84
+
85
+ const filterEl = el.shadowRoot.querySelector('dile-crud-filters');
86
+ filterEl.removeFilter('continent');
87
+
88
+ expect(filterEl.filters[0].active).toBe(false);
89
+ expect(filterEl.filters[0].value).toBe('');
90
+ expect(el.listElement.filters[0].active).toBe(false);
91
+ expect(el.listElement.filters[0].value).toBe('');
92
+ });
93
+ });
@@ -41,6 +41,20 @@ export class DileCrudList extends DileI18nMixin(DileLoading(LitElement)) {
41
41
  padding: var(--dile-crud-list-empty-padding, 3rem 1rem);
42
42
  text-align: var(--dile-crud-list-empty-text-align, center);
43
43
  }
44
+
45
+ .error {
46
+ padding: var(--dile-crud-list-error-padding, 3rem 1rem);
47
+ text-align: var(--dile-crud-list-error-text-align, center);
48
+ background-color: var(--dile-crud-list-error-background-color, #fff3cd);
49
+ border: var(--dile-crud-list-error-border, 1px solid #ffc107);
50
+ border-radius: var(--dile-crud-list-error-border-radius, 4px);
51
+ color: var(--dile-crud-list-error-color, #333);
52
+ }
53
+
54
+ .error p {
55
+ margin: 0 0 1rem 0;
56
+ font-size: var(--dile-crud-list-error-font-size, 1rem);
57
+ }
44
58
 
45
59
  @media(min-width: 500px) {
46
60
  .prev-summary {
@@ -74,6 +88,7 @@ export class DileCrudList extends DileI18nMixin(DileLoading(LitElement)) {
74
88
  belongsTo: { type: String },
75
89
  relationId: { type: String },
76
90
  disableLoadOnStart: { type: Boolean },
91
+ listError: { type: Object },
77
92
  };
78
93
  }
79
94
 
@@ -90,12 +105,19 @@ export class DileCrudList extends DileI18nMixin(DileLoading(LitElement)) {
90
105
  this.isSelectAllActive = false;
91
106
  this.loading = true;
92
107
  this.disableLoadOnStart = false;
108
+ this.listError = null;
93
109
  }
94
110
 
95
111
  firstUpdated() {
96
112
  this.pageSize = this.config.pageSize?.initial ?? this.pageSize;
97
113
  this.elservice = this.shadowRoot.getElementById('elservice');
98
114
  this.ajaxgetallids = this.shadowRoot.getElementById('ajaxgetallids');
115
+
116
+ const activeFilters = (this.config?.availableFilters || []).filter(filter => filter.active);
117
+ if (activeFilters.length > 0) {
118
+ this.filters = activeFilters;
119
+ }
120
+
99
121
  if(!this.disableLoadOnStart) {
100
122
  this.updateComplete.then( () => this.refresh());
101
123
  }
@@ -109,14 +131,16 @@ export class DileCrudList extends DileI18nMixin(DileLoading(LitElement)) {
109
131
 
110
132
  ${this.filterListTemplate}
111
133
 
112
- ${this.loading
113
- ? this.loadingTemplate
114
- : this.elements.length == 0
115
- ? this.emptyTemplate
116
- : html`
117
- ${this.elementsTemplate}
118
- ${this.config.customization?.hidePageReport ? '' : this.paginationTemplate}
119
- `
134
+ ${this.listError
135
+ ? this.errorTemplate
136
+ : this.loading
137
+ ? this.loadingTemplate
138
+ : this.elements.length == 0
139
+ ? this.emptyTemplate
140
+ : html`
141
+ ${this.elementsTemplate}
142
+ ${this.config.customization?.hidePageReport ? '' : this.paginationTemplate}
143
+ `
120
144
  }
121
145
  `;
122
146
  }
@@ -170,6 +194,7 @@ export class DileCrudList extends DileI18nMixin(DileLoading(LitElement)) {
170
194
  belongsTo=${this.belongsTo}
171
195
  relationId=${this.relationId}
172
196
  @crud-list-get-success=${this.getSuccess}
197
+ @crud-list-data-error=${this.onListError}
173
198
  language="${this.language}"
174
199
  ></dile-crud-list-service>
175
200
  <dile-ajax
@@ -200,6 +225,19 @@ export class DileCrudList extends DileI18nMixin(DileLoading(LitElement)) {
200
225
  `;
201
226
  }
202
227
 
228
+ get errorTemplate() {
229
+ return html`
230
+ <div class="error">
231
+ <p>${this.translations.list_load_error}</p>
232
+ <p>
233
+ <dile-button @click=${this.retryLoadList}>
234
+ ${this.translations.retry_label}
235
+ </dile-button>
236
+ </p>
237
+ </div>
238
+ `;
239
+ }
240
+
203
241
  insertLabelComputed(label, translations) {
204
242
  return label ? label : translations?.insert_label ? translations.insert_label : 'Insert';
205
243
  }
@@ -372,4 +410,14 @@ export class DileCrudList extends DileI18nMixin(DileLoading(LitElement)) {
372
410
  }
373
411
 
374
412
  }
413
+
414
+ onListError(e) {
415
+ this.loading = false;
416
+ this.listError = e.detail;
417
+ }
418
+
419
+ retryLoadList() {
420
+ this.listError = null;
421
+ this.refresh();
422
+ }
375
423
  }
@@ -35,30 +35,46 @@ export class DileCrudFilters extends DileI18nMixin(LitElement) {
35
35
  }
36
36
 
37
37
  removeFilter(filterName) {
38
- this.shadowRoot.getElementById('elform').resetField(filterName);
38
+ const form = this.shadowRoot.getElementById('elform');
39
+ if (form) {
40
+ form.clearField(filterName);
41
+ }
42
+
43
+ this.filters = this.filters.map(filter => {
44
+ if (filter.name === filterName) {
45
+ const isSelectType = filter.type === 'select' || filter.type === 'select_ajax';
46
+ this.setFilterValue(filter, isSelectType ? '' : false);
47
+ }
48
+ return filter;
49
+ });
50
+ this.dispatchFiltersChanged();
39
51
  }
40
52
 
41
53
  filtersChanged(e) {
42
- let data = e.detail.data;
54
+ const data = e.detail.data;
43
55
  this.filters = this.filters.map(filter => {
44
56
  if (filter.name in data) {
45
- switch(filter.type) {
46
- case 'select':
47
- case 'select_ajax':
48
- if(data[filter.name] === '') {
49
- filter.active = false;
50
- } else {
51
- filter.active = true;
52
- filter.value = data[filter.name];
53
- }
54
- break;
55
- default:
56
- filter.active = data[filter.name];
57
- filter.value = data[filter.name];
58
- }
57
+ this.setFilterValue(filter, data[filter.name]);
59
58
  }
60
59
  return filter;
61
60
  });
61
+ this.dispatchFiltersChanged();
62
+ }
63
+
64
+ setFilterValue(filter, value) {
65
+ switch (filter.type) {
66
+ case 'select':
67
+ case 'select_ajax':
68
+ filter.active = value !== '';
69
+ filter.value = value;
70
+ break;
71
+ default:
72
+ filter.active = value;
73
+ filter.value = value;
74
+ }
75
+ }
76
+
77
+ dispatchFiltersChanged() {
62
78
  this.dispatchEvent(new CustomEvent('filters-changed', {
63
79
  bubbles: true,
64
80
  composed: true,
@@ -43,11 +43,11 @@ export class DileCrudFiltersForm extends DileFormChangeDetect(DileForm(LitElemen
43
43
  switch (filter.type) {
44
44
  case 'select':
45
45
  return html`
46
- <dile-select label="${filter.label}" name="${filter.name}" value="">
46
+ <dile-select label="${filter.label}" name="${filter.name}" value="${filter.value ?? ''}">
47
47
  <select slot="select">
48
48
  <option value="">-</option>
49
49
  ${filter.options.map(option => html`
50
- <option value="${option.value}">${option.label}</option>
50
+ <option value="${option.value}" ?selected=${filter.value === option.value}>${option.label}</option>
51
51
  `)}
52
52
  </select>
53
53
  </dile-select>
package/lib/i18n/en.js CHANGED
@@ -70,4 +70,6 @@ export const translations = {
70
70
  confirm_submit_text: "Are you sure you want to submit this form?",
71
71
  add_relation_label: "Add",
72
72
  select_relation_placeholder: "Select...",
73
+ list_load_error: "Error loading the list. Please try again.",
74
+ retry_label: "Retry",
73
75
  };
package/lib/i18n/es.js CHANGED
@@ -70,4 +70,6 @@ export const translations = {
70
70
  confirm_submit_text: "¿Estás seguro de que deseas enviar este formulario?",
71
71
  add_relation_label: "Añadir",
72
72
  select_relation_placeholder: "Selecciona...",
73
+ list_load_error: "Error al cargar la lista. Por favor, intenta de nuevo.",
74
+ retry_label: "Reintentar",
73
75
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dile/crud",
3
- "version": "2.5.4",
3
+ "version": "2.5.6",
4
4
  "description": "Components to create a generic crud system based on Web Components and Lit",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -25,12 +25,12 @@
25
25
  },
26
26
  "homepage": "https://dile-components.com/",
27
27
  "dependencies": {
28
- "@dile/ui": "^3.6.5",
28
+ "@dile/ui": "^3.6.7",
29
29
  "axios": "^1.19.0",
30
30
  "lit": "^2.7.0 || ^3.0.0"
31
31
  },
32
32
  "publishConfig": {
33
33
  "access": "public"
34
34
  },
35
- "gitHead": "ee029c01956874746ff8c78f02f4868ef4ce4875"
35
+ "gitHead": "d62c55983a8fcdf7b1a4cb2b6da64d4d1e30b9c6"
36
36
  }