Skip to content

Commit

Permalink
feat: finalize oer page
Browse files Browse the repository at this point in the history
  • Loading branch information
pyphilia committed Apr 29, 2024
1 parent 93ca5b3 commit 89f254a
Show file tree
Hide file tree
Showing 19 changed files with 615 additions and 214 deletions.
5 changes: 3 additions & 2 deletions app/oer/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Wrapper from '../../src/components/common/Wrapper';
import OERInformation from '../../src/components/pages/OERInformation';
import { APP_AUTHOR } from '../../src/config/constants';
import getQueryClient from '../../src/config/get-query-client';
import LIBRARY from '../../src/langs/constants';
import en from '../../src/langs/en.json';
import { buildSeo } from '../seo';

Expand All @@ -16,8 +17,8 @@ export async function generateMetadata() {
const t = (s: string): string => en[s];

return buildSeo({
title: t('OER information'),
description: t('Information about Open Educational Resources OER'),
title: t(LIBRARY.OER_INFORMATION_PAGE_TITLE),
description: t(LIBRARY.OER_INFORMATION_PAGE_DESCRIPTION),
author: APP_AUTHOR,
});
}
Expand Down
61 changes: 13 additions & 48 deletions src/components/collection/Badges.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
import truncate from 'lodash.truncate';
import { Stack } from '@mui/material';

import { useEffect, useState } from 'react';

import { Email, Facebook, Twitter } from '@mui/icons-material';
import { IconButton, Stack } from '@mui/material';

import {
MAIL_BREAK_LINE,
TWITTER_MESSAGE_MAX_LENGTH,
} from '../../config/constants';
import { useLibraryTranslation } from '../../config/i18n';
import LIBRARY from '../../langs/constants';
import { openInNewTab } from '../../utils/helpers';
import { removeTagsFromString } from '../../utils/text';
import EmailButton from '../common/EmailButton';
import FacebookButton from '../common/FacebookButton';
import TwitterButton from '../common/TwitterButton';

