-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
582 additions
and
543 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
// BrandController.js | ||
class BrandController { | ||
constructor(model, view) { | ||
this.model = model; | ||
this.view = view; | ||
this.onSectionChanged = this.onSectionChanged.bind(this); | ||
this.deleteField = this.deleteField.bind(this); | ||
this.initializeEventListeners(); | ||
this.view.setOnSectionChangedHandler(this.onSectionChanged); | ||
this.view.setOnDeleteFieldHandler(this.deleteField); | ||
} | ||
|
||
async initializeApp() { | ||
this.model.brandKey = this.model.getQueryFromUrl('brand_key'); | ||
this.model.source = this.model.getQueryFromUrl('source') || 'remote'; | ||
|
||
try { | ||
const { sectionItems, brandName } = await this.model.fetchSections(); | ||
this.view.updateAppNameTitle(brandName); | ||
await this.loadSections(sectionItems); | ||
|
||
const { isCurrentBrand, contentChanged } = await this.model.fetchCurrentBrand(); | ||
if (!isCurrentBrand) { | ||
this.view.showSwitchButton(); | ||
} else if (contentChanged) { | ||
this.view.showApplyChangesButton(); | ||
} | ||
|
||
await this.checkBrandHealth(); | ||
} 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}`; | ||
}); | ||
|
||
document.getElementById('applyChangesButton').addEventListener('click', () => this.switchToBrand()); | ||
document.getElementById('switchButton').addEventListener('click', () => this.switchToBrand()); | ||
} | ||
|
||
async loadSections(sectionItems) { | ||
try { | ||
for (let i = 0; i < sectionItems.length; i++) { | ||
const sectionInfo = sectionItems[i]; | ||
console.log('Processing section:', i, sectionInfo); | ||
|
||
const sectionElement = this.view.createSection(sectionInfo.name, sectionInfo.type, sectionInfo.subtitle); | ||
this.view.sectionsContainer.appendChild(sectionElement); | ||
|
||
console.log('Section element created:', sectionElement); | ||
|
||
this.view.populateSection(sectionInfo, sectionElement, sectionInfo.content, sectionInfo.name, sectionInfo.type, sectionInfo.inputType); | ||
|
||
const addButton = document.createElement('button'); | ||
addButton.textContent = 'Add Field'; | ||
addButton.className = 'add-field-btn'; | ||
addButton.onclick = () => this.addNewField(sectionInfo, sectionElement, sectionInfo.name, sectionInfo.type, sectionInfo.inputType); | ||
sectionElement.appendChild(addButton); | ||
} | ||
} catch (error) { | ||
console.error('Error loading sections:', error); | ||
alert(error.message); | ||
} | ||
} | ||
|
||
async onSectionChanged(sectionItem, sectionElement, sectionName, sectionType) { | ||
console.log('onSectionChanged called with:', this); | ||
try { | ||
const configuration = this.getSectionConfiguration(sectionElement); | ||
await this.model.saveSection(sectionItem, configuration); | ||
this.view.showApplyChangesButton(); | ||
await this.checkBrandHealth(); | ||
} catch (error) { | ||
console.error('Error saving section:', error); | ||
alert(error.message); | ||
} | ||
} | ||
|
||
getSectionConfiguration(sectionElement) { | ||
const configuration = {}; | ||
const inputs = sectionElement.querySelectorAll('input:not(.array-item-input)'); | ||
inputs.forEach(input => { | ||
const keys = input.id.split('.'); | ||
let current = configuration; | ||
for (let i = 0; i < keys.length - 1; i++) { | ||
if (!current[keys[i]]) { | ||
current[keys[i]] = {}; | ||
} | ||
current = current[keys[i]]; | ||
} | ||
const lastKey = keys[keys.length - 1]; | ||
|
||
if (input.classList.contains('array-input')) { | ||
const arrayItemsContainer = input.closest('.input-wrapper').querySelector('.array-items-container'); | ||
current[lastKey] = this.getArrayValue(arrayItemsContainer); | ||
} else { | ||
let value = input.value; | ||
if (input.type === 'color') { | ||
value = `#${value.substring(1).toUpperCase()}`; | ||
} | ||
current[lastKey] = value; | ||
} | ||
}); | ||
return configuration; | ||
} | ||
|
||
addNewField(sectionItem, sectionElement, sectionName, sectionType, inputType) { | ||
this.view.showAddFieldForm(sectionItem, sectionElement, sectionName, sectionType, inputType); | ||
} | ||
|
||
deleteField(sectionItem, fieldContainer, sectionName, sectionType) { | ||
this.view.showConfirmationDialog( | ||
'Are you sure you want to delete this item?', | ||
() => { | ||
const sectionElement = fieldContainer.closest('.section'); | ||
fieldContainer.remove(); | ||
this.onSectionChanged(sectionItem, sectionElement, sectionName, sectionType); | ||
} | ||
); | ||
} | ||
|
||
getArrayValue(container) { | ||
const arrayItems = container.querySelectorAll('.array-item-input'); | ||
return Array.from(arrayItems).map(item => item.value); | ||
} | ||
|
||
async switchToBrand() { | ||
try { | ||
await this.model.switchToBrand(); | ||
const applyChangesButton = document.getElementById('applyChangesButton'); | ||
applyChangesButton.style.display = 'none'; | ||
location.reload(); | ||
} catch (error) { | ||
console.error('Error switching to brand:', error); | ||
alert(error.message); | ||
} | ||
} | ||
|
||
async checkBrandHealth() { | ||
try { | ||
const result = await this.model.checkBrandHealth(); | ||
const errorButton = document.getElementById('error-button'); | ||
|
||
if (!result.passed) { | ||
errorButton.style.display = "flex"; | ||
const errors = result.errors | ||
.map((error, index) => `${index + 1}. ${error}`) | ||
.join('\n'); | ||
this.view.updateErrorCount(result.errors.length); | ||
|
||
errorButton.onclick = () => { | ||
this.view.showMessage(`Health check for all brands completed with errors: \n\n${errors}`); | ||
}; | ||
} else { | ||
errorButton.style.display = "none"; | ||
} | ||
} catch (error) { | ||
console.error('Error checking brand health:', error); | ||
alert(error.message); | ||
} | ||
} | ||
} | ||
|
||
export default BrandController; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// BrandModel.js | ||
class BrandModel { | ||
constructor() { | ||
this.sectionItems = []; | ||
this.brandName = ''; | ||
this.brandKey = ''; | ||
this.isCurrentBrand = false; | ||
this.source = 'remote'; | ||
this.savingInProgress = false; | ||
} | ||
|
||
getQueryFromUrl(name) { | ||
const urlParams = new URLSearchParams(window.location.search); | ||
return urlParams.get(name); | ||
} | ||
|
||
async fetchSections() { | ||
try { | ||
if (!this.brandKey) { | ||
throw new Error('No brand_key provided in URL'); | ||
} | ||
|
||
const url = `/sections?brand_key=${encodeURIComponent(this.brandKey)}`; | ||
console.log('Fetching sections from:', url); | ||
|
||
const response = await fetch(url); | ||
const result = await response.json(); | ||
if (!response.ok) { | ||
throw new Error(result.error); | ||
} | ||
this.sectionItems = result.result.sections; | ||
this.brandName = result.result.brand_name; | ||
return { sectionItems: this.sectionItems, brandName: this.brandName }; | ||
} catch (error) { | ||
console.error('Error fetching config sections:', error); | ||
throw error; | ||
} | ||
} | ||
|
||
async fetchCurrentBrand() { | ||
try { | ||
const response = await fetch('/brand/current'); | ||
let result = await response.json(); | ||
if (!response.ok) { | ||
throw new Error(result.error); | ||
} | ||
this.isCurrentBrand = result.key === this.brandKey; | ||
return { isCurrentBrand: this.isCurrentBrand, contentChanged: result.content_changed }; | ||
} catch (error) { | ||
console.error('Error fetching current brand:', error); | ||
throw error; | ||
} | ||
} | ||
|
||
async saveSection(sectionItem, configuration) { | ||
if (this.savingInProgress) return; | ||
this.savingInProgress = true; | ||
|
||
const dataToSend = { | ||
brand_key: this.brandKey, | ||
key: sectionItem.key, | ||
data: configuration | ||
}; | ||
|
||
try { | ||
const response = await fetch(`/section/edit`, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json' | ||
}, | ||
body: JSON.stringify(dataToSend) | ||
}); | ||
|
||
const result = await response.json(); | ||
|
||
if (!response.ok) { | ||
throw new Error(result.error); | ||
} | ||
|
||
console.log(`${sectionItem.name} configuration saved successfully!`); | ||
return true; | ||
} catch (error) { | ||
console.error('Error saving configuration:', error); | ||
throw error; | ||
} finally { | ||
this.savingInProgress = false; | ||
} | ||
} | ||
|
||
async switchToBrand() { | ||
try { | ||
const response = await fetch('/switch', { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({brand_key: this.brandKey}), | ||
}); | ||
|
||
const result = await response.json(); | ||
|
||
if (!response.ok) { | ||
throw new Error(result.error); | ||
} | ||
|
||
console.log('Switch to brand result:', result); | ||
return true; | ||
} catch (error) { | ||
console.error('Error switching to brand:', error); | ||
throw error; | ||
} | ||
} | ||
|
||
async checkBrandHealth() { | ||
try { | ||
const response = await fetch(`/brand/doctor?brand_key=${encodeURIComponent(this.brandKey)}`); | ||
const result = await response.json(); | ||
|
||
if (!response.ok) { | ||
throw new Error(result.error); | ||
} | ||
|
||
return result.result; | ||
} catch (error) { | ||
console.error('Error calling doctor API:', error); | ||
throw error; | ||
} | ||
} | ||
} | ||
|
||
export default BrandModel; |
Oops, something went wrong.