@necrolab/dashboard 0.4.215 → 0.4.216

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@necrolab/dashboard",
3
- "version": "0.4.215",
3
+ "version": "0.4.216",
4
4
  "scripts": {
5
5
  "build": "npx workbox-cli generateSW workbox-config.js && vite build",
6
6
  "dev": "vite",
@@ -152,7 +152,7 @@ const getFilterTitle = () => {
152
152
  return `${filter.value.section} (first row) ${excluded}`;
153
153
  case filterTypes.NORMAL: {
154
154
  const selectedRowAmount = filter.value?.rows?.length;
155
- const totalRowAmount = document.querySelectorAll(`path[sectionname='${filter.value.section}']`)?.length;
155
+ const totalRowAmount = document.querySelectorAll(`path[section='${filter.value.section}']`)?.length;
156
156
  isAllRows.value = selectedRowAmount === totalRowAmount || !filter.value?.rows?.length;
157
157
 
158
158
  if (isAllRows.value) return `${filter.value.section} (full section) ${excluded}`;
@@ -83,15 +83,23 @@ const cleanupFilter = (f) => {
83
83
  return ret;
84
84
  }
85
85
 
86
- if (f.rows && document.querySelectorAll(`path[sectionname="${f.section}"]`)?.length === f.rows?.length)
87
- delete f.rows;
86
+ if (f.rows && document.querySelectorAll(`path[section="${f.section}"]`)?.length === f.rows?.length) delete f.rows;
88
87
  if (f.rows) ret.rows = f.rows.sort(sortAlphaNum);
89
88
 
90
89
  return ret;
91
90
  };
92
-
93
91
  const getSectionNameMapping = () => {
94
92
  const sectionRealName = {};
93
+ [...document.querySelectorAll("path")].forEach((t) => {
94
+ try {
95
+ const sec = t.attributes.section.nodeValue.trim();
96
+ const secName = t.attributes.sectionname.nodeValue.trim();
97
+ sectionRealName[sec] = secName;
98
+ } catch {
99
+ /* empty */
100
+ }
101
+ });
102
+
95
103
  [...document.querySelectorAll("tspan")].forEach((t) => {
96
104
  const sec = t.attributes.section.nodeValue.trim();
97
105
  if (!sectionRealName[sec]) sectionRealName[sec] = t.innerHTML.trim();
@@ -102,6 +110,26 @@ const getSectionNameMapping = () => {
102
110
  return sectionRealName;
103
111
  };
104
112
 
113
+ const getReverseSectionNameMapping = () => {
114
+ const reverseSectionName = {};
115
+ [...document.querySelectorAll("path")].forEach((t) => {
116
+ try {
117
+ const sec = t.attributes.section.nodeValue.trim();
118
+ const secName = t.attributes.sectionname.nodeValue.trim();
119
+ if (!reverseSectionName[secName]) {
120
+ reverseSectionName[secName] = [];
121
+ }
122
+ if (!reverseSectionName[secName].includes(sec)) {
123
+ reverseSectionName[secName].push(sec);
124
+ }
125
+ } catch {
126
+ /* empty */
127
+ }
128
+ });
129
+ log("getReverseSectionNameMapping", reverseSectionName);
130
+ return reverseSectionName;
131
+ };
132
+
105
133
  export default class FilterBuilder {
106
134
  constructor() {
107
135
  this.filters = [];
@@ -164,7 +192,7 @@ export default class FilterBuilder {
164
192
  const row = this.rows[i];
165
193
  row.onclick = () => {
166
194
  const parsed = {
167
- section: row.attributes.sectionname.nodeValue,
195
+ section: row.attributes.section.nodeValue,
168
196
  row: row.attributes.row.nodeValue,
169
197
  id: row.attributes.id.nodeValue
170
198
  };
@@ -191,7 +219,7 @@ export default class FilterBuilder {
191
219
 
192
220
  row.onmouseover = () => {
193
221
  const parsed = {
194
- section: row.attributes.sectionname.nodeValue,
222
+ section: row.attributes.section.nodeValue,
195
223
  row: row.attributes.row.nodeValue,
196
224
  id: row.attributes.id.nodeValue
197
225
  };
@@ -242,6 +270,18 @@ export default class FilterBuilder {
242
270
  addFilter(filter) {
243
271
  if (!this.filters) this.filters = [];
244
272
 
273
+ // Check if a filter with the same properties (excluding id) already exists
274
+ const existingFilter = this.filters.find((f) => {
275
+ const n = { ...f };
276
+ delete n.id;
277
+ return JSON.stringify(n) === JSON.stringify(filter);
278
+ });
279
+
280
+ if (existingFilter) {
281
+ console.log("Filter already exists:", existingFilter);
282
+ return; // Don't add the filter if it already exists
283
+ }
284
+
245
285
  if (this.expandedFilter) {
246
286
  const parent = this.filters.find((f) => f.event === filter.event && f.section === filter.section);
247
287
  if (parent) return this.addFilterToParent(filter, parent);
@@ -295,6 +335,7 @@ export default class FilterBuilder {
295
335
  // eslint-disable-next-line no-unused-vars
296
336
  ([_, v]) => v === filter.section && v.includes(" ")
297
337
  )?.[0];
338
+
298
339
  if (tryFindRealName) {
299
340
  log(`Real name for ${filter.section}: ${tryFindRealName}`);
300
341
  } else {
@@ -309,15 +350,14 @@ export default class FilterBuilder {
309
350
  case this.filterTypes.NORMAL:
310
351
  // If it has no 'rows' property
311
352
  if (!Array.isArray(filter.rows)) {
312
- const isGA = document.querySelectorAll(`path[sectionname='${filter.section}']`)?.length === 0;
353
+ const isGA = document.querySelectorAll(`path[section='${filter.section}']`)?.length === 0;
313
354
 
314
355
  if (isGA) this.cssClasses += `path[name="${tryFindRealName}"] {fill: ${color} !important}`;
315
- else this.cssClasses += `path[sectionname="${filter.section}"] {stroke: ${color} !important}`;
356
+ else this.cssClasses += `path[section="${filter.section}"] {stroke: ${color} !important}`;
316
357
  } else {
317
358
  this.cssClasses += filter.rows
318
359
  .map(
319
- (row) =>
320
- `path[sectionname="${filter.section}"][row="${row}"] {stroke: ${color} !important}`
360
+ (row) => `path[section="${filter.section}"][row="${row}"] {stroke: ${color} !important}`
321
361
  )
322
362
  ?.join("\n");
323
363
  }
@@ -340,10 +380,10 @@ export default class FilterBuilder {
340
380
  });
341
381
 
342
382
  this.unselectable.forEach((unselectable) => {
343
- const [sectionName, row] = unselectable.split("/");
344
- log("UpdateCSS: adding unselectable", sectionName, row);
383
+ const [section, row] = unselectable.split("/");
384
+ log("UpdateCSS: adding unselectable", section, row);
345
385
  const color = colors.UNSELECTABLE;
346
- this.cssClasses += `path[sectionname="${sectionName}"][row="${row}"] {stroke: ${color} !important} `;
386
+ this.cssClasses += `path[section="${section}"][row="${row}"] {stroke: ${color} !important} `;
347
387
  });
348
388
  log(this.cssClasses);
349
389
  }
@@ -364,11 +404,7 @@ export default class FilterBuilder {
364
404
  if (f.section !== section && f.section !== gaSectionNameMapping[section]) return false;
365
405
  return true;
366
406
  });
367
- // (((f.section === section || f.section === gaSectionNameMapping[section]) && !f.rows) ||
368
- // (f.section === section &&
369
- // document.querySelectorAll(`path[sectionname="${section}"]`).length ===
370
- // f.rows.length)) &&
371
- // this.isForCurrentEvent(f)
407
+
372
408
  if (matchingFilter) {
373
409
  log(`Filter for ${section} already exists (${matchingFilter.id})`);
374
410
  if (this.expandedFilter === matchingFilter.id) this.setExpandedFilter(null);
@@ -388,9 +424,14 @@ export default class FilterBuilder {
388
424
  event: this.currentEventId
389
425
  });
390
426
  } else {
391
- this.addFilter({
392
- section: section.trim(),
393
- event: this.currentEventId
427
+ const reverseMapping = getReverseSectionNameMapping();
428
+ const sections = reverseMapping[section.trim()] || [section.trim()];
429
+ log("labelHandler: non-ga", sections, section);
430
+ sections.forEach((s) => {
431
+ this.addFilter({
432
+ section: s,
433
+ event: this.currentEventId
434
+ });
394
435
  });
395
436
  }
396
437
  log("Added labelHandler filter", section);
@@ -477,9 +518,9 @@ export default class FilterBuilder {
477
518
  if (this.filters.find((f) => f.section === filter.name)) return;
478
519
  newCSS += `path[name="${filter.section || filter.name}"] {fill: ${colors.HIGHLIGHT} !important}`;
479
520
  } else if (filter.row) {
480
- newCSS += `path[sectionname="${filter.section}"][row="${filter.row}"] {stroke: ${colors.HIGHLIGHT} !important}`;
521
+ newCSS += `path[section="${filter.section}"][row="${filter.row}"] {stroke: ${colors.HIGHLIGHT} !important}`;
481
522
  } else {
482
- newCSS += `path[sectionname="${filter.section}"] {stroke: ${colors.HIGHLIGHT} !important}`;
523
+ newCSS += `path[section="${filter.section}"] {stroke: ${colors.HIGHLIGHT} !important}`;
483
524
  }
484
525
  this.temporaryCSS += newCSS;
485
526
  }
@@ -18,7 +18,6 @@ const LOG_COLORS = {
18
18
  yellow: "color: #ffbb33; font-weight: bold", // Yellow
19
19
  reset: ""
20
20
  };
21
-
22
21
  class Logger {
23
22
  constructor() {
24
23
  this.ENABLED = true;
@@ -45,11 +44,20 @@ class Logger {
45
44
 
46
45
  args.unshift(timestamp);
47
46
 
47
+ // Format objects for console output
48
+ const formattedArgs = args.map((arg) => {
49
+ if (typeof arg === "object" && arg !== null) {
50
+ console.log(arg._value ? arg._value : arg);
51
+ return arg;
52
+ }
53
+ return arg;
54
+ });
55
+
48
56
  // For styled console output in browser
49
57
  if (style) {
50
- console.log(`%c${args.join(" ")}`, style);
58
+ console.log(`%c${formattedArgs.join(" ")}`, style);
51
59
  } else {
52
- console.log(...args);
60
+ console.log(...formattedArgs);
53
61
  }
54
62
  }
55
63
 
package/src/stores/ui.js CHANGED
@@ -202,22 +202,16 @@ export const useUIStore = defineStore("ui", () => {
202
202
 
203
203
  let relevantTasks = Object.values(tasks.value).filter((t) => t.siteId === currentCountry.value.siteId);
204
204
  if (currentEvent.value) relevantTasks = relevantTasks.filter((t) => t.eventId === currentEvent.value);
205
- // logger.Info("mqm tasks:", relevantTasks);
206
- const tasksInQueue = relevantTasks.filter((t) => t.status.includes(" - ETA:"));
207
205
 
208
206
  queueStats.value.total = 0;
209
- queueStats.value.queued =
210
- tasksInQueue.length + relevantTasks.filter((t) => t.status?.toLowerCase()?.includes("queueit")).length || 0;
207
+ queueStats.value.queued = relevantTasks.filter((t) => t.inQueue).length || 0;
211
208
  queueStats.value.show = queueStats.value.total > 0;
212
209
  const sleepingStatuses = ["sleeping in queue", "waiting for drop", "waiting for carting", "waiting for queue"];
213
210
  queueStats.value.sleeping = relevantTasks.filter((t) =>
214
211
  sleepingStatuses.includes(t.status.toLowerCase())
215
212
  ).length;
216
- const positions = tasksInQueue
217
- .map((t) => parseInt(t.status.split(" users ahead - ETA:")[0]))
218
- .filter((e) => !isNaN(e));
213
+ const positions = relevantTasks.map((t) => t.queuePosition).filter((e) => !isNaN(e));
219
214
  queueStats.value.nextQueuePasses = positions.sort((a, b) => a - b);
220
- // logger.Info("Refreshing queue stats", queueStats.value);
221
215
  };
222
216
 
223
217
  const toggleModal = (name, clearValue = false) => {
@@ -171,135 +171,135 @@ const activeModal = computed(() => ui.activeModal);
171
171
  const ui = useUIStore();
172
172
  const hasLoaded = ref(false);
173
173
 
174
- let isShiftPressed = false;
175
- window.onkeyup = (e) => {
176
- if (e.keyCode === 16) isShiftPressed = false;
177
- };
178
- window.onkeydown = (e) => {
179
- if (e.keyCode === 16) isShiftPressed = true;
180
- };
181
-
182
- const doDragSelect = () => {
183
- // https://dragselect.com/docs/API/Settings
184
- const ds = new DragSelect({
185
- selectables: [
186
- ...document.querySelectorAll("path[row]"),
187
- ...document.querySelectorAll("path[generaladmission]")
188
- ],
189
- area: document.getElementById("svg-wrapper"),
190
- selectionThreshold: 0.1,
191
- multiSelectKeys: []
192
- });
193
-
194
- ds.subscribe("DS:start:pre", () => {
195
- // ui.logger.Info("DS:start:pre - shift pressed:", isShiftPressed);
196
- if (!isShiftPressed) {
197
- ds.stop(false, false);
198
- ds.start();
199
- } else {
200
- panzoomInstance.pause();
201
- }
202
- });
203
-
204
- const parseSelected = (items) => {
205
- const parsed = items
206
- .map((e) => {
207
- return {
208
- section: e.attributes.sectionname?.nodeValue || e.attributes.name?.nodeValue,
209
- row: e.attributes.row?.nodeValue,
210
- GA: e.attributes.generaladmission?.nodeValue,
211
- name: e.attributes.name?.nodeValue
212
- };
213
- })
214
- .filter((e) => !filterBuilder.value.isUnselectable(e.section, e.row));
215
-
216
- const sectionMapping = {};
217
- parsed
218
- .filter((p) => !p.GA)
219
- .forEach((p) => {
220
- if (!sectionMapping[p.section]) sectionMapping[p.section] = [];
221
- sectionMapping[p.section].push(p);
222
- });
223
- parsed
224
- .filter((p) => p.GA)
225
- .forEach((p) => {
226
- sectionMapping[p.section] = {
227
- GA: true,
228
- section: p.section,
229
- name: p.name
230
- };
231
- });
232
- return sectionMapping;
233
- };
234
-
235
- ds.subscribe("DS:update:pre", (e) => {
236
- // ui.logger.Info("DS:update:pre - shift pressed:", isShiftPressed, e.items);
237
- filterBuilder.value.isDragging = true;
238
- if (!isShiftPressed) return;
239
- const sectionMapping = parseSelected(e.items);
240
- filterBuilder.value.clearHighlight();
241
- Object.entries(sectionMapping).forEach(([section, rows]) => {
242
- if (rows.GA) {
243
- const isSelected = filterBuilder.value.filters.find(
244
- (f) => filterBuilder.value.isForCurrentEvent(f) && f.section === section
245
- );
246
- if (isSelected) return;
247
- filterBuilder.value.highlight({ section: section }, true);
248
- } else
249
- rows.forEach((row) => {
250
- const isSelected = filterBuilder.value.filters.find(
251
- (f) =>
252
- (f.section === section && f.rows?.includes(row.row)) ||
253
- (!f.rows && f.section === section && filterBuilder.value.isForCurrentEvent(f))
254
- );
255
- if (isSelected) return;
256
-
257
- filterBuilder.value.highlight({ section, row: row.row });
258
- });
259
- });
260
- });
261
-
262
- ds.subscribe("DS:end", (e) => {
263
- filterBuilder.value.isDragging = false;
264
- panzoomInstance.resume();
265
- filterBuilder.value.clearHighlight();
266
- [...document.querySelectorAll("path")].map((f) => (f.style = ""));
267
- if (!isShiftPressed) return;
268
- const sectionMapping = parseSelected(e.items);
269
- const secNameMapping = filterBuilder.value.getSectionNameMapping();
270
-
271
- Object.entries(sectionMapping).forEach(([section, rows]) => {
272
- if (rows.GA) {
273
- const isSelected = filterBuilder.value.filters.find(
274
- (f) => filterBuilder.value.isForCurrentEvent(f) && f.section === secNameMapping[section]
275
- );
276
- if (isSelected) return;
277
- filterBuilder.value.addFilter({
278
- event: filterBuilder.value.currentEventId,
279
- section: secNameMapping[section]
280
- });
281
- } else {
282
- const unselectedRows = [];
283
- rows.forEach((row) => {
284
- const isSelected = filterBuilder.value.filters.find(
285
- (f) =>
286
- (f.section === section && f.rows?.includes(row.row)) ||
287
- (!f.rows && f.section === section && filterBuilder.value.isForCurrentEvent(f))
288
- );
289
- if (isSelected) return;
290
- unselectedRows.push(row.row);
291
- });
292
- if (unselectedRows.length === 0) return;
293
- filterBuilder.value.addFilter({
294
- event: filterBuilder.value.currentEventId,
295
- section,
296
- rows: unselectedRows
297
- });
298
- }
299
- });
300
- isShiftPressed = false;
301
- });
302
- };
174
+ // let isShiftPressed = false;
175
+ // window.onkeyup = (e) => {
176
+ // if (e.keyCode === 16) isShiftPressed = false;
177
+ // };
178
+ // window.onkeydown = (e) => {
179
+ // if (e.keyCode === 16) isShiftPressed = true;
180
+ // };
181
+
182
+ // const doDragSelect = () => {
183
+ // // https://dragselect.com/docs/API/Settings
184
+ // const ds = new DragSelect({
185
+ // selectables: [
186
+ // ...document.querySelectorAll("path[row]"),
187
+ // ...document.querySelectorAll("path[generaladmission]")
188
+ // ],
189
+ // area: document.getElementById("svg-wrapper"),
190
+ // selectionThreshold: 0.1,
191
+ // multiSelectKeys: []
192
+ // });
193
+
194
+ // ds.subscribe("DS:start:pre", () => {
195
+ // // ui.logger.Info("DS:start:pre - shift pressed:", isShiftPressed);
196
+ // if (!isShiftPressed) {
197
+ // ds.stop(false, false);
198
+ // ds.start();
199
+ // } else {
200
+ // panzoomInstance.pause();
201
+ // }
202
+ // });
203
+
204
+ // const parseSelected = (items) => {
205
+ // const parsed = items
206
+ // .map((e) => {
207
+ // return {
208
+ // section: e.attributes.sectionname?.nodeValue || e.attributes.name?.nodeValue,
209
+ // row: e.attributes.row?.nodeValue,
210
+ // GA: e.attributes.generaladmission?.nodeValue,
211
+ // name: e.attributes.name?.nodeValue
212
+ // };
213
+ // })
214
+ // .filter((e) => !filterBuilder.value.isUnselectable(e.section, e.row));
215
+
216
+ // const sectionMapping = {};
217
+ // parsed
218
+ // .filter((p) => !p.GA)
219
+ // .forEach((p) => {
220
+ // if (!sectionMapping[p.section]) sectionMapping[p.section] = [];
221
+ // sectionMapping[p.section].push(p);
222
+ // });
223
+ // parsed
224
+ // .filter((p) => p.GA)
225
+ // .forEach((p) => {
226
+ // sectionMapping[p.section] = {
227
+ // GA: true,
228
+ // section: p.section,
229
+ // name: p.name
230
+ // };
231
+ // });
232
+ // return sectionMapping;
233
+ // };
234
+
235
+ // ds.subscribe("DS:update:pre", (e) => {
236
+ // // ui.logger.Info("DS:update:pre - shift pressed:", isShiftPressed, e.items);
237
+ // filterBuilder.value.isDragging = true;
238
+ // if (!isShiftPressed) return;
239
+ // const sectionMapping = parseSelected(e.items);
240
+ // filterBuilder.value.clearHighlight();
241
+ // Object.entries(sectionMapping).forEach(([section, rows]) => {
242
+ // if (rows.GA) {
243
+ // const isSelected = filterBuilder.value.filters.find(
244
+ // (f) => filterBuilder.value.isForCurrentEvent(f) && f.section === section
245
+ // );
246
+ // if (isSelected) return;
247
+ // filterBuilder.value.highlight({ section: section }, true);
248
+ // } else
249
+ // rows.forEach((row) => {
250
+ // const isSelected = filterBuilder.value.filters.find(
251
+ // (f) =>
252
+ // (f.section === section && f.rows?.includes(row.row)) ||
253
+ // (!f.rows && f.section === section && filterBuilder.value.isForCurrentEvent(f))
254
+ // );
255
+ // if (isSelected) return;
256
+
257
+ // filterBuilder.value.highlight({ section, row: row.row });
258
+ // });
259
+ // });
260
+ // });
261
+
262
+ // ds.subscribe("DS:end", (e) => {
263
+ // filterBuilder.value.isDragging = false;
264
+ // panzoomInstance.resume();
265
+ // filterBuilder.value.clearHighlight();
266
+ // [...document.querySelectorAll("path")].map((f) => (f.style = ""));
267
+ // if (!isShiftPressed) return;
268
+ // const sectionMapping = parseSelected(e.items);
269
+ // const secNameMapping = filterBuilder.value.getSectionNameMapping();
270
+
271
+ // Object.entries(sectionMapping).forEach(([section, rows]) => {
272
+ // if (rows.GA) {
273
+ // const isSelected = filterBuilder.value.filters.find(
274
+ // (f) => filterBuilder.value.isForCurrentEvent(f) && f.section === secNameMapping[section]
275
+ // );
276
+ // if (isSelected) return;
277
+ // filterBuilder.value.addFilter({
278
+ // event: filterBuilder.value.currentEventId,
279
+ // section: secNameMapping[section]
280
+ // });
281
+ // } else {
282
+ // const unselectedRows = [];
283
+ // rows.forEach((row) => {
284
+ // const isSelected = filterBuilder.value.filters.find(
285
+ // (f) =>
286
+ // (f.section === section && f.rows?.includes(row.row)) ||
287
+ // (!f.rows && f.section === section && filterBuilder.value.isForCurrentEvent(f))
288
+ // );
289
+ // if (isSelected) return;
290
+ // unselectedRows.push(row.row);
291
+ // });
292
+ // if (unselectedRows.length === 0) return;
293
+ // filterBuilder.value.addFilter({
294
+ // event: filterBuilder.value.currentEventId,
295
+ // section,
296
+ // rows: unselectedRows
297
+ // });
298
+ // }
299
+ // });
300
+ // isShiftPressed = false;
301
+ // });
302
+ // };
303
303
 
304
304
  const panzoomOptions = {
305
305
  maxZoom: 8, // max zoom-in facor
@@ -376,7 +376,7 @@ const updateShownVenue = async () => {
376
376
  await nextTick();
377
377
  await loadFilter();
378
378
  filterBuilder.value.reload(eventId.value);
379
- doDragSelect();
379
+ // doDragSelect();
380
380
  };
381
381
 
382
382
  const loadFilter = async () => {