Replace the merged-cell positional table (one column per tracking-number segment,
hierarchy via shared ancestors, built by creating folders) with a plain editable
spreadsheet: one row per file, with the tracking number, the rev (status), and
the title as three separate editable columns. Columns are hideable + resizable.
The storage model is unchanged — a file's tracking identity is still its
placement in the tracking-folder tree. The grid is a flat presentation + inline-
edit layer over it; editing a cell re-materializes the placement via the existing
path (addTrackingPath → place(…,'tracking') → setTitleOverride), generalized to
per-field.
- classify.js: `trackingWorkset` (serialized) so a dropped file is a row before
it has a number; `addToTrackingGrid`/`removeFromTrackingGrid`/`trackingGridKeys`
(union with files that have a tracking placement — incl. ones named via "From a
list"); `setFileIdentity(key, {tracking, rev, title})` re-files + prunes the old
leaf; blank tracking = an unfilled row, blank rev = a PENDING_REV leaf.
- target-tree.js: `renderTrackingGrid` (Status badge · Original name preview ·
Tracking number · Rev (status) · Title · ✕); drag onto the grid adds rows and
auto-fills any file whose own name already parses as ZDDC; a "Columns ▾" chooser
+ drag-resize (resize.js, now parameterized) persisted to localStorage. The
status badge validates the NAME only (the transmittal is a different tab).
Removed the merged-cell machinery + per-node CRUD (+ Root folder, ✎/🗑, brace
expansion) and the now-dead drop-on-node path.
- template/css: tracking toolbar → Columns chooser + hint; flat-grid + chooser CSS.
Tests: replaced the merged-cell/+Root-folder/drop-on-leaf/filename-edit tests with
grid tests (render, drop+auto-fill, per-cell re-file, filter, hide/persist,
preview link). Suite 342 green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
79 lines
2.4 KiB
JavaScript
79 lines
2.4 KiB
JavaScript
/**
|
|
* Column Resize Module
|
|
* Handles resizable table columns
|
|
*/
|
|
(function() {
|
|
'use strict';
|
|
|
|
let resizingColumn = null;
|
|
let startX = 0;
|
|
let startWidth = 0;
|
|
let activeTable = null;
|
|
let activeOnResize = null;
|
|
|
|
/**
|
|
* Initialize column resizing on a table. Defaults to the rename-in-place
|
|
* spreadsheet when no table is passed (back-compatible). onResize(table) is
|
|
* called after each drag ends, so a caller can persist the new widths.
|
|
*/
|
|
function init(table, onResize) {
|
|
table = table || (window.app.dom && window.app.dom.spreadsheet);
|
|
if (!table) return;
|
|
const headers = table.querySelectorAll('thead th');
|
|
|
|
headers.forEach(th => {
|
|
// Skip if resize handle already exists
|
|
if (th.querySelector('.column-resizer')) return;
|
|
|
|
// Add resize handle
|
|
const resizer = document.createElement('div');
|
|
resizer.className = 'column-resizer';
|
|
th.appendChild(resizer);
|
|
|
|
// Mouse down on resizer
|
|
resizer.addEventListener('mousedown', (e) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
resizingColumn = th;
|
|
startX = e.pageX;
|
|
startWidth = th.offsetWidth;
|
|
activeTable = table;
|
|
activeOnResize = onResize || null;
|
|
|
|
document.addEventListener('mousemove', handleMouseMove);
|
|
document.addEventListener('mouseup', handleMouseUp);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Handle mouse move during resize
|
|
*/
|
|
function handleMouseMove(e) {
|
|
if (!resizingColumn) return;
|
|
|
|
const diff = e.pageX - startX;
|
|
const newWidth = Math.max(50, startWidth + diff);
|
|
|
|
resizingColumn.style.width = newWidth + 'px';
|
|
resizingColumn.style.minWidth = newWidth + 'px';
|
|
resizingColumn.style.maxWidth = newWidth + 'px';
|
|
}
|
|
|
|
/**
|
|
* Handle mouse up - end resize
|
|
*/
|
|
function handleMouseUp() {
|
|
resizingColumn = null;
|
|
document.removeEventListener('mousemove', handleMouseMove);
|
|
document.removeEventListener('mouseup', handleMouseUp);
|
|
if (activeOnResize && activeTable) { try { activeOnResize(activeTable); } catch (_) { /* ignore */ } }
|
|
activeTable = null; activeOnResize = null;
|
|
}
|
|
|
|
// Export module
|
|
window.app.modules.resize = {
|
|
init
|
|
};
|
|
})();
|