Skip to content

Commit

Permalink
refactors routes and front-end so that defaultlang can be anything, n…
Browse files Browse the repository at this point in the history
…ot just en
  • Loading branch information
jhmullen committed Feb 7, 2019
1 parent b8713f5 commit 5c3873c
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 41 deletions.
7 changes: 4 additions & 3 deletions packages/cms/src/api/cmsRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -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/");

Expand Down Expand Up @@ -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 {
Expand All @@ -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);
Expand Down
21 changes: 14 additions & 7 deletions packages/cms/src/api/mortarRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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 => {
Expand All @@ -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: [
Expand Down
10 changes: 5 additions & 5 deletions packages/cms/src/components/cards/GeneratorCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "";
Expand Down Expand Up @@ -146,12 +146,12 @@ class GeneratorCard extends Component {
{/* title & edit toggle button */}
<h5 className="cms-card-header">
<span className={`cms-card-header-icon pt-icon-standard pt-icon-th ${type}`} />
{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" && <button className="cms-button" onClick={this.openEditor.bind(this)}>
{locale === localeDefault && <button className="cms-button" onClick={this.openEditor.bind(this)}>
Edit <span className="pt-icon pt-icon-cog" />
</button>}
</h5>
Expand Down
36 changes: 23 additions & 13 deletions packages/cms/src/components/cards/TextCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,32 @@ 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));
});
}

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
Expand All @@ -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});
}

Expand Down Expand Up @@ -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 <Loading />;

