diff --git a/solara/lib/core/dashboard/brand/BrandController.js b/solara/lib/core/dashboard/brand/BrandController.js index 773a949..0514250 100644 --- a/solara/lib/core/dashboard/brand/BrandController.js +++ b/solara/lib/core/dashboard/brand/BrandController.js @@ -1,4 +1,5 @@ -// BrandController.js +import {DataSource} from './BrandModel.js'; + class BrandController { constructor(model, view) { this.model = model; @@ -6,16 +7,30 @@ class BrandController { this.onSectionChanged = this.onSectionChanged.bind(this); this.deleteField = this.deleteField.bind(this); this.initializeEventListeners(); - this.view.setOnSectionChangedHandler(this.onSectionChanged); - this.view.setOnDeleteFieldHandler(this.deleteField); + this.view.setOnSectionChangedHandler(this.onSectionChanged.bind(this)); + this.view.setOnSelectBrandFolder(this.onLoadSections.bind(this)); + this.view.setOnDeleteFieldHandler(this.deleteField.bind(this)); } async initializeApp() { - try { - const {sectionItems, brandName} = await this.model.fetchSections(); - this.view.updateAppNameTitle(brandName); - await this.loadSections(sectionItems); + switch (this.model.source) { + case DataSource.LOCAL: + return await this.initLoal(); + case DataSource.REMOTE: + return await this.initRemote(); + default: + throw new Error('Unknown data source'); + } + } + + async initRemote() { + this.view.initializeApp() + } + async initLoal() { + try { + const sections = await this.model.fetchSections(); + await this.onLoadSections(sections); const {isCurrentBrand, contentChanged} = await this.model.fetchCurrentBrand(); if (!isCurrentBrand) { @@ -31,6 +46,21 @@ class BrandController { } } + async onLoadSections(sections) { + try { + const brandName = sections.brandName + const sectionItems = sections.sectionItems + console.log(brandName) + console.log(sectionItems) + console.log(this.view); + this.view.updateAppNameTitle(brandName); + await this.loadSections(sectionItems); + } catch (error) { + console.error('Error initializing app:', error); + alert(error.message); + } + } + initializeEventListeners() { document.getElementById('allBrandsButton').addEventListener('click', () => { window.location.href = `../brands/brands.html?source=${this.model.source}`; diff --git a/solara/lib/core/dashboard/brand/BrandModel.js b/solara/lib/core/dashboard/brand/BrandModel.js index fa8ea3b..5dfbb73 100644 --- a/solara/lib/core/dashboard/brand/BrandModel.js +++ b/solara/lib/core/dashboard/brand/BrandModel.js @@ -1,7 +1,7 @@ import BrandLocalSource from './source/BrandLocalSource.js'; import BrandRemoteSource from './source/BrandRemoteSource.js'; -const DataSource = { +export const DataSource = { LOCAL: 'local', REMOTE: 'remote', }; @@ -77,4 +77,4 @@ class BrandModel { } } -export default BrandModel; \ No newline at end of file +export default BrandModel; diff --git a/solara/lib/core/dashboard/brand/BrandView.js b/solara/lib/core/dashboard/brand/BrandView.js index 58df4ac..2916e96 100644 --- a/solara/lib/core/dashboard/brand/BrandView.js +++ b/solara/lib/core/dashboard/brand/BrandView.js @@ -1,11 +1,96 @@ -// BrandView.js +import {DataSource} from './BrandModel.js'; + class BrandView { - constructor() { + constructor(model) { + this.model = model; this.sectionsContainer = document.getElementById('sections'); this.addFieldSheet = document.getElementById('addFieldSheet'); this.overlay = document.getElementById('overlay'); this.confirmationDialog = document.getElementById('confirmationDialog'); this.messageBottomSheet = document.getElementById('messageBottomSheet'); + this.selectFolderBtn = document.getElementById('selectFolder'); + } + + async initializeApp() { + switch (this.model.source) { + case DataSource.LOCAL: + return await this.initLoal(); + case DataSource.REMOTE: + return await this.initRemote(); + default: + throw new Error('Unknown data source'); + } + } + + async initRemote() { + this.selectFolderBtn.style.display = 'block'; + this.selectFolderBtn.addEventListener('click', async () => { + try { + const dirHandle = await window.showDirectoryPicker(); + const configList = await this.processFolder(dirHandle); + const json = JSON.stringify(configList, null, 2); + console.log(json, this); + const sections = {sectionItems: configList, brandName: dirHandle.name}; + this.onSelectBrandFolder(sections) + } catch (error) { + console.error('Error:', error); + } + }); + } + + async processFolder(dirHandle) { + const configList = []; + const expectedFiles = [ + {key: 'theme', name: 'Theme Configuration', input_type: 'color', filename: 'theme.json'}, + {key: 'brand_config', name: 'Brand Configuration', input_type: 'text', filename: 'brand_config.json'}, + { + key: 'android_config', + name: 'Android Platform Configuration', + input_type: 'text', + filename: 'android_config.json' + }, + {key: 'android_signing', name: 'Android Signing', input_type: 'text', filename: 'android_signing.json'}, + {key: 'ios_config', name: 'iOS Platform Configuration', input_type: 'text', filename: 'ios_config.json'}, + {key: 'ios_signing', name: 'iOS Signing', input_type: 'text', filename: 'ios_signing.json'} + ]; + + for (const file of expectedFiles) { + try { + const fileContent = await this.findAndReadFile(dirHandle, file.filename); + if (fileContent) { + configList.push({ + key: file.key, + name: file.name, + inputType: file.input_type, + content: JSON.parse(fileContent) + }); + } + } catch (error) { + console.warn(`File not found or invalid JSON: ${file.filename}`); + } + } + + return configList; + } + + async findAndReadFile(dirHandle, filename) { + const queue = [dirHandle]; + while (queue.length > 0) { + const currentHandle = queue.shift(); + for await (const entry of currentHandle.values()) { + if (entry.kind === 'file' && entry.name === filename) { + const file = await entry.getFile(); + return await file.text(); + } else if (entry.kind === 'directory') { + queue.push(entry); + } + } + } + return null; + } + + async initLoal() { + } updateAppNameTitle(brandName) { @@ -265,6 +350,10 @@ class BrandView { this.onSectionChanged = handler; } + setOnSelectBrandFolder(handler) { + this.onSelectBrandFolder = handler; + } + setOnDeleteFieldHandler(handler) { this.onDeleteField = handler; } diff --git a/solara/lib/core/dashboard/brand/brand.html b/solara/lib/core/dashboard/brand/brand.html index 9624794..d8d87ca 100644 --- a/solara/lib/core/dashboard/brand/brand.html +++ b/solara/lib/core/dashboard/brand/brand.html @@ -530,6 +530,9 @@ .close-message:hover { background-color: #0056b3; /* Darker shade on hover */ } + .select-brand-folder { + display: none; + } @@ -554,6 +557,7 @@

