diff --git a/packages/cms/src/api/cmsRoute.js b/packages/cms/src/api/cmsRoute.js index 89a9a93ef..081728300 100644 --- a/packages/cms/src/api/cmsRoute.js +++ b/packages/cms/src/api/cmsRoute.js @@ -7,6 +7,7 @@ const path = require("path"); const Op = sequelize.Op; const client = new Client(process.env.CANON_LOGICLAYER_CUBE); +const envLoc = process.env.CANON_LANGUAGE_DEFAULT || "en"; const topicTypeDir = path.join(__dirname, "../components/topics/"); @@ -362,7 +363,7 @@ module.exports = function(app) { db[ref].create(req.body).then(newObj => { // For a certain subset of translated tables, we need to also insert a new, corresponding english content row. if (contentTables.includes(ref)) { - const payload = Object.assign({}, req.body, {id: newObj.id, lang: "en"}); + const payload = Object.assign({}, req.body, {id: newObj.id, lang: envLoc}); db[`${ref}_content`].create(payload).then(() => res.json(newObj).end()); } else { @@ -375,9 +376,9 @@ module.exports = function(app) { app.post("/api/cms/profile/newScaffold", isEnabled, (req, res) => { const profileData = req.body; db.profile.create({slug: profileData.slug, ordering: profileData.ordering, dimension: profileData.dimName}).then(profile => { - db.profile_content.create({id: profile.id, lang: "en"}).then(() => { + db.profile_content.create({id: profile.id, lang: envLoc}).then(() => { db.topic.create({ordering: 0, profile_id: profile.id}).then(topic => { - db.topic_content.create({id: topic.id, lang: "en"}).then(() => { + db.topic_content.create({id: topic.id, lang: envLoc}).then(() => { db.profile.findAll(profileReqTreeOnly).then(profiles => { profiles = sortProfileTree(db, profiles); populateSearch(profileData, db); diff --git a/packages/cms/src/api/mortarRoute.js b/packages/cms/src/api/mortarRoute.js index 2ff3a5bb7..9021ae226 100644 --- a/packages/cms/src/api/mortarRoute.js +++ b/packages/cms/src/api/mortarRoute.js @@ -8,6 +8,7 @@ const FUNC = require("../utils/FUNC"), yn = require("yn"); const verbose = yn(process.env.CANON_CMS_LOGGING); +const envLoc = process.env.CANON_LANGUAGE_DEFAULT || "en"; const searchMap = { cip: "CIP", @@ -130,11 +131,17 @@ const sortStory = story => { */ const bubbleUp = (obj, locale) => { - const enCon = obj.content.find(c => c.lang === "en"); + const fieldSet = []; + obj.content.forEach(c => { + Object.keys(c).forEach(k => { + if (!fieldSet.includes(k)) fieldSet.push(k); + }); + }); + const defCon = obj.content.find(c => c.lang === envLoc); const thisCon = obj.content.find(c => c.lang === locale); - Object.keys(enCon).forEach(k => { + fieldSet.forEach(k => { if (k !== "id" && k !== "lang") { - thisCon && thisCon[k] ? obj[k] = thisCon[k] : obj[k] = enCon[k]; + thisCon && thisCon[k] ? obj[k] = thisCon[k] : obj[k] = defCon ? defCon[k] : ""; } }); delete obj.content; @@ -176,14 +183,14 @@ module.exports = function(app) { app.get("/api/internalprofile/:slug", (req, res) => { const {slug} = req.params; - const locale = req.query.locale ? req.query.locale : "en"; + const locale = req.query.locale ? req.query.locale : envLoc; const reqObj = Object.assign({}, profileReq, {where: {slug}}); db.profile.findOne(reqObj).then(profile => res.json(sortProfile(extractLocaleContent(profile, locale, "profile"))).end()); }); app.get("/api/variables/:slug/:id", (req, res) => { // app.get("/api/variables/:slug/:id", jsonCache, (req, res) => { - const locale = req.query.locale ? req.query.locale : "en"; + const locale = req.query.locale ? req.query.locale : envLoc; req.setTimeout(1000 * 60 * 30); // 30 minute timeout for non-cached cube queries const {slug, id} = req.params; @@ -366,7 +373,7 @@ module.exports = function(app) { // Endpoint for getting a story app.get("/api/story/:id", (req, res) => { const {id} = req.params; - const locale = req.query.locale ? req.query.locale : "en"; + const locale = req.query.locale ? req.query.locale : envLoc; // Using a Sequelize OR when the two OR columns are of different types causes a Sequelize error, necessitating this workaround. const reqObj = !isNaN(id) ? Object.assign({}, storyReq, {where: {id}}) : Object.assign({}, storyReq, {where: {slug: id}}); db.story.findOne(reqObj).then(story => { @@ -380,7 +387,7 @@ module.exports = function(app) { // Endpoint for getting all stories app.get("/api/story", (req, res) => { - const locale = req.query.locale ? req.query.locale : "en"; + const locale = req.query.locale ? req.query.locale : envLoc; db.story.findAll({include: [ {association: "content"}, {association: "authors", include: [ diff --git a/packages/cms/src/components/cards/GeneratorCard.jsx b/packages/cms/src/components/cards/GeneratorCard.jsx index a858c67e0..e3e8f61cc 100644 --- a/packages/cms/src/components/cards/GeneratorCard.jsx +++ b/packages/cms/src/components/cards/GeneratorCard.jsx @@ -110,7 +110,7 @@ class GeneratorCard extends Component { } render() { - const {type, variables, item, parentArray, preview, locale} = this.props; + const {type, variables, item, parentArray, preview, locale, localeDefault} = this.props; const {displayData, minData, isOpen, alertObj} = this.state; let description = ""; @@ -146,12 +146,12 @@ class GeneratorCard extends Component { {/* title & edit toggle button */}
- {locale === "en" ? minData.name : `${minData.name} (${locale})`} - {/* In multi-lang, there are two sets of gens and mats, one for english, and one for the other locale. + {locale === localeDefault ? minData.name : `${minData.name} (${locale})`} + {/* In multi-lang, there are two sets of gens and mats, one for default, and one for the other locale. * If we put an edit button on both, then two visual entities can edit the same db structure, which is confusing - * the english gen/mat is the "master/only" one, so only show the edit button if this is english (the one for the + * the default gen/mat is the "master/only" one, so only show the edit button if this is default (the one for the * other locale is essentially for display purposes only)*/} - {locale === "en" && }
diff --git a/packages/cms/src/components/cards/TextCard.jsx b/packages/cms/src/components/cards/TextCard.jsx index 1f3eb1be6..486a962e5 100644 --- a/packages/cms/src/components/cards/TextCard.jsx +++ b/packages/cms/src/components/cards/TextCard.jsx @@ -38,18 +38,24 @@ class TextCard extends Component { } hitDB() { - const {item, type, locale} = this.props; + const {item, type, locale, localeDefault, fields, plainfields} = this.props; const {id} = item; axios.get(`/api/cms/${type}/get/${id}`).then(resp => { - // If this has been opened with a non english locale, and there is NO row for that locale, + // If this has been opened with a non default locale, and there is NO row for that locale, // create a placeholder row that can be edited in the text boxes (and later saved) const minData = resp.data; if (!minData.content.find(c => c.lang === locale)) { - const english = minData.content.find(c => c.lang === "en"); + const def = minData.content.find(c => c.lang === localeDefault); const newLangObj = {id: minData.id, lang: locale}; - Object.keys(english).forEach(k => { - if (k !== "id" && k !== "lang") newLangObj[k] = english[k]; - }); + // If the default has had any portion filled in, pre-populate the placeholder with those. + if (def) { + Object.keys(def).forEach(k => { + if (k !== "id" && k !== "lang") newLangObj[k] = def[k]; + }); + } + // If for any reason the default was missing fields, fill the rest with blanks + fields.forEach(k => !newLangObj[k] ? newLangObj[k] = "" : null); + if (plainfields) plainfields.forEach(k => !newLangObj[k] ? newLangObj[k] = "" : null); minData.content.push(newLangObj); } this.setState({minData}, this.formatDisplay.bind(this)); @@ -57,7 +63,7 @@ class TextCard extends Component { } formatDisplay() { - const {variables, selectors, locale} = this.props; + const {variables, selectors, locale, localeDefault, fields, plainfields} = this.props; const {formatters} = this.context; const {minData} = this.state; // Setting "selectors" here is pretty hacky. The varSwap needs selectors in order @@ -66,13 +72,18 @@ class TextCard extends Component { minData.selectors = selectors; // Swap vars, and extract the actual (multilingual) content const content = varSwapRecursive(minData, formatters, variables).content; - const english = content.find(c => c.lang === "en"); + const def = content.find(c => c.lang === localeDefault); const currLang = content.find(c => c.lang === locale); - // Map over each of the english keys, and fetch its equivalent locale version (or default to english) + // Map over each of the default keys, and fetch its equivalent locale version (or default) const displayData = {}; - Object.keys(english).forEach(k => { - displayData[k] = currLang[k] ? currLang[k] : english[k]; - }); + if (def) { + Object.keys(def).forEach(k => { + displayData[k] = currLang[k] ? currLang[k] : def[k]; + }); + } + // If for any reason the default was missing fields, fill the rest with blanks + fields.forEach(k => displayData[k] = currLang[k] ? currLang[k] : ""); + if (plainfields) plainfields.forEach(k => displayData[k] = currLang[k] ? currLang[k] : ""); this.setState({displayData}); } @@ -142,7 +153,6 @@ class TextCard extends Component { render() { const {displayData, minData, isOpen, alertObj} = this.state; const {variables, fields, plainfields, type, parentArray, item, locale} = this.props; - const {ordering} = item; if (!minData || !displayData) return ; diff --git a/packages/cms/src/components/cards/VisualizationCard.jsx b/packages/cms/src/components/cards/VisualizationCard.jsx index 78db650f9..313f488de 100644 --- a/packages/cms/src/components/cards/VisualizationCard.jsx +++ b/packages/cms/src/components/cards/VisualizationCard.jsx @@ -96,7 +96,7 @@ class VisualizationCard extends Component { if (!minData) return ; const {formatters} = this.context; - const {selectors, type, variables, parentArray, item, preview, locale} = this.props; + const {selectors, type, variables, parentArray, item, preview, locale, localeDefault} = this.props; minData.selectors = selectors; const {logic} = varSwapRecursive(minData, formatters, variables); @@ -135,7 +135,7 @@ class VisualizationCard extends Component { {/* title & edit toggle button */} - {locale === "en" &&
+ {locale === localeDefault &&
diff --git a/packages/cms/src/story/StoryEditor.jsx b/packages/cms/src/story/StoryEditor.jsx index c27e7cb90..1bb4e9a96 100644 --- a/packages/cms/src/story/StoryEditor.jsx +++ b/packages/cms/src/story/StoryEditor.jsx @@ -122,7 +122,8 @@ class StoryEditor extends Component {
; @@ -129,7 +129,8 @@ class StoryTopicEditor extends Component {
{ +const envLoc = process.env.CANON_LANGUAGE_DEFAULT || "en"; + +export default (logic, formatters = {}, variables = {}, locale = envLoc) => { let config; diff --git a/packages/cms/src/utils/mortarEval.js b/packages/cms/src/utils/mortarEval.js index a12d81f3c..037716b1c 100644 --- a/packages/cms/src/utils/mortarEval.js +++ b/packages/cms/src/utils/mortarEval.js @@ -1,6 +1,8 @@ const libs = require("./libs"); -module.exports = (varInnerName, varOuterValue, logic, formatterFunctions, locale = "en") => { +const envLoc = process.env.CANON_LANGUAGE_DEFAULT || "en"; + +module.exports = (varInnerName, varOuterValue, logic, formatterFunctions, locale = envLoc) => { let vars = {}; // Because logic is arbitrary javascript, it may be malformed. We need to wrap the // entire execution in a try/catch.