Dokumentit: asiakaskohtaiset kansiot
- Dokumentit-tab näyttää ensin asiakaskansioruudukon (jokainen asiakas = oma kansio) - Klikkaamalla asiakaskansiota → avaa asiakkaan dokumenttilista - Takaisin-nappi palaa kansionäkymään - Asiakas-sarake poistettu dokumenttitaulusta (tarpeeton kansiossa) - Asiakas-dropdown piilotettu dokumentin luonnissa (valitaan automaattisesti) - Hakukenttä asiakkaiden suodatukseen kansionäkymässä - Kansiot järjestetty: ensin eniten dokumentteja, sitten aakkosittain - URL hash tuki: #documents/customerId Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
167
script.js
167
script.js
@@ -307,7 +307,18 @@ function switchToTab(target, subTab) {
|
||||
switchSupportSubTab('support-tickets');
|
||||
}
|
||||
}
|
||||
if (target === 'documents') { loadDocuments(); showDocsListView(); if (subTab === 'kokoukset') switchDocSubTab('docs-kokoukset'); else switchDocSubTab('docs-all'); }
|
||||
if (target === 'documents') {
|
||||
if (subTab && subTab !== 'kokoukset') {
|
||||
// subTab on customer_id → avaa suoraan asiakkaan kansio
|
||||
currentDocCustomerId = subTab;
|
||||
loadDocuments();
|
||||
openDocCustomerFolder(subTab);
|
||||
} else {
|
||||
currentDocCustomerId = null;
|
||||
loadDocuments();
|
||||
showDocCustomerFoldersView();
|
||||
}
|
||||
}
|
||||
if (target === 'netadmin') loadNetadmin();
|
||||
if (target === 'users') loadUsers();
|
||||
if (target === 'settings') loadSettings();
|
||||
@@ -4833,19 +4844,31 @@ const docCategoryLabels = {
|
||||
muu: 'Muu'
|
||||
};
|
||||
|
||||
let currentDocCustomerId = null; // Valittu asiakaskansio
|
||||
|
||||
function showDocCustomerFoldersView() {
|
||||
document.getElementById('docs-customer-folders-view').style.display = '';
|
||||
document.getElementById('docs-list-view').style.display = 'none';
|
||||
document.getElementById('doc-read-view').style.display = 'none';
|
||||
document.getElementById('doc-edit-view').style.display = 'none';
|
||||
}
|
||||
|
||||
function showDocsListView() {
|
||||
document.getElementById('docs-customer-folders-view').style.display = 'none';
|
||||
document.getElementById('docs-list-view').style.display = '';
|
||||
document.getElementById('doc-read-view').style.display = 'none';
|
||||
document.getElementById('doc-edit-view').style.display = 'none';
|
||||
}
|
||||
|
||||
function showDocReadView() {
|
||||
document.getElementById('docs-customer-folders-view').style.display = 'none';
|
||||
document.getElementById('docs-list-view').style.display = 'none';
|
||||
document.getElementById('doc-read-view').style.display = '';
|
||||
document.getElementById('doc-edit-view').style.display = 'none';
|
||||
}
|
||||
|
||||
function showDocEditView() {
|
||||
document.getElementById('docs-customer-folders-view').style.display = 'none';
|
||||
document.getElementById('docs-list-view').style.display = 'none';
|
||||
document.getElementById('doc-read-view').style.display = 'none';
|
||||
document.getElementById('doc-edit-view').style.display = '';
|
||||
@@ -4855,36 +4878,115 @@ async function loadDocuments() {
|
||||
try {
|
||||
allDocuments = await apiCall('documents');
|
||||
try { allDocFolders = await apiCall('document_folders'); } catch (e2) { allDocFolders = []; }
|
||||
populateDocCustomerFilter();
|
||||
renderDocFolderBar();
|
||||
renderDocumentsList();
|
||||
if (currentDocCustomerId) {
|
||||
// Ollaan asiakkaan kansion sisällä → näytä dokumenttilista
|
||||
renderDocFolderBar();
|
||||
renderDocumentsList();
|
||||
} else {
|
||||
// Näytä asiakaskansiot
|
||||
renderDocCustomerFolders();
|
||||
}
|
||||
} catch (e) { console.error('Dokumenttien lataus epäonnistui:', e); }
|
||||
}
|
||||
|
||||
function populateDocCustomerFilter() {
|
||||
const sel = document.getElementById('doc-filter-customer');
|
||||
const existing = sel.value;
|
||||
// Kerää uniikki lista asiakkaista
|
||||
const customerMap = {};
|
||||
function renderDocCustomerFolders() {
|
||||
const grid = document.getElementById('doc-customer-folders-grid');
|
||||
const noFolders = document.getElementById('no-doc-folders');
|
||||
const search = (document.getElementById('doc-folder-search')?.value || '').toLowerCase().trim();
|
||||
|
||||
// Hae asiakasnimien map
|
||||
const customerNameMap = {};
|
||||
if (typeof customers !== 'undefined') {
|
||||
customers.forEach(c => { customerNameMap[c.id] = c.yritys; });
|
||||
}
|
||||
|
||||
// Laske dokumenttien määrä per asiakas
|
||||
const docCountMap = {};
|
||||
allDocuments.forEach(d => {
|
||||
if (d.customer_id) {
|
||||
customerMap[d.customer_id] = d.customer_id; // käytetään myöhemmin nimeä jos saatavilla
|
||||
docCountMap[d.customer_id] = (docCountMap[d.customer_id] || 0) + 1;
|
||||
}
|
||||
});
|
||||
// Käytä customers-listaa nimien näyttämiseen
|
||||
sel.innerHTML = '<option value="">Kaikki asiakkaat</option>';
|
||||
if (typeof customers !== 'undefined' && customers.length > 0) {
|
||||
|
||||
// Näytä kaikki asiakkaat joilla on dokumentteja TAI kaikki aktiiviset asiakkaat
|
||||
let folderList = [];
|
||||
if (typeof customers !== 'undefined') {
|
||||
customers.forEach(c => {
|
||||
sel.innerHTML += `<option value="${c.id}">${esc(c.yritys)}</option>`;
|
||||
});
|
||||
} else {
|
||||
Object.keys(customerMap).forEach(id => {
|
||||
sel.innerHTML += `<option value="${id}">${id}</option>`;
|
||||
const count = docCountMap[c.id] || 0;
|
||||
folderList.push({ id: c.id, name: c.yritys || c.id, count });
|
||||
});
|
||||
}
|
||||
sel.value = existing || '';
|
||||
// Lisää asiakkaat jotka ovat dokumenteissa mutta eivät customers-listassa
|
||||
Object.keys(docCountMap).forEach(custId => {
|
||||
if (!folderList.find(f => f.id === custId)) {
|
||||
folderList.push({ id: custId, name: customerNameMap[custId] || custId, count: docCountMap[custId] });
|
||||
}
|
||||
});
|
||||
|
||||
// Suodata hakusanalla
|
||||
if (search) {
|
||||
folderList = folderList.filter(f => f.name.toLowerCase().includes(search));
|
||||
}
|
||||
|
||||
// Järjestä: ensin ne joilla on dokumentteja (count desc), sitten aakkosjärjestys
|
||||
folderList.sort((a, b) => {
|
||||
if (b.count !== a.count) return b.count - a.count;
|
||||
return a.name.localeCompare(b.name, 'fi');
|
||||
});
|
||||
|
||||
if (folderList.length === 0) {
|
||||
grid.innerHTML = '';
|
||||
noFolders.style.display = '';
|
||||
return;
|
||||
}
|
||||
noFolders.style.display = 'none';
|
||||
|
||||
grid.innerHTML = folderList.map(f => `
|
||||
<div class="doc-customer-folder${f.count === 0 ? ' empty' : ''}" onclick="openDocCustomerFolder('${f.id}')">
|
||||
<div class="doc-customer-folder-icon">🏢</div>
|
||||
<div class="doc-customer-folder-name">${esc(f.name)}</div>
|
||||
<div class="doc-customer-folder-count">${f.count} ${f.count === 1 ? 'dokumentti' : 'dokumenttia'}</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
function openDocCustomerFolder(customerId) {
|
||||
currentDocCustomerId = customerId;
|
||||
currentDocFolderId = null;
|
||||
docSubTabMode = 'docs-all';
|
||||
|
||||
// Aseta otsikko
|
||||
const customerNameMap = {};
|
||||
if (typeof customers !== 'undefined') {
|
||||
customers.forEach(c => { customerNameMap[c.id] = c.yritys; });
|
||||
}
|
||||
const name = customerNameMap[customerId] || customerId;
|
||||
document.getElementById('docs-list-title').textContent = '📄 ' + name;
|
||||
|
||||
// Reset sub-tab
|
||||
document.querySelectorAll('#doc-sub-tab-bar .sub-tab').forEach(t => t.classList.remove('active'));
|
||||
const allBtn = document.querySelector('[data-doc-subtab="docs-all"]');
|
||||
if (allBtn) allBtn.classList.add('active');
|
||||
document.getElementById('btn-new-document').style.display = '';
|
||||
document.getElementById('btn-new-meeting-note').style.display = 'none';
|
||||
|
||||
showDocsListView();
|
||||
renderDocFolderBar();
|
||||
renderDocumentsList();
|
||||
window.location.hash = 'documents/' + customerId;
|
||||
}
|
||||
|
||||
function backToDocCustomerFolders() {
|
||||
currentDocCustomerId = null;
|
||||
currentDocFolderId = null;
|
||||
showDocCustomerFoldersView();
|
||||
renderDocCustomerFolders();
|
||||
window.location.hash = 'documents';
|
||||
}
|
||||
|
||||
document.getElementById('btn-docs-back-to-folders')?.addEventListener('click', backToDocCustomerFolders);
|
||||
document.getElementById('doc-folder-search')?.addEventListener('input', renderDocCustomerFolders);
|
||||
|
||||
// ---- Kansionavigointi ----
|
||||
|
||||
function renderDocFolderBar() {
|
||||
@@ -4974,11 +5076,15 @@ document.querySelectorAll('#doc-sub-tab-bar .sub-tab').forEach(btn => {
|
||||
|
||||
function renderDocumentsList() {
|
||||
const query = (document.getElementById('doc-search')?.value || '').toLowerCase().trim();
|
||||
const filterCustomer = document.getElementById('doc-filter-customer')?.value || '';
|
||||
const filterCategory = document.getElementById('doc-filter-category')?.value || '';
|
||||
|
||||
let filtered = allDocuments;
|
||||
|
||||
// Suodata valitun asiakkaan perusteella
|
||||
if (currentDocCustomerId) {
|
||||
filtered = filtered.filter(d => d.customer_id === currentDocCustomerId);
|
||||
}
|
||||
|
||||
// Sub-tab suodatus: kokoukset = vain kokousmuistiot
|
||||
if (docSubTabMode === 'docs-kokoukset') {
|
||||
filtered = filtered.filter(d => d.category === 'kokousmuistio');
|
||||
@@ -5000,9 +5106,6 @@ function renderDocumentsList() {
|
||||
(d.description || '').toLowerCase().includes(query)
|
||||
);
|
||||
}
|
||||
if (filterCustomer) {
|
||||
filtered = filtered.filter(d => d.customer_id === filterCustomer);
|
||||
}
|
||||
if (filterCategory && docSubTabMode !== 'docs-kokoukset') {
|
||||
filtered = filtered.filter(d => d.category === filterCategory);
|
||||
}
|
||||
@@ -5017,21 +5120,13 @@ function renderDocumentsList() {
|
||||
}
|
||||
noDocsEl.style.display = 'none';
|
||||
|
||||
// Hae asiakasnimien map
|
||||
const customerNameMap = {};
|
||||
if (typeof customers !== 'undefined') {
|
||||
customers.forEach(c => { customerNameMap[c.id] = c.yritys; });
|
||||
}
|
||||
|
||||
tbody.innerHTML = filtered.map(d => {
|
||||
const customerName = d.customer_id ? (customerNameMap[d.customer_id] || d.customer_id) : '<span style="color:#aaa;">Yleinen</span>';
|
||||
const catLabel = docCategoryLabels[d.category] || d.category || '-';
|
||||
const version = d.current_version || 0;
|
||||
const date = d.muokattu ? new Date(d.muokattu).toLocaleDateString('fi-FI') : '-';
|
||||
const author = d.version_author || d.created_by || '-';
|
||||
return `<tr onclick="openDocRead('${d.id}')" style="cursor:pointer;">
|
||||
<td><strong>${esc(d.title)}</strong></td>
|
||||
<td>${customerName}</td>
|
||||
<td><span class="doc-category cat-${d.category || 'muu'}">${catLabel}</span></td>
|
||||
<td style="text-align:center;">v${version}</td>
|
||||
<td>${date}</td>
|
||||
@@ -5041,7 +5136,6 @@ function renderDocumentsList() {
|
||||
}
|
||||
|
||||
document.getElementById('doc-search')?.addEventListener('input', renderDocumentsList);
|
||||
document.getElementById('doc-filter-customer')?.addEventListener('change', renderDocumentsList);
|
||||
document.getElementById('doc-filter-category')?.addEventListener('change', renderDocumentsList);
|
||||
|
||||
async function openDocRead(docId) {
|
||||
@@ -5267,7 +5361,7 @@ function openDocEdit(doc, forceCategory, forceCustomerId) {
|
||||
? (isMeeting ? 'Muokkaa kokousmuistiota' : 'Muokkaa dokumenttia')
|
||||
: (isMeeting ? 'Uusi kokousmuistio' : 'Uusi dokumentti');
|
||||
|
||||
// Täytä asiakas-dropdown
|
||||
// Aseta asiakas automaattisesti nykyisen kansion perusteella
|
||||
const custSel = document.getElementById('doc-edit-customer');
|
||||
custSel.innerHTML = '<option value="">Ei asiakasta (yleinen)</option>';
|
||||
if (typeof customers !== 'undefined') {
|
||||
@@ -5275,8 +5369,13 @@ function openDocEdit(doc, forceCategory, forceCustomerId) {
|
||||
custSel.innerHTML += `<option value="${c.id}" ${(forceCustomerId === c.id || doc?.customer_id === c.id) ? 'selected' : ''}>${esc(c.yritys)}</option>`;
|
||||
});
|
||||
}
|
||||
if (forceCustomerId) custSel.value = forceCustomerId;
|
||||
// Aseta customer_id: kansionäkymästä tai parametrista
|
||||
const effectiveCustomerId = forceCustomerId || currentDocCustomerId;
|
||||
if (effectiveCustomerId) custSel.value = effectiveCustomerId;
|
||||
else if (doc?.customer_id) custSel.value = doc.customer_id;
|
||||
// Piilota asiakas-dropdown kun ollaan asiakkaan kansiossa (automaattinen valinta)
|
||||
const custGroup = custSel.closest('.form-group');
|
||||
if (custGroup) custGroup.style.display = currentDocCustomerId ? 'none' : '';
|
||||
|
||||
// Toggle kokousmuistio vs tiedostokenttä
|
||||
toggleDocMeetingFields(cat);
|
||||
|
||||
Reference in New Issue
Block a user