@necrolab/dashboard 0.4.220 → 0.5.1
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 +27 -1
- package/.vscode/extensions.json +1 -1
- package/README.md +64 -2
- package/artwork/image.png +0 -0
- package/backend/api.js +26 -24
- package/backend/auth.js +2 -2
- package/backend/batching.js +1 -1
- package/backend/endpoints.js +8 -11
- package/backend/index.js +2 -2
- package/backend/mock-data.js +27 -36
- package/backend/mock-src/classes/logger.js +5 -7
- package/backend/mock-src/classes/utils.js +3 -2
- package/backend/mock-src/ticketmaster.js +4 -4
- package/backend/validator.js +2 -2
- package/config/configs.json +0 -1
- package/dev-server.js +134 -0
- package/exit +209 -0
- package/index.html +78 -8
- package/index.js +1 -1
- package/jsconfig.json +16 -0
- package/package.json +39 -25
- package/postcss.config.js +1 -1
- package/postinstall.js +124 -20
- 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/img/logo_trans.png +0 -0
- package/public/img/necro_logo.png +0 -0
- package/public/manifest.json +16 -10
- package/run +176 -9
- package/src/App.vue +498 -85
- package/src/assets/css/base/reset.scss +43 -0
- package/src/assets/css/base/scroll.scss +114 -0
- package/src/assets/css/base/typography.scss +37 -0
- package/src/assets/css/components/buttons.scss +216 -0
- package/src/assets/css/components/forms.scss +221 -0
- package/src/assets/css/components/modals.scss +13 -0
- package/src/assets/css/components/tables.scss +27 -0
- package/src/assets/css/components/toasts.scss +100 -0
- package/src/assets/css/main.scss +201 -122
- package/src/assets/img/background.svg +2 -2
- package/src/assets/img/background.svg.backup +11 -0
- package/src/assets/img/logo_trans.png +0 -0
- package/src/components/Auth/LoginForm.vue +62 -11
- package/src/components/Editors/Account/Account.vue +116 -40
- package/src/components/Editors/Account/AccountCreator.vue +88 -39
- package/src/components/Editors/Account/AccountView.vue +102 -34
- package/src/components/Editors/Account/CreateAccount.vue +80 -32
- package/src/components/Editors/Profile/CreateProfile.vue +269 -83
- package/src/components/Editors/Profile/Profile.vue +132 -47
- package/src/components/Editors/Profile/ProfileCountryChooser.vue +82 -20
- package/src/components/Editors/Profile/ProfileView.vue +89 -32
- package/src/components/Editors/TagLabel.vue +67 -6
- package/src/components/Editors/TagToggle.vue +7 -2
- package/src/components/Filter/Filter.vue +288 -71
- package/src/components/Filter/FilterPreview.vue +202 -31
- package/src/components/Filter/PriceSortToggle.vue +76 -6
- package/src/components/Table/Header.vue +1 -1
- package/src/components/Table/Row.vue +1 -1
- package/src/components/Table/Table.vue +19 -2
- package/src/components/Tasks/CheckStock.vue +6 -8
- package/src/components/Tasks/Controls/DesktopControls.vue +27 -17
- package/src/components/Tasks/Controls/MobileControls.vue +8 -45
- package/src/components/Tasks/CreateTaskAXS.vue +80 -72
- package/src/components/Tasks/CreateTaskTM.vue +95 -141
- package/src/components/Tasks/MassEdit.vue +4 -6
- package/src/components/Tasks/QuickSettings.vue +199 -30
- package/src/components/Tasks/ScrapeVenue.vue +5 -6
- package/src/components/Tasks/Stats.vue +50 -24
- package/src/components/Tasks/Task.vue +384 -179
- package/src/components/Tasks/TaskLabel.vue +2 -2
- package/src/components/Tasks/TaskView.vue +136 -48
- package/src/components/Tasks/Utilities.vue +25 -10
- package/src/components/Tasks/ViewTask.vue +321 -0
- package/src/components/icons/Bag.vue +1 -1
- package/src/components/icons/Check.vue +5 -0
- package/src/components/icons/Close.vue +21 -0
- package/src/components/icons/CloseX.vue +5 -0
- package/src/components/icons/Eye.vue +6 -0
- package/src/components/icons/Key.vue +21 -0
- package/src/components/icons/Loyalty.vue +1 -1
- package/src/components/icons/Mail.vue +2 -2
- package/src/components/icons/Pencil.vue +21 -0
- package/src/components/icons/Play.vue +2 -2
- package/src/components/icons/Profile.vue +18 -0
- package/src/components/icons/Reload.vue +4 -5
- package/src/components/icons/Sandclock.vue +2 -2
- package/src/components/icons/Sell.vue +21 -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 +1 -1
- package/src/components/icons/Wildcard.vue +18 -0
- package/src/components/icons/index.js +26 -1
- package/src/components/ui/Modal.vue +107 -13
- package/src/components/ui/Navbar.vue +175 -40
- package/src/components/ui/ReconnectIndicator.vue +351 -55
- package/src/components/ui/Splash.vue +5 -35
- package/src/components/ui/controls/CountryChooser.vue +200 -62
- package/src/components/ui/controls/atomic/Checkbox.vue +119 -10
- package/src/components/ui/controls/atomic/Dropdown.vue +216 -39
- package/src/components/ui/controls/atomic/LoadingButton.vue +45 -0
- package/src/components/ui/controls/atomic/MultiDropdown.vue +300 -37
- package/src/components/ui/controls/atomic/Switch.vue +53 -25
- package/src/composables/useClickOutside.js +21 -0
- package/src/composables/useDropdownPosition.js +174 -0
- package/src/libs/Filter.js +60 -24
- package/src/registerServiceWorker.js +1 -1
- package/src/stores/connection.js +4 -4
- package/src/stores/sampleData.js +172 -199
- package/src/stores/ui.js +55 -20
- package/src/stores/utils.js +30 -4
- package/src/types/index.js +41 -0
- package/src/utils/debug.js +1 -0
- package/src/views/Accounts.vue +116 -50
- package/src/views/Console.vue +394 -79
- package/src/views/Editor.vue +1176 -123
- package/src/views/FilterBuilder.vue +528 -250
- package/src/views/Login.vue +76 -14
- package/src/views/Profiles.vue +119 -34
- package/src/views/Tasks.vue +266 -98
- package/static/offline.html +192 -50
- package/switch-branch.sh +41 -0
- package/tailwind.config.js +119 -27
- package/vite.config.js +73 -16
- package/workbox-config.cjs +63 -0
- package/ICONS.md +0 -21
- package/public/img/background.svg +0 -14
- 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/src/assets/css/_input.scss +0 -143
- 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/vue.config.js +0 -32
- package/workbox-config.js +0 -7
|
@@ -1,54 +1,52 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Row
|
|
3
|
-
class="relative
|
|
3
|
+
class="relative h-16 grid-cols-5 text-white md:grid-cols-7"
|
|
4
4
|
@click="ui.setOpenContextMenu('')"
|
|
5
|
-
@click.right.prevent="ui.setOpenContextMenu('')"
|
|
6
|
-
|
|
7
|
-
<div class="col-span-3 lg:col-span-2 flex">
|
|
5
|
+
@click.right.prevent="ui.setOpenContextMenu('')">
|
|
6
|
+
<div class="col-span-3 flex lg:col-span-2">
|
|
8
7
|
<Checkbox
|
|
9
8
|
class="ml-0 mr-4"
|
|
10
|
-
:toggled="props.
|
|
11
|
-
@valueUpdate="ui.toggleAccountSelected(props.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
{{ props.task.email }}
|
|
9
|
+
:toggled="props.account.selected"
|
|
10
|
+
@valueUpdate="ui.toggleAccountSelected(props.account.id)" />
|
|
11
|
+
<h4 class="mx-auto text-white" @click="copy(props.account.email)">
|
|
12
|
+
{{ props.account.email }}
|
|
15
13
|
</h4>
|
|
16
14
|
</div>
|
|
17
|
-
<div class="col-span-2 hidden
|
|
15
|
+
<div class="col-span-2 hidden md:block" @click="copy(props.account.password)">
|
|
18
16
|
<h4 class="text-white">
|
|
19
|
-
{{ props.
|
|
17
|
+
{{ props.account.privacy ? "•".repeat(props.account.password.length) : props.account.password }}
|
|
20
18
|
</h4>
|
|
21
19
|
</div>
|
|
22
20
|
<div class="col-span-1">
|
|
23
|
-
<h4 v-if="props.
|
|
24
|
-
<img
|
|
21
|
+
<h4 v-if="props.account.enabled" class="flex justify-center text-green-400">
|
|
22
|
+
<img class="green h-3 w-3" src="/img/controls/enable.svg" />
|
|
25
23
|
</h4>
|
|
26
|
-
<h4 v-else class="text-red-400
|
|
27
|
-
<img
|
|
24
|
+
<h4 v-else class="flex justify-center text-red-400">
|
|
25
|
+
<img class="h-3 w-3 fill-red-400" src="/img/close.svg" />
|
|
28
26
|
</h4>
|
|
29
27
|
</div>
|
|
30
28
|
|
|
31
29
|
<div class="col-span-1 hidden lg:block">
|
|
32
|
-
<h4 class="
|
|
33
|
-
<TagLabel v-for="tag in props.
|
|
30
|
+
<h4 class="flex justify-center gap-1 text-white">
|
|
31
|
+
<TagLabel v-for="tag in props.account.tags" :key="tag" :text="tag" />
|
|
34
32
|
</h4>
|
|
35
33
|
</div>
|
|
36
34
|
|
|
37
35
|
<div class="col-span-1 flex">
|
|
38
|
-
<ul class="
|
|
36
|
+
<ul class="account-buttons">
|
|
39
37
|
<li>
|
|
40
38
|
<button @click="edit">
|
|
41
39
|
<EditIcon />
|
|
42
40
|
</button>
|
|
43
41
|
</li>
|
|
44
|
-
<li v-if="props.
|
|
42
|
+
<li v-if="props.account.enabled">
|
|
45
43
|
<button @click="disable">
|
|
46
|
-
<img
|
|
44
|
+
<img class="h-4 w-4" src="/img/controls/disable.svg" />
|
|
47
45
|
</button>
|
|
48
46
|
</li>
|
|
49
47
|
<li v-else>
|
|
50
48
|
<button @click="enable">
|
|
51
|
-
<img
|
|
49
|
+
<img class="h-4 w-4" src="/img/controls/enable.svg" />
|
|
52
50
|
</button>
|
|
53
51
|
</li>
|
|
54
52
|
</ul>
|
|
@@ -59,33 +57,111 @@
|
|
|
59
57
|
h4 {
|
|
60
58
|
@apply text-center;
|
|
61
59
|
}
|
|
62
|
-
.
|
|
63
|
-
@apply
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
.account-buttons {
|
|
61
|
+
@apply mx-auto flex items-center justify-center rounded border border-dark-650 bg-dark-500;
|
|
62
|
+
padding: 3px;
|
|
63
|
+
gap: 2px;
|
|
64
|
+
|
|
65
|
+
button {
|
|
66
|
+
@apply relative flex items-center justify-center rounded border-0 outline-0 transition-all duration-150;
|
|
67
|
+
background: transparent;
|
|
68
|
+
width: 28px;
|
|
69
|
+
height: 28px;
|
|
70
|
+
color: oklch(0.82 0 0);
|
|
71
|
+
|
|
72
|
+
&:hover {
|
|
73
|
+
background: rgba(255, 255, 255, 0.1);
|
|
74
|
+
color: #ffffff;
|
|
75
|
+
transform: scale(1.05);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
&:active {
|
|
79
|
+
background: rgba(255, 255, 255, 0.2);
|
|
80
|
+
transform: scale(0.95);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
svg,
|
|
85
|
+
img {
|
|
86
|
+
width: 16px;
|
|
87
|
+
height: 16px;
|
|
88
|
+
position: relative;
|
|
89
|
+
z-index: 1;
|
|
67
90
|
}
|
|
68
|
-
}
|
|
69
91
|
|
|
70
|
-
svg {
|
|
71
|
-
|
|
72
|
-
|
|
92
|
+
svg path {
|
|
93
|
+
fill: currentColor;
|
|
94
|
+
}
|
|
73
95
|
}
|
|
74
96
|
|
|
97
|
+
// Tablet optimization
|
|
75
98
|
@media (max-width: 1024px) {
|
|
76
99
|
h4 {
|
|
77
100
|
font-size: 10px !important;
|
|
78
101
|
}
|
|
79
|
-
|
|
80
|
-
|
|
102
|
+
|
|
103
|
+
.account-buttons {
|
|
104
|
+
padding: 3px;
|
|
105
|
+
gap: 2px;
|
|
106
|
+
|
|
107
|
+
button {
|
|
108
|
+
width: 26px;
|
|
109
|
+
height: 26px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
svg,
|
|
113
|
+
img {
|
|
114
|
+
width: 14px;
|
|
115
|
+
height: 14px;
|
|
116
|
+
}
|
|
81
117
|
}
|
|
82
|
-
|
|
118
|
+
|
|
119
|
+
.account-id {
|
|
83
120
|
font-size: 6px !important;
|
|
84
121
|
margin-right: -12px;
|
|
85
122
|
margin-top: 20px;
|
|
86
123
|
}
|
|
87
|
-
|
|
88
|
-
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Mobile optimization
|
|
127
|
+
@media (max-width: 768px) {
|
|
128
|
+
.account-buttons {
|
|
129
|
+
padding: 2px;
|
|
130
|
+
gap: 1px;
|
|
131
|
+
|
|
132
|
+
button {
|
|
133
|
+
width: 22px;
|
|
134
|
+
height: 22px;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
svg,
|
|
138
|
+
img {
|
|
139
|
+
width: 12px;
|
|
140
|
+
height: 12px;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// iPhone vertical (portrait) specific
|
|
146
|
+
@media (max-width: 480px) and (orientation: portrait) {
|
|
147
|
+
.account-buttons {
|
|
148
|
+
padding: 2px;
|
|
149
|
+
gap: 1px;
|
|
150
|
+
|
|
151
|
+
button {
|
|
152
|
+
width: 18px;
|
|
153
|
+
height: 18px;
|
|
154
|
+
|
|
155
|
+
&:hover {
|
|
156
|
+
transform: scale(1.1);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
svg,
|
|
161
|
+
img {
|
|
162
|
+
width: 10px;
|
|
163
|
+
height: 10px;
|
|
164
|
+
}
|
|
89
165
|
}
|
|
90
166
|
}
|
|
91
167
|
</style>
|
|
@@ -94,12 +170,12 @@ import { Row } from "@/components/Table";
|
|
|
94
170
|
import { PlayIcon, TrashIcon, BagWhiteIcon, PauseIcon, EditIcon } from "@/components/icons";
|
|
95
171
|
import Checkbox from "@/components/ui/controls/atomic/Checkbox.vue";
|
|
96
172
|
import { useUIStore } from "@/stores/ui";
|
|
97
|
-
import TagLabel from "@/components/
|
|
173
|
+
import TagLabel from "@/components/Editors/TagLabel.vue";
|
|
98
174
|
|
|
99
175
|
const ui = useUIStore();
|
|
100
176
|
|
|
101
177
|
const props = defineProps({
|
|
102
|
-
|
|
178
|
+
account: { type: Object }
|
|
103
179
|
});
|
|
104
180
|
|
|
105
181
|
const copy = (txt) => {
|
|
@@ -107,10 +183,10 @@ const copy = (txt) => {
|
|
|
107
183
|
navigator.clipboard.writeText(txt);
|
|
108
184
|
ui.showSuccess("Copied text");
|
|
109
185
|
};
|
|
110
|
-
const enable = async () => await ui.addAccount({ ...props.
|
|
111
|
-
const disable = async () => await ui.addAccount({ ...props.
|
|
186
|
+
const enable = async () => await ui.addAccount({ ...props.account, enabled: true });
|
|
187
|
+
const disable = async () => await ui.addAccount({ ...props.account, enabled: false });
|
|
112
188
|
const edit = () => {
|
|
113
|
-
ui.currentlyEditing = props.
|
|
189
|
+
ui.currentlyEditing = props.account;
|
|
114
190
|
ui.toggleModal("create-account");
|
|
115
191
|
};
|
|
116
192
|
</script>
|
|
@@ -6,63 +6,85 @@
|
|
|
6
6
|
</template>
|
|
7
7
|
|
|
8
8
|
<div>
|
|
9
|
-
<div class="
|
|
10
|
-
<div class="input-wrapper col-span-8
|
|
11
|
-
<label class="label-override">
|
|
12
|
-
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
9
|
+
<div class="form-grid mb-4 mt-7">
|
|
10
|
+
<div class="input-wrapper relative-positioned z-tooltip col-span-8">
|
|
11
|
+
<label class="label-override mb-2">
|
|
12
|
+
Account Tag
|
|
13
|
+
<TagIcon />
|
|
14
|
+
</label>
|
|
15
|
+
<Dropdown
|
|
16
|
+
class="input-default dropdown w-full p-4"
|
|
17
|
+
:default="ui.profile.tags[0]"
|
|
18
|
+
:options="ui.profile.tags"
|
|
19
|
+
:onClick="(f) => (creatorConfig.tag = f)"
|
|
20
|
+
:capitalize="true"
|
|
21
|
+
:allowDefault="false"
|
|
22
|
+
:chosen="creatorConfig.tag" />
|
|
22
23
|
</div>
|
|
23
24
|
|
|
24
25
|
<div class="input-wrapper col-span-4">
|
|
25
|
-
<label class="label-override">
|
|
26
|
+
<label class="label-override mb-2">
|
|
27
|
+
Threads
|
|
28
|
+
<EditIcon />
|
|
29
|
+
</label>
|
|
26
30
|
<div :class="`input-default ${errors.includes('threads') ? 'error' : ''}`">
|
|
27
31
|
<input placeholder="1" type="number" min="1" max="50" v-model="creatorConfig.threads" />
|
|
32
|
+
<div class="input-incrementer">
|
|
33
|
+
<button @click="creatorConfig.threads++">
|
|
34
|
+
<UpIcon />
|
|
35
|
+
</button>
|
|
36
|
+
<button @click="if (creatorConfig.threads > 1) creatorConfig.threads--;">
|
|
37
|
+
<DownIcon />
|
|
38
|
+
</button>
|
|
39
|
+
</div>
|
|
28
40
|
</div>
|
|
29
41
|
</div>
|
|
30
42
|
<div class="input-wrapper col-span-8">
|
|
31
|
-
<label class="label-override">
|
|
43
|
+
<label class="label-override mb-2">
|
|
44
|
+
Email catchall
|
|
45
|
+
<MailIcon />
|
|
46
|
+
</label>
|
|
32
47
|
<div :class="`input-default ${errors.includes('catchall') ? 'error' : ''}`">
|
|
33
|
-
<input placeholder="
|
|
48
|
+
<input placeholder="example.com" v-model="creatorConfig.catchall" />
|
|
34
49
|
</div>
|
|
35
50
|
</div>
|
|
36
51
|
<div class="input-wrapper col-span-4">
|
|
37
|
-
<label class="label-override">
|
|
52
|
+
<label class="label-override mb-2">
|
|
53
|
+
Catchall amount
|
|
54
|
+
<BagIcon />
|
|
55
|
+
</label>
|
|
38
56
|
<div :class="`input-default ${errors.includes('number') ? 'error' : ''}`">
|
|
39
57
|
<input placeholder="1" type="number" min="0" max="5000" v-model="creatorConfig.number" />
|
|
58
|
+
<div class="input-incrementer">
|
|
59
|
+
<button @click="creatorConfig.number++">
|
|
60
|
+
<UpIcon />
|
|
61
|
+
</button>
|
|
62
|
+
<button @click="if (creatorConfig.number > 0) creatorConfig.number--;">
|
|
63
|
+
<DownIcon />
|
|
64
|
+
</button>
|
|
65
|
+
</div>
|
|
40
66
|
</div>
|
|
41
67
|
</div>
|
|
42
68
|
<div class="input-wrapper col-span-12">
|
|
43
|
-
<
|
|
44
|
-
|
|
69
|
+
<label class="label-override mb-2">
|
|
70
|
+
Emails
|
|
71
|
+
<MailIcon />
|
|
72
|
+
</label>
|
|
73
|
+
<div :class="`${errors.includes('emails') ? 'error-border' : ''}`">
|
|
74
|
+
<textarea
|
|
75
|
+
v-model="creatorConfig.emails"
|
|
76
|
+
class="proxy-editor"
|
|
77
|
+
spellcheck="false"
|
|
78
|
+
style="max-height: 250px; min-height: 150px"
|
|
79
|
+
placeholder="Enter emails here - One per line"></textarea>
|
|
45
80
|
</div>
|
|
46
|
-
<!-- <div :class="`input-default ${errors.includes('email') ? 'error' : ''}`"> -->
|
|
47
|
-
<!-- <input placeholder="email@example.com" type="email" v-model="account.email" /> -->
|
|
48
|
-
|
|
49
|
-
<CodeEditor
|
|
50
|
-
v-model="creatorConfig.emails"
|
|
51
|
-
width="100%"
|
|
52
|
-
spellcheck="false"
|
|
53
|
-
:hide_header="true"
|
|
54
|
-
:language_selector="false"
|
|
55
|
-
:languages="[['text']]"
|
|
56
|
-
theme="dark"
|
|
57
|
-
:class="`${errors.includes('emails') ? 'error' : ''} max-h-60`"
|
|
58
|
-
></CodeEditor>
|
|
59
81
|
</div>
|
|
60
82
|
</div>
|
|
61
83
|
<button
|
|
62
|
-
class="button-default
|
|
63
|
-
@click="done()"
|
|
64
|
-
|
|
65
|
-
|
|
84
|
+
class="button-default ml-auto mt-4 flex w-48 items-center justify-center gap-x-2 bg-dark-400 text-xs"
|
|
85
|
+
@click="done()">
|
|
86
|
+
Start
|
|
87
|
+
<EditIcon />
|
|
66
88
|
</button>
|
|
67
89
|
</div>
|
|
68
90
|
</Modal>
|
|
@@ -78,16 +100,43 @@
|
|
|
78
100
|
border-color: rgb(238 130 130) !important;
|
|
79
101
|
}
|
|
80
102
|
|
|
103
|
+
.error-border {
|
|
104
|
+
border: 2px solid rgb(238 130 130) !important;
|
|
105
|
+
border-radius: 8px;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* Proxy editor styles */
|
|
109
|
+
.proxy-editor {
|
|
110
|
+
width: 100%;
|
|
111
|
+
background-color: oklch(0.19 0 0);
|
|
112
|
+
color: oklch(0.90 0 0);
|
|
113
|
+
font-family: "JetBrains Mono", "Fira Code", "Menlo", "Monaco", "Courier New", monospace;
|
|
114
|
+
padding: 12px;
|
|
115
|
+
border: none;
|
|
116
|
+
resize: none;
|
|
117
|
+
font-size: 14px;
|
|
118
|
+
line-height: 1.6;
|
|
119
|
+
tab-size: 4;
|
|
120
|
+
outline: none;
|
|
121
|
+
border: 1px solid oklch(0.26 0 0);
|
|
122
|
+
border-radius: 8px;
|
|
123
|
+
overflow: auto;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.proxy-editor:focus {
|
|
127
|
+
border-color: oklch(0.28 0 0);
|
|
128
|
+
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.2);
|
|
129
|
+
}
|
|
130
|
+
|
|
81
131
|
.z-inf {
|
|
82
132
|
z-index: 99999999999999;
|
|
83
133
|
}
|
|
84
134
|
</style>
|
|
85
135
|
<script setup>
|
|
86
136
|
import Modal from "@/components/ui/Modal.vue";
|
|
87
|
-
import { EditIcon } from "@/components/icons";
|
|
137
|
+
import { EditIcon, TagIcon, SpinnerIcon, UpIcon, DownIcon, MailIcon, BagIcon } from "@/components/icons";
|
|
88
138
|
import { useUIStore } from "@/stores/ui";
|
|
89
139
|
import Dropdown from "@/components/ui/controls/atomic/Dropdown.vue";
|
|
90
|
-
import CodeEditor from "simple-code-editor";
|
|
91
140
|
|
|
92
141
|
import { ref } from "vue";
|
|
93
142
|
|
|
@@ -96,7 +145,7 @@ const creatorConfig = ref({
|
|
|
96
145
|
threads: 5,
|
|
97
146
|
catchall: "",
|
|
98
147
|
emails: "",
|
|
99
|
-
tag: ui.profile.
|
|
148
|
+
tag: ui.profile.tags[0],
|
|
100
149
|
number: 0
|
|
101
150
|
});
|
|
102
151
|
|
|
@@ -1,59 +1,62 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Table>
|
|
3
|
-
<Header class="
|
|
4
|
-
<div class="
|
|
3
|
+
<Header class="sticky top-0 z-10 grid-cols-5 bg-dark-400 text-center md:grid-cols-7">
|
|
4
|
+
<div class="col-span-3 flex lg:col-span-2">
|
|
5
5
|
<Checkbox
|
|
6
6
|
class="mr-3"
|
|
7
7
|
:toggled="ui.mainCheckbox.accounts"
|
|
8
8
|
@valueUpdate="ui.toggleMainCheckbox('accounts')"
|
|
9
|
-
|
|
9
|
+
:isHeader="true" />
|
|
10
10
|
<div class="mx-auto flex items-center" @click="ui.toggleSort('eventId')">
|
|
11
|
-
<
|
|
12
|
-
<h4 class="hidden
|
|
11
|
+
<MailIcon class="mr-0 h-4 w-4 md:mr-3" />
|
|
12
|
+
<h4 class="hidden md:flex">Email</h4>
|
|
13
13
|
</div>
|
|
14
14
|
</div>
|
|
15
|
-
<div class="col-span-2 items-center justify-center
|
|
16
|
-
<
|
|
17
|
-
<h4 class="hidden
|
|
15
|
+
<div class="col-span-2 hidden items-center justify-center md:flex" v-once>
|
|
16
|
+
<KeyIcon class="mr-0 h-4 w-4 md:mr-3" />
|
|
17
|
+
<h4 class="hidden md:flex">Password</h4>
|
|
18
18
|
</div>
|
|
19
19
|
<div class="col-span-1 flex items-center justify-center" v-once>
|
|
20
|
-
<
|
|
21
|
-
<h4 class="hidden
|
|
20
|
+
<CheckmarkIcon class="mr-0 h-4 w-4 md:mr-3" />
|
|
21
|
+
<h4 class="hidden md:flex">Enabled</h4>
|
|
22
22
|
</div>
|
|
23
|
-
<div class="col-span-1 hidden
|
|
24
|
-
<TicketIcon class="mr-0
|
|
25
|
-
<h4 class="hidden
|
|
23
|
+
<div class="col-span-1 hidden items-center justify-center lg:flex" v-once>
|
|
24
|
+
<TicketIcon class="mr-0 h-4 w-4 md:mr-3" />
|
|
25
|
+
<h4 class="hidden md:flex">Tags</h4>
|
|
26
26
|
</div>
|
|
27
27
|
<div class="col-span-1 flex items-center justify-center" v-once>
|
|
28
|
-
<ClickIcon class="mr-0
|
|
29
|
-
<h4 class="hidden
|
|
28
|
+
<ClickIcon class="mr-0 h-4 w-4 md:mr-3" />
|
|
29
|
+
<h4 class="hidden md:flex">Actions</h4>
|
|
30
30
|
</div>
|
|
31
31
|
</Header>
|
|
32
|
-
<div
|
|
32
|
+
<div
|
|
33
|
+
v-if="toRender.length != 0"
|
|
34
|
+
class="hidden-scrollbars stop-pan overflow-y-auto overflow-x-hidden"
|
|
35
|
+
:style="{ maxHeight: dynamicTableHeight }">
|
|
33
36
|
<RecycleScroller
|
|
34
37
|
:items="toRender"
|
|
35
38
|
:item-size="64"
|
|
36
|
-
key-field="
|
|
37
|
-
class="scroller vue-recycle-scroller ready direction-vertical flex flex-col divide-y
|
|
38
|
-
>
|
|
39
|
+
key-field="index"
|
|
40
|
+
class="scroller vue-recycle-scroller ready direction-vertical flex flex-col divide-y divide-dark-650">
|
|
39
41
|
<template #default="props">
|
|
40
|
-
<div class="
|
|
42
|
+
<div class="account" :key="`account-${props.item.id || props.item.index}`">
|
|
41
43
|
<Account
|
|
42
|
-
@click="i[props.item.
|
|
43
|
-
:class="
|
|
44
|
-
:
|
|
45
|
-
/>
|
|
44
|
+
@click="i[props.item.index]++"
|
|
45
|
+
:class="props.item.index % 2 == 1 ? 'table-row-even' : 'table-row-odd'"
|
|
46
|
+
:account="props.item" />
|
|
46
47
|
</div>
|
|
47
48
|
</template>
|
|
48
49
|
</RecycleScroller>
|
|
49
50
|
</div>
|
|
50
|
-
<div v-else class="flex
|
|
51
|
-
|
|
51
|
+
<div v-else class="empty-state flex flex-col items-center justify-center bg-dark-400 py-8 text-center">
|
|
52
|
+
<MailIcon class="mb-3 h-12 w-12 text-dark-400 opacity-50" />
|
|
53
|
+
<p class="text-sm text-light-400">No accounts found</p>
|
|
54
|
+
<p class="mt-1 text-xs text-light-500">Create accounts to get started</p>
|
|
52
55
|
</div>
|
|
53
56
|
</Table>
|
|
54
57
|
</template>
|
|
55
58
|
<style lang="scss" scoped>
|
|
56
|
-
.
|
|
59
|
+
.account {
|
|
57
60
|
height: 64px;
|
|
58
61
|
}
|
|
59
62
|
h4 {
|
|
@@ -63,25 +66,90 @@ h4 {
|
|
|
63
66
|
.stop-pan {
|
|
64
67
|
touch-action: pan-y pan-up pan-down;
|
|
65
68
|
}
|
|
69
|
+
|
|
70
|
+
.empty-state {
|
|
71
|
+
color: #969696;
|
|
72
|
+
font-size: 14px;
|
|
73
|
+
font-weight: 500;
|
|
74
|
+
}
|
|
66
75
|
</style>
|
|
67
76
|
<script setup>
|
|
68
77
|
import { Table, Header } from "@/components/Table";
|
|
69
|
-
import {
|
|
78
|
+
import {
|
|
79
|
+
EventIcon,
|
|
80
|
+
TicketIcon,
|
|
81
|
+
StatusIcon,
|
|
82
|
+
ClickIcon,
|
|
83
|
+
DownIcon,
|
|
84
|
+
MailIcon,
|
|
85
|
+
KeyIcon,
|
|
86
|
+
CheckmarkIcon
|
|
87
|
+
} from "@/components/icons";
|
|
70
88
|
import Account from "./Account.vue";
|
|
71
89
|
import Checkbox from "@/components/ui/controls/atomic/Checkbox.vue";
|
|
72
90
|
import { useUIStore } from "@/stores/ui";
|
|
73
|
-
import { computed, ref } from "vue";
|
|
91
|
+
import { computed, ref, onMounted, onUnmounted } from "vue";
|
|
74
92
|
|
|
75
93
|
const props = defineProps({
|
|
76
|
-
|
|
94
|
+
accounts: { type: Object }
|
|
77
95
|
});
|
|
78
|
-
const i = ref({});
|
|
79
|
-
props.tasks.forEach((t) => (i.value[t._id] = 0));
|
|
80
|
-
|
|
81
96
|
const ui = useUIStore();
|
|
82
97
|
|
|
98
|
+
const i = ref({});
|
|
83
99
|
const toRender = computed(() => {
|
|
84
100
|
let c = 0;
|
|
85
|
-
|
|
101
|
+
const rendered = props.accounts.map((t) => ({ ...t, index: c++ }));
|
|
102
|
+
|
|
103
|
+
// Initialize reactive refs for click tracking
|
|
104
|
+
rendered.forEach((t) => {
|
|
105
|
+
if (t.id && !(t.id in i.value)) {
|
|
106
|
+
i.value[t.id] = 0;
|
|
107
|
+
}
|
|
108
|
+
if (!(t.index in i.value)) {
|
|
109
|
+
i.value[t.index] = 0;
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
return rendered;
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Dynamic height calculation for perfect item fitting
|
|
117
|
+
const windowHeight = ref(window.innerHeight);
|
|
118
|
+
const windowWidth = ref(window.innerWidth);
|
|
119
|
+
|
|
120
|
+
const updateDimensions = () => {
|
|
121
|
+
windowHeight.value = window.innerHeight;
|
|
122
|
+
windowWidth.value = window.innerWidth;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
onMounted(() => {
|
|
126
|
+
window.addEventListener("resize", updateDimensions);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
onUnmounted(() => {
|
|
130
|
+
window.removeEventListener("resize", updateDimensions);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const dynamicTableHeight = computed(() => {
|
|
134
|
+
// Calculate available space for accounts table with conservative buffer
|
|
135
|
+
const headerHeight = 60; // Header + navbar
|
|
136
|
+
const titleHeight = 50; // Accounts title and controls
|
|
137
|
+
const searchHeight = 50; // Search and filter controls
|
|
138
|
+
const margins = windowWidth.value >= 1024 ? 40 : 25;
|
|
139
|
+
const bufferSpace = 50; // Conservative buffer to prevent partial items
|
|
140
|
+
|
|
141
|
+
const totalUsedSpace = headerHeight + titleHeight + searchHeight + margins + bufferSpace;
|
|
142
|
+
const availableHeight = windowHeight.value - totalUsedSpace;
|
|
143
|
+
|
|
144
|
+
// Account row height is always 64px
|
|
145
|
+
const rowHeight = 64;
|
|
146
|
+
const minRowsToShow = 2;
|
|
147
|
+
const minHeight = minRowsToShow * rowHeight;
|
|
148
|
+
|
|
149
|
+
// Calculate exact number of complete rows that fit with conservative approach
|
|
150
|
+
const maxCompleteRows = Math.floor(Math.max(availableHeight, minHeight) / rowHeight);
|
|
151
|
+
const exactHeight = maxCompleteRows * rowHeight;
|
|
152
|
+
|
|
153
|
+
return exactHeight + "px";
|
|
86
154
|
});
|
|
87
155
|
</script>
|