upload_d_n_d 0.9.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.

Potentially problematic release.


This version of upload_d_n_d might be problematic. Click here for more details.

Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +229 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/upload_d_n_d_manifest.js +3 -0
  6. data/app/assets/stylesheets/upload_d_n_d/application.css +604 -0
  7. data/app/components/upload_d_n_d/upload_component.html.erb +53 -0
  8. data/app/components/upload_d_n_d/upload_component.rb +204 -0
  9. data/app/controllers/concerns/upload_d_n_d/rate_limiting.rb +89 -0
  10. data/app/controllers/upload_d_n_d/attachments_controller.rb +218 -0
  11. data/app/controllers/upload_d_n_d/base_attachments_controller.rb +250 -0
  12. data/app/controllers/upload_d_n_d/temporary_attachments_controller.rb +200 -0
  13. data/app/helpers/upload_d_n_d/application_helper.rb +51 -0
  14. data/app/helpers/upload_d_n_d/controllers/helpers.rb +21 -0
  15. data/app/javascript/upload_d_n_d/controllers/preview_controller.js +217 -0
  16. data/app/javascript/upload_d_n_d/controllers/uploads_controller.js +396 -0
  17. data/app/javascript/upload_d_n_d/index.js +13 -0
  18. data/app/jobs/upload_d_n_d/application_job.rb +4 -0
  19. data/app/jobs/upload_d_n_d/cleanup_temporary_attachments_job.rb +17 -0
  20. data/app/jobs/upload_d_n_d/purge_orphan_blobs_job.rb +25 -0
  21. data/app/jobs/upload_d_n_d/purge_rejected_blob_job.rb +24 -0
  22. data/app/models/upload_d_n_d/application_record.rb +5 -0
  23. data/app/models/upload_d_n_d/temporary_attachment.rb +129 -0
  24. data/app/views/upload_d_n_d/shared/_file_icon.html.erb +9 -0
  25. data/app/views/upload_d_n_d/shared/_files_list.html.erb +63 -0
  26. data/app/views/upload_d_n_d/shared/_temp_files_list.html.erb +53 -0
  27. data/config/importmap.rb +5 -0
  28. data/config/initializers/inflections.rb +11 -0
  29. data/config/locales/upload_d_n_d.en.yml +80 -0
  30. data/config/locales/upload_d_n_d.fr.yml +80 -0
  31. data/config/routes.rb +12 -0
  32. data/docs/CHANGELOG.md +282 -0
  33. data/lib/generators/upload_d_n_d/POLICY_README +49 -0
  34. data/lib/generators/upload_d_n_d/USAGE +80 -0
  35. data/lib/generators/upload_d_n_d/install_generator.rb +174 -0
  36. data/lib/generators/upload_d_n_d/mime_type_helper.rb +106 -0
  37. data/lib/generators/upload_d_n_d/model_generator.rb +313 -0
  38. data/lib/generators/upload_d_n_d/policy_generator.rb +25 -0
  39. data/lib/generators/upload_d_n_d/templates/POST_INSTALL +62 -0
  40. data/lib/generators/upload_d_n_d/templates/concerns/controllers_uploadable.rb +115 -0
  41. data/lib/generators/upload_d_n_d/templates/concerns/upload_authorization.rb +91 -0
  42. data/lib/generators/upload_d_n_d/templates/concerns/uploadable.rb +101 -0
  43. data/lib/generators/upload_d_n_d/templates/controller.rb.tt +60 -0
  44. data/lib/generators/upload_d_n_d/templates/helpers/upload_helper.rb +105 -0
  45. data/lib/generators/upload_d_n_d/templates/initializers/upload_d_n_d.rb +69 -0
  46. data/lib/generators/upload_d_n_d/templates/migrations/create_upload_d_n_d_temporary_attachments.rb +18 -0
  47. data/lib/generators/upload_d_n_d/templates/policies/upload_d_n_d_attachment_policy.rb +37 -0
  48. data/lib/generators/upload_d_n_d/templates/policies/upload_d_n_d_temporary_attachment_policy.rb +56 -0
  49. data/lib/generators/upload_d_n_d/templates/validators/file_validator.rb +171 -0
  50. data/lib/tasks/upload_d_n_d_storage.rake +27 -0
  51. data/lib/tasks/upload_d_n_d_tasks.rake +20 -0
  52. data/lib/upload_d_n_d/attachment_lookup.rb +24 -0
  53. data/lib/upload_d_n_d/authorization/can_can_can_adapter.rb +29 -0
  54. data/lib/upload_d_n_d/authorization/no_authorization.rb +13 -0
  55. data/lib/upload_d_n_d/authorization/pundit_adapter.rb +41 -0
  56. data/lib/upload_d_n_d/authorization/unconfigured.rb +15 -0
  57. data/lib/upload_d_n_d/authorization.rb +66 -0
  58. data/lib/upload_d_n_d/configuration.rb +97 -0
  59. data/lib/upload_d_n_d/controllers/uploadable.rb +271 -0
  60. data/lib/upload_d_n_d/engine.rb +50 -0
  61. data/lib/upload_d_n_d/field_constraints.rb +92 -0
  62. data/lib/upload_d_n_d/field_reference.rb +44 -0
  63. data/lib/upload_d_n_d/file_validator.rb +156 -0
  64. data/lib/upload_d_n_d/mime_types.rb +75 -0
  65. data/lib/upload_d_n_d/orphan_blobs.rb +151 -0
  66. data/lib/upload_d_n_d/rejected_blob.rb +42 -0
  67. data/lib/upload_d_n_d/session_id.rb +25 -0
  68. data/lib/upload_d_n_d/uploadable.rb +117 -0
  69. data/lib/upload_d_n_d/version.rb +3 -0
  70. data/lib/upload_d_n_d.rb +62 -0
  71. metadata +150 -0
