mirror of
https://github.com/elyby/accounts-frontend.git
synced 2024-11-23 00:22:57 +05:30
Centralize all redux types into one place, add overrides for the connect, useSelector and useDispatch functions
This commit is contained in:
parent
96e74cf9bb
commit
5a9c54002d
@ -148,6 +148,7 @@ module.exports = {
|
|||||||
|
|
||||||
// ts
|
// ts
|
||||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||||
|
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||||
'@typescript-eslint/no-explicit-any': 'off',
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
'@typescript-eslint/no-use-before-define': 'off',
|
'@typescript-eslint/no-use-before-define': 'off',
|
||||||
'@typescript-eslint/ban-ts-ignore': 'off',
|
'@typescript-eslint/ban-ts-ignore': 'off',
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { FormattedMessage as Message } from 'react-intl';
|
import { FormattedMessage as Message } from 'react-intl';
|
||||||
|
|
||||||
|
import { connect } from 'app/functions';
|
||||||
import * as loader from 'app/services/loader';
|
import * as loader from 'app/services/loader';
|
||||||
import { SKIN_DARK, COLOR_WHITE, Skin } from 'app/components/ui';
|
import { SKIN_DARK, COLOR_WHITE, Skin } from 'app/components/ui';
|
||||||
import { Button } from 'app/components/ui/form';
|
import { Button } from 'app/components/ui/form';
|
||||||
import { authenticate, revoke } from 'app/components/accounts/actions';
|
import { authenticate, revoke } from 'app/components/accounts/actions';
|
||||||
import { getActiveAccount, Account } from 'app/components/accounts/reducer';
|
import { getActiveAccount, Account } from 'app/components/accounts/reducer';
|
||||||
import { RootState } from 'app/reducers';
|
import { State as AccountState } from 'app/components/accounts/reducer';
|
||||||
|
|
||||||
import styles from './accountSwitcher.scss';
|
import styles from './accountSwitcher.scss';
|
||||||
|
|
||||||
@ -19,7 +20,7 @@ interface Props {
|
|||||||
onAfterAction: () => void;
|
onAfterAction: () => void;
|
||||||
// called after switching an account. The active account will be passed as arg
|
// called after switching an account. The active account will be passed as arg
|
||||||
onSwitch: (account: Account) => void;
|
onSwitch: (account: Account) => void;
|
||||||
accounts: RootState['accounts'];
|
accounts: AccountState;
|
||||||
skin: Skin;
|
skin: Skin;
|
||||||
// whether active account should be expanded and shown on the top
|
// whether active account should be expanded and shown on the top
|
||||||
highlightActiveAccount: boolean;
|
highlightActiveAccount: boolean;
|
||||||
@ -166,7 +167,7 @@ export class AccountSwitcher extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
({ accounts }: RootState) => ({
|
({ accounts }) => ({
|
||||||
accounts,
|
accounts,
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@ import { authenticate, revoke, logoutAll, logoutStrangers } from 'app/components
|
|||||||
import { add, activate, remove, reset } from 'app/components/accounts/actions/pure-actions';
|
import { add, activate, remove, reset } from 'app/components/accounts/actions/pure-actions';
|
||||||
import { updateUser, setUser } from 'app/components/user/actions';
|
import { updateUser, setUser } from 'app/components/user/actions';
|
||||||
import { setLogin, setAccountSwitcher } from 'app/components/auth/actions';
|
import { setLogin, setAccountSwitcher } from 'app/components/auth/actions';
|
||||||
import { Dispatch, RootState } from 'app/reducers';
|
import { Dispatch, State as RootState } from 'app/types';
|
||||||
|
|
||||||
import { Account } from './reducer';
|
import { Account } from './reducer';
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import { relogin as navigateToLogin, setAccountSwitcher } from 'app/components/a
|
|||||||
import { updateUser, setGuest } from 'app/components/user/actions';
|
import { updateUser, setGuest } from 'app/components/user/actions';
|
||||||
import { setLocale } from 'app/components/i18n/actions';
|
import { setLocale } from 'app/components/i18n/actions';
|
||||||
import logger from 'app/services/logger';
|
import logger from 'app/services/logger';
|
||||||
import { ThunkAction } from 'app/reducers';
|
import { Action as AppAction } from 'app/types';
|
||||||
|
|
||||||
import { getActiveAccount, Account } from './reducer';
|
import { getActiveAccount, Account } from './reducer';
|
||||||
import { add, remove, activate, reset, updateToken } from './actions/pure-actions';
|
import { add, remove, activate, reset, updateToken } from './actions/pure-actions';
|
||||||
@ -26,7 +26,7 @@ export function authenticate(
|
|||||||
token: string;
|
token: string;
|
||||||
refreshToken: string | null;
|
refreshToken: string | null;
|
||||||
},
|
},
|
||||||
): ThunkAction<Promise<Account>> {
|
): AppAction<Promise<Account>> {
|
||||||
const { token, refreshToken } = account;
|
const { token, refreshToken } = account;
|
||||||
const email = 'email' in account ? account.email : null;
|
const email = 'email' in account ? account.email : null;
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ export function authenticate(
|
|||||||
/**
|
/**
|
||||||
* Re-fetch user data for currently active account
|
* Re-fetch user data for currently active account
|
||||||
*/
|
*/
|
||||||
export function refreshUserData(): ThunkAction<Promise<void>> {
|
export function refreshUserData(): AppAction<Promise<void>> {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
const activeAccount = getActiveAccount(getState());
|
const activeAccount = getActiveAccount(getState());
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ function findAccountIdFromToken(token: string): number {
|
|||||||
*
|
*
|
||||||
* @returns {Function}
|
* @returns {Function}
|
||||||
*/
|
*/
|
||||||
export function ensureToken(): ThunkAction<Promise<void>> {
|
export function ensureToken(): AppAction<Promise<void>> {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const { token } = getActiveAccount(getState()) || {};
|
const { token } = getActiveAccount(getState()) || {};
|
||||||
|
|
||||||
@ -182,7 +182,7 @@ export function recoverFromTokenError(
|
|||||||
status: number;
|
status: number;
|
||||||
message: string;
|
message: string;
|
||||||
} | void,
|
} | void,
|
||||||
): ThunkAction<Promise<void>> {
|
): AppAction<Promise<void>> {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
if (error && error.status === 401) {
|
if (error && error.status === 401) {
|
||||||
const activeAccount = getActiveAccount(getState());
|
const activeAccount = getActiveAccount(getState());
|
||||||
@ -218,7 +218,7 @@ export function recoverFromTokenError(
|
|||||||
*
|
*
|
||||||
* @returns {Function}
|
* @returns {Function}
|
||||||
*/
|
*/
|
||||||
export function requestNewToken(): ThunkAction<Promise<void>> {
|
export function requestNewToken(): AppAction<Promise<void>> {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const { refreshToken } = getActiveAccount(getState()) || {};
|
const { refreshToken } = getActiveAccount(getState()) || {};
|
||||||
|
|
||||||
@ -250,7 +250,7 @@ export function requestNewToken(): ThunkAction<Promise<void>> {
|
|||||||
*
|
*
|
||||||
* @returns {Function}
|
* @returns {Function}
|
||||||
*/
|
*/
|
||||||
export function revoke(account: Account): ThunkAction<Promise<void>> {
|
export function revoke(account: Account): AppAction<Promise<void>> {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
const accountToReplace: Account | null =
|
const accountToReplace: Account | null =
|
||||||
getState().accounts.available.find(({ id }) => id !== account.id) || null;
|
getState().accounts.available.find(({ id }) => id !== account.id) || null;
|
||||||
@ -276,7 +276,7 @@ export function revoke(account: Account): ThunkAction<Promise<void>> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function relogin(email?: string): ThunkAction<Promise<void>> {
|
export function relogin(email?: string): AppAction<Promise<void>> {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
const activeAccount = getActiveAccount(getState());
|
const activeAccount = getActiveAccount(getState());
|
||||||
|
|
||||||
@ -288,7 +288,7 @@ export function relogin(email?: string): ThunkAction<Promise<void>> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function logoutAll(): ThunkAction<Promise<void>> {
|
export function logoutAll(): AppAction<Promise<void>> {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
dispatch(setGuest());
|
dispatch(setGuest());
|
||||||
|
|
||||||
@ -317,7 +317,7 @@ export function logoutAll(): ThunkAction<Promise<void>> {
|
|||||||
*
|
*
|
||||||
* @returns {Function}
|
* @returns {Function}
|
||||||
*/
|
*/
|
||||||
export function logoutStrangers(): ThunkAction<Promise<void>> {
|
export function logoutStrangers(): AppAction<Promise<void>> {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
const {
|
const {
|
||||||
accounts: { available },
|
accounts: { available },
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React, { CSSProperties, MouseEventHandler, ReactElement, ReactNode } from 'react';
|
import React, { CSSProperties, MouseEventHandler, ReactElement, ReactNode } from 'react';
|
||||||
|
|
||||||
import { AccountsState } from 'app/components/accounts';
|
import { AccountsState } from 'app/components/accounts';
|
||||||
import { User } from 'app/components/user';
|
import { User } from 'app/components/user';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'app/functions';
|
||||||
import { TransitionMotion, spring, PlainStyle, Style, TransitionStyle, TransitionPlainStyle } from 'react-motion';
|
import { TransitionMotion, spring, PlainStyle, Style, TransitionStyle, TransitionPlainStyle } from 'react-motion';
|
||||||
import { Panel, PanelBody, PanelFooter, PanelHeader } from 'app/components/ui/Panel';
|
import { Panel, PanelBody, PanelFooter, PanelHeader } from 'app/components/ui/Panel';
|
||||||
import { Form } from 'app/components/ui/form';
|
import { Form } from 'app/components/ui/form';
|
||||||
@ -9,7 +10,6 @@ import MeasureHeight from 'app/components/MeasureHeight';
|
|||||||
import panelStyles from 'app/components/ui/panel.scss';
|
import panelStyles from 'app/components/ui/panel.scss';
|
||||||
import icons from 'app/components/ui/icons.scss';
|
import icons from 'app/components/ui/icons.scss';
|
||||||
import authFlow from 'app/services/authFlow';
|
import authFlow from 'app/services/authFlow';
|
||||||
import { RootState } from 'app/reducers';
|
|
||||||
|
|
||||||
import { Provider as AuthContextProvider } from './Context';
|
import { Provider as AuthContextProvider } from './Context';
|
||||||
import { getLogin, State as AuthState } from './reducer';
|
import { getLogin, State as AuthState } from './reducer';
|
||||||
@ -546,7 +546,7 @@ class PanelTransition extends React.PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
(state: RootState) => {
|
(state) => {
|
||||||
const login = getLogin(state);
|
const login = getLogin(state);
|
||||||
let user = {
|
let user = {
|
||||||
...state.user,
|
...state.user,
|
||||||
|
@ -23,7 +23,7 @@ import dispatchBsod from 'app/components/ui/bsod/dispatchBsod';
|
|||||||
import { create as createPopup } from 'app/components/ui/popup/actions';
|
import { create as createPopup } from 'app/components/ui/popup/actions';
|
||||||
import ContactForm from 'app/components/contact';
|
import ContactForm from 'app/components/contact';
|
||||||
import { Account } from 'app/components/accounts/reducer';
|
import { Account } from 'app/components/accounts/reducer';
|
||||||
import { ThunkAction, Dispatch } from 'app/reducers';
|
import { Action as AppAction, Dispatch } from 'app/types';
|
||||||
import { Resp } from 'app/services/request';
|
import { Resp } from 'app/services/request';
|
||||||
|
|
||||||
import { Credentials, Client, OAuthState, getCredentials } from './reducer';
|
import { Credentials, Client, OAuthState, getCredentials } from './reducer';
|
||||||
@ -189,7 +189,7 @@ export function register({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function activate({ key = '' }: { key: string }): ThunkAction<Promise<Account>> {
|
export function activate({ key = '' }: { key: string }): AppAction<Promise<Account>> {
|
||||||
return wrapInLoader((dispatch) =>
|
return wrapInLoader((dispatch) =>
|
||||||
activateEndpoint(key)
|
activateEndpoint(key)
|
||||||
.then(authHandler(dispatch))
|
.then(authHandler(dispatch))
|
||||||
@ -239,7 +239,7 @@ export function setLogin(login: string | null): SetCredentialsAction {
|
|||||||
return setCredentials(login ? { login } : null);
|
return setCredentials(login ? { login } : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function relogin(login: string | null): ThunkAction {
|
export function relogin(login: string | null): AppAction {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const credentials = getCredentials(getState());
|
const credentials = getCredentials(getState());
|
||||||
const returnUrl = credentials.returnUrl || location.pathname + location.search;
|
const returnUrl = credentials.returnUrl || location.pathname + location.search;
|
||||||
@ -266,7 +266,7 @@ function requestTotp({
|
|||||||
login: string;
|
login: string;
|
||||||
password: string;
|
password: string;
|
||||||
rememberMe: boolean;
|
rememberMe: boolean;
|
||||||
}): ThunkAction {
|
}): AppAction {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
// merging with current credentials to propogate returnUrl
|
// merging with current credentials to propogate returnUrl
|
||||||
const credentials = getCredentials(getState());
|
const credentials = getCredentials(getState());
|
||||||
@ -521,7 +521,7 @@ export function setOAuthCode(payload: { success: boolean; code: string; displayC
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resetOAuth(): ThunkAction {
|
export function resetOAuth(): AppAction {
|
||||||
return (dispatch): void => {
|
return (dispatch): void => {
|
||||||
localStorage.removeItem('oauthData');
|
localStorage.removeItem('oauthData');
|
||||||
dispatch(setOAuthRequest({}));
|
dispatch(setOAuthRequest({}));
|
||||||
@ -531,7 +531,7 @@ export function resetOAuth(): ThunkAction {
|
|||||||
/**
|
/**
|
||||||
* Resets all temporary state related to auth
|
* Resets all temporary state related to auth
|
||||||
*/
|
*/
|
||||||
export function resetAuth(): ThunkAction {
|
export function resetAuth(): AppAction {
|
||||||
return (dispatch, getSate): Promise<void> => {
|
return (dispatch, getSate): Promise<void> => {
|
||||||
dispatch(setLogin(null));
|
dispatch(setLogin(null));
|
||||||
dispatch(resetOAuth());
|
dispatch(resetOAuth());
|
||||||
@ -588,7 +588,7 @@ export function setLoadingState(isLoading: boolean): SetLoadingAction {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function wrapInLoader<T>(fn: ThunkAction<Promise<T>>): ThunkAction<Promise<T>> {
|
function wrapInLoader<T>(fn: AppAction<Promise<T>>): AppAction<Promise<T>> {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
dispatch(setLoadingState(true));
|
dispatch(setLoadingState(true));
|
||||||
const endLoading = () => dispatch(setLoadingState(false));
|
const endLoading = () => dispatch(setLoadingState(false));
|
||||||
@ -671,3 +671,12 @@ function validationErrorsHandler(
|
|||||||
return Promise.reject(resp);
|
return Promise.reject(resp);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Action =
|
||||||
|
| ErrorAction
|
||||||
|
| CredentialsAction
|
||||||
|
| AccountSwitcherAction
|
||||||
|
| LoadingAction
|
||||||
|
| ClientAction
|
||||||
|
| OAuthAction
|
||||||
|
| ScopesAction;
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React, { MouseEventHandler } from 'react';
|
import React, { MouseEventHandler } from 'react';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { defineMessages, FormattedMessage as Message } from 'react-intl';
|
import { defineMessages, FormattedMessage as Message } from 'react-intl';
|
||||||
import { Helmet } from 'react-helmet-async';
|
import { Helmet } from 'react-helmet-async';
|
||||||
|
|
||||||
|
import { connect } from 'app/functions';
|
||||||
import { Button } from 'app/components/ui/form';
|
import { Button } from 'app/components/ui/form';
|
||||||
import copy from 'app/services/copy';
|
import copy from 'app/services/copy';
|
||||||
import { RootState } from 'app/reducers';
|
|
||||||
|
|
||||||
import styles from './finish.scss';
|
import styles from './finish.scss';
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ class Finish extends React.Component<Props> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(({ auth }: RootState) => {
|
export default connect(({ auth }) => {
|
||||||
if (!auth || !auth.client || !auth.oauth) {
|
if (!auth || !auth.client || !auth.oauth) {
|
||||||
throw new Error('Can not connect Finish component. No auth data in state');
|
throw new Error('Can not connect Finish component. No auth data in state');
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { combineReducers, Reducer } from 'redux';
|
import { combineReducers, Reducer } from 'redux';
|
||||||
import { RootState } from 'app/reducers';
|
|
||||||
import { Scope } from '../../services/api/oauth';
|
import { State as RootState } from 'app/types';
|
||||||
|
import { Scope } from 'app/services/api/oauth';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ErrorAction,
|
ErrorAction,
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import React, { ComponentType, useCallback, useRef, useState } from 'react';
|
import React, { ComponentType, useCallback, useRef, useState } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
|
|
||||||
import { send as sendFeedback } from 'app/services/api/feedback';
|
import { send as sendFeedback } from 'app/services/api/feedback';
|
||||||
import { RootState } from 'app/reducers';
|
|
||||||
import logger from 'app/services/logger';
|
import logger from 'app/services/logger';
|
||||||
|
import { useReduxSelector } from 'app/functions';
|
||||||
|
|
||||||
import ContactFormPopup from './ContactFormPopup';
|
import ContactFormPopup from './ContactFormPopup';
|
||||||
import SuccessContactFormPopup from './SuccessContactFormPopup';
|
import SuccessContactFormPopup from './SuccessContactFormPopup';
|
||||||
@ -13,7 +12,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ContactForm: ComponentType<Props> = ({ onClose }) => {
|
const ContactForm: ComponentType<Props> = ({ onClose }) => {
|
||||||
const userEmail = useSelector((state: RootState) => state.user.email);
|
const userEmail = useReduxSelector((state) => state.user.email);
|
||||||
const usedEmailRef = useRef(userEmail); // Use ref to avoid unneeded redraw
|
const usedEmailRef = useRef(userEmail); // Use ref to avoid unneeded redraw
|
||||||
const [isSent, setIsSent] = useState<boolean>(false);
|
const [isSent, setIsSent] = useState<boolean>(false);
|
||||||
const onSubmit = useCallback(
|
const onSubmit = useCallback(
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
import { connect } from 'app/functions';
|
||||||
import { create as createPopup } from 'app/components/ui/popup/actions';
|
import { create as createPopup } from 'app/components/ui/popup/actions';
|
||||||
import ContactForm from 'app/components/contact';
|
import ContactForm from 'app/components/contact';
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { Dispatch, Action as ReduxAction } from 'redux';
|
import { Dispatch, Action as ReduxAction } from 'redux';
|
||||||
|
|
||||||
import { OauthAppResponse } from 'app/services/api/oauth';
|
import { OauthAppResponse } from 'app/services/api/oauth';
|
||||||
import oauth from 'app/services/api/oauth';
|
import oauth from 'app/services/api/oauth';
|
||||||
import { User } from 'app/components/user';
|
import { User } from 'app/components/user';
|
||||||
import { ThunkAction } from 'app/reducers';
|
import { Action as AppAction } from 'app/types';
|
||||||
|
|
||||||
import { Apps } from './reducer';
|
import { State } from './reducer';
|
||||||
|
|
||||||
interface SetAvailableAction extends ReduxAction {
|
interface SetAvailableAction extends ReduxAction {
|
||||||
type: 'apps:setAvailable';
|
type: 'apps:setAvailable';
|
||||||
@ -18,11 +19,11 @@ export function setAppsList(apps: Array<OauthAppResponse>): SetAvailableAction {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getApp(state: { apps: Apps }, clientId: string): OauthAppResponse | null {
|
export function getApp(state: { apps: State }, clientId: string): OauthAppResponse | null {
|
||||||
return state.apps.available.find((app) => app.clientId === clientId) || null;
|
return state.apps.available.find((app) => app.clientId === clientId) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchApp(clientId: string): ThunkAction<Promise<void>> {
|
export function fetchApp(clientId: string): AppAction<Promise<void>> {
|
||||||
return async (dispatch) => {
|
return async (dispatch) => {
|
||||||
const app = await oauth.getApp(clientId);
|
const app = await oauth.getApp(clientId);
|
||||||
|
|
||||||
@ -78,7 +79,7 @@ function createDeleteAppAction(clientId: string): DeleteAppAction {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resetApp(clientId: string, resetSecret: boolean): ThunkAction<Promise<void>> {
|
export function resetApp(clientId: string, resetSecret: boolean): AppAction<Promise<void>> {
|
||||||
return async (dispatch) => {
|
return async (dispatch) => {
|
||||||
const { data: app } = await oauth.reset(clientId, resetSecret);
|
const { data: app } = await oauth.reset(clientId, resetSecret);
|
||||||
|
|
||||||
|
@ -2,15 +2,15 @@ import { OauthAppResponse } from 'app/services/api/oauth';
|
|||||||
|
|
||||||
import { Action } from './actions';
|
import { Action } from './actions';
|
||||||
|
|
||||||
export interface Apps {
|
export interface State {
|
||||||
available: Array<OauthAppResponse>;
|
available: Array<OauthAppResponse>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaults: Apps = {
|
const defaults: State = {
|
||||||
available: [],
|
available: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function apps(state: Apps = defaults, action: Action): Apps {
|
export default function apps(state: State = defaults, action: Action): State {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'apps:setAvailable':
|
case 'apps:setAvailable':
|
||||||
return {
|
return {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React, { ComponentType, MouseEventHandler, useCallback } from 'react';
|
import React, { ComponentType, MouseEventHandler, useCallback } from 'react';
|
||||||
import { useDispatch } from 'react-redux';
|
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { FormattedMessage as Message } from 'react-intl';
|
import { FormattedMessage as Message } from 'react-intl';
|
||||||
|
|
||||||
|
import { useReduxDispatch } from 'app/functions';
|
||||||
import LanguageSwitcher from 'app/components/languageSwitcher';
|
import LanguageSwitcher from 'app/components/languageSwitcher';
|
||||||
import SourceCode from 'app/components/sourceCode';
|
import SourceCode from 'app/components/sourceCode';
|
||||||
import { create as createPopup } from 'app/components/ui/popup/actions';
|
import { create as createPopup } from 'app/components/ui/popup/actions';
|
||||||
@ -10,7 +11,7 @@ import { ContactLink } from 'app/components/contact';
|
|||||||
import styles from './footerMenu.scss';
|
import styles from './footerMenu.scss';
|
||||||
|
|
||||||
const FooterMenu: ComponentType = () => {
|
const FooterMenu: ComponentType = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useReduxDispatch();
|
||||||
|
|
||||||
const createPopupHandler = useCallback(
|
const createPopupHandler = useCallback(
|
||||||
(popup: ComponentType): MouseEventHandler<HTMLAnchorElement> => (event) => {
|
(popup: ComponentType): MouseEventHandler<HTMLAnchorElement> => (event) => {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import React, { useState, useEffect, ComponentType } from 'react';
|
import React, { useState, useEffect, ComponentType } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
import { RawIntlProvider, IntlShape } from 'react-intl';
|
import { RawIntlProvider, IntlShape } from 'react-intl';
|
||||||
|
|
||||||
import i18n from 'app/services/i18n';
|
import i18n from 'app/services/i18n';
|
||||||
import { RootState } from 'app/reducers';
|
import { useReduxSelector } from 'app/functions';
|
||||||
|
|
||||||
const IntlProvider: ComponentType = ({ children }) => {
|
const IntlProvider: ComponentType = ({ children }) => {
|
||||||
const [intl, setIntl] = useState<IntlShape>();
|
const [intl, setIntl] = useState<IntlShape>();
|
||||||
const locale = useSelector(({ i18n: i18nState }: RootState) => i18nState.locale);
|
const locale = useReduxSelector(({ i18n: i18nState }) => i18nState.locale);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (process.env.NODE_ENV === 'test') {
|
if (process.env.NODE_ENV === 'test') {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { Action as ReduxAction } from 'redux';
|
import { Action as ReduxAction } from 'redux';
|
||||||
import i18n from 'app/services/i18n';
|
|
||||||
import { ThunkAction } from 'app/reducers';
|
|
||||||
|
|
||||||
export function setLocale(desiredLocale: string): ThunkAction<Promise<string>> {
|
import i18n from 'app/services/i18n';
|
||||||
|
import { Action as AppAction } from 'app/types';
|
||||||
|
|
||||||
|
export function setLocale(desiredLocale: string): AppAction<Promise<string>> {
|
||||||
return async (dispatch) => {
|
return async (dispatch) => {
|
||||||
const locale = i18n.detectLanguage(desiredLocale);
|
const locale = i18n.detectLanguage(desiredLocale);
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import React, { ComponentType, useCallback } from 'react';
|
import React, { ComponentType, useCallback } from 'react';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
|
||||||
|
|
||||||
import LOCALES from 'app/i18n';
|
import LOCALES from 'app/i18n';
|
||||||
import { changeLang } from 'app/components/user/actions';
|
import { changeLang } from 'app/components/user/actions';
|
||||||
import { RootState } from 'app/reducers';
|
import { useReduxDispatch, useReduxSelector } from 'app/functions';
|
||||||
|
|
||||||
import LanguageSwitcherPopup from './LanguageSwitcherPopup';
|
import LanguageSwitcherPopup from './LanguageSwitcherPopup';
|
||||||
|
|
||||||
@ -12,8 +11,8 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const LanguageSwitcher: ComponentType<Props> = ({ onClose = () => {} }) => {
|
const LanguageSwitcher: ComponentType<Props> = ({ onClose = () => {} }) => {
|
||||||
const selectedLocale = useSelector((state: RootState) => state.i18n.locale);
|
const selectedLocale = useReduxSelector((state) => state.i18n.locale);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useReduxDispatch();
|
||||||
|
|
||||||
const onChangeLang = useCallback(
|
const onChangeLang = useCallback(
|
||||||
(lang: string) => {
|
(lang: string) => {
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
import React, { ComponentType, useCallback } from 'react';
|
import React, { ComponentType, useCallback } from 'react';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
|
import { useReduxDispatch, useReduxSelector } from 'app/functions';
|
||||||
import { getLocaleIconUrl } from 'app/components/i18n';
|
import { getLocaleIconUrl } from 'app/components/i18n';
|
||||||
import LANGS from 'app/i18n';
|
import LANGS from 'app/i18n';
|
||||||
import { create as createPopup } from 'app/components/ui/popup/actions';
|
import { create as createPopup } from 'app/components/ui/popup/actions';
|
||||||
import LanguageSwitcher from 'app/components/languageSwitcher';
|
import LanguageSwitcher from 'app/components/languageSwitcher';
|
||||||
import { RootState } from 'app/reducers';
|
|
||||||
|
|
||||||
import styles from './link.scss';
|
import styles from './link.scss';
|
||||||
|
|
||||||
const LanguageLink: ComponentType = () => {
|
const LanguageLink: ComponentType = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useReduxDispatch();
|
||||||
const showLanguageSwitcherPopup = useCallback(() => {
|
const showLanguageSwitcherPopup = useCallback(() => {
|
||||||
dispatch(createPopup({ Popup: LanguageSwitcher }));
|
dispatch(createPopup({ Popup: LanguageSwitcher }));
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
const userLang = useSelector((state: RootState) => state.user.lang);
|
const userLang = useReduxSelector((state) => state.user.lang);
|
||||||
const interfaceLocale = useSelector((state: RootState) => state.i18n.locale);
|
const interfaceLocale = useReduxSelector((state) => state.i18n.locale);
|
||||||
|
|
||||||
const localeDefinition = LANGS[userLang] || LANGS[interfaceLocale];
|
const localeDefinition = LANGS[userLang] || LANGS[interfaceLocale];
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
|
||||||
import { ContextProvider } from 'app/shell';
|
import { ContextProvider } from 'app/shell';
|
||||||
import { Store } from 'app/reducers';
|
import { Store } from 'app/types';
|
||||||
import { History } from 'history';
|
import { History } from 'history';
|
||||||
|
|
||||||
import { bsod } from './actions';
|
import { bsod } from './actions';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import request from 'app/services/request';
|
import request from 'app/services/request';
|
||||||
import logger from 'app/services/logger';
|
import logger from 'app/services/logger';
|
||||||
import { Store } from 'app/reducers';
|
import { Store } from 'app/types';
|
||||||
import { History } from 'history';
|
import { History } from 'history';
|
||||||
|
|
||||||
import dispatchBsod, { inject } from './dispatchBsod';
|
import dispatchBsod, { inject } from './dispatchBsod';
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import React, { ReactNode } from 'react';
|
import React, { ReactNode } from 'react';
|
||||||
import { TransitionGroup, CSSTransition } from 'react-transition-group';
|
import { TransitionGroup, CSSTransition } from 'react-transition-group';
|
||||||
import { browserHistory } from 'app/services/history';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { Location } from 'history';
|
import { Location } from 'history';
|
||||||
import { RootState } from 'app/reducers';
|
|
||||||
|
import { connect } from 'app/functions';
|
||||||
|
import { browserHistory } from 'app/services/history';
|
||||||
|
|
||||||
import { PopupConfig } from './reducer';
|
import { PopupConfig } from './reducer';
|
||||||
import { destroy } from './actions';
|
import { destroy } from './actions';
|
||||||
@ -95,7 +95,7 @@ export class PopupStack extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
(state: RootState) => ({
|
(state) => ({
|
||||||
...state.popup,
|
...state.popup,
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,7 @@ import { Action as ReduxAction } from 'redux';
|
|||||||
|
|
||||||
import { changeLang as changeLangEndpoint, acceptRules as acceptRulesEndpoint } from 'app/services/api/accounts';
|
import { changeLang as changeLangEndpoint, acceptRules as acceptRulesEndpoint } from 'app/services/api/accounts';
|
||||||
import { setLocale } from 'app/components/i18n/actions';
|
import { setLocale } from 'app/components/i18n/actions';
|
||||||
import { ThunkAction } from 'app/reducers';
|
import { Action as AppAction } from 'app/types';
|
||||||
|
|
||||||
import { User } from './reducer';
|
import { User } from './reducer';
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ function changeLangPure(payload: string): ChangeLangAction {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function changeLang(targetLang: string): ThunkAction<Promise<void>> {
|
export function changeLang(targetLang: string): AppAction<Promise<void>> {
|
||||||
return (dispatch, getState) =>
|
return (dispatch, getState) =>
|
||||||
dispatch(setLocale(targetLang)).then((lang: string) => {
|
dispatch(setLocale(targetLang)).then((lang: string) => {
|
||||||
const { id, isGuest, lang: oldLang } = getState().user;
|
const { id, isGuest, lang: oldLang } = getState().user;
|
||||||
@ -72,7 +72,7 @@ export function changeLang(targetLang: string): ThunkAction<Promise<void>> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setGuest(): ThunkAction<Promise<void>> {
|
export function setGuest(): AppAction<Promise<void>> {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
dispatch(
|
dispatch(
|
||||||
setUser({
|
setUser({
|
||||||
@ -83,7 +83,7 @@ export function setGuest(): ThunkAction<Promise<void>> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function acceptRules(): ThunkAction<Promise<{ success: boolean }>> {
|
export function acceptRules(): AppAction<Promise<{ success: boolean }>> {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const { id } = getState().user;
|
const { id } = getState().user;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { authenticate, logoutStrangers } from 'app/components/accounts/actions';
|
import { authenticate, logoutStrangers } from 'app/components/accounts/actions';
|
||||||
import { getActiveAccount } from 'app/components/accounts/reducer';
|
import { getActiveAccount } from 'app/components/accounts/reducer';
|
||||||
import request from 'app/services/request';
|
import request from 'app/services/request';
|
||||||
import { Store } from 'app/reducers';
|
import { Store } from 'app/types';
|
||||||
|
|
||||||
import { changeLang } from './actions';
|
import { changeLang } from './actions';
|
||||||
import bearerHeaderMiddleware from './middlewares/bearerHeaderMiddleware';
|
import bearerHeaderMiddleware from './middlewares/bearerHeaderMiddleware';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||||
import expect from 'app/test/unexpected';
|
import expect from 'app/test/unexpected';
|
||||||
import { RootState } from 'app/reducers';
|
import { State as RootState } from 'app/types';
|
||||||
|
|
||||||
import bearerHeaderMiddleware from 'app/components/user/middlewares/bearerHeaderMiddleware';
|
import bearerHeaderMiddleware from 'app/components/user/middlewares/bearerHeaderMiddleware';
|
||||||
import { MiddlewareRequestOptions } from '../../../services/request/PromiseMiddlewareLayer';
|
import { MiddlewareRequestOptions } from '../../../services/request/PromiseMiddlewareLayer';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { getActiveAccount } from 'app/components/accounts/reducer';
|
import { getActiveAccount } from 'app/components/accounts/reducer';
|
||||||
import { Store } from 'app/reducers';
|
import { Store } from 'app/types';
|
||||||
import { Middleware } from 'app/services/request';
|
import { Middleware } from 'app/services/request';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ensureToken, recoverFromTokenError } from 'app/components/accounts/actions';
|
import { ensureToken, recoverFromTokenError } from 'app/components/accounts/actions';
|
||||||
import { getActiveAccount } from 'app/components/accounts/reducer';
|
import { getActiveAccount } from 'app/components/accounts/reducer';
|
||||||
import { Store } from 'app/reducers';
|
import { Store } from 'app/types';
|
||||||
import { Middleware } from 'app/services/request';
|
import { Middleware } from 'app/services/request';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React, { ComponentType } from 'react';
|
import React, { ComponentType } from 'react';
|
||||||
import { Route, Redirect, RouteProps } from 'react-router-dom';
|
import { Route, Redirect, RouteProps } from 'react-router-dom';
|
||||||
import { Location } from 'history';
|
import { Location } from 'history';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
import { connect } from 'app/functions';
|
||||||
import { getActiveAccount } from 'app/components/accounts/reducer';
|
import { getActiveAccount } from 'app/components/accounts/reducer';
|
||||||
import { Account } from 'app/components/accounts';
|
import { Account } from 'app/components/accounts';
|
||||||
import { RootState } from 'app/reducers';
|
|
||||||
|
|
||||||
interface Props extends RouteProps {
|
interface Props extends RouteProps {
|
||||||
component: ComponentType<any>;
|
component: ComponentType<any>;
|
||||||
@ -20,6 +20,6 @@ const PrivateRoute = ({ account, component: Component, ...rest }: Props) => (
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default connect((state: RootState) => ({
|
export default connect((state) => ({
|
||||||
account: getActiveAccount(state),
|
account: getActiveAccount(state),
|
||||||
}))(PrivateRoute);
|
}))(PrivateRoute);
|
||||||
|
@ -1,3 +1,26 @@
|
|||||||
|
import {
|
||||||
|
connect as reduxConnect,
|
||||||
|
MapDispatchToPropsParam,
|
||||||
|
MapStateToPropsParam,
|
||||||
|
useDispatch,
|
||||||
|
useSelector,
|
||||||
|
} from 'react-redux';
|
||||||
|
|
||||||
|
import { State, Dispatch } from 'app/types';
|
||||||
|
|
||||||
|
export const connect = <TStateProps = {}, TDispatchProps = {}, TOwnProps = {}>(
|
||||||
|
mapStateToProps?: MapStateToPropsParam<TStateProps, TOwnProps, State> | null | undefined,
|
||||||
|
dispatchProps?: MapDispatchToPropsParam<TDispatchProps, TOwnProps> | null | undefined,
|
||||||
|
// mergeProps,
|
||||||
|
// options,
|
||||||
|
) => reduxConnect(mapStateToProps, dispatchProps /*, mergeProps, options*/);
|
||||||
|
|
||||||
|
export const useReduxDispatch = () => useDispatch<Dispatch>();
|
||||||
|
export const useReduxSelector = <TSelected>(
|
||||||
|
selector: (state: State) => TSelected,
|
||||||
|
equalityFn?: (left: TSelected, right: TSelected) => boolean,
|
||||||
|
): TSelected => useSelector<State, TSelected>(selector, equalityFn);
|
||||||
|
|
||||||
let lastId = 0;
|
let lastId = 0;
|
||||||
export function uniqueId(prefix: string = 'id'): string {
|
export function uniqueId(prefix: string = 'id'): string {
|
||||||
return `${prefix}${++lastId}`;
|
return `${prefix}${++lastId}`;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import React, { ComponentType, ReactNode, useCallback, useState } from 'react';
|
import React, { ComponentType, ReactNode, useCallback, useState } from 'react';
|
||||||
import { Route, Switch, Redirect, RouteComponentProps } from 'react-router-dom';
|
import { Route, Switch, Redirect, RouteComponentProps } from 'react-router-dom';
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
|
|
||||||
import AppInfo from 'app/components/auth/appInfo/AppInfo';
|
import AppInfo from 'app/components/auth/appInfo/AppInfo';
|
||||||
import PanelTransition from 'app/components/auth/PanelTransition';
|
import PanelTransition from 'app/components/auth/PanelTransition';
|
||||||
@ -17,7 +16,7 @@ import RecoverPassword from 'app/components/auth/recoverPassword/RecoverPassword
|
|||||||
import Mfa from 'app/components/auth/mfa/Mfa';
|
import Mfa from 'app/components/auth/mfa/Mfa';
|
||||||
import Finish from 'app/components/auth/finish/Finish';
|
import Finish from 'app/components/auth/finish/Finish';
|
||||||
|
|
||||||
import { RootState } from 'app/reducers';
|
import { useReduxSelector } from 'app/functions';
|
||||||
import { Factory } from 'app/components/auth/factory';
|
import { Factory } from 'app/components/auth/factory';
|
||||||
|
|
||||||
import styles from './auth.scss';
|
import styles from './auth.scss';
|
||||||
@ -30,7 +29,7 @@ let isSidebarHiddenCache = false;
|
|||||||
|
|
||||||
const AuthPage: ComponentType = () => {
|
const AuthPage: ComponentType = () => {
|
||||||
const [isSidebarHidden, setIsSidebarHidden] = useState<boolean>(isSidebarHiddenCache);
|
const [isSidebarHidden, setIsSidebarHidden] = useState<boolean>(isSidebarHiddenCache);
|
||||||
const client = useSelector((state: RootState) => state.auth.client);
|
const client = useReduxSelector((state) => state.auth.client);
|
||||||
|
|
||||||
const goToAuth = useCallback(() => {
|
const goToAuth = useCallback(() => {
|
||||||
isSidebarHiddenCache = true;
|
isSidebarHiddenCache = true;
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { RouteComponentProps } from 'react-router-dom';
|
import { RouteComponentProps } from 'react-router-dom';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
import { connect } from 'app/functions';
|
||||||
import { fetchAvailableApps, resetApp, deleteApp } from 'app/components/dev/apps/actions';
|
import { fetchAvailableApps, resetApp, deleteApp } from 'app/components/dev/apps/actions';
|
||||||
import ApplicationsIndex from 'app/components/dev/apps/ApplicationsIndex';
|
import ApplicationsIndex from 'app/components/dev/apps/ApplicationsIndex';
|
||||||
import { User } from 'app/components/user';
|
import { User } from 'app/components/user';
|
||||||
import { OauthAppResponse } from 'app/services/api/oauth';
|
import { OauthAppResponse } from 'app/services/api/oauth';
|
||||||
import { RootState } from 'app/reducers';
|
|
||||||
|
|
||||||
interface Props extends RouteComponentProps {
|
interface Props extends RouteComponentProps {
|
||||||
user: User;
|
user: User;
|
||||||
@ -75,7 +75,7 @@ class ApplicationsListPage extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
(state: RootState) => ({
|
(state) => ({
|
||||||
user: state.user,
|
user: state.user,
|
||||||
apps: state.apps.available,
|
apps: state.apps.available,
|
||||||
}),
|
}),
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import logger from 'app/services/logger';
|
|
||||||
import { RouteComponentProps } from 'react-router';
|
import { RouteComponentProps } from 'react-router';
|
||||||
|
|
||||||
|
import logger from 'app/services/logger';
|
||||||
|
import { connect } from 'app/functions';
|
||||||
import { FormModel } from 'app/components/ui/form';
|
import { FormModel } from 'app/components/ui/form';
|
||||||
import { browserHistory } from 'app/services/history';
|
import { browserHistory } from 'app/services/history';
|
||||||
import oauth from 'app/services/api/oauth';
|
import oauth from 'app/services/api/oauth';
|
||||||
@ -10,7 +11,6 @@ import PageNotFound from 'app/pages/404/PageNotFound';
|
|||||||
import { getApp, fetchApp as fetchAppAction } from 'app/components/dev/apps/actions';
|
import { getApp, fetchApp as fetchAppAction } from 'app/components/dev/apps/actions';
|
||||||
import ApplicationForm from 'app/components/dev/apps/applicationForm/ApplicationForm';
|
import ApplicationForm from 'app/components/dev/apps/applicationForm/ApplicationForm';
|
||||||
import { OauthAppResponse } from 'app/services/api/oauth';
|
import { OauthAppResponse } from 'app/services/api/oauth';
|
||||||
import { RootState } from 'app/reducers';
|
|
||||||
|
|
||||||
type OwnProps = RouteComponentProps<{
|
type OwnProps = RouteComponentProps<{
|
||||||
clientId: string;
|
clientId: string;
|
||||||
@ -100,7 +100,7 @@ class UpdateApplicationPage extends React.Component<
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
(state: RootState, props: OwnProps) => ({
|
(state, props: OwnProps) => ({
|
||||||
app: getApp(state, props.match.params.clientId),
|
app: getApp(state, props.match.params.clientId),
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { RouteComponentProps, Redirect } from 'react-router-dom';
|
import { RouteComponentProps, Redirect } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { connect } from 'app/functions';
|
||||||
import FormModel from 'app/components/ui/form/FormModel';
|
import FormModel from 'app/components/ui/form/FormModel';
|
||||||
import ChangeEmail, { ChangeEmailStep } from 'app/components/profile/changeEmail/ChangeEmail';
|
import ChangeEmail, { ChangeEmailStep } from 'app/components/profile/changeEmail/ChangeEmail';
|
||||||
import { requestEmailChange, setNewEmail, confirmNewEmail } from 'app/services/api/accounts';
|
import { requestEmailChange, setNewEmail, confirmNewEmail } from 'app/services/api/accounts';
|
||||||
import { RootState } from 'app/reducers';
|
|
||||||
import Context from 'app/components/profile/Context';
|
import Context from 'app/components/profile/Context';
|
||||||
|
|
||||||
interface RouteParams {
|
interface RouteParams {
|
||||||
@ -92,6 +92,6 @@ function handleErrors(repeatUrl?: string): <T extends { errors: Record<string, a
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect((state: RootState) => ({
|
export default connect((state) => ({
|
||||||
email: state.user.email,
|
email: state.user.email,
|
||||||
}))(ChangeEmailPage);
|
}))(ChangeEmailPage);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
import { connect } from 'app/functions';
|
||||||
import { changePassword } from 'app/services/api/accounts';
|
import { changePassword } from 'app/services/api/accounts';
|
||||||
import { FormModel } from 'app/components/ui/form';
|
import { FormModel } from 'app/components/ui/form';
|
||||||
import ChangePassword from 'app/components/profile/changePassword/ChangePassword';
|
import ChangePassword from 'app/components/profile/changePassword/ChangePassword';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
import { connect } from 'app/functions';
|
||||||
import { updateUser } from 'app/components/user/actions';
|
import { updateUser } from 'app/components/user/actions';
|
||||||
import { RootState } from 'app/reducers';
|
|
||||||
import { changeUsername } from 'app/services/api/accounts';
|
import { changeUsername } from 'app/services/api/accounts';
|
||||||
import { FormModel } from 'app/components/ui/form';
|
import { FormModel } from 'app/components/ui/form';
|
||||||
import ChangeUsername from 'app/components/profile/changeUsername/ChangeUsername';
|
import ChangeUsername from 'app/components/profile/changeUsername/ChangeUsername';
|
||||||
@ -66,7 +66,7 @@ class ChangeUsernamePage extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
(state: RootState) => ({
|
(state) => ({
|
||||||
username: state.user.username,
|
username: state.user.username,
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { RouteComponentProps, Redirect } from 'react-router-dom';
|
import { RouteComponentProps, Redirect } from 'react-router-dom';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
import { connect } from 'app/functions';
|
||||||
import MultiFactorAuth, { MfaStep } from 'app/components/profile/multiFactorAuth';
|
import MultiFactorAuth, { MfaStep } from 'app/components/profile/multiFactorAuth';
|
||||||
import { FormModel } from 'app/components/ui/form';
|
import { FormModel } from 'app/components/ui/form';
|
||||||
import { User } from 'app/components/user';
|
import { User } from 'app/components/user';
|
||||||
import { RootState } from 'app/reducers';
|
|
||||||
import Context from 'app/components/profile/Context';
|
import Context from 'app/components/profile/Context';
|
||||||
|
|
||||||
interface Props
|
interface Props
|
||||||
@ -74,4 +74,4 @@ class MultiFactorAuthPage extends React.Component<Props> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(({ user }: RootState) => ({ user }))(MultiFactorAuthPage);
|
export default connect(({ user }) => ({ user }))(MultiFactorAuthPage);
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React, { ComponentType, useCallback } from 'react';
|
import React, { ComponentType, useCallback } from 'react';
|
||||||
import { Route, Switch, Redirect } from 'react-router-dom';
|
import { Route, Switch, Redirect } from 'react-router-dom';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
|
import { connect } from 'app/functions';
|
||||||
|
import { Dispatch } from 'app/types';
|
||||||
import { refreshUserData } from 'app/components/accounts/actions';
|
import { refreshUserData } from 'app/components/accounts/actions';
|
||||||
import { create as createPopup } from 'app/components/ui/popup/actions';
|
import { create as createPopup } from 'app/components/ui/popup/actions';
|
||||||
import PasswordRequestForm from 'app/components/profile/passwordRequestForm';
|
import PasswordRequestForm from 'app/components/profile/passwordRequestForm';
|
||||||
@ -9,7 +10,6 @@ import logger from 'app/services/logger';
|
|||||||
import { browserHistory } from 'app/services/history';
|
import { browserHistory } from 'app/services/history';
|
||||||
import { FooterMenu } from 'app/components/footerMenu';
|
import { FooterMenu } from 'app/components/footerMenu';
|
||||||
import { FormModel } from 'app/components/ui/form';
|
import { FormModel } from 'app/components/ui/form';
|
||||||
import { Dispatch, RootState } from 'app/reducers';
|
|
||||||
import { Provider } from 'app/components/profile/Context';
|
import { Provider } from 'app/components/profile/Context';
|
||||||
import { ComponentLoader } from 'app/components/ui/loader';
|
import { ComponentLoader } from 'app/components/ui/loader';
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ const ProfileController: ComponentType<Props> = ({ userId, onSubmit, refreshUser
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
(state: RootState) => ({
|
(state) => ({
|
||||||
userId: state.user.id!,
|
userId: state.user.id!,
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import React, { ComponentType } from 'react';
|
import React, { ComponentType } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
|
|
||||||
import { RootState } from 'app/reducers';
|
import { useReduxSelector } from 'app/functions';
|
||||||
|
|
||||||
import Profile from 'app/components/profile/Profile';
|
import Profile from 'app/components/profile/Profile';
|
||||||
|
|
||||||
const ProfileController: ComponentType = () => {
|
const ProfileController: ComponentType = () => {
|
||||||
const [user, activeLocale] = useSelector((state: RootState) => [state.user, state.i18n.locale]);
|
const [user, activeLocale] = useReduxSelector((state) => [state.user, state.i18n.locale]);
|
||||||
|
|
||||||
return <Profile user={user} activeLocale={activeLocale} />;
|
return <Profile user={user} activeLocale={activeLocale} />;
|
||||||
};
|
};
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { resetAuth } from 'app/components/auth/actions';
|
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { FormattedMessage as Message } from 'react-intl';
|
import { FormattedMessage as Message } from 'react-intl';
|
||||||
import { Route, Link, Switch } from 'react-router-dom';
|
import { Route, Link, Switch } from 'react-router-dom';
|
||||||
import { Helmet } from 'react-helmet-async';
|
import { Helmet } from 'react-helmet-async';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
|
import { connect } from 'app/functions';
|
||||||
|
import { resetAuth } from 'app/components/auth/actions';
|
||||||
import { ScrollIntoView } from 'app/components/ui/scroll';
|
import { ScrollIntoView } from 'app/components/ui/scroll';
|
||||||
import PrivateRoute from 'app/containers/PrivateRoute';
|
import PrivateRoute from 'app/containers/PrivateRoute';
|
||||||
import AuthFlowRoute from 'app/containers/AuthFlowRoute';
|
import AuthFlowRoute from 'app/containers/AuthFlowRoute';
|
||||||
@ -15,7 +16,6 @@ import * as loader from 'app/services/loader';
|
|||||||
import { getActiveAccount } from 'app/components/accounts/reducer';
|
import { getActiveAccount } from 'app/components/accounts/reducer';
|
||||||
import { User } from 'app/components/user';
|
import { User } from 'app/components/user';
|
||||||
import { Account } from 'app/components/accounts/reducer';
|
import { Account } from 'app/components/accounts/reducer';
|
||||||
import { RootState } from 'app/reducers';
|
|
||||||
import { ComponentLoader } from 'app/components/ui/loader';
|
import { ComponentLoader } from 'app/components/ui/loader';
|
||||||
|
|
||||||
import styles from './root.scss';
|
import styles from './root.scss';
|
||||||
@ -113,7 +113,7 @@ class RootPage extends React.PureComponent<{
|
|||||||
|
|
||||||
export default withRouter(
|
export default withRouter(
|
||||||
connect(
|
connect(
|
||||||
(state: RootState) => ({
|
(state) => ({
|
||||||
user: state.user,
|
user: state.user,
|
||||||
account: getActiveAccount(state),
|
account: getActiveAccount(state),
|
||||||
isPopupActive: state.popup.popups.length > 0,
|
isPopupActive: state.popup.popups.length > 0,
|
||||||
|
@ -1,37 +1,16 @@
|
|||||||
import { combineReducers } from 'redux';
|
import { combineReducers } from 'redux';
|
||||||
|
|
||||||
import auth, { State as AuthState } from 'app/components/auth/reducer';
|
import auth from 'app/components/auth/reducer';
|
||||||
import user, { State as UserState } from 'app/components/user/reducer';
|
import user from 'app/components/user/reducer';
|
||||||
import accounts, { State as AccountsState } from 'app/components/accounts/reducer';
|
import accounts from 'app/components/accounts/reducer';
|
||||||
import i18n, { State as I18nState } from 'app/components/i18n/reducer';
|
import i18n from 'app/components/i18n/reducer';
|
||||||
import popup, { State as PopupState } from 'app/components/ui/popup/reducer';
|
import popup from 'app/components/ui/popup/reducer';
|
||||||
import bsod, { State as BsodState } from 'app/components/ui/bsod/reducer';
|
import bsod from 'app/components/ui/bsod/reducer';
|
||||||
import apps, { Apps } from 'app/components/dev/apps/reducer';
|
import apps from 'app/components/dev/apps/reducer';
|
||||||
import { ThunkDispatch, ThunkAction as ReduxThunkAction } from 'redux-thunk';
|
|
||||||
import { Store as ReduxStore } from 'redux';
|
|
||||||
|
|
||||||
export interface RootState {
|
import { State } from 'app/types';
|
||||||
auth: AuthState;
|
|
||||||
bsod: BsodState;
|
|
||||||
accounts: AccountsState;
|
|
||||||
user: UserState;
|
|
||||||
popup: PopupState;
|
|
||||||
apps: Apps;
|
|
||||||
i18n: I18nState;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Action<T = any> {
|
export default combineReducers<State>({
|
||||||
type: string;
|
|
||||||
payload?: T;
|
|
||||||
}
|
|
||||||
export type Dispatch<T extends Action = Action> = ThunkDispatch<RootState, undefined, T>;
|
|
||||||
export type GetState = () => RootState;
|
|
||||||
export type ThunkAction<T = any> = ReduxThunkAction<T, RootState, undefined, Action>;
|
|
||||||
export type Store = ReduxStore<RootState> & {
|
|
||||||
dispatch: Dispatch;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default combineReducers<RootState>({
|
|
||||||
bsod,
|
bsod,
|
||||||
auth,
|
auth,
|
||||||
user,
|
user,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { browserHistory } from 'app/services/history';
|
import { browserHistory } from 'app/services/history';
|
||||||
import logger from 'app/services/logger';
|
import logger from 'app/services/logger';
|
||||||
import localStorage from 'app/services/localStorage';
|
import localStorage from 'app/services/localStorage';
|
||||||
import { RootState, Store } from 'app/reducers';
|
import { Store, State as RootState } from 'app/types';
|
||||||
|
|
||||||
import RegisterState from './RegisterState';
|
import RegisterState from './RegisterState';
|
||||||
import LoginState from './LoginState';
|
import LoginState from './LoginState';
|
||||||
|
@ -2,7 +2,7 @@ import { hot } from 'react-hot-loader/root';
|
|||||||
import React, { ComponentType } from 'react';
|
import React, { ComponentType } from 'react';
|
||||||
import { Route, Switch } from 'react-router-dom';
|
import { Route, Switch } from 'react-router-dom';
|
||||||
|
|
||||||
import { Store } from 'app/reducers';
|
import { Store } from 'app/types';
|
||||||
import AuthFlowRoute from 'app/containers/AuthFlowRoute';
|
import AuthFlowRoute from 'app/containers/AuthFlowRoute';
|
||||||
import RootPage from 'app/pages/root/RootPage';
|
import RootPage from 'app/pages/root/RootPage';
|
||||||
import { ComponentLoader } from 'app/components/ui/loader';
|
import { ComponentLoader } from 'app/components/ui/loader';
|
||||||
|
@ -5,7 +5,7 @@ import { HelmetProvider } from 'react-helmet-async';
|
|||||||
import { History } from 'history';
|
import { History } from 'history';
|
||||||
|
|
||||||
import { IntlProvider } from 'app/components/i18n';
|
import { IntlProvider } from 'app/components/i18n';
|
||||||
import { Store } from 'app/reducers';
|
import { Store } from 'app/types';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
@ -3,7 +3,7 @@ import { createMemoryHistory } from 'history';
|
|||||||
import { DeepPartial } from 'utility-types';
|
import { DeepPartial } from 'utility-types';
|
||||||
|
|
||||||
import storeFactory from 'app/storeFactory';
|
import storeFactory from 'app/storeFactory';
|
||||||
import { RootState } from 'app/reducers';
|
import { State as RootState } from 'app/types';
|
||||||
|
|
||||||
import ContextProvider from './ContextProvider';
|
import ContextProvider from './ContextProvider';
|
||||||
|
|
||||||
|
@ -6,7 +6,8 @@ import { createStore, applyMiddleware, compose, StoreEnhancer } from 'redux';
|
|||||||
import thunk from 'redux-thunk';
|
import thunk from 'redux-thunk';
|
||||||
import persistState from 'redux-localstorage';
|
import persistState from 'redux-localstorage';
|
||||||
|
|
||||||
import reducers, { Store } from 'app/reducers';
|
import reducers from 'app/reducers';
|
||||||
|
import { Store } from 'app/types';
|
||||||
|
|
||||||
export default function storeFactory(preloadedState = {}): Store {
|
export default function storeFactory(preloadedState = {}): Store {
|
||||||
const middlewares = applyMiddleware(thunk);
|
const middlewares = applyMiddleware(thunk);
|
||||||
|
41
packages/app/types.ts
Normal file
41
packages/app/types.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { Store as ReduxStore } from 'redux';
|
||||||
|
import { ThunkAction, ThunkDispatch } from 'redux-thunk';
|
||||||
|
|
||||||
|
import { Action as AuthActions } from 'app/components/auth/actions';
|
||||||
|
import { State as AuthState } from 'app/components/auth/reducer';
|
||||||
|
|
||||||
|
import { Action as BsodActions } from 'app/components/ui/bsod/actions';
|
||||||
|
import { State as BsodState } from 'app/components/ui/bsod/reducer';
|
||||||
|
|
||||||
|
import { Action as AccountActions } from 'app/components/accounts/actions/pure-actions';
|
||||||
|
import { State as AccountState } from 'app/components/accounts/reducer';
|
||||||
|
|
||||||
|
import { Action as UserActions } from 'app/components/user/actions';
|
||||||
|
import { State as UserState } from 'app/components/user/reducer';
|
||||||
|
|
||||||
|
import { Action as PopupActions } from 'app/components/ui/popup/actions';
|
||||||
|
import { State as PopupState } from 'app/components/ui/popup/reducer';
|
||||||
|
|
||||||
|
import { Action as AppsActions } from 'app/components/dev/apps/actions';
|
||||||
|
import { State as AppsState } from 'app/components/dev/apps/reducer';
|
||||||
|
|
||||||
|
import { Action as I18nActions } from 'app/components/i18n/actions';
|
||||||
|
import { State as I18nState } from 'app/components/i18n/reducer';
|
||||||
|
|
||||||
|
type PureActions = AuthActions | BsodActions | AccountActions | UserActions | PopupActions | AppsActions | I18nActions;
|
||||||
|
|
||||||
|
export interface State {
|
||||||
|
readonly auth: AuthState;
|
||||||
|
readonly bsod: BsodState;
|
||||||
|
readonly accounts: AccountState;
|
||||||
|
readonly user: UserState;
|
||||||
|
readonly popup: PopupState;
|
||||||
|
readonly apps: AppsState;
|
||||||
|
readonly i18n: I18nState;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Action<R = void, S = State> = ThunkAction<R, S, undefined, PureActions>;
|
||||||
|
export type Dispatch = ThunkDispatch<State, undefined, PureActions>;
|
||||||
|
export interface Store extends ReduxStore<State, PureActions> {
|
||||||
|
dispatch: Dispatch;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user