@craftercms/studio-ui
Version:
Services, components, models & utils to build CrafterCMS authoring extensions.
186 lines (184 loc) • 7.36 kB
JavaScript
/*
* Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { FormattedMessage } from 'react-intl';
import AddIcon from '@mui/icons-material/Add';
import React, { useCallback, useEffect, useState } from 'react';
import UsersGridUI, { UsersGridSkeletonTable } from '../UsersGrid';
import CreateUserDialog from '../CreateUserDialog';
import EditUserDialog from '../EditUserDialog';
import { fetchAll } from '../../services/users';
import GlobalAppToolbar from '../GlobalAppToolbar';
import Button from '@mui/material/Button';
import SearchBar from '../SearchBar/SearchBar';
import { useDebouncedInput } from '../../hooks/useDebouncedInput';
import useStyles from './styles';
import Paper from '@mui/material/Paper';
import { useEnhancedDialogState } from '../../hooks/useEnhancedDialogState';
import { useWithPendingChangesCloseRequest } from '../../hooks/useWithPendingChangesCloseRequest';
import { ApiResponseErrorState } from '../ApiResponseErrorState';
import { EmptyState } from '../EmptyState';
export function UserManagement(props) {
const { passwordRequirementsMinComplexity = 4 } = props;
const [offset, setOffset] = useState(0);
const [limit, setLimit] = useState(10);
const [fetching, setFetching] = useState(false);
const [users, setUsers] = useState(null);
const [error, setError] = useState();
const [viewUser, setViewUser] = useState(null);
const [showSearchBox, setShowSearchBox] = useState(false);
const [keyword, setKeyword] = useState('');
const { classes, cx: clsx } = useStyles();
const fetchUsers = useCallback(
(keyword = '', _offset = offset) => {
setFetching(true);
fetchAll({ limit, offset: _offset, keyword }).subscribe({
next(users) {
setUsers(users);
setFetching(false);
},
error({ response }) {
setError(response);
setFetching(false);
}
});
},
[limit, offset]
);
useEffect(() => {
fetchUsers();
}, [fetchUsers]);
const createUserDialogState = useEnhancedDialogState();
const createUserDialogPendingChangesCloseRequest = useWithPendingChangesCloseRequest(createUserDialogState.onClose);
const editUserDialogState = useEnhancedDialogState();
const editUserDialogPendingChangesCloseRequest = useWithPendingChangesCloseRequest(editUserDialogState.onClose);
const onUserCreated = () => {
createUserDialogState.onClose();
fetchUsers();
};
const editUserDialogClosed = () => {
setViewUser(null);
};
const onUserEdited = () => {
fetchUsers();
};
const onRowClicked = (user) => {
setViewUser({ ...user });
editUserDialogState.onOpen();
};
const onPageChange = (page) => {
setOffset(page * limit);
};
const onRowsPerPageChange = (e) => {
setLimit(e.target.value);
};
const onShowSearchBox = () => {
setShowSearchBox(!showSearchBox);
};
const onSearch = useCallback(
(keyword) => {
fetchUsers(keyword, 0);
},
[fetchUsers]
);
const onSearch$ = useDebouncedInput(onSearch, 400);
function handleSearchKeyword(keyword) {
setKeyword(keyword);
onSearch$.next(keyword);
}
return React.createElement(
Paper,
{ elevation: 0 },
React.createElement(GlobalAppToolbar, {
title: React.createElement(FormattedMessage, { id: 'words.users', defaultMessage: 'Users' }),
leftContent: React.createElement(
Button,
{
startIcon: React.createElement(AddIcon, null),
variant: 'outlined',
color: 'primary',
onClick: () => createUserDialogState.onOpen()
},
React.createElement(FormattedMessage, { id: 'usersGrid.createUser', defaultMessage: 'Create User' })
),
rightContent: React.createElement(SearchBar, {
classes: { root: clsx(classes.searchBarRoot, !showSearchBox && 'hidden') },
keyword: keyword,
onChange: handleSearchKeyword,
onDecoratorButtonClick: onShowSearchBox,
showActionButton: Boolean(keyword)
})
}),
error
? React.createElement(ApiResponseErrorState, { error: error })
: fetching
? React.createElement(UsersGridSkeletonTable, { numOfItems: limit })
: users
? users.length
? React.createElement(UsersGridUI, {
users: users,
onRowClicked: onRowClicked,
onPageChange: onPageChange,
onRowsPerPageChange: onRowsPerPageChange
})
: React.createElement(EmptyState, {
title: React.createElement(FormattedMessage, {
id: 'usersGrid.emptyStateMessage',
defaultMessage: 'No Users Found'
})
})
: React.createElement(React.Fragment, null),
React.createElement(CreateUserDialog, {
open: createUserDialogState.open,
onCreateSuccess: onUserCreated,
onClose: createUserDialogState.onClose,
passwordRequirementsMinComplexity: passwordRequirementsMinComplexity,
isSubmitting: createUserDialogState.isSubmitting,
isMinimized: createUserDialogState.isMinimized,
hasPendingChanges: createUserDialogState.hasPendingChanges,
onWithPendingChangesCloseRequest: createUserDialogPendingChangesCloseRequest,
onSubmittingAndOrPendingChange: createUserDialogState.onSubmittingAndOrPendingChange
}),
React.createElement(EditUserDialog, {
open: editUserDialogState.open,
onClose: editUserDialogState.onClose,
onClosed: editUserDialogClosed,
onUserEdited: onUserEdited,
user: viewUser,
isSubmitting: editUserDialogState.isSubmitting,
isMinimized: editUserDialogState.isMinimized,
hasPendingChanges: editUserDialogState.hasPendingChanges,
passwordRequirementsMinComplexity: passwordRequirementsMinComplexity,
onWithPendingChangesCloseRequest: editUserDialogPendingChangesCloseRequest,
onSubmittingAndOrPendingChange: editUserDialogState.onSubmittingAndOrPendingChange
})
);
}
export default UserManagement;