fix(qa-report): version tag, /drafts redirect, audit filter complete, i18n cleanup
QA report v2.31.x batch:
- **VersionController.tag**: было 'none' (maven build на main без git tag) → UI
показывал «dev · 6077d4df». Helm передаёт image.tag через env
ORDINIS_BUILD_IMAGE_TAG, controller парсит «v2-31-2-e3c82775» → «v2.31.2».
Helm chart change в ordinis-infra (separate MR).
- **/drafts redirect** (BUG-003): пустой 404 «Not Found» plain text → теперь
static redirect на /my-drafts.
- **Audit action filter** (BUG-004): дропдаун содержал только 3 значения
(CREATE/UPDATE/CLOSE), но в таблице 11 типов (DRAFT_*, DEFINITION_*).
Frontend AuditAction enum + ACTIONS list синхронизированы с backend
AuditLogger/SchemaDraftService/DraftService.
- **i18n cleanup** (BUG-006/007/UX-005):
- myDrafts.description: «Все ваши submissions с pending/approved...» →
«Все ваши черновики с историей: ожидает рассмотрения, одобрен...»
- reviews.description: «Pending drafts от makers, ждут approve/reject» →
«Черновики от авторов, ждут одобрения или отклонения. Общая очередь...»
- reviews.queueTotal: «N pending drafts» → «N черновиков в очереди»
- myDrafts.col.reviewer: «Reviewer» → «Рецензент» (RU only)
- notifications chip labels: 'submit/approved/rejected' → 'отправлен/
одобрен/отклонён'
- audit.action.* expanded к 13 entries для каждого backend action
type, с понятными лейблами «Черновик одобрен» вместо «DRAFT_APPROVE»
- **WhatsNewModal markdown** (UX-006): тексты вроде «**График доставки
webhook'ов**» рендерились с буквальными звёздочками. Mini inline renderer
для **bold**, *italic*, `code` — без full markdown library.
This commit is contained in:
@@ -220,17 +220,21 @@ function badgeVariant(
|
||||
* Event type → short russian label для chip. Server-side resolution лучше,
|
||||
* но пока mapping inline здесь — backend payloadPreview уже несёт полный
|
||||
* человеческий текст, chip это просто категория.
|
||||
*
|
||||
* <p>UX-005 fix: были английские labels (submit/approved/rejected) — chip
|
||||
* читается носителями русского как «Draft approved 15.05.2026», что выглядит
|
||||
* как baked-in EN текст. Теперь короткие русские.
|
||||
*/
|
||||
function humanEventType(eventType: string): string {
|
||||
const map: Record<string, string> = {
|
||||
RecordDraftSubmitted: 'submit',
|
||||
RecordDraftApproved: 'approved',
|
||||
RecordDraftRejected: 'rejected',
|
||||
RecordDraftWithdrawn: 'withdrawn',
|
||||
SchemaDraftSubmitted: 'schema submit',
|
||||
SchemaDraftApproved: 'schema approved',
|
||||
SchemaDraftRejected: 'schema rejected',
|
||||
SchemaDraftPublished: 'schema published',
|
||||
RecordDraftSubmitted: 'отправлен',
|
||||
RecordDraftApproved: 'одобрен',
|
||||
RecordDraftRejected: 'отклонён',
|
||||
RecordDraftWithdrawn: 'отозван',
|
||||
SchemaDraftSubmitted: 'схема: отправлена',
|
||||
SchemaDraftApproved: 'схема: одобрена',
|
||||
SchemaDraftRejected: 'схема: отклонена',
|
||||
SchemaDraftPublished: 'схема: опубликована',
|
||||
}
|
||||
return map[eventType] ?? eventType
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type * as React from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { SparkleIcon } from '@phosphor-icons/react'
|
||||
@@ -136,6 +137,32 @@ function EntryCard({ entry, isUnread }: { entry: ChangelogEntry; isUnread: boole
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Mini inline-markdown renderer для changelog описаний. UX-006: тексты
|
||||
* вроде «**График доставки webhook'ов**» рендерились с буквальными
|
||||
* звёздочками. Pulling full markdown library overkill для трёх правил.
|
||||
*
|
||||
* <p>Поддерживает: {@code **bold**}, {@code *italic*}, {@code `code`}.
|
||||
* Stops parsing на первом неподдержанном паттерне — текст остаётся как есть.
|
||||
*/
|
||||
function renderInlineMarkdown(text: string): React.ReactNode {
|
||||
const parts: React.ReactNode[] = []
|
||||
// Pattern matches **bold**, `code`, или *italic* (lazy, non-greedy).
|
||||
const pattern = /(\*\*([^*\n]+?)\*\*|`([^`\n]+?)`|\*([^*\n]+?)\*)/g
|
||||
let lastIndex = 0
|
||||
let key = 0
|
||||
let m: RegExpExecArray | null
|
||||
while ((m = pattern.exec(text)) !== null) {
|
||||
if (m.index > lastIndex) parts.push(text.slice(lastIndex, m.index))
|
||||
if (m[2] !== undefined) parts.push(<strong key={key++}>{m[2]}</strong>)
|
||||
else if (m[3] !== undefined) parts.push(<code key={key++} className="text-mono text-cap bg-surface-2 px-1 rounded-sm">{m[3]}</code>)
|
||||
else if (m[4] !== undefined) parts.push(<em key={key++}>{m[4]}</em>)
|
||||
lastIndex = pattern.lastIndex
|
||||
}
|
||||
if (lastIndex < text.length) parts.push(text.slice(lastIndex))
|
||||
return parts.length > 0 ? parts : text
|
||||
}
|
||||
|
||||
function SectionBlock({ section }: { section: ChangelogSection }) {
|
||||
return (
|
||||
<div>
|
||||
@@ -151,7 +178,7 @@ function SectionBlock({ section }: { section: ChangelogSection }) {
|
||||
{item.scope && (
|
||||
<span className="text-mono text-cap text-accent mr-1.5">{item.scope}:</span>
|
||||
)}
|
||||
<span>{item.description}</span>
|
||||
<span>{renderInlineMarkdown(item.description)}</span>
|
||||
{item.commit && item.commitUrl && (
|
||||
<a
|
||||
href={item.commitUrl}
|
||||
|
||||
Reference in New Issue
Block a user