Funcionando con la edicion de los esquemas
This commit is contained in:
parent
6b72069c51
commit
64a8b41881
Binary file not shown.
|
@ -1,20 +1,20 @@
|
||||||
{
|
{
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"batch_size": {
|
"batch_size": {
|
||||||
"description": "N\u00c3\u00bamero de elementos a procesar por lote",
|
"type": "number",
|
||||||
"title": "Tama\u00c3\u00b1o de Lote",
|
"title": "Tama\u00c3\u00b1o de Lote",
|
||||||
"type": "number"
|
"description": "N\u00c3\u00bamero de elementos a procesar por lote"
|
||||||
},
|
},
|
||||||
"input_dir": {
|
"input_dir": {
|
||||||
"description": "Ruta al directorio de archivos de entrada",
|
"type": "string",
|
||||||
"title": "Directorio de Entrada",
|
"title": "Directorio de Entrada",
|
||||||
"type": "string"
|
"description": "Ruta al directorio de archivos de entrada"
|
||||||
},
|
},
|
||||||
"output_dir": {
|
"output_dir": {
|
||||||
"description": "Ruta al directorio para archivos generados",
|
"type": "string",
|
||||||
"title": "Directorio de Salida",
|
"title": "Directorio de Salida",
|
||||||
"type": "string"
|
"description": "Ruta al directorio para archivos generados"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"name": "Grupo de Ejemplo",
|
||||||
|
"description": "Scripts de demostración que muestran las funcionalidades básicas del sistema",
|
||||||
|
"version": "1.0",
|
||||||
|
"author": "Admin"
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {}
|
||||||
|
}
|
|
@ -66,13 +66,36 @@ class ConfigurationManager:
|
||||||
|
|
||||||
return {"status": "success", "path": path}
|
return {"status": "success", "path": path}
|
||||||
|
|
||||||
def get_script_groups(self) -> List[str]:
|
def get_script_groups(self) -> List[Dict[str, Any]]:
|
||||||
"""Returns list of available script groups."""
|
"""Returns list of available script groups with their descriptions."""
|
||||||
return [
|
groups = []
|
||||||
d
|
for d in os.listdir(self.script_groups_path):
|
||||||
for d in os.listdir(self.script_groups_path)
|
group_path = os.path.join(self.script_groups_path, d)
|
||||||
if os.path.isdir(os.path.join(self.script_groups_path, d))
|
if os.path.isdir(group_path):
|
||||||
]
|
description = self._get_group_description(group_path)
|
||||||
|
groups.append(
|
||||||
|
{
|
||||||
|
"id": d,
|
||||||
|
"name": description.get("name", d),
|
||||||
|
"description": description.get(
|
||||||
|
"description", "Sin descripción"
|
||||||
|
),
|
||||||
|
"version": description.get("version", "1.0"),
|
||||||
|
"author": description.get("author", "Unknown"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return groups
|
||||||
|
|
||||||
|
def _get_group_description(self, group_path: str) -> Dict[str, Any]:
|
||||||
|
"""Get description for a script group."""
|
||||||
|
description_file = os.path.join(group_path, "description.json")
|
||||||
|
try:
|
||||||
|
if os.path.exists(description_file):
|
||||||
|
with open(description_file, "r", encoding="utf-8") as f:
|
||||||
|
return json.load(f)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error reading group description: {e}")
|
||||||
|
return {}
|
||||||
|
|
||||||
def get_config(self, level: str, group: str = None) -> Dict[str, Any]:
|
def get_config(self, level: str, group: str = None) -> Dict[str, Any]:
|
||||||
"""Get configuration for specified level."""
|
"""Get configuration for specified level."""
|
||||||
|
@ -93,27 +116,159 @@ class ConfigurationManager:
|
||||||
|
|
||||||
def get_schema(self, level: str, group: str = None) -> Dict[str, Any]:
|
def get_schema(self, level: str, group: str = None) -> Dict[str, Any]:
|
||||||
"""Get schema for specified level."""
|
"""Get schema for specified level."""
|
||||||
# Clean level parameter (remove -form suffix if present)
|
|
||||||
level = level.split("-")[0]
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Clean level parameter
|
||||||
|
level = str(level).split("-")[0]
|
||||||
|
|
||||||
|
# Determine schema path based on level
|
||||||
if level == "1":
|
if level == "1":
|
||||||
path = os.path.join(self.data_path, "esquema.json")
|
path = os.path.join(self.data_path, "esquema.json")
|
||||||
|
# Try esquema.json first, then schema.json if not found
|
||||||
|
if not os.path.exists(path):
|
||||||
|
path = os.path.join(self.data_path, "schema.json")
|
||||||
elif level == "2":
|
elif level == "2":
|
||||||
path = os.path.join(self.script_groups_path, "esquema.json")
|
path = os.path.join(self.script_groups_path, group, "esquema.json")
|
||||||
|
# Try esquema.json first, then schema.json if not found
|
||||||
|
if not os.path.exists(path):
|
||||||
|
path = os.path.join(self.script_groups_path, group, "schema.json")
|
||||||
elif level == "3":
|
elif level == "3":
|
||||||
if not group:
|
if not group:
|
||||||
return {} # Return empty schema if no group is specified
|
return {"type": "object", "properties": {}}
|
||||||
path = os.path.join(self.script_groups_path, group, "esquema.json")
|
path = os.path.join(self.script_groups_path, group, "esquema.json")
|
||||||
|
# Try esquema.json first, then schema.json if not found
|
||||||
|
if not os.path.exists(path):
|
||||||
|
path = os.path.join(self.script_groups_path, group, "schema.json")
|
||||||
else:
|
else:
|
||||||
return {} # Return empty schema for invalid levels
|
return {"type": "object", "properties": {}}
|
||||||
|
|
||||||
with open(path, "r") as f:
|
# Read existing schema from whichever file exists
|
||||||
return json.load(f)
|
if os.path.exists(path):
|
||||||
except FileNotFoundError:
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
return {} # Return empty schema if file doesn't exist
|
schema = json.load(f)
|
||||||
except json.JSONDecodeError:
|
return (
|
||||||
return {} # Return empty schema if file is invalid JSON
|
schema
|
||||||
|
if isinstance(schema, dict)
|
||||||
|
else {"type": "object", "properties": {}}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create default schema if no file exists
|
||||||
|
default_schema = {"type": "object", "properties": {}}
|
||||||
|
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||||
|
with open(path, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(default_schema, f, indent=2)
|
||||||
|
return default_schema
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error loading schema: {str(e)}")
|
||||||
|
return {"type": "object", "properties": {}}
|
||||||
|
|
||||||
|
def update_schema(
|
||||||
|
self, level: str, data: Dict[str, Any], group: str = None
|
||||||
|
) -> Dict[str, str]:
|
||||||
|
"""Update schema for specified level and clean corresponding config."""
|
||||||
|
try:
|
||||||
|
# Determinar rutas de schema y config
|
||||||
|
if level == "1":
|
||||||
|
schema_path = os.path.join(self.data_path, "esquema.json")
|
||||||
|
config_path = os.path.join(self.data_path, "data.json")
|
||||||
|
elif level == "2":
|
||||||
|
schema_path = os.path.join(
|
||||||
|
self.script_groups_path, group, "esquema.json"
|
||||||
|
)
|
||||||
|
config_path = os.path.join(self.script_groups_path, group, "data.json")
|
||||||
|
elif level == "3":
|
||||||
|
if not group:
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": "Group is required for level 3",
|
||||||
|
}
|
||||||
|
schema_path = os.path.join(
|
||||||
|
self.script_groups_path, group, "esquema.json"
|
||||||
|
)
|
||||||
|
config_path = (
|
||||||
|
os.path.join(self.working_directory, "data.json")
|
||||||
|
if self.working_directory
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return {"status": "error", "message": "Invalid level"}
|
||||||
|
|
||||||
|
# Ensure directory exists
|
||||||
|
os.makedirs(os.path.dirname(schema_path), exist_ok=True)
|
||||||
|
|
||||||
|
# Validate schema structure
|
||||||
|
if (
|
||||||
|
not isinstance(data, dict)
|
||||||
|
or "type" not in data
|
||||||
|
or "properties" not in data
|
||||||
|
):
|
||||||
|
data = {
|
||||||
|
"type": "object",
|
||||||
|
"properties": data if isinstance(data, dict) else {},
|
||||||
|
}
|
||||||
|
|
||||||
|
# Write schema
|
||||||
|
with open(schema_path, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(data, f, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
|
# Clean corresponding config file
|
||||||
|
self._clean_config_for_schema(config_path, data)
|
||||||
|
|
||||||
|
return {"status": "success"}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error updating schema: {str(e)}")
|
||||||
|
return {"status": "error", "message": str(e)}
|
||||||
|
|
||||||
|
def _clean_config_for_schema(
|
||||||
|
self, config_path: str, schema: Dict[str, Any]
|
||||||
|
) -> None:
|
||||||
|
"""Clean configuration file to match schema structure."""
|
||||||
|
if not config_path or not os.path.exists(config_path):
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Cargar configuración actual
|
||||||
|
with open(config_path, "r", encoding="utf-8") as f:
|
||||||
|
config = json.load(f)
|
||||||
|
|
||||||
|
# Limpiar configuración recursivamente
|
||||||
|
cleaned_config = self._clean_object_against_schema(config, schema)
|
||||||
|
|
||||||
|
# Guardar configuración limpia
|
||||||
|
with open(config_path, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(cleaned_config, f, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error cleaning config: {str(e)}")
|
||||||
|
|
||||||
|
def _clean_object_against_schema(
|
||||||
|
self, data: Dict[str, Any], schema: Dict[str, Any]
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
"""Recursively clean object to match schema structure."""
|
||||||
|
if not isinstance(data, dict) or not isinstance(schema, dict):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
result = {}
|
||||||
|
schema_props = schema.get("properties", {})
|
||||||
|
|
||||||
|
for key, value in data.items():
|
||||||
|
# Solo mantener campos que existen en el schema
|
||||||
|
if key in schema_props:
|
||||||
|
prop_schema = schema_props[key]
|
||||||
|
|
||||||
|
# Si es un objeto anidado, limpiar recursivamente
|
||||||
|
if prop_schema.get("type") == "object":
|
||||||
|
result[key] = self._clean_object_against_schema(value, prop_schema)
|
||||||
|
# Si es un enum, verificar que el valor sea válido
|
||||||
|
elif "enum" in prop_schema:
|
||||||
|
if value in prop_schema["enum"]:
|
||||||
|
result[key] = value
|
||||||
|
# Para otros tipos, mantener el valor
|
||||||
|
else:
|
||||||
|
result[key] = value
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
def update_config(
|
def update_config(
|
||||||
self, level: str, data: Dict[str, Any], group: str = None
|
self, level: str, data: Dict[str, Any], group: str = None
|
||||||
|
@ -132,20 +287,6 @@ class ConfigurationManager:
|
||||||
with open(path, "w") as f:
|
with open(path, "w") as f:
|
||||||
json.dump(data, f, indent=2)
|
json.dump(data, f, indent=2)
|
||||||
|
|
||||||
def update_schema(
|
|
||||||
self, level: str, data: Dict[str, Any], group: str = None
|
|
||||||
) -> None:
|
|
||||||
"""Update schema for specified level."""
|
|
||||||
if level == "1":
|
|
||||||
path = os.path.join(self.data_path, "esquema.json")
|
|
||||||
elif level == "2":
|
|
||||||
path = os.path.join(self.script_groups_path, "esquema.json")
|
|
||||||
elif level == "3":
|
|
||||||
path = os.path.join(self.script_groups_path, group, "esquema.json")
|
|
||||||
|
|
||||||
with open(path, "w") as f:
|
|
||||||
json.dump(data, f, indent=2)
|
|
||||||
|
|
||||||
def list_scripts(self, group: str) -> List[Dict[str, str]]:
|
def list_scripts(self, group: str) -> List[Dict[str, str]]:
|
||||||
"""List all scripts in a group with their descriptions."""
|
"""List all scripts in a group with their descriptions."""
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
{
|
{
|
||||||
"api_key": "your-api-key-here",
|
"api_key": "your-api-key-here",
|
||||||
"model": "gpt-3.5-turbo",
|
"model": "gpt-3.5-turbo"
|
||||||
"max_tokens": 1000,
|
|
||||||
"temperature": 0.7
|
|
||||||
}
|
}
|
|
@ -1,32 +1,20 @@
|
||||||
{
|
{
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"api_key": {
|
"api_key": {
|
||||||
"description": "Tu clave de API para servicios externos",
|
"type": "string",
|
||||||
"title": "API Key",
|
"title": "API Key",
|
||||||
"type": "string"
|
"description": "Tu clave de API para servicios externos"
|
||||||
},
|
|
||||||
"max_tokens": {
|
|
||||||
"description": "N\u00c3\u00bamero m\u00c3\u00a1ximo de tokens por respuesta",
|
|
||||||
"title": "Tokens M\u00c3\u00a1ximos",
|
|
||||||
"type": "number"
|
|
||||||
},
|
},
|
||||||
"model": {
|
"model": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "Modelo LLM",
|
||||||
"description": "Modelo de lenguaje a utilizar",
|
"description": "Modelo de lenguaje a utilizar",
|
||||||
"enum": [
|
"enum": [
|
||||||
"gpt-3.5-turbo",
|
"gpt-3.5-turbo",
|
||||||
"gpt-4",
|
"gpt-4",
|
||||||
"claude-v1"
|
"claude-v1"
|
||||||
],
|
]
|
||||||
"title": "Modelo LLM",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"temperature": {
|
|
||||||
"description": "Creatividad de las respuestas (0-1)",
|
|
||||||
"maximum": 1,
|
|
||||||
"minimum": 0,
|
|
||||||
"title": "Temperatura",
|
|
||||||
"type": "number"
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
|
@ -5,9 +5,7 @@ Iniciando ejecución de x1.py...
|
||||||
Configuraciones cargadas:
|
Configuraciones cargadas:
|
||||||
Nivel 1: {
|
Nivel 1: {
|
||||||
"api_key": "your-api-key-here",
|
"api_key": "your-api-key-here",
|
||||||
"model": "gpt-3.5-turbo",
|
"model": "gpt-3.5-turbo"
|
||||||
"max_tokens": 1000,
|
|
||||||
"temperature": 0.7
|
|
||||||
}
|
}
|
||||||
Nivel 2: {
|
Nivel 2: {
|
||||||
"input_dir": "D:/Datos/Entrada",
|
"input_dir": "D:/Datos/Entrada",
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {}
|
||||||
|
}
|
|
@ -92,7 +92,7 @@
|
||||||
|
|
||||||
// Form rendering functionality
|
// Form rendering functionality
|
||||||
async function renderForm(containerId, data) {
|
async function renderForm(containerId, data) {
|
||||||
console.log(`Rendering form for ${containerId}`); // Debug line
|
console.log(`Rendering form for ${containerId} with data:`, data); // Debug line
|
||||||
const container = document.getElementById(containerId);
|
const container = document.getElementById(containerId);
|
||||||
const level = containerId.replace('level', '').split('-')[0];
|
const level = containerId.replace('level', '').split('-')[0];
|
||||||
|
|
||||||
|
@ -101,13 +101,14 @@
|
||||||
const schema = await schemaResponse.json();
|
const schema = await schemaResponse.json();
|
||||||
console.log(`Schema for level ${level}:`, schema); // Debug line
|
console.log(`Schema for level ${level}:`, schema); // Debug line
|
||||||
|
|
||||||
if (Object.keys(schema).length === 0) {
|
if (!schema || !schema.properties || Object.keys(schema.properties).length === 0) {
|
||||||
container.innerHTML = '<p class="text-gray-500">No hay esquema definido para este nivel.</p>';
|
container.innerHTML = '<p class="text-gray-500">No hay esquema definido para este nivel.</p>';
|
||||||
} else {
|
return;
|
||||||
const formHtml = generateFormFields(schema, data, '', level);
|
|
||||||
console.log(`Generated HTML for ${containerId}:`, formHtml.substring(0, 100) + '...'); // Debug line
|
|
||||||
container.innerHTML = formHtml;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const formHtml = generateFormFields(schema, data || {}, '', level);
|
||||||
|
console.log(`Generated HTML for ${containerId}:`, formHtml.substring(0, 100) + '...'); // Debug line
|
||||||
|
container.innerHTML = formHtml;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error rendering form ${containerId}:`, error);
|
console.error(`Error rendering form ${containerId}:`, error);
|
||||||
container.innerHTML = '<p class="text-red-500">Error cargando el esquema.</p>';
|
container.innerHTML = '<p class="text-red-500">Error cargando el esquema.</p>';
|
||||||
|
@ -115,10 +116,18 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateFormFields(schema, data, prefix, level) {
|
function generateFormFields(schema, data, prefix, level) {
|
||||||
|
console.log('Generating fields with data:', { schema, data, prefix, level }); // Debug line
|
||||||
let html = '';
|
let html = '';
|
||||||
|
|
||||||
|
if (!schema.properties) {
|
||||||
|
console.warn('Schema has no properties');
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
for (const [key, def] of Object.entries(schema.properties)) {
|
for (const [key, def] of Object.entries(schema.properties)) {
|
||||||
const fullKey = prefix ? `${prefix}.${key}` : key;
|
const fullKey = prefix ? `${prefix}.${key}` : key;
|
||||||
const value = getValue(data, fullKey);
|
const value = getValue(data, fullKey);
|
||||||
|
console.log(`Field ${fullKey}:`, { definition: def, value: value }); // Debug line
|
||||||
|
|
||||||
html += `<div class="mb-4">
|
html += `<div class="mb-4">
|
||||||
<label class="block text-gray-700 text-sm font-bold mb-2">${def.title || key}</label>`;
|
<label class="block text-gray-700 text-sm font-bold mb-2">${def.title || key}</label>`;
|
||||||
|
@ -139,6 +148,15 @@
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getValue(data, path) {
|
||||||
|
console.log('Getting value for path:', { path, data }); // Debug line
|
||||||
|
if (!data || !path) return undefined;
|
||||||
|
|
||||||
|
const value = path.split('.').reduce((obj, key) => obj?.[key], data);
|
||||||
|
console.log('Found value:', value); // Debug line
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
function generateInputField(def, key, value, level) {
|
function generateInputField(def, key, value, level) {
|
||||||
const baseClasses = "w-full p-2 border rounded bg-green-50"; // Agregado bg-green-50 para fondo verde claro
|
const baseClasses = "w-full p-2 border rounded bg-green-50"; // Agregado bg-green-50 para fondo verde claro
|
||||||
|
|
||||||
|
@ -177,33 +195,45 @@
|
||||||
try {
|
try {
|
||||||
console.log('Loading schema for level:', level); // Debug line
|
console.log('Loading schema for level:', level); // Debug line
|
||||||
const response = await fetch(`/api/schema/${level}?group=${currentGroup}`);
|
const response = await fetch(`/api/schema/${level}?group=${currentGroup}`);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
const schema = await response.json();
|
const schema = await response.json();
|
||||||
console.log('Loaded schema:', schema); // Debug line
|
console.log('Loaded schema:', schema); // Debug line
|
||||||
|
|
||||||
// Show schema editor modal
|
// Show schema editor modal
|
||||||
const modal = document.getElementById('schema-editor');
|
const modal = document.getElementById('schema-editor');
|
||||||
|
if (!modal) {
|
||||||
|
throw new Error('Schema editor modal not found');
|
||||||
|
}
|
||||||
modal.classList.remove('hidden');
|
modal.classList.remove('hidden');
|
||||||
|
|
||||||
// Inicializar JSON editor
|
// Inicializar el esquema si está vacío
|
||||||
const jsonEditor = document.getElementById('json-editor');
|
const finalSchema = Object.keys(schema).length === 0 ?
|
||||||
jsonEditor.value = JSON.stringify(schema, null, 2);
|
{ type: 'object', properties: {} } : schema;
|
||||||
|
|
||||||
// Inicializar visual editor
|
// Inicializar editores
|
||||||
|
const jsonEditor = document.getElementById('json-editor');
|
||||||
const visualEditor = document.getElementById('visual-editor');
|
const visualEditor = document.getElementById('visual-editor');
|
||||||
|
const schemaLevel = document.getElementById('schema-level');
|
||||||
|
|
||||||
|
if (!jsonEditor || !visualEditor || !schemaLevel) {
|
||||||
|
throw new Error('Required editor elements not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonEditor.value = JSON.stringify(finalSchema, null, 2);
|
||||||
visualEditor.innerHTML = '<div id="schema-fields" class="mb-4"></div>' +
|
visualEditor.innerHTML = '<div id="schema-fields" class="mb-4"></div>' +
|
||||||
'<button onclick="addSchemaField()" class="mt-4 bg-green-500 text-white px-4 py-2 rounded">Agregar Campo</button>';
|
'<button onclick="addSchemaField()" class="mt-4 bg-green-500 text-white px-4 py-2 rounded">Agregar Campo</button>';
|
||||||
|
schemaLevel.value = level;
|
||||||
|
|
||||||
// Renderizar campos existentes
|
// Renderizar editor visual
|
||||||
renderVisualEditor(schema);
|
renderVisualEditor(finalSchema);
|
||||||
|
|
||||||
// Guardar nivel actual
|
|
||||||
document.getElementById('schema-level').value = level;
|
|
||||||
|
|
||||||
// Activar pestaña visual por defecto
|
// Activar pestaña visual por defecto
|
||||||
switchEditorMode('visual');
|
switchEditorMode('visual');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading schema:', error);
|
console.error('Error loading schema:', error);
|
||||||
alert('Error cargando el esquema');
|
alert('Error cargando el esquema: ' + error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,11 +248,27 @@
|
||||||
jsonEditor.classList.add('hidden');
|
jsonEditor.classList.add('hidden');
|
||||||
visualTab.classList.add('border-blue-500');
|
visualTab.classList.add('border-blue-500');
|
||||||
jsonTab.classList.remove('border-blue-500');
|
jsonTab.classList.remove('border-blue-500');
|
||||||
|
|
||||||
|
// Actualizar el editor visual desde JSON
|
||||||
|
try {
|
||||||
|
const schema = JSON.parse(jsonEditor.value);
|
||||||
|
renderVisualEditor(schema);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Error parsing JSON:', e);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
visualEditor.classList.add('hidden');
|
visualEditor.classList.add('hidden');
|
||||||
jsonEditor.classList.remove('hidden');
|
jsonEditor.classList.remove('hidden');
|
||||||
visualTab.classList.remove('border-blue-500');
|
visualTab.classList.remove('border-blue-500');
|
||||||
jsonTab.classList.add('border-blue-500');
|
jsonTab.classList.add('border-blue-500');
|
||||||
|
|
||||||
|
// Actualizar el JSON desde el editor visual
|
||||||
|
try {
|
||||||
|
const schema = updateVisualSchema();
|
||||||
|
jsonEditor.value = JSON.stringify(schema, null, 2);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Error updating JSON:', e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,91 +379,85 @@
|
||||||
|
|
||||||
// Funciones de actualización del esquema visual
|
// Funciones de actualización del esquema visual
|
||||||
function updateVisualSchema() {
|
function updateVisualSchema() {
|
||||||
const fields = document.getElementById('schema-fields').children;
|
try {
|
||||||
const schema = {
|
const fields = document.getElementById('schema-fields').children;
|
||||||
type: 'object',
|
const schema = {
|
||||||
properties: {}
|
type: 'object',
|
||||||
};
|
properties: {}
|
||||||
|
|
||||||
Array.from(fields).forEach(field => {
|
|
||||||
const inputs = field.getElementsByTagName('input');
|
|
||||||
const select = field.getElementsByTagName('select')[0];
|
|
||||||
const key = inputs[0].value;
|
|
||||||
|
|
||||||
schema.properties[key] = {
|
|
||||||
type: select.value === 'enum' ? 'string' : select.value,
|
|
||||||
title: inputs[1].value,
|
|
||||||
description: inputs[2].value
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (select.value === 'enum') {
|
Array.from(fields).forEach(field => {
|
||||||
const textarea = field.getElementsByTagName('textarea')[0];
|
const inputs = field.getElementsByTagName('input');
|
||||||
schema.properties[key].enum = textarea.value.split('\n').filter(v => v.trim());
|
const select = field.getElementsByTagName('select')[0];
|
||||||
}
|
const key = inputs[0].value;
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById('schema-content').value = JSON.stringify(schema, null, 2);
|
schema.properties[key] = {
|
||||||
return schema;
|
type: select.value === 'enum' ? 'string' : select.value,
|
||||||
|
title: inputs[1].value,
|
||||||
|
description: inputs[2].value
|
||||||
|
};
|
||||||
|
|
||||||
|
if (select.value === 'enum') {
|
||||||
|
const textarea = field.getElementsByTagName('textarea')[0];
|
||||||
|
if (textarea) {
|
||||||
|
schema.properties[key].enum = textarea.value.split('\n').filter(v => v.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Actualizar el JSON editor directamente
|
||||||
|
const jsonEditor = document.getElementById('json-editor');
|
||||||
|
if (jsonEditor) {
|
||||||
|
jsonEditor.value = JSON.stringify(schema, null, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return schema;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error updating schema:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveSchema() {
|
async function saveSchema() {
|
||||||
try {
|
try {
|
||||||
const level = document.getElementById('schema-level').value;
|
const level = document.getElementById('schema-level').value;
|
||||||
const schema = updateVisualSchema();
|
let schema;
|
||||||
|
|
||||||
await fetch(`/api/schema/${level}?group=${currentGroup}`, {
|
// Obtener el esquema según el modo activo
|
||||||
|
const visualEditor = document.getElementById('visual-editor');
|
||||||
|
const jsonEditor = document.getElementById('json-editor');
|
||||||
|
|
||||||
|
if (!visualEditor.classList.contains('hidden')) {
|
||||||
|
schema = updateVisualSchema();
|
||||||
|
} else {
|
||||||
|
schema = JSON.parse(jsonEditor.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Saving schema:', schema); // Debug line
|
||||||
|
|
||||||
|
const response = await fetch(`/api/schema/${level}?group=${currentGroup}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify(schema)
|
body: JSON.stringify(schema)
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await fetch(`/api/config/${level}?group=${currentGroup}`);
|
if (!response.ok) {
|
||||||
const data = await response.json();
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
renderForm(`level${level}-form`, data);
|
}
|
||||||
|
|
||||||
|
// Recargar el formulario
|
||||||
|
const configResponse = await fetch(`/api/config/${level}?group=${currentGroup}`);
|
||||||
|
const data = await configResponse.json();
|
||||||
|
await renderForm(`level${level}-form`, data);
|
||||||
|
|
||||||
|
// Cerrar modal
|
||||||
document.getElementById('schema-editor').classList.add('hidden');
|
document.getElementById('schema-editor').classList.add('hidden');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
console.error('Error saving schema:', e);
|
||||||
alert('Error guardando esquema: ' + e.message);
|
alert('Error guardando esquema: ' + e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getValue(data, path) {
|
|
||||||
return path.split('.').reduce((obj, key) => obj?.[key], data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualizar configuración cuando cambia un campo
|
|
||||||
async function updateConfig(level, key, value) {
|
|
||||||
const group = currentGroup;
|
|
||||||
// Obtener configuración actual
|
|
||||||
const response = await fetch(`/api/config/${level}?group=${group}`);
|
|
||||||
const config = await response.json();
|
|
||||||
|
|
||||||
// Actualizar el valor usando la ruta del campo
|
|
||||||
setNestedValue(config, key, value);
|
|
||||||
|
|
||||||
// Guardar configuración actualizada
|
|
||||||
await fetch(`/api/config/${level}?group=${group}`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify(config)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Función auxiliar para establecer valor en objeto anidado
|
|
||||||
function setNestedValue(obj, path, value) {
|
|
||||||
const keys = path.split('.');
|
|
||||||
let current = obj;
|
|
||||||
|
|
||||||
for (let i = 0; i < keys.length - 1; i++) {
|
|
||||||
if (!(keys[i] in current)) {
|
|
||||||
current[keys[i]] = {};
|
|
||||||
}
|
|
||||||
current = current[keys[i]];
|
|
||||||
}
|
|
||||||
|
|
||||||
current[keys[keys.length - 1]] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function setWorkingDirectory() {
|
async function setWorkingDirectory() {
|
||||||
if (!currentGroup) {
|
if (!currentGroup) {
|
||||||
alert('Por favor, seleccione un grupo de scripts primero');
|
alert('Por favor, seleccione un grupo de scripts primero');
|
||||||
|
@ -537,6 +577,17 @@
|
||||||
}
|
}
|
||||||
currentGroup = selectElement.value; // Siempre establecer currentGroup con el valor actual del select
|
currentGroup = selectElement.value; // Siempre establecer currentGroup con el valor actual del select
|
||||||
console.log('Current group initialized as:', currentGroup); // Debug line
|
console.log('Current group initialized as:', currentGroup); // Debug line
|
||||||
|
updateGroupDescription(); // Actualizar descripción inicial
|
||||||
|
|
||||||
|
// Configurar el evento de cambio de grupo
|
||||||
|
selectElement.addEventListener('change', async (e) => {
|
||||||
|
currentGroup = e.target.value;
|
||||||
|
localStorage.setItem('selectedGroup', e.target.value);
|
||||||
|
console.log('Group changed to:', currentGroup); // Debug line
|
||||||
|
updateGroupDescription(); // Actualizar descripción al cambiar
|
||||||
|
await initWorkingDirectory();
|
||||||
|
await loadConfigs();
|
||||||
|
});
|
||||||
|
|
||||||
// Luego cargar el directorio de trabajo
|
// Luego cargar el directorio de trabajo
|
||||||
await initWorkingDirectory();
|
await initWorkingDirectory();
|
||||||
|
@ -582,6 +633,13 @@
|
||||||
logArea.innerHTML += lines;
|
logArea.innerHTML += lines;
|
||||||
logArea.scrollTop = logArea.scrollHeight;
|
logArea.scrollTop = logArea.scrollHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateGroupDescription() {
|
||||||
|
const select = document.getElementById('script-group');
|
||||||
|
const option = select.options[select.selectedIndex];
|
||||||
|
const description = option.getAttribute('data-description');
|
||||||
|
document.getElementById('group-description').textContent = description;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-gray-100">
|
<body class="bg-gray-100">
|
||||||
|
@ -606,11 +664,16 @@
|
||||||
<!-- Script Group Selection -->
|
<!-- Script Group Selection -->
|
||||||
<div class="mb-8 bg-white p-6 rounded-lg shadow">
|
<div class="mb-8 bg-white p-6 rounded-lg shadow">
|
||||||
<h2 class="text-xl font-bold mb-4">Grupo de Scripts</h2>
|
<h2 class="text-xl font-bold mb-4">Grupo de Scripts</h2>
|
||||||
<select id="script-group" class="w-full p-2 border rounded">
|
<select id="script-group" class="w-full p-2 border rounded mb-2">
|
||||||
{% for group in script_groups %}
|
{% for group in script_groups %}
|
||||||
<option value="{{ group }}">{{ group }}</option>
|
<option value="{{ group.id }}" data-description="{{ group.description }}">{{ group.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
|
<p id="group-description" class="text-gray-600 text-sm italic"></p>
|
||||||
|
<div class="text-xs text-gray-500 mt-2">
|
||||||
|
<span id="group-version"></span>
|
||||||
|
<span id="group-author"></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Level 2 Configuration -->
|
<!-- Level 2 Configuration -->
|
||||||
|
|
Loading…
Reference in New Issue