diff --git a/packages/demo/config/load-links.js b/packages/demo/config/load-links.js
index 3f1fc80e3..9f51a45b4 100644
--- a/packages/demo/config/load-links.js
+++ b/packages/demo/config/load-links.js
@@ -18,7 +18,6 @@ const rawLinks = [
{ label: 'math-rendering', path: '/math-rendering' },
{ label: 'math-toolbar', path: '/math-toolbar' },
{ label: 'render-ui', path: '/render-ui' },
- { label: 'rubric', path: '/rubric' },
{ label: 'scoring-config', path: '/scoring-config' },
{ label: 'text-select', path: '/text-select' },
{ label: 'text-select math', path: '/text-select-math' },
diff --git a/packages/demo/pages/rubric/index.js b/packages/demo/pages/rubric/index.js
deleted file mode 100644
index 69261fd47..000000000
--- a/packages/demo/pages/rubric/index.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import { Authoring } from '@pie-lib/pie-toolbox/rubric';
-import React from 'react';
-import withRoot from '../../source/withRoot';
-import { withStyles } from '@material-ui/core';
-import Section from '../../source/formatting/section';
-import Pre from '../../source/formatting/pre';
-
-class Demo extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- rubric: {
- excludeZero: false,
- // the index is the points
- points: ['nothing right', 'a teeny bit right', 'mostly right', 'bingo'],
- // if the value is null or 'null', the Sample Answer input field for that point will not be dispalyed
- // if the value is '', the Sample Answer input field will be empty
- sampleAnswers: [null, 'just right', 'not left', null],
- },
- };
- }
-
- componentDidMount() {
- this.setState({ mounted: true });
- }
-
- render() {
- const { mounted, rubric } = this.state;
- // TODO: check similar comps to see what they support...
- return mounted ? (
-
-
-
- this.setState({ rubric })} />
-
-
-
- ) : (
-
- );
- }
-}
-
-const Styled = withStyles((theme) => ({}))(Demo);
-
-export default withRoot(Styled);
diff --git a/packages/pie-toolbox/src/code/rubric/__tests__/__snapshots__/rubric.test.jsx.snap b/packages/pie-toolbox/src/code/rubric/__tests__/__snapshots__/rubric.test.jsx.snap
deleted file mode 100644
index 46d73199c..000000000
--- a/packages/pie-toolbox/src/code/rubric/__tests__/__snapshots__/rubric.test.jsx.snap
+++ /dev/null
@@ -1,48 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Rubric render snapshot 1`] = `
-
-
- Rubric
-
-
-
-
- }
- label="Exclude zeros"
- />
-
-
-
-
-
-
-
-
-
-`;
diff --git a/packages/pie-toolbox/src/code/rubric/__tests__/rubric.test.jsx b/packages/pie-toolbox/src/code/rubric/__tests__/rubric.test.jsx
deleted file mode 100644
index 7033bc74a..000000000
--- a/packages/pie-toolbox/src/code/rubric/__tests__/rubric.test.jsx
+++ /dev/null
@@ -1,91 +0,0 @@
-import { shallow, mount } from 'enzyme';
-import React from 'react';
-import { RawAuthoring } from '../authoring';
-import { Draggable } from 'react-beautiful-dnd';
-import _ from 'lodash';
-
-jest.mock('../../editable-html', () => () => );
-
-describe('Rubric', () => {
- let w;
-
- const points = ['nothing right', 'a teeny bit right', 'mostly right', 'bingo'];
- const sampleAnswers = [null, 'just right', 'not left', null];
- const wrapper = (value, opts) => {
- const props = {
- classes: {},
- onChange: jest.fn(),
- className: 'className',
- value: {
- excludeZero: false,
- points,
- sampleAnswers,
- ...value,
- },
- };
- const fn = opts && opts.mount ? mount : shallow;
- return fn(, opts);
- };
-
- describe('render', () => {
- it('snapshot', () => {
- w = wrapper();
- expect(w).toMatchSnapshot();
- });
-
- describe('draggable', () => {
- it('renders correctly for excluded zeroes', () => {
- let w = wrapper({ excludeZero: true }, { mount: true });
- expect(w.find(Draggable).length).toEqual(3);
- });
- it('renders correctly for excluded zeroes', () => {
- let w = wrapper({ excludeZero: false }, { mount: true });
- expect(w.find(Draggable).length).toEqual(4);
- });
- });
- });
-
- describe('logic', () => {
- describe('rendering', () => {});
-
- describe('changeMaxPoints', () => {
- const assertChangeMax = (points, excludeZero, expectedPoints, expectedSampleAnswers) => {
- it(`${points} calls onChange with: ${expectedPoints} and ${expectedSampleAnswers}`, () => {
- let w = wrapper({ excludeZero });
- w.instance().changeMaxPoints(points);
- expect(w.instance().props.onChange).toHaveBeenCalledWith({
- excludeZero,
- points: expectedPoints,
- sampleAnswers: expectedSampleAnswers,
- maxPoints: expectedPoints.length - 1,
- });
- });
- };
-
- assertChangeMax(1, false, _.takeRight(points, 2), _.takeRight(sampleAnswers, 2));
- assertChangeMax(1, true, _.takeRight(points, 2), _.takeRight(sampleAnswers, 2));
- assertChangeMax(2, true, _.takeRight(points, 3), _.takeRight(sampleAnswers, 3));
- assertChangeMax(2, false, _.takeRight(points, 3), _.takeRight(sampleAnswers, 3));
- assertChangeMax(5, false, ['', ''].concat(points), [null, null].concat(sampleAnswers));
- });
-
- describe('changeSampleResponse', () => {
- const assertChangeSample = (index, clickedItem, excludeZero, expectedPoints, expectedSampleAnswers) => {
- it(`Point ${index} calls onChange with: ${expectedPoints} and ${expectedSampleAnswers}`, () => {
- let w = wrapper({ excludeZero });
- w.instance().onPointMenuChange(index, clickedItem);
- expect(w.instance().props.onChange).toHaveBeenCalledWith({
- excludeZero,
- points: expectedPoints,
- sampleAnswers: expectedSampleAnswers,
- });
- });
- };
-
- assertChangeSample(0, 'sample', false, points, ['', 'just right', 'not left', null]);
- assertChangeSample(3, 'sample', false, points, [null, 'just right', 'not left', '']);
- assertChangeSample(1, 'sample', true, points, [null, null, 'not left', null]);
- assertChangeSample(3, 'sample', true, points, [null, 'just right', 'not left', '']);
- });
- });
-});
diff --git a/packages/pie-toolbox/src/code/rubric/authoring.jsx b/packages/pie-toolbox/src/code/rubric/authoring.jsx
deleted file mode 100644
index 23a3649de..000000000
--- a/packages/pie-toolbox/src/code/rubric/authoring.jsx
+++ /dev/null
@@ -1,446 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { withStyles } from '@material-ui/core/styles';
-import classNames from 'classnames';
-import OutlinedInput from '@material-ui/core/OutlinedInput';
-import InputLabel from '@material-ui/core/InputLabel';
-import Select from '@material-ui/core/Select';
-import FormControl from '@material-ui/core/FormControl';
-import MenuItem from '@material-ui/core/MenuItem';
-import times from 'lodash/times';
-import Checkbox from '@material-ui/core/Checkbox';
-import FormGroup from '@material-ui/core/FormGroup';
-import FormControlLabel from '@material-ui/core/FormControlLabel';
-import grey from '@material-ui/core/colors/grey';
-import Typography from '@material-ui/core/Typography';
-import DragIndicator from '@material-ui/icons/DragIndicator';
-import EditableHtml from '../editable-html';
-import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
-import debug from 'debug';
-import takeRight from 'lodash/takeRight';
-import PointMenu from './point-menu';
-
-import range from 'lodash/range';
-import { InputContainer } from '../config-ui';
-
-const log = debug('pie-lib:rubric:authoring');
-
-const reorder = (list, startIndex, endIndex) => {
- const result = Array.from(list);
- const [removed] = result.splice(startIndex, 1);
-
- result.splice(endIndex, 0, removed);
-
- return result;
-};
-
-export const RubricType = PropTypes.shape({
- excludeZero: PropTypes.bool,
- points: PropTypes.arrayOf(PropTypes.string),
- sampleAnswers: PropTypes.arrayOf(PropTypes.string),
- maxPoints: PropTypes.number,
- rubriclessInstruction: PropTypes.string,
-});
-
-const MaxPoints = withStyles((theme) => ({
- formControl: {
- minWidth: '120px',
- margin: theme.spacing.unit,
- },
-}))((props) => {
- const { value, onChange, max, classes } = props;
-
- return (
-
-
- Max Points
-
-
-
- );
-});
-
-// if the value is null or 'null', the Sample Answer input field for that point will not be dispalyed
-// if the value is '', the Sample Answer input field will be empty
-const checkSampleAnswer = (sampleAnswer) => sampleAnswer === null || sampleAnswer === 'null';
-
-export const PointConfig = withStyles((theme) => ({
- pointConfig: {},
- row: {
- display: 'flex',
- width: '100%',
- position: 'relative',
- },
- editor: {
- width: '100%',
- backgroundColor: `${theme.palette.common.white} !important`,
- },
- dragIndicator: {
- paddingTop: theme.spacing.unit,
- color: grey[500],
- },
- pointsLabel: {
- color: grey[500],
- paddingBottom: theme.spacing.unit,
- textTransform: 'uppercase',
- },
- sampleAnswersEditor: {
- paddingLeft: theme.spacing.unit * 3,
- },
- pointMenu: {
- position: 'absolute',
- right: 0,
- },
- errorText: {
- fontSize: theme.typography.fontSize - 2,
- color: theme.palette.error.main,
- paddingLeft: theme.spacing.unit * 3,
- paddingTop: theme.spacing.unit,
- },
-}))((props) => {
- const { points, content, classes, sampleAnswer, mathMlOptions = {}, error, pluginOpts = {} } = props;
- const pointsLabel = `${points} ${points <= 1 ? 'pt' : 'pts'}`;
- const showSampleAnswer = checkSampleAnswer(sampleAnswer);
-
- return (
-
-
- {pointsLabel}
-
-
-
- {error &&
{error}
}
- {!showSampleAnswer && (
-
-
- Sample Response
-
-
-
- )}
-
- );
-});
-
-export class RawAuthoring extends React.Component {
- static propTypes = {
- classes: PropTypes.object.isRequired,
- className: PropTypes.string,
- value: RubricType,
- config: PropTypes.object,
- pluginOpts: PropTypes.object,
- rubricless: PropTypes.bool,
- onChange: PropTypes.func,
- };
-
- static defaultProps = {};
-
- dragEnd = (result) => {
- if (!result.destination) {
- return;
- }
-
- const { value, onChange } = this.props;
-
- const points = reorder(value.points, result.source.index, result.destination.index);
- const sampleAnswers = reorder(value.sampleAnswers, result.source.index, result.destination.index);
-
- onChange({ ...value, points, sampleAnswers });
- };
-
- changeRubriclessInstruction = (input) => {
- const { value, onChange } = this.props;
- onChange({ ...value, rubriclessInstruction: input });
- };
-
- changeMaxPoints = (maxPoints) => {
- const { value, onChange, rubricless } = this.props;
- const currentMax = value.points.length - 1;
-
- log('current', currentMax, 'new: ', maxPoints);
-
- let points, sampleAnswers;
- if (maxPoints > currentMax) {
- points = times(maxPoints - currentMax)
- .map(() => '')
- .concat(value.points);
- sampleAnswers = times(maxPoints - currentMax)
- .map(() => null)
- .concat(value.sampleAnswers);
- }
-
- if (maxPoints < currentMax) {
- log('less than');
- points = takeRight(value.points, maxPoints + 1);
- sampleAnswers = takeRight(value.sampleAnswers, maxPoints + 1);
- }
-
- if (points && !rubricless) {
- onChange({ ...value, points, sampleAnswers, maxPoints });
- } else {
- onChange({ ...value, maxPoints });
- }
- };
-
- changeContent = (index, content, type) => {
- // type could be 'points' or 'sampleAnswers'
- log(`changeModel[${type}]:`, index, content);
-
- if (type !== 'points' && type !== 'sampleAnswers') {
- return;
- }
-
- const { value, onChange } = this.props;
- const items = value[type] && Array.from(value[type]);
-
- items.splice(index, 1, content);
- log(`changeModel[${type}]:`, items);
-
- onChange({ ...value, [type]: items });
- };
-
- excludeZeros = () => {
- const { value, onChange } = this.props;
-
- onChange({ ...value, excludeZero: !value.excludeZero });
- };
-
- shouldRenderPoint = (index, value) => {
- if (!value.excludeZero) {
- return true;
- } else {
- if (index < value.points.length - 1) {
- return true;
- } else if (index === value.points.length - 1) {
- return false;
- }
-
- return true;
- }
- };
-
- onPointMenuChange = (index, clickedItem) => {
- if (clickedItem === 'sample') {
- const { value } = this.props;
- const sampleAnswers = Array.from(value.sampleAnswers || []);
-
- if (checkSampleAnswer(sampleAnswers[index])) {
- // an empty string will display an empty Sample Answer input field
- this.changeContent(index, '', 'sampleAnswers');
- } else {
- // when the content is null or 'null', the Sample Answer input field will not be displayed
- this.changeContent(index, null, 'sampleAnswers');
- }
- }
- };
-
- render() {
- const {
- classes,
- className,
- value,
- mathMlOptions = {},
- config = {},
- rubricless = false,
- pluginOpts = {},
- } = this.props;
- let {
- excludeZeroEnabled = true,
- maxPointsEnabled = true,
- errors = {},
- rubriclessInstructionEnabled = false,
- maxPoints = 10,
- } = value || {};
- // rubric will contain a max value for maxPoints
- const { rubriclessInstruction = {}, maxMaxPoints = 10 } = config || {};
- const { pointsDescriptorsErrors } = errors || {};
- if (value && Number.isFinite(value.maxPoints)) {
- // eslint-disable-next-line no-console
- console.warn('maxPoints is deprecated - remove from model');
- }
-
- // for rubric value is computed based on points
- const maxPointsValue = !rubricless ? value.points.length - 1 : maxPoints;
-
- return (
-
-
- Rubric
-
-
- {maxPointsEnabled && (
-
- )}
- {excludeZeroEnabled && (
- }
- />
- )}
-
-
- {rubriclessInstructionEnabled && rubricless && (
-
-
-
- )}
-
-
-
-
- {(provided) => (
-
- {value.points.map(
- (p, index) =>
- this.shouldRenderPoint(index, value) && (
-
- {(provided) => (
-
-
this.changeContent(index, content, 'points')}
- onSampleChange={(content) => this.changeContent(index, content, 'sampleAnswers')}
- onMenuChange={(clickedItem) => this.onPointMenuChange(index, clickedItem)}
- mathMlOptions={mathMlOptions}
- pluginOpts={pluginOpts}
- />
-
- )}
-
- ),
- )}
- {provided.placeholder}
-
- )}
-
-
-
-
- );
- }
-}
-
-const styles = (theme) => ({
- container: {
- backgroundColor: grey[200],
- borderWidth: 1,
- borderStyle: 'solid',
- borderColor: grey[300],
- padding: theme.spacing.unit * 2,
- margin: theme.spacing.unit,
- },
- inputContainer: {
- width: '100%',
- paddingTop: theme.spacing.unit * 2,
- marginBottom: theme.spacing.unit * 2,
- },
- rubricless: {
- display: 'none',
- },
- configHolder: {
- paddingTop: theme.spacing.unit,
- paddingBottom: theme.spacing.unit,
- },
- rubricTitle: {
- paddingLeft: theme.spacing.unit,
- margin: theme.spacing.unit,
- },
-});
-
-const StyledRawAuthoring = withStyles(styles)(RawAuthoring);
-
-const Reverse = (props) => {
- const { rubricless = false, config = {}, pluginOpts = {} } = props || {};
- const points = Array.from(props.value.points || []).reverse();
- let sampleAnswers = Array.from(props.value.sampleAnswers || []).reverse();
-
- if (points.length > sampleAnswers.length) {
- sampleAnswers = times(points.length - sampleAnswers.length)
- .map(() => null)
- .concat(sampleAnswers);
- }
-
- const value = { ...props.value, points, sampleAnswers };
-
- const onChange = (value) => {
- props.onChange({
- ...value,
- points: Array.from(value.points || []).reverse(),
- sampleAnswers: Array.from(value.sampleAnswers || []).reverse(),
- });
- };
-
- return (
-
- );
-};
-
-Reverse.propTypes = {
- value: RubricType,
- config: PropTypes.object,
- pluginOpts: PropTypes.object,
- rubricless: PropTypes.bool,
- getIndex: PropTypes.func,
- onChange: PropTypes.func,
-};
-
-export default Reverse;
diff --git a/packages/pie-toolbox/src/code/rubric/index.js b/packages/pie-toolbox/src/code/rubric/index.js
deleted file mode 100644
index fcf988b48..000000000
--- a/packages/pie-toolbox/src/code/rubric/index.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import Authoring from './authoring';
-
-const RUBRIC_TYPES = {
- SIMPLE_RUBRIC: 'simpleRubric',
- MULTI_TRAIT_RUBRIC: 'multiTraitRubric',
- RUBRICLESS: 'rubricless',
-};
-
-export { Authoring, RUBRIC_TYPES };
diff --git a/packages/pie-toolbox/src/code/rubric/point-menu.jsx b/packages/pie-toolbox/src/code/rubric/point-menu.jsx
deleted file mode 100644
index 26454b7fc..000000000
--- a/packages/pie-toolbox/src/code/rubric/point-menu.jsx
+++ /dev/null
@@ -1,94 +0,0 @@
-import Menu from '@material-ui/core/Menu';
-import MenuItem from '@material-ui/core/MenuItem';
-import MoreVertIcon from '@material-ui/icons/MoreVert';
-import MoreHorizIcon from '@material-ui/icons/MoreHoriz';
-import IconButton from '@material-ui/core/IconButton';
-import PropTypes from 'prop-types';
-import React from 'react';
-
-export class IconMenu extends React.Component {
- static propTypes = {
- opts: PropTypes.object,
- onClick: PropTypes.func.isRequired,
- classes: PropTypes.object.isRequired,
- };
-
- constructor(props) {
- super(props);
- this.state = {
- anchorEl: undefined,
- open: false,
- };
- }
-
- handleClick = (event) => this.setState({ open: true, anchorEl: event.currentTarget });
-
- handleRequestClose = () => this.setState({ open: false });
-
- render() {
- const { opts, onClick, classes } = this.props;
- const { open, anchorEl } = this.state;
- const keys = Object.keys(opts) || [];
-
- const handleMenuClick = (key) => () => {
- onClick(key);
- this.handleRequestClose();
- };
-
- const iconColor = open ? 'inherit' : 'disabled';
-
- return (
-
-
-
- {open ? : }
-
-
-
-
- );
- }
-}
-
-export default class PointMenu extends React.Component {
- static propTypes = {
- onChange: PropTypes.func.isRequired,
- classes: PropTypes.object.isRequired,
- showSampleAnswer: PropTypes.bool.isRequired,
- };
-
- static defaultProps = {
- classes: {},
- };
-
- render() {
- const { onChange, classes, showSampleAnswer } = this.props;
- const sampleText = showSampleAnswer ? 'Provide Sample Response' : 'Remove Sample Response';
-
- return (
- onChange(key)}
- opts={{
- sample: sampleText,
- }}
- classes={classes}
- />
- );
- }
-}
diff --git a/packages/pie-toolbox/src/rubric.js b/packages/pie-toolbox/src/rubric.js
deleted file mode 100644
index 630c5a95a..000000000
--- a/packages/pie-toolbox/src/rubric.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import { Authoring, RUBRIC_TYPES } from './code/rubric';
-
-export { Authoring, RUBRIC_TYPES };