Separate artifact settings from GitHub graph fetch (#108)

Summary:
We need to know the repo owner and name for purposes other than fetching
the GitHub graph: for instance, fetching the `artifacts.json` file that
describes the artifact subgraph. It makes sense that these should be
settings global to the application. This commit separates a settings
component and the original GitHub graph fetcher.

This invalidates localStorage; you can manually migrate.

Paired with @dandelionmane.

Test Plan:
Note that the data continues to be stored in localStorage and that it is
updated on each keypress. Note that the state is properly passed around:
if you change the repository name from `example-repo` to `sourcecred`,
e.g., and click “Fetch GitHub graph”, then the proper graph is fetched.

wchargin-branch: separate-artifact-settings
This commit is contained in:
William Chargin 2018-03-26 13:26:44 -07:00 committed by GitHub
parent d310561b94
commit 007cf88172
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 119 additions and 64 deletions

View File

@ -11,15 +11,18 @@ import type {
NodePayload as GithubNodePayload, NodePayload as GithubNodePayload,
EdgePayload as GithubEdgePayload, EdgePayload as GithubEdgePayload,
} from "../../github/githubPlugin"; } from "../../github/githubPlugin";
import type {Settings} from "./SettingsConfig";
import {ArtifactList} from "./ArtifactList"; import {ArtifactList} from "./ArtifactList";
import {ContributionList} from "./ContributionList"; import {ContributionList} from "./ContributionList";
import {GithubGraphFetcher} from "./GithubGraphFetcher"; import {GithubGraphFetcher} from "./GithubGraphFetcher";
import {SettingsConfig, defaultSettings} from "./SettingsConfig";
import standardAdapterSet from "./standardAdapterSet"; import standardAdapterSet from "./standardAdapterSet";
type Props = {}; type Props = {};
type State = { type State = {
artifacts: Node<ArtifactNodePayload>[], artifacts: Node<ArtifactNodePayload>[],
githubGraph: ?Graph<GithubNodePayload, GithubEdgePayload>, githubGraph: ?Graph<GithubNodePayload, GithubEdgePayload>,
settings: Settings,
}; };
function createSampleArtifact(name) { function createSampleArtifact(name) {
@ -41,6 +44,7 @@ export default class App extends React.Component<Props, State> {
this.state = { this.state = {
artifacts: [], artifacts: [],
githubGraph: null, githubGraph: null,
settings: defaultSettings(),
}; };
} }
@ -50,7 +54,13 @@ export default class App extends React.Component<Props, State> {
<header className={css(styles.header)}> <header className={css(styles.header)}>
<h1>Artifact editor</h1> <h1>Artifact editor</h1>
</header> </header>
<SettingsConfig
onChange={(settings) => {
this.setState({settings});
}}
/>
<GithubGraphFetcher <GithubGraphFetcher
settings={this.state.settings}
onCreateGraph={(githubGraph) => { onCreateGraph={(githubGraph) => {
this.setState({githubGraph}); this.setState({githubGraph});
}} }}

View File

@ -3,7 +3,7 @@
import React from "react"; import React from "react";
import type {Graph} from "../../../core/graph"; import type {Graph} from "../../../core/graph";
import LocalStore from "./LocalStore"; import type {Settings} from "./SettingsConfig";
import fetchGithubRepo from "../../github/fetchGithubRepo"; import fetchGithubRepo from "../../github/fetchGithubRepo";
import type { import type {
NodePayload as GithubNodePayload, NodePayload as GithubNodePayload,
@ -12,78 +12,25 @@ import type {
import {GithubParser} from "../../github/githubPlugin"; import {GithubParser} from "../../github/githubPlugin";
type Props = { type Props = {
settings: Settings,
onCreateGraph: (graph: Graph<GithubNodePayload, GithubEdgePayload>) => void, onCreateGraph: (graph: Graph<GithubNodePayload, GithubEdgePayload>) => void,
}; };
type State = {
apiToken: string,
repoOwner: string,
repoName: string,
};
const SETTINGS_KEY = "GithubGraphFetcher.settings";
export class GithubGraphFetcher extends React.Component<Props, State> {
constructor() {
super();
const defaultState = {
apiToken: "",
repoOwner: "",
repoName: "",
};
this.state = LocalStore.get(SETTINGS_KEY, defaultState);
}
export class GithubGraphFetcher extends React.Component<Props> {
render() { render() {
const {settings} = this.props;
const haveSettings =
!!settings.githubApiToken && !!settings.repoOwner && !!settings.repoName;
return ( return (
<div> <button onClick={() => this.fetchGraph()} disabled={!haveSettings}>
<label> Fetch GitHub graph
API token{" "} </button>
<input
value={this.state.apiToken}
onChange={(e) => {
const value = e.target.value;
this.setState((state) => ({
apiToken: value,
}));
}}
/>
</label>
<br />
<label>
Repository owner{" "}
<input
value={this.state.repoOwner}
onChange={(e) => {
const value = e.target.value;
this.setState((state) => ({
repoOwner: value,
}));
}}
/>
</label>
<br />
<label>
Repository name{" "}
<input
value={this.state.repoName}
onChange={(e) => {
const value = e.target.value;
this.setState((state) => ({
repoName: value,
}));
}}
/>
</label>
<br />
<button onClick={() => this.fetchGraph()}>Fetch!</button>
</div>
); );
} }
fetchGraph() { fetchGraph() {
const {repoOwner, repoName, apiToken} = this.state; const {repoOwner, repoName, githubApiToken} = this.props.settings;
LocalStore.set(SETTINGS_KEY, {apiToken, repoOwner, repoName}); fetchGithubRepo(repoOwner, repoName, githubApiToken)
fetchGithubRepo(repoOwner, repoName, apiToken)
.then((json) => { .then((json) => {
const parser = new GithubParser(`${repoOwner}/${repoName}`); const parser = new GithubParser(`${repoOwner}/${repoName}`);
parser.addData(json.data); parser.addData(json.data);

View File

@ -0,0 +1,98 @@
// @flow
import React from "react";
import LocalStore from "./LocalStore";
export type Settings = {
githubApiToken: string,
repoOwner: string,
repoName: string,
};
type Props = {
onChange: (Settings) => void,
};
type State = Settings;
const LOCAL_STORE_SETTINGS_KEY = "SettingsConfig.settings";
export function defaultSettings() {
return {
githubApiToken: "",
repoOwner: "",
repoName: "",
};
}
export class SettingsConfig extends React.Component<Props, State> {
constructor() {
super();
this.state = defaultSettings();
}
componentDidMount() {
this.setState(LocalStore.get(LOCAL_STORE_SETTINGS_KEY, this.state), () => {
this.props.onChange(this.state);
});
}
render() {
return (
<div>
<label>
API token{" "}
<input
value={this.state.githubApiToken}
onChange={(e) => {
const value = e.target.value;
this.setState(
(state) => ({
githubApiToken: value,
}),
this._updateSettings.bind(this)
);
}}
/>
</label>
<br />
<label>
Repository owner{" "}
<input
value={this.state.repoOwner}
onChange={(e) => {
const value = e.target.value;
this.setState(
(state) => ({
repoOwner: value,
}),
this._updateSettings.bind(this)
);
}}
/>
</label>
<br />
<label>
Repository name{" "}
<input
value={this.state.repoName}
onChange={(e) => {
const value = e.target.value;
this.setState(
(state) => ({
repoName: value,
}),
this._updateSettings.bind(this)
);
}}
/>
</label>
</div>
);
}
_updateSettings() {
LocalStore.set(LOCAL_STORE_SETTINGS_KEY, this.state);
this.props.onChange(this.state);
}
}