solara 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (175) hide show
  1. checksums.yaml +7 -0
  2. data/bin/solara +18 -0
  3. data/solara/lib/.DS_Store +0 -0
  4. data/solara/lib/core/.DS_Store +0 -0
  5. data/solara/lib/core/aliases/alias_generator.rb +128 -0
  6. data/solara/lib/core/aliases/alias_generator_manager.rb +28 -0
  7. data/solara/lib/core/aliases/solara_terminal_setup.rb +103 -0
  8. data/solara/lib/core/brands/brand_onboarder.rb +46 -0
  9. data/solara/lib/core/brands/brand_switcher.rb +204 -0
  10. data/solara/lib/core/brands/brands_manager.rb +154 -0
  11. data/solara/lib/core/dashboard/.DS_Store +0 -0
  12. data/solara/lib/core/dashboard/brand/.DS_Store +0 -0
  13. data/solara/lib/core/dashboard/brand/BrandDetail.js +11 -0
  14. data/solara/lib/core/dashboard/brand/BrandDetailController.js +361 -0
  15. data/solara/lib/core/dashboard/brand/BrandDetailModel.js +155 -0
  16. data/solara/lib/core/dashboard/brand/BrandDetailView.js +245 -0
  17. data/solara/lib/core/dashboard/brand/brand.html +477 -0
  18. data/solara/lib/core/dashboard/brand/source/BrandLocalSource.js +123 -0
  19. data/solara/lib/core/dashboard/brand/source/BrandRemoteSource.js +260 -0
  20. data/solara/lib/core/dashboard/brands/Brands.js +10 -0
  21. data/solara/lib/core/dashboard/brands/BrandsController.js +155 -0
  22. data/solara/lib/core/dashboard/brands/BrandsModel.js +136 -0
  23. data/solara/lib/core/dashboard/brands/BrandsView.js +136 -0
  24. data/solara/lib/core/dashboard/brands/brands.html +345 -0
  25. data/solara/lib/core/dashboard/component/AddFieldSheet.js +212 -0
  26. data/solara/lib/core/dashboard/component/AliasesBottomSheet.js +128 -0
  27. data/solara/lib/core/dashboard/component/BrandOptionsBottomSheet.js +130 -0
  28. data/solara/lib/core/dashboard/component/ConfirmationDialog.js +103 -0
  29. data/solara/lib/core/dashboard/component/MessageBottomSheet.js +80 -0
  30. data/solara/lib/core/dashboard/component/OnboardBrandBottomSheet.js +214 -0
  31. data/solara/lib/core/dashboard/dashboard_manager.rb +19 -0
  32. data/solara/lib/core/dashboard/dashboard_server.rb +132 -0
  33. data/solara/lib/core/dashboard/handler/base_handler.rb +25 -0
  34. data/solara/lib/core/dashboard/handler/brand_alisases_handler.rb +33 -0
  35. data/solara/lib/core/dashboard/handler/brand_configurations_handler.rb +18 -0
  36. data/solara/lib/core/dashboard/handler/brand_configurations_manager.rb +73 -0
  37. data/solara/lib/core/dashboard/handler/brand_icon_handler.rb +20 -0
  38. data/solara/lib/core/dashboard/handler/brand_section_handler.rb +20 -0
  39. data/solara/lib/core/dashboard/handler/brands_handler.rb +14 -0
  40. data/solara/lib/core/dashboard/handler/current_brand_handler.rb +18 -0
  41. data/solara/lib/core/dashboard/handler/doctor_handler.rb +39 -0
  42. data/solara/lib/core/dashboard/handler/edit_section_handler.rb +55 -0
  43. data/solara/lib/core/dashboard/handler/offboard_brand_handler.rb +34 -0
  44. data/solara/lib/core/dashboard/handler/onboard_brand_handler.rb +53 -0
  45. data/solara/lib/core/dashboard/handler/redirect_handler.rb +12 -0
  46. data/solara/lib/core/dashboard/handler/switch_handler.rb +25 -0
  47. data/solara/lib/core/dashboard/index.html +36 -0
  48. data/solara/lib/core/dashboard/local.html +41 -0
  49. data/solara/lib/core/dashboard/res/favicon/android-chrome-192x192.png +0 -0
  50. data/solara/lib/core/dashboard/res/favicon/android-chrome-512x512.png +0 -0
  51. data/solara/lib/core/dashboard/res/favicon/apple-touch-icon.png +0 -0
  52. data/solara/lib/core/dashboard/res/favicon/favicon-16x16.png +0 -0
  53. data/solara/lib/core/dashboard/res/favicon/favicon-32x32.png +0 -0
  54. data/solara/lib/core/dashboard/res/favicon/favicon.ico +0 -0
  55. data/solara/lib/core/dashboard/res/favicon/site.webmanifest +1 -0
  56. data/solara/lib/core/dashboard/solara.png +0 -0
  57. data/solara/lib/core/doctor/brand_doctor.rb +94 -0
  58. data/solara/lib/core/doctor/doctor_manager.rb +35 -0
  59. data/solara/lib/core/doctor/project_doctor.rb +8 -0
  60. data/solara/lib/core/doctor/schema/brand_configurations.json +60 -0
  61. data/solara/lib/core/doctor/schema/platform/android/android_config.json +23 -0
  62. data/solara/lib/core/doctor/schema/platform/android/android_signing.json +23 -0
  63. data/solara/lib/core/doctor/schema/platform/ios/ios_config.json +27 -0
  64. data/solara/lib/core/doctor/schema/platform/ios/ios_signing.json +27 -0
  65. data/solara/lib/core/doctor/schema/platform/shared/theme.json +48 -0
  66. data/solara/lib/core/doctor/validator/brand_settings_validator.rb +55 -0
  67. data/solara/lib/core/doctor/validator/brand_settings_validator_manager.rb +82 -0
  68. data/solara/lib/core/doctor/validator/directory_structure_validator.rb +38 -0
  69. data/solara/lib/core/doctor/validator/file_structure_validator.rb +37 -0
  70. data/solara/lib/core/doctor/validator/json_file_validator.rb +21 -0
  71. data/solara/lib/core/doctor/validator/json_schema_validator.rb +32 -0
  72. data/solara/lib/core/doctor/validator/project_filesystem_validator.rb +70 -0
  73. data/solara/lib/core/doctor/validator/template/android_template_validation_config.yml +51 -0
  74. data/solara/lib/core/doctor/validator/template/flutter_template_validation_config.yml +53 -0
  75. data/solara/lib/core/doctor/validator/template/ios_template_validation_config.yml +51 -0
  76. data/solara/lib/core/doctor/validator/template/template_validator.rb +108 -0
  77. data/solara/lib/core/doctor/validator/validation_strategy.rb +7 -0
  78. data/solara/lib/core/scripts/brand_config_generator.rb +245 -0
  79. data/solara/lib/core/scripts/brand_config_manager.rb +90 -0
  80. data/solara/lib/core/scripts/brand_exporter.rb +38 -0
  81. data/solara/lib/core/scripts/brand_importer.rb +84 -0
  82. data/solara/lib/core/scripts/brand_offboarder.rb +19 -0
  83. data/solara/lib/core/scripts/brand_resources_manager.rb +77 -0
  84. data/solara/lib/core/scripts/directory_creator.rb +22 -0
  85. data/solara/lib/core/scripts/file_manager.rb +90 -0
  86. data/solara/lib/core/scripts/file_path.rb +327 -0
  87. data/solara/lib/core/scripts/folder_copier.rb +41 -0
  88. data/solara/lib/core/scripts/gitignore_manager.rb +54 -0
  89. data/solara/lib/core/scripts/interactive_file_system_validator.rb +110 -0
  90. data/solara/lib/core/scripts/platform/android/android_manifest_switcher.rb +24 -0
  91. data/solara/lib/core/scripts/platform/android/android_strings_switcher.rb +39 -0
  92. data/solara/lib/core/scripts/platform/android/gradle_switcher.rb +233 -0
  93. data/solara/lib/core/scripts/platform/android/properties_generator.rb +31 -0
  94. data/solara/lib/core/scripts/platform/ios/ios_file_path_manager.rb +109 -0
  95. data/solara/lib/core/scripts/platform/ios/ios_plist_manager.rb +42 -0
  96. data/solara/lib/core/scripts/platform/ios/xcconfig_generator.rb +44 -0
  97. data/solara/lib/core/scripts/platform/ios/xcode_asset_manager.rb +56 -0
  98. data/solara/lib/core/scripts/platform/ios/xcode_project_manager.rb +82 -0
  99. data/solara/lib/core/scripts/platform/ios/xcode_project_switcher.rb +130 -0
  100. data/solara/lib/core/scripts/project_settings_manager.rb +39 -0
  101. data/solara/lib/core/scripts/solara_logger.rb +103 -0
  102. data/solara/lib/core/scripts/solara_settings_manager.rb +73 -0
  103. data/solara/lib/core/scripts/solara_status_manager.rb +55 -0
  104. data/solara/lib/core/scripts/solara_version_manager.rb +42 -0
  105. data/solara/lib/core/scripts/strings_xml_manager.rb +22 -0
  106. data/solara/lib/core/scripts/terminal_input_manager.rb +22 -0
  107. data/solara/lib/core/scripts/theme_generator.rb +250 -0
  108. data/solara/lib/core/scripts/yaml_manager.rb +72 -0
  109. data/solara/lib/core/solara_configurator.rb +15 -0
  110. data/solara/lib/core/template/brands/android/android_config.json +8 -0
  111. data/solara/lib/core/template/brands/android/android_signing.json +6 -0
  112. data/solara/lib/core/template/brands/android/res/.DS_Store +0 -0
  113. data/solara/lib/core/template/brands/android/res/mipmap-hdpi/ic_launcher.png +0 -0
  114. data/solara/lib/core/template/brands/android/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  115. data/solara/lib/core/template/brands/android/res/mipmap-mdpi/ic_launcher.png +0 -0
  116. data/solara/lib/core/template/brands/android/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  117. data/solara/lib/core/template/brands/android/res/mipmap-xhdpi/ic_launcher.png +0 -0
  118. data/solara/lib/core/template/brands/android/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  119. data/solara/lib/core/template/brands/android/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  120. data/solara/lib/core/template/brands/android/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  121. data/solara/lib/core/template/brands/android/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  122. data/solara/lib/core/template/brands/android/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  123. data/solara/lib/core/template/brands/brands.json +4 -0
  124. data/solara/lib/core/template/brands/ios/assets/.DS_Store +0 -0
  125. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/100.png +0 -0
  126. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/102.png +0 -0
  127. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/1024.png +0 -0
  128. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/114.png +0 -0
  129. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/120.png +0 -0
  130. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/128.png +0 -0
  131. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/144.png +0 -0
  132. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/152.png +0 -0
  133. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/16.png +0 -0
  134. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/167.png +0 -0
  135. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/172.png +0 -0
  136. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/180.png +0 -0
  137. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/196.png +0 -0
  138. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/20.png +0 -0
  139. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/216.png +0 -0
  140. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/256.png +0 -0
  141. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/29.png +0 -0
  142. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/32.png +0 -0
  143. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/40.png +0 -0
  144. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/48.png +0 -0
  145. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/50.png +0 -0
  146. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/512.png +0 -0
  147. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/55.png +0 -0
  148. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/57.png +0 -0
  149. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/58.png +0 -0
  150. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/60.png +0 -0
  151. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/64.png +0 -0
  152. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/66.png +0 -0
  153. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/72.png +0 -0
  154. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/76.png +0 -0
  155. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/80.png +0 -0
  156. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/87.png +0 -0
  157. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/88.png +0 -0
  158. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/92.png +0 -0
  159. data/solara/lib/core/template/brands/ios/assets/AppIcon.appiconset/Contents.json +1 -0
  160. data/solara/lib/core/template/brands/ios/ios_config.json +7 -0
  161. data/solara/lib/core/template/brands/ios/ios_signing.json +7 -0
  162. data/solara/lib/core/template/brands/shared/.DS_Store +0 -0
  163. data/solara/lib/core/template/brands/shared/brand_config.json +2 -0
  164. data/solara/lib/core/template/brands/shared/theme.json +46 -0
  165. data/solara/lib/core/template/config/android_template_config.json +57 -0
  166. data/solara/lib/core/template/config/flutter_template_config.json +62 -0
  167. data/solara/lib/core/template/config/ios_template_config.json +57 -0
  168. data/solara/lib/core/template/project_template_generator.rb +63 -0
  169. data/solara/lib/platform_detector.rb +84 -0
  170. data/solara/lib/solara/cli.rb +5 -0
  171. data/solara/lib/solara/version.rb +3 -0
  172. data/solara/lib/solara.rb +238 -0
  173. data/solara/lib/solara_initializer.rb +44 -0
  174. data/solara/lib/solara_manager.rb +73 -0
  175. metadata +346 -0
