@necrolab/dashboard 0.4.61 → 0.4.208
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/.prettierrc +1 -27
- package/.vscode/extensions.json +1 -1
- package/README.md +79 -43
- package/backend/api.js +48 -40
- package/backend/auth.js +3 -3
- package/backend/batching.js +1 -1
- package/backend/endpoints.js +77 -13
- package/backend/index.js +2 -2
- package/backend/mock-data.js +38 -29
- package/backend/mock-src/classes/logger.js +8 -8
- package/backend/mock-src/classes/utils.js +3 -7
- package/backend/mock-src/database.js +0 -0
- package/backend/mock-src/ticketmaster.js +79 -79
- package/backend/validator.js +2 -2
- package/config/configs.json +3 -2
- package/config/filter.json +3 -2
- package/index.html +10 -81
- package/index.js +1 -1
- package/package.json +25 -40
- package/postcss.config.js +1 -1
- package/postinstall.js +17 -98
- package/public/android-chrome-192x192.png +0 -0
- package/public/android-chrome-512x512.png +0 -0
- package/public/apple-touch-icon.png +0 -0
- package/public/favicon-16x16.png +0 -0
- package/public/favicon-32x32.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/manifest.json +7 -12
- package/public/sw.js +2 -0
- package/public/workbox-49fdaf31.js +2 -0
- package/public/workbox-49fdaf31.js.map +1 -0
- package/public/workbox-88575b92.js +2 -0
- package/public/workbox-88575b92.js.map +1 -0
- package/public/workbox-a67a7b11.js +2 -0
- package/public/workbox-a67a7b11.js.map +1 -0
- package/public/workbox-d4314735.js +2 -0
- package/public/workbox-d4314735.js.map +1 -0
- package/public/workbox-e0f89ef3.js +2 -0
- package/public/workbox-e0f89ef3.js.map +1 -0
- package/run +9 -176
- package/src/App.vue +85 -498
- package/src/assets/css/_input.scss +99 -144
- package/src/assets/css/main.scss +99 -450
- package/src/assets/img/background.svg +2 -2
- package/src/assets/img/logo_icon.png +0 -0
- package/src/components/Auth/LoginForm.vue +11 -62
- package/src/components/Editors/Account/Account.vue +40 -116
- package/src/components/Editors/Account/AccountCreator.vue +39 -88
- package/src/components/Editors/Account/AccountView.vue +34 -102
- package/src/components/Editors/Account/CreateAccount.vue +32 -80
- package/src/components/Editors/Profile/CreateProfile.vue +83 -269
- package/src/components/Editors/Profile/Profile.vue +47 -132
- package/src/components/Editors/Profile/ProfileCountryChooser.vue +20 -82
- package/src/components/Editors/Profile/ProfileView.vue +34 -91
- package/src/components/Editors/TagLabel.vue +6 -67
- package/src/components/Filter/Filter.vue +72 -289
- package/src/components/Filter/FilterPreview.vue +30 -171
- package/src/components/Filter/PriceSortToggle.vue +4 -74
- package/src/components/Table/Header.vue +1 -1
- package/src/components/Table/Row.vue +1 -1
- package/src/components/Table/Table.vue +2 -19
- package/src/components/Tasks/CheckStock.vue +13 -28
- package/src/components/Tasks/Controls/DesktopControls.vue +17 -17
- package/src/components/Tasks/Controls/MobileControls.vue +45 -8
- package/src/components/Tasks/CreateTaskAXS.vue +73 -79
- package/src/components/Tasks/CreateTaskTM.vue +142 -94
- package/src/components/Tasks/MassEdit.vue +7 -9
- package/src/components/Tasks/QuickSettings.vue +55 -169
- package/src/components/Tasks/ScrapeVenue.vue +4 -7
- package/src/components/Tasks/Stats.vue +23 -52
- package/src/components/Tasks/Task.vue +136 -378
- package/src/components/Tasks/TaskView.vue +47 -107
- package/src/components/Tasks/Utilities.vue +6 -5
- package/src/components/icons/Bag.vue +1 -1
- package/src/components/icons/Loyalty.vue +1 -1
- package/src/components/icons/Mail.vue +2 -2
- package/src/components/icons/Play.vue +2 -2
- package/src/components/icons/Reload.vue +5 -4
- package/src/components/icons/Sandclock.vue +2 -2
- package/src/components/icons/Stadium.vue +1 -1
- package/src/components/icons/index.js +1 -24
- package/src/components/ui/Modal.vue +13 -105
- package/src/components/ui/Navbar.vue +38 -171
- package/src/components/ui/ReconnectIndicator.vue +55 -351
- package/src/components/ui/Splash.vue +35 -5
- package/src/components/ui/controls/CountryChooser.vue +62 -200
- package/src/components/ui/controls/atomic/Checkbox.vue +10 -119
- package/src/components/ui/controls/atomic/Dropdown.vue +39 -208
- package/src/components/ui/controls/atomic/MultiDropdown.vue +37 -300
- package/src/libs/Filter.js +170 -200
- package/src/registerServiceWorker.js +1 -1
- package/src/stores/connection.js +53 -51
- package/src/stores/logger.js +3 -11
- package/src/stores/sampleData.js +235 -207
- package/src/stores/ui.js +44 -112
- package/src/stores/utils.js +6 -90
- package/src/views/Accounts.vue +35 -44
- package/src/views/Console.vue +90 -341
- package/src/views/Editor.vue +123 -1176
- package/src/views/FilterBuilder.vue +251 -607
- package/src/views/Login.vue +14 -76
- package/src/views/Profiles.vue +25 -44
- package/src/views/Tasks.vue +100 -187
- package/static/offline.html +50 -192
- package/tailwind.config.js +26 -104
- package/vite.config.js +16 -73
- package/vue.config.js +32 -0
- package/workbox-config.js +11 -0
- package/artwork/image.png +0 -0
- package/dev-server.js +0 -136
- package/exit +0 -209
- package/jsconfig.json +0 -16
- package/src/assets/css/_utilities.scss +0 -388
- package/src/assets/img/background.svg.backup +0 -11
- package/src/components/icons/Check.vue +0 -5
- package/src/components/icons/Close.vue +0 -21
- package/src/components/icons/CloseX.vue +0 -5
- package/src/components/icons/Key.vue +0 -21
- package/src/components/icons/Pencil.vue +0 -21
- package/src/components/icons/Profile.vue +0 -18
- package/src/components/icons/Sell.vue +0 -21
- package/src/components/icons/Spinner.vue +0 -42
- package/src/components/icons/SquareCheck.vue +0 -18
- package/src/components/icons/SquareUncheck.vue +0 -18
- package/src/components/icons/Wildcard.vue +0 -18
- package/src/components/ui/controls/atomic/LoadingButton.vue +0 -45
- package/src/composables/useClickOutside.js +0 -21
- package/src/composables/useDropdownPosition.js +0 -174
- package/src/types/index.js +0 -41
- package/src/utils/debug.js +0 -1
- package/switch-branch.sh +0 -41
- package/workbox-config.cjs +0 -63
- /package/src/assets/img/{logo_icon-old.png → logo_icon_2.png} +0 -0
|
@@ -1,125 +1,144 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<Row
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
padding: 0 !important;
|
|
10
|
-
margin: 0 !important;
|
|
11
|
-
color: #c9cad1 !important;
|
|
12
|
-
font-size: 11px !important;
|
|
13
|
-
font-weight: 600 !important;
|
|
14
|
-
letter-spacing: 0.4px !important;
|
|
15
|
-
">
|
|
2
|
+
<Row
|
|
3
|
+
class="relative text-white"
|
|
4
|
+
@click="ui.setOpenContextMenu('')"
|
|
5
|
+
@click.right.prevent="ui.setOpenContextMenu('')"
|
|
6
|
+
>
|
|
7
|
+
<div class="block md:hidden absolute left-1 top-0">
|
|
8
|
+
<h4 class="text-xs task-id text-white">
|
|
16
9
|
{{ props.task.taskId }}
|
|
17
10
|
</h4>
|
|
18
11
|
</div>
|
|
19
|
-
<div class="col-span-1
|
|
12
|
+
<div class="col-span-1 lg:col-span-2 flex">
|
|
20
13
|
<Checkbox
|
|
21
|
-
class="ml-
|
|
14
|
+
class="ml-0 mr-4"
|
|
22
15
|
:toggled="props.task.selected"
|
|
23
|
-
@valueUpdate="ui.toggleTaskSelected(props.task.taskId)"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@click="copy(props.task.eventId)">
|
|
16
|
+
@valueUpdate="ui.toggleTaskSelected(props.task.taskId)"
|
|
17
|
+
/>
|
|
18
|
+
<h4 class="task-id-alt mx-auto hidden md:block text-white" @click="copy(props.task.eventId)">
|
|
27
19
|
{{ props.task.eventId }}
|
|
28
20
|
</h4>
|
|
29
21
|
</div>
|
|
22
|
+
<div class="col-span-2 hidden md:block">
|
|
23
|
+
<h4 class="text-white">{{ props.task.quantity }}</h4>
|
|
24
|
+
</div>
|
|
30
25
|
<div class="col-span-2">
|
|
31
26
|
<h4 class="text-white">
|
|
32
27
|
<span v-if="!props.task.reservedTicketsList">-</span>
|
|
33
28
|
<div v-else>
|
|
34
|
-
<div v-for="l in props.task.reservedTicketsList.split('
|
|
29
|
+
<div v-for="l in props.task.reservedTicketsList.split(' | ')" :key="l">
|
|
35
30
|
<span v-if="!!l.trim()">{{ l.trim() }}</span>
|
|
36
31
|
</div>
|
|
37
32
|
</div>
|
|
38
33
|
<span
|
|
39
34
|
class="ml-1 font-bold"
|
|
40
|
-
:class="
|
|
41
|
-
'
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
35
|
+
:class="[
|
|
36
|
+
props.task._timeLeftString == '00:00' || props.task._timeLeftString == 'No Cartholds'
|
|
37
|
+
? 'text-red-400'
|
|
38
|
+
: ''
|
|
39
|
+
]"
|
|
40
|
+
>{{ props.task._timeLeftString !== "00:00" ? props.task._timeLeftString : "Expired" }}</span
|
|
41
|
+
>
|
|
46
42
|
</h4>
|
|
47
43
|
</div>
|
|
48
|
-
<div class="col-span-
|
|
49
|
-
<div class="
|
|
44
|
+
<div class="col-span-6 md:col-span-4 lg:col-span-3 text-center justify-center">
|
|
45
|
+
<div class="flex md:gap-x-2 rounded-2xl w-fit shadow-3xl mx-auto items-center justify-center bg-dark-600">
|
|
46
|
+
<!-- Status circle -->
|
|
50
47
|
<div
|
|
51
|
-
class="
|
|
52
|
-
:class="
|
|
48
|
+
class="w-2 h-2 rounded-full mx-1 md:ml-3 ml-2"
|
|
49
|
+
:class="[
|
|
53
50
|
colorToClass(
|
|
54
51
|
props.task.active || props.task.status.toLowerCase() === 'idle'
|
|
55
52
|
? props.task.statusColor
|
|
56
53
|
: 'red'
|
|
57
54
|
)
|
|
58
|
-
"
|
|
59
|
-
|
|
55
|
+
]"
|
|
56
|
+
></div>
|
|
57
|
+
<!-- Actual status -->
|
|
58
|
+
<span class="font-bold text-sm p-1 md:mr-3 mr-2 truncate uppercase">{{
|
|
59
|
+
truncate(props.task.status, statusTruncateLength)
|
|
60
|
+
}}</span>
|
|
60
61
|
</div>
|
|
61
62
|
</div>
|
|
62
|
-
<div class="col-span-2 flex
|
|
63
|
-
<ul class="task-buttons">
|
|
63
|
+
<div class="col-span-2 flex">
|
|
64
|
+
<ul class="task-buttons bg-dark-600 px-1 lg:px-2 rounded-full shadow-3xl items-center">
|
|
64
65
|
<li>
|
|
65
|
-
<button v-if="task.active" @click="ui.stopTask(task.taskId)">
|
|
66
|
+
<button class="p-1" v-if="task.active" @click="ui.stopTask(task.taskId)">
|
|
66
67
|
<PauseIcon />
|
|
67
68
|
</button>
|
|
68
|
-
<button v-else @click="ui.startTask(task.taskId)">
|
|
69
|
+
<button class="p-1" v-else @click="ui.startTask(task.taskId)">
|
|
69
70
|
<PlayIcon />
|
|
70
71
|
</button>
|
|
71
72
|
</li>
|
|
72
|
-
<li v-if="task.status?.toLowerCase()
|
|
73
|
-
<button @click="ui.continueTask(task.taskId, 'autocheckout')">
|
|
73
|
+
<li v-if="task.status?.toLowerCase() === 'waiting' && props.task._timeLeftString !== '00:00'">
|
|
74
|
+
<button class="p-1" @click="ui.continueTask(task.taskId, 'autocheckout')">
|
|
74
75
|
<BagWhiteIcon />
|
|
75
76
|
</button>
|
|
76
77
|
</li>
|
|
77
|
-
<li v-if="task.status?.toLowerCase()
|
|
78
|
-
<button @click="ui.continueTask(task.taskId, 'change_reservation')">
|
|
78
|
+
<li v-if="task.status?.toLowerCase() === 'waiting'">
|
|
79
|
+
<button class="p-1" @click="ui.continueTask(task.taskId, 'change_reservation')">
|
|
79
80
|
<EditIcon />
|
|
80
81
|
</button>
|
|
81
82
|
</li>
|
|
82
83
|
<li>
|
|
83
|
-
<button @click="ui.deleteTask(task.taskId)">
|
|
84
|
+
<button class="p-1" @click="ui.deleteTask(task.taskId)">
|
|
84
85
|
<TrashIcon />
|
|
85
86
|
</button>
|
|
86
87
|
</li>
|
|
87
|
-
<li
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
<li
|
|
89
|
+
class="text-xl -mt-2"
|
|
90
|
+
@click.right.prevent="window.setTimeout(() => ui.setOpenContextMenu(task.taskId), 10)"
|
|
91
|
+
>
|
|
92
|
+
<!-- eslint-disable-next-line vue/no-mutating-props -->
|
|
93
|
+
<button class="p-1 mt-1" @click="props.task.isExpanded = !props.task.isExpanded">
|
|
94
|
+
<span>{{ props.task.isExpanded ? "-" : "+" }}</span>
|
|
90
95
|
</button>
|
|
91
96
|
</li>
|
|
92
97
|
</ul>
|
|
93
98
|
</div>
|
|
94
|
-
<div class="absolute right-5 top-4
|
|
95
|
-
<h4 class="
|
|
99
|
+
<div class="hidden md:block col-span-1 absolute right-5 top-4 lg:flex items-center justify-center">
|
|
100
|
+
<h4 class="text-center text-xs task-id text-white">
|
|
96
101
|
{{ props.task.taskId }}
|
|
97
102
|
</h4>
|
|
98
103
|
</div>
|
|
99
104
|
<transition name="fade">
|
|
100
105
|
<div
|
|
101
|
-
class="col-span-
|
|
102
|
-
v-if="props.task.isExpanded"
|
|
106
|
+
class="col-span-12 flex flex-wrap gap-x-4 gap-y-4 lg:gap-x-10 pt-8 pb-2 xl:justify-around will-change-auto"
|
|
107
|
+
v-if="props.task.isExpanded"
|
|
108
|
+
>
|
|
109
|
+
<!-- <div class="flex gap-x-2 " @click="copy(props.task.eventId)">
|
|
110
|
+
<StadiumWhiteIcon />
|
|
111
|
+
<h4 class="text-white">{{ props.task.eventId }}</h4>
|
|
112
|
+
</div>
|
|
113
|
+
<div class="flex gap-x-2 md:hidden">
|
|
114
|
+
<BagWhiteIcon />
|
|
115
|
+
<h4 class="text-white">{{ props.task.quantity }}</h4>
|
|
116
|
+
</div> -->
|
|
117
|
+
|
|
103
118
|
<!-- Details -->
|
|
104
119
|
<TaskLabel
|
|
105
120
|
class="md:hidden"
|
|
106
121
|
image="stadium_w"
|
|
107
122
|
:text="props.task.eventId"
|
|
108
|
-
@click="copy(props.task.eventId)"
|
|
123
|
+
@click="copy(props.task.eventId)"
|
|
124
|
+
/>
|
|
109
125
|
|
|
110
|
-
<TaskLabel class="md:hidden" image="bag_w" :text="
|
|
126
|
+
<TaskLabel class="md:hidden" image="bag_w" :text="props.task.quantity" />
|
|
111
127
|
<TaskLabel
|
|
112
128
|
v-if="props.task.email"
|
|
113
129
|
image="mail"
|
|
114
130
|
:text="props.task.email"
|
|
115
|
-
@click="copy(props.task.email)"
|
|
131
|
+
@click="copy(props.task.email)"
|
|
132
|
+
/>
|
|
116
133
|
<TaskLabel
|
|
117
134
|
v-if="props.task.password"
|
|
118
135
|
image="key"
|
|
119
136
|
:text="props.task.password"
|
|
120
|
-
@click="copy(props.task.password)"
|
|
137
|
+
@click="copy(props.task.password)"
|
|
138
|
+
/>
|
|
121
139
|
<TaskLabel v-if="!props.task.email && !props.task.password" image="mail" text="No account chosen yet" />
|
|
122
140
|
<TaskLabel v-if="props.task.profileName" image="profile" :text="props.task.profileName" />
|
|
141
|
+
<TaskLabel image="camera" :text="props.task.proxy" @click="copy(props.task.proxy)" />
|
|
123
142
|
<TaskLabel image="timer" :text="props.task.smartTimer ? 'On' : 'Off'" />
|
|
124
143
|
<TaskLabel image="groups" :text="props.task.loginAfterCart ? 'On' : 'Off'" />
|
|
125
144
|
<TaskLabel image="hand" :text="props.task.manual ? 'On' : 'Off'" />
|
|
@@ -132,359 +151,88 @@
|
|
|
132
151
|
v-if="props.task.presaleCode"
|
|
133
152
|
@click="copy(props.task.presaleCode)"
|
|
134
153
|
image="pencil"
|
|
135
|
-
:text="props.task.presaleCode"
|
|
154
|
+
:text="props.task.presaleCode"
|
|
155
|
+
/>
|
|
136
156
|
|
|
137
157
|
<TaskLabel v-if="props.task.eventName" image="stadium_w" :text="props.task.eventName" />
|
|
138
158
|
<TaskLabel v-if="props.task.eventVenue" image="stadium_w" :text="props.task.eventVenue" />
|
|
139
159
|
<TaskLabel
|
|
140
160
|
v-if="props.task.eventLocalDate"
|
|
141
161
|
image="stadium_w"
|
|
142
|
-
:text="formatDate(props.task.eventLocalDate)"
|
|
162
|
+
:text=" formatDate(props.task.eventLocalDate)"
|
|
163
|
+
/>
|
|
143
164
|
<TaskLabel image="sandclock" :text="props.task.agedAccount ? 'On' : 'Off'" />
|
|
144
165
|
</div>
|
|
145
166
|
</transition>
|
|
146
167
|
|
|
147
168
|
<!-- Context menu -->
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
169
|
+
|
|
170
|
+
<div class="absolute -bottom-1.5 right-5">
|
|
171
|
+
<transition name="fade">
|
|
172
|
+
<div
|
|
173
|
+
v-if="ui.openContextMenu === task.taskId"
|
|
174
|
+
class="bg-light-300 text-white w-42 grid grid-cols-1 p-1 gap-1 z-50 rounded-lg shadow-xl relative"
|
|
175
|
+
>
|
|
176
|
+
<!-- <span class="text-light-400">{{ task.taskId }}</span> -->
|
|
177
|
+
<button
|
|
178
|
+
class="bg-dark-500 smooth-hover p-1 rounded-lg"
|
|
179
|
+
@click="openInNewTab(`${ui.currentCountry.url}/event/${task.eventId}`)"
|
|
180
|
+
>
|
|
181
|
+
Open Event
|
|
182
|
+
</button>
|
|
183
|
+
<button
|
|
184
|
+
v-if="task.openerLink"
|
|
185
|
+
class="bg-dark-500 smooth-hover p-1 rounded-lg"
|
|
186
|
+
@click="openInBrowser(false)"
|
|
187
|
+
>
|
|
188
|
+
Open in browser (proxy)
|
|
189
|
+
</button>
|
|
190
|
+
<button
|
|
191
|
+
v-if="task.openerLink"
|
|
192
|
+
class="bg-dark-500 smooth-hover p-1 rounded-lg"
|
|
193
|
+
@click="openInBrowser(true)"
|
|
194
|
+
>
|
|
195
|
+
Open in browser (debug)
|
|
196
|
+
</button>
|
|
197
|
+
</div>
|
|
198
|
+
</transition>
|
|
199
|
+
</div>
|
|
165
200
|
</Row>
|
|
166
201
|
</template>
|
|
167
202
|
<style lang="scss" scoped>
|
|
168
203
|
h4 {
|
|
169
204
|
@apply text-center;
|
|
170
|
-
color: #e2e2e5;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
.status-container {
|
|
174
|
-
@apply mx-auto flex w-fit items-center justify-center rounded-lg border border-dark-650 bg-dark-500;
|
|
175
|
-
padding: 6px 12px;
|
|
176
|
-
gap: 6px;
|
|
177
|
-
transition: all 0.15s ease;
|
|
178
|
-
max-width: 100%;
|
|
179
|
-
|
|
180
|
-
&:hover {
|
|
181
|
-
@apply border-dark-700 bg-dark-550;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
.status-text {
|
|
186
|
-
@apply truncate text-sm font-medium uppercase;
|
|
187
|
-
color: #e2e2e5;
|
|
188
|
-
letter-spacing: 0.025em;
|
|
189
205
|
}
|
|
190
206
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
gap: 1px;
|
|
195
|
-
|
|
196
|
-
button {
|
|
197
|
-
@apply relative flex items-center justify-center rounded border-0 outline-0 transition-all duration-150;
|
|
198
|
-
background: transparent;
|
|
199
|
-
width: 22px;
|
|
200
|
-
height: 22px;
|
|
201
|
-
color: #cccccc;
|
|
202
|
-
border-radius: 4px;
|
|
203
|
-
|
|
204
|
-
&:hover {
|
|
205
|
-
background: rgba(255, 255, 255, 0.1);
|
|
206
|
-
color: #ffffff;
|
|
207
|
-
transform: scale(1.05);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
&:active {
|
|
211
|
-
background: rgba(255, 255, 255, 0.2);
|
|
212
|
-
transform: scale(0.95);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
svg,
|
|
217
|
-
img {
|
|
218
|
-
width: 12px;
|
|
219
|
-
height: 12px;
|
|
220
|
-
position: relative;
|
|
221
|
-
z-index: 1;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
svg path {
|
|
225
|
-
fill: currentColor;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
span {
|
|
229
|
-
@apply relative z-[1] text-xs font-medium;
|
|
207
|
+
@media (max-width: 1024px) {
|
|
208
|
+
h4 {
|
|
209
|
+
font-size: 10px !important;
|
|
230
210
|
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/* Tablet sizing - medium buttons */
|
|
234
|
-
@media (min-width: 768px) and (max-width: 1023px) {
|
|
235
211
|
.task-buttons {
|
|
236
|
-
|
|
237
|
-
gap: 1px;
|
|
238
|
-
border-radius: 6px;
|
|
239
|
-
|
|
240
|
-
button {
|
|
241
|
-
width: 26px;
|
|
242
|
-
height: 26px;
|
|
243
|
-
border-radius: 5px;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
svg,
|
|
247
|
-
img {
|
|
248
|
-
width: 14px;
|
|
249
|
-
height: 14px;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
span {
|
|
253
|
-
font-size: 0.75rem;
|
|
254
|
-
}
|
|
212
|
+
@apply gap-x-3;
|
|
255
213
|
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/* Desktop sizing - large buttons */
|
|
259
|
-
@media (min-width: 1024px) {
|
|
260
|
-
.task-buttons {
|
|
261
|
-
padding: 3px;
|
|
262
|
-
gap: 2px;
|
|
263
|
-
border-radius: 8px;
|
|
264
|
-
|
|
265
|
-
button {
|
|
266
|
-
width: 28px;
|
|
267
|
-
height: 28px;
|
|
268
|
-
border-radius: 6px;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
svg,
|
|
272
|
-
img {
|
|
273
|
-
width: 16px;
|
|
274
|
-
height: 16px;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
span {
|
|
278
|
-
font-size: 0.875rem;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/* Mobile portrait specific styling */
|
|
284
|
-
@media (max-width: 480px) and (orientation: portrait) {
|
|
285
|
-
/* Position adjustment for mobile taskId */
|
|
286
|
-
.block.md\\:hidden {
|
|
287
|
-
left: 4rem !important;
|
|
288
|
-
top: 0.25rem !important;
|
|
289
|
-
z-index: 1 !important;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/* Improved button layout for mobile portrait */
|
|
293
|
-
.task-buttons {
|
|
294
|
-
padding: 1px;
|
|
295
|
-
gap: 1px;
|
|
296
|
-
border-radius: 4px;
|
|
297
|
-
border: 1px solid #3d3e44 !important;
|
|
298
|
-
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) !important;
|
|
299
|
-
max-width: 100%;
|
|
300
|
-
min-height: 28px;
|
|
301
|
-
height: auto;
|
|
302
|
-
flex-wrap: wrap;
|
|
303
|
-
justify-content: center;
|
|
304
|
-
align-items: center;
|
|
305
|
-
background: #2e2f34;
|
|
306
|
-
|
|
307
|
-
button {
|
|
308
|
-
width: 20px;
|
|
309
|
-
height: 20px;
|
|
310
|
-
border-radius: 3px;
|
|
311
|
-
min-width: 20px;
|
|
312
|
-
border: none !important;
|
|
313
|
-
flex-shrink: 0;
|
|
314
|
-
margin: 0.5px;
|
|
315
|
-
background: transparent;
|
|
316
|
-
|
|
317
|
-
&:hover {
|
|
318
|
-
background: rgba(255, 255, 255, 0.1);
|
|
319
|
-
transform: scale(1.05);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
&:active {
|
|
323
|
-
background: rgba(255, 255, 255, 0.15);
|
|
324
|
-
transform: scale(0.95);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
svg,
|
|
329
|
-
img {
|
|
330
|
-
width: 10px;
|
|
331
|
-
height: 10px;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
span {
|
|
335
|
-
font-size: 0.7rem;
|
|
336
|
-
line-height: 1;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
/* Improved list item layout */
|
|
340
|
-
li {
|
|
341
|
-
display: flex;
|
|
342
|
-
margin: 0;
|
|
343
|
-
padding: 0;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
/* Make the actions column more flexible */
|
|
348
|
-
.col-span-2.lg\\:col-span-3 {
|
|
349
|
-
min-width: 0;
|
|
350
|
-
flex-shrink: 0;
|
|
351
|
-
display: flex;
|
|
352
|
-
align-items: center;
|
|
353
|
-
justify-content: center;
|
|
354
|
-
padding: 0 2px;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/* Compact status container */
|
|
358
|
-
.status-container {
|
|
359
|
-
border: none !important;
|
|
360
|
-
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) !important;
|
|
361
|
-
padding: 2px 4px;
|
|
362
|
-
font-size: 0.7rem;
|
|
363
|
-
max-width: 100%;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
.status-text {
|
|
367
|
-
font-size: 0.65rem;
|
|
368
|
-
letter-spacing: 0;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
/* Reduce row height to accommodate smaller elements */
|
|
372
|
-
.task-row-container {
|
|
373
|
-
min-height: 45px !important;
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
.task-id {
|
|
378
|
-
font-size: 10px;
|
|
379
|
-
font-weight: 600;
|
|
380
|
-
letter-spacing: 0.5px;
|
|
381
|
-
margin: 0;
|
|
382
|
-
color: #a0a0a6;
|
|
383
|
-
background: rgba(46, 47, 52, 0.4);
|
|
384
|
-
padding: 2px 6px;
|
|
385
|
-
border-radius: 4px;
|
|
386
|
-
border: 1px solid #3d3e44;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
.task-event-id {
|
|
390
|
-
font-size: 11px;
|
|
391
|
-
font-weight: 500;
|
|
392
|
-
text-align: center;
|
|
393
|
-
color: #d0d0d3;
|
|
394
|
-
|
|
395
|
-
&:hover {
|
|
396
|
-
color: #ffffff;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
@media (max-width: 1024px) {
|
|
400
|
-
font-size: 10px;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
@media (max-width: 768px) {
|
|
404
|
-
font-size: 9px;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/* Responsive task styling */
|
|
409
|
-
@screen lg {
|
|
410
|
-
h4 {
|
|
411
|
-
font-size: 10px;
|
|
412
|
-
}
|
|
413
|
-
|
|
414
214
|
.task-id {
|
|
415
|
-
font-size:
|
|
215
|
+
font-size: 6px !important;
|
|
416
216
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
font-size: 10px;
|
|
217
|
+
.task-id-alt {
|
|
218
|
+
font-size: 7px !important;
|
|
420
219
|
}
|
|
421
220
|
}
|
|
422
221
|
</style>
|
|
423
|
-
|
|
424
222
|
<script setup>
|
|
425
|
-
/// <reference path="@/types/index.js" />
|
|
426
|
-
|
|
427
223
|
import { Row } from "@/components/Table";
|
|
428
224
|
import { PlayIcon, TrashIcon, BagWhiteIcon, PauseIcon, EditIcon } from "@/components/icons";
|
|
429
225
|
import Checkbox from "@/components/ui/controls/atomic/Checkbox.vue";
|
|
430
226
|
import { useUIStore } from "@/stores/ui";
|
|
431
227
|
import TaskLabel from "@/components/Tasks/TaskLabel.vue";
|
|
432
|
-
import {
|
|
228
|
+
import { ref } from "vue";
|
|
433
229
|
|
|
434
230
|
const ui = useUIStore();
|
|
435
231
|
|
|
436
|
-
/** @type {{ task: Task }} */
|
|
437
232
|
const props = defineProps({
|
|
438
233
|
task: { type: Object }
|
|
439
234
|
});
|
|
440
235
|
|
|
441
|
-
// Context menu positioning
|
|
442
|
-
const contextMenuPosition = ref({});
|
|
443
|
-
const contextMenuRef = ref(null);
|
|
444
|
-
|
|
445
|
-
// Handle right-click to position context menu
|
|
446
|
-
const handleRightClick = (event) => {
|
|
447
|
-
const menuWidth = 168; // w-42 = 10.5rem = 168px
|
|
448
|
-
const menuHeight = 200; // Approximate height
|
|
449
|
-
|
|
450
|
-
let x = event.clientX;
|
|
451
|
-
let y = event.clientY - 55;
|
|
452
|
-
|
|
453
|
-
// Prevent menu from going off screen
|
|
454
|
-
if (x + menuWidth > window.innerWidth) {
|
|
455
|
-
x = event.clientX - menuWidth; // Show to the left instead
|
|
456
|
-
}
|
|
457
|
-
if (y + menuHeight > window.innerHeight) {
|
|
458
|
-
y = event.clientY - menuHeight; // Show above instead
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
contextMenuPosition.value = {
|
|
462
|
-
left: `${x}px`,
|
|
463
|
-
top: `${y}px`
|
|
464
|
-
};
|
|
465
|
-
|
|
466
|
-
// Open the context menu for this task
|
|
467
|
-
ui.setOpenContextMenu(props.task.taskId);
|
|
468
|
-
|
|
469
|
-
// Add click outside listener after menu opens
|
|
470
|
-
nextTick(() => {
|
|
471
|
-
document.addEventListener("click", handleClickOutside);
|
|
472
|
-
});
|
|
473
|
-
};
|
|
474
|
-
|
|
475
|
-
// Handle clicking outside the context menu
|
|
476
|
-
const handleClickOutside = (event) => {
|
|
477
|
-
if (contextMenuRef.value && !contextMenuRef.value.contains(event.target)) {
|
|
478
|
-
ui.setOpenContextMenu("");
|
|
479
|
-
document.removeEventListener("click", handleClickOutside);
|
|
480
|
-
}
|
|
481
|
-
};
|
|
482
|
-
|
|
483
|
-
// Cleanup on unmount
|
|
484
|
-
onUnmounted(() => {
|
|
485
|
-
document.removeEventListener("click", handleClickOutside);
|
|
486
|
-
});
|
|
487
|
-
|
|
488
236
|
const copy = (txt) => {
|
|
489
237
|
if (!txt) return;
|
|
490
238
|
navigator.clipboard.writeText(txt);
|
|
@@ -500,29 +248,28 @@ const colorToClass = (color) => {
|
|
|
500
248
|
return colorMapping.get(color) || "bg-white";
|
|
501
249
|
};
|
|
502
250
|
|
|
251
|
+
const truncate = (text, after) => {
|
|
252
|
+
if (text?.length <= after || after === -1) return text;
|
|
253
|
+
return text?.substring(0, after) + "...";
|
|
254
|
+
};
|
|
255
|
+
|
|
503
256
|
const openInBrowser = (debug) => {
|
|
504
257
|
if (!props.task.openerLink) return;
|
|
505
258
|
ui.showSuccess(`Opening in browser ${debug ? "(debug)" : ""}`);
|
|
506
259
|
const input = props.task.openerLink;
|
|
507
|
-
const data = JSON.parse(atob(input.split("://")
|
|
260
|
+
const data = JSON.parse(atob(input.split("://")[1]));
|
|
508
261
|
data.config.debug = debug;
|
|
509
|
-
const out = "
|
|
262
|
+
const out = "russonoro://" + btoa(JSON.stringify(data));
|
|
510
263
|
openInNewTab(out);
|
|
511
264
|
};
|
|
512
265
|
|
|
513
266
|
const formatDate = (date) => {
|
|
514
|
-
if (!date) return "
|
|
267
|
+
if (!date) return "-";
|
|
515
268
|
const d = new Date(date);
|
|
516
|
-
|
|
517
|
-
const [year, month, day] = iso.substring(0, 10).split("-");
|
|
518
|
-
const time = iso.substring(11, 16);
|
|
519
|
-
const dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
520
|
-
const dayName = dayNames[d.getUTCDay()];
|
|
521
|
-
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
522
|
-
const monthName = monthNames[parseInt(month) - 1];
|
|
523
|
-
return `${dayName} ${monthName} ${parseInt(day)} ${year} ${time}`;
|
|
269
|
+
return `${d.toDateString()} ${d.toTimeString().split(":").slice(0, 2).join(":")}`;
|
|
524
270
|
};
|
|
525
271
|
|
|
272
|
+
|
|
526
273
|
const openInNewTab = (href) => {
|
|
527
274
|
if (!href) return;
|
|
528
275
|
ui.logger.Info("Opening", href);
|
|
@@ -532,4 +279,15 @@ const openInNewTab = (href) => {
|
|
|
532
279
|
href: href
|
|
533
280
|
}).click();
|
|
534
281
|
};
|
|
282
|
+
|
|
283
|
+
const getMaxStatusLength = (width) => {
|
|
284
|
+
if (width > 1279) return -1;
|
|
285
|
+
if (width > 767) return 25;
|
|
286
|
+
if (width > 639) return 30;
|
|
287
|
+
if (width > 540) return 18;
|
|
288
|
+
return 13;
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
let statusTruncateLength = ref(getMaxStatusLength(window.innerWidth));
|
|
292
|
+
window.addEventListener("resize", () => (statusTruncateLength.value = getMaxStatusLength(window.innerWidth)));
|
|
535
293
|
</script>
|