Skip to content

Commit

Permalink
SAK-48451 fix criterion edit popover (sakaiproject#11556)
Browse files Browse the repository at this point in the history
* SAK-48451 fix criterion edit popover

https://sakaiproject.atlassian.net/browse/SAK-48451

* Update webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric.js

* Update webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric.js

* Update webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric.js

* Update webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric-criterion-edit.js

* Update webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric.js
  • Loading branch information
adrianfish authored May 16, 2023
1 parent 9450fc3 commit 54188fe
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@ sakai-rubric-student-comment {

[class*="edit-popover"] {
width: 400px;
--bs-popover-max-width: 800px;

.popover-content {
word-break: break-word;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export class SakaiRubricCriteria extends RubricsElement {
<span @focus="${this.onFocus}" @focusout="${this.focusOut}" tabindex="0" role="button" title="${tr("drag_order")}" aria-label="${tr("drag_order")}" class="reorder-icon fa fa-bars"></span>
${c.title}
<sakai-rubric-criterion-edit
id="criterion-edit-${this.criterion.id}"
@criterion-edited="${this.criterionEdited}"
site-id="${this.siteId}"
rubric-id="${this.rubricId}"
Expand All @@ -100,6 +101,7 @@ export class SakaiRubricCriteria extends RubricsElement {
<span @focus="${this.onFocus}" @focusout="${this.focusOut}" tabindex="0" role="button" title="${tr("drag_order")}" aria-label="${tr("drag_order")}" class="reorder-icon fa fa-bars"></span>
${c.title}
<sakai-rubric-criterion-edit
id="criterion-edit-${c.id}"
@criterion-edited="${this.criterionEdited}"
site-id="${this.siteId}"
rubric-id="${this.rubricId}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,34 +37,52 @@ export class SakaiRubricCriterionEdit extends RubricsElement {

get criterion() { return this._criterion; }

firstUpdated() {

new bootstrap.Popover(this.querySelector("button"), {
content: () => this.querySelector(`#edit-criterion-${this.criterion.id}`).innerHTML,
customClass: "criterion-edit-popover",
html: true,
placement: "bottom",
sanitize: false,
});

this.querySelector("button").addEventListener("shown.bs.popover", () => {

const save = document.querySelector(".popover.show .btn-primary");
save.addEventListener("click", this.saveEdit);
save.closest(".popover-body").querySelector("input").focus();

document.querySelector(".popover.show .btn-secondary")
.addEventListener("click", this.cancelEdit);
});
}

render() {

return html`
<a tabindex="0" role="button" class="linkStyle edit fa fa-edit" @focus="${this.onFocus}" @keyup="${this.openEditWithKeyboard}" @click="${this.editCriterion}" title="${tr("edit_criterion")} ${this.criterion.title}" aria-label="${tr("edit_criterion")} ${this.criterion.title}" href="#"></a>
<div id="edit_criterion_${this.criterion.id}" class="popover criterion-edit-popover bottom rubrics-popover">
<div class="arrow-1"></div>
<div class="popover-title">
<div class="buttons act">
<button class="active save" @click="${this.saveEdit}">
<sr-lang key="save">Save</sr-lang>
</button>
<button class="btn btn-link btn-xs cancel" @click="${this.cancelEdit}">
<sr-lang key="cancel">Cancel</sr-lang>
</button>
</div>
</div>
<div class="popover-content form">
<div class="form-group">
<label class="label-rubrics" for="criterion-title-field-${this.criterion.id}">
${this.isCriterionGroup ? html`
<sr-lang key="criterion_group_title">Criterion Group Title</sr-lang>
` : html`
<sr-lang key="criterion_title">Criterion Title</sr-lang>
`}
<button class="btn btn-icon edit"
id="edit-criterion-trigger-${this.criterion.id}"
type="button
data-bs-toggle="popup"
aria-haspopup="true"
aria-expanded="false"
aria-controls="edit-criterion-${this.criterion.id}"
title="${tr("edit_criterion")} ${this.criterion.title}"
aria-label="${tr("edit_criterion")} ${this.criterion.title}">
<i class="si si-edit"></i>
</button>
<div id="edit-criterion-${this.criterion.id}" class="criterion-edit-popover d-none">
<div>
<div>
<label class="label-rubrics" for="criterion-title-edit-${this.criterion.id}">
<sr-lang key="criterion_title">Criterion Title</sr-lang>
</label>
<input id="criterion-title-field-${this.criterion.id}" type="text" class="form-control" value="${this.criterionClone.title}" maxlength="255">
<input title="${tr("criterion_title")}" id="criterion-title-edit-${this.criterion.id}" type="text" value="${this.criterionClone.title}" maxlength="255">
</div>
</div>
<div class="form">
<div class="form-group">
<label class="label-rubrics" for="criterion-description-field-${this.criterion.id}">
${this.isCriterionGroup ? html`
Expand All @@ -80,91 +98,43 @@ export class SakaiRubricCriterionEdit extends RubricsElement {
id="criterion-description-field-${this.criterion.id}">
</sakai-editor>
</div>
<div class="mt-2">
<div>
<button class="btn btn-primary" type="button" data-site-id="${this.siteId}" data-rubric-id="${this.rubricId}" data-criterion-id="${this.criterion.id}">
<sr-lang key="save">Save</sr-lang>
</button>
<button class="btn btn-secondary" type="button" data-criterion-id="${this.criterion.id}">
<sr-lang key="cancel">Cancel</sr-lang>
</button>
</div>
</div>
</div>
</div>
`;
}

onFocus(e) {

e.target.closest('.criterion-row').classList.add("focused");
}

closeOpen() {
$('.show-tooltip .cancel').click();
}

editCriterion(e) {
e.preventDefault();
e.stopPropagation();

this.dispatchEvent(new CustomEvent('show-tooltip', {detail: this.criterion}));

// title input box reference
const titleinput = this.querySelector('[type="text"]');

if (!this.classList.contains("show-tooltip")) {

this.closeOpen();
this.classList.add("show-tooltip");

const popover = $(`#edit_criterion_${this.criterion.id}`);
popover[0].style.top = `${e.target.offsetTop + 20 }px`;
popover[0].style.left = `${e.target.offsetLeft - popover.width() / 2 }px`;
popover.show();

// and highlight the title
titleinput.setSelectionRange(0, titleinput.value.length);
titleinput.focus();

} else {
// if the tooltip is showing
// hide the tooltip
this.hideToolTip();
$(`#edit_criterion_${this.criterion.id}`).hide();
}
}

hideToolTip() {

// hide the edit popover
this.classList.remove("show-tooltip");

// fire hide-tooltip event to allow parent components to take action.
this.dispatchEvent(new CustomEvent('hide-tooltip', {details: {criterion: this.criterion}}));
}

cancelEdit(e) {

e.stopPropagation();

// revert changed data
this.criterionClone.title = this.criterion.title;
this.criterionClone.description = this.criterion.description;

// hide popover
this.hideToolTip();
this.dispatchEvent(new CustomEvent('hide-tooltip', {details: this.criterion}));
$(`#edit_criterion_${this.criterion.id}`).hide();
const popover = $(`#edit_criterion_${this.criterion.id}`);
popover.find("input[type='text']")[0].value = this.criterion.title;
this.querySelector("sakai-editor").setContent(this.criterion.description);
popover.hide();
const trigger = document.getElementById(`edit-criterion-trigger-${this.dataset.criterionId}`);
bootstrap.Popover.getInstance(trigger).hide();
trigger.focus();
}

saveEdit(e) {

e.stopPropagation();

const title = document.getElementById(`criterion-title-field-${this.criterion.id}`).value;
const description = this.criterionClone.description;
const title = e.target.closest(".popover-body").querySelector("input").value;
const description = e.target.closest("div.form").querySelector("sakai-editor").getContent();

const body = JSON.stringify([
{ "op": "replace", "path": "/title", "value": title },
{ "op": "replace", "path": "/description", "value": description },
]);

const url = `/api/sites/${this.siteId}/rubrics/${this.rubricId}/criteria/${this.criterion.id}`;
const url = `/api/sites/${this.dataset.siteId}/rubrics/${this.dataset.rubricId}/criteria/${this.dataset.criterionId}`;
fetch(url, {
credentials: "include",
headers: { "Content-Type": "application/json-patch+json" },
Expand All @@ -178,29 +148,25 @@ export class SakaiRubricCriterionEdit extends RubricsElement {
}

throw new Error("Network error while updating criterion");
}).then(criterion => {
})
.then(criterion => {

this.dispatchEvent(new CustomEvent('criterion-edited', { detail: criterion }));
this.dispatchEvent(new SharingChangeEvent());
const originalEditor = document.getElementById(`criterion-edit-${this.dataset.criterionId}`);
originalEditor.dispatchEvent(new CustomEvent("criterion-edited", { detail: criterion }));
originalEditor.dispatchEvent(new SharingChangeEvent());
})
.catch (error => console.error(error));

// hide the popover
this.hideToolTip();
this.dispatchEvent(new CustomEvent('hide-tooltip', {detail: this.criterion}));
document.getElementById(`edit_criterion_${this.criterion.id}`).style.display = "none";
}

openEditWithKeyboard(e) {

if (e.keyCode == 32) {
this.editCriterion(e);
}
const trigger = document.getElementById(`edit-criterion-trigger-${this.dataset.criterionId}`);
bootstrap.Popover.getInstance(trigger).hide();
trigger.focus();
document.getElementById(`edit-criterion-${this.dataset.criterionId}`).style.display = "none";
}

updateCriterionDescription(e) {
this.criterionClone.description = e.detail.content;
}
}

customElements.define("sakai-rubric-criterion-edit", SakaiRubricCriterionEdit);
const tagName = "sakai-rubric-criterion-edit";
!customElements.get(tagName) && customElements.define(tagName, SakaiRubricCriterionEdit);
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export class SakaiRubricEdit extends RubricsElement {
<button class="btn btn-icon edit"
id="edit-rubric-trigger-${this.rubric.id}"
type="button"
@click=${e => e.stopPropagation()}
data-bs-toggle="popup"
aria-haspopup="true"
aria-expanded="false"
Expand All @@ -48,7 +49,7 @@ export class SakaiRubricEdit extends RubricsElement {
<div id="edit-rubric-${this.rubric.id}" class="rubric-edit-popover d-none">
<div>
<div>
<label class="label-rubrics" for="rubric_title_edit">
<label class="label-rubrics" for="rubric-title-edit-${this.rubric.id}">
<sr-lang key="rubric_title">Rubric Title</sr-lang>
</label>
<input title="${tr("rubric_title")}" id="rubric-title-edit-${this.rubric.id}" type="text" value="${this.rubricClone.title}" maxlength="255">
Expand Down

0 comments on commit 54188fe

Please sign in to comment.