diff --git a/docs/decisions/0005-moment-to-dayjs.rst b/docs/decisions/0005-moment-to-dayjs.rst new file mode 100644 index 0000000000..edc8a2cdf3 --- /dev/null +++ b/docs/decisions/0005-moment-to-dayjs.rst @@ -0,0 +1,46 @@ +5. Replacing Moment.js library with Day.js +============================================================ + +Status +****** + +In progress + +Context +******* + +Moment.js is a widely used time and date library, but the creators have decided to make it a legacy project that no +longer fixes bugs or adds new features. Because of this, and because of the large size that the Moment.js package takes up +(4.23 MB according to npm and the minified size is 6.3KB), we are choosing to replace all instances of Moment.js +in our enterprise repositories. + +Decisions +********* + +In its stead, we are choosing to replace this library with the Day.js project. This is one of the projects that were +explicitly recommended from the Moment.js team as a recommended alternative. Out of the box, it supports basic usage, +and additional plugins have been identified based on a look through our current usages of Moment.js in our codebase. +The plugins that we will need to add are Duration, UTC, and Timezone, with more possibilities available for future use. + +Day.js also has almost identical functions to Moment, and was definitely created with this in mind. So most files will +just need to replace the package name and nothing else + +``moment(date).format('MMMM D, YYYY') -> dayjs(date).format('MMMM D, YYYY')`` + +Consequences +************ + +By choosing Day.js over another, larger library like date-fns, we sacrifice more of the out of the box functionality +that comes from having a bigger library. Also, day.js does not support tree-shaking like the date-fns library does. +However, by only installing needed plugins and starting from a much smaller package size, Day.js will considerably +decrease the JS bundle size while still maintaining the core functionality. + +Alternatives Considered +*********************** + +date-fns +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Date-fns has a 162.1 kB bundle size compared to 6.4 kB of day.js bundle. Since the majority of the functionality +we are using with these libraries is basic, and the intended goal is to ultimately decrease the bundle size, +opting for the more lightweight library was the preferred path forward. \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7cb996d04f..ea06117091 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,11 +17,6 @@ "@edx/frontend-enterprise-utils": "3.2.0", "@edx/frontend-platform": "4.0.1", "@edx/paragon": "20.39.2", - "@fortawesome/fontawesome-svg-core": "1.2.35", - "@fortawesome/free-brands-svg-icons": "5.15.3", - "@fortawesome/free-regular-svg-icons": "5.15.3", - "@fortawesome/free-solid-svg-icons": "5.15.3", - "@fortawesome/react-fontawesome": "0.1.14", "algoliasearch": "4.8.3", "axios-mock-adapter": "1.19.0", "classnames": "2.2.6", @@ -29,6 +24,7 @@ "color-contrast-checker": "^2.1.0", "core-js": "3.7.0", "dash-embedded-component": "file:packages/dash-embedded-component-2.0.2.tgz", + "dayjs": "^1.11.9", "file-saver": "1.3.8", "font-awesome": "4.7.0", "frontend-platform-shim": "file:packages/frontend-platform-shim", @@ -37,7 +33,6 @@ "jest-environment-jsdom": "26.6.1", "lodash": "4.17.21", "lodash.debounce": "4.0.8", - "moment": "2.27.0", "prop-types": "15.7.2", "react": "16.14.0", "react-dom": "16.13.1", @@ -3994,6 +3989,7 @@ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz", "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==", "hasInstallScript": true, + "peer": true, "engines": { "node": ">=6" } @@ -4003,30 +3999,7 @@ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.35.tgz", "integrity": "sha512-uLEXifXIL7hnh2sNZQrIJWNol7cTVIzwI+4qcBIq9QWaZqUblm0IDrtSqbNg+3SQf8SMGHkiSigD++rHmCHjBg==", "hasInstallScript": true, - "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.2.35" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/free-brands-svg-icons": { - "version": "5.15.3", - "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.3.tgz", - "integrity": "sha512-1hirPcbjj72ZJtFvdnXGPbAbpn3Ox6mH3g5STbANFp3vGSiE5u5ingAKV06mK6ZVqNYxUPlh4DlTnaIvLtF2kw==", - "hasInstallScript": true, - "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.2.35" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/free-regular-svg-icons": { - "version": "5.15.3", - "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.3.tgz", - "integrity": "sha512-q4/p8Xehy9qiVTdDWHL4Z+o5PCLRChePGZRTXkl+/Z7erDVL8VcZUuqzJjs6gUz6czss4VIPBRdCz6wP37/zMQ==", - "hasInstallScript": true, + "peer": true, "dependencies": { "@fortawesome/fontawesome-common-types": "^0.2.35" }, @@ -4039,6 +4012,7 @@ "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.3.tgz", "integrity": "sha512-XPeeu1IlGYqz4VWGRAT5ukNMd4VHUEEJ7ysZ7pSSgaEtNvSo+FLurybGJVmiqkQdK50OkSja2bfZXOeyMGRD8Q==", "hasInstallScript": true, + "peer": true, "dependencies": { "@fortawesome/fontawesome-common-types": "^0.2.35" }, @@ -4050,6 +4024,7 @@ "version": "0.1.14", "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.14.tgz", "integrity": "sha512-4wqNb0gRLVaBm/h+lGe8UfPPivcbuJ6ecI4hIgW0LjI7kzpYB9FkN0L9apbVzg+lsBdcTf0AlBtODjcSX5mmKA==", + "peer": true, "dependencies": { "prop-types": "^15.7.2" }, @@ -9285,6 +9260,11 @@ "node": ">=10" } }, + "node_modules/dayjs": { + "version": "1.11.9", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz", + "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -16838,14 +16818,6 @@ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, - "node_modules/moment": { - "version": "2.27.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", - "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==", - "engines": { - "node": "*" - } - }, "node_modules/moo": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", diff --git a/package.json b/package.json index b38707ffd8..c358cbf26d 100644 --- a/package.json +++ b/package.json @@ -33,11 +33,6 @@ "@edx/frontend-enterprise-utils": "3.2.0", "@edx/frontend-platform": "4.0.1", "@edx/paragon": "20.39.2", - "@fortawesome/fontawesome-svg-core": "1.2.35", - "@fortawesome/free-brands-svg-icons": "5.15.3", - "@fortawesome/free-regular-svg-icons": "5.15.3", - "@fortawesome/free-solid-svg-icons": "5.15.3", - "@fortawesome/react-fontawesome": "0.1.14", "algoliasearch": "4.8.3", "axios-mock-adapter": "1.19.0", "classnames": "2.2.6", @@ -45,6 +40,7 @@ "color-contrast-checker": "^2.1.0", "core-js": "3.7.0", "dash-embedded-component": "file:packages/dash-embedded-component-2.0.2.tgz", + "dayjs": "^1.11.9", "file-saver": "1.3.8", "font-awesome": "4.7.0", "frontend-platform-shim": "file:packages/frontend-platform-shim", @@ -53,7 +49,6 @@ "jest-environment-jsdom": "26.6.1", "lodash": "4.17.21", "lodash.debounce": "4.0.8", - "moment": "2.27.0", "prop-types": "15.7.2", "react": "16.14.0", "react-dom": "16.13.1", diff --git a/src/components/Admin/AdminCards.jsx b/src/components/Admin/AdminCards.jsx index d1afe4ac95..b367dff596 100644 --- a/src/components/Admin/AdminCards.jsx +++ b/src/components/Admin/AdminCards.jsx @@ -2,6 +2,9 @@ import React from 'react'; import PropTypes from 'prop-types'; import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; +import { + Award, Check, Groups, RemoveRedEye, +} from '@edx/paragon/icons'; import NumberCard from '../NumberCard'; @@ -17,7 +20,7 @@ class AdminCards extends React.Component { id: 'adminPortal.cards.registeredLearners', defaultMessage: 'total number of learners registered', }), - iconClassName: 'fa fa-users', + icon: Groups, actions: [{ label: intl.formatMessage({ id: 'adminPortal.cards.registeredUnenrolledLearners', @@ -32,7 +35,7 @@ class AdminCards extends React.Component { id: 'adminPortal.cards.enrolledOneCourse', defaultMessage: 'learners enrolled in at least one course', }), - iconClassName: 'fa fa-check', + icon: Check, actions: [{ label: intl.formatMessage({ id: 'adminPortal.cards.enrolledLearners', @@ -53,7 +56,7 @@ class AdminCards extends React.Component { id: 'adminPortal.cards.activeLearnersPastWeek', defaultMessage: 'active learners in the past week', }), - iconClassName: 'fa fa-eye', + icon: RemoveRedEye, actions: [{ label: intl.formatMessage({ id: 'adminPortal.cards.learnersActiveWeek', @@ -77,7 +80,7 @@ class AdminCards extends React.Component { courseCompletions: { ref: React.createRef(), description: 'course completions', - iconClassName: 'fa fa-trophy', + icon: Award, actions: [{ label: intl.formatMessage({ id: 'adminPortal.cards.completedLearners', @@ -107,7 +110,7 @@ class AdminCards extends React.Component { id={cardKey} title={title} description={card.description} - iconClassName={card.iconClassName} + icon={card.icon} detailActions={card.actions} /> diff --git a/src/components/Admin/AdminSearchForm.jsx b/src/components/Admin/AdminSearchForm.jsx index 92d14f7ed8..3fcec0a454 100644 --- a/src/components/Admin/AdminSearchForm.jsx +++ b/src/components/Admin/AdminSearchForm.jsx @@ -1,10 +1,10 @@ /* eslint-disable camelcase */ import React from 'react'; -import moment from 'moment'; +import dayjs from 'dayjs'; import PropTypes from 'prop-types'; -import { faInfoCircle } from '@fortawesome/free-solid-svg-icons'; import { Form } from '@edx/paragon'; +import { Info } from '@edx/paragon/icons'; import SearchBar from '../SearchBar'; import { updateUrl } from '../../utils'; @@ -80,7 +80,7 @@ class AdminSearchForm extends React.Component { Filter by start date @@ -101,7 +101,7 @@ class AdminSearchForm extends React.Component { value={date} key={date} > - {moment(date).format('MMMM D, YYYY')} + {dayjs(date).format('MMMM D, YYYY')} ))} diff --git a/src/components/Admin/EmbeddedSubscription.jsx b/src/components/Admin/EmbeddedSubscription.jsx index 22d73e3a28..24bf7575bc 100644 --- a/src/components/Admin/EmbeddedSubscription.jsx +++ b/src/components/Admin/EmbeddedSubscription.jsx @@ -1,7 +1,7 @@ import React, { useContext, useState } from 'react'; +import dayjs from 'dayjs'; import { useParams, Link } from 'react-router-dom'; import { Form, Icon } from '@edx/paragon'; -import moment from 'moment'; import { Lightbulb, ArrowOutward } from '@edx/paragon/icons'; import ConnectedSubscriptionDetailPage from './SubscriptionDetailPage'; import { SubscriptionContext } from '../subscriptions/SubscriptionData'; @@ -15,7 +15,7 @@ const EmbeddedSubscription = () => { const [subscriptionUUID, setSubscriptionUUID] = useState(null); const [firstLoad, setFirstLoad] = useState(true); const sortedSubscriptions = sortSubscriptionsByStatus(subscriptions); - const activeSubscriptions = sortedSubscriptions.filter(c => !moment().isAfter(c.expirationDate)); + const activeSubscriptions = sortedSubscriptions.filter(c => !dayjs().isAfter(c.expirationDate)); const match = { params: { subscriptionUUID } }; if (!loading && activeSubscriptions.length > 0 && firstLoad) { match.params.subscriptionUUID = activeSubscriptions[0].uuid; diff --git a/src/components/Admin/SubscriptionDetails.jsx b/src/components/Admin/SubscriptionDetails.jsx index 71d556ac3e..2c94bedf5b 100644 --- a/src/components/Admin/SubscriptionDetails.jsx +++ b/src/components/Admin/SubscriptionDetails.jsx @@ -1,7 +1,7 @@ import React, { useContext, useState } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; -import moment from 'moment'; +import dayjs from 'dayjs'; import { Row, Col, Toast, Button, } from '@edx/paragon'; @@ -37,7 +37,7 @@ const SubscriptionDetails = ({ enterpriseSlug }) => {
- {moment(subscription.startDate).format('MMMM D, YYYY')} - {moment(subscription.expirationDate).format('MMMM D, YYYY')} + {dayjs(subscription.startDate).format('MMMM D, YYYY')} - {dayjs(subscription.expirationDate).format('MMMM D, YYYY')}
diff --git a/src/components/Admin/__snapshots__/Admin.test.jsx.snap b/src/components/Admin/__snapshots__/Admin.test.jsx.snap index 13fb8a3fa2..fd763719cf 100644 --- a/src/components/Admin/__snapshots__/Admin.test.jsx.snap +++ b/src/components/Admin/__snapshots__/Admin.test.jsx.snap @@ -219,10 +219,24 @@ exports[` renders correctly with dashboard analytics data renders # cou 3 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders # cou

- - Show details + + + + + Show details +
@@ -312,10 +340,24 @@ exports[` renders correctly with dashboard analytics data renders # cou 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders # cou

- - Show details + + + + + Show details +
@@ -421,10 +477,24 @@ exports[` renders correctly with dashboard analytics data renders # cou 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders # cou

- - Show details + + + + + Show details +
@@ -546,10 +630,24 @@ exports[` renders correctly with dashboard analytics data renders # cou 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders # cou

- - Show details + + + + + Show details +
@@ -682,10 +794,24 @@ exports[` renders correctly with dashboard analytics data renders # cou onClick={[Function]} > + className="pgn__icon mr-2" + > + + + + Reset to Full Report @@ -724,11 +850,19 @@ exports[` renders correctly with dashboard analytics data renders # cou onClick={[Function]} type="button" > - + + + Download current report (CSV) @@ -798,10 +932,24 @@ exports[` renders correctly with dashboard analytics data renders # of 3 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders # of

- - Show details + + + + + Show details +
@@ -891,10 +1053,24 @@ exports[` renders correctly with dashboard analytics data renders # of 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders # of

- - Show details + + + + + Show details +
@@ -1000,10 +1190,24 @@ exports[` renders correctly with dashboard analytics data renders # of 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders # of

- - Show details + + + + + Show details +
@@ -1125,10 +1343,24 @@ exports[` renders correctly with dashboard analytics data renders # of 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders # of

- - Show details + + + + + Show details +
@@ -1261,10 +1507,24 @@ exports[` renders correctly with dashboard analytics data renders # of onClick={[Function]} > + className="pgn__icon mr-2" + > + + + + Reset to Full Report @@ -1303,11 +1563,19 @@ exports[` renders correctly with dashboard analytics data renders # of onClick={[Function]} type="button" > - + + + Download current report (CSV) @@ -1377,10 +1645,24 @@ exports[` renders correctly with dashboard analytics data renders # of 3 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders # of

- - Show details + + + + + Show details +
@@ -1470,10 +1766,24 @@ exports[` renders correctly with dashboard analytics data renders # of 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders # of

- - Show details + + + + + Show details +
@@ -1579,10 +1903,24 @@ exports[` renders correctly with dashboard analytics data renders # of 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders # of

- - Show details + + + + + Show details +
@@ -1704,10 +2056,24 @@ exports[` renders correctly with dashboard analytics data renders # of 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders # of

- - Show details + + + + + Show details +
@@ -1840,10 +2220,24 @@ exports[` renders correctly with dashboard analytics data renders # of onClick={[Function]} > + className="pgn__icon mr-2" + > + + + + Reset to Full Report @@ -1886,11 +2280,19 @@ exports[` renders correctly with dashboard analytics data renders # of onClick={[Function]} type="button" > - + + + Download current report (CSV) @@ -1960,10 +2362,24 @@ exports[` renders correctly with dashboard analytics data renders colla 3 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders colla

- - Show details + + + + + Show details +
@@ -2053,10 +2483,24 @@ exports[` renders correctly with dashboard analytics data renders colla 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders colla

- - Show details + + + + + Show details +
@@ -2162,10 +2620,24 @@ exports[` renders correctly with dashboard analytics data renders colla 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders colla

- - Show details + + + + + Show details +
@@ -2287,10 +2773,24 @@ exports[` renders correctly with dashboard analytics data renders colla 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders colla

- - Show details + + + + + Show details +
@@ -2451,11 +2965,19 @@ exports[` renders correctly with dashboard analytics data renders colla onClick={[Function]} type="button" > - + + + Download full report (CSV) @@ -2477,7 +2999,7 @@ exports[` renders correctly with dashboard analytics data renders colla > @@ -2486,7 +3008,7 @@ exports[` renders correctly with dashboard analytics data renders colla > renders correctly with dashboard analytics data renders colla > + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders full

- - Show details + + + + + Show details +
@@ -2900,10 +3480,24 @@ exports[` renders correctly with dashboard analytics data renders full 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders full

- - Show details + + + + + Show details +
@@ -3025,10 +3633,24 @@ exports[` renders correctly with dashboard analytics data renders full 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders full

- - Show details + + + + + Show details +
@@ -3189,11 +3825,19 @@ exports[` renders correctly with dashboard analytics data renders full onClick={[Function]} type="button" > - + + + Download full report (CSV) @@ -3215,7 +3859,7 @@ exports[` renders correctly with dashboard analytics data renders full > @@ -3224,7 +3868,7 @@ exports[` renders correctly with dashboard analytics data renders full > renders correctly with dashboard analytics data renders full > + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders inact

- - Show details + + + + + Show details +
@@ -3638,10 +4340,24 @@ exports[` renders correctly with dashboard analytics data renders inact 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders inact

- - Show details + + + + + Show details +
@@ -3763,10 +4493,24 @@ exports[` renders correctly with dashboard analytics data renders inact 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders inact

- - Show details + + + + + Show details +
@@ -3899,10 +4657,24 @@ exports[` renders correctly with dashboard analytics data renders inact onClick={[Function]} > + className="pgn__icon mr-2" + > + + + + Reset to Full Report @@ -3945,11 +4717,19 @@ exports[` renders correctly with dashboard analytics data renders inact onClick={[Function]} type="button" > - + + + Download current report (CSV) @@ -4019,10 +4799,24 @@ exports[` renders correctly with dashboard analytics data renders inact 3 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders inact

- - Show details + + + + + Show details +
@@ -4112,10 +4920,24 @@ exports[` renders correctly with dashboard analytics data renders inact 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders inact

- - Show details + + + + + Show details +
@@ -4221,10 +5057,24 @@ exports[` renders correctly with dashboard analytics data renders inact 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders inact

- - Show details + + + + + Show details +
@@ -4346,10 +5210,24 @@ exports[` renders correctly with dashboard analytics data renders inact 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders inact

- - Show details + + + + + Show details +
@@ -4482,10 +5374,24 @@ exports[` renders correctly with dashboard analytics data renders inact onClick={[Function]} > + className="pgn__icon mr-2" + > + + + + Reset to Full Report @@ -4528,11 +5434,19 @@ exports[` renders correctly with dashboard analytics data renders inact onClick={[Function]} type="button" > - + + + Download current report (CSV) @@ -4602,10 +5516,24 @@ exports[` renders correctly with dashboard analytics data renders learn 3 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders learn

- - Show details + + + + + Show details +
@@ -4695,10 +5637,24 @@ exports[` renders correctly with dashboard analytics data renders learn 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders learn

- - Show details + + + + + Show details +
@@ -4804,10 +5774,24 @@ exports[` renders correctly with dashboard analytics data renders learn 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders learn

- - Show details + + + + + Show details +
@@ -4929,10 +5927,24 @@ exports[` renders correctly with dashboard analytics data renders learn 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders learn

- - Show details + + + + + Show details +
@@ -5065,10 +6091,24 @@ exports[` renders correctly with dashboard analytics data renders learn onClick={[Function]} > + className="pgn__icon mr-2" + > + + + + Reset to Full Report @@ -5111,11 +6151,19 @@ exports[` renders correctly with dashboard analytics data renders learn onClick={[Function]} type="button" > - + + + Download current report (CSV) @@ -5185,10 +6233,24 @@ exports[` renders correctly with dashboard analytics data renders regis 3 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders regis

- - Show details + + + + + Show details +
@@ -5278,10 +6354,24 @@ exports[` renders correctly with dashboard analytics data renders regis 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders regis

- - Show details + + + + + Show details +
@@ -5387,10 +6491,24 @@ exports[` renders correctly with dashboard analytics data renders regis 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders regis

- - Show details + + + + + Show details +
@@ -5512,10 +6644,24 @@ exports[` renders correctly with dashboard analytics data renders regis 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders regis

- - Show details + + + + + Show details +
@@ -5648,10 +6808,24 @@ exports[` renders correctly with dashboard analytics data renders regis onClick={[Function]} > + className="pgn__icon mr-2" + > + + + + Reset to Full Report @@ -5690,11 +6864,19 @@ exports[` renders correctly with dashboard analytics data renders regis onClick={[Function]} type="button" > - + + + Download current report (CSV) @@ -5764,10 +6946,24 @@ exports[` renders correctly with dashboard analytics data renders top a 3 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders top a

- - Show details + + + + + Show details +
@@ -5857,10 +7067,24 @@ exports[` renders correctly with dashboard analytics data renders top a 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders top a

- - Show details + + + + + Show details +
@@ -5966,10 +7204,24 @@ exports[` renders correctly with dashboard analytics data renders top a 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders top a

- - Show details + + + + + Show details +
@@ -6091,10 +7357,24 @@ exports[` renders correctly with dashboard analytics data renders top a 1 + className="pgn__icon d-flex align-items-center justify-content-center" + > + + + +

renders correctly with dashboard analytics data renders top a

- - Show details + + + + + Show details +
@@ -6227,10 +7521,24 @@ exports[` renders correctly with dashboard analytics data renders top a onClick={[Function]} > + className="pgn__icon mr-2" + > + + + + Reset to Full Report @@ -6273,11 +7581,19 @@ exports[` renders correctly with dashboard analytics data renders top a onClick={[Function]} type="button" > - + + + Download current report (CSV) diff --git a/src/components/Admin/index.jsx b/src/components/Admin/index.jsx index 4f95e3e94a..45db4b5059 100644 --- a/src/components/Admin/index.jsx +++ b/src/components/Admin/index.jsx @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import Helmet from 'react-helmet'; import { Alert, Icon } from '@edx/paragon'; -import { Error } from '@edx/paragon/icons'; +import { Error, Undo } from '@edx/paragon/icons'; import { Link } from 'react-router-dom'; import Hero from '../Hero'; @@ -225,7 +225,7 @@ class Admin extends React.Component { return ( - + Reset to {this.getMetadataForAction().title} ); @@ -242,7 +242,7 @@ class Admin extends React.Component { const resetLink = resetQuery ? `${pathname}?${resetQuery}` : pathname; return ( - + Reset Filters ); diff --git a/src/components/Admin/licenses/LicenseManagementTable/index.jsx b/src/components/Admin/licenses/LicenseManagementTable/index.jsx index e39c4fa291..e15ed547ea 100644 --- a/src/components/Admin/licenses/LicenseManagementTable/index.jsx +++ b/src/components/Admin/licenses/LicenseManagementTable/index.jsx @@ -2,17 +2,18 @@ import _ from 'lodash'; import React, { useCallback, useMemo, useContext, useState, } from 'react'; +import PropTypes from 'prop-types'; +import debounce from 'lodash.debounce'; +import dayjs from 'dayjs'; + +import { sendEnterpriseTrackEvent } from '@edx/frontend-enterprise-utils'; import { DataTable, TextFilter, CheckboxFilter, Toast, } from '@edx/paragon'; -import debounce from 'lodash.debounce'; -import moment from 'moment'; -import { sendEnterpriseTrackEvent } from '@edx/frontend-enterprise-utils'; -import PropTypes from 'prop-types'; import { SubscriptionContext } from '../../../subscriptions/SubscriptionData'; import { SubscriptionDetailContext } from '../../../subscriptions/SubscriptionDetailContextProvider'; import { @@ -77,7 +78,7 @@ const LicenseManagementTable = ({ subscriptionUUID }) => { setUserStatusFilter, } = useContext(SubscriptionDetailContext); - const isExpired = moment().isAfter(subscription.expirationDate); + const isExpired = dayjs().isAfter(subscription.expirationDate); const sendStatusFilterEvent = useCallback((statusFilter) => { sendEnterpriseTrackEvent( diff --git a/src/components/BulkEnrollmentPage/table/CourseSearchResultsCells.jsx b/src/components/BulkEnrollmentPage/table/CourseSearchResultsCells.jsx index a0a28d69a3..62a4035ff4 100644 --- a/src/components/BulkEnrollmentPage/table/CourseSearchResultsCells.jsx +++ b/src/components/BulkEnrollmentPage/table/CourseSearchResultsCells.jsx @@ -1,8 +1,8 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { Popover, Button, OverlayTrigger } from '@edx/paragon'; +import dayjs from 'dayjs'; -import moment from 'moment'; +import { Popover, Button, OverlayTrigger } from '@edx/paragon'; import { configuration } from '../../../config'; @@ -51,7 +51,7 @@ CourseNameCell.propTypes = { export const FormattedDateCell = ({ startValue, endValue }) => ( - {moment(startValue).format('MMM D, YYYY')} - {moment(endValue).format('MMM D, YYYY')} + {dayjs(startValue).format('MMM D, YYYY')} - {dayjs(endValue).format('MMM D, YYYY')} ); diff --git a/src/components/CodeAssignmentModal/constants.jsx b/src/components/CodeAssignmentModal/constants.jsx index 995adefa65..a1f427ebd1 100644 --- a/src/components/CodeAssignmentModal/constants.jsx +++ b/src/components/CodeAssignmentModal/constants.jsx @@ -1,4 +1,4 @@ -import { faInfoCircle } from '@fortawesome/free-solid-svg-icons'; +import { Info } from '@edx/paragon/icons'; import { MODAL_TYPES } from '../EmailTemplateForm/constants'; import { getTemplateEmailFields } from '../EmailTemplateForm'; import CheckboxWithTooltip from '../ReduxFormCheckbox/CheckboxWithTooltip'; @@ -20,7 +20,7 @@ export const getAssignmentModalFields = formatMessage => { id: EMAIL_TEMPLATE_NUDGE_EMAIL_ID, component: CheckboxWithTooltip, className: 'auto-reminder-wrapper', - icon: faInfoCircle, + icon: Info, altText: formatMessage(messages.modalAltText), tooltipText: formatMessage(messages.modalTooltipText), label: formatMessage(messages.modalFieldLabel), diff --git a/src/components/CodeAssignmentModal/index.jsx b/src/components/CodeAssignmentModal/index.jsx index e492fef0b2..270411d242 100644 --- a/src/components/CodeAssignmentModal/index.jsx +++ b/src/components/CodeAssignmentModal/index.jsx @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { reduxForm, SubmissionError } from 'redux-form'; import { - Button, Icon, Modal, Form, + Button, Modal, Form, Spinner, } from '@edx/paragon'; import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; @@ -418,7 +418,7 @@ export class BaseCodeAssignmentModal extends React.Component { data-testid={SUBMIT_BUTTON_TEST_ID} > <> - {mode === MODAL_TYPES.assign && submitting && } + {mode === MODAL_TYPES.assign && submitting && } {`Assign ${isBulkAssign ? 'Codes' : 'Code'}`} , diff --git a/src/components/CodeManagement/ManageCodesTab.jsx b/src/components/CodeManagement/ManageCodesTab.jsx index 23f4dd7195..1e7e3cb61e 100644 --- a/src/components/CodeManagement/ManageCodesTab.jsx +++ b/src/components/CodeManagement/ManageCodesTab.jsx @@ -9,7 +9,9 @@ import { Icon, Pagination, } from '@edx/paragon'; -import { CheckCircle, Info, WarningFilled } from '@edx/paragon/icons'; +import { + CheckCircle, Info, Plus, SpinnerIcon, WarningFilled, +} from '@edx/paragon/icons'; import SearchBar from '../SearchBar'; import CodeSearchResults from '../CodeSearchResults'; @@ -277,7 +279,7 @@ class ManageCodesTab extends React.Component { disabled={loading} > <> - + Refresh data @@ -286,7 +288,7 @@ class ManageCodesTab extends React.Component { to={`/${enterpriseSlug}/admin/${ROUTE_NAMES.codeManagement}/request-codes`} > <> - + Request more codes diff --git a/src/components/CodeManagement/ManageRequestsTab.jsx b/src/components/CodeManagement/ManageRequestsTab.jsx index 4525567dad..2d51a43111 100644 --- a/src/components/CodeManagement/ManageRequestsTab.jsx +++ b/src/components/CodeManagement/ManageRequestsTab.jsx @@ -1,8 +1,9 @@ import React, { useContext, useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; +import dayjs from 'dayjs'; + import { Stack } from '@edx/paragon'; -import moment from 'moment'; import { camelCaseObject } from '@edx/frontend-platform'; import SubsidyRequestManagementTable, { @@ -41,9 +42,9 @@ const ManageRequestsTab = ({ return ; } - const now = moment(); + const now = dayjs(); const coupons = couponsData.results; - const hasAvailableCodes = coupons.some(coupon => moment(coupon.endDate) > now && coupon.numUnassigned > 0); + const hasAvailableCodes = coupons.some(coupon => dayjs(coupon.endDate) > now && coupon.numUnassigned > 0); return ( diff --git a/src/components/CodeManagement/tests/ManageCodesTab.test.jsx b/src/components/CodeManagement/tests/ManageCodesTab.test.jsx index ea08c4cf96..2e8451de7a 100644 --- a/src/components/CodeManagement/tests/ManageCodesTab.test.jsx +++ b/src/components/CodeManagement/tests/ManageCodesTab.test.jsx @@ -268,7 +268,7 @@ describe('ManageCodesTabWrapper', () => { const store = mockStore({ ...initialState }); const wrapper = mount(); store.clearActions(); - wrapper.find('.fa-refresh').hostNodes().simulate('click'); + wrapper.find('[data-testid="refresh-data"]').hostNodes().simulate('click'); expect(store.getActions().filter(action => action.type === COUPONS_REQUEST)).toHaveLength(1); }); diff --git a/src/components/CodeManagement/tests/ManageRequestsTab.test.jsx b/src/components/CodeManagement/tests/ManageRequestsTab.test.jsx index a4a1be4e60..d658fb68a6 100644 --- a/src/components/CodeManagement/tests/ManageRequestsTab.test.jsx +++ b/src/components/CodeManagement/tests/ManageRequestsTab.test.jsx @@ -3,13 +3,9 @@ import PropTypes from 'prop-types'; import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; import configureMockStore from 'redux-mock-store'; -import moment from 'moment'; +import dayjs from 'dayjs'; import userEvent from '@testing-library/user-event'; -import { - screen, - render, - cleanup, -} from '@testing-library/react'; +import { screen, render, cleanup } from '@testing-library/react'; import '@testing-library/jest-dom/extend-expect'; import ManageRequestsTab from '../ManageRequestsTab'; @@ -254,7 +250,7 @@ describe('', () => { loading: false, data: { results: [{ - endDate: moment().add(1, 'days').toISOString(), + endDate: dayjs().add(1, 'days').toISOString(), numUnassigned: 3, }], }, @@ -274,7 +270,7 @@ describe('', () => { loading: false, data: { results: [{ - endDate: moment().add(1, 'days').toISOString(), + endDate: dayjs().add(1, 'days').toISOString(), numUnassigned: 3, }], }, @@ -312,7 +308,7 @@ describe('', () => { loading: false, data: { results: [{ - endDate: moment().add(1, 'days').toISOString(), + endDate: dayjs().add(1, 'days').toISOString(), numUnassigned: 3, }], }, @@ -374,7 +370,7 @@ describe('', () => { loading: false, data: { results: [{ - endDate: moment().add(1, 'days').toISOString(), + endDate: dayjs().add(1, 'days').toISOString(), numUnassigned: 3, }], }, diff --git a/src/components/CodeManagement/tests/__snapshots__/ManageCodesTab.test.jsx.snap b/src/components/CodeManagement/tests/__snapshots__/ManageCodesTab.test.jsx.snap index 7e568a0fdc..13de3d3b8a 100644 --- a/src/components/CodeManagement/tests/__snapshots__/ManageCodesTab.test.jsx.snap +++ b/src/components/CodeManagement/tests/__snapshots__/ManageCodesTab.test.jsx.snap @@ -91,10 +91,25 @@ Array [ type="button" > + className="pgn__icon mr-2" + data-testid="refresh-data" + > + + + + Refresh data + className="pgn__icon" + > + + + + Request more codes @@ -201,7 +230,7 @@ Array [ >