+
diff --git a/solara/lib/core/dashboard/brand/brand.js b/solara/lib/core/dashboard/brand/brand.js index dd20958..9cc8ad9 100644 --- a/solara/lib/core/dashboard/brand/brand.js +++ b/solara/lib/core/dashboard/brand/brand.js @@ -3,9 +3,9 @@ import BrandModel from './BrandModel.js'; import BrandView from './BrandView.js'; import BrandController from './BrandController.js'; -document.addEventListener('DOMContentLoaded', () => { +document.addEventListener('DOMContentLoaded', async () => { const model = new BrandModel(); - const view = new BrandView(); + const view = new BrandView(model); const controller = new BrandController(model, view); - controller.initializeApp(); + await controller.initializeApp(); }); \ No newline at end of file diff --git a/solara/lib/core/dashboard/brand/source/BrandRemoteSource.js b/solara/lib/core/dashboard/brand/source/BrandRemoteSource.js index ce431ce..9f64360 100644 --- a/solara/lib/core/dashboard/brand/source/BrandRemoteSource.js +++ b/solara/lib/core/dashboard/brand/source/BrandRemoteSource.js @@ -2,9 +2,8 @@ class BrandRemoteSource { constructor() { } - // Keep functions for future implementation async fetchSections(brandKey) { - // Empty for now + } async fetchCurrentBrand(brandKey) {