Devtools page pocket (#4628)
* 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:
Родитель
b44b4d6e9c
Коммит
ca13342298
|
@ -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: [],
|
||||
|
|
Загрузка…
Ссылка в новой задаче