Skip to content

Commit

Permalink
CSCEXAM-000 Take new editor in use everywhere
Browse files Browse the repository at this point in the history
- fix various issues still
  • Loading branch information
lupari committed Nov 24, 2024
1 parent a35bad1 commit ea8509c
Show file tree
Hide file tree
Showing 23 changed files with 166 additions and 122 deletions.
7 changes: 2 additions & 5 deletions ui/src/app/administrative/settings/settings.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,9 @@
<label for="editor">{{ 'i18n_user_agreement' | translate }}</label>
<xm-ckeditor
id="editor"
#ck="ngModel"
name="editor"
ck-editor
rows="10"
cols="80"
[(ngModel)]="config.eula"
[data]="config.eula"
(dataChange)="eulaChanged($event)"
></xm-ckeditor>
</div>
</div>
Expand Down
2 changes: 2 additions & 0 deletions ui/src/app/administrative/settings/settings.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export class SettingsComponent implements OnInit {
updateReservationWindow = () =>
this.Settings.updateReservationWindow$(this.config).subscribe({ next: this.onSuccess, error: this.onError });

eulaChanged = (event: string) => (this.config.eula = event);

private onSuccess = () =>
this.toast.info(this.translate.instant('i18n_settings') + ' ' + this.translate.instant('i18n_updated'));

Expand Down
19 changes: 3 additions & 16 deletions ui/src/app/exam/editor/basic/basic-exam-info.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -252,15 +252,7 @@
</sup>
</div>
<div class="col-md-9">
<xm-ckeditor
rows="4"
cols="150"
[enableClozeTest]="false"
[(ngModel)]="exam.instruction"
(onBlur)="updateExam(false)"
#ck="ngModel"
name="ck"
></xm-ckeditor>
<xm-ckeditor [data]="exam.instruction" (dataChange)="updateExam(false)" />
</div>
</div>
</div>
Expand Down Expand Up @@ -288,13 +280,8 @@
}
<div class="col-md-9">
<xm-ckeditor
rows="4"
cols="150"
[enableClozeTest]="false"
[(ngModel)]="exam.enrollInstruction"
(onBlur)="updateExam(false)"
#ck="ngModel"
name="ck"
[data]="exam.enrollInstruction"
(dataChange)="enrollInstructionsChanged($event)"
></xm-ckeditor>
</div>
</div>
Expand Down
2 changes: 2 additions & 0 deletions ui/src/app/exam/editor/basic/basic-exam-info.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ export class BasicExamInfoComponent implements OnInit, OnDestroy {
});
};

enrollInstructionsChanged = (event: string) => (this.exam.enrollInstruction = event);

getExecutionTypeTranslation = () => !this.exam || this.Exam.getExecutionTypeTranslation(this.exam.executionType);

getExaminationTypeName = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export class ExaminationEssayQuestionComponent implements OnInit {
const decodedString = doc.documentElement.innerText;
this.questionTitle = decodedString;
}

answerChanged = (event: string) => (this.sq.essayAnswer.answer = event);
saveAnswer = () => this.Examination.saveTextualAnswer$(this.sq, this.exam?.hash || '', false, false).subscribe();

