projects: add tracker_url and project create modal
This commit is contained in:
@@ -125,6 +125,12 @@ function escapeHtml(text) {
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
function resolveProjectTrackerURL(projectData) {
|
||||
if (!projectData) return '';
|
||||
const explicitURL = (projectData.tracker_url || '').trim();
|
||||
return explicitURL;
|
||||
}
|
||||
|
||||
function setConfigStatusMode(mode) {
|
||||
if (mode !== 'active' && mode !== 'archived') return;
|
||||
configStatusMode = mode;
|
||||
@@ -224,8 +230,18 @@ async function loadProject() {
|
||||
project = await resp.json();
|
||||
document.getElementById('project-title').textContent = project.name;
|
||||
const trackerLink = document.getElementById('tracker-link');
|
||||
if (trackerLink && project && project.name) {
|
||||
trackerLink.href = 'https://tracker.yandex.ru/' + encodeURIComponent(project.name);
|
||||
if (trackerLink) {
|
||||
if (project && project.is_system) {
|
||||
trackerLink.classList.add('hidden');
|
||||
return true;
|
||||
}
|
||||
const trackerURL = resolveProjectTrackerURL(project);
|
||||
if (trackerURL) {
|
||||
trackerLink.href = trackerURL;
|
||||
trackerLink.classList.remove('hidden');
|
||||
} else {
|
||||
trackerLink.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<a href="/configs" class="px-4 py-2 bg-gray-200 text-gray-800 rounded hover:bg-gray-300">
|
||||
Все конфигурации
|
||||
</a>
|
||||
<button onclick="createProject()" class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">
|
||||
<button onclick="openCreateProjectModal()" class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">
|
||||
+ Новый проект
|
||||
</button>
|
||||
</div>
|
||||
@@ -27,6 +27,28 @@
|
||||
<div id="projects-table" class="bg-white rounded-lg shadow p-4 text-gray-500">Загрузка...</div>
|
||||
</div>
|
||||
|
||||
<div id="create-project-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-4">Новый проект</h2>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label for="create-project-code" class="block text-sm font-medium text-gray-700 mb-1">Код проекта</label>
|
||||
<input id="create-project-code" type="text" placeholder="Например: OPS-123"
|
||||
class="w-full px-3 py-2 border rounded focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
||||
</div>
|
||||
<div>
|
||||
<label for="create-project-tracker-url" class="block text-sm font-medium text-gray-700 mb-1">Ссылка на трекер</label>
|
||||
<input id="create-project-tracker-url" type="url" placeholder="https://tracker.yandex.ru/OPS-123"
|
||||
class="w-full px-3 py-2 border rounded focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end gap-2 mt-6">
|
||||
<button type="button" onclick="closeCreateProjectModal()" class="px-4 py-2 text-gray-600 hover:text-gray-800">Отмена</button>
|
||||
<button type="button" onclick="createProject()" class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">Создать</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let status = 'active';
|
||||
let projectsSearch = '';
|
||||
@@ -35,6 +57,10 @@ let currentPage = 1;
|
||||
let perPage = 10;
|
||||
let sortField = 'created_at';
|
||||
let sortDir = 'desc';
|
||||
let createProjectTrackerManuallyEdited = false;
|
||||
let createProjectLastAutoTrackerURL = '';
|
||||
|
||||
const trackerBaseURL = 'https://tracker.yandex.ru/';
|
||||
|
||||
function escapeHtml(text) {
|
||||
const div = document.createElement('div');
|
||||
@@ -218,18 +244,60 @@ function goToPage(page) {
|
||||
loadProjects();
|
||||
}
|
||||
|
||||
function buildTrackerURLFromProjectCode(projectCode) {
|
||||
const code = (projectCode || '').trim();
|
||||
if (!code) return '';
|
||||
return trackerBaseURL + encodeURIComponent(code);
|
||||
}
|
||||
|
||||
function openCreateProjectModal() {
|
||||
const codeInput = document.getElementById('create-project-code');
|
||||
const trackerInput = document.getElementById('create-project-tracker-url');
|
||||
codeInput.value = '';
|
||||
trackerInput.value = '';
|
||||
createProjectTrackerManuallyEdited = false;
|
||||
createProjectLastAutoTrackerURL = '';
|
||||
document.getElementById('create-project-modal').classList.remove('hidden');
|
||||
document.getElementById('create-project-modal').classList.add('flex');
|
||||
codeInput.focus();
|
||||
}
|
||||
|
||||
function closeCreateProjectModal() {
|
||||
document.getElementById('create-project-modal').classList.add('hidden');
|
||||
document.getElementById('create-project-modal').classList.remove('flex');
|
||||
}
|
||||
|
||||
function updateCreateProjectTrackerURL() {
|
||||
const codeInput = document.getElementById('create-project-code');
|
||||
const trackerInput = document.getElementById('create-project-tracker-url');
|
||||
const generatedURL = buildTrackerURLFromProjectCode(codeInput.value);
|
||||
if (!createProjectTrackerManuallyEdited || trackerInput.value.trim() === '' || trackerInput.value === createProjectLastAutoTrackerURL) {
|
||||
trackerInput.value = generatedURL;
|
||||
createProjectLastAutoTrackerURL = generatedURL;
|
||||
}
|
||||
}
|
||||
|
||||
async function createProject() {
|
||||
const name = prompt('Название проекта');
|
||||
if (!name || !name.trim()) return;
|
||||
const codeInput = document.getElementById('create-project-code');
|
||||
const trackerInput = document.getElementById('create-project-tracker-url');
|
||||
const name = (codeInput.value || '').trim();
|
||||
if (!name) {
|
||||
alert('Введите код проекта');
|
||||
return;
|
||||
}
|
||||
const resp = await fetch('/api/projects', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({name: name.trim()})
|
||||
body: JSON.stringify({
|
||||
name: name,
|
||||
tracker_url: (trackerInput.value || '').trim()
|
||||
})
|
||||
});
|
||||
if (!resp.ok) {
|
||||
alert('Не удалось создать проект');
|
||||
return;
|
||||
}
|
||||
closeCreateProjectModal();
|
||||
loadProjects();
|
||||
}
|
||||
|
||||
@@ -324,6 +392,34 @@ document.getElementById('projects-search').addEventListener('input', function(e)
|
||||
currentPage = 1;
|
||||
loadProjects();
|
||||
});
|
||||
|
||||
document.getElementById('create-project-code').addEventListener('input', function() {
|
||||
updateCreateProjectTrackerURL();
|
||||
});
|
||||
|
||||
document.getElementById('create-project-tracker-url').addEventListener('input', function(e) {
|
||||
createProjectTrackerManuallyEdited = (e.target.value || '').trim() !== createProjectLastAutoTrackerURL;
|
||||
});
|
||||
|
||||
document.getElementById('create-project-code').addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
createProject();
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('create-project-tracker-url').addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
createProject();
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('create-project-modal').addEventListener('click', function(e) {
|
||||
if (e.target === this) {
|
||||
closeCreateProjectModal();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{{end}}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user