@@ -348,51 +348,78 @@ function postPluginGraphQL(gqlField, prefix, foreignKey, dtRequest, callback) {
348348 });
349349}
350350
351- // Fire a single batched GraphQL request to fetch the Objects dbCount for
352- // every plugin and populate the sidebar badges immediately on page load.
353- function prefetchPluginBadges() {
354- const apiToken = getSetting("API_TOKEN");
355- const apiBase = getApiBase();
351+ // Fetch badge counts for every plugin and populate sidebar + sub-tab counters.
352+ // Fast path: static JSON (~1KB) when no MAC filter is active.
353+ // Filtered path: batched GraphQL aliases when a foreignKey (MAC) is set.
354+ async function prefetchPluginBadges() {
356355 const mac = $("#txtMacFilter").val();
357356 const foreignKey = (mac && mac !== "--") ? mac : null;
358357
359- // Build one aliased sub-query per visible plugin
360358 const prefixes = pluginDefinitions
361359 .filter(p => p.show_ui)
362360 .map(p => p.unique_prefix);
363361
364362 if (prefixes.length === 0) return;
365363
366- // GraphQL aliases must be valid identifiers — prefixes already are (A-Z0-9_)
367- const fkOpt = foreignKey ? `, foreignKey: "${foreignKey}"` : '';
368- const fragments = prefixes.map(p => [
369- `${p}_obj: pluginsObjects(options: {plugin: "${p}", page: 1, limit: 1${fkOpt}}) { dbCount }`,
370- `${p}_evt: pluginsEvents(options: {plugin: "${p}", page: 1, limit: 1${fkOpt}}) { dbCount }`,
371- `${p}_hist: pluginsHistory(options: {plugin: "${p}", page: 1, limit: 1${fkOpt}}) { dbCount }`,
372- ].join('\n ')).join('\n ');
373-
374- const query = `query BadgeCounts {\n ${fragments}\n }`;
375-
376- $.ajax({
377- method: "POST",
378- url: `${apiBase}/graphql`,
379- headers: { "Authorization": `Bearer ${apiToken}`, "Content-Type": "application/json" },
380- data: JSON.stringify({ query }),
381- success: function(response) {
382- if (response.errors) {
383- console.error("[plugins] badge prefetch errors:", response.errors);
384- return;
364+ try {
365+ let counts = {}; // { PREFIX: { objects: N, events: N, history: N } }
366+
367+ if (!foreignKey) {
368+ // ---- FAST PATH: lightweight pre-computed JSON ----
369+ const stats = await fetchJson('table_plugins_stats.json');
370+ for (const row of stats.data) {
371+ const p = row.tableName; // 'objects' | 'events' | 'history'
372+ const plugin = row.plugin;
373+ if (!counts[plugin]) counts[plugin] = { objects: 0, events: 0, history: 0 };
374+ counts[plugin][p] = row.cnt;
385375 }
386- prefixes.forEach(p => {
387- const obj = response.data[`${p}_obj`];
388- const evt = response.data[`${p}_evt`];
389- const hist = response.data[`${p}_hist`];
390- if (obj) { $(`#badge_${p}`).text(obj.dbCount); $(`#objCount_${p}`).text(obj.dbCount); }
391- if (evt) { $(`#evtCount_${p}`).text(evt.dbCount); }
392- if (hist) { $(`#histCount_${p}`).text(hist.dbCount); }
376+ } else {
377+ // ---- FILTERED PATH: GraphQL with foreignKey ----
378+ const apiToken = getSetting("API_TOKEN");
379+ const apiBase = getApiBase();
380+ const fkOpt = `, foreignKey: "${foreignKey}"`;
381+ const fragments = prefixes.map(p => [
382+ `${p}_obj: pluginsObjects(options: {plugin: "${p}", page: 1, limit: 1${fkOpt}}) { dbCount }`,
383+ `${p}_evt: pluginsEvents(options: {plugin: "${p}", page: 1, limit: 1${fkOpt}}) { dbCount }`,
384+ `${p}_hist: pluginsHistory(options: {plugin: "${p}", page: 1, limit: 1${fkOpt}}) { dbCount }`,
385+ ].join('\n ')).join('\n ');
386+
387+ const query = `query BadgeCounts {\n ${fragments}\n }`;
388+ const response = await $.ajax({
389+ method: "POST",
390+ url: `${apiBase}/graphql`,
391+ headers: { "Authorization": `Bearer ${apiToken}`, "Content-Type": "application/json" },
392+ data: JSON.stringify({ query }),
393393 });
394+ if (response.errors) { console.error("[plugins] badge GQL errors:", response.errors); return; }
395+ for (const p of prefixes) {
396+ counts[p] = {
397+ objects: response.data[`${p}_obj`]?.dbCount ?? 0,
398+ events: response.data[`${p}_evt`]?.dbCount ?? 0,
399+ history: response.data[`${p}_hist`]?.dbCount ?? 0,
400+ };
401+ }
394402 }
395- });
403+
404+ // Update DOM
405+ for (const [prefix, c] of Object.entries(counts)) {
406+ $(`#badge_${prefix}`).text(c.objects);
407+ $(`#objCount_${prefix}`).text(c.objects);
408+ $(`#evtCount_${prefix}`).text(c.events);
409+ $(`#histCount_${prefix}`).text(c.history);
410+ }
411+ // Zero out plugins with no rows in any table
412+ prefixes.forEach(prefix => {
413+ if (!counts[prefix]) {
414+ $(`#badge_${prefix}`).text(0);
415+ $(`#objCount_${prefix}`).text(0);
416+ $(`#evtCount_${prefix}`).text(0);
417+ $(`#histCount_${prefix}`).text(0);
418+ }
419+ });
420+ } catch (err) {
421+ console.error('[plugins] badge prefetch failed:', err);
422+ }
396423}
397424
398425function generateTabs() {
0 commit comments