diff --git a/src/features/control-center/pages/ModulesPage.tsx b/src/features/control-center/pages/ModulesPage.tsx index 4ca8ef6..df22b00 100644 --- a/src/features/control-center/pages/ModulesPage.tsx +++ b/src/features/control-center/pages/ModulesPage.tsx @@ -5,10 +5,12 @@ import { Pause, RotateCcw, Sliders, + Sparkles, } from 'lucide-react'; import { useKccStore, useOperatorRole } from '../store/kccStore'; import { StatusBadge } from '../components/StatusBadge'; import { RolloutStage } from '../contracts'; +import { RU_ROLLOUT_STAGE, RU_MODULE_CATEGORY } from '../locales/ru'; export const ModulesPage: React.FC = () => { const modules = useKccStore((state) => state.modules); @@ -31,10 +33,11 @@ export const ModulesPage: React.FC = () => { const handleStageChange = (stage: RolloutStage, percentage: number) => { if (!activeRollout) return; + const stageLabel = RU_ROLLOUT_STAGE[stage] || stage; openConfirmModal({ title: `Смена фазы раскатки: ${activeRollout.moduleName}`, actionName: `rollout.stage_${stage}`, - impactSummary: `Конвейер раскатки будет переведен в состояние «${stage}» (${percentage}% трафика).`, + impactSummary: `Конвейер раскатки будет переведен в состояние «${stageLabel}» (${percentage}% трафика).`, targetType: 'rollout', targetId: activeRollout.rolloutId, targetName: activeRollout.moduleName, @@ -68,34 +71,39 @@ export const ModulesPage: React.FC = () => { }; return ( -
+
{/* Header */} -
+
-

- +

+ Каталог модулей и Rollout конвейер

-

- Управление манифестами, compatibility core/schema, пилотными организациями и фазовыми релизами +

+ Управление версиями модулей, совместимостью с ядром, пилотными группами и канареечным развертыванием

-
- Всего модулей: {modules.length} • Активных раскаток:{' '} - {rollouts.length} +
+ + Всего модулей: {modules.length} + + + Активных раскаток: {rollouts.length} +
{/* Grid: Module Selector + Module Detail & Rollout Manager */} -
+
{/* Left Column: Modules Catalog List */} -
-
+
+
Каталог системных модулей
-
+ {/* Module list with min 44px items */} +
{modules.map((m) => { const isSelected = m.moduleId === selectedModuleId; const hasRollout = rollouts.some((r) => r.moduleId === m.moduleId); @@ -104,24 +112,24 @@ export const ModulesPage: React.FC = () => {
setSelectedModuleId(m.moduleId)} - className={`p-3 rounded-lg border text-xs cursor-pointer transition-colors space-y-1.5 ${ + className={`min-h-[44px] p-3 rounded-lg border text-xs cursor-pointer transition-colors space-y-1.5 ${ isSelected - ? 'bg-amber-500/15 border-amber-500/40 text-zinc-100' - : 'bg-zinc-950/60 border-zinc-800 text-zinc-400 hover:bg-zinc-800/50 hover:text-zinc-200' + ? 'bg-amber-500/15 border-amber-500/40 text-krona-primary shadow-xs' + : 'bg-krona-workspace border-krona-border text-krona-secondary hover:bg-krona-surface hover:text-krona-primary' }`} >
- {m.name} - + {m.name} + v{m.latestVersion}
-

{m.description}

-
- Тенантов: {m.activeTenantsCount} • Инстансов: {m.instancesCount} +

{m.description}

+
+ Организаций: {m.activeTenantsCount} • Установок: {m.instancesCount} {hasRollout && ( - - Rollout + + Раскатка )}
@@ -132,97 +140,115 @@ export const ModulesPage: React.FC = () => {
{/* Right 2 Columns: Module Details & Rollout Controller */} -
+
{selectedModule && ( <> {/* Module Header Card */} -
-
+
+
-
- {selectedModule.code} - • - Категория: {selectedModule.category} +
+ {selectedModule.code} + • + + Категория: {RU_MODULE_CATEGORY[selectedModule.category] || selectedModule.category} +
-

{selectedModule.name}

-

{selectedModule.description}

+

{selectedModule.name}

+

{selectedModule.description}

-
- Текущая стабильная версия: -
v{selectedModule.latestVersion}
+
+ Текущая версия: +
+ v{selectedModule.latestVersion} +
-
-
-
Канал релиза:
-
{selectedModule.rolloutChannel}
+
+
+
Канал релиза:
+
{selectedModule.rolloutChannel}
-
-
Манифест:
-
v{selectedModule.manifestVersion}
+
+
Манифест:
+
v{selectedModule.manifestVersion}
-
-
Зависимости:
-
- {selectedModule.dependencies.length > 0 ? selectedModule.dependencies.join(', ') : 'Нет (Базовый)'} +
+
Зависимости:
+
+ {selectedModule.dependencies.length > 0 ? selectedModule.dependencies.join(', ') : 'Базовый'}
- {/* Rollout Control Panel (Сценарий 8) */} -
-
+ {/* Rollout Control Panel */} +
+
- -

Управление раскаткой (Rollout Pipeline)

+ +

+ Управление конвейером раскатки (Rollout) +

- {activeRollout && } + {activeRollout && ( + + )}
{activeRollout ? (
{/* Progress visualizer */} -
+
- - Целевая версия: v{activeRollout.targetVersion} + + Целевая версия:{' '} + v{activeRollout.targetVersion} - {activeRollout.percentage}% + {activeRollout.percentage}%
-
+
-
- Стадия: {activeRollout.stage} +
+ + Стадия:{' '} + + {RU_ROLLOUT_STAGE[activeRollout.stage] || activeRollout.stage} + + Пилотных организаций: {activeRollout.pilotTenantIds.length} Старт: {new Date(activeRollout.startedAt).toLocaleDateString('ru-RU')}
- {/* Rollout Action Buttons */} + {/* Rollout Action Buttons with min 44px touch targets */}
@@ -231,7 +257,7 @@ export const ModulesPage: React.FC = () => { type="button" disabled={!permissions.canTriggerRollouts || activeRollout.stage === 'general_availability'} onClick={() => handleStageChange('general_availability', 100)} - className="px-3 py-1.5 rounded-lg bg-emerald-950 text-emerald-300 border border-emerald-700 hover:bg-emerald-900 text-xs font-bold disabled:opacity-40 transition-colors" + className="min-h-[44px] px-4 py-2 rounded-lg bg-emerald-500/15 text-emerald-600 dark:text-emerald-300 border border-emerald-500/40 hover:bg-emerald-500/25 text-xs font-bold disabled:opacity-40 transition-colors shadow-xs" > Фаза 3: Полный релиз (100% GA) @@ -241,19 +267,19 @@ export const ModulesPage: React.FC = () => { type="button" disabled={!permissions.canPauseRollbackRollouts} onClick={() => handleStageChange('paused', activeRollout.percentage)} - className="px-3 py-1.5 rounded-lg bg-amber-950/70 text-amber-300 border border-amber-700 hover:bg-amber-900/60 text-xs font-bold disabled:opacity-40 transition-colors flex items-center gap-1.5" + className="min-h-[44px] px-3.5 py-2 rounded-lg bg-amber-500/15 text-amber-600 dark:text-amber-300 border border-amber-500/40 hover:bg-amber-500/25 text-xs font-bold disabled:opacity-40 transition-colors flex items-center gap-1.5 shadow-xs" > - - Поставить на паузу + + На паузу ) : ( )} @@ -262,47 +288,50 @@ export const ModulesPage: React.FC = () => { type="button" disabled={!permissions.canPauseRollbackRollouts || activeRollout.stage === 'rolled_back'} onClick={() => handleStageChange('rolled_back', 0)} - className="px-3 py-1.5 rounded-lg bg-rose-950 text-rose-300 border border-rose-700 hover:bg-rose-900 text-xs font-bold disabled:opacity-40 transition-colors flex items-center gap-1.5" + className="min-h-[44px] px-3.5 py-2 rounded-lg bg-rose-500/15 text-rose-600 dark:text-rose-300 border border-rose-500/40 hover:bg-rose-500/25 text-xs font-bold disabled:opacity-40 transition-colors flex items-center gap-1.5 shadow-xs" > - - Rollback (Откат) + + Откат (Rollback)
) : ( -
-

- Для модуля {selectedModule.name} нет активных раскаток. - Вы можете запустить пилотный релиз новой версии. +

+

+ Для модуля {selectedModule.name} нет активных раскаток. + Вы можете запустить пилотный релиз новой версии для проверки совместимости.

)}
{/* Release History & Deployments */} -
-

История релизов и совместимость (Compatibility)

+
+

+ + История релизов и совместимость +

{selectedModule.releaseHistory.map((rel) => ( -
+
- v{rel.version} - + v{rel.version} + {new Date(rel.releasedAt).toLocaleDateString('ru-RU')}
-

{rel.changelog}

-
- Совместимость с Core: {rel.compatibleCore} +

{rel.changelog}

+
+ Совместимость с ядром: {rel.compatibleCore}
))} @@ -315,3 +344,4 @@ export const ModulesPage: React.FC = () => {
); }; +