@necrolab/dashboard 0.5.18 → 0.5.20

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.5.18",
3
+ "version": "0.5.20",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "build": "rm -rf dist && vite build && npx workbox-cli generateSW workbox-config.cjs",
package/postinstall.js CHANGED
@@ -17,7 +17,7 @@ try {
17
17
 
18
18
  try {
19
19
  // Detect if we're running inside the project itself or as a dependency
20
- const isInsideProject = __dirname.includes('node_modules') === false;
20
+ const isInsideProject = __dirname.includes("node_modules") === false;
21
21
 
22
22
  let distPath, versionFilePath;
23
23
 
@@ -46,7 +46,7 @@ try {
46
46
  `Version mismatch (Installed: ${installedVersion}, Target: ${currentVersion}). Proceeding with build.`
47
47
  );
48
48
  }
49
- } catch (readErr) {
49
+ } catch {
50
50
  console.log("Could not read version file. Proceeding with build.");
51
51
  }
52
52
  } else {
@@ -61,8 +61,6 @@ import { useUIStore } from "@/stores/ui";
61
61
  import TagLabel from "@/components/Editors/TagLabel.vue";
62
62
  import { useRowSelection } from "@/composables/useRowSelection";
63
63
  import { useCopyToClipboard } from "@/composables/useCopyToClipboard";
64
- import { computed } from "vue";
65
- import { useEnableDisable } from "@/composables/useEnableDisable";
66
64
 
67
65
  const ui = useUIStore();
68
66
  const { copy } = useCopyToClipboard();
@@ -140,9 +140,10 @@ const isEditorVisible = computed(() => props.currentFile !== '');
140
140
  const isJsonFile = computed(() => props.currentFile.endsWith('.json'));
141
141
 
142
142
  const errorMessage = computed(() => {
143
- if (!isJsonFile.value) return;
143
+ if (!isJsonFile.value) return null;
144
144
  try {
145
145
  JSON.parse(props.content);
146
+ return null;
146
147
  } catch (e) {
147
148
  return e.message;
148
149
  }
@@ -107,7 +107,7 @@ export function useDropdownPosition(dropdownRef, options = {}) {
107
107
  zIndex,
108
108
  maxHeight: `${maxHeight}px`
109
109
  };
110
- } catch (error) {
110
+ } catch {
111
111
  menuStyle.value = {
112
112
  position: "fixed",
113
113
  top: "0px",
@@ -13,10 +13,6 @@ export function useFormValidation() {
13
13
  }
14
14
  };
15
15
 
16
- const hasError = (fieldName) => {
17
- return errors.value.includes(fieldName);
18
- };
19
-
20
16
  const isValidEmail = (email) => {
21
17
  return email && email.includes("@");
22
18
  };
@@ -52,10 +48,6 @@ export function useFormValidation() {
52
48
  return true; // Not required for other countries
53
49
  };
54
50
 
55
- const isValidZipCode = (zipCode) => {
56
- return zipCode && zipCode.trim().length > 0;
57
- };
58
-
59
51
  const validateAccount = (account) => {
60
52
  clearErrors();
61
53
 
@@ -253,7 +253,6 @@ export function useNotchHandling(logger) {
253
253
 
254
254
  // Vue-specific watchers
255
255
  onMounted(() => {
256
- let attempts = 0;
257
256
  const maxAttempts = 5;
258
257
  const delays = [0, 50, 150, 300, 500];
259
258
 
@@ -118,7 +118,9 @@ export class ConnectionHandler {
118
118
  } else if (msg.update) {
119
119
  try {
120
120
  Object.entries(msg.update).forEach((change) => (this.ui.tasks[msg.id][change[0]] = change[1]));
121
- } catch {}
121
+ } catch {
122
+ // Ignore update errors if task doesn't exist
123
+ }
122
124
  } else {
123
125
  if (!this.ui.tasks[msg.id]) this.ui.tasks[msg.id] = msg.task;
124
126
  if (!this.ui.taskIdOrder.includes(msg.id)) {
@@ -46,13 +46,13 @@ class Logger {
46
46
 
47
47
  // For styled console output in browser
48
48
  if (style) {
49
- /* eslint-disable no-console */
49
+
50
50
  console.log(`%c${args.join(" ")}`, style);
51
- /* eslint-enable no-console */
51
+
52
52
  } else {
53
- /* eslint-disable no-console */
53
+
54
54
  console.log(...args);
55
- /* eslint-enable no-console */
55
+
56
56
  }
57
57
  }
58
58
 
@@ -16,7 +16,7 @@
16
16
  :taskLogMapping="taskLogMapping"
17
17
  :userScrolledUp="userScrolledUp"
18
18
  :filteredCount="filteredCount"
19
- @scroll="handleScrollDirection"
19
+ @scroll="startScrolling"
20
20
  @scroll-stop="stopScrolling"
21
21
  @autoscroll-toggle="onAutoscrollToggle" />
22
22
 
@@ -122,11 +122,10 @@ import { Smoothie } from "vue-smoothie";
122
122
  import { DEBUG } from "@/utils/debug";
123
123
 
124
124
  import Filter from "@/libs/ansii.js";
125
- import { ConsoleIcon, DownIcon, UpIcon } from "@/components/icons";
125
+ import { ConsoleIcon } from "@/components/icons";
126
126
  import Switch from "@/components/ui/controls/atomic/Switch.vue";
127
127
  import WebsocketHeartbeatJs from "websocket-heartbeat-js";
128
128
  import { onMounted, onUnmounted, ref, nextTick, computed, watch } from "vue";
129
- import Dropdown from "@/components/ui/controls/atomic/Dropdown.vue";
130
129
  import ConsoleToolbar from "@/components/Console/ConsoleToolbar.vue";
131
130
 
132
131
  const $autoscroll = ref(null);
@@ -216,7 +215,7 @@ const performScroll = (direction, smooth = true) => {
216
215
  }
217
216
 
218
217
  return true;
219
- } catch (e) {
218
+ } catch {
220
219
  if (DEBUG) return false;
221
220
  return false;
222
221
  }
@@ -70,8 +70,6 @@ let previous = {
70
70
 
71
71
  const loadAvailableFiles = async () => (availableFiles.value = await loadFromApi("/api/json-files"));
72
72
 
73
- const isJsonFile = () => currentFile.value.endsWith(".json");
74
-
75
73
  const loadFile = async (f) => {
76
74
  currentFile.value = f;
77
75
  if (DEBUG) {
@@ -12,7 +12,7 @@
12
12
  v-model="eventId"
13
13
  aria-label="Event ID" />
14
14
  <button
15
- class="flex h-10 w-9 flex-shrink-0 items-center justify-center bg-dark-400 text-white transition-standard hover:bg-dark-450"
15
+ class="transition-standard hover:bg-dark-450 flex h-10 w-9 flex-shrink-0 items-center justify-center bg-dark-400 text-white"
16
16
  @click="updateShownVenue"
17
17
  aria-label="Load venue">
18
18
  <ReloadIcon class="icon-md" />
@@ -20,16 +20,14 @@
20
20
  </div>
21
21
  </div>
22
22
 
23
- <div class="mb-3 flex flex-1 flex-col overflow-hidden rounded border border-dark-650 bg-dark-400 p-3 shadow-sm md:mb-4">
23
+ <div
24
+ class="mb-3 flex flex-1 flex-col overflow-hidden rounded border border-dark-650 bg-dark-400 p-3 shadow-sm md:mb-4">
24
25
  <div class="flex h-full w-full flex-col gap-3 lg:flex-row lg:gap-4">
25
- <div class="relative flex min-h-75 min-w-0 w-full flex-col overflow-hidden rounded-lg lg:min-h-125 lg:w-3/5">
26
- <div v-if="svg" class="mb-2 flex-gap-2 items-center">
27
- <button @click="handleZoom(true)" class="btn-icon-small" aria-label="Zoom in">
28
- +
29
- </button>
30
- <button @click="handleZoom(false)" class="btn-icon-small" aria-label="Zoom out">
31
- -
32
- </button>
26
+ <div
27
+ class="min-h-75 lg:min-h-125 relative flex w-full min-w-0 flex-col overflow-hidden rounded-lg lg:w-3/5">
28
+ <div v-if="svg" class="flex-gap-2 mb-2 items-center">
29
+ <button @click="handleZoom(true)" class="btn-icon-small" aria-label="Zoom in">+</button>
30
+ <button @click="handleZoom(false)" class="btn-icon-small" aria-label="Zoom out">-</button>
33
31
  <button @click="handleZoom('r')" class="btn-icon-small" aria-label="Reset zoom">
34
32
  <ReloadIcon class="icon-md text-white" />
35
33
  </button>
@@ -37,14 +35,14 @@
37
35
  <div class="selecto-wrapper flex-1 overflow-hidden">
38
36
  <div
39
37
  v-if="svg"
40
- class="hidden-scrollbars relative h-full min-h-87.5 w-full overflow-auto rounded border border-dark-550 bg-dark-500 p-2 shadow">
38
+ class="hidden-scrollbars min-h-87.5 relative h-full w-full overflow-auto rounded border border-dark-550 bg-dark-500 p-2 shadow">
41
39
  <div class="svg-wrapper" id="svg-wrapper" v-html="svg"></div>
42
40
  </div>
43
41
  <div
44
42
  v-else
45
- class="relative flex h-full min-h-87.5 w-full items-center justify-center rounded border border-dark-550 bg-dark-500 p-2 shadow">
43
+ class="min-h-87.5 relative flex h-full w-full items-center justify-center rounded border border-dark-550 bg-dark-500 p-2 shadow">
46
44
  <div class="text-center">
47
- <FilterIcon class="mx-auto empty-state-icon" />
45
+ <FilterIcon class="empty-state-icon mx-auto" />
48
46
  <p class="text-sm text-light-400">No Map</p>
49
47
  <p class="mt-1 text-xs text-light-500">
50
48
  Enter an event ID and click "Load" to display the venue map
@@ -53,7 +51,7 @@
53
51
  </div>
54
52
  </div>
55
53
  </div>
56
- <div class="flex min-h-75 min-w-0 w-full flex-col lg:min-h-125 lg:w-2/5">
54
+ <div class="min-h-75 lg:min-h-125 flex w-full min-w-0 flex-col lg:w-2/5">
57
55
  <div class="mb-2 flex flex-shrink-0 flex-wrap items-center gap-2 text-white" v-if="hasLoaded">
58
56
  <PriceSortToggle
59
57
  :current="filterBuilder.globalFilter.priceSort"
@@ -72,7 +70,8 @@
72
70
  class="input-default h-8 w-16 px-2 text-sm"
73
71
  placeholder="999" />
74
72
  </div>
75
- <div class="flex min-h-0 flex-1 flex-col overflow-hidden rounded-lg border border-dark-550 bg-dark-500 shadow-sm">
73
+ <div
74
+ class="flex min-h-0 flex-1 flex-col overflow-hidden rounded-lg border border-dark-550 bg-dark-500 shadow-sm">
76
75
  <div class="flex-shrink-0 border-b border-dark-550 bg-dark-300 px-4 py-3 text-xs text-white">
77
76
  <div class="flex w-full items-center justify-between gap-2">
78
77
  <div class="flex-gap-2 items-center">
@@ -85,10 +84,7 @@
85
84
  :options="['All', 'WL', 'BL']"
86
85
  :current="shownFilters"
87
86
  @change="(e) => (shownFilters = e)" />
88
- <button
89
- class="filter-action-btn"
90
- @click="saveFilter"
91
- title="Save filter">
87
+ <button class="filter-action-btn" @click="saveFilter" title="Save filter">
92
88
  <EditIcon class="h-3 w-3 flex-shrink-0" />
93
89
  <span>Save</span>
94
90
  </button>
@@ -103,33 +99,31 @@
103
99
  </div>
104
100
  </div>
105
101
  <div class="hidden-scrollbars flex-1 overflow-auto bg-dark-400">
106
- <draggable
107
- v-if="filterBuilder.filters.length"
108
- v-model="draggableFilters"
109
- handle=".handle"
110
- item-key="id"
111
- tag="div"
112
- class="space-y-0 p-1"
113
- ghost-class="opacity-30 border border-dark-550 bg-dark-550/10"
114
- drag-class="z-50 shadow-xl"
115
- :animation="200">
116
- <template #item="{ element: f, index: i }">
117
- <Filter
118
- v-show="doesFilterShow(f)"
119
- :filter="f"
120
- :index="i"
121
- :filterBuilder="filterBuilder"
122
- class="!p-1 !text-xs" />
123
- </template>
124
- </draggable>
125
- <div
126
- v-else
127
- class="empty-state flex flex-col items-center justify-center py-8 text-center">
128
- <FilterIcon class="empty-state-icon" />
129
- <p class="text-sm text-light-400">No filters yet</p>
130
- <p class="mt-1 text-xs text-light-500">Click on the map to create filters</p>
131
- </div>
102
+ <draggable
103
+ v-if="filterBuilder.filters.length"
104
+ v-model="draggableFilters"
105
+ handle=".handle"
106
+ item-key="id"
107
+ tag="div"
108
+ class="space-y-0 p-1"
109
+ ghost-class="opacity-30 border border-dark-550 bg-dark-550/10"
110
+ drag-class="z-50 shadow-xl"
111
+ :animation="200">
112
+ <template #item="{ element: f, index: i }">
113
+ <Filter
114
+ v-show="doesFilterShow(f)"
115
+ :filter="f"
116
+ :index="i"
117
+ :filterBuilder="filterBuilder"
118
+ class="!p-1 !text-xs" />
119
+ </template>
120
+ </draggable>
121
+ <div v-else class="empty-state flex flex-col items-center justify-center py-8 text-center">
122
+ <FilterIcon class="empty-state-icon" />
123
+ <p class="text-sm text-light-400">No filters yet</p>
124
+ <p class="mt-1 text-xs text-light-500">Click on the map to create filters</p>
132
125
  </div>
126
+ </div>
133
127
  </div>
134
128
  <div class="mt-2 flex flex-shrink-0 items-center justify-between gap-2">
135
129
  <button
@@ -139,9 +133,7 @@
139
133
  :title="hasWildcardFilter ? 'Wildcard filter already exists' : 'Add wildcard filter'">
140
134
  * Wildcard
141
135
  </button>
142
- <button
143
- @click="ui.toggleModal('preview-filter')"
144
- class="filter-action-btn">
136
+ <button @click="ui.toggleModal('preview-filter')" class="filter-action-btn">
145
137
  <CameraIcon class="h-3 w-3" />
146
138
  <span>JSON</span>
147
139
  </button>
@@ -158,8 +150,7 @@
158
150
 
159
151
  <script setup>
160
152
  import draggable from "vuedraggable";
161
- import { ref, computed, defineAsyncComponent, watch, onMounted, onUnmounted, nextTick } from "vue";
162
- import { onBeforeRouteLeave } from "vue-router";
153
+ import { ref, computed, defineAsyncComponent, watch, nextTick } from "vue";
163
154
  import { useFilterCSS } from "@/composables/useFilterCSS";
164
155
  import Filter from "@/components/Filter/Filter.vue";
165
156
  import { FilterIcon } from "@/components/icons";
@@ -216,7 +207,7 @@ const addWildcardFilter = () => {
216
207
 
217
208
  let RendererFactory = import("@necrolab/tm-renderer");
218
209
 
219
- const { injectStyles, cssUpdateTrigger } = useFilterCSS(filterBuilder, svg);
210
+ useFilterCSS(filterBuilder, svg);
220
211
 
221
212
  const doesFilterShow = (filter) => {
222
213
  if ((filter.event || filter.eventId) !== filterBuilder.value.currentEventId) return;
@@ -242,6 +233,10 @@ const updateShownVenue = async () => {
242
233
  if (eventId.value.length === 16) {
243
234
  // 16-char eventIds are global, but try current country first as fallback
244
235
  country = ui.currentCountry?.id || null;
236
+ // For TM module, convert "US" to "USA"
237
+ if (ui.currentModule === "TM" && country === "US") {
238
+ country = "USA";
239
+ }
245
240
  } else if (eventId.value.length > 0) {
246
241
  // Shorter eventIds need country specification
247
242
  country = ui.currentCountry?.id;
@@ -249,6 +244,10 @@ const updateShownVenue = async () => {
249
244
  ui.showError("Invalid eventId or missing country!");
250
245
  return;
251
246
  }
247
+ // For TM module, convert "US" to "USA"
248
+ if (ui.currentModule === "TM" && country === "US") {
249
+ country = "USA";
250
+ }
252
251
  } else {
253
252
  ui.showError("Event ID is required!");
254
253
  return;
@@ -326,9 +325,6 @@ const updateShownVenue = async () => {
326
325
  await nextTick();
327
326
  await loadFilter();
328
327
  filterBuilder.value.reload(eventId.value);
329
-
330
- // Re-setup CSS system after reload
331
- setupCSSUpdates();
332
328
  filterBuilder.value.updateCss();
333
329
  };
334
330
 
@@ -164,7 +164,7 @@ watch(
164
164
  const f = (p) => searchRegex.test(p[filterFieldMap[field]]);
165
165
  ui.search.profiles.results = profs.filter(f);
166
166
 
167
- allTags.value = getAllTags();
167
+ allTags.value = useGetAllTags(ui.search.profiles.results);
168
168
  }
169
169
  );
170
170