-
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
510 additions
and
504 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,153 @@ | ||
class BrandsController { | ||
constructor(model, view) { | ||
this.model = model; | ||
this.view = view; | ||
this.view.setOnSwitch(this.switchToBrand.bind(this)); | ||
} | ||
|
||
async init() { | ||
await this.model.fetchCurrentBrand(); | ||
await this.renderBrands(); | ||
this.checkBrandsHealth(); | ||
this.attachEventListeners(); | ||
} | ||
|
||
async renderBrands() { | ||
const brands = await this.model.fetchBrands(); | ||
this.view.renderBrands(brands, this.model.currentBrand); | ||
} | ||
|
||
attachEventListeners() { | ||
document.querySelector('.onboard-brand-button').addEventListener('click', () => this.showOnboardBrandForm()); | ||
document.getElementById('brandSearch').addEventListener('input', (e) => this.filterBrands(e.target.value)); | ||
document.getElementById('closeAliases').addEventListener('click', () => this.view.hideAliasesBottomSheet()); | ||
|
||
// Attach event listeners for bottom sheet options | ||
const bottomSheet = document.getElementById('bottomSheet'); | ||
document.getElementById('cloneOption').onclick = (event) => this.handleCloneOption(event); | ||
document.getElementById('offboardOption').onclick = (event) => this.handleOffboardOption(event); | ||
document.getElementById('doctorOption').onclick = (event) => this.handleDoctorOption(event); | ||
document.getElementById('aliasesOption').onclick = (event) => this.handleAliasesOption(event); | ||
document.getElementById('settingsOption').onclick = (event) => this.handleSettingsOption(event); | ||
|
||
// Add more event listeners as needed | ||
} | ||
|
||
showOnboardBrandForm() { | ||
this.view.showOnboardBrandForm(); | ||
const form = document.getElementById('onboardBrandForm'); | ||
form.onsubmit = (event) => this.handleOnboardBrandSubmit(event); | ||
} | ||
|
||
async handleOnboardBrandSubmit(event) { | ||
event.preventDefault(); | ||
const brandName = document.getElementById('brandName').value; | ||
const brandKey = document.getElementById('brandKey').value; | ||
|
||
const brandKeyRegex = /^[A-Za-z][A-Za-z0-9_-]*$/; | ||
|
||
if (!brandKeyRegex.test(brandKey)) { | ||
alert('Brand key must start with a letter and contain no spaces. Only letters, numbers, underscores, and hyphens are allowed.'); | ||
return; | ||
} | ||
|
||
try { | ||
await this.model.onboardBrand(brandName, brandKey); | ||
this.view.hideOnboardBrandForm(); | ||
location.reload(); | ||
} catch (error) { | ||
console.error('Error during submission:', error); | ||
alert(error); | ||
} | ||
} | ||
|
||
filterBrands(searchTerm) { | ||
const filteredBrands = this.model.filterBrands(searchTerm); | ||
this.view.renderBrands(filteredBrands, this.model.currentBrand); | ||
} | ||
|
||
async checkBrandsHealth() { | ||
const result = await this.model.runDoctor(""); | ||
const errorButton = document.getElementById('error-button'); | ||
|
||
if (!result.passed) { | ||
this.view.showErrorButton(); | ||
this.view.updateErrorCount(result.errors.length); | ||
|
||
errorButton.addEventListener('click', () => { | ||
const errors = result.errors | ||
.map((error, index) => `${index + 1}. ${error}`) | ||
.join('\n'); | ||
this.view.showMessage(`Health check for all brands completed with errors: \n\n${errors}`); | ||
}); | ||
} else { | ||
this.view.hideErrorButton(); | ||
} | ||
} | ||
|
||
handleCloneOption(event) { | ||
event.stopPropagation(); | ||
this.view.hideBrandOptionsBottomSheet(); | ||
this.showOnboardBrandForm(); | ||
} | ||
|
||
handleOffboardOption(event) { | ||
event.stopPropagation(); | ||
this.view.hideBrandOptionsBottomSheet(); | ||
|
||
const brandKey = this.view.bottomSheet.dataset.brandKey; | ||
const brandName = this.view.bottomSheet.dataset.brandName; | ||
this.view.showConfirmationDialog(`Are you sure you need to offboard ${brandKey} (${brandName}) and delete all its configurations?`); | ||
document.getElementById('confirmButton').onclick = async () => { | ||
await this.model.offboardBrand(brandKey); | ||
location.reload(); | ||
}; | ||
} | ||
|
||
async handleDoctorOption(event) { | ||
event.stopPropagation(); | ||
this.view.hideBrandOptionsBottomSheet(); | ||
|
||
const brandKey = this.view.bottomSheet.dataset.brandKey; | ||
const result = await this.model.runDoctor(brandKey); | ||
if (!result.passed) { | ||
const errors = result.errors | ||
.map((error, index) => `${index + 1}. ${error}`) | ||
.join('\n'); | ||
this.view.showMessage(`Health check for ${brandKey} completed with errors:\n${errors}`); | ||
} else { | ||
this.view.showMessage(`Health check for ${brandKey}. All systems operational.`); | ||
} | ||
} | ||
|
||
async handleAliasesOption(event) { | ||
event.stopPropagation(); | ||
this.view.hideBrandOptionsBottomSheet(); | ||
|
||
const brandKey = this.view.bottomSheet.dataset.brandKey; | ||
const aliases = await this.model.fetchAliases(brandKey); | ||
if (aliases) { | ||
this.view.showAliasesBottomSheet(aliases, brandKey); | ||
} | ||
} | ||
|
||
handleSettingsOption(event) { | ||
event.stopPropagation(); | ||
this.view.hideBrandOptionsBottomSheet(); | ||
|
||
const brandKey = this.view.bottomSheet.dataset.brandKey; | ||
window.location.href = this.view.brandUrl(brandKey); | ||
} | ||
|
||
async switchToBrand(brandKey) { | ||
try { | ||
await this.model.switchToBrand(brandKey); | ||
location.reload(); | ||
} catch (error) { | ||
console.error('Error switching to brand:', error); | ||
alert(error.message); | ||
} | ||
} | ||
} | ||
|
||
export default BrandsController; |
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,136 @@ | ||
class BrandsModel { | ||
constructor() { | ||
this.allBrands = []; | ||
this.currentBrand = null; | ||
this.source = this.getQueryFromUrl('source') || 'remote'; | ||
} | ||
|
||
getQueryFromUrl(name) { | ||
const urlParams = new URLSearchParams(window.location.search); | ||
return urlParams.get(name); | ||
} | ||
|
||
async fetchCurrentBrand() { | ||
try { | ||
const response = await fetch('/brand/current'); | ||
let result = await response.json(); | ||
if (!response.ok) { | ||
throw new Error(result.error); | ||
} | ||
this.currentBrand = result; | ||
return result; | ||
} catch (error) { | ||
console.error('Error fetching current brand:', error); | ||
return null; | ||
} | ||
} | ||
|
||
async fetchBrands() { | ||
try { | ||
const response = await fetch('/brands.json'); | ||
const result = await response.json(); | ||
if (!response.ok) { | ||
throw new Error(result.error); | ||
} | ||
this.allBrands = result.sort((a, b) => a.key.localeCompare(b.key)); | ||
return this.allBrands; | ||
} catch (error) { | ||
console.error('Error fetching brands:', error); | ||
throw error; | ||
} | ||
} | ||
|
||
async fetchAliases(brand) { | ||
try { | ||
const response = await fetch(`/brand/aliases?brand_key=${brand.key}`); | ||
let result = await response.json(); | ||
if (!response.ok) { | ||
throw new Error(result.error); | ||
} | ||
return result; | ||
} catch (error) { | ||
console.error('Error fetching aliases:', error); | ||
return null; | ||
} | ||
} | ||
|
||
async switchToBrand(brandKey) { | ||
try { | ||
const response = await fetch('/switch', { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({brand_key: brandKey}), | ||
}); | ||
const result = await response.json(); | ||
if (!response.ok) { | ||
throw new Error(result.error); | ||
} | ||
return result; | ||
} catch (error) { | ||
console.error('Error switching to brand:', error); | ||
throw error; | ||
} | ||
} | ||
|
||
async onboardBrand(brandName, brandKey, cloneBrandKey = null) { | ||
try { | ||
const response = await fetch('/brand/onboard', { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({brand_name: brandName, brand_key: brandKey, clone_brand_key: cloneBrandKey}), | ||
}); | ||
const result = await response.json(); | ||
if (!response.ok) { | ||
throw new Error(result.error); | ||
} | ||
return result; | ||
} catch (error) { | ||
console.error('Error onboarding brand:', error); | ||
throw error; | ||
} | ||
} | ||
|
||
async offboardBrand(brandKey) { | ||
try { | ||
const response = await fetch(`/brand/offboard?brand_key=${encodeURIComponent(brandKey)}`, { | ||
method: 'GET', | ||
}); | ||
const result = await response.json(); | ||
if (!response.ok) { | ||
throw new Error(result.error); | ||
} | ||
return result; | ||
} catch (error) { | ||
console.error('Error offboarding brand:', error); | ||
throw error; | ||
} | ||
} | ||
|
||
async runDoctor(brandKey) { | ||
try { | ||
const response = await fetch(`/brand/doctor?brand_key=${encodeURIComponent(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; | ||
} | ||
} | ||
|
||
filterBrands(searchTerm) { | ||
return this.allBrands.filter(brand => | ||
brand.name.toLowerCase().includes(searchTerm.toLowerCase()) || | ||
brand.key.toLowerCase().includes(searchTerm.toLowerCase()) | ||
); | ||
} | ||
|
||
} | ||
|
||
export default BrandsModel; |
Oops, something went wrong.