Мастер без лицензии учёта: глава 2 называется «Организация», подзаголовок мастера собирается из глав этой установки; в шапке «НРД не подключён» вместо «Нет связи с НРД», пока обмен не настроен

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
zuevav
2026-10-05 19:07:41 +03:00
parent ba1aae705d
commit 79d20bc2cf
5 changed files with 33 additions and 2 deletions
+6
View File
@@ -212,6 +212,12 @@ func TestWizardChaptersWithoutLicense(t *testing.T) {
if len(wizModuleViews(rc, rc.Snapshot())) != 0 { if len(wizModuleViews(rc, rc.Snapshot())) != 0 {
t.Fatal("без лицензии модулей в мастере быть не должно") t.Fatal("без лицензии модулей в мастере быть не должно")
} }
if chapters[1].Title != "Организация" {
t.Fatalf("без учёта DEPO и QUIK глава 2 — «Организация», а не %q", chapters[1].Title)
}
if l := wizChaptersLine(chapters); l != "Четыре главы: сервер, организация, НРД, запуск." {
t.Fatalf("подзаголовок: %q", l)
}
} }
func TestLettersFill(t *testing.T) { func TestLettersFill(t *testing.T) {
+2
View File
@@ -187,6 +187,7 @@ type WizardData struct {
StepRequired bool StepRequired bool
StepTitle string StepTitle string
ChapterTitle string ChapterTitle string
ChaptersLine string // «Четыре главы: сервер, организация, НРД, запуск.»
Modules []WizModule // глава «Запуск»: модули по лицензии Modules []WizModule // глава «Запуск»: модули по лицензии
Done struct { Done struct {
License bool License bool
@@ -289,6 +290,7 @@ func (h *setupHandlers) renderWizard(w http.ResponseWriter, r *http.Request) {
d.ChapterTitle = c.Title d.ChapterTitle = c.Title
} }
} }
d.ChaptersLine = wizChaptersLine(d.Chapters)
if done[2] { if done[2] {
d.AutoDone = append(d.AutoDone, "База bj создана установщиком"+pickStr(" — "+d.PGSummary, "")) d.AutoDone = append(d.AutoDone, "База bj создана установщиком"+pickStr(" — "+d.PGSummary, ""))
} }
@@ -31,7 +31,7 @@ a.wstep:hover .bub { box-shadow:0 0 0 4px var(--accent-weak); }
<div class="wiz-head"> <div class="wiz-head">
<h1>Настройка Bridge&amp;Join</h1> <h1>Настройка Bridge&amp;Join</h1>
<p>Четыре главы: сервер, учёт и организация, НРД, запуск. Всё сохраняется сразу — можно прерваться и вернуться</p> <p>{{.ChaptersLine}} Всё сохраняется сразу — можно прерваться и вернуться.</p>
</div> </div>
<div class="wizard-progress" style="max-width:720px"> <div class="wizard-progress" style="max-width:720px">
+1 -1
View File
@@ -361,7 +361,7 @@ details:has(> pre.copyable) { min-width:0; max-width:100%; }
<div class="topbar-right"> <div class="topbar-right">
<span class="sys-block"> <span class="sys-block">
{{if and .NSDLink.Configured (not .IsMockMode)}}<a id="nsd-chain" href="/admin/status#nsd" class="sys-status nsd-chain {{.NSDLink.State}}" title="{{nsdSegTip .NSDLink}}"><i></i><span>Шлюз НРД</span></a>{{else}}<span class="sys-status {{if .IsMockMode}}warn{{end}}" title="Состояние обмена с НРД"> {{if and .NSDLink.Configured (not .IsMockMode)}}<a id="nsd-chain" href="/admin/status#nsd" class="sys-status nsd-chain {{.NSDLink.State}}" title="{{nsdSegTip .NSDLink}}"><i></i><span>Шлюз НРД</span></a>{{else}}<span class="sys-status {{if .IsMockMode}}warn{{end}}" title="Состояние обмена с НРД">
<span class="pulse"></span>{{if .IsMockMode}}{{if devOn}}Эмуляция{{else}}Нет связи с НРД{{end}}{{else}}НРД на связи{{end}}</span>{{end}} <span class="pulse"></span>{{if .IsMockMode}}{{if devOn}}Эмуляция{{else}}НРД не подключён{{end}}{{else}}НРД на связи{{end}}</span>{{end}}
<span class="clock">{{.Now}}</span> <span class="clock">{{.Now}}</span>
</span> </span>
<span class="dd user-dd{{if or (eq .Active "setup") (eq .Active "status") (eq .Active "help")}} active{{end}}"> <span class="dd user-dd{{if or (eq .Active "setup") (eq .Active "status") (eq .Active "help")}} active{{end}}">
+23
View File
@@ -7,6 +7,8 @@ package lkgateway
// - сделан установщиком без участия человека (база bj, Валидата) — шага нет в пути, в главе «Сервер» // - сделан установщиком без участия человека (база bj, Валидата) — шага нет в пути, в главе «Сервер»
// это показано строкой «сделано автоматически». // это показано строкой «сделано автоматически».
import "strings"
// wizChapters — главы мастера: название и шаги по порядку. // wizChapters — главы мастера: название и шаги по порядку.
var wizChapters = []struct { var wizChapters = []struct {
Title string Title string
@@ -91,6 +93,9 @@ func wizPath(rc *RuntimeConfig, done map[int]bool, current int) (path []int, cha
if len(c.Steps) == 0 { if len(c.Steps) == 0 {
continue continue
} }
if len(c.Steps) == 1 { // в главе один шаг (остальные не в лицензии) — глава называется по нему: «Организация»
c.Title = c.Steps[0].Title
}
// переход по главе — на первый несделанный шаг главы // переход по главе — на первый несделанный шаг главы
for _, s := range c.Steps { for _, s := range c.Steps {
if !s.Done { if !s.Done {
@@ -103,6 +108,24 @@ func wizPath(rc *RuntimeConfig, done map[int]bool, current int) (path []int, cha
return path, chapters return path, chapters
} }
// wizChaptersLine — подзаголовок мастера: «Четыре главы: сервер, организация, НРД, запуск».
func wizChaptersLine(chapters []WizChapter) string {
words := []string{"", "Одна глава", "Две главы", "Три главы", "Четыре главы"}
var names []string
for _, c := range chapters {
t := c.Title
if t != "НРД" && t != "" {
r := []rune(t)
t = strings.ToLower(string(r[:1])) + string(r[1:])
}
names = append(names, t)
}
if len(chapters) == 0 || len(chapters) >= len(words) {
return ""
}
return words[len(chapters)] + ": " + strings.Join(names, ", ") + "."
}
// wizNeighbours — предыдущий и следующий шаг в пути (0 — нет). // wizNeighbours — предыдущий и следующий шаг в пути (0 — нет).
func wizNeighbours(path []int, current int) (prev, next int) { func wizNeighbours(path []int, current int) (prev, next int) {
for i, n := range path { for i, n := range path {