Skip to content

Commit

Permalink
Solara
Browse files Browse the repository at this point in the history
  • Loading branch information
ideyaa committed Sep 7, 2024
1 parent 1f08ebb commit 221777f
Show file tree
Hide file tree
Showing 5 changed files with 510 additions and 504 deletions.
153 changes: 153 additions & 0 deletions solara/lib/core/dashboard/brands/BrandsController.js
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;
136 changes: 136 additions & 0 deletions solara/lib/core/dashboard/brands/BrandsModel.js
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;
Loading

0 comments on commit 221777f

Please sign in to comment.