Expand Down
4 changes: 2 additions & 2 deletions packages/cms/src/components/cards/VisualizationCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class VisualizationCard extends Component {
if (!minData) return <Loading />;

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);
Expand Down Expand Up @@ -135,7 +135,7 @@ class VisualizationCard extends Component {
</Alert>

{/* title & edit toggle button */}
{locale === "en" && <h5 className="cms-card-header">
{locale === localeDefault && <h5 className="cms-card-header">
<button className="cms-button" onClick={this.openEditor.bind(this)}>
Edit <span className="pt-icon pt-icon-cog" />
</button>
Expand Down
16 changes: 12 additions & 4 deletions packages/cms/src/story/StoryEditor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ class StoryEditor extends Component {
<div className="cms-card-list">
<TextCard
item={minData}
locale="en"
locale={localeDefault}
localeDefault={localeDefault}
fields={["title", "subtitle"]}
plainfields={["image"]}
type="story"
Expand All @@ -132,6 +133,7 @@ class StoryEditor extends Component {
{locale && <TextCard
item={minData}
locale={locale}
localeDefault={localeDefault}
fields={["title", "subtitle"]}
plainfields={["image"]}
type="story"
Expand Down Expand Up @@ -162,7 +164,8 @@ class StoryEditor extends Component {
{ minData.descriptions && minData.descriptions.map(d =>
<TextCard key={d.id}
item={d}
locale="en"
locale={localeDefault}
localeDefault={localeDefault}
onDelete={this.onDelete.bind(this)}
fields={["description"]}
type="story_description"
Expand All @@ -177,6 +180,7 @@ class StoryEditor extends Component {
<TextCard key={d.id}
item={d}
locale={locale}
localeDefault={localeDefault}
onDelete={this.onDelete.bind(this)}
fields={["description"]}
type="story_description"
Expand All @@ -198,7 +202,8 @@ class StoryEditor extends Component {
{ minData.footnotes && minData.footnotes.map(d =>
<TextCard key={d.id}
item={d}
locale="en"
locale={localeDefault}
localeDefault={localeDefault}
ordering={d.ordering}
onDelete={this.onDelete.bind(this)}
fields={["title", "description"]}
Expand All @@ -214,6 +219,7 @@ class StoryEditor extends Component {
<TextCard key={d.id}
item={d}
locale={locale}
localeDefault={localeDefault}
ordering={d.ordering}
onDelete={this.onDelete.bind(this)}
fields={["title", "description"]}
Expand All @@ -236,7 +242,8 @@ class StoryEditor extends Component {
{ minData.authors && minData.authors.map(d =>
<TextCard key={d.id}
item={d}
locale="en"
locale={localeDefault}
localeDefault={localeDefault}
onDelete={this.onDelete.bind(this)}
fields={["bio"]}
plainfields={["name", "title", "image", "twitter"]}
Expand All @@ -252,6 +259,7 @@ class StoryEditor extends Component {
<TextCard key={d.id}
item={d}
locale={locale}
localeDefault={localeDefault}
onDelete={this.onDelete.bind(this)}
fields={["bio"]}
plainfields={["name", "title", "image", "twitter"]}
Expand Down
20 changes: 15 additions & 5 deletions packages/cms/src/story/StoryTopicEditor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class StoryTopicEditor extends Component {
render() {

const {minData} = this.state;
const {locale} = this.props;
const {locale, localeDefault} = this.props;

if (!minData) return <Loading />;

Expand Down Expand Up @@ -129,7 +129,8 @@ class StoryTopicEditor extends Component {
<div className="cms-card-list">
<TextCard
item={minData}
locale="en"
locale={localeDefault}
localeDefault={localeDefault}
fields={["title"]}
plainfields={["image"]}
type="storytopic"
Expand All @@ -139,6 +140,7 @@ class StoryTopicEditor extends Component {
{locale && <TextCard
item={minData}
locale={locale}
localeDefault={localeDefault}
fields={["title"]}
plainfields={["image"]}
type="storytopic"
Expand All @@ -159,7 +161,8 @@ class StoryTopicEditor extends Component {
<TextCard
key={s.id}
item={s}
locale="en"
locale={localeDefault}
localeDefault={localeDefault}
fields={["subtitle"]}
type="storytopic_subtitle"
onDelete={this.onDelete.bind(this)}
Expand All @@ -174,6 +177,7 @@ class StoryTopicEditor extends Component {
<TextCard
key={s.id}
locale={locale}
localeDefault={localeDefault}
item={s}
fields={["subtitle"]}
type="storytopic_subtitle"
Expand All @@ -197,7 +201,8 @@ class StoryTopicEditor extends Component {
<TextCard
key={s.id}
item={s}
locale="en"
locale={localeDefault}
localeDefault={localeDefault}
fields={["title", "subtitle", "value", "tooltip"]}
type="storytopic_stat"
onDelete={this.onDelete.bind(this)}
Expand All @@ -213,6 +218,7 @@ class StoryTopicEditor extends Component {
key={s.id}
item={s}
locale={locale}
localeDefault={localeDefault}
fields={["title", "subtitle", "value", "tooltip"]}
type="storytopic_stat"
onDelete={this.onDelete.bind(this)}
Expand All @@ -235,7 +241,8 @@ class StoryTopicEditor extends Component {
<TextCard
key={d.id}
item={d}
locale="en"
locale={localeDefault}
localeDefault={localeDefault}
fields={["description"]}
type="storytopic_description"
onDelete={this.onDelete.bind(this)}
Expand All @@ -251,6 +258,7 @@ class StoryTopicEditor extends Component {
key={d.id}
item={d}
locale={locale}
localeDefault={localeDefault}
fields={["description"]}
type="storytopic_description"
onDelete={this.onDelete.bind(this)}
Expand All @@ -273,6 +281,8 @@ class StoryTopicEditor extends Component {
<VisualizationCard
key={v.id}
item={v}
locale={locale}
localeDefault={localeDefault}
onDelete={this.onDelete.bind(this)}
type="storytopic_visualization"
variables={{}}
Expand Down
4 changes: 3 additions & 1 deletion packages/cms/src/utils/d3plusPropify.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {assign} from "d3plus-common";
import {parse} from "./FUNC";

export default (logic, formatters = {}, variables = {}, locale = "en") => {
const envLoc = process.env.CANON_LANGUAGE_DEFAULT || "en";

export default (logic, formatters = {}, variables = {}, locale = envLoc) => {

let config;

Expand Down
4 changes: 3 additions & 1 deletion packages/cms/src/utils/mortarEval.js
Original file line number Diff line number Diff line change
@@ -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.
Expand Down

0 comments on commit 5c3873c

Please sign in to comment.