Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SAK-50440 Rubrics remove sharing of public rubrics from other sites #12839

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rubrics/api/src/main/bundle/rubrics.properties
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ save=Save
done=Done
total=Total
confirm_remove=Are you sure you want to remove "{}" ?
confirm_remove_public=Are you sure you want to remove "{}" both from publicly shared rubrics and from its site origin?
is_locked=is locked: Only titles, descriptions and criterion order can be modified
locked_warning=Rubric in use. Editable content will be updated on all previously associated items.
points=Points
Expand Down
1 change: 1 addition & 0 deletions rubrics/api/src/main/bundle/rubrics_ca.properties
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ save=Desa
done=Fet
total=Total
confirm_remove=Esteu segur de voler-ho eliminar
confirm_remove_public=Esteu segur que voleu eliminar "{}" tant de les r\u00fabriques compartides p\u00fablicament com del seu origen del lloc?
is_locked=est\u00e0 bloquejada\: Nom\u00e9s es poden modificar els t\u00edtols, les descripcions i l\u2019ordre dels criteris
locked_warning=La r\u00fabrica s\u2019est\u00e0 usant. El contingut editable s\u2019actualitzar\u00e0 a tots els elements pr\u00e8viament associats.
points=Punts
Expand Down
1 change: 1 addition & 0 deletions rubrics/api/src/main/bundle/rubrics_es.properties
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ save=Guardar
done=Aceptar
total=Total
confirm_remove=\u00bfEst\u00e1s seguro de que deseas borrar "{}"?
confirm_remove_public=\u00bfEst\u00e1s seguro de que deseas borrar "{}", tanto de las r\u00fabricas compartidas p\u00fablicamente como del sitio de origen?
is_locked=bloqueada\: Solo los t\u00edtulos, descripciones y el orden de los criterios pueden ser modificados
locked_warning=R\u00fabrica en uso. El contenido editable se actualizar\u00e1 en todos los elementos asociados previamente.
points=Puntos
Expand Down
1 change: 1 addition & 0 deletions rubrics/api/src/main/bundle/rubrics_eu.properties
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ save=Gorde
done=Egina
total=Guztira
confirm_remove=Ziur zaude kendu egin nahi duzula?
confirm_remove_public=Ziur "{}" publikoki partekatutako errubriketatik eta webgunearen jatorritik kendu nahi duzula?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PabloSanRoman can you check this, please?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @bgarciaentornos!
Best with a little change:

  • confirm_remove_public= Ziur kendu nahi duzula errubrika hau, "{}", publikoki partekatutako errubriketatik eta gunetik bertatik?

is_locked=blokeatuta dago\: tituluak, deskripzioak eta irizpideen ordena bakarrik alda daitezke
locked_warning=Erabiltzen ari den errubrika. Eduki editagarria aldez aurretik lotutako item guztietan eguneratuko da.
points=Puntuak
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.sakaiproject.webapi.controllers;

