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:
Zimin A.N.
2026-05-15 22:02:29 +03:00
parent e3c827752e
commit ff7e72e0fd
8 changed files with 201 additions and 28 deletions
@@ -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}