recycle_bin 1.1.0 → 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.
data/docs/logo.svg ADDED
@@ -0,0 +1,71 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">
2
+ <defs>
3
+ <!-- Gradient for the main container -->
4
+ <linearGradient id="containerGradient" x1="0%" y1="0%" x2="100%" y2="100%">
5
+ <stop offset="0%" style="stop-color:#667eea;stop-opacity:1" />
6
+ <stop offset="100%" style="stop-color:#764ba2;stop-opacity:1" />
7
+ </linearGradient>
8
+
9
+ <!-- Gradient for the lid -->
10
+ <linearGradient id="lidGradient" x1="0%" y1="0%" x2="100%" y2="100%">
11
+ <stop offset="0%" style="stop-color:#8b9cf7;stop-opacity:1" />
12
+ <stop offset="100%" style="stop-color:#667eea;stop-opacity:1" />
13
+ </linearGradient>
14
+
15
+ <!-- Shadow filter -->
16
+ <filter id="dropShadow" x="-50%" y="-50%" width="200%" height="200%">
17
+ <feDropShadow dx="3" dy="6" stdDeviation="4" flood-color="rgba(0,0,0,0.3)"/>
18
+ </filter>
19
+
20
+ <!-- Glow effect -->
21
+ <filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
22
+ <feGaussianBlur stdDeviation="3" result="coloredBlur"/>
23
+ <feMerge>
24
+ <feMergeNode in="coloredBlur"/>
25
+ <feMergeNode in="SourceGraphic"/>
26
+ </feMerge>
27
+ </filter>
28
+ </defs>
29
+
30
+ <!-- Background circle -->
31
+ <circle cx="100" cy="100" r="95" fill="url(#containerGradient)" filter="url(#dropShadow)" opacity="0.1"/>
32
+
33
+ <!-- Main trash bin body -->
34
+ <rect x="60" y="80" width="80" height="90" rx="8" ry="8" fill="url(#containerGradient)" filter="url(#dropShadow)"/>
35
+
36
+ <!-- Trash bin lid -->
37
+ <rect x="50" y="70" width="100" height="12" rx="6" ry="6" fill="url(#lidGradient)" filter="url(#dropShadow)"/>
38
+
39
+ <!-- Lid handle -->
40
+ <rect x="90" y="55" width="20" height="8" rx="4" ry="4" fill="url(#lidGradient)"/>
41
+ <rect x="95" y="63" width="10" height="12" fill="url(#lidGradient)"/>
42
+
43
+ <!-- Vertical lines on trash bin -->
44
+ <line x1="80" y1="90" x2="80" y2="155" stroke="rgba(255,255,255,0.3)" stroke-width="2" stroke-linecap="round"/>
45
+ <line x1="100" y1="90" x2="100" y2="155" stroke="rgba(255,255,255,0.3)" stroke-width="2" stroke-linecap="round"/>
46
+ <line x1="120" y1="90" x2="120" y2="155" stroke="rgba(255,255,255,0.3)" stroke-width="2" stroke-linecap="round"/>
47
+
48
+ <!-- Restore arrow (curved arrow indicating recovery) -->
49
+ <g transform="translate(130, 40)" filter="url(#glow)">
50
+ <path d="M 0 15 Q 10 5 20 15 Q 15 10 15 20" stroke="#28a745" stroke-width="3" fill="none" stroke-linecap="round"/>
51
+ <polygon points="12,18 18,18 15,24" fill="#28a745"/>
52
+ </g>
53
+
54
+ <!-- Floating particles (representing restored items) -->
55
+ <circle cx="45" cy="50" r="3" fill="#28a745" opacity="0.7">
56
+ <animate attributeName="cy" values="50;45;50" dur="2s" repeatCount="indefinite"/>
57
+ </circle>
58
+ <circle cx="155" cy="60" r="2" fill="#ffc107" opacity="0.8">
59
+ <animate attributeName="cy" values="60;55;60" dur="1.5s" repeatCount="indefinite"/>
60
+ <animate attributeName="opacity" values="0.8;0.4;0.8" dur="1.5s" repeatCount="indefinite"/>
61
+ </circle>
62
+ <circle cx="40" cy="120" r="2.5" fill="#17a2b8" opacity="0.6">
63
+ <animate attributeName="cy" values="120;115;120" dur="2.5s" repeatCount="indefinite"/>
64
+ </circle>
65
+
66
+ <!-- Subtle highlight on the bin -->
67
+ <rect x="62" y="82" width="15" height="60" rx="4" ry="4" fill="rgba(255,255,255,0.2)"/>
68
+
69
+ <!-- Brand text (small) -->
70
+ <text x="100" y="190" text-anchor="middle" font-family="Inter, sans-serif" font-size="14" font-weight="600" fill="url(#containerGradient)">RecycleBin</text>
71
+ </svg>
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RecycleBin
4
- VERSION = '1.1.0'
4
+ VERSION = '1.1.1'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: recycle_bin
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rishi Somani
@@ -9,7 +9,7 @@ authors:
9
9
  - Raghav Agrawal
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-05-25 00:00:00.000000000 Z
12
+ date: 2025-05-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -92,13 +92,20 @@ files:
92
92
  - app/controllers/recycle_bin/application_controller.rb
