Skip to content

Commit

Permalink
Configure helpdesk home per profile 2/2
Browse files Browse the repository at this point in the history
  • Loading branch information
AdrienClairembault authored Jan 29, 2025
1 parent 847c711 commit cc45406
Show file tree
Hide file tree
Showing 21 changed files with 1,401 additions and 57 deletions.
8 changes: 8 additions & 0 deletions css/includes/components/_utils.scss
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,11 @@
.fs-5x {
font-size: 5em !important;
}

.opacity-100-hover:hover {
opacity: 1 !important;
}

.min-height-110 {
min-height: 110px;
}
311 changes: 301 additions & 10 deletions js/modules/Helpdesk/HelpdeskConfigController.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ export class GlpiHelpdeskConfigController

// We don't need a class but it won't work if this param is empty.
placeholderClass: "not-a-real-class",

// Specify target items to make sure we exclude the special "add tile" item.
items: "[data-glpi-draggable-item]",
});

sortable(tiles_container)[0].addEventListener('sortstart', () => {
Expand All @@ -76,6 +79,7 @@ export class GlpiHelpdeskConfigController

#initEventsHandlers()
{
// Watch for tile reordering actions
this.#container
.querySelector('[data-glpi-helpdesk-config-reorder-action-cancel')
.addEventListener('click', async () => {
Expand All @@ -84,7 +88,6 @@ export class GlpiHelpdeskConfigController
this.#is_reordering_tiles = false;
})
;

this.#container
.querySelector('[data-glpi-helpdesk-config-reorder-action-save')
.addEventListener('click', async() => {
Expand All @@ -94,15 +97,74 @@ export class GlpiHelpdeskConfigController
})
;

this.#container
.querySelectorAll('[data-glpi-helpdesk-config-action-delete')
.forEach((node) => {
node.addEventListener('click', (e) => {
const tile = e.target.closest('[data-glpi-helpdesk-config-tile-container]');
this.#deleteTile(tile);
});
})
;
// Watch for tile deletion
this.#container.addEventListener('click', (e) => {
const delete_button = e.target.closest('[data-glpi-helpdesk-config-action-delete]');
if (delete_button === null) {
return;
}

const tile = delete_button.closest('[data-glpi-helpdesk-config-tile-container]');
this.#deleteTile(tile);
});

// Watch for tile edition
this.#container.addEventListener('click', (e) => {
const edit_button = e.target.closest('[data-glpi-helpdesk-config-action-show-edit-form]');
if (edit_button === null) {
return;
}

const tile = edit_button.closest('[data-glpi-helpdesk-config-tile-container]');
this.#showEditTileForm(tile);
});
this.#container.addEventListener('click', (e) => {
const cancel_button = e.target.closest('[data-glpi-helpdesk-config-edit-tile-cancel]');
if (cancel_button === null) {
return;
}

this.#cancelTileEdit();
});
this.#container.addEventListener('click', (e) => {
const save_button = e.target.closest('[data-glpi-helpdesk-config-edit-tile-save]');
if (save_button === null) {
return;
}

this.#saveTileEdit(e.target.closest('form'));
});

// Watch for tile creation
this.#container.addEventListener('click', (e) => {
const edit_button = e.target.closest('[data-glpi-helpdesk-config-action-new-tile]');
if (edit_button === null) {
return;
}

this.#showAddTileForm();
});
this.#container.addEventListener('click', (e) => {
const cancel_button = e.target.closest('[data-glpi-helpdesk-config-add-tile-cancel]');
if (cancel_button === null) {
return;
}

this.#cancelAddTile();
});
this.#container.addEventListener('click', (e) => {
const submit_button = e.target.closest('[data-glpi-helpdesk-config-add-tile-submit]');
if (submit_button === null) {
return;
}

this.#saveNewTile(e.target.closest('form'));
});

// Note: we use jquery here because event listener on select2 doesn't seems to work with vanilla JS.
$(this.#container).on('change', '[data-glpi-helpdesk-config-add-tile-type]', (e) => {
this.#triggerTypeChange(e.target.value);
});
}

#showReorderUI()
Expand All @@ -125,6 +187,11 @@ export class GlpiHelpdeskConfigController
tile_body.classList.add('border-dashed');
})
;
this.#container
.querySelector('[data-glpi-helpdesk-config-action-new-tile]')
.classList
.add('d-none')
;
}

#hideReorderUI()
Expand All @@ -147,6 +214,11 @@ export class GlpiHelpdeskConfigController
tile_body.classList.remove('border-dashed');
})
;
this.#container
.querySelector('[data-glpi-helpdesk-config-action-new-tile]')
.classList
.remove('d-none')
;
}

async #reloadTiles()
Expand Down Expand Up @@ -219,6 +291,21 @@ export class GlpiHelpdeskConfigController
return this.#container.querySelector("[data-glpi-helpdesk-config-tiles");
}

#getDefaultViewDiv()
{
return this.#container.querySelector("[data-glpi-helpdesk-config-default-view");
}

#getEditTileViewDiv()
{
return this.#container.querySelector("[data-glpi-helpdesk-config-edit-view");
}

#getAddTileViewDiv()
{
return this.#container.querySelector("[data-glpi-helpdesk-config-add-view");
}

async #deleteTile(tile_container)
{
// Hide content immediatly (optimistic UI)
Expand Down Expand Up @@ -262,4 +349,208 @@ export class GlpiHelpdeskConfigController
console.error(e);
}
}

