sidekiq_queue_manager 1.0.2 → 1.1.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.
@@ -236,10 +236,48 @@
236
236
 
237
237
  .sqm-stats-grid {
238
238
  display: grid;
239
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
239
+ grid-template-columns: repeat(7, 1fr);
240
240
  gap: 1rem;
241
241
  }
242
242
 
243
+ @media (max-width: 1200px) {
244
+ .sqm-stats-grid {
245
+ grid-template-columns: repeat(4, 1fr);
246
+ }
247
+ }
248
+
249
+ @media (max-width: 900px) {
250
+ .sqm-stats-grid {
251
+ grid-template-columns: repeat(2, 1fr);
252
+ }
253
+ }
254
+
255
+ @media (max-width: 600px) {
256
+ .sqm-stats-grid {
257
+ grid-template-columns: 1fr;
258
+ }
259
+
260
+ .sqm-stat-card {
261
+ padding: 0.75rem;
262
+ text-align: center;
263
+ }
264
+
265
+ .sqm-stat-value {
266
+ font-size: 1.5rem !important;
267
+ }
268
+
269
+ .sqm-stat-value[data-length="8"],
270
+ .sqm-stat-value[data-length="9"],
271
+ .sqm-stat-value[data-length="10"],
272
+ .sqm-stat-value[data-length="11"],
273
+ .sqm-stat-value[data-length="12"],
274
+ .sqm-stat-value[data-length="13"],
275
+ .sqm-stat-value[data-length="14"],
276
+ .sqm-stat-value[data-length="long"] {
277
+ font-size: 1.25rem !important;
278
+ }
279
+ }
280
+
243
281
  .sqm-stat-card {
244
282
  background: var(--sqm-card);
245
283
  border: 1px solid var(--sqm-border);
@@ -248,6 +286,7 @@
248
286
  transition: var(--sqm-transition);
249
287
  position: relative;
250
288
  overflow: hidden;
289
+ min-width: 0; /* Allow flex shrinking */
251
290
  }
252
291
 
253
292
  .sqm-stat-card:hover {
@@ -268,7 +307,28 @@
268
307
  font-weight: 700;
269
308
  color: var(--sqm-foreground);
270
309
  font-family: var(--sqm-font-mono);
271
- line-height: 1;
310
+ line-height: 1.1;
311
+ word-break: break-all;
312
+ overflow-wrap: break-word;
313
+ min-width: 0;
314
+ }
315
+
316
+ /* Responsive font sizing for large numbers */
317
+ .sqm-stat-value[data-length="8"],
318
+ .sqm-stat-value[data-length="9"] {
319
+ font-size: 1.5rem;
320
+ }
321
+
322
+ .sqm-stat-value[data-length="10"],
323
+ .sqm-stat-value[data-length="11"] {
324
+ font-size: 1.25rem;
325
+ }
326
+
327
+ .sqm-stat-value[data-length="12"],
328
+ .sqm-stat-value[data-length="13"],
329
+ .sqm-stat-value[data-length="14"],
330
+ .sqm-stat-value[data-length="long"] {
331
+ font-size: 1rem;
272
332
  }
273
333
 
