solara 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/solara/lib/.DS_Store +0 -0
  3. data/solara/lib/core/.DS_Store +0 -0
  4. data/solara/lib/core/brands/brand_switcher.rb +58 -1
  5. data/solara/lib/core/dashboard/brand/BrandDetail.js +34 -2
  6. data/solara/lib/core/dashboard/brand/BrandDetailController.js +23 -233
  7. data/solara/lib/core/dashboard/brand/BrandDetailModel.js +13 -5
  8. data/solara/lib/core/dashboard/brand/BrandDetailView.js +16 -200
  9. data/solara/lib/core/dashboard/brand/SectionsFormManager.js +232 -0
  10. data/solara/lib/core/dashboard/brand/brand.html +187 -177
  11. data/solara/lib/core/dashboard/brand/source/BrandLocalSource.js +2 -5
  12. data/solara/lib/core/dashboard/brand/source/BrandRemoteSource.js +36 -133
  13. data/solara/lib/core/dashboard/brands/Brands.js +31 -0
  14. data/solara/lib/core/dashboard/brands/BrandsController.js +0 -5
  15. data/solara/lib/core/dashboard/brands/BrandsView.js +2 -2
  16. data/solara/lib/core/dashboard/brands/brands.html +71 -52
  17. data/solara/lib/core/dashboard/component/AliasesBottomSheet.js +6 -6
  18. data/solara/lib/core/dashboard/component/BrandOptionsBottomSheet.js +4 -4
  19. data/solara/lib/core/dashboard/component/ConfirmationDialog.js +15 -10
  20. data/solara/lib/core/dashboard/component/EditJsonSheet.js +160 -0
  21. data/solara/lib/core/dashboard/component/MessageBottomSheet.js +5 -5
  22. data/solara/lib/core/dashboard/component/OnboardBrandBottomSheet.js +5 -3
  23. data/solara/lib/core/dashboard/handler/base_handler.rb +1 -0
  24. data/solara/lib/core/dashboard/handler/edit_section_handler.rb +1 -5
  25. data/solara/lib/core/doctor/schema/brand_configurations.json +0 -8
  26. data/solara/lib/core/doctor/schema/platform/global/resources_manifest.json +30 -0
  27. data/solara/lib/core/doctor/schema/platform/json_manifest.json +57 -0
  28. data/solara/lib/core/doctor/validator/template/android_template_validation_config.yml +35 -1
  29. data/solara/lib/core/doctor/validator/template/flutter_template_validation_config.yml +30 -1
  30. data/solara/lib/core/doctor/validator/template/ios_template_validation_config.yml +35 -1
  31. data/solara/lib/core/doctor/validator/template/template_validator.rb +9 -9
  32. data/solara/lib/core/scripts/brand_config_manager.rb +1 -1
  33. data/solara/lib/core/scripts/brand_configurations_manager.rb +41 -0
  34. data/solara/lib/core/scripts/code_generator.rb +342 -118
  35. data/solara/lib/core/scripts/file_path.rb +21 -1
  36. data/solara/lib/core/scripts/gitignore_manager.rb +11 -3
  37. data/solara/lib/core/scripts/json_manifest_processor.rb +95 -0
  38. data/solara/lib/core/scripts/platform/ios/infoplist_string_catalog_manager.rb +11 -1
  39. data/solara/lib/core/scripts/resource_manifest_processor.rb +151 -0
  40. data/solara/lib/core/scripts/solara_status_manager.rb +1 -1
  41. data/solara/lib/core/scripts/theme_generator.rb +21 -242
  42. data/solara/lib/core/solara_configurator.rb +1 -1
  43. data/solara/lib/core/template/brands/global/resources_manifest.json +10 -0
  44. data/solara/lib/core/template/brands/json/Json-Manifest.md +61 -0
  45. data/solara/lib/core/template/brands/json/json_manifest.json +18 -0
  46. data/solara/lib/core/template/brands/shared/theme.json +213 -29
  47. data/solara/lib/core/template/config/android_template_config.json +50 -0
  48. data/solara/lib/core/template/config/flutter_template_config.json +35 -0
  49. data/solara/lib/core/template/config/ios_template_config.json +50 -0
  50. data/solara/lib/core/template/configurations.json +46 -0
  51. data/solara/lib/core/template/project_template_generator.rb +2 -0
  52. data/solara/lib/solara/version.rb +1 -1
  53. data/solara/lib/solara.rb +19 -0
  54. metadata +13 -4
  55. data/solara/lib/core/dashboard/component/AddFieldSheet.js +0 -175
  56. data/solara/lib/core/dashboard/handler/brand_configurations_manager.rb +0 -73
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b672162bbb4a247a016626afacc37b2deaab1dbde0c2f86e30a4ceedeb8a635d
4
- data.tar.gz: a0e53ed9ce61d791a50df3c292b1c096414903e7c573164e7553089048f289cc
3
+ metadata.gz: 714797cd507e354e49c4a1981a516f6ad3e659797ba40b6040c7e7a6f30f11aa
4
+ data.tar.gz: 3b3d4ed6c116abea9dd15c2db4b5df308320649be4381623e3c7a3c863ef0385
5
5
  SHA512:
