refactor missing model filter bindings

This commit is contained in:
Dariusz L
2026-08-05 15:10:39 +02:00
parent b9cf600cc6
commit d964f5fad7
2 changed files with 124 additions and 30 deletions
@@ -2416,6 +2416,96 @@ test('workflow analysis and loaded model caches stay independent and cloned', ()
assert.equal(dialog.workflowAnalysisCaches.get(dialog.workflowKey).data.missing_models.length, 1);
});
test('Missing Models filter toggles persist state and rerender once per change', () => {
const bindMissingFilterToggle = eval(
`(${extractMethod(missingBrowserMethodsSource, 'bindMissingFilterToggle')})`
);
const wireMissingModelsBrowser = eval(
`(${extractMethod(missingBrowserMethodsSource, 'wireMissingModelsBrowser')})`
);
const window = new Window();
const previousDocument = globalThis.document;
const previousElement = globalThis.Element;
const previousHTMLElement = globalThis.HTMLElement;
const previousLocalStorage = globalThis.localStorage;
const localStorageValues = new Map();
const container = window.document.createElement('div');
container.innerHTML = `
<div class="mr-missing-browser">
<input id="mr-show-resolved-models" type="checkbox">
<input id="mr-show-auto-download-models" type="checkbox">
<input id="mr-show-inactive-models" type="checkbox">
</div>
`;
const renderOptions = [];
const dialog = {
showResolvedModels: false,
showAutoDownloadModels: true,
showInactiveModels: false,
showResolvedModelsStorageKey: 'test_show_resolved_models',
showAutoDownloadModelsStorageKey: 'test_show_auto_download_models',
showInactiveModelsStorageKey: 'test_show_inactive_models',
missingModelsTypeFilterMenuOpen: false,
bindMissingFilterToggle,
wireMissingBrowserSplitter() {},
wireVisibleMissingModelRows() {},
setupMissingModelsVirtualizer() {},
displayMissingModels(_container, _data, options) {
renderOptions.push(options);
},
};
globalThis.document = window.document;
globalThis.Element = window.Element;
globalThis.HTMLElement = window.HTMLElement;
globalThis.localStorage = {
getItem(key) {
return localStorageValues.has(key) ? localStorageValues.get(key) : null;
},
setItem(key, value) {
localStorageValues.set(key, String(value));
},
removeItem(key) {
localStorageValues.delete(key);
},
};
try {
wireMissingModelsBrowser.call(dialog, container, {}, []);
wireMissingModelsBrowser.call(dialog, container, {}, []);
const resolvedToggle = container.querySelector('#mr-show-resolved-models');
const autoDownloadToggle = container.querySelector('#mr-show-auto-download-models');
const inactiveToggle = container.querySelector('#mr-show-inactive-models');
resolvedToggle.checked = true;
autoDownloadToggle.checked = false;
inactiveToggle.checked = true;
resolvedToggle.dispatchEvent(new window.Event('change'));
autoDownloadToggle.dispatchEvent(new window.Event('change'));
inactiveToggle.dispatchEvent(new window.Event('change'));
assert.equal(dialog.showResolvedModels, true);
assert.equal(dialog.showAutoDownloadModels, false);
assert.equal(dialog.showInactiveModels, true);
assert.equal(safeStorage.getItem(dialog.showResolvedModelsStorageKey), '1');
assert.equal(safeStorage.getItem(dialog.showAutoDownloadModelsStorageKey), '0');
assert.equal(safeStorage.getItem(dialog.showInactiveModelsStorageKey), '1');
assert.deepEqual(renderOptions, [
{ preserveBrowser: true },
{ preserveBrowser: true },
{ preserveBrowser: true },
]);
} finally {
safeStorage.removeItem(dialog.showResolvedModelsStorageKey);
safeStorage.removeItem(dialog.showAutoDownloadModelsStorageKey);
safeStorage.removeItem(dialog.showInactiveModelsStorageKey);
globalThis.document = previousDocument;
globalThis.Element = previousElement;
globalThis.HTMLElement = previousHTMLElement;
globalThis.localStorage = previousLocalStorage;
}
});
test('node widget changes request a content-preserving Missing Models refresh', async () => {
const log = { debug() {} };
const refreshForActiveWorkflowChange = eval(
+34 -30
View File
@@ -1083,6 +1083,19 @@ export const missingBrowserMethods = {
});
},
bindMissingFilterToggle(toggle, { boundKey, storageKey, setValue, container, data }) {
if (!toggle || toggle.dataset[boundKey] === 'true') return;
toggle.dataset[boundKey] = 'true';
toggle.addEventListener('change', () => {
const value = Boolean(toggle.checked);
setValue(value);
try {
safeStorage.setItem(storageKey, value ? '1' : '0');
} catch (_e) {}
this.displayMissingModels(container, data, { preserveBrowser: true });
});
},
wireMissingModelsBrowser(container, data, sortedMissingModels) {
this.wireMissingBrowserSplitter(container);
@@ -1161,40 +1174,31 @@ export const missingBrowserMethods = {
}
const showResolvedToggle = container.querySelector('#mr-show-resolved-models');
if (showResolvedToggle && showResolvedToggle.dataset.mlResolvedBound !== 'true') {
showResolvedToggle.dataset.mlResolvedBound = 'true';
showResolvedToggle.addEventListener('change', () => {
this.showResolvedModels = Boolean(showResolvedToggle.checked);
try {
safeStorage.setItem(this.showResolvedModelsStorageKey, this.showResolvedModels ? '1' : '0');
} catch (_e) {}
this.displayMissingModels(container, data, { preserveBrowser: true });
});
}
this.bindMissingFilterToggle(showResolvedToggle, {
boundKey: 'mlResolvedBound',
storageKey: this.showResolvedModelsStorageKey,
setValue: value => { this.showResolvedModels = value; },
container,
data,
});
const showAutoDownloadToggle = container.querySelector('#mr-show-auto-download-models');
if (showAutoDownloadToggle && showAutoDownloadToggle.dataset.mlAutoDownloadBound !== 'true') {
showAutoDownloadToggle.dataset.mlAutoDownloadBound = 'true';
showAutoDownloadToggle.addEventListener('change', () => {
this.showAutoDownloadModels = Boolean(showAutoDownloadToggle.checked);
try {
safeStorage.setItem(this.showAutoDownloadModelsStorageKey, this.showAutoDownloadModels ? '1' : '0');
} catch (_e) {}
this.displayMissingModels(container, data, { preserveBrowser: true });
});
}
this.bindMissingFilterToggle(showAutoDownloadToggle, {
boundKey: 'mlAutoDownloadBound',
storageKey: this.showAutoDownloadModelsStorageKey,
setValue: value => { this.showAutoDownloadModels = value; },
container,
data,
});
const showInactiveToggle = container.querySelector('#mr-show-inactive-models');
if (showInactiveToggle && showInactiveToggle.dataset.mlInactiveBound !== 'true') {
showInactiveToggle.dataset.mlInactiveBound = 'true';
showInactiveToggle.addEventListener('change', () => {
this.showInactiveModels = Boolean(showInactiveToggle.checked);
try {
safeStorage.setItem(this.showInactiveModelsStorageKey, this.showInactiveModels ? '1' : '0');
} catch (_e) {}
this.displayMissingModels(container, data, { preserveBrowser: true });
});
}
this.bindMissingFilterToggle(showInactiveToggle, {
boundKey: 'mlInactiveBound',
storageKey: this.showInactiveModelsStorageKey,
setValue: value => { this.showInactiveModels = value; },
container,
data,
});
const getCurrentMissingModels = () => (
Array.isArray(this.missingModels)