Skip to content

Commit

Permalink
chore: improved SPA routes
Browse files Browse the repository at this point in the history
  • Loading branch information
PKulkoRaccoonGang committed Oct 31, 2024
1 parent 56e025a commit d507d68
Show file tree
Hide file tree
Showing 44 changed files with 991 additions and 327 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"extends @edx/browserslist-config"
],
"scripts": {
"build": "fedx-scripts webpack",
"build": "sh run-build-for-gh-deps.sh",
"i18n_extract": "fedx-scripts formatjs extract",
"stylelint": "stylelint \"plugins/**/*.scss\" \"src/**/*.scss\" \"scss/**/*.scss\" --config .stylelintrc.json",
"lint": "npm run stylelint && fedx-scripts eslint --ext .js --ext .jsx --ext .ts --ext .tsx .",
Expand Down
39 changes: 39 additions & 0 deletions run-build-for-gh-deps.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/bin/bash

# TODO: This file is temporary and will be removed after testing

log() {
echo "=============================== $1 ==============================="
}

run_command() {
echo "\$ $1"
eval $1
}

log "Starting deployment script"
run_command "pwd"

# frontend-component-header
log "Processing frontend-component-header"
run_command "cd node_modules/@edx/" || exit
log "Current directory: $(pwd)"
run_command "rm -rf frontend-component-header"
run_command "mkdir frontend-component-header" || exit
run_command "git clone -b Peter_Kulko/use-SPA-functionality --single-branch https://github.com/raccoongang/frontend-component-header.git frontend-component-header-temp"
run_command "cd frontend-component-header-temp" || exit
log "Current directory: $(pwd)"
run_command "npm ci" || exit
run_command "npm run build" || exit
run_command "cp -r dist ../frontend-component-header/" || exit
run_command "cp -r package.json ../frontend-component-header/" || exit
run_command "cd .."
run_command "rm -rf frontend-component-header-temp"
run_command "cd ../.." || exit
log "Current directory: $(pwd)"

# webpack
log "Running webpack"
run_command "fedx-scripts webpack"

log "Deployment script finished."
3 changes: 2 additions & 1 deletion src/CourseAuthoringPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from 'react-router-dom';
import { StudioFooter } from '@edx/frontend-component-footer';
import Header from './header';
import { fetchCourseDetail } from './data/thunks';
import { fetchCourseDetail, fetchWaffleFlags } from './data/thunks';
import { useModel } from './generic/model-store';
import NotFoundAlert from './generic/NotFoundAlert';
import PermissionDeniedAlert from './generic/PermissionDeniedAlert';
Expand All @@ -21,6 +21,7 @@ const CourseAuthoringPage = ({ courseId, children }) => {

useEffect(() => {
dispatch(fetchCourseDetail(courseId));
dispatch(fetchWaffleFlags(courseId));
}, [courseId]);

useEffect(() => {
Expand Down
125 changes: 75 additions & 50 deletions src/course-checklist/ChecklistSection/ChecklistItemBody.jsx
Original file line number Diff line number Diff line change
@@ -1,70 +1,95 @@
import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl, intlShape, FormattedMessage } from '@edx/frontend-platform/i18n';
import {
ActionRow,
Button,
Hyperlink,
Icon,
} from '@openedx/paragon';
import { Link } from 'react-router-dom';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import { ActionRow, Button, Icon } from '@openedx/paragon';
import { useSelector } from 'react-redux';
import { CheckCircle, RadioButtonUnchecked } from '@openedx/paragon/icons';
import { getConfig } from '@edx/frontend-platform';

import { getWaffleFlags } from '../../data/selectors';
import messages from './messages';

const getUpdateLinks = (courseId, waffleFlags) => {
const baseUrl = getConfig().STUDIO_BASE_URL;
const isLegacyGradingUrl = !waffleFlags.useNewGradingPage;
const isLegacyCertificateUrl = !waffleFlags.useNewCertificatesPage;
const isLegacyCourseDatesUrl = !waffleFlags.useNewScheduleDetailsPage;
const isLegacyOutlineUrl = !waffleFlags.useNewCourseOutlinePage;

return {
welcomeMessage: `/course/${courseId}/course_info`,
gradingPolicy: isLegacyGradingUrl
? `${baseUrl}/settings/grading/${courseId}` : `/course/${courseId}/settings/grading`,
certificate: isLegacyCertificateUrl
? `${baseUrl}/certificates/${courseId}` : `/course/${courseId}/certificates`,
courseDates: isLegacyCourseDatesUrl
? `${baseUrl}/settings/details/${courseId}#schedule` : `/course/${courseId}/settings/details/#schedule`,
proctoringEmail: `${baseUrl}/pages-and-resources/proctoring/settings`,
outline: isLegacyOutlineUrl ? `${baseUrl}/course/${courseId}` : `/course/${courseId}`,
};
};

const ChecklistItemBody = ({
courseId,
checkId,
isCompleted,
updateLink,
// injected
intl,
}) => (
<ActionRow>
<div className="mr-3" id={`icon-${checkId}`} data-testid={`icon-${checkId}`}>
{isCompleted ? (
<Icon
data-testid="completed-icon"
src={CheckCircle}
className="text-success"
style={{ height: '32px', width: '32px' }}
screenReaderText={intl.formatMessage(messages.completedItemLabel)}
/>
) : (
<Icon
data-testid="uncompleted-icon"
src={RadioButtonUnchecked}
style={{ height: '32px', width: '32px' }}
screenReaderText={intl.formatMessage(messages.uncompletedItemLabel)}
/>
)}
</div>
<div>
<div>
<FormattedMessage {...messages[`${checkId}ShortDescription`]} />
}) => {
const intl = useIntl();
const waffleFlags = useSelector(getWaffleFlags);
const updateLinks = getUpdateLinks(courseId, waffleFlags);

return (
<ActionRow>
<div className="mr-3" id={`icon-${checkId}`} data-testid={`icon-${checkId}`}>
{isCompleted ? (
<Icon
data-testid="completed-icon"
src={CheckCircle}
className="text-success"
style={{ height: '32px', width: '32px' }}
screenReaderText={intl.formatMessage(messages.completedItemLabel)}
/>
) : (
<Icon
data-testid="uncompleted-icon"
src={RadioButtonUnchecked}
style={{ height: '32px', width: '32px' }}
screenReaderText={intl.formatMessage(messages.uncompletedItemLabel)}
/>
)}
</div>
<div className="small">
<FormattedMessage {...messages[`${checkId}LongDescription`]} />
<div>
<div>
<FormattedMessage {...messages[`${checkId}ShortDescription`]} />
</div>
<div className="small">
<FormattedMessage {...messages[`${checkId}LongDescription`]} />
</div>
</div>
</div>
<ActionRow.Spacer />
{updateLink && (
<Hyperlink destination={updateLink} data-testid="update-hyperlink">
<Button size="sm">
<FormattedMessage {...messages.updateLinkLabel} />
</Button>
</Hyperlink>
)}
</ActionRow>
);
<ActionRow.Spacer />
{updateLinks?.[checkId] && (
<Link
to={updateLinks[checkId]}
data-testid="update-link"
>
<Button size="sm">
<FormattedMessage {...messages.updateLinkLabel} />
</Button>
</Link>
)}
</ActionRow>
);
};

ChecklistItemBody.defaultProps = {
updateLink: null,
};

ChecklistItemBody.propTypes = {
courseId: PropTypes.string.isRequired,
checkId: PropTypes.string.isRequired,
isCompleted: PropTypes.bool.isRequired,
updateLink: PropTypes.string,
// injected
intl: intlShape.isRequired,
};

export default injectIntl(ChecklistItemBody);
export default ChecklistItemBody;
19 changes: 14 additions & 5 deletions src/course-checklist/ChecklistSection/ChecklistItemComment.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import { injectIntl, FormattedMessage, FormattedNumber } from '@edx/frontend-platform/i18n';
import { Hyperlink, Icon } from '@openedx/paragon';
import { Icon } from '@openedx/paragon';
import { Link } from 'react-router-dom';
import { ModeComment } from '@openedx/paragon/icons';
import { getConfig } from '@edx/frontend-platform';
import { getWaffleFlags } from '../../data/selectors';
import messages from './messages';

const ChecklistItemComment = ({
courseId,
checkId,
outlineUrl,
data,
}) => {
const waffleFlags = useSelector(getWaffleFlags);

const getPathToCourseOutlinePage = (assignmentId) => (waffleFlags.useNewCourseOutlinePage
? `/course/${courseId}#${assignmentId}` : `${getConfig().STUDIO_BASE_URL}/course/${courseId}#${assignmentId}`);

const commentWrapper = (comment) => (
<div className="row m-0 mt-3 pt-3 border-top align-items-center" data-identifier="comment">
<div className="mr-4">
Expand Down Expand Up @@ -79,9 +87,9 @@ const ChecklistItemComment = ({
<ul className="assignment-list">
{gradedAssignmentsOutsideDateRange.map(assignment => (
<li className="assignment-list-item" key={assignment.id}>
<Hyperlink destination={`${outlineUrl}#${assignment.id}`}>
<Link to={getPathToCourseOutlinePage(assignment.id)}>
{assignment.displayName}
</Hyperlink>
</Link>
</li>
))}
</ul>
Expand All @@ -96,6 +104,7 @@ const ChecklistItemComment = ({
};

ChecklistItemComment.propTypes = {
courseId: PropTypes.string.isRequired,
checkId: PropTypes.string.isRequired,
outlineUrl: PropTypes.string.isRequired,
data: PropTypes.oneOfType([
Expand Down
18 changes: 4 additions & 14 deletions src/course-checklist/ChecklistSection/ChecklistSection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import ChecklistItemComment from './ChecklistItemComment';
import { checklistItems } from './utils/courseChecklistData';

const ChecklistSection = ({
courseId,
dataHeading,
data,
idPrefix,
isLoading,
updateLinks,
}) => {
const dataList = checklistItems[idPrefix];
const getCompletionCountID = () => (`${idPrefix}-completion-count`);
Expand All @@ -37,18 +37,16 @@ const ChecklistSection = ({
{checks.map(check => {
const checkId = check.id;
const isCompleted = values[checkId];
const updateLink = updateLinks?.[checkId];
const outlineUrl = updateLinks.outline;
return (
<div
className={`bg-white border py-3 px-4 ${isCompleted && 'checklist-item-complete'}`}
id={`checklist-item-${checkId}`}
data-testid={`checklist-item-${checkId}`}
key={checkId}
>
<ChecklistItemBody {...{ checkId, isCompleted, updateLink }} />
<ChecklistItemBody courseId={courseId} {...{ checkId, isCompleted }} />
<div data-testid={`comment-section-${checkId}`}>
<ChecklistItemComment {...{ checkId, outlineUrl, data }} />
<ChecklistItemComment {...{ courseId, checkId, data }} />
</div>
</div>
);
Expand All @@ -61,11 +59,11 @@ const ChecklistSection = ({
};

ChecklistSection.defaultProps = {
updateLinks: {},
data: {},
};

ChecklistSection.propTypes = {
courseId: PropTypes.string.isRequired,
dataHeading: PropTypes.string.isRequired,
data: PropTypes.oneOfType([
PropTypes.shape({
Expand Down Expand Up @@ -129,14 +127,6 @@ ChecklistSection.propTypes = {
]),
idPrefix: PropTypes.string.isRequired,
isLoading: PropTypes.bool.isRequired,
updateLinks: PropTypes.shape({
welcomeMessage: PropTypes.string,
gradingPolicy: PropTypes.string,
certificate: PropTypes.string,
courseDates: PropTypes.string,
proctoringEmail: PropTypes.string,
outline: PropTypes.string,
}),
};

export default injectIntl(ChecklistSection);
Loading

0 comments on commit d507d68

Please sign in to comment.