163 lines
4.6 KiB
JavaScript
163 lines
4.6 KiB
JavaScript
async function getHTML(endpoint, options = {}) {
|
|
let query = {};
|
|
if (options._query !== undefined) {
|
|
query = options._query;
|
|
delete options._query;
|
|
}
|
|
|
|
const params = new URLSearchParams(query);
|
|
const res = await fetch(`${endpoint}?${params}`, options);
|
|
|
|
return { body: await res.text(), status: res.status };
|
|
}
|
|
|
|
const validateBase64Img = dataURL => new Promise(resolve => {
|
|
const img = new Image();
|
|
img.onload = () => {
|
|
resolve(img.width === 88 && img.height === 31);
|
|
};
|
|
img.src = dataURL;
|
|
});
|
|
|
|
export const b = {
|
|
init: 'badgeEditorInit',
|
|
}
|
|
|
|
const badgeEditorEndpoint = '/hyperapi/badges/editor/'
|
|
const MAX_BADGES = 10;
|
|
let badgesCount = 0;
|
|
let customImageDatas = {};
|
|
|
|
export async function badgeEditorInit(_, __, el) {
|
|
const res = await getHTML(badgeEditorEndpoint);
|
|
if (res.status != 200) {
|
|
return;
|
|
}
|
|
el.innerHTML = res.body;
|
|
badgesCount = el.querySelectorAll('.sortable-item').length;
|
|
b.trigger('badgeEditorAssignImgId');
|
|
b.trigger('setBadgeCount');
|
|
}
|
|
|
|
export function badgeEditorAssignImgId(_, __, el) {
|
|
if (el.dataset.imgId) return;
|
|
|
|
const id = b.uuid();
|
|
const filePicker = el.querySelector('input[type=file]');
|
|
const img = el.querySelector('img.badge-button');
|
|
console.log(img);
|
|
el.dataset.imgId = id;
|
|
filePicker.dataset.imgId = id;
|
|
img.dataset.imgId = id;
|
|
}
|
|
|
|
export function badgeEditorSetPreview(ev, sender, el) {
|
|
if (!sender.parentNode.contains(el)) return;
|
|
|
|
const selectedItem = sender.selectedOptions[0];
|
|
if (selectedItem.value !== 'custom') {
|
|
el.src = selectedItem.dataset.filePath;
|
|
} else if (customImageDatas[el.dataset.imgId]) {
|
|
el.src = customImageDatas[el.dataset.imgId];
|
|
} else {
|
|
el.removeAttribute('src');
|
|
}
|
|
}
|
|
|
|
export function badgeEditorSetPreviewCustom(payload, _, el) {
|
|
if (!payload.badge.contains(el)) return;
|
|
if (!customImageDatas[el.dataset.imgId]) {
|
|
el.removeAttribute('src');
|
|
} else {
|
|
el.src = customImageDatas[el.dataset.imgId];
|
|
}
|
|
}
|
|
|
|
export function badgeEditorToggleFilePicker(ev, sender, el) {
|
|
if (!sender.parentNode.parentNode.contains(el)) return;
|
|
|
|
const selectedItem = sender.selectedOptions[0];
|
|
const picker = el.querySelector('input[type=file]');
|
|
if (selectedItem.value !== 'custom') {
|
|
el.classList.add('hidden');
|
|
picker.required = false;
|
|
picker.setCustomValidity('');
|
|
} else {
|
|
el.classList.remove('hidden');
|
|
picker.required = true;
|
|
picker.setCustomValidity(picker.dataset.validity || '');
|
|
}
|
|
}
|
|
|
|
export function badgeEditorAddBadge(ev, sender, el) {
|
|
// TODO: page templates do not get updated on mutation
|
|
const badge = document.getElementById('badge-template').innerText;
|
|
el.innerHTML += badge;
|
|
b.trigger('badgeEditorAssignImgId');
|
|
badgesCount++;
|
|
b.trigger('setBadgeCount');
|
|
}
|
|
|
|
export function badgeEditorDelete(ev, sender, el) {
|
|
if (!el.contains(sender)) return;
|
|
el.remove();
|
|
badgesCount--;
|
|
b.trigger('setBadgeCount');
|
|
}
|
|
|
|
export function badgeEditorShowFilePicker(ev, sender, el) {
|
|
if (sender.nextElementSibling !== el) return;
|
|
el.showPicker();
|
|
}
|
|
|
|
export async function badgeEditorFileSelected(ev, sender, el) {
|
|
const file = sender.files[0];
|
|
const badge = sender.parentNode.parentNode;
|
|
|
|
if (
|
|
!['image/png', 'image/jpeg', 'image/jpg', 'image/webp'].includes(file.type)
|
|
) {
|
|
sender.dataset.validity = 'The badge file must be an image.';
|
|
sender.setCustomValidity(sender.dataset.validity);
|
|
sender.reportValidity();
|
|
customImageDatas[sender.dataset.imgId] = null;
|
|
b.send({ badge: badge }, 'badgeEditorSetPreviewCustom');
|
|
return;
|
|
}
|
|
if (file.size >= 1000 * 500) {
|
|
sender.dataset.validity = 'The badge image must be smaller than 500KB.';
|
|
sender.setCustomValidity(sender.dataset.validity);
|
|
sender.reportValidity();
|
|
customImageDatas[sender.dataset.imgId] = null;
|
|
b.send({ badge: badge }, 'badgeEditorSetPreviewCustom');
|
|
return;
|
|
}
|
|
|
|
const reader = new FileReader();
|
|
reader.onload = async e => {
|
|
const dimsValid = await validateBase64Img(e.target.result);
|
|
if (!dimsValid) {
|
|
sender.setCustomValidity('The badge image must be exactly 88x31 pixels.');
|
|
sender.reportValidity();
|
|
customImageDatas[sender.dataset.imgId] = null;
|
|
b.send({ badge: badge }, 'badgeEditorSetPreviewCustom');
|
|
return;
|
|
}
|
|
customImageDatas[sender.dataset.imgId] = e.target.result;
|
|
|
|
sender.dataset.validity = '';
|
|
sender.setCustomValidity('');
|
|
b.send({ badge: badge }, 'badgeEditorSetPreviewCustom');
|
|
}
|
|
|
|
reader.readAsDataURL(file);
|
|
}
|
|
|
|
export function setBadgeCount(_, __, el) {
|
|
if (el instanceof HTMLButtonElement) {
|
|
el.disabled = badgesCount === MAX_BADGES;
|
|
} else {
|
|
el.innerText = `${badgesCount}/${MAX_BADGES}`;
|
|
}
|
|
}
|