Skip to content
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
37 changes: 17 additions & 20 deletions src/commons/ContentDisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,29 @@
import { Card, Elevation } from '@blueprintjs/core';
import * as React from 'react';
import React, { useEffect } from 'react';

export type ContentDisplayProps = {
fullWidth?: boolean;
display: JSX.Element;
loadContentDispatch: () => void;
};

class ContentDisplay extends React.Component<ContentDisplayProps, {}> {
public componentDidMount() {
this.props.loadContentDispatch();
}
const ContentDisplay: React.FC<ContentDisplayProps> = props => {
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(() => props.loadContentDispatch(), []);

public render() {
return (
<div className="ContentDisplay row center-xs">
<div
className={`${
this.props.fullWidth ? 'col-md-12' : 'col-md-10 col-xs-11'
} contentdisplay-content-parent`}
>
<Card className="contentdisplay-content" elevation={Elevation.THREE}>
{this.props.display}
</Card>
</div>
return (
<div className="ContentDisplay row center-xs">
<div
className={`${
props.fullWidth ? 'col-md-12' : 'col-md-10 col-xs-11'
} contentdisplay-content-parent`}
>
<Card className="contentdisplay-content" elevation={Elevation.THREE}>
{props.display}
</Card>
</div>
);
}
}
</div>
);
};

export default ContentDisplay;
8 changes: 3 additions & 5 deletions src/commons/achievement/AchievementTask.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Collapse } from '@blueprintjs/core';
import { useContext, useState } from 'react';
import React, { useContext, useState } from 'react';

import {
AchievementContext,
Expand All @@ -14,9 +14,7 @@ type AchievementTaskProps = {
focusState: [string, any];
};

function AchievementTask(props: AchievementTaskProps) {
const { uuid, filterStatus, focusState } = props;

const AchievementTask: React.FC<AchievementTaskProps> = ({ uuid, filterStatus, focusState }) => {
const inferencer = useContext(AchievementContext);
const prerequisiteUuids = [...inferencer.getImmediateChildren(uuid)];
const taskColor = getAbilityColor();
Expand Down Expand Up @@ -108,6 +106,6 @@ function AchievementTask(props: AchievementTaskProps) {
)}
</>
);
}
};

export default AchievementTask;
Original file line number Diff line number Diff line change
Expand Up @@ -24,50 +24,19 @@ type StateProps = {
questionId: number;
};

export class AutograderTab extends React.Component<AutograderProps, {}> {
public render() {
const question = this.props.assessment.questions[this.props.questionId] as IProgrammingQuestion;
const publicTestPath = ['questions', this.props.questionId, 'testcases'];

const publicTestcases = question.testcases.map((testcase, index) => (
<div key={index}>{this.autograderCard(publicTestPath, index)}</div>
));

const privateTestPath = ['questions', this.props.questionId, 'testcasesPrivate'];
const privateTestcases = question.testcasesPrivate!.map((testcase, index) => (
<div key={index}>{this.autograderCard(privateTestPath, index)}</div>
));

return (
<div>
Public Testcases
{publicTestcases}
{controlButton('New public testcase', IconNames.PLUS, this.addTestcase(question.testcases))}
<br />
<br />
Private Testcases
{privateTestcases}
{controlButton(
'New private testcase',
IconNames.PLUS,
this.addTestcase(question.testcasesPrivate!)
)}
</div>
);
}

private addTestcase = (testcases: Testcase[]) => () => {
export const AutograderTab: React.FC<AutograderProps> = props => {
const addTestcase = (testcases: Testcase[]) => () => {
testcases.push(testcaseTemplate());
this.props.updateAssessment(this.props.assessment);
props.updateAssessment(props.assessment);
};

private removeTestcase = (testcases: Testcase[], id: number) => {
const removeTestcase = (testcases: Testcase[], id: number) => {
testcases.splice(id, 1);
this.props.updateAssessment(this.props.assessment);
props.updateAssessment(props.assessment);
};

private autograderCard = (testcasePath: Array<string | number>, index: number) => {
const testcases = getValueFromPath(testcasePath, this.props.assessment) as Testcase[];
const autograderCard = (testcasePath: Array<string | number>, index: number) => {
const testcases = getValueFromPath(testcasePath, props.assessment) as Testcase[];
const testcase = testcases[index];

return (
Expand All @@ -79,48 +48,73 @@ export class AutograderTab extends React.Component<AutograderProps, {}> {
<H6>
Test Program:
<TextAreaContent
assessment={this.props.assessment}
assessment={props.assessment}
path={testcasePath.concat([index, 'program'])}
useRawValue={true}
updateAssessment={this.props.updateAssessment}
updateAssessment={props.updateAssessment}
/>
</H6>
</div>
<div className="row listing-expected">
<H6>
Score:
<TextAreaContent
assessment={this.props.assessment}
assessment={props.assessment}
isNumber={true}
path={testcasePath.concat([index, 'score'])}
updateAssessment={this.props.updateAssessment}
updateAssessment={props.updateAssessment}
/>
</H6>
</div>
<div className="row listing-expected">
<H6>
Expected Answer:
<TextAreaContent
assessment={this.props.assessment}
assessment={props.assessment}
path={testcasePath.concat([index, 'answer'])}
useRawValue={true}
updateAssessment={this.props.updateAssessment}
updateAssessment={props.updateAssessment}
/>
</H6>
</div>
<div className="listing-controls">
<div>
{controlButton('Test', IconNames.PLAY, () =>
this.props.handleTestcaseEval(testcase)
)}
{controlButton('Delete', IconNames.DELETE, () =>
this.removeTestcase(testcases, index)
)}
{controlButton('Test', IconNames.PLAY, () => props.handleTestcaseEval(testcase))}
{controlButton('Delete', IconNames.DELETE, () => removeTestcase(testcases, index))}
</div>
</div>
</div>
</Card>
</div>
);
};
}

const question = props.assessment.questions[props.questionId] as IProgrammingQuestion;
const publicTestPath = ['questions', props.questionId, 'testcases'];

const publicTestcases = question.testcases.map((testcase, index) => (
<div key={index}>{autograderCard(publicTestPath, index)}</div>
));

const privateTestPath = ['questions', props.questionId, 'testcasesPrivate'];
const privateTestcases = question.testcasesPrivate!.map((testcase, index) => (
<div key={index}>{autograderCard(privateTestPath, index)}</div>
));

return (
<div>
Public Testcases
{publicTestcases}
{controlButton('New public testcase', IconNames.PLUS, addTestcase(question.testcases))}
<br />
<br />
Private Testcases
{privateTestcases}
{controlButton(
'New private testcase',
IconNames.PLUS,
addTestcase(question.testcasesPrivate!)
)}
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,25 @@ type StateProps = {
path: Array<string | number>;
};

export class GradingTab extends React.Component<GradingTabProps, {}> {
public constructor(props: GradingTabProps) {
super(props);
}

public render() {
return this.gradingTab();
}

private textareaContent = (path: Array<string | number>) => {
export const GradingTab: React.FC<GradingTabProps> = props => {
const textareaContent = (path: Array<string | number>) => {
return (
<TextAreaContent
assessment={this.props.assessment}
assessment={props.assessment}
isNumber={true}
path={path}
processResults={limitNumberRange(0)}
updateAssessment={this.props.updateAssessment}
updateAssessment={props.updateAssessment}
/>
);
};

private gradingTab = () => (
return (
<div>
Max Xp:
{this.textareaContent(this.props.path.concat(['maxXp']))}
{textareaContent(props.path.concat(['maxXp']))}
</div>
);
}
};

export default GradingTab;
Loading