solara 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/solara/lib/core/.DS_Store +0 -0
- data/solara/lib/core/aliases/alias_generator.rb +1 -0
- data/solara/lib/core/aliases/alias_generator_manager.rb +2 -1
- data/solara/lib/core/aliases/solara_terminal_setup.rb +1 -1
- data/solara/lib/core/brands/brand_font_switcher.rb +154 -0
- data/solara/lib/core/brands/brand_onboarder.rb +8 -6
- data/solara/lib/core/brands/brand_switcher.rb +232 -166
- data/solara/lib/core/brands/brands_manager.rb +15 -39
- data/solara/lib/core/dashboard/brand/BrandDetail.js +19 -0
- data/solara/lib/core/dashboard/brand/BrandDetailController.js +50 -8
- data/solara/lib/core/dashboard/brand/BrandDetailModel.js +9 -30
- data/solara/lib/core/dashboard/brand/BrandDetailView.js +49 -3
- data/solara/lib/core/dashboard/brand/InfoPlistStringCatalogManager.js +19 -0
- data/solara/lib/core/dashboard/brand/brand.html +209 -62
- data/solara/lib/core/dashboard/brand/source/BrandLocalSource.js +1 -1
- data/solara/lib/core/dashboard/brand/source/BrandRemoteSource.js +38 -53
- data/solara/lib/core/dashboard/brands/BrandsController.js +6 -5
- data/solara/lib/core/dashboard/brands/BrandsModel.js +2 -2
- data/solara/lib/core/dashboard/brands/BrandsView.js +2 -2
- data/solara/lib/core/dashboard/brands/brands.html +3 -1
- data/solara/lib/core/dashboard/component/AliasesBottomSheet.js +7 -5
- data/solara/lib/core/dashboard/dashboard_manager.rb +2 -0
- data/solara/lib/core/dashboard/dashboard_server.rb +1 -3
- data/solara/lib/core/dashboard/handler/brand_alisases_handler.rb +4 -11
- data/solara/lib/core/dashboard/handler/brand_configurations_manager.rb +11 -11
- data/solara/lib/core/dashboard/handler/{brand_configurations_handler.rb → brand_details_handler.rb} +4 -4
- data/solara/lib/core/dashboard/handler/brands_handler.rb +1 -1
- data/solara/lib/core/dashboard/handler/edit_section_handler.rb +8 -8
- data/solara/lib/core/doctor/brand_doctor.rb +31 -31
- data/solara/lib/core/doctor/doctor_manager.rb +0 -1
- data/solara/lib/core/doctor/project_doctor.rb +0 -1
- data/solara/lib/core/doctor/schema/platform/android/android_config.json +0 -4
- data/solara/lib/core/doctor/schema/platform/ios/InfoPlist.xcstrings +15 -0
- data/solara/lib/core/doctor/schema/platform/ios/ios_config.json +0 -5
- data/solara/lib/core/doctor/schema/platform/shared/brand_config.json +9 -0
- data/solara/lib/core/doctor/schema/platform/shared/theme.json +94 -9
- data/solara/lib/core/doctor/validator/brand_settings_validator.rb +6 -0
- data/solara/lib/core/doctor/validator/brand_settings_validator_manager.rb +9 -21
- data/solara/lib/core/doctor/validator/template/android_template_validation_config.yml +22 -4
- data/solara/lib/core/doctor/validator/template/flutter_template_validation_config.yml +22 -6
- data/solara/lib/core/doctor/validator/template/ios_template_validation_config.yml +22 -4
- data/solara/lib/core/scripts/brand_config_generator.rb +1 -0
- data/solara/lib/core/scripts/brand_config_manager.rb +2 -4
- data/solara/lib/core/scripts/brand_exporter.rb +1 -1
- data/solara/lib/core/scripts/brand_importer.rb +2 -3
- data/solara/lib/core/scripts/brand_offboarder.rb +5 -0
- data/solara/lib/core/scripts/brand_resources_manager.rb +127 -54
- data/solara/lib/core/scripts/directory_creator.rb +2 -2
- data/solara/lib/core/scripts/file_manager.rb +53 -19
- data/solara/lib/core/scripts/file_path.rb +175 -30
- data/solara/lib/core/scripts/folder_copier.rb +3 -7
- data/solara/lib/core/scripts/gitignore_manager.rb +21 -10
- data/solara/lib/core/scripts/interactive_file_system_validator.rb +8 -2
- data/solara/lib/core/scripts/platform/android/android_manifest_switcher.rb +3 -3
- data/solara/lib/core/scripts/platform/android/android_strings_switcher.rb +26 -24
- data/solara/lib/core/scripts/platform/android/gradle_switcher.rb +7 -6
- data/solara/lib/core/scripts/platform/ios/infoplist_string_catalog_manager.rb +123 -0
- data/solara/lib/core/scripts/platform/ios/infoplist_switcher.rb +59 -0
- data/solara/lib/core/scripts/platform/ios/ios_plist_manager.rb +11 -20
- data/solara/lib/core/scripts/platform/ios/plist_font_manager.rb +33 -0
- data/solara/lib/core/scripts/platform/ios/xcconfig_generator.rb +15 -3
- data/solara/lib/core/scripts/platform/ios/xcode_asset_manager.rb +2 -3
- data/solara/lib/core/scripts/platform/ios/xcode_project_manager.rb +80 -1
- data/solara/lib/core/scripts/platform/ios/xcode_project_switcher.rb +15 -34
- data/solara/lib/core/scripts/solara_logger.rb +10 -0
- data/solara/lib/core/scripts/solara_settings_manager.rb +26 -1
- data/solara/lib/core/scripts/strings_xml_manager.rb +17 -2
- data/solara/lib/core/scripts/theme_generator.rb +133 -130
- data/solara/lib/core/scripts/yaml_manager.rb +23 -0
- data/solara/lib/core/solara_configurator.rb +1 -1
- data/solara/lib/core/template/brands/android/android_config.json +0 -1
- data/solara/lib/core/template/brands/android/res/values/strings.xml +4 -0
- data/solara/lib/core/template/brands/ios/InfoPlist.xcstrings +30 -0
- data/solara/lib/core/template/brands/ios/ios_config.json +1 -2
- data/solara/lib/core/template/brands/shared/brand_config.json +1 -0
- data/solara/lib/core/template/brands/shared/theme.json +3 -3
- data/solara/lib/core/template/config/android_template_config.json +11 -1
- data/solara/lib/core/template/config/flutter_template_config.json +12 -2
- data/solara/lib/core/template/config/ios_template_config.json +11 -1
- data/solara/lib/core/template/project_template_generator.rb +8 -3
- data/solara/lib/solara/version.rb +1 -1
- data/solara/lib/solara.rb +8 -4
- data/solara/lib/solara_initializer.rb +5 -2
- data/solara/lib/solara_manager.rb +1 -1
- metadata +62 -43
- data/solara/lib/core/dashboard/handler/brand_section_handler.rb +0 -20
- data/solara/lib/core/doctor/validator/directory_structure_validator.rb +0 -38
- data/solara/lib/core/doctor/validator/file_structure_validator.rb +0 -37
- data/solara/lib/core/scripts/platform/ios/ios_file_path_manager.rb +0 -109
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/.DS_Store +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/100.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/102.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/1024.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/114.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/120.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/128.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/144.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/152.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/16.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/167.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/172.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/180.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/196.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/20.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/216.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/256.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/29.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/32.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/40.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/48.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/50.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/512.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/55.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/57.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/58.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/60.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/64.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/66.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/72.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/76.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/80.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/87.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/88.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/92.png +0 -0
- /data/solara/lib/core/template/brands/ios/{assets → xcassets}/AppIcon.appiconset/Contents.json +0 -0
@@ -5,25 +5,22 @@ require 'rubygems'
|
|
5
5
|
class BrandsManager
|
6
6
|
include Singleton
|
7
7
|
|
8
|
+
# Class method to access the singleton instance
|
9
|
+
def self.instance
|
10
|
+
@instance ||= new
|
11
|
+
end
|
12
|
+
|
8
13
|
def initialize
|
9
14
|
brands_list_path = FilePath.brands_list
|
10
15
|
@brands_list = JSON.parse(File.read(brands_list_path))
|
11
16
|
end
|
12
17
|
|
13
|
-
def first_brand
|
14
|
-
brands_list.first
|
15
|
-
end
|
16
|
-
|
17
18
|
def first_brand_key
|
18
19
|
brands_list.first["key"]
|
19
20
|
rescue
|
20
21
|
nil
|
21
22
|
end
|
22
23
|
|
23
|
-
def brand_name(brand_key)
|
24
|
-
brand_data(brand_key)["name"]
|
25
|
-
end
|
26
|
-
|
27
24
|
def brand_with_configurations(brand_key)
|
28
25
|
configurations = BrandConfigurationsManager.new(brand_key).create
|
29
26
|
{
|
@@ -41,17 +38,8 @@ class BrandsManager
|
|
41
38
|
@brands_list["brands"]
|
42
39
|
end
|
43
40
|
|
44
|
-
def find(brand_key)
|
45
|
-
brands = brands_list
|
46
|
-
brands.find { |b| b["key"] == brand_key }
|
47
|
-
end
|
48
|
-
|
49
|
-
def brands_json
|
50
|
-
@brands_list
|
51
|
-
end
|
52
|
-
|
53
41
|
def exists(brand_key)
|
54
|
-
!brand_data(brand_key).nil?
|
42
|
+
!brand_data(brand_key).nil? && File.exist?(FilePath.brand(brand_key))
|
55
43
|
end
|
56
44
|
|
57
45
|
def add_brand(brand_name, brand_key)
|
@@ -59,11 +47,11 @@ class BrandsManager
|
|
59
47
|
existing_brand = brand_data(brand_key)
|
60
48
|
if existing_brand
|
61
49
|
update_brand(brands_list.index(existing_brand), brand)
|
62
|
-
Solara.logger.debug("#{brand_name} Brand updated in the list.")
|
50
|
+
Solara.logger.debug("#{brand_name} Brand updated in the brands list.")
|
63
51
|
else
|
64
52
|
brands_list.push(brand)
|
65
53
|
save_brands_list
|
66
|
-
Solara.logger.debug("#{brand_name} added to the list.")
|
54
|
+
Solara.logger.debug("#{brand_name} added to the brands list.")
|
67
55
|
end
|
68
56
|
end
|
69
57
|
|
@@ -71,13 +59,6 @@ class BrandsManager
|
|
71
59
|
JSON.parse(File.read(FilePath.current_brand))
|
72
60
|
end
|
73
61
|
|
74
|
-
def current_brand_content_changed(brand_key)
|
75
|
-
unless is_current_brand(brand_key)
|
76
|
-
return false
|
77
|
-
end
|
78
|
-
current_brand['content_changed'] == true
|
79
|
-
end
|
80
|
-
|
81
62
|
def set_current_brand_content_changed(brand_key, changed)
|
82
63
|
unless is_current_brand(brand_key)
|
83
64
|
return false
|
@@ -85,7 +66,7 @@ class BrandsManager
|
|
85
66
|
Solara.logger.debug("")
|
86
67
|
brand = current_brand
|
87
68
|
brand['content_changed'] = changed
|
88
|
-
|
69
|
+
save_current_brand_data(brand)
|
89
70
|
Solara.logger.debug("#{brand_key} changed saved to current_brand.json.")
|
90
71
|
end
|
91
72
|
|
@@ -95,17 +76,17 @@ class BrandsManager
|
|
95
76
|
|
96
77
|
def save_current_brand(brand_key)
|
97
78
|
brand = brand_data(brand_key)
|
98
|
-
|
79
|
+
save_current_brand_data(brand)
|
99
80
|
Solara.logger.debug("#{brand_key} saved as current brand.")
|
100
81
|
end
|
101
82
|
|
102
|
-
def
|
103
|
-
|
83
|
+
def save_current_brand_data(brand_data)
|
84
|
+
path = FilePath.current_brand
|
104
85
|
|
105
86
|
# Create the file if it doesn't exist
|
106
|
-
FileUtils.touch(
|
87
|
+
FileUtils.touch(path) unless File.exist?(path)
|
107
88
|
|
108
|
-
File.open(
|
89
|
+
File.open(path, 'w') do |file|
|
109
90
|
file.write(JSON.pretty_generate(brand_data))
|
110
91
|
end
|
111
92
|
|
@@ -128,7 +109,7 @@ class BrandsManager
|
|
128
109
|
if index
|
129
110
|
brand_dir = FilePath.brand(brand_key)
|
130
111
|
remove_brand(index)
|
131
|
-
|
112
|
+
FileManager.delete_if_exists(brand_dir)
|
132
113
|
save_brands_list
|
133
114
|
Solara.logger.debug("Brand removed.")
|
134
115
|
else
|
@@ -136,11 +117,6 @@ class BrandsManager
|
|
136
117
|
end
|
137
118
|
end
|
138
119
|
|
139
|
-
# Class method to access the singleton instance
|
140
|
-
def self.instance
|
141
|
-
@instance ||= new
|
142
|
-
end
|
143
|
-
|
144
120
|
private
|
145
121
|
|
146
122
|
def save_brands_list
|
@@ -3,6 +3,25 @@ import BrandDetailModel from './BrandDetailModel.js';
|
|
3
3
|
import BrandDetailView from './BrandDetailView.js';
|
4
4
|
import BrandDetailController from './BrandDetailController.js';
|
5
5
|
|
6
|
+
window.onload = function () {
|
7
|
+
document.getElementById('loadingOverlay').style.display = 'none';
|
8
|
+
};
|
9
|
+
|
10
|
+
let lastScrollTop = 0;
|
11
|
+
const header = document.getElementById('header');
|
12
|
+
|
13
|
+
window.addEventListener('scroll', function () {
|
14
|
+
let scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
15
|
+
if (scrollTop > lastScrollTop) {
|
16
|
+
// Scrolling down
|
17
|
+
header.classList.add('scroll-down');
|
18
|
+
} else {
|
19
|
+
// Scrolling up
|
20
|
+
header.classList.remove('scroll-down');
|
21
|
+
}
|
22
|
+
lastScrollTop = scrollTop;
|
23
|
+
});
|
24
|
+
|
6
25
|
document.addEventListener('DOMContentLoaded', async () => {
|
7
26
|
const model = new BrandDetailModel();
|
8
27
|
const view = new BrandDetailView(model);
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import {DataSource} from './BrandDetailModel.js';
|
2
|
+
import InfoPlistStringCatalogManager from "./InfoPlistStringCatalogManager.js";
|
2
3
|
|
3
4
|
class BrandDetailController {
|
4
5
|
constructor(model, view) {
|
@@ -112,8 +113,11 @@ class BrandDetailController {
|
|
112
113
|
|
113
114
|
async onLoadSections(configuraationsResult) {
|
114
115
|
try {
|
116
|
+
this.view.addBrandOverlay.style.display = 'none'
|
117
|
+
this.view.header.style.display = 'flex';
|
115
118
|
this.view.updateAppNameTitle(`${configuraationsResult.brand.key} (${configuraationsResult.brand.name})`);
|
116
119
|
await this.showSections(configuraationsResult);
|
120
|
+
this.view.showIndex();
|
117
121
|
} catch (error) {
|
118
122
|
console.error('Error initializing app:', error);
|
119
123
|
alert(error.message);
|
@@ -142,10 +146,17 @@ class BrandDetailController {
|
|
142
146
|
const sectionInfo = sectionItems[i];
|
143
147
|
console.log('Processing section:', i, sectionInfo);
|
144
148
|
|
145
|
-
if (sectionInfo.key === 'theme') {
|
149
|
+
if (sectionInfo.key === 'theme.json') {
|
146
150
|
this.createThemeSections(sectionInfo)
|
151
|
+
} else if (sectionInfo.key === 'InfoPlist.xcstrings') {
|
152
|
+
this.createSection(
|
153
|
+
sectionInfo.key,
|
154
|
+
sectionInfo,
|
155
|
+
new InfoPlistStringCatalogManager(sectionInfo.content).extractLocalizations(),
|
156
|
+
sectionInfo.name,
|
157
|
+
sectionInfo.inputType)
|
147
158
|
} else {
|
148
|
-
this.createSection(sectionInfo, sectionInfo.content, sectionInfo.name, sectionInfo.inputType)
|
159
|
+
this.createSection(sectionInfo.key, sectionInfo, sectionInfo.content, sectionInfo.name, sectionInfo.inputType)
|
149
160
|
}
|
150
161
|
}
|
151
162
|
} catch (error) {
|
@@ -155,15 +166,42 @@ class BrandDetailController {
|
|
155
166
|
}
|
156
167
|
|
157
168
|
createThemeSections(sectionInfo) {
|
158
|
-
this.createSection(sectionInfo
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
169
|
+
this.createSection(`${sectionInfo.key}_colors`,
|
170
|
+
sectionInfo,
|
171
|
+
sectionInfo.content.colors,
|
172
|
+
'Theme Colors',
|
173
|
+
'color',
|
174
|
+
'colors')
|
175
|
+
this.createSection(`${sectionInfo.key}_typography`,
|
176
|
+
sectionInfo,
|
177
|
+
sectionInfo.content.typography,
|
178
|
+
'Theme Typography',
|
179
|
+
'text',
|
180
|
+
'typography')
|
181
|
+
this.createSection(`${sectionInfo.key}_spacing`,
|
182
|
+
sectionInfo,
|
183
|
+
sectionInfo.content.spacing,
|
184
|
+
'Theme Spacing', 'text',
|
185
|
+
'spacing')
|
186
|
+
this.createSection(
|
187
|
+
`${sectionInfo.key}_borderRadius`,
|
188
|
+
sectionInfo,
|
189
|
+
sectionInfo.content.borderRadius,
|
190
|
+
'Theme Border Radius',
|
191
|
+
'text',
|
192
|
+
'borderRadius')
|
193
|
+
this.createSection(
|
194
|
+
`${sectionInfo.key}_elevation`,
|
195
|
+
sectionInfo,
|
196
|
+
sectionInfo.content.elevation,
|
197
|
+
'Theme Elevation',
|
198
|
+
'text',
|
199
|
+
'elevation')
|
163
200
|
}
|
164
201
|
|
165
|
-
createSection(sectionInfo, content, sectionName, inputType, propertiesGroupName = null) {
|
202
|
+
createSection(id, sectionInfo, content, sectionName, inputType, propertiesGroupName = null) {
|
166
203
|
const sectionElement = this.view.createSection(sectionInfo.key, sectionName, inputType);
|
204
|
+
sectionElement.id = id;
|
167
205
|
sectionElement.dataset.propertiesGroupName = propertiesGroupName
|
168
206
|
|
169
207
|
this.view.sectionsContainer.appendChild(sectionElement);
|
@@ -208,6 +246,8 @@ class BrandDetailController {
|
|
208
246
|
if (input.classList.contains('array-input')) {
|
209
247
|
const arrayItemsContainer = input.closest('.input-wrapper').querySelector('.array-items-container');
|
210
248
|
current[lastKey] = this.getArrayValue(arrayItemsContainer);
|
249
|
+
} else if (input.type === 'checkbox') {
|
250
|
+
current[lastKey] = input.checked;
|
211
251
|
} else {
|
212
252
|
let value = input.value;
|
213
253
|
if (input.type === 'color') {
|
@@ -358,4 +398,6 @@ class BrandDetailController {
|
|
358
398
|
|
359
399
|
}
|
360
400
|
|
401
|
+
|
402
|
+
|
361
403
|
export default BrandDetailController;
|
@@ -14,9 +14,7 @@ class BrandDetailModel {
|
|
14
14
|
this.brandKey = this.getQueryFromUrl('brand_key');
|
15
15
|
|
16
16
|
const sourceFromUrl = this.getQueryFromUrl('source');
|
17
|
-
|
18
|
-
this.source = sourceFromUrl === DataSource.LOCAL ? DataSource.LOCAL : DataSource.REMOTE;
|
19
|
-
// this.source = DataSource.REMOTE;
|
17
|
+
this.source = sourceFromUrl === DataSource.LOCAL ? DataSource.LOCAL : DataSource.REMOTE;
|
20
18
|
}
|
21
19
|
|
22
20
|
getQueryFromUrl(name) {
|
@@ -24,25 +22,11 @@ class BrandDetailModel {
|
|
24
22
|
}
|
25
23
|
|
26
24
|
async fetchBrandDetails() {
|
27
|
-
|
28
|
-
case DataSource.LOCAL:
|
29
|
-
return await this.localSource.fetchBrandDetails(this.brandKey);
|
30
|
-
case DataSource.REMOTE:
|
31
|
-
return await this.remoteSource.fetchBrandDetails(this.brandKey);
|
32
|
-
default:
|
33
|
-
throw new Error('Unknown data source');
|
34
|
-
}
|
25
|
+
return await this.localSource.fetchBrandDetails(this.brandKey);
|
35
26
|
}
|
36
27
|
|
37
28
|
async fetchCurrentBrand() {
|
38
|
-
|
39
|
-
case DataSource.LOCAL:
|
40
|
-
return await this.localSource.fetchCurrentBrand(this.brandKey);
|
41
|
-
case DataSource.REMOTE:
|
42
|
-
return await this.remoteSource.fetchCurrentBrand(this.brandKey);
|
43
|
-
default:
|
44
|
-
throw new Error('Unknown data source');
|
45
|
-
}
|
29
|
+
return await this.localSource.fetchCurrentBrand(this.brandKey);
|
46
30
|
}
|
47
31
|
|
48
32
|
async saveSection(sectionItem, configuration) {
|
@@ -50,29 +34,24 @@ class BrandDetailModel {
|
|
50
34
|
case DataSource.LOCAL:
|
51
35
|
return await this.localSource.saveSection(sectionItem, configuration, this.brandKey);
|
52
36
|
case DataSource.REMOTE:
|
53
|
-
|
37
|
+
// Saving is not supported remotely. Instead, user can export the brand.
|
38
|
+
return
|
54
39
|
default:
|
55
40
|
throw new Error('Unknown data source');
|
56
41
|
}
|
57
42
|
}
|
58
43
|
|
59
44
|
async switchToBrand() {
|
60
|
-
|
61
|
-
case DataSource.LOCAL:
|
62
|
-
return await this.localSource.switchToBrand(this.brandKey);
|
63
|
-
case DataSource.REMOTE:
|
64
|
-
return await this.remoteSource.switchToBrand(this.brandKey);
|
65
|
-
default:
|
66
|
-
throw new Error('Unknown data source');
|
67
|
-
}
|
45
|
+
return await this.localSource.switchToBrand(this.brandKey);
|
68
46
|
}
|
69
47
|
|
70
48
|
async checkBrandHealth() {
|
71
49
|
switch (this.source) {
|
72
50
|
case DataSource.LOCAL:
|
73
|
-
|
51
|
+
return await this.localSource.checkBrandHealth(this.brandKey);
|
74
52
|
case DataSource.REMOTE:
|
75
|
-
|
53
|
+
// Checking health is not supported remotely yet.
|
54
|
+
return
|
76
55
|
default:
|
77
56
|
throw new Error('Unknown data source');
|
78
57
|
}
|
@@ -7,7 +7,11 @@ import '../component/MessageBottomSheet.js';
|
|
7
7
|
class BrandDetailView {
|
8
8
|
constructor(model) {
|
9
9
|
this.model = model;
|
10
|
+
|
11
|
+
this.header = document.getElementById('header');
|
12
|
+
|
10
13
|
this.brandDetailsContainer = document.getElementById('brand-details-container');
|
14
|
+
this.addBrandOverlay = document.getElementById('add-brand-overlay');
|
11
15
|
this.addBrandContainer = document.getElementById('add-brand-container');
|
12
16
|
|
13
17
|
this.sectionsContainer = document.getElementById('sections');
|
@@ -38,11 +42,15 @@ class BrandDetailView {
|
|
38
42
|
}
|
39
43
|
|
40
44
|
async setupLocal() {
|
45
|
+
this.addBrandOverlay.style.display = 'none'
|
46
|
+
this.header.style.display = 'flex'
|
41
47
|
this.allBrandsButton.style.display = 'block'
|
42
48
|
this.toggleAddBrandContainer(false);
|
43
49
|
}
|
44
50
|
|
45
51
|
async setupRemote() {
|
52
|
+
this.addBrandOverlay.style.display = 'flex'
|
53
|
+
this.header.style.display = 'none'
|
46
54
|
this.allBrandsButton.style.display = 'none'
|
47
55
|
this.toggleAddBrandContainer(true);
|
48
56
|
}
|
@@ -76,7 +84,7 @@ class BrandDetailView {
|
|
76
84
|
|
77
85
|
const subtitleElement = document.createElement('p');
|
78
86
|
subtitleElement.className = 'section-subtitle';
|
79
|
-
subtitleElement.textContent =
|
87
|
+
subtitleElement.textContent = key;
|
80
88
|
titleContainer.appendChild(subtitleElement);
|
81
89
|
|
82
90
|
section.appendChild(titleContainer);
|
@@ -90,10 +98,12 @@ class BrandDetailView {
|
|
90
98
|
sectionElement.appendChild(this.createInputField(sectionItem, key, value, 'array'));
|
91
99
|
} else if (typeof value === 'object' && value !== null) {
|
92
100
|
for (const [subKey, subValue] of Object.entries(value)) {
|
93
|
-
|
101
|
+
const subInputType = subValue === true || subValue === false ? 'boolean' : inputType;
|
102
|
+
sectionElement.appendChild(this.createInputField(sectionItem, `${key}.${subKey}`, subValue, subInputType));
|
94
103
|
}
|
95
104
|
} else {
|
96
|
-
|
105
|
+
const fieldInputType = value === true || value === false ? 'boolean' : inputType;
|
106
|
+
sectionElement.appendChild(this.createInputField(sectionItem, key, value, fieldInputType));
|
97
107
|
}
|
98
108
|
}
|
99
109
|
}
|
@@ -142,11 +152,30 @@ class BrandDetailView {
|
|
142
152
|
input.value = '';
|
143
153
|
});
|
144
154
|
|
155
|
+
} else if (inputType === 'boolean') {
|
156
|
+
const checkbox = document.createElement('input');
|
157
|
+
checkbox.type = 'checkbox';
|
158
|
+
checkbox.id = key;
|
159
|
+
checkbox.checked = value;
|
160
|
+
|
161
|
+
const checkboxLabel = document.createElement('label');
|
162
|
+
checkboxLabel.className = 'checkbox-label';
|
163
|
+
checkboxLabel.htmlFor = key;
|
164
|
+
checkboxLabel.textContent = value ? 'True' : 'False';
|
165
|
+
|
166
|
+
checkbox.addEventListener('change', () => {
|
167
|
+
checkboxLabel.textContent = checkbox.checked ? 'True' : 'False';
|
168
|
+
this.onSectionChanged(sectionItem, container.closest('.section'));
|
169
|
+
});
|
170
|
+
|
171
|
+
inputWrapper.appendChild(checkbox);
|
172
|
+
inputWrapper.appendChild(checkboxLabel);
|
145
173
|
} else {
|
146
174
|
const input = document.createElement('input');
|
147
175
|
input.type = inputType;
|
148
176
|
input.id = key;
|
149
177
|
|
178
|
+
console.log(value)
|
150
179
|
if (inputType === 'color') {
|
151
180
|
input.value = value.startsWith('#') ? value : `#${value.substring(4)}`;
|
152
181
|
} else {
|
@@ -236,6 +265,23 @@ class BrandDetailView {
|
|
236
265
|
this.onboardSheet.show('Brand Details', 'Add Brand', onSubmit);
|
237
266
|
}
|
238
267
|
|
268
|
+
showIndex() {
|
269
|
+
const sectionsContainer = this.sectionsContainer;
|
270
|
+
const sectionElements = Array.from(sectionsContainer.querySelectorAll('.section'));
|
271
|
+
|
272
|
+
const indexElement = document.getElementById('index');
|
273
|
+
|
274
|
+
// Clear existing items if needed
|
275
|
+
indexElement.innerHTML = '';
|
276
|
+
|
277
|
+
sectionElements.forEach(sectionElement => {
|
278
|
+
const newItem = document.createElement('li');
|
279
|
+
newItem.classList.add('index-item');
|
280
|
+
newItem.innerHTML = `<a href="#${sectionElement.id}">${sectionElement.dataset.name}</a>`;
|
281
|
+
indexElement.appendChild(newItem);
|
282
|
+
});
|
283
|
+
}
|
284
|
+
|
239
285
|
async hideOnboardBrandForm() {
|
240
286
|
this.onboardSheet.hide();
|
241
287
|
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class InfoPlistStringCatalogManager {
|
2
|
+
constructor(jsonData) {
|
3
|
+
this.data = jsonData;
|
4
|
+
this.localizations = {};
|
5
|
+
this.extractLocalizations();
|
6
|
+
}
|
7
|
+
|
8
|
+
extractLocalizations() {
|
9
|
+
for (const [key, details] of Object.entries(this.data.strings)) {
|
10
|
+
for (const [lang, localization] of Object.entries(details.localizations)) {
|
11
|
+
const formattedKey = `${key}.${lang}`;
|
12
|
+
this.localizations[formattedKey] = localization.stringUnit.value;
|
13
|
+
}
|
14
|
+
}
|
15
|
+
return this.localizations
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
export default InfoPlistStringCatalogManager;
|