Skip to content

Commit

Permalink
Add syncing between advanced and simple editor
Browse files Browse the repository at this point in the history
  • Loading branch information
Dagonite committed Oct 4, 2024
1 parent a4afabd commit 6534934
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 91 deletions.
211 changes: 121 additions & 90 deletions src/ConfigSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';

// Material UI components
import { Box, Button, Typography, Tabs, Tab, useTheme, Grid, Tooltip, IconButton } from '@mui/material';
import { Box, Button, Typography, Tabs, Tab, useTheme, Grid, Input, Tooltip, IconButton } from '@mui/material';
import { Info, UploadFile, Edit } from '@mui/icons-material';

// Monaco components
Expand All @@ -20,7 +20,7 @@ interface TabPanelProps {
const TabPanel: React.FC<TabPanelProps> = ({ children, value, index, ...other }): JSX.Element => {
return (
<div role="tabpanel" hidden={value !== index} id={`tabpanel-${index}`} aria-labelledby={`tab-${index}`} {...other}>
{value === index && <Box sx={{ p: 3, height: 'calc(85vh - 48px - 48px - 24px)' }}>{children}</Box>}
{value === index && <Box sx={{ p: 3 }}>{children}</Box>}
</div>
);
};
Expand All @@ -34,14 +34,9 @@ const ConfigSettings: React.FC = () => {
const theme = useTheme();
const { instrumentName } = useParams<{ instrumentName: string }>();
const [reductionStatus, setReductionStatus] = useState<'ON' | 'OFF'>('ON');
const [jsonContent, setJsonContent] = useState(`{
"instrumentName": "MARI",
"settings": {
"algorithm": "levmar",
"fit": "gaussian",
"color_map": "veridis"
}
}`);
const [jsonContent, setJsonContent] = useState<string>('{}'); // Default JSON content
const [formFields, setFormFields] = useState<{ [key: string]: string }>({}); // Dynamic form fields
const [enabledStatus, setEnabledStatus] = useState<boolean>(true); // Separate state for "enabled"
const [tabValue, setTabValue] = useState(0);

// Fetch the current specification and set the reduction status
Expand All @@ -60,7 +55,17 @@ const ConfigSettings: React.FC = () => {
}

const data = await response.json();
setReductionStatus(data.enabled ? 'ON' : 'OFF');

// Exclude the "enabled" key from the JSON
const { enabled, ...filteredData } = data;

// Set the reduction status button on/off based on the "enabled" field
setReductionStatus(enabled ? 'ON' : 'OFF');
setEnabledStatus(enabled);

const specJson = JSON.stringify(filteredData, null, 2);
setJsonContent(specJson);
syncFormWithJson(specJson);
} catch (error) {
console.error('Error fetching specification:', error);
}
Expand All @@ -71,78 +76,90 @@ const ConfigSettings: React.FC = () => {
}
}, [instrumentName]);