93
93
  - app/controllers/recycle_bin/trash_controller.rb
94
94
  - app/helpers/recycle_bin/application_helper.rb
95
- - app/views/layouts/recycle_bin/application.html.erb
96
- - app/views/layouts/recycle_bin/recycle_bin/application.html.erb
97
- - app/views/layouts/recycle_bin/recycle_bin/trash/index.html.erb
98
- - app/views/layouts/recycle_bin/recycle_bin/trash/show.html.erb
95
+ - app/views/recycle_bin/layouts/recycle_bin.html.erb
96
+ - app/views/recycle_bin/shared/_error_messages.html.erb
97
+ - app/views/recycle_bin/shared/_flash_messages.html.erb
98
+ - app/views/recycle_bin/trash/_action_history.html.erb
99
+ - app/views/recycle_bin/trash/_associations.html.erb
100
+ - app/views/recycle_bin/trash/_filters.html.erb
101
+ - app/views/recycle_bin/trash/_item.html.erb
102
+ - app/views/recycle_bin/trash/_pagination.html.erb
103
+ - app/views/recycle_bin/trash/_stats.html.erb
99
104
  - app/views/recycle_bin/trash/index.html.erb
100
105
  - app/views/recycle_bin/trash/show.html.erb
101
106
  - config/routes.rb
107
+ - docs/index.html
108
+ - docs/logo.svg
102
109
  - lib/generators/recycle_bin/add_deleted_at/add_deleted_at_generator.rb
103
110
  - lib/generators/recycle_bin/add_deleted_at/templates/add_deleted_at_migration.rb.erb
104
111
  - lib/generators/recycle_bin/install/install_generator.rb
