@necrolab/dashboard 0.4.48 → 0.4.49

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.
Files changed (38) hide show
  1. package/.claude/settings.local.json +2 -1
  2. package/exit +209 -0
  3. package/index.html +1 -1
  4. package/package.json +1 -1
  5. package/public/manifest.json +8 -3
  6. package/src/assets/css/_input.scss +104 -111
  7. package/src/assets/css/_utilities.scss +441 -0
  8. package/src/assets/css/main.scss +228 -154
  9. package/src/components/Auth/LoginForm.vue +8 -8
  10. package/src/components/Editors/Account/Account.vue +156 -146
  11. package/src/components/Editors/Account/AccountCreator.vue +1 -1
  12. package/src/components/Editors/Account/AccountView.vue +13 -13
  13. package/src/components/Editors/Account/CreateAccount.vue +25 -16
  14. package/src/components/Editors/Profile/CreateProfile.vue +1 -1
  15. package/src/components/Editors/Profile/Profile.vue +1 -1
  16. package/src/components/Editors/Profile/ProfileCountryChooser.vue +83 -19
  17. package/src/components/Editors/Profile/ProfileView.vue +11 -11
  18. package/src/components/Tasks/CreateTaskAXS.vue +3 -3
  19. package/src/components/Tasks/CreateTaskTM.vue +7 -35
  20. package/src/components/Tasks/QuickSettings.vue +112 -9
  21. package/src/components/Tasks/Stats.vue +29 -25
  22. package/src/components/Tasks/Task.vue +489 -365
  23. package/src/components/Tasks/TaskView.vue +21 -23
  24. package/src/components/icons/Sandclock.vue +2 -2
  25. package/src/components/icons/Stadium.vue +1 -1
  26. package/src/components/ui/Modal.vue +37 -35
  27. package/src/components/ui/controls/CountryChooser.vue +200 -62
  28. package/src/components/ui/controls/atomic/Dropdown.vue +177 -91
  29. package/src/components/ui/controls/atomic/MultiDropdown.vue +247 -168
  30. package/src/composables/useClickOutside.js +21 -0
  31. package/src/composables/useDropdownPosition.js +174 -0
  32. package/src/stores/ui.js +5 -4
  33. package/src/views/Accounts.vue +2 -2
  34. package/src/views/Console.vue +25 -45
  35. package/src/views/Editor.vue +1194 -730
  36. package/src/views/Profiles.vue +2 -2
  37. package/src/views/Tasks.vue +170 -137
  38. package/tailwind.config.js +47 -21
@@ -52,7 +52,8 @@
52
52
  "Bash(timeout 10s npm run dev)",
53
53
  "Bash(gtimeout:*)",
54
54
  "Bash(echo $SHELL)",
55
- "Bash(mkdir:*)"
55
+ "Bash(mkdir:*)",
56
+ "Bash(base64:*)"
56
57
  ],
57
58
  "deny": []
58
59
  }
