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

SKCAN-85 feat: implement changes to the autosave #118

Merged
merged 3 commits into from
May 4, 2023
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
1 change: 1 addition & 0 deletions frontend/src/Pages/SentenceDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ const SentencesDetails = () => {
disabled={disabled}
format="small"
setter={setSentence}
enableAutoSave={true}
/>
</Grid>

Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/DistillationTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const DistillationTab = ({ statement, setStatement, refreshStatement, disabled }
statement_id: statement.id,
knowledge_statement: statement.knowledge_statement,
}}
enableAutoSave={true}
uiFields={[
"sex_id",
"apinatomy_model",
Expand Down
53 changes: 48 additions & 5 deletions frontend/src/components/Forms/FormBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ export const FormBase = (props: any) => {
templates,
submitButtonProps,
className = false,
showErrorList
showErrorList,
submitOnChangeFields = [],
submitOnBlurFields = []
} = props;
const [localData, setLocalData] = useState<any>(data);
const [isSaving, setIsSaving] = useState<boolean>(false);
Expand All @@ -40,6 +42,8 @@ export const FormBase = (props: any) => {
const [customSchema, setCustomSchema] = useState<any>(schema);
const [customUiSchema, setCustomUiSchema] = useState<any>(uiSchema);

const timer = useRef<any>(null)

const submitButtonRef = useRef<any>(null);
const removeProp = (obj: any, prop: string) => {
const { [prop]: removedProp, ...newObj } = obj;
Expand Down Expand Up @@ -68,6 +72,27 @@ export const FormBase = (props: any) => {
}
}, [data]);

const startTimer = () => timer.current = setTimeout(()=>{
if(enableAutoSave){
onSave()
}
},EDIT_DEBOUNCE)

const stopTimer = () =>{
clearTimeout(timer.current)
}

const resetTimer = () =>{
stopTimer()
startTimer()
}


useEffect(() => {
return () => stopTimer()
}, [])


const onError = (errors: any) => {
log("errors");
log(errors);
Expand Down Expand Up @@ -105,19 +130,35 @@ export const FormBase = (props: any) => {
});
};

const handleUpdate = async (event: IChangeEvent) => {
const handleUpdate = async (event: IChangeEvent, id: any) => {
const formData = { ...event.formData, ...extraData };
if(submitOnBlurFields.some((field:string)=> id.includes(field))){
resetTimer()
}
if(submitOnChangeFields.some((field:string)=> id.includes(field))){
return onSave()
}
setLocalData(formData);
if (formIsValid && !formIsValid(formData)) {
setIsSubmitButtonDisabled(true);
} else {
setIsSubmitButtonDisabled(false);
if (enableAutoSave) {
return triggerAutoSave();
}
}
};

const handleBlur = async (id: string) => {
if(submitOnBlurFields.some((field:string)=> id.includes(field))){
stopTimer()
return onSave()
}
}

const handleFocus = (id: string) => {
if(submitOnBlurFields.some((field:string)=> id.includes(field))){
startTimer()
}
}

return (
<>
{(!data || isSaving) && (
Expand All @@ -135,6 +176,8 @@ export const FormBase = (props: any) => {
onChange={handleUpdate}
onSubmit={handleSubmit}
onError={onError}
onBlur={handleBlur}
onFocus={handleFocus}
widgets={widgets}
className={className}
templates={templates}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Forms/SentenceAddForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const SentenceAddForm = (props: any) => {
schema={customSchema}
uiSchema={customUiSchema}
uiFields={uiFields}
enableAutoSave={true}
enableAutoSave={false}
formIsValid={format === "create" && formIsValid}
disableSubmitButton={setDisabled}
submitButtonProps={submitButtonProps}
Expand Down
6 changes: 2 additions & 4 deletions frontend/src/components/Forms/SentenceForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,12 @@ const SentenceForm = (props: any) => {
schema={customSchema}
uiSchema={customUiSchema}
uiFields={uiFields}
enableAutoSave={true}
enableAutoSave={false}
children={true}
submitOnBlurFields={['title']}
{...props}
/>
<Box mt={2}>
{/* <Typography color={vars.labelColor} fontWeight={500} mb={1}>
PMID (PubMed identifier)
</Typography> */}
{
linkedChip({id: data?.pmid, uri: data?.pmid_uri, label: "PMID"})
}
Expand Down
16 changes: 9 additions & 7 deletions frontend/src/components/Forms/StatementForm.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React from "react";
import { FormBase } from "./FormBase";
import { jsonSchemas } from "../../services/JsonSchema";
import statementService from "../../services/StatementService";
Expand All @@ -10,6 +10,7 @@ import AnatomicalEntitiesField from "../AnatomicalEntitiesField";
import { sexes } from '../../services/SexService';
import { phenotypes } from '../../services/PhenotypeService';


const StatementForm = (props: any) => {
const { uiFields, statement, setter, format } = props;
const { schema, uiSchema } = jsonSchemas.getConnectivityStatementSchema();
Expand Down Expand Up @@ -37,7 +38,7 @@ const StatementForm = (props: any) => {
copiedUISchema.projection= {
"ui:widget": "radio",
"ui:options": {
classNames: 'col-xs-12 col-md-6'
classNames: 'col-xs-12 col-md-6',
}
}

Expand Down Expand Up @@ -67,7 +68,7 @@ const StatementForm = (props: any) => {
placeholder: "Select Phenotype",
data: phenotypes.getPhenotypes().map((row: any) => ({ label: row.name, value: row.id })),
},
value: statement?.phenotype_id ?? ""
value: statement?.phenotype_id ?? "",
}

copiedUISchema.knowledge_statement = {
Expand All @@ -76,7 +77,6 @@ const StatementForm = (props: any) => {
label: "Knowledge Statement",
placeholder: "Enter Knowledge Statement",
rows: 4,
hasDebouncedOnChange: true,
value: statement?.knowledge_statement ?? "",
},
};
Expand Down Expand Up @@ -127,7 +127,7 @@ const StatementForm = (props: any) => {
label: "Additional Information",
placeholder: "Enter additional information on the knowledge statement",
multiline: true,
rows: 4
rows: 4,
},
value: statement?.additional_information ?? "",
};
Expand All @@ -146,17 +146,19 @@ const StatementForm = (props: any) => {

return (
<FormBase
{...props}
data={statement}
service={statementService}
schema={copiedSchema}
uiSchema={copiedUISchema}
uiFields={uiFields}
enableAutoSave={true}
enableAutoSave={false}
children={true}
widgets={widgets}
templates={templates}
showErrorList={false}
submitOnBlurFields={['knowledge_statement', 'additional_information', 'apinatomy_model']}
submitOnChangeFields={['phenotype_id', 'sex_id', 'laterality', 'circuit_type', 'projection', 'destination_type', 'path_type']}
{...props}
/>
);
};
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/components/ProofingTab/PathsBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ const PathsBuilder = (props: any) => {
setter={refreshStatement}
extraData={{ sentence_id: statement.sentence.id }}
uiFields={["origin_id"]}
enableAutoSave={false}
submitOnChangeFields={['origin_id']}
/>
</Grid>
</Grid>
Expand All @@ -68,6 +70,8 @@ const PathsBuilder = (props: any) => {
extraData={{ sentence_id: statement.sentence.id }}
uiFields={["path"]}
className="vias"
enableAutoSave={false}
submitOnChangeFields={['path']}
/>
</Box>
<Box height={24} width={2} bgcolor='#D0D5DD' ml='34px'/>
Expand All @@ -84,6 +88,8 @@ const PathsBuilder = (props: any) => {
extraData={{ sentence_id: statement.sentence.id }}
uiFields={["destination_id", "destination_type"]}
className="inLineForm"
enableAutoSave={false}
submitOnChangeFields={["destination_id", "destination_type"]}
/>
</TableRow>
</TableBody>
Expand Down
5 changes: 2 additions & 3 deletions frontend/src/components/ProofingTab/ProofingTab.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from "react";
import { ConnectivityStatement } from "../../apiclient/backend";
import { Grid, Typography, Box, Stack, Divider, Paper } from "@mui/material";
import StatementChart from "./StatementChart";
import StatementWithProvenances from "../StatementWithProvenances";
Expand All @@ -9,7 +8,7 @@ import { useTheme } from "@mui/system";
import PathsBuilder from "./PathsBuilder";

const ProofingTab = (props: any) => {
const { statement } = props;
const { statement, refreshStatement, setStatement } = props;
const theme = useTheme();
const sectionStyle = useSectionStyle(theme);

Expand Down Expand Up @@ -42,7 +41,7 @@ const ProofingTab = (props: any) => {
textAlign: "center",
}}
>
<StatementWithProvenances statement={statement} />
<StatementWithProvenances statement={statement} refreshStatement={refreshStatement} setStatement={setStatement}/>
</Box>
</Paper>
</Grid>
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/StatementWithProvenances.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const StatementWithProvenances = ({ statement, background = "#fff", refreshState
uiFields={["knowledge_statement"]}
className='ks'
disabled={disabled}
enableAutoSave={true}
/>

<ProvenancesForm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const StatementDetailsAccordion = (props: any) => {
statement={statement}
format="small"
setter={setter}
enableAutoSave={true}
extraData={{
sentence_id: sentence.id,
knowledge_statement: statement.knowledge_statement,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const TriageStatementSection = (props: any) => {
extraData={{ sentence_id: sentence.id }}
uiFields={["knowledge_statement"]}
className='ks'
enableAutoSave={true}
/>

<ProvenancesForm
Expand Down
35 changes: 5 additions & 30 deletions frontend/src/components/Widgets/CustomTextArea.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import * as React from "react";
import TextField from "@mui/material/TextField";
import FormControl from "@mui/material/FormControl";
import {useDebouncedCallback} from "use-debounce";
import {EDIT_DEBOUNCE} from "../../settings";
import { styled } from "@mui/material";

const StyledInput = styled(TextField)(({ theme }) => ({
Expand All @@ -22,46 +20,23 @@ const StyledInput = styled(TextField)(({ theme }) => ({
}));


export default function TextArea({value, placeholder, required, disabled, onChange, options: { rows, hasDebouncedOnChange } }: any) {
export default function TextArea({ id, value, placeholder, required, disabled, onChange, onBlur, onFocus, options: { rows } }: any) {

const [inputValue, setInputValue] = React.useState(value)

const debouncedChangeHandler = useDebouncedCallback(
(event) => onChange(event.target.value),
EDIT_DEBOUNCE
);

const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement|HTMLInputElement>) => {
const inputValue = e.target.value;
setInputValue(inputValue);
debouncedChangeHandler(e);
};

React.useEffect(()=>setInputValue(value), [value])

return (
<FormControl variant="standard">
{hasDebouncedOnChange
? <StyledInput defaultValue={value}
multiline
rows={rows}
placeholder={placeholder}
fullWidth
required={required}
disabled={disabled}
value={inputValue}
onChange={handleChange}/>
:<StyledInput
<StyledInput
value={value?value:''}
multiline
rows={rows}
placeholder={placeholder}
fullWidth
required={required}
onChange={(e)=>onChange(e.target.value)}
onBlur={(e)=>onBlur(id,e.target.value)}
onFocus={(e)=>onFocus(id,e.target.value)}
disabled={disabled}
/>
}

</FormControl>
);
}
8 changes: 7 additions & 1 deletion frontend/src/components/Widgets/CustomTextField.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as React from "react";
import TextField from "@mui/material/TextField";
import InputLabel from "@mui/material/InputLabel";
import FormControl from "@mui/material/FormControl";
import { styled } from "@mui/material";
import Typography from "@mui/material/Typography";
Expand All @@ -16,12 +15,17 @@ const StyledInput = styled(TextField)(({ theme }) => ({
}));

export default function CustomTextField({
id,
value,
placeholder,
disabled,
onChange,
onBlur,
onFocus,
options: { label, multiline, rows },
}: any) {


return (
<FormControl variant="standard">
<Typography variant="h6" fontWeight={500} marginBottom={2} color={vars.titleFontColor}>
Expand All @@ -36,6 +40,8 @@ export default function CustomTextField({
rows={rows}
value={value ? value : ''}
disabled={disabled}
onBlur={(e=>onBlur(id,e.target.value))}
onFocus={(e=>onFocus(id,e.target.value))}
/>
</FormControl>
);
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/settings.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export const EDIT_DEBOUNCE = 1500 // 1.5 seconds
export const EDIT_DEBOUNCE = 120000 // 120 seconds
export const SEARCH_DEBOUNCE = 300 // 0.3 seconds
export const ROWS_PER_PAGE = 10 //number of records displayed at sentence and statement list