274
334
  /* ========================================
@@ -933,11 +993,6 @@
933
993
  gap: 0.75rem;
934
994
  }
935
995
 
936
- .sqm-stats-grid {
937
- grid-template-columns: 1fr;
938
- gap: 0.75rem;
939
- }
940
-
941
996
  .sqm-controls {
942
997
  flex-direction: column;
943
998
  align-items: stretch;
@@ -1015,4 +1070,409 @@
1015
1070
  transition-duration: 0.01ms !important;
1016
1071
  scroll-behavior: auto !important;
1017
1072
  }
1073
+ }
1074
+
1075
+ /* ========================================
1076
+ Tab Navigation System
1077
+ ======================================== */
1078
+
1079
+ .sqm-tabs-nav {
1080
+ display: flex;
1081
+ align-items: center;
1082
+ gap: 0.125rem;
1083
+ margin-bottom: 1.5rem;
1084
+ padding: 0.25rem;
1085
+ background: var(--sqm-muted);
1086
+ border-radius: var(--sqm-radius);
1087
+ border: 1px solid var(--sqm-border);
1088
+ }
1089
+
1090
+ .sqm-tab {
1091
+ display: flex;
1092
+ align-items: center;
1093
+ gap: 0.5rem;
1094
+ padding: 0.75rem 1rem;
1095
+ font-size: 0.875rem;
1096
+ font-weight: 500;
1097
+ line-height: 1;
1098
+ color: var(--sqm-muted-foreground);
1099
+ background: transparent;
1100
+ border: none;
1101
+ border-radius: var(--sqm-radius-sm);
1102
+ cursor: pointer;
1103
+ transition: var(--sqm-transition);
1104
+ white-space: nowrap;
1105
+ min-height: 2.5rem;
1106
+ }
1107
+
1108
+ .sqm-tab:hover {
1109
+ color: var(--sqm-foreground);
1110
+ background: var(--sqm-accent);
1111
+ }
1112
+
1113
+ .sqm-tab:focus {
1114
+ outline: 2px solid var(--sqm-ring);
1115
+ outline-offset: 2px;
1116
+ }
1117
+
1118
+ .sqm-tab-active {
1119
+ color: var(--sqm-foreground);
1120
+ background: var(--sqm-background);
1121
+ border: 1px solid var(--sqm-border);
1122
+ box-shadow: var(--sqm-shadow-sm);
1123
+ }
1124
+
1125
+ .sqm-tab-active:hover {
1126
+ background: var(--sqm-background);
1127
+ }
1128
+
1129
+ .sqm-tab svg {
1130
+ flex-shrink: 0;
1131
+ width: 1rem;
1132
+ height: 1rem;
1133
+ }
1134
+
1135
+ .sqm-tab-count {
1136
+ display: inline-flex;
1137
+ align-items: center;
1138
+ justify-content: center;
1139
+ min-width: 1.25rem;
1140
+ height: 1.25rem;
1141
+ padding: 0 0.375rem;
1142
+ font-size: 0.75rem;
1143
+ font-weight: 600;
1144
+ line-height: 1;
1145
+ color: var(--sqm-muted-foreground);
1146
+ background: var(--sqm-muted);
1147
+ border-radius: 0.625rem;
1148
+ transition: var(--sqm-transition);
1149
+ }
1150
+
1151
+ .sqm-tab-active .sqm-tab-count {
1152
+ color: var(--sqm-primary-foreground);
1153
+ background: var(--sqm-primary);
1154
+ }
1155
+
1156
+ /* ========================================
1157
+ Tab Content System
1158
+ ======================================== */
1159
+
1160
+ .sqm-tab-content {
1161
+ position: relative;
1162
+ }
1163
+
1164
+ .sqm-tab-panel {
1165
+ display: block;
1166
+ outline: none;
1167
+ }
1168
+
1169
+ .sqm-tab-panel.sqm-hidden {
1170
+ display: none;
1171
+ }
1172
+
1173
+ .sqm-tab-panel-active {
1174
+ display: block;
1175
+ }
1176
+
1177
+ /* ========================================
1178
+ Section Controls
1179
+ ======================================== */
1180
+
1181
+ .sqm-section-controls {
1182
+ display: flex;
1183
+ align-items: center;
1184
+ justify-content: space-between;
1185
+ gap: 1rem;
1186
+ margin-bottom: 1.5rem;
1187
+ padding: 1rem;
1188
+ background: var(--sqm-card);
1189
+ border: 1px solid var(--sqm-border);
1190
+ border-radius: var(--sqm-radius);
1191
+ }
1192
+
1193
+ .sqm-controls-left,
1194
+ .sqm-controls-right {
1195
+ display: flex;
1196
+ align-items: center;
1197
+ gap: 0.75rem;
1198
+ }
1199
+
1200
+ .sqm-filter-input {
1201
+ width: 240px;
1202
+ height: 2.5rem;
1203
+ padding: 0 0.75rem;
1204
+ font-size: 0.875rem;
1205
+ color: var(--sqm-foreground);
1206
+ background: var(--sqm-background);
1207
+ border: 1px solid var(--sqm-border);
1208
+ border-radius: var(--sqm-radius);
1209
+ transition: var(--sqm-transition);
1210
+ }
1211
+
1212
+ .sqm-filter-input:focus {
1213
+ outline: none;
1214
+ border-color: var(--sqm-ring);
1215
+ box-shadow: 0 0 0 2px rgba(var(--sqm-ring), 0.2);
1216
+ }
1217
+
1218
+ .sqm-filter-input::placeholder {
1219
+ color: var(--sqm-muted-foreground);
1220
+ }
1221
+
1222
+ /* ========================================
1223
+ Pagination System
1224
+ ======================================== */
1225
+
1226
+ .sqm-pagination {
1227
+ display: flex;
1228
+ align-items: center;
1229
+ justify-content: space-between;
1230
+ margin-top: 1.5rem;
1231
+ padding: 1rem;
1232
+ background: var(--sqm-card);
1233
+ border: 1px solid var(--sqm-border);
1234
+ border-radius: var(--sqm-radius);
1235
+ }
1236
+
1237
+ .sqm-pagination-info {
1238
+ font-size: 0.875rem;
1239
+ color: var(--sqm-muted-foreground);
1240
+ }
1241
+
1242
+ .sqm-pagination-controls {
1243
+ display: flex;
1244
+ align-items: center;
1245
+ gap: 0.5rem;
1246
+ }
1247
+
1248
+ .sqm-pagination-btn {
1249
+ display: flex;
1250
+ align-items: center;
1251
+ justify-content: center;
1252
+ width: 2.5rem;
1253
+ height: 2.5rem;
1254
+ font-size: 0.875rem;
1255
+ font-weight: 500;
1256
+ color: var(--sqm-foreground);
1257
+ background: var(--sqm-background);
1258
+ border: 1px solid var(--sqm-border);
1259
+ border-radius: var(--sqm-radius);
1260
+ cursor: pointer;
1261
+ transition: var(--sqm-transition);
1262
+ }
1263
+
1264
+ .sqm-pagination-btn:hover:not(:disabled) {
1265
+ background: var(--sqm-accent);
1266
+ }
1267
+
1268
+ .sqm-pagination-btn:disabled {
1269
+ color: var(--sqm-muted-foreground);
1270
+ cursor: not-allowed;
1271
+ opacity: 0.5;
1272
+ }
1273
+
1274
+ .sqm-pagination-btn svg {
1275
+ width: 1rem;
1276
+ height: 1rem;
1277
+ }
1278
+
1279
+ .sqm-pagination-current {
1280
+ background: var(--sqm-primary);
1281
+ color: var(--sqm-primary-foreground);
1282
+ border-color: var(--sqm-primary);
1283
+ }
1284
+
1285
+ .sqm-pagination-current:hover {
1286
+ background: var(--sqm-primary);
1287
+ }
1288
+
1289
+ /* ========================================
1290
+ Enhanced Table Styles for New Tabs
1291
+ ======================================== */
1292
+
1293
+ .sqm-scheduled-section .sqm-table,
1294
+ .sqm-retries-section .sqm-table,
1295
+ .sqm-dead-section .sqm-table {
1296
+ margin-top: 0;
1297
+ }
1298
+
1299
+ .sqm-table .sqm-error-preview {
1300
+ max-width: 200px;
1301
+ font-family: var(--sqm-font-mono);
1302
+ font-size: 0.75rem;
1303
+ color: var(--sqm-destructive);
1304
+ white-space: nowrap;
1305
+ overflow: hidden;
1306
+ text-overflow: ellipsis;
1307
+ }
1308
+
1309
+ .sqm-table .sqm-time-relative {
1310
+ font-size: 0.75rem;
1311
+ color: var(--sqm-muted-foreground);
1312
+ white-space: nowrap;
1313
+ }
1314
+
1315
+ .sqm-table .sqm-job-args {
1316
+ max-width: 150px;
1317
+ font-family: var(--sqm-font-mono);
1318
+ font-size: 0.75rem;
1319
+ color: var(--sqm-muted-foreground);
1320
+ white-space: nowrap;
1321
+ overflow: hidden;
1322
+ text-overflow: ellipsis;
1323
+ }
1324
+
1325
+ .sqm-table .sqm-retry-count {
1326
+ display: inline-flex;
1327
+ align-items: center;
1328
+ gap: 0.25rem;
1329
+ font-size: 0.75rem;
1330
+ font-weight: 500;
1331
+ }
1332
+
1333
+ .sqm-table .sqm-retry-progress {
1334
+ display: inline-block;
1335
+ width: 60px;
1336
+ height: 4px;
1337
+ background: var(--sqm-muted);
1338
+ border-radius: 2px;
1339
+ overflow: hidden;
1340
+ }
1341
+
1342
+ .sqm-table .sqm-retry-progress-bar {
1343
+ height: 100%;
1344
+ background: var(--sqm-warning);
1345
+ transition: width 0.3s ease;
1346
+ }
1347
+
1348
+ /* ========================================
1349
+ Job Status Indicators
1350
+ ======================================== */
1351
+
1352
+ .sqm-job-status {
1353
+ display: inline-flex;
1354
+ align-items: center;
1355
+ gap: 0.375rem;
1356
+ padding: 0.25rem 0.5rem;
1357
+ font-size: 0.75rem;
1358
+ font-weight: 500;
1359
+ border-radius: var(--sqm-radius-sm);
1360
+ }
1361
+
1362
+ .sqm-job-status-scheduled {
1363
+ color: var(--sqm-info-foreground);
1364
+ background: var(--sqm-info);
1365
+ }
1366
+
1367
+ .sqm-job-status-retrying {
1368
+ color: var(--sqm-warning-foreground);
1369
+ background: var(--sqm-warning);
1370
+ }
1371
+
1372
+ .sqm-job-status-dead {
1373
+ color: var(--sqm-destructive-foreground);
1374
+ background: var(--sqm-destructive);
1375
+ }
1376
+
1377
+ .sqm-job-status-dot {
1378
+ width: 0.375rem;
1379
+ height: 0.375rem;
1380
+ border-radius: 50%;
1381
+ background: currentColor;
1382
+ }
1383
+
1384
+ /* ========================================
1385
+ Action Button Variants for Job Management
1386
+ ======================================== */
1387
+
1388
+ .sqm-btn-enqueue {
1389
+ color: var(--sqm-info-foreground);
1390
+ background: var(--sqm-info);
1391
+ border-color: var(--sqm-info);
1392
+ }
1393
+
1394
+ .sqm-btn-enqueue:hover {
1395
+ background: hsl(199.1 89.1% 42%);
1396
+ }
1397
+
1398
+ .sqm-btn-resurrect {
1399
+ color: var(--sqm-success-foreground);
1400
+ background: var(--sqm-success);
1401
+ border-color: var(--sqm-success);
1402
+ }
1403
+
1404
+ .sqm-btn-resurrect:hover {
1405
+ background: hsl(142.1 76.2% 32%);
1406
+ }
1407
+
1408
+ .sqm-btn-kill {
1409
+ color: var(--sqm-destructive-foreground);
1410
+ background: var(--sqm-destructive);
1411
+ border-color: var(--sqm-destructive);
1412
+ }
1413
+
1414
+ .sqm-btn-kill:hover {
1415
+ background: hsl(0 84.2% 55%);
1416
+ }
1417
+
1418
+ /* ========================================
1419
+ Responsive Design for Tabs
1420
+ ======================================== */
1421
+
1422
+ @media (max-width: 768px) {
1423
+ .sqm-tabs-nav {
1424
+ flex-wrap: wrap;
1425
+ gap: 0.25rem;
1426
+ }
1427
+
1428
+ .sqm-tab {
1429
+ flex: 1;
1430
+ min-width: 0;
1431
+ justify-content: center;
1432
+ padding: 0.625rem 0.75rem;
1433
+ }
1434
+
1435
+ .sqm-tab span:not(.sqm-tab-count) {
1436
+ display: none;
1437
+ }
1438
+
1439
+ .sqm-section-controls {
1440
+ flex-direction: column;
1441
+ align-items: stretch;
1442
+ gap: 1rem;
1443
+ }
1444
+
1445
+ .sqm-controls-left,
1446
+ .sqm-controls-right {
1447
+ justify-content: center;
1448
+ }
1449
+
1450
+ .sqm-filter-input {
1451
+ width: 100%;
1452
+ max-width: 300px;
1453
+ }
1454
+
1455
+ .sqm-pagination {
1456
+ flex-direction: column;
1457
+ gap: 1rem;
1458
+ text-align: center;
1459
+ }
1460
+ }
1461
+
1462
+ @media (max-width: 480px) {
1463
+ .sqm-tab-count {
1464
+ min-width: 1rem;
1465
+ height: 1rem;
1466
+ font-size: 0.625rem;
1467
+ }
1468
+
1469
+ .sqm-section-controls {
1470
+ padding: 0.75rem;
1471
+ }
1472
+
1473
+ .sqm-controls-left,
1474
+ .sqm-controls-right {
1475
+ flex-wrap: wrap;
1476
+ gap: 0.5rem;
1477
+ }
1018
1478
  }
@@ -179,12 +179,21 @@ module SidekiqQueueManager
179
179
 
180
180
  # Get the mount path from the engine's routes
181
181
  def engine_mount_path
182
- # Extract mount path from the current request path
183
- if request.path =~ %r{^(/[^/]+)}
184
- Regexp.last_match(1)
185
- else
186
- '/sidekiq_manager' # Default fallback
182
+ # Look through Rails routes for engine mounts
183
+ Rails.application.routes.routes.each do |route|
184
+ next unless route.respond_to?(:app)
185
+ next unless route.app.respond_to?(:app)
186
+
187
+ # Check if this route's app is our engine
188
+ if route.app.app == SidekiqQueueManager::Engine
189
+ path_spec = route.path.spec.to_s
190
+ return path_spec.gsub(/\(\.:format\)$/, '').chomp('/')
191
+ end
187
192
  end
193
+
194
+ nil
195
+ rescue StandardError
196
+ nil
188
197
  end
189
198
 
190
199
  # Common helper for accessing main application methods