refactor: replace query-string pkg, remove unused <ShareButton> (#1676)
This commit is contained in:
19
package-lock.json
generated
19
package-lock.json
generated
@@ -36,7 +36,6 @@
|
||||
"lodash.camelcase": "4.3.0",
|
||||
"postcss-loader": "^8.1.1",
|
||||
"prop-types": "15.8.1",
|
||||
"query-string": "^7.1.3",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-helmet": "6.1.0",
|
||||
@@ -18318,24 +18317,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/query-string": {
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz",
|
||||
"integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"decode-uri-component": "^0.2.2",
|
||||
"filter-obj": "^1.1.0",
|
||||
"split-on-first": "^1.0.0",
|
||||
"strict-uri-encode": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/querystringify": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
|
||||
|
||||
@@ -59,7 +59,6 @@
|
||||
"lodash.camelcase": "4.3.0",
|
||||
"postcss-loader": "^8.1.1",
|
||||
"prop-types": "15.8.1",
|
||||
"query-string": "^7.1.3",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-helmet": "6.1.0",
|
||||
|
||||
@@ -16,6 +16,7 @@ jest.mock('react-router-dom', () => ({
|
||||
useLocation: () => ({
|
||||
search: '?consentPath=/some-path',
|
||||
}),
|
||||
useSearchParams: () => [new URLSearchParams('?consentPath=/some-path'), () => {}],
|
||||
}));
|
||||
|
||||
describe('RedirectPage component', () => {
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
generatePath, useParams, useLocation,
|
||||
generatePath, useParams, useLocation, useSearchParams,
|
||||
} from 'react-router-dom';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
|
||||
import queryString from 'query-string';
|
||||
import { REDIRECT_MODES } from '../constants';
|
||||
|
||||
const RedirectPage = ({
|
||||
pattern, mode,
|
||||
}) => {
|
||||
interface Props {
|
||||
pattern: string;
|
||||
mode: string;
|
||||
}
|
||||
|
||||
const RedirectPage = ({ pattern = '', mode }: Props) => {
|
||||
const { courseId } = useParams();
|
||||
const location = useLocation();
|
||||
const { consentPath } = queryString.parse(location?.search);
|
||||
const [searchParams] = useSearchParams();
|
||||
const consentPath = searchParams.get('consentPath') ?? '';
|
||||
|
||||
const {
|
||||
LMS_BASE_URL,
|
||||
@@ -39,13 +41,4 @@ const RedirectPage = ({
|
||||
return null;
|
||||
};
|
||||
|
||||
RedirectPage.propTypes = {
|
||||
pattern: PropTypes.string,
|
||||
mode: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
RedirectPage.defaultProps = {
|
||||
pattern: null,
|
||||
};
|
||||
|
||||
export default RedirectPage;
|
||||
@@ -1,35 +0,0 @@
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { stringifyUrl } from 'query-string';
|
||||
|
||||
export const iframeParams = {
|
||||
show_title: 0,
|
||||
show_bookmark: 0,
|
||||
recheck_access: 1,
|
||||
};
|
||||
|
||||
export const getIFrameUrl = ({
|
||||
id,
|
||||
view,
|
||||
format,
|
||||
examAccess,
|
||||
jumpToId,
|
||||
preview,
|
||||
}) => {
|
||||
const xblockUrl = `${getConfig().LMS_BASE_URL}/xblock/${id}`;
|
||||
return stringifyUrl({
|
||||
url: xblockUrl,
|
||||
query: {
|
||||
...iframeParams,
|
||||
view,
|
||||
preview,
|
||||
...(format && { format }),
|
||||
...(!examAccess.blockAccess && { exam_access: examAccess.accessToken }),
|
||||
jumpToId, // Pass jumpToId as query param as fragmentIdentifier is not passed to server.
|
||||
},
|
||||
fragmentIdentifier: jumpToId, // this is used by browser to scroll to correct block.
|
||||
});
|
||||
};
|
||||
|
||||
export default {
|
||||
getIFrameUrl,
|
||||
};
|
||||
@@ -1,83 +0,0 @@
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { stringifyUrl } from 'query-string';
|
||||
import { getIFrameUrl, iframeParams } from './urls';
|
||||
|
||||
jest.mock('@edx/frontend-platform', () => ({
|
||||
getConfig: jest.fn(),
|
||||
}));
|
||||
jest.mock('query-string', () => ({
|
||||
stringifyUrl: jest.fn((arg) => ({ stringifyUrl: arg })),
|
||||
}));
|
||||
|
||||
const config = { LMS_BASE_URL: 'test-lms-url' };
|
||||
getConfig.mockReturnValue(config);
|
||||
|
||||
const props = {
|
||||
id: 'test-id',
|
||||
view: 'test-view',
|
||||
format: 'test-format',
|
||||
examAccess: { blockAccess: false, accessToken: 'test-access-token' },
|
||||
preview: false,
|
||||
};
|
||||
|
||||
describe('urls module getIFrameUrl', () => {
|
||||
test('format provided, exam access and token available', () => {
|
||||
const url = stringifyUrl({
|
||||
url: `${config.LMS_BASE_URL}/xblock/${props.id}`,
|
||||
query: {
|
||||
...iframeParams,
|
||||
view: props.view,
|
||||
format: props.format,
|
||||
exam_access: props.examAccess.accessToken,
|
||||
preview: props.preview,
|
||||
},
|
||||
});
|
||||
expect(getIFrameUrl(props)).toEqual(url);
|
||||
});
|
||||
test('no format provided, exam access blocked', () => {
|
||||
const url = stringifyUrl({
|
||||
url: `${config.LMS_BASE_URL}/xblock/${props.id}`,
|
||||
query: { ...iframeParams, view: props.view, preview: props.preview },
|
||||
});
|
||||
expect(getIFrameUrl({
|
||||
id: props.id,
|
||||
view: props.view,
|
||||
preview: props.preview,
|
||||
examAccess: { blockAccess: true },
|
||||
})).toEqual(url);
|
||||
});
|
||||
test('jumpToId and fragmentIdentifier is added to url', () => {
|
||||
const url = stringifyUrl({
|
||||
url: `${config.LMS_BASE_URL}/xblock/${props.id}`,
|
||||
query: {
|
||||
...iframeParams,
|
||||
view: props.view,
|
||||
format: props.format,
|
||||
preview: props.preview,
|
||||
exam_access: props.examAccess.accessToken,
|
||||
jumpToId: 'some-xblock-id',
|
||||
},
|
||||
fragmentIdentifier: 'some-xblock-id',
|
||||
});
|
||||
expect(getIFrameUrl({
|
||||
...props,
|
||||
jumpToId: 'some-xblock-id',
|
||||
})).toEqual(url);
|
||||
});
|
||||
test('preview is true and url param equals 1', () => {
|
||||
const url = stringifyUrl({
|
||||
url: `${config.LMS_BASE_URL}/xblock/${props.id}`,
|
||||
query: {
|
||||
...iframeParams,
|
||||
view: props.view,
|
||||
format: props.format,
|
||||
preview: true,
|
||||
exam_access: props.examAccess.accessToken,
|
||||
},
|
||||
});
|
||||
expect(getIFrameUrl({
|
||||
...props,
|
||||
preview: true,
|
||||
})).toEqual(url);
|
||||
});
|
||||
});
|
||||
42
src/courseware/course/sequence/Unit/urls.test.ts
Normal file
42
src/courseware/course/sequence/Unit/urls.test.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { getIFrameUrl } from './urls';
|
||||
|
||||
jest.mock('@edx/frontend-platform', () => ({
|
||||
getConfig: jest.fn(),
|
||||
}));
|
||||
const config = { LMS_BASE_URL: 'https://test-lms-url' };
|
||||
getConfig.mockReturnValue(config);
|
||||
|
||||
const props = {
|
||||
id: 'test-id',
|
||||
view: 'test-view',
|
||||
format: 'test-format',
|
||||
examAccess: { blockAccess: false, accessToken: 'test-access-token' },
|
||||
preview: false,
|
||||
};
|
||||
|
||||
describe('urls module getIFrameUrl', () => {
|
||||
test('format provided, exam access and token available', () => {
|
||||
expect(getIFrameUrl(props)).toEqual('https://test-lms-url/xblock/test-id?exam_access=test-access-token&format=test-format&preview=false&recheck_access=1&show_bookmark=0&show_title=0&view=test-view');
|
||||
});
|
||||
test('no format provided, exam access blocked', () => {
|
||||
expect(getIFrameUrl({
|
||||
id: props.id,
|
||||
view: props.view,
|
||||
preview: props.preview,
|
||||
examAccess: { blockAccess: true },
|
||||
})).toEqual('https://test-lms-url/xblock/test-id?preview=false&recheck_access=1&show_bookmark=0&show_title=0&view=test-view');
|
||||
});
|
||||
test('jumpToId and fragmentIdentifier is added to url', () => {
|
||||
expect(getIFrameUrl({
|
||||
...props,
|
||||
jumpToId: 'some-xblock-id',
|
||||
})).toEqual('https://test-lms-url/xblock/test-id?exam_access=test-access-token&format=test-format&jumpToId=some-xblock-id&preview=false&recheck_access=1&show_bookmark=0&show_title=0&view=test-view#some-xblock-id');
|
||||
});
|
||||
test('preview is true and url param equals 1', () => {
|
||||
expect(getIFrameUrl({
|
||||
...props,
|
||||
preview: true,
|
||||
})).toEqual('https://test-lms-url/xblock/test-id?exam_access=test-access-token&format=test-format&preview=true&recheck_access=1&show_bookmark=0&show_title=0&view=test-view');
|
||||
});
|
||||
});
|
||||
49
src/courseware/course/sequence/Unit/urls.ts
Normal file
49
src/courseware/course/sequence/Unit/urls.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
|
||||
export const iframeParams = {
|
||||
show_title: 0,
|
||||
show_bookmark: 0,
|
||||
recheck_access: 1,
|
||||
};
|
||||
|
||||
interface Props {
|
||||
id: string;
|
||||
view: string;
|
||||
format?: string | null;
|
||||
examAccess: { blockAccess: boolean, accessToken?: string };
|
||||
jumpToId?: string;
|
||||
preview: boolean;
|
||||
}
|
||||
|
||||
export const getIFrameUrl = ({
|
||||
id,
|
||||
view,
|
||||
format = null,
|
||||
examAccess,
|
||||
jumpToId,
|
||||
preview,
|
||||
}: Props) => {
|
||||
const xblockUrl = new URL(`${getConfig().LMS_BASE_URL}/xblock/${id}`);
|
||||
for (const [key, value] of Object.entries(iframeParams)) {
|
||||
xblockUrl.searchParams.set(key, String(value));
|
||||
}
|
||||
xblockUrl.searchParams.set('view', view);
|
||||
xblockUrl.searchParams.set('preview', String(preview));
|
||||
if (format) {
|
||||
xblockUrl.searchParams.set('format', format);
|
||||
}
|
||||
if (!examAccess.blockAccess) {
|
||||
xblockUrl.searchParams.set('exam_access', examAccess.accessToken!);
|
||||
}
|
||||
// Pass jumpToId as query param as fragmentIdentifier is not passed to server.
|
||||
if (jumpToId) {
|
||||
xblockUrl.searchParams.set('jumpToId', jumpToId);
|
||||
xblockUrl.hash = `#${jumpToId}`; // this is used by browser to scroll to correct block.
|
||||
}
|
||||
xblockUrl.searchParams.sort();
|
||||
return xblockUrl.toString();
|
||||
};
|
||||
|
||||
export default {
|
||||
getIFrameUrl,
|
||||
};
|
||||
@@ -1,49 +0,0 @@
|
||||
import React from 'react';
|
||||
import { PropTypes } from 'prop-types';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { TwitterShareButton, TwitterIcon } from 'react-share';
|
||||
import { stringifyUrl } from 'query-string';
|
||||
|
||||
import { Icon } from '@openedx/paragon';
|
||||
import messages from './messages';
|
||||
|
||||
const ShareTwitterIcon = () => (
|
||||
<TwitterIcon
|
||||
round
|
||||
iconFillColor="#0A3055"
|
||||
bgStyle={{
|
||||
fill: '#fff',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
const ShareButton = ({ url }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const twitterUrl = stringifyUrl({
|
||||
url,
|
||||
query: {
|
||||
utm_source: 'twitter',
|
||||
utm_medium: 'social',
|
||||
utm_campaign: 'social-share-exp',
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<TwitterShareButton
|
||||
url={twitterUrl}
|
||||
title={formatMessage(messages.shareQuote)}
|
||||
resetButtonStyle={false}
|
||||
className="px-1 ml-n1 btn-sm text-primary-500 btn btn-link"
|
||||
>
|
||||
<Icon src={ShareTwitterIcon} />
|
||||
{formatMessage(messages.shareButton)}
|
||||
</TwitterShareButton>
|
||||
);
|
||||
};
|
||||
|
||||
ShareButton.propTypes = {
|
||||
url: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default ShareButton;
|
||||
@@ -1,26 +0,0 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
shareButton: {
|
||||
id: 'learn.sequence.share.button',
|
||||
defaultMessage: 'Share this content',
|
||||
description: 'share message button message',
|
||||
},
|
||||
shareModalTitle: {
|
||||
id: 'learn.sequence.share.modal.title',
|
||||
defaultMessage: 'Title',
|
||||
description: 'share message modal title',
|
||||
},
|
||||
shareModalBody: {
|
||||
id: 'learn.sequence.share.modal.body',
|
||||
defaultMessage: 'Copy the link below to share this content.',
|
||||
description: 'share message modal body',
|
||||
},
|
||||
shareQuote: {
|
||||
id: 'learn.sequence.share.quote',
|
||||
defaultMessage: 'Here\'s a fun clip from a class I\'m taking on @edXonline.\n',
|
||||
description: 'share message quote',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
Reference in New Issue
Block a user