@necrolab/dashboard 0.5.15 → 0.5.16
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/backend/api.js +2 -3
- package/eslint.config.js +46 -0
- package/index.html +2 -1
- package/package.json +5 -2
- package/src/App.vue +140 -170
- package/src/assets/css/base/mixins.scss +72 -0
- package/src/assets/css/base/reset.scss +0 -2
- package/src/assets/css/base/scroll.scss +43 -36
- package/src/assets/css/base/typography.scss +9 -10
- package/src/assets/css/base/variables.scss +43 -0
- package/src/assets/css/components/accessibility.scss +37 -0
- package/src/assets/css/components/buttons.scss +58 -15
- package/src/assets/css/components/forms.scss +31 -32
- package/src/assets/css/components/headers.scss +12 -20
- package/src/assets/css/components/modals.scss +2 -2
- package/src/assets/css/components/search-groups.scss +28 -22
- package/src/assets/css/components/tables.scss +5 -7
- package/src/assets/css/components/toasts.scss +7 -7
- package/src/assets/css/components/utilities.scss +220 -0
- package/src/assets/css/main.scss +66 -77
- package/src/components/Auth/LoginForm.vue +5 -84
- package/src/components/Editors/Account/Account.vue +8 -10
- package/src/components/Editors/Account/AccountCreator.vue +28 -59
- package/src/components/Editors/Account/AccountView.vue +38 -86
- package/src/components/Editors/Account/CreateAccount.vue +8 -50
- package/src/components/Editors/Profile/CreateProfile.vue +74 -131
- package/src/components/Editors/Profile/Profile.vue +15 -17
- package/src/components/Editors/Profile/ProfileCountryChooser.vue +16 -60
- package/src/components/Editors/Profile/ProfileView.vue +46 -96
- package/src/components/Editors/TagLabel.vue +16 -55
- package/src/components/Editors/TagToggle.vue +20 -8
- package/src/components/Filter/Filter.vue +62 -75
- package/src/components/Filter/FilterPreview.vue +161 -135
- package/src/components/Filter/PriceSortToggle.vue +36 -43
- package/src/components/Table/Header.vue +1 -1
- package/src/components/Table/Table.vue +45 -51
- package/src/components/Tasks/CheckStock.vue +7 -16
- package/src/components/Tasks/Controls/DesktopControls.vue +15 -60
- package/src/components/Tasks/Controls/MobileControls.vue +5 -20
- package/src/components/Tasks/CreateTaskAXS.vue +20 -118
- package/src/components/Tasks/CreateTaskTM.vue +33 -189
- package/src/components/Tasks/EventDetailRow.vue +21 -0
- package/src/components/Tasks/MassEdit.vue +6 -16
- package/src/components/Tasks/QuickSettings.vue +140 -216
- package/src/components/Tasks/ScrapeVenue.vue +4 -13
- package/src/components/Tasks/Stats.vue +19 -38
- package/src/components/Tasks/Task.vue +65 -268
- package/src/components/Tasks/TaskLabel.vue +9 -3
- package/src/components/Tasks/TaskView.vue +43 -63
- package/src/components/Tasks/Utilities.vue +10 -44
- package/src/components/Tasks/ViewTask.vue +23 -107
- package/src/components/icons/Close.vue +2 -8
- package/src/components/icons/Gear.vue +8 -8
- package/src/components/icons/Hash.vue +5 -0
- package/src/components/icons/Key.vue +2 -8
- package/src/components/icons/Pencil.vue +2 -8
- package/src/components/icons/Profile.vue +2 -8
- package/src/components/icons/Sell.vue +2 -8
- package/src/components/icons/Spinner.vue +4 -7
- package/src/components/icons/SquareCheck.vue +2 -8
- package/src/components/icons/SquareUncheck.vue +2 -8
- package/src/components/icons/Wildcard.vue +2 -8
- package/src/components/icons/index.js +3 -1
- package/src/components/ui/ActionButtonGroup.vue +113 -52
- package/src/components/ui/BalanceIndicator.vue +60 -0
- package/src/components/ui/EmptyState.vue +24 -0
- package/src/components/ui/EnableDisableToggle.vue +23 -0
- package/src/components/ui/FormField.vue +48 -48
- package/src/components/ui/IconLabel.vue +23 -0
- package/src/components/ui/InfoRow.vue +21 -54
- package/src/components/ui/Modal.vue +89 -56
- package/src/components/ui/Navbar.vue +60 -41
- package/src/components/ui/ReadonlyFieldsSection.vue +31 -0
- package/src/components/ui/ReconnectIndicator.vue +111 -124
- package/src/components/ui/SectionCard.vue +6 -14
- package/src/components/ui/Splash.vue +2 -10
- package/src/components/ui/StatusBadge.vue +26 -28
- package/src/components/ui/TaskToggle.vue +54 -0
- package/src/components/ui/controls/CountryChooser.vue +27 -64
- package/src/components/ui/controls/EyeToggle.vue +1 -1
- package/src/components/ui/controls/atomic/Checkbox.vue +40 -121
- package/src/components/ui/controls/atomic/Dropdown.vue +103 -139
- package/src/components/ui/controls/atomic/MultiDropdown.vue +71 -119
- package/src/components/ui/controls/atomic/Switch.vue +21 -84
- package/src/composables/useColorMapping.js +15 -0
- package/src/composables/useCopyToClipboard.js +1 -1
- package/src/composables/useDateFormatting.js +21 -0
- package/src/composables/useDeviceDetection.js +14 -0
- package/src/composables/useDropdownPosition.js +3 -4
- package/src/composables/useDynamicTableHeight.js +31 -0
- package/src/composables/useRowSelection.js +0 -3
- package/src/composables/useTicketPricing.js +16 -0
- package/src/composables/useWindowDimensions.js +21 -0
- package/src/libs/Filter.js +14 -20
- package/src/libs/panzoom.js +1 -5
- package/src/libs/utils/array.js +60 -0
- package/src/{stores/utils.js → libs/utils/dataGeneration.js} +2 -250
- package/src/libs/utils/eventUrl.js +40 -0
- package/src/libs/utils/string.js +28 -0
- package/src/libs/utils/time.js +20 -0
- package/src/libs/utils/validation.js +88 -0
- package/src/main.js +0 -2
- package/src/stores/connection.js +1 -4
- package/src/stores/logger.js +6 -12
- package/src/stores/sampleData.js +1 -2
- package/src/stores/ui.js +59 -36
- package/src/views/Accounts.vue +13 -24
- package/src/views/Console.vue +70 -172
- package/src/views/Editor.vue +211 -379
- package/src/views/FilterBuilder.vue +188 -371
- package/src/views/Login.vue +3 -28
- package/src/views/Profiles.vue +8 -15
- package/src/views/Tasks.vue +49 -36
- package/tailwind.config.js +82 -71
- package/workbox-config.cjs +47 -5
- package/docs/plans/2026-02-08-tailwind-consolidation.md +0 -2438
- package/exit +0 -209
- package/run +0 -177
- package/src/assets/css/base/color-fallbacks.scss +0 -10
- package/switch-branch.sh +0 -41
- /package/public/{reconnect-logo.png → img/reconnect-logo.png} +0 -0
package/src/stores/ui.js
CHANGED
|
@@ -3,7 +3,8 @@ import { defineStore } from "pinia";
|
|
|
3
3
|
import { ConnectionHandler } from "@/stores/connection.js";
|
|
4
4
|
import { toast } from "vue3-toastify";
|
|
5
5
|
import { createLogger } from "@/stores/logger";
|
|
6
|
-
import { timeDifference
|
|
6
|
+
import { timeDifference } from "@/libs/utils/time";
|
|
7
|
+
import { betterSort, sortTaskIds } from "@/libs/utils/array";
|
|
7
8
|
|
|
8
9
|
import mockTaskData from "@/stores/sampleData.js";
|
|
9
10
|
import { useRouter } from "vue-router";
|
|
@@ -60,9 +61,6 @@ export const useUIStore = defineStore("ui", () => {
|
|
|
60
61
|
const selectedTaskForView = ref(null);
|
|
61
62
|
const connection = new ConnectionHandler();
|
|
62
63
|
|
|
63
|
-
const startPoint = ref(0);
|
|
64
|
-
const pullChange = ref(0);
|
|
65
|
-
|
|
66
64
|
const currentEvent = ref("");
|
|
67
65
|
const currentCountry = ref({ id: "US", siteId: "TM_US", url: "https://www.ticketmaster.com" });
|
|
68
66
|
const currentModule = ref("TM");
|
|
@@ -99,19 +97,33 @@ export const useUIStore = defineStore("ui", () => {
|
|
|
99
97
|
});
|
|
100
98
|
const currentDropdown = ref("");
|
|
101
99
|
|
|
102
|
-
//
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
100
|
+
// Optimized: Use requestAnimationFrame instead of setInterval to reduce CPU waste
|
|
101
|
+
// Only update times when tab is visible and at most once per second
|
|
102
|
+
let lastTimeUpdate = 0;
|
|
103
|
+
let lastSyncCheck = 0;
|
|
104
|
+
let rafId = null;
|
|
105
|
+
|
|
106
|
+
const updateTaskTimes = (timestamp) => {
|
|
107
|
+
// Only update once per second
|
|
108
|
+
if (timestamp - lastTimeUpdate >= 1000) {
|
|
109
|
+
lastTimeUpdate = timestamp;
|
|
110
|
+
const now = Date.now();
|
|
111
|
+
|
|
112
|
+
for (const [key, value] of Object.entries(tasks.value)) {
|
|
113
|
+
if (value.expirationTime) {
|
|
114
|
+
tasks.value[key]._timeLeftString =
|
|
115
|
+
value.expirationTime == "Invalid Date"
|
|
116
|
+
? "No Cartholds"
|
|
117
|
+
: timeDifference(Date.parse(value.expirationTime), now);
|
|
118
|
+
} else {
|
|
119
|
+
tasks.value[key]._timeLeftString = undefined;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
112
122
|
}
|
|
113
123
|
|
|
114
|
-
|
|
124
|
+
// Sync taskIdOrder every 10 seconds (optimized with Map for O(1) lookups)
|
|
125
|
+
if (timestamp - lastSyncCheck >= 10000) {
|
|
126
|
+
lastSyncCheck = timestamp;
|
|
115
127
|
const allIds = new Set(Object.keys(tasks.value));
|
|
116
128
|
const orderIds = new Set(taskIdOrder.value);
|
|
117
129
|
|
|
@@ -123,20 +135,44 @@ export const useUIStore = defineStore("ui", () => {
|
|
|
123
135
|
|
|
124
136
|
if (missingIds.length > 0) {
|
|
125
137
|
missingIds.sort(sortTaskIds);
|
|
138
|
+
// Optimized: Binary search for insertion point
|
|
126
139
|
for (const id of missingIds) {
|
|
127
|
-
let
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
140
|
+
let left = 0;
|
|
141
|
+
let right = taskIdOrder.value.length;
|
|
142
|
+
while (left < right) {
|
|
143
|
+
const mid = Math.floor((left + right) / 2);
|
|
144
|
+
if (sortTaskIds(id, taskIdOrder.value[mid]) < 0) {
|
|
145
|
+
right = mid;
|
|
146
|
+
} else {
|
|
147
|
+
left = mid + 1;
|
|
132
148
|
}
|
|
133
149
|
}
|
|
134
|
-
taskIdOrder.value.splice(
|
|
150
|
+
taskIdOrder.value.splice(left, 0, id);
|
|
135
151
|
}
|
|
136
152
|
}
|
|
137
153
|
}
|
|
138
154
|
}
|
|
139
|
-
|
|
155
|
+
|
|
156
|
+
rafId = requestAnimationFrame(updateTaskTimes);
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
rafId = requestAnimationFrame(updateTaskTimes);
|
|
160
|
+
|
|
161
|
+
// Pause updates when tab is hidden to save CPU
|
|
162
|
+
document.addEventListener('visibilitychange', () => {
|
|
163
|
+
if (document.hidden) {
|
|
164
|
+
if (rafId) {
|
|
165
|
+
cancelAnimationFrame(rafId);
|
|
166
|
+
rafId = null;
|
|
167
|
+
}
|
|
168
|
+
} else {
|
|
169
|
+
if (!rafId) {
|
|
170
|
+
lastTimeUpdate = 0;
|
|
171
|
+
lastSyncCheck = 0;
|
|
172
|
+
rafId = requestAnimationFrame(updateTaskTimes);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
});
|
|
140
176
|
|
|
141
177
|
connection.init("/api/updates?type=tasks");
|
|
142
178
|
|
|
@@ -155,7 +191,6 @@ export const useUIStore = defineStore("ui", () => {
|
|
|
155
191
|
document.body.style.top = `-${scrollY}px`;
|
|
156
192
|
document.body.style.width = "100%";
|
|
157
193
|
document.body.style.height = "100%";
|
|
158
|
-
document.body.style.left = "0"; // Add left positioning
|
|
159
194
|
|
|
160
195
|
// iOS specific properties
|
|
161
196
|
document.body.style.overflow = "hidden";
|
|
@@ -372,7 +407,7 @@ export const useUIStore = defineStore("ui", () => {
|
|
|
372
407
|
};
|
|
373
408
|
|
|
374
409
|
const startSpinner = (msg) => {
|
|
375
|
-
if (router.currentRoute.value.name == "login"
|
|
410
|
+
if (router.currentRoute.value.name == "login") return;
|
|
376
411
|
showSpinner.value = true;
|
|
377
412
|
spinnerMessage.value = msg;
|
|
378
413
|
preventScroll();
|
|
@@ -421,10 +456,6 @@ export const useUIStore = defineStore("ui", () => {
|
|
|
421
456
|
reverseTasks,
|
|
422
457
|
|
|
423
458
|
// refresh
|
|
424
|
-
startPoint,
|
|
425
|
-
pullChange,
|
|
426
|
-
setStartPoint: (point) => (startPoint.value = point),
|
|
427
|
-
setPullChange: () => (pullChange.value = length),
|
|
428
459
|
tasks,
|
|
429
460
|
|
|
430
461
|
// top main checkbox
|
|
@@ -472,14 +503,6 @@ export const useUIStore = defineStore("ui", () => {
|
|
|
472
503
|
const selectedTasks = getSelectedTasks();
|
|
473
504
|
for (const value of Object.values(selectedTasks)) connection.sendDeleteTask(value.taskId);
|
|
474
505
|
},
|
|
475
|
-
foldTasks: () => {
|
|
476
|
-
const selectedTasks = getSelectedTasks();
|
|
477
|
-
for (const key of Object.keys(selectedTasks)) tasks.value[key].isExpanded = false;
|
|
478
|
-
},
|
|
479
|
-
expandTasks: () => {
|
|
480
|
-
const selectedTasks = getSelectedTasks();
|
|
481
|
-
for (const key of Object.keys(selectedTasks)) tasks.value[key].isExpanded = true;
|
|
482
|
-
},
|
|
483
506
|
startTasks: () => {
|
|
484
507
|
const selectedTasks = getSelectedTasks();
|
|
485
508
|
for (const value of Object.values(selectedTasks)) if (!value.active) connection.sendStartTask(value.taskId);
|
package/src/views/Accounts.vue
CHANGED
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
<button
|
|
14
14
|
:disabled="ui.disabledButtons['create-accounts']"
|
|
15
15
|
@click="ui.toggleModal('account-creator', true)"
|
|
16
|
-
class="smooth-hover"
|
|
16
|
+
class="smooth-hover"
|
|
17
|
+
aria-label="Create accounts">
|
|
17
18
|
<PlayIcon class="w-4 h-4" />
|
|
18
19
|
</button>
|
|
19
20
|
</li>
|
|
@@ -21,7 +22,8 @@
|
|
|
21
22
|
<button
|
|
22
23
|
:disabled="ui.disabledButtons['add-accounts']"
|
|
23
24
|
@click="ui.toggleModal('create-account', true)"
|
|
24
|
-
class="smooth-hover"
|
|
25
|
+
class="smooth-hover"
|
|
26
|
+
aria-label="Add account">
|
|
25
27
|
<PlusIcon class="w-4 h-4" />
|
|
26
28
|
</button>
|
|
27
29
|
</li>
|
|
@@ -38,6 +40,7 @@
|
|
|
38
40
|
<input
|
|
39
41
|
class="h-10 w-44 text-white text-sm p-2 bg-dark-500 flex items-center relative"
|
|
40
42
|
placeholder="Search Email"
|
|
43
|
+
aria-label="Search email"
|
|
41
44
|
autocomplete="new-password"
|
|
42
45
|
data-dashlane-rid=""
|
|
43
46
|
data-dashlane-label=""
|
|
@@ -64,7 +67,7 @@
|
|
|
64
67
|
</div>
|
|
65
68
|
<button
|
|
66
69
|
:disabled="ui.disabledButtons['create-accounts']"
|
|
67
|
-
class="bg-dark-400 disabled:opacity-70 smooth-hover border border-dark-650 hover:border-dark-700 w-44 flex text-white text-xs font-medium justify-center items-center rounded-md ml-auto h-10"
|
|
70
|
+
class="bg-dark-400 disabled:opacity-70 smooth-hover border border-dark-650 hover:border-dark-700 btn-focus-ring w-44 flex text-white text-xs font-medium justify-center items-center rounded-md ml-auto h-10"
|
|
68
71
|
@click="ui.toggleModal('account-creator')">
|
|
69
72
|
Create Accounts
|
|
70
73
|
<PlayIcon class="ml-2" />
|
|
@@ -72,7 +75,7 @@
|
|
|
72
75
|
|
|
73
76
|
<button
|
|
74
77
|
:disabled="ui.disabledButtons['add-accounts']"
|
|
75
|
-
class="bg-dark-400 disabled:opacity-70 smooth-hover border border-dark-650 hover:border-dark-700 w-44 flex text-white text-xs font-medium justify-center items-center rounded-md ml-auto h-10"
|
|
78
|
+
class="bg-dark-400 disabled:opacity-70 smooth-hover border border-dark-650 hover:border-dark-700 btn-focus-ring w-44 flex text-white text-xs font-medium justify-center items-center rounded-md ml-auto h-10"
|
|
76
79
|
@click="ui.toggleModal('create-account')">
|
|
77
80
|
Add Account
|
|
78
81
|
<PlusIcon class="ml-2" />
|
|
@@ -81,7 +84,7 @@
|
|
|
81
84
|
</div>
|
|
82
85
|
|
|
83
86
|
<!-- Tasks (Table) -->
|
|
84
|
-
<AccountView :accounts="processedTasks"
|
|
87
|
+
<AccountView :accounts="processedTasks" />
|
|
85
88
|
|
|
86
89
|
<!-- Modal -->
|
|
87
90
|
<transition-group name="fade">
|
|
@@ -90,27 +93,9 @@
|
|
|
90
93
|
</transition-group>
|
|
91
94
|
</div>
|
|
92
95
|
</template>
|
|
93
|
-
<style lang="scss" scoped>
|
|
94
|
-
/* Page buttons styling - match Tasks page */
|
|
95
|
-
button.bg-dark-400 {
|
|
96
|
-
&:active,
|
|
97
|
-
&:focus {
|
|
98
|
-
outline: 1px solid oklch(0.72 0.15 145);
|
|
99
|
-
outline-offset: 0;
|
|
100
|
-
border-color: oklch(0.72 0.15 145) !important;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
.max-h-big-acc {
|
|
105
|
-
max-height: calc(100vh - 14rem);
|
|
106
|
-
overflow: auto;
|
|
107
|
-
}
|
|
108
|
-
</style>
|
|
109
96
|
<script setup>
|
|
110
|
-
import { computed, watch, ref } from "vue";
|
|
97
|
+
import { computed, defineAsyncComponent, watch, ref } from "vue";
|
|
111
98
|
import AccountView from "@/components/Editors/Account/AccountView.vue";
|
|
112
|
-
import AccountCreator from "@/components/Editors/Account/AccountCreator.vue";
|
|
113
|
-
import CreateAccount from "@/components/Editors/Account/CreateAccount.vue";
|
|
114
99
|
import { useUIStore } from "@/stores/ui";
|
|
115
100
|
import { PlusIcon, PlayIcon, MailIcon } from "@/components/icons";
|
|
116
101
|
import Dropdown from "@/components/ui/controls/atomic/Dropdown.vue";
|
|
@@ -118,6 +103,10 @@ import TagToggle from "@/components/Editors/TagToggle.vue";
|
|
|
118
103
|
import Switch from "@/components/ui/controls/atomic/Switch.vue";
|
|
119
104
|
import EyeToggle from "@/components/ui/controls/EyeToggle.vue";
|
|
120
105
|
|
|
106
|
+
// Lazy-loaded modal components
|
|
107
|
+
const AccountCreator = defineAsyncComponent(() => import("@/components/Editors/Account/AccountCreator.vue"));
|
|
108
|
+
const CreateAccount = defineAsyncComponent(() => import("@/components/Editors/Account/CreateAccount.vue"));
|
|
109
|
+
|
|
121
110
|
const ui = useUIStore();
|
|
122
111
|
const activeModal = computed(() => ui.activeModal);
|
|
123
112
|
const allTags = ref([]);
|