sf-crud 13.2.56 → 13.2.58

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.
@@ -972,6 +972,7 @@ class TableroService {
972
972
  read: undefined,
973
973
  update: undefined,
974
974
  delete: undefined,
975
+ refresh: undefined,
975
976
  });
976
977
  _loading = signal({ inProgress: false, target: undefined });
977
978
  searchTimeout = null;
@@ -1161,7 +1162,6 @@ class TableroService {
1161
1162
  return endpoint;
1162
1163
  }
1163
1164
  serializeFilterValue(value) {
1164
- console.log('Serializing filter value:', value);
1165
1165
  if (value === null || value === undefined) {
1166
1166
  return '';
1167
1167
  }
@@ -1185,6 +1185,7 @@ class TableroService {
1185
1185
  const items = [];
1186
1186
  const buttons = { ...this._btn() };
1187
1187
  buttons.create = config.opciones.find((x) => x.label == 'Crear');
1188
+ buttons.refresh = config.opciones.find((x) => x.label == 'Refrescar');
1188
1189
  config.opciones
1189
1190
  .filter((opc) => opc.valor.action)
1190
1191
  .forEach((opc) => {
@@ -1293,6 +1294,10 @@ class TableroService {
1293
1294
  this.getInfoTablero();
1294
1295
  }, 400);
1295
1296
  }
1297
+ refresh() {
1298
+ this._currentPage.set(1);
1299
+ this.getInfoTablero();
1300
+ }
1296
1301
  destroy() {
1297
1302
  if (this.searchTimeout) {
1298
1303
  clearTimeout(this.searchTimeout);
@@ -1314,6 +1319,7 @@ class TableroService {
1314
1319
  read: undefined,
1315
1320
  update: undefined,
1316
1321
  delete: undefined,
1322
+ refresh: undefined,
1317
1323
  });
1318
1324
  this._loading.set({ inProgress: false, target: undefined });
1319
1325
  this._config.set(null);
@@ -1380,11 +1386,11 @@ class TableroHeaderComponent {
1380
1386
  this.searchChange.emit(value);
1381
1387
  }
1382
1388
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TableroHeaderComponent, deps: [{ token: TableroService }], target: i0.ɵɵFactoryTarget.Component });
1383
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: TableroHeaderComponent, isStandalone: true, selector: "lib-tablero-header", inputs: { disabled: "disabled" }, outputs: { searchChange: "searchChange" }, ngImport: i0, template: "<div class=\"flex align-items-center justify-content-between flex-wrap lg:flex-row w-full\">\r\n <div class=\"flex justify-content-between align-items-center w-full lg:w-auto\">\r\n <h5 class=\"m-0\">{{ config?.label }}</h5>\r\n <p-button *ngIf=\"btn.create\" [label]=\"btn.create.label\" [icon]=\"btn.create.icon\" severity=\"success\"\r\n (click)=\"tableroService.showAddDialog()\" class=\"inline-flex lg:hidden\"></p-button>\r\n </div>\r\n <div class=\"flex align-items-center gap-2 pt-2 lg:pt-0 w-full lg:w-auto\">\r\n <p-iconfield styleClass=\"w-full\">\r\n <p-inputicon styleClass=\"pi pi-search\" />\r\n <input type=\"text\" pInputText\r\n (input)=\"onSearch($event)\"\r\n placeholder=\"Buscar...\" class=\"w-full\" \r\n [disabled]=\"disabled\" />\r\n </p-iconfield>\r\n <p-button *ngIf=\"btn.create\" [label]=\"btn.create.label\" [icon]=\"btn.create.icon\" severity=\"success\"\r\n (click)=\"tableroService.showAddDialog()\" class=\"hidden lg:inline-flex\"></p-button>\r\n </div>\r\n</div>", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: IconFieldModule }, { kind: "component", type: i3.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["iconPosition", "styleClass"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }, { kind: "ngmodule", type: InputIconModule }, { kind: "component", type: i5$1.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["styleClass"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i7.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }] });
1389
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: TableroHeaderComponent, isStandalone: true, selector: "lib-tablero-header", inputs: { disabled: "disabled" }, outputs: { searchChange: "searchChange" }, ngImport: i0, template: "<div class=\"flex align-items-center justify-content-between flex-wrap lg:flex-row w-full\">\r\n <div class=\"flex justify-content-between align-items-center w-full lg:w-auto\">\r\n <h5 class=\"m-0\">{{ config?.label }}</h5>\r\n </div>\r\n <div class=\"flex align-items-start gap-2 pt-2 lg:pt-0 w-full lg:w-auto flex-column md:flex-row md:flex-row-reverse md:align-items-center\">\r\n <div class=\"flex align-items-center gap-2\">\r\n <p-button *ngIf=\"btn.refresh\" [label]=\"btn.refresh.valor.label || ''\"\r\n [icon]=\"btn.refresh.icon || btn.refresh.valor.icon\" [severity]=\"btn.refresh.valor.severity\"\r\n [variant]=\"btn.refresh.valor.variant || 'outlined'\" (click)=\"tableroService.refresh()\"></p-button>\r\n <p-button *ngIf=\"btn.create\" [label]=\"btn.create.label\" [icon]=\"btn.create.icon || btn.create.valor.icon\"\r\n severity=\"success\" (click)=\"tableroService.showAddDialog()\"></p-button>\r\n </div>\r\n <p-iconfield styleClass=\"w-full\">\r\n <p-inputicon styleClass=\"pi pi-search\" />\r\n <input type=\"text\" pInputText (input)=\"onSearch($event)\" placeholder=\"Buscar...\" class=\"w-full\"\r\n [disabled]=\"disabled\" />\r\n </p-iconfield>\r\n </div>\r\n</div>", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: IconFieldModule }, { kind: "component", type: i3.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["iconPosition", "styleClass"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }, { kind: "ngmodule", type: InputIconModule }, { kind: "component", type: i5$1.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["styleClass"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i7.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }] });
1384
1390
  }
