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.
@@ -1,24 +1,267 @@
1
- <tr>
2
- <td><input type="checkbox" class="item-checkbox" value="<%= item.class.name %>:<%= item.id %>" onchange="updateBulkActions()"></td>
3
- <td><span class="model-badge"><%= item.class.name %></span></td>
4
- <td>
5
- <div class="card-title">
6
- <%= link_to truncate(item.recyclable_title, length: 60), recycle_bin.trash_path(item.class.name, item.id) %>
1
+ <tr class="item-row" data-item-id="<%= item.id %>" data-model-type="<%= item.class.name %>">
2
+ <td class="checkbox-column">
3
+ <input type="checkbox"
4
+ class="item-checkbox"
5
+ value="<%= item.class.name %>:<%= item.id %>"
6
+ onchange="updateBulkCount()">
7
+ </td>
8
+
9
+ <td class="type-column">
10
+ <span class="model-badge <%= item.class.name.downcase %>">
11
+ <%= item.class.name %>
12
+ </span>
13
+ </td>
14
+
15
+ <td class="item-column">
16
+ <div class="item-content">
17
+ <div class="item-title">
18
+ <% if params[:search].present? %>
19
+ <%= highlight_search_terms(item.recyclable_title, params[:search]) %>
20
+ <% else %>
21
+ <%= item.recyclable_title %>
22
+ <% end %>
23
+ </div>
24
+ <div class="item-meta">
25
+ <span class="item-id">ID: <%= item.id %></span>
26
+ <% if item.respond_to?(:user_id) && item.user_id.present? %>
27
+ <span class="item-user">User: <%= item.user_id %></span>
28
+ <% end %>
29
+ <% if item.respond_to?(:email) && item.email.present? %>
30
+ <span class="item-email">
31
+ <% if params[:search].present? %>
32
+ <%= highlight_search_terms(item.email, params[:search]) %>
33
+ <% else %>
34
+ <%= item.email %>
35
+ <% end %>
36
+ </span>
37
+ <% end %>
38
+ </div>
39
+ </div>
40
+ </td>
41
+
42
+ <td class="timestamp-column">
43
+ <div class="timestamp-content">
44
+ <div class="timestamp-relative">
45
+ <%= time_ago_in_words(item.deleted_at) %> ago
46
+ </div>
47
+ <div class="timestamp-absolute">
48
+ <%= item.deleted_at.strftime('%B %d, %Y at %l:%M %p') %>
49
+ </div>
7
50
  </div>
8
- <div class="timestamp">ID: <%= item.id %></div>
9
51
  </td>
10
- <td>
11
- <div class="card-title"><%= time_ago_in_words(item.deleted_at) %> ago</div>
12
- <div class="timestamp"><%= item.deleted_at.strftime('%B %d, %Y at %l:%M %p') %></div>
52
+
53
+ <td class="size-column">
54
+ <span class="size-badge <%= size_class(item) %>">
55
+ <%= human_file_size(calculate_item_memory_size(item)) %>
56
+ </span>
13
57
  </td>
14
- <td>
15
- <div class="card-actions">
16
- <%= form_with url: recycle_bin.restore_trash_path(item.class.name, item.id), method: :patch, local: true do |form| %>
17
- <%= form.submit " Restore", class: "btn btn-success btn-sm", onclick: "return confirm('Restore this #{item.class.name.downcase}?')" %>
18
- <% end %>
19
- <%= form_with url: recycle_bin.destroy_trash_path(item.class.name, item.id), method: :delete, local: true do |form| %>
20
- <%= form.submit "🗑️ Delete", class: "btn btn-danger btn-sm", onclick: "return confirm('Permanently delete this #{item.class.name.downcase}? This cannot be undone!')" %>
21
- <% end %>
58
+
59
+ <td class="actions-column">
60
+ <div class="action-buttons">
61
+ <%= link_to "👁️ View", recycle_bin.trash_path(item.class.name, item),
62
+ class: "btn btn-sm btn-outline",
63
+ title: "View details" %>
64
+ <%= link_to " Restore", recycle_bin.restore_trash_path(item.class.name, item),
65
+ method: :patch,
66
+ class: "btn btn-sm btn-success",
67
+ title: "Restore item",
68
+ data: { confirm: "Restore this #{item.class.name.downcase}?" } %>
69
+ <%= link_to "🗑️ Delete", recycle_bin.destroy_trash_path(item.class.name, item),
70
+ method: :delete,
71
+ class: "btn btn-sm btn-danger",
72
+ title: "Permanently delete",
73
+ data: { confirm: "Permanently delete this #{item.class.name.downcase}? This cannot be undone!" } %>
22
74
  </div>
