diff --git a/src/generic/CollapsableEditor.jsx b/src/generic/CollapsableEditor.jsx
index 113ba22db..d1e451767 100644
--- a/src/generic/CollapsableEditor.jsx
+++ b/src/generic/CollapsableEditor.jsx
@@ -79,4 +79,4 @@ CollapsableEditor.defaultProps = {
},
};
-export default CollapsableEditor;
+export default React.memo(CollapsableEditor);
diff --git a/src/generic/ConfirmationPopup.jsx b/src/generic/ConfirmationPopup.jsx
index 754491466..43e57528f 100644
--- a/src/generic/ConfirmationPopup.jsx
+++ b/src/generic/ConfirmationPopup.jsx
@@ -9,6 +9,10 @@ const ConfirmationPopup = ({
confirmLabel,
onCancel,
cancelLabel,
+ confirmVariant,
+ confirmButtonClass,
+ cancelButtonClass,
+ sectionClasses,
}) => (
- {bodyText}
+ {bodyText}
-
@@ -37,6 +41,16 @@ ConfirmationPopup.propTypes = {
onCancel: PropTypes.func.isRequired,
confirmLabel: PropTypes.string.isRequired,
cancelLabel: PropTypes.string.isRequired,
+ confirmButtonClass: PropTypes.string,
+ cancelButtonClass: PropTypes.string,
+ confirmVariant: PropTypes.string,
+ sectionClasses: PropTypes.string,
+};
+ConfirmationPopup.defaultProps = {
+ confirmVariant: 'outline-brand',
+ confirmButtonClass: '',
+ cancelButtonClass: '',
+ sectionClasses: '',
};
-export default ConfirmationPopup;
+export default React.memo(ConfirmationPopup);
diff --git a/src/generic/FieldFeedback.jsx b/src/generic/FieldFeedback.jsx
index f0214ef16..58373f763 100644
--- a/src/generic/FieldFeedback.jsx
+++ b/src/generic/FieldFeedback.jsx
@@ -50,4 +50,4 @@ FieldFeedback.defaultProps = {
errorMessage: '',
};
-export default FieldFeedback;
+export default React.memo(FieldFeedback);
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.jsx b/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.jsx
index 5eb97ce13..8ff66c8dd 100644
--- a/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.jsx
@@ -12,7 +12,7 @@ import messages from '../../messages';
import { checkFieldErrors } from '../../utils';
import AnonymousPostingFields from '../shared/AnonymousPostingFields';
import AppConfigFormDivider from '../shared/AppConfigFormDivider';
-import BlackoutDatesField from '../shared/BlackoutDatesField';
+import DiscussionRestriction from '../shared/DiscussionRestriction';
import DiscussionTopics from '../shared/discussion-topics/DiscussionTopics';
import DivisionByGroupFields from '../shared/DivisionByGroupFields';
import ReportedContentEmailNotifications from '../shared/ReportedContentEmailNotifications';
@@ -38,7 +38,7 @@ const OpenedXConfigForm = ({
allowAnonymousPostsPeers: appConfigObj?.allowAnonymousPostsPeers || false,
reportedContentEmailNotifications: appConfigObj?.reportedContentEmailNotifications || false,
enableReportedContentEmailNotifications: Boolean(appConfigObj?.enableReportedContentEmailNotifications) || false,
- blackoutDates: appConfigObj?.blackoutDates || [],
+ restrictedDates: appConfigObj?.restrictedDates || [],
discussionTopics: discussionTopicsModel || [],
divideByCohorts: appConfigObj?.divideByCohorts || false,
divideCourseTopicsByCohorts: appConfigObj?.divideCourseTopicsByCohorts || false,
@@ -53,27 +53,27 @@ const OpenedXConfigForm = ({
};
const validationSchema = Yup.object().shape({
// eslint-disable-next-line react/forbid-prop-types
- blackoutDates: Yup.array(
+ restrictedDates: Yup.array(
Yup.object().shape({
startDate: Yup.string()
- .checkFormat(intl.formatMessage(messages.blackoutStartDateInValidFormat), 'date')
- .required(intl.formatMessage(messages.blackoutStartDateRequired)),
+ .checkFormat(intl.formatMessage(messages.restrictedStartDateInValidFormat), 'date')
+ .required(intl.formatMessage(messages.restrictedStartDateRequired)),
endDate: Yup.string()
- .checkFormat(intl.formatMessage(messages.blackoutEndDateInValidFormat), 'date')
- .required(intl.formatMessage(messages.blackoutEndDateRequired))
+ .checkFormat(intl.formatMessage(messages.restrictedEndDateInValidFormat), 'date')
+ .required(intl.formatMessage(messages.restrictedEndDateRequired))
.when('startDate', {
is: (startDate) => startDate,
- then: Yup.string().compare(intl.formatMessage(messages.blackoutEndDateInPast), 'date'),
+ then: Yup.string().compare(intl.formatMessage(messages.restrictedEndDateInPast), 'date'),
}),
startTime: Yup.string().checkFormat(
- intl.formatMessage(messages.blackoutStartTimeInValidFormat),
+ intl.formatMessage(messages.restrictedStartTimeInValidFormat),
'time',
),
endTime: Yup.string()
- .checkFormat(intl.formatMessage(messages.blackoutEndTimeInValidFormat), 'time')
+ .checkFormat(intl.formatMessage(messages.restrictedEndTimeInValidFormat), 'time')
.when('startTime', {
is: (startTime) => startTime,
- then: Yup.string().compare(intl.formatMessage(messages.blackoutEndTimeInPast), 'time'),
+ then: Yup.string().compare(intl.formatMessage(messages.restrictedEndTimeInPast), 'time'),
}),
}),
),
@@ -96,23 +96,23 @@ const OpenedXConfigForm = ({
{({
handleSubmit, handleChange, handleBlur, values, errors, touched,
}) => {
- const { discussionTopics, blackoutDates } = values;
+ const { discussionTopics, restrictedDates } = values;
const discussionTopicErrors = discussionTopics.map((value, index) => checkFieldErrors(touched, errors, `discussionTopics.${index}`, 'name'));
- const blackoutDatesErrors = blackoutDates.map(
- (value, index) => checkFieldErrors(touched, errors, `blackoutDates.${index}`, 'startDate')
- || checkFieldErrors(touched, errors, `blackoutDates.${index}`, 'endDate')
- || checkFieldErrors(touched, errors, `blackoutDates.${index}`, 'startTime')
- || checkFieldErrors(touched, errors, `blackoutDates.${index}`, 'endTime'),
+ const restrictedDatesErrors = restrictedDates.map(
+ (value, index) => checkFieldErrors(touched, errors, `restrictedDates.${index}`, 'startDate')
+ || checkFieldErrors(touched, errors, `restrictedDates.${index}`, 'endDate')
+ || checkFieldErrors(touched, errors, `restrictedDates.${index}`, 'startTime')
+ || checkFieldErrors(touched, errors, `restrictedDates.${index}`, 'endTime'),
);
const contextValue = {
validDiscussionTopics,
setValidDiscussionTopics,
discussionTopicErrors,
- blackoutDatesErrors,
+ restrictedDatesErrors,
isFormInvalid:
discussionTopicErrors.some((error) => error)
- || blackoutDatesErrors.some((error) => error),
+ || restrictedDatesErrors.some((error) => error),
};
return (
@@ -139,7 +139,7 @@ const OpenedXConfigForm = ({
-
+
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.test.jsx b/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.test.jsx
index 19dd45fb1..7efa06450 100644
--- a/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.test.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.test.jsx
@@ -49,7 +49,7 @@ const defaultAppConfig = (divideDiscussionIds = []) => ({
reportedContentEmailNotifications: false,
enableReportedContentEmailNotifications: false,
allowDivisionByUnit: false,
- blackoutDates: [],
+ restrictedDates: [],
cohortsEnabled: false,
});
describe('OpenedXConfigForm', () => {
@@ -169,8 +169,8 @@ describe('OpenedXConfigForm', () => {
expect(container.querySelector('#reportedContentEmailNotifications')).toBeInTheDocument();
expect(container.querySelector('#reportedContentEmailNotifications')).not.toBeChecked();
- // BlackoutDatesField
- expect(queryByText(container, messages.blackoutDatesLabel.defaultMessage)).toBeInTheDocument();
+ // Discussion Restriction Field
+ expect(queryByText(container, messages.discussionRestrictionLabel.defaultMessage)).toBeInTheDocument();
});
test('folded sub-fields are in the DOM when parents are enabled', async () => {
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/shared/BlackoutDatesField.jsx b/src/pages-and-resources/discussions/app-config-form/apps/shared/BlackoutDatesField.jsx
deleted file mode 100644
index 3c6341bf2..000000000
--- a/src/pages-and-resources/discussions/app-config-form/apps/shared/BlackoutDatesField.jsx
+++ /dev/null
@@ -1,95 +0,0 @@
-import React, { useCallback } from 'react';
-import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
-import { Button } from '@edx/paragon';
-import { Add } from '@edx/paragon/icons';
-
-import { FieldArray, useFormikContext } from 'formik';
-import { v4 as uuid } from 'uuid';
-
-import messages from '../../messages';
-import BlackoutDatesItem from './blackout-dates/BlackoutDatesItem';
-import { checkStatus } from '../../utils';
-import { denormalizeBlackoutDate } from '../../../data/api';
-import { blackoutDatesStatus as STATUS } from '../../../data/constants';
-
-const BlackoutDatesField = ({ intl }) => {
- const {
- values: appConfig,
- setFieldValue,
- errors,
- validateForm,
- } = useFormikContext();
- const { blackoutDates } = appConfig;
-
- const handleOnClose = useCallback((index) => {
- const updatedBlackoutDates = [...blackoutDates];
- updatedBlackoutDates[index] = {
- ...updatedBlackoutDates[index],
- status: checkStatus(denormalizeBlackoutDate(updatedBlackoutDates[index])),
- };
- setFieldValue('blackoutDates', updatedBlackoutDates);
- }, [blackoutDates]);
-
- const newBlackoutDateItem = {
- id: uuid(),
- startDate: '',
- startTime: '',
- endDate: '',
- endTime: '',
- status: STATUS.UPCOMING,
- };
-
- const onAddNewItem = async (push) => {
- await push(newBlackoutDateItem);
- validateForm();
- };
- return (
- <>
-
- {intl.formatMessage(messages.blackoutDatesLabel)}
-
-
-
- {intl.formatMessage(messages.blackoutDatesHelp)}
-
-
-
(
-
- {blackoutDates.map((blackoutDate, index) => (
-
remove(index)}
- onClose={() => handleOnClose(index)}
- hasError={Boolean(errors?.blackoutDates?.[index])}
- />
- ))}
-
- onAddNewItem(push)}
- variant="link"
- iconBefore={Add}
- className="text-primary-500 p-0"
- >
- {intl.formatMessage(messages.addBlackoutDatesButton)}
-
-
-
- )}
- />
-
- >
- );
-};
-
-BlackoutDatesField.propTypes = {
- intl: intlShape.isRequired,
-};
-
-export default injectIntl(BlackoutDatesField);
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/shared/DiscussionRestriction.jsx b/src/pages-and-resources/discussions/app-config-form/apps/shared/DiscussionRestriction.jsx
new file mode 100644
index 000000000..691993268
--- /dev/null
+++ b/src/pages-and-resources/discussions/app-config-form/apps/shared/DiscussionRestriction.jsx
@@ -0,0 +1,137 @@
+import React, { useCallback, useState } from 'react';
+import { injectIntl, useIntl } from '@edx/frontend-platform/i18n';
+import { Button, ButtonGroup } from '@edx/paragon';
+import { Add } from '@edx/paragon/icons';
+
+import { FieldArray, useFormikContext } from 'formik';
+import { v4 as uuid } from 'uuid';
+import ConfirmationPopup from '../../../../../generic/ConfirmationPopup';
+
+import messages from '../../messages';
+import DiscussionRestrictionItem from './discussion-restrictions/DiscussionRestrictionItem';
+import { checkStatus } from '../../utils';
+import { denormalizeRestrictedDate } from '../../../data/api';
+import { restrictedDatesStatus as STATUS, discussionRestrictionOptions } from '../../../data/constants';
+import DiscussionRestrictionOption from './discussion-restrictions/DiscussionRestrictionOption';
+
+const DiscussionRestriction = () => {
+ const {
+ values: appConfig,
+ setFieldValue,
+ errors,
+ validateForm,
+ } = useFormikContext();
+
+ const intl = useIntl();
+ const { restrictedDates } = appConfig;
+ const [selectedOption, setSelectedOption] = useState('');
+
+ const handleOnClose = useCallback((index) => {
+ const updatedRestrictedDates = [...restrictedDates];
+ updatedRestrictedDates[index] = {
+ ...updatedRestrictedDates[index],
+ status: checkStatus(denormalizeRestrictedDate(updatedRestrictedDates[index])),
+ };
+ setFieldValue('restrictedDates', updatedRestrictedDates);
+ }, [restrictedDates]);
+
+ const newRestrictedDateItem = {
+ id: uuid(),
+ startDate: '',
+ startTime: '',
+ endDate: '',
+ endTime: '',
+ status: STATUS.UPCOMING,
+ };
+
+ const onAddNewItem = useCallback(async (push) => {
+ await push(newRestrictedDateItem);
+ validateForm();
+ }, []);
+
+ const handleClick = useCallback((value) => {
+ setSelectedOption(value);
+ }, []);
+
+ const handleCancel = useCallback(() => {
+ setSelectedOption('');
+ }, []);
+
+ return (
+
+
+ {intl.formatMessage(messages.discussionRestrictionLabel)}
+
+
+ {discussionRestrictionOptions.map((option) => (
+ {option.label}
+
+
+ ))}
+
+ {(selectedOption === 'on' || selectedOption === 'off') && (
+
+ {intl.formatMessage(messages.discussionRestrictionHelp)}
+
+ )}
+
+ {selectedOption === 'on' && (
+
+ )}
+
+ {selectedOption === 'scheduled' && (
+
+
+ {intl.formatMessage(messages.discussionRestrictionDatesHelp)}
+
+
(
+
+ {restrictedDates.map((restrictedDate, index) => (
+
remove(index)}
+ onClose={() => handleOnClose(index)}
+ hasError={Boolean(errors?.restrictedDates?.[index])}
+ />
+ ))}
+
+ onAddNewItem(push)}
+ variant="link"
+ iconBefore={Add}
+ className="text-primary-500 p-0"
+ style={{ height: 28 }}
+ >
+ {intl.formatMessage(messages.addRestrictedDatesButton)}
+
+
+
+ )}
+ />
+
+ )}
+
+ );
+};
+
+export default injectIntl(React.memo(DiscussionRestriction));
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/shared/blackout-dates/CollapseCardHeading.jsx b/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-restrictions/CollapseCardHeading.jsx
similarity index 70%
rename from src/pages-and-resources/discussions/app-config-form/apps/shared/blackout-dates/CollapseCardHeading.jsx
rename to src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-restrictions/CollapseCardHeading.jsx
index 428516047..8bd6c8df1 100644
--- a/src/pages-and-resources/discussions/app-config-form/apps/shared/blackout-dates/CollapseCardHeading.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-restrictions/CollapseCardHeading.jsx
@@ -14,9 +14,9 @@ const CollapseCardHeading = ({
}
return (
-
- {badgeStatus &&
{badgeStatus}}
-
{collapseHeadingText}
+
+ {badgeStatus &&
{badgeStatus}}
+
{collapseHeadingText}
);
};
@@ -34,4 +34,4 @@ CollapseCardHeading.defaultProps = {
badgeStatus: '',
};
-export default CollapseCardHeading;
+export default React.memo(CollapseCardHeading);
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/shared/blackout-dates/BlackoutDatesItem.jsx b/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-restrictions/DiscussionRestrictionItem.jsx
similarity index 56%
rename from src/pages-and-resources/discussions/app-config-form/apps/shared/blackout-dates/BlackoutDatesItem.jsx
rename to src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-restrictions/DiscussionRestrictionItem.jsx
index 32b1317dc..e7661cf53 100644
--- a/src/pages-and-resources/discussions/app-config-form/apps/shared/blackout-dates/BlackoutDatesItem.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-restrictions/DiscussionRestrictionItem.jsx
@@ -1,106 +1,116 @@
-import React, { useState } from 'react';
-import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
+import React, { useState, useCallback } from 'react';
+import { useIntl } from '@edx/frontend-platform/i18n';
import { Form } from '@edx/paragon';
import { useFormikContext } from 'formik';
import PropTypes from 'prop-types';
import _ from 'lodash';
import messages from '../../../messages';
-import BlackoutDatesInput from './BlackoutDatesInput';
-import { formatBlackoutDates } from '../../../utils';
+import RestrictDatesInput from './RestrictDatesInput';
+import { formatRestrictedDates } from '../../../utils';
import {
- blackoutDatesStatus as constants,
- deleteHelperText,
+ restrictedDatesStatus as constants,
+ deleteRestrictedDatesHelperText,
badgeVariant,
} from '../../../../data/constants';
import CollapsableEditor from '../../../../../../generic/CollapsableEditor';
import ConfirmationPopup from '../../../../../../generic/ConfirmationPopup';
import CollapseCardHeading from './CollapseCardHeading';
-const BlackoutDatesItem = ({
- intl,
- blackoutDate,
+const DiscussionRestrictionItem = ({
+ restrictedDate,
onDelete,
hasError,
onClose,
fieldNameCommonBase,
}) => {
- const blackoutDateError = !blackoutDate.startDate || !blackoutDate.endDate || hasError;
+ const restrictedDateError = !restrictedDate.startDate || !restrictedDate.endDate || hasError;
const [showDeletePopup, setShowDeletePopup] = useState(false);
- const [collapseIsOpen, setCollapseOpen] = useState(blackoutDateError);
+ const [collapseIsOpen, setCollapseOpen] = useState(restrictedDateError);
const { setFieldTouched } = useFormikContext();
+ const intl = useIntl();
- const handleToggle = (isOpen) => {
+ const handleToggle = useCallback((isOpen) => {
if (!isOpen && hasError) {
return setCollapseOpen(true);
}
return setCollapseOpen(isOpen);
- };
+ }, [hasError]);
- const getHeading = (isOpen) => (
-
- );
-
- if (showDeletePopup) {
- return (
-
setShowDeletePopup(false)}
- cancelLabel={intl.formatMessage(messages.cancelButton)}
- />
- );
- }
-
- const handleOnClose = () => {
+ const handleOnClose = useCallback(() => {
['startDate', 'startTime', 'endDate', 'endTime'].forEach(field => (
setFieldTouched(`${fieldNameCommonBase}.${field}`, true)
));
if (!hasError) {
onClose();
}
- };
+ }, [hasError, onClose]);
+
+ const getHeading = useCallback((isOpen) => (
+
+ ), [restrictedDate]);
+
+ const handleShowDeletePopup = useCallback(() => {
+ setShowDeletePopup(true);
+ }, []);
+
+ const handleCancelDeletePopup = useCallback(() => {
+ setShowDeletePopup(false);
+ }, []);
+
+ if (showDeletePopup) {
+ return (
+
+ );
+ }
return (
setShowDeletePopup(true)}
+ onDelete={handleShowDeletePopup}
expandAlt={intl.formatMessage(messages.expandAltText)}
collapseAlt={intl.formatMessage(messages.collapseAltText)}
deleteAlt={intl.formatMessage(messages.deleteAltText)}
- data-testid={blackoutDate.id}
- onClose={() => handleOnClose()}
+ data-testid={restrictedDate.id}
+ onClose={handleOnClose}
>
-
-
-
- (
+ onClick(value)}
+ style={{ padding: '8px 12px', fontWeight: 500 }}
+ >
+ {label}
+
+ );
+
+DiscussionRestrictionOption.propTypes = {
+ value: PropTypes.string.isRequired,
+ label: PropTypes.string.isRequired,
+ onClick: PropTypes.func.isRequired,
+ selectedOption: PropTypes.string.isRequired,
+};
+
+export default React.memo(DiscussionRestrictionOption);
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/shared/blackout-dates/BlackoutDatesInput.jsx b/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-restrictions/RestrictDatesInput.jsx
similarity index 81%
rename from src/pages-and-resources/discussions/app-config-form/apps/shared/blackout-dates/BlackoutDatesInput.jsx
rename to src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-restrictions/RestrictDatesInput.jsx
index 0c88a132c..1509d794d 100644
--- a/src/pages-and-resources/discussions/app-config-form/apps/shared/blackout-dates/BlackoutDatesInput.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-restrictions/RestrictDatesInput.jsx
@@ -1,11 +1,11 @@
-import React, { useState } from 'react';
+import React, { useState, useCallback } from 'react';
import { Form } from '@edx/paragon';
import { useFormikContext, getIn } from 'formik';
import PropTypes from 'prop-types';
import FieldFeedback from '../../../../../../generic/FieldFeedback';
-const BlackoutDatesInput = ({
+const RestictDatesInput = ({
value,
type,
label,
@@ -25,10 +25,14 @@ const BlackoutDatesInput = ({
const fieldTouched = getIn(touched, `${fieldNameCommonBase}.${fieldName}`);
const isInvalidInput = Boolean(!inFocus && fieldError && fieldTouched);
- const handleFocusOut = (event) => {
+ const handleFocusOut = useCallback((event) => {
handleBlur(event);
setInFocus(false);
- };
+ }, [handleBlur, setInFocus]);
+
+ const handleSetFocus = useCallback(() => {
+ setInFocus(true);
+ }, [setInFocus]);
return (
handleFocusOut(event)}
- onFocus={() => setInFocus(true)}
+ onBlur={handleFocusOut}
+ onFocus={handleSetFocus}
/>
(
array.filter(item => item[key] !== value)
@@ -47,7 +47,7 @@ export const decodeDateTime = (date, time) => {
return moment(mergeDateTime(nDate, nTime));
};
-export const sortBlackoutDatesByStatus = (data, status, order) => (
+export const sortRestrictedDatesByStatus = (data, status, order) => (
_.orderBy(
data.filter(date => date.status === status),
[(obj) => decodeDateTime(obj.startDate, startOfDayTime(obj.startTime))],
@@ -55,7 +55,7 @@ data.filter(date => date.status === status),
)
);
-export const formatBlackoutDates = ({
+export const formatRestrictedDates = ({
startDate, startTime, endDate, endTime,
}) => {
let formattedDate;
diff --git a/src/pages-and-resources/discussions/app-list/AppList.scss b/src/pages-and-resources/discussions/app-list/AppList.scss
index 40e2a3c73..3aa109914 100644
--- a/src/pages-and-resources/discussions/app-list/AppList.scss
+++ b/src/pages-and-resources/discussions/app-list/AppList.scss
@@ -25,3 +25,53 @@
}
}
}
+
+.height-36{
+ height: 2.25rem !important;
+}
+.line-height-20{
+ line-height: 1.25rem !important;
+}
+.font-size-14{
+ font-size: 14px !important;
+}
+
+.discussion-restriction{
+ .unselected-button{
+ &:hover{
+ background: #e9e6e4 !important;
+ }
+ }
+ .action-btn{
+ padding: 10px 16px;
+ width: 80px;
+ height: 44px;
+ font-weight: 500;
+ font-size: 18px;
+ line-height: 24px;
+ }
+ .w-92{
+ width: 92px;
+ }
+ .card-body-section{
+ padding-top: 12px !important;
+ padding-bottom: 20px !important;
+ }
+ .form-control{
+ border-radius: 0px !important;
+ font-weight: 400;
+ font-size: 14px;
+ line-height: 24px;
+ }
+ .collapsible-card{
+ padding: 14px 14px 14px 24px !important;
+ min-height:100px;
+ .collapsible-trigger{
+ padding: 0px !important;
+ .badge{
+ font-size: 12px;
+ line-height: 20px;
+ }
+ }
+ }
+}
diff --git a/src/pages-and-resources/discussions/data/api.js b/src/pages-and-resources/discussions/data/api.js
index 0b272c474..20122c7f7 100644
--- a/src/pages-and-resources/discussions/data/api.js
+++ b/src/pages-and-resources/discussions/data/api.js
@@ -10,10 +10,10 @@ import {
mergeDateTime,
normalizeDate,
normalizeTime,
- sortBlackoutDatesByStatus,
+ sortRestrictedDatesByStatus,
startOfDayTime,
} from '../app-config-form/utils';
-import { blackoutDatesStatus as constants } from './constants';
+import { restrictedDatesStatus as constants } from './constants';
ensureConfig([
'STUDIO_BASE_URL',
@@ -31,7 +31,7 @@ function normalizeLtiConfig(data) {
};
}
-export function normalizeBlackoutDates(data) {
+export function normalizeRestrictedDates(data) {
if (!data || Object.keys(data).length < 1) {
return [];
}
@@ -46,9 +46,9 @@ export function normalizeBlackoutDates(data) {
}));
return [
- ...sortBlackoutDatesByStatus(normalizeData, constants.ACTIVE, 'desc'),
- ...sortBlackoutDatesByStatus(normalizeData, constants.UPCOMING, 'asc'),
- ...sortBlackoutDatesByStatus(normalizeData, constants.COMPLETE, 'desc'),
+ ...sortRestrictedDatesByStatus(normalizeData, constants.ACTIVE, 'desc'),
+ ...sortRestrictedDatesByStatus(normalizeData, constants.UPCOMING, 'asc'),
+ ...sortRestrictedDatesByStatus(normalizeData, constants.COMPLETE, 'desc'),
];
}
@@ -66,7 +66,7 @@ function normalizePluginConfig(data) {
enableReportedContentEmailNotifications: data.reported_content_email_notifications_flag,
divisionScheme: data.division_scheme,
alwaysDivideInlineDiscussions: data.always_divide_inline_discussions,
- blackoutDates: normalizeBlackoutDates(data.discussion_blackouts),
+ restrictedDates: normalizeRestrictedDates(data.discussion_blackouts),
allowDivisionByUnit: false,
divideByCohorts: enableDivideByCohorts,
divideCourseTopicsByCohorts: enableDivideCourseTopicsByCohorts,
@@ -155,15 +155,15 @@ function normalizeSettings(data) {
};
}
-export function denormalizeBlackoutDate(blackoutPeriod) {
+export function denormalizeRestrictedDate(restrictedPeriod) {
return [
mergeDateTime(
- normalizeDate(blackoutPeriod.startDate),
- normalizeTime(startOfDayTime(blackoutPeriod.startTime)),
+ normalizeDate(restrictedPeriod.startDate),
+ normalizeTime(startOfDayTime(restrictedPeriod.startTime)),
),
mergeDateTime(
- normalizeDate(blackoutPeriod.endDate),
- normalizeTime(endOfDayTime(blackoutPeriod.endTime)),
+ normalizeDate(restrictedPeriod.endDate),
+ normalizeTime(endOfDayTime(restrictedPeriod.endTime)),
),
];
}
@@ -187,11 +187,11 @@ function denormalizeData(courseId, appId, data) {
if ('groupAtSubsection' in data) {
pluginConfiguration.group_at_subsection = data.groupAtSubsection;
}
- if (data.blackoutDates?.length) {
- pluginConfiguration.discussion_blackouts = data.blackoutDates.map((blackoutDates) => (
- denormalizeBlackoutDate(blackoutDates)
+ if (data.restrictedDates?.length) {
+ pluginConfiguration.discussion_blackouts = data.restrictedDates.map((restrictedDates) => (
+ denormalizeRestrictedDate(restrictedDates)
));
- } else if (data.blackoutDates?.length === 0) {
+ } else if (data.restrictedDates?.length === 0) {
pluginConfiguration.discussion_blackouts = [];
}
if (data.discussionTopics?.length) {
diff --git a/src/pages-and-resources/discussions/data/constants.js b/src/pages-and-resources/discussions/data/constants.js
index 98215bb2f..a87c48639 100644
--- a/src/pages-and-resources/discussions/data/constants.js
+++ b/src/pages-and-resources/discussions/data/constants.js
@@ -2,7 +2,7 @@ import moment from 'moment';
import messages from '../app-config-form/messages';
-export const blackoutDatesStatus = {
+export const restrictedDatesStatus = {
UPCOMING: 'UPCOMING',
COMPLETE: 'COMPLETE',
ACTIVE: 'ACTIVE',
@@ -14,12 +14,42 @@ export const badgeVariant = {
ACTIVE: 'success',
};
-export const deleteHelperText = {
- UPCOMING: messages.blackoutDatesDeletionHelp,
- COMPLETE: messages.completeBlackoutDatesDeletionHelp,
- ACTIVE: messages.activeBlackoutDatesDeletionHelp,
+export const deleteRestrictedDatesHelperText = {
+ UPCOMING: messages.restrictedDatesDeletionHelp,
+ COMPLETE: messages.completeRestrictedDatesDeletionHelp,
+ ACTIVE: messages.activeRestrictedDatesDeletionHelp,
};
+export const discussionRestriction = {
+ OFF: 'off',
+ ON: 'on',
+ SCHEDULED: 'scheduled',
+};
+
+export const discussionRestrictionLabel = {
+ [discussionRestriction.OFF]: 'Off',
+ [discussionRestriction.ON]: 'On',
+ [discussionRestriction.SCHEDULED]: 'Scheduled',
+};
+
+export const discussionRestrictionOptions = [
+ {
+ value: discussionRestriction.OFF,
+ description: messages.discussionRestrictionOffLabel,
+ label: discussionRestrictionLabel[discussionRestriction.OFF],
+ },
+ {
+ value: discussionRestriction.ON,
+ description: messages.discussionRestrictionOnLabel,
+ label: discussionRestrictionLabel[discussionRestriction.ON],
+ },
+ {
+ value: discussionRestriction.SCHEDULED,
+ description: messages.discussionRestrictionScheduledLabel,
+ label: discussionRestrictionLabel[discussionRestriction.SCHEDULED],
+ },
+];
+
export const today = moment();
export const active = [today.format('YYYY-MM-DDTHH:mm'), today.add(5, 'hours').format('YYYY-MM-DDTHH:mm')];
export const upcoming = [today.add(2, 'days').format('YYYY-MM-DD'), today.add(5, 'days').format('YYYY-MM-DD')];
diff --git a/src/pages-and-resources/discussions/data/redux.test.js b/src/pages-and-resources/discussions/data/redux.test.js
index cc464db36..9eb72e023 100644
--- a/src/pages-and-resources/discussions/data/redux.test.js
+++ b/src/pages-and-resources/discussions/data/redux.test.js
@@ -244,7 +244,7 @@ describe('Data layer integration tests', () => {
allowAnonymousPostsPeers: false,
reportedContentEmailNotifications: false,
enableReportedContentEmailNotifications: false,
- blackoutDates: [],
+ restrictedDates: [],
// TODO: Note! As of this writing, all the data below this line is NOT returned in the API
// but we add it in during normalization.
divisionScheme: DivisionSchemes.COHORT,
@@ -449,7 +449,7 @@ describe('Data layer integration tests', () => {
allowAnonymousPosts: true,
allowAnonymousPostsPeers: true,
reportedContentEmailNotifications: true,
- blackoutDates: [],
+ restrictedDates: [],
// TODO: Note! As of this writing, all the data below this line is NOT returned in the API
// but we technically send it to the thunk, so here it is.
divideByCohorts: true,
@@ -486,7 +486,7 @@ describe('Data layer integration tests', () => {
allowAnonymousPostsPeers: true,
reportedContentEmailNotifications: true,
alwaysDivideInlineDiscussions: true,
- blackoutDates: [],
+ restrictedDates: [],
// TODO: Note! The values we tried to save were ignored, this test reflects what currently
// happens, but NOT what we want to have happen!
divideByCohorts: true,