diff --git a/FabWorks.Api/wwwroot/js/pages.js b/FabWorks.Api/wwwroot/js/pages.js
index c89b136..5ad16c8 100644
--- a/FabWorks.Api/wwwroot/js/pages.js
+++ b/FabWorks.Api/wwwroot/js/pages.js
@@ -32,7 +32,7 @@ const pages = {
setPage('Exports', `${data.items.length} exports`);
const rows = data.items.map((e, i) => `
-
+
| ${e.id} |
${esc(e.drawingNumber) || '\u2014'} |
${esc(e.title) || ''} |
@@ -62,85 +62,6 @@ const pages = {
}
},
- async exportDetail(id) {
- const actions = document.getElementById('topbar-actions');
- const content = document.getElementById('page-content');
- setPage('Loading...');
- actions.innerHTML = '';
- content.innerHTML = `Loading export
`;
-
- try {
- const exp = await api.get(`/api/exports/${id}`);
- setPage(exp.drawingNumber || `Export #${exp.id}`, 'export detail');
-
- const dxfCount = (exp.bomItems || []).filter(b => b.cutTemplate?.contentHash).length;
-
- const bomRows = (exp.bomItems || []).map((b, i) => {
- const hasDetails = b.cutTemplate || b.formProgram;
- const toggleId = `bom-${b.id}`;
- return `
-
- | ${hasDetails ? `${icons.chevron}` : ''} |
- ${esc(b.itemNo)} |
- ${esc(b.partName)} |
- ${esc(b.description)} |
- ${esc(b.material)} |
- ${b.qty ?? ''} |
- ${b.totalQty ?? ''} |
-
- ${b.cutTemplate ? `${icons.laser} DXF` : ''}
- ${b.formProgram ? `${icons.bend} Form` : ''}
- |
-
- ${hasDetails ? `| ${renderBomDetails(b)} |
` : ''}`;
- }).join('');
-
- content.innerHTML = `
- ${icons.back} Back to exports
-
-
-
-
-
-
${esc(exp.drawingNumber) || '\u2014'}
- ${exp.title ? `
` : ''}
-
${esc(exp.exportedBy)}
-
${fmtDate(exp.exportedAt)}
-
${esc(exp.sourceFilePath)}
-
-
-
-
-
-
- ${exp.bomItems?.length ? `
-
-
- |
- Item |
- Part Name |
- Description |
- Material |
- Qty |
- Total |
- Data |
-
- ${bomRows}
-
` : '
No BOM items for this export.
'}
-
`;
- } catch (err) {
- content.innerHTML = `Error: ${esc(err.message)}
`;
- }
- },
-
async drawings(params) {
const actions = document.getElementById('topbar-actions');
const content = document.getElementById('page-content');
@@ -255,8 +176,9 @@ const pages = {
}
},
- async drawingDetail(drawingEncoded) {
+ async drawingDetail(drawingEncoded, params) {
const drawingNumber = decodeURIComponent(drawingEncoded);
+ const exportId = params?.eid ? parseInt(params.eid) : null;
const actions = document.getElementById('topbar-actions');
const content = document.getElementById('page-content');
setPage(drawingNumber, 'drawing');
@@ -273,12 +195,23 @@ const pages = {
return;
}
- const allBom = [];
- exports.forEach(exp => {
- (exp.bomItems || []).forEach(b => {
- allBom.push({ ...b, exportId: exp.id, exportedAt: exp.exportedAt });
+ let allBom;
+ const singleExport = exportId ? exports.find(e => e.id === exportId) : null;
+ if (singleExport) {
+ // Viewing a specific export - show only its BOM items
+ allBom = (singleExport.bomItems || []).map(b => ({ ...b, exportId: singleExport.id, exportedAt: singleExport.exportedAt }));
+ } else {
+ // Viewing drawing overview - deduplicate by itemNo, keeping latest revision (exports are newest-first)
+ const bomByItem = new Map();
+ exports.forEach(exp => {
+ (exp.bomItems || []).forEach(b => {
+ if (!bomByItem.has(b.itemNo)) {
+ bomByItem.set(b.itemNo, { ...b, exportId: exp.id, exportedAt: exp.exportedAt });
+ }
+ });
});
- });
+ allBom = [...bomByItem.values()];
+ }
const bomRows = allBom.map((b, i) => {
const hasDetails = b.cutTemplate || b.formProgram;
@@ -288,6 +221,7 @@ const pages = {
${hasDetails ? `${icons.chevron}` : ''} |
${esc(b.itemNo)} |
${esc(b.partName)} |
+ ${b.cutTemplate?.revision ?? ''} |
${esc(b.description)} |
${esc(b.material)} |
${b.qty ?? ''} |
@@ -297,22 +231,43 @@ const pages = {
${b.formProgram ? `${icons.bend} Form` : ''}
- ${hasDetails ? `| ${renderBomDetails(b)} |
` : ''}`;
+ ${hasDetails ? `| ${renderBomDetails(b)} |
` : ''}`;
}).join('');
- content.innerHTML = `
- ${icons.back} Back to drawings
+ const backLink = singleExport
+ ? `${icons.back} Back to exports`
+ : `${icons.back} Back to drawings`;
-
+ const statsHtml = singleExport
+ ? `
+
Exported By
${esc(singleExport.exportedBy)}
+
BOM Items
${allBom.length}
+
Exported
${fmtDate(singleExport.exportedAt)}
+
`
+ : `
BOM Items
${allBom.length}
Latest Export
${fmtDate(exports[0].exportedAt)}
-
+
`;
+
+ const bomHeader = singleExport ? 'BOM Items' : 'All BOM Items';
+ const activeExport = singleExport || exports[0];
+ const dxfCount = allBom.filter(b => b.cutTemplate?.contentHash).length;
+ const pdfHash = activeExport.pdfContentHash;
+ const pdfName = encodeURIComponent((drawingNumber || 'drawing') + '.pdf');
+
+ content.innerHTML = `
+ ${backLink}
+ ${statsHtml}
${allBom.length ? `
@@ -320,6 +275,7 @@ const pages = {
|
Item |
Part Name |
+ Rev |
Description |
Material |
Qty |
diff --git a/FabWorks.Api/wwwroot/js/router.js b/FabWorks.Api/wwwroot/js/router.js
index 66fdfc1..a767652 100644
--- a/FabWorks.Api/wwwroot/js/router.js
+++ b/FabWorks.Api/wwwroot/js/router.js
@@ -1,6 +1,9 @@
const router = {
go(page, params = {}) {
- const hash = page + (params.id ? '/' + params.id : '') + (params.q ? '?q=' + encodeURIComponent(params.q) : '');
+ const qParts = [];
+ if (params.q) qParts.push('q=' + encodeURIComponent(params.q));
+ if (params.eid) qParts.push('eid=' + encodeURIComponent(params.eid));
+ const hash = page + (params.id ? '/' + params.id : '') + (qParts.length ? '?' + qParts.join('&') : '');
location.hash = hash;
},
parse() {
@@ -20,12 +23,10 @@ const router = {
document.querySelectorAll('.nav-item').forEach(el => {
el.classList.toggle('active',
el.dataset.page === page ||
- (page === 'export-detail' && el.dataset.page === 'exports') ||
(page === 'drawing-detail' && el.dataset.page === 'drawings'));
});
switch(page) {
case 'exports': pages.exports(params); break;
- case 'export-detail': pages.exportDetail(id); break;
case 'drawings': pages.drawings(params); break;
case 'drawing-detail': pages.drawingDetail(id, params); break;
case 'files': pages.files(params); break;