Add saving state

This commit is contained in:
c-bata
2022-03-19 02:27:52 +09:00
parent 40c2aab767
commit b366191d82
5 changed files with 34 additions and 15 deletions
+7 -4
View File
@@ -282,20 +282,23 @@ def create_app(storage: BaseStorage) -> Bottle:
],
}
@app.post("/api/studies/<study_id:int>/note")
@app.put("/api/studies/<study_id:int>/note")
@handle_json_api_exception
def save_note(study_id: int) -> BottleViewReturn:
response.content_type = "application/json"
system_attrs = storage.get_study_system_attrs(study_id)
req_note_ver = request.json.get("version", None)
req_note_body = request.json.get("body", None)
if req_note_ver is None or req_note_body is None:
response.status = 400 # Bad request
return {"reason": "Invalid request."}
system_attrs = storage.get_study_system_attrs(study_id)
if not note.version_is_incremented(system_attrs, req_note_ver):
response.status = 400 # Bad request
return {"reason": "The text you are editing has changed. Please copy your edits and refresh the page."}
response.status = 409 # Conflict
return {
"reason": "The text you are editing has changed. Please copy your edits and refresh the page.",
}
note.save_note(storage, study_id, req_note_ver, req_note_body)
response.status = 204 # No content
+3 -2
View File
@@ -96,8 +96,8 @@ export const actionCreator = () => {
})
}
const saveNote = (studyId: number, note: Note) => {
saveNoteAPI(studyId, note)
const saveNote = (studyId: number, note: Note): Promise<void> => {
return saveNoteAPI(studyId, note)
.then(() => {
const newStudy = Object.assign({}, studyDetails[studyId])
newStudy.note = note
@@ -113,6 +113,7 @@ export const actionCreator = () => {
enqueueSnackbar(`Failed: ${reason}`, {
variant: "error",
})
throw err
})
}
+1 -1
View File
@@ -189,7 +189,7 @@ export const saveNoteAPI = (
note: { version: number; body: string }
): Promise<void> => {
return axiosInstance
.post<void>(`/api/studies/${studyId}/note`, note)
.put<void>(`/api/studies/${studyId}/note`, note)
.then((res) => {
return
})
+17 -7
View File
@@ -10,6 +10,7 @@ export const Note: FC<{
latestNote: Note
}> = ({ studyId, latestNote }) => {
const theme = useTheme()
const [saving, setSaving] = useState(false)
const [disable, setDisable] = useState(true)
const [curNote, setCurNote] = useState({ version: 0, body: "" })
const textAreaRef = createRef<HTMLTextAreaElement>()
@@ -20,12 +21,20 @@ export const Note: FC<{
setCurNote(latestNote)
}, [])
const handleSave = () => {
const nextVersion = curNote.version + 1
const newNote = {
version: curNote.version + 1,
body: textAreaRef.current ? textAreaRef.current.value : ""
version: nextVersion,
body: textAreaRef.current ? textAreaRef.current.value : "",
}
setCurNote(newNote)
action.saveNote(studyId, newNote)
setSaving(true)
action
.saveNote(studyId, newNote)
.then(() => {
setCurNote(newNote)
})
.finally(() => {
setSaving(false)
})
}
const handleRefresh = () => {
if (!textAreaRef.current) {
@@ -39,6 +48,7 @@ export const Note: FC<{
return (
<>
<TextField
disabled={saving}
minRows={10}
multiline={true}
placeholder="Take a note (The note is saved to study's system_attrs)"
@@ -47,11 +57,11 @@ export const Note: FC<{
defaultValue={curNote.body}
onChange={() => {
const cur = textAreaRef.current ? textAreaRef.current.value : ""
setDisable(cur === latestNote.body)
setDisable(cur === curNote.body)
}}
/>
<Box sx={{ display: "flex", flexDirection: "row", alignItems: "center" }}>
{notLatest && (
{notLatest && !saving && (
<>
<Typography
sx={{
@@ -77,7 +87,7 @@ export const Note: FC<{
<Box sx={{ flexGrow: 1 }} />
<LoadingButton
onClick={handleSave}
loading={false}
loading={saving}
loadingPosition="start"
startIcon={<SaveIcon />}
variant="contained"
@@ -385,7 +385,12 @@ export const StudyDetail: FC<{
</Card>
<Card sx={{ margin: theme.spacing(2) }}>
<CardContent>
<Typography variant="h6" sx={{fontSize: "1.25rem", fontWeight: 600}}>Note</Typography>
<Typography
variant="h6"
sx={{ fontSize: "1.25rem", fontWeight: 600 }}
>
Note
</Typography>
{studyDetail !== null && (
<Note studyId={studyIdNumber} latestNote={studyDetail.note} />
)}