The /incoming/ path regex in browse/js/grid.js was the second-most
visible client-side hardcode of the canonical convention. Migrating
it to the cascade:
Header surface:
X-ZDDC-Default-Tool: <name> The cascade-resolved default tool
for the listing's directory. Empty
header = no default declared.
Client wiring:
loader.fetchServerChildren reads the header into
state.scopeDefaultTool on every listing fetch (initial mount,
rescope on dblclick, popstate). grid.classifierAvailableHere
now returns scopeDefaultTool === 'classifier' instead of
regex-matching the URL.
Effect:
Grid mode auto-activates wherever the cascade picks classifier
as the default — currently archive/<party>/incoming per
defaults.zddc.yaml. An operator who sets default_tool: classifier
on a custom directory gets grid mode there too, no code change.
An operator who removes the default at incoming sees grid mode
stop auto-activating there.
Bootstrap timing fix:
The initial events.init() runs applyResolvedViewMode before the
detection fetch completes, so state.scopeDefaultTool is empty
at that point and grid never auto-activates on first paint.
app.js bootstrap now re-applies the resolved view mode after
autoDetectServerMode returns, so a fresh /incoming URL lands
on grid mode immediately.
The /incoming/ regex is gone. Two client hardcodes remaining
(archive source heuristics, shared/nav stage strip) — Phase 4c/d.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
69 lines
2.6 KiB
JavaScript
69 lines
2.6 KiB
JavaScript
// grid.js — "Grid mode" plugin for browse. Loads the classifier tool
|
|
// as an iframe scoped to the current directory so users get classifier's
|
|
// full bulk-rename workflow without leaving browse.
|
|
//
|
|
// Availability: the cascade decides. Grid auto-activates wherever the
|
|
// .zddc cascade resolves default_tool=classifier (defaults.zddc.yaml
|
|
// declares this for archive/<party>/incoming/). Operators can extend
|
|
// — e.g. setting default_tool=classifier on a custom dir activates
|
|
// grid mode there too — without touching this code.
|
|
//
|
|
// Iframe src resolution: <currentDirURL>/classifier.html. Iframe
|
|
// embedding only works in server mode; file:// pages don't get the
|
|
// Grid toggle.
|
|
(function () {
|
|
'use strict';
|
|
|
|
var state = window.app.state;
|
|
var mounted = false;
|
|
|
|
function classifierAvailableHere() {
|
|
// state.scopeDefaultTool is set by the loader from the
|
|
// X-ZDDC-Default-Tool response header on every listing fetch.
|
|
// Grid mode is meaningful exactly where the cascade picks
|
|
// classifier as the default — no client-side path matching.
|
|
return state.scopeDefaultTool === 'classifier';
|
|
}
|
|
|
|
function activate() {
|
|
var host = document.getElementById('gridView');
|
|
if (!host) return;
|
|
if (mounted) return;
|
|
if (state.source !== 'server' || !classifierAvailableHere()) return;
|
|
|
|
// Compute the iframe src: current page's directory + classifier.html.
|
|
var pathname = window.location.pathname || '/';
|
|
if (!pathname.endsWith('/')) {
|
|
var lastSlash = pathname.lastIndexOf('/');
|
|
pathname = lastSlash >= 0 ? pathname.substring(0, lastSlash + 1) : '/';
|
|
}
|
|
var src = pathname + 'classifier.html';
|
|
|
|
host.innerHTML = '';
|
|
var frame = document.createElement('iframe');
|
|
frame.src = src;
|
|
frame.title = 'ZDDC Classifier (Grid mode)';
|
|
frame.style.cssText = 'width:100%;height:100%;border:0;display:block;'
|
|
+ 'background:var(--bg);';
|
|
host.appendChild(frame);
|
|
mounted = true;
|
|
}
|
|
|
|
// When the user navigates between scopes (client-side rescope on
|
|
// dblclick), the iframe needs to be reloaded for the new path.
|
|
// Callers reset before re-activating.
|
|
function reset() {
|
|
mounted = false;
|
|
var host = document.getElementById('gridView');
|
|
if (host) host.innerHTML = '';
|
|
}
|
|
|
|
window.app.modules.grid = {
|
|
activate: activate,
|
|
reset: reset,
|
|
// Hook for events.js to show/hide the Grid toggle button.
|
|
availableHere: function () {
|
|
return state.source === 'server' && classifierAvailableHere();
|
|
}
|
|
};
|
|
})();
|