mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-25 11:16:31 -05:00
Restructure redux code (#109)
* Restructure redux code Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de> Co-authored-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
parent
db5bec7000
commit
570c45017c
28 changed files with 214 additions and 231 deletions
8
src/api/backend-config/index.ts
Normal file
8
src/api/backend-config/index.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { expectResponseCode, getBackendUrl } from '../../utils/apiUtils'
|
||||||
|
import { BackendConfig } from './types'
|
||||||
|
|
||||||
|
export const getBackendConfig = async (): Promise<BackendConfig> => {
|
||||||
|
const response = await fetch(getBackendUrl() + '/config')
|
||||||
|
expectResponseCode(response)
|
||||||
|
return await response.json() as Promise<BackendConfig>
|
||||||
|
}
|
39
src/api/backend-config/types.ts
Normal file
39
src/api/backend-config/types.ts
Normal file
|
@ -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,
|
||||||
|
}
|
|
@ -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<BackendConfigState> => {
|
|
||||||
const response = await fetch(getBackendUrl() + '/config')
|
|
||||||
expectResponseCode(response)
|
|
||||||
return await response.json() as Promise<BackendConfigState>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getFrontendConfig = async (baseUrl: string): Promise<FrontendConfigState> => {
|
|
||||||
const response = await fetch(`${baseUrl}config.json`)
|
|
||||||
expectResponseCode(response)
|
|
||||||
return await response.json() as Promise<FrontendConfigState>
|
|
||||||
}
|
|
8
src/api/frontend-config/index.ts
Normal file
8
src/api/frontend-config/index.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { expectResponseCode } from '../../utils/apiUtils'
|
||||||
|
import { FrontendConfig } from './types'
|
||||||
|
|
||||||
|
export const getFrontendConfig = async (baseUrl: string): Promise<FrontendConfig> => {
|
||||||
|
const response = await fetch(`${baseUrl}config.json`)
|
||||||
|
expectResponseCode(response)
|
||||||
|
return await response.json() as Promise<FrontendConfig>
|
||||||
|
}
|
3
src/api/frontend-config/types.ts
Normal file
3
src/api/frontend-config/types.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export interface FrontendConfig {
|
||||||
|
backendUrl: string
|
||||||
|
}
|
|
@ -2,9 +2,9 @@ import React from 'react'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
import { useParams } from 'react-router'
|
import { useParams } from 'react-router'
|
||||||
import { ApplicationState } from '../../redux'
|
import { ApplicationState } from '../../redux'
|
||||||
import { EditorMode } from '../../redux/editor/types'
|
|
||||||
import { EditorWindow } from './editor-window/editor-window'
|
import { EditorWindow } from './editor-window/editor-window'
|
||||||
import { MarkdownPreview } from './markdown-preview/markdown-preview'
|
import { MarkdownPreview } from './markdown-preview/markdown-preview'
|
||||||
|
import { EditorMode } from './task-bar/editor-view-mode'
|
||||||
import { TaskBar } from './task-bar/task-bar'
|
import { TaskBar } from './task-bar/task-bar'
|
||||||
|
|
||||||
interface RouteParameters {
|
interface RouteParameters {
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
import { ToggleButton, ToggleButtonGroup } from 'react-bootstrap'
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { ToggleButton, ToggleButtonGroup } from 'react-bootstrap'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
import { ForkAwesomeIcon } from '../../../fork-awesome/fork-awesome-icon'
|
import { ForkAwesomeIcon } from '../../../fork-awesome/fork-awesome-icon'
|
||||||
import { ApplicationState } from '../../../redux'
|
import { ApplicationState } from '../../../redux'
|
||||||
import { EditorMode } from '../../../redux/editor/types'
|
|
||||||
import { setEditorModeConfig } from '../../../redux/editor/methods'
|
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 { t } = useTranslation()
|
||||||
const editorConfig = useSelector((state: ApplicationState) => state.editorConfig)
|
const editorConfig = useSelector((state: ApplicationState) => state.editorConfig)
|
||||||
return (
|
return (
|
||||||
|
@ -15,7 +20,9 @@ const EditorViewMode: React.FC = () => {
|
||||||
type="radio"
|
type="radio"
|
||||||
name="options"
|
name="options"
|
||||||
defaultValue={editorConfig.editorMode}
|
defaultValue={editorConfig.editorMode}
|
||||||
onChange={(value: EditorMode) => { setEditorModeConfig(value) }}>
|
onChange={(value: EditorMode) => {
|
||||||
|
setEditorModeConfig(value)
|
||||||
|
}}>
|
||||||
<ToggleButton value={EditorMode.PREVIEW} variant="outline-secondary" title={t('editor.viewMode.view')}>
|
<ToggleButton value={EditorMode.PREVIEW} variant="outline-secondary" title={t('editor.viewMode.view')}>
|
||||||
<ForkAwesomeIcon icon="eye"/>
|
<ForkAwesomeIcon icon="eye"/>
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
|
@ -28,5 +35,3 @@ const EditorViewMode: React.FC = () => {
|
||||||
</ToggleButtonGroup>
|
</ToggleButtonGroup>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export { EditorViewMode }
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { Navbar } from 'react-bootstrap'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
import { ApplicationState } from '../../../../../redux'
|
import { ApplicationState } from '../../../../../redux'
|
||||||
import { LoginStatus } from '../../../../../redux/user/types'
|
|
||||||
import { HeaderNavLink } from '../header-nav-link'
|
import { HeaderNavLink } from '../header-nav-link'
|
||||||
import { NewGuestNoteButton } from '../new-guest-note-button'
|
import { NewGuestNoteButton } from '../new-guest-note-button'
|
||||||
import { NewUserNoteButton } from '../new-user-note-button'
|
import { NewUserNoteButton } from '../new-user-note-button'
|
||||||
|
@ -26,7 +25,7 @@ const HeaderBar: React.FC = () => {
|
||||||
</HeaderNavLink>
|
</HeaderNavLink>
|
||||||
</div>
|
</div>
|
||||||
<div className="d-inline-flex">
|
<div className="d-inline-flex">
|
||||||
{user.status === LoginStatus.forbidden
|
{!user
|
||||||
? <Fragment>
|
? <Fragment>
|
||||||
<span className={'mr-1 d-flex'}>
|
<span className={'mr-1 d-flex'}>
|
||||||
<NewGuestNoteButton/>
|
<NewGuestNoteButton/>
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
import { Dropdown } from 'react-bootstrap'
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { Dropdown } from 'react-bootstrap'
|
||||||
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
|
import { LinkContainer } from 'react-router-bootstrap'
|
||||||
import { ForkAwesomeIcon } from '../../../../../fork-awesome/fork-awesome-icon'
|
import { ForkAwesomeIcon } from '../../../../../fork-awesome/fork-awesome-icon'
|
||||||
import { ApplicationState } from '../../../../../redux'
|
import { ApplicationState } from '../../../../../redux'
|
||||||
import { LinkContainer } from 'react-router-bootstrap'
|
|
||||||
import { clearUser } from '../../../../../redux/user/methods'
|
import { clearUser } from '../../../../../redux/user/methods'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
|
||||||
import { UserAvatar } from '../../user-avatar/user-avatar'
|
import { UserAvatar } from '../../user-avatar/user-avatar'
|
||||||
|
|
||||||
export const UserDropdown: React.FC = () => {
|
export const UserDropdown: React.FC = () => {
|
||||||
useTranslation()
|
useTranslation()
|
||||||
const user = useSelector((state: ApplicationState) => state.user)
|
const user = useSelector((state: ApplicationState) => state.user)
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropdown alignRight>
|
<Dropdown alignRight>
|
||||||
<Dropdown.Toggle size="sm" variant="dark" id="dropdown-user" className={'d-flex align-items-center'}>
|
<Dropdown.Toggle size="sm" variant="dark" id="dropdown-user" className={'d-flex align-items-center'}>
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
|
||||||
import { Button } from 'react-bootstrap'
|
import { Button } from 'react-bootstrap'
|
||||||
import { LoginStatus } from '../../../../../redux/user/types'
|
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
import { ApplicationState } from '../../../../../redux'
|
import { ApplicationState } from '../../../../../redux'
|
||||||
import './cover-buttons.scss'
|
import './cover-buttons.scss'
|
||||||
|
|
||||||
|
@ -11,7 +10,7 @@ export const CoverButtons: React.FC = () => {
|
||||||
useTranslation()
|
useTranslation()
|
||||||
const user = useSelector((state: ApplicationState) => state.user)
|
const user = useSelector((state: ApplicationState) => state.user)
|
||||||
|
|
||||||
if (user.status === LoginStatus.ok) {
|
if (user) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,19 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Card, Col, Row } from 'react-bootstrap'
|
import { Card, Col, Row } from 'react-bootstrap'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
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 { useSelector } from 'react-redux'
|
||||||
import { ApplicationState } from '../../../../redux'
|
|
||||||
import { ViaOpenId } from './auth/via-openid'
|
|
||||||
import { Redirect } from 'react-router'
|
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 = () => {
|
export const Login: React.FC = () => {
|
||||||
useTranslation()
|
useTranslation()
|
||||||
const authProviders = useSelector((state: ApplicationState) => state.backendConfig.authProviders)
|
const authProviders = useSelector((state: ApplicationState) => state.backendConfig.authProviders)
|
||||||
const customAuthNames = useSelector((state: ApplicationState) => state.backendConfig.customAuthNames)
|
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 ? <ViaEMail/> : null
|
const emailForm = authProviders.email ? <ViaEMail/> : null
|
||||||
const ldapForm = authProviders.ldap ? <ViaLdap/> : null
|
const ldapForm = authProviders.ldap ? <ViaLdap/> : null
|
||||||
const openIdForm = authProviders.openid ? <ViaOpenId/> : null
|
const openIdForm = authProviders.openid ? <ViaOpenId/> : null
|
||||||
|
@ -30,7 +29,7 @@ export const Login: React.FC = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userLoginState === LoginStatus.ok) {
|
if (userLoginState) {
|
||||||
// TODO Redirect to previous page?
|
// TODO Redirect to previous page?
|
||||||
return (
|
return (
|
||||||
<Redirect to='/history'/>
|
<Redirect to='/history'/>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { Col, Row } from 'react-bootstrap'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
import { Redirect } from 'react-router'
|
import { Redirect } from 'react-router'
|
||||||
import { ApplicationState } from '../../../../redux'
|
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 { ProfileAccountManagement } from './settings/profile-account-management'
|
||||||
import { ProfileChangePassword } from './settings/profile-change-password'
|
import { ProfileChangePassword } from './settings/profile-change-password'
|
||||||
import { ProfileDisplayName } from './settings/profile-display-name'
|
import { ProfileDisplayName } from './settings/profile-display-name'
|
||||||
|
@ -11,9 +11,9 @@ import { ProfileDisplayName } from './settings/profile-display-name'
|
||||||
export const Profile: React.FC = () => {
|
export const Profile: React.FC = () => {
|
||||||
const user = useSelector((state: ApplicationState) => state.user)
|
const user = useSelector((state: ApplicationState) => state.user)
|
||||||
|
|
||||||
if (user.status === LoginStatus.forbidden) {
|
if (!user) {
|
||||||
return (
|
return (
|
||||||
<Redirect to={'/login'} />
|
<Redirect to={'/login'}/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ export const Profile: React.FC = () => {
|
||||||
<Row className="h-100 flex justify-content-center">
|
<Row className="h-100 flex justify-content-center">
|
||||||
<Col lg={6}>
|
<Col lg={6}>
|
||||||
<ProfileDisplayName/>
|
<ProfileDisplayName/>
|
||||||
{ user.provider === LoginProvider.EMAIL ? <ProfileChangePassword/> : null }
|
{user.provider === LoginProvider.EMAIL ? <ProfileChangePassword/> : null}
|
||||||
<ProfileAccountManagement/>
|
<ProfileAccountManagement/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { ChangeEvent, FormEvent, useState } from 'react'
|
import React, { ChangeEvent, FormEvent, useEffect, useState } from 'react'
|
||||||
import { Button, Card, Form } from 'react-bootstrap'
|
import { Alert, Button, Card, Form } from 'react-bootstrap'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
import { updateDisplayName } from '../../../../../api/me'
|
import { updateDisplayName } from '../../../../../api/me'
|
||||||
|
@ -7,13 +7,22 @@ import { ApplicationState } from '../../../../../redux'
|
||||||
import { getAndSetUser } from '../../../../../utils/apiUtils'
|
import { getAndSetUser } from '../../../../../utils/apiUtils'
|
||||||
|
|
||||||
export const ProfileDisplayName: React.FC = () => {
|
export const ProfileDisplayName: React.FC = () => {
|
||||||
|
const regexInvalidDisplayName = /^\s*$/
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const user = useSelector((state: ApplicationState) => state.user)
|
const user = useSelector((state: ApplicationState) => state.user)
|
||||||
const [submittable, setSubmittable] = useState(false)
|
const [submittable, setSubmittable] = useState(false)
|
||||||
const [error, setError] = 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 <Alert variant={'danger'}>User not logged in</Alert>
|
||||||
|
}
|
||||||
|
|
||||||
const changeNameField = (event: ChangeEvent<HTMLInputElement>) => {
|
const changeNameField = (event: ChangeEvent<HTMLInputElement>) => {
|
||||||
setSubmittable(!regexInvalidDisplayName.test(event.target.value))
|
setSubmittable(!regexInvalidDisplayName.test(event.target.value))
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { getBackendConfig, getFrontendConfig } from '../api/config'
|
import { getBackendConfig } from '../api/backend-config'
|
||||||
import { setFrontendConfig } from '../redux/frontend-config/methods'
|
import { getFrontendConfig } from '../api/frontend-config'
|
||||||
import { setBackendConfig } from '../redux/backend-config/methods'
|
import { setBackendConfig } from '../redux/backend-config/methods'
|
||||||
|
import { setFrontendConfig } from '../redux/frontend-config/methods'
|
||||||
import { getAndSetUser } from '../utils/apiUtils'
|
import { getAndSetUser } from '../utils/apiUtils'
|
||||||
|
|
||||||
export const loadAllConfig: (baseUrl: string) => Promise<void> = async (baseUrl) => {
|
export const loadAllConfig: (baseUrl: string) => Promise<void> = async (baseUrl) => {
|
||||||
|
|
|
@ -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 { store } from '../../utils/store'
|
||||||
|
import { BackendConfigActionType, SetBackendConfigAction } from './types'
|
||||||
|
|
||||||
export const setBackendConfig = (state: BackendConfigState): void => {
|
export const setBackendConfig = (state: BackendConfig): void => {
|
||||||
const action: SetBackendConfigAction = {
|
const action: SetBackendConfigAction = {
|
||||||
type: SET_BACKEND_CONFIG_ACTION_TYPE,
|
type: BackendConfigActionType.SET_BACKEND_CONFIG,
|
||||||
payload: {
|
state: state
|
||||||
state
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
store.dispatch(action)
|
store.dispatch(action)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { Reducer } from 'redux'
|
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,
|
allowAnonymous: true,
|
||||||
authProviders: {
|
authProviders: {
|
||||||
facebook: false,
|
facebook: false,
|
||||||
|
@ -33,10 +34,10 @@ export const initialState: BackendConfigState = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BackendConfigReducer: Reducer<BackendConfigState, BackendConfigActions> = (state: BackendConfigState = initialState, action: BackendConfigActions) => {
|
export const BackendConfigReducer: Reducer<(BackendConfig), BackendConfigActions> = (state: (BackendConfig) = initialState, action: BackendConfigActions) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case SET_BACKEND_CONFIG_ACTION_TYPE:
|
case BackendConfigActionType.SET_BACKEND_CONFIG:
|
||||||
return action.payload.state
|
return (action as SetBackendConfigAction).state
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,52 +1,14 @@
|
||||||
import { Action } from 'redux'
|
import { Action } from 'redux'
|
||||||
|
import { BackendConfig } from '../../api/backend-config/types'
|
||||||
|
|
||||||
export const SET_BACKEND_CONFIG_ACTION_TYPE = 'backend-config/set'
|
export enum BackendConfigActionType {
|
||||||
|
SET_BACKEND_CONFIG = 'backend-config/set'
|
||||||
export interface BackendConfigState {
|
|
||||||
allowAnonymous: boolean,
|
|
||||||
authProviders: AuthProvidersState,
|
|
||||||
customAuthNames: CustomAuthNames,
|
|
||||||
specialLinks: SpecialLinks,
|
|
||||||
version: BackendVersion,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BackendVersion {
|
export interface BackendConfigActions extends Action<BackendConfigActionType>{
|
||||||
version: string,
|
type: BackendConfigActionType;
|
||||||
sourceCodeUrl: string
|
|
||||||
issueTrackerUrl: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AuthProvidersState {
|
export interface SetBackendConfigAction extends BackendConfigActions {
|
||||||
facebook: boolean,
|
state: BackendConfig;
|
||||||
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,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SetBackendConfigAction extends Action {
|
|
||||||
type: string;
|
|
||||||
payload: {
|
|
||||||
state: BackendConfigState;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export type BackendConfigActions = SetBackendConfigAction;
|
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
import {
|
import { EditorMode } from '../../components/editor/task-bar/editor-view-mode'
|
||||||
EditorMode,
|
|
||||||
SET_EDITOR_CONFIG_MODE_ACTION_TYPE,
|
|
||||||
SetEditorConfigAction
|
|
||||||
} from './types'
|
|
||||||
import { store } from '../../utils/store'
|
import { store } from '../../utils/store'
|
||||||
|
import { EditorConfigActionType, SetEditorConfigAction } from './types'
|
||||||
|
|
||||||
export const setEditorModeConfig = (editorMode: EditorMode): void => {
|
export const setEditorModeConfig = (editorMode: EditorMode): void => {
|
||||||
const action: SetEditorConfigAction = {
|
const action: SetEditorConfigAction = {
|
||||||
type: SET_EDITOR_CONFIG_MODE_ACTION_TYPE,
|
type: EditorConfigActionType.SET_EDITOR_VIEW_MODE,
|
||||||
payload: editorMode
|
mode: editorMode
|
||||||
}
|
}
|
||||||
store.dispatch(action)
|
store.dispatch(action)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,17 @@
|
||||||
import { Reducer } from 'redux'
|
import { Reducer } from 'redux'
|
||||||
import {
|
import { EditorMode } from '../../components/editor/task-bar/editor-view-mode'
|
||||||
EditorConfigActions,
|
import { EditorConfig, EditorConfigActions, EditorConfigActionType, SetEditorConfigAction } from './types'
|
||||||
EditorConfigState,
|
|
||||||
EditorMode,
|
|
||||||
SET_EDITOR_CONFIG_MODE_ACTION_TYPE
|
|
||||||
} from './types'
|
|
||||||
|
|
||||||
export const initialState: EditorConfigState = {
|
export const initialState: EditorConfig = {
|
||||||
editorMode: EditorMode.PREVIEW
|
editorMode: EditorMode.PREVIEW
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EditorConfigReducer: Reducer<EditorConfigState, EditorConfigActions> = (state: EditorConfigState = initialState, action: EditorConfigActions) => {
|
export const EditorConfigReducer: Reducer<EditorConfig, EditorConfigActions> = (state: EditorConfig = initialState, action: EditorConfigActions) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case SET_EDITOR_CONFIG_MODE_ACTION_TYPE:
|
case EditorConfigActionType.SET_EDITOR_VIEW_MODE:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
editorMode: action.payload
|
editorMode: (action as SetEditorConfigAction).mode
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
import { Action } from 'redux'
|
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 enum EditorConfigActionType {
|
||||||
|
SET_EDITOR_VIEW_MODE = 'editor/mode/set'
|
||||||
export interface EditorConfigState {
|
|
||||||
editorMode: EditorMode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum EditorMode {
|
export interface EditorConfig {
|
||||||
PREVIEW,
|
editorMode: EditorMode;
|
||||||
BOTH,
|
|
||||||
EDITOR,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SetEditorConfigAction extends Action {
|
export interface EditorConfigActions extends Action<EditorConfigActionType> {
|
||||||
type: string;
|
type: EditorConfigActionType;
|
||||||
payload: EditorMode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type EditorConfigActions = SetEditorConfigAction;
|
export interface SetEditorConfigAction extends EditorConfigActions {
|
||||||
|
mode: EditorMode;
|
||||||
|
}
|
||||||
|
|
|
@ -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 { store } from '../../utils/store'
|
||||||
|
import { FrontendConfigActionType, SetFrontendConfigAction } from './types'
|
||||||
|
|
||||||
export const setFrontendConfig = (state: FrontendConfigState): void => {
|
export const setFrontendConfig = (state: FrontendConfig): void => {
|
||||||
const action: SetFrontendConfigAction = {
|
const action: SetFrontendConfigAction = {
|
||||||
type: SET_FRONTEND_CONFIG_ACTION_TYPE,
|
type: FrontendConfigActionType.SET_FRONTEND_CONFIG,
|
||||||
payload: {
|
state: {
|
||||||
state: {
|
...state,
|
||||||
...state,
|
backendUrl: state.backendUrl + '/api/v2.0/'
|
||||||
backendUrl: state.backendUrl + '/api/v2.0/'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
store.dispatch(action)
|
store.dispatch(action)
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
import { Reducer } from 'redux'
|
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: ''
|
backendUrl: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FrontendConfigReducer: Reducer<FrontendConfigState, FrontendConfigActions> = (state: FrontendConfigState = initialState, action: FrontendConfigActions) => {
|
export const FrontendConfigReducer: Reducer<(FrontendConfig), FrontendConfigActions> = (state: (FrontendConfig) = initialState, action: FrontendConfigActions) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case SET_FRONTEND_CONFIG_ACTION_TYPE:
|
case FrontendConfigActionType.SET_FRONTEND_CONFIG:
|
||||||
return action.payload.state
|
return (action as SetFrontendConfigAction).state
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
import { Action } from 'redux'
|
import { Action } from 'redux'
|
||||||
|
import { FrontendConfig } from '../../api/frontend-config/types'
|
||||||
|
|
||||||
export const SET_FRONTEND_CONFIG_ACTION_TYPE = 'frontend-config/set'
|
export enum FrontendConfigActionType {
|
||||||
|
SET_FRONTEND_CONFIG = 'frontend-config/set'
|
||||||
export interface SetFrontendConfigAction extends Action {
|
|
||||||
type: string;
|
|
||||||
payload: {
|
|
||||||
state: FrontendConfigState;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FrontendConfigState {
|
export interface FrontendConfigActions extends Action<FrontendConfigActionType> {
|
||||||
backendUrl: string,
|
type: FrontendConfigActionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FrontendConfigActions = SetFrontendConfigAction;
|
export interface SetFrontendConfigAction extends FrontendConfigActions {
|
||||||
|
state: FrontendConfig;
|
||||||
|
}
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import { combineReducers, Reducer } from 'redux'
|
import { combineReducers, Reducer } from 'redux'
|
||||||
import { UserState } from './user/types'
|
import { BackendConfig } from '../api/backend-config/types'
|
||||||
import { UserReducer } from './user/reducers'
|
import { FrontendConfig } from '../api/frontend-config/types'
|
||||||
import { BackendConfigState } from './backend-config/types'
|
|
||||||
import { FrontendConfigState } from './frontend-config/types'
|
|
||||||
import { BackendConfigReducer } from './backend-config/reducers'
|
import { BackendConfigReducer } from './backend-config/reducers'
|
||||||
import { FrontendConfigReducer } from './frontend-config/reducers'
|
|
||||||
import { EditorConfigState } from './editor/types'
|
|
||||||
import { EditorConfigReducer } from './editor/reducers'
|
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 {
|
export interface ApplicationState {
|
||||||
user: UserState;
|
user: MaybeUserState;
|
||||||
backendConfig: BackendConfigState;
|
backendConfig: BackendConfig;
|
||||||
frontendConfig: FrontendConfigState;
|
frontendConfig: FrontendConfig;
|
||||||
editorConfig: EditorConfigState;
|
editorConfig: EditorConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const allReducers: Reducer<ApplicationState> = combineReducers<ApplicationState>({
|
export const allReducers: Reducer<ApplicationState> = combineReducers<ApplicationState>({
|
||||||
|
|
|
@ -1,20 +1,17 @@
|
||||||
import { CLEAR_USER_ACTION_TYPE, ClearUserAction, SET_USER_ACTION_TYPE, SetUserAction, UserState } from './types'
|
|
||||||
import { store } from '../../utils/store'
|
import { store } from '../../utils/store'
|
||||||
|
import { ClearUserAction, SetUserAction, UserActionType, UserState } from './types'
|
||||||
|
|
||||||
export const setUser: (state: UserState) => void = (state: UserState) => {
|
export const setUser: (state: UserState) => void = (state: UserState) => {
|
||||||
const action: SetUserAction = {
|
const action: SetUserAction = {
|
||||||
type: SET_USER_ACTION_TYPE,
|
type: UserActionType.SET_USER,
|
||||||
payload: {
|
state
|
||||||
state
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
store.dispatch(action)
|
store.dispatch(action)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const clearUser: () => void = () => {
|
export const clearUser: () => void = () => {
|
||||||
const action: ClearUserAction = {
|
const action: ClearUserAction = {
|
||||||
type: CLEAR_USER_ACTION_TYPE,
|
type: UserActionType.CLEAR_USER
|
||||||
payload: null
|
|
||||||
}
|
}
|
||||||
store.dispatch(action)
|
store.dispatch(action)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,12 @@
|
||||||
import { Reducer } from 'redux'
|
import { Reducer } from 'redux'
|
||||||
import {
|
import { MaybeUserState, SetUserAction, UserActions, UserActionType } from './types'
|
||||||
CLEAR_USER_ACTION_TYPE,
|
|
||||||
LoginProvider,
|
|
||||||
LoginStatus,
|
|
||||||
SET_USER_ACTION_TYPE,
|
|
||||||
SetUserAction,
|
|
||||||
UserActions,
|
|
||||||
UserState
|
|
||||||
} from './types'
|
|
||||||
|
|
||||||
export const initialState: UserState = {
|
export const UserReducer: Reducer<MaybeUserState, UserActions> = (state: MaybeUserState = null, action: UserActions) => {
|
||||||
id: '',
|
|
||||||
name: '',
|
|
||||||
photo: '',
|
|
||||||
status: LoginStatus.forbidden,
|
|
||||||
provider: LoginProvider.EMAIL
|
|
||||||
}
|
|
||||||
|
|
||||||
export const UserReducer: Reducer<UserState, UserActions> = (state: UserState = initialState, action: UserActions) => {
|
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case SET_USER_ACTION_TYPE:
|
case UserActionType.SET_USER:
|
||||||
return (action as SetUserAction).payload.state
|
return (action as SetUserAction).state
|
||||||
case CLEAR_USER_ACTION_TYPE:
|
case UserActionType.CLEAR_USER:
|
||||||
return initialState
|
return null
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,45 +1,39 @@
|
||||||
import { Action } from 'redux'
|
import { Action } from 'redux'
|
||||||
|
|
||||||
export const SET_USER_ACTION_TYPE = 'user/set'
|
export enum UserActionType {
|
||||||
export const CLEAR_USER_ACTION_TYPE = 'user/clear'
|
SET_USER = 'user/set',
|
||||||
|
CLEAR_USER = 'user/clear'
|
||||||
export interface SetUserAction extends Action {
|
|
||||||
type: string;
|
|
||||||
payload: {
|
|
||||||
state: UserState,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClearUserAction extends Action {
|
export interface UserActions extends Action<UserActionType> {
|
||||||
type: string;
|
type: UserActionType;
|
||||||
payload: null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SetUserAction extends UserActions {
|
||||||
|
state: UserState;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ClearUserAction = UserActions
|
||||||
|
|
||||||
export interface UserState {
|
export interface UserState {
|
||||||
status: LoginStatus;
|
id: string;
|
||||||
id: string;
|
name: string;
|
||||||
name: string;
|
photo: string;
|
||||||
photo: string;
|
provider: LoginProvider;
|
||||||
provider: LoginProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum LoginStatus {
|
|
||||||
forbidden = 'forbidden',
|
|
||||||
ok = 'ok'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum LoginProvider {
|
export enum LoginProvider {
|
||||||
FACEBOOK = 'facebook',
|
FACEBOOK = 'facebook',
|
||||||
GITHUB = 'github',
|
GITHUB = 'github',
|
||||||
TWITTER = 'twitter',
|
TWITTER = 'twitter',
|
||||||
GITLAB = 'gitlab',
|
GITLAB = 'gitlab',
|
||||||
DROPBOX = 'dropbox',
|
DROPBOX = 'dropbox',
|
||||||
GOOGLE = 'google',
|
GOOGLE = 'google',
|
||||||
SAML = 'saml',
|
SAML = 'saml',
|
||||||
OAUTH2 = 'oauth2',
|
OAUTH2 = 'oauth2',
|
||||||
EMAIL = 'email',
|
EMAIL = 'email',
|
||||||
LDAP = 'ldap',
|
LDAP = 'ldap',
|
||||||
OPENID = 'openid'
|
OPENID = 'openid'
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UserActions = SetUserAction | ClearUserAction;
|
export type MaybeUserState = (UserState | null)
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
import { getMe } from '../api/me'
|
import { getMe } from '../api/me'
|
||||||
import { setUser } from '../redux/user/methods'
|
import { setUser } from '../redux/user/methods'
|
||||||
import { LoginStatus } from '../redux/user/types'
|
|
||||||
import { store } from './store'
|
import { store } from './store'
|
||||||
|
|
||||||
export const getAndSetUser: () => (Promise<void>) = async () => {
|
export const getAndSetUser: () => (Promise<void>) = async () => {
|
||||||
const me = await getMe()
|
const me = await getMe()
|
||||||
setUser({
|
setUser({
|
||||||
status: LoginStatus.ok,
|
|
||||||
id: me.id,
|
id: me.id,
|
||||||
name: me.name,
|
name: me.name,
|
||||||
photo: me.photo,
|
photo: me.photo,
|
||||||
|
|
Loading…
Reference in a new issue