type Props = {
name?: string;
Expand All @@ -21,48 +14,20 @@ type Props = {

const Badges = ({ name, description }: Props) => {
const { t } = useLibraryTranslation();
const [pageLocation, setPageLocation] = useState<string>();
const parsedDescription = removeTagsFromString(description);

useEffect(() => {
setPageLocation(window?.location.href);
}, []);

const shareOnTwitter = () => {
const message = truncate(
`${t(LIBRARY.SHARE_TWITTER_MESSAGE, {
name,
})} ${pageLocation} : ${parsedDescription}`,
{ length: TWITTER_MESSAGE_MAX_LENGTH, separator: /,? +/ },
);
openInNewTab(`https://twitter.com/intent/tweet?text=${message}`);
};

const shareOnFacebook = () => {
const link = pageLocation;
openInNewTab(`https://www.facebook.com/sharer/sharer.php?u=${link}`);
};

const subject = `${t(LIBRARY.SHARE_FACEBOOK_SUBJECT, { name })}`;
const message = `${t(LIBRARY.SHARE_FACEBOOK_SUBJECT, {
name,
})} ${pageLocation}${MAIL_BREAK_LINE}${MAIL_BREAK_LINE}${parsedDescription}`;
const mailString = `mailto:?subject=${subject}&body=${message}`;
const parsedDescription = removeTagsFromString(description);

const iconSize = 'medium';
return (
<Stack direction="row" justifyItems="space-between" alignItems="center">
<IconButton color="primary" onClick={shareOnFacebook}>
<Facebook fontSize={iconSize} />
</IconButton>
<IconButton color="primary" onClick={shareOnTwitter}>
<Twitter fontSize={iconSize} />
</IconButton>
<a href={mailString} aria-label="Send by email">
<IconButton color="primary">
<Email fontSize={iconSize} />
</IconButton>
</a>
<FacebookButton iconSize={iconSize} />
<TwitterButton
message={`${t(LIBRARY.SHARE_TWITTER_MESSAGE, {
name,
})}: ${parsedDescription}`}
iconSize={iconSize}
/>
<EmailButton description={description} name={name} iconSize={iconSize} />
</Stack>
);
};
Expand Down
16 changes: 2 additions & 14 deletions src/components/collection/ItemCollection.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
import React from 'react';

import {
Box,
Container,
SxProps,
Theme,
Typography,
styled,
} from '@mui/material';
import { Container, SxProps, Theme, Typography } from '@mui/material';

import { DiscriminatedItem } from '@graasp/sdk';

import { SECTION_TITLE_ID } from '../../config/selectors';
import StyledContainer from '../layout/StyledContainer';
import CollectionsGrid from './CollectionsGrid';

const StyledContainer = styled(Box)(({ theme }) => ({
backgroundColor: 'white',
':nth-child(even)': { backgroundColor: '#fafafa' },
padding: theme.spacing(4, 3, 8, 3),
}));

type ItemCollectionProps = {
id: string;
collectionGridId?: string;
Expand Down
95 changes: 95 additions & 0 deletions src/components/collection/oer/VideoWithCC.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { List, ListItem, Stack } from '@mui/material';

import { CCLicenseAdaptions } from '@graasp/sdk';

import { useLibraryTranslation } from '../../../config/i18n';
import LIBRARY from '../../../langs/constants';
import CreativeCommons from '../../common/CreativeCommons';

type Props = {
ccLicenseAdaption?: CCLicenseAdaptions;
url: string;
title: string;
production?: string;
duration?: string;
edition?: string;
};

const VideoWithCC = ({
url,
title,
ccLicenseAdaption = CCLicenseAdaptions.CC_BY_SA,
production,
duration,
edition,
}: Props): JSX.Element => {
const { t } = useLibraryTranslation();

return (
<Stack
p={3}
style={{
borderRadius: 20,
border: '1px solid lightgrey',
textAlign: 'center',
background: 'white',
width: 'fit-content',
margin: 'auto',
}}
gap={3}
alignContent="center"
>
<Stack direction="row" justifyContent="center" alignItems="center">
<iframe
style={{ margin: 'auto', border: 'none', display: 'block' }}
width="560"
height="315"
src={url}
title={title}
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowFullScreen
/>
</Stack>
<Stack direction="row" justifyContent="center" alignItems="center">
<Stack>
<List dense>
{production && (
<ListItem>
<strong>
{t(LIBRARY.OER_INFORMATION_VIDEO_DESCRIPTION_PRODUCTION)}
</strong>
: {production}
</ListItem>
)}
{duration && (
<ListItem>
<strong>
{t(LIBRARY.OER_INFORMATION_VIDEO_DESCRIPTION_DURATION)}
</strong>
: {duration}
</ListItem>
)}
{edition && (
<ListItem>
<strong>
{t(LIBRARY.OER_INFORMATION_VIDEO_DESCRIPTION_EDITION)}
</strong>
: {edition}
</ListItem>
)}
</List>
</Stack>
<Stack>
{ccLicenseAdaption && (
<CreativeCommons
iconSize={30}
ccLicenseAdaption={ccLicenseAdaption}
/>
)}
</Stack>
</Stack>
</Stack>
);
};

export default VideoWithCC;
48 changes: 3 additions & 45 deletions src/components/collection/summary/SummaryDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
DiscriminatedItem,
formatDate,
} from '@graasp/sdk';
import { CCSharingVariant, CreativeCommons } from '@graasp/ui';

import { CATEGORY_COLORS, UrlSearch } from '../../../config/constants';
import {
Expand All @@ -37,6 +36,7 @@ import {
} from '../../../config/selectors';
import LIBRARY from '../../../langs/constants';
import { QueryClientContext } from '../../QueryClientContext';
import CreativeCommons from '../../common/CreativeCommons';

const DetailCard = styled(Box)(() => ({
border: '1px solid #ddd',
Expand All @@ -45,31 +45,6 @@ const DetailCard = styled(Box)(() => ({
height: '100%',
}));

const convertLicense = (ccLicenseAdaption: string) => {
// Legacy licenses.
if (['alike', 'allow'].includes(ccLicenseAdaption)) {
return {
requireAccreditation: true,
allowCommercialUse: true,
allowSharing: ccLicenseAdaption === 'alike' ? 'alike' : 'yes',
};
}

return {
requireAccreditation: ccLicenseAdaption?.includes('BY'),
allowCommercialUse: !ccLicenseAdaption?.includes('NC'),
allowSharing: (() => {
if (!ccLicenseAdaption || !ccLicenseAdaption.length) {
return '';
}
if (ccLicenseAdaption?.includes('SA')) {
return 'alike';
}
return ccLicenseAdaption?.includes('ND') ? 'no' : 'yes';
})(),
};
};

type CategoryChipProps = {
category: Category;
};
Expand Down Expand Up @@ -157,12 +132,6 @@ const SummaryDetails: React.FC<SummaryDetailsProps> = ({
?.filter((c) => c.category.type === CategoryType.Language)
?.map((c) => c.category);

const { allowSharing, allowCommercialUse, requireAccreditation } =
React.useMemo(
() => convertLicense(ccLicenseAdaption ?? ''),
[ccLicenseAdaption],
);

return (
<Grid
container
Expand Down Expand Up @@ -244,12 +213,7 @@ const SummaryDetails: React.FC<SummaryDetailsProps> = ({
{isLoading ? (
<Skeleton>
<Box maxWidth={600}>
<CreativeCommons
allowCommercialUse
allowSharedAdaptation="yes"
iconSize={48}
sx={{ marginY: 0, paddingY: 0 }}
/>
<CreativeCommons ccLicenseAdaption="CC BY-NC" />
</Box>
</Skeleton>
) : (
Expand All @@ -258,13 +222,7 @@ const SummaryDetails: React.FC<SummaryDetailsProps> = ({
className={ccLicenseAdaption}
>
{ccLicenseAdaption && ccLicenseAdaption.length > 0 ? (
<CreativeCommons
allowSharedAdaptation={allowSharing as CCSharingVariant}
allowCommercialUse={allowCommercialUse}
requireAccreditation={requireAccreditation}
iconSize={48}
sx={{ marginY: 0, paddingY: 0 }}
/>
<CreativeCommons ccLicenseAdaption={ccLicenseAdaption} />
) : (
<Typography
variant="body1"
Expand Down
76 changes: 76 additions & 0 deletions src/components/common/CreativeCommons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { useMemo } from 'react';

import { Typography } from '@mui/material';

import { DiscriminatedItem } from '@graasp/sdk';
import {
CCSharingVariant,
CreativeCommons as GraaspCreativeCommons,
} from '@graasp/ui';

import { useLibraryTranslation } from '../../config/i18n';
import LIBRARY from '../../langs/constants';

const convertLicense = (ccLicenseAdaption: string) => {
// Legacy licenses.
if (['alike', 'allow'].includes(ccLicenseAdaption)) {
return {
requireAccreditation: true,
allowCommercialUse: true,
allowSharing: ccLicenseAdaption === 'alike' ? 'alike' : 'yes',
};
}

return {
requireAccreditation: ccLicenseAdaption?.includes('BY'),
allowCommercialUse: !ccLicenseAdaption?.includes('NC'),
allowSharing: (() => {
if (!ccLicenseAdaption || !ccLicenseAdaption.length) {
return '';
}
if (ccLicenseAdaption?.includes('SA')) {
return 'alike';
}
return ccLicenseAdaption?.includes('ND') ? 'no' : 'yes';
})(),
};
};

type Props = {
id?: string;
ccLicenseAdaption: DiscriminatedItem['settings']['ccLicenseAdaption'];
iconSize?: number;
};

const CreativeCommons = ({
id,
ccLicenseAdaption,
iconSize = 48,
}: Props): JSX.Element => {
const { t } = useLibraryTranslation();

const { allowSharing, allowCommercialUse, requireAccreditation } = useMemo(
() => convertLicense(ccLicenseAdaption ?? ''),
[ccLicenseAdaption],
);

if (ccLicenseAdaption && ccLicenseAdaption.length > 0) {
return (
<GraaspCreativeCommons
allowSharedAdaptation={allowSharing as CCSharingVariant}
allowCommercialUse={allowCommercialUse}
requireAccreditation={requireAccreditation}
iconSize={iconSize}
sx={{ marginY: 0, paddingY: 0 }}
/>
);
}

return (
<Typography variant="body1" color="text.secondary" id={id}>
{t(LIBRARY.SUMMARY_DETAILS_EMPTY_LICENSE_TEXT)}
</Typography>
);
};

export default CreativeCommons;
Loading

0 comments on commit 89f254a

Please sign in to comment.