Show article history in a table via GET /article/{sku}/history.
This commit is contained in:
@@ -4,16 +4,25 @@ import { ApiClient } from './ApiClient';
|
||||
/**
|
||||
* Stale-while-revalidate cache: readers keep the current promise; update()
|
||||
* swaps only after a successful reload. Failed updates leave the cache intact.
|
||||
* replace() writes local data without a round-trip.
|
||||
*/
|
||||
function createCache(label, load) {
|
||||
let promise = load().catch((err) => {
|
||||
console.error(`[storageMgr] ${label} failed`, err);
|
||||
throw err;
|
||||
});
|
||||
/** Settled value, or `undefined` if not loaded yet / last load failed. */
|
||||
let current;
|
||||
let promise = load()
|
||||
.then((data) => {
|
||||
current = data;
|
||||
return data;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(`[storageMgr] ${label} failed`, err);
|
||||
throw err;
|
||||
});
|
||||
|
||||
async function update() {
|
||||
try {
|
||||
const data = await load();
|
||||
current = data;
|
||||
promise = Promise.resolve(data);
|
||||
return data;
|
||||
} catch (err) {
|
||||
@@ -22,11 +31,36 @@ function createCache(label, load) {
|
||||
}
|
||||
}
|
||||
|
||||
function replace(data) {
|
||||
current = data;
|
||||
promise = Promise.resolve(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
function clear() {
|
||||
current = undefined;
|
||||
promise = load()
|
||||
.then((data) => {
|
||||
current = data;
|
||||
return data;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(`[storageMgr] ${label} failed`, err);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
update,
|
||||
replace,
|
||||
clear,
|
||||
get promise() {
|
||||
return promise;
|
||||
},
|
||||
/** Loaded value, or `undefined` if the initial load has not settled successfully. */
|
||||
get value() {
|
||||
return current;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -36,15 +70,33 @@ function createCache(label, load) {
|
||||
export class StorageManager extends ApiClient {
|
||||
/** @type {EventSource | null} */
|
||||
#events = null;
|
||||
/** @type {ReturnType<typeof createCache> | null} */
|
||||
#articleIndexCache = null;
|
||||
|
||||
constructor(baseUrl = window.location.origin) {
|
||||
super(baseUrl);
|
||||
this.#initCaches();
|
||||
}
|
||||
|
||||
/** Patch local articleIndex name if already loaded; no-op otherwise. */
|
||||
setArticleIndexName(sku, name) {
|
||||
const articles = this.#articleIndexCache.value;
|
||||
if (!articles) return;
|
||||
this.#articleIndexCache.replace(
|
||||
articles.map((a) => (String(a.sku) === String(sku) ? { ...a, name } : a)),
|
||||
);
|
||||
}
|
||||
|
||||
/** Drop local articleIndex if loaded (forces reload on next read). */
|
||||
clearArticleIndex() {
|
||||
if (!this.#articleIndexCache.value) return;
|
||||
this.#articleIndexCache.clear();
|
||||
}
|
||||
|
||||
#initCaches() {
|
||||
const authMeCache = createCache('GET /auth/me', () => this.#loadAuthMe());
|
||||
const articleIndexCache = createCache('GET /articleIndex', () => this.#loadArticleIndex());
|
||||
this.#articleIndexCache = createCache('GET /articleIndex', () => this.#loadArticleIndex());
|
||||
const articleIndexCache = this.#articleIndexCache;
|
||||
const brandCache = createCache('GET /brand', () => this.#loadBrands());
|
||||
const unitCache = createCache('GET /unit', () => this.#loadUnits());
|
||||
const companyCache = createCache('GET /company', () => this.#loadCompanies());
|
||||
@@ -87,12 +139,12 @@ export class StorageManager extends ApiClient {
|
||||
const es = new EventSource(this.urlFor('/api/events'), { withCredentials: true });
|
||||
es.addEventListener('category', () => {
|
||||
void this.updateCategoryTree().catch((err) => {
|
||||
console.error('[storageMgr] category event refresh failed', err);
|
||||
console.error('[storageMgr] category SSE refresh failed', err);
|
||||
});
|
||||
});
|
||||
es.addEventListener('articles', () => {
|
||||
void this.updateArticleIndex().catch((err) => {
|
||||
console.error('[storageMgr] articles event refresh failed', err);
|
||||
console.error('[storageMgr] articles SSE refresh failed', err);
|
||||
});
|
||||
});
|
||||
es.onerror = () => {
|
||||
|
||||
Reference in New Issue
Block a user