Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import React from 'react';
import { Provider } from 'react-redux';
import { MemoryRouter } from 'react-router';

import configureStore from '../client/store';
import { configureStore } from '../client/store';
import '../client/i18n-test';
import '../client/styles/storybook.css'
import '../client/styles/storybook.css';
import { withThemeProvider, themeToolbarItem } from './decorator-theme';

const initialState = window.__INITIAL_STATE__;
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion client/index.integration.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React from 'react';
import Routing from './routes';

import { reduxRender, act, waitFor, screen, within } from './test-utils';
import configureStore from './store';
import { configureStore } from './store';
import * as Actions from './modules/User/actions';
import { userResponse } from './testData/testServerResponses';

Expand Down
2 changes: 1 addition & 1 deletion client/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Provider } from 'react-redux';
import { Router } from 'react-router-dom';

import browserHistory from './browserHistory';
import configureStore from './store';
import { configureStore } from './store';
import Routing from './routes';
import ThemeProvider from './modules/App/components/ThemeProvider';
import Loader from './modules/App/components/loader';
Expand Down
5 changes: 0 additions & 5 deletions client/middleware.js

This file was deleted.

3 changes: 3 additions & 0 deletions client/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createListenerMiddleware } from '@reduxjs/toolkit';

export const listenerMiddleware = createListenerMiddleware();
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,46 @@ import i18next from 'i18next';
import { apiClient } from '../../../utils/apiClient';
import * as ActionTypes from '../../../constants';

function updatePreferences(formParams, dispatch) {
// Not included in Preferences Form to post to BE
type IdePreferencesTabIndex = number;
type IdeAllAccessibleOutput = boolean;

// Included in Preferences Form to post to BE
type IdeFontSize = number;
type IdeLineNumber = boolean;
type IdeAutoCloseBracketQuotes = boolean;
type IdeAutoCompleteHinter = boolean;
type IdeAutoSave = boolean;
type IdeLineWrap = boolean;
type IdeLintWarning = boolean;
type IdeTextOutput = boolean;
type IdeGridOutput = boolean;
enum IdeTheme {
LIGHT = 'light',
DARK = 'dark',
CONTRAST = 'contrast'
}
type IdeAutoRefresh = boolean;
type IdeLanguage = string;

export interface PreferencesFormParam {
preferences: Partial<{
fontSize: IdeFontSize;
lineNumbers: IdeLineNumber;
autocloseBracketsQuotes: IdeAutoCloseBracketQuotes;
autocompleteHinter: IdeAutoCompleteHinter;
autosave: IdeAutoSave;
linewrap: IdeLineWrap;
lintWarning: IdeLintWarning;
textOutput: IdeTextOutput;
gridOutput: IdeGridOutput;
theme: IdeTheme;
autorefresh: IdeAutoRefresh;
language: IdeLanguage;
}>;
}

function updatePreferences(formParams: PreferencesFormParam, dispatch) {
apiClient
.put('/preferences', formParams)
.then(() => {})
Expand All @@ -14,14 +53,14 @@ function updatePreferences(formParams, dispatch) {
});
}

