Dependency-inject `LocalStore` (#522)
Summary: This commit modifies components that directly depend on the browser-specific local store implementation to instead have their dependencies injected. Test Plan: Tests pass, but are likely not sufficient. Manual testing indicates that the local storage still works, for both reads and writes, on a fresh profile or with existing data, for both the repository owner/name and the weight configuration. wchargin-branch: di-localstore
This commit is contained in:
parent
1fa039ba6c
commit
801b4ec700
|
@ -3,7 +3,8 @@
|
|||
import React from "react";
|
||||
import {StyleSheet, css} from "aphrodite/no-important";
|
||||
|
||||
import LocalStore from "./LocalStore";
|
||||
import type {LocalStore} from "../localStore";
|
||||
import BrowserLocalStore from "../browserLocalStore";
|
||||
import {StaticPluginAdapter as GithubAdapter} from "../../plugins/github/pluginAdapter";
|
||||
import {StaticPluginAdapter as GitAdapter} from "../../plugins/git/pluginAdapter";
|
||||
import {Graph} from "../../core/graph";
|
||||
|
@ -16,7 +17,22 @@ import type {PagerankNodeDecomposition} from "../../core/attribution/pagerankNod
|
|||
|
||||
import * as NullUtil from "../../util/null";
|
||||
|
||||
type Props = {||};
|
||||
const REPO_OWNER_KEY = "repoOwner";
|
||||
const REPO_NAME_KEY = "repoName";
|
||||
const MAX_ENTRIES_PER_LIST = 100;
|
||||
|
||||
export default class AppPage extends React.Component<{||}> {
|
||||
static _LOCAL_STORE = new BrowserLocalStore({
|
||||
version: "1",
|
||||
keyPrefix: "cred-explorer",
|
||||
});
|
||||
|
||||
render() {
|
||||
return <App localStore={AppPage._LOCAL_STORE} />;
|
||||
}
|
||||
}
|
||||
|
||||
type Props = {|+localStore: LocalStore|};
|
||||
type State = {
|
||||
repoOwner: string,
|
||||
repoName: string,
|
||||
|
@ -32,11 +48,7 @@ type State = {
|
|||
edgeEvaluator: ?EdgeEvaluator,
|
||||
};
|
||||
|
||||
const REPO_OWNER_KEY = "repoOwner";
|
||||
const REPO_NAME_KEY = "repoName";
|
||||
const MAX_ENTRIES_PER_LIST = 100;
|
||||
|
||||
export default class App extends React.Component<Props, State> {
|
||||
export class App extends React.Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -48,13 +60,15 @@ export default class App extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {localStore} = this.props;
|
||||
this.setState((state) => ({
|
||||
repoOwner: LocalStore.get(REPO_OWNER_KEY, state.repoOwner),
|
||||
repoName: LocalStore.get(REPO_NAME_KEY, state.repoName),
|
||||
repoOwner: localStore.get(REPO_OWNER_KEY, state.repoOwner),
|
||||
repoName: localStore.get(REPO_NAME_KEY, state.repoName),
|
||||
}));
|
||||
}
|
||||
|
||||
render() {
|
||||
const {localStore} = this.props;
|
||||
const {edgeEvaluator} = this.state;
|
||||
const {graphWithMetadata, pnd} = this.state.data;
|
||||
return (
|
||||
|
@ -70,7 +84,7 @@ export default class App extends React.Component<Props, State> {
|
|||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
this.setState({repoOwner: value}, () => {
|
||||
LocalStore.set(REPO_OWNER_KEY, this.state.repoOwner);
|
||||
localStore.set(REPO_OWNER_KEY, this.state.repoOwner);
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
@ -83,7 +97,7 @@ export default class App extends React.Component<Props, State> {
|
|||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
this.setState({repoName: value}, () => {
|
||||
LocalStore.set(REPO_NAME_KEY, this.state.repoName);
|
||||
localStore.set(REPO_NAME_KEY, this.state.repoName);
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
@ -122,7 +136,10 @@ export default class App extends React.Component<Props, State> {
|
|||
) : (
|
||||
<p>Graph not loaded.</p>
|
||||
)}
|
||||
<WeightConfig onChange={(ee) => this.setState({edgeEvaluator: ee})} />
|
||||
<WeightConfig
|
||||
localStore={localStore}
|
||||
onChange={(ee) => this.setState({edgeEvaluator: ee})}
|
||||
/>
|
||||
<PagerankTable
|
||||
adapters={NullUtil.map(graphWithMetadata, (x) => x.adapters)}
|
||||
pnd={pnd}
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
import React from "react";
|
||||
import {shallow} from "enzyme";
|
||||
|
||||
import BrowserLocalStore from "../browserLocalStore";
|
||||
import {pagerank} from "../../core/attribution/pagerank";
|
||||
import App from "./App";
|
||||
import {App} from "./App";
|
||||
|
||||
import {Graph, NodeAddress, EdgeAddress} from "../../core/graph";
|
||||
|
||||
|
@ -95,17 +96,27 @@ function example() {
|
|||
}
|
||||
|
||||
describe("app/credExplorer/App", () => {
|
||||
function makeLocalStore() {
|
||||
// TODO(@wchargin): This should be an in-memory implementation of
|
||||
// LocalStore, not the browser version. This only works because the
|
||||
// store is not actually needed for the shallow render to complete
|
||||
// successfully.
|
||||
return new BrowserLocalStore({
|
||||
version: "1",
|
||||
keyPrefix: "cred-explorer",
|
||||
});
|
||||
}
|
||||
it("renders with clean state", () => {
|
||||
shallow(<App />);
|
||||
shallow(<App localStore={makeLocalStore()} />);
|
||||
});
|
||||
it("renders with graph and adapters set", () => {
|
||||
const app = shallow(<App />);
|
||||
const app = shallow(<App localStore={makeLocalStore()} />);
|
||||
const {graph, adapters} = example();
|
||||
const data = {graph, adapters, pagerankResult: null};
|
||||
app.setState({data});
|
||||
});
|
||||
it("renders with graph and adapters and pagerankResult", () => {
|
||||
const app = shallow(<App />);
|
||||
const app = shallow(<App localStore={makeLocalStore()} />);
|
||||
const {graph, adapters, pagerankResult} = example();
|
||||
const data = {graph, adapters, pagerankResult};
|
||||
app.setState({data});
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import LocalStore from "../browserLocalStore";
|
||||
|
||||
export default new LocalStore({version: "1", keyPrefix: "cred-explorer"});
|
|
@ -9,9 +9,9 @@ import {
|
|||
NodeAddress,
|
||||
} from "../../core/graph";
|
||||
|
||||
import type {LocalStore} from "../localStore";
|
||||
import {type EdgeEvaluator} from "../../core/attribution/pagerank";
|
||||
import {byEdgeType, byNodeType} from "./edgeWeights";
|
||||
import LocalStore from "./LocalStore";
|
||||
import * as MapUtil from "../../util/map";
|
||||
import * as NullUtil from "../../util/null";
|
||||
|
||||
|
@ -19,9 +19,10 @@ import type {StaticPluginAdapter} from "../pluginAdapter";
|
|||
import {StaticPluginAdapter as GithubAdapter} from "../../plugins/github/pluginAdapter";
|
||||
import {StaticPluginAdapter as GitAdapter} from "../../plugins/git/pluginAdapter";
|
||||
|
||||
type Props = {
|
||||
onChange: (EdgeEvaluator) => void,
|
||||
};
|
||||
type Props = {|
|
||||
+localStore: LocalStore,
|
||||
+onChange: (EdgeEvaluator) => void,
|
||||
|};
|
||||
|
||||
type EdgeWeights = Map<EdgeAddressT, UserEdgeWeight>;
|
||||
type UserEdgeWeight = {|+logWeight: number, +directionality: number|};
|
||||
|
@ -71,15 +72,16 @@ export class WeightConfig extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {localStore} = this.props;
|
||||
this.setState(
|
||||
(state) => {
|
||||
return {
|
||||
edgeWeights: NullUtil.orElse(
|
||||
NullUtil.map(LocalStore.get(EDGE_WEIGHTS_KEY), MapUtil.fromObject),
|
||||
NullUtil.map(localStore.get(EDGE_WEIGHTS_KEY), MapUtil.fromObject),
|
||||
state.edgeWeights
|
||||
),
|
||||
nodeWeights: NullUtil.orElse(
|
||||
NullUtil.map(LocalStore.get(NODE_WEIGHTS_KEY), MapUtil.fromObject),
|
||||
NullUtil.map(localStore.get(NODE_WEIGHTS_KEY), MapUtil.fromObject),
|
||||
state.nodeWeights
|
||||
),
|
||||
};
|
||||
|
@ -126,9 +128,10 @@ export class WeightConfig extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
fire() {
|
||||
const {localStore} = this.props;
|
||||
const {edgeWeights, nodeWeights} = this.state;
|
||||
LocalStore.set(EDGE_WEIGHTS_KEY, MapUtil.toObject(edgeWeights));
|
||||
LocalStore.set(NODE_WEIGHTS_KEY, MapUtil.toObject(nodeWeights));
|
||||
localStore.set(EDGE_WEIGHTS_KEY, MapUtil.toObject(edgeWeights));
|
||||
localStore.set(NODE_WEIGHTS_KEY, MapUtil.toObject(nodeWeights));
|
||||
const edgePrefixes = Array.from(edgeWeights.entries()).map(
|
||||
([prefix, {logWeight, directionality}]) => ({
|
||||
prefix,
|
||||
|
|
Loading…
Reference in New Issue