mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
Merge pull request #127 from ets-cfuhrman-pfe/fuhrmanator/issue79
Fuhrmanator/issue79
This commit is contained in:
commit
fd68131e9d
20 changed files with 274 additions and 286 deletions
370
client/package-lock.json
generated
370
client/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -31,7 +31,6 @@
|
||||||
"nanoid": "^5.0.2",
|
"nanoid": "^5.0.2",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-latex": "^2.0.0",
|
|
||||||
"react-modal": "^3.16.1",
|
"react-modal": "^3.16.1",
|
||||||
"react-router-dom": "^6.26.2",
|
"react-router-dom": "^6.26.2",
|
||||||
"remark-math": "^6.0.0",
|
"remark-math": "^6.0.0",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// TextType.test.ts
|
// TextType.test.ts
|
||||||
|
|
||||||
import { TextFormat } from "gift-pegjs";
|
import { TextFormat } from "gift-pegjs";
|
||||||
import TextType from "../../../components/GiftTemplate/templates/TextType";
|
import textType from "../../../components/GiftTemplate/templates/TextType";
|
||||||
|
|
||||||
describe('TextType', () => {
|
describe('TextType', () => {
|
||||||
it('should format text with basic characters correctly', () => {
|
it('should format text with basic characters correctly', () => {
|
||||||
|
|
@ -10,7 +10,7 @@ describe('TextType', () => {
|
||||||
format: 'plain'
|
format: 'plain'
|
||||||
};
|
};
|
||||||
const expectedOutput = 'Hello, world! 5 > 3, right?';
|
const expectedOutput = 'Hello, world! 5 > 3, right?';
|
||||||
expect(TextType({ text: input })).toBe(expectedOutput);
|
expect(textType({ text: input })).toBe(expectedOutput);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should format text with newlines correctly', () => {
|
it('should format text with newlines correctly', () => {
|
||||||
|
|
@ -19,7 +19,7 @@ describe('TextType', () => {
|
||||||
format: 'plain'
|
format: 'plain'
|
||||||
};
|
};
|
||||||
const expectedOutput = 'Hello,<br>world!<br>5 > 3, right?';
|
const expectedOutput = 'Hello,<br>world!<br>5 > 3, right?';
|
||||||
expect(TextType({ text: input })).toBe(expectedOutput);
|
expect(textType({ text: input })).toBe(expectedOutput);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should format text with LaTeX correctly', () => {
|
it('should format text with LaTeX correctly', () => {
|
||||||
|
|
@ -33,7 +33,7 @@ describe('TextType', () => {
|
||||||
// by running the test and copying the "Received string:" in jest output
|
// by running the test and copying the "Received string:" in jest output
|
||||||
// when it fails (assuming the output is correct)
|
// when it fails (assuming the output is correct)
|
||||||
const expectedOutput = '<span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>E</mi><mo>=</mo><mi>m</mi><msup><mi>c</mi><mn>2</mn></msup></mrow><annotation encoding=\"application/x-tex\">E=mc^2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">E</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8641em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mord\"><span class=\"mord mathnormal\">c</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span></span></span></span></span>';
|
const expectedOutput = '<span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>E</mi><mo>=</mo><mi>m</mi><msup><mi>c</mi><mn>2</mn></msup></mrow><annotation encoding=\"application/x-tex\">E=mc^2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">E</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8641em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mord\"><span class=\"mord mathnormal\">c</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span></span></span></span></span>';
|
||||||
expect(TextType({ text: input })).toContain(expectedOutput);
|
expect(textType({ text: input })).toContain(expectedOutput);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should format text with two equations (inline and separate) correctly', () => {
|
it('should format text with two equations (inline and separate) correctly', () => {
|
||||||
|
|
@ -43,7 +43,7 @@ describe('TextType', () => {
|
||||||
};
|
};
|
||||||
// hint: katex-display is the class that indicates a separate equation
|
// hint: katex-display is the class that indicates a separate equation
|
||||||
const expectedOutput = '<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>a</mi><mo>+</mo><mi>b</mi><mo>=</mo><mi>c</mi></mrow><annotation encoding=\"application/x-tex\">a + b = c</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">a</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">c</span></span></span></span> ? <span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>E</mi><mo>=</mo><mi>m</mi><msup><mi>c</mi><mn>2</mn></msup></mrow><annotation encoding=\"application/x-tex\">E=mc^2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">E</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8641em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mord\"><span class=\"mord mathnormal\">c</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span></span></span></span></span>';
|
const expectedOutput = '<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>a</mi><mo>+</mo><mi>b</mi><mo>=</mo><mi>c</mi></mrow><annotation encoding=\"application/x-tex\">a + b = c</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">a</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">c</span></span></span></span> ? <span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>E</mi><mo>=</mo><mi>m</mi><msup><mi>c</mi><mn>2</mn></msup></mrow><annotation encoding=\"application/x-tex\">E=mc^2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05764em;\">E</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8641em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mord\"><span class=\"mord mathnormal\">c</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span></span></span></span></span>';
|
||||||
expect(TextType({ text: input })).toContain(expectedOutput);
|
expect(textType({ text: input })).toContain(expectedOutput);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should format text with a katex matrix correctly', () => {
|
it('should format text with a katex matrix correctly', () => {
|
||||||
|
|
@ -55,7 +55,7 @@ describe('TextType', () => {
|
||||||
format: 'plain'
|
format: 'plain'
|
||||||
};
|
};
|
||||||
const expectedOutput = 'Donnez le déterminant de la matrice suivante.<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow></mrow><annotation encoding=\"application/x-tex\"></annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"></span></span>\\begin{pmatrix}<br> a&b \\\\<br> c&d<br>\\end{pmatrix}';
|
const expectedOutput = 'Donnez le déterminant de la matrice suivante.<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow></mrow><annotation encoding=\"application/x-tex\"></annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"></span></span>\\begin{pmatrix}<br> a&b \\\\<br> c&d<br>\\end{pmatrix}';
|
||||||
expect(TextType({ text: input })).toContain(expectedOutput);
|
expect(textType({ text: input })).toContain(expectedOutput);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should format text with Markdown correctly', () => {
|
it('should format text with Markdown correctly', () => {
|
||||||
|
|
@ -65,7 +65,7 @@ describe('TextType', () => {
|
||||||
};
|
};
|
||||||
// TODO: investigate why the output has an extra newline
|
// TODO: investigate why the output has an extra newline
|
||||||
const expectedOutput = '<strong>Bold</strong>\n';
|
const expectedOutput = '<strong>Bold</strong>\n';
|
||||||
expect(TextType({ text: input })).toBe(expectedOutput);
|
expect(textType({ text: input })).toBe(expectedOutput);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should format text with HTML correctly', () => {
|
it('should format text with HTML correctly', () => {
|
||||||
|
|
@ -74,7 +74,7 @@ describe('TextType', () => {
|
||||||
format: 'html'
|
format: 'html'
|
||||||
};
|
};
|
||||||
const expectedOutput = '<em>yes</em>';
|
const expectedOutput = '<em>yes</em>';
|
||||||
expect(TextType({ text: input })).toBe(expectedOutput);
|
expect(textType({ text: input })).toBe(expectedOutput);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should format plain text correctly', () => {
|
it('should format plain text correctly', () => {
|
||||||
|
|
@ -83,7 +83,7 @@ describe('TextType', () => {
|
||||||
format: 'plain'
|
format: 'plain'
|
||||||
};
|
};
|
||||||
const expectedOutput = 'Just plain text';
|
const expectedOutput = 'Just plain text';
|
||||||
expect(TextType({ text: input })).toBe(expectedOutput);
|
expect(textType({ text: input })).toBe(expectedOutput);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add more tests for other formats if needed
|
// Add more tests for other formats if needed
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { TemplateOptions, Description as DescriptionType } from './types';
|
import { TemplateOptions, Description as DescriptionType } from './types';
|
||||||
import QuestionContainer from './QuestionContainer';
|
import QuestionContainer from './QuestionContainer';
|
||||||
import Title from './Title';
|
import Title from './Title';
|
||||||
import TextType from './TextType';
|
import textType from './TextType';
|
||||||
import { ParagraphStyle } from '../constants';
|
import { ParagraphStyle } from '../constants';
|
||||||
import { state } from '.';
|
import { state } from '.';
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@ export default function Description({ title, stem }: DescriptionOptions): string
|
||||||
type: 'Description',
|
type: 'Description',
|
||||||
title: title
|
title: title
|
||||||
}),
|
}),
|
||||||
`<p style="${ParagraphStyle(state.theme)}">${TextType({
|
`<p style="${ParagraphStyle(state.theme)}">${textType({
|
||||||
text: stem
|
text: stem
|
||||||
})}</p>`
|
})}</p>`
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { TemplateOptions, Essay as EssayType } from './types';
|
import { TemplateOptions, Essay as EssayType } from './types';
|
||||||
import QuestionContainer from './QuestionContainer';
|
import QuestionContainer from './QuestionContainer';
|
||||||
import Title from './Title';
|
import Title from './Title';
|
||||||
import TextType from './TextType';
|
import textType from './TextType';
|
||||||
import GlobalFeedback from './GlobalFeedback';
|
import GlobalFeedback from './GlobalFeedback';
|
||||||
import { ParagraphStyle, TextAreaStyle } from '../constants';
|
import { ParagraphStyle, TextAreaStyle } from '../constants';
|
||||||
import { state } from '.';
|
import { state } from '.';
|
||||||
|
|
@ -15,7 +15,7 @@ export default function Essay({ title, stem, globalFeedback }: EssayOptions): st
|
||||||
type: 'Développement',
|
type: 'Développement',
|
||||||
title: title
|
title: title
|
||||||
}),
|
}),
|
||||||
`<p style="${ParagraphStyle(state.theme)}">${TextType({
|
`<p style="${ParagraphStyle(state.theme)}">${textType({
|
||||||
text: stem
|
text: stem
|
||||||
})}</p>`,
|
})}</p>`,
|
||||||
`<textarea class="gift-textarea" style="${TextAreaStyle(
|
`<textarea class="gift-textarea" style="${TextAreaStyle(
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { TemplateOptions, Question } from './types';
|
import { TemplateOptions, Question } from './types';
|
||||||
import TextType from './TextType';
|
import textType from './TextType';
|
||||||
import { state } from '.';
|
import { state } from '.';
|
||||||
import { theme } from '../constants';
|
import { theme } from '../constants';
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ export default function GlobalFeedback({ feedback }: GlobalFeedbackOptions): str
|
||||||
|
|
||||||
return feedback !== null
|
return feedback !== null
|
||||||
? `<div style="${Container}">
|
? `<div style="${Container}">
|
||||||
<p>${TextType({ text: feedback })}</p>
|
<p>${textType({ text: feedback })}</p>
|
||||||
</div>`
|
</div>`
|
||||||
: ``;
|
: ``;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { TemplateOptions, Matching as MatchingType } from './types';
|
import { TemplateOptions, Matching as MatchingType } from './types';
|
||||||
import QuestionContainer from './QuestionContainer';
|
import QuestionContainer from './QuestionContainer';
|
||||||
import Title from './Title';
|
import Title from './Title';
|
||||||
import TextType from './TextType';
|
import textType from './TextType';
|
||||||
import GlobalFeedback from './GlobalFeedback';
|
import GlobalFeedback from './GlobalFeedback';
|
||||||
import { ParagraphStyle, SelectStyle } from '../constants';
|
import { ParagraphStyle, SelectStyle } from '../constants';
|
||||||
import { state } from '.';
|
import { state } from '.';
|
||||||
|
|
@ -24,7 +24,7 @@ export default function Matching({
|
||||||
type: 'Appariement',
|
type: 'Appariement',
|
||||||
title: title
|
title: title
|
||||||
}),
|
}),
|
||||||
`<p style="${ParagraphStyle(state.theme)}">${TextType({
|
`<p style="${ParagraphStyle(state.theme)}">${textType({
|
||||||
text: stem
|
text: stem
|
||||||
})}</p>`,
|
})}</p>`,
|
||||||
MatchAnswers({ choices: matchPairs }),
|
MatchAnswers({ choices: matchPairs }),
|
||||||
|
|
@ -67,7 +67,7 @@ function MatchAnswers({ choices }: MatchAnswerOptions): string {
|
||||||
.map(({ subquestion }) => {
|
.map(({ subquestion }) => {
|
||||||
return `
|
return `
|
||||||
<div style="${OptionTable} ${ParagraphStyle(state.theme)}">
|
<div style="${OptionTable} ${ParagraphStyle(state.theme)}">
|
||||||
${TextType({ text: subquestion })}
|
${textType({ text: subquestion })}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<select class="gift-select" style="${SelectStyle(state.theme)} ${Dropdown}">
|
<select class="gift-select" style="${SelectStyle(state.theme)} ${Dropdown}">
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { TemplateOptions, MultipleChoice as MultipleChoiceType } from './types';
|
||||||
import QuestionContainer from './QuestionContainer';
|
import QuestionContainer from './QuestionContainer';
|
||||||
import GlobalFeedback from './GlobalFeedback';
|
import GlobalFeedback from './GlobalFeedback';
|
||||||
import Title from './Title';
|
import Title from './Title';
|
||||||
import TextType from './TextType';
|
import textType from './TextType';
|
||||||
import MultipleChoiceAnswers from './MultipleChoiceAnswers';
|
import MultipleChoiceAnswers from './MultipleChoiceAnswers';
|
||||||
import { ParagraphStyle } from '../constants';
|
import { ParagraphStyle } from '../constants';
|
||||||
import { state } from '.';
|
import { state } from '.';
|
||||||
|
|
@ -21,7 +21,7 @@ export default function MultipleChoice({
|
||||||
type: 'Choix multiple',
|
type: 'Choix multiple',
|
||||||
title: title
|
title: title
|
||||||
}),
|
}),
|
||||||
`<p style="${ParagraphStyle(state.theme)}">${TextType({
|
`<p style="${ParagraphStyle(state.theme)}">${textType({
|
||||||
text: stem
|
text: stem
|
||||||
})}</p>`,
|
})}</p>`,
|
||||||
MultipleChoiceAnswers({ choices: choices }),
|
MultipleChoiceAnswers({ choices: choices }),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
import { TemplateOptions, TextFormat, Choice, MultipleChoice as MultipleChoiceType } from './types';
|
import { TemplateOptions, TextFormat, Choice, MultipleChoice as MultipleChoiceType } from './types';
|
||||||
import TextType from './TextType';
|
import textType from './TextType';
|
||||||
import AnswerIcon from './AnswerIcon';
|
import AnswerIcon from './AnswerIcon';
|
||||||
import { state } from '.';
|
import { state } from '.';
|
||||||
import { ParagraphStyle, theme } from '../constants';
|
import { ParagraphStyle, theme } from '../constants';
|
||||||
|
|
@ -41,7 +41,7 @@ export default function MultipleChoiceAnswers({ choices }: MultipleChoiceAnswerO
|
||||||
}" id="${inputId}" name="${id}">
|
}" id="${inputId}" name="${id}">
|
||||||
${AnswerWeight({ correct: isCorrectOption, weight: weight })}
|
${AnswerWeight({ correct: isCorrectOption, weight: weight })}
|
||||||
<label style="${CustomLabel} ${ParagraphStyle(state.theme)}" for="${inputId}">
|
<label style="${CustomLabel} ${ParagraphStyle(state.theme)}" for="${inputId}">
|
||||||
${TextType({ text: text as TextFormat })}
|
${textType({ text: text as TextFormat })}
|
||||||
</label>
|
</label>
|
||||||
${AnswerIcon({ correct: isCorrectOption })}
|
${AnswerIcon({ correct: isCorrectOption })}
|
||||||
${AnswerFeedback({ feedback: feedback })}
|
${AnswerFeedback({ feedback: feedback })}
|
||||||
|
|
@ -85,5 +85,5 @@ function AnswerFeedback({ feedback }: AnswerFeedbackOptions): string {
|
||||||
color: ${theme(state.theme, 'teal700', 'gray700')};
|
color: ${theme(state.theme, 'teal700', 'gray700')};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return feedback ? `<span style="${Container}">${TextType({ text: feedback })}</span>` : ``;
|
return feedback ? `<span style="${Container}">${textType({ text: feedback })}</span>` : ``;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { TemplateOptions, Numerical as NumericalType, NumericalFormat } from './types';
|
import { TemplateOptions, Numerical as NumericalType, NumericalFormat } from './types';
|
||||||
import QuestionContainer from './QuestionContainer';
|
import QuestionContainer from './QuestionContainer';
|
||||||
import Title from './Title';
|
import Title from './Title';
|
||||||
import TextType from './TextType';
|
import textType from './TextType';
|
||||||
import GlobalFeedback from './GlobalFeedback';
|
import GlobalFeedback from './GlobalFeedback';
|
||||||
import { ParagraphStyle, InputStyle } from '../constants';
|
import { ParagraphStyle, InputStyle } from '../constants';
|
||||||
import { state } from '.';
|
import { state } from '.';
|
||||||
|
|
@ -21,7 +21,7 @@ export default function Numerical({
|
||||||
type: 'Numérique',
|
type: 'Numérique',
|
||||||
title: title
|
title: title
|
||||||
}),
|
}),
|
||||||
`<p style="${ParagraphStyle(state.theme)}">${TextType({
|
`<p style="${ParagraphStyle(state.theme)}">${textType({
|
||||||
text: stem
|
text: stem
|
||||||
})}</p>`,
|
})}</p>`,
|
||||||
NumericalAnswers({ choices: choices }),
|
NumericalAnswers({ choices: choices }),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { TemplateOptions, ShortAnswer as ShortAnswerType, TextFormat } from './types';
|
import { TemplateOptions, ShortAnswer as ShortAnswerType, TextFormat } from './types';
|
||||||
import QuestionContainer from './QuestionContainer';
|
import QuestionContainer from './QuestionContainer';
|
||||||
import Title from './Title';
|
import Title from './Title';
|
||||||
import TextType from './TextType';
|
import textType from './TextType';
|
||||||
import GlobalFeedback from './GlobalFeedback';
|
import GlobalFeedback from './GlobalFeedback';
|
||||||
import { ParagraphStyle, InputStyle } from '../constants';
|
import { ParagraphStyle, InputStyle } from '../constants';
|
||||||
import { state } from './index';
|
import { state } from './index';
|
||||||
|
|
@ -21,7 +21,7 @@ export default function ShortAnswer({
|
||||||
type: 'Réponse courte',
|
type: 'Réponse courte',
|
||||||
title: title
|
title: title
|
||||||
}),
|
}),
|
||||||
`<p style="${ParagraphStyle(state.theme)}">${TextType({
|
`<p style="${ParagraphStyle(state.theme)}">${textType({
|
||||||
text: stem
|
text: stem
|
||||||
})}</p>`,
|
})}</p>`,
|
||||||
Answers({ choices: choices }),
|
Answers({ choices: choices }),
|
||||||
|
|
@ -32,7 +32,7 @@ export default function ShortAnswer({
|
||||||
|
|
||||||
function Answers({ choices }: AnswerOptions): string {
|
function Answers({ choices }: AnswerOptions): string {
|
||||||
const placeholder = choices
|
const placeholder = choices
|
||||||
.map(({ text }) => TextType({ text: text as TextFormat }))
|
.map(({ text }) => textType({ text: text as TextFormat }))
|
||||||
.join(', ');
|
.join(', ');
|
||||||
return `
|
return `
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ interface TextTypeOptions extends TemplateOptions {
|
||||||
text: TextFormat;
|
text: TextFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatLatex(text: string): string {
|
export function formatLatex(text: string): string {
|
||||||
return text
|
return text
|
||||||
.replace(/\$\$(.*?)\$\$/g, (_, inner) => katex.renderToString(inner, { displayMode: true }))
|
.replace(/\$\$(.*?)\$\$/g, (_, inner) => katex.renderToString(inner, { displayMode: true }))
|
||||||
.replace(/\$(.*?)\$/g, (_, inner) => katex.renderToString(inner, { displayMode: false }))
|
.replace(/\$(.*?)\$/g, (_, inner) => katex.renderToString(inner, { displayMode: false }))
|
||||||
|
|
@ -28,7 +28,7 @@ function formatLatex(text: string): string {
|
||||||
* @see marked
|
* @see marked
|
||||||
* @see katex
|
* @see katex
|
||||||
*/
|
*/
|
||||||
export default function TextType({ text }: TextTypeOptions) {
|
export default function textType({ text }: TextTypeOptions) {
|
||||||
const formatText = formatLatex(text.text.trim()); // latex needs pure "&", ">", etc. Must not be escaped
|
const formatText = formatLatex(text.text.trim()); // latex needs pure "&", ">", etc. Must not be escaped
|
||||||
|
|
||||||
switch (text.format) {
|
switch (text.format) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { TemplateOptions, TextChoice, TrueFalse as TrueFalseType } from './types';
|
import { TemplateOptions, TextChoice, TrueFalse as TrueFalseType } from './types';
|
||||||
import QuestionContainer from './QuestionContainer';
|
import QuestionContainer from './QuestionContainer';
|
||||||
import TextType from './TextType';
|
import textType from './TextType';
|
||||||
import GlobalFeedback from './GlobalFeedback';
|
import GlobalFeedback from './GlobalFeedback';
|
||||||
import MultipleChoiceAnswers from './MultipleChoiceAnswers';
|
import MultipleChoiceAnswers from './MultipleChoiceAnswers';
|
||||||
import Title from './Title';
|
import Title from './Title';
|
||||||
|
|
@ -44,7 +44,7 @@ export default function TrueFalse({
|
||||||
type: 'Vrai/Faux',
|
type: 'Vrai/Faux',
|
||||||
title: title
|
title: title
|
||||||
}),
|
}),
|
||||||
`<p style="${ParagraphStyle(state.theme)}">${TextType({
|
`<p style="${ParagraphStyle(state.theme)}">${textType({
|
||||||
text: stem
|
text: stem
|
||||||
})}</p>`,
|
})}</p>`,
|
||||||
MultipleChoiceAnswers({ choices: choices }),
|
MultipleChoiceAnswers({ choices: choices }),
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@ import {
|
||||||
TableHead,
|
TableHead,
|
||||||
TableRow
|
TableRow
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Latex from 'react-latex';
|
|
||||||
import { UserType } from '../../Types/UserType';
|
import { UserType } from '../../Types/UserType';
|
||||||
|
import { formatLatex } from '../GiftTemplate/templates/TextType';
|
||||||
|
|
||||||
interface LiveResultsProps {
|
interface LiveResultsProps {
|
||||||
socket: Socket | null;
|
socket: Socket | null;
|
||||||
|
|
@ -51,14 +51,14 @@ const LiveResults: React.FC<LiveResultsProps> = ({ socket, questions, showSelect
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Set student list before starting
|
// Set student list before starting
|
||||||
let newStudents:StudentResult[] = [];
|
let newStudents: StudentResult[] = [];
|
||||||
|
|
||||||
for (const student of students as UserType[]) {
|
for (const student of students as UserType[]) {
|
||||||
newStudents.push( { username: student.name, idUser: student.id, answers: [] } )
|
newStudents.push({ username: student.name, idUser: student.id, answers: [] })
|
||||||
}
|
}
|
||||||
|
|
||||||
setStudentResults(newStudents);
|
setStudentResults(newStudents);
|
||||||
|
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -242,16 +242,11 @@ const LiveResults: React.FC<LiveResultsProps> = ({ socket, questions, showSelect
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Table size="small" stickyHeader component={Paper}>
|
<div className="table-container">
|
||||||
|
<Table size="small" component={Paper}>
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell
|
<TableCell className="sticky-column">
|
||||||
sx={{
|
|
||||||
borderStyle: 'solid',
|
|
||||||
borderWidth: 1,
|
|
||||||
borderColor: 'rgba(224, 224, 224, 1)'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="text-base text-bold">Nom d'utilisateur</div>
|
<div className="text-base text-bold">Nom d'utilisateur</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
{Array.from({ length: maxQuestions }, (_, index) => (
|
{Array.from({ length: maxQuestions }, (_, index) => (
|
||||||
|
|
@ -259,7 +254,7 @@ const LiveResults: React.FC<LiveResultsProps> = ({ socket, questions, showSelect
|
||||||
key={index}
|
key={index}
|
||||||
sx={{
|
sx={{
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
cursor: `pointer`,
|
cursor: 'pointer',
|
||||||
borderStyle: 'solid',
|
borderStyle: 'solid',
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
borderColor: 'rgba(224, 224, 224, 1)'
|
borderColor: 'rgba(224, 224, 224, 1)'
|
||||||
|
|
@ -270,6 +265,7 @@ const LiveResults: React.FC<LiveResultsProps> = ({ socket, questions, showSelect
|
||||||
</TableCell>
|
</TableCell>
|
||||||
))}
|
))}
|
||||||
<TableCell
|
<TableCell
|
||||||
|
className="sticky-header"
|
||||||
sx={{
|
sx={{
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
borderStyle: 'solid',
|
borderStyle: 'solid',
|
||||||
|
|
@ -285,6 +281,7 @@ const LiveResults: React.FC<LiveResultsProps> = ({ socket, questions, showSelect
|
||||||
{studentResults.map((student) => (
|
{studentResults.map((student) => (
|
||||||
<TableRow key={student.idUser}>
|
<TableRow key={student.idUser}>
|
||||||
<TableCell
|
<TableCell
|
||||||
|
className="sticky-column"
|
||||||
sx={{
|
sx={{
|
||||||
borderStyle: 'solid',
|
borderStyle: 'solid',
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
|
|
@ -301,6 +298,7 @@ const LiveResults: React.FC<LiveResultsProps> = ({ socket, questions, showSelect
|
||||||
);
|
);
|
||||||
const answerText = answer ? answer.answer.toString() : '';
|
const answerText = answer ? answer.answer.toString() : '';
|
||||||
const isCorrect = answer ? answer.isCorrect : false;
|
const isCorrect = answer ? answer.isCorrect : false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableCell
|
<TableCell
|
||||||
key={index}
|
key={index}
|
||||||
|
|
@ -319,7 +317,7 @@ const LiveResults: React.FC<LiveResultsProps> = ({ socket, questions, showSelect
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{showCorrectAnswers ? (
|
{showCorrectAnswers ? (
|
||||||
<Latex>{answerText}</Latex>
|
<div>{formatLatex(answerText)}</div>
|
||||||
) : isCorrect ? (
|
) : isCorrect ? (
|
||||||
<FontAwesomeIcon icon={faCheck} />
|
<FontAwesomeIcon icon={faCheck} />
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -347,7 +345,7 @@ const LiveResults: React.FC<LiveResultsProps> = ({ socket, questions, showSelect
|
||||||
</TableBody>
|
</TableBody>
|
||||||
<TableFooter>
|
<TableFooter>
|
||||||
<TableRow sx={{ backgroundColor: '#d3d3d34f' }}>
|
<TableRow sx={{ backgroundColor: '#d3d3d34f' }}>
|
||||||
<TableCell sx={{ color: 'black' }}>
|
<TableCell className="sticky-column" sx={{ color: 'black' }}>
|
||||||
<div className="text-base text-bold">% réussite</div>
|
<div className="text-base text-bold">% réussite</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
{Array.from({ length: maxQuestions }, (_, index) => (
|
{Array.from({ length: maxQuestions }, (_, index) => (
|
||||||
|
|
@ -384,6 +382,7 @@ const LiveResults: React.FC<LiveResultsProps> = ({ socket, questions, showSelect
|
||||||
</TableFooter>
|
</TableFooter>
|
||||||
</Table>
|
</Table>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,3 +12,75 @@
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Flexbox container for the action bar */
|
||||||
|
.action-bar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Flexbox container for the form group */
|
||||||
|
.form-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-cell-border {
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
border-color: rgba(224, 224, 224, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------- */
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
overflow-x: auto;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sticky-header {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
background-color: white;
|
||||||
|
z-index: 2; /* Ensure it stays above other cells */
|
||||||
|
}
|
||||||
|
|
||||||
|
.sticky-column {
|
||||||
|
position: sticky;
|
||||||
|
left: 0;
|
||||||
|
background-color: white;
|
||||||
|
z-index: 1; /* Ensure it stays above other cells but below the header */
|
||||||
|
}
|
||||||
|
|
||||||
|
.sticky-intersection {
|
||||||
|
z-index: 3; /* Ensure the top-left cell stays above both header and column */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------- */
|
||||||
|
|
||||||
|
/* Media query for narrow screens */
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.action-bar {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-2xl {
|
||||||
|
font-size: 1.5rem; /* Adjust font size for smaller screens */
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-sm {
|
||||||
|
font-size: 0.875rem; /* Adjust font size for smaller screens */
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-1 {
|
||||||
|
margin-bottom: 0.5rem; /* Adjust margin for smaller screens */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import '../questionStyle.css';
|
import '../questionStyle.css';
|
||||||
import { Button } from '@mui/material';
|
import { Button } from '@mui/material';
|
||||||
import TextType from '../../GiftTemplate/templates/TextType';
|
import textType, { formatLatex } from '../../GiftTemplate/templates/TextType';
|
||||||
import { TextFormat } from '../../GiftTemplate/templates/types';
|
import { TextFormat } from '../../GiftTemplate/templates/types';
|
||||||
import Latex from 'react-latex';
|
// import Latex from 'react-latex';
|
||||||
|
|
||||||
type Choices = {
|
type Choices = {
|
||||||
feedback: { format: string; text: string } | null;
|
feedback: { format: string; text: string } | null;
|
||||||
|
|
@ -39,7 +39,7 @@ const MultipleChoiceQuestion: React.FC<Props> = (props) => {
|
||||||
return (
|
return (
|
||||||
<div className="question-container">
|
<div className="question-container">
|
||||||
<div className="question content">
|
<div className="question content">
|
||||||
<div dangerouslySetInnerHTML={{ __html: TextType({text: questionContent}) }} />
|
<div dangerouslySetInnerHTML={{ __html: textType({text: questionContent}) }} />
|
||||||
</div>
|
</div>
|
||||||
<div className="choices-wrapper mb-1">
|
<div className="choices-wrapper mb-1">
|
||||||
{choices.map((choice, i) => {
|
{choices.map((choice, i) => {
|
||||||
|
|
@ -56,7 +56,7 @@ const MultipleChoiceQuestion: React.FC<Props> = (props) => {
|
||||||
(choice.isCorrect ? '✅' : '❌')}
|
(choice.isCorrect ? '✅' : '❌')}
|
||||||
<div className={`circle ${selected}`}>{alphabet[i]}</div>
|
<div className={`circle ${selected}`}>{alphabet[i]}</div>
|
||||||
<div className={`answer-text ${selected}`}>
|
<div className={`answer-text ${selected}`}>
|
||||||
<Latex>{choice.text.text}</Latex>
|
{formatLatex(choice.text.text)}
|
||||||
</div>
|
</div>
|
||||||
</Button>
|
</Button>
|
||||||
{choice.feedback && showAnswer && (
|
{choice.feedback && showAnswer && (
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import '../questionStyle.css';
|
import '../questionStyle.css';
|
||||||
import { Button, TextField } from '@mui/material';
|
import { Button, TextField } from '@mui/material';
|
||||||
import TextType from '../../GiftTemplate/templates/TextType';
|
import textType from '../../GiftTemplate/templates/TextType';
|
||||||
import { TextFormat } from '../../GiftTemplate/templates/types';
|
import { TextFormat } from '../../GiftTemplate/templates/types';
|
||||||
|
|
||||||
type CorrectAnswer = {
|
type CorrectAnswer = {
|
||||||
|
|
@ -34,7 +34,7 @@ const NumericalQuestion: React.FC<Props> = (props) => {
|
||||||
return (
|
return (
|
||||||
<div className="question-wrapper">
|
<div className="question-wrapper">
|
||||||
<div>
|
<div>
|
||||||
<div dangerouslySetInnerHTML={{ __html: TextType({text: questionContent}) }} />
|
<div dangerouslySetInnerHTML={{ __html: textType({text: questionContent}) }} />
|
||||||
</div>
|
</div>
|
||||||
{showAnswer ? (
|
{showAnswer ? (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import '../questionStyle.css';
|
import '../questionStyle.css';
|
||||||
import { Button, TextField } from '@mui/material';
|
import { Button, TextField } from '@mui/material';
|
||||||
import TextType from '../../GiftTemplate/templates/TextType';
|
import textType from '../../GiftTemplate/templates/TextType';
|
||||||
import { TextFormat } from '../../GiftTemplate/templates/types';
|
import { TextFormat } from '../../GiftTemplate/templates/types';
|
||||||
|
|
||||||
type Choices = {
|
type Choices = {
|
||||||
|
|
@ -27,7 +27,7 @@ const ShortAnswerQuestion: React.FC<Props> = (props) => {
|
||||||
return (
|
return (
|
||||||
<div className="question-wrapper">
|
<div className="question-wrapper">
|
||||||
<div className="question content">
|
<div className="question content">
|
||||||
<div dangerouslySetInnerHTML={{ __html: TextType({text: questionContent}) }} />
|
<div dangerouslySetInnerHTML={{ __html: textType({text: questionContent}) }} />
|
||||||
</div>
|
</div>
|
||||||
{showAnswer ? (
|
{showAnswer ? (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import '../questionStyle.css';
|
import '../questionStyle.css';
|
||||||
import { Button } from '@mui/material';
|
import { Button } from '@mui/material';
|
||||||
import TextType from '../../GiftTemplate/templates/TextType';
|
import textType from '../../GiftTemplate/templates/TextType';
|
||||||
import { TextFormat } from '../../GiftTemplate/templates/types';
|
import { TextFormat } from '../../GiftTemplate/templates/types';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -27,7 +27,7 @@ const TrueFalseQuestion: React.FC<Props> = (props) => {
|
||||||
return (
|
return (
|
||||||
<div className="question-container">
|
<div className="question-container">
|
||||||
<div className="question content">
|
<div className="question content">
|
||||||
<div dangerouslySetInnerHTML={{ __html: TextType({ text: questionContent }) }} />
|
<div dangerouslySetInnerHTML={{ __html: textType({ text: questionContent }) }} />
|
||||||
</div>
|
</div>
|
||||||
<div className="choices-wrapper mb-1">
|
<div className="choices-wrapper mb-1">
|
||||||
<Button
|
<Button
|
||||||
|
|
|
||||||
|
|
@ -255,8 +255,8 @@ const ManageRoom: React.FC = () => {
|
||||||
<div className='dumb'></div>
|
<div className='dumb'></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
{/* the following breaks the css (nested room classes) */}
|
||||||
<div className='room'>
|
<div className=''>
|
||||||
|
|
||||||
{quizQuestions ? (
|
{quizQuestions ? (
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue