* ASRouterAdmin devtools routing

* Adding pocket section with topstories to asrouter devtools.

* Small changes

* tests fixed

* few more little changes

* Styles
This commit is contained in:
ScottDowne 2018-12-21 16:14:56 -05:00 коммит произвёл GitHub
Родитель b44b4d6e9c
Коммит ca13342298
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 137 добавлений и 28 удалений

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

@ -1,8 +1,10 @@
import {ASRouterUtils} from "../../asrouter/asrouter-content";
import {connect} from "react-redux";
import {ModalOverlay} from "../../asrouter/components/ModalOverlay/ModalOverlay";
import React from "react";
import {SimpleHashRouter} from "./SimpleHashRouter";
export class ASRouterAdmin extends React.PureComponent {
export class ASRouterAdminInner extends React.PureComponent {
constructor(props) {
super(props);
this.onMessage = this.onMessage.bind(this);
@ -374,6 +376,23 @@ export class ASRouterAdmin extends React.PureComponent {
ASRouterUtils.sendMessage({type: "FORCE_ATTRIBUTION", data: this.state.attributionParameters});
}
renderPocketStory(story) {
return (<tr className="message-item" key={story.guid}>
<td className="message-id"><span>{story.guid} <br /></span></td>
<td className="message-summary">
<pre>{JSON.stringify(story, null, 2)}</pre>
</td>
</tr>);
}
renderPocketStories() {
const {rows} = this.props.Sections.find(Section => Section.id === "topstories") || {};
return (<table><tbody>
{rows && rows.map(story => this.renderPocketStory(story))}
</tbody></table>);
}
renderAttributionParamers() {
return (
<div>
@ -399,9 +418,45 @@ export class ASRouterAdmin extends React.PureComponent {
</div>);
}
getSection() {
const [section] = this.props.location.routes;
switch (section) {
case "targeting":
return (<React.Fragment>
<h2>Targeting Utilities</h2>
<button className="button" onClick={this.expireCache}>Expire Cache</button> (This expires the cache in ASR Targeting for bookmarks and top sites)
{this.renderTargetingParameters()}
{this.renderAttributionParamers()}
</React.Fragment>);
case "pocket":
return (<React.Fragment>
<h2>Pocket</h2>
{this.renderPocketStories()}
</React.Fragment>);
default:
return (<React.Fragment>
<h2>Message Providers <button title="Restore all provider settings that ship with Firefox" className="button" onClick={this.resetPref}>Restorear default prefs</button></h2>
{this.state.providers ? this.renderProviders() : null}
<h2>Messages</h2>
{this.renderMessageFilter()}
{this.renderMessages()}
{this.renderPasteModal()}
</React.Fragment>);
}
}
render() {
return (<div className="asrouter-admin outer-wrapper">
return (<div className="asrouter-admin">
<aside className="sidebar">
<ul>
<li><a href="#devtools">General</a></li>
<li><a href="#devtools-targeting">Targeting</a></li>
<li><a href="#devtools-pocket">Pocket</a></li>
</ul>
</aside>
<main className="main-panel">
<h1>AS Router Admin</h1>
<p className="helpLink">
<span className="icon icon-small-spacer icon-info" />
{" "}
@ -409,17 +464,12 @@ export class ASRouterAdmin extends React.PureComponent {
Need help using these tools? Check out our <a target="blank" href="https://github.com/mozilla/activity-stream/blob/master/content-src/asrouter/docs/debugging-docs.md">documentation</a>
</span>
</p>
<h2>Targeting Utilities</h2>
<button className="button" onClick={this.expireCache}>Expire Cache</button> (This expires the cache in ASR Targeting for bookmarks and top sites)
<h2>Message Providers <button title="Restore all provider settings that ship with Firefox" className="button" onClick={this.resetPref}>Restore default prefs</button></h2>
{this.state.providers ? this.renderProviders() : null}
<h2>Messages</h2>
{this.renderMessageFilter()}
{this.renderMessages()}
{this.renderPasteModal()}
{this.renderTargetingParameters()}
{this.renderAttributionParamers()}
{this.getSection()}
</main>
</div>);
}
}
export const _ASRouterAdmin = props => (<SimpleHashRouter><ASRouterAdminInner {...props} /></SimpleHashRouter>);
export const ASRouterAdmin = connect(state => ({Sections: state.Sections}))(_ASRouterAdmin);

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

@ -2,12 +2,32 @@
.asrouter-admin {
$border-color: var(--newtab-border-secondary-color);
$monospace: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Mono', 'Droid Sans Mono', 'Source Code Pro', monospace;
max-width: 996px;
margin: 0 auto;
font-size: 14px;
// Reset .outer-wrapper styles
display: inherit;
padding: 0 0 92px;
display: flex;
.sidebar {
position: fixed;
width: 240px;
padding: 30px 20px;
ul {
margin: 0;
padding: 0;
list-style: none;
}
li a {
padding: 10px 34px;
display: block;
&:hover {
background: $grey-20;
}
}
}
h1 {
font-weight: 200;

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

@ -0,0 +1,31 @@
import React from "react";
export class SimpleHashRouter extends React.PureComponent {
constructor(props) {
super(props);
this.onHashChange = this.onHashChange.bind(this);
this.state = {hash: global.location.hash};
}
onHashChange() {
this.setState({hash: global.location.hash});
}
componentWillMount() {
global.addEventListener("hashchange", this.onHashChange);
}
componentWillUnmount() {
global.removeEventListener("hashchange", this.onHashChange);
}
render() {
const [, ...routes] = this.state.hash.replace("#asrouter", "").split("-");
return React.cloneElement(this.props.children, {
location: {
hash: this.state.hash,
routes,
},
});
}
}

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

@ -82,10 +82,11 @@ export class _Base extends React.PureComponent {
const prefs = props.Prefs.values;
if (prefs["asrouter.devtoolsEnabled"]) {
if (window.location.hash === "#asrouter") {
if (window.location.hash.startsWith("#asrouter") ||
window.location.hash.startsWith("#devtools")) {
return (<ASRouterAdmin />);
}
console.log("ASRouter devtools enabled. To access visit %cabout:newtab#asrouter", "font-weight: bold"); // eslint-disable-line no-console
console.log("Activity Stream devtools enabled. To access visit %cabout:newtab#devtools", "font-weight: bold"); // eslint-disable-line no-console
}
if (!props.isPrerendered && !initialized) {

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

@ -1,4 +1,4 @@
import {ASRouterAdmin} from "content-src/components/ASRouterAdmin/ASRouterAdmin";
import {ASRouterAdminInner} from "content-src/components/ASRouterAdmin/ASRouterAdmin";
import {GlobalOverrider} from "test/unit/utils";
import React from "react";
import {shallow} from "enzyme";
@ -9,6 +9,7 @@ describe("ASRouterAdmin", () => {
let sendMessageStub;
let addListenerStub;
let removeListenerStub;
let wrapper;
let FAKE_PROVIDER_PREF = [{
enabled: true,
id: "snippets_local_testing",
@ -32,37 +33,43 @@ describe("ASRouterAdmin", () => {
globals.set("RPMSendAsyncMessage", sendMessageStub);
globals.set("RPMAddMessageListener", addListenerStub);
globals.set("RPMRemoveMessageListener", removeListenerStub);
wrapper = shallow(<ASRouterAdminInner location={{routes: [""]}} />);
});
afterEach(() => {
sandbox.restore();
globals.restore();
});
it("should render ASRouterAdmin component", () => {
const wrapper = shallow(<ASRouterAdmin />);
assert.ok(wrapper.exists());
});
it("should send ADMIN_CONNECT_STATE on mount", () => {
shallow(<ASRouterAdmin />);
assert.calledOnce(sendMessageStub);
assert.propertyVal(sendMessageStub.firstCall.args[1], "type", "ADMIN_CONNECT_STATE");
});
it("should set a listener on mount", () => {
const wrapper = shallow(<ASRouterAdmin />);
assert.calledOnce(addListenerStub);
assert.calledWithExactly(addListenerStub, sinon.match.string, wrapper.instance().onMessage);
});
it("should remove listener on unmount", () => {
const wrapper = shallow(<ASRouterAdmin />);
wrapper.unmount();
assert.calledOnce(removeListenerStub);
});
describe("#getSection", () => {
it("should render a message provider section by default", () => {
assert.equal(wrapper.find("h2").at(1).text(), "Messages");
});
it("should render a targeting section for targeting route", () => {
wrapper = shallow(<ASRouterAdminInner location={{routes: ["targeting"]}} />);
assert.equal(wrapper.find("h2").at(0).text(), "Targeting Utilities");
});
it("should render a pocket section for pocket route", () => {
wrapper = shallow(<ASRouterAdminInner location={{routes: ["pocket"]}} Sections={[]} />);
assert.equal(wrapper.find("h2").at(0).text(), "Pocket");
});
});
describe("#render", () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<ASRouterAdmin />);
wrapper.setState({
providerPrefs: [],
providers: [],