editoria11y-1.0.0-alpha8/js/editoria11y-admin.js
js/editoria11y-admin.js
/* globals Drupal, drupalSettings, Ed11y, console */
/**
* Drupal initializer.
* Launch as behavior and pull variables from config.
*/
Drupal.behaviors.editoria11yAdmin = {
attach: function (context, settings) {
"use strict";
if (context === document && CSS.supports("selector(:is(body))")) {
const filters = document.querySelector('.view-filters > form');
if (filters) {
const details = document.createElement('details');
// @todo 3.0 test and style in Gin admin theme.
details.classList.add('claro-details', 'ed11y-filters');
const summary = document.createElement('summary');
summary.classList.add('claro-details__summary');
summary.textContent = Drupal.t('Filter');
details.appendChild(summary);
if (document.querySelector('#edit-reset')) {
details.open = true;
}
filters.insertAdjacentElement('beforebegin', details);
}
if (!drupalSettings.path.language || drupalSettings.path.language === 'en') {
document.body.classList.add('ed11y-no-th-hyphens');
}
// Set refs for path tracebacks.
const ed1s = document.querySelectorAll('a[href][data-ed1ref]');
ed1s?.forEach((el) => {
let append = el.getAttribute('href');
append += append.indexOf('?') > -1 ? '&ed1ref=' : '?ed1ref=';
append += encodeURIComponent(el.getAttribute('data-ed1ref'));
el.setAttribute('href', append);
});
// Look for resetters.
let resetPath = document.querySelector('.ed11y-reset-this-path');
let resetDismissal = [];
let resetDismissalWrapper = document.querySelectorAll('span.ed11y-reset-dismissal:not(.done)');
resetDismissalWrapper.forEach(el => {
const button = document.createElement('button');
button.classList.add('ed11y-reset-this-dismissal','action-link','action-link--icon-trash');
const eid = el.querySelector('.ed11y-page-id');
const id = el.querySelector('.ed11y-dismissal-id');
eid.hidden = true;
id.hidden = true;
button.appendChild(eid);
button.appendChild(id);
el.appendChild(button);
resetDismissal.push(button);
el.classList.add('done');
});
if (drupalSettings.editoria11y.api_url && ((drupalSettings.editoria11y.admin && !!resetPath) || resetDismissal.length > 0)) {
// Set up error handling.
const messages = new Drupal.Message();
const handleErrors = function(data) {
messages.add(`${data.message}: ${data.description}`, {type: 'warning'});
};
let apiUrl = drupalSettings.editoria11y.api_url;
let sessionUrl = drupalSettings.editoria11y.session_url;
// Get cross-request token for API
let csrfToken = false;
let getCsrfToken = async function (data, action) {
{
fetch(`${sessionUrl}`, {
method: "GET"
})
.then(res => res.text())
.then(token => {
csrfToken = token;
postData(data, action).catch((error) => {
console.log(error);
});
})
.catch((error) => {
console.log(error);
});
}
};
let hidables = [];
// Send a request to the purge API endpoint.
let postData = async function (data, action) {
if (!csrfToken) {
await getCsrfToken(data, action);
}
if (csrfToken) {
let apiRoot = apiUrl.replace('results/report', 'purge');
let url = `${apiRoot}/${action}`;
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken,
},
body: JSON.stringify(data),
})
.catch((error) => {
console.log(error);
})
.then((response) => response.json())
.then((data) => {
if (data.message === 'error') {
handleErrors(data);
} else {
messages.add('Deleted.', {type: 'status'});
}
});
}
};
// Responsive tables: drupal.org/project/editoria11y/issues/3536720.
const deSaw = (el) => {
const inner = el.querySelector('.tablesaw-cell-content');
return inner ? inner.textContent.trim() : el.textContent.trim();
// todo 3.0 rewrite this maybe go back to inner hidden span
};
if (!!resetPath) {
let purgeThisPage = function (event) {
event.preventDefault();
let data = {
page_path: deSaw( event.target.querySelector('.ed11y-api-path') )
};
hidables = document.querySelectorAll('.view-editoria11y-results td');
hidables?.forEach(el => {
el.parentElement.removeChild(el);
});
postData(data, 'page', hidables).then();
};
resetPath.removeAttribute('hidden');
resetPath.querySelector('a')?.addEventListener('click', purgeThisPage);
} else if (!!resetDismissal) {
let purgeThisDismissal = function (event) {
event.preventDefault();
const eid = deSaw ( event.target.querySelector('.ed11y-page-id') );
const dismissal = deSaw ( event.target.querySelector('.ed11y-dismissal-id') );
const data = {
dismissal_id: dismissal,
pid: eid,
};
const tr = event.target.closest('tr');
let previous = tr?.previousElementSibling;
postData(data, 'dismissal', hidables).then(
// @todo 3.x error handling?
);
previous?.querySelector('a')?.focus();
window.setTimeout((tr)=> {
tr.parentElement.removeChild( tr );
}, 500, tr);
};
resetDismissal.forEach(el => { el.addEventListener('click', purgeThisDismissal); });
}
}
// Alert for missing views.
const views = ['pages', 'results', 'dismissals'];
views.forEach((type) => {
const missingView = document.querySelector(`.ed11y-${type}-view h2:last-child`);
if (missingView) {
const viewsMessage = Drupal.t('<p>The Editoria11y <strong><em>@type</em></strong> view is missing.</p>', {'@type': type});
const viewsExplanation = Drupal.t("<p>There are three view configurations this module installs, found in its /config/install folder. Each must be installed for this dashboard to display results.</p>");
const viewsInstruction = Drupal.t('<p>To fix: copy and paste the contents of <strong>/editoria11y/config/install/views.view.editoria11y_@type.yml</strong> into a "View" type import at <a href="/admin/config/development/configuration/single/import">/admin/config/development/configuration/single/import</a>. If you sync your configuration to the filesystem, be sure to include these Views in your repository.</p>', {'@type': type});
const message = new Drupal.Message();
message.add(viewsMessage + viewsExplanation + viewsInstruction, {type: 'error'});
}
});
}
}
};