removeQuestionAnswerAttachment = () => {
Expand Down
2 changes: 1 addition & 1 deletion ui/src/app/maturity/maturity.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface LanguageInspection {
modifier: User;
creator: User;
created: Date;
statement: { attachment?: Attachment; comment?: string };
statement: { attachment?: Attachment; comment: string };
}

export interface LanguageInspectionData extends LanguageInspection {
Expand Down
2 changes: 0 additions & 2 deletions ui/src/app/question/question-basic-info.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,6 @@ import { CKEditorComponent } from 'src/app/shared/ckeditor/ckeditor.component';
<xm-ckeditor
id="editor"
name="editor"
rows="10"
cols="50"
[enableClozeTest]="question()?.type === 'ClozeTestQuestion'"
[data]="question()?.question || ''"
(dataChange)="textChanged($event)"
Expand Down
2 changes: 1 addition & 1 deletion ui/src/app/question/question.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export interface LibraryQuestion extends ReverseQuestion {
export interface EssayAnswer {
id?: number;
evaluatedScore?: number;
answer?: string;
answer: string;
objectVersion?: number;
attachment?: Attachment;
}
Expand Down
5 changes: 4 additions & 1 deletion ui/src/app/question/question.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { map } from 'rxjs/operators';
import { SessionService } from 'src/app/session/session.service';
import { AttachmentService } from 'src/app/shared/attachment/attachment.service';
import { FileService } from 'src/app/shared/file/file.service';
import { CkEditorService } from '../shared/ckeditor/ckeditor.service';
import {
ExamSectionQuestion,
ExamSectionQuestionOption,
Expand All @@ -29,6 +30,7 @@ export class QuestionService {
private Session: SessionService,
private Files: FileService,
private Attachment: AttachmentService,
private EditorService: CkEditorService,
) {}

getQuestionType = (type: string) => {
Expand Down Expand Up @@ -299,10 +301,11 @@ export class QuestionService {
private questionOwnerApi = (id?: number) => (!id ? '/app/questions/owner' : `/app/questions/owner/${id}`);

private getQuestionData(question: Partial<Question>): Partial<Question> {
const sanitizedQuestion = question.question ? this.EditorService.fixHtml(question.question) : '';
const questionToUpdate: Partial<Question> = {
type: question.type,
defaultMaxScore: question.defaultMaxScore,
question: question.question,
question: sanitizedQuestion,
shared: question.shared,
defaultAnswerInstructions: question.defaultAnswerInstructions,
defaultEvaluationCriteria: question.defaultEvaluationCriteria,
Expand Down
9 changes: 4 additions & 5 deletions ui/src/app/review/assessment/feedback/feedback.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,9 @@ import { FileService } from 'src/app/shared/file/file.service';
<div class="col-md-12">
<xm-ckeditor
id="feedback-editor"
[enableClozeTest]="false"
[(ngModel)]="exam.examFeedback.comment"
#ck="ngModel"
[data]="exam.examFeedback.comment"
(dataChange)="commentChanged($event)"
name="ck"
rows="10"
cols="80"
></xm-ckeditor>
</div>
</div>
Expand Down Expand Up @@ -144,6 +141,8 @@ export class FeedbackComponent implements OnInit {
}
};

commentChanged = (event: string) => (this.exam.examFeedback.comment = event);

private _saveFeedback$ = () => this.Assessment.saveFeedback$(this.exam);

private _saveCollaborativeFeedback$ = () =>
Expand Down
9 changes: 4 additions & 5 deletions ui/src/app/review/assessment/feedback/statement.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,9 @@ import { FileService } from 'src/app/shared/file/file.service';
<div class="row mt-2 mb-1">
<div class="col-md-12">
<xm-ckeditor
[enableClozeTest]="false"
[(ngModel)]="exam.languageInspection.statement.comment"
#ck="ngModel"
[data]="exam.languageInspection.statement.comment"
(dataChange)="commentChanged($event)"
name="ck"
rows="10"
cols="80"
></xm-ckeditor>
</div>
</div>
Expand Down Expand Up @@ -93,6 +90,8 @@ export class StatementComponent {
private Assessment: AssessmentService,
) {}

commentChanged = (event: string) => (this.exam.languageInspection.statement.comment = event);

hasGoneThroughLanguageInspection = () => this.exam.languageInspection?.finishedAt;

toggleEditorVisibility = () => (this.hideEditor = !this.hideEditor);
Expand Down
15 changes: 12 additions & 3 deletions ui/src/app/review/assessment/questions/essay-question.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,27 @@ export class EssayQuestionComponent implements OnInit {

set scoreValue(value: number | undefined) {
this._score = value;
const answer = this.sectionQuestion.essayAnswer!.answer;
if (!this.form || this.form.valid) {
this.sectionQuestion.essayAnswer = { ...this.sectionQuestion.essayAnswer, evaluatedScore: value };
this.sectionQuestion.essayAnswer = {
...this.sectionQuestion.essayAnswer,
evaluatedScore: value,
answer: answer,
};
} else {
this.sectionQuestion.essayAnswer = { ...this.sectionQuestion.essayAnswer, evaluatedScore: undefined };
this.sectionQuestion.essayAnswer = {
...this.sectionQuestion.essayAnswer,
evaluatedScore: undefined,
answer: answer,
};
}
}

ngOnInit() {
this.id = this.route.snapshot.params.id;
this.ref = this.route.snapshot.params.ref;
if (!this.sectionQuestion.essayAnswer) {
this.sectionQuestion.essayAnswer = { id: 0 };
this.sectionQuestion.essayAnswer = { answer: '' };
}
this.scoreValue = this.sectionQuestion.essayAnswer.evaluatedScore;
}
Expand Down
7 changes: 4 additions & 3 deletions ui/src/app/review/listing/dialogs/feedback.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ import { CKEditorComponent } from 'src/app/shared/ckeditor/ckeditor.component';
@if (exam.examFeedback !== null) {
<div class="col-md-12 ps-0">
<xm-ckeditor
rows="10"
#ck="ngModel"
[(ngModel)]="exam.examFeedback.comment"
[data]="exam.examFeedback.comment"
(dataChange)="commentChanged($event)"
autofocus
></xm-ckeditor>
</div>
Expand Down Expand Up @@ -56,6 +55,8 @@ export class SpeedReviewFeedbackComponent implements OnInit {
}
}

commentChanged = (event: string) => (this.exam.examFeedback.comment = event);

ok = () => {
if (!this.exam.examFeedback) {
this.exam.examFeedback = { comment: '', feedbackStatus: false };
Expand Down
2 changes: 1 addition & 1 deletion ui/src/app/shared/ckeditor/ckeditor.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ export class CKEditorComponent implements AfterViewInit {
const wordCountPlugin = e.plugins.get('WordCount');
const wordCountWrapper = document.getElementById('word-count') as HTMLElement;
wordCountWrapper.appendChild(wordCountPlugin.wordCountContainer);
CKEditorInspector.attach(e);
//CKEditorInspector.attach(e);
}

onChange({ editor }: ChangeEvent) {
Expand Down
26 changes: 26 additions & 0 deletions ui/src/app/shared/ckeditor/ckeditor.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-FileCopyrightText: 2024 The members of the EXAM Consortium
//
// SPDX-License-Identifier: EUPL-1.2

import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class CkEditorService {
// This is needed until we can figure out what messes our cloze-test
// HTML when initially kicking up the editor. Hopefully we can get rid
// of this soon.
fixHtml = (html: string) => {
const doc = new DOMParser().parseFromString(html, 'text/html');
const spans = doc.querySelectorAll<HTMLSpanElement>('span');
spans.forEach((span) => {
const nestedSpan = span.querySelector<HTMLSpanElement>('span[cloze="true"]');
if (nestedSpan) {
// Copy attributes from the nested span to the outer span
Array.from(nestedSpan.attributes).forEach((attr) => span.setAttribute(attr.name, attr.value));
// Replace the inner span with its text content
nestedSpan.replaceWith(...Array.from(nestedSpan.childNodes));
}
});
return doc.documentElement.lastElementChild!.innerHTML;
};
}
21 changes: 8 additions & 13 deletions ui/src/app/shared/ckeditor/ckeditor.styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
*
* SPDX-License-Identifier: EUPL-1.2
*/

.editor-container_classic-editor .editor-container__editor {
min-height: 500px;
max-height: 795px;
}
.ck.ck-word-count {
display: flex;
justify-content: flex-end;
Expand All @@ -21,28 +24,20 @@
padding: var(--ck-spacing-large);
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(5, 1fr);
column-gap: 0px;
row-gap: var(--ck-spacing-standard);
grid-template-rows: repeat(4, 1fr);
}
.ck.ck-cloze-form .ck.ck-labeled-field-view:nth-of-type(1) {
grid-area: 1 / 1 / 2 / 3;
}
.ck.ck-cloze-form .ck.ck-labeled-field-view:nth-of-type(2) {
grid-area: 4 / 1 / 4 / 3;
}
.ck.ck-cloze-form .ck-button:nth-of-type(1) {
grid-area: 2 / 1 / 2 / 3;
}
.ck.ck-cloze-form .ck-button:nth-of-type(2) {
grid-area: 3 / 1 / 3 / 3;
}
.ck.ck-cloze-form .ck.ck-labeled-field-view:nth-of-type(2) {
grid-area: 4 / 1 / 4 / 3;
}
.ck.ck-cloze-form .ck-button:nth-of-type(3) {
grid-area: 5 / 1 / 5 / 2;
}
.ck.ck-cloze-form .ck-button:nth-of-type(4) {
grid-area: 5 / 2 / 5 / 3;
}
.cloze-test-wrapper {
background-color: yellow;
border: 1px solid;
Expand Down
2 changes: 0 additions & 2 deletions ui/src/app/shared/ckeditor/plugins/clozetest/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ export class ClozeCommand extends Command {

override execute({ text, caseSensitive, numeric, precision }: CommandValue) {
const model = this.editor.model;
const hasId = model.document.selection.hasAttribute('ckId');
console.log(hasId);
model.change((writer) => {
model.insertContent(
writer.createText(text, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@
const dictionary: Record<string, string> = {
'Cloze Test': 'Embedded Answer',
Answer: 'Correct Answer',
'Case Sensitive': 'Case sensitive (textual answer only)',
'Case Sensitive label': 'Case sensitive',
'Case Sensitive tooltip': 'Case sensitivity (textual answer only)',
Numeric: 'Numeric Answer',
Precision: 'Required answer precision (± of correct numeric answer value)',
Precision: 'Required answer precision',
'Precision description': '(± of correct numeric answer value)',
Save: 'Save',
Cancel: 'Cancel',
Usage: `Use vertical bar ( | ) to separate correct answer options from each other.
Use asterisk ( * ) as a wildcard to match any series of characters. For example
'*ship|boat|ferry' would match answers "ship", "flagship", "boat" and "ferry".
If you really do want to match an asterisk or a vertical pipe then use a backslash
like this: ( \ )`,
};
export default dictionary;
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,18 @@
const dictionary: Record<string, string> = {
'Cloze Test': 'Aukkotehtävä',
Answer: 'Oikea vastaus',
'Case Sensitive': 'Onko pienillä ja isoilla kirjaimilla eroa (tekstimuotoisen vastauksen osalta)',
'Case Sensitive label': 'Kirjainkoon merkittävyys',
'Case Sensitive tooltip': 'Onko pienillä ja isoilla kirjaimilla eroa (tekstimuotoisen vastauksen osalta)',
Numeric: 'Numeerinen vastaus',
Precision: 'Vaadittu tarkkuus (± oikean vastauksen arvosta)',
Precision: 'Vaadittu tarkkuus',
'Precision description': '(± oikean vastauksen arvosta)',
Save: 'Tallenna',
Cancel: 'Peruuta',
Usage: `Käytä pystyviivaa ( | ) erottamaan oikeat vastausvaihtoehdot toisistaan.
Käytä tähteä ( * ) wildcardina, jos mikä tahansa merkki käy. Esimerkiksi
'*laiva|vene|lautta' tarkoittaa, että vaikkapa "laiva", "lippulaiva",
"vene" ja "lautta" olisivat oikeita vastauksia. Jos haluat, että vastaus
sisältää oikeasti pystyviivan tai tähden, pitää tällaista merkkiä edeltää
kenoviiva: ( \ )`,
};
export default dictionary;
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@
const dictionary: Record<string, string> = {
'Cloze Test': 'Lucktest',
Answer: 'Rätt svar',
'Case Sensitive': 'Är det skillnad mellan stor och liten bokstav (gäller endast svar i textform)',
'Case Sensitive label': 'Stora och små bokstäver olika',
'Case Sensitive tooltip': 'Är det skillnad mellan stor och liten bokstav (gäller endast svar i textform)',
Numeric: 'Numeriskt svar',
Precision: 'Krav på svarets precision (± av värdet på det korrekta svaret)',
Precision: 'Krav på svarets precision',
'Precision description': '(± av värdet på det korrekta svaret)',
Save: 'Spara',
Cancel: 'Avbryt',
Usage: `Använd vertikalt steck ( | ) för att skilja korrekta svar från varandra. Använd asterisk
( * ) om vilken som helst serie av tecken duger. Till exempel '*skepp|båt|färja' betyder
att "skepp", "flaggskepp", "båt" och "färja" skulle duga som korrekta svar. Om du vill
att svaret de facto innehåller antingen en asterisk eller ett vertikalt streck så bör ett
sådant tecken föregås av enkel apostrof: ( \ )`,
};
export default dictionary;
Loading

0 comments on commit ea8509c

Please sign in to comment.