@@ -0,0 +1,604 @@
1
+ :root {
2
+ --udnd-accent-color: #e97451;
3
+ --udnd-accent-rgb: 233 116 81;
4
+ --udnd-border-color: #e5e7eb;
5
+ --udnd-bg: #ffffff;
6
+ --udnd-bg-hover: #f9fafb;
7
+ --udnd-text-primary: #111827;
8
+ --udnd-text-secondary: #6b7280;
9
+ --udnd-shadow: 0 10px 25px rgba(17, 24, 39, 0.08);
10
+ }
11
+
12
+ .udnd-container {
13
+ width: 100%;
14
+ font-family: inherit;
15
+ background-color: #ffffff;
16
+ border: 1px solid #e5e7eb;
17
+ border-radius: 0.75rem;
18
+ padding: 1rem;
19
+ margin: 1rem 0;
20
+ }
21
+
22
+ .udnd-dropzone {
23
+ border: 1.5px solid rgb(var(--udnd-accent-rgb) / 0.45);
24
+ border-radius: 0.5rem;
25
+ padding: 2rem 1.5rem;
26
+ text-align: center;
27
+ position: relative;
28
+ background: linear-gradient(
29
+ 180deg,
30
+ rgba(255, 255, 255, 0.92),
31
+ rgba(255, 255, 255, 0.75)
32
+ );
33
+ box-shadow: 0 1px 0 rgba(17, 24, 39, 0.04);
34
+ transition: transform 0.18s ease, box-shadow 0.18s ease,
35
+ border-color 0.18s ease, background-color 0.18s ease;
36
+ cursor: pointer;
37
+ }
38
+
39
+ .udnd-dropzone:hover {
40
+ box-shadow: var(--udnd-shadow);
41
+ transform: translateY(-1px);
42
+ }
43
+
44
+ .udnd-dropzone:focus-within {
45
+ outline: none;
46
+ border-color: var(--udnd-accent-color);
47
+ box-shadow: 0 0 0 4px rgb(var(--udnd-accent-rgb) / 0.18), var(--udnd-shadow);
48
+ }
49
+
50
+ .udnd-dropzone.dragover {
51
+ border-color: var(--udnd-accent-color);
52
+ background-color: var(--udnd-bg-hover);
53
+ box-shadow: 0 0 0 4px rgb(var(--udnd-accent-rgb) / 0.18), var(--udnd-shadow);
54
+ transform: translateY(-1px);
55
+ }
56
+
57
+ .udnd-input-hidden {
58
+ position: absolute;
59
+ inset: 0;
60
+ width: 100%;
61
+ height: 100%;
62
+ opacity: 0;
63
+ cursor: pointer;
64
+ }
65
+
66
+ .udnd-dropzone-content {
67
+ display: flex;
68
+ flex-direction: column;
69
+ align-items: center;
70
+ gap: 0.375rem;
71
+ }
72
+
73
+ .udnd-icon-wrapper {
74
+ width: 3.25rem;
75
+ height: 3.25rem;
76
+ display: flex;
77
+ align-items: center;
78
+ justify-content: center;
79
+ border-radius: 9999px;
80
+ background: rgb(var(--udnd-accent-rgb) / 0.12);
81
+ color: var(--udnd-accent-color);
82
+ margin-bottom: 0.25rem;
83
+ box-shadow: 0 1px 0 rgba(17, 24, 39, 0.05);
84
+ }
85
+
86
+ /* Lucide inline SVG icons */
87
+ .udnd-icon {
88
+ width: 1em;
89
+ height: 1em;
90
+ vertical-align: -0.125em;
91
+ flex-shrink: 0;
92
+ }
93
+
94
+ .udnd-icon-lg {
95
+ width: 1.35rem;
96
+ height: 1.35rem;
97
+ }
98
+
99
+ .udnd-icon-xl {
100
+ width: 3rem;
101
+ height: 3rem;
102
+ }
103
+
104
+ .udnd-text-main {
105
+ font-weight: 600;
106
+ color: var(--udnd-text-primary);
107
+ font-size: 0.95rem;
108
+ line-height: 1.35;
109
+ margin: 0;
110
+ }
111
+
112
+ .udnd-text-sub {
113
+ color: var(--udnd-text-secondary);
114
+ font-size: 0.825rem;
115
+ line-height: 1.35;
116
+ margin: 0;
117
+ }
118
+
119
+ .udnd-progress-container {
120
+ height: 6px;
121
+ background: rgba(17, 24, 39, 0.08);
122
+ border-radius: 9999px;
123
+ margin: 12px auto 0;
124
+ overflow: hidden;
125
+ display: none;
126
+ }
127
+
128
+ .udnd-dropzone.upload-active .udnd-progress-container {
129
+ display: block;
130
+ }
131
+
132
+ .udnd-container.upload-active .udnd-progress-container {
133
+ display: block;
134
+ }
135
+
136
+ .udnd-progress-bar {
137
+ height: 100%;
138
+ background: linear-gradient(
139
+ 90deg,
140
+ rgba(233, 116, 81, 0.75),
141
+ var(--udnd-accent-color)
142
+ );
143
+ width: 0%;
144
+ transition: width 0.1s ease;
145
+ }
146
+
147
+ /* Files list */
148
+ .udnd-files-list {
149
+ margin-top: 1rem;
150
+ }
151
+
152
+ .udnd-file-items {
153
+ list-style: none;
154
+ padding: 0;
155
+ margin: 0;
156
+ }
157
+
158
+ .udnd-file-item {
159
+ display: flex;
160
+ align-items: center;
161
+ justify-content: space-between;
162
+ padding: 0.75rem;
163
+ border: 1px solid var(--udnd-border-color);
164
+ border-radius: 0.375rem;
165
+ margin-bottom: 0.5rem;
166
+ transition: background-color 0.2s ease;
167
+ }
168
+
169
+ .udnd-file-item:hover {
170
+ background-color: var(--udnd-bg-hover);
171
+ }
172
+
173
+ .udnd-file-info {
174
+ display: flex;
175
+ align-items: center;
176
+ gap: 0.75rem;
177
+ flex: 1;
178
+ }
179
+
180
+ .udnd-file-icon {
181
+ display: flex;
182
+ align-items: center;
183
+ justify-content: center;
184
+ width: 2.5rem;
185
+ height: 2.5rem;
186
+ border-radius: 0.375rem;
187
+ background-color: var(--udnd-bg-hover);
188
+ color: var(--udnd-accent-color);
189
+ font-size: 1.25rem;
190
+ }
191
+
192
+ .udnd-file-details {
193
+ display: flex;
194
+ flex-direction: column;
195
+ gap: 0.125rem;
196
+ }
197
+
198
+ .udnd-filename {
199
+ font-weight: 500;
200
+ color: var(--udnd-text-primary);
201
+ font-size: 0.875rem;
202
+ }
203
+
204
+ .udnd-filesize {
205
+ font-size: 0.75rem;
206
+ color: var(--udnd-text-secondary);
207
+ }
208
+
209
+ .udnd-btn-remove {
210
+ display: flex;
211
+ align-items: center;
212
+ justify-content: center;
213
+ width: 2rem;
214
+ height: 2rem;
215
+ border: none;
216
+ border-radius: 0.375rem;
217
+ background-color: transparent;
218
+ color: #ef4444;
219
+ cursor: pointer;
220
+ transition: all 0.2s ease;
221
+ }
222
+
223
+ .udnd-btn-remove:hover {
224
+ background-color: #fee2e2;
225
+ transform: scale(1.1);
226
+ }
227
+
228
+ .udnd-no-files {
229
+ text-align: center;
230
+ color: var(--udnd-text-secondary);
231
+ font-size: 0.875rem;
232
+ padding: 1rem;
233
+ margin: 0;
234
+ }
235
+
236
+ /* === Actions des fichiers === */
237
+ .udnd-file-actions {
238
+ display: flex;
239
+ gap: 0.5rem;
240
+ align-items: center;
241
+ }
242
+
243
+ .udnd-btn-preview {
244
+ display: flex;
245
+ align-items: center;
246
+ justify-content: center;
247
+ width: 2rem;
248
+ height: 2rem;
249
+ border: none;
250
+ border-radius: 0.375rem;
251
+ background-color: transparent;
252
+ color: #27885d;
253
+ cursor: pointer;
254
+ transition: all 0.2s ease;
255
+ }
256
+
257
+ .udnd-btn-preview:hover {
258
+ background-color: #d8f3e7;
259
+ transform: scale(1.1);
260
+ }
261
+
262
+ /* === Modale de prévisualisation === */
263
+ .udnd-preview-modal {
264
+ position: fixed;
265
+ inset: 0;
266
+ z-index: 9999;
267
+ display: flex;
268
+ align-items: center;
269
+ justify-content: center;
270
+ opacity: 0;
271
+ transition: opacity 0.3s ease;
272
+ }
273
+
274
+ .udnd-preview-modal.show {
275
+ width: 100%;
276
+ opacity: 1;
277
+ }
278
+
279
+ .udnd-preview-overlay {
280
+ position: absolute;
281
+ inset: 0;
282
+ background-color: rgba(0, 0, 0, 0.75);
283
+ backdrop-filter: blur(4px);
284
+ }
285
+
286
+ .udnd-preview-container {
287
+ position: relative;
288
+ background-color: white;
289
+ border-radius: 0.75rem;
290
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
291
+ width: 60%;
292
+ max-height: 100%;
293
+ display: flex;
294
+ flex-direction: column;
295
+ overflow: hidden;
296
+ }
297
+
298
+ @media (max-width: 768px) {
299
+ .udnd-preview-container {
300
+ width: 90%;
301
+ }
302
+ }
303
+
304
+ .udnd-preview-header {
305
+ display: flex;
306
+ align-items: center;
307
+ justify-content: space-between;
308
+ padding: 1rem;
309
+ border-bottom: 1px solid var(--udnd-border-color);
310
+ background-color: #f9fafb;
311
+ }
312
+
313
+ .udnd-preview-title {
314
+ margin: 0;
315
+ font-size: 1.125rem;
316
+ font-weight: 600;
317
+ color: var(--udnd-text-primary);
318
+ max-width: 80%;
319
+ overflow: hidden;
320
+ text-overflow: ellipsis;
321
+ white-space: nowrap;
322
+ }
323
+
324
+ .udnd-preview-close {
325
+ display: flex;
326
+ align-items: center;
327
+ justify-content: center;
328
+ width: 2.5rem;
329
+ height: 2.5rem;
330
+ border: none;
331
+ border-radius: 0.5rem;
332
+ background-color: transparent;
333
+ color: #6b7280;
334
+ cursor: pointer;
335
+ transition: all 0.2s ease;
336
+ font-size: 1.25rem;
337
+ }
338
+
339
+ .udnd-preview-close:hover {
340
+ background-color: #e5e7eb;
341
+ color: #111827;
342
+ }
343
+
344
+ .udnd-preview-body {
345
+ padding: 1.5rem;
346
+ overflow: auto;
347
+ display: flex;
348
+ align-items: center;
349
+ justify-content: center;
350
+ min-height: 200px;
351
+ }
352
+
353
+ .udnd-preview-image {
354
+ display: block;
355
+ max-width: 100%;
356
+ max-height: 80vh;
357
+ object-fit: contain;
358
+ border-radius: 0.5rem;
359
+ }
360
+
361
+ .udnd-preview-pdf {
362
+ width: 100%;
363
+ min-height: 80vh;
364
+ border: none;
365
+ border-radius: 0.5rem;
366
+ }
367
+
368
+ .udnd-preview-unsupported {
369
+ display: flex;
370
+ flex-direction: column;
371
+ align-items: center;
372
+ justify-content: center;
373
+ gap: 1rem;
374
+ padding: 3rem;
375
+ text-align: center;
376
+ color: var(--udnd-text-secondary);
377
+ }
378
+
379
+ .udnd-preview-unsupported svg {
380
+ color: var(--udnd-text-secondary);
381
+ opacity: 0.5;
382
+ }
383
+
384
+ .udnd-btn-download {
385
+ display: inline-flex;
386
+ align-items: center;
387
+ gap: 0.5rem;
388
+ padding: 0.75rem 1.5rem;
389
+ background-color: var(--udnd-accent-color);
390
+ color: white;
391
+ text-decoration: none;
392
+ border-radius: 0.5rem;
393
+ font-weight: 500;
394
+ transition: all 0.2s ease;
395
+ }
396
+
397
+ .udnd-btn-download:hover {
398
+ background-color: color-mix(in srgb, var(--udnd-accent-color) 85%, black);
399
+ transform: translateY(-2px);
400
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
401
+ }
402
+ /* ================================================
403
+ MODAL SYSTEM - Native modals for alerts & confirms
404
+ ================================================ */
405
+
406
+ /* Overlay */
407
+ .udnd-modal-overlay {
408
+ position: fixed;
409
+ top: 0;
410
+ left: 0;
411
+ right: 0;
412
+ bottom: 0;
413
+ background-color: rgba(17, 24, 39, 0.5);
414
+ backdrop-filter: blur(4px);
415
+ display: flex;
416
+ align-items: center;
417
+ justify-content: center;
418
+ z-index: 9999;
419
+ opacity: 0;
420
+ transition: opacity 0.3s ease;
421
+ padding: 1rem;
422
+ }
423
+
424
+ .udnd-modal-overlay--active {
425
+ opacity: 1;
426
+ }
427
+
428
+ /* Modal container */
429
+ .udnd-modal {
430
+ background: white;
431
+ border-radius: 1rem;
432
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1),
433
+ 0 10px 10px -5px rgba(0, 0, 0, 0.04);
434
+ max-width: 28rem;
435
+ width: 100%;
436
+ transform: scale(0.95);
437
+ transition: transform 0.3s ease;
438
+ animation: udnd-modal-slide-up 0.3s ease forwards;
439
+ }
440
+
441
+ .udnd-modal-overlay--active .udnd-modal {
442
+ transform: scale(1);
443
+ }
444
+
445
+ @keyframes udnd-modal-slide-up {
446
+ from {
447
+ transform: translateY(1rem) scale(0.95);
448
+ opacity: 0;
449
+ }
450
+ to {
451
+ transform: translateY(0) scale(1);
452
+ opacity: 1;
453
+ }
454
+ }
455
+
456
+ /* Modal header */
457
+ .udnd-modal-header {
458
+ padding: 1.5rem 1.5rem 0.5rem;
459
+ display: flex;
460
+ justify-content: center;
461
+ }
462
+
463
+ .udnd-modal-icon {
464
+ width: 3rem;
465
+ height: 3rem;
466
+ border-radius: 50%;
467
+ display: flex;
468
+ align-items: center;
469
+ justify-content: center;
470
+ }
471
+
472
+ .udnd-modal-icon svg {
473
+ width: 1.75rem;
474
+ height: 1.75rem;
475
+ }
476
+
477
+ .udnd-modal-icon--info {
478
+ background-color: rgba(59, 130, 246, 0.1);
479
+ color: #3b82f6;
480
+ }
481
+
482
+ .udnd-modal-icon--success {
483
+ background-color: rgba(16, 185, 129, 0.1);
484
+ color: #10b981;
485
+ }
486
+
487
+ .udnd-modal-icon--warning {
488
+ background-color: rgba(245, 158, 11, 0.1);
489
+ color: #f59e0b;
490
+ }
491
+
492
+ .udnd-modal-icon--error {
493
+ background-color: rgba(239, 68, 68, 0.1);
494
+ color: #ef4444;
495
+ }
496
+
497
+ /* Modal body */
498
+ .udnd-modal-body {
499
+ padding: 1rem 1.5rem;
500
+ text-align: center;
501
+ }
502
+
503
+ .udnd-modal-title {
504
+ font-size: 1.125rem;
505
+ font-weight: 600;
506
+ color: #111827;
507
+ margin: 0 0 0.5rem 0;
508
+ }
509
+
510
+ .udnd-modal-message {
511
+ font-size: 0.875rem;
512
+ color: #6b7280;
513
+ margin: 0;
514
+ line-height: 1.5;
515
+ }
516
+
517
+ /* Modal footer */
518
+ .udnd-modal-footer {
519
+ padding: 0.75rem 1.5rem 1.5rem;
520
+ display: flex;
521
+ gap: 0.75rem;
522
+ justify-content: center;
523
+ }
524
+
525
+ .udnd-modal-button {
526
+ padding: 0.625rem 1.25rem;
527
+ border-radius: 0.5rem;
528
+ font-size: 0.875rem;
529
+ font-weight: 500;
530
+ border: none;
531
+ cursor: pointer;
532
+ transition: all 0.2s ease;
533
+ font-family: inherit;
534
+ flex: 1;
535
+ max-width: 10rem;
536
+ }
537
+
538
+ .udnd-modal-button:focus {
539
+ outline: 2px solid rgb(var(--udnd-accent-rgb));
540
+ outline-offset: 2px;
541
+ }
542
+
543
+ /* Primary button (OK dans alerts) */
544
+ .udnd-modal-button--primary {
545
+ background-color: var(--udnd-accent-color);
546
+ color: white;
547
+ }
548
+
549
+ .udnd-modal-button--primary:hover {
550
+ background-color: color-mix(in srgb, var(--udnd-accent-color) 85%, black);
551
+ transform: translateY(-1px);
552
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
553
+ }
554
+
555
+ .udnd-modal-button--primary:active {
556
+ transform: translateY(0);
557
+ }
558
+
559
+ /* Confirm button (dans confirms) */
560
+ .udnd-modal-button--confirm {
561
+ background-color: #ef4444;
562
+ color: white;
563
+ }
564
+
565
+ .udnd-modal-button--confirm:hover {
566
+ background-color: #dc2626;
567
+ transform: translateY(-1px);
568
+ box-shadow: 0 4px 6px -1px rgba(239, 68, 68, 0.3);
569
+ }
570
+
571
+ .udnd-modal-button--confirm:active {
572
+ transform: translateY(0);
573
+ }
574
+
575
+ /* Cancel button */
576
+ .udnd-modal-button--cancel {
577
+ background-color: #f3f4f6;
578
+ color: #374151;
579
+ }
580
+
581
+ .udnd-modal-button--cancel:hover {
582
+ background-color: #e5e7eb;
583
+ }
584
+
585
+ .udnd-modal-button--cancel:active {
586
+ background-color: #d1d5db;
587
+ }
588
+
589
+ /* Responsive */
590
+ @media (max-width: 640px) {
591
+ .udnd-modal {
592
+ margin: 1rem;
593
+ max-width: calc(100% - 2rem);
594
+ }
595
+
596
+ .udnd-modal-footer {
597
+ flex-direction: column-reverse;
598
+ }
599
+
600
+ .udnd-modal-button {
601
+ max-width: none;
602
+ width: 100%;
603
+ }
604
+ }
@@ -0,0 +1,53 @@
1
+ <div class="udnd-container"
2
+ style="--udnd-accent-color: <%= main_color %>; --udnd-accent-rgb: <%= main_color_rgb %>;"
3
+ data-controller="upload-d-n-d--uploads"
4
+ data-upload-d-n-d--uploads-record-id-value="<%= record&.id %>"
5
+ data-upload-d-n-d--uploads-record-gid-value="<%= record_gid %>"
6
+ data-upload-d-n-d--uploads-attribute-name-value="<%= attribute_name %>"
7
+ data-upload-d-n-d--uploads-attach-url-value="<%= attach_path %>"
8
+ data-upload-d-n-d--uploads-max-size-value="<%= max_size %>"
9
+ data-upload-d-n-d--uploads-accepted-types-value="<%= accepted_types %>"
10
+ data-upload-d-n-d--uploads-mime-types-value="<%= accepted_mime_types %>"
11
+ data-upload-d-n-d--uploads-field-ref-value="<%= field_ref %>"
12
+ data-upload-d-n-d--uploads-multiple-value="<%= multiple %>"
13
+ data-upload-d-n-d--uploads-i18n-value="<%= i18n_messages.to_json %>">
14
+
15
+ <div class="udnd-dropzone"
16
+ role="button"
17
+ tabindex="0"
18
+ aria-label="<%= t('upload_d_n_d.drag_and_drop') %>"
19
+ data-action="dragover->upload-d-n-d--uploads#handleDragOver dragenter->upload-d-n-d--uploads#handleDragEnter dragleave->upload-d-n-d--uploads#handleDragLeave drop->upload-d-n-d--uploads#handleDrop">
20
+
21
+ <input type="file"
22
+ class="udnd-input-hidden"
23
+ aria-label="<%= t('upload_d_n_d.drag_and_drop') %>"
24
+ data-action="change->upload-d-n-d--uploads#previewFiles"
25
+ accept="<%= accepted_types %>"
26
+ <%= 'multiple' if multiple %>>
27
+
28
+ <div class="udnd-dropzone-content">
29
+ <div class="udnd-icon-wrapper">
30
+ <svg class="udnd-icon udnd-icon-lg" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 13v8"/><path d="M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"/><path d="m8 17 4-4 4 4"/></svg>
31
+ </div>
32
+ <p class="udnd-text-main"><%= t('upload_d_n_d.drag_and_drop') %></p>
33
+ <p class="udnd-text-sub"><%= accepted_types %> (max. <%= number_to_human_size(max_size) %>)</p>
34
+ </div>
35
+
36
+ <div class="udnd-progress-container"
37
+ role="progressbar"
38
+ aria-valuenow="0"
39
+ aria-valuemin="0"
40
+ aria-valuemax="100"
41
+ aria-label="<%= t('upload_d_n_d.progress', default: 'Upload progress') %>">
42
+ <div class="udnd-progress-bar" data-upload-d-n-d--uploads-target="progressBar"></div>
43
+ </div>
44
+ </div>
45
+
46
+ <%# Record persisté : ses attachments. Sinon : les fichiers temporaires de la session,
47
+ pour que la zone reste remplie après un rechargement de page. %>
48
+ <% if record&.persisted? %>
49
+ <%= render "upload_d_n_d/shared/files_list", record: record, attribute_name: attribute_name %>
50
+ <% else %>
51
+ <%= render "upload_d_n_d/shared/temp_files_list", files: files, attribute_name: attribute_name %>
52
+ <% end %>
53
+ </div>