Fix up `Session` in preperation for i18n hotfix

pull/426/head
Rick Carlino 2017-08-25 10:11:11 -05:00
parent b7e2639cae
commit 5418447374
13 changed files with 66 additions and 59 deletions

View File

@ -18,7 +18,7 @@ export function deleteUser(payload: DeletionRequest): Thunk {
})
.then((resp: HttpData<{}>) => {
alert("We're sorry to see you go. :(");
Session.clear(true);
Session.clear();
})
.catch((err: UnsafeError) => {
toastErrors({ err });

View File

@ -30,7 +30,7 @@ export function didLogin(authState: AuthState, dispatch: Function) {
function onLogin(dispatch: Function) {
return (response: HttpData<AuthState>) => {
let { data } = response;
Session.put(data);
Session.replace(data);
didLogin(data, dispatch);
push("/app/controls");
};
@ -126,8 +126,8 @@ export function logout() {
// In those cases, seeing a logout message may confuse the user.
// To circumvent this, we must check if the user had a token.
// If there was infact a token, we can safely show the message.
if (Session.get()) { success("You have been logged out."); }
Session.clear(true);
if (Session.getAll()) { success("You have been logged out."); }
Session.clear();
// Technically this is unreachable code:
return {
type: "LOGOUT",

View File

@ -5,7 +5,7 @@ import { Session } from "../session";
/** Lets Redux know that the app is ready to bootstrap. */
export function ready(): Thunk {
return (dispatch, getState) => {
let state = Session.get() || getState().auth;
let state = Session.getAll() || getState().auth;
if (state) { didLogin(state, dispatch); }
};
}

View File

@ -1,16 +1,10 @@
import { BotState, HardwareState, Xyz, ControlPanelState } from "./interfaces";
import { generateReducer } from "../redux/generate_reducer";
import { SyncStatus } from "farmbot/dist";
import { localStorageBoolFetch } from "../util";
import { Actions } from "../constants";
import { EncoderDisplay } from "../controls/interfaces";
import { EXPECTED_MAJOR, EXPECTED_MINOR } from "./actions";
export const X_AXIS_INVERTED = "x_axis_inverted";
export const Y_AXIS_INVERTED = "y_axis_inverted";
export const Z_AXIS_INVERTED = "z_axis_inverted";
export const RAW_ENCODERS = "raw_encoders";
export const SCALED_ENCODERS = "scaled_encoders";
import { Session, BooleanSetting } from "../session";
/**
* TODO: Refactor this method to use semverCompare() now that it is a thing.
@ -73,11 +67,11 @@ export let initialState: BotState = {
dirty: false,
currentOSVersion: undefined,
currentFWVersion: undefined,
x_axis_inverted: !localStorageBoolFetch(X_AXIS_INVERTED),
y_axis_inverted: !localStorageBoolFetch(Y_AXIS_INVERTED),
z_axis_inverted: !localStorageBoolFetch(Z_AXIS_INVERTED),
raw_encoders: !localStorageBoolFetch(RAW_ENCODERS),
scaled_encoders: !localStorageBoolFetch(SCALED_ENCODERS)
x_axis_inverted: !Session.getBool(BooleanSetting.X_AXIS_INVERTED),
y_axis_inverted: !Session.getBool(BooleanSetting.Y_AXIS_INVERTED),
z_axis_inverted: !Session.getBool(BooleanSetting.Z_AXIS_INVERTED),
raw_encoders: !Session.getBool(BooleanSetting.RAW_ENCODERS),
scaled_encoders: !Session.getBool(BooleanSetting.SCALED_ENCODERS),
};
export let botReducer = generateReducer<BotState>(initialState)
@ -120,18 +114,15 @@ export let botReducer = generateReducer<BotState>(initialState)
switch (payload) {
case "x":
s.x_axis_inverted = !s.x_axis_inverted;
localStorage.setItem(X_AXIS_INVERTED,
JSON.stringify(localStorageBoolFetch(X_AXIS_INVERTED)));
Session.setBool(BooleanSetting.X_AXIS_INVERTED, s.x_axis_inverted);
return s;
case "y":
s.y_axis_inverted = !s.y_axis_inverted;
localStorage.setItem(Y_AXIS_INVERTED,
JSON.stringify(localStorageBoolFetch(Y_AXIS_INVERTED)));
Session.setBool(BooleanSetting.Y_AXIS_INVERTED, s.y_axis_inverted);
return s;
case "z":
s.z_axis_inverted = !s.z_axis_inverted;
localStorage.setItem(Z_AXIS_INVERTED,
JSON.stringify(localStorageBoolFetch(Z_AXIS_INVERTED)));
Session.setBool(BooleanSetting.Z_AXIS_INVERTED, s.z_axis_inverted);
return s;
default:
throw new Error("Attempted to invert invalid jog button direction.");
@ -141,13 +132,11 @@ export let botReducer = generateReducer<BotState>(initialState)
switch (payload) {
case "raw_encoders":
s.raw_encoders = !s.raw_encoders;
localStorage.setItem(RAW_ENCODERS,
JSON.stringify(localStorageBoolFetch(RAW_ENCODERS)));
Session.setBool(BooleanSetting.RAW_ENCODERS, s.raw_encoders);
return s;
case "scaled_encoders":
s.scaled_encoders = !s.scaled_encoders;
localStorage.setItem(SCALED_ENCODERS,
JSON.stringify(localStorageBoolFetch(SCALED_ENCODERS)));
Session.setBool(BooleanSetting.SCALED_ENCODERS, s.scaled_encoders);
return s;
default:
throw new Error("Attempted to toggle display of invalid data.");

View File

@ -9,16 +9,12 @@ import {
} from "./interfaces";
import { cloneDeep } from "lodash";
import { TaggedResource } from "../resources/tagged_resources";
import { localStorageNumFetch } from "../util";
import { Actions } from "../constants";
import { Session, NumericSetting } from "../session";
export const BOT_ORIGIN_QUADRANT = "bot_origin_quadrant";
export const ZOOM_LEVEL = "zoom_level";
let botOriginVal = localStorageNumFetch(BOT_ORIGIN_QUADRANT);
let botOriginVal = Session.getNum(NumericSetting.BOT_ORIGIN_QUADRANT);
let botOriginQuadrant = isBotOriginQuadrant(botOriginVal) ? botOriginVal : 2;
let zoomLevelVal = localStorageNumFetch(ZOOM_LEVEL);
let zoomLevelVal = Session.getNum(NumericSetting.ZOOM_LEVEL);
let zoomLevel = zoomLevelVal ? zoomLevelVal : 1;
export let initialState: DesignerState = {
@ -48,14 +44,14 @@ export let designer = generateReducer<DesignerState>(initialState)
return s;
})
.add<BotOriginQuadrant>(Actions.UPDATE_BOT_ORIGIN_QUADRANT, (s, a) => {
localStorage.setItem(BOT_ORIGIN_QUADRANT, JSON.stringify(a.payload));
Session.setNum(NumericSetting.BOT_ORIGIN_QUADRANT, a.payload);
s.botOriginQuadrant = a.payload;
return s;
})
.add<ZoomLevelPayl>(Actions.UPDATE_MAP_ZOOM_LEVEL, (s, { payload }) => {
let value = s.zoomLevel + payload;
s.zoomLevel = value;
localStorage.setItem(ZOOM_LEVEL, value.toString());
Session.setNum(NumericSetting.ZOOM_LEVEL, value);
return s;
})
.add<CropLiveSearchResult[]>(Actions.OF_SEARCH_RESULTS_OK, (s, a) => {

View File

@ -30,7 +30,7 @@ export class FrontPage extends React.Component<{}, Partial<FrontPageState>> {
}
componentDidMount() {
if (Session.get()) { window.location.href = "/app/controls"; }
if (Session.getAll()) { window.location.href = "/app/controls"; }
logInit();
API.setBaseUrl(API.fetchBrowserLocation());
this.setState({
@ -63,7 +63,7 @@ export class FrontPage extends React.Component<{}, Partial<FrontPageState>> {
API.setBaseUrl(url);
axios.post(API.current.tokensPath, payload)
.then((resp: HttpData<AuthState>) => {
Session.put(resp.data);
Session.replace(resp.data);
window.location.href = "/app/controls";
}).catch((error: Error) => {
if (_.get(error, "response.status") === 451) {
@ -346,5 +346,5 @@ export class FrontPage extends React.Component<{}, Partial<FrontPageState>> {
);
}
render() { return Session.get() ? <div /> : this.defaultContent(); }
render() { return Session.getAll() ? <div /> : this.defaultContent(); }
}

View File

@ -24,7 +24,7 @@ export class NavBar extends React.Component<NavBarProps, Partial<NavBarState>> {
tickerListOpen: false
};
logout = () => Session.clear(true);
logout = () => Session.clear();
toggle = (name: keyof NavBarState) => () =>
this.setState({ [name]: !this.state[name] });

View File

@ -23,7 +23,7 @@ export function rootReducer(
state: any,
action: ReduxAction<{}>) {
if (action.type === Actions.LOGOUT) {
Session.clear(true);
Session.clear();
}
// TODO: Get rid of this nasty type case / hack. Resulted from TSC 2.4 upgrade
// - RC 30 JUN 17

View File

@ -70,14 +70,14 @@ export class RootComponent extends React.Component<RootComponentProps, {}> {
requireAuth(_discard: RouterState, replace: RedirectFunction) {
let { store } = this.props;
if (Session.get()) { // has a previous session in cache
if (Session.getAll()) { // has a previous session in cache
if (store.getState().auth) { // Has session, logged in.
return;
} else { // Has session but not logged in (returning visitor).
store.dispatch(ready());
}
} else { // Not logged in yet.
Session.clear(true);
Session.clear();
}
}
@ -281,7 +281,7 @@ export class RootComponent extends React.Component<RootComponentProps, {}> {
render() {
// ==== TEMPORARY HACK. TODO: Add a before hook, if such a thing exists in
// React Router. Or switch routing libs.
let notLoggedIn = !Session.get();
let notLoggedIn = !Session.getAll();
let restrictedArea = window.location.pathname.includes("/app/");
if (notLoggedIn && restrictedArea) {
window.location.href = "/";

View File

@ -1,16 +1,30 @@
import { AuthState } from "./auth/interfaces";
import { box } from "boxed_value";
import { get, isNumber } from "lodash";
export enum BooleanSetting {
X_AXIS_INVERTED = "x_axis_inverted",
Y_AXIS_INVERTED = "y_axis_inverted",
Z_AXIS_INVERTED = "z_axis_inverted",
RAW_ENCODERS = "raw_encoders",
SCALED_ENCODERS = "scaled_encoders"
}
export enum NumericSetting {
BOT_ORIGIN_QUADRANT = "bot_origin_quadrant",
ZOOM_LEVEL = "zoom_level",
}
export namespace Session {
const KEY = "session";
/** Replace the contents of session storage. */
export function put(nextState: AuthState) {
export function replace(nextState: AuthState) {
localStorage[KEY] = JSON.stringify(nextState);
}
/** Fetch the previous session. */
export function get(): AuthState | undefined {
export function getAll(): AuthState | undefined {
try {
let v: AuthState = JSON.parse(localStorage[KEY]);
if (box(v).kind === "object") {
@ -24,9 +38,27 @@ export namespace Session {
}
/** Clear localstorage and sessionstorage. */
export function clear(_redirectToFrontPage = false) {
export function clear() {
localStorage.clear();
sessionStorage.clear();
window.location.href = window.location.origin;
}
export function getBool(key: BooleanSetting): boolean {
let output = JSON.parse(get(localStorage, key, "false"));
return !output;
}
export function setBool(key: BooleanSetting, val: boolean): void {
localStorage.setItem(key, JSON.stringify(val));
}
export function getNum(key: NumericSetting): number | undefined {
let output = JSON.parse(get(localStorage, key, "null"));
return (isNumber(output)) ? output : undefined;
}
export function setNum(key: NumericSetting, val: number): void {
localStorage.setItem(key, JSON.stringify(val));
}
}

View File

@ -52,7 +52,7 @@ export class Wow extends React.Component<Props, Partial<State>> {
axios
.post(API.current.tokensPath, payload)
.then((resp: HttpData<AuthState>) => {
Session.put(resp.data);
Session.replace(resp.data);
window.location.href = "/app/controls";
})
.catch(error => {

View File

@ -146,16 +146,6 @@ export function safeStringFetch(obj: any, key: string): string {
}
}
export function localStorageNumFetch(key: string): number | undefined {
let output = JSON.parse(_.get(localStorage, key, "null"));
return (_.isNumber(output)) ? output : undefined;
}
export function localStorageBoolFetch(key: string): boolean {
let output = JSON.parse(_.get(localStorage, key, "false"));
return !output;
}
/** We don't support IE. This method stops users from trying to use the site.
* It's unfortunate that we need to do this, but the site simply won't work on
* old browsers and our error logs were getting full of IE related bugs. */

View File

@ -13,7 +13,7 @@ export async function verify() {
const url = API.fetchBrowserLocation();
try {
let r: HttpData<AuthState> = await axios.put(url + "/api/users/verify/" + token);
Session.put(r.data);
Session.replace(r.data);
window.location.href = window.location.origin + "/app/controls";
} catch (e) {
document.write(`