g360-cli 1.13.1 → 1.14.0
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/package.json +1 -1
- package/src/assets/config/g360-skills.json +39 -0
- package/src/assets/config/project-types.json +15 -4
- package/src/assets/templates/python-flet/README.md +6 -1
- package/src/assets/templates/python-flet/pyproject.toml +1 -2
- package/src/assets/templates/python-flet-polished/README.md +170 -0
- package/src/assets/templates/python-flet-polished/assets/data/sample_data.json +12 -0
- package/src/assets/templates/python-flet-polished/assets/fonts/Inter-Variable.ttf +0 -0
- package/src/assets/templates/python-flet-polished/assets/fonts/JetBrainsMono-Variable.ttf +0 -0
- package/src/assets/templates/python-flet-polished/assets/images/app.ico +0 -0
- package/src/assets/templates/python-flet-polished/assets/images/logo.svg +9 -0
- package/src/assets/templates/python-flet-polished/build-portable.bat +42 -0
- package/src/assets/templates/python-flet-polished/create_shortcut.vbs +15 -0
- package/src/assets/templates/python-flet-polished/g360_flet/__init__.py +0 -0
- package/src/assets/templates/python-flet-polished/g360_flet/g360_signature.py +210 -0
- package/src/assets/templates/python-flet-polished/launch.vbs +3 -0
- package/src/assets/templates/python-flet-polished/launch_minimized.bat +3 -0
- package/src/assets/templates/python-flet-polished/main.py +47 -0
- package/src/assets/templates/python-flet-polished/pyproject.toml +18 -0
- package/src/assets/templates/python-flet-polished/requirements.txt +3 -0
- package/src/assets/templates/python-flet-polished/run.bat +189 -0
- package/src/assets/templates/python-flet-polished/skill.json +28 -0
- package/src/assets/templates/python-flet-polished/src/__init__.py +0 -0
- package/src/assets/templates/python-flet-polished/src/app.py +343 -0
- package/src/assets/templates/python-flet-polished/src/config/__init__.py +0 -0
- package/src/assets/templates/python-flet-polished/src/config/theme.py +122 -0
- package/src/assets/templates/python-flet-polished/src/core/__init__.py +0 -0
- package/src/assets/templates/python-flet-polished/src/core/constants.py +49 -0
- package/src/assets/templates/python-flet-polished/src/core/processor.py +128 -0
- package/src/assets/templates/python-flet-polished/src/core/skill.json +41 -0
- package/src/assets/templates/python-flet-polished/src/ui/__init__.py +0 -0
- package/src/assets/templates/python-flet-polished/src/ui/dashboard.py +308 -0
- package/src/assets/templates/python-flet-polished/src/ui/kpi_card.py +69 -0
- package/src/assets/templates/python-flet-polished/src/ui/search_overlay.py +143 -0
- package/src/assets/templates/python-flet-polished/sync_portable.py +71 -0
- package/src/cli.js +4 -4
- package/src/commands/init.js +33 -2
- package/py/src/g360_core/__pycache__/__init__.cpython-312.pyc +0 -0
- package/py/src/g360_core/__pycache__/__init__.cpython-314.pyc +0 -0
- package/py/src/g360_core/__pycache__/batch_processor.cpython-312.pyc +0 -0
- package/py/src/g360_core/__pycache__/batch_processor.cpython-314.pyc +0 -0
- package/py/src/g360_core/__pycache__/commercial_engine.cpython-314.pyc +0 -0
- package/py/src/g360_core/__pycache__/logger.cpython-312.pyc +0 -0
- package/py/src/g360_core/__pycache__/logger.cpython-314.pyc +0 -0
- package/py/src/g360_core/__pycache__/pipeline.cpython-312.pyc +0 -0
- package/py/src/g360_core/__pycache__/pipeline.cpython-314.pyc +0 -0
- package/py/src/g360_core/__pycache__/processor.cpython-312.pyc +0 -0
- package/py/src/g360_core/__pycache__/processor.cpython-314.pyc +0 -0
- package/py/src/g360_core/__pycache__/processor_segmentacion.cpython-312.pyc +0 -0
- package/py/src/g360_core/__pycache__/processor_segmentacion.cpython-314.pyc +0 -0
- package/py/src/g360_core/__pycache__/processor_sku.cpython-312.pyc +0 -0
- package/py/src/g360_core/__pycache__/processor_sku.cpython-314.pyc +0 -0
- package/py/src/g360_core/__pycache__/scanner.cpython-312.pyc +0 -0
- package/py/src/g360_core/__pycache__/scanner.cpython-314.pyc +0 -0
- package/py/src/g360_core/__pycache__/utils.cpython-312.pyc +0 -0
- package/py/src/g360_core/__pycache__/utils.cpython-314.pyc +0 -0
- package/src/assets/ingestion/core/__pycache__/ingestion.cpython-312.pyc +0 -0
- package/src/assets/signature/g360_flet/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/assets/signature/g360_flet/__pycache__/__init__.cpython-314.pyc +0 -0
- package/src/assets/signature/g360_flet/__pycache__/g360_signature.cpython-312.pyc +0 -0
- package/src/assets/signature/g360_flet/__pycache__/g360_signature.cpython-314.pyc +0 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""
|
|
2
|
+
G360 KPI Card - Componente reutilizable para indicadores clave.
|
|
3
|
+
|
|
4
|
+
Patron: Card con glow backlight por color, valor numerico grande,
|
|
5
|
+
subtexto opcional. Clickable para abrir dialogos detallados.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import flet as ft
|
|
10
|
+
from src.config.theme import rgba
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class KPICard(ft.Container):
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
label: str,
|
|
17
|
+
value: str,
|
|
18
|
+
color: str,
|
|
19
|
+
subtext: str = "",
|
|
20
|
+
on_click=None,
|
|
21
|
+
):
|
|
22
|
+
super().__init__()
|
|
23
|
+
self._label = label
|
|
24
|
+
self._value = value
|
|
25
|
+
self._color = color
|
|
26
|
+
self._subtext = subtext
|
|
27
|
+
self._on_click = on_click
|
|
28
|
+
|
|
29
|
+
self.content = ft.Column(
|
|
30
|
+
controls=[
|
|
31
|
+
ft.Text(label, size=11, color=rgba(color, 0.8), weight=ft.FontWeight.W_500),
|
|
32
|
+
ft.Container(height=4),
|
|
33
|
+
ft.Text(
|
|
34
|
+
value,
|
|
35
|
+
size=22,
|
|
36
|
+
color=color,
|
|
37
|
+
weight=ft.FontWeight.W_700,
|
|
38
|
+
font_family="JetBrains Mono",
|
|
39
|
+
),
|
|
40
|
+
ft.Container(height=2),
|
|
41
|
+
ft.Text(subtext, size=10, color=rgba(color, 0.6)),
|
|
42
|
+
],
|
|
43
|
+
spacing=0,
|
|
44
|
+
horizontal_alignment=ft.CrossAxisAlignment.START,
|
|
45
|
+
)
|
|
46
|
+
self.padding = ft.Padding(left=14, right=14, top=10, bottom=10)
|
|
47
|
+
self.bgcolor = rgba(color, 0.08)
|
|
48
|
+
self.border_radius = 10
|
|
49
|
+
self.shadow = ft.BoxShadow(
|
|
50
|
+
spread_radius=0.5,
|
|
51
|
+
blur_radius=12,
|
|
52
|
+
color=rgba(color, 0.15),
|
|
53
|
+
offset=ft.Offset(0, 2),
|
|
54
|
+
)
|
|
55
|
+
self.border = ft.Border(bottom=ft.BorderSide(2, rgba(color, 0.4)))
|
|
56
|
+
self.cursor_type = ft.CursorType.CLICK if on_click else ft.CursorType.NONE
|
|
57
|
+
|
|
58
|
+
if on_click:
|
|
59
|
+
self.on_click = on_click
|
|
60
|
+
else:
|
|
61
|
+
self.on_click = None
|
|
62
|
+
|
|
63
|
+
def update_value(self, value: str, subtext: str = ""):
|
|
64
|
+
self._value = value
|
|
65
|
+
self._subtext = subtext
|
|
66
|
+
self.content.controls[2].value = value
|
|
67
|
+
if len(self.content.controls) > 3:
|
|
68
|
+
self.content.controls[3].value = subtext
|
|
69
|
+
self.update()
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"""
|
|
2
|
+
G360 Search Overlay - Buscador flotante con debounce.
|
|
3
|
+
|
|
4
|
+
Busqueda contextual en tiempo real con resultados en vivo.
|
|
5
|
+
Enter abre el primer resultado, Escape o click fuera cierra.
|
|
6
|
+
Auto-limpieza al enfocar con texto previo.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import asyncio
|
|
11
|
+
|
|
12
|
+
import flet as ft
|
|
13
|
+
from src.config.theme import rgba
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SearchOverlay(ft.Container):
|
|
17
|
+
def __init__(self, page: ft.Page, colors: dict):
|
|
18
|
+
super().__init__()
|
|
19
|
+
self.page = page
|
|
20
|
+
self.c = colors
|
|
21
|
+
self._results: list[dict] = []
|
|
22
|
+
self._debounce_task = None
|
|
23
|
+
self._selected_index = 0
|
|
24
|
+
|
|
25
|
+
self.field = ft.TextField(
|
|
26
|
+
hint_text="Buscar SKU, descripción, línea...",
|
|
27
|
+
border_radius=10,
|
|
28
|
+
height=44,
|
|
29
|
+
text_size=13,
|
|
30
|
+
dense=True,
|
|
31
|
+
border=ft.InputBorder.OUTLINE,
|
|
32
|
+
border_color=self.c["border"],
|
|
33
|
+
focused_border_color=self.c["accent"],
|
|
34
|
+
cursor_color=self.c["accent"],
|
|
35
|
+
hint_style=ft.TextStyle(size=12, color=self.c["text_muted"]),
|
|
36
|
+
autofocus=True,
|
|
37
|
+
on_change=self._on_change,
|
|
38
|
+
on_submit=self._on_submit,
|
|
39
|
+
on_focus=self._on_focus,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
self.content = ft.Column(
|
|
43
|
+
controls=[
|
|
44
|
+
self.field,
|
|
45
|
+
ft.Container(
|
|
46
|
+
content=ft.Column([], scroll=ft.ScrollMode.AUTO, max_height=300, id="search_results"),
|
|
47
|
+
bgcolor=self.c["surface"],
|
|
48
|
+
border_radius=ft.BorderRadius.only(bottom_left=10, bottom_right=10),
|
|
49
|
+
border=ft.border.Top(border_color=self.c["border"], border_style=ft.BorderSide(1)),
|
|
50
|
+
visible=False,
|
|
51
|
+
padding=ft.Padding(left=0, right=0, top=0, bottom=0),
|
|
52
|
+
max_height=300,
|
|
53
|
+
height=300,
|
|
54
|
+
),
|
|
55
|
+
],
|
|
56
|
+
spacing=0,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
self.bgcolor = self.c["surface"]
|
|
60
|
+
self.border_radius = 10
|
|
61
|
+
self.padding = ft.Padding(left=16, right=16, top=12, bottom=12)
|
|
62
|
+
self.width = 480
|
|
63
|
+
self.alignment = ft.alignment.top_center
|
|
64
|
+
self.margin = ft.margin.only(top=60)
|
|
65
|
+
|
|
66
|
+
def _on_focus(self, e):
|
|
67
|
+
if self.field.value:
|
|
68
|
+
self.field.value = ""
|
|
69
|
+
self.field.update()
|
|
70
|
+
|
|
71
|
+
async def _on_change(self, e):
|
|
72
|
+
query = (e.control.value or "").strip().lower()
|
|
73
|
+
if self._debounce_task:
|
|
74
|
+
self._debounce_task.cancel()
|
|
75
|
+
if len(query) < 2:
|
|
76
|
+
self._hide_results()
|
|
77
|
+
return
|
|
78
|
+
self._debounce_task = asyncio.create_task(self._debounce_search(query))
|
|
79
|
+
|
|
80
|
+
async def _debounce_search(self, query: str):
|
|
81
|
+
await asyncio.sleep(0.25)
|
|
82
|
+
self._results = await self._do_search(query)
|
|
83
|
+
self._show_results(self._results)
|
|
84
|
+
|
|
85
|
+
async def _do_search(self, query: str) -> list[dict]:
|
|
86
|
+
"""Implementar en subclase. Retorna lista de dicts {sku, desc, ...}."""
|
|
87
|
+
return []
|
|
88
|
+
|
|
89
|
+
def _show_results(self, results: list[dict]):
|
|
90
|
+
if not results:
|
|
91
|
+
self._hide_results()
|
|
92
|
+
return
|
|
93
|
+
controls = []
|
|
94
|
+
for i, item in enumerate(results[:10]):
|
|
95
|
+
is_selected = i == self._selected_index
|
|
96
|
+
controls.append(
|
|
97
|
+
ft.Container(
|
|
98
|
+
content=ft.Row([
|
|
99
|
+
ft.Text(item.get("sku", ""), size=12, color=self.c["accent"], weight=ft.FontWeight.W_600),
|
|
100
|
+
ft.Container(width=8),
|
|
101
|
+
ft.Text(item.get("desc", item.get("descripcion", "")), size=12, color=self.c["text_primary"]),
|
|
102
|
+
], spacing=0),
|
|
103
|
+
bgcolor=rgba(self.c["accent"], 0.1) if is_selected else "transparent",
|
|
104
|
+
border_radius=6,
|
|
105
|
+
padding=ft.Padding(left=12, right=12, top=8, bottom=8),
|
|
106
|
+
on_click=lambda _, r=item: self._on_select(r),
|
|
107
|
+
mouse_cursor=ft.CursorType.CLICK,
|
|
108
|
+
)
|
|
109
|
+
)
|
|
110
|
+
results_col = self.content.controls[1]
|
|
111
|
+
results_col.content.controls = controls
|
|
112
|
+
results_col.visible = True
|
|
113
|
+
self.update()
|
|
114
|
+
|
|
115
|
+
def _hide_results(self):
|
|
116
|
+
results_col = self.content.controls[1]
|
|
117
|
+
results_col.content.controls = []
|
|
118
|
+
results_col.visible = False
|
|
119
|
+
self.update()
|
|
120
|
+
|
|
121
|
+
def _on_submit(self, e):
|
|
122
|
+
if self._results:
|
|
123
|
+
self._on_select(self._results[self._selected_index])
|
|
124
|
+
|
|
125
|
+
def _on_select(self, item: dict):
|
|
126
|
+
self._hide_results()
|
|
127
|
+
self.page.close(self)
|
|
128
|
+
|
|
129
|
+
def did_mount(self):
|
|
130
|
+
"""Captura Escape para cerrar."""
|
|
131
|
+
def on_keyboard(e: ft.KeyboardEvent):
|
|
132
|
+
if e.key == "Escape":
|
|
133
|
+
self.page.close(self)
|
|
134
|
+
elif e.key == "ArrowDown":
|
|
135
|
+
self._selected_index = min(self._selected_index + 1, len(self._results) - 1)
|
|
136
|
+
self._show_results(self._results)
|
|
137
|
+
elif e.key == "ArrowUp":
|
|
138
|
+
self._selected_index = max(self._selected_index - 1, 0)
|
|
139
|
+
self._show_results(self._results)
|
|
140
|
+
elif e.key == "Enter" and self._results:
|
|
141
|
+
self._on_select(self._results[self._selected_index])
|
|
142
|
+
|
|
143
|
+
self.page.on_keyboard_event = on_keyboard
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def sync_dir(src, dst):
|
|
7
|
+
if not os.path.exists(src):
|
|
8
|
+
return
|
|
9
|
+
if not os.path.exists(dst):
|
|
10
|
+
os.makedirs(dst)
|
|
11
|
+
for item in os.listdir(dst):
|
|
12
|
+
dst_item = os.path.join(dst, item)
|
|
13
|
+
src_item = os.path.join(src, item)
|
|
14
|
+
if not os.path.exists(src_item):
|
|
15
|
+
if os.path.isdir(dst_item):
|
|
16
|
+
shutil.rmtree(dst_item)
|
|
17
|
+
print(f"Eliminado directorio obsoleto: {dst_item}")
|
|
18
|
+
else:
|
|
19
|
+
os.remove(dst_item)
|
|
20
|
+
print(f"Eliminado archivo obsoleto: {dst_item}")
|
|
21
|
+
for item in os.listdir(src):
|
|
22
|
+
src_item = os.path.join(src, item)
|
|
23
|
+
dst_item = os.path.join(dst, item)
|
|
24
|
+
if os.path.isdir(src_item):
|
|
25
|
+
if item == "__pycache__":
|
|
26
|
+
continue
|
|
27
|
+
sync_dir(src_item, dst_item)
|
|
28
|
+
else:
|
|
29
|
+
if (not os.path.exists(dst_item) or
|
|
30
|
+
os.stat(src_item).st_mtime != os.stat(dst_item).st_mtime or
|
|
31
|
+
os.stat(src_item).st_size != os.stat(dst_item).st_size):
|
|
32
|
+
shutil.copy2(src_item, dst_item)
|
|
33
|
+
print(f"Sincronizado: {src_item} -> {dst_item}")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def main():
|
|
37
|
+
base_dir = os.path.dirname(os.path.abspath(__file__))
|
|
38
|
+
portable_dir = os.path.join(base_dir, "g360-app-polished-portable")
|
|
39
|
+
|
|
40
|
+
if not os.path.exists(portable_dir):
|
|
41
|
+
print(f"Error: No se encontro la carpeta portable '{portable_dir}'")
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
print("Iniciando sincronizacion con la version portable...")
|
|
45
|
+
|
|
46
|
+
files_to_sync = [
|
|
47
|
+
"main.py",
|
|
48
|
+
"run.bat", "launch.vbs", "launch_minimized.bat", "create_shortcut.vbs",
|
|
49
|
+
"build-portable.bat", "README.md",
|
|
50
|
+
]
|
|
51
|
+
for filename in files_to_sync:
|
|
52
|
+
src_file = os.path.join(base_dir, filename)
|
|
53
|
+
dst_file = os.path.join(portable_dir, filename)
|
|
54
|
+
if os.path.exists(src_file):
|
|
55
|
+
shutil.copy2(src_file, dst_file)
|
|
56
|
+
print(f"Copiado: {filename} -> portable/{filename}")
|
|
57
|
+
else:
|
|
58
|
+
print(f"Omitido (no existe en origen): {filename}")
|
|
59
|
+
|
|
60
|
+
sync_dir(os.path.join(base_dir, "src"), os.path.join(portable_dir, "src"))
|
|
61
|
+
sync_dir(os.path.join(base_dir, "assets"), os.path.join(portable_dir, "assets"))
|
|
62
|
+
sync_dir(os.path.join(base_dir, "g360_flet"), os.path.join(portable_dir, "g360_flet"))
|
|
63
|
+
|
|
64
|
+
for pyc in Path(portable_dir).rglob("__pycache__"):
|
|
65
|
+
shutil.rmtree(pyc)
|
|
66
|
+
|
|
67
|
+
print("\nSincronizacion finalizada con exito!")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
if __name__ == "__main__":
|
|
71
|
+
main()
|
package/src/cli.js
CHANGED
|
@@ -33,7 +33,7 @@ function configAction(options) {
|
|
|
33
33
|
console.log(chalk.gray(' positions: bottom-right, bottom-left, bottom-center, footer-right, footer-left'));
|
|
34
34
|
console.log(chalk.white(' templates:'));
|
|
35
35
|
console.log(chalk.gray(' web-pwa, lit-web, solid-web, svelte-web,'));
|
|
36
|
-
console.log(chalk.gray(' python-cli, python-flet, python-flet-migrate, python-customtkinter, vba-excel'));
|
|
36
|
+
console.log(chalk.gray(' python-cli, python-flet-polished (default), python-flet-legacy, python-flet-migrate, python-customtkinter, vba-excel'));
|
|
37
37
|
console.log(chalk.white(' skills:'));
|
|
38
38
|
console.log(chalk.gray(' corporativo, corporativo-movil, corporativo-g360, corporativo-g360-movil,'));
|
|
39
39
|
console.log(chalk.gray(' moderno, moderno-movil, minimalista, custom,'));
|
|
@@ -72,8 +72,8 @@ program
|
|
|
72
72
|
program
|
|
73
73
|
.command('init')
|
|
74
74
|
.argument('<name>', 'Project name')
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
.option('-t, --template <type>', 'Project template type (default: auto segun skill — python-flet-polished para Flet)', 'auto')
|
|
76
|
+
.option('-s, --skill <skill>', 'Skill to use (corporativo, corporativo-movil, moderno, moderno-movil, minimalista, custom, flet-desktop, flet-desktop-corporativo, flet-desktop-polished, cipsa, cipsa-movil)', 'corporativo-movil')
|
|
77
77
|
.option('-d, --dir <path>', 'Target directory', '.')
|
|
78
78
|
.option('--dry-run', 'Preview without creating files')
|
|
79
79
|
.option('--force', 'Overwrite existing files')
|
|
@@ -143,7 +143,7 @@ program
|
|
|
143
143
|
program
|
|
144
144
|
.command('convert')
|
|
145
145
|
.argument('[path]', 'Path to convert', '.')
|
|
146
|
-
|
|
146
|
+
.option('-s, --skill <skill>', 'Skill to apply (corporativo, corporativo-movil, moderno, moderno-movil, minimalista, custom, flet-desktop, flet-desktop-corporativo, flet-desktop-polished, cipsa, cipsa-movil)', 'corporativo-movil')
|
|
147
147
|
.option('--dry-run', 'Preview without applying')
|
|
148
148
|
.option('--restructure', 'Restructure project files')
|
|
149
149
|
.option('--force', 'Force dangerous changes')
|
package/src/commands/init.js
CHANGED
|
@@ -10,7 +10,24 @@ import inquirer from 'inquirer';
|
|
|
10
10
|
|
|
11
11
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
12
|
|
|
13
|
-
const PORTABLE_TEMPLATES = ['python-flet', 'python-flet-migrate', 'python-cli', 'python-customtkinter'];
|
|
13
|
+
const PORTABLE_TEMPLATES = ['python-flet', 'python-flet-migrate', 'python-flet-polished', 'python-cli', 'python-customtkinter'];
|
|
14
|
+
|
|
15
|
+
// Templates por defecto segun skill (mapeo automatico)
|
|
16
|
+
const TEMPLATE_DEFAULTS = {
|
|
17
|
+
'flet-desktop': 'python-flet-polished',
|
|
18
|
+
'flet-desktop-corporativo': 'python-flet-polished',
|
|
19
|
+
'flet-desktop-polished': 'python-flet-polished',
|
|
20
|
+
'cipsa': 'python-flet-polished',
|
|
21
|
+
'cipsa-movil': 'python-flet-polished',
|
|
22
|
+
'corporativo': 'web-pwa',
|
|
23
|
+
'corporativo-movil': 'web-pwa',
|
|
24
|
+
'corporativo-g360': 'web-pwa',
|
|
25
|
+
'corporativo-g360-movil': 'web-pwa',
|
|
26
|
+
'moderno': 'web-pwa',
|
|
27
|
+
'moderno-movil': 'web-pwa',
|
|
28
|
+
'minimalista': 'python-cli',
|
|
29
|
+
'custom': 'web-pwa',
|
|
30
|
+
};
|
|
14
31
|
|
|
15
32
|
async function askPortableOption(template) {
|
|
16
33
|
if (!PORTABLE_TEMPLATES.includes(template)) {
|
|
@@ -31,7 +48,7 @@ async function askPortableOption(template) {
|
|
|
31
48
|
|
|
32
49
|
export async function init(name, options) {
|
|
33
50
|
const {
|
|
34
|
-
template
|
|
51
|
+
template: rawTemplate,
|
|
35
52
|
skill = 'corporativo-movil',
|
|
36
53
|
dir = '.',
|
|
37
54
|
dryRun = false,
|
|
@@ -40,6 +57,20 @@ export async function init(name, options) {
|
|
|
40
57
|
brand = false,
|
|
41
58
|
} = options;
|
|
42
59
|
|
|
60
|
+
// Resolver template: usar default segun skill si no se especifico
|
|
61
|
+
let template = rawTemplate || TEMPLATE_DEFAULTS[skill] || 'web-pwa';
|
|
62
|
+
|
|
63
|
+
// Advertir si se usa template legacy
|
|
64
|
+
if (template === 'python-flet') {
|
|
65
|
+
console.log(chalk.yellow('⚠️ Template "python-flet" esta deprecado. Se usara "python-flet-polished" (estandar actual).\n'));
|
|
66
|
+
template = 'python-flet-polished';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Si el template es auto, usar default segun skill
|
|
70
|
+
if (template === 'auto') {
|
|
71
|
+
template = TEMPLATE_DEFAULTS[skill] || 'web-pwa';
|
|
72
|
+
}
|
|
73
|
+
|
|
43
74
|
const targetDir = path.join(process.cwd(), dir, name);
|
|
44
75
|
|
|
45
76
|
// Leer version del CLI desde package.json
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|