Skip to content

Commit 5f5052a

Browse files
committed
TaskSolutionComponent: быстрое оценивание
1 parent c3c130d commit 5f5052a

1 file changed

Lines changed: 59 additions & 16 deletions

File tree

hwproj.front/src/components/Solutions/TaskSolutionComponent.tsx

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
SolutionState,
1010
SolutionActualityDto,
1111
SolutionActualityPart, StudentDataDto
12-
} from '../../api'
12+
} from '@/api'
1313
import ApiSingleton from "../../api/ApiSingleton";
1414
import {Alert, Avatar, Rating, Stack, Tooltip, Card, CardContent, CardActions, IconButton, Chip} from "@mui/material";
1515
import AvatarUtils from "../Utils/AvatarUtils";
@@ -24,6 +24,8 @@ import CloseIcon from '@mui/icons-material/Close';
2424
import {useSnackbar} from 'notistack';
2525
import StudentStatsUtils from "../../services/StudentStatsUtils";
2626
import {StudentCharacteristics} from "@/components/Students/StudentCharacteristics";
27+
import KeyboardCommandKeyIcon from '@mui/icons-material/KeyboardCommandKey';
28+
import MouseOutlinedIcon from '@mui/icons-material/MouseOutlined';
2729

2830
interface ISolutionProps {
2931
courseId: number,
@@ -70,6 +72,34 @@ const TaskSolutionComponent: FC<ISolutionProps> = (props) => {
7072
getActuality()
7173
}, [props.student.userId, props.task.id, props.solution?.id, props.solution?.rating])
7274

75+
const [isCtrlPressed, setIsCtrlPressed] = useState(false)
76+
77+
useEffect(() => {
78+
if (!props.forMentor) return
79+
80+
const handleKeyDown = (event: KeyboardEvent) => {
81+
if (event.key === "Control") {
82+
setIsCtrlPressed(true);
83+
}
84+
}
85+
86+
const handleKeyUp = (event: KeyboardEvent) => {
87+
if (event.key === "Control") {
88+
setIsCtrlPressed(false);
89+
}
90+
}
91+
92+
window.addEventListener("keydown", handleKeyDown);
93+
window.addEventListener("keyup", handleKeyUp);
94+
95+
return () => {
96+
if (!props.forMentor) return
97+
window.removeEventListener("keydown", handleKeyDown);
98+
window.removeEventListener("keyup", handleKeyUp);
99+
}
100+
}, [])
101+
102+
73103
useEffect(() => {
74104
if (!state.clickedForRate) return
75105
RatingStorage.set(storageKey, {points: state.points, comment: state.lecturerComment})
@@ -111,7 +141,7 @@ const TaskSolutionComponent: FC<ISolutionProps> = (props) => {
111141
}
112142
}
113143

114-
const rateSolution = async () => {
144+
const rateSolution = async (points: number, lecturerComment: string) => {
115145
setRateInProgressState(true)
116146
if (props.solution) {
117147
await ApiSingleton.solutionsApi.solutionsRateSolution(
@@ -126,9 +156,9 @@ const TaskSolutionComponent: FC<ISolutionProps> = (props) => {
126156
{
127157
comment: "",
128158
githubUrl: "",
129-
lecturerComment: state.lecturerComment,
159+
lecturerComment: lecturerComment,
130160
publicationDate: undefined,
131-
rating: state.points,
161+
rating: points,
132162
studentId: props.student.userId
133163
}
134164
)
@@ -173,15 +203,20 @@ const TaskSolutionComponent: FC<ISolutionProps> = (props) => {
173203
title={<div>{status.comment}</div>}>{icon}</Tooltip>
174204
}
175205

206+
const clickForRate = async (points: number, clickedForRate: boolean) => {
207+
setState((prevState) => ({
208+
...prevState,
209+
points: points,
210+
clickedForRate: clickedForRate && !isCtrlPressed
211+
}))
212+
if (isCtrlPressed) await rateSolution(points, lecturerComment)
213+
}
214+
176215
const renderRateInput = () => {
177216
const showThumbs = maxRating === 1
178217
const isEditable = props.forMentor && (!isRated || state.clickedForRate)
179218
const thumbsHandler = (rating: number) => {
180-
setState((prevState) => ({
181-
...prevState,
182-
points: rating,
183-
clickedForRate: isEditable
184-
}))
219+
clickForRate(rating, isEditable)
185220
}
186221
if (maxRating <= 10 && points <= maxRating && !addBonusPoints)
187222
return (<Grid container item direction={"row"} spacing={1} alignItems={"center"}>
@@ -204,12 +239,7 @@ const TaskSolutionComponent: FC<ISolutionProps> = (props) => {
204239
value={points}
205240
readOnly={!isEditable}
206241
onChange={(_, newValue) => {
207-
setState((prevState) => ({
208-
...prevState,
209-
points: newValue || 0,
210-
addBonusPoints: points > maxRating,
211-
clickedForRate: true
212-
}))
242+
clickForRate(newValue || 0, true)
213243
}}
214244
/>
215245
</Grid>}
@@ -288,6 +318,19 @@ const TaskSolutionComponent: FC<ISolutionProps> = (props) => {
288318
<Grid item>
289319
{renderRateInput()}
290320
</Grid>
321+
{!isRated && !state.clickedForRate && maxRating <= 10 && !addBonusPoints && <Grid item>
322+
<Typography variant={"caption"} style={{color: "GrayText"}}>
323+
Нажмите{" "}
324+
<span style={{color: isCtrlPressed ? "blue" : "inherit"}}>
325+
<KeyboardCommandKeyIcon style={{fontSize: 10, marginTop: -2}}/>
326+
Ctrl
327+
</span>{" "} + {" "}
328+
<span>
329+
ЛКМ
330+
<MouseOutlinedIcon style={{fontSize: 10, marginTop: -2}}/>
331+
</span>{" "}для быстрого оценивания
332+
</Typography>
333+
</Grid>}
291334
{lastRating !== undefined && state.clickedForRate &&
292335
<Grid item>
293336
<Typography variant={"caption"} style={{color: "GrayText", marginTop: -10}}>
@@ -343,7 +386,7 @@ const TaskSolutionComponent: FC<ISolutionProps> = (props) => {
343386
loading={rateInProgress}
344387
loadingPosition="end"
345388
size="small"
346-
onClick={rateSolution}
389+
onClick={() => rateSolution(points, lecturerComment)}
347390
>
348391
{isRated ? "Изменить оценку" : "Оценить решение"}
349392
</LoadingButton>

0 commit comments

Comments
 (0)