fix: course optimizer issues (#2450)

- don't show `Scan results` heading until there are some results to show.
- change spinner from paragon with spinner icon which looks better than spinner itself.
- disable `update all` button when single update prev Link is in progress.

Co-authored-by: Muhammad Faraz  Maqsood <faraz.maqsood@A006-01130.local>
This commit is contained in:
Muhammad Faraz Maqsood
2025-09-18 10:44:18 +05:00
committed by GitHub
parent b95b3a60ad
commit 9f6a882e61
5 changed files with 33 additions and 29 deletions

View File

@@ -7,6 +7,7 @@ export const STATEFUL_BUTTON_STATES = {
default: 'default',
pending: 'pending',
error: 'error',
disable: 'disable',
};
export const USER_ROLES = {

View File

@@ -5,8 +5,9 @@ import {
import { useDispatch, useSelector } from 'react-redux';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
Badge, Container, Layout, Card, Spinner, StatefulButton,
Badge, Container, Layout, Card, Icon, StatefulButton,
} from '@openedx/paragon';
import { SpinnerSimple } from '@openedx/paragon/icons';
import { Helmet } from 'react-helmet';
import CourseStepper from '../generic/course-stepper';
@@ -218,11 +219,7 @@ const CourseOptimizerPage: FC<{ courseId: string }> = ({ courseId }) => {
}}
icons={{
default: '',
pending: <Spinner
animation="border"
size="sm"
className="mr-2 spinner-icon"
/>,
pending: <Icon src={SpinnerSimple} className="icon-spin" />,
}}
state={getScanButtonState()}
onClick={() => dispatch(startLinkCheck(courseId))}
@@ -246,7 +243,7 @@ const CourseOptimizerPage: FC<{ courseId: string }> = ({ courseId }) => {
/>
</Card.Section>
)}
{!showStepper && (
{linkCheckPresent && linkCheckResult && (
<>
<Card.Header
className="scan-header h3 px-3 text-black mb-2"
@@ -255,18 +252,16 @@ const CourseOptimizerPage: FC<{ courseId: string }> = ({ courseId }) => {
<Card.Section className="px-3 py-1">
<p className="small"> {lastScannedAt && `${intl.formatMessage(messages.lastScannedOn)} ${intl.formatDate(lastScannedAt, { year: 'numeric', month: 'long', day: 'numeric' })}`}</p>
</Card.Section>
<ScanResults
data={linkCheckResult}
courseId={courseId}
onErrorStateChange={setScanResultsError}
rerunLinkUpdateInProgress={rerunLinkUpdateInProgress}
rerunLinkUpdateResult={rerunLinkUpdateResult}
/>
</>
)}
</Card>
{linkCheckPresent && linkCheckResult && (
<ScanResults
data={linkCheckResult}
courseId={courseId}
onErrorStateChange={setScanResultsError}
rerunLinkUpdateInProgress={rerunLinkUpdateInProgress}
rerunLinkUpdateResult={rerunLinkUpdateResult}
/>
)}
</article>
</Layout.Element>
</Layout>

View File

@@ -1,12 +1,13 @@
import {
Card, Icon, DataTable, StatefulButton, Spinner,
Card, Icon, DataTable, StatefulButton,
} from '@openedx/paragon';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
SpinnerSimple,
ArrowForwardIos,
LinkOff,
Check,
} from '@openedx/paragon/icons';
import { useIntl } from '@edx/frontend-platform/i18n';
import React, { FC } from 'react';
import { Filters, Unit } from '../types';
import messages from './messages';
@@ -133,7 +134,7 @@ const LinksCol: FC<{
default: intl.formatMessage(messages.updateButton),
pending: intl.formatMessage(messages.updateButton),
}}
icons={{ default: '', pending: <Spinner animation="border" size="sm" className="mr-2 spinner-icon" /> }}
icons={{ default: '', pending: <Icon src={SpinnerSimple} className="icon-spin" /> }}
state={isUpdating ? STATEFUL_BUTTON_STATES.pending : STATEFUL_BUTTON_STATES.default}
onClick={handleUpdate}
disabled={isUpdating}

View File

@@ -8,14 +8,15 @@ import {
import {
Chip,
Button,
Icon,
useCheckboxSetValues,
useToggle,
StatefulButton,
Spinner,
} from '@openedx/paragon';
import {
ArrowDropDown,
CloseSmall,
SpinnerSimple,
} from '@openedx/paragon/icons';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useDispatch } from 'react-redux';
@@ -1043,21 +1044,23 @@ const ScanResults: FC<Props> = ({
<StatefulButton
className="px-4 rounded-0 update-all-course-btn"
labels={{
default: 'Update all',
pending: 'Update all',
default: intl.formatMessage(messages.updateAllButtonText),
disable: intl.formatMessage(messages.updateAllButtonText),
pending: intl.formatMessage(messages.updateAllButtonText),
}}
icons={{
default: '',
pending: <Spinner
animation="border"
size="sm"
className="mr-2 spinner-icon"
/>,
disable: '',
pending: <Icon src={SpinnerSimple} className="icon-spin" />,
}}
state={getUpdateAllButtonState()}
state={
Object.keys(updatingLinkIds).length > 0
? STATEFUL_BUTTON_STATES.disable
: getUpdateAllButtonState()
}
onClick={handleUpdateAllCourseLinks}
disabled={areAllLinksUpdated}
disabledStates={['pending']}
disabledStates={['disable', 'pending']}
variant="primary"
data-testid="update-all-course"
/>

View File

@@ -82,6 +82,10 @@ const messages = defineMessages({
id: 'course-authoring.scanResults.updated',
defaultMessage: 'Updated',
},
updateAllButtonText: {
id: 'course-authoring.scanResults.updateAllButtonText',
defaultMessage: 'Update all',
},
});
export default messages;