@necrolab/dashboard 0.4.3
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/.claude/settings.local.json +45 -0
- package/.eslintrc.js +24 -0
- package/.prettierignore +1 -0
- package/.prettierrc +10 -0
- package/.vscode/extensions.json +3 -0
- package/ICONS.md +21 -0
- package/README.md +65 -0
- package/backend/api.js +430 -0
- package/backend/auth.js +62 -0
- package/backend/batching.js +43 -0
- package/backend/endpoints.js +343 -0
- package/backend/index.js +23 -0
- package/backend/mock-data.js +66 -0
- package/backend/mock-src/classes/logger.js +112 -0
- package/backend/mock-src/classes/utils.js +42 -0
- package/backend/mock-src/ticketmaster.js +92 -0
- package/backend/validator.js +62 -0
- package/config/configs.json +20 -0
- package/config/filter.json +3 -0
- package/config/presale.csv +3 -0
- package/config/proxies.txt +6 -0
- package/config/used-codes.json +4 -0
- package/index.html +114 -0
- package/index.js +2 -0
- package/jsconfig.json +16 -0
- package/package.json +48 -0
- package/postcss.config.js +6 -0
- package/postinstall.js +9 -0
- 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/flags/ae.svg +1 -0
- package/public/flags/at.svg +1 -0
- package/public/flags/au.svg +1 -0
- package/public/flags/be.svg +1 -0
- package/public/flags/ch.svg +1 -0
- package/public/flags/cz.svg +1 -0
- package/public/flags/de.svg +1 -0
- package/public/flags/dk.svg +1 -0
- package/public/flags/es.svg +1 -0
- package/public/flags/nl.svg +1 -0
- package/public/flags/no.svg +1 -0
- package/public/flags/nz.svg +1 -0
- package/public/flags/pl.svg +1 -0
- package/public/flags/se.svg +1 -0
- package/public/flags/uk.svg +1 -0
- package/public/flags/us.svg +1 -0
- package/public/img/award.svg +3 -0
- package/public/img/background.svg +14 -0
- package/public/img/bag_w.svg +12 -0
- package/public/img/banks/amex.svg +4 -0
- package/public/img/banks/mastercard.svg +4 -0
- package/public/img/banks/visa.svg +4 -0
- package/public/img/camera.svg +3 -0
- package/public/img/close.svg +3 -0
- package/public/img/controls/disable.svg +5 -0
- package/public/img/controls/enable.svg +5 -0
- package/public/img/groups.svg +3 -0
- package/public/img/hand.svg +3 -0
- package/public/img/key.svg +3 -0
- package/public/img/logo.png +0 -0
- package/public/img/logo_icon.png +0 -0
- package/public/img/logo_icon_2.png +0 -0
- package/public/img/logo_trans.png +0 -0
- package/public/img/loyalty.svg +3 -0
- package/public/img/mail.svg +3 -0
- package/public/img/pencil.svg +3 -0
- package/public/img/profile.svg +4 -0
- package/public/img/reload.svg +3 -0
- package/public/img/sandclock.svg +25 -0
- package/public/img/save.svg +5 -0
- package/public/img/savings.svg +3 -0
- package/public/img/scanner.svg +3 -0
- package/public/img/sell.svg +3 -0
- package/public/img/shield.svg +3 -0
- package/public/img/ski.svg +3 -0
- package/public/img/stadium.svg +8 -0
- package/public/img/stadium_w.svg +8 -0
- package/public/img/timer.svg +3 -0
- package/public/manifest.json +27 -0
- package/public/robots.txt +2 -0
- package/run +10 -0
- package/src/App.vue +307 -0
- package/src/assets/css/_input.scss +197 -0
- package/src/assets/css/main.scss +269 -0
- package/src/assets/css/tailwind.css +3 -0
- package/src/assets/img/award.svg +3 -0
- package/src/assets/img/background.svg +11 -0
- package/src/assets/img/camera.svg +3 -0
- package/src/assets/img/close.svg +3 -0
- package/src/assets/img/eyes/closed.svg +13 -0
- package/src/assets/img/eyes/open.svg +12 -0
- package/src/assets/img/groups.svg +3 -0
- package/src/assets/img/hand.svg +3 -0
- package/src/assets/img/key.svg +3 -0
- package/src/assets/img/logo.png +0 -0
- package/src/assets/img/logo_icon.png +0 -0
- package/src/assets/img/logo_icon_2.png +0 -0
- package/src/assets/img/logo_trans.png +0 -0
- package/src/assets/img/loyalty.svg +3 -0
- package/src/assets/img/mail.svg +3 -0
- package/src/assets/img/pencil.svg +3 -0
- package/src/assets/img/reload.svg +3 -0
- package/src/assets/img/savings.svg +3 -0
- package/src/assets/img/scanner.svg +3 -0
- package/src/assets/img/sell.svg +3 -0
- package/src/assets/img/shield.svg +3 -0
- package/src/assets/img/ski.svg +3 -0
- package/src/assets/img/square_check.svg +5 -0
- package/src/assets/img/square_uncheck.svg +5 -0
- package/src/assets/img/stadium.svg +8 -0
- package/src/assets/img/timer.svg +3 -0
- package/src/assets/img/wildcard.svg +7 -0
- package/src/components/Auth/LoginForm.vue +48 -0
- package/src/components/Editors/Account/Account.vue +119 -0
- package/src/components/Editors/Account/AccountCreator.vue +147 -0
- package/src/components/Editors/Account/AccountView.vue +87 -0
- package/src/components/Editors/Account/CreateAccount.vue +106 -0
- package/src/components/Editors/Profile/CreateProfile.vue +321 -0
- package/src/components/Editors/Profile/Profile.vue +142 -0
- package/src/components/Editors/Profile/ProfileCountryChooser.vue +75 -0
- package/src/components/Editors/Profile/ProfileView.vue +96 -0
- package/src/components/Editors/TagLabel.vue +16 -0
- package/src/components/Editors/TagToggle.vue +41 -0
- package/src/components/Filter/Filter.vue +409 -0
- package/src/components/Filter/FilterPreview.vue +236 -0
- package/src/components/Filter/PriceSortToggle.vue +105 -0
- package/src/components/Table/Header.vue +5 -0
- package/src/components/Table/Row.vue +5 -0
- package/src/components/Table/Table.vue +14 -0
- package/src/components/Table/index.js +4 -0
- package/src/components/Tasks/CheckStock.vue +62 -0
- package/src/components/Tasks/Controls/DesktopControls.vue +73 -0
- package/src/components/Tasks/Controls/MobileControls.vue +32 -0
- package/src/components/Tasks/Controls/index.js +3 -0
- package/src/components/Tasks/CreateTaskAXS.vue +339 -0
- package/src/components/Tasks/CreateTaskTM.vue +459 -0
- package/src/components/Tasks/MassEdit.vue +50 -0
- package/src/components/Tasks/QuickSettings.vue +167 -0
- package/src/components/Tasks/ScrapeVenue.vue +42 -0
- package/src/components/Tasks/Stats.vue +66 -0
- package/src/components/Tasks/Task.vue +296 -0
- package/src/components/Tasks/TaskLabel.vue +20 -0
- package/src/components/Tasks/TaskView.vue +126 -0
- package/src/components/Tasks/Utilities.vue +33 -0
- package/src/components/icons/Award.vue +8 -0
- package/src/components/icons/Bag.vue +8 -0
- package/src/components/icons/BagWhite.vue +8 -0
- package/src/components/icons/Box.vue +8 -0
- package/src/components/icons/Camera.vue +8 -0
- package/src/components/icons/Cart.vue +8 -0
- package/src/components/icons/Check.vue +5 -0
- package/src/components/icons/Checkmark.vue +11 -0
- package/src/components/icons/Click.vue +8 -0
- package/src/components/icons/Close.vue +21 -0
- package/src/components/icons/CloseX.vue +5 -0
- package/src/components/icons/Console.vue +13 -0
- package/src/components/icons/Down.vue +8 -0
- package/src/components/icons/Edit.vue +13 -0
- package/src/components/icons/Event.vue +8 -0
- package/src/components/icons/Expand.vue +8 -0
- package/src/components/icons/Filter.vue +13 -0
- package/src/components/icons/Gear.vue +8 -0
- package/src/components/icons/Group.vue +8 -0
- package/src/components/icons/Hand.vue +8 -0
- package/src/components/icons/Key.vue +21 -0
- package/src/components/icons/Logout.vue +13 -0
- package/src/components/icons/Loyalty.vue +8 -0
- package/src/components/icons/Mail.vue +8 -0
- package/src/components/icons/Menu.vue +8 -0
- package/src/components/icons/Pause.vue +5 -0
- package/src/components/icons/Pencil.vue +21 -0
- package/src/components/icons/Play.vue +8 -0
- package/src/components/icons/Plus.vue +8 -0
- package/src/components/icons/Profile.vue +18 -0
- package/src/components/icons/Reload.vue +7 -0
- package/src/components/icons/Sandclock.vue +33 -0
- package/src/components/icons/Savings.vue +8 -0
- package/src/components/icons/Scanner.vue +8 -0
- package/src/components/icons/Scrape.vue +8 -0
- package/src/components/icons/Sell.vue +21 -0
- package/src/components/icons/Shield.vue +8 -0
- package/src/components/icons/Shrink.vue +8 -0
- package/src/components/icons/Ski.vue +8 -0
- package/src/components/icons/Spinner.vue +42 -0
- package/src/components/icons/SquareCheck.vue +18 -0
- package/src/components/icons/SquareUncheck.vue +18 -0
- package/src/components/icons/Stadium.vue +13 -0
- package/src/components/icons/StadiumWhite.vue +13 -0
- package/src/components/icons/Status.vue +8 -0
- package/src/components/icons/Tag.vue +8 -0
- package/src/components/icons/Tasks.vue +13 -0
- package/src/components/icons/Ticket.vue +8 -0
- package/src/components/icons/Timer.vue +8 -0
- package/src/components/icons/Trash.vue +8 -0
- package/src/components/icons/Up.vue +10 -0
- package/src/components/icons/Wildcard.vue +18 -0
- package/src/components/icons/index.js +111 -0
- package/src/components/ui/Modal.vue +61 -0
- package/src/components/ui/Navbar.vue +207 -0
- package/src/components/ui/ReconnectIndicator.vue +90 -0
- package/src/components/ui/Splash.vue +24 -0
- package/src/components/ui/controls/CountryChooser.vue +87 -0
- package/src/components/ui/controls/EyeToggle.vue +11 -0
- package/src/components/ui/controls/atomic/Checkbox.vue +28 -0
- package/src/components/ui/controls/atomic/Dropdown.vue +138 -0
- package/src/components/ui/controls/atomic/LoadingButton.vue +45 -0
- package/src/components/ui/controls/atomic/MultiDropdown.vue +262 -0
- package/src/components/ui/controls/atomic/Switch.vue +84 -0
- package/src/libs/Filter.js +593 -0
- package/src/libs/ansii.js +565 -0
- package/src/libs/panzoom.js +1413 -0
- package/src/main.js +23 -0
- package/src/registerServiceWorker.js +32 -0
- package/src/router/index.js +65 -0
- package/src/stores/cities.json +1 -0
- package/src/stores/connection.js +399 -0
- package/src/stores/countries.js +88 -0
- package/src/stores/logger.js +103 -0
- package/src/stores/requests.js +88 -0
- package/src/stores/sampleData.js +1034 -0
- package/src/stores/ui.js +584 -0
- package/src/stores/utils.js +554 -0
- package/src/types/index.js +42 -0
- package/src/utils/debug.js +1 -0
- package/src/views/Accounts.vue +191 -0
- package/src/views/Console.vue +224 -0
- package/src/views/Editor.vue +785 -0
- package/src/views/FilterBuilder.vue +785 -0
- package/src/views/Login.vue +27 -0
- package/src/views/Profiles.vue +209 -0
- package/src/views/Tasks.vue +157 -0
- package/static/offline.html +184 -0
- package/tailwind.config.js +57 -0
- package/vite.config.js +63 -0
- package/vue.config.js +32 -0
- package/workbox-config.js +66 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<div class="flex-between pt-5 pb-2">
|
|
4
|
+
<!-- Heading -->
|
|
5
|
+
<div class="flex-center gap-4">
|
|
6
|
+
<MailIcon class="cursor-pointer smooth-hover text-white" />
|
|
7
|
+
<h4 class="text-heading">
|
|
8
|
+
Accounts
|
|
9
|
+
<span class="text-subheading pl-1">{{ ui.getSelectedAccounts().length }}</span>
|
|
10
|
+
</h4>
|
|
11
|
+
</div>
|
|
12
|
+
<ul class="mobile-icons">
|
|
13
|
+
<li>
|
|
14
|
+
<EyeToggle v-model="privacy" />
|
|
15
|
+
</li>
|
|
16
|
+
<li>
|
|
17
|
+
<button
|
|
18
|
+
:disabled="ui.disabledButtons['create-accounts']"
|
|
19
|
+
@click="ui.toggleModal('account-creator', true)"
|
|
20
|
+
class="smooth-hover"
|
|
21
|
+
>
|
|
22
|
+
<PlayIcon class="w-4 h-4" />
|
|
23
|
+
</button>
|
|
24
|
+
</li>
|
|
25
|
+
<li>
|
|
26
|
+
<button
|
|
27
|
+
:disabled="ui.disabledButtons['add-accounts']"
|
|
28
|
+
@click="ui.toggleModal('create-account', true)"
|
|
29
|
+
class="smooth-hover"
|
|
30
|
+
>
|
|
31
|
+
<PlusIcon class="w-4 h-4" />
|
|
32
|
+
</button>
|
|
33
|
+
</li>
|
|
34
|
+
</ul>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<div class="flex items-center mb-3">
|
|
38
|
+
<div class="flex sm:w-auto w-full justify-start items-center gap-1">
|
|
39
|
+
<TagToggle
|
|
40
|
+
class="smooth-hover rounded-l min-w-9"
|
|
41
|
+
:options="['All', 'Enabled', 'Disabled']"
|
|
42
|
+
@change="(f) => (ui.search.accounts.show = f)"
|
|
43
|
+
/>
|
|
44
|
+
<input
|
|
45
|
+
class="h-10 w-44 text-white text-sm p-2 bg-dark-500 flex items-center relative border-2 border-dark-550"
|
|
46
|
+
placeholder="Search Email"
|
|
47
|
+
v-model="ui.search.accounts.query"
|
|
48
|
+
/>
|
|
49
|
+
|
|
50
|
+
<!-- <Dropdown
|
|
51
|
+
class="min-w-16 text-sm lg:w-24 bg-dark-550 rounded-none"
|
|
52
|
+
:onClick="(f) => (ui.search.accounts.show = f)"
|
|
53
|
+
default="All"
|
|
54
|
+
:chosen="ui.search.accounts.show"
|
|
55
|
+
:options="['All', 'Enabled', 'Disabled']"
|
|
56
|
+
rightAmount="right-2"
|
|
57
|
+
/> -->
|
|
58
|
+
<!-- <TagToggle
|
|
59
|
+
class="smooth-hover rounded-r w-32"
|
|
60
|
+
:options="allTags"
|
|
61
|
+
@change="(f) => (ui.search.accounts.tag = f)"
|
|
62
|
+
/> -->
|
|
63
|
+
|
|
64
|
+
<Dropdown
|
|
65
|
+
class="rounded-r-lg min-w-32 bg-dark-500 relative z-50 border-2 border-dark-550 search-dropdown"
|
|
66
|
+
style="margin-left: 0 !important; border-width: 2px !important"
|
|
67
|
+
rightAmount="right-1"
|
|
68
|
+
default="Any"
|
|
69
|
+
:value="ui.search.accounts.tag"
|
|
70
|
+
:onClick="(f) => (ui.search.accounts.tag = f)"
|
|
71
|
+
:options="allTags"
|
|
72
|
+
:capitalize="true"
|
|
73
|
+
/>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<div class="ml-auto gap-2 hidden lg:flex">
|
|
77
|
+
<div
|
|
78
|
+
class="bg-dark-400 border border-light-300 justify-between px-4 w-44 flex text-white text-xs font-medium items-center rounded-md ml-auto h-10"
|
|
79
|
+
>
|
|
80
|
+
<p>Privacy</p>
|
|
81
|
+
<Switch class="scale-75" v-model="privacy" />
|
|
82
|
+
</div>
|
|
83
|
+
<button
|
|
84
|
+
:disabled="ui.disabledButtons['create-accounts']"
|
|
85
|
+
class="bg-dark-400 disabled:opacity-70 smooth-hover border border-light-300 hover:border-light-400 w-44 flex text-white text-xs font-medium justify-center items-center rounded-md ml-auto h-10"
|
|
86
|
+
@click="ui.toggleModal('account-creator')"
|
|
87
|
+
>
|
|
88
|
+
Create Accounts <PlayIcon class="ml-2" />
|
|
89
|
+
</button>
|
|
90
|
+
|
|
91
|
+
<button
|
|
92
|
+
:disabled="ui.disabledButtons['add-accounts']"
|
|
93
|
+
class="bg-dark-400 disabled:opacity-70 smooth-hover border border-light-300 hover:border-light-400 w-44 flex text-white text-xs font-medium justify-center items-center rounded-md ml-auto h-10"
|
|
94
|
+
@click="ui.toggleModal('create-account')"
|
|
95
|
+
>
|
|
96
|
+
Add Account
|
|
97
|
+
<PlusIcon class="ml-2" />
|
|
98
|
+
</button>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<!-- Tasks (Table) -->
|
|
103
|
+
<AccountView :tasks="processedTasks" class="max-h-big-acc" />
|
|
104
|
+
|
|
105
|
+
<!-- Modal -->
|
|
106
|
+
<transition-group name="fade" mode="out-in">
|
|
107
|
+
<CreateAccount v-if="activeModal === 'create-account'" />
|
|
108
|
+
<AccountCreator v-if="activeModal === 'account-creator'" />
|
|
109
|
+
</transition-group>
|
|
110
|
+
</div>
|
|
111
|
+
</template>
|
|
112
|
+
<style lang="scss" scoped>
|
|
113
|
+
.custom-dropdown-content {
|
|
114
|
+
top: 2.6rem !important;
|
|
115
|
+
left: -13px;
|
|
116
|
+
@apply border border-light-300;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/* Search dropdown should always be h-10 and have no left corners */
|
|
120
|
+
.search-dropdown {
|
|
121
|
+
height: 2.5rem !important; /* Always 40px regardless of screen size */
|
|
122
|
+
border-top-left-radius: 0 !important;
|
|
123
|
+
border-bottom-left-radius: 0 !important;
|
|
124
|
+
}
|
|
125
|
+
.max-h-big-acc {
|
|
126
|
+
max-height: calc(100vh - 14rem);
|
|
127
|
+
overflow: hidden;
|
|
128
|
+
}
|
|
129
|
+
</style>
|
|
130
|
+
<script setup>
|
|
131
|
+
import { computed, watch, ref } from "vue";
|
|
132
|
+
import AccountView from "@/components/Editors/Account/AccountView.vue";
|
|
133
|
+
import AccountCreator from "@/components/Editors/Account/AccountCreator.vue";
|
|
134
|
+
import CreateAccount from "@/components/Editors/Account/CreateAccount.vue";
|
|
135
|
+
import { useUIStore } from "@/stores/ui";
|
|
136
|
+
import { PlusIcon, PlayIcon, MailIcon } from "@/components/icons";
|
|
137
|
+
import Dropdown from "@/components/ui/controls/atomic/Dropdown.vue";
|
|
138
|
+
import TagToggle from "@/components/Editors/TagToggle.vue";
|
|
139
|
+
import Switch from "@/components/ui/controls/atomic/Switch.vue";
|
|
140
|
+
import EyeToggle from "@/components/ui/controls/EyeToggle.vue";
|
|
141
|
+
|
|
142
|
+
const ui = useUIStore();
|
|
143
|
+
const activeModal = computed(() => ui.activeModal);
|
|
144
|
+
const allTags = ref([]);
|
|
145
|
+
const privacy = ref(true);
|
|
146
|
+
|
|
147
|
+
const filterAccounts = () => {
|
|
148
|
+
const { query, show, tag } = ui.search.accounts;
|
|
149
|
+
let accs = ui.accounts;
|
|
150
|
+
if (show === "Enabled") accs = accs.filter((p) => p.enabled);
|
|
151
|
+
if (show === "Disabled") accs = accs.filter((p) => !p.enabled);
|
|
152
|
+
ui.logger.Info(`Filtered accounts for ${ui.currentModule}`);
|
|
153
|
+
|
|
154
|
+
accs = accs.filter((acc) => acc.module === ui.currentModule);
|
|
155
|
+
|
|
156
|
+
if (tag !== "Any") accs = accs.filter((p) => p.tags.includes(ui.search.accounts.tag));
|
|
157
|
+
if (!query) return (ui.search.accounts.results = accs);
|
|
158
|
+
let searchRegex = new RegExp(query, "i");
|
|
159
|
+
accs = accs.filter((a) => searchRegex.test(a.email));
|
|
160
|
+
return accs;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
ui.search.accounts.results = filterAccounts();
|
|
164
|
+
|
|
165
|
+
const processedTasks = computed(() => {
|
|
166
|
+
return ui.search.accounts.results.map((e) => ({ ...e, privacy: privacy.value }));
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
watch(
|
|
170
|
+
() =>
|
|
171
|
+
ui.search.accounts.query +
|
|
172
|
+
ui.search.accounts.show +
|
|
173
|
+
ui.accounts.length +
|
|
174
|
+
ui.search.accounts.tag +
|
|
175
|
+
ui.currentModule,
|
|
176
|
+
() => {
|
|
177
|
+
ui.search.accounts.results = filterAccounts();
|
|
178
|
+
}
|
|
179
|
+
);
|
|
180
|
+
const getAllTags = () => {
|
|
181
|
+
let tags = ["Any"];
|
|
182
|
+
ui.search.accounts.results.forEach((p) =>
|
|
183
|
+
p.tags.forEach((tag) => {
|
|
184
|
+
if (!tags.includes(tag)) tags.push(tag);
|
|
185
|
+
})
|
|
186
|
+
);
|
|
187
|
+
return tags;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
allTags.value = getAllTags();
|
|
191
|
+
</script>
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<h4 class="text-white font-bold mb-5 pt-5 flex gap-2 text-xl items-center">Console <ConsoleIcon /></h4>
|
|
4
|
+
|
|
5
|
+
<div>
|
|
6
|
+
<div class="flex items-center justify-between mb-3">
|
|
7
|
+
<div class="w-64">
|
|
8
|
+
<Dropdown
|
|
9
|
+
class="console-dropdown input-default w-64 bg-dark-500 border-2 border-dark-550"
|
|
10
|
+
rightAmount="right-2"
|
|
11
|
+
default="All logs"
|
|
12
|
+
:allowDefault="true"
|
|
13
|
+
:value="currentTaskLog"
|
|
14
|
+
:onClick="(f) => (currentTaskLog = f.split(' ')[0])"
|
|
15
|
+
:options="
|
|
16
|
+
Object.entries(taskLogMapping)
|
|
17
|
+
.map(([k, v]) => `${k} (${v.length})`)
|
|
18
|
+
.sort((a, b) => a.localeCompare(b))
|
|
19
|
+
"
|
|
20
|
+
/>
|
|
21
|
+
</div>
|
|
22
|
+
<div class="flex items-center gap-3">
|
|
23
|
+
<!-- Hide Monitors and Auto buttons only on desktop -->
|
|
24
|
+
<div class="hidden ipadlg:flex items-center gap-3">
|
|
25
|
+
<button
|
|
26
|
+
class="flex rounded gap-3 card-dark px-2 h-10 flex-center"
|
|
27
|
+
>
|
|
28
|
+
<h3 class="text-sm text-white">Hide Monitors</h3>
|
|
29
|
+
<Switch class="scale-75" v-model="filteredLogs" />
|
|
30
|
+
</button>
|
|
31
|
+
<button
|
|
32
|
+
class="flex rounded gap-3 card-dark px-2 h-10 flex-center"
|
|
33
|
+
>
|
|
34
|
+
<h3 class="text-sm text-white">Auto</h3>
|
|
35
|
+
<Switch class="scale-75" v-model="autoscrollToggled" />
|
|
36
|
+
</button>
|
|
37
|
+
</div>
|
|
38
|
+
<!-- Scroll buttons always visible -->
|
|
39
|
+
<button
|
|
40
|
+
class="rounded card-dark w-10 h-10 flex-center"
|
|
41
|
+
>
|
|
42
|
+
<UpIcon class="cursor-pointer mx-1 lg:w-4 w-5 h-5" @click="scrollTo('up')" />
|
|
43
|
+
</button>
|
|
44
|
+
<button
|
|
45
|
+
class="rounded card-dark w-10 h-10 flex-center"
|
|
46
|
+
>
|
|
47
|
+
<DownIcon class="cursor-pointer ml-1 lg:w-4 w-5 h-5" @click="scrollTo('down')" />
|
|
48
|
+
</button>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<Smoothie
|
|
53
|
+
:weight="0.1"
|
|
54
|
+
class="hidden-scrollbars console overflow-y-auto overflow-x-hidden font-mono text-white"
|
|
55
|
+
style="min-height: 14rem !important"
|
|
56
|
+
ref="$autoscroll"
|
|
57
|
+
>
|
|
58
|
+
<pre
|
|
59
|
+
class="hidden-scrollbars"
|
|
60
|
+
v-for="line in currentTaskLog
|
|
61
|
+
? taskLogMapping[currentTaskLog]
|
|
62
|
+
: logLines.filter((l) => (filteredLogs ? !['-DISCORD'].some((s) => l.includes(s)) : true))"
|
|
63
|
+
v-bind:key="line"
|
|
64
|
+
><code class="md:text-sm lg:text-base" v-html="line"></code></pre>
|
|
65
|
+
</Smoothie>
|
|
66
|
+
<div class="flex ipadlg:hidden justify-between mt-3">
|
|
67
|
+
<button
|
|
68
|
+
class="flex rounded gap-3 card-dark px-2 h-10 flex-center"
|
|
69
|
+
>
|
|
70
|
+
<h3 class="text-sm text-white">Hide Monitors</h3>
|
|
71
|
+
<Switch class="scale-75" v-model="filteredLogs" />
|
|
72
|
+
</button>
|
|
73
|
+
<button
|
|
74
|
+
class="flex rounded gap-3 card-dark px-2 h-10 flex-center"
|
|
75
|
+
>
|
|
76
|
+
<h3 class="text-sm text-white">Auto</h3>
|
|
77
|
+
<Switch class="scale-75" v-model="autoscrollToggled" />
|
|
78
|
+
</button>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
</template>
|
|
83
|
+
<style lang="scss" scoped>
|
|
84
|
+
.console {
|
|
85
|
+
@apply bg-dark-400 lg:p-5 p-2 rounded relative border-dark-550 border-2;
|
|
86
|
+
height: calc(100vh - 16.5rem);
|
|
87
|
+
textarea {
|
|
88
|
+
background: transparent;
|
|
89
|
+
resize: none;
|
|
90
|
+
|
|
91
|
+
@apply w-full focus:outline-none text-white;
|
|
92
|
+
}
|
|
93
|
+
// $border: 1px;
|
|
94
|
+
// &:before {
|
|
95
|
+
// content: "";
|
|
96
|
+
// @apply absolute top-0 left-0 right-0 bottom-0 opacity-60;
|
|
97
|
+
// z-index: -2;
|
|
98
|
+
// margin: -$border;
|
|
99
|
+
// border-radius: inherit;
|
|
100
|
+
// background: radial-gradient(rgba(96, 66, 255, 0.6), rgba(255, 255, 255, 0));
|
|
101
|
+
// }
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.text-xxs {
|
|
105
|
+
font-size: 0.5rem;
|
|
106
|
+
line-height: 0.8rem;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.header-wrapper {
|
|
110
|
+
svg {
|
|
111
|
+
width: 30px;
|
|
112
|
+
height: 30px;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
.max-h-big-con {
|
|
116
|
+
max-height: calc(100vh - 12rem);
|
|
117
|
+
overflow: hidden;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* Console dropdown styling - simplified to match input-default pattern */
|
|
121
|
+
.console-dropdown {
|
|
122
|
+
font-size: 0.875rem !important; /* text-sm */
|
|
123
|
+
font-weight: 500 !important; /* medium font weight */
|
|
124
|
+
}
|
|
125
|
+
</style>
|
|
126
|
+
<script setup>
|
|
127
|
+
import { Smoothie } from "vue-smoothie";
|
|
128
|
+
import { DEBUG } from "@/utils/debug";
|
|
129
|
+
|
|
130
|
+
import Filter from "@/libs/ansii.js";
|
|
131
|
+
import { ConsoleIcon, DownIcon, UpIcon } from "@/components/icons";
|
|
132
|
+
import Switch from "@/components/ui/controls/atomic/Switch.vue";
|
|
133
|
+
import WebsocketHeartbeatJs from "websocket-heartbeat-js";
|
|
134
|
+
import { onMounted, ref, nextTick } from "vue";
|
|
135
|
+
import Dropdown from "@/components/ui/controls/atomic/Dropdown.vue";
|
|
136
|
+
import { sortAlphaNum } from "@/stores/utils";
|
|
137
|
+
|
|
138
|
+
import { useUIStore } from "@/stores/ui";
|
|
139
|
+
|
|
140
|
+
const ui = useUIStore();
|
|
141
|
+
|
|
142
|
+
const $autoscroll = ref(null);
|
|
143
|
+
const logLines = ref([]);
|
|
144
|
+
const ansii = new Filter();
|
|
145
|
+
const autoscrollToggled = ref(true);
|
|
146
|
+
const taskLogMapping = ref({});
|
|
147
|
+
const currentTaskLog = ref(false);
|
|
148
|
+
const filteredLogs = ref(true);
|
|
149
|
+
|
|
150
|
+
const path = "/api/updates?type=console";
|
|
151
|
+
const url = (window.location.protocol === "http:" ? "ws://" : "wss://") + window.location.host + path;
|
|
152
|
+
const scrollTo = (dir) => {
|
|
153
|
+
try {
|
|
154
|
+
if (dir === "up") $autoscroll.value.el.scrollTop = 0;
|
|
155
|
+
else $autoscroll.value.el.scrollTop = parseInt($autoscroll.value.el.children[1].style.height);
|
|
156
|
+
} catch (e) {
|
|
157
|
+
if (DEBUG) console.log("Error scrolling", e);
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const addAnsiToOutput = (a) => {
|
|
162
|
+
const html = ansii.toHtml(a.log);
|
|
163
|
+
logLines.value.push(html);
|
|
164
|
+
if (autoscrollToggled.value)
|
|
165
|
+
nextTick().then(() => {
|
|
166
|
+
scrollTo("down");
|
|
167
|
+
});
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const handleWebsocketMessages = (msg) => {
|
|
171
|
+
const data = msg.log;
|
|
172
|
+
if (msg.type === "console-init") {
|
|
173
|
+
logLines.value = [];
|
|
174
|
+
taskLogMapping.value = {};
|
|
175
|
+
makeTaskLogMapping(data);
|
|
176
|
+
|
|
177
|
+
data.forEach((l) => {
|
|
178
|
+
addAnsiToOutput(l);
|
|
179
|
+
});
|
|
180
|
+
} else if (msg.type === "console") {
|
|
181
|
+
makeTaskLogMapping([msg]);
|
|
182
|
+
if (data.includes("Cleared logs")) logLines.value = [];
|
|
183
|
+
addAnsiToOutput(msg);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const makeTaskLogMapping = (lines) => {
|
|
188
|
+
lines.forEach((l) => {
|
|
189
|
+
if (!l.metadata) {
|
|
190
|
+
if (DEBUG) console.log("Error getting metadata", l);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const region = l.metadata.siteId?.split("_")?.[1];
|
|
194
|
+
const n = l.metadata.global ? "Global" : `${region}-${l.metadata.taskId}`;
|
|
195
|
+
if (!taskLogMapping.value[n]) taskLogMapping.value[n] = [];
|
|
196
|
+
taskLogMapping.value[n].push(ansii.toHtml(l.log));
|
|
197
|
+
});
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
window.startDebugConsoleMessages = () => {
|
|
201
|
+
setInterval(() => {
|
|
202
|
+
const line = `\u001b[96m[12:16:02.273]\u001b[00m \u001b[96m[TASK-${Math.round(
|
|
203
|
+
Math.random() * 10
|
|
204
|
+
)}]\u001b[00m AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Needs To Queue: false - Queue up: false`;
|
|
205
|
+
addAnsiToOutput(line);
|
|
206
|
+
makeTaskLogMapping([line]);
|
|
207
|
+
}, 500);
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
if (DEBUG) window.startDebugConsoleMessages();
|
|
211
|
+
|
|
212
|
+
// Listen for messages
|
|
213
|
+
onMounted(() => {
|
|
214
|
+
const socket = new WebsocketHeartbeatJs({ url, pingMsg: "ping" });
|
|
215
|
+
|
|
216
|
+
socket.onmessage = (event) => {
|
|
217
|
+
const msg = JSON.parse(event.data);
|
|
218
|
+
if (DEBUG) console.log("Received message", msg);
|
|
219
|
+
msg.forEach((e) => {
|
|
220
|
+
handleWebsocketMessages(e);
|
|
221
|
+
});
|
|
222
|
+
};
|
|
223
|
+
});
|
|
224
|
+
</script>
|