Commit 5596f48e authored by Viacheslav Pavlov's avatar Viacheslav Pavlov

Fixed SSR, replaced all User admin logic to saga usage

parent bd3c77b8
import { END } from 'redux-saga';
export default function fetchComponentData(dispatch, branch, search, state = null) {
const promisesWithProps = [];
......@@ -19,5 +21,5 @@ export default function fetchComponentData(dispatch, branch, search, state = nul
.forEach((promise) => promisesWithProps.push(promise));
});
return Promise.all(promisesWithProps);
return Promise.all(promisesWithProps).then(() => dispatch(END));
}
......@@ -12,6 +12,7 @@ import { routerMiddleware } from 'connected-react-router';
import { createStore, applyMiddleware } from 'redux';
import { I18nextProvider } from 'react-i18next';
import thunk from 'redux-thunk';
import createSagaMiddleware from 'redux-saga'
import rootReducer from 'reducers';
import languages from 'data/Languages';
......@@ -32,6 +33,7 @@ import config from '../config';
import checkAuthToken from './checkAuthToken';
import { configure, receiveLang } from 'actions/applicationConfig';
import ApiError from 'model/ApiError';
import sagas from 'actions/saga';
// react-loadable webpack stats
import * as path from 'path';
......@@ -48,10 +50,12 @@ const prerenderer = (html, errHtml) => (req, res) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'X-Requested-With');
const his = createMemoryHistory();
const sagaMiddleware = createSagaMiddleware();
const store = createStore(rootReducer(), {} as any, applyMiddleware(thunk, routerMiddleware(his)));
const store = createStore(rootReducer(), {} as any, applyMiddleware(thunk, sagaMiddleware, routerMiddleware(his)));
// Only send public data to client
store.dispatch(configure({ frontendPath: config.frontendPath, apiUrl: config.apiUrl, googleClientId: config.googleClientId, clientId: config.clientId, anonToken: config.access_token }));
const sagaReady = sagaMiddleware.run(sagas);
if (!isServerStorageLoaded()) {
const errFilledHtml = makeErrorHtml(errHtml, {status: '503 Service temporary unavailable ', data: 'Waiting for Genesys server to be available'});
......@@ -181,8 +185,10 @@ const prerenderer = (html, errHtml) => (req, res) => {
// res.status(500).set('Content-Type', 'text/html').send(errFilledHtml);
})
.then(() => {
console.log('Fetched all component data');
return renderView();
return sagaReady.toPromise().then(() => {
console.log('Fetched all component data');
return renderView();
});
}).then((html) => {
const serverRenderTime = `${Date.now() - startTime}ms`;
console.log('Server render time:', startTime, Date.now(), serverRenderTime);
......
import axios from 'axios';
import { put, call, fork, cancel, cancelled } from 'redux-saga/effects'
// actions
import {showSnackbar} from 'actions/snackbar';
// model
......@@ -132,49 +130,13 @@ export const createPureApiCaller = (method, config: {direct?: boolean, withoutTi
};
export const createSagaApiCaller = (serviceMethod, action) => {
let cancelToken;
let apiCall;
function* sagaApiCaller(params, xhrConfig) {
try {
yield put({type: action, payload: {apiCall: ApiCall.start()}});
const data = yield call(serviceMethod, ...ensureParamsAmount(serviceMethod, params), xhrConfig);
yield put({type: action, payload: {apiCall: ApiCall.success(data)}});
return Promise.resolve(data);
} finally {
if (yield cancelled()) {
console.log(`Previous call was canceled`);
cancelToken.cancel(); // Cancel previous
}
apiCall = null;
}
}
return function* (sagaAction) {
if (apiCall) {
yield cancel(apiCall);
}
cancelToken = axios.CancelToken.source();
const xhrConfig: any = {
cancelToken: cancelToken && cancelToken.token,
};
apiCall = yield fork(sagaApiCaller, sagaAction.params, xhrConfig);
}
};
/**
* Add undefined values to params to fit method signature.
*
* @param method
* @param params
*/
const ensureParamsAmount = (method, params) => {
export const ensureParamsAmount = (method, params) => {
const paramAmount = method.length;
if (paramAmount < params.length) {
......
import axios from 'axios';
import {all, call, cancel, cancelled, fork, put} from 'redux-saga/effects';
// actions
import {ensureParamsAmount} from 'actions/ApiCall';
// model
import ApiCall from 'model/ApiCall';
import OpResponse from 'model/OpResponse';
export const createSagaApiCaller = (serviceMethod, action?) => {
let cancelToken;
let apiCall;
function* sagaApiCaller(params, xhrConfig, thenAction) {
try {
yield action && put({type: action, payload: {apiCall: ApiCall.start()}});
const data = yield call(serviceMethod, ...ensureParamsAmount(serviceMethod, params), xhrConfig);
yield action && put({type: action, payload: {apiCall: ApiCall.success(data)}});
if (thenAction) {
thenAction(data);
}
} finally {
if (yield cancelled()) {
console.log(`Previous call was canceled`);
cancelToken.cancel(); // Cancel previous
}
apiCall = null;
}
}
return function* (sagaAction) {
if (apiCall) {
yield cancel(apiCall);
}
cancelToken = axios.CancelToken.source();
const xhrConfig: any = {
cancelToken: cancelToken && cancelToken.token,
};
apiCall = yield fork(sagaApiCaller, sagaAction.params, xhrConfig, sagaAction.then);
};
};
export const createOpResponseApiCaller = (serviceMethod, action?) => {
let cancelToken;
let apiCall;
function* sagaApiCaller(params, xhrConfig, handleSuccess, handleError) {
try {
yield action && put({type: action, payload: {apiCall: ApiCall.start()}});
const data: OpResponse<any>[] = yield call(serviceMethod, ...ensureParamsAmount(serviceMethod, params), xhrConfig);
yield action && all(data.map( // TODO add some onSuccess/onError handle
(opResponse) => put({
type: action,
payload: {apiCall: opResponse.success ? ApiCall.success(opResponse.success) : ApiCall.error(opResponse.error)},
},
),
));
if (handleSuccess) {
handleSuccess(data);
}
} catch (e) {
console.log('Error has happen: ', e);
if (handleError) {
handleError(e);
}
} finally {
if (yield cancelled()) {
console.log(`Previous call was canceled`);
cancelToken.cancel(); // Cancel axios request
}
apiCall = null;
}
}
return function* (sagaAction) {
if (apiCall) {
yield cancel(apiCall);
}
cancelToken = axios.CancelToken.source();
const xhrConfig: any = {
cancelToken: cancelToken && cancelToken.token,
};
apiCall = yield fork(sagaApiCaller, sagaAction.params, xhrConfig, sagaAction.onSuccess, sagaAction.onError);
}
};
import { all } from 'redux-saga/effects';
import { all, takeEvery } from 'redux-saga/effects';
import {userAdminSagas} from 'user/actions/admin';
export default function*() {
yield all([
process.env.NODE_ENV === 'development' ? takeEvery((action) => /^api\//.test(action.type), logApi) : {},
...userAdminSagas,
]);
}
function* logApi(action) {
console.log('Api call to ', action.type);
console.log('Params: ', action.params);
// const state = yield select();
// console.log('State after', state);
}
......@@ -5,21 +5,23 @@ import { User } from 'model/user/User';
import * as QueryString from 'query-string';
import UserFilter from 'model/UserFilter';
import FilteredPage, {IPageRequest} from 'model/FilteredPage';
import UUIDandVersion from 'model/UUIDandVersion';
import OpResponse from 'model/OpResponse';
const REGISTER_URL = `/api/v1/user/register`;
const GET_USER_PROFILE_URL = `/api/v1/me/profile`;
const CHANGE_USER_PASSWORD_URL = `/api/v1/me/password`;
const URL_VALIDATE_E_MAIL = UrlTemplate.parse(`/api/v1/user/{tokenUuid}/validate`);
const URL_LIST_USERS = `/api/v1/user/list`;
const URL_GET_USER = UrlTemplate.parse(`/api/v1/user/u/{uuid}`);
const URL_DISABLE_ACCOUNT = UrlTemplate.parse(`/api/v1/user/u/{uuid}/disable`);
const URL_ENABLE_ACCOUNT = UrlTemplate.parse(`/api/v1/user/u/{uuid}/enable`);
const URL_LOCK_ACCOUNT = UrlTemplate.parse(`/api/v1/user/u/{uuid}/lock`);
const URL_LIST_USERS = `/api/v2/user/list`;
const URL_GET_USER = UrlTemplate.parse(`/api/v2/user/u/{uuid}`);
const URL_DISABLE_ACCOUNTS = `/api/v2/user/u/disable`;
const URL_ENABLE_ACCOUNTS = `/api/v2/user/u/enable`;
const URL_LOCK_ACCOUNTS = `/api/v2/user/u/lock`;
const URL_UNLOCK_ACCOUNTS = `/api/v2/user/u/unlock`;
const URL_GENERATE_FTP_PASSWORD = UrlTemplate.parse(`/api/v1/user/u/{uuid}/ftp-password`);
const URL_UNLOCK_ACCOUNT = UrlTemplate.parse(`/api/v1/user/u/{uuid}/unlock`);
const URL_ARCHIVE_ACCOUNT = UrlTemplate.parse(`/api/v1/user/u/{uuid}/archive`);
const URL_SEND_EMAIL = UrlTemplate.parse(`/api/v1/user/u/{uuid}/email-verification`);
const URL_UPDATE_USER = `/api/v1/user/user`;
const URL_ARCHIVE_ACCOUNTS = `/api/v2/user/u/archive`;
const URL_SEND_EMAILS = `/api/v2/user/u/email-verification`;
const URL_UPDATE_USERS = `/api/v2/user/update`;
export class UserService {
......@@ -87,7 +89,7 @@ export class UserService {
/**
* listUsers at /api/v1/user/list
* listUsers at /api/v2/user/list
*
* @param filter the user filter
* @param page the page
......@@ -147,128 +149,142 @@ export class UserService {
}
/**
* disableAccount at /api/v1/user/u/{uuid}/disable
* disableAccounts at /api/v2/user/u/disable
*
* @param uuid uuid
* @param entities entities
* @param xhrConfig additional xhr config
*/
public static disableAccount(uuid: string, xhrConfig?): Promise<User> {
public static disableAccounts(entities: UUIDandVersion[], xhrConfig?: any): Promise<OpResponse<User>[]> {
const apiUrl = URL_DISABLE_ACCOUNT.expand({uuid});
const content = { /* No content in request body */ };
const apiUrl = URL_DISABLE_ACCOUNTS;
// console.log(`Fetching from ${apiUrl}`);
const content = { data: entities };
return axiosBackend({
return axiosBackend.request({
...xhrConfig,
url: apiUrl,
method: 'POST',
...content,
}).then(({ data }) => data as User);
}).then(({ data }) => data as OpResponse<User>[]);
}
/**
* enableAccount at /api/v1/user/u/{uuid}/enable
* enableAccounts at /api/v2/user/u/enable
*
* @param uuid uuid
* @param entities entities
* @param xhrConfig additional xhr config
*/
public static enableAccount(uuid: string, xhrConfig?): Promise<User> {
public static enableAccounts(entities: UUIDandVersion[], xhrConfig?: any): Promise<OpResponse<User>[]> {
const apiUrl = URL_ENABLE_ACCOUNT.expand({uuid});
const content = { /* No content in request body */ };
const apiUrl = URL_ENABLE_ACCOUNTS;
// console.log(`Fetching from ${apiUrl}`);
const content = { data: entities };
return axiosBackend({
return axiosBackend.request({
...xhrConfig,
url: apiUrl,
method: 'POST',
...content,
}).then(({ data }) => data as User);
}).then(({ data }) => data as OpResponse<User>[]);
}
/**
* lockAccount at /api/v1/user/u/{uuid}/lock
* lockAccounts at /api/v2/user/u/lock
*
* @param uuid uuid
* @param entities entities
* @param xhrConfig additional xhr config
*/
public static lockAccount(uuid: string, xhrConfig?): Promise<User> {
public static lockAccounts(entities: UUIDandVersion[], xhrConfig?: any): Promise<OpResponse<User>[]> {
const apiUrl = URL_LOCK_ACCOUNT.expand({uuid});
const content = { /* No content in request body */ };
const apiUrl = URL_LOCK_ACCOUNTS;
// console.log(`Fetching from ${apiUrl}`);
const content = {data: entities};
return axiosBackend({
return axiosBackend.request({
...xhrConfig,
url: apiUrl,
method: 'POST',
...content,
}).then(({ data }) => data as User);
}).then(({data}) => data as OpResponse<User>[]);
}
/**
* unlockAccount at /api/v1/user/u/{uuid}/unlock
* unlockAccounts at /api/v2/user/u/unlock
*
* @param uuid uuid
* @param entities entities
* @param xhrConfig additional xhr config
*/
public static unlockAccount(uuid: string, xhrConfig?): Promise<User> {
public static unlockAccounts(entities: UUIDandVersion[], xhrConfig?: any): Promise<OpResponse<User>[]> {
const apiUrl = URL_UNLOCK_ACCOUNT.expand({uuid});
const content = { /* No content in request body */ };
const apiUrl = URL_UNLOCK_ACCOUNTS;
// console.log(`Fetching from ${apiUrl}`);
const content = {data: entities};
return axiosBackend({
return axiosBackend.request({
...xhrConfig,
url: apiUrl,
method: 'POST',
...content,
}).then(({ data }) => data as User);
}).then(({data}) => data as OpResponse<User>[]);
}
/**
* archiveAccount at /api/v1/user/u/{uuid}/archive
* archiveAccounts at /api/v2/user/u/archive
*
* @param uuid uuid
* @param entities entities
* @param xhrConfig additional xhr config
*/
public static archiveAccount(uuid: string, xhrConfig?): Promise<User> {
public static archiveAccounts(entities: UUIDandVersion[], xhrConfig?: any): Promise<OpResponse<User>[]> {
const apiUrl = URL_ARCHIVE_ACCOUNT.expand({uuid});
const content = { /* No content in request body */ };
const apiUrl = URL_ARCHIVE_ACCOUNTS;
// console.log(`Fetching from ${apiUrl}`);
const content = {data: entities};
return axiosBackend({
return axiosBackend.request({
...xhrConfig,
url: apiUrl,
method: 'POST',
...content,
}).then(({ data }) => data as User);
}).then(({data}) => data as OpResponse<User>[]);
}
/**
* sendEmail at /api/v1/user/u/{uuid}/email-verification
* sendEmails at /api/v2/user/u/email-verification
*
* @param uuid uuid
* @param uuids uuids
* @param xhrConfig additional xhr config
*/
public static sendEmail(uuid: string, xhrConfig?): Promise<boolean> {
public static sendEmails(uuids: string[], xhrConfig?: any): Promise<OpResponse<boolean>[]> {
const apiUrl = URL_SEND_EMAIL.expand({uuid});
const content = { /* No content in request body */ };
const apiUrl = URL_SEND_EMAILS;
// console.log(`Fetching from ${apiUrl}`);
const content = {data: uuids};
return axiosBackend({
return axiosBackend.request({
...xhrConfig,
url: apiUrl,
method: 'POST',
...content,
}).then(({ data }) => data as boolean);
}).then(({data}) => data as OpResponse<boolean>[]);
}
/**
* updateUser at /api/v1/user/user
* updateUsers at /api/v2/user/update
*
* @param user user
* @param users users
* @param xhrConfig additional xhr config
*/
public static updateUser(user: User, xhrConfig?): Promise<User> {
public static updateUsers(users: User[], xhrConfig?: any): Promise<OpResponse<User>[]> {
const apiUrl = URL_UPDATE_USER;
const content = { data: user };
const apiUrl = URL_UPDATE_USERS;
// console.log(`Fetching from ${apiUrl}`);
const content = {data: users};
return axiosBackend({
return axiosBackend.request({
...xhrConfig,
url: apiUrl,
method: 'PUT',
...content,
}).then(({ data }) => data as User);
}).then(({data}) => data as OpResponse<User>[]);
}
}
......@@ -12,24 +12,27 @@ import {
ADMIN_RECEIVE_OAUTH_CLIENT_DETAILS,
ADMIN_RECEIVE_USER,
ADMIN_REMOVE_OAUTH_CLIENT,
ADMIN_TOGGLE_USER_MODAL,
ADMIN_TOGGLE_USER_MODAL, API_ADMIN_ARCHIVE_USERS,
API_ADMIN_DISABLE_USERS,
API_ADMIN_ENABLE_USERS,
API_ADMIN_GET_USER,
API_ADMIN_LIST_USERS,
API_ADMIN_LOCK_USERS,
API_ADMIN_SEND_EMAILS,
API_ADMIN_UNLOCK_USERS,
API_ADMIN_UPDATE_USERS,
} from 'user/constants';
import { showSnackbar } from 'actions/snackbar';
import navigateTo from 'actions/navigation';
import {filterCodeToUrl} from 'actions/filterCode';
import {createApiCaller, createPureApiCaller, createSagaApiCaller} from 'actions/ApiCall';
import {createApiCaller, createPureApiCaller} from 'actions/ApiCall';
import {createSagaApiCaller, createOpResponseApiCaller} from 'actions/SagaApiCall';
import UserFilter from 'model/UserFilter';
import Page from 'model/Page';
import OAuthClient from 'model/oauth/OAuthClient';
import ApiCall from 'model/ApiCall';
// Wrapped API Calls
const apiLoadUser = createApiCaller(UserService.getUser, ADMIN_RECEIVE_USER);
const apiLockAccount = createApiCaller(UserService.lockAccount, ADMIN_RECEIVE_USER);
const apiUnlockAccount = createApiCaller(UserService.unlockAccount, ADMIN_RECEIVE_USER);
const apiArchiveAccount = createPureApiCaller(UserService.archiveAccount);
const apiSendEmail = createPureApiCaller(UserService.sendEmail);
const apiUpdateUser = createApiCaller(UserService.updateUser, ADMIN_RECEIVE_USER);
import UUIDandVersion from 'model/UUIDandVersion';
const apiListOauthClients = createApiCaller(OAuthManagementService.listClients, ADMIN_APPEND_OAUTH_CLIENTS);
const apiLoadOauthClientDetails = createApiCaller(OAuthManagementService.clientDetailsInfo, ADMIN_RECEIVE_OAUTH_CLIENT_DETAILS);
......@@ -39,61 +42,87 @@ const apiGenerateClientSecret = createPureApiCaller(OAuthManagementService.gener
const apiRemoveClientSecret = createPureApiCaller(OAuthManagementService.removeSecret);
export const userAdminSagas = [
takeEvery('apiEnableAccount', createSagaApiCaller(UserService.enableAccount, ADMIN_RECEIVE_USER)),
takeEvery('apiDisableAccount', createSagaApiCaller(UserService.disableAccount, ADMIN_RECEIVE_USER)),
takeEvery('apiListUsers', createSagaApiCaller(UserService.listUsers, ADMIN_APPEND_USERS)),
takeEvery(API_ADMIN_LIST_USERS, createSagaApiCaller(UserService.listUsers, ADMIN_APPEND_USERS)),
takeEvery(API_ADMIN_GET_USER, createSagaApiCaller(UserService.getUser, ADMIN_RECEIVE_USER)),
takeEvery(API_ADMIN_UPDATE_USERS, createOpResponseApiCaller(UserService.updateUsers, ADMIN_RECEIVE_USER)),
takeEvery(API_ADMIN_ENABLE_USERS, createOpResponseApiCaller(UserService.enableAccounts, ADMIN_RECEIVE_USER)),
takeEvery(API_ADMIN_DISABLE_USERS, createOpResponseApiCaller(UserService.disableAccounts, ADMIN_RECEIVE_USER)),
takeEvery(API_ADMIN_LOCK_USERS, createOpResponseApiCaller(UserService.lockAccounts, ADMIN_RECEIVE_USER)),
takeEvery(API_ADMIN_UNLOCK_USERS, createOpResponseApiCaller(UserService.unlockAccounts, ADMIN_RECEIVE_USER)),
takeEvery(API_ADMIN_ARCHIVE_USERS, createOpResponseApiCaller(UserService.archiveAccounts, ADMIN_RECEIVE_USER)),
takeEvery(API_ADMIN_ARCHIVE_USERS, createOpResponseApiCaller(UserService.archiveAccounts, ADMIN_RECEIVE_USER)),
takeEvery(API_ADMIN_SEND_EMAILS, createOpResponseApiCaller(UserService.sendEmails)),
];
const receiveUser = (apiCall: ApiCall<User>) => (dispatch) => {
dispatch({ type: ADMIN_RECEIVE_USER, payload: { apiCall } });
};
export const loadUser = (uuid: string) => (dispatch) => {
return dispatch(apiLoadUser(uuid));
return dispatch({
type: API_ADMIN_GET_USER,
params: [uuid],
});
};
export const enableAccount = (uuid: string, enable: boolean = true) => (dispatch) => {
const updateAccountStatus = enable ? 'apiEnableAccount' : 'apiDisableAccount';
export const enableAccounts = (uuidAndVersions: UUIDandVersion[], enable: boolean = true) => (dispatch) => {
const updateAccountStatus = enable ? API_ADMIN_ENABLE_USERS : API_ADMIN_DISABLE_USERS;
return dispatch({
type: updateAccountStatus,
params: [uuidAndVersions],
onSuccess: (user) => dispatch(showSnackbar(`Account is ${enable ? 'enabled' : 'disabled'}`)),
});
return dispatch({type: updateAccountStatus, params: [uuid] })
.then((user) => dispatch(showSnackbar(`Account is ${enable ? 'enabled' : 'disabled'}`)));
};
export const lockAccount = (uuid: string, lock: boolean = true) => (dispatch) => {
const updateAccountStatus = lock ? apiLockAccount : apiUnlockAccount;
export const lockAccounts = (uuidAndVersions: UUIDandVersion[], lock: boolean = true) => (dispatch) => {
const updateAccountStatus = lock ? API_ADMIN_LOCK_USERS : API_ADMIN_UNLOCK_USERS;
return dispatch(updateAccountStatus(uuid))
.then((user) => dispatch(showSnackbar(`Account is ${lock ? 'locked' : 'unlocked'}`)));
return dispatch({
type: updateAccountStatus,
params: [uuidAndVersions],
onSuccess: (user) => dispatch(showSnackbar(`Account is ${lock ? 'locked' : 'unlocked'}`)),
});
};
export const deleteAccount = (uuid: string) => (dispatch) => {
return dispatch(apiArchiveAccount(uuid))
.then((user) => {
dispatch(receiveUser(ApiCall.success(user)));
dispatch(showSnackbar(`Account is deleted`));
});
export const deleteAccounts = (uuidAndVersions: UUIDandVersion[]) => (dispatch) => {
return dispatch({
type: API_ADMIN_ARCHIVE_USERS,
params: [uuidAndVersions],
onSuccess: (user) => dispatch(showSnackbar(`Account is deleted`)),
});
};
export const sendVerificationEmail = (uuid: string) => (dispatch) => {
return dispatch(apiSendEmail(uuid))
.then(() => dispatch(showSnackbar(`Email is sent`)));
export const sendVerificationEmails = (uuids: string[]) => (dispatch) => {
return dispatch({
type: API_ADMIN_SEND_EMAILS,
params: [uuids],
onSuccess: () => dispatch(showSnackbar(`Email is sent`)),
});
};
export const updateUser = (user: User) => (dispatch) => {
return dispatch(apiUpdateUser(user))
.then((updatedUser) => dispatch(navigateTo(`/admin/users/${updatedUser.uuid}`)));
export const updateUsers = (users: User[]) => (dispatch) => {
return dispatch({
type: API_ADMIN_UPDATE_USERS,
params: users,
onSuccess: (updatedUser) => dispatch(navigateTo(`/admin/users/${updatedUser.uuid}`)),
});
};
export const applyFilters = (filters: string | UserFilter, page: IPageRequest = { page: 0 }) => (dispatch) => {
console.log('Applying new filter', filters, page);
dispatch(navigateTo('/admin/users'));
return dispatch({type: 'apiListUsers', params: [filters, page]});
// .then((paged) => dispatch(updateRoute(paged))); TODO
return dispatch({
type: API_ADMIN_LIST_USERS,
params: [filters, page],
onSuccess: (paged) => dispatch(updateRoute(paged)),
});
};
export const loadMoreUsers = (paged?: FilteredPage<User>) => (dispatch) => {
return dispatch({type: 'apiListUsers', params: [paged ? paged.filterCode : '', Page.nextPage(paged)]});
// .then((paged) => dispatch(updateRoute(paged))); TODO
return dispatch({
type: API_ADMIN_LIST_USERS,
params: [paged ? paged.filterCode : '', Page.nextPage(paged)],
onSuccess: (paged) => dispatch(updateRoute(paged)),
});
};
export const updateRoute = (paged: FilteredPage<User>) => (dispatch) => {
......
......@@ -11,3 +11,14 @@ export const ADMIN_REMOVE_OAUTH_CLIENT = 'user/admin/REMOVE_OAUTH_CLIENT';
export const ADMIN_RECEIVE_OAUTH_CLIENT_DETAILS = 'user/admin/RECEIVE_OAUTH_CLIENT_DETAILS';
export const ADMIN_APPEND_OAUTH_CLIENTS = 'user/admin/APPEND_OAUTH_CLIENTS';
export const ADMIN_UPDATE_OAUTH_CLIENT_FORM = 'Form/user/admin/UPDATE_OAUTH_CLIENT_FORM';
// Api constants
export const API_ADMIN_LIST_USERS = 'api/user/ADMIN_LIST_USERS';
export const API_ADMIN_GET_USER = 'api/user/ADMIN_GET_USER';
export const API_ADMIN_UPDATE_USERS = 'api/user/ADMIN_UPDATE_USERS';
export const API_ADMIN_ENABLE_USERS = 'api/user/ADMIN_ENABLE_USERS';
export const API_ADMIN_DISABLE_USERS = 'api/user/ADMIN_DISABLE_USERS';
export const API_ADMIN_LOCK_USERS = 'api/user/ADMIN_LOCK_USERS';
export const API_ADMIN_UNLOCK_USERS = 'api/user/ADMIN_UNLOCK_USERS';
export const API_ADMIN_ARCHIVE_USERS = 'api/user/ADMIN_ARCHIVE_USERS';
export const API_ADMIN_SEND_EMAILS = 'api/user/ADMIN_SEND_EMAILS';
......@@ -4,7 +4,7 @@ import {bindActionCreators} from 'redux';
import { WithTranslation, withTranslation } from 'react-i18next';
// Actions
import {deleteAccount, enableAccount, loadUser, lockAccount, sendVerificationEmail} from 'user/actions/admin';
import {deleteAccounts, enableAccounts, loadUser, lockAccounts, sendVerificationEmails} from 'user/actions/admin';
import navigateTo from 'actions/navigation';
// Models
......@@ -21,16 +21,17 @@ import UserProfileCard from 'user/ui/c/UserProfileCard';
import confirm from 'utilities/confirmAlert';
import { ScrollToTopOnMount } from 'ui/common/page/scrollers';
import ButtonBar from 'ui/common/buttons/ButtonBar';
import UUIDandVersion from 'model/UUIDandVersion';
interface IDisplayPageProps extends React.ClassAttributes<any>, WithTranslation {
t: any;
user: User;
loading: boolean;
userUuid: string;
enableAccount: (uuid: string, enable?: boolean) => void;
lockAccount: (uuid: string, lock?: boolean) => void;
deleteAccount: (uuid: string) => void;
sendVerificationEmail: (uuid: string) => void;
enableAccounts: (uuidAndVersions: UUIDandVersion[], enable?: boolean) => void;
lockAccounts: (uuidAndVersions: UUIDandVersion[], lock?: boolean) => void;
deleteAccounts: (uuidAndVersions: UUIDandVersion[]) => void;
sendVerificationEmail: (uuids: string[]) => void;
loadUser: (uuid: string) => void;
navigateTo: (path: string) => void;
}
......@@ -53,13 +54,13 @@ class DisplayPage extends React.Component<IDisplayPageProps, any> {
}
private handleDelete = () => {
const {user, deleteAccount, t} = this.props;
const {user, deleteAccounts, t} = this.props;
confirm(<span>{ `${t('common:action.delete')} ${user.fullName} ?` }</span>, {
confirmLabel: t('common:action.delete'),
abortLabel: t('common:action.cancel'),
}).then(() => {
deleteAccount(user.uuid);
deleteAccounts([{uuid: user.uuid, version: user.version}]);
}).catch(() => {
// don't delete
});
......@@ -67,7 +68,7 @@ class DisplayPage extends React.Component<IDisplayPageProps, any> {
public render() {
const {user, loading, enableAccount, lockAccount, sendVerificationEmail, navigateTo, t} = this.props;
const {user, loading, enableAccounts, lockAccounts, sendVerificationEmail, navigateTo, t} = this.props;