diff --git a/README.md b/README.md index 9a1c3f2bc..4ab46ba56 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,11 @@ You'll need at least Node 10 (we recommend 12). We use [yarn](https://yarnpkg.co 1. Clone this repo (e.g. `git clone https://github.com/codimd/react-client.git codimd-react-client`) 2. Go inside the repo (e.g. `cd codimd-react-client`) 3. run `yarn install` -4. run `yarn start` +4. Either run + - `yarn start:dev` (expects [a server](https://github.com/codimd/server/tree/develop) running under [http://localhost:3000](http://localhost:3000)) + - `yarn start` (makes all api calls to the same domain the react-client runs on (normally [http://localhost:3001](http://localhost:3001) )) -This should run the app in the development mode and open [http://localhost:3000](http://localhost:3000) in your browser. +This should run the app in the development mode and open [http://localhost:3001](http://localhost:3001) in your browser. The page will reload if you make edits. You will also see any lint errors in the console. @@ -26,7 +28,7 @@ You will also see any lint errors in the console. Unit testing is done via jest. -1. `yarn test` +1. run `yarn test` #### End2End diff --git a/cypress.json b/cypress.json index 5993cb871..f070aa584 100644 --- a/cypress.json +++ b/cypress.json @@ -1,5 +1,5 @@ { - "baseUrl": "http://localhost:3000/", + "baseUrl": "http://localhost:3001/", "defaultCommandTimeout": 15000, "experimentalFetchPolyfill": true } diff --git a/cypress/support/config.ts b/cypress/support/config.ts index c9dbbacfd..b92e7b357 100644 --- a/cypress/support/config.ts +++ b/cypress/support/config.ts @@ -5,7 +5,7 @@ export const banner = { export const branding = { name: 'ACME Corp', - logo: 'http://localhost:3000/acme.png' + logo: 'http://localhost:3001/acme.png' } beforeEach(() => { diff --git a/package.json b/package.json index 90656c7b8..c529632aa 100644 --- a/package.json +++ b/package.json @@ -85,15 +85,16 @@ "use-resize-observer": "6.1.0" }, "scripts": { - "start": "react-scripts start", + "start": "PORT=3001 react-scripts start", + "start:dev": "REACT_APP_BACKEND=http://localhost:3000 yarn start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject", "cy:open": "cypress open", "cy:run:chrome": "cypress run --browser chrome", "cy:run:firefox": "cypress run --browser firefox", - "e2e:chrome": "start-server-and-test start http-get://localhost:3000 cy:run:chrome", - "e2e:firefox": "start-server-and-test start http-get://localhost:3000 cy:run:firefox" + "e2e:chrome": "start-server-and-test start http-get://localhost:3001 cy:run:chrome", + "e2e:firefox": "start-server-and-test start http-get://localhost:3001 cy:run:firefox" }, "eslintConfig": { "parserOptions": { diff --git a/public/api/v2/config b/public/api/v2/config index ba74eae9c..30ab2aa80 100644 --- a/public/api/v2/config +++ b/public/api/v2/config @@ -15,7 +15,7 @@ }, "branding": { "name": "ACME Corp", - "logo": "http://localhost:3000/acme.png" + "logo": "http://localhost:3001/acme.png" }, "banner": { "text": "This is the test banner text", diff --git a/public/config.json b/public/config.json deleted file mode 100644 index c2b272d3b..000000000 --- a/public/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "backendUrl": "http://localhost:3000" -} diff --git a/src/api/auth.ts b/src/api/auth.ts index 87f1a890b..538ab8c9c 100644 --- a/src/api/auth.ts +++ b/src/api/auth.ts @@ -1,8 +1,8 @@ -import { expectResponseCode, getBackendUrl } from '../utils/apiUtils' +import { expectResponseCode, getApiUrl } from '../utils/apiUtils' import { defaultFetchConfig } from './default' export const doEmailLogin = async (email: string, password: string): Promise => { - const response = await fetch(getBackendUrl() + '/auth/email', { + const response = await fetch(getApiUrl() + '/auth/email', { ...defaultFetchConfig, method: 'POST', body: JSON.stringify({ @@ -15,7 +15,7 @@ export const doEmailLogin = async (email: string, password: string): Promise => { - const response = await fetch(getBackendUrl() + '/auth/ldap', { + const response = await fetch(getApiUrl() + '/auth/ldap', { ...defaultFetchConfig, method: 'POST', body: JSON.stringify({ @@ -28,7 +28,7 @@ export const doLdapLogin = async (username: string, password: string): Promise => { - const response = await fetch(getBackendUrl() + '/auth/openid', { + const response = await fetch(getApiUrl() + '/auth/openid', { ...defaultFetchConfig, method: 'POST', body: JSON.stringify({ diff --git a/src/api/backend-config/index.ts b/src/api/backend-config/index.ts deleted file mode 100644 index c368aab66..000000000 --- a/src/api/backend-config/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -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/config/index.ts b/src/api/config/index.ts new file mode 100644 index 000000000..c4878dcfc --- /dev/null +++ b/src/api/config/index.ts @@ -0,0 +1,11 @@ +import { expectResponseCode, getApiUrl } from '../../utils/apiUtils' +import { defaultFetchConfig } from '../default' +import { Config } from './types' + +export const getConfig = async (): Promise => { + const response = await fetch(getApiUrl() + '/config', { + ...defaultFetchConfig + }) + expectResponseCode(response) + return await response.json() as Promise +} diff --git a/src/api/backend-config/types.ts b/src/api/config/types.ts similarity index 96% rename from src/api/backend-config/types.ts rename to src/api/config/types.ts index 77c299214..f69a53c99 100644 --- a/src/api/backend-config/types.ts +++ b/src/api/config/types.ts @@ -1,4 +1,4 @@ -export interface BackendConfig { +export interface Config { allowAnonymous: boolean, authProviders: AuthProvidersState, branding: BrandingConfig, diff --git a/src/api/frontend-config/index.ts b/src/api/frontend-config/index.ts deleted file mode 100644 index d7c6df8af..000000000 --- a/src/api/frontend-config/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -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 deleted file mode 100644 index 12fb48058..000000000 --- a/src/api/frontend-config/types.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface FrontendConfig { - backendUrl: string -} diff --git a/src/api/history.ts b/src/api/history.ts index 765b020c6..6acaa3874 100644 --- a/src/api/history.ts +++ b/src/api/history.ts @@ -1,15 +1,15 @@ import { HistoryEntry } from '../components/landing/pages/history/history' -import { expectResponseCode, getBackendUrl } from '../utils/apiUtils' +import { expectResponseCode, getApiUrl } from '../utils/apiUtils' import { defaultFetchConfig } from './default' export const getHistory = async (): Promise => { - const response = await fetch(getBackendUrl() + '/history') + const response = await fetch(getApiUrl() + '/history') expectResponseCode(response) return await response.json() as Promise } export const setHistory = async (entries: HistoryEntry[]): Promise => { - const response = await fetch(getBackendUrl() + '/history', { + const response = await fetch(getApiUrl() + '/history', { ...defaultFetchConfig, method: 'POST', body: JSON.stringify({ @@ -20,7 +20,7 @@ export const setHistory = async (entries: HistoryEntry[]): Promise => { } export const deleteHistory = async (): Promise => { - const response = await fetch(getBackendUrl() + '/history', { + const response = await fetch(getApiUrl() + '/history', { ...defaultFetchConfig, method: 'DELETE' }) @@ -28,7 +28,7 @@ export const deleteHistory = async (): Promise => { } export const updateHistoryEntry = async (noteId: string, entry: HistoryEntry): Promise => { - const response = await fetch(getBackendUrl() + '/history/' + noteId, { + const response = await fetch(getApiUrl() + '/history/' + noteId, { ...defaultFetchConfig, method: 'PUT', body: JSON.stringify(entry) @@ -38,7 +38,7 @@ export const updateHistoryEntry = async (noteId: string, entry: HistoryEntry): P } export const deleteHistoryEntry = async (noteId: string): Promise => { - const response = await fetch(getBackendUrl() + '/history/' + noteId, { + const response = await fetch(getApiUrl() + '/history/' + noteId, { ...defaultFetchConfig, method: 'DELETE' }) diff --git a/src/api/imageProxy.ts b/src/api/imageProxy.ts index c80a27246..042235093 100644 --- a/src/api/imageProxy.ts +++ b/src/api/imageProxy.ts @@ -1,9 +1,9 @@ import { ImageProxyResponse } from '../components/editor/markdown-renderer/replace-components/image/types' -import { expectResponseCode, getBackendUrl } from '../utils/apiUtils' +import { expectResponseCode, getApiUrl } from '../utils/apiUtils' import { defaultFetchConfig } from './default' export const getProxiedUrl = async (imageUrl: string): Promise => { - const response = await fetch(getBackendUrl() + '/media/proxy', { + const response = await fetch(getApiUrl() + '/media/proxy', { ...defaultFetchConfig, method: 'POST', body: JSON.stringify({ diff --git a/src/api/me.ts b/src/api/me.ts index fa8cb8c4f..5cf5ac25e 100644 --- a/src/api/me.ts +++ b/src/api/me.ts @@ -1,5 +1,5 @@ import { LoginProvider } from '../redux/user/types' -import { expectResponseCode, getBackendUrl } from '../utils/apiUtils' +import { expectResponseCode, getApiUrl } from '../utils/apiUtils' import { defaultFetchConfig } from './default' export const getMe = async (): Promise => { @@ -16,7 +16,7 @@ export interface meResponse { } export const updateDisplayName = async (displayName: string): Promise => { - const response = await fetch(getBackendUrl() + '/me', { + const response = await fetch(getApiUrl() + '/me', { ...defaultFetchConfig, method: 'POST', body: JSON.stringify({ @@ -28,7 +28,7 @@ export const updateDisplayName = async (displayName: string): Promise => { } export const changePassword = async (oldPassword: string, newPassword: string): Promise => { - const response = await fetch(getBackendUrl() + '/me/password', { + const response = await fetch(getApiUrl() + '/me/password', { ...defaultFetchConfig, method: 'POST', body: JSON.stringify({ @@ -41,7 +41,7 @@ export const changePassword = async (oldPassword: string, newPassword: string): } export const deleteUser = async (): Promise => { - const response = await fetch(getBackendUrl() + '/me', { + const response = await fetch(getApiUrl() + '/me', { ...defaultFetchConfig, method: 'DELETE' }) diff --git a/src/api/note.ts b/src/api/note.ts index a399e6b53..761789a99 100644 --- a/src/api/note.ts +++ b/src/api/note.ts @@ -1,4 +1,4 @@ -import { expectResponseCode, getBackendUrl } from '../utils/apiUtils' +import { expectResponseCode, getApiUrl } from '../utils/apiUtils' import { defaultFetchConfig } from './default' interface LastChange { @@ -19,13 +19,13 @@ export interface Note { } export const getNote = async (noteId: string): Promise => { - const response = await fetch(getBackendUrl() + `/notes/${noteId}`) + const response = await fetch(getApiUrl() + `/notes/${noteId}`) expectResponseCode(response) return await response.json() as Promise } export const deleteNote = async (noteId: string): Promise => { - const response = await fetch(getBackendUrl() + `/notes/${noteId}`, { + const response = await fetch(getApiUrl() + `/notes/${noteId}`, { ...defaultFetchConfig, method: 'DELETE' }) diff --git a/src/components/application-loader/application-loader.tsx b/src/components/application-loader/application-loader.tsx index 47c6ba47d..16f8bd07e 100644 --- a/src/components/application-loader/application-loader.tsx +++ b/src/components/application-loader/application-loader.tsx @@ -9,8 +9,7 @@ export const ApplicationLoader: React.FC = ({ children }) => { const { pathname } = useLocation() const setUpTasks = useCallback(() => { - const baseUrl: string = window.location.pathname.replace(pathname, '') + '/' - console.debug('Base URL is', baseUrl) + const baseUrl: string = window.location.pathname.replace(pathname, '') return createSetUpTaskList(baseUrl) }, [pathname]) diff --git a/src/components/application-loader/initializers/configLoader.ts b/src/components/application-loader/initializers/configLoader.ts index 13cf0ef7d..b7fcc3923 100644 --- a/src/components/application-loader/initializers/configLoader.ts +++ b/src/components/application-loader/initializers/configLoader.ts @@ -1,24 +1,21 @@ -import { getBackendConfig } from '../../../api/backend-config' -import { getFrontendConfig } from '../../../api/frontend-config' -import { setBackendConfig } from '../../../redux/backend-config/methods' +import { getConfig } from '../../../api/config' +import { setApiUrl } from '../../../redux/api-url/methods' import { setBanner } from '../../../redux/banner/methods' -import { setFrontendConfig } from '../../../redux/frontend-config/methods' +import { setConfig } from '../../../redux/config/methods' import { getAndSetUser } from '../../../utils/apiUtils' export const loadAllConfig: (baseUrl: string) => Promise = async (baseUrl) => { - const frontendConfig = await getFrontendConfig(baseUrl) - if (!frontendConfig) { - return Promise.reject(new Error('Frontend config empty!')) - } - setFrontendConfig(frontendConfig) + setApiUrl({ + apiUrl: (process.env.REACT_APP_BACKEND || baseUrl) + '/api/v2' + }) - const backendConfig = await getBackendConfig() - if (!backendConfig) { - return Promise.reject(new Error('Backend config empty!')) + const config = await getConfig() + if (!config) { + return Promise.reject(new Error('Config empty!')) } - setBackendConfig(backendConfig) + setConfig(config) - const banner = backendConfig.banner + const banner = config.banner if (banner.text !== '') { const lastAcknowledgedTimestamp = window.localStorage.getItem('bannerTimeStamp') || '' setBanner({ diff --git a/src/components/common/branding/branding.tsx b/src/components/common/branding/branding.tsx index 5f8de4fe9..7829800ee 100644 --- a/src/components/common/branding/branding.tsx +++ b/src/components/common/branding/branding.tsx @@ -9,7 +9,7 @@ export interface BrandingProps { } export const Branding: React.FC = ({ inline = false }) => { - const branding = useSelector((state: ApplicationState) => state.backendConfig.branding) + const branding = useSelector((state: ApplicationState) => state.config.branding) const showBranding = !!branding.name || !!branding.logo return ( diff --git a/src/components/common/document-title/document-title.tsx b/src/components/common/document-title/document-title.tsx index 16399227f..41d777900 100644 --- a/src/components/common/document-title/document-title.tsx +++ b/src/components/common/document-title/document-title.tsx @@ -7,7 +7,7 @@ export interface DocumentTitleProps { } export const DocumentTitle: React.FC = ({ title }) => { - const branding = useSelector((state: ApplicationState) => state.backendConfig.branding) + const branding = useSelector((state: ApplicationState) => state.config.branding) useEffect(() => { document.title = `${title ? title + ' - ' : ''}CodiMD ${branding.name ? ` @ ${branding.name}` : ''}` diff --git a/src/components/editor/markdown-renderer/replace-components/image/image-frame.tsx b/src/components/editor/markdown-renderer/replace-components/image/image-frame.tsx index 02d2830ad..4421ae9ea 100644 --- a/src/components/editor/markdown-renderer/replace-components/image/image-frame.tsx +++ b/src/components/editor/markdown-renderer/replace-components/image/image-frame.tsx @@ -5,7 +5,7 @@ import { ApplicationState } from '../../../../../redux' export const ImageFrame: React.FC> = ({ alt, src, ...props }) => { const [imageUrl, setImageUrl] = useState('') - const imageProxyEnabled = useSelector((state: ApplicationState) => state.backendConfig.useImageProxy) + const imageProxyEnabled = useSelector((state: ApplicationState) => state.config.useImageProxy) useEffect(() => { if (!imageProxyEnabled || !src) { diff --git a/src/components/landing/layout/footer/powered-by-links.tsx b/src/components/landing/layout/footer/powered-by-links.tsx index 9e2baed7f..b6038dfb7 100644 --- a/src/components/landing/layout/footer/powered-by-links.tsx +++ b/src/components/landing/layout/footer/powered-by-links.tsx @@ -10,7 +10,7 @@ import { VersionInfo } from '../version-info/version-info' export const PoweredByLinks: React.FC = () => { useTranslation() - const config = useSelector((state: ApplicationState) => state.backendConfig) + const config = useSelector((state: ApplicationState) => state.config) return (

