@ddiazr/dynamic-report 0.0.1

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/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # Generic Report
2
+
3
+ Reporte dinamico Angular 21+
4
+
5
+ ## Instalación
6
+
7
+ ```bash
8
+ npm install @ddiazr/dynamic-report
9
+ ```
10
+
11
+ ## Peer Dependencies
12
+
13
+ ```bash
14
+ ng add @angular/cdk
15
+ npm i bootstrap @fortawesome/fontawesome-free
16
+ ```
17
+
18
+ ## Campos
19
+
20
+ | Propiedad | Tipo | Obligatorio | Descripción |
21
+ | --------------- | ---------------- | ----------- | ----------------------------------------------------- |
22
+ | `dataReport` | `any[]` | ✅ Sí | Campos a para elegir al reporte |
23
+ | `dataReportDefault` | `any[]` | ✅ Sí | Si es una creacion puede ir vacio y si es edicion lo que ya tiene almacenado |
24
+ | `dataSubmitted` | `function` | ✅ Sí | Accion donde devuelve un objeto con los campos llenos del reporte |
25
+
26
+
27
+ ## Uso básico
28
+
29
+ ```typescript
30
+ import { DynamicReport } from '@ddiazr/dynamic-report';
31
+
32
+ @Component({
33
+ imports: [DynamicReport],
34
+ template: `
35
+ <dr-dynamic-report
36
+ [dataReport]="data()"
37
+ [dataReportDefault]="dataDefault()"
38
+ (dataSubmitted)="dataSubmitted($event)"
39
+ />
40
+ `,
41
+ })
42
+ export class AppComponent {
43
+ data = signal<any[]>([
44
+ {
45
+ field: 'direccion',
46
+ label: 'Direccion',
47
+ },
48
+ {
49
+ field: 'tel',
50
+ label: 'Telefono',
51
+ },
52
+ ]);
53
+ //SI ES CREACION PUEDEN IR VACIO SI ES ACTUALIZACON PUEDE LLEVAR DATOS
54
+ dataDefault = signal<any[]>();
55
+ //ESTA FUNCION ES LA QUE RECIBE LA RESPUESTA YA FINAL GENERADA
56
+ dataSubmitted(data: any) {
57
+ console.log('reporte obtenido..', data);
58
+ }
59
+ }
60
+ ```
61
+
62
+ ## Configuración de estilos
63
+
64
+ En tu `angular.json`:
65
+
66
+ ```json
67
+ "styles": [
68
+ "node_modules/bootstrap/dist/css/bootstrap.min.css",
69
+ "node_modules/@fortawesome/fontawesome-free/css/all.min.css"
70
+ ]
71
+ ```
72
+
73
+ ## Licencia
74
+
75
+ MIT
76
+
77
+ # Source files
78
+
79
+ src/
80
+ _.ts
81
+ !_.d.ts
@@ -0,0 +1,103 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import * as i0 from '@angular/core';
3
+ import { input, output, signal, effect, Component } from '@angular/core';
4
+ import { moveItemInArray, transferArrayItem, CdkDropListGroup, CdkDropList, CdkDrag } from '@angular/cdk/drag-drop';
5
+
6
+ class DynamicReport {
7
+ dataReport = input.required(...(ngDevMode ? [{ debugName: "dataReport" }] : []));
8
+ dataReportDefault = input.required(...(ngDevMode ? [{ debugName: "dataReportDefault" }] : []));
9
+ dataSubmitted = output();
10
+ response = signal({
11
+ name: '',
12
+ data: [],
13
+ }, ...(ngDevMode ? [{ debugName: "response" }] : []));
14
+ constructor() {
15
+ effect(() => {
16
+ const value = this.dataReportDefault();
17
+ if (value.length) {
18
+ this.response.update((current) => ({
19
+ ...current,
20
+ data: value,
21
+ }));
22
+ }
23
+ });
24
+ }
25
+ drop(event) {
26
+ if (event.previousContainer === event.container) {
27
+ // Reordenar dentro del mismo contenedor
28
+ const currentData = event.container.data;
29
+ moveItemInArray(currentData, event.previousIndex, event.currentIndex);
30
+ // Si es el basket, actualizar el signal
31
+ if (event.container.id === 'basket-list') {
32
+ this.updateResponse(currentData);
33
+ }
34
+ }
35
+ else {
36
+ // Transferir entre contenedores
37
+ transferArrayItem(event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex);
38
+ // Si se movió AL basket, actualizar el signal
39
+ if (event.container.id === 'basket-list') {
40
+ this.updateResponse(event.container.data);
41
+ }
42
+ // Si se QUITÓ del basket, actualizar el signal
43
+ else if (event.previousContainer.id === 'basket-list') {
44
+ this.updateResponse(event.previousContainer.data);
45
+ }
46
+ }
47
+ }
48
+ updateResponse(data) {
49
+ this.response.update((current) => ({
50
+ ...current,
51
+ data: [...data], // Copia inmutable
52
+ }));
53
+ }
54
+ // Método opcional para obtener solo los fields
55
+ getSelectedFields() {
56
+ return this.response().data.map((item) => item.label);
57
+ }
58
+ updateName(newName) {
59
+ this.response.update((current) => ({
60
+ ...current,
61
+ name: newName,
62
+ }));
63
+ }
64
+ // Enviar datos
65
+ submit() {
66
+ const currentResponse = this.response();
67
+ // Validación
68
+ if (!currentResponse.name.trim()) {
69
+ alert('Por favor ingresa un nombre');
70
+ return;
71
+ }
72
+ if (currentResponse.data.length === 0) {
73
+ alert('Por favor selecciona al menos un campo');
74
+ return;
75
+ }
76
+ // Emitir los datos
77
+ this.dataSubmitted.emit(currentResponse);
78
+ // Mostrar confirmación
79
+ console.log('Datos enviados:', currentResponse);
80
+ }
81
+ // Verificar si se puede enviar
82
+ canSubmit() {
83
+ const current = this.response();
84
+ return current.name.trim().length > 0 && current.data.length > 0;
85
+ }
86
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: DynamicReport, deps: [], target: i0.ɵɵFactoryTarget.Component });
87
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: DynamicReport, isStandalone: true, selector: "dr-dynamic-report", inputs: { dataReport: { classPropertyName: "dataReport", publicName: "dataReport", isSignal: true, isRequired: true, transformFunction: null }, dataReportDefault: { classPropertyName: "dataReportDefault", publicName: "dataReportDefault", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { dataSubmitted: "dataSubmitted" }, ngImport: i0, template: "<!-- Estado de validaci\u00F3n -->\r\n@if (!canSubmit()) {\r\n <div class=\"alert alert-warning mt-0 mb-3\">\r\n <i class=\"fas fa-exclamation-triangle me-2\"></i>\r\n <strong>Atenci\u00F3n:</strong>\r\n @if (!response().name.trim()) {\r\n Debes ingresar un nombre.\r\n }\r\n @if (response().data.length === 0) {\r\n Debes seleccionar al menos un campo.\r\n }\r\n </div>\r\n}\r\n\r\n<div class=\"row g-3\">\r\n <div class=\"col-md-4\">\r\n <!-- Panel de configuraci\u00F3n y env\u00EDo -->\r\n <div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"card shadow\">\r\n <div class=\"card-header bg-success text-white\">\r\n <h5 class=\"mb-0\">\r\n <i class=\"fas fa-cog me-2\"></i>\r\n Configuraci\u00F3n y Env\u00EDo\r\n </h5>\r\n </div>\r\n <div class=\"card-body\">\r\n <!-- Input para el nombre -->\r\n <div class=\"mb-2\">\r\n <label for=\"responseName\" class=\"form-label fw-bold\">\r\n <i class=\"fas fa-tag me-2\"></i>\r\n Nombre del reporte:\r\n </label>\r\n <input\r\n id=\"responseName\"\r\n type=\"text\"\r\n class=\"form-control\"\r\n placeholder=\"Ej: Reporte de Usuarios\"\r\n [value]=\"response().name\"\r\n (input)=\"updateName($any($event.target).value)\"\r\n maxlength=\"100\"\r\n />\r\n </div>\r\n\r\n <!-- Resumen de selecci\u00F3n -->\r\n <div class=\"row mb-2 g-2\">\r\n <div class=\"col-12\">\r\n <div class=\"alert alert-info mb-0\">\r\n <h6 class=\"alert-heading\">\r\n <i class=\"fas fa-info-circle me-2\"></i>\r\n Resumen\r\n </h6>\r\n <ul class=\"mb-0\">\r\n <li>\r\n <strong>Nombre:</strong>\r\n {{ response().name || '(sin nombre)' }}\r\n </li>\r\n <li>\r\n <strong>Campos seleccionados:</strong>\r\n {{ response().data.length }}\r\n </li>\r\n </ul>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <div class=\"alert alert-secondary mb-0\">\r\n <h6 class=\"alert-heading\">\r\n <i class=\"fas fa-list me-2\"></i>\r\n Campos Seleccionados\r\n </h6>\r\n @if (response().data.length > 0) {\r\n <div class=\"d-flex flex-wrap gap-2\">\r\n @for (item of response().data; track item.field) {\r\n <span class=\"badge bg-primary\">\r\n {{ item.label }}\r\n </span>\r\n }\r\n </div>\r\n } @else {\r\n <small class=\"text-muted\"> No hay campos seleccionados </small>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Botones de acci\u00F3n -->\r\n <div class=\"d-grid\">\r\n <button class=\"btn btn-success\" [disabled]=\"!canSubmit()\" (click)=\"submit()\">\r\n <i class=\"fas fa-paper-plane me-2\"></i>\r\n Enviar Configuraci\u00F3n\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"col-md-8\">\r\n <div cdkDropListGroup class=\"row g-3\">\r\n <!-- Lista de datos disponibles -->\r\n <div class=\"col-lg-6\">\r\n <div class=\"card shadow-sm\">\r\n <div class=\"card-header bg-secondary text-white\">\r\n <h5 class=\"mb-0\">\r\n <i class=\"fas fa-database me-2\"></i>\r\n Datos Disponibles\r\n <span class=\"badge bg-light text-dark float-end\">{{ dataReport().length }}</span>\r\n </h5>\r\n </div>\r\n <div class=\"card-body p-0\">\r\n <div\r\n id=\"items-list\"\r\n cdkDropList\r\n [cdkDropListData]=\"dataReport()\"\r\n [cdkDropListConnectedTo]=\"['basket-list']\"\r\n class=\"example-list\"\r\n cdkDropListSortingDisabled\r\n (cdkDropListDropped)=\"drop($event)\"\r\n >\r\n @for (item of dataReport(); track item.field) {\r\n <div class=\"example-box border-bottom p-3\" cdkDrag>\r\n <div class=\"d-flex align-items-center\">\r\n <i class=\"fas fa-grip-vertical text-muted me-3\" cdkDragHandle></i>\r\n <div>\r\n <strong>{{ item.label }}</strong>\r\n <small class=\"d-block text-muted\">{{ item.field }}</small>\r\n </div>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div class=\"text-center text-muted p-4\">\r\n <i class=\"fas fa-inbox fa-3x mb-3\"></i>\r\n <p>No hay datos disponibles</p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Lista de datos adquiridos -->\r\n <div class=\"col-lg-6\">\r\n <div class=\"card shadow-sm\">\r\n <div class=\"card-header bg-primary text-white\">\r\n <h5 class=\"mb-0\">\r\n <i class=\"fas fa-check-circle me-2\"></i>\r\n Datos Adquiridos\r\n <span class=\"badge bg-light text-dark float-end\">{{ response().data.length }}</span>\r\n </h5>\r\n </div>\r\n <div class=\"card-body p-0\">\r\n <div\r\n id=\"basket-list\"\r\n cdkDropList\r\n [cdkDropListData]=\"response().data\"\r\n [cdkDropListConnectedTo]=\"['items-list']\"\r\n class=\"example-list\"\r\n (cdkDropListDropped)=\"drop($event)\"\r\n >\r\n @for (item of response().data; track item.field) {\r\n <div class=\"example-box border-bottom p-3 bg-light\" cdkDrag>\r\n <div class=\"d-flex align-items-center\">\r\n <i class=\"fas fa-grip-vertical text-muted me-3\" cdkDragHandle></i>\r\n <div>\r\n <strong class=\"text-primary\">{{ item.label }}</strong>\r\n <small class=\"d-block text-muted\">{{ item.field }}</small>\r\n </div>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div class=\"text-center text-muted p-4\">\r\n <i class=\"fas fa-hand-pointer fa-3x mb-3\"></i>\r\n <p>Arrastra elementos aqu\u00ED</p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".example-list{border:solid 1px #ccc;min-height:60px;background:#fff;border-radius:4px;overflow:hidden;display:block}h2{font-family:sans-serif}.example-box{cursor:move;font-family:sans-serif}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }] });
88
+ }
89
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: DynamicReport, decorators: [{
90
+ type: Component,
91
+ args: [{ selector: 'dr-dynamic-report', imports: [CommonModule, CdkDropListGroup, CdkDropList, CdkDrag], template: "<!-- Estado de validaci\u00F3n -->\r\n@if (!canSubmit()) {\r\n <div class=\"alert alert-warning mt-0 mb-3\">\r\n <i class=\"fas fa-exclamation-triangle me-2\"></i>\r\n <strong>Atenci\u00F3n:</strong>\r\n @if (!response().name.trim()) {\r\n Debes ingresar un nombre.\r\n }\r\n @if (response().data.length === 0) {\r\n Debes seleccionar al menos un campo.\r\n }\r\n </div>\r\n}\r\n\r\n<div class=\"row g-3\">\r\n <div class=\"col-md-4\">\r\n <!-- Panel de configuraci\u00F3n y env\u00EDo -->\r\n <div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"card shadow\">\r\n <div class=\"card-header bg-success text-white\">\r\n <h5 class=\"mb-0\">\r\n <i class=\"fas fa-cog me-2\"></i>\r\n Configuraci\u00F3n y Env\u00EDo\r\n </h5>\r\n </div>\r\n <div class=\"card-body\">\r\n <!-- Input para el nombre -->\r\n <div class=\"mb-2\">\r\n <label for=\"responseName\" class=\"form-label fw-bold\">\r\n <i class=\"fas fa-tag me-2\"></i>\r\n Nombre del reporte:\r\n </label>\r\n <input\r\n id=\"responseName\"\r\n type=\"text\"\r\n class=\"form-control\"\r\n placeholder=\"Ej: Reporte de Usuarios\"\r\n [value]=\"response().name\"\r\n (input)=\"updateName($any($event.target).value)\"\r\n maxlength=\"100\"\r\n />\r\n </div>\r\n\r\n <!-- Resumen de selecci\u00F3n -->\r\n <div class=\"row mb-2 g-2\">\r\n <div class=\"col-12\">\r\n <div class=\"alert alert-info mb-0\">\r\n <h6 class=\"alert-heading\">\r\n <i class=\"fas fa-info-circle me-2\"></i>\r\n Resumen\r\n </h6>\r\n <ul class=\"mb-0\">\r\n <li>\r\n <strong>Nombre:</strong>\r\n {{ response().name || '(sin nombre)' }}\r\n </li>\r\n <li>\r\n <strong>Campos seleccionados:</strong>\r\n {{ response().data.length }}\r\n </li>\r\n </ul>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <div class=\"alert alert-secondary mb-0\">\r\n <h6 class=\"alert-heading\">\r\n <i class=\"fas fa-list me-2\"></i>\r\n Campos Seleccionados\r\n </h6>\r\n @if (response().data.length > 0) {\r\n <div class=\"d-flex flex-wrap gap-2\">\r\n @for (item of response().data; track item.field) {\r\n <span class=\"badge bg-primary\">\r\n {{ item.label }}\r\n </span>\r\n }\r\n </div>\r\n } @else {\r\n <small class=\"text-muted\"> No hay campos seleccionados </small>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Botones de acci\u00F3n -->\r\n <div class=\"d-grid\">\r\n <button class=\"btn btn-success\" [disabled]=\"!canSubmit()\" (click)=\"submit()\">\r\n <i class=\"fas fa-paper-plane me-2\"></i>\r\n Enviar Configuraci\u00F3n\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"col-md-8\">\r\n <div cdkDropListGroup class=\"row g-3\">\r\n <!-- Lista de datos disponibles -->\r\n <div class=\"col-lg-6\">\r\n <div class=\"card shadow-sm\">\r\n <div class=\"card-header bg-secondary text-white\">\r\n <h5 class=\"mb-0\">\r\n <i class=\"fas fa-database me-2\"></i>\r\n Datos Disponibles\r\n <span class=\"badge bg-light text-dark float-end\">{{ dataReport().length }}</span>\r\n </h5>\r\n </div>\r\n <div class=\"card-body p-0\">\r\n <div\r\n id=\"items-list\"\r\n cdkDropList\r\n [cdkDropListData]=\"dataReport()\"\r\n [cdkDropListConnectedTo]=\"['basket-list']\"\r\n class=\"example-list\"\r\n cdkDropListSortingDisabled\r\n (cdkDropListDropped)=\"drop($event)\"\r\n >\r\n @for (item of dataReport(); track item.field) {\r\n <div class=\"example-box border-bottom p-3\" cdkDrag>\r\n <div class=\"d-flex align-items-center\">\r\n <i class=\"fas fa-grip-vertical text-muted me-3\" cdkDragHandle></i>\r\n <div>\r\n <strong>{{ item.label }}</strong>\r\n <small class=\"d-block text-muted\">{{ item.field }}</small>\r\n </div>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div class=\"text-center text-muted p-4\">\r\n <i class=\"fas fa-inbox fa-3x mb-3\"></i>\r\n <p>No hay datos disponibles</p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Lista de datos adquiridos -->\r\n <div class=\"col-lg-6\">\r\n <div class=\"card shadow-sm\">\r\n <div class=\"card-header bg-primary text-white\">\r\n <h5 class=\"mb-0\">\r\n <i class=\"fas fa-check-circle me-2\"></i>\r\n Datos Adquiridos\r\n <span class=\"badge bg-light text-dark float-end\">{{ response().data.length }}</span>\r\n </h5>\r\n </div>\r\n <div class=\"card-body p-0\">\r\n <div\r\n id=\"basket-list\"\r\n cdkDropList\r\n [cdkDropListData]=\"response().data\"\r\n [cdkDropListConnectedTo]=\"['items-list']\"\r\n class=\"example-list\"\r\n (cdkDropListDropped)=\"drop($event)\"\r\n >\r\n @for (item of response().data; track item.field) {\r\n <div class=\"example-box border-bottom p-3 bg-light\" cdkDrag>\r\n <div class=\"d-flex align-items-center\">\r\n <i class=\"fas fa-grip-vertical text-muted me-3\" cdkDragHandle></i>\r\n <div>\r\n <strong class=\"text-primary\">{{ item.label }}</strong>\r\n <small class=\"d-block text-muted\">{{ item.field }}</small>\r\n </div>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div class=\"text-center text-muted p-4\">\r\n <i class=\"fas fa-hand-pointer fa-3x mb-3\"></i>\r\n <p>Arrastra elementos aqu\u00ED</p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".example-list{border:solid 1px #ccc;min-height:60px;background:#fff;border-radius:4px;overflow:hidden;display:block}h2{font-family:sans-serif}.example-box{cursor:move;font-family:sans-serif}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"] }]
92
+ }], ctorParameters: () => [], propDecorators: { dataReport: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataReport", required: true }] }], dataReportDefault: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataReportDefault", required: true }] }], dataSubmitted: [{ type: i0.Output, args: ["dataSubmitted"] }] } });
93
+
94
+ /*
95
+ * Public API Surface of dynamic-report
96
+ */
97
+
98
+ /**
99
+ * Generated bundle index. Do not edit.
100
+ */
101
+
102
+ export { DynamicReport };
103
+ //# sourceMappingURL=ddiazr-dynamic-report.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ddiazr-dynamic-report.mjs","sources":["../../../projects/dynamic-report/src/lib/dynamic-report.ts","../../../projects/dynamic-report/src/lib/dynamic-report.html","../../../projects/dynamic-report/src/public-api.ts","../../../projects/dynamic-report/src/ddiazr-dynamic-report.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\r\nimport { Component, effect, input, output, signal } from '@angular/core';\r\nimport {\r\n CdkDrag,\r\n CdkDragDrop,\r\n CdkDropList,\r\n CdkDropListGroup,\r\n moveItemInArray,\r\n transferArrayItem,\r\n} from '@angular/cdk/drag-drop';\r\n\r\ninterface DataI {\r\n field: string;\r\n label: string;\r\n}\r\ninterface ResponseI {\r\n name: string;\r\n data: DataI[];\r\n}\r\n\r\n@Component({\r\n selector: 'dr-dynamic-report',\r\n imports: [CommonModule, CdkDropListGroup, CdkDropList, CdkDrag],\r\n templateUrl: './dynamic-report.html',\r\n styleUrl: './dynamic-report.scss',\r\n})\r\nexport class DynamicReport {\r\n dataReport = input.required<DataI[]>();\r\n dataReportDefault = input.required<DataI[]>();\r\n dataSubmitted = output<ResponseI>();\r\n response = signal<ResponseI>({\r\n name: '',\r\n data: [],\r\n });\r\n\r\n constructor() {\r\n effect(() => {\r\n const value = this.dataReportDefault();\r\n if (value.length) {\r\n this.response.update((current) => ({\r\n ...current,\r\n data: value,\r\n }));\r\n }\r\n });\r\n }\r\n\r\n drop(event: CdkDragDrop<DataI[]>) {\r\n if (event.previousContainer === event.container) {\r\n // Reordenar dentro del mismo contenedor\r\n const currentData = event.container.data;\r\n moveItemInArray(currentData, event.previousIndex, event.currentIndex);\r\n\r\n // Si es el basket, actualizar el signal\r\n if (event.container.id === 'basket-list') {\r\n this.updateResponse(currentData);\r\n }\r\n } else {\r\n // Transferir entre contenedores\r\n transferArrayItem(\r\n event.previousContainer.data,\r\n event.container.data,\r\n event.previousIndex,\r\n event.currentIndex,\r\n );\r\n\r\n // Si se movió AL basket, actualizar el signal\r\n if (event.container.id === 'basket-list') {\r\n this.updateResponse(event.container.data);\r\n }\r\n // Si se QUITÓ del basket, actualizar el signal\r\n else if (event.previousContainer.id === 'basket-list') {\r\n this.updateResponse(event.previousContainer.data);\r\n }\r\n }\r\n }\r\n\r\n private updateResponse(data: DataI[]): void {\r\n this.response.update((current) => ({\r\n ...current,\r\n data: [...data], // Copia inmutable\r\n }));\r\n }\r\n\r\n // Método opcional para obtener solo los fields\r\n getSelectedFields(): string[] {\r\n return this.response().data.map((item) => item.label);\r\n }\r\n\r\n updateName(newName: string): void {\r\n this.response.update((current) => ({\r\n ...current,\r\n name: newName,\r\n }));\r\n }\r\n\r\n // Enviar datos\r\n submit(): void {\r\n const currentResponse = this.response();\r\n\r\n // Validación\r\n if (!currentResponse.name.trim()) {\r\n alert('Por favor ingresa un nombre');\r\n return;\r\n }\r\n\r\n if (currentResponse.data.length === 0) {\r\n alert('Por favor selecciona al menos un campo');\r\n return;\r\n }\r\n\r\n // Emitir los datos\r\n this.dataSubmitted.emit(currentResponse);\r\n\r\n // Mostrar confirmación\r\n console.log('Datos enviados:', currentResponse);\r\n }\r\n\r\n // Verificar si se puede enviar\r\n canSubmit(): boolean {\r\n const current = this.response();\r\n return current.name.trim().length > 0 && current.data.length > 0;\r\n }\r\n}\r\n","<!-- Estado de validación -->\r\n@if (!canSubmit()) {\r\n <div class=\"alert alert-warning mt-0 mb-3\">\r\n <i class=\"fas fa-exclamation-triangle me-2\"></i>\r\n <strong>Atención:</strong>\r\n @if (!response().name.trim()) {\r\n Debes ingresar un nombre.\r\n }\r\n @if (response().data.length === 0) {\r\n Debes seleccionar al menos un campo.\r\n }\r\n </div>\r\n}\r\n\r\n<div class=\"row g-3\">\r\n <div class=\"col-md-4\">\r\n <!-- Panel de configuración y envío -->\r\n <div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"card shadow\">\r\n <div class=\"card-header bg-success text-white\">\r\n <h5 class=\"mb-0\">\r\n <i class=\"fas fa-cog me-2\"></i>\r\n Configuración y Envío\r\n </h5>\r\n </div>\r\n <div class=\"card-body\">\r\n <!-- Input para el nombre -->\r\n <div class=\"mb-2\">\r\n <label for=\"responseName\" class=\"form-label fw-bold\">\r\n <i class=\"fas fa-tag me-2\"></i>\r\n Nombre del reporte:\r\n </label>\r\n <input\r\n id=\"responseName\"\r\n type=\"text\"\r\n class=\"form-control\"\r\n placeholder=\"Ej: Reporte de Usuarios\"\r\n [value]=\"response().name\"\r\n (input)=\"updateName($any($event.target).value)\"\r\n maxlength=\"100\"\r\n />\r\n </div>\r\n\r\n <!-- Resumen de selección -->\r\n <div class=\"row mb-2 g-2\">\r\n <div class=\"col-12\">\r\n <div class=\"alert alert-info mb-0\">\r\n <h6 class=\"alert-heading\">\r\n <i class=\"fas fa-info-circle me-2\"></i>\r\n Resumen\r\n </h6>\r\n <ul class=\"mb-0\">\r\n <li>\r\n <strong>Nombre:</strong>\r\n {{ response().name || '(sin nombre)' }}\r\n </li>\r\n <li>\r\n <strong>Campos seleccionados:</strong>\r\n {{ response().data.length }}\r\n </li>\r\n </ul>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <div class=\"alert alert-secondary mb-0\">\r\n <h6 class=\"alert-heading\">\r\n <i class=\"fas fa-list me-2\"></i>\r\n Campos Seleccionados\r\n </h6>\r\n @if (response().data.length > 0) {\r\n <div class=\"d-flex flex-wrap gap-2\">\r\n @for (item of response().data; track item.field) {\r\n <span class=\"badge bg-primary\">\r\n {{ item.label }}\r\n </span>\r\n }\r\n </div>\r\n } @else {\r\n <small class=\"text-muted\"> No hay campos seleccionados </small>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Botones de acción -->\r\n <div class=\"d-grid\">\r\n <button class=\"btn btn-success\" [disabled]=\"!canSubmit()\" (click)=\"submit()\">\r\n <i class=\"fas fa-paper-plane me-2\"></i>\r\n Enviar Configuración\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"col-md-8\">\r\n <div cdkDropListGroup class=\"row g-3\">\r\n <!-- Lista de datos disponibles -->\r\n <div class=\"col-lg-6\">\r\n <div class=\"card shadow-sm\">\r\n <div class=\"card-header bg-secondary text-white\">\r\n <h5 class=\"mb-0\">\r\n <i class=\"fas fa-database me-2\"></i>\r\n Datos Disponibles\r\n <span class=\"badge bg-light text-dark float-end\">{{ dataReport().length }}</span>\r\n </h5>\r\n </div>\r\n <div class=\"card-body p-0\">\r\n <div\r\n id=\"items-list\"\r\n cdkDropList\r\n [cdkDropListData]=\"dataReport()\"\r\n [cdkDropListConnectedTo]=\"['basket-list']\"\r\n class=\"example-list\"\r\n cdkDropListSortingDisabled\r\n (cdkDropListDropped)=\"drop($event)\"\r\n >\r\n @for (item of dataReport(); track item.field) {\r\n <div class=\"example-box border-bottom p-3\" cdkDrag>\r\n <div class=\"d-flex align-items-center\">\r\n <i class=\"fas fa-grip-vertical text-muted me-3\" cdkDragHandle></i>\r\n <div>\r\n <strong>{{ item.label }}</strong>\r\n <small class=\"d-block text-muted\">{{ item.field }}</small>\r\n </div>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div class=\"text-center text-muted p-4\">\r\n <i class=\"fas fa-inbox fa-3x mb-3\"></i>\r\n <p>No hay datos disponibles</p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Lista de datos adquiridos -->\r\n <div class=\"col-lg-6\">\r\n <div class=\"card shadow-sm\">\r\n <div class=\"card-header bg-primary text-white\">\r\n <h5 class=\"mb-0\">\r\n <i class=\"fas fa-check-circle me-2\"></i>\r\n Datos Adquiridos\r\n <span class=\"badge bg-light text-dark float-end\">{{ response().data.length }}</span>\r\n </h5>\r\n </div>\r\n <div class=\"card-body p-0\">\r\n <div\r\n id=\"basket-list\"\r\n cdkDropList\r\n [cdkDropListData]=\"response().data\"\r\n [cdkDropListConnectedTo]=\"['items-list']\"\r\n class=\"example-list\"\r\n (cdkDropListDropped)=\"drop($event)\"\r\n >\r\n @for (item of response().data; track item.field) {\r\n <div class=\"example-box border-bottom p-3 bg-light\" cdkDrag>\r\n <div class=\"d-flex align-items-center\">\r\n <i class=\"fas fa-grip-vertical text-muted me-3\" cdkDragHandle></i>\r\n <div>\r\n <strong class=\"text-primary\">{{ item.label }}</strong>\r\n <small class=\"d-block text-muted\">{{ item.field }}</small>\r\n </div>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div class=\"text-center text-muted p-4\">\r\n <i class=\"fas fa-hand-pointer fa-3x mb-3\"></i>\r\n <p>Arrastra elementos aquí</p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n","/*\r\n * Public API Surface of dynamic-report\r\n */\r\n\r\nexport * from './lib/dynamic-report';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@ddiazr/dynamic-report",
3
+ "version": "0.0.1",
4
+ "description": "Para crear reportes dinamicos segun campos entrantes",
5
+ "author": {
6
+ "name": "Dany Díaz",
7
+ "email": "danylen1@hotmail.com"
8
+ },
9
+ "license": "MIT",
10
+ "peerDependencies": {
11
+ "@angular/common": "^21.1.0",
12
+ "@angular/core": "^21.1.0",
13
+ "@angular/cdk": "^21.1.2",
14
+ "bootstrap": "^5.3.8",
15
+ "@fortawesome/fontawesome-free": "^7.1.0"
16
+ },
17
+ "dependencies": {
18
+ "tslib": "^2.3.0"
19
+ },
20
+ "sideEffects": false,
21
+ "module": "fesm2022/ddiazr-dynamic-report.mjs",
22
+ "typings": "types/ddiazr-dynamic-report.d.ts",
23
+ "exports": {
24
+ "./package.json": {
25
+ "default": "./package.json"
26
+ },
27
+ ".": {
28
+ "types": "./types/ddiazr-dynamic-report.d.ts",
29
+ "default": "./fesm2022/ddiazr-dynamic-report.mjs"
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,28 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { CdkDragDrop } from '@angular/cdk/drag-drop';
3
+
4
+ interface DataI {
5
+ field: string;
6
+ label: string;
7
+ }
8
+ interface ResponseI {
9
+ name: string;
10
+ data: DataI[];
11
+ }
12
+ declare class DynamicReport {
13
+ dataReport: _angular_core.InputSignal<DataI[]>;
14
+ dataReportDefault: _angular_core.InputSignal<DataI[]>;
15
+ dataSubmitted: _angular_core.OutputEmitterRef<ResponseI>;
16
+ response: _angular_core.WritableSignal<ResponseI>;
17
+ constructor();
18
+ drop(event: CdkDragDrop<DataI[]>): void;
19
+ private updateResponse;
20
+ getSelectedFields(): string[];
21
+ updateName(newName: string): void;
22
+ submit(): void;
23
+ canSubmit(): boolean;
24
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DynamicReport, never>;
25
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DynamicReport, "dr-dynamic-report", never, { "dataReport": { "alias": "dataReport"; "required": true; "isSignal": true; }; "dataReportDefault": { "alias": "dataReportDefault"; "required": true; "isSignal": true; }; }, { "dataSubmitted": "dataSubmitted"; }, never, never, true, never>;
26
+ }
27
+
28
+ export { DynamicReport };