1385
1391
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TableroHeaderComponent, decorators: [{
1386
1392
  type: Component,
1387
- args: [{ selector: 'lib-tablero-header', imports: [CommonModule, IconFieldModule, InputTextModule, InputIconModule, ButtonModule], template: "<div class=\"flex align-items-center justify-content-between flex-wrap lg:flex-row w-full\">\r\n <div class=\"flex justify-content-between align-items-center w-full lg:w-auto\">\r\n <h5 class=\"m-0\">{{ config?.label }}</h5>\r\n <p-button *ngIf=\"btn.create\" [label]=\"btn.create.label\" [icon]=\"btn.create.icon\" severity=\"success\"\r\n (click)=\"tableroService.showAddDialog()\" class=\"inline-flex lg:hidden\"></p-button>\r\n </div>\r\n <div class=\"flex align-items-center gap-2 pt-2 lg:pt-0 w-full lg:w-auto\">\r\n <p-iconfield styleClass=\"w-full\">\r\n <p-inputicon styleClass=\"pi pi-search\" />\r\n <input type=\"text\" pInputText\r\n (input)=\"onSearch($event)\"\r\n placeholder=\"Buscar...\" class=\"w-full\" \r\n [disabled]=\"disabled\" />\r\n </p-iconfield>\r\n <p-button *ngIf=\"btn.create\" [label]=\"btn.create.label\" [icon]=\"btn.create.icon\" severity=\"success\"\r\n (click)=\"tableroService.showAddDialog()\" class=\"hidden lg:inline-flex\"></p-button>\r\n </div>\r\n</div>" }]
1393
+ args: [{ selector: 'lib-tablero-header', imports: [CommonModule, IconFieldModule, InputTextModule, InputIconModule, ButtonModule], template: "<div class=\"flex align-items-center justify-content-between flex-wrap lg:flex-row w-full\">\r\n <div class=\"flex justify-content-between align-items-center w-full lg:w-auto\">\r\n <h5 class=\"m-0\">{{ config?.label }}</h5>\r\n </div>\r\n <div class=\"flex align-items-start gap-2 pt-2 lg:pt-0 w-full lg:w-auto flex-column md:flex-row md:flex-row-reverse md:align-items-center\">\r\n <div class=\"flex align-items-center gap-2\">\r\n <p-button *ngIf=\"btn.refresh\" [label]=\"btn.refresh.valor.label || ''\"\r\n [icon]=\"btn.refresh.icon || btn.refresh.valor.icon\" [severity]=\"btn.refresh.valor.severity\"\r\n [variant]=\"btn.refresh.valor.variant || 'outlined'\" (click)=\"tableroService.refresh()\"></p-button>\r\n <p-button *ngIf=\"btn.create\" [label]=\"btn.create.label\" [icon]=\"btn.create.icon || btn.create.valor.icon\"\r\n severity=\"success\" (click)=\"tableroService.showAddDialog()\"></p-button>\r\n </div>\r\n <p-iconfield styleClass=\"w-full\">\r\n <p-inputicon styleClass=\"pi pi-search\" />\r\n <input type=\"text\" pInputText (input)=\"onSearch($event)\" placeholder=\"Buscar...\" class=\"w-full\"\r\n [disabled]=\"disabled\" />\r\n </p-iconfield>\r\n </div>\r\n</div>" }]
1388
1394
  }], ctorParameters: () => [{ type: TableroService }], propDecorators: { disabled: [{
1389
1395
  type: Input
1390
1396
  }], searchChange: [{
@@ -2202,6 +2208,7 @@ class ControlComponent {
2202
2208
  isLoading = false;
2203
2209
  dataFromService = [];
2204
2210
  uploadedFiles = [];
2211
+ _loadFilesId = 0;
2205
2212
  displayAdd = false;
2206
2213
  tempValue;
2207
2214
  clicked = false;
@@ -2370,24 +2377,70 @@ class ControlComponent {
2370
2377
  this.value = this.tempValue;
2371
2378
  this.sendValue();
2372
2379
  }
2373
- loadFiles() {
2380
+ async loadFiles() {
2381
+ const runId = ++this._loadFilesId;
2374
2382
  this.isLoading = true;
2375
2383
  this.uploadedFiles = [];
2376
2384
  if (!this.value) {
2377
2385
  this.isLoading = false;
2378
2386
  this.cdr.detectChanges();
2387
+ return;
2379
2388
  }
2380
- else if (this.control.config.namePattern && this.control.type == "string") {
2381
- let urls = this.control.config.separator ? this.value.split(",") : [this.value];
2382
- urls.forEach(url => this.uploadedFiles.push({ url: url, name: this.getNameFile(this.control.config.namePattern, url) }));
2383
- this.isLoading = false;
2384
- this.cdr.detectChanges();
2389
+ const mimeTypes = {
2390
+ pdf: 'application/pdf', jpg: 'image/jpeg', jpeg: 'image/jpeg',
2391
+ png: 'image/png', gif: 'image/gif', bmp: 'image/bmp'
2392
+ };
2393
+ const resolveUrl = async (url) => {
2394
+ try {
2395
+ const res = await fetch(url, { method: 'HEAD' });
2396
+ if (res.ok)
2397
+ return url;
2398
+ const lastSlash = url.lastIndexOf('/');
2399
+ const uploadedUrl = url.substring(0, lastSlash + 1) + 'UPLOADED_' + url.substring(lastSlash + 1);
2400
+ const res2 = await fetch(uploadedUrl, { method: 'HEAD' });
2401
+ if (!res2.ok)
2402
+ return null;
2403
+ const ext = url.substring(url.lastIndexOf('.') + 1).toLowerCase();
2404
+ const mimeType = mimeTypes[ext] ?? 'application/octet-stream';
2405
+ const content = await fetch(uploadedUrl);
2406
+ const buffer = await content.arrayBuffer();
2407
+ return URL.createObjectURL(new Blob([buffer], { type: mimeType }));
2408
+ }
2409
+ catch {
2410
+ return null;
2411
+ }
2412
+ };
2413
+ if (this.control.config.namePattern && this.control.type == "string") {
2414
+ const urls = this.control.config.separator ? this.value.split(",") : [this.value];
2415
+ const validUrls = [];
2416
+ for (const url of urls) {
2417
+ const resolved = await resolveUrl(url);
2418
+ if (runId !== this._loadFilesId)
2419
+ return;
2420
+ if (resolved !== null) {
2421
+ this.uploadedFiles.push({ url: resolved, name: this.getNameFile(this.control.config.namePattern, url) });
2422
+ validUrls.push(url);
2423
+ }
2424
+ }
2425
+ if (validUrls.length !== urls.length)
2426
+ this.value = validUrls.length > 0 ? validUrls.join(this.control.config?.separator || ',') : null;
2385
2427
  }
2386
2428
  else if (this.control.config.namePattern && this.control.type == "array") {
2387
- this.value.forEach((url) => this.uploadedFiles.push({ url: url, name: this.getNameFile(this.control.config.namePattern, url) }));
2388
- this.isLoading = false;
2389
- this.cdr.detectChanges();
2429
+ const validUrls = [];
2430
+ for (const url of this.value) {
2431
+ const resolved = await resolveUrl(url);
2432
+ if (runId !== this._loadFilesId)
2433
+ return;
2434
+ if (resolved !== null) {
2435
+ this.uploadedFiles.push({ url: resolved, name: this.getNameFile(this.control.config.namePattern, url) });
2436
+ validUrls.push(url);
2437
+ }
2438
+ }
2439
+ if (validUrls.length !== this.value.length)
2440
+ this.value = validUrls.length > 0 ? validUrls : null;
2390
2441
  }
2442
+ this.isLoading = false;
2443
+ this.cdr.detectChanges();
2391
2444
  }
2392
2445
  onDeleteFile(index) {
2393
2446
  if ((!this.control.config?.limit || this.control.config?.limit == 1) && this.control.type == "string")