diff --git a/assets/gui/css/alas.css b/assets/gui/css/alas.css index 82dbace97..735dc2012 100644 --- a/assets/gui/css/alas.css +++ b/assets/gui/css/alas.css @@ -4,11 +4,11 @@ details { margin-bottom: .25rem !important; } -details[open]>summary { +details[open] > summary { border-bottom: unset !important; } -details[open]>div { +details[open] > div { margin-left: 0.625rem; } @@ -117,6 +117,22 @@ footer { margin-bottom: .25rem !important; } +.hr-task-group-box { + display: flex; + align-items: center; + margin-bottom: 0.5rem; +} + +.hr-task-group-line { + border-top: 0.125rem solid; + flex-grow: 1; +} + +.hr-task-group-text { + margin: 0 0.5rem; + font-size: 0.875rem; +} + input[type="checkbox"] { width: 1.25rem; height: 1.25rem; @@ -171,7 +187,7 @@ button.btn.dropdown-toggle { display: none; } -.bootstrap-select>select { +.bootstrap-select > select { position: unset !important; bottom: unset !important; left: unset !important; @@ -199,7 +215,7 @@ button.btn.dropdown-toggle { } .alas-icon, -.alas-icon>image { +.alas-icon > image { width: 42px; height: 42px; } @@ -246,6 +262,7 @@ pre.rich-traceback-code { #pywebio-scope-menu { z-index: 90; padding-left: .5rem; + padding-right: .5rem; padding-top: 1.2rem; overflow-y: auto; width: 12rem; @@ -280,7 +297,7 @@ pre.rich-traceback-code { margin: auto; } -#pywebio-scope-header_title>p { +#pywebio-scope-header_title > p { font-size: 1.2rem; margin: auto; overflow: hidden; @@ -293,7 +310,7 @@ pre.rich-traceback-code { margin-bottom: auto; } -#pywebio-scope-header_status>div>div+div+p { +#pywebio-scope-header_status > div > div + div + p { margin: 0; } @@ -311,7 +328,7 @@ pre.rich-traceback-code { grid-template-columns: 1fr minmax(25rem, 5fr) 2fr; } -#pywebio-scope-group__info>p { +#pywebio-scope-group__info > p { font-size: .80rem !important; font-weight: 400; } @@ -322,13 +339,13 @@ pre.rich-traceback-code { padding: 1rem; } -[id^="pywebio-scope-group_"]>p { +[id^="pywebio-scope-group_"] > p { font-size: 1.25rem; font-weight: 500; margin: 0 .25rem 0 .25rem !important; } -[id^="pywebio-scope-group_"]>p+p { +[id^="pywebio-scope-group_"] > p + p { font-size: .80rem; margin: .2rem .25rem .1rem .25rem !important; } @@ -337,6 +354,10 @@ pre.rich-traceback-code { overflow-y: auto; } +#pywebio-scope-groups:not(:has(*)) { + display: none; +} + #pywebio-scope-navigator { margin: .5rem 1rem .5rem; height: min-content; @@ -388,9 +409,9 @@ pre.rich-traceback-code { grid-template-rows: auto auto 1fr; } -#pywebio-scope-running>p, -#pywebio-scope-pending>p, -#pywebio-scope-waiting>p { +#pywebio-scope-running > p, +#pywebio-scope-pending > p, +#pywebio-scope-waiting > p { font-size: 1.25rem; font-weight: 500; margin: 0 0.625rem 0 !important; diff --git a/assets/gui/css/dark-alas.css b/assets/gui/css/dark-alas.css index 94481d617..79c1835ab 100644 --- a/assets/gui/css/dark-alas.css +++ b/assets/gui/css/dark-alas.css @@ -36,8 +36,16 @@ background-color: #40444b !important; } +.hr-task-group-line { + border-top-color: #adb5bd; +} + +.hr-task-group-text { + color: #adb5bd; +} + .form-control, -.bootstrap-select>select { +.bootstrap-select > select { border-bottom: .125rem solid #7a77bb; } @@ -59,7 +67,7 @@ textarea { border: 1px solid #21262d; } -.aside-icon>path { +.aside-icon > path { fill: #c9d1d9; } @@ -118,6 +126,6 @@ pre.rich-traceback-code { } *[style*="--arg-help--"], -[id^="pywebio-scope-group_"]>p+p { +[id^="pywebio-scope-group_"] > p + p { color: #adb5bd; } \ No newline at end of file diff --git a/assets/gui/css/light-alas.css b/assets/gui/css/light-alas.css index 8c42cc4cd..8db33eac7 100644 --- a/assets/gui/css/light-alas.css +++ b/assets/gui/css/light-alas.css @@ -37,8 +37,16 @@ background-color: #eaecef !important; } +.hr-task-group-line { + border-top-color: #d0d0d0; +} + +.hr-task-group-text { + color: #777777; +} + .form-control, -.bootstrap-select>select { +.bootstrap-select > select { border-bottom: .125rem solid #4e4c97; } @@ -60,7 +68,7 @@ textarea { border: 1px solid lightgrey; } -.aside-icon>path { +.aside-icon > path { fill: #2c2c2c; } @@ -117,6 +125,6 @@ pre.rich-traceback-code { } *[style*="--arg-help--"], -[id^="pywebio-scope-group_"]>p+p { +[id^="pywebio-scope-group_"] > p + p { color: #777777; } \ No newline at end of file diff --git a/module/config/argument/menu.json b/module/config/argument/menu.json index 8af4fb904..4745bacdb 100644 --- a/module/config/argument/menu.json +++ b/module/config/argument/menu.json @@ -1,6 +1,8 @@ { - "Task": { - "Alas": [ + "Alas": { + "menu": "list", + "page": "setting", + "tasks": [ "Alas", "Restart" ] diff --git a/module/config/argument/task.yaml b/module/config/argument/task.yaml index f391112f0..a97c47db5 100644 --- a/module/config/argument/task.yaml +++ b/module/config/argument/task.yaml @@ -5,12 +5,16 @@ # ==================== Alas ==================== Alas: - - Emulator - - EmulatorInfo - - Error - - Optimization -Restart: - - Scheduler + menu: 'list' + page: 'setting' + tasks: + Alas: + - Emulator + - EmulatorInfo + - Error + - Optimization + Restart: + - Scheduler # ==================== Farm ==================== diff --git a/module/config/config_updater.py b/module/config/config_updater.py index f597d61f8..51299a68a 100644 --- a/module/config/config_updater.py +++ b/module/config/config_updater.py @@ -67,8 +67,9 @@ class ConfigGenerator: @cached_property def task(self): """ - : - - + : + : + : """ return read_file(filepath_argument('task')) @@ -112,7 +113,10 @@ class ConfigGenerator: """ # Construct args data = {} - for task, groups in self.task.items(): + for path, groups in deep_iter(self.task, depth=3): + if 'tasks' not in path: + continue + task = path[2] # Add storage to all task groups.append('Storage') for group in groups: @@ -164,7 +168,10 @@ class ConfigGenerator: deep_set(data, keys=p + ['value'], value=v) deep_set(data, keys=p + ['display'], value='hide') # Set command - for task in self.task.keys(): + for path, groups in deep_iter(self.task, depth=3): + if 'tasks' not in path: + continue + task = path[2] if deep_get(data, keys=f'{task}.Scheduler.Command'): deep_set(data, keys=f'{task}.Scheduler.Command.value', value=task) deep_set(data, keys=f'{task}.Scheduler.Command.display', value='hide') @@ -220,12 +227,12 @@ class ConfigGenerator: deep_set(new, keys=k, value=v) # Menu - for path, data in deep_iter(self.menu, depth=2): - func, group = path - deep_load(['Menu', func]) - deep_load(['Menu', group]) - for task in data: - deep_load([func, task]) + for path, data in deep_iter(self.task, depth=3): + if 'tasks' not in path: + continue + task_group, _, task = path + deep_load(['Menu', task_group]) + deep_load(['Task', task]) # Arguments visited_group = set() for path, data in deep_iter(self.argument, depth=2): @@ -273,23 +280,18 @@ class ConfigGenerator: """ data = {} - - # Task menu - group = '' - tasks = [] - with open(filepath_argument('task'), 'r', encoding='utf-8') as f: - for line in f.readlines(): - line = line.strip('\n') - if '=====' in line: - if tasks: - deep_set(data, keys=f'Task.{group}', value=tasks) - group = line.strip('#=- ') - tasks = [] - if group: - if line.endswith(':'): - tasks.append(line.strip('\n=-#: ')) - if tasks: - deep_set(data, keys=f'Task.{group}', value=tasks) + for task_group in self.task.keys(): + value = deep_get(self.task, keys=[task_group, 'menu']) + if value not in ['collapse', 'list']: + value = 'collapse' + deep_set(data, keys=[task_group, 'menu'], value=value) + value = deep_get(self.task, keys=[task_group, 'page']) + if value not in ['setting', 'tool']: + value = 'setting' + deep_set(data, keys=[task_group, 'page'], value=value) + tasks = deep_get(self.task, keys=[task_group, 'tasks'], default={}) + tasks = list(tasks.keys()) + deep_set(data, keys=[task_group, 'tasks'], value=tasks) return data diff --git a/module/config/i18n/en-US.json b/module/config/i18n/en-US.json index 0218ae5aa..ebad5ce2c 100644 --- a/module/config/i18n/en-US.json +++ b/module/config/i18n/en-US.json @@ -1,9 +1,5 @@ { "Menu": { - "Task": { - "name": "", - "help": "" - }, "Alas": { "name": "SRC", "help": "" diff --git a/module/config/i18n/ja-JP.json b/module/config/i18n/ja-JP.json index 23283ca56..c6bdf19c2 100644 --- a/module/config/i18n/ja-JP.json +++ b/module/config/i18n/ja-JP.json @@ -1,9 +1,5 @@ { "Menu": { - "Task": { - "name": "", - "help": "" - }, "Alas": { "name": "Menu.Alas.name", "help": "Menu.Alas.help" diff --git a/module/config/i18n/zh-CN.json b/module/config/i18n/zh-CN.json index 4eecde3fa..cfc6cfe21 100644 --- a/module/config/i18n/zh-CN.json +++ b/module/config/i18n/zh-CN.json @@ -1,9 +1,5 @@ { "Menu": { - "Task": { - "name": "", - "help": "" - }, "Alas": { "name": "SRC", "help": "" diff --git a/module/config/i18n/zh-TW.json b/module/config/i18n/zh-TW.json index a03b9bac8..3e07e23ab 100644 --- a/module/config/i18n/zh-TW.json +++ b/module/config/i18n/zh-TW.json @@ -1,9 +1,5 @@ { "Menu": { - "Task": { - "name": "", - "help": "" - }, "Alas": { "name": "SRC", "help": "" diff --git a/module/webui/app.py b/module/webui/app.py index ba77c64a8..181d966f0 100644 --- a/module/webui/app.py +++ b/module/webui/app.py @@ -167,41 +167,50 @@ class AlasGUI(Frame): Set menu """ put_buttons( - [ - { - "label": t("Gui.MenuAlas.Overview"), - "value": "Overview", - "color": "menu", - } - ], + [{ + "label": t("Gui.MenuAlas.Overview"), + "value": "Overview", + "color": "menu", + }], onclick=[self.alas_overview], - ).style(f"--menu-Overview--"), + ).style(f"--menu-Overview--") - for key, tasks in deep_iter(self.ALAS_MENU, depth=2): - # path = '.'.join(key) - menu = key[1] - - if menu == "Tool": + for menu, task_data in self.ALAS_MENU.items(): + if task_data.get("page") == "tool": _onclick = self.alas_daemon_overview else: _onclick = self.alas_set_group - task_btn_list = [] - for task in tasks: - task_btn_list.append( + if task_data.get("menu") == "collapse": + task_btn_list = [ put_buttons( - [ - { - "label": t(f"Task.{task}.name"), - "value": task, - "color": "menu", - } - ], + [{ + "label": t(f"Task.{task}.name"), + "value": task, + "color": "menu", + }], onclick=_onclick, ).style(f"--menu-{task}--") - ) - - put_collapse(title=t(f"Menu.{menu}.name"), content=task_btn_list) + for task in task_data.get("tasks", []) + ] + put_collapse(title=t(f"Menu.{menu}.name"), content=task_btn_list) + else: + title = t(f"Menu.{menu}.name") + put_html('
' + '' + f'{title}' + '' + '
' + ) + for task in task_data.get("tasks", []): + put_buttons( + [{ + "label": t(f"Task.{task}.name"), + "value": task, + "color": "menu", + }], + onclick=_onclick, + ).style(f"--menu-{task}--").style(f"padding-left: 0.75rem") self.alas_overview() @@ -625,6 +634,21 @@ class AlasGUI(Frame): continue self.set_group(group, arg_dict, config, task) + run_js(""" + $("#pywebio-scope-log").css( + "grid-row-start", + -2 - $("#pywebio-scope-_daemon").children().filter( + function(){ + return $(this).css("display") === "none"; + } + ).length + ); + $("#pywebio-scope-log").css( + "grid-row-end", + -1 + ); + """) + self.task_handler.add(switch_scheduler.g(), 1, True) self.task_handler.add(switch_log_scroll.g(), 1, True) self.task_handler.add(log.put_log(self.alas), 0.25, True)