From d648beede271abd92b10d4e659437a2f62fe283d Mon Sep 17 00:00:00 2001 From: Emil Date: Thu, 23 Jul 2026 22:45:36 +0300 Subject: [PATCH] Use English operator UI copy --- .../internal/transport/http/server_test.go | 2 +- .../transport/http/templates/dashboard.html | 48 +++------------ .../transport/http/templates/job.html | 36 ++++------- .../transport/http/templates/new-job.html | 60 ++++--------------- coordinator/internal/transport/http/ui.go | 38 ++++++------ .../internal/transport/http/ui_test.go | 8 +-- 6 files changed, 52 insertions(+), 140 deletions(-) diff --git a/coordinator/internal/transport/http/server_test.go b/coordinator/internal/transport/http/server_test.go index 6199c51..01c299f 100644 --- a/coordinator/internal/transport/http/server_test.go +++ b/coordinator/internal/transport/http/server_test.go @@ -140,7 +140,7 @@ func TestUIRequiresDistinctCredentialAndRendersDashboard(t *testing.T) { t.Fatalf("UI status: %d", resp.StatusCode) } body, _ := io.ReadAll(resp.Body) - if !strings.Contains(string(body), "Панель оператора SciMesh") { + if !strings.Contains(string(body), "SciMesh operator dashboard") { t.Errorf("dashboard body missing title") } } diff --git a/coordinator/internal/transport/http/templates/dashboard.html b/coordinator/internal/transport/http/templates/dashboard.html index 695c3c8..f4769ee 100644 --- a/coordinator/internal/transport/http/templates/dashboard.html +++ b/coordinator/internal/transport/http/templates/dashboard.html @@ -1,56 +1,22 @@ {{define "dashboard.html"}} - + - SciMesh — панель оператора + SciMesh operator dashboard
-
-
-

Локальный coordinator

-

Панель оператора SciMesh

-

Здесь видно, где находится вычисление и что нужно сделать дальше.

-
- Запустить проверку -
- -
- Текущий этап — диагностика shard-задач. - Worker загружает частичные CSV в coordinator. Пока reducer не реализован, эти файлы не являются единым финальным научным результатом. -
1. Загрузить TSVCoordinator делит файл на shard-задачи.
2. Дождаться workerWorker берёт shard, вычисляет сходство и возвращает CSV.
3. Проверить артефактыСкачайте частичный результат из карточки задачи.
-
- -

Последние задания

-
- - - {{range .Jobs}} - - - - - - - {{else}} - - {{end}} -
ВычислениеСостояниеПрогрессСоздано
{{workloadLabel .Workload}}
Открыть детали задачи
{{statusLabel .Status}}
{{statusHint .Status}}
{{.Completed}} / {{.Total}} завершено{{if gt .Failed 0}} · ошибок: {{.Failed}}{{end}}
{{time .CreatedAt}}
Заданий пока нет.
Нажмите «Запустить проверку», загрузите небольшой TSV и оставьте worker запущенным.
-
- +

Local coordinator

SciMesh operator dashboard

See where a computation is and what should happen next.

Start a check
+
This screen currently diagnoses shard jobs.Workers upload partial CSVs to the coordinator. Until a reducer is implemented, those files are not one final scientific result.
1. Upload TSVThe coordinator splits the file into shard tasks.
2. Wait for a workerA worker claims a shard, calculates similarity, and returns a CSV.
3. Inspect artifactsDownload a partial result from the job page.
+

Recent jobs

+
{{range .Jobs}}{{else}}{{end}}
ComputationStateProgressCreated
{{workloadLabel .Workload}}
Open job details
{{statusLabel .Status}}
{{statusHint .Status}}
{{.Completed}} / {{.Total}} complete{{if gt .Failed 0}} · failed: {{.Failed}}{{end}}
{{time .CreatedAt}}
No jobs yet.
Click “Start a check”, upload a small TSV, and leave a worker running.

Workers

-
- {{range .Workers}} -
{{.Name}}
{{.ID}}
{{workerStatusLabel .Status}}
{{range .Capabilities}}{{.}} {{end}}
Последний сигнал
{{time .LastHeartbeatAt}}
- {{else}} -
Worker ещё не зарегистрирован.
Запустите scimesh-worker с URL coordinator и worker token.
- {{end}} -
+
{{range .Workers}}
{{.Name}}
{{.ID}}
{{workerStatusLabel .Status}}
{{range .Capabilities}}{{.}} {{end}}
Last signal
{{time .LastHeartbeatAt}}
{{else}}
No worker is registered yet.
Run scimesh-worker with the coordinator URL and worker token.
{{end}}
diff --git a/coordinator/internal/transport/http/templates/job.html b/coordinator/internal/transport/http/templates/job.html index 1b0d2d1..3d744de 100644 --- a/coordinator/internal/transport/http/templates/job.html +++ b/coordinator/internal/transport/http/templates/job.html @@ -1,41 +1,27 @@ {{define "job.html"}} - + - Задача SciMesh + SciMesh job
- ← К списку заданий -