23
75
  </td>
24
- </tr>
76
+ </tr>
77
+
78
+ <style>
79
+ .item-row {
80
+ transition: background-color 0.2s ease;
81
+ }
82
+
83
+ .item-row:hover {
84
+ background-color: #f8f9fa;
85
+ }
86
+
87
+ .item-content {
88
+ display: flex;
89
+ flex-direction: column;
90
+ gap: 4px;
91
+ }
92
+
93
+ .item-title {
94
+ font-weight: 600;
95
+ color: #212529;
96
+ line-height: 1.3;
97
+ }
98
+
99
+ .item-meta {
100
+ display: flex;
101
+ gap: 12px;
102
+ flex-wrap: wrap;
103
+ font-size: 0.85rem;
104
+ color: #6c757d;
105
+ }
106
+
107
+ .item-id, .item-user, .item-email {
108
+ background: #f8f9fa;
109
+ padding: 2px 6px;
110
+ border-radius: 4px;
111
+ border: 1px solid #e9ecef;
112
+ }
113
+
114
+ .timestamp-content {
115
+ display: flex;
116
+ flex-direction: column;
117
+ gap: 2px;
118
+ }
119
+
120
+ .timestamp-relative {
121
+ font-weight: 600;
122
+ color: #495057;
123
+ }
124
+
125
+ .timestamp-absolute {
126
+ font-size: 0.8rem;
127
+ color: #6c757d;
128
+ }
129
+
130
+ .size-column {
131
+ text-align: center;
132
+ }
133
+
134
+ .size-badge {
135
+ padding: 4px 8px;
136
+ border-radius: 12px;
137
+ font-size: 0.8rem;
138
+ font-weight: 600;
139
+ text-align: center;
140
+ min-width: 60px;
141
+ display: inline-block;
142
+ }
143
+
144
+ .size-badge.small {
145
+ background: #d4edda;
146
+ color: #155724;
147
+ border: 1px solid #c3e6cb;
148
+ }
149
+
150
+ .size-badge.medium {
151
+ background: #fff3cd;
152
+ color: #856404;
153
+ border: 1px solid #ffeaa7;
154
+ }
155
+
156
+ .size-badge.large {
157
+ background: #f8d7da;
158
+ color: #721c24;
159
+ border: 1px solid #f5c6cb;
160
+ }
161
+
162
+ .action-buttons {
163
+ display: flex;
164
+ gap: 4px;
165
+ flex-wrap: wrap;
166
+ }
167
+
168
+ .action-buttons .btn {
169
+ font-size: 0.8rem;
170
+ padding: 4px 8px;
171
+ }
172
+
173
+ /* Search highlighting */
174
+ mark {
175
+ background: #fff3cd;
176
+ color: #856404;
177
+ padding: 1px 3px;
178
+ border-radius: 3px;
179
+ font-weight: 600;
180
+ }
181
+
182
+ /* Model type badges */
183
+ .model-badge {
184
+ padding: 4px 8px;
185
+ border-radius: 12px;
186
+ font-size: 0.75rem;
187
+ font-weight: 600;
188
+ text-transform: uppercase;
189
+ letter-spacing: 0.5px;
190
+ }
191
+
192
+ .model-badge.user {
193
+ background: #e3f2fd;
194
+ color: #1976d2;
195
+ }
196
+
197
+ .model-badge.post {
198
+ background: #f3e5f5;
199
+ color: #7b1fa2;
200
+ }
201
+
202
+ .model-badge.comment {
203
+ background: #e8f5e8;
204
+ color: #388e3c;
205
+ }
206
+
207
+ .model-badge.order {
208
+ background: #fff3e0;
209
+ color: #f57c00;
210
+ }
211
+
212
+ .model-badge.product {
213
+ background: #fce4ec;
214
+ color: #c2185b;
215
+ }
216
+
217
+ /* Responsive adjustments */
218
+ @media (max-width: 768px) {
219
+ .item-meta {
220
+ flex-direction: column;
221
+ gap: 4px;
222
+ }
223
+
224
+ .action-buttons {
225
+ flex-direction: column;
226
+ gap: 2px;
227
+ }
228
+
229
+ .action-buttons .btn {
230
+ width: 100%;
231
+ text-align: center;
232
+ }
233
+ }
234
+ </style>
235
+
236
+ <script>
237
+ // Helper function to determine size class for styling
238
+ function sizeClass(item) {
239
+ // This will be handled by the helper method in the controller
240
+ return 'medium'; // Default fallback
241
+ }
242
+
243
+ // Update bulk count when checkboxes change
244
+ function updateBulkCount() {
245
+ const checkboxes = document.querySelectorAll('.item-checkbox:checked');
246
+ const bulkCount = document.getElementById('bulk-count');
247
+ const bulkActions = document.getElementById('bulk-actions');
248
+
249
+ if (bulkCount) {
250
+ bulkCount.textContent = `${checkboxes.length} item${checkboxes.length === 1 ? '' : 's'} selected`;
251
+ }
252
+
253
+ if (bulkActions) {
254
+ bulkActions.style.display = checkboxes.length > 0 ? 'flex' : 'none';
255
+ }
256
+
257
+ // Update bulk action forms
258
+ const selectedItems = Array.from(checkboxes).map(cb => cb.value);
259
+ document.getElementById('bulk-restore-items').value = JSON.stringify(selectedItems);
260
+ document.getElementById('bulk-destroy-items').value = JSON.stringify(selectedItems);
261
+ }
262
+
263
+ // Initialize bulk count on page load
264
+ document.addEventListener('DOMContentLoaded', function() {
265
+ updateBulkCount();
266
+ });
267
+ </script>
@@ -3,7 +3,12 @@
3
3
  <div class="stat-number"><%= number_with_delimiter(total_count) %></div>
