Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into int
Browse files Browse the repository at this point in the history
  • Loading branch information
finlay-jisc committed Nov 18, 2024
2 parents 733ea17 + f18a788 commit 53d5d72
Show file tree
Hide file tree
Showing 19 changed files with 222 additions and 196 deletions.
2 changes: 1 addition & 1 deletion e2e/tests/PageModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export const PageModel = {
verifyEmailForMoreButton: 'text=Verify your email for more actions',
addBookmark: '[title="Bookmark this publication"]',
removeBookmark: '[title="Remove bookmark"]',
writeReview: 'button[aria-label="Write a review"]',
writeReview: 'a[aria-label="Write a review"]',
flagConcern: 'button[aria-label="Flag a concern with this publication"]',
redFlagComment: '#red-flag-comment',
redFlagSubmit: '[aria-label="Submit"]',
Expand Down
10 changes: 6 additions & 4 deletions e2e/tests/helpers/livePublication.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { expect, Page } from '@playwright/test';
import { BrowserContext, expect, Page } from '@playwright/test';
import { PageModel } from '../PageModel';

export const checkLivePublicationLayout = async (page: Page, id: string, loggedIn?: boolean) => {
Expand All @@ -20,8 +20,10 @@ export const checkLivePublicationLayout = async (page: Page, id: string, loggedI
);

if (loggedIn) {
// Confirm review link
await page.locator(PageModel.livePublication.writeReview).locator('visible=true').click();
await expect(page).toHaveURL(`/create?for=${id}&type=PEER_REVIEW`);
// Expect review link
await expect(page.locator(PageModel.livePublication.writeReview).locator('visible=true')).toHaveAttribute(
'href',
`/create?for=${id}&type=PEER_REVIEW`
);
}
};
3 changes: 2 additions & 1 deletion ui/src/components/AccordionSection/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const AccordionSection: React.FC<Props> = (props) => {
<Components.Button
id={toggleId}
title={props.title}
className={`w-full justify-between bg-grey-50 px-6 py-1 font-inter transition-all duration-300 children:border-0 dark:bg-grey-700 ${
variant="block"
className={`w-full justify-between bg-grey-50 px-6 py-1 font-inter transition-all duration-300 dark:bg-grey-700 ${
expanded ? 'rounded-none rounded-t' : ''
}`}
endIcon={
Expand Down
82 changes: 42 additions & 40 deletions ui/src/components/Button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,60 +3,62 @@ import React from 'react';
import * as Components from '@/components';

type CommonProps = {
id?: string;
title: string;
endIcon?: React.ReactElement;
startIcon?: React.ReactElement;
onClick?: (e: React.MouseEvent) => void;
disabled?: boolean;
className?: string;
childClassName?: string;
textSize?: string;
padding?: string;
children?: React.ReactNode;
accordionConfig?: {
contentElementId: string;
expanded: Boolean;
};
childClassName?: string;
children?: React.ReactNode;
className?: string;
disabled?: boolean;
endIcon?: React.ReactElement;
id?: string;
onClick?: (e: React.MouseEvent) => void;
padding?: string;
startIcon?: React.ReactElement;
textSize?: string;
title: string;
variant?: 'underlined' | 'block' | 'block-alt';
};

type ConditionalProps = { href: string; openNew?: boolean } | { href?: never; openNew?: never };

type Props = CommonProps & ConditionalProps;

const blockClasses =
'border-2 px-2.5 text-white-50 shadow-sm focus:ring-offset-2 children:border-0 children:text-white-50 ';

const Button: React.FC<Props> = (props): React.ReactElement | null => {
const parentStyles = React.useMemo(() => {
return `
group
inline-flex
items-center
outline-0
focus:ring-2
focus:ring-yellow-400
disabled:select-none
disabled:opacity-50
disabled:hover:cursor-not-allowed
${props.className ?? ''}
`;
}, [props.className]);
let classes =
'disabled:select-none disabled:opacity-50 disabled:hover:cursor-not-allowed inline-flex items-center w-fit ';
switch (props.variant) {
case 'block':
classes += blockClasses + 'bg-teal-600 ';
break;
case 'block-alt':
classes += blockClasses + 'bg-green-600 ';
break;
default:
classes += 'outline-0 focus:ring-2 focus:ring-yellow-400 ';
}
classes += props.className ?? '';
return classes;
}, [props.className, props.variant]);

const childStyles = React.useMemo(() => {
return `
${props.startIcon ? 'ml-3' : ''}
${props.endIcon ? 'mr-3' : ''}
${props.padding ? props.padding : 'py-2'}
font-montserrat
text-${props.textSize ? props.textSize : 'sm'}
font-semibold
text-grey-800
dark:text-white-50
transition-colors
duration-500
border-b-2
border-b-teal-500
dark:border-b-teal-400
${props.childClassName ?? ''}
`;
return (
// Shared classes
'font-montserrat font-semibold' +
// Underline only
(props.variant !== 'block'
? ' border-b-2 border-b-teal-500 dark:border-b-teal-400 text-grey-800 dark:text-white-50 transition-colors duration-500'
: '') +
(props.startIcon ? ' ml-3' : '') +
(props.endIcon ? ' mr-3' : '') +
(props.padding ? ' ' + props.padding : ' py-2') +
` text-${props.textSize ? props.textSize : 'sm'} ${props.childClassName ?? ''}`
);
}, [props.endIcon, props.padding, props.startIcon, props.textSize]);

return props.href ? (
Expand Down
20 changes: 12 additions & 8 deletions ui/src/components/Nav/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,17 @@ const Nav: React.FC = (): React.ReactElement => {
setOpen(false);
}, []);

const handleLogOut = useCallback(async () => {
await router.push({
pathname: `${Config.urls.home.path}`
});
Helpers.clearJWT();
setUser(null);
}, [router, setUser]);
const handleLogOut = useCallback(
(event: React.MouseEvent<HTMLAnchorElement>) => {
event.preventDefault();
Helpers.clearJWT();
setUser(null);
router.push({
pathname: `${Config.urls.home.path}`
});
},
[router, setUser]
);

const items = useMemo(() => {
const menuItems: Interfaces.NavMenuItem[] = [
Expand Down Expand Up @@ -122,7 +126,7 @@ const Nav: React.FC = (): React.ReactElement => {
{
label: 'Log out',
value: '#log-out',
onClick: () => handleLogOut()
onClick: handleLogOut
}
]
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type Props = {
onEditAffiliations: () => void;
};

const ActionBar: React.FC<Props> = (props) => {
const CoAuthoringActions: React.FC<Props> = (props) => {
const { user } = Stores.useAuthStore();

const author = React.useMemo(
Expand Down Expand Up @@ -167,7 +167,8 @@ const ActionBar: React.FC<Props> = (props) => {

{props.isCorrespondingAuthor ? (
<Components.Button
className="inline-flex max-w-fit items-center border-2 bg-teal-600 px-2.5 text-white-50 shadow-sm outline-0 focus:overflow-hidden focus:ring-offset-2 disabled:select-none disabled:opacity-50 disabled:hover:cursor-not-allowed children:border-0 children:text-white-50"
className="max-w-fit"
variant="block"
disabled={!props.isReadyForPublish || props.isPublishing}
endIcon={<OutlineIcons.CloudArrowUpIcon className="w-5 shrink-0 text-white-50" />}
title="Publish"
Expand All @@ -177,7 +178,8 @@ const ActionBar: React.FC<Props> = (props) => {
</Components.Button>
) : isApproved ? (
<Components.Button
className="inline-flex max-w-fit items-center border-2 bg-red-600 px-2.5 text-white-50 shadow-sm outline-0 focus:overflow-hidden focus:ring-offset-2 disabled:select-none disabled:opacity-50 disabled:hover:cursor-not-allowed children:border-0 children:text-white-50"
className="max-w-fit"
variant="block"
endIcon={<OutlineIcons.XMarkIcon className="w-5 shrink-0 text-white-50" />}
title="Cancel your approval"
onClick={props.onCancelApproval}
Expand All @@ -186,7 +188,8 @@ const ActionBar: React.FC<Props> = (props) => {
</Components.Button>
) : (
<Components.Button
className="inline-flex max-w-fit items-center border-2 bg-teal-600 px-2.5 text-white-50 shadow-sm outline-0 focus:overflow-hidden focus:ring-offset-2 disabled:select-none disabled:opacity-50 disabled:hover:cursor-not-allowed children:border-0 children:text-white-50"
className="max-w-fit"
variant="block"
disabled={!(author?.isIndependent || author?.affiliations.length)}
endIcon={<OutlineIcons.CheckIcon className="w-5 shrink-0 text-white-50" />}
title="Approve this publication"
Expand All @@ -200,4 +203,4 @@ const ActionBar: React.FC<Props> = (props) => {
);
};

export default ActionBar;
export default CoAuthoringActions;
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from 'react';
import * as Components from '@/components';
import * as Config from '@/config';
import * as Helpers from '@/helpers';
import * as Stores from '@/stores';
import * as Types from '@/types';

type Props = {
authorIds: string[];
publicationId: string;
publicationType: Types.PublicationType;
};

const HeaderActions: React.FC<Props> = (props) => {
const { user } = Stores.useAuthStore();

if (!user) {
return null;
}

return (
<div className="col-span-8 mb-10 pb-10 flex flex-col md:flex-row gap-4 md:gap-8 border-b border-grey-200">
{Helpers.linkedPublicationTypes[props.publicationType as keyof typeof Helpers.linkedPublicationTypes].map(
(childPublicationType) => {
return (
<Components.Button
variant="block"
title={`Write a linked ${Helpers.formatPublicationType(childPublicationType as Types.PublicationType)}`}
key={childPublicationType}
href={`${Config.urls.createPublication.path}?for=${props.publicationId}&type=${childPublicationType}`}
openNew={true}
/>
);
}
)}
{!props.authorIds.includes(user.id) && (
<Components.Button
title="Write a review"
variant="block"
href={`${Config.urls.createPublication.path}?for=${props.publicationId}&type=PEER_REVIEW`}
openNew={true}
/>
)}
</div>
);
};

export default HeaderActions;
9 changes: 6 additions & 3 deletions ui/src/components/Publication/RelatedPublications/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ const RelatedPublications: React.FC<Props> = (props) => {
<>
<Components.Button
title="View All"
className="border-2 bg-teal-600 px-2.5 text-white-50 shadow-sm focus:ring-offset-2 children:border-0 children:text-white-50 justify-center w-full md:w-1/2 lg:w-full"
variant="block"
className="justify-center w-full md:w-1/2 lg:w-full"
onClick={openViewAllModal}
/>
<Components.RelatedPublicationsViewAllModal
Expand All @@ -96,7 +97,8 @@ const RelatedPublications: React.FC<Props> = (props) => {
<>
<Components.Button
title="Suggest a link"
className="border-2 bg-teal-600 px-2.5 text-white-50 shadow-sm focus:ring-offset-2 children:border-0 children:text-white-50 justify-center w-full md:w-1/2 lg:w-full"
variant="block"
className="justify-center w-full md:w-1/2 lg:w-full"
onClick={() => setSuggestModalVisibility((prevState) => !prevState)}
/>
<Components.RelatedPublicationsSuggestModal
Expand All @@ -112,7 +114,8 @@ const RelatedPublications: React.FC<Props> = (props) => {
) : (
<Components.Button
title="Sign in to suggest a link"
className="border-2 bg-teal-600 px-2.5 text-white-50 shadow-sm focus:ring-offset-2 children:border-0 children:text-white-50 justify-center w-full md:w-1/2 lg:w-full"
variant="block"
className="justify-center w-full md:w-1/2 lg:w-full"
href={`${Config.urls.orcidLogin.path}&state=${encodeURIComponent(router.asPath)}`}
/>
)}
Expand Down
59 changes: 10 additions & 49 deletions ui/src/components/Publication/SidebarCard/Actions/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from 'react';
import Image from 'next/image';
import * as SWR from 'swr';
import * as Router from 'next/router';
import * as OutlineIcons from '@heroicons/react/24/outline';
import * as Interfaces from '@/interfaces';
import * as Components from '@/components';
Expand All @@ -19,7 +18,6 @@ type ActionProps = {
};

const Actions: React.FC<ActionProps> = (props): React.ReactElement => {
const router = Router.useRouter();
const SWRConfig = SWR.useSWRConfig();
// Store
const user = Stores.useAuthStore((state) => state.user);
Expand All @@ -36,6 +34,10 @@ const Actions: React.FC<ActionProps> = (props): React.ReactElement => {
const [error, setError] = React.useState<string | undefined>();
const [submitting, setSubmitting] = React.useState(false);

const authorIds = props.publicationVersion.coAuthors.flatMap((coAuthor) =>
coAuthor.linkedUser ? [coAuthor.linkedUser] : []
);

const saveRedFlag = async () => {
setError(undefined);
setSubmitting(true);
Expand Down Expand Up @@ -208,53 +210,12 @@ const Actions: React.FC<ActionProps> = (props): React.ReactElement => {
Make your name visible on your ORCiD profile for more actions
</Components.Link>
) : user && user.email ? (
<>
{/* if the publication is a peer review, no options shall be given to write a linked publication */}
{props.publicationVersion.publication.type !== 'PEER_REVIEW' && (
<>
{Helpers.linkedPublicationTypes[
props.publicationVersion.publication
.type as keyof typeof Helpers.linkedPublicationTypes
].map((item: any) => {
return (
<Components.PublicationSidebarCardActionsButton
label={`Write a linked ${Helpers.formatPublicationType(item)}`}
key={item}
onClick={() => {
router.push({
pathname: `${Config.urls.createPublication.path}`,
query: {
for: props.publicationVersion.versionOf,
type: item
}
});
}}
/>
);
})}
{props.publicationVersion.user.id !== user.id && (
<>
<Components.PublicationSidebarCardActionsButton
label="Write a review"
onClick={() => {
router.push({
pathname: `${Config.urls.createPublication.path}`,
query: {
for: props.publicationVersion.versionOf,
type: 'PEER_REVIEW'
}
});
}}
/>
<Components.PublicationSidebarCardActionsButton
label="Flag a concern with this publication"
onClick={() => setShowRedFlagModal(true)}
/>
</>
)}
</>
)}
</>
!authorIds.includes(user.id) && (
<Components.PublicationSidebarCardActionsButton
label="Flag a concern with this publication"
onClick={() => setShowRedFlagModal(true)}
/>
)
) : (
<>
<Components.Link
Expand Down
Loading

0 comments on commit 53d5d72

Please sign in to comment.