Skip to content

Commit

Permalink
refactors endpoints and redux for storyvars
Browse files Browse the repository at this point in the history
  • Loading branch information
jhmullen committed Oct 8, 2021
1 parent 2020753 commit d088c90
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 88 deletions.
17 changes: 9 additions & 8 deletions packages/cms/src/actions/profiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ export function fetchVariables(config) {
dispatch({type: "VARIABLES_FETCH", data: "Generators"});
const {localeDefault, localeSecondary, currentPid, currentStoryPid} = getStore().cms.status;
const {auth} = getStore();
const isStory = config && config.parentType === "story";
const isStory = config.type.includes("story_");
const previews = isStory ? [] : getStore().cms.status.previews;

const thisProfile = isStory
Expand Down Expand Up @@ -370,11 +370,10 @@ export function fetchVariables(config) {
if (!variables[thisLocale]._genStatus.durations) variables[thisLocale]._genStatus.durations = {};
variables[thisLocale]._genStatus.durations.attributes = durationByLocale[thisLocale];
let paramString = previews.reduce((acc, p, i) => `${acc}&slug${i + 1}=${p.slug}&id${i + 1}=${p.id}`, "");
if (config && (config.type === "materializer" || config.type === "generator")) paramString += `&${config.type}=${config.id}`;
if (isStory) paramString += "&parentType=story";
if (!config || config && config.type === "generator") {
// If given a config, clear that generator. If not given a config, this is a first run, clear everything.
const gids = config ? [config.id] : thisProfile.generators.map(d => d.id);
if (config.id && ["generator", "materializer", "story_generator", "story_materializer"].includes(config.type)) paramString += `&${config.type}=${config.id}`;
if (config.type.includes("generator")) {
// If given an id, clear that generator. If not given an, this is a first run, clear everything.
const gids = config.id ? [config.id] : thisProfile.generators.map(d => d.id);
for (const gid of gids) {
if (variables[thisLocale]._genStatus[gid]) {
Object.keys(variables[thisLocale]._genStatus[gid]).forEach(k => {
Expand All @@ -383,7 +382,8 @@ export function fetchVariables(config) {
}
delete variables[thisLocale]._genStatus[gid];
}
const gen = await axios.post(`${getStore().env.CANON_API}/api/generators/${thisID}?locale=${thisLocale}${paramString}`, {attributes}).catch(catcher);
const endpoint = isStory ? "story_generators" : "generators";
const gen = await axios.post(`${getStore().env.CANON_API}/api/${endpoint}/${thisID}?locale=${thisLocale}${paramString}`, {attributes}).catch(catcher);
variables[thisLocale] = assign({}, variables[thisLocale], gen.data);
}
dispatch({type: "VARIABLES_FETCH", data: "Materializers"});
Expand All @@ -394,7 +394,8 @@ export function fetchVariables(config) {
});
delete variables[thisLocale]._matStatus[mid];
});
const mat = await axios.post(`${getStore().env.CANON_API}/api/materializers/${thisID}?locale=${thisLocale}${paramString}`, {variables: variables[thisLocale]}).catch(catcher);
const endpoint = isStory ? "story_materializers" : "materializers";
const mat = await axios.post(`${getStore().env.CANON_API}/api/${endpoint}/${thisID}?locale=${thisLocale}${paramString}`, {variables: variables[thisLocale]}).catch(catcher);
variables[thisLocale] = assign({}, variables[thisLocale], mat.data);
const diffCounter = getStore().cms.status.diffCounter + 1;
dispatch({type: "VARIABLES_SET", data: {variables}});
Expand Down
32 changes: 21 additions & 11 deletions packages/cms/src/api/mortarRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -413,18 +413,20 @@ module.exports = function(app) {

};

app.get("/api/generators/:pid", async(req, res) =>
req.params.parentType === "story"
? res.json(await runStoryGenerators(req, req.params.pid, req.query.generator))
: res.json(await runGenerators(req, req.params.pid, req.query.generator)));
app.post("/api/generators/:pid", async(req, res) =>
req.params.parentType === "story"
? res.json(await runStoryGenerators(req, req.params.pid, req.query.generator, req.body.attributes))
: res.json(await runGenerators(req, req.params.pid, req.query.generator, req.body.attributes)));

const runMaterializers = async(req, variables, pid) => {
app.get("/api/story_generators/:pid", async(req, res) => res.json(await runStoryGenerators(req, req.params.pid, req.query.story_generator)));
app.post("/api/story_generators/:pid", async(req, res) => res.json(await runStoryGenerators(req, req.params.pid, req.query.story_generator, req.body.attributes)));
app.get("/api/generators/:pid", async(req, res) => res.json(await runGenerators(req, req.params.pid, req.query.generator)));
app.post("/api/generators/:pid", async(req, res) => res.json(await runGenerators(req, req.params.pid, req.query.generator, req.body.attributes)));

const runMaterializers = async(req, variables, pid, isStory) => {
const locale = req.query.locale ? req.query.locale : envLoc;
let materializers = await db.materializer.findAll({where: {profile_id: pid}}).catch(catcher);
let materializers;
if (isStory) {
materializers = await db.story_materializer.findAll({where: {story_id: pid}}).catch(catcher);
}
else {
materializers = await db.materializer.findAll({where: {profile_id: pid}}).catch(catcher);
}
materializers = materializers
.map(m => m.toJSON())
.filter(m => !m.allowed || m.allowed === "always" || variables[m.allowed]);
Expand Down Expand Up @@ -453,6 +455,14 @@ module.exports = function(app) {
return res.json(await runMaterializers(req, variables, materializer.profile_id));
});

app.post("/api/story_materializers/:pid", async(req, res) => {
const {pid} = req.params;
const {variables} = req.body;
const materializer = await db.story_materializer.findOne({where: {story_id: pid}}).catch(catcher);
if (!materializer) return res.json({});
return res.json(await runMaterializers(req, variables, materializer.profile_id, true));
});

/* Main API Route to fetch a profile, given a list of slug/id pairs
* slugs represent the type of page (geo, naics, soc, cip, university)
* ids represent actual entities / locations (nyc, bu)
Expand Down
25 changes: 16 additions & 9 deletions packages/cms/src/components/cards/VariableCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import {setStatus} from "../../actions/status";

import "./VariableCard.css";

const isGenMat = d => ["generator", "materializer", "story_generator", "story_materializer"].includes(d);

class VariableCard extends Component {

constructor(props) {
super(props);
this.state = {
Expand All @@ -44,14 +47,18 @@ class VariableCard extends Component {
const {type, minData} = this.props;
const {id} = minData;

const didUpdate = this.props.status.justUpdated && this.props.status.justUpdated.type === type && this.props.status.justUpdated.id === this.props.minData.id && JSON.stringify(this.props.status.justUpdated) !== JSON.stringify(prevProps.status.justUpdated);
const didUpdate =
this.props.status.justUpdated &&
this.props.status.justUpdated.type === type &&
this.props.status.justUpdated.id === this.props.minData.id &&
JSON.stringify(this.props.status.justUpdated) !== JSON.stringify(prevProps.status.justUpdated);
if (didUpdate) {
const Toast = this.context.toast.current;
const {status} = this.props.status.justUpdated;
if (status === "SUCCESS") {
Toast.show({icon: "saved", intent: Intent.SUCCESS, message: "Saved!", timeout: 1000});
// If a gen/mat was saved, re-run fetchvariables for just this one gen/mat.
if (type === "generator" || type === "materializer") {
if (isGenMat(type)) {
const config = {type, id: minData.id};
this.props.fetchVariables(config);
// Unlike other cards, who can simply set dialogOpen:false in status.js in redux, a gen/mat may have
Expand All @@ -73,7 +80,7 @@ class VariableCard extends Component {
// If diffCounter incremented, it means a variables update completed, either from this card saving,
// or from ANOTHER card saving. If it was this card, we need to update the front panel, if it was another card,
// we may need to update whether this card contains a duplicate. Either way, format the display.
if (type === "generator" || type === "materializer") {
if (isGenMat(type)) {
const variablesChanged = prevProps.status.diffCounter !== this.props.status.diffCounter;
if (variablesChanged) this.formatDisplay.bind(this)();
}
Expand All @@ -95,27 +102,27 @@ class VariableCard extends Component {
let dupes = [];
let size = 0;
let duration = false;
if (type === "generator") {
if (type === "generator" || type === "story_generator") {
displayData = variables._genStatus[id];
if (localeSecondary) {
secondaryDisplayData = secondaryVariables._genStatus[id];
}
if (variables._genStatus.durations) duration = variables._genStatus.durations[id];
}
else if (type === "materializer") {
else if (type === "materializer" || type === "story_materalizer") {
displayData = variables._matStatus[id];
if (localeSecondary) {
secondaryDisplayData = secondaryVariables._matStatus[id];
}
}
if (type === "generator" || type === "materializer") {
const status = type === "generator" ? "_genStatus" : "_matStatus";
if (isGenMat(type)) {
const status = type === "generator" || type === "story_generator" ? "_genStatus" : "_matStatus";
const theseVars = variables[status][id];
if (theseVars) {
const otherGens = Object.keys(variables._genStatus).reduce((acc, _id) =>
type === "materializer" || String(id) !== String(_id) ? Object.assign({}, acc, variables._genStatus[_id]) : acc, {});
type === "materializer" || type === "story_materializer" || String(id) !== String(_id) ? Object.assign({}, acc, variables._genStatus[_id]) : acc, {});
const otherMats = Object.keys(variables._matStatus).reduce((acc, _id) =>
type === "generator" || String(id) !== String(_id) ? Object.assign({}, acc, variables._matStatus[_id]) : acc, {});
type === "generator" || type === "story_generator" || String(id) !== String(_id) ? Object.assign({}, acc, variables._matStatus[_id]) : acc, {});
const thoseVars = {...otherGens, ...otherMats};
dupes = dupes.concat(Object.keys(theseVars).reduce((acc, k) => k !== "error" && thoseVars[k] !== undefined ? acc.concat(k) : acc, []));
size = JSON.stringify(theseVars).length;
Expand Down
24 changes: 14 additions & 10 deletions packages/cms/src/components/editors/VariableEditor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@ import "./VariableEditor.css";

const preMessage = {
generator: <Fragment>You have access to the variable <strong>resp</strong>, which represents the response to the above API call.</Fragment>,
story_generator: <Fragment>You have access to the variable <strong>resp</strong>, which represents the response to the above API call.</Fragment>,
materializer: <Fragment>You have access to all variables previously created by generators</Fragment>,
story_materializer: <Fragment>You have access to all variables previously created by generators</Fragment>,
visualization: <Fragment>You have access to all variables previously created by generators and materializers.</Fragment>,
formatter: <Fragment>You have access to the variable <code>n</code>, which represents the string to be formatted.</Fragment>
};

const postMessage = {
generator: <Fragment>Be sure to return an <strong>object</strong> with the variables you want stored as keys.</Fragment>,
story_generator: <Fragment>Be sure to return an <strong>object</strong> with the variables you want stored as keys.</Fragment>,
materalizer: <Fragment>Be sure to return an <strong>object</strong> with the variables you want stored as keys.</Fragment>,
story_materalizer: <Fragment>Be sure to return an <strong>object</strong> with the variables you want stored as keys.</Fragment>,
visualization: <Fragment>Be sure to return a valid config object for a visualization</Fragment>,
formatter: <Fragment>Be sure to return a <strong>string</strong> that represents your formatted content.</Fragment>
};
Expand All @@ -47,7 +51,7 @@ class VariableEditor extends Component {
const {data, type} = this.props;
// If simple has been used in the past and this is a generator, we MUST fetch the payload from the
// API so that the results for the variables can be filled in.
if (type === "generator") {
if (type.includes("generator")) {
const maybePreview = () => data.simple ? this.previewPayload(true) : null;
this.setState({data}, maybePreview);
}
Expand Down Expand Up @@ -190,7 +194,7 @@ class VariableEditor extends Component {
// If we are enabling simple mode
else {
// If it's a generator, then we need a payload before we can switch over.
if (type === "generator") {
if (type.includes("generator")) {
this.previewPayload.bind(this)(true);
}
// However it's a visualization, no payload is needed. Enable simple mode and switch without an API call.
Expand Down Expand Up @@ -226,7 +230,7 @@ class VariableEditor extends Component {

// add the UI mode toggle to footer
let modeSwitcher = null;
if (type === "generator" || type.includes("visualization")) {
if (type.includes("generator") || type.includes("visualization")) {
modeSwitcher =
<Switch
checked={simple}
Expand All @@ -242,7 +246,7 @@ class VariableEditor extends Component {
<Fragment>
<div className="cms-variable-editor" key="e">
{/* name & description fields */}
{(type === "generator" || type === "materializer" || type === "formatter") &&
{(type.includes("generator") || type.includes("materializer") || type === "formatter") &&
<div className="cms-field-group">
<TextInput
label="Name"
Expand All @@ -261,7 +265,7 @@ class VariableEditor extends Component {
</div>
}

{type === "generator" && <Fragment key="gf">
{type.includes("generator") && <Fragment key="gf">
<TextButtonGroup
namespace="cms"
inputProps={{
Expand All @@ -287,7 +291,7 @@ class VariableEditor extends Component {

<div className={`cms-variable-editor-group u-margin-top-off ${simple ? "ui-mode" : "js-mode"}`}>

{type === "generator" ? modeSwitcher : ""}
{type.includes("generator") ? modeSwitcher : ""}

{/* json */}
{payload &&
Expand All @@ -302,7 +306,7 @@ class VariableEditor extends Component {
}

{simple
? type === "generator"
? type.includes("generator")
? payload
? <VariableEditorUI
key="simp-gen"
Expand Down Expand Up @@ -347,11 +351,11 @@ class VariableEditor extends Component {
}

{/* visibility */}
{["generator", "materializer", "visualization"].includes(type) &&
{["generator", "materializer", "story_generator", "story_materializer", "visualization"].includes(type) &&
<VisibleSelector
type="generator"
hideCustom={["generator", "materializer"].includes(type)}
variables={["generator"].includes(type) ? magicVariables : variables}
hideCustom={["generator", "materializer", "story_generator", "story_materializer"].includes(type)}
variables={["generator", "story_generator"].includes(type) ? magicVariables : variables}
value={data.allowed !== undefined ? data.allowed : "always"}
onChange={this.changeData.bind(this, "allowed")}
/>
Expand Down
4 changes: 2 additions & 2 deletions packages/cms/src/components/interface/Deck.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default class Deck extends Component {
const entity = this.props.entity || title.toLowerCase();

let inToolbox = false;
if (entity === "generator" || entity === "materializer" || entity === "formatter" || entity === "selector") {
if (["generator", "materializer", "formatter", "selector", "story_generator", "story_materializer", "story_selector"].includes(entity)) {
inToolbox = true;
}

Expand All @@ -38,7 +38,7 @@ export default class Deck extends Component {
<span className="u-visually-hidden"> ({isOpen ? "collapse" : "open"} section)</span>
<Icon className="cms-deck-button-icon" icon="caret-down" />
</button>
{(cards && cards.length > 0 && addItem) || inToolbox === true
{cards && cards.length > 0 && addItem || inToolbox === true
? <Button onClick={addItem} className="cms-deck-heading-add-button" fontSize="xxs" namespace="cms" icon="plus">
add {entity === "description" ? "paragraph" : entity}
</Button>
Expand Down
Loading

0 comments on commit d088c90

Please sign in to comment.