266 lines
8.0 KiB
JavaScript
266 lines
8.0 KiB
JavaScript
(function () {
|
|
'use strict';
|
|
|
|
if (window.__nqsTalkEmbedInitialized) {
|
|
return;
|
|
}
|
|
window.__nqsTalkEmbedInitialized = true;
|
|
|
|
var path = String(window.location && window.location.pathname ? window.location.pathname : '');
|
|
var isTalkPath = /\/apps\/spreed(\/|$)/.test(path)
|
|
|| /^\/call\/[^/?#]+/i.test(path)
|
|
|| /^\/room\/[^/?#]+/i.test(path)
|
|
|| /^\/conversation\/[^/?#]+/i.test(path);
|
|
if (!isTalkPath) {
|
|
return;
|
|
}
|
|
|
|
var placementTimer = null;
|
|
var activeToken = '';
|
|
var elements = buildUi();
|
|
|
|
function requestToken() {
|
|
if (typeof OC !== 'undefined' && OC.requestToken) {
|
|
return OC.requestToken;
|
|
}
|
|
var meta = document.querySelector('meta[name="requesttoken"]');
|
|
return meta && meta.content ? meta.content : '';
|
|
}
|
|
|
|
function appUrl(pathPart) {
|
|
if (typeof OC !== 'undefined' && typeof OC.generateUrl === 'function') {
|
|
return OC.generateUrl('/apps/nuqloud_scrum' + pathPart);
|
|
}
|
|
return '/apps/nuqloud_scrum' + pathPart;
|
|
}
|
|
|
|
function parseJsonResponse(response) {
|
|
return response.text().then(function (text) {
|
|
var data = {};
|
|
if (text) {
|
|
try {
|
|
data = JSON.parse(text);
|
|
} catch (_error) {
|
|
data = {};
|
|
}
|
|
}
|
|
if (!response.ok || (data && data.ok === false)) {
|
|
throw new Error((data && data.error) ? data.error : 'Request failed.');
|
|
}
|
|
return data;
|
|
});
|
|
}
|
|
|
|
function getJson(url) {
|
|
return fetch(url, {
|
|
method: 'GET',
|
|
credentials: 'same-origin',
|
|
headers: {
|
|
Accept: 'application/json',
|
|
requesttoken: requestToken()
|
|
}
|
|
}).then(parseJsonResponse);
|
|
}
|
|
|
|
function postJson(url, payload) {
|
|
return fetch(url, {
|
|
method: 'POST',
|
|
credentials: 'same-origin',
|
|
headers: {
|
|
Accept: 'application/json',
|
|
'Content-Type': 'application/json',
|
|
requesttoken: requestToken()
|
|
},
|
|
body: JSON.stringify(payload || {})
|
|
}).then(parseJsonResponse);
|
|
}
|
|
|
|
function extractConversationToken() {
|
|
var currentPath = String(window.location && window.location.pathname ? window.location.pathname : '');
|
|
var hashPath = String(window.location && window.location.hash ? window.location.hash : '');
|
|
var patterns = [
|
|
/^\/call\/([^/?#]+)/i,
|
|
/^\/room\/([^/?#]+)/i,
|
|
/^\/conversation\/([^/?#]+)/i,
|
|
/\/apps\/spreed\/call\/([^/?#]+)/i,
|
|
/\/apps\/spreed\/room\/([^/?#]+)/i,
|
|
/\/apps\/spreed\/conversation\/([^/?#]+)/i
|
|
];
|
|
for (var index = 0; index < patterns.length; index += 1) {
|
|
var match = currentPath.match(patterns[index]);
|
|
if (match && match[1]) {
|
|
return decodeURIComponent(match[1]);
|
|
}
|
|
}
|
|
for (var hashIndex = 0; hashIndex < patterns.length; hashIndex += 1) {
|
|
var hashMatch = hashPath.match(patterns[hashIndex]);
|
|
if (hashMatch && hashMatch[1]) {
|
|
return decodeURIComponent(hashMatch[1]);
|
|
}
|
|
}
|
|
var params = new URLSearchParams(window.location.search);
|
|
var queryCandidates = ['conversationToken', 'conversation', 'token'];
|
|
for (var keyIndex = 0; keyIndex < queryCandidates.length; keyIndex += 1) {
|
|
var value = params.get(queryCandidates[keyIndex]);
|
|
if (value && value.trim()) {
|
|
return value.trim();
|
|
}
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function conversationNameFallback() {
|
|
var title = String(document.title || '').replace(/\s+-\s+Nextcloud.*$/i, '').trim();
|
|
return title || activeToken;
|
|
}
|
|
|
|
function buildUi() {
|
|
var section = document.createElement('details');
|
|
section.className = 'nqs-talk-settings-section';
|
|
section.open = true;
|
|
|
|
var summary = document.createElement('summary');
|
|
summary.textContent = 'NuQloud Scrum';
|
|
|
|
var body = document.createElement('div');
|
|
body.className = 'nqs-talk-settings-body';
|
|
body.innerHTML = ''
|
|
+ '<p class="nqs-talk-note">Use this Talk channel as a Scrum project. Talk threads become tasks; Deck comments are the next mirror step.</p>'
|
|
+ '<div class="nqs-talk-status" role="status" aria-live="polite"></div>'
|
|
+ '<button type="button" class="button button-primary nqs-talk-toggle">Enable Scrum</button>';
|
|
|
|
section.appendChild(summary);
|
|
section.appendChild(body);
|
|
document.body.appendChild(section);
|
|
|
|
return {
|
|
section: section,
|
|
status: body.querySelector('.nqs-talk-status'),
|
|
toggle: body.querySelector('.nqs-talk-toggle')
|
|
};
|
|
}
|
|
|
|
function isVisibleNode(node) {
|
|
if (!node || !node.isConnected || node.getAttribute('aria-hidden') === 'true') {
|
|
return false;
|
|
}
|
|
try {
|
|
var style = window.getComputedStyle(node);
|
|
return style.display !== 'none' && style.visibility !== 'hidden';
|
|
} catch (_error) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
function findConversationSettingsHost() {
|
|
var selectors = [
|
|
'[role="dialog"] [data-cy-conversation-settings]',
|
|
'[aria-modal="true"] [data-cy-conversation-settings]',
|
|
'.modal-container [data-cy-conversation-settings]',
|
|
'.modal-wrapper [data-cy-conversation-settings]',
|
|
'.nc-modal [data-cy-conversation-settings]',
|
|
'.v--modal-box [data-cy-conversation-settings]',
|
|
'[role="dialog"] [id*="conversation-settings"]',
|
|
'[aria-modal="true"] [id*="conversation-settings"]',
|
|
'[role="dialog"] [class*="conversation-settings"]',
|
|
'[aria-modal="true"] [class*="conversation-settings"]'
|
|
];
|
|
for (var index = 0; index < selectors.length; index += 1) {
|
|
var nodes = document.querySelectorAll(selectors[index]);
|
|
for (var nodeIndex = 0; nodeIndex < nodes.length; nodeIndex += 1) {
|
|
if (isVisibleNode(nodes[nodeIndex])) {
|
|
return nodes[nodeIndex];
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function setStatus(message, isError) {
|
|
if (!elements.status) {
|
|
return;
|
|
}
|
|
elements.status.textContent = message;
|
|
elements.status.classList.toggle('nqs-talk-error', Boolean(isError));
|
|
}
|
|
|
|
function renderStatus(status) {
|
|
var enabled = Boolean(status && status.enabled);
|
|
elements.toggle.textContent = enabled ? 'Disable Scrum' : 'Enable Scrum';
|
|
elements.toggle.dataset.enabled = enabled ? '1' : '0';
|
|
setStatus(enabled ? 'Scrum is enabled for this project.' : 'Scrum is disabled for this project.', false);
|
|
}
|
|
|
|
function loadStatus() {
|
|
var token = extractConversationToken();
|
|
if (!token) {
|
|
activeToken = '';
|
|
elements.toggle.disabled = true;
|
|
setStatus('Open a Talk conversation to manage Scrum.', false);
|
|
return Promise.resolve();
|
|
}
|
|
activeToken = token;
|
|
elements.toggle.disabled = true;
|
|
setStatus('Loading Scrum status...', false);
|
|
return getJson(appUrl('/api/conversations/' + encodeURIComponent(token) + '/scrum'))
|
|
.then(function (result) {
|
|
var data = result && result.data ? result.data : {};
|
|
renderStatus(data);
|
|
})
|
|
.catch(function (error) {
|
|
setStatus('Unable to load Scrum status for this conversation. ' + error.message, true);
|
|
})
|
|
.finally(function () {
|
|
elements.toggle.disabled = false;
|
|
});
|
|
}
|
|
|
|
function toggleScrum() {
|
|
var token = activeToken || extractConversationToken();
|
|
if (!token) {
|
|
setStatus('Open a Talk conversation to manage Scrum.', true);
|
|
return;
|
|
}
|
|
var enabled = elements.toggle.dataset.enabled !== '1';
|
|
elements.toggle.disabled = true;
|
|
setStatus(enabled ? 'Enabling Scrum...' : 'Disabling Scrum...', false);
|
|
postJson(appUrl('/api/conversations/' + encodeURIComponent(token) + '/scrum'), {
|
|
enabled: enabled,
|
|
talkRoomName: conversationNameFallback()
|
|
}).then(function (result) {
|
|
var data = result && result.data ? result.data : {};
|
|
renderStatus(data);
|
|
}).catch(function (error) {
|
|
setStatus('Unable to update Scrum for this conversation. ' + error.message, true);
|
|
}).finally(function () {
|
|
elements.toggle.disabled = false;
|
|
});
|
|
}
|
|
|
|
function syncPlacement() {
|
|
var host = findConversationSettingsHost();
|
|
if (!host) {
|
|
if (elements.section.parentNode !== document.body) {
|
|
document.body.appendChild(elements.section);
|
|
}
|
|
elements.section.classList.add('nqs-hidden');
|
|
return;
|
|
}
|
|
if (elements.section.parentNode !== host) {
|
|
host.appendChild(elements.section);
|
|
loadStatus();
|
|
}
|
|
elements.section.classList.remove('nqs-hidden');
|
|
}
|
|
|
|
elements.toggle.addEventListener('click', toggleScrum);
|
|
|
|
placementTimer = window.setInterval(syncPlacement, 1100);
|
|
document.addEventListener('click', function () {
|
|
window.setTimeout(syncPlacement, 100);
|
|
}, true);
|
|
window.addEventListener('hashchange', loadStatus);
|
|
window.addEventListener('popstate', loadStatus);
|
|
syncPlacement();
|
|
}());
|