data_porter 0.1.0 → 0.4.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.
Files changed (168) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +62 -1
  3. data/README.md +63 -386
  4. data/ROADMAP.md +89 -0
  5. data/app/assets/javascripts/data_porter/stimulus.min.js +2 -0
  6. data/app/assets/javascripts/data_porter/turbo.min.js +29 -0
  7. data/app/assets/stylesheets/data_porter/alerts.css +25 -0
  8. data/app/assets/stylesheets/data_porter/application.css +12 -646
  9. data/app/assets/stylesheets/data_porter/badges.css +73 -0
  10. data/app/assets/stylesheets/data_porter/base.css +56 -0
  11. data/app/assets/stylesheets/data_porter/cards.css +60 -0
  12. data/app/assets/stylesheets/data_porter/layout.css +128 -0
  13. data/app/assets/stylesheets/data_porter/mapping.css +79 -0
  14. data/app/assets/stylesheets/data_porter/modal.css +49 -0
  15. data/app/assets/stylesheets/data_porter/preview.css +24 -0
  16. data/app/assets/stylesheets/data_porter/progress.css +37 -0
  17. data/app/assets/stylesheets/data_porter/table.css +45 -0
  18. data/app/controllers/data_porter/imports_controller.rb +74 -10
  19. data/app/controllers/data_porter/mapping_templates_controller.rb +85 -0
  20. data/app/javascript/data_porter/mapping_controller.js +86 -0
  21. data/app/javascript/data_porter/progress_controller.js +1 -1
  22. data/app/javascript/data_porter/template_form_controller.js +46 -0
  23. data/app/jobs/data_porter/extract_headers_job.rb +12 -0
  24. data/app/models/data_porter/data_import.rb +8 -2
  25. data/app/models/data_porter/mapping_template.rb +15 -0
  26. data/app/views/data_porter/imports/index.html.erb +9 -8
  27. data/app/views/data_porter/imports/new.html.erb +10 -4
  28. data/app/views/data_porter/imports/show.html.erb +41 -13
  29. data/app/views/data_porter/mapping_templates/_form.html.erb +40 -0
  30. data/app/views/data_porter/mapping_templates/edit.html.erb +11 -0
  31. data/app/views/data_porter/mapping_templates/index.html.erb +42 -0
  32. data/app/views/data_porter/mapping_templates/new.html.erb +11 -0
  33. data/app/views/layouts/data_porter/application.html.erb +162 -0
  34. data/config/routes.rb +3 -0
  35. data/docs/CONFIGURATION.md +81 -0
  36. data/docs/MAPPING.md +44 -0
  37. data/docs/SOURCES.md +94 -0
  38. data/docs/TARGETS.md +176 -0
  39. data/docs/screenshots/mapping.jpg +0 -0
  40. data/lib/data_porter/components/mapping/column_row.rb +52 -0
  41. data/lib/data_porter/components/mapping/form.rb +127 -0
  42. data/lib/data_porter/components/mapping/template_select.rb +35 -0
  43. data/lib/data_porter/components/preview/results_summary.rb +21 -0
  44. data/lib/data_porter/components/preview/summary_cards.rb +32 -0
  45. data/lib/data_porter/components/preview/table.rb +56 -0
  46. data/lib/data_porter/components/progress/bar.rb +35 -0
  47. data/lib/data_porter/components/shared/failure_alert.rb +22 -0
  48. data/lib/data_porter/components/shared/status_badge.rb +18 -0
  49. data/lib/data_porter/components.rb +9 -6
  50. data/lib/data_porter/configuration.rb +1 -1
  51. data/lib/data_porter/engine.rb +7 -1
  52. data/lib/data_porter/orchestrator.rb +21 -1
  53. data/lib/data_porter/sources/base.rb +18 -3
  54. data/lib/data_porter/sources/csv.rb +5 -0
  55. data/lib/data_porter/sources/xlsx.rb +76 -0
  56. data/lib/data_porter/sources.rb +3 -1
  57. data/lib/data_porter/version.rb +1 -1
  58. data/lib/generators/data_porter/install/install_generator.rb +4 -0
  59. data/lib/generators/data_porter/install/templates/create_data_porter_mapping_templates.rb.erb +16 -0
  60. data/lib/generators/data_porter/install/templates/initializer.rb +1 -1
  61. metadata +72 -135
  62. data/.claude/commands/blog-status.md +0 -10
  63. data/.claude/commands/blog.md +0 -109
  64. data/.claude/commands/task-done.md +0 -27
  65. data/.claude/commands/tm/add-dependency.md +0 -58
  66. data/.claude/commands/tm/add-subtask.md +0 -79
  67. data/.claude/commands/tm/add-task.md +0 -81
  68. data/.claude/commands/tm/analyze-complexity.md +0 -124
  69. data/.claude/commands/tm/analyze-project.md +0 -100
  70. data/.claude/commands/tm/auto-implement-tasks.md +0 -100
  71. data/.claude/commands/tm/command-pipeline.md +0 -80
  72. data/.claude/commands/tm/complexity-report.md +0 -120
  73. data/.claude/commands/tm/convert-task-to-subtask.md +0 -74
  74. data/.claude/commands/tm/expand-all-tasks.md +0 -52
  75. data/.claude/commands/tm/expand-task.md +0 -52
  76. data/.claude/commands/tm/fix-dependencies.md +0 -82
  77. data/.claude/commands/tm/help.md +0 -101
  78. data/.claude/commands/tm/init-project-quick.md +0 -49
  79. data/.claude/commands/tm/init-project.md +0 -53
  80. data/.claude/commands/tm/install-taskmaster.md +0 -118
  81. data/.claude/commands/tm/learn.md +0 -106
  82. data/.claude/commands/tm/list-tasks-by-status.md +0 -42
  83. data/.claude/commands/tm/list-tasks-with-subtasks.md +0 -30
  84. data/.claude/commands/tm/list-tasks.md +0 -46
  85. data/.claude/commands/tm/next-task.md +0 -69
  86. data/.claude/commands/tm/parse-prd-with-research.md +0 -51
  87. data/.claude/commands/tm/parse-prd.md +0 -52
  88. data/.claude/commands/tm/project-status.md +0 -67
  89. data/.claude/commands/tm/quick-install-taskmaster.md +0 -23
  90. data/.claude/commands/tm/remove-all-subtasks.md +0 -94
  91. data/.claude/commands/tm/remove-dependency.md +0 -65
  92. data/.claude/commands/tm/remove-subtask.md +0 -87
  93. data/.claude/commands/tm/remove-subtasks.md +0 -89
  94. data/.claude/commands/tm/remove-task.md +0 -110
  95. data/.claude/commands/tm/setup-models.md +0 -52
  96. data/.claude/commands/tm/show-task.md +0 -85
  97. data/.claude/commands/tm/smart-workflow.md +0 -58
  98. data/.claude/commands/tm/sync-readme.md +0 -120
  99. data/.claude/commands/tm/tm-main.md +0 -147
  100. data/.claude/commands/tm/to-cancelled.md +0 -58
  101. data/.claude/commands/tm/to-deferred.md +0 -50
  102. data/.claude/commands/tm/to-done.md +0 -47
  103. data/.claude/commands/tm/to-in-progress.md +0 -39
  104. data/.claude/commands/tm/to-pending.md +0 -35
  105. data/.claude/commands/tm/to-review.md +0 -43
  106. data/.claude/commands/tm/update-single-task.md +0 -122
  107. data/.claude/commands/tm/update-task.md +0 -75
  108. data/.claude/commands/tm/update-tasks-from-id.md +0 -111
  109. data/.claude/commands/tm/validate-dependencies.md +0 -72
  110. data/.claude/commands/tm/view-models.md +0 -52
  111. data/.env.example +0 -12
  112. data/.mcp.json +0 -24
  113. data/.taskmaster/CLAUDE.md +0 -435
  114. data/.taskmaster/config.json +0 -44
  115. data/.taskmaster/docs/prd.txt +0 -2044
  116. data/.taskmaster/state.json +0 -6
  117. data/.taskmaster/tasks/task_001.md +0 -19
  118. data/.taskmaster/tasks/task_002.md +0 -19
  119. data/.taskmaster/tasks/task_003.md +0 -19
  120. data/.taskmaster/tasks/task_004.md +0 -19
  121. data/.taskmaster/tasks/task_005.md +0 -19
  122. data/.taskmaster/tasks/task_006.md +0 -19
  123. data/.taskmaster/tasks/task_007.md +0 -19
  124. data/.taskmaster/tasks/task_008.md +0 -19
  125. data/.taskmaster/tasks/task_009.md +0 -19
  126. data/.taskmaster/tasks/task_010.md +0 -19
  127. data/.taskmaster/tasks/task_011.md +0 -19
  128. data/.taskmaster/tasks/task_012.md +0 -19
  129. data/.taskmaster/tasks/task_013.md +0 -19
  130. data/.taskmaster/tasks/task_014.md +0 -19
  131. data/.taskmaster/tasks/task_015.md +0 -19
  132. data/.taskmaster/tasks/task_016.md +0 -19
  133. data/.taskmaster/tasks/task_017.md +0 -19
  134. data/.taskmaster/tasks/task_018.md +0 -19
  135. data/.taskmaster/tasks/task_019.md +0 -19
  136. data/.taskmaster/tasks/task_020.md +0 -19
  137. data/.taskmaster/tasks/tasks.json +0 -299
  138. data/.taskmaster/templates/example_prd.txt +0 -47
  139. data/.taskmaster/templates/example_prd_rpg.txt +0 -511
  140. data/CLAUDE.md +0 -65
  141. data/config/database.yml +0 -3
  142. data/docs/SPEC.md +0 -2012
  143. data/docs/UI.md +0 -32
  144. data/docs/blog/001-why-build-a-data-import-engine.md +0 -166
  145. data/docs/blog/002-scaffolding-a-rails-engine.md +0 -188
  146. data/docs/blog/003-configuration-dsl.md +0 -222
  147. data/docs/blog/004-store-model-jsonb.md +0 -237
  148. data/docs/blog/005-target-dsl.md +0 -284
  149. data/docs/blog/006-parsing-csv-sources.md +0 -300
  150. data/docs/blog/007-orchestrator.md +0 -247
  151. data/docs/blog/008-actioncable-stimulus.md +0 -376
  152. data/docs/blog/009-phlex-ui-components.md +0 -446
  153. data/docs/blog/010-controllers-routing.md +0 -374
  154. data/docs/blog/011-generators.md +0 -364
  155. data/docs/blog/012-json-api-sources.md +0 -323
  156. data/docs/blog/013-testing-rails-engine.md +0 -618
  157. data/docs/blog/014-dry-run.md +0 -307
  158. data/docs/blog/015-publishing-retro.md +0 -264
  159. data/docs/blog/016-erb-view-templates.md +0 -431
  160. data/docs/blog/017-showcase-final-retro.md +0 -220
  161. data/docs/blog/BACKLOG.md +0 -8
  162. data/docs/blog/SERIES.md +0 -154
  163. data/lib/data_porter/components/failure_alert.rb +0 -20
  164. data/lib/data_porter/components/preview_table.rb +0 -54
  165. data/lib/data_porter/components/progress_bar.rb +0 -33
  166. data/lib/data_porter/components/results_summary.rb +0 -19
  167. data/lib/data_porter/components/status_badge.rb +0 -16
  168. data/lib/data_porter/components/summary_cards.rb +0 -30