6
- metadata.gz: a22345201f6d5756cc2a54702dc8a0db0806d4fd1fd47f9f85dfde81545368908d22408345dae944bc004c4fe3507ceef563e6044cf7a90daad5a157efb1295f
7
- data.tar.gz: be3473d1802240cf75b4f934561e22302cbf93dee710dead6c0439b474e3b7c16ca858f3b647e480e04a493622ce9b8da488135179bca97caa808feedd1b2b18
6
+ metadata.gz: b4c46c3f893d95eddbde530e7d83fe340ce36698974880073b3517779bb8e39b31813863c13f7743e821936b814e6d7f5d42337c10b3ef37a4cd6767732f5a20
7
+ data.tar.gz: 750e7851fa9584bb85b00b5f01e48ea246892914f1bbfafeb7a2b18db8e138d0da5f8fd2a2253434bed1dd6b6d9b0c6911dcaec908714e96ff69c894653490b8
data/solara/lib/.DS_Store CHANGED
Binary file
Binary file
@@ -30,6 +30,9 @@ class BrandSwitcher
30
30
  def switch
31
31
  BrandFontSwitcher.new(@brand_key).switch
32
32
 
33
+ ResourceManifestSwitcher.new(@brand_key).switch
34
+ JsonManifestSwitcher.new(@brand_key).switch
35
+
33
36
  case @platform
34
37
  when Platform::Flutter
35
38
  IOSBrandSwitcher.new(@brand_key).switch
@@ -42,6 +45,60 @@ class BrandSwitcher
42
45
  else
43
46
  raise ArgumentError, "Invalid platform: #{@platform}"
44
47
  end
48
+
49
+ end
50
+
51
+ end
52
+
53
+ class ResourceManifestSwitcher
54
+ def initialize(brand_key)
55
+ @brand_key = brand_key
56
+ end
57
+
58
+ def switch
59
+ Solara.logger.start_step("Process resource manifest: #{FilePath.resources_manifest}")
60
+ brand_resource_copier = ResourceManifestProcessor.new(@brand_key)
61
+ brand_resource_copier.copy
62
+ Solara.logger.debug("#{@brand_key} resources copied successfully according to the manifest: #{FilePath.resources_manifest}.")
63
+ Solara.logger.end_step("Process resource manifest: #{FilePath.resources_manifest}")
64
+ end
65
+
66
+ end
67
+
68
+ class JsonManifestSwitcher
69
+ def initialize(brand_key)
70
+ @brand_key = brand_key
71
+ @manifest_path = FilePath.brand_json_dir(brand_key)
72
+ end
73
+
74
+ def switch
75
+ Solara.logger.start_step("Process JSON manifest: #{@manifest_path}")
76
+
77
+
78
+ case SolaraSettingsManager.instance.platform
79
+ when Platform::Flutter
80
+ process_maifest(Language::Dart, FilePath.flutter_lib_artifacts)
81
+ process_maifest(Language::Dart, FilePath.brand_global_json_dir)
82
+ when Platform::IOS
83
+ process_maifest(Language::Swift, FilePath.ios_project_root_artifacts)
84
+ process_maifest(Language::Swift, FilePath.brand_global_json_dir)
85
+ when Platform::Android
86
+ process_maifest(Language::Kotlin, FilePath.android_project_java_artifacts )
87
+ process_maifest(Language::Kotlin, FilePath.brand_global_json_dir)
88
+ else
89
+ raise ArgumentError, "Invalid platform: #{@platform}"
90
+ end
91
+
92
+ Solara.logger.end_step("Process JSON manifest: #{@manifest_path}")
93
+ end
94
+
95
+ def process_maifest(language, output_path)
96
+ processor = JsonManifestProcessor.new(
97
+ @manifest_path,
98
+ language,
99
+ output_path
100
+ )
101
+ processor.process
45
102
  end
