You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
6.4 KiB
JavaScript

'use strict';
define('forum/flags/list', [
'components', 'Chart', 'categoryFilter', 'autocomplete', 'api', 'alerts',
], function (components, Chart, categoryFilter, autocomplete, api, alerts) {
const Flags = {};
let selectedCids;
Flags.init = function () {
Flags.enableFilterForm();
Flags.enableCheckboxes();
Flags.handleBulkActions();
selectedCids = [];
if (ajaxify.data.filters.hasOwnProperty('cid')) {
selectedCids = Array.isArray(ajaxify.data.filters.cid) ?
ajaxify.data.filters.cid : [ajaxify.data.filters.cid];
}
categoryFilter.init($('[component="category/dropdown"]'), {
privilege: 'moderate',
selectedCids: selectedCids,
onHidden: function (data) {
selectedCids = data.selectedCids;
},
});
components.get('flags/list')
.on('click', '[data-flag-id]', function (e) {
if (['BUTTON', 'A'].includes(e.target.nodeName)) {
return;
}
const flagId = this.getAttribute('data-flag-id');
ajaxify.go('flags/' + flagId);
});
$('#flags-daily-wrapper').one('shown.bs.collapse', function () {
Flags.handleGraphs();
});
autocomplete.user($('#filter-assignee, #filter-targetUid, #filter-reporterId'), (ev, ui) => {
setTimeout(() => { ev.target.value = ui.item.user.uid; });
});
};
Flags.enableFilterForm = function () {
const $filtersEl = components.get('flags/filters');
// Parse ajaxify data to set form values to reflect current filters
for (const filter in ajaxify.data.filters) {
if (ajaxify.data.filters.hasOwnProperty(filter)) {
$filtersEl.find('[name="' + filter + '"]').val(ajaxify.data.filters[filter]);
}
}
$filtersEl.find('[name="sort"]').val(ajaxify.data.sort);
document.getElementById('apply-filters').addEventListener('click', function () {
const payload = $filtersEl.serializeArray();
// cid is special comes from categoryFilter module
selectedCids.forEach(function (cid) {
payload.push({ name: 'cid', value: cid });
});
ajaxify.go('flags?' + (payload.length ? $.param(payload) : 'reset=1'));
});
$filtersEl.find('button[data-target="#more-filters"]').click((ev) => {
const textVariant = ev.target.getAttribute('data-text-variant');
if (!textVariant) {
return;
}
ev.target.setAttribute('data-text-variant', ev.target.textContent);
ev.target.firstChild.textContent = textVariant;
});
};
Flags.enableCheckboxes = function () {
const flagsList = document.querySelector('[component="flags/list"]');
const checkboxes = flagsList.querySelectorAll('[data-flag-id] input[type="checkbox"]');
const bulkEl = document.querySelector('[component="flags/bulk-actions"] button');
let lastClicked;
document.querySelector('[data-action="toggle-all"]').addEventListener('click', function () {
const state = this.checked;
checkboxes.forEach(function (el) {
el.checked = state;
});
bulkEl.disabled = !state;
});
flagsList.addEventListener('click', function (e) {
const subselector = e.target.closest('input[type="checkbox"]');
if (subselector) {
// Stop checkbox clicks from going into the flag details
e.stopImmediatePropagation();
if (lastClicked && e.shiftKey && lastClicked !== subselector) {
// Select all the checkboxes in between
const state = subselector.checked;
let started = false;
checkboxes.forEach(function (el) {
if ([subselector, lastClicked].some(function (ref) {
return ref === el;
})) {
started = !started;
}
if (started) {
el.checked = state;
}
});
}
// (De)activate bulk actions button based on checkboxes' state
bulkEl.disabled = !Array.prototype.some.call(checkboxes, function (el) {
return el.checked;
});
lastClicked = subselector;
}
// If you miss the checkbox, don't descend into the flag details, either
if (e.target.querySelector('input[type="checkbox"]')) {
e.stopImmediatePropagation();
}
});
};
Flags.handleBulkActions = function () {
document.querySelector('[component="flags/bulk-actions"]').addEventListener('click', function (e) {
const subselector = e.target.closest('[data-action]');
if (subselector) {
const action = subselector.getAttribute('data-action');
const flagIds = Flags.getSelected();
const promises = flagIds.map((flagId) => {
const data = {};
if (action === 'bulk-assign') {
data.assignee = app.user.uid;
} else if (action === 'bulk-mark-resolved') {
data.state = 'resolved';
}
return api.put(`/flags/${flagId}`, data);
});
Promise.allSettled(promises).then(function (results) {
const fulfilled = results.filter(function (res) {
return res.status === 'fulfilled';
}).length;
const errors = results.filter(function (res) {
return res.status === 'rejected';
});
if (fulfilled) {
alerts.success('[[flags:bulk-success, ' + fulfilled + ']]');
ajaxify.refresh();
}
errors.forEach(function (res) {
alerts.error(res.reason);
});
});
}
});
};
Flags.getSelected = function () {
const checkboxes = document.querySelectorAll('[component="flags/list"] [data-flag-id] input[type="checkbox"]');
const payload = [];
checkboxes.forEach(function (el) {
if (el.checked) {
payload.push(el.closest('[data-flag-id]').getAttribute('data-flag-id'));
}
});
return payload;
};
Flags.handleGraphs = function () {
const dailyCanvas = document.getElementById('flags:daily');
const dailyLabels = utils.getDaysArray().map(function (text, idx) {
return idx % 3 ? '' : text;
});
if (utils.isMobile()) {
Chart.defaults.global.tooltips.enabled = false;
}
const data = {
'flags:daily': {
labels: dailyLabels,
datasets: [
{
label: '',
backgroundColor: 'rgba(151,187,205,0.2)',
borderColor: 'rgba(151,187,205,1)',
pointBackgroundColor: 'rgba(151,187,205,1)',
pointHoverBackgroundColor: '#fff',
pointBorderColor: '#fff',
pointHoverBorderColor: 'rgba(151,187,205,1)',
data: ajaxify.data.analytics,
},
],
},
};
dailyCanvas.width = $(dailyCanvas).parent().width();
new Chart(dailyCanvas.getContext('2d'), {
type: 'line',
data: data['flags:daily'],
options: {
responsive: true,
animation: false,
legend: {
display: false,
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
precision: 0,
},
}],
},
},
});
};
return Flags;
});