recycle_bin 1.1.1 → 1.2.0

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.
@@ -0,0 +1,618 @@
1
+ <% content_for :title, "Dashboard" %>
2
+
3
+ <!-- Dashboard Stats Overview -->
4
+ <div class="dashboard-container">
5
+ <!-- Main Stats Grid -->
6
+ <div class="dashboard-stats-grid">
7
+ <%= render 'recycle_bin/trash/stats',
8
+ total_count: @total_count,
9
+ model_types: @model_types,
10
+ filtered_items: @all_deleted_items,
11
+ current_page: 1,
12
+ per_page: @total_count,
13
+ total_pages: 1,
14
+ dashboard_view: true %>
15
+ </div>
16
+
17
+ <!-- Dashboard Content Grid -->
18
+ <div class="dashboard-content-grid">
19
+ <!-- Recent Activity Panel -->
20
+ <div class="dashboard-panel">
21
+ <div class="panel-header">
22
+ <h3 class="panel-title">📊 Recent Activity</h3>
23
+ <%= link_to "View All Items", recycle_bin.trash_index_path,
24
+ class: "panel-action-link" %>
25
+ </div>
26
+ <div class="panel-content">
27
+ <% if @recent_items.any? %>
28
+ <div class="recent-items-list">
29
+ <% @recent_items.each do |item| %>
30
+ <div class="recent-item">
31
+ <div class="item-info">
32
+ <span class="model-badge"><%= item.class.name %></span>
33
+ <span class="item-title">
34
+ <%= link_to "#{item.class.name} ##{item.id}",
35
+ recycle_bin.trash_path(item.class.name, item.id),
36
+ class: "item-link" %>
37
+ </span>
38
+ </div>
39
+ <div class="item-meta">
40
+ <span class="timestamp">
41
+ 🕒 <%= time_ago_in_words(item.deleted_at) %> ago
42
+ </span>
43
+ <div class="item-actions">
44
+ <%= link_to "↶", recycle_bin.restore_trash_path(item.class.name, item.id),
45
+ method: :patch,
46
+ class: "quick-action-btn restore-btn",
47
+ title: "Restore",
48
+ data: { confirm: "Restore this item?" } %>
49
+ <%= link_to "🗑️", recycle_bin.trash_path(item.class.name, item.id),
50
+ method: :delete,
51
+ class: "quick-action-btn delete-btn",
52
+ title: "Delete Permanently",
53
+ data: { confirm: "Permanently delete this item?" } %>
54
+ </div>
55
+ </div>
56
+ </div>
57
+ <% end %>
58
+ </div>
59
+
60
+ <% if @total_count > @recent_items.count %>
61
+ <div class="panel-footer">
62
+ <p class="more-items-text">
63
+ Showing <%= @recent_items.count %> of <%= number_with_delimiter(@total_count) %> deleted items
64
+ </p>
65
+ <%= link_to "View All Items →", recycle_bin.trash_index_path,
66
+ class: "btn btn-primary btn-sm" %>
67
+ </div>
68
+ <% end %>
69
+ <% else %>
70
+ <div class="empty-state-mini">
71
+ <div class="empty-icon">🎉</div>
72
+ <h4 class="empty-title">All Clean!</h4>
73
+ <p class="empty-subtitle">No deleted items to show. Your recycle bin is empty.</p>
74
+ </div>
75
+ <% end %>
76
+ </div>
77
+ </div>
78
+
79
+ <!-- Model Types Breakdown -->
80
+ <div class="dashboard-panel">
81
+ <div class="panel-header">
82
+ <h3 class="panel-title">📁 Model Breakdown</h3>
83
+ </div>
84
+ <div class="panel-content">
85
+ <% if @model_breakdown.any? %>
86
+ <div class="model-breakdown-list">
87
+ <% @model_breakdown.each do |model_data| %>
88
+ <div class="model-breakdown-item">
89
+ <div class="model-info">
90
+ <span class="model-badge model-<%= model_data[:name].downcase %>">
91
+ <%= model_data[:name] %>
92
+ </span>
93
+ <div class="model-details">
94
+ <span class="model-count"><%= model_data[:count] %> items</span>
95
+ <span class="model-percentage">
96
+ <%= number_to_percentage(model_data[:percentage], precision: 1) %>
97
+ </span>
98
+ </div>
99
+ </div>
100
+ <div class="model-progress">
101
+ <div class="progress-bar">
102
+ <div class="progress-fill"
103
+ style="width: <%= model_data[:percentage] %>%"></div>
104
+ </div>
105
+ </div>
106
+ <div class="model-actions">
107
+ <%= link_to "View", recycle_bin.trash_index_path(type: model_data[:name]),
108
+ class: "btn btn-outline btn-sm" %>
109
+ </div>
110
+ </div>
111
+ <% end %>
112
+ </div>
113
+ <% else %>
114
+ <div class="empty-state-mini">
115
+ <div class="empty-icon">📁</div>
116
+ <p class="empty-subtitle">No model data available</p>
117
+ </div>
118
+ <% end %>
119
+ </div>
120
+ </div>
121
+
122
+ <!-- Quick Actions Panel -->
123
+ <div class="dashboard-panel">
124
+ <div class="panel-header">
125
+ <h3 class="panel-title">⚡ Quick Actions</h3>
126
+ </div>
127
+ <div class="panel-content">
128
+ <div class="quick-actions-grid">
129
+ <div class="quick-action-card">
130
+ <div class="action-icon">📋</div>
131
+ <h4 class="action-title">View All Items</h4>
132
+ <p class="action-description">Browse and manage all deleted items with advanced filtering</p>
133
+ <%= link_to "Browse Items", recycle_bin.trash_index_path,
134
+ class: "btn btn-primary btn-sm" %>
135
+ </div>
136
+
137
+ <div class="quick-action-card">
138
+ <div class="action-icon">📊</div>
139
+ <h4 class="action-title">Export Data</h4>
140
+ <p class="action-description">Export all deleted items to CSV or JSON format</p>
141
+ <div class="action-buttons">
142
+ <%= link_to "CSV", recycle_bin.trash_index_path(format: :csv),
143
+ class: "btn btn-outline btn-sm" %>
144
+ <%= link_to "JSON", recycle_bin.trash_index_path(format: :json),
145
+ class: "btn btn-outline btn-sm" %>
146
+ </div>
147
+ </div>
148
+
149
+ <% if @total_count > 0 %>
150
+ <div class="quick-action-card">
151
+ <div class="action-icon">🔍</div>
152
+ <h4 class="action-title">Search Items</h4>
153
+ <p class="action-description">Find specific items using advanced search</p>
154
+ <%= link_to "Advanced Search", recycle_bin.trash_index_path(anchor: "filters"),
155
+ class: "btn btn-primary btn-sm" %>
156
+ </div>
157
+ <% end %>
158
+ </div>
159
+ </div>
160
+ </div>
161
+
162
+ <!-- Time-based Activity (if we have recent activity) -->
163
+ <% if @weekly_stats.any? %>
164
+ <div class="dashboard-panel full-width">
165
+ <div class="panel-header">
166
+ <h3 class="panel-title">📈 Weekly Activity</h3>
167
+ </div>
168
+ <div class="panel-content">
169
+ <div class="weekly-stats-chart">
170
+ <% @weekly_stats.each do |day_stat| %>
171
+ <div class="day-stat">
172
+ <div class="day-bar"
173
+ style="height: <%= [day_stat[:percentage], 10].max %>%"
174
+ title="<%= day_stat[:count] %> items on <%= day_stat[:day] %>">
175
+ </div>
176
+ <span class="day-label"><%= day_stat[:day] %></span>
177
+ <span class="day-count"><%= day_stat[:count] %></span>
178
+ </div>
179
+ <% end %>
180
+ </div>
181
+ </div>
182
+ </div>
183
+ <% end %>
184
+ </div>
185
+ </div>
186
+
187
+ <style>
188
+ .dashboard-container {
189
+ display: flex;
190
+ flex-direction: column;
191
+ gap: 24px;
192
+ }
193
+
194
+ .dashboard-stats-grid {
195
+ margin-bottom: 8px;
196
+ }
197
+
198
+ .dashboard-content-grid {
199
+ display: grid;
200
+ grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
201
+ gap: 24px;
202
+ align-items: start;
203
+ }
204
+
205
+ .dashboard-panel {
206
+ background: white;
207
+ border-radius: 12px;
208
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
209
+ overflow: hidden;
210
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
211
+ }
212
+
213
+ .dashboard-panel:hover {
214
+ transform: translateY(-2px);
215
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
216
+ }
217
+
218
+ .dashboard-panel.full-width {
219
+ grid-column: 1 / -1;
220
+ }
221
+
222
+ .panel-header {
223
+ padding: 20px 24px;
224
+ background: #f8f9fa;
225
+ border-bottom: 1px solid #e9ecef;
226
+ display: flex;
227
+ justify-content: space-between;
228
+ align-items: center;
229
+ }
230
+
231
+ .panel-title {
232
+ font-size: 18px;
233
+ font-weight: 600;
234
+ color: #495057;
235
+ margin: 0;
236
+ display: flex;
237
+ align-items: center;
238
+ gap: 8px;
239
+ }
240
+
241
+ .panel-action-link {
242
+ color: #667eea;
243
+ text-decoration: none;
244
+ font-size: 14px;
245
+ font-weight: 500;
246
+ transition: color 0.3s ease;
247
+ }
248
+
249
+ .panel-action-link:hover {
250
+ color: #5a67d8;
251
+ text-decoration: none;
252
+ }
253
+
254
+ .panel-content {
255
+ padding: 24px;
256
+ }
257
+
258
+ .panel-footer {
259
+ padding: 16px 24px;
260
+ background: #f8f9fa;
261
+ border-top: 1px solid #e9ecef;
262
+ text-align: center;
263
+ }
264
+
265
+ .more-items-text {
266
+ color: #6c757d;
267
+ font-size: 14px;
268
+ margin: 0 0 12px 0;
269
+ }
270
+
271
+ /* Recent Items */
272
+ .recent-items-list {
273
+ display: flex;
274
+ flex-direction: column;
275
+ gap: 16px;
276
+ }
277
+
278
+ .recent-item {
279
+ display: flex;
280
+ justify-content: space-between;
281
+ align-items: center;
282
+ padding: 16px;
283
+ border: 1px solid #e9ecef;
284
+ border-radius: 8px;
285
+ transition: border-color 0.3s ease, background-color 0.3s ease;
286
+ }
287
+
288
+ .recent-item:hover {
289
+ border-color: #667eea;
290
+ background: #f8f9fa;
291
+ }
292
+
293
+ .item-info {
294
+ display: flex;
295
+ flex-direction: column;
296
+ gap: 4px;
297
+ flex: 1;
298
+ }
299
+
300
+ .item-link {
301
+ color: #495057;
302
+ text-decoration: none;
303
+ font-weight: 500;
304
+ font-size: 14px;
305
+ }
306
+
307
+ .item-link:hover {
308
+ color: #667eea;
309
+ text-decoration: none;
310
+ }
311
+
312
+ .item-meta {
313
+ display: flex;
314
+ flex-direction: column;
315
+ align-items: flex-end;
316
+ gap: 8px;
317
+ }
318
+
319
+ .timestamp {
320
+ font-size: 12px;
321
+ color: #6c757d;
322
+ }
323
+
324
+ .item-actions {
325
+ display: flex;
326
+ gap: 4px;
327
+ }
328
+
329
+ .quick-action-btn {
330
+ width: 24px;
331
+ height: 24px;
332
+ display: flex;
333
+ align-items: center;
334
+ justify-content: center;
335
+ border-radius: 4px;
336
+ text-decoration: none;
337
+ font-size: 12px;
338
+ transition: all 0.3s ease;
339
+ }
340
+
341
+ .quick-action-btn.restore-btn {
342
+ background: #28a745;
343
+ color: white;
344
+ }
345
+
346
+ .quick-action-btn.restore-btn:hover {
347
+ background: #218838;
348
+ color: white;
349
+ text-decoration: none;
350
+ }
351
+
352
+ .quick-action-btn.delete-btn {
353
+ background: #dc3545;
354
+ color: white;
355
+ }
356
+
357
+ .quick-action-btn.delete-btn:hover {
358
+ background: #c82333;
359
+ color: white;
360
+ text-decoration: none;
361
+ }
362
+
363
+ /* Model Breakdown */
364
+ .model-breakdown-list {
365
+ display: flex;
366
+ flex-direction: column;
367
+ gap: 16px;
368
+ }
369
+
370
+ .model-breakdown-item {
371
+ display: flex;
372
+ align-items: center;
373
+ gap: 12px;
374
+ padding: 12px;
375
+ border-radius: 8px;
376
+ background: #f8f9fa;
377
+ }
378
+
379
+ .model-info {
380
+ display: flex;
381
+ flex-direction: column;
382
+ gap: 4px;
383
+ min-width: 120px;
384
+ }
385
+
386
+ .model-details {
387
+ display: flex;
388
+ flex-direction: column;
389
+ font-size: 12px;
390
+ }
391
+
392
+ .model-count {
393
+ font-weight: 600;
394
+ color: #495057;
395
+ }
396
+
397
+ .model-percentage {
398
+ color: #6c757d;
399
+ }
400
+
401
+ .model-progress {
402
+ flex: 1;
403
+ margin: 0 12px;
404
+ }
405
+
406
+ .progress-bar {
407
+ height: 8px;
408
+ background: #e9ecef;
409
+ border-radius: 4px;
410
+ overflow: hidden;
411
+ }
412
+
413
+ .progress-fill {
414
+ height: 100%;
415
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
416
+ border-radius: 4px;
417
+ transition: width 0.3s ease;
418
+ }
419
+
420
+ /* Quick Actions */
421
+ .quick-actions-grid {
422
+ display: flex;
423
+ flex-direction: column;
424
+ gap: 16px;
425
+ }
426
+
427
+ .quick-action-card {
428
+ padding: 20px;
429
+ border: 1px solid #e9ecef;
430
+ border-radius: 8px;
431
+ text-align: center;
432
+ transition: border-color 0.3s ease, transform 0.3s ease;
433
+ }
434
+
435
+ .quick-action-card:hover {
436
+ border-color: #667eea;
437
+ transform: translateY(-2px);
438
+ }
439
+
440
+ .action-icon {
441
+ font-size: 2rem;
442
+ margin-bottom: 12px;
443
+ }
444
+
445
+ .action-title {
446
+ font-size: 16px;
447
+ font-weight: 600;
448
+ color: #495057;
449
+ margin: 0 0 8px 0;
450
+ }
451
+
452
+ .action-description {
453
+ font-size: 14px;
454
+ color: #6c757d;
455
+ margin: 0 0 16px 0;
456
+ line-height: 1.4;
457
+ }
458
+
459
+ .action-buttons {
460
+ display: flex;
461
+ gap: 8px;
462
+ justify-content: center;
463
+ }
464
+
465
+ /* Weekly Stats Chart */
466
+ .weekly-stats-chart {
467
+ display: flex;
468
+ justify-content: space-between;
469
+ align-items: end;
470
+ gap: 8px;
471
+ height: 200px;
472
+ padding: 20px 0;
473
+ }
474
+
475
+ .day-stat {
476
+ display: flex;
477
+ flex-direction: column;
478
+ align-items: center;
479
+ flex: 1;
480
+ gap: 8px;
481
+ }
482
+
483
+ .day-bar {
484
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
485
+ width: 100%;
486
+ border-radius: 4px;
487
+ transition: all 0.3s ease;
488
+ cursor: pointer;
489
+ min-height: 10px;
490
+ }
491
+
492
+ .day-bar:hover {
493
+ opacity: 0.8;
494
+ }
495
+
496
+ .day-label {
497
+ font-size: 12px;
498
+ color: #6c757d;
499
+ font-weight: 500;
500
+ }
501
+
502
+ .day-count {
503
+ font-size: 12px;
504
+ font-weight: 600;
505
+ color: #495057;
506
+ }
507
+
508
+ /* Empty States */
509
+ .empty-state-mini {
510
+ text-align: center;
511
+ padding: 40px 20px;
512
+ }
513
+
514
+ .empty-state-mini .empty-icon {
515
+ font-size: 3rem;
516
+ margin-bottom: 16px;
517
+ opacity: 0.5;
518
+ }
519
+
520
+ .empty-state-mini .empty-title {
521
+ font-size: 18px;
522
+ font-weight: 600;
523
+ color: #495057;
524
+ margin: 0 0 8px 0;
525
+ }
526
+
527
+ .empty-state-mini .empty-subtitle {
528
+ font-size: 14px;
529
+ color: #6c757d;
530
+ margin: 0;
531
+ }
532
+
533
+ /* Model Badge Variations */
534
+ .model-badge.model-post {
535
+ background: #28a745;
536
+ }
537
+
538
+ .model-badge.model-user {
539
+ background: #17a2b8;
540
+ }
541
+
542
+ .model-badge.model-comment {
543
+ background: #ffc107;
544
+ color: #212529;
545
+ }
546
+
547
+ .model-badge.model-article {
548
+ background: #6f42c1;
549
+ }
550
+
551
+ /* Responsive Design */
552
+ @media (max-width: 768px) {
553
+ .dashboard-content-grid {
554
+ grid-template-columns: 1fr;
555
+ gap: 16px;
556
+ }
557
+
558
+ .panel-header {
559
+ padding: 16px 20px;
560
+ flex-direction: column;
561
+ gap: 12px;
562
+ align-items: flex-start;
563
+ }
564
+
565
+ .panel-content {
566
+ padding: 20px;
567
+ }
568
+
569
+ .recent-item {
570
+ flex-direction: column;
571
+ align-items: flex-start;
572
+ gap: 12px;
573
+ }
574
+
575
+ .item-meta {
576
+ align-items: flex-start;
577
+ width: 100%;
578
+ }
579
+
580
+ .model-breakdown-item {
581
+ flex-direction: column;
582
+ align-items: flex-start;
583
+ gap: 12px;
584
+ }
585
+
586
+ .model-progress {
587
+ width: 100%;
588
+ margin: 0;
589
+ }
590
+
591
+ .quick-actions-grid {
592
+ gap: 12px;
593
+ }
594
+
595
+ .weekly-stats-chart {
596
+ height: 150px;
597
+ padding: 16px 0;
598
+ }
599
+ }
600
+
601
+ @media (max-width: 480px) {
602
+ .dashboard-container {
603
+ gap: 16px;
604
+ }
605
+
606
+ .recent-items-list {
607
+ gap: 12px;
608
+ }
609
+
610
+ .recent-item {
611
+ padding: 12px;
612
+ }
613
+
614
+ .action-buttons {
615
+ flex-direction: column;
616
+ }
617
+ }
618
+ </style>