46
103
  end
47
104
 
@@ -225,7 +282,7 @@ class ThemeSwitcher
225
282
  def generate_theme(name, language, platform)
226
283
  Solara.logger.start_step("Generate #{name} for #{platform}")
227
284
 
228
- theme_manager = ThemeGeneratorManager.new(FilePath.brand_theme(@brand_key))
285
+ theme_manager = ThemeGenerator.new(FilePath.brand_theme(@brand_key))
229
286
  theme_manager.generate(language, FilePath.generated_config(name, platform))
230
287
 
231
288
  Solara.logger.end_step("Generate #{name} for #{platform}")
@@ -2,6 +2,37 @@ import BrandDetailModel from './BrandDetailModel.js';
2
2
  import BrandDetailView from './BrandDetailView.js';
3
3
  import BrandDetailController from './BrandDetailController.js';
4
4
 
5
+ const modeToggle = document.getElementById('modeToggle');
6
+ const body = document.body;
7
+ const icon = modeToggle.querySelector('i');
8
+
9
+ function applyMode(mode) {
10
+ if (mode === 'dark') {
11
+ body.classList.add('dark-mode');
12
+ icon.classList.remove('fa-sun');
13
+ icon.classList.add('fa-moon');
14
+ } else {
15
+ body.classList.remove('dark-mode');
16
+ icon.classList.remove('fa-moon');
17
+ icon.classList.add('fa-sun');
18
+ }
19
+ }
20
+
21
+ const savedMode = localStorage.getItem('mode');
22
+ if (savedMode) {
23
+ applyMode(savedMode);
24
+ } else {
25
+ const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
26
+ applyMode(systemPrefersDark ? 'dark' : 'light');
27
+ }
28
+
29
+ modeToggle.addEventListener('click', () => {
30
+ const currentMode = body.classList.contains('dark-mode') ? 'dark' : 'light';
31
+ const newMode = currentMode === 'dark' ? 'light' : 'dark';
32
+ applyMode(newMode);
33
+ localStorage.setItem('mode', newMode);
34
+ });
35
+
5
36
  window.onload = function () {
6
37
  document.getElementById('loadingOverlay').style.display = 'none';
7
38
  };
@@ -20,10 +51,11 @@ window.addEventListener('scroll', function () {
20
51
  }
21
52
  lastScrollTop = scrollTop;
22
53
  });
23
-
54
+
24
55
  document.addEventListener('DOMContentLoaded', async () => {
25
56
  const model = new BrandDetailModel();
26
57
  const view = new BrandDetailView(model);
27
58
  const controller = new BrandDetailController(model, view);
28
59
  await controller.initializeApp();
29
- });
60
+ });
61
+
@@ -1,15 +1,10 @@
1
1
  import {DataSource} from './BrandDetailModel.js';
2
- import InfoPlistStringCatalogManager from "./InfoPlistStringCatalogManager.js";
3
2
 
