From faf1541020ecc3839470960c86cca636d837e9ad Mon Sep 17 00:00:00 2001 From: Irv Katz <60225276+exidy80@users.noreply.github.com> Date: Sun, 27 Apr 2025 09:10:50 -0400 Subject: [PATCH 01/21] upgrade quill-container --- app/components/quill-container.js | 156 +++++++------------ app/index.html | 7 +- app/templates/components/quill-container.hbs | 9 +- package-lock.json | 54 ++++++- package.json | 2 + 5 files changed, 122 insertions(+), 106 deletions(-) diff --git a/app/components/quill-container.js b/app/components/quill-container.js index 52ee18cfb..c75dc0ac1 100644 --- a/app/components/quill-container.js +++ b/app/components/quill-container.js @@ -1,15 +1,19 @@ -import { inject as service } from '@ember/service'; -import Component from '@ember/component'; -import $ from 'jquery'; +// app/components/quill-container.js -export default Component.extend({ - classNames: ['quill-container'], - utils: service('utility-methods'), +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { tracked } from '@glimmer/tracking'; +import { service } from '@ember/service'; +import Quill from 'quill'; - isEmpty: true, - isOverLengthLimit: false, +export default class QuillContainerComponent extends Component { + @service('utility-methods') utils; - defaultOptions: { + @tracked quillInstance = null; + @tracked isEmpty = true; + @tracked isOverLengthLimit = false; + + defaultOptions = { debug: 'false', modules: { toolbar: [ @@ -24,110 +28,68 @@ export default Component.extend({ theme: 'snow', placeholder: 'Type a detailed explanation here. This box will expand as you type.', - }, - - defaultMaxLength: 14680064, // 14MB - - didReceiveAttrs() { - this._super(); - let attrSectionId = this.attrSectionId; - if (!attrSectionId) { - this.set('sectionId', 'editor'); - } else { - this.set('sectionId', attrSectionId); - } + }; - let limit = this.maxLength || this.defaultMaxLength; - this.set('lengthLimit', limit); - }, + defaultMaxLength = 14680064; // 14MB - didInsertElement() { - let elId = this.elementId; - let selector = `#${elId} section`; + get sectionId() { + return this.args.attrSectionId || 'editor'; + } - let options; - if (!this.options) { - options = this.defaultOptions; - } - options.bounds = selector; + get lengthLimit() { + return this.args.maxLength || this.defaultMaxLength; + } - $(selector).ready(() => { - let quill = new window.Quill(selector, options); - this.set('quillInstance', quill); + @action + setupQuill(element) { + const options = this.args.options || this.defaultOptions; + options.bounds = element; - quill.on('text-change', (delta, oldDelta, source) => { - this.handleQuillChange(); - }); + const quill = new Quill(element, options); + this.quillInstance = quill; - this.handleStartingText(); - this.handleQuillChange(); - }); - this._super(...arguments); - }, + quill.on('text-change', this.handleQuillChange.bind(this)); - didUpdateAttrs() { - this._super(); this.handleStartingText(); - }, - - willDestroyElement() { - let quill = this.quillInstance; - if (quill) { - quill.off('text-change'); + this.handleQuillChange(); + } + + @action + teardownQuill() { + if (this.quillInstance) { + this.quillInstance.off('text-change'); + this.quillInstance = null; } - this._super(...arguments); - }, + } handleStartingText() { - let attrStartingText = this.startingText; - let startingText = - typeof attrStartingText === 'string' ? attrStartingText : ''; - $('.ql-editor').html(startingText); - }, - // Empty quill editor .html() property returns
{{replyHeadingText}}
Message
-{{@assignment.problem.title}}
+{{@problem.title}}
{{{@assignment.problem.text}}}
+{{{@problem.text}}}
{{replyHeadingText}}
Message
-{{@assignment.problem.title}}
+{{@problem.title}}
{{{@assignment.problem.text}}}
+{{{@problem.text}}}
New to EnCoMPASS?
-
Forgot Password?
-
Already have an account?
-
If you want, you can create a new class
-
diff --git a/app/templates/components/section-list.hbs b/app/templates/components/section-list.hbs
index 778367924..193c2814a 100644
--- a/app/templates/components/section-list.hbs
+++ b/app/templates/components/section-list.hbs
@@ -4,7 +4,7 @@
{{#if this.currentUser.isStudent}}{{else}}
Click on a username to see more info about their account and edit them
Or
-@@ -43,7 +43,7 @@ name='daterange' @type='date' @value={{(format-date @assignment.dueDate 'YYYY-MM-DD')}} - {{on 'change' (action 'updateDueDate')}} + {{on 'change' this.updateDueDate}} /> {{else}}
@@ -102,8 +102,8 @@ @assignment={{@assignment}} @section={{@section}} @problem={{@problem}} - @onCancel={{action (mut showLinkedWsForm) false}} - @handleResults={{action 'handleCreatedLinkedWs'}} + @onCancel={{this.hideLinkedWs}} + @handleResults={{this.handleCreatedLinkedWs}} /> {{/if}} {{#if this.showAddLinkedWsBtn}} @@ -111,7 +111,7 @@ data-test='add-linked-ws' class='add-linkedworkspaces-btn' type='button' - {{action (mut showLinkedWsForm) true}} + {{on 'click' this.showLinkedWs}} > Add Linked Workspaces @@ -146,8 +146,8 @@ @assignment={{@assignment}} @section={{@section}} @problem={{@problem}} - @onCancel={{action (mut showParentWsForm) false}} - @handleResults={{action 'handleCreatedParentWs'}} + @onCancel={{this.hideParentWs}} + @handleResults={{this.handleCreatedParentWs}} /> {{/if}} {{#if this.showAddParentWsBtn}} @@ -155,7 +155,7 @@ data-test='add-parent-ws' class='add-parent-workspace-btn' type='button' - {{action (mut showParentWsForm) true}} + {{on 'click' this.showParentWs}} >Add Parent Workspace {{/if}} {{#if this.showNoParentWsMsg}} @@ -169,7 +169,7 @@ Submissions
{{#if this.areSubmissionsExpanded}} @@ -186,7 +186,7 @@ data-test='edit-assignment' class='edit-assignment-button' type='button' - {{action 'editAssignment'}} + {{on 'click' this.editAssignment}} > Edit Assignment @@ -197,7 +197,7 @@ class='save-assign-btn' data-test='assn-save' type='button' - {{action 'updateAssignment'}} + {{on 'click' this.updateAssignment}} > Save Assignment @@ -206,7 +206,7 @@ class='cancelEditBtn' data-test='assn-cancel' type='button' - {{action 'stopEditing'}} + {{on 'click' this.stopEditing}} > Cancel @@ -215,25 +215,16 @@ data-test='trash-assn' class='right' type='button' - {{action 'showDeleteModal'}} + {{on 'click' this.showDeleteModal}} > {{/if}}{{error}}
- {{/each}} {{#each this.updateRecordErrors as |error|}}{{error}}
{{/each}} - {{#each this.dataFetchErrors as |error|}} -{{error}}
- {{/each}} - {{#if this.isMissingRequiredFields}} -Please provide all required fields.
- {{/if}} {{#if this.invalidDateRange}}Invalid Date Range
{{/if}} diff --git a/app/components/assignment-info-teacher.js b/app/components/assignment-info-teacher.js index fc2966b20..97b807a95 100644 --- a/app/components/assignment-info-teacher.js +++ b/app/components/assignment-info-teacher.js @@ -1,37 +1,32 @@ -import ErrorHandlingComponent from './error-handling'; +import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; import { action } from '@ember/object'; -import { inject as service } from '@ember/service'; -import $ from 'jquery'; -import moment from 'moment'; +import { service } from '@ember/service'; -export default class AssignmentInfoTeacherComponent extends ErrorHandlingComponent { +export default class AssignmentInfoTeacherComponent extends Component { @service store; @service router; @service currentUser; @service('sweet-alert') alert; @service('assignment-permissions') permissions; @service('utility-methods') utils; - @tracked formattedDueDate = null; - @tracked formattedAssignedDate = null; + @service errorHandling; @tracked isEditing = false; - @tracked isPreparingReport = false; - @tracked htmlDateFormat = 'YYYY-MM-DD'; - @tracked displayDateFormat = 'MMM Do YYYY'; @tracked assignmentToDelete = null; - @tracked dataFetchErrors = []; - @tracked findRecordErrors = []; - @tracked updateRecordErrors = []; @tracked areLinkedWsExpanded = true; @tracked showParentWsForm = false; @tracked showLinkedWsForm = false; @tracked areSubmissionsExpanded = true; - @tracked cachedProblem = []; + @tracked invalidDateRange = false; get user() { return this.currentUser.user; } + get updateRecordErrors() { + return this.errorHandling.getErrors('updateRecordErrors'); + } + get showProblemInput() { return this.isEditing && this.canEditProblem; } @@ -65,11 +60,11 @@ export default class AssignmentInfoTeacherComponent extends ErrorHandlingCompone } get showFullLinkedWsMsg() { - if (this.args.assignment.linkedWorkspacesRequest.linkType === 'group') { + if (this.args.assignment.linkedWorkspacesRequest?.linkType === 'group') { return this.isEditing && this.allGroupsHaveWs; } if ( - this.args.assignment.linkedWorkspacesRequest.linkType === 'individual' + this.args.assignment.linkedWorkspacesRequest?.linkType === 'individual' ) { return this.isEditing && this.allStudentsHaveWs; } @@ -79,14 +74,6 @@ export default class AssignmentInfoTeacherComponent extends ErrorHandlingCompone return this.isEditing && this.doesNotHaveLinkedWs; } - constructor() { - super(...arguments); - // get all sections and problems - // only need to get these on init because user won't be creating new sections or problems from this component - - this.cachedProblems = this.store.peekAll('problem'); - } - get isYourOwn() { let creatorId = this.utils.getBelongsToId( this.args.assignment, @@ -157,21 +144,13 @@ export default class AssignmentInfoTeacherComponent extends ErrorHandlingCompone } getMongoDate(htmlDateString) { - const htmlFormat = 'YYYY-MM-DD'; - if (typeof htmlDateString !== 'string') { - return; - } - let dateMoment = moment(htmlDateString, htmlFormat); - return new Date(dateMoment); + if (typeof htmlDateString !== 'string') return; + return new Date(`${htmlDateString}T00:00:00`); } getEndDate(htmlDateString) { - const htmlFormat = 'YYYY-MM-DD HH:mm'; - if (typeof htmlDateString !== 'string') { - return; - } - let dateMoment = moment(htmlDateString, htmlFormat); - let date = new Date(dateMoment); + if (typeof htmlDateString !== 'string') return; + const date = new Date(htmlDateString); date.setHours(23, 59, 59); return date; } @@ -182,35 +161,6 @@ export default class AssignmentInfoTeacherComponent extends ErrorHandlingCompone ); } - get problemOptions() { - let cachedProblems = this.cachedProblems; - let toArray = cachedProblems.toArray(); - return toArray.map((cachedProblem) => { - return { - id: cachedProblem.id, - title: cachedProblem.get('title'), - }; - }); - } - get sectionOptions() { - let sections = this.args.sections || []; - let toArray = sections.toArray(); - return toArray.map((section) => { - return { - id: section.id, - name: section.get('name'), - }; - }); - } - - get initialProblemItem() { - return [this.args.assignment.get('problem.id')]; - } - - get initialSectionItem() { - return [this.args.assignment.get('section.id')]; - } - get showAddParentWsBtn() { return ( this.isEditing && @@ -264,7 +214,7 @@ export default class AssignmentInfoTeacherComponent extends ErrorHandlingCompone return students.reject((student) => { return existingWorkspaces.find((ws) => { let ownerId = this.utils.getBelongsToId(ws, 'owner'); - return ownerId === student.get('id'); + return ownerId === student.id; }); }); } @@ -279,15 +229,15 @@ export default class AssignmentInfoTeacherComponent extends ErrorHandlingCompone } get linkedByGroup() { - return this.args.assignment.linkedWorkspacesRequest.linkType === 'group'; + return this.args.assignment.linkedWorkspacesRequest?.linkType === 'group'; } get missingWorkspaces() { - if (this.args.assignment.linkedWorkspacesRequest.linkType === 'group') { + if (this.args.assignment.linkedWorkspacesRequest?.linkType === 'group') { return this.groupsWithoutWorkspaces; } if ( - this.args.assignment.linkedWorkspacesRequest.linkType === 'individual' + this.args.assignment.linkedWorkspacesRequest?.linkType === 'individual' ) { return this.studentsWithoutWorkspaces; } @@ -318,7 +268,7 @@ export default class AssignmentInfoTeacherComponent extends ErrorHandlingCompone @action deleteAssignment() { const assignment = this.args.assignment; - assignment.set('isTrashed', true); + assignment.isTrashed = true; return assignment .save() .then((assignment) => { @@ -334,7 +284,7 @@ export default class AssignmentInfoTeacherComponent extends ErrorHandlingCompone ) .then((result) => { if (result.value) { - assignment.set('isTrashed', false); + assignment.isTrashed = false; assignment.save().then(() => { this.alert.showToast( 'success', @@ -352,7 +302,7 @@ export default class AssignmentInfoTeacherComponent extends ErrorHandlingCompone }) .catch((err) => { this.assignmentToDelete = null; - this.handleErrors(err, 'updateRecordErrors', assignment); + this.errorHandling.handleErrors(err, 'updateRecordErrors', assignment); }); } @@ -376,10 +326,7 @@ export default class AssignmentInfoTeacherComponent extends ErrorHandlingCompone const assignment = this.args.assignment; - if ( - !this.args.assignment.get('problem') || - !this.args.assignment.get('section') - ) { + if (!this.args.problem || !this.args.section) { return this.alert.showToast( 'error', 'Class and Problem are required', @@ -427,10 +374,10 @@ export default class AssignmentInfoTeacherComponent extends ErrorHandlingCompone } } - if (assignment.get('hasDirtyAttributes')) { + if (assignment.hasDirtyAttributes) { // never creating workspaces from this function - assignment.set('linkedWorkspacesRequest', { doCreate: false }); - assignment.set('parentWorkspaceRequest', { doCreate: false }); + assignment.linkedWorkspacesRequest = { doCreate: false }; + assignment.parentWorkspaceRequest = { doCreate: false }; return assignment .save() @@ -444,12 +391,15 @@ export default class AssignmentInfoTeacherComponent extends ErrorHandlingCompone null ); this.assignmentUpdateSuccess = true; - $('.daterangepicker').remove(); this.isEditing = false; return; }) .catch((err) => { - this.handleErrors(err, 'updateRecordErrors', assignment); + this.errorHandling.handleErrors( + err, + 'updateRecordErrors', + assignment + ); }); } else { this.alert.showToast( @@ -462,7 +412,6 @@ export default class AssignmentInfoTeacherComponent extends ErrorHandlingCompone ); this.args.assignment.rollbackAttributes(); this.isEditing = false; - $('.daterangepicker').remove(); } } @action stopEditing() { @@ -485,33 +434,13 @@ export default class AssignmentInfoTeacherComponent extends ErrorHandlingCompone this.showParentWsForm = false; } this.isEditing = false; - $('.daterangepicker').remove(); } }); } else { this.isEditing = false; - $('.daterangepicker').remove(); } this.args.assignment.rollbackAttributes(); } - @action updateSelectizeSingle(val, $item, propToUpdate, model) { - let errorProp = `${model}FormErrors`; - this[errorProp] = []; - - if ($item === null) { - this.args[propToUpdate] = null; - return; - } - let record = this.store.peekRecord(model, val); - if (!record) { - return; - } - if (propToUpdate === 'section') { - this.args.assignment.section = record; - } else if (propToUpdate === 'problem') { - this.args.assignment.problem = record; - } - } @action handleCreatedParentWs(assignment) { if (assignment) { this.alert.showToast( @@ -553,4 +482,24 @@ export default class AssignmentInfoTeacherComponent extends ErrorHandlingCompone event.target.value.replace(/-/g, '/') ); } + + @action + showLinkedWs() { + this.showLinkedWsForm = true; + } + + @action + hideLinkedWs() { + this.showLinkedWsForm = false; + } + + @action + hideParentWs() { + this.showParentWsForm = false; + } + + @action + showParentWs() { + this.showParentWsForm = true; + } } diff --git a/app/components/assignment-info.hbs b/app/components/assignment-info.hbs index d225aed1d..e6b4f9cfb 100644 --- a/app/components/assignment-info.hbs +++ b/app/components/assignment-info.hbs @@ -11,7 +11,6 @@ {{else}}Clicking "Create Workspaces" will generate a private workspace for each @@ -35,7 +35,7 @@
{{#each @students as |student|}} @@ -48,13 +48,6 @@ {{/each}}{{this.summaryMessage}}
-
+ {{this.summaryMessage}} +
|
|---|