Save graph fetcher credentials in local storage
Test Plan: Make a request, then refresh, and note that the fields are populated. Paired with @dandelionmane. wchargin-branch: graph-fetcher-localstore
This commit is contained in:
parent
5d80e39473
commit
55225fd53e
|
@ -3,6 +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 fetchGitHubRepo from "../../github/fetchGitHubRepo";
|
import fetchGitHubRepo from "../../github/fetchGitHubRepo";
|
||||||
import type {
|
import type {
|
||||||
NodePayload as GitHubNodePayload,
|
NodePayload as GitHubNodePayload,
|
||||||
|
@ -19,14 +20,17 @@ type State = {
|
||||||
repoName: string,
|
repoName: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SETTINGS_KEY = "GitHubGraphFetcher.settings";
|
||||||
|
|
||||||
export class GitHubGraphFetcher extends React.Component<Props, State> {
|
export class GitHubGraphFetcher extends React.Component<Props, State> {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.state = {
|
const defaultState = {
|
||||||
apiToken: "",
|
apiToken: "",
|
||||||
repoOwner: "",
|
repoOwner: "",
|
||||||
repoName: "",
|
repoName: "",
|
||||||
};
|
};
|
||||||
|
this.state = LocalStore.get(SETTINGS_KEY, defaultState);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -78,6 +82,7 @@ export class GitHubGraphFetcher extends React.Component<Props, State> {
|
||||||
|
|
||||||
fetchGraph() {
|
fetchGraph() {
|
||||||
const {repoOwner, repoName, apiToken} = this.state;
|
const {repoOwner, repoName, apiToken} = this.state;
|
||||||
|
LocalStore.set(SETTINGS_KEY, {apiToken, repoOwner, repoName});
|
||||||
fetchGitHubRepo(repoOwner, repoName, apiToken)
|
fetchGitHubRepo(repoOwner, repoName, apiToken)
|
||||||
.then((json) => {
|
.then((json) => {
|
||||||
const parser = new GithubParser(`${repoOwner}/${repoName}`);
|
const parser = new GithubParser(`${repoOwner}/${repoName}`);
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A simple abstraction over 'localStorage' to provide transparent JSON
|
||||||
|
* serialization and deserialization.
|
||||||
|
*
|
||||||
|
* The implementation is borrowed heavily from Khan Academy's LocalStore
|
||||||
|
* module, and also KaVideoPlayer's SafeLocalStore module.
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
// Bump this to expire all old values.
|
||||||
|
version: 1,
|
||||||
|
keyPrefix: "artifact-editor",
|
||||||
|
|
||||||
|
cacheKey(key: string): string {
|
||||||
|
if (!key) {
|
||||||
|
throw new Error("Falsy key provided to cacheKey: " + key);
|
||||||
|
}
|
||||||
|
return [this.keyPrefix, this.version, key].join(":");
|
||||||
|
},
|
||||||
|
|
||||||
|
get(key: string, whenUnavailable: any): any {
|
||||||
|
if (!this.isEnabled()) {
|
||||||
|
return whenUnavailable;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const data = window.localStorage[this.cacheKey(key)];
|
||||||
|
if (data) {
|
||||||
|
return JSON.parse(data);
|
||||||
|
} else {
|
||||||
|
return whenUnavailable;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// If we had trouble retrieving, like FF's NS_FILE_CORRUPTED:
|
||||||
|
// http://stackoverflow.com/q/18877643/
|
||||||
|
return whenUnavailable;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
set(key: string, data: any): void {
|
||||||
|
if (!this.isEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const stringified = JSON.stringify(data);
|
||||||
|
|
||||||
|
try {
|
||||||
|
window.localStorage[this.cacheKey(key)] = stringified;
|
||||||
|
} catch (e) {
|
||||||
|
// Probably went over the storage limit... that's not good.
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete whatever data was associated with the given key.
|
||||||
|
*/
|
||||||
|
del(key: string): void {
|
||||||
|
if (!this.isEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const cacheKey = this.cacheKey(key);
|
||||||
|
if (cacheKey in window.localStorage) {
|
||||||
|
// (IE throws when deleting a non-existent entry.)
|
||||||
|
delete window.localStorage[cacheKey];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local storage might be disabled in old browsers or in Safari's
|
||||||
|
* private browsing mode. Don't die.
|
||||||
|
*/
|
||||||
|
isEnabled(): boolean {
|
||||||
|
const uid = String(+new Date());
|
||||||
|
try {
|
||||||
|
window.sessionStorage[uid] = uid;
|
||||||
|
const enabled = window.sessionStorage[uid] === uid;
|
||||||
|
window.sessionStorage.removeItem(uid);
|
||||||
|
return enabled;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
Loading…
Reference in New Issue