projects: add tracker_url and project create modal

This commit is contained in:
Mikhail Chusavitin
2026-02-06 16:42:32 +03:00
parent 8a8ea10dc2
commit 2f0ac2f6d2
11 changed files with 233 additions and 23 deletions

View File

@@ -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;
}

View File

@@ -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}}