package/exit ADDED
@@ -0,0 +1,209 @@
1
+ #!/bin/bash
2
+
3
+ # 🎯 Necro Dashboard Exit - Fire Edition 🔥
4
+ # Enhanced exit script with style and robust functionality
5
+
6
+ # Colors for that fire output 🌈
7
+ RED='\033[0;31m'
8
+ GREEN='\033[0;32m'
9
+ YELLOW='\033[1;33m'
10
+ BLUE='\033[0;34m'
11
+ PURPLE='\033[0;35m'
12
+ CYAN='\033[0;36m'
13
+ WHITE='\033[1;37m'
14
+ BOLD='\033[1m'
15
+ NC='\033[0m' # No Color
16
+
17
+ # Fire emojis for maximum style
18
+ FIRE="🔥"
19
+ STOP="🛑"
20
+ GEAR="⚙️"
21
+ CHECK="✅"
22
+ CROSS="❌"
23
+ LIGHTNING="⚡"
24
+ SKULL="💀"
25
+
26
+ # Banner function
27
+ show_banner() {
28
+ echo -e "${RED}${BOLD}"
29
+ echo " ███╗ ██╗███████╗ ██████╗██████╗ ██████╗ "
30
+ echo " ████╗ ██║██╔════╝██╔════╝██╔══██╗██╔═══██╗"
31
+ echo " ██╔██╗ ██║█████╗ ██║ ██████╔╝██║ ██║"
32
+ echo " ██║╚██╗██║██╔══╝ ██║ ██╔══██╗██║ ██║"
33
+ echo " ██║ ╚████║███████╗╚██████╗██║ ██║╚██████╔╝"
34
+ echo " ╚═╝ ╚═══╝╚══════╝ ╚═════╝╚═╝ ╚═╝ ╚═════╝ "
35
+ echo -e "${NC}"
36
+ echo -e "${RED}${BOLD}Dashboard Exit ${SKULL} v2.0${NC}"
37
+ echo -e "${WHITE}────────────────────────────────────────────${NC}"
38
+ }
39
+
40
+ # Success message
41
+ success() {
42
+ echo -e "${GREEN}${BOLD}${CHECK} $1${NC}"
43
+ }
44
+
45
+ # Error message
46
+ error() {
47
+ echo -e "${RED}${BOLD}${CROSS} $1${NC}"
48
+ }
49
+
50
+ # Info message
51
+ info() {
52
+ echo -e "${CYAN}${BOLD}${LIGHTNING} $1${NC}"
53
+ }
54
+
55
+ # Warning message
56
+ warn() {
57
+ echo -e "${YELLOW}${BOLD}⚠️ $1${NC}"
58
+ }
59
+
60
+ # Check if lsof is available
61
+ check_lsof() {
62
+ if ! command -v lsof &> /dev/null; then
63
+ error "lsof is not installed or not in PATH"
64
+ warn "Install with: brew install lsof (macOS) or apt-get install lsof (Linux)"
65
+ exit 1
66
+ fi
67
+ }
68
+
69
+ # Function to kill process on a specific port with enhanced feedback
70
+ kill_port() {
71
+ local port=$1
72
+ local service_name=$2
73
+
74
+ info "Checking for processes on port ${port} (${service_name})..."
75
+
76
+ # Get PID using lsof
77
+ local pid=$(lsof -ti:$port 2>/dev/null)
78
+
79
+ if [ -n "$pid" ]; then
80
+ # Get process name for better feedback
81
+ local process_name=$(ps -p $pid -o comm= 2>/dev/null || echo "unknown")
82
+
83
+ warn "Found process: ${process_name} (PID: ${pid}) on port ${port}"
84
+
85
+ # Try graceful termination first
86
+ info "Attempting graceful shutdown..."
87
+ if kill -TERM $pid 2>/dev/null; then
88
+ sleep 2
89
+
90
+ # Check if process is still running
91
+ if kill -0 $pid 2>/dev/null; then
92
+ warn "Process still running, forcing termination..."
93
+ if kill -9 $pid 2>/dev/null; then
94
+ success "Process ${pid} forcefully terminated on port ${port}"
95
+ else
96
+ error "Failed to kill process ${pid} on port ${port}"
97
+ return 1
98
+ fi
99
+ else
100
+ success "Process ${pid} gracefully terminated on port ${port}"
101
+ fi
102
+ else
103
+ error "Failed to send termination signal to process ${pid}"
104
+ return 1
105
+ fi
106
+ else
107
+ info "No process found on port ${port} (${service_name})"
108
+ fi
109
+
110
+ return 0
111
+ }
112
+
113
+ # Function to kill all Node.js processes
114
+ kill_all_node() {
115
+ info "Searching for Node.js processes..."
116
+
117
+ local node_pids=$(pgrep -f "node" 2>/dev/null)
118
+
119
+ if [ -n "$node_pids" ]; then
120
+ warn "Found Node.js processes, terminating..."
121
+ echo "$node_pids" | while read -r pid; do
122
+ if [ -n "$pid" ]; then
123
+ local process_info=$(ps -p $pid -o args= 2>/dev/null || echo "unknown")
124
+ info "Killing Node.js process: $pid ($process_info)"
125
+ kill -TERM $pid 2>/dev/null || kill -9 $pid 2>/dev/null
126
+ fi
127
+ done
128
+ success "All Node.js processes terminated"
129
+ else
130
+ info "No Node.js processes found"
131
+ fi
132
+ }
133
+
134
+ # Function to clean up development servers
135
+ cleanup_dev_servers() {
136
+ info "Cleaning up development servers ${GEAR}"
137
+
138
+ # Kill specific ports used by the dashboard
139
+ kill_port 5173 "Vite Dev Server"
140
+ kill_port 8081 "Backend Server"
141
+ kill_port 3000 "Alternative Dev Server"
142
+ kill_port 8080 "Alternative Backend"
143
+
144
+ echo ""
145
+ }
146
+
147
+ # Help function
148
+ show_help() {
149
+ echo -e "${WHITE}${BOLD}Usage:${NC}"
150
+ echo -e " ${CYAN}./exit${NC} ${WHITE}Stop dashboard servers (ports 5173, 8081)${NC}"
151
+ echo -e " ${CYAN}./exit all${NC} ${WHITE}Stop all Node.js processes${NC}"
152
+ echo -e " ${CYAN}./exit port <n>${NC} ${WHITE}Stop process on specific port${NC}"
153
+ echo -e " ${CYAN}./exit help${NC} ${WHITE}Show this help message${NC}"
154
+ echo ""
155
+ echo -e "${WHITE}${BOLD}Examples:${NC}"
156
+ echo -e " ${YELLOW}./exit${NC} ${GREEN}# Stop dashboard servers${NC}"
157
+ echo -e " ${YELLOW}./exit all${NC} ${GREEN}# Nuclear option - kill all Node.js${NC}"
158
+ echo -e " ${YELLOW}./exit port 3000${NC} ${GREEN}# Stop specific port${NC}"
159
+ echo ""
160
+ echo -e "${RED}Made with ${SKULL} for clean shutdowns${NC}"
161
+ }
162
+
163
+ # Main execution flow
164
+ main() {
165
+ # Clear screen for clean output
166
+ clear
167
+
168
+ # Show the banner
169
+ show_banner
170
+
171
+ # Check dependencies
172
+ check_lsof
173
+
174
+ case "${1:-}" in
175
+ "all")
176
+ kill_all_node
177
+ ;;
178
+ "port")
179
+ if [ -z "$2" ]; then
180
+ error "Port number required"
181
+ echo -e "${CYAN}Usage: ./exit port <port_number>${NC}"
182
+ exit 1
183
+ fi
184
+ kill_port "$2" "Custom Port"
185
+ ;;
186
+ "help"|"-h"|"--help")
187
+ show_help
188
+ ;;
189
+ "")
190
+ cleanup_dev_servers
191
+ ;;
192
+ *)
193
+ warn "Unknown command: $1"
194
+ echo ""
195
+ show_help
196
+ exit 1
197
+ ;;
198
+ esac
199
+
200
+ echo ""
201
+ success "Exit sequence completed ${STOP}"
202
+ echo -e "${PURPLE}Dashboard processes have been terminated ${FIRE}${NC}"
203
+ }
204
+
205
+ # Error handling for script interruption
206
+ trap 'echo -e "\n${YELLOW}${BOLD}${LIGHTNING} Exit script interrupted${NC}"; exit 0' INT
207
+
208
+ # Run the main function
209
+ main "$@"
package/index.html CHANGED
@@ -97,7 +97,7 @@
97
97
  <link rel="preload" as="fetch" href="/manifest.json" crossorigin />