export function setPreferencesTab(value) {
export function setPreferencesTab(value: IdePreferencesTabIndex) {
return {
type: ActionTypes.SET_PREFERENCES_TAB,
value
};
}

export function setFontSize(value) {
export function setFontSize(value: IdeFontSize) {
return (dispatch, getState) => {
// eslint-disable-line
dispatch({
Expand All @@ -40,7 +79,7 @@ export function setFontSize(value) {
};
}

export function setLineNumbers(value) {
export function setLineNumbers(value: IdeLineNumber) {
return (dispatch, getState) => {
dispatch({
type: ActionTypes.SET_LINE_NUMBERS,
Expand All @@ -58,7 +97,7 @@ export function setLineNumbers(value) {
};
}

export function setAutocloseBracketsQuotes(value) {
export function setAutocloseBracketsQuotes(value: IdeAutoCloseBracketQuotes) {
return (dispatch, getState) => {
dispatch({
type: ActionTypes.SET_AUTOCLOSE_BRACKETS_QUOTES,
Expand All @@ -76,7 +115,7 @@ export function setAutocloseBracketsQuotes(value) {
};
}

export function setAutocompleteHinter(value) {
export function setAutocompleteHinter(value: IdeAutoCompleteHinter) {
return (dispatch, getState) => {
dispatch({
type: ActionTypes.SET_AUTOCOMPLETE_HINTER,
Expand All @@ -94,7 +133,7 @@ export function setAutocompleteHinter(value) {
};
}

export function setAutosave(value) {
export function setAutosave(value: IdeAutoSave) {
return (dispatch, getState) => {
dispatch({
type: ActionTypes.SET_AUTOSAVE,
Expand All @@ -112,7 +151,7 @@ export function setAutosave(value) {
};
}

export function setLinewrap(value) {
export function setLinewrap(value: IdeLineWrap) {
return (dispatch, getState) => {
dispatch({
type: ActionTypes.SET_LINEWRAP,
Expand All @@ -130,7 +169,7 @@ export function setLinewrap(value) {
};
}

export function setLintWarning(value) {
export function setLintWarning(value: IdeLintWarning) {
return (dispatch, getState) => {
dispatch({
type: ActionTypes.SET_LINT_WARNING,
Expand All @@ -148,7 +187,7 @@ export function setLintWarning(value) {
};
}

export function setTextOutput(value) {
export function setTextOutput(value: IdeTextOutput) {
return (dispatch, getState) => {
dispatch({
type: ActionTypes.SET_TEXT_OUTPUT,
Expand All @@ -166,7 +205,7 @@ export function setTextOutput(value) {
};
}

export function setGridOutput(value) {
export function setGridOutput(value: IdeGridOutput) {
return (dispatch, getState) => {
dispatch({
type: ActionTypes.SET_GRID_OUTPUT,
Expand All @@ -184,11 +223,7 @@ export function setGridOutput(value) {
};
}

export function setTheme(value) {
// return {
// type: ActionTypes.SET_THEME,
// value
// };
export function setTheme(value: IdeTheme) {
return (dispatch, getState) => {
dispatch({
type: ActionTypes.SET_THEME,
Expand All @@ -206,11 +241,7 @@ export function setTheme(value) {
};
}

export function setAutorefresh(value) {
// return {
// type: ActionTypes.SET_AUTOREFRESH,
// value
// };
export function setAutorefresh(value: IdeAutoRefresh) {
return (dispatch, getState) => {
dispatch({
type: ActionTypes.SET_AUTOREFRESH,
Expand All @@ -228,14 +259,17 @@ export function setAutorefresh(value) {
};
}

export function setAllAccessibleOutput(value) {
export function setAllAccessibleOutput(value: IdeAllAccessibleOutput) {
return (dispatch) => {
dispatch(setTextOutput(value));
dispatch(setGridOutput(value));
};
}

export function setLanguage(value, { persistPreference = true } = {}) {
export function setLanguage(
value: IdeLanguage,
{ persistPreference = true } = {}
) {
return (dispatch, getState) => {
i18next.changeLanguage(value);
dispatch({
Expand Down
File renamed without changes.
27 changes: 0 additions & 27 deletions client/persistState.js

This file was deleted.

31 changes: 31 additions & 0 deletions client/persistState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Saves and loads a snapshot of the Redux store
* state to session storage
*/
const key = 'p5js-editor';
const storage: Storage = sessionStorage;

// Use a generic type for state so consumers can specify the shape
export const saveState = <T>(state: T): void => {
try {
storage.setItem(key, JSON.stringify(state));
} catch (error) {
console.warn('Unable to persist state to storage:', error);
}
};

// Returns the stored state or null if not found
export const loadState = <T>(): T | null => {
try {
const item = storage.getItem(key);
if (!item) return null;
return JSON.parse(item) as T;
} catch (error) {
console.warn('Failed to retrieve initialize state from storage:', error);
return null;
}
};

export const clearState = (): void => {
storage.removeItem(key);
};
4 changes: 1 addition & 3 deletions client/reducers.js → client/reducers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import sorting from './modules/IDE/reducers/sorting';
import loading from './modules/IDE/reducers/loading';
import collections from './modules/IDE/reducers/collections';

const rootReducer = combineReducers({
export const rootReducer = combineReducers({
ide,
files,
preferences,
Expand All @@ -30,5 +30,3 @@ const rootReducer = combineReducers({
loading,
collections
});

export default rootReducer;
29 changes: 21 additions & 8 deletions client/store.js → client/store.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,38 @@
import { configureStore } from '@reduxjs/toolkit';
import listenerMiddleware from './middleware';
import {
configureStore as _configureStore,
PreloadedState
} from '@reduxjs/toolkit';
import { listenerMiddleware } from './middleware';
import DevTools from './modules/App/components/DevTools';
import rootReducer from './reducers';
import { rootReducer } from './reducers';
import { clearState, loadState } from './persistState';
import { getConfig } from './utils/getConfig';

// necessary to add redux devtool extension to Window interface
declare global {
interface Window {
__REDUX_DEVTOOLS_EXTENSION__?: any;
}
}

// Enable DevTools only when rendering on client and during development.
// Display the dock monitor only if no browser extension is found.
export function showReduxDevTools() {
return (
getConfig('CLIENT') &&
getConfig('NODE_ENV') === 'development' &&
// eslint-disable-next-line no-underscore-dangle
!window.__REDUX_DEVTOOLS_EXTENSION__
);
}

export default function setupStore(initialState) {
const savedState = loadState();
export function configureStore(
initialState: PreloadedState<typeof rootReducer>
) {
const savedState = loadState<typeof rootReducer>();
clearState();

const store = configureStore({
const store = _configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
Expand All @@ -32,9 +45,9 @@ export default function setupStore(initialState) {
enhancers: showReduxDevTools() ? [DevTools.instrument()] : []
});

if (module.hot) {
if ((module as any).hot) {
// Enable Webpack hot module replacement for reducers
module.hot.accept('./reducers', () => {
(module as any).hot.accept('./reducers', () => {
const nextRootReducer = require('./reducers').default; // eslint-disable-line global-require
store.replaceReducer(nextRootReducer);
});
Expand Down
2 changes: 1 addition & 1 deletion client/test-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { Context as ResponsiveContext } from 'react-responsive';

import i18n from './i18n-test';
import ThemeProvider from './modules/App/components/ThemeProvider';
import configureStore from './store';
import { configureStore } from './store';
import theme, { Theme } from './theme';

export const history = createMemoryHistory();
Expand Down
Loading