async #showEditTileForm(tile_container)
{
try {
const tile = tile_container.querySelector('[data-glpi-helpdesk-config-tile]');

const url = `${CFG_GLPI.root_doc}/Config/Helpdesk/ShowEditTileForm`;
const url_params = new URLSearchParams({
tile_id: tile.dataset.glpiHelpdeskConfigTileId,
tile_itemtype: tile.dataset.glpiHelpdeskConfigTileItemtype,
});
const response = await fetch(`${url}?${url_params}`);

// Handle server errors
if (!response.ok) {
throw new Error(response.status);
}

// Note: we use jQuery instead of raw JS here because we need scripts
// to be executed for richtext input initialization
$(this.#getEditTileViewDiv()).html(await response.text());

this.#getEditTileViewDiv().classList.remove('d-none');
this.#getDefaultViewDiv().classList.add('d-none');
} catch (e) {
glpi_toast_error(__('An unexpected error occurred.'));
console.error(e);
}
}

#cancelTileEdit()
{
this.#getEditTileViewDiv().classList.add('d-none');
this.#getEditTileViewDiv().innerHTML = "";
this.#getDefaultViewDiv().classList.remove('d-none');
}

async #saveTileEdit(form)
{
// Show spinner and disable button
form.querySelector(
'[data-glpi-helpdesk-config-edit-tile-save-spinner-icon]'
).classList.remove('d-none');
form.querySelector(
'[data-glpi-helpdesk-config-edit-tile-save-plus-icon]'
).classList.add('d-none');
form.querySelector(
'[data-glpi-helpdesk-config-edit-tile-save]'
).disabled = true;

try {
// Update tinymce values
if (window.tinymce !== undefined) {
window.tinymce.get().forEach(editor => {
editor.save();
});
}

// Set up form data
const form_data = new FormData(form);

// Send request
const url = `${CFG_GLPI.root_doc}/Config/Helpdesk/UpdateTile`;
const response = await fetch(url, {
method: 'POST',
body: form_data,
headers: {
'X-Requested-With': 'XMLHttpRequest',
'X-Glpi-Csrf-Token': getAjaxCsrfToken(),
}
});

// Handle server errors
if (!response.ok) {
throw new Error(response.status);
}

glpi_toast_info(__("Configuration updated successfully."));

this.#getTilesContainerDiv().innerHTML = await response.text();
this.#getEditTileViewDiv().classList.add('d-none');
this.#getDefaultViewDiv().classList.remove('d-none');
} catch (e) {
glpi_toast_error(__('An unexpected error occurred.'));
console.error(e);
}
}

async #showAddTileForm()
{
try {
const url = `${CFG_GLPI.root_doc}/Config/Helpdesk/ShowAddTileForm`;
const response = await fetch(url);

// Handle server errors
if (!response.ok) {
throw new Error(response.status);
}

// Note: we use jQuery instead of raw JS here because we need scripts
// to be executed for richtext input initialization
$(this.#getAddTileViewDiv()).html(await response.text());

this.#getAddTileViewDiv().classList.remove('d-none');
this.#getDefaultViewDiv().classList.add('d-none');
} catch (e) {
glpi_toast_error(__('An unexpected error occurred.'));
console.error(e);
}
}

#cancelAddTile()
{
this.#getAddTileViewDiv().classList.add('d-none');
this.#getAddTileViewDiv().innerHTML = "";
this.#getDefaultViewDiv().classList.remove('d-none');
}

async #saveNewTile(form)
{
// Show spinner and disable button
form.querySelector(
'[data-glpi-helpdesk-config-add-tile-submit-spinner-icon]'
).classList.remove('d-none');
form.querySelector(
'[data-glpi-helpdesk-config-add-tile-submit-plus-icon]'
).classList.add('d-none');
form.querySelector(
'[data-glpi-helpdesk-config-add-tile-submit]'
).disabled = true;

try {
// Update tinymce values
if (window.tinymce !== undefined) {
window.tinymce.get().forEach(editor => {
editor.save();
});
}

// Set up form data
const form_data = new FormData(form);
form_data.append('_profile_id', this.#profile_id);

// Send request
const url = `${CFG_GLPI.root_doc}/Config/Helpdesk/AddTile`;
const response = await fetch(url, {
method: 'POST',
body: form_data,
headers: {
'X-Requested-With': 'XMLHttpRequest',
'X-Glpi-Csrf-Token': getAjaxCsrfToken(),
}
});

// Handle server errors
if (!response.ok) {
throw new Error(response.status);
}

glpi_toast_info(__("Configuration updated successfully."));

this.#getTilesContainerDiv().innerHTML = await response.text();
this.#getAddTileViewDiv().classList.add('d-none');
this.#getDefaultViewDiv().classList.remove('d-none');
} catch (e) {
glpi_toast_error(__('An unexpected error occurred.'));
console.error(e);
}
}

#triggerTypeChange(type)
{
// Use '-' instead of '\' to avoid escaping issues in selector
type = type.replaceAll('\\', '-');

const submit_button = this.#container.querySelector('[data-glpi-helpdesk-config-add-tile-submit]');

// Enabled submit button if a type is selected
if (type == 0) {
submit_button.disabled = true;
} else {
submit_button.disabled = false;
}

// Show the correct form
this.#container
.querySelectorAll('[data-glpi-helpdesk-config-add-tile-form-for]')
.forEach((node) => {
node.classList.add('d-none');
node.querySelectorAll('input, select, textarea').forEach((input) => {
input.disabled = true;
});
})
;
this.#container
.querySelectorAll(`[data-glpi-helpdesk-config-add-tile-form-for="${type}"]`)
.forEach((node) => {
node.classList.remove('d-none');
node.querySelectorAll('input, select, textarea').forEach((input) => {
input.disabled = false;
});
})
;
}
}
Loading

0 comments on commit cc45406

Please sign in to comment.