98
98
  <link rel="manifest" href="/manifest.json" />
99
99
  <meta name="theme-color" content="#1a1b1e" />
100
- <link rel="apple-touch-icon" href="/apple-touch-icon.png" />
100
+ <link rel="apple-touch-icon" href="/apple-touch-icon.png?v=2" />
101
101
 
102
102
  <!-- Prism.js for syntax highlighting -->
103
103
  <link
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@necrolab/dashboard",
3
- "version": "0.4.48",
3
+ "version": "0.4.49",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "build": "rm -rf dist && npx workbox-cli generateSW workbox-config.cjs && vite build",
@@ -2,21 +2,26 @@
2
2
  "short_name": "Necro",
3
3
  "name": "Necro Dashboard",
4
4
  "icons": [{
5
- "src": "/android-chrome-192x192.png",
5
+ "src": "/android-chrome-192x192.png?v=2",
6
6
  "type": "image/png",
7
7
  "sizes": "192x192"
8
8
  },
9
9
  {
10
- "src": "/android-chrome-192x192.png",
10
+ "src": "/android-chrome-192x192.png?v=2",
11
11
  "type": "image/png",
12
12
  "sizes": "192x192",
13
13
  "purpose": "any maskable"
14
14
 
15
15
  },
16
16
  {
17
- "src": "/android-chrome-512x512.png",
17
+ "src": "/android-chrome-512x512.png?v=2",
18
18
  "type": "image/png",
19
19
  "sizes": "512x512"
20
+ },
21
+ {
22
+ "src": "/apple-touch-icon.png?v=2",
23
+ "type": "image/png",
24
+ "sizes": "180x180"
20
25
  }
21
26
  ],
