Skip to content

Commit 4f5c495

Browse files
authored
Mission editing slang (#500)
* fix import for firefox * increase abstraction removed numberRange from textArea Reduced save frequency of solutionTemplate
1 parent e024b33 commit 4f5c495

File tree

4 files changed

+99
-38
lines changed

4 files changed

+99
-38
lines changed

src/components/incubator/editingWorkspaceSideContent/GradingTab.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as React from 'react';
22

33
import { IAssessment } from '../../assessment/assessmentShape';
4+
import { limitNumberRange } from './';
45
import TextareaContent from './TextareaContent';
56

67
interface IProps {
@@ -18,12 +19,13 @@ export class GradingTab extends React.Component<IProps, {}> {
1819
return this.gradingTab();
1920
}
2021

21-
private textareaContent = (path: Array<string | number>, isNumber: boolean = false) => {
22+
private textareaContent = (path: Array<string | number>) => {
2223
return (
2324
<TextareaContent
2425
assessment={this.props.assessment}
25-
isNumber={isNumber}
26+
isNumber={true}
2627
path={path}
28+
processResults={limitNumberRange(0)}
2729
updateAssessment={this.props.updateAssessment}
2830
/>
2931
);
@@ -32,10 +34,10 @@ export class GradingTab extends React.Component<IProps, {}> {
3234
private gradingTab = () => (
3335
<div>
3436
Max Grade:
35-
{this.textareaContent(this.props.path.concat(['maxGrade']), true)}
37+
{this.textareaContent(this.props.path.concat(['maxGrade']))}
3638
<br />
3739
Max Xp:
38-
{this.textareaContent(this.props.path.concat(['maxXp']), true)}
40+
{this.textareaContent(this.props.path.concat(['maxXp']))}
3941
</div>
4042
);
4143
}

src/components/incubator/editingWorkspaceSideContent/QuestionTemplateTab.tsx

Lines changed: 77 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as React from 'react';
33
import AceEditor from 'react-ace';
44

55
import { IAssessment, IMCQQuestion } from '../../assessment/assessmentShape';
6-
import { assignToPath, getValueFromPath } from './';
6+
import { assignToPath, getValueFromPath, limitNumberRange } from './';
77
import TextareaContent from './TextareaContent';
88

99
interface IProps {
@@ -12,9 +12,18 @@ interface IProps {
1212
updateAssessment: (assessment: IAssessment) => void;
1313
}
1414

15-
export class QuestionTemplateTab extends React.Component<IProps, {}> {
15+
interface IState {
16+
templateValue: string;
17+
templateFocused: boolean;
18+
}
19+
20+
export class QuestionTemplateTab extends React.Component<IProps, IState> {
1621
public constructor(props: IProps) {
1722
super(props);
23+
this.state = {
24+
templateValue: '',
25+
templateFocused: false
26+
};
1827
}
1928

2029
public render() {
@@ -34,30 +43,60 @@ export class QuestionTemplateTab extends React.Component<IProps, {}> {
3443
const path = ['questions', this.props.questionId, 'answer'];
3544

3645
const handleTemplateChange = (newCode: string) => {
37-
const assessmentVal = this.props.assessment;
38-
assignToPath(path, newCode, assessmentVal);
39-
this.props.updateAssessment(assessmentVal);
46+
this.setState({
47+
templateValue: newCode
48+
});
4049
};
4150

51+
const value = this.state.templateFocused
52+
? this.state.templateValue
53+
: getValueFromPath(path, this.props.assessment);
54+
4255
const display = (
43-
<AceEditor
44-
className="react-ace"
45-
editorProps={{
46-
$blockScrolling: Infinity
47-
}}
48-
fontSize={14}
49-
highlightActiveLine={false}
50-
mode="javascript"
51-
onChange={handleTemplateChange}
52-
theme="cobalt"
53-
value={getValueFromPath(path, this.props.assessment)}
54-
width="100%"
55-
/>
56+
<div onClick={this.focusEditor(path)} onBlur={this.unFocusEditor(path)}>
57+
<AceEditor
58+
className="react-ace"
59+
editorProps={{
60+
$blockScrolling: Infinity
61+
}}
62+
fontSize={14}
63+
highlightActiveLine={false}
64+
mode="javascript"
65+
onChange={handleTemplateChange}
66+
theme="cobalt"
67+
value={value}
68+
width="100%"
69+
/>
70+
</div>
5671
);
5772

5873
return display;
5974
};
6075

76+
private focusEditor = (path: Array<string | number>) => (e: any): void => {
77+
if (!this.state.templateFocused) {
78+
this.setState({
79+
templateValue: getValueFromPath(path, this.props.assessment),
80+
templateFocused: true
81+
});
82+
}
83+
};
84+
85+
private unFocusEditor = (path: Array<string | number>) => (e: any): void => {
86+
if (this.state.templateFocused) {
87+
const value = getValueFromPath(path, this.props.assessment);
88+
if (value !== this.state.templateValue) {
89+
const assessmentVal = this.props.assessment;
90+
assignToPath(path, this.state.templateValue, assessmentVal);
91+
this.props.updateAssessment(assessmentVal);
92+
}
93+
this.setState({
94+
templateValue: '',
95+
templateFocused: false
96+
});
97+
}
98+
};
99+
61100
private mcqTab = () => {
62101
const questionId = this.props.questionId;
63102
const question = this.props.assessment!.questions[questionId] as IMCQQuestion;
@@ -87,17 +126,27 @@ export class QuestionTemplateTab extends React.Component<IProps, {}> {
87126
private textareaContent = (
88127
path: Array<string | number>,
89128
isNumber: boolean = false,
90-
numberRange: number[] = [0]
129+
range: number[] = [0]
91130
) => {
92-
return (
93-
<TextareaContent
94-
assessment={this.props.assessment}
95-
isNumber={isNumber}
96-
numberRange={numberRange}
97-
path={path}
98-
updateAssessment={this.props.updateAssessment}
99-
/>
100-
);
131+
if (isNumber) {
132+
return (
133+
<TextareaContent
134+
assessment={this.props.assessment}
135+
isNumber={true}
136+
path={path}
137+
processResults={limitNumberRange(range[0], range[1])}
138+
updateAssessment={this.props.updateAssessment}
139+
/>
140+
);
141+
} else {
142+
return (
143+
<TextareaContent
144+
assessment={this.props.assessment}
145+
path={path}
146+
updateAssessment={this.props.updateAssessment}
147+
/>
148+
);
149+
}
101150
};
102151
}
103152

src/components/incubator/editingWorkspaceSideContent/TextareaContent.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { assignToPath, getValueFromPath } from './';
88
interface IProps {
99
assessment: IAssessment;
1010
isNumber?: boolean;
11-
numberRange?: number[];
1211
path: Array<string | number>;
1312
useRawValue?: boolean;
1413
processResults?: (newVal: string | number) => string | number;
@@ -54,12 +53,9 @@ export class TextareaContent extends React.Component<IProps, IState> {
5453
private saveEditAssessment = (e: any) => {
5554
let fieldValue: number | string;
5655
if (this.state.isNumber) {
57-
const range = this.props.numberRange || [0];
5856
fieldValue = parseInt(this.state.fieldValue, 10);
59-
if (isNaN(fieldValue) || fieldValue < range[0]) {
60-
fieldValue = range[0];
61-
} else if (range.length > 1 && fieldValue > range[1]) {
62-
fieldValue = range[1];
57+
if (isNaN(fieldValue)) {
58+
fieldValue = getValueFromPath(this.props.path, this.props.assessment);
6359
}
6460
} else {
6561
fieldValue = this.state.fieldValue;

src/components/incubator/editingWorkspaceSideContent/index.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,17 @@ export const assignToPath = (path: Array<string | number>, value: any, obj: any)
2020
}
2121
obj[path[i]] = value;
2222
};
23+
24+
export const limitNumberRange = (min: number | null = 0, max: number | null = null) => (
25+
value: number
26+
): number => {
27+
let result;
28+
if (min !== null && value < min) {
29+
result = min;
30+
} else if (max !== null && value > max) {
31+
result = max;
32+
} else {
33+
result = value;
34+
}
35+
return result;
36+
};

0 commit comments

Comments
 (0)