@pie-lib/rubric 0.8.32-next.0 → 0.8.32-next.1595

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/authoring.jsx CHANGED
@@ -21,6 +21,8 @@ import takeRight from 'lodash/takeRight';
21
21
  import PointMenu from './point-menu';
22
22
 
23
23
  import range from 'lodash/range';
24
+ import { InputContainer } from '@pie-lib/config-ui';
25
+
24
26
  const log = debug('pie-lib:rubric:authoring');
25
27
 
26
28
  const reorder = (list, startIndex, endIndex) => {
@@ -37,6 +39,7 @@ export const RubricType = PropTypes.shape({
37
39
  points: PropTypes.arrayOf(PropTypes.string),
38
40
  sampleAnswers: PropTypes.arrayOf(PropTypes.string),
39
41
  maxPoints: PropTypes.number,
42
+ rubriclessInstruction: PropTypes.string,
40
43
  });
41
44
 
42
45
  const MaxPoints = withStyles((theme) => ({
@@ -53,7 +56,7 @@ const MaxPoints = withStyles((theme) => ({
53
56
  Max Points
54
57
  </InputLabel>
55
58
  <Select value={value} onChange={(e) => onChange(e.target.value)} input={<OutlinedInput labelWidth={80} />}>
56
- {range(1, max).map((v) => (
59
+ {range(1, max + 1).map((v) => (
57
60
  <MenuItem key={`${v}`} value={v}>
58
61
  {v}
59
62
  </MenuItem>
@@ -94,8 +97,14 @@ export const PointConfig = withStyles((theme) => ({
94
97
  position: 'absolute',
95
98
  right: 0,
96
99
  },
100
+ errorText: {
101
+ fontSize: theme.typography.fontSize - 2,
102
+ color: theme.palette.error.main,
103
+ paddingLeft: theme.spacing.unit * 3,
104
+ paddingTop: theme.spacing.unit,
105
+ },
97
106
  }))((props) => {
98
- const { points, content, classes, sampleAnswer, mathMlOptions = {} } = props;
107
+ const { points, content, classes, sampleAnswer, mathMlOptions = {}, error, pluginOpts = {} } = props;
99
108
  const pointsLabel = `${points} ${points <= 1 ? 'pt' : 'pts'}`;
100
109
  const showSampleAnswer = checkSampleAnswer(sampleAnswer);
101
110
 
@@ -109,6 +118,8 @@ export const PointConfig = withStyles((theme) => ({
109
118
  <DragIndicator className={classes.dragIndicator} />
110
119
  <EditableHtml
111
120
  className={classes.editor}
121
+ error={error}
122
+ pluginProps={pluginOpts}
112
123
  markup={content}
113
124
  onChange={props.onChange}
114
125
  mathMlOptions={mathMlOptions}
@@ -121,7 +132,7 @@ export const PointConfig = withStyles((theme) => ({
121
132
  onChange={props.onMenuChange}
122
133
  />
123
134
  </div>
124
-
135
+ {error && <div className={classes.errorText}>{error}</div>}
125
136
  {!showSampleAnswer && (
126
137
  <div className={classes.sampleAnswersEditor}>
127
138
  <Typography variant="overline" className={classes.dragIndicator}>
@@ -130,6 +141,7 @@ export const PointConfig = withStyles((theme) => ({
130
141
  <EditableHtml
131
142
  className={classes.editor}
132
143
  markup={sampleAnswer}
144
+ pluginProps={pluginOpts}
133
145
  onChange={props.onSampleChange}
134
146
  mathMlOptions={mathMlOptions}
135
147
  />
@@ -144,6 +156,9 @@ export class RawAuthoring extends React.Component {
144
156
  classes: PropTypes.object.isRequired,
145
157
  className: PropTypes.string,
146
158
  value: RubricType,
159
+ config: PropTypes.object,
160
+ pluginOpts: PropTypes.object,
161
+ rubricless: PropTypes.bool,
147
162
  onChange: PropTypes.func,
148
163
  };
149
164
 
@@ -162,8 +177,13 @@ export class RawAuthoring extends React.Component {
162
177
  onChange({ ...value, points, sampleAnswers });
163
178
  };
164
179
 
165
- changeMaxPoints = (maxPoints) => {
180
+ changeRubriclessInstruction = (input) => {
166
181
  const { value, onChange } = this.props;
182
+ onChange({ ...value, rubriclessInstruction: input });
183
+ };
184
+
185
+ changeMaxPoints = (maxPoints) => {
186
+ const { value, onChange, rubricless } = this.props;
167
187
  const currentMax = value.points.length - 1;
168
188
 
169
189
  log('current', currentMax, 'new: ', maxPoints);
@@ -184,8 +204,10 @@ export class RawAuthoring extends React.Component {
184
204
  sampleAnswers = takeRight(value.sampleAnswers, maxPoints + 1);
185
205
  }
186
206
 
187
- if (points) {
188
- onChange({ ...value, points, sampleAnswers });
207
+ if (points && !rubricless) {
208
+ onChange({ ...value, points, sampleAnswers, maxPoints });
209
+ } else {
210
+ onChange({ ...value, maxPoints });
189
211
  }
190
212
  };
191
213
 
@@ -242,21 +264,47 @@ export class RawAuthoring extends React.Component {
242
264
  };
243
265
 
244
266
  render() {
245
- const { classes, className, value, mathMlOptions = {} } = this.props;
246
- let { excludeZeroEnabled = true, maxPointsEnabled = true } = value || {};
247
-
267
+ const {
268
+ classes,
269
+ className,
270
+ value,
271
+ mathMlOptions = {},
272
+ config = {},
273
+ rubricless = false,
274
+ pluginOpts = {},
275
+ } = this.props;
276
+ let {
277
+ excludeZeroEnabled = true,
278
+ maxPointsEnabled = true,
279
+ errors = {},
280
+ rubriclessInstructionEnabled = false,
281
+ maxPoints = 10,
282
+ } = value || {};
283
+ // rubric will contain a max value for maxPoints
284
+ const { rubriclessInstruction = {}, maxMaxPoints = 10 } = config || {};
285
+ const { pointsDescriptorsErrors } = errors || {};
248
286
  if (value && Number.isFinite(value.maxPoints)) {
249
287
  // eslint-disable-next-line no-console
250
288
  console.warn('maxPoints is deprecated - remove from model');
251
289
  }
252
290
 
291
+ // for rubric value is computed based on points
292
+ const maxPointsValue = !rubricless ? value.points.length - 1 : maxPoints;
293
+
253
294
  return (
254
295
  <div className={classNames(classes.class, className)}>
255
296
  <Typography variant="h5" className={classes.rubricTitle}>
256
297
  Rubric
257
298
  </Typography>
258
299
  <FormGroup row>
259
- {maxPointsEnabled && <MaxPoints max={10} value={value.points.length - 1} onChange={this.changeMaxPoints} />}
300
+ {maxPointsEnabled && (
301
+ <MaxPoints
302
+ max={maxMaxPoints < 100 ? maxMaxPoints : 100}
303
+ value={maxPointsValue}
304
+ onChange={this.changeMaxPoints}
305
+ pluginOpts={pluginOpts}
306
+ />
307
+ )}
260
308
  {excludeZeroEnabled && (
261
309
  <FormControlLabel
262
310
  label="Exclude zeros"
@@ -265,7 +313,22 @@ export class RawAuthoring extends React.Component {
265
313
  )}
266
314
  </FormGroup>
267
315
 
268
- <div className={classes.container}>
316
+ {rubriclessInstructionEnabled && rubricless && (
317
+ <InputContainer label={rubriclessInstruction.label} className={classes.inputContainer}>
318
+ <EditableHtml
319
+ className={classes.input}
320
+ markup={value.rubriclessInstruction || ''}
321
+ onChange={this.changeRubriclessInstruction}
322
+ pluginProps={pluginOpts}
323
+ nonEmpty={false}
324
+ disableUnderline
325
+ languageCharactersProps={[{ language: 'spanish' }, { language: 'special' }]}
326
+ mathMlOptions={mathMlOptions}
327
+ />
328
+ </InputContainer>
329
+ )}
330
+
331
+ <div className={rubricless ? classes.rubricless : classes.container}>
269
332
  <DragDropContext onDragEnd={this.dragEnd}>
270
333
  <Droppable droppableId="droppable">
271
334
  {(provided) => (
@@ -284,11 +347,15 @@ export class RawAuthoring extends React.Component {
284
347
  <PointConfig
285
348
  points={value.points.length - 1 - index}
286
349
  content={p}
350
+ error={
351
+ pointsDescriptorsErrors && pointsDescriptorsErrors[value.points.length - 1 - index]
352
+ }
287
353
  sampleAnswer={value.sampleAnswers && value.sampleAnswers[index]}
288
354
  onChange={(content) => this.changeContent(index, content, 'points')}
289
355
  onSampleChange={(content) => this.changeContent(index, content, 'sampleAnswers')}
290
356
  onMenuChange={(clickedItem) => this.onPointMenuChange(index, clickedItem)}
291
357
  mathMlOptions={mathMlOptions}
358
+ pluginOpts={pluginOpts}
292
359
  />
293
360
  </div>
294
361
  )}
@@ -315,6 +382,14 @@ const styles = (theme) => ({
315
382
  padding: theme.spacing.unit * 2,
316
383
  margin: theme.spacing.unit,
317
384
  },
385
+ inputContainer: {
386
+ width: '100%',
387
+ paddingTop: theme.spacing.unit * 2,
388
+ marginBottom: theme.spacing.unit * 2,
389
+ },
390
+ rubricless: {
391
+ display: 'none',
392
+ },
318
393
  configHolder: {
319
394
  paddingTop: theme.spacing.unit,
320
395
  paddingBottom: theme.spacing.unit,
@@ -328,6 +403,7 @@ const styles = (theme) => ({
328
403
  const StyledRawAuthoring = withStyles(styles)(RawAuthoring);
329
404
 
330
405
  const Reverse = (props) => {
406
+ const { rubricless = false, config = {}, pluginOpts = {} } = props || {};
331
407
  const points = Array.from(props.value.points || []).reverse();
332
408
  let sampleAnswers = Array.from(props.value.sampleAnswers || []).reverse();
333
409
 
@@ -347,11 +423,22 @@ const Reverse = (props) => {
347
423
  });
348
424
  };
349
425
 
350
- return <StyledRawAuthoring value={value} onChange={onChange} />;
426
+ return (
427
+ <StyledRawAuthoring
428
+ value={value}
429
+ config={config}
430
+ onChange={onChange}
431
+ rubricless={rubricless}
432
+ pluginOpts={pluginOpts}
433
+ />
434
+ );
351
435
  };
352
436
 
353
437
  Reverse.propTypes = {
354
438
  value: RubricType,
439
+ config: PropTypes.object,
440
+ pluginOpts: PropTypes.object,
441
+ rubricless: PropTypes.bool,
355
442
  getIndex: PropTypes.func,
356
443
  onChange: PropTypes.func,
357
444
  };
package/src/index.js CHANGED
@@ -3,6 +3,7 @@ import Authoring from './authoring';
3
3
  const RUBRIC_TYPES = {
4
4
  SIMPLE_RUBRIC: 'simpleRubric',
5
5
  MULTI_TRAIT_RUBRIC: 'multiTraitRubric',
6
+ RUBRICLESS: 'rubricless',
6
7
  };
7
8
 
8
9
  export { Authoring, RUBRIC_TYPES };