Skip to content

Commit

Permalink
Merge pull request #13 from Amsterdam/feature/merge-from-upstream
Browse files Browse the repository at this point in the history
Merge remote-tracking branch 'upstream/master' into feature/merge-fro…
  • Loading branch information
TerryvanWalen authored May 30, 2024
2 parents 7c334e2 + d050e95 commit 9094e11
Show file tree
Hide file tree
Showing 14 changed files with 346 additions and 296 deletions.
8 changes: 5 additions & 3 deletions packages/cms/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ let sites = {};
let sitesById = {};
let sitesResponse = [];
const aposStartingUp = {};
const REFRESH_SITES_INTERVAL = 60000 * 5;
const REFRESH_SITES_INTERVAL = 60000 * 15;


if (process.env.REQUEST_LOGGING === 'ON') {
Expand All @@ -61,8 +61,10 @@ app.set('trust proxy', true);
async function restartAllSites() {
const sites = Object.keys(aposServer);
const promises = sites.map(site => {
const url = new URL('http://' + site);
return fetch(`http://localhost:${process.env.PORT}${url.pathname}/config-reset`,{
const url = new URL('http://' + site);
let resetUrl = `http://localhost:${process.env.PORT}`;
resetUrl += `${url.pathname}/config-reset`.replace('//', '/');
return fetch(resetUrl,{
headers: {
Host: url.hostname
}
Expand Down
7 changes: 6 additions & 1 deletion packages/cms/lib/modules/accordeon-widgets/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ module.exports = {
label: 'Description',
widgetType: 'apostrophe-rich-text',
options: contentWidgets['apostrophe-rich-text'] || {}

},
{
type: 'string',
name: 'actionText',
label: 'Description (legacy, prefer the rich-text field if possible as this option could be removed in future updates)',
textarea: true
}
]
},
Expand Down
61 changes: 60 additions & 1 deletion packages/cms/lib/modules/openstad-global/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,69 @@ const fs = require('fs');
const fields = require('./lib/fields');
const arrangeFields = require('./lib/arrangeFields');

const deepl = require('deepl-node');
const cache = require('../../../services/cache').cache;
const cacheLanguagesLifespan = (24 * 60 * 60) * 7; // set lifespan of language cache to a week;
const translatorConfig = { maxRetries: 5, minTimeout: 10000 };

function unauthorized(req, res) {
var challengeString = 'Basic realm=Openstad';
res.set('WWW-Authenticate', challengeString);
return res.status(401).send('Authentication required.');
}

async function getSupportedLanguages(deeplAuthKey) {
let supportedLanguages = [];
const cacheKeyForLanguages = 'translationLanguages'

if (cache.get(cacheKeyForLanguages)) {
console.log("Received languages from cache");
supportedLanguages = cache.get(cacheKeyForLanguages);
}
else if (deeplAuthKey) {
console.log({deeplAuthKey})
try {
const translator = new deepl.Translator(deeplAuthKey, translatorConfig);
await translator.getTargetLanguages().then(response => {
supportedLanguages = response;
});

// convert items to their own language
const languageTranslatedCollection = [];

for (const language of supportedLanguages) {
languageTranslatedCollection.push(
translator.translateText(
language.name,
'EN',
language.code
)
);
}

await Promise.all(languageTranslatedCollection).then(languages => {
supportedLanguages = languages.map((language, index) => {
language['code'] = supportedLanguages[index].code;
return language;
});

cache.set(`${cacheKeyForLanguages}`, supportedLanguages, {
life: cacheLanguagesLifespan
});
});
} catch(error) {
supportedLanguages = supportedLanguages.map((language, index) => {
language['text'] = supportedLanguages[index].name;
return language;
})
console.error({translationError: error});
}
} else {
console.error({translationError: "Could not fetch languages for the translation widget: Key not set"});
}
console.log("deeplAuthKey")
return supportedLanguages;
}

module.exports = {
improve: 'apostrophe-global',
Expand All @@ -40,8 +97,10 @@ module.exports = {

options.arrangeFields = arrangeFields.concat(options.arrangeFields || []);

self.apos.app.use((req, res, next) => {
self.apos.app.use(async (req, res, next) => {
let deeplAuthKey = options.deeplKey;
req.data.global = req.data.global ? req.data.global : {};
req.data.global.languages = await getSupportedLanguages(deeplAuthKey);
return next();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ module.exports = [
{
name: 'mainMenu',
label: 'Hoofdmenu',
fields: ['arrangeMainMenu', 'displayLoginTopLink', 'mainMenuItems', 'ctaButtonText', 'ctaButtonUrl', 'topLinks', 'displayMyAcount', "myAccountButtonText", 'shouldAutoTranslate']
fields: ['arrangeMainMenu', 'displayLoginTopLink', 'mainMenuItems', 'ctaButtonText', 'ctaButtonUrl', 'topLinks', 'displayMyAcount', "myAccountButtonText", 'translateInMenu']
},
{
name: 'userRights',
Expand Down
4 changes: 2 additions & 2 deletions packages/cms/lib/modules/openstad-global/lib/fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ module.exports = [
},
{
type: 'boolean',
name: 'shouldAutoTranslate',
label: 'Try to translate each page on entering',
name: 'translateInMenu',
label: 'The translate widget should be visible in the menubar',
def: false,
choices: [
{
Expand Down
118 changes: 87 additions & 31 deletions packages/cms/lib/modules/openstad-global/public/js/always.js
Original file line number Diff line number Diff line change
@@ -1,60 +1,104 @@
apos.on('ready', function () {
var firstTimeLoading = true;
var nodes = [];
var selectedLanguage = localStorage.getItem("targetLanguageCode");

/**
* The translate widget if set on the page will trigger an onchange event when it has been loaded
* thus triggering the fetching of translations. Then this one should do nothing and let the dedicated
* widget make the call.
*/
var translationWidgetOnSamePage = $('.translation-widget-select').length > 0;

var userHasSpecialRole = hasModeratorRights; // references global var specified in layout.js';
var shouldTranslate = shouldTranslateOnEveryPage; // references global var specified in layout.js';
var toastContainer = document.querySelector("#openstad-toast");

if(shouldTranslate) {
if (!userHasSpecialRole && !translationWidgetOnSamePage && selectedLanguage && selectedLanguage !== 'nl') {
addToast(toastContainer, "info", "De pagina wordt vertaald...", 3000);
var nlContents = [];

nodes = handleNode(document.body, nodes);
var nlContents = nodes.map(function (itemToTranslate) { return itemToTranslate.orgText });
var languageSelectContainer = $('.language-select-container');

$('#translation-widget-select-global')
.on('change', function (e) {
changeLanguage(e);
});

function setSelectDisabled(select) {
select.setAttribute('disabled', true);
languageSelectContainer.addClass('languageLoading');
};

function setSelectEnabled(select) {
select.removeAttribute('disabled');
languageSelectContainer.removeClass('languageLoading');
};

function saveLanguagePreference(targetLanguageCode) {
try{
localStorage.setItem("targetLanguageCode", targetLanguageCode);
} catch(quotaExceededError) {
console.log("Could not save the language preference");
}
}



function changeLanguage (e) {
var select = e.target;
var targetLanguageCode = select.value;
setSelectDisabled(select);
var node = document.body;

if (firstTimeLoading) {
nodes = handleNode(node, nodes);
nlContents = nodes.map(function(itemToTranslate) { return itemToTranslate.orgText });
firstTimeLoading = false;
}

if (targetLanguageCode === 'nl') {
console.log("Language is set to the default: " + targetLanguageCode +". No need to translate");
changeTextInNodes(nlContents, nodes);
setSelectEnabled(select);
saveLanguagePreference(targetLanguageCode);
syncOtherTranslationWidgets(targetLanguageCode);
} else {
console.log('translating to', targetLanguageCode);

var toastContainer = document.querySelector("#openstad-toast");
addToast(toastContainer, "info", "De pagina wordt vertaald...", 5000);

$.ajax({
url: '/modules/openstad-global/translate',
method: 'post',
url: '/modules/translation-widgets/submit',
method: 'POST',
contentType: "application/json",
data: JSON.stringify({
contents: nlContents,
sourceLanguageCode: 'nl',
targetLanguageCode: selectedLanguage,
targetLanguageCode: targetLanguageCode,
origin: window.location.href
}),
success: function (sentences) {
sentences = sentences.map(function (sentence) { return sentence.text });
saveLanguagePreference(targetLanguageCode);
sentences = sentences.map(function(sentence) { return sentence.text });
changeTextInNodes(sentences, nodes);
setSelectEnabled(select);
addToast(toastContainer, "success", "De pagina is succesvol vertaald");
},
syncOtherTranslationWidgets(targetLanguageCode);
},
error: function() {
setSelectEnabled(select);
// setSelectedLanguage('nl');
addToast(toastContainer, "error", "De pagina kon niet worden vertaald");
}
});
} else if(userHasSpecialRole) {
if(!sessionStorage.getItem("cannot-translate-acknowledged")) {
addToast(toastContainer, "info", "De vertaalwidget kan niet worden gebruikt tijdens het bewerken van de site.", 0, function() {
sessionStorage.setItem("cannot-translate-acknowledged", true);
});
}
}
};


var select = document.querySelector('#translation-widget-select-global');
var isNormalUser = !hasModeratorRights; // references global var specified in layout.js
if(isNormalUser) {
setSelectedLanguage(localStorage.getItem('targetLanguageCode'));
} else if(select) {
select.setAttribute('disabled', true);
}
});

changeTextInNodes = function (sentences, nodes) {

function changeTextInNodes (sentences, nodes) {
sentences.forEach(function (sentence, index) {
nodes[index].node.textContent = sentence;
});
}

handleNode = function (node, toBeTranslated) {
function handleNode (node, toBeTranslated) {
var childNodes = node.childNodes;
for (var i = 0; i < childNodes.length; i++) {
if (childNodes[i].nodeType == Node.ELEMENT_NODE) {
Expand Down Expand Up @@ -118,4 +162,16 @@ function addToast(container, typeOfInfoErrorOrSuccess, text, timeout, onClick) {
}, timeout);
}
}


}

function setSelectedLanguage(language) {
$('#translation-widget-select-global').val(language ? language : 'nl').trigger('change');
}

function syncOtherTranslationWidgets(language) {
document.querySelectorAll("#translation-widget-select").forEach(function(select) {
select.value = language ? language : 'nl';
});
}
20 changes: 17 additions & 3 deletions packages/cms/lib/modules/resource-form-widgets/lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,19 @@ module.exports = async function(self, options) {
await self.addOrUpdateNotification(item, 'User');
} catch (error) {
console.error(
'something went wrong when update admin confirmation settings to api',
'something went wrong when update user confirmation settings to api',
error.message
);
}
} else {
await self.disableNotificationRuleSet(`User-${item.formName}`);
try {
await self.disableNotificationRuleSet(`User-${item.formName}`);
} catch (error) {
console.error(
'something went wrong when disabling user confirmation settings to api',
error.message
);
}
}

if (item.confirmationEnabledAdmin) {
Expand All @@ -39,7 +46,14 @@ module.exports = async function(self, options) {
);
}
} else {
await self.disableNotificationRuleSet(`Admin-${item.formName}`);
try {
await self.disableNotificationRuleSet(`Admin-${item.formName}`);
} catch (error) {
console.error(
'something went wrong when disabling admin confirmation settings to api',
error.message
);
}
}
}
})
Expand Down
Loading

0 comments on commit 9094e11

Please sign in to comment.