UNPKG

@selfcommunity/react-ui

Version:

React UI Components to integrate a Community created with SelfCommunity Platform.

312 lines (303 loc) • 17.2 kB
import { __rest } from "tslib"; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { useCallback, useContext, useMemo, useState } from 'react'; import { styled } from '@mui/material/styles'; import { Backdrop, Box, Button, Collapse, Divider, Grid, Icon, IconButton, Stack, Tooltip, Typography } from '@mui/material'; import { http, Endpoints } from '@selfcommunity/api-services'; import { Link, SCUserContext, UserUtils, useSCContext } from '@selfcommunity/react-core'; import { FormattedMessage } from 'react-intl'; import classNames from 'classnames'; import Widget from '../Widget'; import { useThemeProps } from '@mui/system'; import HiddenPlaceholder from '../../shared/HiddenPlaceholder'; import { CONTACT_PROD, CONTACT_STAGE, HUB_PROD, HUB_STAGE, PREFIX } from './constants'; import LogoPlaceholder from '../../assets/logo'; import Grow from '@mui/material/Grow'; const classes = { root: `${PREFIX}-root`, title: `${PREFIX}-title`, content: `${PREFIX}-content`, actions: `${PREFIX}-actions`, action: `${PREFIX}-action`, actionHighlighted: `${PREFIX}-action-highlighted`, tutorial: `${PREFIX}-tutorial`, tutorialContent: `${PREFIX}-tutorial-content`, tutorialTitle: `${PREFIX}-tutorial-title`, tutorialTitleClose: `${PREFIX}-tutorial-title-close`, tutorialDesc: `${PREFIX}-tutorial-desc`, tutorialOpen: `${PREFIX}-tutorial-open`, divider: `${PREFIX}-divider`, tutorialControls: `${PREFIX}-tutorial-controls`, btnStep: `${PREFIX}-btn-step`, btnPreviousStep: `${PREFIX}-btn-previous-step`, btnNextStep: `${PREFIX}-btn-next-step` }; const Root = styled(Widget, { name: PREFIX, slot: 'Root' })(({ theme }) => ({ padding: '0px !important', [`&.${classes.tutorialOpen}`]: { position: 'relative', zIndex: theme.zIndex.drawer + 2, [`& .${classes.tutorial}`]: { padding: 0 } }, [`& .${classes.title}`]: { display: 'flex', justifyContent: 'center', marginBottom: theme.spacing(1) }, [`& .${classes.content}`]: { padding: `${theme.spacing(2)} 0 0 0`, backgroundColor: '#EFEFEF' }, [`& .${classes.actions}`]: { display: 'flex', paddingBottom: 0, boxShadow: 'inset -1px -3px 7px -4px #CECECE', '-webkit-overflow-scrolling': 'touch', overflowX: 'auto', overflowY: 'hidden', scrollbarWidth: 'none' /* Firefox */, '-ms-overflow-style': 'none' /* IE and Edge */, '&::-webkit-scrollbar': { display: 'none' } }, [`& .${classes.action}`]: { padding: `0px 2px ${theme.spacing(2)} 2px`, display: 'flex', flexGrow: 1, justifyContent: 'center', '& .MuiButton-root': { color: theme.palette.getContrastText(theme.palette.common.white), backgroundColor: theme.palette.common.white, '&:hover': { color: theme.palette.getContrastText(theme.palette.primary.main), backgroundColor: theme.palette.primary.main } } }, [`& .${classes.tutorialContent}`]: { width: '100%' }, [`& .${classes.divider}`]: { paddingTop: theme.spacing() }, [`& .${classes.tutorialTitle}`]: { position: 'relative', fontWeight: 700, fontSize: 15, padding: `${theme.spacing(3)} ${theme.spacing()} ${theme.spacing()} ${theme.spacing(3)}` }, [`& .${classes.tutorialTitleClose}`]: { position: 'absolute', top: theme.spacing(3), right: theme.spacing(3) }, [`& .${classes.tutorialDesc}`]: { fontSize: 14, fontWeight: 500, color: theme.palette.grey[700], padding: `0px ${theme.spacing(3)} ${theme.spacing()} ${theme.spacing(3)}` }, [`& .${classes.tutorialControls}`]: { padding: theme.spacing(2) }, [`& .${classes.actionHighlighted}`]: { position: 'relative', '&:before': { content: '""', display: 'block', position: 'absolute', bottom: -11, width: 10, height: 10, transform: 'translateY(-50%) rotate(45deg)', boxShadow: '0px -20px 20px 0px #CECECE', zIndex: 0, backgroundColor: theme.palette.common.white }, '& .MuiButton-root': { backgroundColor: theme.palette.primary.main, color: theme.palette.common.white } }, [`& .${classes.btnStep}`]: { borderRadius: 3 } })); /** * > API documentation for the Community-JS PlatformWidget component. Learn about the available props and the CSS API. * * * This component renders a widget containing the links that allow users and moderators to handle their application content. * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/Platform) #### Import ```jsx import {PlatformWidget} from '@selfcommunity/react-ui'; ``` #### Component Name The name `SCPlatformWidget` can be used when providing style overrides in the theme. #### CSS |Rule Name|Global class|Description| |---|---|---| |root|.SCPlatformWidget-root|Styles applied to the root element.| |title|.SCPlatformWidget-title|Styles applied to the title element.| |actions|.SCPlatformWidget-actions|Styles applied to the actions container.| |action|.SCPlatformWidget-action|Styles applied to the single action element.| |actionHighlighted|.SCPlatformWidget-action-highlighted|Styles applied to the action highlighted.| |tutorial|.SCPlatformWidget-tutorial|Styles applied to the tutorial element.| |tutorialContent|.SCPlatformWidget-tutorial-content|Styles applied to the content of the tutorial element.| |tutorialTitle|.SCPlatformWidget-tutorial-title|Styles applied to the title element of the tutorial.| |tutorialTitleClose|.SCPlatformWidget-tutorial-title-close|Styles applied to the close button of the title in the tutorial.| |tutorialDesc|.SCPlatformWidget-tutorial-desc|Styles applied to the tutorial description element.| |tutorialOpen|.SCPlatformWidget-tutorial-open|Styles applied to the tutorial element when is active.| |divider|.SCPlatformWidget-divider|Styles applied to the divider element in the tutorial container.| |tutorialControls|.SCPlatformWidget-tutorial-controls|Styles applied to the tutorial bottom controls.| |btnStep|.SCPlatformWidget-btn-step|Styles applied to the button next/previous/skip/close of the tutorial controls.| |btnPreviousStep|.SCPlatformWidget-btn-previous-step|Styles applied to the button previous element of the tutorial controls.| |btnNextStep|.SCPlatformWidget-btn-next-step|Styles applied to the button next element of the tutorial controls.| * * @param inProps */ export default function PlatformWidget(inProps) { var _a; // PROPS const props = useThemeProps({ props: inProps, name: PREFIX }); const { autoHide, className, title = null, startActions = [], endActions = [], hideConsoleAction = false, hideModerationAction = false, hideHubAction = false, hideContactUsAction = false, onHeightChange } = props, rest = __rest(props, ["autoHide", "className", "title", "startActions", "endActions", "hideConsoleAction", "hideModerationAction", "hideHubAction", "hideContactUsAction", "onHeightChange"]); // CONTEXT const scContext = useSCContext(); const scUserContext = useContext(SCUserContext); // STATE const [tutorialIndex, setTutorialIndex] = useState(0); const [isTutorialOpen, setIsTutorialOpen] = useState(false); // CONST const isAdmin = useMemo(() => UserUtils.isAdmin(scUserContext.user), [scUserContext.user]); const isEditor = useMemo(() => UserUtils.isEditor(scUserContext.user), [scUserContext.user]); const isModerator = useMemo(() => UserUtils.isModerator(scUserContext.user), [scUserContext.user]); const isCommunityOwner = useMemo(() => { var _a; return ((_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.id) === 1; }, [scUserContext.user]); const isStage = scContext.settings.portal.includes('stage'); const actions = [ ...startActions, ...((isAdmin || isEditor) && !hideConsoleAction ? [ { render: (_jsx(Button, Object.assign({ variant: "outlined", size: "small", onClick: () => fetchPlatform('') }, { children: _jsx(FormattedMessage, { id: "ui.platformWidget.adm", defaultMessage: "ui.platformWidget.adm" }) }))), title: _jsx(FormattedMessage, { id: "ui.platformWidget.adm", defaultMessage: "ui.platformWidget.adm" }), content: _jsx(FormattedMessage, { id: "ui.platformWidget.adm.desc", defaultMessage: "ui.platformWidget.adm.desc" }) } ] : []), ...((isAdmin || isModerator) && !hideModerationAction ? [ { render: (_jsx(Button, Object.assign({ variant: "outlined", size: "small", onClick: () => fetchPlatform('/moderation/flags/') }, { children: _jsx(FormattedMessage, { id: "ui.platformWidget.mod", defaultMessage: "ui.platformWidget.mod" }) }))), title: _jsx(FormattedMessage, { id: "ui.platformWidget.mod", defaultMessage: "ui.platformWidget.mod" }), content: _jsx(FormattedMessage, { id: "ui.platformWidget.mod.desc", defaultMessage: "ui.platformWidget.mod.desc" }) } ] : []), ...(isAdmin && isCommunityOwner && !hideHubAction ? [ { render: (_jsx(Button, Object.assign({ variant: "outlined", size: "small", component: Link, to: isStage ? HUB_STAGE : HUB_PROD, target: "_blank" }, { children: _jsx(FormattedMessage, { id: "ui.platformWidget.hub", defaultMessage: "ui.platformWidget.hub" }) }))), title: _jsx(FormattedMessage, { id: "ui.platformWidget.hub", defaultMessage: "ui.platformWidget.hub" }), content: _jsx(FormattedMessage, { id: "ui.platformWidget.hub.desc", defaultMessage: "ui.platformWidget.hub.desc" }) } ] : []), ...(isCommunityOwner && !hideContactUsAction ? [ { render: (_jsx(Button, Object.assign({ variant: "outlined", size: "small", component: Link, to: isStage ? CONTACT_STAGE : CONTACT_PROD, target: "_blank" }, { children: _jsx(FormattedMessage, { id: "ui.platformWidget.contactUs", defaultMessage: "ui.platformWidget.contactUs" }) }))), title: _jsx(FormattedMessage, { id: "ui.platformWidget.contactUs", defaultMessage: "ui.platformWidget.contactUs" }), content: _jsx(FormattedMessage, { id: "ui.platformWidget.contactUs.desc", defaultMessage: "ui.platformWidget.contactUs.desc" }) } ] : []), ...endActions ]; /** * Handle open tutorial */ const handleOpenTutorial = useCallback(() => { setTutorialIndex(0); setIsTutorialOpen(true); onHeightChange && onHeightChange(); }, [setTutorialIndex, setIsTutorialOpen, onHeightChange]); /** * Handle close tutorial */ const handleCloseTutorial = useCallback(() => { setIsTutorialOpen(false); setTutorialIndex(0); onHeightChange && onHeightChange(); }, [setIsTutorialOpen, setTutorialIndex, onHeightChange]); /** * Handle next step tutorial */ const handlePrevious = useCallback(() => { if (tutorialIndex > 0) { setTutorialIndex((prev) => prev - 1); } else { handleCloseTutorial(); } onHeightChange && onHeightChange(); }, [tutorialIndex, setTutorialIndex, handleCloseTutorial, onHeightChange]); /** * Handle next step tutorial */ const handleNext = useCallback(() => { if (tutorialIndex < actions.length - 1) { setTutorialIndex((prev) => prev + 1); } else { handleCloseTutorial(); } onHeightChange && onHeightChange(); }, [actions, tutorialIndex, setTutorialIndex, handleCloseTutorial, onHeightChange]); /** * Fetches platform url */ function fetchPlatform(query) { http .request({ url: Endpoints.Platform.url(), method: Endpoints.Platform.method, params: { next: query } }) .then((res) => { const platformUrl = res.data.platform_url; window.open(platformUrl, '_blank').focus(); }) .catch((error) => { console.log(error); }); } /** * Render tutorial */ const tutorial = (_jsxs(Grid, Object.assign({ container: true, spacing: isAdmin ? 1 : 3, justifyContent: "center", className: classes.tutorial }, { children: [!isTutorialOpen && (_jsx(Grid, Object.assign({ item: true, xs: "auto", alignItems: "center", justifyContent: "center" }, { children: _jsx(IconButton, Object.assign({ size: "medium", onClick: handleOpenTutorial }, { children: _jsx(Icon, { children: "info" }) })) }))), _jsx(Collapse, Object.assign({ in: isTutorialOpen, className: classes.tutorialContent }, { children: isTutorialOpen && (_jsxs(Grid, Object.assign({ item: true, xs: "auto" }, { children: [_jsxs(Typography, Object.assign({ variant: 'body2', className: classes.tutorialTitle, component: 'div' }, { children: [_jsx(Grow, Object.assign({ in: true, timeout: 1000 }, { children: _jsx("span", { children: actions[tutorialIndex].title }) })), _jsx(IconButton, Object.assign({ size: 'small', className: classes.tutorialTitleClose, onClick: handleCloseTutorial }, { children: _jsx(Icon, { children: "close" }) }))] })), _jsx(Grow, Object.assign({ in: true, timeout: 1200 }, { children: _jsx(Typography, Object.assign({ variant: 'body2', className: classes.tutorialDesc }, { children: actions[tutorialIndex].content })) })), _jsx(Divider, { className: classes.divider }), _jsxs(Stack, Object.assign({ direction: "row", justifyContent: "space-between", alignItems: "center", spacing: 2, className: classes.tutorialControls }, { children: [_jsx(Button, Object.assign({ variant: "text", size: "small", onClick: handlePrevious, className: classNames(classes.btnStep, classes.btnPreviousStep) }, { children: tutorialIndex === 0 ? (_jsx(FormattedMessage, { id: "ui.platformWidget.tutorial.skip", defaultMessage: "ui.platformWidget.tutorial.skip" })) : (_jsx(FormattedMessage, { id: "ui.platformWidget.tutorial.previous", defaultMessage: "ui.platformWidget.tutorial.previous" })) })), _jsxs(Typography, Object.assign({ component: 'div' }, { children: [tutorialIndex + 1, "/", actions.length] })), _jsx(Button, Object.assign({ variant: "contained", size: "small", color: "primary", onClick: handleNext, className: classNames(classes.btnStep, classes.btnNextStep) }, { children: tutorialIndex === actions.length - 1 ? (_jsx(FormattedMessage, { id: "ui.platformWidget.tutorial.close", defaultMessage: "ui.platformWidget.tutorial.close" })) : (_jsx(FormattedMessage, { id: "ui.platformWidget.tutorial.next", defaultMessage: "ui.platformWidget.tutorial.next" })) }))] }))] }))) }))] }))); /** * Renders platform card */ const content = (_jsxs(Grid, Object.assign({ container: true, spacing: isAdmin ? 1 : 3, justifyContent: "center", className: classes.content }, { children: [_jsx(Grid, Object.assign({ item: true, xs: 12 }, { children: title ? (title) : (_jsx(Box, Object.assign({ className: classes.title }, { children: _jsx(Tooltip, Object.assign({ title: _jsx(FormattedMessage, { id: "ui.platformWidget.title.tooltip", defaultMessage: "ui.platformWidget.title.tooltip" }), placement: "top" }, { children: _jsx("img", { src: LogoPlaceholder, alt: "logo" }) })) }))) })), _jsxs(Grid, Object.assign({ item: true, xs: 12, className: classes.actions }, { children: [_jsx(Grid, { item: true, xs: 1, className: classes.action }), actions.map((a, i) => { return (_jsx(Grid, Object.assign({ item: true, xs: "auto", className: classNames(classes.action, { [classes.actionHighlighted]: tutorialIndex === i && isTutorialOpen }) }, { children: a.render }), i)); }), _jsx(Grid, { item: true, xs: 1, className: classes.action })] }))] }))); /** * Renders root object (if not hidden by autoHide prop) */ if (!autoHide && ((_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.role)) { return (_jsxs(_Fragment, { children: [_jsxs(Root, Object.assign({ className: classNames(classes.root, className, { [classes.tutorialOpen]: isTutorialOpen }) }, rest, { children: [content, tutorial] })), _jsx(Backdrop, { sx: { color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }, open: isTutorialOpen, onClick: handleCloseTutorial })] })); } return _jsx(HiddenPlaceholder, {}); }