@selfcommunity/react-ui
Version:
React UI Components to integrate a Community created with SelfCommunity Platform.
156 lines (155 loc) • 13.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const jsx_runtime_1 = require("react/jsx-runtime");
const material_1 = require("@mui/material");
const react_1 = require("react");
const react_intl_1 = require("react-intl");
const RowSkeleton_1 = tslib_1.__importDefault(require("./RowSkeleton"));
const lab_1 = require("@mui/lab");
const types_1 = require("@selfcommunity/types");
const constants_1 = require("./constants");
const EmptyStatus_1 = tslib_1.__importDefault(require("../EmptyStatus"));
const SeeProgressButton_1 = tslib_1.__importDefault(require("./SeeProgressButton"));
const Skeleton_1 = tslib_1.__importDefault(require("./Skeleton"));
const widget_1 = require("../../utils/widget");
const api_services_1 = require("@selfcommunity/api-services");
const utils_1 = require("@selfcommunity/utils");
const Errors_1 = require("../../constants/Errors");
const ChangeUsersStatus_1 = tslib_1.__importDefault(require("./ChangeUsersStatus"));
const react_core_1 = require("@selfcommunity/react-core");
const RequestButton_1 = tslib_1.__importDefault(require("./RequestButton"));
const course_1 = require("../../types/course");
const RemoveButton_1 = tslib_1.__importDefault(require("./RemoveButton"));
const ConfirmDialog_1 = tslib_1.__importDefault(require("../ConfirmDialog/ConfirmDialog"));
const course_2 = require("../../types/course");
const classes = {
root: `${constants_1.PREFIX}-root`,
search: `${constants_1.PREFIX}-search`,
endAdornmentWrapper: `${constants_1.PREFIX}-end-adornment-wrapper`,
searchButton: `${constants_1.PREFIX}-search-button`,
avatarWrapper: `${constants_1.PREFIX}-avatar-wrapper`,
progressWrapper: `${constants_1.PREFIX}-progress-wrapper`,
progress: `${constants_1.PREFIX}-progress`,
loadingButton: `${constants_1.PREFIX}-loading-button`
};
const Root = (0, material_1.styled)(material_1.Box, {
name: constants_1.PREFIX,
slot: 'Root',
overridesResolver: (_props, styles) => styles.root
})(() => ({}));
function CourseUsersTable(inProps) {
// PROPS
const props = (0, material_1.useThemeProps)({
props: inProps,
name: constants_1.PREFIX
});
const { state, dispatch, course, endpointSearch, endpointQueryParamsSearch = { statuses: JSON.stringify([types_1.SCCourseJoinStatusType.JOINED, types_1.SCCourseJoinStatusType.MANAGER]) }, headerCells, mode, emptyStatusTitle, emptyStatusDescription } = props;
// STATES
const [users, setUsers] = (0, react_1.useState)(null);
const [loadingSearch, setLoadingSearch] = (0, react_1.useState)(false);
const [value, setValue] = (0, react_1.useState)('');
const [dialog, setDialog] = (0, react_1.useState)(null);
// REFS
const buttonRef = (0, react_1.useRef)(null);
const inputRef = (0, react_1.useRef)(null);
// CONTEXTS
const scUserContext = (0, react_core_1.useSCUser)();
// INTL
const intl = (0, react_intl_1.useIntl)();
// HANDLERS
const handleNext = (0, react_1.useCallback)(() => {
dispatch({ type: widget_1.actionWidgetTypes.LOADING_NEXT });
api_services_1.http
.request({
url: state.next,
method: 'GET'
})
.then((res) => {
dispatch({ type: widget_1.actionWidgetTypes.LOAD_NEXT_SUCCESS, payload: res.data });
})
.catch((error) => {
dispatch({ type: widget_1.actionWidgetTypes.LOAD_NEXT_FAILURE, payload: { errorLoadNext: error } });
utils_1.Logger.error(Errors_1.SCOPE_SC_UI, error);
});
}, [state.next, dispatch]);
const handleOpenDialog = (0, react_1.useCallback)((tab) => {
setDialog(tab);
}, [setDialog]);
const handleConfirm = (0, react_1.useCallback)(() => {
switch (dialog.tab) {
case course_2.SCCourseEditTabType.USERS:
buttonRef.current.handleManageUser(dialog.user);
break;
case course_2.SCCourseEditTabType.REQUESTS:
buttonRef.current.handleManageUser(dialog.request);
}
handleOpenDialog(null);
}, [dialog, handleOpenDialog]);
const handleSearchClear = (0, react_1.useCallback)(() => {
setUsers(state.results);
setValue('');
}, [setValue, setUsers, state.results]);
const handleChange = (0, react_1.useCallback)((e) => {
const _value = e.target.value;
if (_value.length === 0) {
handleSearchClear();
}
else {
setValue(_value);
}
}, [setValue, handleSearchClear]);
const handleSearchStart = (0, react_1.useCallback)(() => {
setLoadingSearch(true);
api_services_1.http
.request({
url: endpointSearch.url(),
method: endpointSearch.method,
params: Object.assign(Object.assign({}, endpointQueryParamsSearch), { search: value })
})
.then((res) => {
setUsers(res.data.results);
setLoadingSearch(false);
})
.catch((error) => {
dispatch({ type: widget_1.actionWidgetTypes.LOAD_NEXT_FAILURE, payload: { errorLoadNext: error } });
utils_1.Logger.error(Errors_1.SCOPE_SC_UI, error);
});
}, [value, endpointSearch, setUsers, setLoadingSearch, dispatch]);
const handleKeyUp = (0, react_1.useCallback)((e) => {
if (value.length > 0 && e.key === 'Enter') {
handleSearchStart();
}
}, [value, handleSearchStart]);
// EFFECTS
(0, react_1.useEffect)(() => {
setUsers(state.results);
}, [state.results, setUsers]);
(0, react_1.useEffect)(() => {
var _a;
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener('keyup', handleKeyUp);
return () => {
var _a;
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('keyup', handleKeyUp);
};
}, [handleKeyUp]);
if (!users) {
return (0, jsx_runtime_1.jsx)(Skeleton_1.default, {});
}
return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: classes.root }, { children: [(0, jsx_runtime_1.jsx)(material_1.TextField, { ref: inputRef, placeholder: intl.formatMessage({
id: 'ui.courseUsersTable.searchBar.placeholder',
defaultMessage: 'ui.courseUsersTable.searchBar.placeholder'
}), InputProps: {
startAdornment: ((0, jsx_runtime_1.jsx)(material_1.InputAdornment, Object.assign({ position: "start" }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "search" }) }))),
endAdornment: value.length > 0 ? ((0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.endAdornmentWrapper }, { children: [(0, jsx_runtime_1.jsx)(material_1.InputAdornment, Object.assign({ position: "start" }, { children: (0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ color: "inherit", onClick: handleSearchClear }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "close" }) })) })), (0, jsx_runtime_1.jsx)(material_1.InputAdornment, Object.assign({ position: "end" }, { children: (0, jsx_runtime_1.jsx)(lab_1.LoadingButton, Object.assign({ color: "primary", variant: "contained", onClick: handleSearchStart, loading: loadingSearch, disabled: loadingSearch, className: classes.searchButton }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "search" }) })) }))] }))) : undefined
}, value: value, onChange: handleChange, disabled: users.length === 0 && value.length === 0, fullWidth: true, className: classes.search }), (0, jsx_runtime_1.jsx)(material_1.TableContainer, { children: (0, jsx_runtime_1.jsxs)(material_1.Table, { children: [(0, jsx_runtime_1.jsx)(material_1.TableHead, { children: (0, jsx_runtime_1.jsx)(material_1.TableRow, { children: headerCells.map((cell, i, array) => {
if (i === array.length - 1) {
return (0, jsx_runtime_1.jsx)(material_1.TableCell, { width: "14%" }, i);
}
return ((0, jsx_runtime_1.jsx)(material_1.TableCell, Object.assign({ width: mode === course_1.SCCourseUsersTableModeType.DASHBOARD ? '20%' : '25%' }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: cell.id, defaultMessage: cell.id }) })) }), i));
}) }) }), (0, jsx_runtime_1.jsxs)(material_1.TableBody, { children: [users.length > 0 &&
users.map((user, i) => ((0, jsx_runtime_1.jsxs)(material_1.TableRow, { children: [(0, jsx_runtime_1.jsx)(material_1.TableCell, { children: (0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.avatarWrapper }, { children: [(0, jsx_runtime_1.jsx)(material_1.Avatar, { alt: user.username, src: user.avatar }), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: user.username }))] })) }), mode === course_1.SCCourseUsersTableModeType.DASHBOARD && ((0, jsx_runtime_1.jsx)(material_1.TableCell, { children: (0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.progressWrapper }, { children: [(0, jsx_runtime_1.jsx)(material_1.LinearProgress, { className: classes.progress, variant: "determinate", value: user.user_completion_rate }), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: `${Math.round(user.user_completion_rate)}%` }))] })) })), mode === course_1.SCCourseUsersTableModeType.EDIT && ((0, jsx_runtime_1.jsx)(material_1.TableCell, { children: user.join_status !== types_1.SCCourseJoinStatusType.CREATOR && scUserContext.user.id !== user.id ? ((0, jsx_runtime_1.jsx)(ChangeUsersStatus_1.default, { course: course, user: user })) : ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: `ui.editCourse.tab.users.table.select.${user.join_status}`, defaultMessage: `ui.editCourse.tab.users.table.select.${user.join_status}` }) }))) })), (0, jsx_runtime_1.jsx)(material_1.TableCell, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedDate, { value: mode === course_1.SCCourseUsersTableModeType.REQUESTS ? user.date_joined : user.joined_at || new Date() }) })) }), (0, jsx_runtime_1.jsx)(material_1.TableCell, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedDate, { value: mode === course_1.SCCourseUsersTableModeType.REQUESTS ? user.date_joined : user.last_active_at || new Date() }) })) }), mode === course_1.SCCourseUsersTableModeType.EDIT &&
user.join_status !== types_1.SCCourseJoinStatusType.CREATOR &&
scUserContext.user.id !== user.id ? ((0, jsx_runtime_1.jsx)(material_1.TableCell, { children: (0, jsx_runtime_1.jsx)(RemoveButton_1.default, { ref: buttonRef, course: course, user: user, handleOpenDialog: handleOpenDialog }) })) : (mode === course_1.SCCourseUsersTableModeType.EDIT && (0, jsx_runtime_1.jsx)(material_1.TableCell, {})), mode === course_1.SCCourseUsersTableModeType.DASHBOARD && ((0, jsx_runtime_1.jsx)(material_1.TableCell, { children: (0, jsx_runtime_1.jsx)(SeeProgressButton_1.default, { course: course, user: user }) })), mode === course_1.SCCourseUsersTableModeType.REQUESTS && ((0, jsx_runtime_1.jsx)(material_1.TableCell, { children: (0, jsx_runtime_1.jsx)(RequestButton_1.default, { ref: buttonRef, course: course, user: user, handleOpenDialog: handleOpenDialog }) }))] }, i))), state.isLoadingNext && (0, jsx_runtime_1.jsx)(RowSkeleton_1.default, { editMode: mode !== course_1.SCCourseUsersTableModeType.DASHBOARD })] })] }) }), users.length > 0 && ((0, jsx_runtime_1.jsx)(lab_1.LoadingButton, Object.assign({ size: "small", variant: "outlined", color: "inherit", loading: state.isLoadingNext, disabled: value.length > 0 || !state.next, className: classes.loadingButton, onClick: handleNext }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.courseUsersTable.btn.label", defaultMessage: "ui.courseUsersTable.btn.label" }) })) }))), users.length === 0 && ((0, jsx_runtime_1.jsx)(EmptyStatus_1.default, { icon: "face", title: value.length > 0 ? 'ui.courseUsersTable.empty.search.title' : emptyStatusTitle, description: value.length > 0 ? 'ui.courseUsersTable.empty.search.description' : emptyStatusDescription })), dialog && (0, jsx_runtime_1.jsx)(ConfirmDialog_1.default, { open: true, onClose: () => handleOpenDialog(null), onConfirm: handleConfirm })] })));
}
exports.default = (0, react_1.memo)(CourseUsersTable);