@necrolab/dashboard 0.5.12 → 0.5.13
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/.playwright-mcp/verification-accounts-desktop.png +0 -0
- package/.playwright-mcp/verification-tasks-desktop.png +0 -0
- package/.playwright-mcp/verification-tasks-mobile.png +0 -0
- package/README.md +21 -0
- package/docs/plans/2026-02-08-tailwind-consolidation-results.md +476 -0
- package/docs/plans/2026-02-08-tailwind-consolidation.md +2416 -0
- package/package.json +1 -1
- package/src/App.vue +2 -163
- package/src/assets/css/components/buttons.scss +43 -95
- package/src/assets/css/components/forms.scss +10 -28
- package/src/assets/css/components/search-groups.scss +80 -0
- package/src/assets/css/components/tables.scss +0 -8
- package/src/assets/css/main.scss +2 -43
- package/src/components/Editors/Account/Account.vue +14 -220
- package/src/components/Editors/Account/AccountCreator.vue +0 -4
- package/src/components/Editors/Account/AccountView.vue +0 -1
- package/src/components/Editors/Account/CreateAccount.vue +36 -107
- package/src/components/Editors/Profile/CreateProfile.vue +46 -135
- package/src/components/Editors/Profile/Profile.vue +10 -213
- package/src/components/Editors/Profile/ProfileView.vue +0 -1
- package/src/components/Filter/Filter.vue +14 -17
- package/src/components/Filter/FilterPreview.vue +0 -6
- package/src/components/Table/Row.vue +1 -1
- package/src/components/Table/Table.vue +2 -16
- package/src/components/Tasks/CreateTaskAXS.vue +45 -104
- package/src/components/Tasks/CreateTaskTM.vue +58 -96
- package/src/components/Tasks/Task.vue +22 -209
- package/src/components/Tasks/TaskView.vue +5 -4
- package/src/components/Tasks/ViewTask.vue +201 -214
- package/src/components/icons/Copy.vue +6 -0
- package/src/components/icons/index.js +3 -1
- package/src/components/ui/ActionButtonGroup.vue +70 -0
- package/src/components/ui/FormField.vue +74 -0
- package/src/components/ui/InfoRow.vue +98 -0
- package/src/components/ui/Modal.vue +6 -47
- package/src/components/ui/Navbar.vue +15 -43
- package/src/components/ui/ReconnectIndicator.vue +4 -4
- package/src/components/ui/SectionCard.vue +24 -0
- package/src/components/ui/Splash.vue +1 -6
- package/src/components/ui/StatusBadge.vue +37 -0
- package/src/components/ui/controls/CountryChooser.vue +14 -58
- package/src/components/ui/controls/atomic/Dropdown.vue +16 -24
- package/src/components/ui/controls/atomic/MultiDropdown.vue +7 -1
- package/src/components/ui/controls/atomic/Switch.vue +13 -29
- package/src/composables/useCopyToClipboard.js +25 -0
- package/src/composables/useRowSelection.js +48 -0
- package/src/views/Accounts.vue +0 -81
- package/src/views/Console.vue +4 -21
- package/src/views/Editor.vue +48 -138
- package/src/views/FilterBuilder.vue +0 -23
- package/src/views/Login.vue +14 -63
- package/src/views/Profiles.vue +0 -82
- package/src/views/Tasks.vue +3 -24
- package/tailwind.config.js +47 -5
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Row
|
|
3
|
-
class="relative grid-cols-10 gap-2 text-white lg:grid-cols-12"
|
|
3
|
+
class="relative grid-cols-10 gap-2 text-white lg:grid-cols-12 min-h-full"
|
|
4
4
|
@click="ui.setOpenContextMenu('')"
|
|
5
5
|
@dblclick="handleDoubleClick"
|
|
6
6
|
@touchstart="handleTouchStart"
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
@valueUpdate="ui.toggleTaskSelected(props.task.taskId)" />
|
|
13
13
|
<div
|
|
14
14
|
v-if="props.preferEventName && props.task.eventName"
|
|
15
|
-
class="event-details hidden
|
|
16
|
-
@click="copy(props.task.eventId)"
|
|
15
|
+
class="event-details hidden lg:flex flex-col gap-0.5 justify-center cursor-pointer"
|
|
16
|
+
@click="copy(props.task.eventId, 'Copied event ID')"
|
|
17
17
|
:title="`Event ID: ${props.task.eventId}`">
|
|
18
18
|
<div class="event-name text-white text-[11px] font-semibold leading-tight">
|
|
19
19
|
{{ props.task.eventName }}
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
</div>
|
|
45
45
|
<div
|
|
46
46
|
v-else
|
|
47
|
-
class="event-id-details hidden
|
|
48
|
-
@click="copy(props.task.eventId)">
|
|
47
|
+
class="event-id-details hidden lg:flex flex-col gap-0.5 justify-center cursor-pointer"
|
|
48
|
+
@click="copy(props.task.eventId, 'Copied event ID')">
|
|
49
49
|
<div class="event-id-row flex items-center gap-1 text-[11px] text-white font-semibold">
|
|
50
50
|
<svg class="event-icon" width="11" height="11" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24">
|
|
51
51
|
<path d="M9 11l3 3L22 4"></path>
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
</div>
|
|
100
100
|
</div>
|
|
101
101
|
<div class="col-span-2 flex lg:col-span-3 overflow-visible">
|
|
102
|
-
<
|
|
102
|
+
<ActionButtonGroup class="overflow-visible">
|
|
103
103
|
<li>
|
|
104
104
|
<button v-if="task.active" @click="ui.stopTask(task.taskId)">
|
|
105
105
|
<PauseIcon />
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
<EyeIcon />
|
|
129
129
|
</button>
|
|
130
130
|
</li>
|
|
131
|
-
</
|
|
131
|
+
</ActionButtonGroup>
|
|
132
132
|
</div>
|
|
133
133
|
<div class="absolute right-5 top-4 col-span-1 hidden items-center justify-center md:block lg:flex">
|
|
134
134
|
<h4 class="task-id text-center text-xs text-white">
|
|
@@ -178,20 +178,19 @@ h4 {
|
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
.event-icon {
|
|
181
|
-
min-
|
|
182
|
-
min-height: 10px
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
fill: none !important;
|
|
181
|
+
@apply min-w-[10px] flex-shrink-0;
|
|
182
|
+
min-height: 10px;
|
|
183
|
+
color: oklch(0.60 0 0);
|
|
184
|
+
stroke: oklch(0.60 0 0);
|
|
185
|
+
fill: none;
|
|
187
186
|
|
|
188
187
|
path,
|
|
189
188
|
rect,
|
|
190
189
|
line,
|
|
191
190
|
circle,
|
|
192
191
|
polyline {
|
|
193
|
-
stroke: oklch(0.60 0 0)
|
|
194
|
-
fill: none
|
|
192
|
+
stroke: oklch(0.60 0 0);
|
|
193
|
+
fill: none;
|
|
195
194
|
}
|
|
196
195
|
}
|
|
197
196
|
|
|
@@ -233,159 +232,11 @@ h4 {
|
|
|
233
232
|
}
|
|
234
233
|
}
|
|
235
234
|
|
|
236
|
-
.task-buttons {
|
|
237
|
-
@apply mx-auto flex items-center justify-center rounded;
|
|
238
|
-
background: oklch(0.2046 0 0);
|
|
239
|
-
border: 2px solid oklch(0.2809 0 0);
|
|
240
|
-
padding: 2px;
|
|
241
|
-
gap: 1px;
|
|
242
|
-
flex-shrink: 0;
|
|
243
|
-
overflow: visible;
|
|
244
|
-
|
|
245
|
-
button {
|
|
246
|
-
@apply relative flex items-center justify-center rounded border-0 outline-0 transition-all duration-150;
|
|
247
|
-
background: transparent;
|
|
248
|
-
width: 22px;
|
|
249
|
-
height: 22px;
|
|
250
|
-
color: oklch(0.90 0 0);
|
|
251
|
-
border-radius: 4px;
|
|
252
|
-
|
|
253
|
-
&:hover {
|
|
254
|
-
background: oklch(0.72 0.15 145 / 0.15);
|
|
255
|
-
color: oklch(1 0 0);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
&:active {
|
|
259
|
-
background: oklch(0.72 0.15 145 / 0.25);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
svg,
|
|
264
|
-
img {
|
|
265
|
-
width: 12px;
|
|
266
|
-
height: 12px;
|
|
267
|
-
position: relative;
|
|
268
|
-
z-index: 1;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
svg path {
|
|
272
|
-
fill: currentColor;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
span {
|
|
276
|
-
@apply relative z-[1] text-xs font-medium;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/* Tablet sizing - medium buttons */
|
|
281
|
-
@media (min-width: 768px) and (max-width: 1023px) {
|
|
282
|
-
.task-buttons {
|
|
283
|
-
padding: 2px;
|
|
284
|
-
gap: 1px;
|
|
285
|
-
border-radius: 6px;
|
|
286
|
-
|
|
287
|
-
button {
|
|
288
|
-
width: 26px;
|
|
289
|
-
height: 26px;
|
|
290
|
-
border-radius: 5px;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
svg,
|
|
294
|
-
img {
|
|
295
|
-
width: 14px;
|
|
296
|
-
height: 14px;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
span {
|
|
300
|
-
font-size: 0.75rem;
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/* Desktop sizing - large buttons */
|
|
306
|
-
@media (min-width: 1024px) {
|
|
307
|
-
.task-buttons {
|
|
308
|
-
padding: 3px;
|
|
309
|
-
gap: 2px;
|
|
310
|
-
border-radius: 8px;
|
|
311
|
-
|
|
312
|
-
button {
|
|
313
|
-
width: 28px;
|
|
314
|
-
height: 28px;
|
|
315
|
-
border-radius: 6px;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
svg,
|
|
319
|
-
img {
|
|
320
|
-
width: 16px;
|
|
321
|
-
height: 16px;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
span {
|
|
325
|
-
font-size: 0.875rem;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
|
|
330
235
|
/* Mobile specific styling - changed from 480px to 640px for earlier transition */
|
|
331
236
|
@media (max-width: 640px) {
|
|
332
237
|
/* Position adjustment for mobile taskId */
|
|
333
238
|
.block.md\\:hidden {
|
|
334
|
-
left
|
|
335
|
-
top: 0.25rem !important;
|
|
336
|
-
z-index: 1 !important;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
/* Improved button layout for mobile */
|
|
340
|
-
.task-buttons {
|
|
341
|
-
padding: 1px;
|
|
342
|
-
gap: 1px;
|
|
343
|
-
border-radius: 4px;
|
|
344
|
-
border: 2px solid oklch(0.2809 0 0) !important;
|
|
345
|
-
max-width: 100%;
|
|
346
|
-
min-height: 28px;
|
|
347
|
-
height: auto;
|
|
348
|
-
flex-wrap: wrap;
|
|
349
|
-
justify-content: center;
|
|
350
|
-
align-items: center;
|
|
351
|
-
background: oklch(0.2046 0 0);
|
|
352
|
-
|
|
353
|
-
button {
|
|
354
|
-
width: 20px;
|
|
355
|
-
height: 20px;
|
|
356
|
-
border-radius: 3px;
|
|
357
|
-
min-width: 20px;
|
|
358
|
-
border: none !important;
|
|
359
|
-
flex-shrink: 0;
|
|
360
|
-
margin: 0.5px;
|
|
361
|
-
background: transparent;
|
|
362
|
-
|
|
363
|
-
&:hover {
|
|
364
|
-
background: oklch(0.72 0.15 145 / 0.15);
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
&:active {
|
|
368
|
-
background: oklch(0.72 0.15 145 / 0.25);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
svg,
|
|
373
|
-
img {
|
|
374
|
-
width: 10px;
|
|
375
|
-
height: 10px;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
span {
|
|
379
|
-
font-size: 0.7rem;
|
|
380
|
-
line-height: 1;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/* Improved list item layout */
|
|
384
|
-
li {
|
|
385
|
-
display: flex;
|
|
386
|
-
margin: 0;
|
|
387
|
-
padding: 0;
|
|
388
|
-
}
|
|
239
|
+
@apply left-16 top-1 z-10;
|
|
389
240
|
}
|
|
390
241
|
|
|
391
242
|
/* Make the actions column more flexible */
|
|
@@ -400,8 +251,7 @@ h4 {
|
|
|
400
251
|
|
|
401
252
|
/* Compact status container */
|
|
402
253
|
.status-container {
|
|
403
|
-
border
|
|
404
|
-
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) !important;
|
|
254
|
+
@apply border-0 shadow-sm;
|
|
405
255
|
padding: 2px 4px;
|
|
406
256
|
font-size: 0.7rem;
|
|
407
257
|
max-width: 100%;
|
|
@@ -411,11 +261,6 @@ h4 {
|
|
|
411
261
|
font-size: 0.65rem;
|
|
412
262
|
letter-spacing: 0;
|
|
413
263
|
}
|
|
414
|
-
|
|
415
|
-
/* Reduce row height to accommodate smaller elements */
|
|
416
|
-
.task-row-container {
|
|
417
|
-
min-height: 45px !important;
|
|
418
|
-
}
|
|
419
264
|
}
|
|
420
265
|
|
|
421
266
|
.task-id {
|
|
@@ -471,12 +316,16 @@ h4 {
|
|
|
471
316
|
import { Row } from "@/components/Table";
|
|
472
317
|
import { PlayIcon, TrashIcon, BagWhiteIcon, PauseIcon, EditIcon, EyeIcon, StadiumIcon, TimerIcon } from "@/components/icons";
|
|
473
318
|
import Checkbox from "@/components/ui/controls/atomic/Checkbox.vue";
|
|
319
|
+
import ActionButtonGroup from "@/components/ui/ActionButtonGroup.vue";
|
|
474
320
|
import { useUIStore } from "@/stores/ui";
|
|
475
321
|
import TaskLabel from "@/components/Tasks/TaskLabel.vue";
|
|
476
322
|
import ViewTask from "@/components/Tasks/ViewTask.vue";
|
|
477
323
|
import { computed, ref, onMounted, onUnmounted, nextTick } from "vue";
|
|
324
|
+
import { useRowSelection } from "@/composables/useRowSelection";
|
|
325
|
+
import { useCopyToClipboard } from "@/composables/useCopyToClipboard";
|
|
478
326
|
|
|
479
327
|
const ui = useUIStore();
|
|
328
|
+
const { copy } = useCopyToClipboard();
|
|
480
329
|
|
|
481
330
|
/** @type {{ task: Task }} */
|
|
482
331
|
const props = defineProps({
|
|
@@ -508,40 +357,9 @@ const contextMenuPosition = ref({});
|
|
|
508
357
|
const contextMenuRef = ref(null);
|
|
509
358
|
|
|
510
359
|
// Double-click/tap selection
|
|
511
|
-
|
|
512
|
-
const DOUBLE_TAP_DELAY = 300; // ms
|
|
513
|
-
|
|
514
|
-
const handleDoubleClick = (event) => {
|
|
515
|
-
// Prevent if clicking on buttons or checkbox
|
|
516
|
-
if (event.target.closest('button') || event.target.closest('.checkbox')) {
|
|
517
|
-
return;
|
|
518
|
-
}
|
|
360
|
+
const { handleDoubleClick, handleTouchStart, handleTouchEnd } = useRowSelection(() => {
|
|
519
361
|
ui.toggleTaskSelected(props.task.taskId);
|
|
520
|
-
};
|
|
521
|
-
|
|
522
|
-
const handleTouchStart = (event) => {
|
|
523
|
-
// Store touch time for double-tap detection
|
|
524
|
-
const currentTime = Date.now();
|
|
525
|
-
const tapGap = currentTime - lastTapTime;
|
|
526
|
-
|
|
527
|
-
if (tapGap < DOUBLE_TAP_DELAY && tapGap > 0) {
|
|
528
|
-
// Double-tap detected
|
|
529
|
-
if (!event.target.closest('button') && !event.target.closest('.checkbox')) {
|
|
530
|
-
event.preventDefault(); // Prevent zoom
|
|
531
|
-
ui.toggleTaskSelected(props.task.taskId);
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
lastTapTime = currentTime;
|
|
536
|
-
};
|
|
537
|
-
|
|
538
|
-
const handleTouchEnd = (event) => {
|
|
539
|
-
// Prevent default to avoid potential zoom issues
|
|
540
|
-
// but only if not interacting with buttons/checkbox
|
|
541
|
-
if (event.target.closest('button') || event.target.closest('.checkbox')) {
|
|
542
|
-
return;
|
|
543
|
-
}
|
|
544
|
-
};
|
|
362
|
+
});
|
|
545
363
|
|
|
546
364
|
// Handle right-click to position context menu
|
|
547
365
|
const handleRightClick = (event) => {
|
|
@@ -586,11 +404,6 @@ onUnmounted(() => {
|
|
|
586
404
|
document.removeEventListener("click", handleClickOutside);
|
|
587
405
|
});
|
|
588
406
|
|
|
589
|
-
const copy = (txt) => {
|
|
590
|
-
if (!txt) return;
|
|
591
|
-
navigator.clipboard.writeText(txt);
|
|
592
|
-
ui.showSuccess("Copied text");
|
|
593
|
-
};
|
|
594
407
|
|
|
595
408
|
const openViewTaskModal = () => {
|
|
596
409
|
ui.selectedTaskForView = props.task;
|
|
@@ -78,9 +78,11 @@ h4 {
|
|
|
78
78
|
@apply bg-dark-550 !important;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
// Increase height when showing eventName to accommodate multi-line display
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
// Increase height when showing eventName to accommodate multi-line display (desktop only)
|
|
82
|
+
@media (min-width: 1024px) {
|
|
83
|
+
&:has(.event-details) {
|
|
84
|
+
min-height: 75px;
|
|
85
|
+
}
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
@media (max-width: 768px) {
|
|
@@ -94,7 +96,6 @@ h4 {
|
|
|
94
96
|
|
|
95
97
|
.empty-state {
|
|
96
98
|
@apply bg-dark-400;
|
|
97
|
-
color: #969696;
|
|
98
99
|
font-size: 14px;
|
|
99
100
|
font-weight: 500;
|
|
100
101
|
}
|