Skip to content

Commit

Permalink
Merge pull request #912 from City-of-Helsinki/UHF-11448
Browse files Browse the repository at this point in the history
UHF-11448
  • Loading branch information
rpnykanen authored Feb 24, 2025
2 parents 5f454b4 + f4bf9db commit f6ba6c5
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 166 deletions.
333 changes: 168 additions & 165 deletions assets/js/telia_ace.js
Original file line number Diff line number Diff line change
@@ -1,195 +1,198 @@
// eslint-disable-next-line func-names
(function (Drupal, drupalSettings) {
class TeliaAceLeijuke {
constructor(teliaAceData) {
this.static = {
chatId: teliaAceData.chat_id,
selector: `leijuke_${teliaAceData.chat_id}`,
chatTitle: teliaAceData.chat_title,
scriptUrl: teliaAceData.script_url,
scriptSri: teliaAceData.script_sri
};
this.state = {
cookies: this.cookieCheck(),
chatLoading: false,
chatLoaded: false,
chatOpened: false,
busy: false
};
}

// eslint-disable-next-line class-methods-use-this
cookieCheck() {
return Drupal.cookieConsent.getConsentStatus(['chat']);
}

// eslint-disable-next-line class-methods-use-this
cookieSet() {
if (Drupal.cookieConsent.getConsentStatus(['chat'])) return;

Drupal.cookieConsent.setAcceptedCategories(['chat']);
}

init() {
if (this.state.cookies) {
// Cookies already set so chat assets can be loaded.
this.loadChat();
}

this.initWrapper();
this.render();
}

loadChat() {
const { scriptUrl, scriptSri } = this.static;
const leijuke = this;
const chatScript = document.createElement('script');
chatScript.src = scriptUrl;
chatScript.type = 'text/javascript';
chatScript.setAttribute('async', '');

if (scriptSri) {
chatScript.integrity = scriptSri;
chatScript.crossOrigin = 'anonymous';
}

// eslint-disable-next-line func-names
chatScript.onload = function() {
leijuke.loaded();
};
Drupal.behaviors.telia_ace = {
attach: function attach() {
setTimeout(() => {
if (drupalSettings.telia_ace_data.initialized) {
return;
}

// Insert chatScript into head
const head = document.querySelector('head');
head.appendChild(chatScript);
this.state.chatLoading = true;
}
let chatSettings = {};
try {
chatSettings = new ChatSettings(drupalSettings.telia_ace_data ?? {});
}
catch (e) {
console.error(e);
return;
}

loaded() {
this.state = {
...this.state,
chatLoaded: true,
};
this.openChat();
this.render();
new TeliaAceWidget(chatSettings);
drupalSettings.telia_ace_data.initialized = true;
});
}
};
})(Drupal, drupalSettings);

initWrapper() {
let teliaAceLeijukeWrapper = document.getElementById('telia-ace-leijuke');
if (!teliaAceLeijukeWrapper) {
teliaAceLeijukeWrapper = document.createElement('aside');
teliaAceLeijukeWrapper.id = 'telia-ace-leijuke';
document.body.append(teliaAceLeijukeWrapper);
}

const teliaAceLeijukeInstance = document.createElement('button');
teliaAceLeijukeInstance.id = this.static.selector;
teliaAceLeijukeInstance.classList.add('chat-leijuke');
teliaAceLeijukeInstance.classList.add('telia-chat-leijuke');
class TeliaAceWidget {
constructor(chatSettings) {
this.static = {
chatId: chatSettings.chat_id,
selector: `leijuke_${chatSettings.chat_id}`,
chatTitle: chatSettings.chat_title,
scriptUrl: chatSettings.script_url,
};
this.state = {
cookies: this.cookieCheck(),
chatLoading: false,
chatLoaded: false,
chatOpened: false,
busy: false
};
this.init();
}

teliaAceLeijukeWrapper.append(teliaAceLeijukeInstance);
/**
* Initialize the chat libraries and elements.
*/
init = () => {
const chatButton = this.createChatWidget();
this.addEventListener(chatButton);
this.render();
}

this.prepButton(teliaAceLeijukeInstance);
/**
* Set up the chat button elements.
*/
createChatWidget = () => {
let teliaAceWidgetWrapper = document.getElementById('telia-ace-leijuke');
if (!teliaAceWidgetWrapper) {
teliaAceWidgetWrapper = document.createElement('aside');
teliaAceWidgetWrapper.id = 'telia-ace-leijuke';
document.body.append(teliaAceWidgetWrapper);
}

prepButton(button) {
const teliaAceWidgetInstance = document.createElement('button');
teliaAceWidgetInstance.id = this.static.selector;
teliaAceWidgetInstance.classList.add('chat-leijuke');
teliaAceWidgetInstance.classList.add('telia-chat-leijuke');

button.addEventListener('click', () => {
teliaAceWidgetWrapper.append(teliaAceWidgetInstance);

// Debounce button.
if (this.state.busy) {
return;
}
this.state = {
...this.state,
busy: true,
};

// If chat was loaded, cookies are ok.
if (this.state.chatLoaded) {
this.openChat(true);
return;
}
return teliaAceWidgetInstance;
}

if (!this.state.cookies) {
// Implicitly allow chat cookies if clicking Leijuke.
this.cookieSet();
}
/**
* Adds self-removing event-listener to the chat button.
*
* Automatically accept the chat cookies and load the chat script
* when user clicks the chat button. Then open the chat on "onloaad".
*
* @param chatButton
*/
addEventListener = (chatButton) => {
chatButton.addEventListener('click', () => {
if (!this.cookieCheck()) {
this.cookieSet();
}
this.loadChatScript();
this.openChat(true);
}, { once: true });
}

this.state = {
...this.state,
cookies: this.cookieCheck()
};
/**
* Load the chat script.
*/
loadChatScript = () => {
const chatScript = document.createElement('script');
chatScript.src = this.static.scriptUrl;
chatScript.type = 'text/javascript';
chatScript.setAttribute('async', '');

// If the cookieCheck returns false, it means they could not be set
// implicitly, which means something is wrong in the config.
if (this.state.cookies) {
this.loadChat();
this.openChat(true);
}
chatScript.onload = this.loaded;

});
}
const head = document.querySelector('head');
head.appendChild(chatScript);
this.state.chatLoading = true;
}

openChat(openWidget) {
const leijuke = this;

const teliaAceWidgetInitialized = setInterval(() => {
if(typeof window.humany !== 'undefined' && typeof window.humany.widgets !== 'undefined' && window.humany.widgets.find(leijuke.static.chatId)){
if (openWidget) {
const myWidget = window.humany.widgets.find(leijuke.static.chatId);
myWidget.activate();
myWidget.invoke('show');
}
clearInterval(teliaAceWidgetInitialized);
leijuke.state = {
...leijuke.state,
chatLoading: false,
chatOpened: true,
busy: false,
};
leijuke.render();
}
// Interval is set to 50 milliseconds here.
// This doesn't poll the variables too often but should seem quick to users.
}, 50);
/**
* Render the chat element.
*/
render = () => {
const { chatOpened, chatLoading } = this.state;
const label = chatLoading ? Drupal.t('Loading chat...', {}, {context: 'Telia ACE chat'}) : this.static.chatTitle;
const element = document.getElementById(this.static.selector);
if (!element) {
return;
}

render() {
const { chatOpened, chatLoading } = this.state;
const label = chatLoading ? Drupal.t('Loading chat...', {}, {context: 'Telia ACE chat'}) : this.static.chatTitle;
const element = document.getElementById(this.static.selector);
if (!element) {
return;
}
const innerHTML = `
const innerHTML = `
<span class="hel-icon hel-icon--speechbubble-text"></span>
<span>${label}</span>
<span class="hel-icon hel-icon--angle-up"></span>
`;

if (element.innerHTML !== innerHTML) {
element.innerHTML = innerHTML;
}
element.classList.toggle('loading', chatLoading);
element.classList.toggle('hidden', chatOpened);
if (element.innerHTML !== innerHTML) {
element.innerHTML = innerHTML;
}
element.classList.toggle('loading', chatLoading);
element.classList.toggle('hidden', chatOpened);
}

cookieCheck = () => {
return Drupal.cookieConsent.getConsentStatus(['chat']);
}

Drupal.behaviors.telia_ace = {
attach: function attach() {
const teliaAceData = drupalSettings.telia_ace_data;
cookieSet = () => {
if (Drupal.cookieConsent.getConsentStatus(['chat'])) return;
Drupal.cookieConsent.setAcceptedCategories(['chat']);
}

setTimeout(() => {
// Only load any leijuke once, in case of ajax triggers.
if (teliaAceData.initialized) {
return;
/**
* Onload callback for the chat script.
*/
loaded = () => {
this.state = {
...this.state,
chatLoaded: true,
};
this.openChat();
this.render();
}

/**
* Call the humany activation method if chat is loaded.
*
* @param openWidget
* To open the chat session or not.
*/
openChat = (openWidget) => {
const teliaAceWidgetInitialized = setInterval(() => {
if(typeof window.humany !== 'undefined' && typeof window.humany.widgets !== 'undefined' && window.humany.widgets.find(this.static.chatId)){
if (openWidget) {
const myWidget = window.humany.widgets.find(this.static.chatId);
myWidget.activate();
myWidget.invoke('show');
}
clearInterval(teliaAceWidgetInitialized);
this.state = {
...this.state,
chatLoading: false,
chatOpened: true,
busy: false,
};
this.render();
}
}, 50);
}
}

class ChatSettings {
constructor(settings) {
const requiredSettings = [
'chat_title',
'chat_id',
'script_url'
];

// Check that the required settings exist.
requiredSettings.forEach(value => {
if (!settings.hasOwnProperty(value) || !settings[value]) {
throw new Error(`Missing expected ace chat setting ${value}`);
}
});

const teliaAce = new TeliaAceLeijuke(teliaAceData);
teliaAce.init();
drupalSettings.telia_ace_data.initialized = true;
});
}
};
})(Drupal, drupalSettings);
this.chat_title = settings.chat_title
this.chat_id = settings.chat_id
this.script_url = settings.script_url
}
}
2 changes: 1 addition & 1 deletion helfi_platform_config.libraries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ chat_enhancer:
- core/drupal

telia_ace_widget_loadjs:
version: 1.1.0
version: 1.1.1
css:
theme:
assets/css/telia_ace.css: {}
Expand Down

0 comments on commit f6ba6c5

Please sign in to comment.