From 570c45017c04149843c2e2990904158d8300f96c Mon Sep 17 00:00:00 2001 From: mrdrogdrog Date: Sun, 31 May 2020 22:51:36 +0200 Subject: [PATCH] Restructure redux code (#109) * Restructure redux code Signed-off-by: Tilman Vatteroth Co-authored-by: Erik Michelson --- src/api/backend-config/index.ts | 8 +++ src/api/backend-config/types.ts | 39 ++++++++++++ src/api/config.ts | 15 ----- src/api/frontend-config/index.ts | 8 +++ src/api/frontend-config/types.ts | 3 + src/components/editor/editor.tsx | 2 +- .../editor/task-bar/editor-view-mode.tsx | 19 +++--- .../navigation/header-bar/header-bar.tsx | 3 +- .../user-dropdown/user-dropdown.tsx | 10 +++- .../intro/cover-buttons/cover-buttons.tsx | 5 +- src/components/landing/pages/login/login.tsx | 15 +++-- .../landing/pages/profile/profile.tsx | 8 +-- .../profile/settings/profile-display-name.tsx | 17 ++++-- src/initializers/configLoader.ts | 5 +- src/redux/backend-config/methods.ts | 11 ++-- src/redux/backend-config/reducers.ts | 11 ++-- src/redux/backend-config/types.ts | 52 +++------------- src/redux/editor/methods.ts | 11 ++-- src/redux/editor/reducers.ts | 16 ++--- src/redux/editor/types.ts | 22 ++++--- src/redux/frontend-config/methods.ts | 15 +++-- src/redux/frontend-config/reducers.ts | 11 ++-- src/redux/frontend-config/types.ts | 18 +++--- src/redux/index.ts | 20 +++---- src/redux/user/methods.ts | 11 ++-- src/redux/user/reducers.ts | 28 ++------- src/redux/user/types.ts | 60 +++++++++---------- src/utils/apiUtils.ts | 2 - 28 files changed, 214 insertions(+), 231 deletions(-) create mode 100644 src/api/backend-config/index.ts create mode 100644 src/api/backend-config/types.ts delete mode 100644 src/api/config.ts create mode 100644 src/api/frontend-config/index.ts create mode 100644 src/api/frontend-config/types.ts diff --git a/src/api/backend-config/index.ts b/src/api/backend-config/index.ts new file mode 100644 index 000000000..c368aab66 --- /dev/null +++ b/src/api/backend-config/index.ts @@ -0,0 +1,8 @@ +import { expectResponseCode, getBackendUrl } from '../../utils/apiUtils' +import { BackendConfig } from './types' + +export const getBackendConfig = async (): Promise => { + const response = await fetch(getBackendUrl() + '/config') + expectResponseCode(response) + return await response.json() as Promise +} diff --git a/src/api/backend-config/types.ts b/src/api/backend-config/types.ts new file mode 100644 index 000000000..989b3558a --- /dev/null +++ b/src/api/backend-config/types.ts @@ -0,0 +1,39 @@ +export interface BackendConfig { + allowAnonymous: boolean, + authProviders: AuthProvidersState, + customAuthNames: CustomAuthNames, + specialLinks: SpecialLinks, + version: BackendVersion, +} + +export interface BackendVersion { + version: string, + sourceCodeUrl: string + issueTrackerUrl: string +} + +export interface AuthProvidersState { + facebook: boolean, + github: boolean, + twitter: boolean, + gitlab: boolean, + dropbox: boolean, + ldap: boolean, + google: boolean, + saml: boolean, + oauth2: boolean, + email: boolean, + openid: boolean, +} + +export interface CustomAuthNames { + ldap: string; + oauth2: string; + saml: string; +} + +export interface SpecialLinks { + privacy: string, + termsOfUse: string, + imprint: string, +} diff --git a/src/api/config.ts b/src/api/config.ts deleted file mode 100644 index 04ac2a4b4..000000000 --- a/src/api/config.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { FrontendConfigState } from '../redux/frontend-config/types' -import { BackendConfigState } from '../redux/backend-config/types' -import { expectResponseCode, getBackendUrl } from '../utils/apiUtils' - -export const getBackendConfig = async (): Promise => { - const response = await fetch(getBackendUrl() + '/config') - expectResponseCode(response) - return await response.json() as Promise -} - -export const getFrontendConfig = async (baseUrl: string): Promise => { - const response = await fetch(`${baseUrl}config.json`) - expectResponseCode(response) - return await response.json() as Promise -} diff --git a/src/api/frontend-config/index.ts b/src/api/frontend-config/index.ts new file mode 100644 index 000000000..d7c6df8af --- /dev/null +++ b/src/api/frontend-config/index.ts @@ -0,0 +1,8 @@ +import { expectResponseCode } from '../../utils/apiUtils' +import { FrontendConfig } from './types' + +export const getFrontendConfig = async (baseUrl: string): Promise => { + const response = await fetch(`${baseUrl}config.json`) + expectResponseCode(response) + return await response.json() as Promise +} diff --git a/src/api/frontend-config/types.ts b/src/api/frontend-config/types.ts new file mode 100644 index 000000000..12fb48058 --- /dev/null +++ b/src/api/frontend-config/types.ts @@ -0,0 +1,3 @@ +export interface FrontendConfig { + backendUrl: string +} diff --git a/src/components/editor/editor.tsx b/src/components/editor/editor.tsx index b73e6f74c..e8cfae3f4 100644 --- a/src/components/editor/editor.tsx +++ b/src/components/editor/editor.tsx @@ -2,9 +2,9 @@ import React from 'react' import { useSelector } from 'react-redux' import { useParams } from 'react-router' import { ApplicationState } from '../../redux' -import { EditorMode } from '../../redux/editor/types' import { EditorWindow } from './editor-window/editor-window' import { MarkdownPreview } from './markdown-preview/markdown-preview' +import { EditorMode } from './task-bar/editor-view-mode' import { TaskBar } from './task-bar/task-bar' interface RouteParameters { diff --git a/src/components/editor/task-bar/editor-view-mode.tsx b/src/components/editor/task-bar/editor-view-mode.tsx index e1f587273..90b4d1bef 100644 --- a/src/components/editor/task-bar/editor-view-mode.tsx +++ b/src/components/editor/task-bar/editor-view-mode.tsx @@ -1,13 +1,18 @@ -import { ToggleButton, ToggleButtonGroup } from 'react-bootstrap' import React from 'react' +import { ToggleButton, ToggleButtonGroup } from 'react-bootstrap' +import { useTranslation } from 'react-i18next' import { useSelector } from 'react-redux' import { ForkAwesomeIcon } from '../../../fork-awesome/fork-awesome-icon' import { ApplicationState } from '../../../redux' -import { EditorMode } from '../../../redux/editor/types' import { setEditorModeConfig } from '../../../redux/editor/methods' -import { useTranslation } from 'react-i18next' -const EditorViewMode: React.FC = () => { +export enum EditorMode { + PREVIEW, + BOTH, + EDITOR, +} + +export const EditorViewMode: React.FC = () => { const { t } = useTranslation() const editorConfig = useSelector((state: ApplicationState) => state.editorConfig) return ( @@ -15,7 +20,9 @@ const EditorViewMode: React.FC = () => { type="radio" name="options" defaultValue={editorConfig.editorMode} - onChange={(value: EditorMode) => { setEditorModeConfig(value) }}> + onChange={(value: EditorMode) => { + setEditorModeConfig(value) + }}> @@ -28,5 +35,3 @@ const EditorViewMode: React.FC = () => { ) } - -export { EditorViewMode } diff --git a/src/components/landing/layout/navigation/header-bar/header-bar.tsx b/src/components/landing/layout/navigation/header-bar/header-bar.tsx index 2db8fe215..ba262c82b 100644 --- a/src/components/landing/layout/navigation/header-bar/header-bar.tsx +++ b/src/components/landing/layout/navigation/header-bar/header-bar.tsx @@ -3,7 +3,6 @@ import { Navbar } from 'react-bootstrap' import { Trans, useTranslation } from 'react-i18next' import { useSelector } from 'react-redux' import { ApplicationState } from '../../../../../redux' -import { LoginStatus } from '../../../../../redux/user/types' import { HeaderNavLink } from '../header-nav-link' import { NewGuestNoteButton } from '../new-guest-note-button' import { NewUserNoteButton } from '../new-user-note-button' @@ -26,7 +25,7 @@ const HeaderBar: React.FC = () => {
- {user.status === LoginStatus.forbidden + {!user ? diff --git a/src/components/landing/layout/navigation/user-dropdown/user-dropdown.tsx b/src/components/landing/layout/navigation/user-dropdown/user-dropdown.tsx index 3e1029047..7c80665ee 100644 --- a/src/components/landing/layout/navigation/user-dropdown/user-dropdown.tsx +++ b/src/components/landing/layout/navigation/user-dropdown/user-dropdown.tsx @@ -1,17 +1,21 @@ -import { Dropdown } from 'react-bootstrap' import React from 'react' +import { Dropdown } from 'react-bootstrap' +import { Trans, useTranslation } from 'react-i18next' import { useSelector } from 'react-redux' +import { LinkContainer } from 'react-router-bootstrap' import { ForkAwesomeIcon } from '../../../../../fork-awesome/fork-awesome-icon' import { ApplicationState } from '../../../../../redux' -import { LinkContainer } from 'react-router-bootstrap' import { clearUser } from '../../../../../redux/user/methods' -import { Trans, useTranslation } from 'react-i18next' import { UserAvatar } from '../../user-avatar/user-avatar' export const UserDropdown: React.FC = () => { useTranslation() const user = useSelector((state: ApplicationState) => state.user) + if (!user) { + return null + } + return ( diff --git a/src/components/landing/pages/intro/cover-buttons/cover-buttons.tsx b/src/components/landing/pages/intro/cover-buttons/cover-buttons.tsx index 4ec9f8535..7d64e580a 100644 --- a/src/components/landing/pages/intro/cover-buttons/cover-buttons.tsx +++ b/src/components/landing/pages/intro/cover-buttons/cover-buttons.tsx @@ -1,9 +1,8 @@ import React from 'react' -import { Link } from 'react-router-dom' import { Button } from 'react-bootstrap' -import { LoginStatus } from '../../../../../redux/user/types' import { Trans, useTranslation } from 'react-i18next' import { useSelector } from 'react-redux' +import { Link } from 'react-router-dom' import { ApplicationState } from '../../../../../redux' import './cover-buttons.scss' @@ -11,7 +10,7 @@ export const CoverButtons: React.FC = () => { useTranslation() const user = useSelector((state: ApplicationState) => state.user) - if (user.status === LoginStatus.ok) { + if (user) { return null } diff --git a/src/components/landing/pages/login/login.tsx b/src/components/landing/pages/login/login.tsx index 4ed9c7fe5..846b95fad 100644 --- a/src/components/landing/pages/login/login.tsx +++ b/src/components/landing/pages/login/login.tsx @@ -1,20 +1,19 @@ import React from 'react' import { Card, Col, Row } from 'react-bootstrap' import { Trans, useTranslation } from 'react-i18next' -import { ViaEMail } from './auth/via-email' -import { OneClickType, ViaOneClick } from './auth/via-one-click' -import { ViaLdap } from './auth/via-ldap' import { useSelector } from 'react-redux' -import { ApplicationState } from '../../../../redux' -import { ViaOpenId } from './auth/via-openid' import { Redirect } from 'react-router' -import { LoginStatus } from '../../../../redux/user/types' +import { ApplicationState } from '../../../../redux' +import { ViaEMail } from './auth/via-email' +import { ViaLdap } from './auth/via-ldap' +import { OneClickType, ViaOneClick } from './auth/via-one-click' +import { ViaOpenId } from './auth/via-openid' export const Login: React.FC = () => { useTranslation() const authProviders = useSelector((state: ApplicationState) => state.backendConfig.authProviders) const customAuthNames = useSelector((state: ApplicationState) => state.backendConfig.customAuthNames) - const userLoginState = useSelector((state: ApplicationState) => state.user.status) + const userLoginState = useSelector((state: ApplicationState) => state.user) const emailForm = authProviders.email ? : null const ldapForm = authProviders.ldap ? : null const openIdForm = authProviders.openid ? : null @@ -30,7 +29,7 @@ export const Login: React.FC = () => { } } - if (userLoginState === LoginStatus.ok) { + if (userLoginState) { // TODO Redirect to previous page? return ( diff --git a/src/components/landing/pages/profile/profile.tsx b/src/components/landing/pages/profile/profile.tsx index 3425cb11a..b24bb6055 100644 --- a/src/components/landing/pages/profile/profile.tsx +++ b/src/components/landing/pages/profile/profile.tsx @@ -3,7 +3,7 @@ import { Col, Row } from 'react-bootstrap' import { useSelector } from 'react-redux' import { Redirect } from 'react-router' import { ApplicationState } from '../../../../redux' -import { LoginProvider, LoginStatus } from '../../../../redux/user/types' +import { LoginProvider } from '../../../../redux/user/types' import { ProfileAccountManagement } from './settings/profile-account-management' import { ProfileChangePassword } from './settings/profile-change-password' import { ProfileDisplayName } from './settings/profile-display-name' @@ -11,9 +11,9 @@ import { ProfileDisplayName } from './settings/profile-display-name' export const Profile: React.FC = () => { const user = useSelector((state: ApplicationState) => state.user) - if (user.status === LoginStatus.forbidden) { + if (!user) { return ( - + ) } @@ -22,7 +22,7 @@ export const Profile: React.FC = () => { - { user.provider === LoginProvider.EMAIL ? : null } + {user.provider === LoginProvider.EMAIL ? : null} diff --git a/src/components/landing/pages/profile/settings/profile-display-name.tsx b/src/components/landing/pages/profile/settings/profile-display-name.tsx index a2c875f79..1e85c03e3 100644 --- a/src/components/landing/pages/profile/settings/profile-display-name.tsx +++ b/src/components/landing/pages/profile/settings/profile-display-name.tsx @@ -1,5 +1,5 @@ -import React, { ChangeEvent, FormEvent, useState } from 'react' -import { Button, Card, Form } from 'react-bootstrap' +import React, { ChangeEvent, FormEvent, useEffect, useState } from 'react' +import { Alert, Button, Card, Form } from 'react-bootstrap' import { Trans, useTranslation } from 'react-i18next' import { useSelector } from 'react-redux' import { updateDisplayName } from '../../../../../api/me' @@ -7,13 +7,22 @@ import { ApplicationState } from '../../../../../redux' import { getAndSetUser } from '../../../../../utils/apiUtils' export const ProfileDisplayName: React.FC = () => { + const regexInvalidDisplayName = /^\s*$/ const { t } = useTranslation() const user = useSelector((state: ApplicationState) => state.user) const [submittable, setSubmittable] = useState(false) const [error, setError] = useState(false) - const [displayName, setDisplayName] = useState(user.name) + const [displayName, setDisplayName] = useState('') - const regexInvalidDisplayName = /^\s*$/ + useEffect(() => { + if (user) { + setDisplayName(user.name) + } + }, [user]) + + if (!user) { + return User not logged in + } const changeNameField = (event: ChangeEvent) => { setSubmittable(!regexInvalidDisplayName.test(event.target.value)) diff --git a/src/initializers/configLoader.ts b/src/initializers/configLoader.ts index 5c526f857..25a67c94f 100644 --- a/src/initializers/configLoader.ts +++ b/src/initializers/configLoader.ts @@ -1,6 +1,7 @@ -import { getBackendConfig, getFrontendConfig } from '../api/config' -import { setFrontendConfig } from '../redux/frontend-config/methods' +import { getBackendConfig } from '../api/backend-config' +import { getFrontendConfig } from '../api/frontend-config' import { setBackendConfig } from '../redux/backend-config/methods' +import { setFrontendConfig } from '../redux/frontend-config/methods' import { getAndSetUser } from '../utils/apiUtils' export const loadAllConfig: (baseUrl: string) => Promise = async (baseUrl) => { diff --git a/src/redux/backend-config/methods.ts b/src/redux/backend-config/methods.ts index 464eca527..b6e00697c 100644 --- a/src/redux/backend-config/methods.ts +++ b/src/redux/backend-config/methods.ts @@ -1,12 +1,11 @@ -import { BackendConfigState, SET_BACKEND_CONFIG_ACTION_TYPE, SetBackendConfigAction } from './types' +import { BackendConfig } from '../../api/backend-config/types' import { store } from '../../utils/store' +import { BackendConfigActionType, SetBackendConfigAction } from './types' -export const setBackendConfig = (state: BackendConfigState): void => { +export const setBackendConfig = (state: BackendConfig): void => { const action: SetBackendConfigAction = { - type: SET_BACKEND_CONFIG_ACTION_TYPE, - payload: { - state - } + type: BackendConfigActionType.SET_BACKEND_CONFIG, + state: state } store.dispatch(action) } diff --git a/src/redux/backend-config/reducers.ts b/src/redux/backend-config/reducers.ts index c54a83524..98e50a1e7 100644 --- a/src/redux/backend-config/reducers.ts +++ b/src/redux/backend-config/reducers.ts @@ -1,7 +1,8 @@ import { Reducer } from 'redux' -import { BackendConfigActions, BackendConfigState, SET_BACKEND_CONFIG_ACTION_TYPE } from './types' +import { BackendConfig } from '../../api/backend-config/types' +import { BackendConfigActions, BackendConfigActionType, SetBackendConfigAction } from './types' -export const initialState: BackendConfigState = { +export const initialState: BackendConfig = { allowAnonymous: true, authProviders: { facebook: false, @@ -33,10 +34,10 @@ export const initialState: BackendConfigState = { } } -export const BackendConfigReducer: Reducer = (state: BackendConfigState = initialState, action: BackendConfigActions) => { +export const BackendConfigReducer: Reducer<(BackendConfig), BackendConfigActions> = (state: (BackendConfig) = initialState, action: BackendConfigActions) => { switch (action.type) { - case SET_BACKEND_CONFIG_ACTION_TYPE: - return action.payload.state + case BackendConfigActionType.SET_BACKEND_CONFIG: + return (action as SetBackendConfigAction).state default: return state } diff --git a/src/redux/backend-config/types.ts b/src/redux/backend-config/types.ts index 10842f91e..689ea51d5 100644 --- a/src/redux/backend-config/types.ts +++ b/src/redux/backend-config/types.ts @@ -1,52 +1,14 @@ import { Action } from 'redux' +import { BackendConfig } from '../../api/backend-config/types' -export const SET_BACKEND_CONFIG_ACTION_TYPE = 'backend-config/set' - -export interface BackendConfigState { - allowAnonymous: boolean, - authProviders: AuthProvidersState, - customAuthNames: CustomAuthNames, - specialLinks: SpecialLinks, - version: BackendVersion, +export enum BackendConfigActionType { + SET_BACKEND_CONFIG = 'backend-config/set' } -export interface BackendVersion { - version: string, - sourceCodeUrl: string - issueTrackerUrl: string +export interface BackendConfigActions extends Action{ + type: BackendConfigActionType; } -export interface AuthProvidersState { - facebook: boolean, - github: boolean, - twitter: boolean, - gitlab: boolean, - dropbox: boolean, - ldap: boolean, - google: boolean, - saml: boolean, - oauth2: boolean, - email: boolean, - openid: boolean, +export interface SetBackendConfigAction extends BackendConfigActions { + state: BackendConfig; } - -export interface CustomAuthNames { - ldap: string; - oauth2: string; - saml: string; -} - -export interface SpecialLinks { - privacy: string, - termsOfUse: string, - imprint: string, -} - -export interface SetBackendConfigAction extends Action { - type: string; - payload: { - state: BackendConfigState; - }; -} - -export type BackendConfigActions = SetBackendConfigAction; diff --git a/src/redux/editor/methods.ts b/src/redux/editor/methods.ts index ebdd62b3a..21fdc67d1 100644 --- a/src/redux/editor/methods.ts +++ b/src/redux/editor/methods.ts @@ -1,14 +1,11 @@ -import { - EditorMode, - SET_EDITOR_CONFIG_MODE_ACTION_TYPE, - SetEditorConfigAction -} from './types' +import { EditorMode } from '../../components/editor/task-bar/editor-view-mode' import { store } from '../../utils/store' +import { EditorConfigActionType, SetEditorConfigAction } from './types' export const setEditorModeConfig = (editorMode: EditorMode): void => { const action: SetEditorConfigAction = { - type: SET_EDITOR_CONFIG_MODE_ACTION_TYPE, - payload: editorMode + type: EditorConfigActionType.SET_EDITOR_VIEW_MODE, + mode: editorMode } store.dispatch(action) } diff --git a/src/redux/editor/reducers.ts b/src/redux/editor/reducers.ts index 9a0d733a1..bf4dc62a6 100644 --- a/src/redux/editor/reducers.ts +++ b/src/redux/editor/reducers.ts @@ -1,21 +1,17 @@ import { Reducer } from 'redux' -import { - EditorConfigActions, - EditorConfigState, - EditorMode, - SET_EDITOR_CONFIG_MODE_ACTION_TYPE -} from './types' +import { EditorMode } from '../../components/editor/task-bar/editor-view-mode' +import { EditorConfig, EditorConfigActions, EditorConfigActionType, SetEditorConfigAction } from './types' -export const initialState: EditorConfigState = { +export const initialState: EditorConfig = { editorMode: EditorMode.PREVIEW } -export const EditorConfigReducer: Reducer = (state: EditorConfigState = initialState, action: EditorConfigActions) => { +export const EditorConfigReducer: Reducer = (state: EditorConfig = initialState, action: EditorConfigActions) => { switch (action.type) { - case SET_EDITOR_CONFIG_MODE_ACTION_TYPE: + case EditorConfigActionType.SET_EDITOR_VIEW_MODE: return { ...state, - editorMode: action.payload + editorMode: (action as SetEditorConfigAction).mode } default: return state diff --git a/src/redux/editor/types.ts b/src/redux/editor/types.ts index 7e8fbe95e..cc8120127 100644 --- a/src/redux/editor/types.ts +++ b/src/redux/editor/types.ts @@ -1,20 +1,18 @@ import { Action } from 'redux' +import { EditorMode } from '../../components/editor/task-bar/editor-view-mode' -export const SET_EDITOR_CONFIG_MODE_ACTION_TYPE = 'editor/mode/set' - -export interface EditorConfigState { - editorMode: EditorMode; +export enum EditorConfigActionType { + SET_EDITOR_VIEW_MODE = 'editor/mode/set' } -export enum EditorMode { - PREVIEW, - BOTH, - EDITOR, +export interface EditorConfig { + editorMode: EditorMode; } -export interface SetEditorConfigAction extends Action { - type: string; - payload: EditorMode; +export interface EditorConfigActions extends Action { + type: EditorConfigActionType; } -export type EditorConfigActions = SetEditorConfigAction; +export interface SetEditorConfigAction extends EditorConfigActions { + mode: EditorMode; +} diff --git a/src/redux/frontend-config/methods.ts b/src/redux/frontend-config/methods.ts index c869406d6..7986cac5c 100644 --- a/src/redux/frontend-config/methods.ts +++ b/src/redux/frontend-config/methods.ts @@ -1,14 +1,13 @@ -import { FrontendConfigState, SET_FRONTEND_CONFIG_ACTION_TYPE, SetFrontendConfigAction } from './types' +import { FrontendConfig } from '../../api/frontend-config/types' import { store } from '../../utils/store' +import { FrontendConfigActionType, SetFrontendConfigAction } from './types' -export const setFrontendConfig = (state: FrontendConfigState): void => { +export const setFrontendConfig = (state: FrontendConfig): void => { const action: SetFrontendConfigAction = { - type: SET_FRONTEND_CONFIG_ACTION_TYPE, - payload: { - state: { - ...state, - backendUrl: state.backendUrl + '/api/v2.0/' - } + type: FrontendConfigActionType.SET_FRONTEND_CONFIG, + state: { + ...state, + backendUrl: state.backendUrl + '/api/v2.0/' } } store.dispatch(action) diff --git a/src/redux/frontend-config/reducers.ts b/src/redux/frontend-config/reducers.ts index 34975a428..81e12c930 100644 --- a/src/redux/frontend-config/reducers.ts +++ b/src/redux/frontend-config/reducers.ts @@ -1,14 +1,15 @@ import { Reducer } from 'redux' -import { FrontendConfigActions, FrontendConfigState, SET_FRONTEND_CONFIG_ACTION_TYPE } from './types' +import { FrontendConfig } from '../../api/frontend-config/types' +import { FrontendConfigActions, FrontendConfigActionType, SetFrontendConfigAction } from './types' -export const initialState: FrontendConfigState = { +const initialState: FrontendConfig = { backendUrl: '' } -export const FrontendConfigReducer: Reducer = (state: FrontendConfigState = initialState, action: FrontendConfigActions) => { +export const FrontendConfigReducer: Reducer<(FrontendConfig), FrontendConfigActions> = (state: (FrontendConfig) = initialState, action: FrontendConfigActions) => { switch (action.type) { - case SET_FRONTEND_CONFIG_ACTION_TYPE: - return action.payload.state + case FrontendConfigActionType.SET_FRONTEND_CONFIG: + return (action as SetFrontendConfigAction).state default: return state } diff --git a/src/redux/frontend-config/types.ts b/src/redux/frontend-config/types.ts index 69b2321e5..6343ac860 100644 --- a/src/redux/frontend-config/types.ts +++ b/src/redux/frontend-config/types.ts @@ -1,16 +1,14 @@ import { Action } from 'redux' +import { FrontendConfig } from '../../api/frontend-config/types' -export const SET_FRONTEND_CONFIG_ACTION_TYPE = 'frontend-config/set' - -export interface SetFrontendConfigAction extends Action { - type: string; - payload: { - state: FrontendConfigState; - }; +export enum FrontendConfigActionType { + SET_FRONTEND_CONFIG = 'frontend-config/set' } -export interface FrontendConfigState { - backendUrl: string, +export interface FrontendConfigActions extends Action { + type: FrontendConfigActionType; } -export type FrontendConfigActions = SetFrontendConfigAction; +export interface SetFrontendConfigAction extends FrontendConfigActions { + state: FrontendConfig; +} diff --git a/src/redux/index.ts b/src/redux/index.ts index c8ac92c55..58543d0b5 100644 --- a/src/redux/index.ts +++ b/src/redux/index.ts @@ -1,18 +1,18 @@ import { combineReducers, Reducer } from 'redux' -import { UserState } from './user/types' -import { UserReducer } from './user/reducers' -import { BackendConfigState } from './backend-config/types' -import { FrontendConfigState } from './frontend-config/types' +import { BackendConfig } from '../api/backend-config/types' +import { FrontendConfig } from '../api/frontend-config/types' import { BackendConfigReducer } from './backend-config/reducers' -import { FrontendConfigReducer } from './frontend-config/reducers' -import { EditorConfigState } from './editor/types' import { EditorConfigReducer } from './editor/reducers' +import { EditorConfig } from './editor/types' +import { FrontendConfigReducer } from './frontend-config/reducers' +import { UserReducer } from './user/reducers' +import { MaybeUserState } from './user/types' export interface ApplicationState { - user: UserState; - backendConfig: BackendConfigState; - frontendConfig: FrontendConfigState; - editorConfig: EditorConfigState; + user: MaybeUserState; + backendConfig: BackendConfig; + frontendConfig: FrontendConfig; + editorConfig: EditorConfig; } export const allReducers: Reducer = combineReducers({ diff --git a/src/redux/user/methods.ts b/src/redux/user/methods.ts index ea7e18ee7..ba2585171 100644 --- a/src/redux/user/methods.ts +++ b/src/redux/user/methods.ts @@ -1,20 +1,17 @@ -import { CLEAR_USER_ACTION_TYPE, ClearUserAction, SET_USER_ACTION_TYPE, SetUserAction, UserState } from './types' import { store } from '../../utils/store' +import { ClearUserAction, SetUserAction, UserActionType, UserState } from './types' export const setUser: (state: UserState) => void = (state: UserState) => { const action: SetUserAction = { - type: SET_USER_ACTION_TYPE, - payload: { - state - } + type: UserActionType.SET_USER, + state } store.dispatch(action) } export const clearUser: () => void = () => { const action: ClearUserAction = { - type: CLEAR_USER_ACTION_TYPE, - payload: null + type: UserActionType.CLEAR_USER } store.dispatch(action) } diff --git a/src/redux/user/reducers.ts b/src/redux/user/reducers.ts index 62531e5fb..213a0b7c9 100644 --- a/src/redux/user/reducers.ts +++ b/src/redux/user/reducers.ts @@ -1,28 +1,12 @@ import { Reducer } from 'redux' -import { - CLEAR_USER_ACTION_TYPE, - LoginProvider, - LoginStatus, - SET_USER_ACTION_TYPE, - SetUserAction, - UserActions, - UserState -} from './types' +import { MaybeUserState, SetUserAction, UserActions, UserActionType } from './types' -export const initialState: UserState = { - id: '', - name: '', - photo: '', - status: LoginStatus.forbidden, - provider: LoginProvider.EMAIL -} - -export const UserReducer: Reducer = (state: UserState = initialState, action: UserActions) => { +export const UserReducer: Reducer = (state: MaybeUserState = null, action: UserActions) => { switch (action.type) { - case SET_USER_ACTION_TYPE: - return (action as SetUserAction).payload.state - case CLEAR_USER_ACTION_TYPE: - return initialState + case UserActionType.SET_USER: + return (action as SetUserAction).state + case UserActionType.CLEAR_USER: + return null default: return state } diff --git a/src/redux/user/types.ts b/src/redux/user/types.ts index caadd549d..db338b52f 100644 --- a/src/redux/user/types.ts +++ b/src/redux/user/types.ts @@ -1,45 +1,39 @@ import { Action } from 'redux' -export const SET_USER_ACTION_TYPE = 'user/set' -export const CLEAR_USER_ACTION_TYPE = 'user/clear' - -export interface SetUserAction extends Action { - type: string; - payload: { - state: UserState, - }; +export enum UserActionType { + SET_USER = 'user/set', + CLEAR_USER = 'user/clear' } -export interface ClearUserAction extends Action { - type: string; - payload: null; +export interface UserActions extends Action { + type: UserActionType; } +export interface SetUserAction extends UserActions { + state: UserState; +} + +export type ClearUserAction = UserActions + export interface UserState { - status: LoginStatus; - id: string; - name: string; - photo: string; - provider: LoginProvider; -} - -export enum LoginStatus { - forbidden = 'forbidden', - ok = 'ok' + id: string; + name: string; + photo: string; + provider: LoginProvider; } export enum LoginProvider { - FACEBOOK = 'facebook', - GITHUB = 'github', - TWITTER = 'twitter', - GITLAB = 'gitlab', - DROPBOX = 'dropbox', - GOOGLE = 'google', - SAML = 'saml', - OAUTH2 = 'oauth2', - EMAIL = 'email', - LDAP = 'ldap', - OPENID = 'openid' + FACEBOOK = 'facebook', + GITHUB = 'github', + TWITTER = 'twitter', + GITLAB = 'gitlab', + DROPBOX = 'dropbox', + GOOGLE = 'google', + SAML = 'saml', + OAUTH2 = 'oauth2', + EMAIL = 'email', + LDAP = 'ldap', + OPENID = 'openid' } -export type UserActions = SetUserAction | ClearUserAction; +export type MaybeUserState = (UserState | null) diff --git a/src/utils/apiUtils.ts b/src/utils/apiUtils.ts index 99342f8af..d2378b85a 100644 --- a/src/utils/apiUtils.ts +++ b/src/utils/apiUtils.ts @@ -1,12 +1,10 @@ import { getMe } from '../api/me' import { setUser } from '../redux/user/methods' -import { LoginStatus } from '../redux/user/types' import { store } from './store' export const getAndSetUser: () => (Promise) = async () => { const me = await getMe() setUser({ - status: LoginStatus.ok, id: me.id, name: me.name, photo: me.photo,