Treat current configuration as main

This commit is contained in:
Mikhail Chusavitin
2026-03-17 18:43:49 +03:00
parent 20ce0124be
commit a8d8d7dfa9
4 changed files with 53 additions and 23 deletions

View File

@@ -135,15 +135,18 @@ async function loadVersions() {
}
function renderVersions(versions) {
if (versions.length === 0) {
const currentVersionNo = configData && configData.current_version_no ? Number(configData.current_version_no) : null;
const snapshots = versions.filter(v => Number(v.version_no) !== currentVersionNo);
if (snapshots.length === 0) {
document.getElementById('revisions-list').innerHTML =
'<div class="bg-white rounded-lg shadow p-8 text-center text-gray-500">Нет ревизий</div>';
'<div class="bg-white rounded-lg shadow p-8 text-center text-gray-500">Нет прошлых снимков. Рабочая версия остается main.</div>';
return;
}
let html = '<div class="bg-white rounded-lg shadow overflow-hidden"><table class="w-full">';
html += '<thead class="bg-gray-50"><tr>';
html += '<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Версия</th>';
html += '<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Снимок</th>';
html += '<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Дата</th>';
html += '<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Автор</th>';
html += '<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Артикул</th>';
@@ -152,16 +155,14 @@ function renderVersions(versions) {
html += '<th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase">Действия</th>';
html += '</tr></thead><tbody class="divide-y">';
versions.forEach((v, idx) => {
snapshots.forEach((v) => {
const date = new Date(v.created_at).toLocaleString('ru-RU');
const author = v.created_by || '—';
const snapshot = parseVersionSnapshot(v);
const isCurrent = idx === 0;
html += '<tr class="hover:bg-gray-50' + (isCurrent ? ' bg-blue-50' : '') + '">';
html += '<tr class="hover:bg-gray-50">';
html += '<td class="px-4 py-3 text-sm font-medium">';
html += 'v' + v.version_no;
if (isCurrent) html += ' <span class="text-xs text-blue-600 font-normal">(текущая)</span>';
html += '</td>';
html += '<td class="px-4 py-3 text-sm text-gray-500">' + escapeHtml(date) + '</td>';
html += '<td class="px-4 py-3 text-sm text-gray-500">' + escapeHtml(author) + '</td>';
@@ -178,11 +179,8 @@ function renderVersions(versions) {
html += '<button onclick="cloneFromVersion(' + v.version_no + ')" class="text-green-600 hover:text-green-800" title="Скопировать из этой ревизии">';
html += '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path></svg></button>';
// Rollback (not for current version)
if (!isCurrent) {
html += '<button onclick="rollbackToVersion(' + v.version_no + ')" class="text-orange-600 hover:text-orange-800" title="Восстановить эту ревизию">';
html += '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6"></path></svg></button>';
}
html += '<button onclick="rollbackToVersion(' + v.version_no + ')" class="text-orange-600 hover:text-orange-800" title="Восстановить этот снимок как новую main-версию">';
html += '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6"></path></svg></button>';
html += '</td></tr>';
});
@@ -212,7 +210,7 @@ async function cloneFromVersion(versionNo) {
}
async function rollbackToVersion(versionNo) {
if (!confirm('Восстановить конфигурацию до ревизии v' + versionNo + '?')) return;
if (!confirm('Восстановить снимок v' + versionNo + ' как новую рабочую версию main?')) return;
const resp = await fetch('/api/configs/' + configUUID + '/rollback', {
method: 'POST',
headers: {'Content-Type': 'application/json'},

View File

@@ -24,7 +24,7 @@
<span id="breadcrumb-config-name">Конфигуратор</span>
</a>
<span class="text-gray-400">-</span>
<span id="breadcrumb-config-version">v1</span>
<span id="breadcrumb-config-version">main</span>
</div>
</div>
<div id="save-buttons" class="hidden flex items-center space-x-2">
@@ -476,7 +476,7 @@ function updateConfigBreadcrumbs() {
const fullConfigName = configName || 'Конфигурация';
configEl.textContent = truncateBreadcrumbSpecName(fullConfigName);
configEl.title = fullConfigName;
versionEl.textContent = 'v' + (currentVersionNo || 1);
versionEl.textContent = 'main';
const configNameLinkEl = document.getElementById('breadcrumb-config-name-link');
if (configNameLinkEl && configUUID) {
configNameLinkEl.href = '/configs/' + configUUID + '/revisions';
@@ -2172,9 +2172,8 @@ async function saveConfig(showNotification = true) {
const saved = await resp.json();
if (saved && saved.current_version_no) {
currentVersionNo = saved.current_version_no;
const versionEl = document.getElementById('breadcrumb-config-version');
if (versionEl) versionEl.textContent = 'v' + currentVersionNo;
}
updateConfigBreadcrumbs();
hasUnsavedChanges = false;
clearAutosaveDraft();
exitSaveStarted = false;

View File

@@ -472,8 +472,7 @@ function renderConfigs(configs) {
html += '<td class="px-4 py-3 text-sm text-gray-500"><input type="number" min="1" value="' + serverCount + '" class="w-16 px-1 py-0.5 border rounded text-center text-sm" data-uuid="' + c.uuid + '" data-prev="' + serverCount + '" onchange="updateConfigServerCount(this)"></td>';
}
html += '<td class="px-4 py-3 text-sm text-right" data-total-uuid="' + c.uuid + '">' + formatMoneyNoDecimals(total) + '</td>';
const versionNo = c.current_version_no || 1;
html += '<td class="px-2 py-3 text-sm text-center text-gray-500 w-12">v' + versionNo + '</td>';
html += '<td class="px-2 py-3 text-sm text-center text-gray-500 w-12">main</td>';
html += '<td class="px-4 py-3 text-sm text-right whitespace-nowrap"><div class="inline-flex items-center justify-end gap-2">';
if (configStatusMode === 'archived') {
html += '<button onclick="reactivateConfig(\'' + c.uuid + '\')" class="text-emerald-600 hover:text-emerald-800" title="Восстановить">';