{{workloadLabel .Workload}}

-

Ход выполнения

- -
-
{{statusLabel .Status}}

{{statusHint .Status}}

Сводка обновляется автоматически каждые 2 секунды.
-
-

{{.Completed}} из {{.Total}} задач завершено

-
{{.Total}}всего shard
{{.Completed}}завершено
{{.Pending}}ожидает
{{add .Leased .Running}}у worker
{{.Failed}}ошибок
-
Технические сведения

Job ID: {{.ID}}
Вычисление: {{.Workload}}
Создано: {{time .CreatedAt}}

-
- -
Что можно скачать сейчас?
Файлы partial_result — результат отдельных shards. Они полезны для проверки pipeline, но ещё не являются объединённым финальным CSV: reducer пока не реализован.
- -

Shard-задачи

-

Если есть ошибки, в этой таблице видно код и сообщение. Подробные строки обновляются после обычного обновления страницы.

-
{{range .Tasks}}{{else}}{{end}}
ShardСостояниеПопыткаWorker / leaseОшибка
#{{.ChunkIndex}}{{statusLabel .Status}}{{.Attempt}} / {{.MaxAttempts}}{{if .LeaseOwner}}{{.LeaseOwner}}{{if .LeaseExpiresAt}}
до {{time .LeaseExpiresAt}}{{end}}{{else}}{{end}}
{{if .ErrorCode}}{{.ErrorCode}}
{{.ErrorMessage}}{{else}}{{end}}
Задачи пока не появились.
- -

Артефакты coordinator

-
{{range .Artifacts}}{{else}}{{end}}
ТипФайлРазмерПроверка целостности
{{if .Diagnostic}}Частичный результат
диагностический{{else}}{{.Kind}}{{end}}
{{.Filename}}{{bytes .SizeBytes}}{{.SHA256}}{{if .Downloadable}}Скачать CSV{{else}}Недоступно{{end}}
Артефактов ещё нет: worker загрузит CSV после выполнения shard.
+ ← Back to jobs

{{workloadLabel .Workload}}

Execution progress

+
{{statusLabel .Status}}

{{statusHint .Status}}

Summary refreshes automatically every two seconds.

{{.Completed}} of {{.Total}} tasks complete

{{.Total}}total shards
{{.Completed}}complete
{{.Pending}}waiting
{{add .Leased .Running}}with workers
{{.Failed}}failed
Technical details

Job ID: {{.ID}}
Workload: {{.Workload}}
Created: {{time .CreatedAt}}

+
What can be downloaded now?
partial_result files come from individual shards. They are useful for checking the pipeline, but are not a merged final CSV because the reducer is not implemented yet.
+

Shard tasks

If a task fails, its code and message appear here. Refresh the page to update the detailed rows.

+
{{range .Tasks}}{{else}}{{end}}
ShardStateAttemptWorker / leaseError
#{{.ChunkIndex}}{{statusLabel .Status}}{{.Attempt}} / {{.MaxAttempts}}{{if .LeaseOwner}}{{.LeaseOwner}}{{if .LeaseExpiresAt}}
until {{time .LeaseExpiresAt}}{{end}}{{else}}{{end}}
{{if .ErrorCode}}{{.ErrorCode}}
{{.ErrorMessage}}{{else}}{{end}}
No tasks have appeared yet.
+

Coordinator artifacts

+
{{range .Artifacts}}{{else}}{{end}}
TypeFileSizeIntegrity check
{{if .Diagnostic}}Partial result
diagnostic{{else}}{{.Kind}}{{end}}
{{.Filename}}{{bytes .SizeBytes}}{{.SHA256}}{{if .Downloadable}}Download CSV{{else}}Unavailable{{end}}
No artifacts yet. The worker uploads a CSV after it completes a shard.
diff --git a/coordinator/internal/transport/http/templates/new-job.html b/coordinator/internal/transport/http/templates/new-job.html index 0a7cce7..5a28bf2 100644 --- a/coordinator/internal/transport/http/templates/new-job.html +++ b/coordinator/internal/transport/http/templates/new-job.html @@ -1,69 +1,29 @@ {{define "new-job.html"}} - + - Создать проверку — SciMesh + Create a check — SciMesh
- ← К списку заданий -

Пошаговый запуск

-

Поиск похожих молекул

-

Создаёт диагностическую задачу similarity-search: worker найдёт top-k молекул, похожих на заданный SMILES.

- -
- Перед запуском -
  • Оставьте хотя бы один scimesh-worker запущенным.
  • Для ручной проверки используйте небольшой TSV.
  • «Строк в shard» не ограничивает размер файла. Он делит весь загруженный файл на задачи: большой ChEMBL TSV при 1000 строках создаст тысячи задач.
-
- + ← Back to jobs

Guided run

Search for similar molecules

Creates a diagnostic similarity-search job: a worker finds the top-k molecules most similar to a target SMILES.

