Skip to content

Commit

Permalink
Merge pull request #1251 from isaacphysics/feature/nd-coordinate-qs
Browse files Browse the repository at this point in the history
Support n-dimensional coord Qs
  • Loading branch information
jsharkey13 authored Jan 28, 2025
2 parents 4089610 + 65af241 commit fd8b29a
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 39 deletions.
7 changes: 3 additions & 4 deletions src/IsaacApiTypes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,8 @@ export interface IsaacSymbolicQuestionDTO extends QuestionDTO {

export interface IsaacCoordinateQuestionDTO extends QuestionDTO {
numberOfCoordinates?: number;
placeholderXValue?: string;
placeholderYValue?: string;
numberOfDimensions?: number;
placeholderValues?: string[];
}

export interface IsaacTopicSummaryPageDTO extends SeguePageDTO {
Expand Down Expand Up @@ -513,8 +513,7 @@ export interface ParsonsItemDTO extends ItemDTO {
}

export interface CoordinateItemDTO extends ItemDTO {
x?: string;
y?: string;
coordinates?: string[];
}

export interface QuantityDTO extends ChoiceDTO {
Expand Down
62 changes: 27 additions & 35 deletions src/app/components/content/IsaacCoordinateQuestion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,17 @@ import {IsaacQuestionProps} from "../../../IsaacAppTypes";
import {Immutable} from "immer";
import QuestionInputValidation from "../elements/inputs/QuestionInputValidation";

// Custom input component for coordinates - a pair of inputs, one for x and one for y, formatted with brackets
// and a comma in between.
// Custom input component for coordinates
interface CoordinateInputProps {
value: Immutable<CoordinateItemDTO>;
placeholderXValue?: string;
placeholderYValue?: string;
placeholderValues: string[];
numberOfDimensions: number;
onChange: (value: Immutable<CoordinateItemDTO>) => void;
readonly?: boolean;
remove?: () => void;
}

export const coordinateInputValidator = (input: string[][]) => {
export const coordinateInputValidator = (input: (readonly string[])[]) => {
const errors: string[] = [];
const allBadChars: string[] = [];
let containsComma = false;
Expand Down Expand Up @@ -51,32 +50,25 @@ export const coordinateInputValidator = (input: string[][]) => {
};

const CoordinateInput = (props: CoordinateInputProps) => {
const {value, placeholderXValue, placeholderYValue, onChange, readonly, remove} = props;
return <span className="coordinate-input">
(
<Input
type="text"
className="force-print"
placeholder={placeholderXValue ?? "x"}
value={value.x ?? ""}
onChange={event => onChange({...value, x: event.target.value === "" ? undefined : event.target.value})}
readOnly={readonly}
/>
<span className="coordinate-input-separator">,&nbsp;</span>
<Input
type="text"
className="force-print"
placeholder={placeholderYValue ?? "y"}
value={value.y ?? ""}
onChange={event => onChange({...value, y: event.target.value === "" ? undefined : event.target.value})}
readOnly={readonly}
/>
)
{remove && <Button className="ms-3" size="sm" onClick={remove}>Delete</Button>}
const {value, placeholderValues, numberOfDimensions, onChange, readonly, remove} = props;
return <span className="coordinate-input">({[...Array(numberOfDimensions)].map((_, i) =>
<span key={i}>
<Input
type="text"
className="force-print"
placeholder={placeholderValues[i] ?? ""}
value={isDefined(value.coordinates?.[i]) ? value.coordinates[i] : ""}
onChange={event => onChange({...value, coordinates: value.coordinates && value.coordinates.length ? value.coordinates.with(i, event.target.value) :
(event.target.value === "" ? undefined : Array<string>(numberOfDimensions).fill("").with(i, event.target.value))})}
readOnly={readonly}
/>
{(i < numberOfDimensions - 1) && <span className="coordinate-input-separator">,&nbsp;</span>}
</span>)})
{remove && <Button className="ms-3" size="sm" onClick={remove}>Delete</Button>}
</span>;
};

const DEFAULT_COORDINATE_ITEM = {type: "coordinateItem", x: undefined, y: undefined};
const DEFAULT_COORDINATE_ITEM = {type: "coordinateItem", coordinates: []};

const IsaacCoordinateQuestion = ({doc, questionId, readonly}: IsaacQuestionProps<IsaacCoordinateQuestionDTO>) => {

Expand Down Expand Up @@ -110,8 +102,8 @@ const IsaacCoordinateQuestion = ({doc, questionId, readonly}: IsaacQuestionProps
? Array.from({length: doc.numberOfCoordinates}).map((_, index) =>
<CoordinateInput
key={index}
placeholderXValue={doc.placeholderXValue}
placeholderYValue={doc.placeholderYValue}
placeholderValues={doc.placeholderValues ?? []}
numberOfDimensions={doc.numberOfDimensions ?? 1}
value={currentAttempt?.items?.[index] ?? {...DEFAULT_COORDINATE_ITEM}}
readonly={readonly}
onChange={value => updateItem(index, value)}
Expand All @@ -121,8 +113,8 @@ const IsaacCoordinateQuestion = ({doc, questionId, readonly}: IsaacQuestionProps
{currentAttempt?.items?.map((item, index) =>
<CoordinateInput
key={index}
placeholderXValue={doc.placeholderXValue}
placeholderYValue={doc.placeholderYValue}
placeholderValues={doc.placeholderValues ?? []}
numberOfDimensions={doc.numberOfDimensions ?? 1}
value={item}
readonly={readonly}
onChange={value => updateItem(index, value)}
Expand All @@ -132,14 +124,14 @@ const IsaacCoordinateQuestion = ({doc, questionId, readonly}: IsaacQuestionProps
</>
: <CoordinateInput
key={0}
placeholderXValue={doc.placeholderXValue}
placeholderYValue={doc.placeholderYValue}
placeholderValues={doc.placeholderValues ?? []}
numberOfDimensions={doc.numberOfDimensions ?? 1}
value={{...DEFAULT_COORDINATE_ITEM}}
readonly={readonly}
onChange={value => updateItem(0, value)}
/>
}
<QuestionInputValidation userInput={currentAttempt?.items?.map(answer => [answer.x ?? "", answer.y ?? ""]) ?? []} validator={coordinateInputValidator}/>
<QuestionInputValidation userInput={currentAttempt?.items?.map(answer => answer.coordinates ?? []) ?? []} validator={coordinateInputValidator}/>
{!doc.numberOfCoordinates && <Button color="secondary" size="sm" className="mt-3" onClick={() => updateItem(currentAttempt?.items?.length ?? 1, {...DEFAULT_COORDINATE_ITEM})}>Add coordinate</Button>}
</div>;
};
Expand Down

0 comments on commit fd8b29a

Please sign in to comment.