configs: save pending template changes
This commit is contained in:
@@ -63,10 +63,16 @@
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Проект</label>
|
||||
<select id="create-project-select"
|
||||
class="w-full px-3 py-2 border rounded focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
||||
<option value="">Без проекта</option>
|
||||
</select>
|
||||
<input id="create-project-input"
|
||||
list="create-project-options"
|
||||
placeholder="Начните вводить название проекта"
|
||||
class="w-full px-3 py-2 border rounded focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
||||
<datalist id="create-project-options"></datalist>
|
||||
<div class="mt-2 flex justify-between items-center gap-3">
|
||||
<button type="button" onclick="clearCreateProjectInput()" class="text-sm text-gray-600 hover:text-gray-800">
|
||||
Без проекта
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -171,10 +177,10 @@
|
||||
<div id="create-project-on-move-modal" class="fixed inset-0 bg-black bg-opacity-50 hidden items-center justify-center z-50">
|
||||
<div class="bg-white rounded-lg shadow-xl w-full max-w-md mx-4 p-6">
|
||||
<h2 class="text-xl font-semibold mb-3">Проект не найден</h2>
|
||||
<p class="text-sm text-gray-600 mb-4">Проект "<span id="create-project-on-move-name" class="font-medium text-gray-900"></span>" не найден. Создать и привязать квоту?</p>
|
||||
<p class="text-sm text-gray-600 mb-4">Проект "<span id="create-project-on-move-name" class="font-medium text-gray-900"></span>" не найден. <span id="create-project-on-move-description">Создать и привязать квоту?</span></p>
|
||||
<div class="flex justify-end space-x-3">
|
||||
<button onclick="closeCreateProjectOnMoveModal()" class="px-4 py-2 text-gray-600 hover:text-gray-800">Отмена</button>
|
||||
<button onclick="confirmCreateProjectOnMove()" class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">Создать и привязать</button>
|
||||
<button id="create-project-on-move-confirm-btn" onclick="confirmCreateProjectOnMove()" class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">Создать и привязать</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -190,6 +196,8 @@ let projectsCache = [];
|
||||
let projectNameByUUID = {};
|
||||
let pendingMoveConfigUUID = '';
|
||||
let pendingMoveProjectName = '';
|
||||
let pendingCreateConfigName = '';
|
||||
let pendingCreateProjectName = '';
|
||||
|
||||
function renderConfigs(configs) {
|
||||
const emptyText = configStatusMode === 'archived'
|
||||
@@ -407,6 +415,7 @@ async function cloneConfig() {
|
||||
|
||||
function openCreateModal() {
|
||||
document.getElementById('opportunity-number').value = '';
|
||||
document.getElementById('create-project-input').value = '';
|
||||
document.getElementById('create-modal').classList.remove('hidden');
|
||||
document.getElementById('create-modal').classList.add('flex');
|
||||
document.getElementById('opportunity-number').focus();
|
||||
@@ -425,8 +434,25 @@ async function createConfig() {
|
||||
return;
|
||||
}
|
||||
|
||||
const projectUUID = document.getElementById('create-project-select').value;
|
||||
const projectName = document.getElementById('create-project-input').value.trim();
|
||||
let projectUUID = '';
|
||||
|
||||
if (projectName) {
|
||||
const existingProject = projectsCache.find(p => p.is_active && p.name.toLowerCase() === projectName.toLowerCase());
|
||||
if (existingProject) {
|
||||
projectUUID = existingProject.uuid;
|
||||
} else {
|
||||
pendingCreateConfigName = name;
|
||||
pendingCreateProjectName = projectName;
|
||||
openCreateProjectOnCreateModal(projectName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await createConfigWithProject(name, projectUUID);
|
||||
}
|
||||
|
||||
async function createConfigWithProject(name, projectUUID) {
|
||||
try {
|
||||
const resp = await fetch('/api/configs', {
|
||||
method: 'POST',
|
||||
@@ -442,16 +468,17 @@ async function createConfig() {
|
||||
})
|
||||
});
|
||||
|
||||
const config = await resp.json();
|
||||
if (!resp.ok) {
|
||||
const err = await resp.json();
|
||||
alert('Ошибка: ' + (err.error || 'Не удалось создать'));
|
||||
return;
|
||||
alert('Ошибка: ' + (config.error || 'Не удалось создать'));
|
||||
return false;
|
||||
}
|
||||
|
||||
const config = await resp.json();
|
||||
window.location.href = '/configurator?uuid=' + config.uuid;
|
||||
return true;
|
||||
} catch(e) {
|
||||
alert('Ошибка создания конфигурации');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -510,8 +537,22 @@ function clearMoveProjectInput() {
|
||||
document.getElementById('move-project-input').value = '';
|
||||
}
|
||||
|
||||
function clearCreateProjectInput() {
|
||||
document.getElementById('create-project-input').value = '';
|
||||
}
|
||||
|
||||
function openCreateProjectOnMoveModal(projectName) {
|
||||
document.getElementById('create-project-on-move-name').textContent = projectName;
|
||||
document.getElementById('create-project-on-move-description').textContent = 'Создать и привязать квоту?';
|
||||
document.getElementById('create-project-on-move-confirm-btn').textContent = 'Создать и привязать';
|
||||
document.getElementById('create-project-on-move-modal').classList.remove('hidden');
|
||||
document.getElementById('create-project-on-move-modal').classList.add('flex');
|
||||
}
|
||||
|
||||
function openCreateProjectOnCreateModal(projectName) {
|
||||
document.getElementById('create-project-on-move-name').textContent = projectName;
|
||||
document.getElementById('create-project-on-move-description').textContent = 'Создать и использовать для новой конфигурации?';
|
||||
document.getElementById('create-project-on-move-confirm-btn').textContent = 'Создать и использовать';
|
||||
document.getElementById('create-project-on-move-modal').classList.remove('hidden');
|
||||
document.getElementById('create-project-on-move-modal').classList.add('flex');
|
||||
}
|
||||
@@ -521,9 +562,43 @@ function closeCreateProjectOnMoveModal() {
|
||||
document.getElementById('create-project-on-move-modal').classList.remove('flex');
|
||||
pendingMoveConfigUUID = '';
|
||||
pendingMoveProjectName = '';
|
||||
pendingCreateConfigName = '';
|
||||
pendingCreateProjectName = '';
|
||||
}
|
||||
|
||||
async function confirmCreateProjectOnMove() {
|
||||
if (pendingCreateConfigName && pendingCreateProjectName) {
|
||||
const configName = pendingCreateConfigName;
|
||||
const projectName = pendingCreateProjectName;
|
||||
try {
|
||||
const createResp = await fetch('/api/projects', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({ name: projectName })
|
||||
});
|
||||
if (!createResp.ok) {
|
||||
const err = await createResp.json();
|
||||
alert('Не удалось создать проект: ' + (err.error || 'ошибка'));
|
||||
return;
|
||||
}
|
||||
|
||||
const newProject = await createResp.json();
|
||||
pendingCreateConfigName = '';
|
||||
pendingCreateProjectName = '';
|
||||
await loadProjectsForConfigUI();
|
||||
const created = await createConfigWithProject(configName, newProject.uuid);
|
||||
if (created) {
|
||||
closeCreateProjectOnMoveModal();
|
||||
} else {
|
||||
closeCreateProjectOnMoveModal();
|
||||
document.getElementById('create-project-input').value = projectName;
|
||||
}
|
||||
} catch (e) {
|
||||
alert('Ошибка создания проекта');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const configUUID = pendingMoveConfigUUID;
|
||||
const projectName = pendingMoveProjectName;
|
||||
if (!configUUID || !projectName) {
|
||||
@@ -544,10 +619,15 @@ async function confirmCreateProjectOnMove() {
|
||||
}
|
||||
|
||||
const newProject = await createResp.json();
|
||||
pendingMoveConfigUUID = '';
|
||||
pendingMoveProjectName = '';
|
||||
await loadProjectsForConfigUI();
|
||||
document.getElementById('move-project-input').value = projectName;
|
||||
const moved = await moveConfigToProject(configUUID, newProject.uuid);
|
||||
if (moved) {
|
||||
closeCreateProjectOnMoveModal();
|
||||
closeMoveProjectModal();
|
||||
} else {
|
||||
closeCreateProjectOnMoveModal();
|
||||
}
|
||||
} catch (e) {
|
||||
alert('Ошибка создания проекта');
|
||||
@@ -760,16 +840,18 @@ async function loadProjectsForConfigUI() {
|
||||
const data = await resp.json();
|
||||
projectsCache = (data.projects || []);
|
||||
|
||||
const select = document.getElementById('create-project-select');
|
||||
if (select) {
|
||||
select.innerHTML = '<option value="">Без проекта</option>';
|
||||
projectsCache.forEach(project => {
|
||||
projectNameByUUID[project.uuid] = project.name;
|
||||
});
|
||||
|
||||
const createOptions = document.getElementById('create-project-options');
|
||||
if (createOptions) {
|
||||
createOptions.innerHTML = '';
|
||||
projectsCache.forEach(project => {
|
||||
projectNameByUUID[project.uuid] = project.name;
|
||||
if (!project.is_active) return;
|
||||
const option = document.createElement('option');
|
||||
option.value = project.uuid;
|
||||
option.textContent = project.name;
|
||||
select.appendChild(option);
|
||||
option.value = project.name;
|
||||
createOptions.appendChild(option);
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user