diff --git a/src/components/landing/layout/navigation/sign-in-button.tsx b/src/components/landing/layout/navigation/sign-in-button.tsx index 084ae6996..53ec2778f 100644 --- a/src/components/landing/layout/navigation/sign-in-button.tsx +++ b/src/components/landing/layout/navigation/sign-in-button.tsx @@ -13,7 +13,7 @@ type SignInButtonProps = { export const SignInButton: React.FC = ({ variant, ...props }) => { const { t } = useTranslation() - const authProviders = useSelector((state: ApplicationState) => state.backendConfig.authProviders) + const authProviders = useSelector((state: ApplicationState) => state.config.authProviders) return ( diff --git a/src/components/landing/layout/version-info/version-info.tsx b/src/components/landing/layout/version-info/version-info.tsx index 4d6f94167..990b5939b 100644 --- a/src/components/landing/layout/version-info/version-info.tsx +++ b/src/components/landing/layout/version-info/version-info.tsx @@ -17,7 +17,7 @@ export const VersionInfo: React.FC = () => { const { t } = useTranslation() - const serverVersion = useSelector((state: ApplicationState) => state.backendConfig.version) + const serverVersion = useSelector((state: ApplicationState) => state.config.version) const column = (title: string, version: string, sourceCodeLink: string, issueTrackerLink: string) => ( 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 cc9e7cc94..e3c640cd9 100644 --- a/src/components/landing/pages/intro/cover-buttons/cover-buttons.tsx +++ b/src/components/landing/pages/intro/cover-buttons/cover-buttons.tsx @@ -11,7 +11,7 @@ import './cover-buttons.scss' export const CoverButtons: React.FC = () => { useTranslation() const user = useSelector((state: ApplicationState) => state.user) - const authProviders = useSelector((state: ApplicationState) => state.backendConfig.authProviders) + const authProviders = useSelector((state: ApplicationState) => state.config.authProviders) if (user) { return null diff --git a/src/components/landing/pages/login/auth/via-ldap.tsx b/src/components/landing/pages/login/auth/via-ldap.tsx index aa36c0892..1ea19f4c4 100644 --- a/src/components/landing/pages/login/auth/via-ldap.tsx +++ b/src/components/landing/pages/login/auth/via-ldap.tsx @@ -9,7 +9,7 @@ import { getAndSetUser } from '../../../../../utils/apiUtils' export const ViaLdap: React.FC = () => { const { t } = useTranslation() - const ldapCustomName = useSelector((state: ApplicationState) => state.backendConfig.customAuthNames.ldap) + const ldapCustomName = useSelector((state: ApplicationState) => state.config.customAuthNames.ldap) const [username, setUsername] = useState('') const [password, setPassword] = useState('') diff --git a/src/components/landing/pages/login/auth/via-one-click.tsx b/src/components/landing/pages/login/auth/via-one-click.tsx index 35cc4f4fe..e2bb4f399 100644 --- a/src/components/landing/pages/login/auth/via-one-click.tsx +++ b/src/components/landing/pages/login/auth/via-one-click.tsx @@ -1,4 +1,6 @@ import React from 'react' +import { useSelector } from 'react-redux' +import { ApplicationState } from '../../../../../redux' import { IconName } from '../../../../common/fork-awesome/fork-awesome-icon' import { SocialLinkButton } from './social-link-button/social-link-button' @@ -13,74 +15,75 @@ export enum OneClickType { 'TWITTER' = 'twitter' } -type OneClick2Map = (oneClickType: OneClickType) => { +interface OneClickMetadata { name: string, icon: IconName, className: string, url: string -}; - -const buildBackendAuthUrl = (backendName: string) => { - return `https://localhost:3000/auth/${backendName}` } -const getMetadata: OneClick2Map = (oneClickType: OneClickType) => { +const buildBackendAuthUrl = (backendUrl: string, backendName: string): string => { + return `${backendUrl}/auth/${backendName}` +} + +const getMetadata = (backendUrl: string, oneClickType: OneClickType): OneClickMetadata => { + const buildBackendAuthUrlWithFirstParameterSet = (backendName: string): string => buildBackendAuthUrl(backendUrl, backendName) switch (oneClickType) { case OneClickType.DROPBOX: return { name: 'Dropbox', icon: 'dropbox', className: 'btn-social-dropbox', - url: buildBackendAuthUrl('dropbox') + url: buildBackendAuthUrlWithFirstParameterSet('dropbox') } case OneClickType.FACEBOOK: return { name: 'Facebook', icon: 'facebook', className: 'btn-social-facebook', - url: buildBackendAuthUrl('facebook') + url: buildBackendAuthUrlWithFirstParameterSet('facebook') } case OneClickType.GITHUB: return { name: 'GitHub', icon: 'github', className: 'btn-social-github', - url: buildBackendAuthUrl('github') + url: buildBackendAuthUrlWithFirstParameterSet('github') } case OneClickType.GITLAB: return { name: 'GitLab', icon: 'gitlab', className: 'btn-social-gitlab', - url: buildBackendAuthUrl('gitlab') + url: buildBackendAuthUrlWithFirstParameterSet('gitlab') } case OneClickType.GOOGLE: return { name: 'Google', icon: 'google', className: 'btn-social-google', - url: buildBackendAuthUrl('google') + url: buildBackendAuthUrlWithFirstParameterSet('google') } case OneClickType.OAUTH2: return { name: 'OAuth2', icon: 'address-card', className: 'btn-primary', - url: buildBackendAuthUrl('oauth2') + url: buildBackendAuthUrlWithFirstParameterSet('oauth2') } case OneClickType.SAML: return { name: 'SAML', icon: 'users', className: 'btn-success', - url: buildBackendAuthUrl('saml') + url: buildBackendAuthUrlWithFirstParameterSet('saml') } case OneClickType.TWITTER: return { name: 'Twitter', icon: 'twitter', className: 'btn-social-twitter', - url: buildBackendAuthUrl('twitter') + url: buildBackendAuthUrlWithFirstParameterSet('twitter') } default: return { @@ -98,8 +101,10 @@ export interface ViaOneClickProps { } const ViaOneClick: React.FC = ({ oneClickType, optionalName }) => { - const { name, icon, className, url } = getMetadata(oneClickType) + const backendUrl = useSelector((state: ApplicationState) => state.apiUrl.apiUrl) + const { name, icon, className, url } = getMetadata(backendUrl, oneClickType) const text = optionalName || name + return ( { useTranslation() - const authProviders = useSelector((state: ApplicationState) => state.backendConfig.authProviders) - const customAuthNames = useSelector((state: ApplicationState) => state.backendConfig.customAuthNames) + const authProviders = useSelector((state: ApplicationState) => state.config.authProviders) + const customAuthNames = useSelector((state: ApplicationState) => state.config.customAuthNames) const userLoginState = useSelector((state: ApplicationState) => state.user) const oneClickProviders = [authProviders.dropbox, authProviders.facebook, authProviders.github, authProviders.gitlab, diff --git a/src/components/landing/pages/profile/settings/profile-account-management.tsx b/src/components/landing/pages/profile/settings/profile-account-management.tsx index b38298511..a0dd1c37c 100644 --- a/src/components/landing/pages/profile/settings/profile-account-management.tsx +++ b/src/components/landing/pages/profile/settings/profile-account-management.tsx @@ -3,7 +3,7 @@ import { Button, Card, Modal } from 'react-bootstrap' import { Trans, useTranslation } from 'react-i18next' import { deleteUser } from '../../../../../api/me' import { clearUser } from '../../../../../redux/user/methods' -import { getBackendUrl } from '../../../../../utils/apiUtils' +import { getApiUrl } from '../../../../../utils/apiUtils' import { ForkAwesomeIcon } from '../../../../common/fork-awesome/fork-awesome-icon' export const ProfileAccountManagement: React.FC = () => { @@ -57,7 +57,7 @@ export const ProfileAccountManagement: React.FC = () => { - diff --git a/src/redux/api-url/methods.ts b/src/redux/api-url/methods.ts new file mode 100644 index 000000000..47fbf6ccd --- /dev/null +++ b/src/redux/api-url/methods.ts @@ -0,0 +1,10 @@ +import { store } from '../../utils/store' +import { ApiUrlActionType, ApiUrlObject, SetApiUrlAction } from './types' + +export const setApiUrl = (state: ApiUrlObject): void => { + const action: SetApiUrlAction = { + type: ApiUrlActionType.SET_API_URL, + state + } + store.dispatch(action) +} diff --git a/src/redux/api-url/reducers.ts b/src/redux/api-url/reducers.ts new file mode 100644 index 000000000..59e277a3a --- /dev/null +++ b/src/redux/api-url/reducers.ts @@ -0,0 +1,15 @@ +import { Reducer } from 'redux' +import { ApiUrlActions, ApiUrlActionType, ApiUrlObject, SetApiUrlAction } from './types' + +export const initialState: ApiUrlObject = { + apiUrl: '' +} + +export const ApiUrlReducer: Reducer = (state: ApiUrlObject = initialState, action: ApiUrlActions) => { + switch (action.type) { + case ApiUrlActionType.SET_API_URL: + return (action as SetApiUrlAction).state + default: + return state + } +} diff --git a/src/redux/api-url/types.ts b/src/redux/api-url/types.ts new file mode 100644 index 000000000..6757d7e29 --- /dev/null +++ b/src/redux/api-url/types.ts @@ -0,0 +1,17 @@ +import { Action } from 'redux' + +export enum ApiUrlActionType { + SET_API_URL = 'api-url/set' +} + +export interface ApiUrlActions extends Action { + type: ApiUrlActionType; +} + +export interface SetApiUrlAction extends ApiUrlActions { + state: ApiUrlObject; +} + +export interface ApiUrlObject { + apiUrl: string +} diff --git a/src/redux/backend-config/methods.ts b/src/redux/backend-config/methods.ts deleted file mode 100644 index b6e00697c..000000000 --- a/src/redux/backend-config/methods.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { BackendConfig } from '../../api/backend-config/types' -import { store } from '../../utils/store' -import { BackendConfigActionType, SetBackendConfigAction } from './types' - -export const setBackendConfig = (state: BackendConfig): void => { - const action: SetBackendConfigAction = { - type: BackendConfigActionType.SET_BACKEND_CONFIG, - state: state - } - store.dispatch(action) -} diff --git a/src/redux/backend-config/types.ts b/src/redux/backend-config/types.ts deleted file mode 100644 index 689ea51d5..000000000 --- a/src/redux/backend-config/types.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Action } from 'redux' -import { BackendConfig } from '../../api/backend-config/types' - -export enum BackendConfigActionType { - SET_BACKEND_CONFIG = 'backend-config/set' -} - -export interface BackendConfigActions extends Action{ - type: BackendConfigActionType; -} - -export interface SetBackendConfigAction extends BackendConfigActions { - state: BackendConfig; -} diff --git a/src/redux/config/methods.ts b/src/redux/config/methods.ts new file mode 100644 index 000000000..29298280c --- /dev/null +++ b/src/redux/config/methods.ts @@ -0,0 +1,11 @@ +import { Config } from '../../api/config/types' +import { store } from '../../utils/store' +import { ConfigActionType, SetConfigAction } from './types' + +export const setConfig = (state: Config): void => { + const action: SetConfigAction = { + type: ConfigActionType.SET_CONFIG, + state: state + } + store.dispatch(action) +} diff --git a/src/redux/backend-config/reducers.ts b/src/redux/config/reducers.ts similarity index 59% rename from src/redux/backend-config/reducers.ts rename to src/redux/config/reducers.ts index 90b916169..82eb94e90 100644 --- a/src/redux/backend-config/reducers.ts +++ b/src/redux/config/reducers.ts @@ -1,8 +1,8 @@ import { Reducer } from 'redux' -import { BackendConfig } from '../../api/backend-config/types' -import { BackendConfigActions, BackendConfigActionType, SetBackendConfigAction } from './types' +import { Config } from '../../api/config/types' +import { ConfigActions, ConfigActionType, SetConfigAction } from './types' -export const initialState: BackendConfig = { +export const initialState: Config = { allowAnonymous: true, authProviders: { facebook: false, @@ -43,10 +43,10 @@ export const initialState: BackendConfig = { } } -export const BackendConfigReducer: Reducer<(BackendConfig), BackendConfigActions> = (state: (BackendConfig) = initialState, action: BackendConfigActions) => { +export const ConfigReducer: Reducer = (state: Config = initialState, action: ConfigActions) => { switch (action.type) { - case BackendConfigActionType.SET_BACKEND_CONFIG: - return (action as SetBackendConfigAction).state + case ConfigActionType.SET_CONFIG: + return (action as SetConfigAction).state default: return state } diff --git a/src/redux/config/types.ts b/src/redux/config/types.ts new file mode 100644 index 000000000..5decd6053 --- /dev/null +++ b/src/redux/config/types.ts @@ -0,0 +1,14 @@ +import { Action } from 'redux' +import { Config } from '../../api/config/types' + +export enum ConfigActionType { + SET_CONFIG = 'config/set' +} + +export interface ConfigActions extends Action { + type: ConfigActionType; +} + +export interface SetConfigAction extends ConfigActions { + state: Config; +} diff --git a/src/redux/frontend-config/methods.ts b/src/redux/frontend-config/methods.ts deleted file mode 100644 index 787d36bed..000000000 --- a/src/redux/frontend-config/methods.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { FrontendConfig } from '../../api/frontend-config/types' -import { store } from '../../utils/store' -import { FrontendConfigActionType, SetFrontendConfigAction } from './types' - -export const setFrontendConfig = (state: FrontendConfig): void => { - const action: SetFrontendConfigAction = { - type: FrontendConfigActionType.SET_FRONTEND_CONFIG, - state: { - ...state, - backendUrl: state.backendUrl + '/api/v2' - } - } - store.dispatch(action) -} diff --git a/src/redux/frontend-config/reducers.ts b/src/redux/frontend-config/reducers.ts deleted file mode 100644 index 81e12c930..000000000 --- a/src/redux/frontend-config/reducers.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Reducer } from 'redux' -import { FrontendConfig } from '../../api/frontend-config/types' -import { FrontendConfigActions, FrontendConfigActionType, SetFrontendConfigAction } from './types' - -const initialState: FrontendConfig = { - backendUrl: '' -} - -export const FrontendConfigReducer: Reducer<(FrontendConfig), FrontendConfigActions> = (state: (FrontendConfig) = initialState, action: FrontendConfigActions) => { - switch (action.type) { - 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 deleted file mode 100644 index 6343ac860..000000000 --- a/src/redux/frontend-config/types.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Action } from 'redux' -import { FrontendConfig } from '../../api/frontend-config/types' - -export enum FrontendConfigActionType { - SET_FRONTEND_CONFIG = 'frontend-config/set' -} - -export interface FrontendConfigActions extends Action { - type: FrontendConfigActionType; -} - -export interface SetFrontendConfigAction extends FrontendConfigActions { - state: FrontendConfig; -} diff --git a/src/redux/index.ts b/src/redux/index.ts index b6c7ce2e6..6344b98b2 100644 --- a/src/redux/index.ts +++ b/src/redux/index.ts @@ -1,27 +1,27 @@ import { combineReducers, Reducer } from 'redux' -import { BackendConfig } from '../api/backend-config/types' -import { FrontendConfig } from '../api/frontend-config/types' -import { BackendConfigReducer } from './backend-config/reducers' +import { Config } from '../api/config/types' +import { ApiUrlReducer } from './api-url/reducers' +import { ApiUrlObject } from './api-url/types' import { BannerReducer } from './banner/reducers' import { BannerState } from './banner/types' +import { ConfigReducer } from './config/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 { - user: MaybeUserState; - backendConfig: BackendConfig; - banner: BannerState; - frontendConfig: FrontendConfig; - editorConfig: EditorConfig; + user: MaybeUserState; + config: Config; + banner: BannerState; + apiUrl: ApiUrlObject; + editorConfig: EditorConfig; } export const allReducers: Reducer = combineReducers({ user: UserReducer, - backendConfig: BackendConfigReducer, + config: ConfigReducer, banner: BannerReducer, - frontendConfig: FrontendConfigReducer, + apiUrl: ApiUrlReducer, editorConfig: EditorConfigReducer }) diff --git a/src/utils/apiUtils.ts b/src/utils/apiUtils.ts index dff5a30b1..a41fc022e 100644 --- a/src/utils/apiUtils.ts +++ b/src/utils/apiUtils.ts @@ -12,8 +12,8 @@ export const getAndSetUser: () => (Promise) = async () => { }) } -export const getBackendUrl: (() => string) = () => { - return store.getState().frontendConfig.backendUrl +export const getApiUrl = (): string => { + return store.getState().apiUrl.apiUrl } export const expectResponseCode = (response: Response, code = 200): void => {