@@ -1,646 +1,12 @@
1
- :root {
2
- --dp-primary: #4f46e5;
3
- --dp-primary-hover: #4338ca;
4
- --dp-primary-light: #eef2ff;
5
- --dp-success: #059669;
6
- --dp-success-light: #ecfdf5;
7
- --dp-success-border: #a7f3d0;
8
- --dp-warning: #d97706;
9
- --dp-warning-light: #fffbeb;
10
- --dp-warning-border: #fde68a;
11
- --dp-danger: #dc2626;
12
- --dp-danger-hover: #b91c1c;
13
- --dp-danger-light: #fef2f2;
14
- --dp-danger-border: #fecaca;
15
- --dp-info: #2563eb;
16
- --dp-info-light: #eff6ff;
17
- --dp-info-border: #bfdbfe;
18
- --dp-purple: #7c3aed;
19
- --dp-purple-light: #f5f3ff;
20
- --dp-purple-border: #ddd6fe;
21
- --dp-gray-50: #f9fafb;
22
- --dp-gray-100: #f3f4f6;
23
- --dp-gray-200: #e5e7eb;
24
- --dp-gray-300: #d1d5db;
25
- --dp-gray-400: #9ca3af;
26
- --dp-gray-500: #6b7280;
27
- --dp-gray-600: #4b5563;
28
- --dp-gray-700: #374151;
29
- --dp-gray-800: #1f2937;
30
- --dp-gray-900: #111827;
31
- --dp-radius-sm: 0.375rem;
32
- --dp-radius-md: 0.5rem;
33
- --dp-radius-lg: 0.75rem;
34
- --dp-radius-xl: 1rem;
35
- --dp-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
36
- --dp-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.07), 0 2px 4px -2px rgba(0, 0, 0, 0.05);
37
- --dp-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -4px rgba(0, 0, 0, 0.04);
38
- }
39
-
40
- .data-porter {
41
- font-family: "Inter", system-ui, -apple-system, sans-serif;
42
- color: var(--dp-gray-800);
43
- max-width: 1100px;
44
- margin: 2rem auto;
45
- padding: 0 1.5rem;
46
- line-height: 1.6;
47
- -webkit-font-smoothing: antialiased;
48
- }
49
-
50
- .dp-title {
51
- font-size: 1.75rem;
52
- font-weight: 700;
53
- margin: 0;
54
- letter-spacing: -0.025em;
55
- color: var(--dp-gray-900);
56
- }
57
-
58
- .dp-header {
59
- display: flex;
60
- align-items: center;
61
- justify-content: space-between;
62
- gap: 1rem;
63
- margin-bottom: 2rem;
64
- padding-bottom: 1.5rem;
65
- border-bottom: 1px solid var(--dp-gray-200);
66
- }
67
-
68
- .dp-table {
69
- width: 100%;
70
- border-collapse: separate;
71
- border-spacing: 0;
72
- margin-bottom: 1.5rem;
73
- background: white;
74
- border: 1px solid var(--dp-gray-200);
75
- border-radius: var(--dp-radius-lg);
76
- overflow: hidden;
77
- box-shadow: var(--dp-shadow-sm);
78
- }
79
-
80
- .dp-table th,
81
- .dp-table td {
82
- padding: 0.75rem 1rem;
83
- text-align: left;
84
- }
85
-
86
- .dp-table th {
87
- font-weight: 600;
88
- font-size: 0.75rem;
89
- text-transform: uppercase;
90
- letter-spacing: 0.05em;
91
- color: var(--dp-gray-500);
92
- background: var(--dp-gray-50);
93
- border-bottom: 1px solid var(--dp-gray-200);
94
- }
95
-
96
- .dp-table td {
97
- font-size: 0.875rem;
98
- color: var(--dp-gray-700);
99
- border-bottom: 1px solid var(--dp-gray-100);
100
- }
101
-
102
- .dp-table tbody tr:last-child td {
103
- border-bottom: none;
104
- }
105
-
106
- .dp-table tbody tr {
107
- transition: background-color 0.15s ease;
108
- }
109
-
110
- .dp-table tbody tr:hover {
111
- background: var(--dp-gray-50);
112
- }
113
-
114
- .dp-badge {
115
- display: inline-flex;
116
- align-items: center;
117
- padding: 0.25rem 0.75rem;
118
- border-radius: 9999px;
119
- font-size: 0.7rem;
120
- font-weight: 600;
121
- text-transform: uppercase;
122
- letter-spacing: 0.05em;
123
- border: 1px solid transparent;
124
- }
125
-
126
- .dp-badge--pending {
127
- background: var(--dp-gray-100);
128
- color: var(--dp-gray-600);
129
- border-color: var(--dp-gray-300);
130
- }
131
-
132
- .dp-badge--parsing {
133
- background: var(--dp-info-light);
134
- color: var(--dp-info);
135
- border-color: var(--dp-info-border);
136
- }
137
-
138
- .dp-badge--importing {
139
- background: var(--dp-info-light);
140
- color: var(--dp-info);
141
- border-color: var(--dp-info-border);
142
- animation: dp-pulse 2s ease-in-out infinite;
143
- }
144
-
145
- .dp-badge--previewing {
146
- background: var(--dp-warning-light);
147
- color: var(--dp-warning);
148
- border-color: var(--dp-warning-border);
149
- }
150
-
151
- .dp-badge--completed {
152
- background: var(--dp-success-light);
153
- color: var(--dp-success);
154
- border-color: var(--dp-success-border);
155
- }
156
-
157
- .dp-badge--failed {
158
- background: var(--dp-danger-light);
159
- color: var(--dp-danger);
160
- border-color: var(--dp-danger-border);
161
- }
162
-
163
- .dp-badge--dry_running {
164
- background: var(--dp-purple-light);
165
- color: var(--dp-purple);
166
- border-color: var(--dp-purple-border);
167
- animation: dp-pulse 2s ease-in-out infinite;
168
- }
169
-
170
- @keyframes dp-pulse {
171
- 0%, 100% { opacity: 1; }
172
- 50% { opacity: 0.6; }
173
- }
174
-
175
- .dp-summary-cards {
176
- display: grid;
177
- grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
178
- gap: 1rem;
179
- margin-bottom: 2rem;
180
- }
181
-
182
- .dp-card {
183
- padding: 1.25rem;
184
- border-radius: var(--dp-radius-lg);
185
- border: 1px solid var(--dp-gray-200);
186
- text-align: center;
187
- background: white;
188
- box-shadow: var(--dp-shadow-sm);
189
- transition: transform 0.15s ease, box-shadow 0.15s ease;
190
- }
191
-
192
- .dp-card:hover {
193
- transform: translateY(-1px);
194
- box-shadow: var(--dp-shadow-md);
195
- }
196
-
197
- .dp-card strong {
198
- display: block;
199
- font-size: 2rem;
200
- font-weight: 700;
201
- margin-bottom: 0.25rem;
202
- letter-spacing: -0.025em;
203
- }
204
-
205
- .dp-card span {
206
- font-size: 0.8rem;
207
- font-weight: 500;
208
- text-transform: uppercase;
209
- letter-spacing: 0.05em;
210
- }
211
-
212
- .dp-card--complete {
213
- border-color: var(--dp-success-border);
214
- background: var(--dp-success-light);
215
- }
216
-
217
- .dp-card--complete strong { color: var(--dp-success); }
218
-
219
- .dp-card--partial {
220
- border-color: var(--dp-warning-border);
221
- background: var(--dp-warning-light);
222
- }
223
-
224
- .dp-card--partial strong { color: var(--dp-warning); }
225
-
226
- .dp-card--missing {
227
- border-color: var(--dp-danger-border);
228
- background: var(--dp-danger-light);
229
- }
230
-
231
- .dp-card--missing strong { color: var(--dp-danger); }
232
-
233
- .dp-card--duplicate {
234
- border-color: var(--dp-gray-300);
235
- background: var(--dp-gray-50);
236
- }
237
-
238
- .dp-card--duplicate strong { color: var(--dp-gray-500); }
239
-
240
- .dp-preview-table {
241
- overflow-x: auto;
242
- margin-bottom: 2rem;
243
- border-radius: var(--dp-radius-lg);
244
- border: 1px solid var(--dp-gray-200);
245
- box-shadow: var(--dp-shadow-sm);
246
- }
247
-
248
- .dp-preview-table .dp-table {
249
- margin-bottom: 0;
250
- border: none;
251
- border-radius: 0;
252
- box-shadow: none;
253
- }
254
-
255
- .dp-row--complete { background: var(--dp-success-light); }
256
- .dp-row--partial { background: var(--dp-warning-light); }
257
- .dp-row--missing { background: var(--dp-danger-light); }
258
-
259
- .dp-errors {
260
- color: var(--dp-danger);
261
- font-size: 0.8rem;
262
- font-weight: 500;
263
- }
264
-
265
- .dp-progress {
266
- margin: 2rem 0;
267
- background: var(--dp-gray-200);
268
- border-radius: var(--dp-radius-xl);
269
- overflow: hidden;
270
- height: 1.75rem;
271
- box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.08);
272
- }
273
-
274
- .dp-progress-bar {
275
- height: 100%;
276
- background: linear-gradient(135deg, var(--dp-primary), #818cf8);
277
- border-radius: var(--dp-radius-xl);
278
- transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
279
- display: flex;
280
- align-items: center;
281
- justify-content: center;
282
- color: white;
283
- font-size: 0.75rem;
284
- font-weight: 700;
285
- min-width: 2.5rem;
286
- position: relative;
287
- overflow: hidden;
288
- }
289
-
290
- .dp-progress-bar::after {
291
- content: "";
292
- position: absolute;
293
- inset: 0;
294
- background: linear-gradient(
295
- 90deg,
296
- transparent,
297
- rgba(255, 255, 255, 0.2),
298
- transparent
299
- );
300
- animation: dp-shimmer 1.5s infinite;
301
- }
302
-
303
- @keyframes dp-shimmer {
304
- 0% { transform: translateX(-100%); }
305
- 100% { transform: translateX(100%); }
306
- }
307
-
308
- .dp-results {
309
- padding: 1.5rem;
310
- background: var(--dp-success-light);
311
- border: 1px solid var(--dp-success-border);
312
- border-radius: var(--dp-radius-lg);
313
- margin-bottom: 2rem;
314
- box-shadow: var(--dp-shadow-sm);
315
- }
316
-
317
- .dp-results p {
318
- margin: 0.35rem 0;
319
- font-size: 0.9375rem;
320
- }
321
-
322
- .dp-alert {
323
- padding: 1.25rem 1.5rem;
324
- border-radius: var(--dp-radius-lg);
325
- margin-bottom: 2rem;
326
- box-shadow: var(--dp-shadow-sm);
327
- }
328
-
329
- .dp-alert--danger {
330
- background: var(--dp-danger-light);
331
- border: 1px solid var(--dp-danger-border);
332
- color: var(--dp-danger);
333
- }
334
-
335
- .dp-alert p {
336
- margin: 0.35rem 0;
337
- font-size: 0.9375rem;
338
- }
339
-
340
- .dp-form {
341
- max-width: 520px;
342
- background: white;
343
- padding: 2rem;
344
- border: 1px solid var(--dp-gray-200);
345
- border-radius: var(--dp-radius-lg);
346
- box-shadow: var(--dp-shadow-md);
347
- }
348
-
349
- .dp-field {
350
- margin-bottom: 1.5rem;
351
- }
352
-
353
- .dp-label {
354
- display: block;
355
- font-weight: 600;
356
- margin-bottom: 0.5rem;
357
- font-size: 0.875rem;
358
- color: var(--dp-gray-700);
359
- }
360
-
361
- .dp-select,
362
- .dp-file-input {
363
- display: block;
364
- width: 100%;
365
- padding: 0.625rem 0.875rem;
366
- border: 1px solid var(--dp-gray-300);
367
- border-radius: var(--dp-radius-md);
368
- font-size: 0.9375rem;
369
- background: white;
370
- color: var(--dp-gray-800);
371
- transition: border-color 0.15s ease, box-shadow 0.15s ease;
372
- appearance: none;
373
- }
374
-
375
- .dp-select {
376
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
377
- background-position: right 0.5rem center;
378
- background-repeat: no-repeat;
379
- background-size: 1.5em 1.5em;
380
- padding-right: 2.5rem;
381
- }
382
-
383
- .dp-select:focus,
384
- .dp-file-input:focus {
385
- outline: none;
386
- border-color: var(--dp-primary);
387
- box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15);
388
- }
389
-
390
- .dp-actions {
391
- display: flex;
392
- gap: 0.75rem;
393
- margin: 2rem 0;
394
- }
395
-
396
- .dp-btn {
397
- display: inline-flex;
398
- align-items: center;
399
- justify-content: center;
400
- padding: 0.625rem 1.25rem;
401
- border-radius: var(--dp-radius-md);
402
- font-size: 0.875rem;
403
- font-weight: 600;
404
- text-decoration: none;
405
- border: 1px solid transparent;
406
- cursor: pointer;
407
- transition: all 0.15s ease;
408
- line-height: 1.25;
409
- }
410
-
411
- .dp-btn:active {
412
- transform: scale(0.98);
413
- }
414
-
415
- .dp-btn--primary {
416
- background: var(--dp-primary);
417
- color: white;
418
- box-shadow: var(--dp-shadow-sm);
419
- }
420
-
421
- .dp-btn--primary:hover {
422
- background: var(--dp-primary-hover);
423
- box-shadow: var(--dp-shadow-md);
424
- }
425
-
426
- .dp-btn--secondary {
427
- background: white;
428
- color: var(--dp-gray-700);
429
- border-color: var(--dp-gray-300);
430
- box-shadow: var(--dp-shadow-sm);
431
- }
432
-
433
- .dp-btn--secondary:hover {
434
- background: var(--dp-gray-50);
435
- border-color: var(--dp-gray-400);
436
- }
437
-
438
- .dp-btn--danger {
439
- background: var(--dp-danger);
440
- color: white;
441
- box-shadow: var(--dp-shadow-sm);
442
- }
443
-
444
- .dp-btn--danger:hover {
445
- background: var(--dp-danger-hover);
446
- box-shadow: var(--dp-shadow-md);
447
- }
448
-
449
- .dp-link {
450
- color: var(--dp-primary);
451
- text-decoration: none;
452
- font-weight: 500;
453
- transition: color 0.15s ease;
454
- }
455
-
456
- .dp-link:hover {
457
- color: var(--dp-primary-hover);
458
- text-decoration: underline;
459
- }
460
-
461
- .dp-nav {
462
- margin-top: 2rem;
463
- padding-top: 1.5rem;
464
- border-top: 1px solid var(--dp-gray-200);
465
- }
466
-
467
- .dp-empty {
468
- text-align: center;
469
- padding: 3rem 1rem;
470
- color: var(--dp-gray-400);
471
- font-size: 0.9375rem;
472
- }
473
-
474
- .dp-empty-state {
475
- text-align: center;
476
- padding: 4rem 2rem;
477
- background: white;
478
- border: 2px dashed var(--dp-gray-300);
479
- border-radius: var(--dp-radius-xl);
480
- }
481
-
482
- .dp-empty-state__icon {
483
- font-size: 3rem;
484
- margin-bottom: 1rem;
485
- opacity: 0.6;
486
- }
487
-
488
- .dp-empty-state__text {
489
- font-size: 1.125rem;
490
- color: var(--dp-gray-500);
491
- margin: 0 0 1.5rem;
492
- }
493
-
494
- .dp-modal {
495
- display: none;
496
- position: fixed;
497
- inset: 0;
498
- z-index: 9999;
499
- align-items: center;
500
- justify-content: center;
501
- }
502
-
503
- .dp-modal--open {
504
- display: flex;
505
- }
506
-
507
- .dp-modal__backdrop {
508
- position: fixed;
509
- inset: 0;
510
- background: rgba(0, 0, 0, 0.4);
511
- backdrop-filter: blur(4px);
512
- }
513
-
514
- .dp-modal__content {
515
- position: relative;
516
- background: white;
517
- border-radius: var(--dp-radius-xl);
518
- box-shadow: var(--dp-shadow-lg), 0 25px 50px -12px rgba(0, 0, 0, 0.15);
519
- width: 100%;
520
- max-width: 520px;
521
- max-height: 90vh;
522
- overflow-y: auto;
523
- animation: dp-modal-in 0.2s ease-out;
524
- }
525
-
526
- @keyframes dp-modal-in {
527
- from {
528
- opacity: 0;
529
- transform: scale(0.95) translateY(10px);
530
- }
531
- to {
532
- opacity: 1;
533
- transform: scale(1) translateY(0);
534
- }
535
- }
536
-
537
- .dp-modal__header {
538
- display: flex;
539
- align-items: center;
540
- justify-content: space-between;
541
- padding: 1.5rem 1.5rem 0;
542
- }
543
-
544
- .dp-modal__title {
545
- font-size: 1.25rem;
546
- font-weight: 700;
547
- margin: 0;
548
- color: var(--dp-gray-900);
549
- }
550
-
551
- .dp-modal__close {
552
- background: none;
553
- border: none;
554
- font-size: 1.5rem;
555
- color: var(--dp-gray-400);
556
- cursor: pointer;
557
- padding: 0.25rem;
558
- line-height: 1;
559
- border-radius: var(--dp-radius-sm);
560
- transition: color 0.15s ease, background 0.15s ease;
561
- }
562
-
563
- .dp-modal__close:hover {
564
- color: var(--dp-gray-700);
565
- background: var(--dp-gray-100);
566
- }
567
-
568
- .dp-modal__body {
569
- padding: 1.5rem;
570
- }
571
-
572
- .dp-modal__footer {
573
- display: flex;
574
- gap: 0.75rem;
575
- justify-content: flex-end;
576
- padding-top: 0.5rem;
577
- border-top: 1px solid var(--dp-gray-100);
578
- margin-top: 0.5rem;
579
- padding-top: 1.5rem;
580
- }
581
-
582
- .dp-dropzone {
583
- display: flex;
584
- flex-direction: column;
585
- align-items: center;
586
- justify-content: center;
587
- padding: 2rem 1.5rem;
588
- border: 2px dashed var(--dp-gray-300);
589
- border-radius: var(--dp-radius-lg);
590
- cursor: pointer;
591
- transition: border-color 0.15s ease, background 0.15s ease;
592
- text-align: center;
593
- }
594
-
595
- .dp-dropzone:hover,
596
- .dp-dropzone--dragover {
597
- border-color: var(--dp-primary);
598
- background: var(--dp-primary-light);
599
- }
600
-
601
- .dp-dropzone--has-file {
602
- border-color: var(--dp-success);
603
- background: var(--dp-success-light);
604
- border-style: solid;
605
- }
606
-
607
- .dp-dropzone__input {
608
- position: absolute;
609
- width: 1px;
610
- height: 1px;
611
- overflow: hidden;
612
- clip: rect(0, 0, 0, 0);
613
- }
614
-
615
- .dp-dropzone__content {
616
- display: flex;
617
- flex-direction: column;
618
- align-items: center;
619
- gap: 0.5rem;
620
- }
621
-
622
- .dp-dropzone__icon {
623
- font-size: 2rem;
624
- opacity: 0.5;
625
- }
626
-
627
- .dp-dropzone__text {
628
- font-size: 0.9375rem;
629
- color: var(--dp-gray-600);
630
- }
631
-
632
- .dp-dropzone__text strong {
633
- color: var(--dp-primary);
634
- }
635
-
636
- .dp-dropzone__hint {
637
- font-size: 0.8rem;
638
- color: var(--dp-gray-400);
639
- }
640
-
641
- .dp-dropzone__selected {
642
- font-size: 0.875rem;
643
- font-weight: 600;
644
- color: var(--dp-success);
645
- margin-top: 0.5rem;
646
- }
1
+ /*
2
+ *= require data_porter/base
3
+ *= require data_porter/layout
4
+ *= require data_porter/table
5
+ *= require data_porter/badges
6
+ *= require data_porter/cards
7
+ *= require data_porter/preview
8
+ *= require data_porter/progress
9
+ *= require data_porter/alerts
10
+ *= require data_porter/modal
11
+ *= require data_porter/mapping
12
+ */
@@ -0,0 +1,73 @@
1
+ .dp-badge {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ padding: 0.25rem 0.75rem;
5
+ border-radius: 9999px;
6
+ font-size: 0.7rem;
7
+ font-weight: 600;
8
+ text-transform: uppercase;
9
+ letter-spacing: 0.05em;
10
+ border: 1px solid transparent;
11
+ }
12
+
13
+ .dp-badge--pending {
14
+ background: var(--dp-gray-100);
15
+ color: var(--dp-gray-600);
16
+ border-color: var(--dp-gray-300);
17
+ }
18
+
19
+ .dp-badge--parsing {
20
+ background: var(--dp-info-light);
21
+ color: var(--dp-info);
22
+ border-color: var(--dp-info-border);
23
+ }
24
+
25
+ .dp-badge--importing {
26
+ background: var(--dp-info-light);
27
+ color: var(--dp-info);
28
+ border-color: var(--dp-info-border);
29
+ animation: dp-pulse 2s ease-in-out infinite;
30
+ }
31
+
32
+ .dp-badge--previewing {
33
+ background: var(--dp-warning-light);
34
+ color: var(--dp-warning);
35
+ border-color: var(--dp-warning-border);
36
+ }
37
+
38
+ .dp-badge--completed {
39
+ background: var(--dp-success-light);
40
+ color: var(--dp-success);
41
+ border-color: var(--dp-success-border);
42
+ }
43
+
44
+ .dp-badge--failed {
45
+ background: var(--dp-danger-light);
46
+ color: var(--dp-danger);
47
+ border-color: var(--dp-danger-border);
48
+ }
49
+
50
+ .dp-badge--extracting_headers {
51
+ background: var(--dp-info-light);
52
+ color: var(--dp-info);
53
+ border-color: var(--dp-info-border);
54
+ animation: dp-pulse 2s ease-in-out infinite;
55
+ }
56
+
57
+ .dp-badge--mapping {
58
+ background: var(--dp-purple-light);
59
+ color: var(--dp-purple);
60
+ border-color: var(--dp-purple-border);
61
+ }
62
+
63
+ .dp-badge--dry_running {
64
+ background: var(--dp-purple-light);
65
+ color: var(--dp-purple);
66
+ border-color: var(--dp-purple-border);
67
+ animation: dp-pulse 2s ease-in-out infinite;
68
+ }
69
+
70
+ @keyframes dp-pulse {
71
+ 0%, 100% { opacity: 1; }
72
+ 50% { opacity: 0.6; }
73
+ }