|
|
@@ -13,7 +13,7 @@ interface FormElement {
|
|
|
label: string;
|
|
|
placeholder?: string;
|
|
|
required: boolean;
|
|
|
- options?: string[]; // Para select y radio
|
|
|
+ options?: string[];
|
|
|
id?: string;
|
|
|
name?: string;
|
|
|
value?: string;
|
|
|
@@ -23,10 +23,13 @@ interface FormElement {
|
|
|
description?: string;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
interface Tab {
|
|
|
id: string;
|
|
|
name: string;
|
|
|
active: boolean;
|
|
|
+ rows: number; // Filas específicas de este tab
|
|
|
+ columns: number; // Columnas específicas de este tab
|
|
|
grid: GridCell[][];
|
|
|
}
|
|
|
|
|
|
@@ -39,8 +42,11 @@ export class AdminFormComponent implements OnInit {
|
|
|
public color: string = '';
|
|
|
public textColor: string = '';
|
|
|
formTitle: string = '';
|
|
|
- rows: number = 3;
|
|
|
- columns: number = 3;
|
|
|
+
|
|
|
+ // Dimensiones por defecto para nuevos tabs
|
|
|
+ defaultRows: number = 3;
|
|
|
+ defaultColumns: number = 3;
|
|
|
+
|
|
|
showTooltip: string = '';
|
|
|
|
|
|
// Sistema de tabs
|
|
|
@@ -66,14 +72,28 @@ export class AdminFormComponent implements OnInit {
|
|
|
this.addTab();
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ get rows(): number {
|
|
|
+ return this.currentTab?.rows || this.defaultRows;
|
|
|
+ }
|
|
|
+
|
|
|
+ get columns(): number {
|
|
|
+ return this.currentTab?.columns || this.defaultColumns;
|
|
|
+ }
|
|
|
+
|
|
|
// Métodos para manejo de tabs
|
|
|
- addTab() {
|
|
|
+ addTab(customRows?: number, customColumns?: number) {
|
|
|
const newTabId = `tab_${this.tabs.length + 1}`;
|
|
|
+ const tabRows = customRows || this.defaultRows;
|
|
|
+ const tabColumns = customColumns || this.defaultColumns;
|
|
|
+
|
|
|
const newTab: Tab = {
|
|
|
id: newTabId,
|
|
|
name: `Sección ${this.tabs.length + 1}`,
|
|
|
active: false,
|
|
|
- grid: this.buildNewGrid()
|
|
|
+ rows: tabRows,
|
|
|
+ columns: tabColumns,
|
|
|
+ grid: this.buildNewGrid(tabRows, tabColumns)
|
|
|
};
|
|
|
|
|
|
this.tabs.push(newTab);
|
|
|
@@ -81,12 +101,11 @@ export class AdminFormComponent implements OnInit {
|
|
|
}
|
|
|
|
|
|
removeTab(index: number) {
|
|
|
- if (this.tabs.length === 1) return; // No permitir eliminar el último tab
|
|
|
+ if (this.tabs.length === 1) return;
|
|
|
|
|
|
const tabToRemove = this.tabs[index];
|
|
|
this.tabs.splice(index, 1);
|
|
|
|
|
|
- // Si eliminamos el tab activo, cambiar al primero disponible
|
|
|
if (this.currentTab === tabToRemove) {
|
|
|
this.switchToTab(this.tabs[0]);
|
|
|
}
|
|
|
@@ -116,11 +135,38 @@ export class AdminFormComponent implements OnInit {
|
|
|
tab.name = newName;
|
|
|
}
|
|
|
|
|
|
- buildNewGrid(): GridCell[][] {
|
|
|
+ // Actualizar dimensiones de un tab específico
|
|
|
+ updateTabDimensions(tab: Tab, newRows: number, newColumns: number) {
|
|
|
+ const oldGrid = [...tab.grid];
|
|
|
+ tab.rows = newRows;
|
|
|
+ tab.columns = newColumns;
|
|
|
+ tab.grid = this.buildNewGrid(newRows, newColumns);
|
|
|
+
|
|
|
+ // Preservar elementos existentes si caben en las nuevas dimensiones
|
|
|
+ this.preserveElementsInNewGrid(oldGrid, tab.grid, newRows, newColumns);
|
|
|
+
|
|
|
+ // Si es el tab activo, actualizar el grid actual
|
|
|
+ if (this.currentTab === tab) {
|
|
|
+ this.grid = [...tab.grid];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Preservar elementos al cambiar dimensiones
|
|
|
+ private preserveElementsInNewGrid(oldGrid: GridCell[][], newGrid: GridCell[][], newRows: number, newColumns: number) {
|
|
|
+ oldGrid.forEach(row => {
|
|
|
+ row.forEach(cell => {
|
|
|
+ if (cell.element && cell.row < newRows && cell.col < newColumns) {
|
|
|
+ newGrid[cell.row][cell.col].element = cell.element;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ buildNewGrid(rows: number, columns: number): GridCell[][] {
|
|
|
const newGrid: GridCell[][] = [];
|
|
|
- for(let r = 0; r < this.rows; r++) {
|
|
|
+ for(let r = 0; r < rows; r++) {
|
|
|
const row: GridCell[] = [];
|
|
|
- for(let c = 0; c < this.columns; c++) {
|
|
|
+ for(let c = 0; c < columns; c++) {
|
|
|
row.push({row: r, col: c, selected: false});
|
|
|
}
|
|
|
newGrid.push(row);
|
|
|
@@ -129,97 +175,125 @@ export class AdminFormComponent implements OnInit {
|
|
|
}
|
|
|
|
|
|
buildGrid() {
|
|
|
- this.grid = this.buildNewGrid();
|
|
|
-
|
|
|
- // Actualizar el grid del tab actual
|
|
|
if (this.currentTab) {
|
|
|
+ this.grid = this.buildNewGrid(this.currentTab.rows, this.currentTab.columns);
|
|
|
this.currentTab.grid = [...this.grid];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // Métodos que usará el template para interactuar con la cuadrícula
|
|
|
- selectElementForEditing(cell: GridCell) {
|
|
|
- this.editingElement = cell.element || null;
|
|
|
- }
|
|
|
-
|
|
|
- removeElementFromCell(cell: GridCell) {
|
|
|
- cell.element = undefined;
|
|
|
- this.updateCurrentTabGrid();
|
|
|
- }
|
|
|
-
|
|
|
+ // Métodos de configuración JSON optimizados
|
|
|
logConfiguration() {
|
|
|
- // Guardar el grid actual en el tab activo antes de generar el JSON
|
|
|
if (this.currentTab) {
|
|
|
this.currentTab.grid = [...this.grid];
|
|
|
}
|
|
|
|
|
|
const configuration = {
|
|
|
- formTitle: this.formTitle,
|
|
|
- rows: this.rows,
|
|
|
- columns: this.columns,
|
|
|
- tabs: this.tabs.map(tab => ({
|
|
|
- id: tab.id,
|
|
|
- name: tab.name,
|
|
|
- grid: tab.grid.map(row =>
|
|
|
- row.map(cell => ({
|
|
|
- row: cell.row,
|
|
|
- col: cell.col,
|
|
|
- element: cell.element ? {
|
|
|
- type: cell.element.type,
|
|
|
- label: cell.element.label,
|
|
|
- placeholder: cell.element.placeholder,
|
|
|
- required: cell.element.required,
|
|
|
- options: cell.element.options,
|
|
|
- id: cell.element.id,
|
|
|
- name: cell.element.name,
|
|
|
- value: cell.element.value,
|
|
|
- min: cell.element.min,
|
|
|
- max: cell.element.max,
|
|
|
- pattern: cell.element.pattern,
|
|
|
- description: cell.element.description
|
|
|
- } : undefined
|
|
|
- }))
|
|
|
- )
|
|
|
- }))
|
|
|
+ title: this.formTitle,
|
|
|
+ tabs: this.tabs.map(tab => this.serializeTab(tab))
|
|
|
};
|
|
|
|
|
|
console.log('Configuración completa:', configuration);
|
|
|
return configuration;
|
|
|
}
|
|
|
|
|
|
- // Métodos para actualizar el grid del tab actual
|
|
|
- updateCurrentTabGrid() {
|
|
|
- if (this.currentTab) {
|
|
|
- this.currentTab.grid = [...this.grid];
|
|
|
- }
|
|
|
+ private serializeTab(tab: Tab) {
|
|
|
+ return {
|
|
|
+ id: tab.id,
|
|
|
+ title: tab.name,
|
|
|
+ rows: tab.rows,
|
|
|
+ columns: tab.columns,
|
|
|
+ elements: this.extractElementsFromGrid(tab.grid)
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
- clearSelection() {
|
|
|
- this.grid.forEach(row => row.forEach(c => c.selected = false));
|
|
|
- this.selectedCell = null;
|
|
|
- this.showElementSelector = false;
|
|
|
- this.editingElement = null;
|
|
|
+ private extractElementsFromGrid(grid: GridCell[][]): any[] {
|
|
|
+ const elements: any[] = [];
|
|
|
+
|
|
|
+ grid.forEach(row => {
|
|
|
+ row.forEach(cell => {
|
|
|
+ if (cell.element) {
|
|
|
+ elements.push({
|
|
|
+ position: {
|
|
|
+ row: cell.row,
|
|
|
+ col: cell.col
|
|
|
+ },
|
|
|
+ element: this.serializeElement(cell.element)
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ return elements;
|
|
|
+ }
|
|
|
+
|
|
|
+ private serializeElement(element: FormElement): any {
|
|
|
+ const serialized: any = {
|
|
|
+ type: element.type,
|
|
|
+ label: element.label,
|
|
|
+ required: element.required
|
|
|
+ };
|
|
|
+
|
|
|
+ if (element.placeholder) serialized.placeholder = element.placeholder;
|
|
|
+ if (element.id) serialized.id = element.id;
|
|
|
+ if (element.name) serialized.name = element.name;
|
|
|
+ if (element.value) serialized.value = element.value;
|
|
|
+ if (element.description) serialized.description = element.description;
|
|
|
+
|
|
|
+ if (element.options && element.options.length > 0) {
|
|
|
+ serialized.options = element.options;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (element.min !== undefined) serialized.min = element.min;
|
|
|
+ if (element.max !== undefined) serialized.max = element.max;
|
|
|
+ if (element.pattern) serialized.pattern = element.pattern;
|
|
|
+
|
|
|
+ return serialized;
|
|
|
}
|
|
|
|
|
|
- // Manejar eventos emitidos por el panel de configuración
|
|
|
+ // Eventos del panel de configuración
|
|
|
onFormTitleChange(newTitle: string) {
|
|
|
this.formTitle = newTitle;
|
|
|
}
|
|
|
|
|
|
onRowsChange(newRows: number) {
|
|
|
- this.rows = newRows;
|
|
|
- this.buildGrid();
|
|
|
+ if (this.currentTab) {
|
|
|
+ this.updateTabDimensions(this.currentTab, newRows, this.currentTab.columns);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
onColumnsChange(newCols: number) {
|
|
|
- this.columns = newCols;
|
|
|
- this.buildGrid();
|
|
|
+ if (this.currentTab) {
|
|
|
+ this.updateTabDimensions(this.currentTab, this.currentTab.rows, newCols);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
onShowTooltipChange(field: string) {
|
|
|
this.showTooltip = field;
|
|
|
}
|
|
|
|
|
|
+ // Resto de métodos existentes...
|
|
|
+ selectElementForEditing(cell: GridCell) {
|
|
|
+ this.editingElement = cell.element || null;
|
|
|
+ }
|
|
|
+
|
|
|
+ removeElementFromCell(cell: GridCell) {
|
|
|
+ cell.element = undefined;
|
|
|
+ this.updateCurrentTabGrid();
|
|
|
+ }
|
|
|
+
|
|
|
+ updateCurrentTabGrid() {
|
|
|
+ if (this.currentTab) {
|
|
|
+ this.currentTab.grid = [...this.grid];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ clearSelection() {
|
|
|
+ this.grid.forEach(row => row.forEach(c => c.selected = false));
|
|
|
+ this.selectedCell = null;
|
|
|
+ this.showElementSelector = false;
|
|
|
+ this.editingElement = null;
|
|
|
+ }
|
|
|
+
|
|
|
// Propiedades existentes para el selector de elementos
|
|
|
showElementSelector: boolean = false;
|
|
|
selectedCell: GridCell | null = null;
|