@selfcommunity/react-ui
Version:
React UI Components to integrate a Community created with SelfCommunity Platform.
252 lines (247 loc) • 18.4 kB
JavaScript
"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;