import lombok.extern.slf4j.Slf4j;
import org.sakaiproject.authz.api.SecurityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
@Slf4j
public class UserController extends AbstractSakaiApiController{

@Autowired
private SecurityService securityService;

@GetMapping("/user/roles")
public ResponseEntity<Map<String, Boolean>> checkSuperUser() {

Map<String, Boolean> roles = new HashMap<>();
roles.put("isSuperUser", securityService.isSuperUser());

return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(roles);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,36 @@ export class SakaiRubricReadonly extends SakaiRubric {
static properties = {

rubric: { type: Object },
isSuperUser: { type: Boolean },
enablePdfExport: { attribute: "enable-pdf-export", type: Boolean },
};

constructor() {

super();

this.isSuperUser = false;
this.enablePdfExport = false;
this.checkSuperUser();
}

async checkSuperUser() {
try {
const response = await fetch("/api/user/roles", {
method: "GET",
credentials: "include",
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const roles = await response.json();
this.isSuperUser = roles.isSuperUser;

console.log("Is SuperUser:", this.isSuperUser);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
console.log("Is SuperUser:", this.isSuperUser);
console.debug("Is SuperUser:", this.isSuperUser);

} catch (error) {
console.error("Error fetching user roles:", error);
}
}

shouldUpdate() { return this.rubric; }
Expand Down Expand Up @@ -54,6 +76,12 @@ export class SakaiRubricReadonly extends SakaiRubric {
<div class="d-none d-sm-block">${this.rubric.formattedModifiedDate}</div>

<div class="actions">
${this.isSuperUser ? html`
<div class="action-container">
<span class="d-none d-sm-none d-md-block visually-hidden">${this._i18n.delete_rubric}</span>
<span role="button" title="${this._i18n.revoke.replace("{}", this.rubric.title)}" tabindex="0" class="fa fa-users" @click="${this.revokeShareRubric}"></span>
</div>
` : ""}
<div class="action-container">
<span class="d-none d-sm-none d-md-block visually-hidden">${this._i18n.copy}</span>
<span role="button" title="${this._i18n.copy_to_site.replace("{}", this.rubric.title)}" tabindex="0" class="clone fa fa-copy" @click="${this.copyToSite}"></span>
Expand All @@ -67,6 +95,12 @@ export class SakaiRubricReadonly extends SakaiRubric {
</sakai-rubric-pdf>
</div>
` : ""}
${this.isSuperUser ? html`
<div class="action-container">
<span class="d-none d-sm-none d-md-block visually-hidden">${this._i18n.delete_rubric}</span>
<span role="button" title="${this._i18n.remove.replace("{}", this.rubric.title)}" tabindex="0" class="fa fa-times" @click="${this.deleteRubric}"></span>
</div>
` : ""}
</div>
</div>

Expand All @@ -83,4 +117,14 @@ export class SakaiRubricReadonly extends SakaiRubric {
e.stopPropagation();
this.dispatchEvent(new CustomEvent("copy-to-site", { detail: this.rubric.id }));
}

deleteRubric(e) {
e.stopPropagation();
this.dispatchEvent(new CustomEvent("delete-rubric", { detail: { id: this.rubric.id, title: this.rubric.title }, bubbles: true, composed: true, }));
}

revokeShareRubric(e) {
e.stopPropagation();
this.dispatchEvent(new CustomEvent("revoke-shared-rubric", { detail: { id: this.rubric.id, title: this.rubric.title, shared: this.rubric.shared }, bubbles: true, composed: true, }));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export class SakaiRubricsManager extends RubricsElement {
<div class="actions">${this.tr("actions")}</div>
</div>
<br>
<sakai-rubrics-shared-list id="sakai-rubrics-shared-list" site-id="${this.siteId}" @copy-share-site="${this.copyShareSite}" ?enable-pdf-export=${this.enablePdfExport}></sakai-rubrics-shared-list>
<sakai-rubrics-shared-list id="sakai-rubrics-shared-list" site-id="${this.siteId}" @copy-share-site="${this.copyShareSite}" @update-rubric-list="${this.handleRubricList}" ?enable-pdf-export=${this.enablePdfExport}></sakai-rubrics-shared-list>
</div>
<br>
</div>
Expand All @@ -188,6 +188,10 @@ export class SakaiRubricsManager extends RubricsElement {
this.querySelector("sakai-rubrics-list").refresh();
}

handleRubricList() {
this.querySelector("sakai-rubrics-list").refresh();
}

filterRubrics(e) {

this.querySelectorAll("sakai-rubrics-list, sakai-rubrics-shared-list").forEach(rubricList => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { html } from "lit";
import "../sakai-rubric-readonly.js";
import "../sakai-rubrics-list.js";
import { SakaiRubricsHelpers } from "./SakaiRubricsHelpers.js";
import { SakaiRubricsList } from "./SakaiRubricsList.js";
import { SharingChangeEvent } from "./SharingChangeEvent.js";

const rubricName = "name";
const rubricTitle = "title";
Expand All @@ -10,6 +12,9 @@ const rubricModified = "modified";

export class SakaiRubricsSharedList extends SakaiRubricsList {

rubricIdToDelete = null;
rubricTitleToDelete = null;

static properties = {

siteId: { attribute: "site-id", type: String },
Expand All @@ -22,6 +27,12 @@ export class SakaiRubricsSharedList extends SakaiRubricsList {

super();

this.updateRubricOptions = {
method: "PATCH",
credentials: "include",
headers: { "Content-Type": "application/json-patch+json" },
};

this.getSharedRubrics();
}

Expand All @@ -34,9 +45,31 @@ export class SakaiRubricsSharedList extends SakaiRubricsList {
return html`
<div role="tablist">
${this._rubrics.map(r => html`
<sakai-rubric-readonly .rubric=${r} @copy-to-site=${this.copyToSite} ?enablePdfExport=${this.enablePdfExport}></sakai-rubric-readonly>
<sakai-rubric-readonly .rubric=${r}
@copy-to-site=${this.copyToSite}
@delete-rubric=${this.showDeleteModal}
@revoke-shared-rubric=${this.sharingChange}
?enablePdfExport=${this.enablePdfExport}>
</sakai-rubric-readonly>
`)}
</div>
<div class="modal fade" id="delete-modal" tabindex="-1" aria-labelledby="delete-modal-label" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="delete-modal-label">${this._i18n.delete_item_title.replace("{}", this.rubricTitleToDelete || "")}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>${this._i18n.confirm_remove_public.replace("{}", this.rubricTitleToDelete || "")}</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" @click="${this.confirmDelete}">${this._i18n.remove_label}</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">${this._i18n.cancel}</button>
</div>
</div>
</div>
</div>
`;
}

Expand All @@ -45,7 +78,6 @@ export class SakaiRubricsSharedList extends SakaiRubricsList {
}

getSharedRubrics() {

const url = "/api/rubrics/shared";
fetch(url, { credentials: "include" })
.then(r => {
Expand All @@ -59,12 +91,60 @@ export class SakaiRubricsSharedList extends SakaiRubricsList {
.catch (error => console.error(error));
}

showDeleteModal(e) {
e.stopPropagation();
this.rubricIdToDelete = e.detail.id;
this.rubricTitleToDelete = e.detail.title;
this.requestUpdate();
const modal = new bootstrap.Modal(document.getElementById("delete-modal"));
modal.show();
}
copyToSite(e) {

SakaiRubricsHelpers.get(`/api/sites/${this.siteId}/rubrics/${e.detail}/copyToSite`, {})
.then(() => this.dispatchEvent(new CustomEvent("copy-share-site")));
}

confirmDelete(e) {
e.stopPropagation();
const url = `/api/sites/${this.siteId}/rubrics/${this.rubricIdToDelete}`;
fetch(url, {
method: "DELETE",
credentials: "include",
headers: { "Content-Type": "application/json" }
})
.then(r => {
if (!r.ok) {
throw new Error(`Failed to delete shared rubric with id ${this.rubricIdToDelete}`);
}
this._rubrics = this._rubrics.filter(rubric => rubric.id !== this.rubricIdToDelete);
this.requestUpdate();
bootstrap.Modal.getOrCreateInstance(this.querySelector(".modal")).hide();
this.dispatchEvent(new CustomEvent("update-rubric-list")); })
.catch(error => console.error(error));
}

sharingChange(e) {

e.stopPropagation();
e.detail.shared = !e.detail.shared;

this.updateRubricOptions.body = JSON.stringify([ { "op": "replace", "path": "/shared", "value": e.detail.shared } ]);
const url = `/api/sites/${e.detail.ownerId}/rubrics/${e.detail.id}`;
fetch(url, this.updateRubricOptions)
.then(r => {

if (r.ok) {
this.dispatchEvent(new SharingChangeEvent());
this.refresh();
this.dispatchEvent(new CustomEvent("update-rubric-list"));
} else {
throw new Error("Network error while updating rubric");
}
})
.catch (error => console.error(error));
}

sortRubrics(rubricType, ascending) {

switch (rubricType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ save=Save
done=Done
total=Total
confirm_remove=Are you sure you want to remove
confirm_remove_public=Are you sure you want to remove {} both from Publicly Shared Rubrics and from its site origin?
is_locked=is locked: Only titles, descriptions and criterion order can be modified
locked_warning=Rubric in use. Editable content will be updated on all previously associated items.
points=Points
Expand Down
Loading