@@ -1,266 +0,0 @@
1
-
2
- <!DOCTYPE html>
3
- <html>
4
- <head>
5
- <title>Recycle Bin</title>
6
- <meta name="viewport" content="width=device-width,initial-scale=1">
7
- <%= csrf_meta_tags %>
8
- <%= csp_meta_tag %>
9
-
10
- <style>
11
- /* Simple, clean CSS for V1 MVP */
12
- * {
13
- box-sizing: border-box;
14
- margin: 0;
15
- padding: 0;
16
- }
17
-
18
- body {
19
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
20
- line-height: 1.6;
21
- color: #333;
22
- background-color: #f8f9fa;
23
- }
24
-
25
- .container {
26
- max-width: 1200px;
27
- margin: 0 auto;
28
- padding: 0 20px;
29
- }
30
-
31
- /* Header */
32
- .header {
33
- background: #fff;
34
- border-bottom: 1px solid #dee2e6;
35
- padding: 1rem 0;
36
- margin-bottom: 2rem;
37
- }
38
-
39
- .header h1 {
40
- color: #495057;
41
- font-size: 1.5rem;
42
- display: flex;
43
- align-items: center;
44
- gap: 0.5rem;
45
- }
46
-
47
- .header .trash-icon {
48
- font-size: 1.8rem;
49
- }
50
-
51
- /* Navigation */
52
- .nav {
53
- margin-top: 1rem;
54
- }
55
-
56
- .nav a {
57
- color: #6c757d;
58
- text-decoration: none;
59
- margin-right: 1.5rem;
60
- padding: 0.5rem 0;
61
- border-bottom: 2px solid transparent;
62
- transition: all 0.2s;
63
- }
64
-
65
- .nav a:hover,
66
- .nav a.active {
67
- color: #495057;
68
- border-bottom-color: #007bff;
69
- }
70
-
71
- /* Cards */
72
- .card {
73
- background: #fff;
74
- border-radius: 8px;
75
- box-shadow: 0 1px 3px rgba(0,0,0,0.1);
76
- padding: 1.5rem;
77
- margin-bottom: 1rem;
78
- }
79
-
80
- /* Buttons */
81
- .btn {
82
- display: inline-block;
83
- padding: 0.5rem 1rem;
84
- border: none;
85
- border-radius: 4px;
86
- text-decoration: none;
87
- cursor: pointer;
88
- font-size: 0.875rem;
89
- transition: all 0.2s;
90
- }
91
-
92
- .btn-primary {
93
- background: #007bff;
94
- color: white;
95
- }
96
-
97
- .btn-primary:hover {
98
- background: #0056b3;
99
- }
100
-
101
- .btn-success {
102
- background: #28a745;
103
- color: white;
104
- }
105
-
106
- .btn-success:hover {
107
- background: #1e7e34;
108
- }
109
-
110
- .btn-danger {
111
- background: #dc3545;
112
- color: white;
113
- }
114
-
115
- .btn-danger:hover {
116
- background: #c82333;
117
- }
118
-
119
- .btn-sm {
120
- padding: 0.25rem 0.75rem;
121
- font-size: 0.8rem;
122
- }
123
-
124
- /* Tables */
125
- .table {
126
- width: 100%;
127
- border-collapse: collapse;
128
- background: #fff;
129
- border-radius: 8px;
130
- overflow: hidden;
131
- box-shadow: 0 1px 3px rgba(0,0,0,0.1);
132
- }
133
-
134
- .table th,
135
- .table td {
136
- padding: 1rem;
137
- text-align: left;
138
- border-bottom: 1px solid #dee2e6;
139
- }
140
-
141
- .table th {
142
- background: #f8f9fa;
143
- font-weight: 600;
144
- color: #495057;
145
- }
146
-
147
- .table tr:hover {
148
- background: #f8f9fa;
149
- }
150
-
151
- /* Stats */
152
- .stats {
153
- display: grid;
154
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
155
- gap: 1rem;
156
- margin-bottom: 2rem;
157
- }
158
-
159
- .stat-card {
160
- background: #fff;
161
- padding: 1.5rem;
162
- border-radius: 8px;
163
- box-shadow: 0 1px 3px rgba(0,0,0,0.1);
164
- text-align: center;
165
- }
166
-
167
- .stat-number {
168
- font-size: 2rem;
169
- font-weight: bold;
170
- color: #007bff;
171
- }
172
-
173
- .stat-label {
174
- color: #6c757d;
175
- font-size: 0.875rem;
176
- margin-top: 0.5rem;
177
- }
178
-
179
- /* Empty state */
180
- .empty-state {
181
- text-align: center;
182
- padding: 4rem 2rem;
183
- color: #6c757d;
184
- }
185
-
186
- .empty-state-icon {
187
- font-size: 4rem;
188
- margin-bottom: 1rem;
189
- }
190
-
191
- /* Responsive */
192
- @media (max-width: 768px) {
193
- .container {
194
- padding: 0 15px;
195
- }
196
-
197
- .table {
198
- font-size: 0.875rem;
199
- }
200
-
201
- .table th,
202
- .table td {
203
- padding: 0.75rem 0.5rem;
204
- }
205
-
206
- .btn {
207
- font-size: 0.8rem;
208
- padding: 0.4rem 0.8rem;
209
- }
210
- }
211
-
212
- /* Alerts */
213
- .alert {
214
- padding: 0.75rem 1rem;
215
- margin-bottom: 1rem;
216
- border-radius: 4px;
217
- }
218
-
219
- .alert-success {
220
- background: #d4edda;
221
- color: #155724;
222
- border: 1px solid #c3e6cb;
223
- }
224
-
225
- .alert-danger {
226
- background: #f8d7da;
227
- color: #721c24;
228
- border: 1px solid #f5c6cb;
229
- }
230
-
231
- .alert-info {
232
- background: #d1ecf1;
233
- color: #0c5460;
234
- border: 1px solid #bee5eb;
235
- }
236
- </style>
237
- </head>
238
-
239
- <body>
240
- <div class="header">
241
- <div class="container">
242
- <h1>
243
- <span class="trash-icon">🗑️</span>
244
- Recycle Bin
245
- </h1>
246
- <nav class="nav">
247
- <%= link_to "All Items", recycle_bin.trash_index_path,
248
- class: ("active" if current_page?(recycle_bin.trash_index_path)) %>
249
- <%= link_to "Statistics", "#", class: "disabled" %>
250
- </nav>
251
- </div>
252
- </div>
253
-
254
- <div class="container">
255
- <% if notice %>
256
- <div class="alert alert-success"><%= notice %></div>
257
- <% end %>
258
-
259
- <% if alert %>
260
- <div class="alert alert-danger"><%= alert %></div>
261
- <% end %>
262
-
263
- <%= yield %>
264
- </div>
265
- </body>
266
- </html>
@@ -1,133 +0,0 @@
1
- <% content_for :title, "Recycle Bin" %>
2
-
3
- <!-- Statistics Cards -->
4
- <div class="stats">
5
- <div class="stat-card">
6
- <div class="stat-number"><%= @deleted_items.count %></div>
7
- <div class="stat-label">Items in Trash</div>
8
- </div>
9
-
10
- <div class="stat-card">
11
- <div class="stat-number"><%= @model_types.count %></div>
12
- <div class="stat-label">Different Types</div>
13
- </div>
14
-
15
- <div class="stat-card">
16
- <div class="stat-number">
17
- <%= @deleted_items.where('deleted_at > ?', 1.day.ago).count %>
18
- </div>
19
- <div class="stat-label">Deleted Today</div>
20
- </div>
21
- </div>
22
-
23
- <!-- Main Content -->
24
- <div class="card">
25
- <% if @deleted_items.any? %>
26
- <h2 style="margin-bottom: 1.5rem; color: #495057;">
27
- Deleted Items
28
- <span style="font-size: 0.8em; color: #6c757d;">
29
- (<%= @deleted_items.count %> items)
30
- </span>
31
- </h2>
32
-
33
- <!-- Model Type Filter -->
34
- <div style="margin-bottom: 1.5rem;">
35
- <strong>Filter by type:</strong>
36
- <%= link_to "All", recycle_bin.trash_index_path,
37
- class: "btn btn-sm #{'btn-primary' if params[:type].blank?}" %>
38
- <% @model_types.each do |model_type| %>
39
- <%= link_to model_type, recycle_bin.trash_index_path(type: model_type),
40
- class: "btn btn-sm #{'btn-primary' if params[:type] == model_type}" %>
41
- <% end %>
42
- </div>
43
-
44
- <!-- Items Table -->
45
- <table class="table">
46
- <thead>
47
- <tr>
48
- <th>Type</th>
49
- <th>Title</th>
50
- <th>Deleted At</th>
51
- <th>Actions</th>
52
- </tr>
53
- </thead>
54
- <tbody>
55
- <% @deleted_items.each do |item| %>
56
- <tr>
57
- <td>
58
- <strong><%= item.class.name %></strong>
59
- </td>
60
- <td>
61
- <%= link_to truncate(item.recyclable_title, length: 50),
62
- recycle_bin.trash_path(item),
63
- style: "text-decoration: none; color: #007bff;" %>
64
- </td>
65
- <td>
66
- <span style="color: #6c757d;">
67
- <%= time_ago_in_words(item.deleted_at) %> ago
68
- </span>
69
- <br>
70
- <small style="color: #adb5bd;">
71
- <%= item.deleted_at.strftime('%B %d, %Y at %I:%M %p') %>
72
- </small>
73
- </td>
74
- <td>
75
- <%= link_to "View", recycle_bin.trash_path(item),
76
- class: "btn btn-sm btn-primary" %>
77
- <%= link_to "Restore", recycle_bin.restore_trash_path(item),
78
- method: :patch,
79
- class: "btn btn-sm btn-success",
80
- data: {
81
- confirm: "Are you sure you want to restore this #{item.class.name.downcase}?"
82
- } %>
83
- <%= link_to "Delete Forever", recycle_bin.trash_path(item),
84
- method: :delete,
85
- class: "btn btn-sm btn-danger",
86
- data: {
87
- confirm: "This will permanently delete this #{item.class.name.downcase}. This action cannot be undone!"
88
- } %>
89
- </td>
90
- </tr>
91
- <% end %>
92
- </tbody>
93
- </table>
94
-
95
- <!-- Bulk Actions -->
96
- <div style="margin-top: 2rem; padding-top: 1rem; border-top: 1px solid #dee2e6;">
97
- <p style="color: #6c757d; font-size: 0.875rem;">
98
- <strong>Bulk Actions:</strong>
99
- Select items above to restore or delete multiple items at once.
100
- <em>(Coming in v1.1)</em>
101
- </p>
102
- </div>
103
-
104
- <% else %>
105
- <!-- Empty State -->
106
- <div class="empty-state">
107
- <div class="empty-state-icon">🎉</div>
108
- <h3>Your trash is empty!</h3>
109
- <p>When you delete items from your application, they'll appear here so you can restore them if needed.</p>
110
-
111
- <div style="margin-top: 2rem;">
112
- <h4 style="color: #495057;">How to use RecycleBin:</h4>
113
- <div style="text-align: left; max-width: 500px; margin: 1rem auto;">
114
- <p><strong>1.</strong> Add <code>include RecycleBin::SoftDeletable</code> to your models</p>
115
- <p><strong>2.</strong> Add <code>deleted_at:datetime</code> column to your tables</p>
116
- <p><strong>3.</strong> Call <code>.destroy</code> on records - they'll come here instead of being deleted</p>
117
- <p><strong>4.</strong> Use <code>.restore</code> to bring them back</p>
118
- </div>
119
- </div>
120
- </div>
121
- <% end %>
122
- </div>
123
-
124
- <!-- Help Section -->
125
- <div class="card" style="margin-top: 2rem; background: #f8f9fa;">
126
- <h4 style="color: #495057; margin-bottom: 1rem;">💡 Pro Tips</h4>
127
- <ul style="color: #6c757d; line-height: 1.8;">
128
- <li><strong>Restore:</strong> Click "Restore" to bring items back to your application</li>
129
- <li><strong>Permanent Delete:</strong> "Delete Forever" removes items completely (cannot be undone)</li>
130
- <li><strong>Auto-cleanup:</strong> Items older than 30 days are automatically cleaned up</li>
131
- <li><strong>Search:</strong> Use your browser's find (Ctrl/Cmd+F) to search this page</li>
132
- </ul>
133
- </div>