Bug 1621110 - Enable message editing for CFRs and Snippets on the general tab r=pdahiya

Differential Revision: https://phabricator.services.mozilla.com/D79916
This commit is contained in:
emcminn 2020-06-30 22:53:07 +00:00
Родитель 2ba9319525
Коммит aaf096ab28
7 изменённых файлов: 155 добавлений и 11 удалений

Просмотреть файл

@ -508,6 +508,7 @@ export class ASRouterAdminInner extends React.PureComponent {
messageFilter: "all", messageFilter: "all",
WNMessages: [], WNMessages: [],
collapsedMessages: [], collapsedMessages: [],
modifiedMessages: [],
evaluationStatus: {}, evaluationStatus: {},
trailhead: {}, trailhead: {},
stringTargetingParameters: null, stringTargetingParameters: null,
@ -580,6 +581,23 @@ export class ASRouterAdminInner extends React.PureComponent {
return () => ASRouterUtils.unblockById(msg.id); return () => ASRouterUtils.unblockById(msg.id);
} }
resetJSON(msg) {
// reset the displayed JSON for the given message
document.getElementById(`${msg.id}-textarea`).value = JSON.stringify(
msg,
null,
2
);
// remove the message from the list of modified IDs
let index = this.state.modifiedMessages.indexOf(msg.id);
this.setState(prevState => ({
modifiedMessages: [
...prevState.modifiedMessages.slice(0, index),
...prevState.modifiedMessages.slice(index + 1),
],
}));
}
handleOverride(id) { handleOverride(id) {
return () => ASRouterUtils.overrideMessage(id); return () => ASRouterUtils.overrideMessage(id);
} }
@ -788,6 +806,20 @@ export class ASRouterAdminInner extends React.PureComponent {
} }
} }
modifyJson(msg) {
ASRouterUtils.modifyMessageJson(
JSON.parse(document.getElementById(`${msg.id}-textarea`).value)
);
}
handleChange(msgId) {
if (!this.state.modifiedMessages.includes(msgId)) {
this.setState(prevState => ({
modifiedMessages: prevState.modifiedMessages.concat(msgId),
}));
}
}
renderMessageItem(msg) { renderMessageItem(msg) {
const isBlockedByGroup = this.state.groups const isBlockedByGroup = this.state.groups
.filter(group => msg.groups.includes(group.id)) .filter(group => msg.groups.includes(group.id))
@ -805,6 +837,7 @@ export class ASRouterAdminInner extends React.PureComponent {
? this.state.messageImpressions[msg.id].length ? this.state.messageImpressions[msg.id].length
: 0; : 0;
const isCollapsed = this.state.collapsedMessages.includes(msg.id); const isCollapsed = this.state.collapsedMessages.includes(msg.id);
const isModified = this.state.modifiedMessages.includes(msg.id);
let itemClassName = "message-item"; let itemClassName = "message-item";
if (isBlocked) { if (isBlocked) {
@ -834,11 +867,32 @@ export class ASRouterAdminInner extends React.PureComponent {
> >
{isBlocked ? "Unblock" : "Block"} {isBlocked ? "Unblock" : "Block"}
</button> </button>
{isBlocked ? null : ( {// eslint-disable-next-line no-nested-ternary
<button className="button" onClick={this.handleOverride(msg.id)}> isBlocked ? null : isModified ? (
<button
className="button restore"
// eslint-disable-next-line react/jsx-no-bind
onClick={e => this.resetJSON(msg)}
>
Reset
</button>
) : (
<button
className="button show"
onClick={this.handleOverride(msg.id)}
>
Show Show
</button> </button>
)} )}
{isBlocked ? null : (
<button
className="button modify"
// eslint-disable-next-line react/jsx-no-bind
onClick={e => this.modifyJson(msg)}
>
Modify
</button>
)}
<br />({impressions} impressions) <br />({impressions} impressions)
</td> </td>
<td className="message-summary"> <td className="message-summary">
@ -852,7 +906,16 @@ export class ASRouterAdminInner extends React.PureComponent {
)} )}
<tr> <tr>
<pre className={isCollapsed ? "collapsed" : "expanded"}> <pre className={isCollapsed ? "collapsed" : "expanded"}>
<textarea
id={`${msg.id}-textarea`}
name={msg.id}
className="general-textarea"
disabled={isBlocked}
// eslint-disable-next-line react/jsx-no-bind
onChange={e => this.handleChange(msg.id)}
>
{JSON.stringify(msg, null, 2)} {JSON.stringify(msg, null, 2)}
</textarea>
</pre> </pre>
</tr> </tr>
</td> </td>
@ -959,12 +1022,19 @@ export class ASRouterAdminInner extends React.PureComponent {
return ( return (
<div> <div>
<button <button
className="ASRouterButton slim button" className="ASRouterButton slim"
// eslint-disable-next-line react/jsx-no-bind // eslint-disable-next-line react/jsx-no-bind
onClick={e => this.toggleAllMessages(messagesToShow)} onClick={e => this.toggleAllMessages(messagesToShow)}
> >
Collapse/Expand All Collapse/Expand All
</button> </button>
<p className="helpLink">
<span className="icon icon-small-spacer icon-info" />{" "}
<span>
To modify a message, change the JSON and click 'Modify' to see your
changes. Click 'Reset' to restore the JSON to the original.
</span>
</p>
<table> <table>
<tbody> <tbody>
{messagesToShow.map(msg => this.renderMessageItem(msg))} {messagesToShow.map(msg => this.renderMessageItem(msg))}

Просмотреть файл

@ -78,6 +78,15 @@
margin-bottom: 0; margin-bottom: 0;
} }
.general-textarea {
width: 740px;
height: 500px;
overflow: auto;
resize: none;
border-radius: 4px;
display: flex;
}
.wnp-textarea { .wnp-textarea {
width: 740px; width: 740px;
height: 500px; height: 500px;

Просмотреть файл

@ -1727,6 +1727,13 @@ main {
padding: 6px 12px; padding: 6px 12px;
margin-inline-start: 5px; margin-inline-start: 5px;
margin-bottom: 0; } margin-bottom: 0; }
.asrouter-admin .general-textarea {
width: 740px;
height: 500px;
overflow: auto;
resize: none;
border-radius: 4px;
display: flex; }
.asrouter-admin .wnp-textarea { .asrouter-admin .wnp-textarea {
width: 740px; width: 740px;
height: 500px; height: 500px;

Просмотреть файл

@ -1730,6 +1730,13 @@ main {
padding: 6px 12px; padding: 6px 12px;
margin-inline-start: 5px; margin-inline-start: 5px;
margin-bottom: 0; } margin-bottom: 0; }
.asrouter-admin .general-textarea {
width: 740px;
height: 500px;
overflow: auto;
resize: none;
border-radius: 4px;
display: flex; }
.asrouter-admin .wnp-textarea { .asrouter-admin .wnp-textarea {
width: 740px; width: 740px;
height: 500px; height: 500px;

Просмотреть файл

@ -1727,6 +1727,13 @@ main {
padding: 6px 12px; padding: 6px 12px;
margin-inline-start: 5px; margin-inline-start: 5px;
margin-bottom: 0; } margin-bottom: 0; }
.asrouter-admin .general-textarea {
width: 740px;
height: 500px;
overflow: auto;
resize: none;
border-radius: 4px;
display: flex; }
.asrouter-admin .wnp-textarea { .asrouter-admin .wnp-textarea {
width: 740px; width: 740px;
height: 500px; height: 500px;

Просмотреть файл

@ -1189,6 +1189,7 @@ class ASRouterAdminInner extends react__WEBPACK_IMPORTED_MODULE_4___default.a.Pu
messageFilter: "all", messageFilter: "all",
WNMessages: [], WNMessages: [],
collapsedMessages: [], collapsedMessages: [],
modifiedMessages: [],
evaluationStatus: {}, evaluationStatus: {},
trailhead: {}, trailhead: {},
stringTargetingParameters: null, stringTargetingParameters: null,
@ -1266,6 +1267,16 @@ class ASRouterAdminInner extends react__WEBPACK_IMPORTED_MODULE_4___default.a.Pu
return () => _asrouter_asrouter_content__WEBPACK_IMPORTED_MODULE_1__["ASRouterUtils"].unblockById(msg.id); return () => _asrouter_asrouter_content__WEBPACK_IMPORTED_MODULE_1__["ASRouterUtils"].unblockById(msg.id);
} }
resetJSON(msg) {
// reset the displayed JSON for the given message
document.getElementById(`${msg.id}-textarea`).value = JSON.stringify(msg, null, 2); // remove the message from the list of modified IDs
let index = this.state.modifiedMessages.indexOf(msg.id);
this.setState(prevState => ({
modifiedMessages: [...prevState.modifiedMessages.slice(0, index), ...prevState.modifiedMessages.slice(index + 1)]
}));
}
handleOverride(id) { handleOverride(id) {
return () => _asrouter_asrouter_content__WEBPACK_IMPORTED_MODULE_1__["ASRouterUtils"].overrideMessage(id); return () => _asrouter_asrouter_content__WEBPACK_IMPORTED_MODULE_1__["ASRouterUtils"].overrideMessage(id);
} }
@ -1510,6 +1521,18 @@ class ASRouterAdminInner extends react__WEBPACK_IMPORTED_MODULE_4___default.a.Pu
} }
} }
modifyJson(msg) {
_asrouter_asrouter_content__WEBPACK_IMPORTED_MODULE_1__["ASRouterUtils"].modifyMessageJson(JSON.parse(document.getElementById(`${msg.id}-textarea`).value));
}
handleChange(msgId) {
if (!this.state.modifiedMessages.includes(msgId)) {
this.setState(prevState => ({
modifiedMessages: prevState.modifiedMessages.concat(msgId)
}));
}
}
renderMessageItem(msg) { renderMessageItem(msg) {
const isBlockedByGroup = this.state.groups.filter(group => msg.groups.includes(group.id)).some(group => !group.enabled); const isBlockedByGroup = this.state.groups.filter(group => msg.groups.includes(group.id)).some(group => !group.enabled);
const msgProvider = this.state.providers.find(provider => provider.id === msg.provider) || {}; const msgProvider = this.state.providers.find(provider => provider.id === msg.provider) || {};
@ -1518,6 +1541,7 @@ class ASRouterAdminInner extends react__WEBPACK_IMPORTED_MODULE_4___default.a.Pu
const isBlocked = isMessageBlocked || isBlockedByGroup || isProviderExcluded; const isBlocked = isMessageBlocked || isBlockedByGroup || isProviderExcluded;
const impressions = this.state.messageImpressions[msg.id] ? this.state.messageImpressions[msg.id].length : 0; const impressions = this.state.messageImpressions[msg.id] ? this.state.messageImpressions[msg.id].length : 0;
const isCollapsed = this.state.collapsedMessages.includes(msg.id); const isCollapsed = this.state.collapsedMessages.includes(msg.id);
const isModified = this.state.modifiedMessages.includes(msg.id);
let itemClassName = "message-item"; let itemClassName = "message-item";
if (isBlocked) { if (isBlocked) {
@ -1538,14 +1562,30 @@ class ASRouterAdminInner extends react__WEBPACK_IMPORTED_MODULE_4___default.a.Pu
}, react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("button", { }, react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("button", {
className: `button ${isBlocked ? "" : " primary"}`, className: `button ${isBlocked ? "" : " primary"}`,
onClick: isBlocked ? this.handleUnblock(msg) : this.handleBlock(msg) onClick: isBlocked ? this.handleUnblock(msg) : this.handleBlock(msg)
}, isBlocked ? "Unblock" : "Block"), isBlocked ? null : react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("button", { }, isBlocked ? "Unblock" : "Block"), // eslint-disable-next-line no-nested-ternary
className: "button", isBlocked ? null : isModified ? react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("button", {
className: "button restore" // eslint-disable-next-line react/jsx-no-bind
,
onClick: e => this.resetJSON(msg)
}, "Reset") : react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("button", {
className: "button show",
onClick: this.handleOverride(msg.id) onClick: this.handleOverride(msg.id)
}, "Show"), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("br", null), "(", impressions, " impressions)"), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("td", { }, "Show"), isBlocked ? null : react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("button", {
className: "button modify" // eslint-disable-next-line react/jsx-no-bind
,
onClick: e => this.modifyJson(msg)
}, "Modify"), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("br", null), "(", impressions, " impressions)"), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("td", {
className: "message-summary" className: "message-summary"
}, isBlocked && react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("tr", null, "Block reason:", isBlockedByGroup && " Blocked by group", isProviderExcluded && " Excluded by provider", isMessageBlocked && " Message blocked"), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("tr", null, react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("pre", { }, isBlocked && react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("tr", null, "Block reason:", isBlockedByGroup && " Blocked by group", isProviderExcluded && " Excluded by provider", isMessageBlocked && " Message blocked"), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("tr", null, react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("pre", {
className: isCollapsed ? "collapsed" : "expanded" className: isCollapsed ? "collapsed" : "expanded"
}, JSON.stringify(msg, null, 2))))); }, react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("textarea", {
id: `${msg.id}-textarea`,
name: msg.id,
className: "general-textarea",
disabled: isBlocked // eslint-disable-next-line react/jsx-no-bind
,
onChange: e => this.handleChange(msg.id)
}, JSON.stringify(msg, null, 2))))));
} }
restoreWNMessageState() { restoreWNMessageState() {
@ -1622,10 +1662,14 @@ class ASRouterAdminInner extends react__WEBPACK_IMPORTED_MODULE_4___default.a.Pu
const messagesToShow = this.state.messageFilter === "all" ? this.state.messages : this.state.messages.filter(message => message.provider === this.state.messageFilter); const messagesToShow = this.state.messageFilter === "all" ? this.state.messages : this.state.messages.filter(message => message.provider === this.state.messageFilter);
return react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("div", null, react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("button", { return react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("div", null, react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("button", {
className: "ASRouterButton slim button" // eslint-disable-next-line react/jsx-no-bind className: "ASRouterButton slim" // eslint-disable-next-line react/jsx-no-bind
, ,
onClick: e => this.toggleAllMessages(messagesToShow) onClick: e => this.toggleAllMessages(messagesToShow)
}, "Collapse/Expand All"), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("table", null, react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("tbody", null, messagesToShow.map(msg => this.renderMessageItem(msg))))); }, "Collapse/Expand All"), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("p", {
className: "helpLink"
}, react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("span", {
className: "icon icon-small-spacer icon-info"
}), " ", react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("span", null, "To modify a message, change the JSON and click 'Modify' to see your changes. Click 'Reset' to restore the JSON to the original.")), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("table", null, react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("tbody", null, messagesToShow.map(msg => this.renderMessageItem(msg)))));
} }
renderWNMessages() { renderWNMessages() {

Просмотреть файл

@ -266,7 +266,7 @@ describe("ASRouterAdmin", () => {
}); });
assert.lengthOf(wrapper.find(".message-id"), 1); assert.lengthOf(wrapper.find(".message-id"), 1);
wrapper.find(".message-item button:not(.primary)").simulate("click"); wrapper.find(".message-item button.show").simulate("click");
// first call is ADMIN_CONNECT_STATE // first call is ADMIN_CONNECT_STATE
assert.propertyVal( assert.propertyVal(
sendMessageStub.secondCall.args[1], sendMessageStub.secondCall.args[1],