Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix theme save #802

Merged
merged 4 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added frontend/CommitHash.js
Empty file.
273 changes: 142 additions & 131 deletions frontend/components/Admin/Theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@ import Loading from '../Reusable/Loading';
import { addError } from '../../redux/actions';
import { useDispatch, useSelector } from 'react-redux';
import { useState, useEffect } from 'react';
import Loader from 'react-loader-spinner';
import { isValidURI } from '../Viewing/Shell';
const { publicRuntimeConfig } = getConfig();

export default function Theme() {
const dispatch = useDispatch();
const [loading, setLoading] = useState(true); // Initialize loading state to true
const [loading, setLoading] = useState(true);
const [theme, setTheme] = useState({});
const [instanceName, setInstanceName] = useState(''); // Default to empty
const [frontPageText, setFrontPageText] = useState(''); // Default to empty
const [instanceName, setInstanceName] = useState('');
const [frontPageText, setFrontPageText] = useState('');
const [altHome, setAltHome] = useState('');
const [baseColor, setBaseColor] = useState('');
const [logoFile, setLogoFile] = useState(null);
Expand All @@ -23,30 +22,39 @@ export default function Theme() {
const token = useSelector(state => state.user.token);

useEffect(() => {
// Fetch theme data from localStorage or remote if needed
fetchThemeData();
}, []);

const fetchThemeData = () => {
const fetchThemeData = async () => {
setLoading(true);
const themeData = JSON.parse(localStorage.getItem('theme')) || {};
setTheme(themeData);
setLoading(false);
};

useEffect(() => {
if (theme) {
setInstanceName(theme.instanceName || '');
setFrontPageText(theme.frontPageText || '');
setAltHome(theme.altHome || '');
try {
const response = await axios.get(`${publicRuntimeConfig.backend}/admin/theme`, {
headers: {
Accept: 'application/json',
'X-authorization': token
}
});
const themeData = response.data;
updateThemeState(themeData);
localStorage.setItem('theme', JSON.stringify(themeData));
} catch (error) {
console.error('Error fetching theme:', error);
const cachedTheme = JSON.parse(localStorage.getItem('theme')) || {};
updateThemeState(cachedTheme);
} finally {
setLoading(false);
}
}, [theme]);
};

useEffect(() => {
if (theme && theme.themeParameters && theme.themeParameters[0]) {
setBaseColor(theme.themeParameters[0].value || '');
}
}, [theme]);
const updateThemeState = (themeData) => {
setTheme(themeData);
setInstanceName(themeData.instanceName || '');
setFrontPageText(themeData.frontPageText || '');
setAltHome(themeData.altHome || '');
setBaseColor(themeData.themeParameters?.[0]?.value || '');
setShowModuleInteractions(themeData.showModuleInteractions ?? true);
setRemovePublicEnabled(themeData.removePublicEnabled ?? true);
};

const handleShowModuleInteractionsChange = (event) => {
setShowModuleInteractions(event.target.checked);
Expand All @@ -61,142 +69,145 @@ export default function Theme() {
};

const handleSave = async () => {
const url = `${publicRuntimeConfig.backend}/admin/theme`;
const headers = {
Accept: 'text/plain',
'X-authorization': token
};

if (altHome !== '' && !isValidURI(altHome)) {
alert('Alternate Home Page must be empty or contain a valid URL.');
return; // Prevent form submission
return;
}

setLoading(true);
const formData = new FormData();
formData.append('instanceName', instanceName);
formData.append('frontPageText', frontPageText);
formData.append('altHome', altHome);
formData.append('baseColor', baseColor);
formData.append('removePublicEnabled', removePublicEnabled);
formData.append('showModuleInteractions', showModuleInteractions);
// if (logoFile) {
// formData.append('logo', logoFile);
// }
if (logoFile) {
formData.append('logo', logoFile);
}

try {
const response = await fetch(url, { method: 'POST', headers, body: formData });
console.log(response);
const data = await response.text();
const response = await fetch(`${publicRuntimeConfig.backend}/admin/theme`, {
method: 'POST',
headers: {
Accept: 'text/plain',
'X-authorization': token
},
body: formData
});

if (response.ok) {
console.log(localStorage.getItem('theme'));

console.log(data);

if (data.requestBody) {
// Get the current theme from local storage
let currentTheme = JSON.parse(localStorage.getItem('theme')) || {};

// Update only the values that match and are different
Object.keys(data.requestBody).forEach(key => {
if (currentTheme[key] !== undefined && currentTheme[key] !== data.requestBody[key]) {
currentTheme[key] = data.requestBody[key];
}
});

// Store the updated theme in local storage
localStorage.setItem('theme', JSON.stringify(currentTheme));
console.log(localStorage);
}
// Create updated theme object
const updatedTheme = {
...theme,
instanceName,
frontPageText,
altHome,
themeParameters: [{ value: baseColor }],
showModuleInteractions,
removePublicEnabled
};

// Update localStorage
localStorage.setItem('theme', JSON.stringify(updatedTheme));

// Update component state
updateThemeState(updatedTheme);

alert('Theme saved successfully!');
window.location.reload();
} else {
alert("Error saving theme");
throw new Error('Failed to save theme');
}
} catch (error) {
alert("Error saving theme");
console.error('Error saving theme:', error);
alert('Error saving theme');
} finally {
setLoading(false);
}
};

if (loading) return <Loading />;

return (
<div>
<div>Logo</div>
<input type="file" onChange={(e) => setLogoFile(e.target.files[0])} />
<div>Instance Name</div>
<input
type="text"
value={instanceName}
onChange={(e) => setInstanceName(e.target.value)}
style={{ width: '400px' }}
/>
<div>Front Page Description</div>
<textarea
value={frontPageText}
onChange={(e) => setFrontPageText(e.target.value)}
rows={10} // Number of rows
cols={100} // Number of columns
/>
<div>Alternate Home Page</div>
<input
type="text"
value={altHome}
onChange={(e) => setAltHome(e.target.value)}
style={{ width: '600px' }}
/>

<div>Color Settings</div>
<table className={styles.table}>
<tbody>
<tr>
<td>Base Color</td>
<td>
<input
type="text"
value={baseColor}
onChange={handleBaseColorChange}
/>
</td>
</tr>
</tbody>
</table>
<div>
<div className="p-4">
<div className="mb-4">
<div className="font-medium mb-2">Logo</div>
<input
type="file"
onChange={(e) => setLogoFile(e.target.files[0])}
className="mb-4"
/>

<div className="font-medium mb-2">Instance Name</div>
<input
type="checkbox"
checked={showModuleInteractions}
onChange={handleShowModuleInteractionsChange}
type="text"
value={instanceName}
onChange={(e) => setInstanceName(e.target.value)}
/>
Show Module Interactions
</div>
<div>

<div className="font-medium mb-2 mt-4">Front Page Description</div>
<textarea
value={frontPageText}
onChange={(e) => setFrontPageText(e.target.value)}
rows={10}
cols={100}
/>

<div className="font-medium mb-2 mt-4">Alternate Home Page</div>
<input
type="checkbox"
checked={removePublicEnabled}
onChange={handleRemovePublicEnabledChange}
type="text"
value={altHome}
onChange={(e) => setAltHome(e.target.value)}
/>
Remove Public Enabled

<div className="font-medium mb-2 mt-4">Color Settings</div>
<table className={styles.table}>
<tbody>
<tr>
<td>Base Color</td>
<td>
<input
type="text"
value={baseColor}
onChange={handleBaseColorChange}
/>
</td>
</tr>
</tbody>
</table>

<div className="mt-4">
<label className="flex items-center space-x-2">
<input
type="checkbox"
checked={showModuleInteractions}
onChange={handleShowModuleInteractionsChange}
className="form-checkbox"
/>
<span>Show Module Interactions</span>
</label>
</div>

<div className="mt-2">
<label className="flex items-center space-x-2">
<input
type="checkbox"
checked={removePublicEnabled}
onChange={handleRemovePublicEnabledChange}
className="form-checkbox"
/>
<span>Remove Public Enabled</span>
</label>
</div>

<button
onClick={handleSave}
className="mt-6 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors"
>
Save
</button>
</div>
<button onClick={handleSave}>Save</button>
</div>
);
}

const fetcher = (url, dispatch) =>
axios
.get(url, {
headers: {
Accept: 'application/json'
}
})
.then(response => response.data)
.catch(error => {
if (error.message === 'Network Error') {
// Change the error message or handle it differently
console.error('Unable to connect to the server. Please check your network connection.');
dispatch(addError(error));
} else {
// Handle other errors
error.customMessage = 'Request failed for GET /admin/theme31278931739137131';
error.fullUrl = url;
dispatch(addError(error));
}

});
}
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "git rev-parse HEAD > ./public/commitHash.txt; next dev -p 3333",
"dev": "next dev -p 3333",
"devNextGen": "git rev-parse HEAD > ./public/commitHash.txt; NODE_OPTIONS=--openssl-legacy-provider next dev -p 3333",
"build": "git rev-parse HEAD > ./public/commitHash.txt; next build",
"buildNextGen": "git rev-parse HEAD > ./public/commitHash.txt; NODE_OPTIONS=--openssl-legacy-provider next build",
Expand Down
Loading