UNPKG

@selfcommunity/react-ui

Version:

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

252 lines (247 loc) • 18.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const jsx_runtime_1 = require("react/jsx-runtime"); const lab_1 = require("@mui/lab"); const material_1 = require("@mui/material"); const styles_1 = require("@mui/material/styles"); const system_1 = require("@mui/system"); const types_1 = require("@selfcommunity/types"); const classnames_1 = tslib_1.__importDefault(require("classnames")); const react_1 = require("react"); const react_intl_1 = require("react-intl"); const LiveStream_1 = require("../../constants/LiveStream"); const constants_1 = require("./constants"); const UploadEventCover_1 = tslib_1.__importDefault(require("../EventForm/UploadEventCover")); const LiveStreamFormSettings_1 = tslib_1.__importDefault(require("./LiveStreamFormSettings")); const api_services_1 = require("@selfcommunity/api-services"); const Errors_1 = require("../../constants/Errors"); const utils_1 = require("@selfcommunity/utils"); const deafultCover_1 = tslib_1.__importDefault(require("../../assets/deafultCover")); const react_core_1 = require("@selfcommunity/react-core"); const constants_2 = require("../PlatformWidget/constants"); const constants_3 = require("../LiveStreamRoom/constants"); const classes = { root: `${constants_1.PREFIX}-root`, warning: `${constants_1.PREFIX}-warning`, form: `${constants_1.PREFIX}-form`, title: `${constants_1.PREFIX}-title`, cover: `${constants_1.PREFIX}-cover`, slug: `${constants_1.PREFIX}-slug`, description: `${constants_1.PREFIX}-description`, content: `${constants_1.PREFIX}-content`, actions: `${constants_1.PREFIX}-actions`, error: `${constants_1.PREFIX}-error`, genericError: `${constants_1.PREFIX}-generic-error` }; const Root = (0, styles_1.styled)(material_1.Box, { name: constants_1.PREFIX, slot: 'Root' })(({ theme }) => ({})); const messages = (0, react_intl_1.defineMessages)({ title: { id: 'ui.liveStreamForm.title.placeholder', defaultMessage: 'ui.liveStreamForm.title.placeholder' }, slug: { id: 'ui.liveStreamForm.slug.placeholder', defaultMessage: 'ui.liveStreamForm.slug.placeholder' }, description: { id: 'ui.liveStreamForm.description.placeholder', defaultMessage: 'ui.liveStreamForm.description.placeholder' } }); /** *> API documentation for the Community-JS LiveStreamForm component. Learn about the available props and the CSS API. * #### Import ```jsx import {LiveStreamForm} from '@selfcommunity/react-ui'; ``` #### Component Name The name `LiveStreamForm` can be used when providing style overrides in the theme. #### CSS |Rule Name|Global class|Description| |---|---|---| |root|.SCLiveStreamForm-root|Styles applied to the root element.| |title|.SCLiveStreamForm-title|Styles applied to the title element.| |cover|.SCLiveStreamForm-cover|Styles applied to the cover field.| |form|.SCLiveStreamForm-form|Styles applied to the form element.| |name|.SCLiveStreamForm-name|Styles applied to the name field.| |description|.SCLiveStreamForm-description|Styles applied to the description field.| |content|.SCLiveStreamForm-content|Styles applied to the element.| |error|.SCLiveStreamForm-error|Styles applied to the error elements.| * @param inProps */ function LiveStreamForm(inProps) { var _a, _b, _c, _d; //PROPS const props = (0, system_1.useThemeProps)({ props: inProps, name: constants_1.PREFIX }); const { className, onSuccess, onError, liveStream = null } = props, rest = tslib_1.__rest(props, ["className", "onSuccess", "onError", "liveStream"]); // HOOKS const scUserContext = (0, react_core_1.useSCUser)(); const { preferences } = (0, react_core_1.useSCPreferences)(); const isCommunityOwner = (0, react_1.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 isFreeTrialTier = (0, react_1.useMemo)(() => preferences && react_core_1.SCPreferences.CONFIGURATIONS_SUBSCRIPTION_TIER in preferences && preferences[react_core_1.SCPreferences.CONFIGURATIONS_SUBSCRIPTION_TIER].value && preferences[react_core_1.SCPreferences.CONFIGURATIONS_SUBSCRIPTION_TIER].value === types_1.SCCommunitySubscriptionTier.FREE_TRIAL, [preferences]); const isEnterpriseTier = (0, react_1.useMemo)(() => preferences && react_core_1.SCPreferences.CONFIGURATIONS_SUBSCRIPTION_TIER in preferences && preferences[react_core_1.SCPreferences.CONFIGURATIONS_SUBSCRIPTION_TIER].value && preferences[react_core_1.SCPreferences.CONFIGURATIONS_SUBSCRIPTION_TIER].value === types_1.SCCommunitySubscriptionTier.ENTERPRISE, [preferences]); const isStage = (0, react_1.useMemo)(() => preferences && react_core_1.SCPreferences.STATIC_ENVIRONMENT in preferences && preferences[react_core_1.SCPreferences.STATIC_ENVIRONMENT].value === types_1.SCCommunityEnvironment.STAGE, [preferences]); const communityStackId = (0, react_1.useMemo)(() => preferences && react_core_1.SCPreferences.STATIC_ENVIRONMENT in preferences && preferences[react_core_1.SCPreferences.STATIC_STACKID].value, [preferences]); const canCreateLiveStream = (0, react_1.useMemo)(() => { var _a, _b; return (_b = (_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission) === null || _b === void 0 ? void 0 : _b.create_live_stream; }, [(_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission]); const intl = (0, react_intl_1.useIntl)(); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const initialFieldState = { title: (liveStream === null || liveStream === void 0 ? void 0 : liveStream.title) || '', description: (liveStream === null || liveStream === void 0 ? void 0 : liveStream.description) || '', slug: (liveStream === null || liveStream === void 0 ? void 0 : liveStream.slug) || '', settings: (liveStream === null || liveStream === void 0 ? void 0 : liveStream.settings) || constants_1.LIVESTREAM_DEFAULT_SETTINGS, cover: (liveStream === null || liveStream === void 0 ? void 0 : liveStream.cover) || '', coverFile: (liveStream === null || liveStream === void 0 ? void 0 : liveStream.cover) || '', isSubmitting: false }; // STATE const [field, setField] = (0, react_1.useState)(initialFieldState); const [error, setError] = (0, react_1.useState)({}); const [genericError, setGenericError] = (0, react_1.useState)(null); const [timeRemaining, setTimeRemaining] = (0, react_1.useState)(null); const _backgroundCover = Object.assign({}, (field.cover ? { background: `url('${field.cover}') center / cover` } : { background: `url('${deafultCover_1.default}') no-repeat 0 0 / 100% 100%` })); const handleChangeCover = (0, react_1.useCallback)((cover) => { setField((prev) => (Object.assign(Object.assign({}, prev), { ['coverFile']: cover }))); const reader = new FileReader(); reader.onloadend = () => { setField((prev) => (Object.assign(Object.assign({}, prev), { ['cover']: reader.result }))); }; reader.readAsDataURL(cover); if (error.coverError) { delete error.coverError; setError(error); } }, [error]); const handleSubmit = (0, react_1.useCallback)(() => { setField((prev) => (Object.assign(Object.assign({}, prev), { ['isSubmitting']: true }))); setGenericError(null); const formData = new FormData(); if (field.coverFile) { formData.append('cover', field.coverFile); } formData.append('title', field.title); formData.append('description', field.description); formData.append('slug', field.slug); formData.append('settings', JSON.stringify(field.settings)); let liveStreamService; if (liveStream) { liveStreamService = api_services_1.LiveStreamService.update(liveStream.id, formData, { headers: { 'Content-Type': 'multipart/form-data' } }); } else { liveStreamService = api_services_1.LiveStreamService.create(formData, { headers: { 'Content-Type': 'multipart/form-data' } }); } liveStreamService .then((data) => { setField((prev) => (Object.assign(Object.assign({}, prev), { ['isSubmitting']: false }))); onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(data); }) .catch((e) => { const _error = (0, api_services_1.formatHttpErrorCode)(e); if ('errorsError' in _error || !Object.keys(_error).length) { setGenericError(intl.formatMessage({ id: 'ui.liveStreamForm.error.monthlyMinuteLimitReached', defaultMessage: 'ui.liveStreamForm.error.monthlyMinuteLimitReached' })); } else { setGenericError(null); } let __errors = {}; if ('coverError' in _error) { __errors = Object.assign(Object.assign({}, __errors), { ['coverError']: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamForm.cover.error.invalid", defaultMessage: "ui.liveStreamForm.cover.error.invalid" }) }); } if ('titleError' in _error) { __errors = Object.assign(Object.assign({}, __errors), { ['titleError']: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamForm.title.error.invalid", defaultMessage: "ui.liveStreamForm.title.error.invalid" }) }); } if ('slugError' in _error) { __errors = Object.assign(Object.assign({}, __errors), { ['slugError']: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamForm.slug.error.invalid", defaultMessage: "ui.liveStreamForm.slug.error.invalid" }) }); } setError(__errors); setField((prev) => (Object.assign(Object.assign({}, prev), { ['isSubmitting']: false }))); utils_1.Logger.error(Errors_1.SCOPE_SC_UI, e); onError === null || onError === void 0 ? void 0 : onError(e); }); }, [field, onSuccess, onError]); const handleChange = (0, react_1.useCallback)((event) => { const { name, value } = event.target; setField((prev) => (Object.assign(Object.assign({}, prev), { [name]: value }))); if (error[`${name}Error`]) { delete error[`${name}Error`]; setError(error); } setGenericError(null); }, [error, setGenericError]); const handleChangeSettings = (0, react_1.useCallback)((data) => { setField((prev) => (Object.assign(Object.assign({}, prev), { settings: data }))); }, [setField]); const warning = (0, react_1.useMemo)(() => { let _message; if (isFreeTrialTier && isCommunityOwner && !isEnterpriseTier) { _message = ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamForm.selector.warningSubscriptionRequired", defaultMessage: "ui.liveStreamForm.selector.warningSubscriptionRequired", values: { // eslint-disable-next-line @typescript-eslint/ban-ts-ignore // @ts-ignore link: (...chunks) => ((0, jsx_runtime_1.jsx)(react_core_1.Link, Object.assign({ target: "_blank", to: `${isStage ? constants_2.HUB_STAGE : constants_2.HUB_PROD}dashboard/community/${communityStackId}/subscription` }, { children: chunks }))) } })); } else if (timeRemaining !== null && timeRemaining <= constants_3.WARNING_THRESHOLD_EXPIRING_SOON) { if (timeRemaining <= 1) { _message = ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamForm.selector.warningMinutesExausted", defaultMessage: "ui.liveStreamForm.selector.warningMinutesExausted" })); } else if (timeRemaining <= constants_3.WARNING_THRESHOLD_EXPIRING_SOON) { _message = ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamForm.selector.warningRemainingMinutes", defaultMessage: "ui.liveStreamForm.selector.warningRemainingMinutes", values: { minutes: timeRemaining } })); } } if (_message) { return ((0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.warning }, { children: (0, jsx_runtime_1.jsx)(material_1.Alert, Object.assign({ variant: "filled", severity: "warning" }, { children: _message })) }))); } return null; }, [isFreeTrialTier, isCommunityOwner, timeRemaining]); const fetchLivestreamStatus = () => { api_services_1.LiveStreamApiClient.getMonthlyDuration() .then((r) => { setTimeRemaining(r.remaining_minutes); }) .catch((error) => { console.error('Error fetching live status:', error); }); }; (0, react_1.useEffect)(() => { fetchLivestreamStatus(); }, []); /** * Renders root object */ return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: (0, classnames_1.default)(classes.root, className) }, rest, { children: [warning, (0, jsx_runtime_1.jsx)(material_1.Paper, Object.assign({ style: _backgroundCover, classes: { root: classes.cover } }, { children: (0, jsx_runtime_1.jsx)(UploadEventCover_1.default, { isCreationMode: true, onChange: handleChangeCover }) })), Boolean(error['coverError']) && (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ color: "error" }, { children: error['coverError'] })), (0, jsx_runtime_1.jsxs)(material_1.FormGroup, Object.assign({ className: classes.form }, { children: [(0, jsx_runtime_1.jsx)(material_1.TextField, { required: true, className: classes.title, placeholder: `${intl.formatMessage(messages.title)}`, margin: "normal", value: field.title, name: "title", onChange: handleChange, InputProps: { endAdornment: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: LiveStream_1.LIVE_STREAM_TITLE_MAX_LENGTH - field.title.length })) }, error: Boolean(field.title.length > LiveStream_1.LIVE_STREAM_TITLE_MAX_LENGTH) || Boolean(error['titleError']), helperText: field.title.length > LiveStream_1.LIVE_STREAM_TITLE_MAX_LENGTH ? ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamForm.title.error.maxLength", defaultMessage: "ui.liveStreamForm.title.error.maxLength" })) : error['titleError'] ? (error['titleError']) : null }), (0, jsx_runtime_1.jsx)(material_1.TextField, { required: true, className: classes.slug, placeholder: `${intl.formatMessage(messages.slug)}`, margin: "normal", value: field.slug, name: "slug", onChange: handleChange, InputProps: { endAdornment: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: LiveStream_1.LIVE_STREAM_SLUG_MAX_LENGTH - field.slug.length })) }, error: Boolean(field.slug.length > LiveStream_1.LIVE_STREAM_SLUG_MAX_LENGTH) || Boolean(error['slugError']), helperText: field.title.length > LiveStream_1.LIVE_STREAM_SLUG_MAX_LENGTH ? ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamForm.slug.error.maxLength", defaultMessage: "ui.liveStreamForm.slug.error.maxLength" })) : error['slugError'] ? (error['slugError']) : null }), (0, jsx_runtime_1.jsx)(material_1.TextField, { multiline: true, rows: 4, className: classes.description, placeholder: `${intl.formatMessage(messages.description)}`, margin: "normal", value: field.description, name: "description", onChange: handleChange, InputProps: { endAdornment: ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: ((_b = field.description) === null || _b === void 0 ? void 0 : _b.length) ? LiveStream_1.LIVE_STREAM_DESCRIPTION_MAX_LENGTH - field.description.length : LiveStream_1.LIVE_STREAM_DESCRIPTION_MAX_LENGTH }))) }, error: Boolean(((_c = field.description) === null || _c === void 0 ? void 0 : _c.length) > LiveStream_1.LIVE_STREAM_DESCRIPTION_MAX_LENGTH), helperText: ((_d = field.description) === null || _d === void 0 ? void 0 : _d.length) > LiveStream_1.LIVE_STREAM_DESCRIPTION_MAX_LENGTH ? ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamForm.description.error.maxLength", defaultMessage: "ui.liveStreamForm.description.error.maxLength" })) : null }), (0, jsx_runtime_1.jsx)(LiveStreamFormSettings_1.default, { settings: field.settings, onChange: handleChangeSettings }), genericError && ((0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.genericError }, { children: (0, jsx_runtime_1.jsx)(material_1.Alert, Object.assign({ variant: "filled", severity: "error" }, { children: genericError })) }))), (0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.actions }, { children: (0, jsx_runtime_1.jsx)(lab_1.LoadingButton, Object.assign({ loading: field.isSubmitting, disabled: !field.title || field.isSubmitting || field.title.length > LiveStream_1.LIVE_STREAM_TITLE_MAX_LENGTH || field.description.length > LiveStream_1.LIVE_STREAM_DESCRIPTION_MAX_LENGTH || isFreeTrialTier || timeRemaining <= constants_3.WARNING_THRESHOLD_EXPIRING_SOON || !canCreateLiveStream, variant: "contained", onClick: handleSubmit, color: "secondary" }, { children: liveStream ? ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamForm.button.edit", defaultMessage: "ui.liveStreamForm.button.edit" })) : ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamForm.button.create", defaultMessage: "ui.liveStreamForm.button.create" })) })) }))] }))] }))); } exports.default = LiveStreamForm;