@mtldev514/retro-portfolio-engine 1.0.0 → 1.1.2

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 (52) hide show
  1. package/.github/workflows/build-and-deploy.yml +105 -0
  2. package/ADMIN_SETUP.md +306 -0
  3. package/README.md +193 -301
  4. package/USAGE.md +451 -0
  5. package/build.sh +326 -0
  6. package/index.html +85 -0
  7. package/js/manifest-loader.js +313 -0
  8. package/manifest.json +74 -0
  9. package/package.json +14 -38
  10. package/setup-admin.sh +134 -0
  11. package/sync-after-admin.sh +58 -0
  12. package/bin/cli.js +0 -103
  13. package/engine/admin/admin.css +0 -720
  14. package/engine/admin/admin.html +0 -801
  15. package/engine/admin/admin_api.py +0 -230
  16. package/engine/admin/scripts/backup.sh +0 -116
  17. package/engine/admin/scripts/config_loader.py +0 -180
  18. package/engine/admin/scripts/init.sh +0 -141
  19. package/engine/admin/scripts/manager.py +0 -308
  20. package/engine/admin/scripts/restore.sh +0 -121
  21. package/engine/admin/scripts/server.py +0 -41
  22. package/engine/admin/scripts/update.sh +0 -321
  23. package/engine/admin/scripts/validate_json.py +0 -62
  24. package/engine/fonts.css +0 -37
  25. package/engine/index.html +0 -190
  26. package/engine/js/config-loader.js +0 -370
  27. package/engine/js/config.js +0 -173
  28. package/engine/js/counter.js +0 -17
  29. package/engine/js/effects.js +0 -97
  30. package/engine/js/i18n.js +0 -68
  31. package/engine/js/init.js +0 -107
  32. package/engine/js/media.js +0 -264
  33. package/engine/js/render.js +0 -282
  34. package/engine/js/router.js +0 -133
  35. package/engine/js/sparkle.js +0 -123
  36. package/engine/js/themes.js +0 -607
  37. package/engine/style.css +0 -2037
  38. package/index.js +0 -35
  39. package/scripts/admin.js +0 -67
  40. package/scripts/build.js +0 -142
  41. package/scripts/init.js +0 -237
  42. package/scripts/post-install.js +0 -16
  43. package/scripts/serve.js +0 -54
  44. package/templates/user-portfolio/.github/workflows/deploy.yml +0 -57
  45. package/templates/user-portfolio/config/app.json +0 -36
  46. package/templates/user-portfolio/config/categories.json +0 -241
  47. package/templates/user-portfolio/config/languages.json +0 -15
  48. package/templates/user-portfolio/config/media-types.json +0 -59
  49. package/templates/user-portfolio/data/painting.json +0 -3
  50. package/templates/user-portfolio/data/projects.json +0 -3
  51. package/templates/user-portfolio/lang/en.json +0 -114
  52. package/templates/user-portfolio/lang/fr.json +0 -114
