Commit 8a20b0a5 authored by Zhige  Yu's avatar Zhige Yu
Browse files

Add api calls to backend for submission declaration tab

parent 70b730a6
......@@ -8,6 +8,8 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faPlusCircle } from "@fortawesome/free-solid-svg-icons/faPlusCircle";
import { faMinusCircle } from "@fortawesome/free-solid-svg-icons/faMinusCircle";
import classNames from "classnames";
import { DeclarationHelper, DeclarationStatus } from "constants/types";
import { faCheckCircle, faEye } from "@fortawesome/free-solid-svg-icons";
interface Declaration {
name: string
......@@ -15,52 +17,43 @@ interface Declaration {
}
interface Props {
// validatePair: (name: string, login: string) => boolean
// addDeclarations: (declarations: Declaration[]) => void
}
enum DeclarationStatus {
NOTSET = "NotSet",
UNAIDED = "Unaided",
WITH_HELP = "With help",
status: DeclarationStatus
declaredHelpers: DeclarationHelper[]
onUnset: () => void
onSetUnaided: () => void
onSetWithHelp: () => void
addHelper: (name: string, login: string) => void
removeHelper: (name: string, login: string) => void
}
const SubmitDeclarationSection: React.FC<Props> = ({
status,
declaredHelpers,
onUnset,
onSetUnaided,
onSetWithHelp,
addHelper,
removeHelper,
}) => {
const [declarationSubmitted, setDeclarationSubmitted] = useState<boolean>(false);
const [declarationStatus, setDeclarationStatus] = useState<DeclarationStatus>(DeclarationStatus.NOTSET)
const declarationSubmitted = status !== DeclarationStatus.NOTSET
const [name, setName] = useState<string>("")
const [login, setLogin] = useState<string>("")
const [declarationList, setDeclarationList] = useState<Declaration[]>([])
const switchDeclarationStatus = () => setDeclarationSubmitted(!declarationSubmitted)
const addRow = (name: string, login: string) => {
setDeclarationList([...declarationList, {name, login}])
if (name !== "" && !declaredHelpers.find(({ name: n, login: l }) => n === name && login === l)) {
addHelper(name, login)
}
setName("")
setLogin("")
}
const deleteRow = (targetName: string, targetLogin: string) => {
setDeclarationList(declarationList.filter(({ name, login }) => targetName !== name || targetLogin !== login))
}
const resetForm = () => {
setDeclarationStatus(DeclarationStatus.NOTSET)
setDeclarationList([])
onUnset()
setName("")
setLogin("")
}
const submitForm = () => {
if (declarationList.length === 0) {
setDeclarationStatus(DeclarationStatus.UNAIDED)
} else {
setDeclarationStatus(DeclarationStatus.WITH_HELP)
}
setName("")
setLogin("")
}
......@@ -81,21 +74,20 @@ const SubmitDeclarationSection: React.FC<Props> = ({
[DeclarationStatus.NOTSET]: ["", ""],
[DeclarationStatus.UNAIDED]: [styles.active, styles.collapsed],
[DeclarationStatus.WITH_HELP]: [styles.collapsed, styles.active],
}[declarationStatus]
console.log(unaidedClass, withHelpClass)
}[status]
const unaided: JSX.Element = (
<div
className={classNames(styles.unaidedPanel, unaidedClass, styles.center)}
onClick={() => {
submitForm()
setDeclarationStatus(DeclarationStatus.UNAIDED)
onSetUnaided()
}}
>
<div className={styles.center}>
<div className={styles.center}>
<p className={styles.submitDeclParagraphBold}>
{declarationStatus === DeclarationStatus.NOTSET ? unaidedSelectText : unaidedDeclarationText}
{status === DeclarationStatus.UNAIDED && <FontAwesomeIcon icon={faCheckCircle} style={{ marginRight: '0.3rem' }}/> }
{status === DeclarationStatus.NOTSET ? unaidedSelectText : unaidedDeclarationText}
</p>
</div>
</div>
......@@ -103,7 +95,7 @@ const SubmitDeclarationSection: React.FC<Props> = ({
const DeclarationRow: JSX.Element =
<>
{declarationList.map(
{declaredHelpers.map(
({ name, login }, index) => {
return (
<Form.Row className={styles.submitDeclRow} key={index}>
......@@ -126,7 +118,7 @@ const SubmitDeclarationSection: React.FC<Props> = ({
<Col sm="2">
<Button
className={styles.submitDeclButton}
onClick={() => deleteRow(name, login)}
onClick={() => removeHelper(name, login)}
variant="secondary"
>
<FontAwesomeIcon icon={faMinusCircle} />
......@@ -142,14 +134,20 @@ const SubmitDeclarationSection: React.FC<Props> = ({
<div
className={classNames(styles.withHelpPanel, withHelpClass)}
style={{ height: 'auto' }}
onClick={() => setDeclarationStatus(DeclarationStatus.WITH_HELP)}
onClick={() => {
if (status !== DeclarationStatus.WITH_HELP) {
onSetWithHelp()
}
}}
>
<div className={declarationStatus === DeclarationStatus.NOTSET ? styles.center : ""}>
<div className={status === DeclarationStatus.NOTSET ? styles.center : ""}>
<span className={styles.submitDeclParagraphBold}>
{declarationStatus === DeclarationStatus.NOTSET ? withHelpSelectText : withHelpDeclarationText}
{status === DeclarationStatus.NOTSET || <FontAwesomeIcon icon={faEye} style={{ marginRight: '0.3rem' }}/>}
{status === DeclarationStatus.NOTSET ? withHelpSelectText : withHelpDeclarationText}
</span>
{DeclarationRow}
{(declarationStatus === DeclarationStatus.WITH_HELP) && <>
{(status === DeclarationStatus.WITH_HELP) && <>
{DeclarationRow}
<Form.Row className={styles.submitDeclFirstRow}>
<Col sm="5">
<Form.Label className={styles.submitDeclTitle}>Name</Form.Label>
......@@ -201,10 +199,10 @@ const SubmitDeclarationSection: React.FC<Props> = ({
<Form>
<Form.Group>
<div style={{ display: 'flex' }}>
{declarationStatus !== DeclarationStatus.WITH_HELP && unaided}
{declarationStatus !== DeclarationStatus.UNAIDED && withHelp}
{status !== DeclarationStatus.WITH_HELP && unaided}
{status !== DeclarationStatus.UNAIDED && withHelp}
</div>
{declarationStatus === DeclarationStatus.WITH_HELP && (
{status === DeclarationStatus.WITH_HELP && (
<Form.Text muted className={styles.submitDeclHelpText}>
Names must contain only alphabetic characters [A-Za-z],
spaces and hyphens (-); logins must contain only lower case
......@@ -212,7 +210,7 @@ const SubmitDeclarationSection: React.FC<Props> = ({
syntax will be ignored.
</Form.Text>)
}
{declarationStatus !== DeclarationStatus.NOTSET && (
{status !== DeclarationStatus.NOTSET && (
<Form.Row className={styles.submitDeclRow}>
<Col>
<Button
......
......@@ -84,6 +84,7 @@
.unaidedPanel {
background-color: var(--teal-background);
color: var(--teal-text);
cursor: pointer;
height: 9rem;
width: 50%;
text-align: center;
......@@ -102,6 +103,7 @@
}
.unaidedPanel.active {
cursor: default;
width: 100%;
}
......@@ -116,6 +118,7 @@
.withHelpPanel {
background-color: var(--blue-background);
color: var(--blue-text);
cursor: pointer;
height: 9rem;
width: 50%;
text-align: center;
......@@ -134,6 +137,7 @@
}
.withHelpPanel.active {
cursor: default;
width: 100%;
}
......
import React, {useEffect, useState} from "react"
import Button from "react-bootstrap/Button"
import styles from "./style.module.scss"
import {EnumDictionary, ResourceUploadRequirement, ResourceUploadStatus, TimelineEvent, UserInfo} from "constants/types"
import {DeclarationHelper, DeclarationStatus, EnumDictionary, ResourceUploadRequirement, ResourceUploadStatus, TimelineEvent, UserInfo} from "constants/types"
import ButtonGroup from "react-bootstrap/esm/ButtonGroup"
import SubmissionFileUploadTab from "../SubmissionFileUploadTab"
import { api, methods } from "constants/routes"
......@@ -9,6 +9,7 @@ import { download, request } from "utils/api"
import SubmitDeclarationSection from "../SubmissionDeclarationTab";
import authenticationService from "utils/auth"
import SubmissionGroupFormation from "../SubmissionGroupFormation";
import { stringify } from "querystring"
enum Stage {
DECLARATION = "Declaration",
......@@ -40,6 +41,8 @@ const SubmissionSection: React.FC<Props> = ({
const [isLoaded, setIsLoaded] = useState(false)
const [requirements, setRequirements] = useState<ResourceUploadRequirement[]>([])
const [uploaded, setUploaded] = useState<ResourceUploadStatus[]>([])
const [declarationStatus, setDeclarationStatus] = useState<DeclarationStatus>(DeclarationStatus.NOTSET)
const [declaredHelpers, setDeclaredHelpers] = useState<DeclarationHelper[]>([])
const [groupMembers, setGroupMembers] = useState<UserInfo[]>([])
const currentUser = authenticationService.getUserInfo()["username"]
......@@ -68,13 +71,7 @@ const SubmissionSection: React.FC<Props> = ({
const refresh = () => {
setIsLoaded(false)
const onSuccess = (data: {
requirements: ResourceUploadRequirement[],
}) => {
setRequirements(data.requirements)
setIsLoaded(true)
}
const onError = () => { alert("err") }
const onError = (part: string) => () => { alert(part) }
request({
url: api.CATE_FILE_UPLOAD(courseCode, exerciseID),
......@@ -82,10 +79,35 @@ const SubmissionSection: React.FC<Props> = ({
body: {
username: authenticationService.getUserInfo()["username"]
},
onSuccess,
onError,
onSuccess: (data: { requirements: ResourceUploadRequirement[] }) => {
setRequirements(data.requirements)
setIsLoaded(true)
},
onError: onError("file"),
sendFile: false
})
request({
url: api.CATE_DECLARATION(courseCode, exerciseID),
method: methods.GET,
body: {
username: authenticationService.getUserInfo()["username"],
operation: 'get'
},
onSuccess: (data: null | "Unaided" | { name: string, login: string }[]) => {
if (data === null) {
setDeclarationStatus(DeclarationStatus.NOTSET)
setDeclaredHelpers([])
} else if (data === "Unaided") {
setDeclarationStatus(DeclarationStatus.UNAIDED)
setDeclaredHelpers([])
} else {
setDeclarationStatus(DeclarationStatus.WITH_HELP)
setDeclaredHelpers(data)
}
},
onError: onError("decl"),
})
}
useEffect(refresh, [])
......@@ -93,6 +115,29 @@ const SubmissionSection: React.FC<Props> = ({
if (isLoaded) console.log("refresh!")
}, [isLoaded])
const addDeclarationHelper = (name: string, login: string) => {
const newHelpers = [...declaredHelpers, { name, login }]
uploadDeclaration(newHelpers)
}
const removeDeclarationHelper = (targetName: string, targetLogin: string) => {
uploadDeclaration(declaredHelpers.filter(({ name, login }) => targetName !== name || targetLogin !== login))
}
const uploadDeclaration = (data: "Unaided" | DeclarationHelper[]) => {
console.log(data)
request({
url: api.CATE_DECLARATION(courseCode, exerciseID),
method: methods.PUT,
body: {
username: authenticationService.getUserInfo()["username"],
declaration: data
},
onSuccess: () => {},
onError: () => alert("error")
}).then(refresh)
}
const uploadFile = (file: File, index: number) => {
const requirement = requirements[index]
......@@ -153,7 +198,21 @@ const SubmissionSection: React.FC<Props> = ({
const mainSectionDict: EnumDictionary<Stage, JSX.Element> = {
[Stage.DECLARATION]: (
<SubmitDeclarationSection/>
<SubmitDeclarationSection
status={declarationStatus}
declaredHelpers={declaredHelpers}
onUnset={() => setDeclarationStatus(DeclarationStatus.NOTSET)}
onSetUnaided={() => {
uploadDeclaration("Unaided")
}}
onSetWithHelp={() => {
uploadDeclaration([])
}}
addHelper={(name, login) => {
addDeclarationHelper(name, login)
}}
removeHelper={removeDeclarationHelper}
/>
),
[Stage.GROUP_FORMATION]: (
<SubmissionGroupFormation
......
......@@ -26,6 +26,7 @@ export const api = {
CATE_GROUP_INFO: (courseCode: string, exerciseID: number) => `${config.CATE_URL}/groups/${courseCode}/${exerciseID}`,
CATE_FILE_UPLOAD: (courseCode: string, exerciseID: number) => `${config.CATE_URL}/upload/${courseCode}/${exerciseID}`,
CATE_FILE_DOWNLOAD: `${config.CATE_URL}/download`,
CATE_DECLARATION: (courseCode: string, exerciseID: number) => `${config.CATE_URL}/declaration/${courseCode}/${exerciseID}`,
MATERIALS_LOGIN: `${config.MATERIALS_URL}/auth/login`,
MATERIALS_COURSES: (year: string) =>
`${config.MATERIALS_URL}/courses/${year}`,
......
......@@ -19,6 +19,18 @@ export interface UserInfo {
signatureTime: Date
}
export interface DeclarationHelper {
name: string,
login: string
}
export enum DeclarationStatus {
NOTSET = "NotSet",
UNAIDED = "Unaided",
WITH_HELP = "With help",
}
export interface Resource {
title: string
type: FileType
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment