- db.py: ProjectDB class with SQLite schema (projects, data_files, sequences, history_trees), WAL mode, CRUD, import, and query helpers - api_routes.py: REST API endpoints on NiceGUI/FastAPI for ComfyUI to query project data over the network - project_loader.py: ComfyUI nodes (ProjectLoaderDynamic, Standard, VACE, LoRA) that fetch data from NiceGUI REST API via HTTP - web/project_dynamic.js: Frontend JS for dynamic project loader node - tab_projects_ng.py: Projects management tab in NiceGUI UI - state.py: Added db, current_project, db_enabled fields - main.py: DB init, API route registration, projects tab - utils.py: sync_to_db() dual-write helper - tab_batch_ng.py, tab_raw_ng.py, tab_timeline_ng.py: dual-write sync calls after save_json when project DB is enabled - __init__.py: Merged project node class mappings - tests/test_db.py: 30 tests for database layer - tests/test_project_loader.py: 17 tests for ComfyUI connector nodes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
76 lines
2.7 KiB
Python
76 lines
2.7 KiB
Python
import copy
|
|
import json
|
|
|
|
from nicegui import ui
|
|
|
|
from state import AppState
|
|
from utils import save_json, sync_to_db, get_file_mtime, KEY_HISTORY_TREE, KEY_PROMPT_HISTORY
|
|
|
|
|
|
def render_raw_editor(state: AppState):
|
|
data = state.data_cache
|
|
file_path = state.file_path
|
|
|
|
with ui.card().classes('w-full q-pa-md'):
|
|
ui.label(f'Raw Editor: {file_path.name}').classes('text-h6 q-mb-md')
|
|
|
|
hide_history = ui.checkbox(
|
|
'Hide History (Safe Mode)',
|
|
value=True,
|
|
)
|
|
|
|
@ui.refreshable
|
|
def render_editor():
|
|
# Prepare display data
|
|
if hide_history.value:
|
|
display_data = copy.deepcopy(data)
|
|
display_data.pop(KEY_HISTORY_TREE, None)
|
|
display_data.pop(KEY_PROMPT_HISTORY, None)
|
|
else:
|
|
display_data = data
|
|
|
|
try:
|
|
json_str = json.dumps(display_data, indent=4, ensure_ascii=False)
|
|
except Exception as e:
|
|
ui.notify(f'Error serializing JSON: {e}', type='negative')
|
|
json_str = '{}'
|
|
|
|
text_area = ui.textarea(
|
|
'JSON Content',
|
|
value=json_str,
|
|
).classes('w-full font-mono').props('outlined rows=30')
|
|
|
|
def do_save():
|
|
try:
|
|
input_data = json.loads(text_area.value)
|
|
|
|
# Merge hidden history back in if safe mode
|
|
if hide_history.value:
|
|
if KEY_HISTORY_TREE in data:
|
|
input_data[KEY_HISTORY_TREE] = data[KEY_HISTORY_TREE]
|
|
if KEY_PROMPT_HISTORY in data:
|
|
input_data[KEY_PROMPT_HISTORY] = data[KEY_PROMPT_HISTORY]
|
|
|
|
save_json(file_path, input_data)
|
|
if state.db_enabled and state.current_project and state.db:
|
|
sync_to_db(state.db, state.current_project, file_path, input_data)
|
|
|
|
data.clear()
|
|
data.update(input_data)
|
|
state.last_mtime = get_file_mtime(file_path)
|
|
|
|
ui.notify('Raw JSON Saved Successfully!', type='positive')
|
|
render_editor.refresh()
|
|
|
|
except json.JSONDecodeError as e:
|
|
ui.notify(f'Invalid JSON Syntax: {e}', type='negative')
|
|
except Exception as e:
|
|
ui.notify(f'Unexpected Error: {e}', type='negative')
|
|
|
|
ui.button('Save Raw Changes', icon='save', on_click=do_save).props(
|
|
'color=primary'
|
|
).classes('w-full q-mt-md')
|
|
|
|
hide_history.on_value_change(lambda _: render_editor.refresh())
|
|
render_editor()
|