22
27
  "start_url": "/",
@@ -1,132 +1,87 @@
1
+ /* ==========================================================================
2
+ INPUT COMPONENTS STYLING
3
+ ========================================================================== */
4
+
1
5
  .input-default {
2
- @apply h-12 bg-dark-500 flex items-center bg-clip-padding rounded-lg relative box-border border-dark-550 border-2;
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;
8
+ transition: border-color 0.15s ease;
3
9
 
4
- input {
5
- @apply h-full w-full px-4 focus:outline-none text-xs text-white;
6
- background-color: transparent;
10
+ &:focus-within {
11
+ @apply border-dark-700;
7
12
  }
8
13
 
9
- /* When input has incrementer, add right padding */
10
- &:has(.input-incrementer) input {
11
- @apply pr-10;
14
+ input {
15
+ @apply h-full w-full focus:outline-none text-sm text-white;
16
+ background: transparent;
12
17
  }
13
18
 
14
- /* Required field indicator */
15
- &.required {
16
- /* Professional style with colored border */
17
- border-left: 3px solid rgba(239, 68, 68, 0.7);
19
+ .input-incrementer {
20
+ @apply flex flex-col ml-2 gap-0.5;
18
21
 
19
- /* Red bullet indicator directly in the field */
20
- &::after {
21
- content: "";
22
- position: absolute;
23
- right: 8px;
24
- top: 50%;
25
- transform: translateY(-50%);
26
- width: 6px;
27
- height: 6px;
28
- border-radius: 50%;
29
- background-color: #ef4444;
22
+ button {
23
+ @apply w-6 h-4 flex items-center justify-center text-white transition-all duration-200 rounded-sm border border-dark-650;
24
+ background: linear-gradient(135deg, #2a2b30 0%, #2e2f34 100%);
25
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
26
+
27
+ &:hover {
28
+ @apply border-dark-700;
29
+ background: linear-gradient(135deg, #2e2f34 0%, #32333a 100%);
30
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
31
+ transform: translateY(-0.5px);
32
+ }
33
+
34
+ &:active {
35
+ @apply border-dark-600;
36
+ background: linear-gradient(135deg, #26272c 0%, #2a2b30 100%);
37
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3);
38
+ transform: translateY(0);
39
+ }
40
+
41
+ &:first-child {
42
+ border-radius: 4px 4px 2px 2px;
43
+ }
44
+
45
+ &:last-child {
46
+ border-radius: 2px 2px 4px 4px;
47
+ }
30
48
  }
31
49
 
32
- &:has(.input-incrementer)::after {
33
- right: 16px;
50
+ svg {
51
+ @apply w-2.5 h-2.5;
52
+ filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.3));
34
53
  }
35
54
  }
36
55
  }
37
- .input-wrapper {
38
- @apply z-20;
39
56
 
40
- label {
41
- @apply text-xs text-light-300 block;
42
- }
57
+ .input-wrapper label {
58
+ @apply text-white font-medium mb-2 block;
59
+ font-size: 16px;
43
60
  }
44
61
 
45
62
  .button-default {
46
63
  @apply text-white font-medium h-12 rounded-lg duration-150 border border-dark-650 hover:border-dark-700 !important;
47
64
  }
48
65
 
49
- // Remove number input spinners
66
+ /* Remove number input spinners */
50
67
  input[type="number"] {
51
- -webkit-appearance: textfield;
52
68
  -moz-appearance: textfield;
53
- appearance: textfield;
54
-
55
- &::-webkit-inner-spin-button,
56
- &::-webkit-outer-spin-button {
57
- -webkit-appearance: none;
58
- }
59
69
  }
60
70
 
61
- .input-incrementer {
62
- @apply flex flex-col absolute right-2 top-1/2 transform -translate-y-1/2 !important;
63
- gap: 2px;
64
-
65
-
66
- button {
67
- @apply w-6 h-4 flex items-center justify-center transition-all duration-150 rounded-sm;
68
- background: rgba(46, 47, 52, 0.8);
69
- border: 1px solid rgba(61, 62, 68, 0.6);
70
- color: rgba(255, 255, 255, 0.9);
71
- font-size: 8px;
72
-
73
- &:hover {
74
- background: rgba(68, 69, 75, 0.9);
75
- border-color: rgba(255, 255, 255, 0.4);
76
- color: white;
77
- }
78
-
79
- &:active {
80
- background: rgba(35, 36, 41, 0.9);
81
- }
82
-
83
- svg {
84
- @apply w-2.5 h-2.5;
85
- }
86
- }
71
+ input[type="number"]::-webkit-outer-spin-button,
72
+ input[type="number"]::-webkit-inner-spin-button {
73
+ -webkit-appearance: none;
74
+ margin: 0;
87
75
  }
88
76
 
89
- // Mobile responsive adjustments
90
- @media (max-width: 810px) {
91
- .input-default {
92
- height: 40px;
93
-
94
- input {
95
- font-size: 12px;
96
- }
97
-
98
- .input-incrementer button {
99
- @apply w-5 h-3;
100
-
101
- svg {
102
- @apply w-2 h-2;
103
- }
104
- }
105
- }
106
-
107
- .input-wrapper label {
108
- font-size: 15px;
109
- }
110
-
111
- .ant-select {
112
- height: fit-content;
113
- min-height: 40px;
114
- padding: 0;
115
-
116
- &-show-search:not(.ant-select-customize-input) .ant-select-selector {
117
- font-size: 12px;
118
- }
77
+ /* ==========================================================================
78
+ ANT DESIGN SELECT STYLING
79
+ ========================================================================== */
119
80
 
120
- &-multiple .ant-select-selection-item {
121
- height: 25px;
122
- }
123
- }
124
- }
125
- // Ant Design Select styling
126
81
  .ant-select-dropdown {
127
82
  z-index: 10000 !important;
128
83
  position: relative;
129
- @apply rounded-lg !important;
84
+ @apply rounded-lg bg-dark-400 !important;
130
85
  }
131
86
 
132
87
  .ant-select {
@@ -140,10 +95,15 @@ input[type="number"] {
140
95
  background-color: transparent !important;
141
96
  border: 0 !important;
142
97
  box-shadow: 0 0 0 !important;
98
+
99
+ &:before {
100
+ content: "";
101
+ position: absolute;
102
+ @apply bg-light-400 h-1 w-1 right-1 rounded-full !important;
103
+ }
143
104
  }
144
105
  }
145
106
 
146
- // Ant Design Select item styling
147
107
  .ant-select-multiple .ant-select-selection-item {
148
108
  @apply bg-dark-400 items-center gap-x-4 !important;
149
109
  padding-inline-end: 15px;
@@ -151,17 +111,19 @@ input[type="number"] {
151
111
  border-radius: 10px;
152
112
  height: 40px;
153
113
  border: 0;
114
+ color: #ffffff;
154
115
 
155
116
  &-remove > .anticon {
156
117
  vertical-align: 0.05rem;
157
118
  }
158
119
  }
120
+
159
121
  .ant-select-selection-item-remove > .anticon svg {
160
122
  color: #fff;
161
- }
162
123
 
163
- .ant-select-selection-item-remove > .anticon svg path {
164
- fill: currentColor;
124
+ path {
125
+ fill: currentColor;
126
+ }
165
127
  }
166
128
 
167
129
  .ant-select-item-option {
@@ -186,12 +148,43 @@ input[type="number"] {
186
148
  }
187
149
  }
188
150
 
189
- .ant-select-dropdown {
190
- @apply bg-dark-400 !important;
191
- }
151
+ /* ==========================================================================
152
+ RESPONSIVE ADJUSTMENTS
153
+ ========================================================================== */
154
+
155
+ @screen md {
156
+ .input-default {
157
+ height: 40px;
158
+
159
+ input {
160
+ font-size: 12px;
161
+ }
192
162
 
193
- .ant-select-selector:before {
194
- content: "";
195
- position: absolute;
196
- @apply bg-light-400 h-1 w-1 right-1 rounded-full !important;
163
+ .input-incrementer button {
164
+ @apply w-5 h-3;
165
+
166
+ svg {
167
+ @apply w-2 h-2;
168
+ }
169
+ }
170
+ }
171
+
172
+ .input-wrapper label {
173
+ font-size: 15px;
174
+ }
175
+
176
+ .ant-select {
177
+ height: fit-content;
178
+ min-height: 40px;
179
+ padding: 0;
180
+
181
+ &-show-search:not(.ant-select-customize-input) .ant-select-selector {
182
+ font-size: 12px;
183
+ }
184
+
185
+ &-multiple .ant-select-selection-item {
186
+ height: 25px;
187
+ font-size: 10px;
188
+ }
189
+ }
197
190
  }