+
Before starting
  • Keep at least one scimesh-worker running.
  • Use a small TSV for a hands-on check.
  • “Rows per shard” does not limit the file size. It splits the entire upload into tasks: a full ChEMBL TSV at 1,000 rows per shard creates thousands of tasks.
- - -

Ожидаются столбцы chembl_id и canonical_smiles.

- - - -

Пример CCO — этанол. Для гефитиниба используйте его SMILES или локальный CLI с --query-id.

- - - -

Top-k для каждого shard. Это пока не глобальный top-k всего датасета.

- - - -

Меньше строк — больше задач и более наглядный прогресс; больше строк — меньше задач, но дольше каждая.

- - - - +

Expected columns: chembl_id and canonical_smiles.

+

CCO is ethanol. For gefitinib, use its SMILES here or the local CLI with --query-id.

+

This is the top-k within each shard, not a global top-k for the whole dataset yet.

+

Fewer rows mean more tasks and more visible progress; more rows mean fewer, longer tasks.

+
diff --git a/coordinator/internal/transport/http/ui.go b/coordinator/internal/transport/http/ui.go index 3074e1a..e483ea8 100644 --- a/coordinator/internal/transport/http/ui.go +++ b/coordinator/internal/transport/http/ui.go @@ -40,15 +40,15 @@ func formatUITime(t time.Time) string { func uiStatusLabel(status string) string { switch status { case "pending": - return "Ожидает worker" + return "Waiting for a worker" case "leased": - return "Выдана worker" + return "Assigned to a worker" case "running": - return "Выполняется" + return "Running" case "completed": - return "Задачи завершены" + return "Tasks complete" case "failed": - return "Требует внимания" + return "Needs attention" default: return status } @@ -57,17 +57,17 @@ func uiStatusLabel(status string) string { func uiStatusHint(status string) string { switch status { case "pending": - return "Ожидает свободный worker с нужной возможностью." + return "Waiting for an available worker with the required capability." case "leased": - return "Worker уже забрал задачу и должен скоро начать вычисление." + return "A worker has claimed the task and should begin processing shortly." case "running": - return "Worker читает shard, считает fingerprints и загружает результат через coordinator." + return "A worker is reading a shard, calculating fingerprints, and uploading its result through the coordinator." case "completed": - return "Все shard-задачи завершены. Доступные ниже файлы пока являются частичными результатами." + return "Every shard task is complete. Files below are still partial results." case "failed": - return "Одна или несколько shard-задач завершились ошибкой. Откройте список задач ниже." + return "One or more shard tasks failed. Open the task list below for details." default: - return "Статус получен от coordinator." + return "Status reported by the coordinator." } } @@ -87,9 +87,9 @@ func uiStatusClass(status string) string { func uiWorkerStatusLabel(status string) string { switch status { case "online": - return "Доступен" + return "Available" case "offline": - return "Нет связи" + return "Offline" default: return status } @@ -98,9 +98,9 @@ func uiWorkerStatusLabel(status string) string { func uiWorkloadLabel(workload string) string { switch workload { case "similarity-search", "similarity_search": - return "Поиск похожих молекул" + return "Molecule similarity search" case "similarity-graph", "similarity_graph": - return "Граф молекулярного сходства" + return "Molecular similarity graph" default: return workload } @@ -120,15 +120,15 @@ func uiProgressPercent(completed, failed, total int) int { func uiBytes(n int64) string { const kib = 1024 if n < kib { - return fmt.Sprintf("%d Б", n) + return fmt.Sprintf("%d B", n) } if n < kib*kib { - return fmt.Sprintf("%.1f КиБ", float64(n)/kib) + return fmt.Sprintf("%.1f KiB", float64(n)/kib) } if n < kib*kib*kib { - return fmt.Sprintf("%.1f МиБ", float64(n)/(kib*kib)) + return fmt.Sprintf("%.1f MiB", float64(n)/(kib*kib)) } - return fmt.Sprintf("%.1f ГиБ", float64(n)/(kib*kib*kib)) + return fmt.Sprintf("%.1f GiB", float64(n)/(kib*kib*kib)) } func (s *Server) renderUI(w http.ResponseWriter, name string, data any) { diff --git a/coordinator/internal/transport/http/ui_test.go b/coordinator/internal/transport/http/ui_test.go index 993036d..cb56a88 100644 --- a/coordinator/internal/transport/http/ui_test.go +++ b/coordinator/internal/transport/http/ui_test.go @@ -8,10 +8,10 @@ func TestUIStatusPresentation(t *testing.T) { label string class string }{ - {"pending", "Ожидает worker", "waiting"}, - {"running", "Выполняется", "active"}, - {"completed", "Задачи завершены", "success"}, - {"failed", "Требует внимания", "danger"}, + {"pending", "Waiting for a worker", "waiting"}, + {"running", "Running", "active"}, + {"completed", "Tasks complete", "success"}, + {"failed", "Needs attention", "danger"}, } for _, test := range tests { t.Run(test.status, func(t *testing.T) {