@@ -0,0 +1,345 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Solara Dashboard</title>
7
+ <link rel="icon" href="../res/favicon/favicon.ico" type="image/x-icon">
8
+ <style>
9
+ :root {
10
+ --primary-color: #4A90E2;
11
+ --secondary-color: #50E3C2;
12
+ --background-color: #F5F7FA;
13
+ --text-color: #333;
14
+ --border-color: #E1E4E8;
15
+ --offboard-color: #dc3545;
16
+ --field-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
17
+ }
18
+ body {
19
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
20
+ background-color: var(--background-color);
21
+ color: var(--text-color);
22
+ line-height: 1.6;
23
+ margin: 0;
24
+ padding-top: 110px;
25
+ }
26
+ .container {
27
+ max-width: 1000px;
28
+ margin: 0 auto;
29
+ padding: 20px;
30
+ }
31
+
32
+ h1 {
33
+ margin: 0;
34
+ font-size: 2.5em;
35
+ }
36
+ .brand-list {
37
+ max-width: 700px;
38
+ margin: 0 auto;
39
+ }
40
+ .brand-item {
41
+ background-color: #fff;
42
+ border-radius: 12px;
43
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
44
+ padding: 20px;
45
+ display: flex;
46
+ align-items: center;
47
+ cursor: pointer;
48
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
49
+ margin-bottom: 20px;
50
+ position: relative;
51
+ overflow: hidden;
52
+ }
53
+ .brand-item:hover {
54
+ transform: translateY(-5px);
55
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
56
+ }
57
+ .brand-image {
58
+ width: 80px;
59
+ height: 80px;
60
+ display: flex;
61
+ justify-content: center;
62
+ align-items: center;
63
+ margin-right: 20px;
64
+ border-radius: 12px;
65
+ overflow: hidden;
66
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
67
+ }
68
+ .brand-image img {
69
+ width: 100%;
70
+ height: 100%;
71
+ object-fit: cover;
72
+ }
73
+ .brand-info {
74
+ flex-grow: 1;
75
+ }
76
+ .brand-name {
77
+ font-size: 20px;
78
+ font-weight: bold;
79
+ margin-bottom: 5px;
80
+ color: var(--primary-color);
81
+ }
82
+ .brand-key {
83
+ font-size: 14px;
84
+ color: #7f8c8d;
85
+ }
86
+ .brand-actions {
87
+ display: flex;
88
+ align-items: center;
89
+ }
90
+ .switch-button {
91
+ background-color: var(--primary-color);
92
+ color: white;
93
+ border: none;
94
+ padding: 10px 20px;
95
+ border-radius: 5px;
96
+ cursor: pointer;
97
+ font-size: 16px;
98
+ transition: background-color 0.3s ease;
99
+ margin-right: 15px;
100
+ }
101
+ .switch-button:hover {
102
+ background-color: #3a7bc8;
103
+ }
104
+ .overflow-menu {
105
+ cursor: pointer;
106
+ font-size: 20px;
107
+ color: #7f8c8d;
108
+ transition: color 0.3s ease;
109
+ padding: 10px;
110
+ margin: -10px;
111
+ }
112
+ .overflow-menu:hover {
113
+ color: var(--primary-color);
114
+ }
115
+
116
+ .current-brand, .brands-list {
117
+ margin-bottom: 40px;
118
+ max-width: 700px;
119
+ margin-left: auto;
120
+ margin-right: auto;
121
+ }
122
+ .current-brand h2, .brands-list h2 {
123
+ margin: 0 0 20px 0;
124
+ font-size: 1.8em;
125
+ color: var(--primary-color);
126
+ }
127
+ .section-title {
128
+ font-size: 1.5em;
129
+ color: var(--primary-color);
130
+ margin-bottom: 20px;
131
+ text-align: center;
132
+ }
133
+ .brands-list-header {
134
+ display: flex;
135
+ justify-content: space-between;
136
+ align-items: center;
137
+ margin-bottom: 20px;
138
+ margin-right: 40px;
139
+ }
140
+ .onboard-brand-button {
141
+ background-color: var(--primary-color);
142
+ color: white;
143
+ border: none;
144
+ padding: 10px 20px;
145
+ border-radius: 5px;
146
+ cursor: pointer;
147
+ font-size: 16px;
148
+ transition: background-color 0.3s ease;
149
+ }
150
+ .onboard-brand-button:hover {
151
+ background-color: #3a7bc8;
152
+ }
153
+ .onboard-brand-form {
154
+ display: flex;
155
+ flex-direction: column;
156
+ gap: 15px;
157
+ }
158
+ .form-group {
159
+ display: flex;
160
+ flex-direction: column;
161
+ }
162
+ .form-group label {
163
+ display: flex;
164
+ align-items: center;
165
+ margin-bottom: 5px;
166
+ font-weight: bold;
167
+ }
168
+ .form-group input {
169
+ padding: 10px;
170
+ border: 1px solid var(--border-color);
171
+ border-radius: 5px;
172
+ font-size: 16px;
173
+ }
174
+ .question-icon {
175
+ margin-left: 5px;
176
+ cursor: pointer;
177
+ color: var(--primary-color);
178
+ }
179
+ .logo {
180
+ width: 75px;
181
+ height: 75px;
182
+ margin-right: 20px;
183
+ filter: drop-shadow(3px 3px 3px rgba(0, 0, 0, 0.3));
184
+ transition: transform 0.3s ease;
185
+ }
186
+ .logo:hover {
187
+ transform: scale(1.1);
188
+ }
189
+
190
+ .header-container {
191
+ display: flex;
192
+ align-items: center;
193
+ justify-content: center;
194
+ }
195
+
196
+ header {
197
+ background-color: var(--primary-color);
198
+ color: white;
199
+ text-align: center;
200
+ padding: 10px 0;
201
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
202
+ display: flex;
203
+ justify-content: center;
204
+ align-items: center;
205
+ position: fixed;
206
+ top: 0;
207
+ left: 0;
208
+ right: 0;
209
+ z-index: 1000;
210
+ transition: transform 0.3s ease;
211
+ }
212
+ .scroll-up header {
213
+ transform: translateY(0);
214
+ }
215
+ .scroll-down header {
216
+ transform: translateY(-100%);
217
+ }
218
+ .logo {
219
+ width: 50px;
220
+ height: 50px;
221
+ margin-right: 20px;
222
+ filter: drop-shadow(3px 3px 3px rgba(0, 0, 0, 0.3));
223
+ transition: transform 0.3s ease;
224
+ }
225
+ .logo:hover {
226
+ transform: scale(1.1);
227
+ }
228
+ h1 {
229
+ margin: 0;
230
+ font-size: 2.5em;
231
+ }
232
+
233
+ .search-container {
234
+ margin-top: 20px;
235
+ margin-bottom: 20px;
236
+ }
237
+
238
+ #brandSearch {
239
+ padding: 15px;
240
+ margin-bottom: 15px;
241
+ border: 1px solid var(--border-color);
242
+ border-radius: 5px;
243
+ font-size: 16px;
244
+ width: 100%;
245
+ max-width: 670px;
246
+ }
247
+
248
+ .brands-list-header {
249
+ display: flex;
250
+ justify-content: space-between;
251
+ align-items: center;
252
+ margin-bottom: 20px;
253
+ }
254
+
255
+ #error-button {
256
+ position: fixed;
257
+ bottom: 20px;
258
+ right: 20px;
259
+ background-color: #ff4136;
260
+ color: white;
261
+ border: none;
262
+ border-radius: 50%;
263
+ width: 60px;
264
+ height: 60px;
265
+ font-size: 24px;
266
+ cursor: pointer;
267
+ justify-content: center;
268
+ align-items: center;
269
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
270
+ transition: transform 0.2s;
271
+ display: none;
272
+ }
273
+
274
+ #error-button:hover {
275
+ transform: scale(1.1);
276
+ }
277
+
278
+ .count {
279
+ position: absolute;
280
+ top: -5px;
281
+ right: -5px;
282
+ background-color: #ffdc00;
283
+ color: #111;
284
+ border-radius: 50%;
285
+ width: 24px;
286
+ height: 24px;
287
+ font-size: 14px;
288
+ font-weight: bold;
289
+ display: flex;
290
+ justify-content: center;
291
+ align-items: center;
292
+ }
293
+ </style>
294
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css">
295
+ </head>
296
+ <body>
297
+
298
+ <header>
299
+ <div class="header-container">
300
+ <img class="logo" src="../solara.png" alt="Splash Image">
301
+ <h1>Solara Dashboard</h1>
302
+ </div>
303
+
304
+ </header>
305
+
306
+ <button id="error-button">
307
+ ⚠️
308
+ <span class="count">5</span>
309
+ </button>
310
+
311
+ <div class="container">
312
+ <div class="current-brand" id="currentBrandSection" style=" display: none;">
313
+ <h2>Current Brand</h2>
314
+ <div id="currentBrandItem"></div>
315
+ </div>
316
+ <div class="brands-list">
317
+ <div class="brands-list-header">
318
+ <h2>All Brands</h2>
319
+
320
+ <button class="onboard-brand-button">
321
+ <i class="fas fa-plus"></i> Onboard
322
+ </button>
323
+ </div>
324
+
325
+ <div class="search-container">
326
+ <input type="text" id="brandSearch" placeholder="Search brands...">
327
+ </div>
328
+
329
+ <div class="brand-list" id="brandList"></div>
330
+ </div>
331
+ </div>
332
+
333
+ <brand-options-bottom-sheet id="bottomSheet"></brand-options-bottom-sheet>
334
+
335
+ <confirmation-dialog id="confirmationDialog"></confirmation-dialog>
336
+
337
+ <onboard-bottom-sheet id="onboardBottomSheet"></onboard-bottom-sheet>
338
+
339
+ <message-bottom-sheet id="messageBottomSheet"></message-bottom-sheet>
340
+
341
+ <aliases-bottom-sheet id="aliasesSheet"></aliases-bottom-sheet>
342
+
343
+ <script type="module" src="Brands.js"></script>
344
+ </body>
345
+ </html>
@@ -0,0 +1,212 @@
1
+ class AddFieldSheet extends HTMLElement {
2
+ constructor() {
3
+ super();
4
+ this.onSubmit = null;
5
+ this.inputType = null;
6
+
7
+ this.attachShadow({mode: 'open'});
8
+ this.render();
9
+
10
+ this.addFieldSheet = this.shadowRoot.querySelector('#addFieldSheet');
11
+ this.overlay = this.shadowRoot.getElementById('overlay');
12
+
13
+ this.shadowRoot.querySelector('#addFieldForm').onsubmit = (e) => this.handleSubmit(e);
14
+ this.shadowRoot.querySelector('#colorPicker').oninput = (e) => this.updateFieldValue(e);
15
+ this.overlay.onclick = () => this.hideAddFieldForm();
16
+ }
17
+
18
+ render() {
19
+ this.shadowRoot.innerHTML = `
20
+ <style>
21
+ .bottom-sheet {
22
+ position: fixed;
23
+ bottom: -100%;
24
+ left: 0;
25
+ right: 0;
26
+ background-color: white;
27
+ padding: 30px;
28
+ box-shadow: 0 -5px 20px rgba(0, 0, 0, 0.2);
29
+ transition: bottom 0.3s ease-out;
30
+ z-index: 1000;
31
+ border-top-left-radius: 25px;
32
+ border-top-right-radius: 25px;
33
+ height: 60vh;
34
+ max-height: 500px;
35
+ overflow-y: auto;
36
+ max-width: 600px;
37
+ margin: 0 auto;
38
+ }
39
+ .bottom-sheet.show {
40
+ bottom: 0;
41
+ }
42
+ .bottom-sheet h3 {
43
+ color: var(--primary-color);
44
+ margin-top: 0;
45
+ margin-bottom: 20px;
46
+ font-size: 24px;
47
+ }
48
+ .overlay {
49
+ display: none;
50
+ position: fixed;
51
+ top: 0;
52
+ left: 0;
53
+ right: 0;
54
+ bottom: 0;
55
+ background: rgba(0, 0, 0, 0.5);
56
+ z-index: 999;
57
+ }
58
+ .show {
59
+ display: block;
60
+ }
61
+ .form-group {
62
+ margin-bottom: 20px;
63
+ }
64
+ .form-group label {
65
+ display: block;
66
+ margin-bottom: 8px;
67
+ font-weight: bold;
68
+ }
69
+ .form-group input {
70
+ width: 100%;
71
+ padding: 12px;
72
+ border: 1px solid var(--border-color);
73
+ border-radius: 4px;
74
+ font-size: 16px;
75
+ }
76
+ .tooltip {
77
+ position: relative;
78
+ display: inline-block;
79
+ margin-left: 5px;
80
+ }
81
+ .tooltip .tooltiptext {
82
+ visibility: hidden;
83
+ width: 200px;
84
+ background-color: #555;
85
+ color: #fff;
86
+ text-align: center;
87
+ border-radius: 6px;
88
+ padding: 5px;
89
+ position: absolute;
90
+ z-index: 1;
91
+ bottom: 125%;
92
+ left: 50%;
93
+ transform: translateX(-50%);
94
+ opacity: 0;
95
+ transition: opacity 0.3s;
96
+ }
97
+ .tooltip:hover .tooltiptext {
98
+ visibility: visible;
99
+ opacity: 1;
100
+ }
101
+ .add-field-button {
102
+ width: 100%;
103
+ padding: 15px;
104
+ font-size: 18px;
105
+ background-color: var(--primary-color);
106
+ color: white;
107
+ border: none;
108
+ border-radius: 4px;
109
+ cursor: pointer;
110
+ transition: background-color 0.3s ease;
111
+ }
112
+ .add-field-button:hover {
113
+ background-color: #3A7BC8;
114
+ }
115
+ .color-picker-container {
116
+ display: none;
117
+ margin-top: 10px;
118
+ }
119
+ #fieldValue[type="color"] {
120
+ -webkit-appearance: none;
121
+ border: none;
122
+ width: 32px;
123
+ height: 32px;
124
+ cursor: pointer;
125
+ }
126
+ #fieldValue[type="color"]::-webkit-color-swatch-wrapper {
127
+ padding: 0;
128
+ }
129
+ #fieldValue[type="color"]::-webkit-color-swatch {
130
+ border: none;
131
+ }
132
+ #colorPicker {
133
+ -webkit-appearance: none; /* Remove default styling */
134
+ border: none; /* No border */
135
+ width: 100%; /* Set a fixed width */
136
+ height: 60px; /* Increase the height */
137
+ cursor: pointer; /* Pointer cursor on hover */
138
+ border-radius: 4px; /* Optional: Rounded corners */
139
+ }
140
+
141
+ #colorPicker::-webkit-color-swatch {
142
+ border: none; /* No border on the color swatch */
143
+ border-radius: 4px; /* Optional: Rounded corners */
144
+ }
145
+ </style>
146
+ <div id="overlay" class="overlay"></div>
147
+ <div class="bottom-sheet" id="addFieldSheet">
148
+ <h3>Add New Field</h3>
149
+ <form id="addFieldForm">
150
+ <div class="form-group">
151
+ <label for="fieldName">Field Name</label>
152
+ <input type="text" id="fieldName" name="fieldName" required>
153
+ </div>
154
+ <div class="form-group">
155
+ <label for="fieldValue">Field Value</label>
156
+ <input type="text" id="fieldValue" name="fieldValue" required>
157
+ <div class="color-picker-container">
158
+ <input type="color" id="colorPicker" name="colorPicker">
159
+ </div>
160
+ </div>
161
+ <button type="submit" class="add-field-button">Add Field</button>
162
+ </form>
163
+ </div>
164
+ `;
165
+ }
166
+
167
+ show(inputType, onSubmit) {
168
+ this.onSubmit = onSubmit;
169
+ this.inputType = inputType;
170
+ const fieldName = this.shadowRoot.querySelector('#fieldName');
171
+ const fieldValue = this.shadowRoot.querySelector('#fieldValue');
172
+ const colorPickerContainer = this.shadowRoot.querySelector('.color-picker-container');
173
+
174
+ fieldName.value = '';
175
+ fieldValue.value = '';
176
+ colorPickerContainer.style.display = inputType === 'color' ? 'block' : 'none';
177
+
178
+ this.addFieldSheet.style.display = 'block';
179
+ this.overlay.classList.add('show');
180
+ setTimeout(() => this.addFieldSheet.classList.add('show'), 10);
181
+ }
182
+
183
+ hideAddFieldForm() {
184
+ this.addFieldSheet.classList.remove('show');
185
+ this.overlay.classList.remove('show');
186
+ setTimeout(() => {
187
+ this.addFieldSheet.style.display = 'none';
188
+ }, 300);
189
+ }
190
+
191
+ handleSubmit(e) {
192
+ e.preventDefault();
193
+ const fieldName = this.shadowRoot.querySelector('#fieldName').value;
194
+ let defaultValue = this.shadowRoot.querySelector('#fieldValue').value;
195
+
196
+ if (this.inputType === 'color' && !defaultValue.startsWith('#')) {
197
+ defaultValue = '#' + defaultValue;
198
+ }
199
+
200
+ if (this.onSubmit) {
201
+ this.onSubmit(fieldName, defaultValue);
202
+ }
203
+ this.hideAddFieldForm();
204
+ }
205
+
206
+ updateFieldValue(event) {
207
+ const fieldValue = this.shadowRoot.querySelector('#fieldValue');
208
+ fieldValue.value = event.target.value;
209
+ }
210
+ }
211
+
212
+ customElements.define('add-field-sheet', AddFieldSheet);
@@ -0,0 +1,128 @@
1
+ class AliasesBottomSheet extends HTMLElement {
2
+ constructor() {
3
+ super();
4
+ this.attachShadow({ mode: 'open' });
5
+ this.shadowRoot.innerHTML = `
6
+ <style>
7
+ .aliases-bottom-sheet {
8
+ display: none;
9
+ position: fixed;
10
+ bottom: 0;
11
+ left: 0;
12
+ right: 0;
13
+ background-color: white;
14
+ border-top-left-radius: 20px;
15
+ border-top-right-radius: 20px;
16
+ box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
17
+ z-index: 1000;
18
+ padding: 20px;
19
+ transition: transform 0.3s ease-out;
20
+ transform: translateY(100%);
21
+ max-width: 700px;
22
+ margin: 0 auto;
23
+ width: 100%;
24
+ max-height: 80vh;
25
+ overflow-y: auto;
26
+ }
27
+ .aliases-bottom-sheet.show {
28
+ transform: translateY(0);
29
+ }
30
+ .aliases-bottom-sheet h3 {
31
+ color: var(--primary-color);
32
+ margin-top: 0;
33
+ }
34
+ .aliases-bottom-sheet ul {
35
+ list-style-type: none;
36
+ padding: 0;
37
+ }
38
+ .aliases-bottom-sheet li {
39
+ margin-bottom: 10px;
40
+ font-family: monospace;
41
+ background-color: #f1f1f1;
42
+ padding: 5px;
43
+ border-radius: 5px;
44
+ }
45
+ .overlay {
46
+ display: none;
47
+ position: fixed;
48
+ top: 0;
49
+ left: 0;
50
+ right: 0;
51
+ bottom: 0;
52
+ background: rgba(0, 0, 0, 0.5);
53
+ z-index: 999;
54
+ }
55
+ .close-aliases {
56
+ background-color: var(--primary-color);
57
+ color: white;
58
+ border: none;
59
+ padding: 10px 20px;
60
+ border-radius: 5px;
61
+ cursor: pointer;
62
+ font-size: 16px;
63
+ transition: background-color 0.3s ease;
64
+ margin-top: 20px;
65
+ }
66
+ .close-aliases:hover {
67
+ background-color: #3a7bc8;
68
+ }
69
+ </style>
70
+ <div class="overlay"></div>
71
+ <div class="aliases-bottom-sheet" id="aliasesSheet">
72
+ <h3>Aliases</h3>
73
+ <div id="commonAliases">
74
+ <h4>Common Aliases</h4>
75
+ <ul id="commonAliasesList"></ul>
76
+ </div>
77
+ <div id="brandAliases">
78
+ <h4>Brand Aliases</h4>
79
+ <ul id="brandAliasesList"></ul>
80
+ </div>
81
+ <button class="close-aliases" id="closeAliases">Close</button>
82
+ </div>
83
+ `;
84
+
85
+ this.aliasesBottomSheet = this.shadowRoot.getElementById('aliasesSheet');
86
+ this.overlay = this.shadowRoot.querySelector('.overlay');
87
+ this.closeAliasesBtn = this.shadowRoot.getElementById('closeAliases');
88
+
89
+ this.closeAliasesBtn.onclick = () => this.hide();
90
+ this.overlay.onclick = () => this.hide();
91
+ }
92
+
93
+ show(aliases, brand) {
94
+ const commonAliasesList = this.shadowRoot.getElementById('commonAliasesList');
95
+ const brandAliasesList = this.shadowRoot.getElementById('brandAliasesList');
96
+
97
+ commonAliasesList.innerHTML = '';
98
+ brandAliasesList.innerHTML = '';
99
+
100
+ aliases.aliases.common_aliases.forEach(alias => {
101
+ const li = document.createElement('li');
102
+ li.textContent = alias;
103
+ commonAliasesList.appendChild(li);
104
+ });
105
+
106
+ const brandAliases = aliases.aliases.brand_aliases[brand.key] || [];
107
+ brandAliases.forEach(alias => {
108
+ const li = document.createElement('li');
109
+ li.textContent = alias;
110
+ brandAliasesList.appendChild(li);
111
+ });
112
+
113
+ this.aliasesBottomSheet.style.display = 'block';
114
+ this.overlay.style.display = 'block';
115
+
116
+ setTimeout(() => this.aliasesBottomSheet.classList.add('show'), 10);
117
+ }
118
+
119
+ hide() {
120
+ this.aliasesBottomSheet.classList.remove('show');
121
+ setTimeout(() => {
122
+ this.aliasesBottomSheet.style.display = 'none';
123
+ this.overlay.style.display = 'none';
124
+ }, 300); // Match with the CSS transition duration
125
+ }
126
+ }
127
+
128
+ customElements.define('aliases-bottom-sheet', AliasesBottomSheet);