110 lines
5.0 KiB
JavaScript
110 lines
5.0 KiB
JavaScript
// Shared controls for the customer page and service workspace.
|
|
var SupportUI = {
|
|
initAttachments(container, label){
|
|
container.addEventListener('error', function(event){
|
|
const image = event.target;
|
|
if(!image || image.tagName !== 'IMG' || !image.classList.contains('message-image') || image.dataset.unavailable) return;
|
|
image.dataset.unavailable = '1';
|
|
image.hidden = true;
|
|
const hint = document.createElement('span');
|
|
hint.className = 'attachment-unavailable';
|
|
hint.textContent = typeof label === 'function' ? label() : label;
|
|
image.after(hint);
|
|
}, true);
|
|
},
|
|
async enableNotifications(button){
|
|
if(!('Notification' in window)) return;
|
|
try{
|
|
const permission = await Notification.requestPermission();
|
|
button.setAttribute('aria-pressed', String(permission === 'granted'));
|
|
}catch(error){}
|
|
},
|
|
notify(title, body){
|
|
if(!document.hidden || !('Notification' in window) || Notification.permission !== 'granted') return;
|
|
try{
|
|
const notice = new Notification(title, {body:body});
|
|
notice.onclick = function(){ window.focus(); notice.close(); };
|
|
}catch(error){}
|
|
},
|
|
addRating(container, sid, labels){
|
|
const request = labels.fetch || fetch;
|
|
const box = document.createElement('section');
|
|
box.className = 'service-rating';
|
|
const question = document.createElement('p');
|
|
question.textContent = labels.question;
|
|
box.appendChild(question);
|
|
const choices = document.createElement('div');
|
|
choices.className = 'rating-choices';
|
|
box.appendChild(choices);
|
|
const status = document.createElement('p');
|
|
status.setAttribute('role', 'status');
|
|
box.appendChild(status);
|
|
let sending = false;
|
|
[1, 2, 3, 4, 5].forEach(function(stars){
|
|
const button = document.createElement('button');
|
|
button.type = 'button';
|
|
button.textContent = '★';
|
|
button.setAttribute('aria-label', stars+' / 5');
|
|
button.onmouseenter = function(){
|
|
Array.from(choices.children).forEach(function(item, index){ item.classList.toggle('selected', index < stars); });
|
|
};
|
|
button.onclick = async function(){
|
|
if(sending) return;
|
|
sending = true;
|
|
Array.from(choices.children).forEach(function(item){ item.disabled = true; });
|
|
try{
|
|
const response = await request('/api/rate', {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({sid:sid, stars:stars, comment:''})});
|
|
const data = await response.json();
|
|
if(!response.ok || !data.ok) throw new Error('Rating failed');
|
|
box.textContent = labels.thanks+' '+ '★'.repeat(stars);
|
|
}catch(error){
|
|
sending = false;
|
|
status.textContent = labels.failed;
|
|
Array.from(choices.children).forEach(function(item){ item.disabled = false; });
|
|
}
|
|
};
|
|
choices.appendChild(button);
|
|
});
|
|
container.appendChild(box);
|
|
return box;
|
|
},
|
|
initEmoji(button, panel, input, onInsert){
|
|
const emojis = ['😊', '😂', '👍', '❤️', '🙏', '😅', '😢', '🎉', '📦', '🚚'];
|
|
function close(){
|
|
panel.hidden = true;
|
|
button.setAttribute('aria-expanded', 'false');
|
|
}
|
|
button.onclick = function(){
|
|
panel.hidden = !panel.hidden;
|
|
button.setAttribute('aria-expanded', String(!panel.hidden));
|
|
};
|
|
emojis.forEach(function(emoji){
|
|
const choice = document.createElement('button');
|
|
choice.type = 'button';
|
|
choice.textContent = emoji;
|
|
choice.onclick = function(){
|
|
const start = input.selectionStart == null ? input.value.length : input.selectionStart;
|
|
const end = input.selectionEnd == null ? start : input.selectionEnd;
|
|
input.value = input.value.slice(0, start) + emoji + input.value.slice(end);
|
|
close();
|
|
input.focus({preventScroll:true});
|
|
input.setSelectionRange(start + emoji.length, start + emoji.length);
|
|
if(onInsert) onInsert();
|
|
};
|
|
panel.appendChild(choice);
|
|
});
|
|
['pointerdown','mousedown'].forEach(function(name){
|
|
document.addEventListener(name, function(event){
|
|
if(!panel.hidden && !panel.contains(event.target) && !button.contains(event.target)) close();
|
|
});
|
|
});
|
|
document.addEventListener('keydown', function(event){
|
|
if(event.key === 'Escape' && !panel.hidden){
|
|
close();
|
|
button.focus({preventScroll:true});
|
|
}
|
|
});
|
|
return {close:close};
|
|
}
|
|
};
|