diff --git a/console/ui/css/styles.css b/console/ui/css/styles.css new file mode 100644 index 0000000..ba320d1 --- /dev/null +++ b/console/ui/css/styles.css @@ -0,0 +1,320 @@ +:root { + --bg-page: #001120; + --bg-surface: #001929; + --bg-navbar: #001c34; + --border: #0b2d50; + --accent: #1a7fd4; + --text-primary: #e2ecf6; + --text-secondary: #6b8eaa; +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif; + background: var(--bg-page); + color: var(--text-primary); + min-height: 100vh; +} + +.navbar { + height: 56px; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 20px; + background: var(--bg-navbar); + border-bottom: 1px solid var(--border); +} + +.title { + font-weight: 700; + letter-spacing: .3px; +} + +.brand { + display: flex; + align-items: center; + gap: 10px; +} + +.brand-mark { + width: 30px; + height: 30px; + border-radius: 8px; + background: linear-gradient(135deg, #009dff 0%, #0055d4 100%); + color: #fff; + display: grid; + place-items: center; + font-size: 14px; + font-weight: 800; + letter-spacing: .02em; + box-shadow: 0 6px 18px rgba(0, 125, 255, .35); +} + +.brand-text { + display: flex; + flex-direction: column; + line-height: 1.08; +} + +.brand-text .nubes { + font-size: 12px; + letter-spacing: .22em; + font-weight: 800; + color: #8bc7ff; +} + +.brand-text .product { + font-size: 13px; + font-weight: 700; + letter-spacing: .04em; +} + +.btn { + background: var(--accent); + color: #fff; + border: 0; + border-radius: 6px; + padding: 8px 12px; + cursor: pointer; + font-size: 13px; + line-height: 1.2; +} + +.btn:disabled { + opacity: .6; + cursor: not-allowed; +} + +.btn.danger { + background: #b43232; +} + +.btn.ghost { + background: #0c2b49; +} + +.wrap { + max-width: 1100px; + margin: 0 auto; + padding: 20px; +} + +.grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 12px; + margin-bottom: 16px; +} + +.card { + background: var(--bg-surface); + border: 1px solid var(--border); + border-radius: 8px; + padding: 14px; +} + +.k { + color: var(--text-secondary); + font-size: 12px; + text-transform: uppercase; + letter-spacing: .06em; +} + +.v { + font-size: 24px; + font-weight: 700; + margin-top: 6px; +} + +.box { + background: var(--bg-surface); + border: 1px solid var(--border); + border-radius: 8px; + padding: 14px; + margin-top: 12px; +} + +.toolbar { + display: flex; + justify-content: space-between; + gap: 10px; + align-items: center; + margin-bottom: 10px; +} + +table { + width: 100%; + border-collapse: collapse; + font-size: 13px; + margin-top: 8px; +} + +th, +td { + text-align: left; + padding: 8px; + border-bottom: 1px solid #0b2a48; +} + +.hint { + color: var(--text-secondary); + font-size: 12px; + margin-top: 8px; +} + +.mono { + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + font-size: 12px; +} + +.status { + margin-top: 10px; + padding: 9px 10px; + border-radius: 6px; + font-size: 13px; + background: #0c2b49; + border: 1px solid #1d486d; + display: none; +} + +.status.ok { + background: #103625; + border-color: #236843; +} + +.status.err { + background: #411d1d; + border-color: #7a2f2f; +} + +.chip { + display: inline-block; + padding: 2px 7px; + border-radius: 999px; + border: 1px solid #1d486d; + background: #0c2b49; + font-size: 11px; + margin-right: 4px; +} + +.modal { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, .45); + display: none; + align-items: center; + justify-content: center; + padding: 16px; +} + +.modal.open { + display: flex; +} + +.panel { + width: min(820px, 100%); + max-height: 90vh; + overflow: auto; + background: var(--bg-surface); + border: 1px solid var(--border); + border-radius: 10px; + padding: 16px; +} + +.panel h3 { + margin-bottom: 10px; + font-size: 16px; +} + +.row { + display: flex; + gap: 10px; + margin-bottom: 10px; + flex-wrap: wrap; +} + +.field { + flex: 1; + min-width: 180px; +} + +label { + display: block; + margin-bottom: 4px; + font-size: 12px; + color: var(--text-secondary); +} + +input, +select, +textarea { + width: 100%; + border: 1px solid #1d486d; + background: #03192c; + color: var(--text-primary); + border-radius: 6px; + padding: 8px 10px; + font-size: 13px; +} + +textarea { + min-height: 220px; + resize: vertical; + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; +} + +.actions { + display: flex; + gap: 8px; + justify-content: flex-end; + margin-top: 8px; + flex-wrap: wrap; +} + +.nowrap { + white-space: nowrap; +} + +.help-section { + margin-top: 14px; + padding-top: 14px; + border-top: 1px solid #0b2a48; +} + +.help-section:first-of-type { + margin-top: 0; + padding-top: 0; + border-top: 0; +} + +.help-section h4 { + margin-bottom: 8px; + font-size: 14px; +} + +.help-list { + display: grid; + gap: 8px; + font-size: 13px; + line-height: 1.5; + color: var(--text-primary); +} + +.help-code { + margin-top: 8px; + padding: 10px 12px; + border-radius: 8px; + border: 1px solid #0b2a48; + background: #021221; + color: #d8e5f2; + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + font-size: 12px; + white-space: pre-wrap; + word-break: break-word; +} diff --git a/console/ui/embed.go b/console/ui/embed.go index 69baf15..5f2b2d3 100644 --- a/console/ui/embed.go +++ b/console/ui/embed.go @@ -5,7 +5,7 @@ import ( "net/http" ) -//go:embed index.html cron.html +//go:embed index.html cron.html css js var content embed.FS func Handler() http.Handler { diff --git a/console/ui/index.html b/console/ui/index.html index 35a314f..c0b1b13 100644 --- a/console/ui/index.html +++ b/console/ui/index.html @@ -12,328 +12,8 @@ window.location.replace('https://' + window.location.host + window.location.pathname + window.location.search + window.location.hash); } - + +
@@ -912,25 +592,6 @@ return '' + h(text) + ''; } - const LANG_TEMPLATES = { - python: { - entrypoint: 'main.main', - code: 'def main():\n return {"ok": True}' - }, - nodejs: { - entrypoint: 'main', - code: 'module.exports = async function(context) {\n return {\n status: 200,\n body: "hello from fission"\n };\n}' - }, - php: { - entrypoint: 'main.php::handler', - code: 'getBody()->write("hello from fission");\n}' - }, - ruby: { - entrypoint: 'handler', - code: '# frozen_string_literal: true\n\ndef handler\n "hello from fission"\nend' - } - }; - function onLangChange() { var lang = document.getElementById('c-lang').value; var t = LANG_TEMPLATES[lang]; diff --git a/console/ui/js/config.js b/console/ui/js/config.js new file mode 100644 index 0000000..a8187d0 --- /dev/null +++ b/console/ui/js/config.js @@ -0,0 +1,20 @@ +/* config.js — константы и шаблоны языков */ + +const LANG_TEMPLATES = { + python: { + entrypoint: 'main.main', + code: 'def main():\n return {"ok": True}' + }, + nodejs: { + entrypoint: 'main', + code: 'module.exports = async function(context) {\n return {\n status: 200,\n body: "hello from fission"\n };\n}' + }, + php: { + entrypoint: 'main.php::handler', + code: 'getBody()->write("hello from fission");\n}' + }, + ruby: { + entrypoint: 'handler', + code: '# frozen_string_literal: true\n\ndef handler\n "hello from fission"\nend' + } +}; diff --git a/doc/refactor-ui-2026-05-02/plan.md b/doc/refactor-ui-2026-05-02/plan.md new file mode 100644 index 0000000..5b6e08a --- /dev/null +++ b/doc/refactor-ui-2026-05-02/plan.md @@ -0,0 +1,133 @@ +# Рефакторинг UI: монолит → модули + +Дата: 2026-05-02 +Ветка: второмая +Файл-источник: console/ui/index.html (1651 строк, 73 функции) + +--- + +## Целевая структура + +``` +console/ui/ +├── index.html # только HTML-скелет + + + + + + + + + + +``` + +--- + +## Шаги (пошагово, с билдом после каждого) + +### Шаг 1 — CSS +- Вынести `