4
4
  <div class="stat-label">Total Items in Trash</div>
5
5
  <div class="stat-change positive">
6
- <%= filtered_items.items.select { |item| item.deleted_at > 1.day.ago }.count %> deleted today
6
+ <% if defined?(dashboard_view) && dashboard_view %>
7
+ <% today_count = filtered_items.select { |item| item.respond_to?(:deleted_at) && item.deleted_at && item.deleted_at > 1.day.ago }.count %>
8
+ <% else %>
9
+ <% today_count = filtered_items.items.select { |item| item.respond_to?(:deleted_at) && item.deleted_at && item.deleted_at > 1.day.ago }.count %>
10
+ <% end %>
11
+ <%= today_count %> deleted today
7
12
  </div>
8
13
  </div>
9
14
  <div class="stat-card">
@@ -11,22 +16,35 @@
11
16
  <div class="stat-label">Model Types</div>
12
17
  <div class="stat-change">
13
18
  <% if model_types.any? %>
14
- <%= model_types.join(', ') %>
19
+ <%= model_types.first(2).join(', ') %><%= model_types.count > 2 ? " +#{model_types.count - 2}" : "" %>
15
20
  <% else %>
16
21
  No types
17
22
  <% end %>
18
23
  </div>
19
24
  </div>
20
25
  <div class="stat-card">
21
- <div class="stat-number"><%= filtered_items.items.select { |item| item.deleted_at > 7.days.ago }.count %></div>
26
+ <div class="stat-number">
27
+ <% if defined?(dashboard_view) && dashboard_view %>
28
+ <% week_count = filtered_items.select { |item| item.respond_to?(:deleted_at) && item.deleted_at && item.deleted_at > 7.days.ago }.count %>
29
+ <% else %>
30
+ <% week_count = filtered_items.items.select { |item| item.respond_to?(:deleted_at) && item.deleted_at && item.deleted_at > 7.days.ago }.count %>
31
+ <% end %>
32
+ <%= week_count %>
33
+ </div>
22
34
  <div class="stat-label">This Week</div>
23
35
  <div class="stat-change">Recent activity</div>
24
36
  </div>
25
37
  <div class="stat-card">
26
- <div class="stat-number"><%= current_page %> / <%= defined?(total_pages) ? total_pages : 1 %></div>
27
- <div class="stat-label">Current Page</div>
28
- <div class="stat-change">
29
- Showing <%= (current_page - 1) * per_page + 1 %>-<%= [(current_page * per_page), total_count].min %> of <%= number_with_delimiter(total_count) %>
30
- </div>
38
+ <% if defined?(dashboard_view) && dashboard_view %>
39
+ <div class="stat-number">🏠</div>
40
+ <div class="stat-label">Dashboard View</div>
41
+ <div class="stat-change">Overview</div>
42
+ <% else %>
43
+ <div class="stat-number"><%= current_page %> / <%= defined?(total_pages) ? total_pages : 1 %></div>
44
+ <div class="stat-label">Current Page</div>
45
+ <div class="stat-change">
46
+ Showing <%= (current_page - 1) * per_page + 1 %>-<%= [(current_page * per_page), total_count].min %> of <%= number_with_delimiter(total_count) %>
47
+ </div>
48
+ <% end %>
31
49
  </div>
32
- </div>
50
+ </div>