fix(dashboard): add structured routing sections header with title and aligned test-all button

- Wrap test-all button in a clean sections header with Lucide route icon and localized title
- Remove loose inline styles and align button with card grid boundaries
- Add responsive wrapping for mobile displays
- Add Russian localization for Routing sections
- Rebuild LuCI frontend bundle
This commit is contained in:
Dushnilin
2026-09-12 00:05:14 +03:00
parent 0bec2f6f86
commit afd7e270ce
6 changed files with 206 additions and 35 deletions
+3
View File
@@ -6693,6 +6693,9 @@ msgstr ""
msgid "Routing section" msgid "Routing section"
msgstr "" msgstr ""
msgid "Routing sections"
msgstr ""
#: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:995 #: ../luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/settings.js:995
msgid "Routing sections, rules and strategies" msgid "Routing sections, rules and strategies"
msgstr "" msgstr ""
+3
View File
@@ -4160,6 +4160,9 @@ msgstr "Правила маршрутизации"
msgid "Routing section" msgid "Routing section"
msgstr "Секция маршрутизации" msgstr "Секция маршрутизации"
msgid "Routing sections"
msgstr "Секции маршрутизации"
msgid "Routing sections, rules and strategies" msgid "Routing sections, rules and strategies"
msgstr "Секции маршрутизации, правила и стратегии" msgstr "Секции маршрутизации, правила и стратегии"
@@ -1857,8 +1857,41 @@ async function renderSectionsWidget() {
'div', 'div',
{ {
class: 'tachyon_dashboard-page__sections-header', class: 'tachyon_dashboard-page__sections-header',
style: },
'display: flex; justify-content: flex-end; align-items: center; margin-bottom: 12px; gap: 8px;', [
E(
'div',
{
class: 'tachyon_dashboard-page__sections-header__title',
},
[
svgEl(
'svg',
{
width: '16',
height: '16',
viewBox: '0 0 24 24',
fill: 'none',
stroke: 'currentColor',
'stroke-width': '2',
'stroke-linecap': 'round',
'stroke-linejoin': 'round',
},
[
svgEl('circle', { cx: '6', cy: '19', r: '3' }),
svgEl('path', {
d: 'M9 19h8.5a3.5 3.5 0 0 0 0-7h-11a3.5 3.5 0 0 1 0-7H15',
}),
svgEl('circle', { cx: '18', cy: '5', r: '3' }),
],
),
E('span', {}, _('Routing sections')),
],
),
E(
'div',
{
class: 'tachyon_dashboard-page__sections-header__actions',
}, },
[ [
E( E(
@@ -1867,8 +1900,6 @@ async function renderSectionsWidget() {
type: 'button', type: 'button',
id: 'dashboard-test-all-sections-button', id: 'dashboard-test-all-sections-button',
class: 'btn', class: 'btn',
style:
'display: inline-flex; align-items: center; justify-content: center; gap: 6px; white-space: nowrap; padding: 4px 14px; height: 32px; font-size: 13px;',
disabled: isTestingAllSections ? true : undefined, disabled: isTestingAllSections ? true : undefined,
click: () => { click: () => {
void handleTestAllSections(); void handleTestAllSections();
@@ -1882,6 +1913,8 @@ async function renderSectionsWidget() {
: E('span', {}, _('Test all sections')), : E('span', {}, _('Test all sections')),
), ),
], ],
),
],
) )
: null; : null;
@@ -189,13 +189,53 @@ export const styles = `
opacity: 0.65; opacity: 0.65;
} }
#dashboard-test-all-sections-button { .tachyon_dashboard-page__sections-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 16px;
margin-bottom: 4px;
padding: 0 2px;
gap: 12px;
min-width: 0;
}
.tachyon_dashboard-page__sections-header__title {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-color-high);
font-size: 15px;
font-weight: 700;
letter-spacing: 0.2px;
min-width: 0;
overflow-wrap: anywhere;
}
.tachyon_dashboard-page__sections-header__title svg {
flex-shrink: 0;
opacity: 0.85;
}
.tachyon_dashboard-page__sections-header__actions {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 6px;
flex-shrink: 0;
}
.tachyon_dashboard-page .btn#dashboard-test-all-sections-button {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 6px; gap: 6px;
white-space: nowrap; white-space: nowrap;
vertical-align: middle; vertical-align: middle;
padding: 4px 14px;
height: 30px;
min-height: 28px;
font-size: 13px;
} }
#dashboard-test-all-sections-button svg { #dashboard-test-all-sections-button svg {
@@ -210,6 +250,13 @@ export const styles = `
opacity: 0.65; opacity: 0.65;
} }
@media (max-width: 480px) {
.tachyon_dashboard-page__sections-header {
flex-wrap: wrap;
gap: 8px;
}
}
.tachyon_dashboard-page__outbound-grid { .tachyon_dashboard-page__outbound-grid {
margin-top: 5px; margin-top: 5px;
display: grid; display: grid;
@@ -9174,8 +9174,42 @@ async function renderSectionsWidget() {
const testAllHeader = hasTestableSections ? E( const testAllHeader = hasTestableSections ? E(
"div", "div",
{ {
class: "tachyon_dashboard-page__sections-header", class: "tachyon_dashboard-page__sections-header"
style: "display: flex; justify-content: flex-end; align-items: center; margin-bottom: 12px; gap: 8px;" },
[
E(
"div",
{
class: "tachyon_dashboard-page__sections-header__title"
},
[
svgEl(
"svg",
{
width: "16",
height: "16",
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
[
svgEl("circle", { cx: "6", cy: "19", r: "3" }),
svgEl("path", {
d: "M9 19h8.5a3.5 3.5 0 0 0 0-7h-11a3.5 3.5 0 0 1 0-7H15"
}),
svgEl("circle", { cx: "18", cy: "5", r: "3" })
]
),
E("span", {}, _("Routing sections"))
]
),
E(
"div",
{
class: "tachyon_dashboard-page__sections-header__actions"
}, },
[ [
E( E(
@@ -9184,7 +9218,6 @@ async function renderSectionsWidget() {
type: "button", type: "button",
id: "dashboard-test-all-sections-button", id: "dashboard-test-all-sections-button",
class: "btn", class: "btn",
style: "display: inline-flex; align-items: center; justify-content: center; gap: 6px; white-space: nowrap; padding: 4px 14px; height: 32px; font-size: 13px;",
disabled: isTestingAllSections ? true : void 0, disabled: isTestingAllSections ? true : void 0,
click: () => { click: () => {
void handleTestAllSections(); void handleTestAllSections();
@@ -9196,6 +9229,8 @@ async function renderSectionsWidget() {
] : E("span", {}, _("Test all sections")) ] : E("span", {}, _("Test all sections"))
) )
] ]
)
]
) : null; ) : null;
const renderedWidgets = sectionsWithCustomLatencies.map( const renderedWidgets = sectionsWithCustomLatencies.map(
(section) => renderSections({ (section) => renderSections({
@@ -9826,13 +9861,53 @@ var styles = `
opacity: 0.65; opacity: 0.65;
} }
#dashboard-test-all-sections-button { .tachyon_dashboard-page__sections-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 16px;
margin-bottom: 4px;
padding: 0 2px;
gap: 12px;
min-width: 0;
}
.tachyon_dashboard-page__sections-header__title {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-color-high);
font-size: 15px;
font-weight: 700;
letter-spacing: 0.2px;
min-width: 0;
overflow-wrap: anywhere;
}
.tachyon_dashboard-page__sections-header__title svg {
flex-shrink: 0;
opacity: 0.85;
}
.tachyon_dashboard-page__sections-header__actions {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 6px;
flex-shrink: 0;
}
.tachyon_dashboard-page .btn#dashboard-test-all-sections-button {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 6px; gap: 6px;
white-space: nowrap; white-space: nowrap;
vertical-align: middle; vertical-align: middle;
padding: 4px 14px;
height: 30px;
min-height: 28px;
font-size: 13px;
} }
#dashboard-test-all-sections-button svg { #dashboard-test-all-sections-button svg {
@@ -9847,6 +9922,13 @@ var styles = `
opacity: 0.65; opacity: 0.65;
} }
@media (max-width: 480px) {
.tachyon_dashboard-page__sections-header {
flex-wrap: wrap;
gap: 8px;
}
}
.tachyon_dashboard-page__outbound-grid { .tachyon_dashboard-page__outbound-grid {
margin-top: 5px; margin-top: 5px;
display: grid; display: grid;
+3
View File
@@ -4160,6 +4160,9 @@ msgstr "Правила маршрутизации"
msgid "Routing section" msgid "Routing section"
msgstr "Секция маршрутизации" msgstr "Секция маршрутизации"
msgid "Routing sections"
msgstr "Секции маршрутизации"
msgid "Routing sections, rules and strategies" msgid "Routing sections, rules and strategies"
msgstr "Секции маршрутизации, правила и стратегии" msgstr "Секции маршрутизации, правила и стратегии"