const toggleReductionStatus = async (): Promise<void> => {
const newStatus = reductionStatus === 'ON' ? 'OFF' : 'ON';
const statusValue = newStatus === 'ON' ? 'true' : 'false';
const handleTabChange = (event: React.SyntheticEvent, newValue: number): void => {
setTabValue(newValue);
};

// Sync form fields when JSON content is edited
const syncFormWithJson = (jsonString: string): void => {
try {
const response = await fetch(`${fiaApiUrl}/instrument/${instrumentName}/status?status=${statusValue}`, {
method: 'PUT',
headers: {
Authorization: `Bearer ${localStorage.getItem('scigateway:token')}`,
},
});

if (!response.ok) {
throw new Error('Failed to update reduction status');
}
const json = JSON.parse(jsonString);
// Exclude the "enabled" field from syncing -- gets added later when settings applied
const { enabled, ...otherFields } = json;
setFormFields(otherFields);
} catch (error) {
console.error('Error parsing JSON:', error);
}
};

setReductionStatus(newStatus);
// Sync JSON when form fields are edited
const syncJsonWithForm = (updatedFields: { [key: string]: string }): void => {
try {
const json = JSON.parse(jsonContent);
Object.keys(updatedFields).forEach((key) => {
json[key] = updatedFields[key];
});
setJsonContent(JSON.stringify(json, null, 2));
} catch (error) {
console.error('Error updating reduction status:', error);
console.error('Error syncing JSON with form:', error);
}
};

const handleTabChange = (event: React.SyntheticEvent, newValue: number): void => {
setTabValue(newValue);
const handleFormInputChange = (key: string, value: string): void => {
const updatedFields = { ...formFields, [key]: value };
setFormFields(updatedFields);
syncJsonWithForm(updatedFields);
};

const handleMonacoChange = (value: string | undefined): void => {
const updatedJson = value || '{}';
setJsonContent(updatedJson);
syncFormWithJson(updatedJson);
};

const toggleEnabledStatus = (): void => {
setEnabledStatus(!enabledStatus);
setReductionStatus(enabledStatus ? 'OFF' : 'ON');
};

const handleApplySettings = async (): Promise<void> => {
try {
// Parse the current JSON content
const currentJson = JSON.parse(jsonContent);

// Add the "enabled" field based on the current state of the toggle button
const updatedJson = {
...currentJson,
enabled: enabledStatus ? true : false,
};

// Log for now
const finalJsonContent = JSON.stringify(updatedJson, null, 2);
console.log('JSON:', finalJsonContent);
} catch (error) {
console.error('Error preparing settings:', error);
}
};

return (
<Box sx={{ width: '100%', height: '85vh', overflow: 'hidden', color: theme.palette.text.primary }}>
<Box sx={{ width: '100%', height: '85vh', color: theme.palette.text.primary, overflowY: 'auto' }}>
<Box sx={{ m: 2, backgroundColor: theme.palette.background.default }}>
{/* Title */}
<Typography variant="h4" gutterBottom>
{instrumentName} config settings
</Typography>

{/* Reduction status */}
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', mb: 2 }}>
<Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
<Typography variant="body1" sx={{ lineHeight: '1.5', mr: 1 }}>
Toggle reduction status:
</Typography>
<Button
variant="contained"
onClick={toggleReductionStatus}
sx={{
backgroundColor: reductionStatus === 'ON' ? 'green' : theme.palette.error.main,
color: 'white',
'&:hover': {
backgroundColor: reductionStatus === 'ON' ? 'darkgreen' : theme.palette.error.dark,
},
}}
>
{reductionStatus}
</Button>

{/* Tooltip */}
<Tooltip title="Click to toggle the reduction process on or off">
<IconButton sx={{ ml: 1 }}>
<Info sx={{ color: theme.palette.text.secondary }} />
</IconButton>
</Tooltip>
</Box>

{/* Upload file button */}
<Box sx={{ mb: 2 }}>
<Button variant="contained" startIcon={<UploadFile />}>
<Button variant="contained" disabled startIcon={<UploadFile />}>
Upload file...
</Button>
</Box>

{/* Change script button */}
<Box>
<Button variant="contained" startIcon={<Edit />}>
<Button variant="contained" disabled startIcon={<Edit />}>
Change script...
</Button>
</Box>
Expand Down Expand Up @@ -186,58 +203,72 @@ const ConfigSettings: React.FC = () => {

{/* Simple panel */}
<TabPanel value={tabValue} index={0}>
<Grid container direction="column" spacing={1}>
{/* Algorithm */}
{/* Fixed enabled field with toggle button */}
<Grid container direction="column" spacing={2}>
<Grid item>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Typography variant="body1" sx={{ width: '150px', mb: 0 }}>
Algorithm:
enabled:
</Typography>
<input type="text" value="levmar" style={{ margin: 0, width: '140px' }} />
<Button
variant="contained"
onClick={toggleEnabledStatus}
sx={{
backgroundColor: enabledStatus ? 'green' : theme.palette.error.main,
color: 'white',
'&:hover': {
backgroundColor: enabledStatus ? 'darkgreen' : theme.palette.error.dark,
},
}}
>
{enabledStatus ? 'ON' : 'OFF'}
</Button>
{/* Tooltip */}
<Tooltip title="Click to toggle the reduction process on or off">
<IconButton sx={{ ml: 1 }}>
<Info sx={{ color: theme.palette.text.secondary }} />
</IconButton>
</Tooltip>
</Box>
</Grid>

{/* Fit */}
<Grid item>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Typography variant="body1" sx={{ width: '150px', mb: 0 }}>
Fit:
</Typography>
<input type="text" value="gaussian" style={{ margin: 0, width: '140px' }} />
</Box>
</Grid>

{/* Color_map */}
<Grid item>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Typography variant="body1" sx={{ width: '150px', mb: 0 }}>
Color_map:
</Typography>
<input type="text" value="viridis" style={{ margin: 0, width: '140px' }} />
</Box>
</Grid>

{/* Apply settings button */}
<Grid item xs={12}>
<Button variant="contained" sx={{ mt: 3 }}>
Apply settings
</Button>
</Grid>
{/* Dynamically generated form fields */}
{Object.keys(formFields).map((key) => (
<Grid item key={key}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Typography variant="body1" sx={{ width: '150px', mb: 0 }}>
{key}:
</Typography>
<input
value={formFields[key]}
onChange={(e) => handleFormInputChange(key, e.target.value)}
style={{ margin: 0, height: '20px', width: '160px' }}
/>
</Box>
</Grid>
))}
</Grid>
</TabPanel>

{/* Advanced panel */}
<TabPanel value={tabValue} index={1}>
<Box sx={{ height: 'calc(85vh - 48px - 48px - 24px)' }}>
<Box sx={{ height: '35vh' }}>
<MonacoEditor
height="100%"
defaultLanguage="json"
value={jsonContent}
theme={theme.palette.mode === 'dark' ? 'vs-dark' : 'vs-light'}
onChange={(value) => setJsonContent(value || '')}
onChange={handleMonacoChange}
/>
</Box>
</TabPanel>

{/* Apply settings button */}
<Box sx={{ display: 'flex', justifyContent: 'center', mt: 3, mb: 3 }}>
<Button variant="contained" onClick={handleApplySettings}>
Apply settings
</Button>
</Box>
</Box>
);
};
Expand Down
2 changes: 1 addition & 1 deletion src/Jobs/JobsBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ const JobsBase: React.FC<JobsBaseProps> = ({

const openConfigSettings = (): void => {
const url = `/fia/${selectedInstrument}/config-settings`;
const features = 'width=900,height=800,resizable=no';
const features = 'width=1028,height=900,resizable=no';
window.open(url, 'ConfigSettingsWindow', features);
};

Expand Down

0 comments on commit 6534934

Please sign in to comment.