Skip to content

Commit

Permalink
Merge pull request #1310 from data-team-uhn/CARDS-1877_more
Browse files Browse the repository at this point in the history
CARDS-1877: Reset to initial settings in administration pages is broken
  • Loading branch information
sdumitriu authored Feb 7, 2023
2 parents 4cb936f + e147236 commit 8e2f7cb
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// under the License.
//

import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import withStyles from '@mui/styles/withStyles';

Expand Down Expand Up @@ -46,6 +46,10 @@ let MarkdownText = (props) => {
cmd.push(commands.divider);
cmd.push(infoButton);

useEffect(() => {
setValue(props.value || '');
}, [props.value]);

return (
<MDEditor className={classes.markdown} value={value} height={height} preview={preview} onChange={value => {setValue(value); onChange && onChange(value);}} extraCommands={cmd}/>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,20 +65,17 @@ function DowntimeWarningConfiguration() {

useEffect(() => {
// Determine if the end date is earlier than the start date
setDateRangeIsInvalid(fromDate && toDate && new Date(toDate).valueOf() < new Date(fromDate).valueOf());
setDateRangeIsInvalid(!!fromDate && !!toDate && new Date(toDate).valueOf() < new Date(fromDate).valueOf());
}, [fromDate, toDate]);

useEffect(() => {
setHasChanges(true);
}, [enabled, fromDate, toDate]);

return (
<AdminConfigScreen
title="Downtime Warning Banner Settings"
configPath="/apps/cards/config/DowntimeWarning"
configTemplate={{enabled: false, fromDate: "", toDate: ""}}
onConfigFetched={readDowntimeWarningSettings}
hasChanges={hasChanges}
configError={dateRangeIsInvalid ? "Invalid date range" : undefined}
configError={!!dateRangeIsInvalid ? "Invalid date range" : undefined}
buildConfigData={buildConfigData}
onConfigSaved={() => setHasChanges(false)}
>
Expand All @@ -88,7 +85,7 @@ function DowntimeWarningConfiguration() {
control={
<Checkbox
checked={enabled}
onChange={ event => setEnabled(event.target.checked) }
onChange={ event => { setEnabled(event.target.checked); setHasChanges(true); } }
name="enabled"
/>
}
Expand All @@ -102,7 +99,7 @@ function DowntimeWarningConfiguration() {
type="datetime-local"
InputLabelProps={{ shrink: true }}
className={classes.textField}
onChange={(event) => setFromDate(event.target.value) }
onChange={(event) => { setFromDate(event.target.value); setHasChanges(true); } }
onBlur={(event) => setFromDate(event.target.value) }
placeholder={dateFormat.toLowerCase()}
value={fromDate || ""}
Expand All @@ -115,7 +112,7 @@ function DowntimeWarningConfiguration() {
type="datetime-local"
InputLabelProps={{ shrink: true }}
className={classes.textField}
onChange={(event) => setToDate(event.target.value) }
onChange={(event) => { setToDate(event.target.value); setHasChanges(true); } }
onBlur={(event) => setToDate(event.target.value) }
placeholder={dateFormat.toLowerCase()}
value={toDate || ""}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ const useStyles = makeStyles(theme => ({
* </AdminConfigScreen>
*
* @param {string} title - the title of the administration screen, required
* @param {string} configPath - the path of the configuration node; will be used for loading and saving the data
* @param {string} configPath - the path of the configuration node; will be used for loading and saving the data, required
* @param {object} configTemplate - what an empty config would look like; should list all the possible fields with empty values, required
* @param {function} onConfigFetched - handler to pass the loaded configuration json to the parent component
* @param {boolean} hasChanges - how the parent component notifies that the user changed the form values
* @param {string} configError - how the parent component notifies that there's a data sanity issue
Expand All @@ -97,7 +98,7 @@ const useStyles = makeStyles(theme => ({
*/

function AdminConfigScreen(props) {
const { title, configPath, onConfigFetched, hasChanges, configError, buildConfigData, onConfigSaved, children } = props;
const { title, configPath, configTemplate, onConfigFetched, hasChanges, configError, buildConfigData, onConfigSaved, children } = props;
const [ config, setConfig ] = useState();
const [ configIsInitial, setConfigIsInitial ] = useState(true);
const [ error, setError ] = useState();
Expand All @@ -115,8 +116,9 @@ function AdminConfigScreen(props) {
fetchWithReLogin(globalContext, `${configPath}.json`)
.then((response) => response.ok ? response.json() : Promise.reject(response))
.then(json => {
setConfig(json);
onConfigFetched?.(json);
let conf = Object.assign({}, configTemplate, json);
setConfig(conf);
onConfigFetched?.(conf);
})
.catch(err => {
setConfig(null);
Expand All @@ -138,7 +140,20 @@ function AdminConfigScreen(props) {

// Build formData object.
let formData = new URLSearchParams();
buildConfigData?.(formData);
if (event) {
// If the submit is user-initiated, grab values form the form
buildConfigData?.(formData);
// Use the config template to Fill in any missing values
for (let key of Object.keys(configTemplate)) {
formData.get(key) == null && Array.of(configTemplate[key]).flat().forEach(v => formData.append(key, v));
}
} else {
// Otherwise just save the existing config
// Use the template keys to avoid attempts to save reserved properties like "jcr:...", "sling:...", "@..."
for (let key of Object.keys(configTemplate)) {
Array.of(config[key]).flat().forEach(v => formData.append(key, v));
}
}

fetchWithReLogin(globalContext, configPath,
{
Expand Down Expand Up @@ -189,7 +204,7 @@ function AdminConfigScreen(props) {
variant="contained"
color="primary"
size="small"
disabled={configError || !hasChanges}
disabled={!!configError || !hasChanges}
>
Save
</Button>
Expand Down Expand Up @@ -234,7 +249,8 @@ function AdminConfigScreen(props) {

AdminConfigScreen.propTypes = {
title: PropTypes.string.isRequired,
configPath: PropTypes.string,
configPath: PropTypes.string.isRequired,
configTemplate: PropTypes.object.isRequired,
onConfigFetched: PropTypes.func,
hasChanges: PropTypes.bool,
configError: PropTypes.string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,11 @@ function QuickSearchConfiguration(props) {
setAllowedResourceTypes(types);
}

useEffect(() => {
setHasChanges(true);
}, [limit, showTotalRows]);

return (
<AdminConfigScreen
title="Quick Search Settings"
configPath="/apps/cards/config/QuickSearch"
configTemplate={{limit: "", showTotalRows: false, allowedResourceTypes: [""]}}
onConfigFetched={readQuickSearchSettings}
hasChanges={hasChanges}
buildConfigData={buildConfigData}
Expand All @@ -88,7 +85,7 @@ function QuickSearchConfiguration(props) {
type="number"
label="Limit"
value={limit}
onChange={ event => setLimit(event.target.value) }
onChange={ event => { setLimit(event.target.value); setHasChanges(true); } }
style={{'width' : '250px'}}
helperText="How many results should be displayed"
/>
Expand All @@ -98,7 +95,7 @@ function QuickSearchConfiguration(props) {
control={
<Checkbox
checked={showTotalRows}
onChange={ event => setShowTotalRows(event.target.checked) }
onChange={ event => { setShowTotalRows(event.target.checked); setHasChanges(true); } }
name="showTotalRows"
/>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,6 @@ function DashboardSettingsConfiguration() {
type: "boolean"
}];

useEffect(() => {
setHasChanges(true);
}, [enableTimeTabs, eventsLabel, eventTimeLabel]);

let buildConfigData = (formData) => {
formData.append('enableTimeTabs', enableTimeTabs);
formData.append('eventsLabel', eventsLabel);
Expand All @@ -72,6 +68,7 @@ function DashboardSettingsConfiguration() {
<AdminConfigScreen
title="Clinic dashboard"
configPath={"/Survey/DashboardSettings"}
configTemplate={fields.reduce((t, k) => ({...t, [k.key] : ""}), {})}
onConfigFetched={readDashboardSettings}
hasChanges={hasChanges}
buildConfigData={buildConfigData}
Expand All @@ -90,14 +87,14 @@ function DashboardSettingsConfiguration() {
type="text"
label={camelCaseToWords(field.key)}
value={field.value}
onChange={(event) => { field.setter(event.target.value); }}
onChange={(event) => { field.setter(event.target.value); setHasChanges(true); }}
/>
:
<FormControlLabel
control={
<Checkbox
checked={field.value}
onChange={ event => field.setter(event.target.checked) }
onChange={ event => { field.setter(event.target.checked); setHasChanges(true); } }
name={field.key}
/>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,17 @@ function PatientAccessConfiguration() {
}
}

useEffect(() => {
setHasChanges(true);
}, [patientAccessConfig]);

let renderConfigCheckbox = (key, valueOverride) => (
<ListItem>
<FormControlLabel control={
<Checkbox
name={key}
checked={valueOverride || patientAccessConfig?.[key] || DEFAULT_PATIENT_ACCESS_CONFIG[key]}
disabled={valueOverride}
onChange={event => setPatientAccessConfig({...patientAccessConfig, [key]: valueOverride || event.target.checked})}
onChange={event => {
setPatientAccessConfig({...patientAccessConfig, [key]: valueOverride || event.target.checked});
setHasChanges(true);
}}
/>}
label={labels[key]}
/>
Expand All @@ -91,8 +90,8 @@ function PatientAccessConfiguration() {
<TextField
variant="standard"
type="number"
onChange={event => setPatientAccessConfig({...patientAccessConfig, [key]: event.target.value})}
onBlur={event => setPatientAccessConfig({...patientAccessConfig, [key]: event.target.value})}
onChange={event => { setPatientAccessConfig({...patientAccessConfig, [key]: event.target.value}); setHasChanges(true); }}
onBlur={event => { setPatientAccessConfig({...patientAccessConfig, [key]: event.target.value}); setHasChanges(true); }}
placeholder={DEFAULT_PATIENT_ACCESS_CONFIG[key] || ""}
value={patientAccessConfig?.[key]}
InputProps={{
Expand All @@ -107,6 +106,7 @@ function PatientAccessConfiguration() {
<AdminConfigScreen
title="Patient Access"
configPath={PATIENT_ACCESS_CONFIG_PATH}
configTemplate={Object.keys(DEFAULT_PATIENT_ACCESS_CONFIG).reduce((t, k) => ({...t, [k] : ""}), {})}
onConfigFetched={setPatientAccessConfig}
hasChanges={hasChanges}
buildConfigData={buildConfigData}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,11 @@ function SurveyInstructionsConfiguration() {

let getUnsetValue = (key) => (key?.startsWith("enable") ? false : "");

useEffect(() => {
setHasChanges(true);
}, [surveyInstructions]);

return (
<AdminConfigScreen
title="Patient Portal Survey Instructions"
configPath={SURVEY_INSTRUCTIONS_PATH}
configTemplate={Object.values(labels).flat().reduce((t, k) => ({...t, [k]: getUnsetValue(k)}), {})}
onConfigFetched={setSurveyInstructions}
hasChanges={hasChanges}
buildConfigData={buildConfigData}
Expand All @@ -90,14 +87,20 @@ function SurveyInstructionsConfiguration() {
{ key == "welcomeMessage" ?
<WelcomeMessageConfiguration
welcomeMessage={surveyInstructions?.[key]}
onChange={(text) => { setSurveyInstructions({...surveyInstructions, [key]: text}); }}
onChange={(text) => {
setSurveyInstructions({...surveyInstructions, [key]: text});
setHasChanges(true);
}}
/>
:
key.startsWith("enable") ?
<FormControlLabel control={
<Checkbox
checked={!!(surveyInstructions?.[key])}
onChange={event => setSurveyInstructions({...surveyInstructions, [key]: !!event.target.checked})}
onChange={event => {
setSurveyInstructions({...surveyInstructions, [key]: !!event.target.checked});
setHasChanges(true);
}}
/>}
label={camelCaseToWords(key)}
/>
Expand All @@ -113,7 +116,10 @@ function SurveyInstructionsConfiguration() {
label={camelCaseToWords(key)}
value={surveyInstructions?.[key] || ""}
placeholder={DEFAULT_INSTRUCTIONS[key] || ""}
onChange={(event) => { setSurveyInstructions({...surveyInstructions, [key]: event.target.value}); }}
onChange={(event) => {
setSurveyInstructions({...surveyInstructions, [key]: event.target.value});
setHasChanges(true);
}}
fullWidth
/>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,11 @@ function ToUConfiguration() {
formData.append('text', text);
}

useEffect(() => {
setHasChanges(true);
}, [title, version, text, acceptanceRequired]);

return (
<AdminConfigScreen
title="Patient Portal Terms of Use"
configPath="/Survey/TermsOfUse"
configTemplate={{"acceptanceRequired" : false, "title" : "", "version" : "", "text" : ""}}
onConfigFetched={readToUData}
hasChanges={hasChanges}
buildConfigData={buildConfigData}
Expand All @@ -84,7 +81,7 @@ function ToUConfiguration() {
type="text"
label="Title"
value={title}
onChange={(event) => { setTitle(event.target.value); }}
onChange={(event) => { setTitle(event.target.value); setHasChanges(true); }}
/>
</ListItem>
<ListItem key="version">
Expand All @@ -96,7 +93,7 @@ function ToUConfiguration() {
type="version"
label="Version"
value={version}
onChange={(event) => { setVersion(event.target.value); }}
onChange={(event) => { setVersion(event.target.value); setHasChanges(true); }}
style={{'width' : '250px'}}
/>
</ListItem>
Expand All @@ -105,15 +102,15 @@ function ToUConfiguration() {
<MarkdownText
value={text}
height={350}
onChange={value => { setText(value); }}
onChange={value => { setText(value); setHasChanges(true); }}
/>
</ListItem>
<ListItem key="acceptanceRequired">
<FormControlLabel
control={
<Checkbox
checked={acceptanceRequired}
onChange={(event) => { setAcceptanceRequired(event.target.checked); }}
onChange={(event) => { setAcceptanceRequired(event.target.checked); setHasChanges(true); }}
name="acceptanceRequired"
/>
}
Expand Down

0 comments on commit 8e2f7cb

Please sign in to comment.