4
3
  class BrandDetailController {
5
4
  constructor(model, view) {
6
5
  this.model = model;
7
6
  this.view = view;
8
- this.onSectionChanged = this.onSectionChanged.bind(this);
9
- this.deleteField = this.deleteField.bind(this);
10
7
  this.initializeEventListeners();
11
- this.view.setOnSectionChangedHandler(this.onSectionChanged.bind(this));
12
- this.view.setOnDeleteFieldHandler(this.deleteField.bind(this));
13
8
  }
14
9
 
15
10
  async initializeApp() {
@@ -80,7 +75,7 @@ class BrandDetailController {
80
75
 
81
76
  async addNewBrand() {
82
77
  this.view.showOnboardBrandForm(async (key, name) => {
83
- const configurations = await this.model.createNewBrandConfogurations()
78
+ const configurations = await this.model.createNewBrandConfigurations()
84
79
  await this.addBrand(key, name, configurations)
85
80
  })
86
81
  }
@@ -97,10 +92,10 @@ class BrandDetailController {
97
92
  await this.onLoadSections(response.result);
98
93
  const {isCurrentBrand, contentChanged} = await this.model.fetchCurrentBrand();
99
94
 
100
- if (!isCurrentBrand) {
95
+ if (isCurrentBrand) {
96
+ this.view.setupSyncBrandButton(contentChanged ? '#ff4136' : '#4A90E2');
97
+ } else {
101
98
  this.view.showSwitchButton();
102
- } else if (contentChanged) {
103
- this.view.showApplyChangesButton();
104
99
  }
105
100
 
106
101
  await this.checkBrandHealth();
@@ -128,7 +123,12 @@ class BrandDetailController {
128
123
  window.location.href = `../brands/brands.html?source=${this.model.source}`;
129
124
  });
130
125
 
131
- document.getElementById('applyChangesButton').addEventListener('click', () => this.switchToBrand());
126
+ document.getElementById('syncBrandButton').addEventListener(
127
+ 'click',
128
+ async () => {
129
+ await this.switchToBrand()
130
+ await this.view.toast("Synced successfully")
131
+ });
132
132
  document.getElementById('switchButton').addEventListener('click', () => this.switchToBrand());
133
133
 
134
134
  this.view.exportBrandBtn.addEventListener('click', () => this.exportBrand());
@@ -141,188 +141,37 @@ class BrandDetailController {
141
141
 
142
142
  const sectionItems = configuraationsResult.configurations
143
143
 
144
- for (let i = 0; i < sectionItems.length; i++) {
145
- const sectionData = sectionItems[i];
146
-
147
- if (sectionData.key === 'theme.json') {
148
- this.createThemeSections(sectionData)
149
- } else if (sectionData.key === 'InfoPlist.xcstrings') {
150
- this.createSection(
151
- sectionData.key,
152
- sectionData,
153
- new InfoPlistStringCatalogManager(sectionData.content).extractLocalizations(),
154
- sectionData.name,
155
- sectionData.inputType)
156
- } else {
157
- this.createSection(sectionData.key, sectionData, sectionData.content, sectionData.name, sectionData.inputType)
158
- }
159
- }
144
+ this.view.sectionsFormManager.display(
145
+ sectionItems,
146
+ (section, container) => {
147
+ this.onSectionChanged(section, container)
148
+ })
149
+
160
150
  } catch (error) {
161
151
  console.error('Error loading configurations:', error);
162
152
  alert(error.message);
163
153
  }
164
154
  }
165
155
 
166
- createThemeSections(sectionData) {
167
- this.createSection(`${sectionData.key}_colors`,
168
- sectionData,
169
- sectionData.content.colors,
170
- 'Theme Colors',
171
- 'color',
172
- 'colors')
173
- this.createSection(`${sectionData.key}_typography`,
174
- sectionData,
175
- sectionData.content.typography,
176
- 'Theme Typography',
177
- 'text',
178
- 'typography')
179
- this.createSection(`${sectionData.key}_spacing`,
180
- sectionData,
181
- sectionData.content.spacing,
182
- 'Theme Spacing', 'text',
183
- 'spacing')
184
- this.createSection(
185
- `${sectionData.key}_borderRadius`,
186
- sectionData,
187
- sectionData.content.borderRadius,
188
- 'Theme Border Radius',
189
- 'text',
190
- 'borderRadius')
191
- this.createSection(
192
- `${sectionData.key}_elevation`,
193
- sectionData,
194
- sectionData.content.elevation,
195
- 'Theme Elevation',
196
- 'text',
197
- 'elevation')
198
- }
199
-
200
- createSection(id, sectionData, content, sectionName, inputType, propertiesGroupName = null) {
201
- const sectionElement = this.view.createSection(sectionData.key, sectionName, inputType);
202
- sectionElement.id = id;
203
- sectionElement.dataset.propertiesGroupName = propertiesGroupName
204
-
205
- this.view.sectionsContainer.appendChild(sectionElement);
206
-
207
- this.view.populateJsonFields(sectionData, sectionElement, content, inputType);
156
+ async onSectionChanged(section, container) {
157
+ if (this.model.isRemote()) return
208
158
 
209
- const addButton = document.createElement('button');
210
- addButton.textContent = 'Add Field';
211
- addButton.className = 'add-field-btn';
212
- addButton.onclick = () => this.addNewField(sectionData, sectionElement, inputType);
213
- sectionElement.appendChild(addButton);
214
- }
215
-
216
- async onSectionChanged(sectionItem, sectionElement) {
217
159
  try {
218
- const configuration = await this.getSectionData(sectionElement.dataset.key)
219
- await this.model.saveSection(sectionItem, configuration);
220
- this.view.showApplyChangesButton();
160
+ await this.model.saveSection(container.dataset.key, section.content);
221
161
  await this.checkBrandHealth();
162
+ await this.switchToBrand(true)
222
163
  } catch (error) {
223
164
  console.error('Error saving section:', error);
224
165
  alert(error.message);
225
166
  }
226
167
  }
227
168
 
228
- collectJsonData(container) {
229
- const data = {};
230
- const level = container.dataset.level
231
-
232
- const jsonObjects = container.querySelectorAll(`.json-object-${level}`);
233
- jsonObjects.forEach(jsonObject => {
234
- const jsonObjectLabel = jsonObject.querySelector('label').textContent;
235
- data[jsonObjectLabel] = this.collectJsonData(jsonObject);
236
-
237
- });
238
-
239
- const group = container.querySelectorAll(`.json-array-${level}`);
240
- group.forEach(arrayItem => {
241
- const label = arrayItem.querySelector('label').textContent;
242
- const items = arrayItem.querySelectorAll(`.json-array-item-${level}`);
243
- const indexed = arrayItem.querySelectorAll(`.json-array-item-indexed-${level}`).length !== 0;
244
-
245
- data[label] = Array.from(items).map((item, index) => {
246
- const values = this.collectJsonData(item)
247
- if (indexed) {
248
- return values[index]
249
- }
250
- return values;
251
- });
252
- });
253
-
254
- const result = this.collectJsonFields(container, level);
255
-
256
- Object.keys(data).forEach(key => {
257
- result[key] = data[key];
258
- });
259
- return result
260
- }
261
-
262
- collectJsonFields(container, level) {
263
- const result = {};
264
-
265
- const inputFields = container.querySelectorAll(`.json-field-${level}`);
266
- inputFields.forEach(inputField => {
267
- const values = this.getInputFieldsData(inputField);
268
- Object.keys(values).forEach(key => {
269
- result[key] = values[key];
270
- });
271
- })
272
- return result
273
- }
274
-
275
- getInputFieldsData(container) {
276
- const data = {};
277
-
278
- const inputs = container.querySelectorAll('input');
279
- inputs.forEach(input => {
280
- if (input.type === 'checkbox') {
281
- data[input.id] = input.checked;
282
- } else {
283
- let value = input.value;
284
- if (input.type === 'color') {
285
- value = `#${value.substring(1).toUpperCase()}`;
286
- } else if (!isNaN(value) && value.trim() !== '') {
287
- // Convert to number if it's a valid number string
288
- value = parseFloat(value);
289
- }
290
- data[input.id] = value;
291
- }
292
- });
293
-
294
- return data;
295
- }
296
-
297
- addNewField(sectionItem, sectionElement, inputType) {
298
- this.view.showAddFieldForm(sectionItem, sectionElement, inputType);
299
- }
300
-
301
- deleteField(sectionItem, fieldContainer) {
302
- this.view.showConfirmationDialog(
303
- 'Are you sure you want to delete this item?',
304
- () => {
305
- const sectionElement = fieldContainer.closest('.section');
306
- fieldContainer.remove();
307
- this.onSectionChanged(sectionItem, sectionElement);
308
- }
309
- );
310
- }
311
-
312
- getArrayValue(container) {
313
- const arrayItems = container.querySelectorAll('.array-item-input');
314
- return Array.from(arrayItems).map(item => item.value);
315
- }
316
-
317
- async switchToBrand() {
169
+ async switchToBrand(silentError = false) {
318
170
  try {
319
171
  await this.model.switchToBrand();
320
- const applyChangesButton = document.getElementById('applyChangesButton');
321
- applyChangesButton.style.display = 'none';
322
- location.reload();
323
172
  } catch (error) {
324
173
  console.error('Error switching to brand:', error);
325
- alert(error.message);
174
+ if (!silentError) alert(error.message);
326
175
  }
327
176
  }
328
177
 
@@ -350,72 +199,13 @@ class BrandDetailController {
350
199
  }
351
200
  }
352
201
 
353
- async getSectionData(sectionKey) {
354
- try {
355
- const container = this.view.sectionsContainer;
356
-
357
- const sectionElements = Array.from(container.querySelectorAll('.section'))
358
- .filter(element => element.dataset.key === sectionKey);
359
-
360
- if (sectionElements.length === 1) {
361
- return this.collectJsonData(sectionElements[0])
362
- }
363
-
364
- const configurations = sectionElements.map(sectionElement => {
365
- const propertiesGroupName = sectionElement.dataset.propertiesGroupName;
366
- const config = this.collectJsonData(sectionElement);
367
-
368
- if (propertiesGroupName !== "null") {
369
- return {[propertiesGroupName]: config};
370
- } else {
371
- return config;
372
- }
373
- });
374
-
375
- return configurations.reduce((acc, config) => {
376
- const key = Object.keys(config)[0]; // Get the key from the configuration item
377
- acc[key] = config[key]; // Assign the value to the dynamic object
378
- return acc;
379
- }, {});
380
-
381
- } catch (error) {
382
- console.error('Error downloading brand:', error);
383
- alert(error.message);
384
- }
385
- }
386
-
387
202
  async exportBrand() {
388
203
  try {
389
- const sectionsContainer = this.view.sectionsContainer;
204
+ const result = this.view.sectionsFormManager.data();
390
205
 
391
206
  const brandKey = this.view.sectionsContainer.dataset.brandKey;
392
207
  const brandName = this.view.sectionsContainer.dataset.brandName;
393
208
 
394
- const sectionElements = Array.from(sectionsContainer.querySelectorAll('.section'));
395
-
396
- const uniqueSections = new Map();
397
-
398
- // The theme section has been divided into multiple categories (e.g., colors, typography).
399
- // In the getSectionData function, we merge these sections. To prevent duplication when
400
- // processing the sections, we will ensure that each section key is processed only once.
401
- await Promise.all(sectionElements.map(async sectionElement => {
402
- const key = sectionElement.dataset.key;
403
- // Check if the key already exists in the map
404
- if (!uniqueSections.has(key)) {
405
- const configurations = await this.getSectionData(key);
406
- uniqueSections.set(
407
- key, {
408
- key: key,
409
- name: sectionElement.dataset.name,
410
- inputType: sectionElement.dataset.inputType,
411
- content: configurations
412
- });
413
- }
414
- }));
415
-
416
- // Convert the map values to an array
417
- const result = Array.from(uniqueSections.values());
418
-
419
209
  this.model.exportBrand(brandKey, brandName, result);
420
210
 
421
211
  } catch (error) {
@@ -17,6 +17,14 @@ class BrandDetailModel {
17
17
  this.source = sourceFromUrl === DataSource.LOCAL ? DataSource.LOCAL : DataSource.REMOTE;
18
18
  }
19
19
 
20
+ isLocal() {
21
+ return this.source === DataSource.LOCAL
22
+ }
23
+
24
+ isRemote() {
25
+ return this.source === DataSource.REMOTE
26
+ }
27
+
20
28
  getQueryFromUrl(name) {
21
29
  return this.localSource.getQueryFromUrl(name);
22
30
  }
@@ -29,10 +37,10 @@ class BrandDetailModel {
29
37
  return await this.localSource.fetchCurrentBrand(this.brandKey);
30
38
  }
31
39
 
32
- async saveSection(sectionItem, configuration) {
40
+ async saveSection(key, configuration) {
33
41
  switch (this.source) {
34
42
  case DataSource.LOCAL:
35
- return await this.localSource.saveSection(sectionItem, configuration, this.brandKey);
43
+ return await this.localSource.saveSection(key, configuration, this.brandKey);
36
44
  case DataSource.REMOTE:
37
45
  // Saving is not supported remotely. Instead, user can export the brand.
38
46
  return
@@ -48,7 +56,7 @@ class BrandDetailModel {
48
56
  async checkBrandHealth() {
49
57
  switch (this.source) {
50
58
  case DataSource.LOCAL:
51
- return await this.localSource.checkBrandHealth(this.brandKey);
59
+ return await this.localSource.checkBrandHealth(this.brandKey);
52
60
  case DataSource.REMOTE:
53
61
  // Checking health is not supported remotely yet.
54
62
  return
@@ -57,8 +65,8 @@ class BrandDetailModel {
57
65
  }
58
66
  }
59
67
 
60
- async createNewBrandConfogurations() {
61
- return await this.remoteSource.createNewBrandConfogurations();
68
+ async createNewBrandConfigurations() {
69
+ return await this.remoteSource.createNewBrandConfigurations();
62
70
  }
63
71
 
64
72
  async createBrandConfigurationsFromDirectory(dirHandle) {