@@ -1,720 +0,0 @@
1
- /* ═══════════════════════════════════════════════════
2
- ADMIN PAGE STYLES
3
- Used by admin.html and edit.html
4
- All colors use centralized CSS variables below
5
- ═══════════════════════════════════════════════════ */
6
-
7
- :root {
8
- --admin-muted-text: #666;
9
- --admin-file-type: blue;
10
- --admin-connected: green;
11
- --admin-bg: #3a6ea5;
12
- --admin-win-bg: #c0c0c0;
13
- --admin-win-blue: #000080;
14
- --admin-win-text: #000;
15
- --admin-win-border-light: #fff;
16
- --admin-win-border-dark: #808080;
17
- --admin-tab-inactive: #d4d4d4;
18
- --admin-console-bg: #000;
19
- --admin-console-text: #0f0;
20
- --admin-readonly-bg: #eee;
21
- --admin-readonly-text: #555;
22
- --admin-save-bg: #e0e0ff;
23
- --admin-hint-bg: #fffff0;
24
- --admin-hint-border: #cc9;
25
- --admin-preview-bg: #eee;
26
- --admin-preview-border: #808080;
27
- --admin-status-success: lime;
28
- --admin-status-error: red;
29
- --admin-status-warn: orange;
30
- --admin-status-info: cyan;
31
- --admin-status-highlight: yellow;
32
- }
33
-
34
- body.admin-page {
35
- background-color: var(--admin-bg);
36
- font-family: var(--font-admin);
37
- display: flex;
38
- justify-content: center;
39
- align-items: center;
40
- min-height: 100vh;
41
- margin: 0;
42
- color: var(--admin-win-text);
43
- background-image: none;
44
- padding: 0;
45
- }
46
-
47
- .admin-page .desktop-icon {
48
- position: absolute;
49
- top: 20px;
50
- left: 20px;
51
- text-align: center;
52
- color: white;
53
- cursor: pointer;
54
- }
55
-
56
- .admin-page .desktop-icon img {
57
- width: 32px;
58
- display: block;
59
- margin: 0 auto 5px;
60
- }
61
-
62
- .admin-page .window {
63
- width: 800px;
64
- background: var(--admin-win-bg);
65
- border: 2px solid;
66
- border-color: var(--admin-win-border-light) var(--admin-win-border-dark) var(--admin-win-border-dark) var(--admin-win-border-light);
67
- box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.5);
68
- padding: 2px;
69
- }
70
-
71
- .admin-page .window.narrow {
72
- width: 700px;
73
- }
74
-
75
- .admin-page .title-bar {
76
- background: var(--admin-win-blue);
77
- color: white;
78
- padding: 3px 5px;
79
- display: flex;
80
- justify-content: space-between;
81
- align-items: center;
82
- font-weight: bold;
83
- font-size: 14px;
84
- }
85
-
86
- .admin-page .title-bar-controls button {
87
- width: 16px;
88
- height: 14px;
89
- font-size: 9px;
90
- padding: 0;
91
- margin-left: 2px;
92
- background: var(--admin-win-bg);
93
- border: 1px solid;
94
- border-color: var(--admin-win-border-light) var(--admin-win-border-dark) var(--admin-win-border-dark) var(--admin-win-border-light);
95
- }
96
-
97
- .admin-page .tab-bar {
98
- padding: 10px 10px 0;
99
- display: flex;
100
- border-bottom: 1px solid var(--admin-win-border-dark);
101
- }
102
-
103
- .admin-page .tab {
104
- padding: 5px 15px;
105
- border: 1px solid var(--admin-win-border-dark);
106
- border-bottom: none;
107
- background: var(--admin-tab-inactive);
108
- cursor: pointer;
109
- margin-right: 2px;
110
- border-radius: 4px 4px 0 0;
111
- }
112
-
113
- .admin-page .tab.active {
114
- background: var(--admin-win-bg);
115
- font-weight: bold;
116
- position: relative;
117
- top: 1px;
118
- z-index: 2;
119
- }
120
-
121
- .admin-page .tab-content {
122
- padding: 20px;
123
- min-height: 400px;
124
- display: none;
125
- }
126
-
127
- .admin-page .tab-content.active {
128
- display: block;
129
- }
130
-
131
- .admin-page .form-group {
132
- margin-bottom: 15px;
133
- }
134
-
135
- .admin-page label {
136
- display: block;
137
- margin-bottom: 5px;
138
- font-weight: bold;
139
- }
140
-
141
- .admin-page input[type="text"],
142
- .admin-page select,
143
- .admin-page textarea {
144
- width: 100%;
145
- padding: 5px;
146
- border: 2px solid;
147
- border-color: var(--admin-win-border-dark) var(--admin-win-border-light) var(--admin-win-border-light) var(--admin-win-border-dark);
148
- box-sizing: border-box;
149
- background: white;
150
- }
151
-
152
- .admin-page button.action {
153
- margin-top: 10px;
154
- padding: 8px 20px;
155
- background: var(--admin-win-bg);
156
- border: 2px solid;
157
- border-color: var(--admin-win-border-light) var(--admin-win-border-dark) var(--admin-win-border-dark) var(--admin-win-border-light);
158
- cursor: pointer;
159
- }
160
-
161
- .admin-page button.action:active {
162
- border-color: var(--admin-win-border-dark) var(--admin-win-border-light) var(--admin-win-border-light) var(--admin-win-border-dark);
163
- }
164
-
165
- .admin-page .status-bar {
166
- margin-top: 10px;
167
- padding: 3px 5px;
168
- background: var(--admin-win-bg);
169
- border-top: 1px solid var(--admin-win-border-dark);
170
- font-size: 12px;
171
- }
172
-
173
- .admin-page .console {
174
- background: var(--admin-console-bg);
175
- color: var(--admin-console-text);
176
- font-family: var(--font-mono);
177
- padding: 10px;
178
- height: 100px;
179
- overflow-y: auto;
180
- margin-top: 20px;
181
- font-size: 12px;
182
- border: 2px inset var(--admin-win-border-dark);
183
- }
184
-
185
- .admin-page .console.short {
186
- height: 80px;
187
- margin-top: 15px;
188
- }
189
-
190
- .admin-page .translation-grid {
191
- display: grid;
192
- grid-template-columns: 1fr 1fr;
193
- gap: 10px;
194
- height: 300px;
195
- overflow-y: auto;
196
- padding: 5px;
197
- background: white;
198
- border: 2px inset var(--admin-win-border-dark);
199
- }
200
-
201
- .admin-page .trans-item {
202
- padding: 5px;
203
- border-bottom: 1px solid var(--admin-readonly-bg);
204
- }
205
-
206
- .admin-page .trans-item input {
207
- font-size: 11px;
208
- }
209
-
210
- /* Edit page specific */
211
- .admin-page .edit-body {
212
- padding: 20px;
213
- }
214
-
215
- .admin-page .form-group label {
216
- display: block;
217
- margin-bottom: 4px;
218
- font-weight: bold;
219
- font-size: 12px;
220
- }
221
-
222
- .admin-page .form-group input[type="text"],
223
- .admin-page .form-group textarea {
224
- width: 100%;
225
- padding: 5px;
226
- border: 2px solid;
227
- border-color: var(--admin-win-border-dark) var(--admin-win-border-light) var(--admin-win-border-light) var(--admin-win-border-dark);
228
- box-sizing: border-box;
229
- background: white;
230
- font-family: inherit;
231
- font-size: 13px;
232
- }
233
-
234
- .admin-page .form-group textarea {
235
- height: 60px;
236
- resize: vertical;
237
- }
238
-
239
- .admin-page .form-group .readonly {
240
- background: var(--admin-readonly-bg);
241
- color: var(--admin-readonly-text);
242
- }
243
-
244
- .admin-page .preview-box {
245
- border: 2px inset var(--admin-win-border-dark);
246
- background: white;
247
- padding: 10px;
248
- text-align: center;
249
- margin-bottom: 15px;
250
- }
251
-
252
- .admin-page .preview-box img {
253
- max-width: 300px;
254
- max-height: 200px;
255
- }
256
-
257
- .admin-page .button-bar {
258
- display: flex;
259
- justify-content: flex-end;
260
- gap: 10px;
261
- margin-top: 20px;
262
- padding-top: 10px;
263
- border-top: 1px solid var(--admin-win-border-dark);
264
- }
265
-
266
- .admin-page .button-bar button {
267
- padding: 6px 20px;
268
- background: var(--admin-win-bg);
269
- border: 2px solid;
270
- border-color: var(--admin-win-border-light) var(--admin-win-border-dark) var(--admin-win-border-dark) var(--admin-win-border-light);
271
- cursor: pointer;
272
- font-weight: bold;
273
- font-size: 12px;
274
- }
275
-
276
- .admin-page .button-bar button:active {
277
- border-color: var(--admin-win-border-dark) var(--admin-win-border-light) var(--admin-win-border-light) var(--admin-win-border-dark);
278
- }
279
-
280
- .admin-page .button-bar .save-btn {
281
- background: var(--admin-save-bg);
282
- }
283
-
284
- .admin-page .info-row {
285
- display: flex;
286
- gap: 15px;
287
- }
288
-
289
- .admin-page .info-row .form-group {
290
- flex: 1;
291
- }
292
-
293
- .admin-page #loading {
294
- text-align: center;
295
- padding: 40px;
296
- font-size: 14px;
297
- }
298
-
299
- .admin-page #editForm {
300
- display: none;
301
- }
302
-
303
- .admin-page #errorBox {
304
- display: none;
305
- text-align: center;
306
- padding: 40px;
307
- color: var(--admin-status-error);
308
- font-weight: bold;
309
- }
310
-
311
- /* Admin console output color classes */
312
- .admin-page .con-error { color: var(--admin-status-error); }
313
- .admin-page .con-success { color: var(--admin-status-success); }
314
- .admin-page .con-warn { color: var(--admin-status-warn); }
315
- .admin-page .con-info { color: var(--admin-status-info); }
316
- .admin-page .con-hi { color: var(--admin-status-highlight); }
317
-
318
- /* Admin utility classes */
319
- .admin-page .admin-muted {
320
- font-size: 10px;
321
- color: var(--admin-muted-text);
322
- }
323
-
324
- .admin-page .admin-hint {
325
- background: var(--admin-hint-bg);
326
- padding: 8px;
327
- border: 1px solid var(--admin-hint-border);
328
- font-size: 10px;
329
- margin-bottom: 10px;
330
- }
331
-
332
- .admin-page .admin-preview-area {
333
- background: var(--admin-preview-bg);
334
- padding: 10px;
335
- border: 1px dashed var(--admin-preview-border);
336
- }
337
-
338
- .admin-page .admin-flex-row {
339
- display: flex;
340
- gap: 20px;
341
- }
342
-
343
- .admin-page .admin-flex-col {
344
- flex: 1;
345
- }
346
-
347
- .admin-page .admin-flex-between {
348
- display: flex;
349
- justify-content: space-between;
350
- margin-bottom: 10px;
351
- }
352
-
353
- .admin-page .admin-content-list {
354
- height: 350px;
355
- overflow-y: auto;
356
- background: white;
357
- border: 2px inset var(--admin-win-border-dark);
358
- padding: 5px;
359
- }
360
-
361
- .admin-page .admin-text-right {
362
- text-align: right;
363
- }
364
-
365
- .admin-page .admin-connected {
366
- color: var(--admin-connected);
367
- font-weight: bold;
368
- }
369
-
370
- .admin-page .admin-file-type {
371
- color: var(--admin-file-type);
372
- }
373
-
374
- .admin-page .src-btn-active {
375
- background: var(--admin-save-bg);
376
- font-weight: bold;
377
- }
378
-
379
- .admin-page .content-row {
380
- padding: 5px;
381
- border-bottom: 1px dotted var(--chrome-soft);
382
- display: flex;
383
- justify-content: space-between;
384
- align-items: center;
385
- font-size: 12px;
386
- }
387
-
388
- .admin-page .content-header {
389
- margin: 10px 0 5px;
390
- border-bottom: 1px solid var(--chrome-soft);
391
- }
392
-
393
- /* ── Bulk Upload ── */
394
- .bulk-drop-zone {
395
- border: 2px dashed var(--admin-win-border-dark);
396
- background: white;
397
- padding: 30px 20px;
398
- text-align: center;
399
- cursor: pointer;
400
- transition: background 0.15s;
401
- }
402
- .bulk-drop-zone:hover,
403
- .bulk-drop-zone.drag-over {
404
- background: var(--admin-save-bg);
405
- border-color: var(--admin-win-blue);
406
- }
407
-
408
- .bulk-queue {
409
- margin-top: 10px;
410
- }
411
-
412
- .bulk-items {
413
- max-height: 320px;
414
- overflow-y: auto;
415
- border: 2px inset var(--admin-win-border-dark);
416
- background: white;
417
- padding: 5px;
418
- }
419
-
420
- .bulk-item {
421
- display: flex;
422
- align-items: center;
423
- gap: 8px;
424
- padding: 5px 4px;
425
- border-bottom: 1px dotted var(--admin-win-border-dark);
426
- }
427
- .bulk-item:last-child { border-bottom: none; }
428
-
429
- .bulk-thumb {
430
- width: 48px;
431
- height: 48px;
432
- flex-shrink: 0;
433
- border: 1px solid var(--admin-win-border-dark);
434
- background: var(--admin-readonly-bg);
435
- display: flex;
436
- align-items: center;
437
- justify-content: center;
438
- overflow: hidden;
439
- }
440
- .bulk-thumb img {
441
- width: 100%;
442
- height: 100%;
443
- object-fit: cover;
444
- }
445
-
446
- .bulk-fields {
447
- flex: 1;
448
- display: flex;
449
- gap: 6px;
450
- align-items: center;
451
- }
452
- .bulk-fields input[type="text"] {
453
- flex: 1;
454
- padding: 3px 5px;
455
- border: 2px solid;
456
- border-color: var(--admin-win-border-dark) var(--admin-win-border-light) var(--admin-win-border-light) var(--admin-win-border-dark);
457
- font-size: 12px;
458
- }
459
- .bulk-fields select {
460
- padding: 3px;
461
- border: 2px solid;
462
- border-color: var(--admin-win-border-dark) var(--admin-win-border-light) var(--admin-win-border-light) var(--admin-win-border-dark);
463
- font-size: 11px;
464
- }
465
-
466
- .bulk-status {
467
- font-size: 11px;
468
- font-weight: bold;
469
- min-width: 30px;
470
- text-align: center;
471
- }
472
-
473
- .bulk-remove {
474
- background: none;
475
- border: none;
476
- font-size: 16px;
477
- cursor: pointer;
478
- color: var(--admin-status-error);
479
- padding: 0 4px;
480
- line-height: 1;
481
- }
482
-
483
- /* ── Pile Picker ── */
484
- .pile-btn {
485
- margin-right: 5px;
486
- color: var(--admin-win-blue);
487
- }
488
-
489
- .pile-picker {
490
- position: absolute;
491
- right: 0;
492
- top: 100%;
493
- z-index: 10;
494
- background: white;
495
- border: 2px solid;
496
- border-color: var(--admin-win-border-light) var(--admin-win-border-dark) var(--admin-win-border-dark) var(--admin-win-border-light);
497
- box-shadow: 2px 2px 6px rgba(0,0,0,0.3);
498
- min-width: 220px;
499
- max-height: 200px;
500
- overflow-y: auto;
501
- font-size: 11px;
502
- }
503
-
504
- .pile-picker-title {
505
- padding: 4px 8px;
506
- background: var(--admin-win-blue);
507
- color: white;
508
- font-weight: bold;
509
- font-size: 10px;
510
- }
511
-
512
- .pile-picker-item {
513
- padding: 4px 8px;
514
- cursor: pointer;
515
- border-bottom: 1px dotted var(--admin-win-border-dark);
516
- }
517
- .pile-picker-item:last-child { border-bottom: none; }
518
- .pile-picker-item:hover {
519
- background: var(--admin-save-bg);
520
- }
521
-
522
- /* ── Gallery Manager ── */
523
- .gallery-manager-grid {
524
- display: grid;
525
- grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
526
- gap: 12px;
527
- padding: 10px;
528
- background: white;
529
- }
530
-
531
- .gallery-card {
532
- position: relative;
533
- border: 2px solid var(--admin-win-border-dark);
534
- background: white;
535
- cursor: move;
536
- transition: transform 0.2s, box-shadow 0.2s;
537
- }
538
-
539
- .gallery-card:hover {
540
- transform: translateY(-2px);
541
- box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.3);
542
- }
543
-
544
- .gallery-card.dragging {
545
- opacity: 0.5;
546
- }
547
-
548
- .gallery-card.drag-over {
549
- border-color: var(--admin-win-blue);
550
- background: var(--admin-save-bg);
551
- }
552
-
553
- .gallery-card-cover {
554
- grid-column: 1 / -1;
555
- max-width: 300px;
556
- border-color: gold;
557
- border-width: 3px;
558
- cursor: default;
559
- }
560
-
561
- .gallery-card-cover:hover {
562
- transform: none;
563
- }
564
-
565
- .gallery-card img {
566
- width: 100%;
567
- height: 150px;
568
- object-fit: cover;
569
- display: block;
570
- }
571
-
572
- .gallery-card-cover img {
573
- height: 200px;
574
- }
575
-
576
- .gallery-card-label {
577
- position: absolute;
578
- top: 4px;
579
- left: 4px;
580
- background: rgba(0, 0, 0, 0.7);
581
- color: white;
582
- padding: 2px 6px;
583
- font-size: 10px;
584
- font-weight: bold;
585
- border-radius: 2px;
586
- }
587
-
588
- .gallery-card-cover .gallery-card-label {
589
- background: rgba(255, 215, 0, 0.9);
590
- color: black;
591
- }
592
-
593
- .gallery-card-actions {
594
- padding: 6px;
595
- text-align: center;
596
- }
597
-
598
- .gallery-action-btn {
599
- padding: 4px 12px;
600
- background: var(--admin-win-bg);
601
- border: 2px solid;
602
- border-color: var(--admin-win-border-light) var(--admin-win-border-dark) var(--admin-win-border-dark) var(--admin-win-border-light);
603
- cursor: pointer;
604
- font-size: 10px;
605
- font-weight: bold;
606
- }
607
-
608
- .gallery-action-btn:hover {
609
- background: var(--admin-save-bg);
610
- }
611
-
612
- .gallery-action-btn:active {
613
- border-color: var(--admin-win-border-dark) var(--admin-win-border-light) var(--admin-win-border-light) var(--admin-win-border-dark);
614
- }
615
-
616
- .gallery-extract-btn {
617
- background: #ffe4e1;
618
- margin-left: 4px;
619
- }
620
-
621
- .gallery-extract-btn:hover {
622
- background: #ffcccb;
623
- }
624
-
625
- /* ── Bulk Edit ── */
626
- .bulk-edit-list {
627
- margin-top: 10px;
628
- }
629
-
630
- .bulk-edit-row {
631
- display: flex;
632
- align-items: center;
633
- gap: 10px;
634
- padding: 8px;
635
- border-bottom: 1px dotted var(--admin-win-border-dark);
636
- }
637
-
638
- .bulk-edit-row:last-child {
639
- border-bottom: none;
640
- }
641
-
642
- .bulk-edit-row input[type="checkbox"] {
643
- flex-shrink: 0;
644
- }
645
-
646
- .bulk-edit-row label {
647
- margin: 0;
648
- }
649
-
650
- .bulk-edit-modal {
651
- position: fixed;
652
- top: 0;
653
- left: 0;
654
- right: 0;
655
- bottom: 0;
656
- background: rgba(0, 0, 0, 0.7);
657
- display: flex;
658
- align-items: center;
659
- justify-content: center;
660
- z-index: 1000;
661
- }
662
-
663
- .bulk-edit-modal-content {
664
- margin: 0;
665
- }
666
-
667
- /* ── Extract Picker ── */
668
- .extract-picker-modal {
669
- position: fixed;
670
- top: 0;
671
- left: 0;
672
- right: 0;
673
- bottom: 0;
674
- background: rgba(0, 0, 0, 0.7);
675
- display: flex;
676
- align-items: center;
677
- justify-content: center;
678
- z-index: 1000;
679
- }
680
-
681
- .extract-picker-content {
682
- margin: 0;
683
- }
684
-
685
- .extract-option-btn {
686
- display: block;
687
- width: 100%;
688
- padding: 12px;
689
- margin-bottom: 10px;
690
- background: var(--admin-win-bg);
691
- border: 2px solid;
692
- border-color: var(--admin-win-border-light) var(--admin-win-border-dark) var(--admin-win-border-dark) var(--admin-win-border-light);
693
- cursor: pointer;
694
- font-size: 13px;
695
- font-weight: bold;
696
- text-align: left;
697
- }
698
-
699
- .extract-option-btn:hover {
700
- background: var(--admin-save-bg);
701
- }
702
-
703
- .extract-option-btn:active {
704
- border-color: var(--admin-win-border-dark) var(--admin-win-border-light) var(--admin-win-border-light) var(--admin-win-border-dark);
705
- }
706
-
707
- .extract-picker-item {
708
- padding: 8px 10px;
709
- cursor: pointer;
710
- border-bottom: 1px dotted var(--admin-win-border-dark);
711
- font-size: 12px;
712
- }
713
-
714
- .extract-picker-item:last-child {
715
- border-bottom: none;
716
- }
717
-
718
- .extract-picker-item:hover {
719
- background: var(--admin-save-bg);
720
- }