@necrolab/dashboard 0.4.50 → 0.4.52
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/package.json +2 -2
- package/src/App.vue +178 -195
- package/src/assets/css/_input.scss +2 -4
- package/src/assets/css/_utilities.scss +0 -53
- package/src/assets/css/main.scss +0 -25
- package/src/components/Editors/Account/AccountView.vue +12 -13
- package/src/components/Editors/Profile/ProfileCountryChooser.vue +4 -6
- package/src/components/Filter/FilterPreview.vue +24 -37
- package/src/components/Tasks/Task.vue +422 -487
- package/src/components/ui/Modal.vue +21 -17
- package/src/components/ui/controls/atomic/Dropdown.vue +126 -131
- package/src/components/ui/controls/atomic/MultiDropdown.vue +200 -206
- package/src/views/Console.vue +1 -1
- package/src/views/Editor.vue +952 -1037
- package/src/views/FilterBuilder.vue +1 -1
- package/src/views/Login.vue +57 -63
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
========================================================================== */
|
|
4
4
|
|
|
5
5
|
.input-default {
|
|
6
|
-
@apply bg-dark-500 flex items-center bg-clip-padding rounded-lg relative box-border px-3 py-2 border-dark-550 border-2;
|
|
7
|
-
height: 3.45em;
|
|
6
|
+
@apply bg-dark-500 flex items-center bg-clip-padding rounded-lg relative box-border px-3 py-2 border-dark-550 border-2 h-10;
|
|
8
7
|
transition: border-color 0.15s ease;
|
|
9
8
|
|
|
10
9
|
&:focus-within {
|
|
@@ -85,8 +84,7 @@ input[type="number"]::-webkit-inner-spin-button {
|
|
|
85
84
|
}
|
|
86
85
|
|
|
87
86
|
.ant-select {
|
|
88
|
-
@apply bg-dark-500 flex items-center bg-clip-padding rounded-lg relative box-border px-1 py-1 border-dark-550 border-2 !important;
|
|
89
|
-
min-height: 3.45em;
|
|
87
|
+
@apply bg-dark-500 flex items-center bg-clip-padding rounded-lg relative box-border px-1 py-1 border-dark-550 border-2 h-10 !important;
|
|
90
88
|
height: fit-content;
|
|
91
89
|
|
|
92
90
|
.ant-select-selector {
|
|
@@ -273,24 +273,6 @@
|
|
|
273
273
|
|
|
274
274
|
/* Mobile portrait utilities */
|
|
275
275
|
@screen mobile-portrait {
|
|
276
|
-
.mobile-portrait-hidden {
|
|
277
|
-
display: none !important;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
.mobile-portrait-full-width {
|
|
281
|
-
width: 100% !important;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
.mobile-portrait-stack {
|
|
285
|
-
flex-direction: column !important;
|
|
286
|
-
gap: 0.75rem !important;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
.mobile-portrait-compact {
|
|
290
|
-
padding: 0.25rem !important;
|
|
291
|
-
gap: 0.25rem !important;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
276
|
.editor-controls-row,
|
|
295
277
|
.proxy-controls-row {
|
|
296
278
|
gap: 0.75rem !important;
|
|
@@ -312,41 +294,6 @@
|
|
|
312
294
|
}
|
|
313
295
|
}
|
|
314
296
|
|
|
315
|
-
/* Desktop-specific utilities */
|
|
316
|
-
@screen lg {
|
|
317
|
-
.desktop-only {
|
|
318
|
-
display: block !important;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
.desktop-hidden {
|
|
322
|
-
display: none !important;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
/* Height-based responsive utilities */
|
|
327
|
-
@screen h-sm {
|
|
328
|
-
.short-screen-compact {
|
|
329
|
-
padding-top: 0.5rem !important;
|
|
330
|
-
padding-bottom: 0.5rem !important;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
.short-screen-hidden {
|
|
334
|
-
display: none !important;
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/* Touch device optimizations */
|
|
339
|
-
@screen touch {
|
|
340
|
-
.touch-larger {
|
|
341
|
-
min-height: 44px !important;
|
|
342
|
-
min-width: 44px !important;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
.touch-spacing {
|
|
346
|
-
margin: 0.25rem !important;
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
|
|
350
297
|
/* ==========================================================================
|
|
351
298
|
CONSOLE UTILITIES
|
|
352
299
|
========================================================================== */
|
package/src/assets/css/main.scss
CHANGED
|
@@ -125,31 +125,6 @@ body > .dropdown-content-portal,
|
|
|
125
125
|
-webkit-overflow-scrolling: touch !important;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
/* iPhone landscape mode - critical editor scrolling overrides */
|
|
129
|
-
@media (max-height: 500px) and (orientation: landscape) {
|
|
130
|
-
.code-editor,
|
|
131
|
-
.proxy-editor,
|
|
132
|
-
.editor-container,
|
|
133
|
-
.proxy-editor-container,
|
|
134
|
-
.editor-wrapper {
|
|
135
|
-
overflow: auto !important;
|
|
136
|
-
-webkit-overflow-scrolling: touch !important;
|
|
137
|
-
touch-action: pan-y !important;
|
|
138
|
-
overscroll-behavior: contain !important;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
body {
|
|
142
|
-
overflow-y: auto !important;
|
|
143
|
-
touch-action: pan-y !important;
|
|
144
|
-
overscroll-behavior: contain !important;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
html {
|
|
148
|
-
overflow-y: auto !important;
|
|
149
|
-
overscroll-behavior: contain !important;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
128
|
/* ==========================================================================
|
|
154
129
|
BODY & LAYOUT
|
|
155
130
|
========================================================================== */
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Table>
|
|
3
|
-
<Header class="text-center grid-cols-5 md:grid-cols-7">
|
|
3
|
+
<Header class="text-center grid-cols-5 md:grid-cols-7 sticky top-0 bg-dark-400 z-10">
|
|
4
4
|
<div class="lg:col-span-2 col-span-3 flex">
|
|
5
5
|
<Checkbox
|
|
6
6
|
class="mr-3"
|
|
7
7
|
:toggled="ui.mainCheckbox.accounts"
|
|
8
8
|
@valueUpdate="ui.toggleMainCheckbox('accounts')"
|
|
9
|
-
:isHeader="true"
|
|
10
|
-
/>
|
|
9
|
+
:isHeader="true" />
|
|
11
10
|
<div class="mx-auto flex items-center" @click="ui.toggleSort('eventId')">
|
|
12
11
|
<MailIcon class="mr-0 md:mr-3 w-4 h-4" />
|
|
13
12
|
<h4 class="hidden md:flex">Email</h4>
|
|
@@ -30,21 +29,21 @@
|
|
|
30
29
|
<h4 class="hidden md:flex">Actions</h4>
|
|
31
30
|
</div>
|
|
32
31
|
</Header>
|
|
33
|
-
<div
|
|
32
|
+
<div
|
|
33
|
+
v-if="toRender.length != 0"
|
|
34
|
+
class="overflow-y-auto hidden-scrollbars overflow-x-hidden stop-pan"
|
|
35
|
+
:style="{ maxHeight: dynamicTableHeight }">
|
|
34
36
|
<RecycleScroller
|
|
35
37
|
:items="toRender"
|
|
36
38
|
:item-size="64"
|
|
37
39
|
key-field="index"
|
|
38
|
-
class="scroller vue-recycle-scroller ready direction-vertical flex flex-col divide-y divide-dark-650
|
|
39
|
-
:style="{ maxHeight: dynamicTableHeight }"
|
|
40
|
-
>
|
|
40
|
+
class="scroller vue-recycle-scroller ready direction-vertical flex flex-col divide-y divide-dark-650">
|
|
41
41
|
<template #default="props">
|
|
42
42
|
<div class="account" :key="`account-${props.item._id || props.item.index}`">
|
|
43
43
|
<Account
|
|
44
44
|
@click="i[props.item.index]++"
|
|
45
45
|
:class="props.item.index % 2 == 1 ? 'table-row-even' : 'table-row-odd'"
|
|
46
|
-
:account="props.item"
|
|
47
|
-
/>
|
|
46
|
+
:account="props.item" />
|
|
48
47
|
</div>
|
|
49
48
|
</template>
|
|
50
49
|
</RecycleScroller>
|
|
@@ -138,19 +137,19 @@ const dynamicTableHeight = computed(() => {
|
|
|
138
137
|
const searchHeight = 50; // Search and filter controls
|
|
139
138
|
const margins = windowWidth.value >= 1024 ? 40 : 25;
|
|
140
139
|
const bufferSpace = 50; // Conservative buffer to prevent partial items
|
|
141
|
-
|
|
140
|
+
|
|
142
141
|
const totalUsedSpace = headerHeight + titleHeight + searchHeight + margins + bufferSpace;
|
|
143
142
|
const availableHeight = windowHeight.value - totalUsedSpace;
|
|
144
|
-
|
|
143
|
+
|
|
145
144
|
// Account row height is always 64px
|
|
146
145
|
const rowHeight = 64;
|
|
147
146
|
const minRowsToShow = 2;
|
|
148
147
|
const minHeight = minRowsToShow * rowHeight;
|
|
149
|
-
|
|
148
|
+
|
|
150
149
|
// Calculate exact number of complete rows that fit with conservative approach
|
|
151
150
|
const maxCompleteRows = Math.floor(Math.max(availableHeight, minHeight) / rowHeight);
|
|
152
151
|
const exactHeight = maxCompleteRows * rowHeight;
|
|
153
|
-
|
|
152
|
+
|
|
154
153
|
return exactHeight + "px";
|
|
155
154
|
});
|
|
156
155
|
</script>
|
|
@@ -13,16 +13,14 @@
|
|
|
13
13
|
:style="menuStyle"
|
|
14
14
|
@click.stop
|
|
15
15
|
@wheel.stop
|
|
16
|
-
@touchmove.stop
|
|
17
|
-
>
|
|
16
|
+
@touchmove.stop>
|
|
18
17
|
<div
|
|
19
18
|
v-for="(country, i) in countries"
|
|
20
19
|
v-bind:key="country"
|
|
21
20
|
:class="`cursor-pointer w-12 ${i === 0 ? '' : 'my-2'}`"
|
|
22
|
-
@click="set(country)"
|
|
23
|
-
>
|
|
21
|
+
@click="set(country)">
|
|
24
22
|
<div class="flex justify-center items-center smooth-hover">
|
|
25
|
-
<span class="text-sm">{{ country }}
|
|
23
|
+
<span class="text-sm">{{ country }}</span>
|
|
26
24
|
<img class="w-5 ml-3" :src="`/flags/${country?.toLowerCase()}.svg`" />
|
|
27
25
|
</div>
|
|
28
26
|
</div>
|
|
@@ -91,11 +89,11 @@ watch(
|
|
|
91
89
|
}
|
|
92
90
|
|
|
93
91
|
.small-dropdown {
|
|
92
|
+
@apply h-10 !important;
|
|
94
93
|
background-clip: border-box !important;
|
|
95
94
|
/* border-radius: 100% !important; */
|
|
96
95
|
padding: 0;
|
|
97
96
|
width: 3em !important;
|
|
98
|
-
height: 3.45em !important; /* Match input-default height */
|
|
99
97
|
display: flex;
|
|
100
98
|
justify-items: center;
|
|
101
99
|
justify-content: center;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Modal class="overflow-y-scroll max-w-screen">
|
|
3
|
-
<template #header>
|
|
3
|
+
<template #header>
|
|
4
|
+
Filter JSON data
|
|
5
|
+
<FilterIcon class="ml-4" />
|
|
6
|
+
</template>
|
|
4
7
|
|
|
5
8
|
<div class="my-3">
|
|
6
9
|
<div class="editor-container">
|
|
@@ -13,27 +16,16 @@
|
|
|
13
16
|
spellcheck="false"
|
|
14
17
|
@scroll="syncScroll"
|
|
15
18
|
@input="highlightCode"
|
|
16
|
-
@keydown.tab.prevent="handleTab"
|
|
17
|
-
></textarea>
|
|
19
|
+
@keydown.tab.prevent="handleTab"></textarea>
|
|
18
20
|
</div>
|
|
19
21
|
</div>
|
|
20
22
|
<p class="text-red-400 text-bold mt-2">{{ errorMessage }}</p>
|
|
21
23
|
</div>
|
|
22
24
|
|
|
23
25
|
<div class="ml-auto flex">
|
|
24
|
-
<button
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
>
|
|
28
|
-
Apply
|
|
29
|
-
</button>
|
|
30
|
-
|
|
31
|
-
<button
|
|
32
|
-
class="btn-action ml-2"
|
|
33
|
-
@click="done()"
|
|
34
|
-
>
|
|
35
|
-
Close
|
|
36
|
-
</button>
|
|
26
|
+
<button class="btn-action" @click="save()">Apply</button>
|
|
27
|
+
|
|
28
|
+
<button class="btn-action ml-2" @click="done()">Close</button>
|
|
37
29
|
</div>
|
|
38
30
|
</Modal>
|
|
39
31
|
</template>
|
|
@@ -72,7 +64,7 @@
|
|
|
72
64
|
/* Make text completely transparent */
|
|
73
65
|
color: rgba(0, 0, 0, 0);
|
|
74
66
|
caret-color: #e2e8f0;
|
|
75
|
-
font-family:
|
|
67
|
+
font-family: "JetBrains Mono", "Fira Code", "Menlo", "Monaco", "Courier New", monospace;
|
|
76
68
|
padding: 12px;
|
|
77
69
|
border: none;
|
|
78
70
|
resize: none;
|
|
@@ -92,7 +84,6 @@
|
|
|
92
84
|
overflow: auto;
|
|
93
85
|
}
|
|
94
86
|
|
|
95
|
-
|
|
96
87
|
.code-highlight {
|
|
97
88
|
width: 100%;
|
|
98
89
|
height: 100%;
|
|
@@ -100,7 +91,7 @@
|
|
|
100
91
|
max-height: 500px;
|
|
101
92
|
overflow: auto;
|
|
102
93
|
white-space: pre;
|
|
103
|
-
font-family:
|
|
94
|
+
font-family: "JetBrains Mono", "Fira Code", "Menlo", "Monaco", "Courier New", monospace;
|
|
104
95
|
font-size: 14px;
|
|
105
96
|
line-height: 1.6;
|
|
106
97
|
background-color: transparent !important;
|
|
@@ -133,30 +124,26 @@ const codeDisplay = ref(null);
|
|
|
133
124
|
// Function to highlight code using Prism
|
|
134
125
|
const highlightCode = () => {
|
|
135
126
|
if (!codeDisplay.value || !codeEditor.value) return;
|
|
136
|
-
|
|
127
|
+
|
|
137
128
|
// Ensure Prism is available
|
|
138
|
-
if (typeof Prism ===
|
|
139
|
-
console.error(
|
|
129
|
+
if (typeof Prism === "undefined") {
|
|
130
|
+
console.error("Prism is not loaded");
|
|
140
131
|
return;
|
|
141
132
|
}
|
|
142
|
-
|
|
133
|
+
|
|
143
134
|
// Use requestAnimationFrame for smoother updates
|
|
144
135
|
requestAnimationFrame(() => {
|
|
145
136
|
try {
|
|
146
137
|
// Update the pre element with highlighted HTML
|
|
147
|
-
const highlighted = Prism.highlight(
|
|
148
|
-
text.value || '',
|
|
149
|
-
Prism.languages.json,
|
|
150
|
-
'json'
|
|
151
|
-
);
|
|
138
|
+
const highlighted = Prism.highlight(text.value || "", Prism.languages.json, "json");
|
|
152
139
|
codeDisplay.value.innerHTML = highlighted;
|
|
153
|
-
codeDisplay.value.className =
|
|
140
|
+
codeDisplay.value.className = "language-json code-highlight";
|
|
154
141
|
} catch (e) {
|
|
155
142
|
console.error("Highlight error:", e);
|
|
156
143
|
// Fallback to plain text if highlighting fails
|
|
157
|
-
codeDisplay.value.textContent = text.value ||
|
|
144
|
+
codeDisplay.value.textContent = text.value || "";
|
|
158
145
|
}
|
|
159
|
-
|
|
146
|
+
|
|
160
147
|
// Ensure scroll positions are synced after highlighting
|
|
161
148
|
syncScroll();
|
|
162
149
|
});
|
|
@@ -165,7 +152,7 @@ const highlightCode = () => {
|
|
|
165
152
|
// Function to sync scrolling between textarea and highlighted code
|
|
166
153
|
const syncScroll = () => {
|
|
167
154
|
if (!codeDisplay.value || !codeEditor.value) return;
|
|
168
|
-
|
|
155
|
+
|
|
169
156
|
// Synchronize scrolling between the textarea and the highlighted code
|
|
170
157
|
requestAnimationFrame(() => {
|
|
171
158
|
codeDisplay.value.scrollTop = codeEditor.value.scrollTop;
|
|
@@ -178,11 +165,11 @@ const handleTab = (e) => {
|
|
|
178
165
|
const textarea = codeEditor.value;
|
|
179
166
|
const start = textarea.selectionStart;
|
|
180
167
|
const end = textarea.selectionEnd;
|
|
181
|
-
|
|
168
|
+
|
|
182
169
|
// Insert 4 spaces at cursor position
|
|
183
|
-
const spaces =
|
|
170
|
+
const spaces = " ";
|
|
184
171
|
text.value = text.value.substring(0, start) + spaces + text.value.substring(end);
|
|
185
|
-
|
|
172
|
+
|
|
186
173
|
// Move cursor position after the inserted tab
|
|
187
174
|
nextTick(() => {
|
|
188
175
|
textarea.selectionStart = textarea.selectionEnd = start + spaces.length;
|
|
@@ -195,12 +182,12 @@ onMounted(() => {
|
|
|
195
182
|
// Apply highlighting when the component is mounted
|
|
196
183
|
nextTick(() => {
|
|
197
184
|
highlightCode();
|
|
198
|
-
|
|
185
|
+
|
|
199
186
|
// Ensure scroll synchronization on initial load
|
|
200
187
|
if (codeEditor.value && codeDisplay.value) {
|
|
201
188
|
syncScroll();
|
|
202
189
|
}
|
|
203
|
-
|
|
190
|
+
|
|
204
191
|
// Focus the editor
|
|
205
192
|
if (codeEditor.value) {
|
|
206
193
|
codeEditor.value.focus();
|