diff --git a/messages/de.json b/messages/de.json index 8e90afad..037d35b5 100644 --- a/messages/de.json +++ b/messages/de.json @@ -1,4 +1,5 @@ { + "BA-BL/Group": "BA-BL/Gruppe", "default": { "(n/a)": "", "A package with the same name and version already exists": "Ein Paket mit demselben Namen und derselben Version ist bereits vorhanden", diff --git a/messages/en.json b/messages/en.json index 1d43fee8..5a516995 100644 --- a/messages/en.json +++ b/messages/en.json @@ -1,4 +1,5 @@ { + "BA-BL/Group": "BA-BL/Group", "default": { "(n/a)": "(n/a)", "A package with the same name and version already exists": "A package with the same name and version already exists", diff --git a/messages/es.json b/messages/es.json index 6f9e6636..10cc1aea 100644 --- a/messages/es.json +++ b/messages/es.json @@ -1,4 +1,5 @@ { + "BA-BL/Group": "BA-BL/Grupo", "default": { "(n/a)": "", "A package with the same name and version already exists": "Ya existe un paquete con el mismo nombre y versión.", diff --git a/messages/fr.json b/messages/fr.json index 0bb4e13a..970f1a60 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -1,4 +1,5 @@ { + "BA-BL/Group": "BA-BL/Groupe", "default": { "(n/a)": "", "A package with the same name and version already exists": "Un package avec le même nom et la même version existe déjà", diff --git a/messages/ja.json b/messages/ja.json index acfeca8a..c6bb7666 100644 --- a/messages/ja.json +++ b/messages/ja.json @@ -1,4 +1,5 @@ { + "BA-BL/Group": "BA-BL/グループ", "default": { "(n/a)": "", "A package with the same name and version already exists": "同じ名前とバージョンのパッケージがすでに存在します", diff --git a/messages/ko.json b/messages/ko.json index 3afc64c7..34fce871 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -1,4 +1,5 @@ { + "BA-BL/Group": "BA-BL/그룹", "default": { "(n/a)": "", "A package with the same name and version already exists": "이름과 버전이 같은 패키지가 이미 존재합니다.", diff --git a/messages/pt-BR.json b/messages/pt-BR.json index 41210931..213085c0 100644 --- a/messages/pt-BR.json +++ b/messages/pt-BR.json @@ -1,4 +1,5 @@ { + "BA-BL/Group": "BA-BL/Grupo", "default": { "(n/a)": "", "A package with the same name and version already exists": "Já existe um pacote com o mesmo nome e versão", diff --git a/messages/vi.json b/messages/vi.json index e4c45b32..f28d6205 100644 --- a/messages/vi.json +++ b/messages/vi.json @@ -1,4 +1,5 @@ { + "BA-BL/Group": "BA-BL/Nhóm", "default": { "(n/a)": "", "A package with the same name and version already exists": "Đã tồn tại gói có cùng tên và phiên bản", diff --git a/messages/zh-CN.json b/messages/zh-CN.json index 1ae64d94..e1601653 100644 --- a/messages/zh-CN.json +++ b/messages/zh-CN.json @@ -1,4 +1,5 @@ { + "BA-BL/Group": "BA-BL/组", "default": { "(n/a)": "", "A package with the same name and version already exists": "已存在同名同版本的包", diff --git a/messages/zh-TW.json b/messages/zh-TW.json index 808ecdf7..d990be0b 100644 --- a/messages/zh-TW.json +++ b/messages/zh-TW.json @@ -1,4 +1,5 @@ { + "BA-BL/Group": "BA-BL/組", "default": { "(n/a)": "", "A package with the same name and version already exists": "已存在同名同版本的包", diff --git a/src/app/[locale]/requests/clearingRequest/detail/[id]/components/ClearingComments.tsx b/src/app/[locale]/requests/clearingRequest/detail/[id]/components/ClearingComments.tsx index a68ac469..e916caa0 100644 --- a/src/app/[locale]/requests/clearingRequest/detail/[id]/components/ClearingComments.tsx +++ b/src/app/[locale]/requests/clearingRequest/detail/[id]/components/ClearingComments.tsx @@ -14,18 +14,18 @@ import { ClearingRequestComments, Embedded, HttpStatus } from '@/object-types' import MessageService from '@/services/message.service' import { ApiUtils, CommonUtils } from '@/utils/index' import parse from 'html-react-parser' -import { getSession, signOut } from 'next-auth/react' +import { getSession, signOut, useSession } from 'next-auth/react' import { useTranslations } from 'next-intl' import Link from 'next/link' import { notFound } from 'next/navigation' -import { ReactElement, useCallback, useEffect, useState } from 'react' +import { ReactNode, useEffect, useState } from 'react' import { Spinner } from 'react-bootstrap' type EmbeddedClearingRequestComments = Embedded export default function ClearingComments({ clearingRequestId, -}: Readonly<{ clearingRequestId: string | undefined }>): ReactElement | undefined { +}: Readonly<{ clearingRequestId: string | undefined }>): ReactNode | undefined { const t = useTranslations('default') const [loading, setLoading] = useState(true) const [comments, setComments] = useState>([]) @@ -33,9 +33,10 @@ export default function ClearingComments({ const [commentPayload, setCommentPayload] = useState({ text: '', }) + const { status } = useSession() - const formatDate = (timestamp: number | undefined): string | null => { - if (timestamp == null) { + const formatDate = (timestamp: number | undefined) : string | null => { + if (timestamp === undefined) { return null } const date = new Date(timestamp) @@ -43,7 +44,7 @@ export default function ClearingComments({ return `${dateISOString.slice(0, 10)} ${dateISOString.slice(11, 19)}` } - const fetchData = useCallback(async (url: string) => { + const fetchData = async (url: string) => { const session = await getSession() if (CommonUtils.isNullOrUndefined(session)) return signOut() const response = await ApiUtils.GET(url, session.user.access_token) @@ -55,7 +56,7 @@ export default function ClearingComments({ } else { notFound() } - }, []) + } useEffect(() => { setLoading(true) @@ -75,7 +76,7 @@ export default function ClearingComments({ } }) .catch((err) => console.error(err)) - }, [fetchData]) + }, []) const updateInputField = (event: React.ChangeEvent) => { setInputComment(event.target.value) @@ -108,79 +109,80 @@ export default function ClearingComments({ if (status === 'unauthenticated') { signOut() } else { - return ( - <> - {loading == false ? ( - - - - - - - - - - - - {t('Preferred Clearing Date')} : - + + + {' '} + { t('reopen clearing request')} + + + + setShowMessage(false)} + show={showMessage} + dismissible> + {message} + + + + + {t('Please enter details to re-open clearing request')} + +
+
+
+ +
+ + + {t('Preferred Clearing Date')} : + + * + + + +
+ + {' '}{t('Learn more about preferred clearing date')}. +
+
+ + + + + {t('Clearing Type')} : + + * + + + - * - - - -
- {' '} - {t('Learn more about preferred clearing date')}. -
-
- - - - - {t('Clearing Type')} : - - * - - - - - - - -
- {' '} - {t('Learn more about clearing request type')}. -
-
- - - - - {t('Critical')} - - - - {t('Comments')} : - - - - - - - - - - ) - } + {t('Reopen Clearing Request')} + + + + + )} } diff --git a/src/app/[locale]/requests/clearingRequest/edit/[id]/page.tsx b/src/app/[locale]/requests/clearingRequest/edit/[id]/page.tsx index 0cd5bd19..1a6a4624 100644 --- a/src/app/[locale]/requests/clearingRequest/edit/[id]/page.tsx +++ b/src/app/[locale]/requests/clearingRequest/edit/[id]/page.tsx @@ -18,7 +18,7 @@ export const metadata: Metadata = { title: 'Requests', } -const EditClearingRequestPage = async ({ params }: Context) => { +const EditClearingRequestPage = ({ params }: Context): JSX.Element => { return } diff --git a/src/app/[locale]/requests/components/BulkDeclineModerationRequestModal.tsx b/src/app/[locale]/requests/components/BulkDeclineModerationRequestModal.tsx index e4a9cd96..487db0c8 100644 --- a/src/app/[locale]/requests/components/BulkDeclineModerationRequestModal.tsx +++ b/src/app/[locale]/requests/components/BulkDeclineModerationRequestModal.tsx @@ -13,20 +13,23 @@ import { HttpStatus, ModerationRequestPayload } from '@/object-types' import { ApiUtils, CommonUtils } from '@/utils/index' import { useTranslations } from 'next-intl' import Link from 'next/link' -import { Dispatch, SetStateAction, useEffect, useState } from 'react' +import { Dispatch, SetStateAction, useEffect, useState, ReactNode } from 'react' import { Form, Modal, OverlayTrigger, Spinner, Tooltip } from 'react-bootstrap' import { AiOutlineQuestionCircle } from 'react-icons/ai' import MessageService from '@/services/message.service' -import { signOut, getSession } from 'next-auth/react' +import { signOut, getSession, useSession } from 'next-auth/react' import { _, Table } from 'next-sw360' import { BiCheckCircle, BiInfoCircle, BiXCircle } from 'react-icons/bi' import { BsFillExclamationCircleFill } from 'react-icons/bs' - interface propType { [key: string]: string } +interface ModerationRequestRow { + moderationRequestId: string, documentName: string +} + export default function BulkDeclineModerationRequestModal({ show, setShow, @@ -35,14 +38,16 @@ export default function BulkDeclineModerationRequestModal({ show: boolean setShow: Dispatch> mrIdNameMap: propType -}) { +}) : ReactNode { const t = useTranslations('default') const [loading, setLoading] = useState(true) const [disableAcceptMr, setDisableAcceptMr] = useState(false) const [disableDeclineMr, setDisableDeclineMr] = useState(false) const [statusCheck, setStatusCheck] = useState() - const [tableData, setTableData] = useState>([]) + const [tableData, setTableData] = useState>([]) const [hasComment, setHasComment] = useState(false) + const { status } = useSession() const [moderationRequestPayload, setModerationRequestPayload] = useState({ action: '', @@ -221,11 +226,12 @@ export default function BulkDeclineModerationRequestModal({ const progressStatus = computeProgress(response.status) setTableData((prevData) => { const updatedData = prevData.map((row) => { - if (row[0].moderationRequestId === singleMrId) { + const r = row[0] as ModerationRequestRow + if (r.moderationRequestId === singleMrId) { return [ { - moderationRequestId: row[0].moderationRequestId, - documentName: row[0].documentName, + moderationRequestId: r.moderationRequestId, + documentName: r.documentName, }, { progressStatus } ] @@ -242,11 +248,12 @@ export default function BulkDeclineModerationRequestModal({ const progressStatus = computeProgress(response.status) setTableData((prevData) => { const updatedData = prevData.map((row) => { - if (row[0].moderationRequestId === singleMrId) { + const r = row[0] as ModerationRequestRow + if (r.moderationRequestId === singleMrId) { return [ { - moderationRequestId: row[0].moderationRequestId, - documentName: row[0].documentName, + moderationRequestId: r.moderationRequestId, + documentName: r.documentName, }, { progressStatus } ] @@ -263,11 +270,12 @@ export default function BulkDeclineModerationRequestModal({ const progressStatus = computeProgress(response.status) setTableData((prevData) => { const updatedData = prevData.map((row) => { - if (row[0].moderationRequestId === singleMrId) { + const r = row[0] as ModerationRequestRow + if (r.moderationRequestId === singleMrId) { return [ { - moderationRequestId: row[0].moderationRequestId, - documentName: row[0].documentName, + moderationRequestId: r.moderationRequestId, + documentName: r.documentName, }, { progressStatus } ] @@ -313,11 +321,12 @@ export default function BulkDeclineModerationRequestModal({ const progressStatus = computeProgress(response.status) setTableData((prevData) => { const updatedData = prevData.map((row) => { - if (row[0].moderationRequestId === singleMrId) { + const r = row[0] as ModerationRequestRow + if (r.moderationRequestId === singleMrId) { return [ { - moderationRequestId: row[0].moderationRequestId, - documentName: row[0].documentName, + moderationRequestId: r.moderationRequestId, + documentName: r.documentName, }, { progressStatus } ] @@ -334,11 +343,12 @@ export default function BulkDeclineModerationRequestModal({ const progressStatus = computeProgress(response.status) setTableData((prevData) => { const updatedData = prevData.map((row) => { - if (row[0].moderationRequestId === singleMrId) { + const r = row[0] as ModerationRequestRow + if (r.moderationRequestId === singleMrId) { return [ { - moderationRequestId: row[0].moderationRequestId, - documentName: row[0].documentName, + moderationRequestId: r.moderationRequestId, + documentName: r.documentName, }, { progressStatus } ] @@ -355,11 +365,12 @@ export default function BulkDeclineModerationRequestModal({ const progressStatus = computeProgress(response.status) setTableData((prevData) => { const updatedData = prevData.map((row) => { - if (row[0].moderationRequestId === singleMrId) { + const r = row[0] as ModerationRequestRow + if (r.moderationRequestId === singleMrId) { return [ { - moderationRequestId: row[0].moderationRequestId, - documentName: row[0].documentName, + moderationRequestId: r.moderationRequestId, + documentName: r.documentName, }, { progressStatus } ] @@ -411,34 +422,37 @@ export default function BulkDeclineModerationRequestModal({ } } - return ( - <> - { - setShow(false) - setHasComment(false) - setStatusCheck(0) - setDisableAcceptMr(false) - setDisableDeclineMr(false) - }} - aria-labelledby={t('Accept Decline All Selected Moderation Requests')} - scrollable - > - + { + setShow(false) + setHasComment(false) + setStatusCheck(0) + setDisableAcceptMr(false) + setDisableDeclineMr(false) + }} + aria-labelledby={t('Accept Decline All Selected Moderation Requests')} + scrollable > - - - {t('Accept Decline All Selected Moderation Requests')} - - - -

{t('Accept Decline All MRs')}

-
+ + + + {t('Accept Decline All Selected Moderation Requests')} + + + +

{t('Accept Decline All MRs')}

+ {t.rich('Your selected Moderation requests are')} @@ -483,7 +497,7 @@ export default function BulkDeclineModerationRequestModal({ /> -
+
{t('Comments')}
- - @@ -181,13 +185,15 @@ function EditClearingRequest({ clearingRequestId }: { clearingRequestId: string {' '} <> {t('Clearing Request Information For Project') + ` `} - - {clearingRequestData?._embedded?.['sw360:project']?.name + - `(${clearingRequestData?._embedded?.['sw360:project']?.version})`} - + { + clearingRequestData?._embedded !== undefined && + + {`${clearingRequestData._embedded['sw360:project']?.name ?? ''}(${clearingRequestData._embedded['sw360:project']?.version ?? ''})`} + + } diff --git a/src/app/[locale]/requests/clearingRequest/edit/[id]/components/EditClearingRequestInfo.tsx b/src/app/[locale]/requests/clearingRequest/edit/[id]/components/EditClearingRequestInfo.tsx index ddb03486..c869c143 100644 --- a/src/app/[locale]/requests/clearingRequest/edit/[id]/components/EditClearingRequestInfo.tsx +++ b/src/app/[locale]/requests/clearingRequest/edit/[id]/components/EditClearingRequestInfo.tsx @@ -10,11 +10,12 @@ 'use client' import { useTranslations } from 'next-intl' -import { ClearingRequestDetails, UpdateClearingRequestPayload } from '@/object-types' +import { ClearingRequestDetails, UpdateClearingRequestPayload, UserGroupType } from '@/object-types' import styles from '@/app/[locale]/requests/requestDetail.module.css' import { signOut, useSession } from 'next-auth/react' -import { useEffect, useState } from 'react' +import { ReactNode, useEffect, useState } from 'react' import { SelectUsersDialog, ShowInfoOnHover } from 'next-sw360' +import { CommonUtils } from '@/utils' interface Props { clearingRequestData: ClearingRequestDetails | undefined, @@ -28,7 +29,7 @@ interface DataTypeProp { export default function EditClearingRequestInfo({ clearingRequestData, updateClearingRequestPayload, - setUpdateClearingRequestPayload }: Props) { + setUpdateClearingRequestPayload }: Props): ReactNode { const t = useTranslations('default') const { data:session, status } = useSession() const [minDate, setMinDate] = useState('') @@ -60,7 +61,7 @@ export default function EditClearingRequestInfo({ clearingRequestData, if (status === 'unauthenticated') { - signOut() + void signOut() } else { return ( <> @@ -82,7 +83,7 @@ export default function EditClearingRequestInfo({ clearingRequestData, name='requestingUser' onClick={() => setDialogOpenRequestingUser(true)} value={updateClearingRequestPayload.requestingUser} - disabled={session?.user.userGroup === "USER"} + disabled={CommonUtils.isNullOrUndefined(session) || session.user.userGroup === UserGroupType.USER} /> diff --git a/src/app/[locale]/requests/clearingRequest/edit/[id]/components/ReopenClosedClearingRequestModal.tsx b/src/app/[locale]/requests/clearingRequest/edit/[id]/components/ReopenClosedClearingRequestModal.tsx index 7f86657e..348eac3f 100644 --- a/src/app/[locale]/requests/clearingRequest/edit/[id]/components/ReopenClosedClearingRequestModal.tsx +++ b/src/app/[locale]/requests/clearingRequest/edit/[id]/components/ReopenClosedClearingRequestModal.tsx @@ -9,20 +9,22 @@ 'use client' -import { CreateClearingRequestPayload } from '@/object-types' -import { signOut, useSession } from 'next-auth/react' -import { useTranslations } from 'next-intl' -import { ShowInfoOnHover } from 'next-sw360' -import { Dispatch, SetStateAction, useCallback, useEffect, useState } from 'react' -import { Alert, Button, Col, Form, Modal, Row } from 'react-bootstrap' -import { FaRegQuestionCircle } from 'react-icons/fa' +import { signOut, useSession } from "next-auth/react" +import { useTranslations } from "next-intl" +import { Dispatch, ReactNode, SetStateAction, useCallback, useEffect, useState } from "react" +import { Alert, Button, Col, Form, Modal, Row } from "react-bootstrap" +import { CreateClearingRequestPayload } from "@/object-types" +import { FaRegQuestionCircle } from "react-icons/fa" +import { ShowInfoOnHover } from "next-sw360" interface Props { show: boolean setShow: Dispatch> } -export default function ReopenClosedClearingRequestModal({ show, setShow }: Props) { +export default function ReopenClosedClearingRequestModal({ show, + setShow + }: Props): ReactNode { const t = useTranslations('default') const { status } = useSession() const [message, setMessage] = useState('') @@ -113,171 +115,156 @@ export default function ReopenClosedClearingRequestModal({ show, setShow }: Prop } if (status === 'unauthenticated') { - signOut() + void signOut() } else { return ( - { - setShow(false) - }} - aria-labelledby={t('Reopen Clearing Request')} - scrollable - > - + { + setShow(false) + }} + aria-labelledby={t('Reopen Clearing Request')} + scrollable > - - {' '} - {t('reopen clearing request')} - - - - setShowMessage(false)} - show={showMessage} - dismissible - > - {message} - -
- - - {t('Please enter details to re-open clearing request')} - -
-
-
- -
- - ) : ( - - )} + if (status === 'unauthenticated') { + void signOut() + } else { + return ( +
+
+ {loading == false ? ( +
+
+ + ) : ( + + )} + - - ) + ) + } } export default ClosedClearingRequest diff --git a/src/app/[locale]/requests/components/ClosedModerationRequest.tsx b/src/app/[locale]/requests/components/ClosedModerationRequest.tsx index bf0c82c5..df930b0e 100644 --- a/src/app/[locale]/requests/components/ClosedModerationRequest.tsx +++ b/src/app/[locale]/requests/components/ClosedModerationRequest.tsx @@ -9,14 +9,14 @@ 'use client' -import { Embedded, HttpStatus, ModerationRequest } from '@/object-types' import { ApiUtils, CommonUtils } from '@/utils/index' -import { getSession, signOut } from 'next-auth/react' +import { signOut, getSession, useSession } from 'next-auth/react' import { useTranslations } from 'next-intl' import { Table, _ } from 'next-sw360' import Link from 'next/link' +import { useEffect, useState, ReactNode } from 'react' +import { Embedded, HttpStatus, ModerationRequest } from '@/object-types' import { notFound } from 'next/navigation' -import { useCallback, useEffect, useState } from 'react' import { Spinner } from 'react-bootstrap' import ExpandingModeratorCell from './ExpandingModeratorCell' @@ -25,11 +25,12 @@ interface ModerationRequestMap { [key: string]: string } -function ClosedModerationRequest() { +function ClosedModerationRequest(): ReactNode { + const { status } = useSession() const t = useTranslations('default') const [loading, setLoading] = useState(true) - const [tableData, setTableData] = useState>([]) - const moderationRequestStatus: ModerationRequestMap = { + const [tableData, setTableData] = useState<(string | object | string[])[][]>([]) + const moderationRequestStatus : ModerationRequestMap = { INPROGRESS: t('In Progress'), APPROVED: t('APPROVED'), PENDING: t('Pending'), @@ -37,7 +38,7 @@ function ClosedModerationRequest() { } const formatDate = (timestamp: number | undefined): string | null => { - if (timestamp == null) { + if (timestamp === undefined) { return null } const date = new Date(timestamp) @@ -47,7 +48,7 @@ function ClosedModerationRequest() { return `${year}-${month}-${day}` } - const fetchData = useCallback(async (url: string) => { + const fetchData = async (url: string) => { const session = await getSession() if (CommonUtils.isNullOrUndefined(session)) return signOut() const response = await ApiUtils.GET(url, session.user.access_token) @@ -59,7 +60,7 @@ function ClosedModerationRequest() { } else { notFound() } - }, []) + } useEffect(() => { setLoading(true) @@ -72,20 +73,21 @@ function ClosedModerationRequest() { if (filteredModerationRequests !== undefined) { setTableData( filteredModerationRequests.map((item: ModerationRequest) => [ - formatDate(item.timestamp), - item.componentType, - _({item.documentName}), - item.requestingUser, - item.requestingUserDepartment, - item.moderators, - item.moderationState !== undefined ? moderationRequestStatus[item.moderationState] : undefined, + formatDate(item.timestamp) ?? '', + item.componentType ?? '', + { id: item.id, documentName: item.documentName }, + item.requestingUser ?? '', + item.requestingUserDepartment ?? '', + item.moderators ?? [], + item.moderationState !== undefined ? + moderationRequestStatus[item.moderationState]: '', '', ]), ) } setLoading(false) }) - }, [fetchData]) + }, []) const columns = [ { @@ -101,6 +103,7 @@ function ClosedModerationRequest() { { id: 'closedModerationRequest.documentName', name: t('Document Name'), + formatter: ({ id, documentName }: { id: string, documentName: string }) => _({documentName}), sort: true, }, { @@ -140,24 +143,28 @@ function ClosedModerationRequest() { }, ] - return ( -
-
- {loading == false ? ( -
-
- - ) : ( - - )} + if (status === 'unauthenticated') { + void signOut() + } else { + return ( +
+
+ {loading == false ? ( +
+
+ + ) : ( + + )} + - - ) + ) + } } export default ClosedModerationRequest diff --git a/src/app/[locale]/requests/components/OpenClearingRequest.tsx b/src/app/[locale]/requests/components/OpenClearingRequest.tsx index be517063..7c01afa6 100644 --- a/src/app/[locale]/requests/components/OpenClearingRequest.tsx +++ b/src/app/[locale]/requests/components/OpenClearingRequest.tsx @@ -9,14 +9,14 @@ 'use client' -import { ClearingRequest, Embedded, HttpStatus } from '@/object-types' +import Link from 'next/link' +import { ReactNode, useEffect, useState } from 'react' +import { Table, _ } from "next-sw360" +import { useTranslations } from 'next-intl' import { ApiUtils, CommonUtils } from '@/utils/index' +import { Embedded, HttpStatus, UserGroupType, ClearingRequest } from '@/object-types' import { getSession, signOut, useSession } from 'next-auth/react' -import { useTranslations } from 'next-intl' -import { Table, _ } from 'next-sw360' -import Link from 'next/link' import { notFound } from 'next/navigation' -import { useCallback, useEffect, useState } from 'react' import { Button, OverlayTrigger, Spinner, Tooltip } from 'react-bootstrap' import { FaPencilAlt } from 'react-icons/fa' @@ -40,16 +40,17 @@ interface ProjectData { projectName?: string } -function LicenseClearing(licenseClearing: LicenseClearing) { +function LicenseClearing(licenseClearing: LicenseClearing): ReactNode { const [lcData, setLcData] = useState(null) useEffect(() => { const controller = new AbortController() const signal = controller.signal - ;(async () => { + void (async () => { try { const session = await getSession() - if (CommonUtils.isNullOrUndefined(session)) return signOut() + if(CommonUtils.isNullOrUndefined(session)) + return signOut() const response = await ApiUtils.GET( `projects/${licenseClearing.projectId}/licenseClearingCount`, @@ -62,7 +63,7 @@ function LicenseClearing(licenseClearing: LicenseClearing) { return notFound() } - const data = await response.json() + const data = await response.json() as LicenseClearingData setLcData(data) } catch (e) { @@ -75,45 +76,55 @@ function LicenseClearing(licenseClearing: LicenseClearing) { return ( <> - {lcData ? ( - <> - {(licenseClearing.openReleases ?? false) && lcData['Release Count'] ? ( -
{`${lcData['Release Count']}`}
- ) : null} - {licenseClearing.clearingProgress ?? false ? ( -
{`${lcData['Approved Count']}/${lcData['Release Count']}`}
- ) : null} - - ) : ( -
- -
- )} + { lcData ? ( + <> + { + licenseClearing.openReleases !== undefined && lcData['Release Count']? ( +
+ {`${lcData['Release Count']}`} +
+ ) : null + } + { + licenseClearing.clearingProgress !== undefined ? ( +
+ {`${lcData['Approved Count']}/${lcData['Release Count']}`} +
+ ) : null} + + ) : ( +
+ +
+ ) + } ) } -function OpenClearingRequest() { +function OpenClearingRequest(): ReactNode | undefined { + const t = useTranslations('default') const { data: session, status } = useSession() const [loading, setLoading] = useState(true) const [isProjectDeleted, setIsProjectDeleted] = useState(false) - const [tableData, setTableData] = useState>([]) + const [tableData, setTableData] = useState<(object | string)[][]>([]) - const fetchData = useCallback(async (url: string) => { - if (CommonUtils.isNullOrUndefined(session)) { + const fetchData = async (url: string) => { + const session = await getSession() + if (CommonUtils.isNullOrUndefined(session)){ return signOut() } const response = await ApiUtils.GET(url, session.user.access_token) if (response.status == HttpStatus.OK) { - const data = (await response.json()) as EmbeddedClearingRequest + const data = await response.json() as EmbeddedClearingRequest return data } else if (response.status == HttpStatus.UNAUTHORIZED) { return signOut() } else { notFound() } - }, []) + } useEffect(() => { if(status !== 'authenticated') return @@ -179,7 +190,7 @@ function OpenClearingRequest() { } setLoading(false) }) - }, [fetchData]) + }, []) const columns = [ { @@ -207,32 +218,25 @@ function OpenClearingRequest() { sort: true, formatter: (projectData: ProjectData) => _( - projectData.isProjectDeleted ?? false ? ( - t('Project Deleted') - ) : ( - + (projectData.isProjectDeleted !== undefined && projectData.isProjectDeleted) ? t('Project Deleted') : + <> + {projectData.projectName} - ), + , ), }, { id: 'openClearingRequest.openReleases', name: t('Open Releases'), sort: true, - formatter: (licenseClearing: LicenseClearing) => - _( - licenseClearing.isProjectDeleted ?? false ? ( - t('Not Available') - ) : ( - - ), + formatter: (licenseClearing: LicenseClearing) => + _( + (licenseClearing.isProjectDeleted !== undefined && licenseClearing.isProjectDeleted) ? t('Not Available') : + ), }, { @@ -340,16 +344,12 @@ function OpenClearingRequest() { id: 'openClearingRequest.clearingProgress', name: t('Clearing Progress'), sort: true, - formatter: (licenseClearing: LicenseClearing) => - _( - licenseClearing.isProjectDeleted ?? false ? ( - t('Not Available') - ) : ( - - ), + formatter: (licenseClearing: LicenseClearing) => + _( + (licenseClearing.isProjectDeleted !== undefined && licenseClearing.isProjectDeleted) ? t('Not Available') : + ), }, { @@ -393,32 +393,32 @@ function OpenClearingRequest() { sort: true, formatter: ({ requestId, requestingUser }: { requestId: string; requestingUser: string }) => _( - {t('Edit')}}> - - , - ), - }, + <> + + {t('Edit')} + }> + + + + + ) + } ] if (status === 'unauthenticated') { - signOut() + void signOut() } else { return (
-
+
{loading == false ? (
>([]) - const [tableData, setTableData] = useState>([]) + const [tableData, setTableData] = useState<(object | string | string[])[][]>([]) const [disableBulkDecline, setDisableBulkDecline] = useState(true) const [bulkDeclineMRModal, setBulkDeclineMRModal] = useState(false) const [mrIdNameMap, setMrIdNameMap] = useState<{ [key: string]: string }>({}) @@ -43,7 +43,7 @@ function OpenModerationRequest() { } const formatDate = (timestamp: number | undefined): string | null => { - if (timestamp == null) { + if(timestamp === undefined){ return null } const date = new Date(timestamp) @@ -55,7 +55,9 @@ function OpenModerationRequest() { const fetchData = useCallback( async (url: string) => { - if (CommonUtils.isNullOrUndefined(session)) return + const session = await getSession() + if (CommonUtils.isNullOrUndefined(session)) + return signOut() const response = await ApiUtils.GET(url, session.user.access_token) if (response.status == HttpStatus.OK) { const data = (await response.json()) as EmbeddedModerationRequest @@ -82,18 +84,17 @@ function OpenModerationRequest() { setTableData( filteredModerationRequests.map((item: ModerationRequest) => { return [ - formatDate(item.timestamp), - item.documentType, + formatDate(item.timestamp) ?? '', + item.documentType ?? '', { id: item.id, documentName: item.documentName, }, - item.requestingUser, - item.requestingUserDepartment, - item.moderators, - item.moderationState !== undefined - ? moderationRequestStatus[item.moderationState] - : undefined, + item.requestingUser ?? '', + item.requestingUserDepartment ?? '', + item.moderators ?? [], + item.moderationState !== undefined ? + moderationRequestStatus[item.moderationState] : '', { moderationRequestId: item.id, documentName: item.documentName, @@ -204,7 +205,7 @@ function OpenModerationRequest() { ] if (status === 'unauthenticated') { - signOut() + void signOut() } else { return ( <> diff --git a/src/app/[locale]/requests/components/Requests.tsx b/src/app/[locale]/requests/components/Requests.tsx index 9ba6cfd0..a0afcb6c 100644 --- a/src/app/[locale]/requests/components/Requests.tsx +++ b/src/app/[locale]/requests/components/Requests.tsx @@ -16,10 +16,10 @@ import OpenModerationRequest from './OpenModerationRequest' import ClosedModerationRequest from './ClosedModerationRequest' import OpenClearingRequest from './OpenClearingRequest' import ClosedClearingRequest from './ClosedClearingRequest' -import { useCallback, useEffect, useState } from 'react' +import { ReactNode, useEffect, useState } from 'react' import { ApiUtils, CommonUtils } from '@/utils/index' import { ClearingRequest, Embedded, HttpStatus, ModerationRequest } from '@/object-types' -import { signOut, useSession } from 'next-auth/react' +import { signOut, useSession, getSession } from 'next-auth/react' import { notFound } from 'next/navigation' @@ -27,10 +27,10 @@ type EmbeddedModerationRequest = Embedded -function Requests() { +function Requests(): ReactNode | undefined { const t = useTranslations('default') - const { data: session, status } = useSession() + const { status } = useSession() const [openModerationRequestCount, setOpenModerationRequestCount] = useState(0) const [closedModerationRequestCount, setClosedModerationRequestCount] = useState(0) const [openClearingRequestCount, setOpenClearingRequestCount] = useState(0) @@ -138,49 +138,44 @@ function Requests() { } ] - const fetchData = useCallback( - async (url: string) => { - if (CommonUtils.isNullOrUndefined(session)) - return - const response = await ApiUtils.GET(url, session.user.access_token) - if (response.status == HttpStatus.OK) { - const data = await response.json() - return data - } else if (response.status == HttpStatus.UNAUTHORIZED) { - return - } else { - notFound() - } - },[session] - ) - useEffect(() => { - void fetchData('moderationrequest') - .then((moderationRequests: EmbeddedModerationRequest | undefined) => { - if(!moderationRequests) return - let openMRCount = 0 - let closedMRCount = 0 - moderationRequests['_embedded']['sw360:moderationRequests'] - .filter((item: ModerationRequest) => { - if (item.moderationState === 'PENDING' || - item.moderationState === 'INPROGRESS') { - openMRCount++; - } - else if (item.moderationState === 'APPROVED' || - item.moderationState === 'REJECTED') { - closedMRCount++; - } - }) + const controller = new AbortController() + const signal = controller.signal + void (async () => { + try { + const session = await getSession() + if(CommonUtils.isNullOrUndefined(session)) + return signOut() + const moderationRequestsPrmosies = ApiUtils.GET('moderationrequest', session.user.access_token, signal) + const clearingRequestsPromises = ApiUtils.GET('clearingrequests', session.user.access_token, signal) + + const responses = await Promise.all([moderationRequestsPrmosies, clearingRequestsPromises]) + if(responses[0].status !== HttpStatus.OK || responses[1].status !== HttpStatus.OK) { + return notFound() + } + + const moderationRequests = await responses[0].json() as EmbeddedModerationRequest + let openMRCount = 0 + let closedMRCount = 0 + moderationRequests['_embedded']['sw360:moderationRequests'] + .map((item: ModerationRequest) => { + if (item.moderationState === 'PENDING' || + item.moderationState === 'INPROGRESS') { + openMRCount++; + } + else if (item.moderationState === 'APPROVED' || + item.moderationState === 'REJECTED') { + closedMRCount++; + } + }) setOpenModerationRequestCount(openMRCount) setClosedModerationRequestCount(closedMRCount) - }) - void fetchData('clearingrequests') - .then((clearingRequests: EmbeddedClearingRequest | undefined) => { - if(!clearingRequests) return + + const clearingRequests = await responses[1].json() as EmbeddedClearingRequest let openCRCount = 0 let closedCRCount = 0 clearingRequests['_embedded']['sw360:clearingRequests'] - .filter((item: ClearingRequest) => { + .map((item: ClearingRequest) => { if (item.clearingState === 'NEW' || item.clearingState === 'ACCEPTED' || item.clearingState === 'IN_QUEUE' || @@ -198,11 +193,18 @@ function Requests() { }) setOpenClearingRequestCount(openCRCount) setClosedClearingRequestCount(closedCRCount) - }) - }, [fetchData, session]) + + } catch(e) { + console.error(e) + } + })() + return () => { + controller.abort() + } + }, []) if (status === 'unauthenticated') { - signOut() + void signOut() } else { return ( <> diff --git a/src/app/[locale]/requests/moderationRequest/[id]/components/ModerationDecision.tsx b/src/app/[locale]/requests/moderationRequest/[id]/components/ModerationDecision.tsx index 51683e04..e8d93e6b 100644 --- a/src/app/[locale]/requests/moderationRequest/[id]/components/ModerationDecision.tsx +++ b/src/app/[locale]/requests/moderationRequest/[id]/components/ModerationDecision.tsx @@ -10,6 +10,7 @@ 'use client' import { ModerationRequestDetails, ModerationRequestPayload } from '@/object-types' +import { ReactNode } from 'react' import { useTranslations } from 'next-intl' import Link from 'next/link' @@ -23,7 +24,10 @@ interface Props { setModerationRequestPayload: React.Dispatch> } -export default function ModerationDecision({ data, moderationRequestPayload, setModerationRequestPayload }: Props) { +export default function ModerationDecision({ data, + moderationRequestPayload, + setModerationRequestPayload }: Props ): ReactNode { + const t = useTranslations('default') const moderationRequestStatus: ModerationRequestMap = { INPROGRESS: t('In Progress'), diff --git a/src/app/[locale]/requests/moderationRequest/[id]/components/ModerationRequestDetail.tsx b/src/app/[locale]/requests/moderationRequest/[id]/components/ModerationRequestDetail.tsx index ad5547b9..54ccada1 100644 --- a/src/app/[locale]/requests/moderationRequest/[id]/components/ModerationRequestDetail.tsx +++ b/src/app/[locale]/requests/moderationRequest/[id]/components/ModerationRequestDetail.tsx @@ -16,10 +16,10 @@ import styles from '@/app/[locale]/requests/requestDetail.module.css' import { HttpStatus, ModerationRequestDetails, ModerationRequestPayload } from '@/object-types' import MessageService from '@/services/message.service' import { ApiUtils, CommonUtils } from '@/utils/index' -import { signOut, useSession } from 'next-auth/react' +import { signOut, getSession, useSession } from 'next-auth/react' import { useTranslations } from 'next-intl' import { notFound, useRouter } from 'next/navigation' -import { useCallback, useEffect, useRef, useState } from 'react' +import { useEffect, useRef, useState, ReactNode } from 'react' import { Button, Card, Col, Collapse, Row, Tab } from 'react-bootstrap' import ModerationDecision from './ModerationDecision' import ModerationRequestInfo from './ModerationRequestInfo' @@ -28,10 +28,10 @@ import CurrentComponentDetail from './currentComponent/CurrentComponentDetail' import CurrentProjectDetail from './currentProject/CurrentProjectDetail' import CurrentReleaseDetail from './currentRelease/CurrentReleaseDetail' -function ModerationRequestDetail({ moderationRequestId }: { moderationRequestId: string }) { +function ModerationRequestDetail({ moderationRequestId }: { moderationRequestId: string }): ReactNode | undefined { const t = useTranslations('default') const [openCardIndex, setOpenCardIndex] = useState(0) - const { data: session, status } = useSession() + const { status } = useSession() const router = useRouter() const [moderationRequestData, setModerationRequestData] = useState({ id: '', @@ -67,21 +67,19 @@ function ModerationRequestDetail({ moderationRequestId }: { moderationRequestId: }) const toastShownRef = useRef(false) - const fetchData = useCallback( - async (url: string) => { - if (CommonUtils.isNullOrUndefined(session)) return signOut() - const response = await ApiUtils.GET(url, session.user.access_token) - if (response.status == HttpStatus.OK) { - const data = (await response.json()) as ModerationRequestDetails - return data - } else if (response.status == HttpStatus.UNAUTHORIZED) { - return signOut() - } else { - notFound() - } - }, - [session], - ) + const fetchData = async (url: string) => { + const session = await getSession() + if (CommonUtils.isNullOrUndefined(session)) return signOut() + const response = await ApiUtils.GET(url, session.user.access_token) + if (response.status == HttpStatus.OK) { + const data = (await response.json()) as ModerationRequestDetails + return data + } else if (response.status == HttpStatus.UNAUTHORIZED) { + return signOut() + } else { + notFound() + } + } useEffect(() => { if (!toastShownRef.current) { @@ -94,7 +92,7 @@ function ModerationRequestDetail({ moderationRequestId }: { moderationRequestId: setModerationRequestData(moderationRequestDetails) }, ) - }, [fetchData, session]) + }, []) const handleCommentValidation = () => { if (!moderationRequestPayload.comment.trim()) { @@ -104,80 +102,128 @@ function ModerationRequestDetail({ moderationRequestId }: { moderationRequestId: } const handleAcceptModerationRequest = async () => { - if (CommonUtils.isNullOrUndefined(session)) return signOut() - const hasComment = handleCommentValidation() - if (hasComment) { - const updatedAcceptPayload = { - ...moderationRequestPayload, - action: 'ACCEPT', - } - setModerationRequestPayload(updatedAcceptPayload) - const response = await ApiUtils.PATCH( - `moderationrequest/${moderationRequestId}`, - updatedAcceptPayload, - session.user.access_token, - ) - if (response.status == HttpStatus.ACCEPTED) { - await response.json() - MessageService.success(t('You have accepted the moderation request')) - router.push('/requests') - } else if (response.status == HttpStatus.UNAUTHORIZED) { - return signOut() + try { + const session = await getSession() + if (CommonUtils.isNullOrUndefined(session)) return signOut() + const hasComment = handleCommentValidation() + if (hasComment) { + const updatedAcceptPayload = { + ...moderationRequestPayload, + action: 'ACCEPT', + } + setModerationRequestPayload(updatedAcceptPayload) + const response = await ApiUtils.PATCH( + `moderationrequest/${moderationRequestId}`, + updatedAcceptPayload, + session.user.access_token, + ) + if (response.status == HttpStatus.ACCEPTED) { + await response.json() + MessageService.success(t('You have accepted the moderation request')) + router.push('/requests') + } else if (response.status == HttpStatus.UNAUTHORIZED) { + return signOut() + } else { + MessageService.error(t('There are some errors while updating moderation request')) + router.push(`/requests/moderationRequest/${moderationRequestId}`) + } } else { - MessageService.error(t('There are some errors while updating moderation request')) - router.push(`/requests/moderationRequest/${moderationRequestId}`) + MessageService.error(t('Mandatory fields are empty please provide required data')) } - } else { - MessageService.error(t('Mandatory fields are empty please provide required data')) + } catch(e) { + console.error(e) } } const handleRejectModerationRequest = async () => { - if (CommonUtils.isNullOrUndefined(session)) return signOut() - const hasComment = handleCommentValidation() - if (hasComment) { - const updatedRejectPayload = { - ...moderationRequestPayload, - action: 'REJECT', - } - setModerationRequestPayload(updatedRejectPayload) - const response = await ApiUtils.PATCH( - `moderationrequest/${moderationRequestId}`, - updatedRejectPayload, - session.user.access_token, - ) - if (response.status == HttpStatus.ACCEPTED) { - await response.json() - MessageService.success(t('You have rejected the moderation request')) - router.push('/requests') - } else if (response.status == HttpStatus.UNAUTHORIZED) { - return signOut() + try { + const session = await getSession() + if (CommonUtils.isNullOrUndefined(session)) return signOut() + const hasComment = handleCommentValidation() + if (hasComment) { + const updatedRejectPayload = { + ...moderationRequestPayload, + action: 'REJECT', + } + setModerationRequestPayload(updatedRejectPayload) + const response = await ApiUtils.PATCH( + `moderationrequest/${moderationRequestId}`, + updatedRejectPayload, + session.user.access_token, + ) + if (response.status == HttpStatus.ACCEPTED) { + await response.json() + MessageService.success(t('You have rejected the moderation request')) + router.push('/requests') + } else if (response.status == HttpStatus.UNAUTHORIZED) { + return signOut() + } else { + MessageService.error(t('There are some errors while updating moderation request')) + router.push(`/requests/moderationRequest/${moderationRequestId}`) + } } else { - MessageService.error(t('There are some errors while updating moderation request')) - router.push(`/requests/moderationRequest/${moderationRequestId}`) + MessageService.error(t('Mandatory fields are empty please provide required data')) } - } else { - MessageService.error(t('Mandatory fields are empty please provide required data')) + } catch(e) { + console.error(e) } } const handlePostponeModerationRequest = async () => { - const hasComment = handleCommentValidation() - if (hasComment) { + try { + const hasComment = handleCommentValidation() + if (hasComment) { + const session = await getSession() + if (CommonUtils.isNullOrUndefined(session)) return signOut() + const updatedPostponePayload = { + ...moderationRequestPayload, + action: 'POSTPONE', + } + setModerationRequestPayload(updatedPostponePayload) + const response = await ApiUtils.PATCH( + `moderationrequest/${moderationRequestId}`, + updatedPostponePayload, + session.user.access_token, + ) + if (response.status == HttpStatus.ACCEPTED) { + await response.json() + MessageService.success(t('You have postponed the moderation request')) + router.push('/requests') + } else if (response.status == HttpStatus.UNAUTHORIZED) { + return signOut() + } else { + MessageService.error(t('There are some errors while updating moderation request')) + router.push(`/requests/moderationRequest/${moderationRequestId}`) + } + } else { + MessageService.error(t('Mandatory fields are empty please provide required data')) + } + } catch(e) { + console.error(e) + } + } + + const handleUnassignModerationRequest = async () => { + try { + const session = await getSession() if (CommonUtils.isNullOrUndefined(session)) return signOut() - const updatedPostponePayload = { + const updatedUnassignPayload = { ...moderationRequestPayload, - action: 'POSTPONE', + action: 'UNASSIGN', } - setModerationRequestPayload(updatedPostponePayload) + setModerationRequestPayload(updatedUnassignPayload) const response = await ApiUtils.PATCH( `moderationrequest/${moderationRequestId}`, - updatedPostponePayload, + updatedUnassignPayload, session.user.access_token, ) if (response.status == HttpStatus.ACCEPTED) { await response.json() - MessageService.success(t('You have postponed the moderation request')) + MessageService.success(t('You have unassigned yourself from the moderation request')) + router.push('/requests') + } else if (response.status == HttpStatus.CONFLICT) { + await response.json() + MessageService.warn(t('You are the last moderator for this request you are not allowed to unsubscribe')) router.push('/requests') } else if (response.status == HttpStatus.UNAUTHORIZED) { return signOut() @@ -185,36 +231,8 @@ function ModerationRequestDetail({ moderationRequestId }: { moderationRequestId: MessageService.error(t('There are some errors while updating moderation request')) router.push(`/requests/moderationRequest/${moderationRequestId}`) } - } else { - MessageService.error(t('Mandatory fields are empty please provide required data')) - } - } - - const handleUnassignModerationRequest = async () => { - if (CommonUtils.isNullOrUndefined(session)) return signOut() - const updatedUnassignPayload = { - ...moderationRequestPayload, - action: 'UNASSIGN', - } - setModerationRequestPayload(updatedUnassignPayload) - const response = await ApiUtils.PATCH( - `moderationrequest/${moderationRequestId}`, - updatedUnassignPayload, - session.user.access_token, - ) - if (response.status == HttpStatus.ACCEPTED) { - await response.json() - MessageService.success(t('You have unassigned yourself from the moderation request')) - router.push('/requests') - } else if (response.status == HttpStatus.CONFLICT) { - await response.json() - MessageService.warn(t('You are the last moderator for this request you are not allowed to unsubscribe')) - router.push('/requests') - } else if (response.status == HttpStatus.UNAUTHORIZED) { - return signOut() - } else { - MessageService.error(t('There are some errors while updating moderation request')) - router.push(`/requests/moderationRequest/${moderationRequestId}`) + } catch(e) { + console.error(e) } } @@ -227,7 +245,7 @@ function ModerationRequestDetail({ moderationRequestId }: { moderationRequestId: } if (status === 'unauthenticated') { - signOut() + return signOut() } else { return (
diff --git a/src/app/[locale]/requests/moderationRequest/[id]/components/ModerationRequestInfo.tsx b/src/app/[locale]/requests/moderationRequest/[id]/components/ModerationRequestInfo.tsx index f9aa5f55..6a3185aa 100644 --- a/src/app/[locale]/requests/moderationRequest/[id]/components/ModerationRequestInfo.tsx +++ b/src/app/[locale]/requests/moderationRequest/[id]/components/ModerationRequestInfo.tsx @@ -12,13 +12,14 @@ import Link from 'next/link' import { useTranslations } from 'next-intl' import { ModerationRequestDetails } from '@/object-types' +import { ReactNode } from 'react' -export default function ModerationRequestInfo({ data }: { data: ModerationRequestDetails | undefined }) { +export default function ModerationRequestInfo({ data }: { data: ModerationRequestDetails | undefined }): ReactNode { const t = useTranslations('default') const formatDate = (timestamp: number | undefined): string | null => { - if(timestamp == null){ + if(timestamp == undefined){ return null } const date = new Date(timestamp); @@ -41,7 +42,7 @@ export default function ModerationRequestInfo({ data }: { data: ModerationReques
diff --git a/src/app/[locale]/requests/moderationRequest/[id]/components/ProposedChanges.tsx b/src/app/[locale]/requests/moderationRequest/[id]/components/ProposedChanges.tsx index bbca02a8..e7d9c8c0 100644 --- a/src/app/[locale]/requests/moderationRequest/[id]/components/ProposedChanges.tsx +++ b/src/app/[locale]/requests/moderationRequest/[id]/components/ProposedChanges.tsx @@ -20,11 +20,11 @@ import { } from '@/object-types' import { ApiUtils, CommonUtils } from '@/utils/index' import { TDataArray } from 'gridjs/dist/src/types' -import { signOut, useSession } from 'next-auth/react' +import { signOut, useSession, getSession } from 'next-auth/react' import { useTranslations } from 'next-intl' import { Table, _ } from 'next-sw360' import { notFound } from 'next/navigation' -import { ReactNode, useCallback, useEffect, useState } from 'react' +import { ReactNode, useEffect, useState } from 'react' import TableHeader from './TableHeader' interface interimDataType { @@ -44,9 +44,9 @@ export default function ProposedChanges({ moderationRequestData, }: { moderationRequestData: ModerationRequestDetails | undefined -}) { +}): ReactNode | undefined { const t = useTranslations('default') - const { data: session, status } = useSession() + const { status } = useSession() const dafaultTitle = t('BASIC FIELD CHANGES') const attachmentTitle = t('ATTACHMENTS') const [requestAdditionType, setRequestAdditionType] = useState('') @@ -102,8 +102,8 @@ export default function ProposedChanges({ }, ] - const fetchData = useCallback( - async (url: string) => { + const fetchData = async (url: string) => { + const session = await getSession() if (CommonUtils.isNullOrUndefined(session)) return signOut() const response = await ApiUtils.GET(url, session.user.access_token) if (response.status == HttpStatus.OK) { @@ -114,9 +114,7 @@ export default function ProposedChanges({ } else { notFound() } - }, - [session], - ) + } const convertToReactNode = ( value: string | object | Array | boolean | number | Array | undefined, @@ -344,7 +342,7 @@ export default function ProposedChanges({ }, [moderationRequestData]) if (status === 'unauthenticated') { - signOut() + return signOut() } else { return ( <> diff --git a/src/app/[locale]/requests/moderationRequest/[id]/components/currentComponent/CurrentComponentDetail.tsx b/src/app/[locale]/requests/moderationRequest/[id]/components/currentComponent/CurrentComponentDetail.tsx index 01f37403..aa81f1cb 100644 --- a/src/app/[locale]/requests/moderationRequest/[id]/components/currentComponent/CurrentComponentDetail.tsx +++ b/src/app/[locale]/requests/moderationRequest/[id]/components/currentComponent/CurrentComponentDetail.tsx @@ -11,6 +11,9 @@ import ReleaseOverview from '@/app/[locale]/components/detail/[id]/components/ReleaseOverview' import Summary from '@/app/[locale]/components/detail/[id]/components/Summary' +import { signOut, getSession } from 'next-auth/react' +import { useTranslations } from 'next-intl' +import { useEffect, useState, ReactNode } from 'react' import Attachments from '@/components/Attachments/Attachments' import ChangeLogDetail from '@/components/ChangeLog/ChangeLogDetail/ChangeLogDetail' import ChangeLogList from '@/components/ChangeLog/ChangeLogList/ChangeLogList' @@ -26,21 +29,17 @@ import { LinkedVulnerability, } from '@/object-types' import { ApiUtils, CommonUtils } from '@/utils' -import { signOut, useSession } from 'next-auth/react' -import { useTranslations } from 'next-intl' import { notFound } from 'next/navigation' -import { useCallback, useEffect, useState } from 'react' type EmbeddedChangelogs = Embedded type EmbeddedVulnerabilities = Embedded interface Props { - componentId: string | undefined + componentId: string } -const CurrentComponentDetail = ({ componentId }: Props): JSX.Element => { +const CurrentComponentDetail = ({ componentId }: Props): ReactNode => { const t = useTranslations('default') - const { data: session } = useSession() const [selectedTab, setSelectedTab] = useState(CommonTabIds.SUMMARY) const [changesLogTab, setChangesLogTab] = useState('list-change') const [changeLogIndex, setChangeLogIndex] = useState(-1) @@ -66,21 +65,19 @@ const CurrentComponentDetail = ({ componentId }: Props): JSX.Element => { }, ] - const fetchData = useCallback( - async (url: string) => { - if (CommonUtils.isNullOrUndefined(session)) return signOut() - const response = await ApiUtils.GET(url, session.user.access_token) - if (response.status == HttpStatus.OK) { - const data = (await response.json()) as Component & EmbeddedVulnerabilities & EmbeddedChangelogs - return data - } else if (response.status == HttpStatus.UNAUTHORIZED) { - await signOut() - } else { - notFound() - } - }, - [session], - ) + const fetchData = async (url: string) => { + const session = await getSession() + if (CommonUtils.isNullOrUndefined(session)) return signOut() + const response = await ApiUtils.GET(url, session.user.access_token) + if (response.status == HttpStatus.OK) { + const data = (await response.json()) as Component & EmbeddedVulnerabilities & EmbeddedChangelogs + return data + } else if (response.status == HttpStatus.UNAUTHORIZED) { + await signOut() + } else { + notFound() + } + } useEffect(() => { fetchData(`components/${componentId}`) @@ -117,7 +114,7 @@ const CurrentComponentDetail = ({ componentId }: Props): JSX.Element => { >
{ hidden={selectedTab !== ComponentTabIds.RELEASE_OVERVIEW} >
@@ -134,7 +131,7 @@ const CurrentComponentDetail = ({ componentId }: Props): JSX.Element => { hidden={selectedTab != CommonTabIds.ATTACHMENTS} > @@ -149,7 +146,7 @@ const CurrentComponentDetail = ({ componentId }: Props): JSX.Element => { > diff --git a/src/app/[locale]/requests/moderationRequest/[id]/components/currentProject/CurrentProjectDetail.tsx b/src/app/[locale]/requests/moderationRequest/[id]/components/currentProject/CurrentProjectDetail.tsx index ff26ad6c..18044068 100644 --- a/src/app/[locale]/requests/moderationRequest/[id]/components/currentProject/CurrentProjectDetail.tsx +++ b/src/app/[locale]/requests/moderationRequest/[id]/components/currentProject/CurrentProjectDetail.tsx @@ -18,13 +18,13 @@ import Summary from '@/app/[locale]/projects/detail/[id]/components/Summary' import VulnerabilityTrackingStatusComponent from '@/app/[locale]/projects/detail/[id]/components/VulnerabilityTrackingStatus' import { AdministrationDataType, HttpStatus, SummaryDataType } from '@/object-types' import { ApiUtils, CommonUtils } from '@/utils' -import { signOut, useSession } from 'next-auth/react' +import { signOut, useSession, getSession } from 'next-auth/react' import { useTranslations } from 'next-intl' import { notFound } from 'next/navigation' -import { useEffect, useState } from 'react' +import { ReactNode, useEffect, useState } from 'react' import { Col, ListGroup, Row, Spinner, Tab } from 'react-bootstrap' -export default function CurrentProjectDetail({ projectId }: Readonly<{ projectId: string }>) { +export default function CurrentProjectDetail({ projectId }: Readonly<{ projectId: string }>): ReactNode { const t = useTranslations('default') const { data: session, status } = useSession() const [summaryData, setSummaryData] = useState(undefined) @@ -34,8 +34,10 @@ export default function CurrentProjectDetail({ projectId }: Readonly<{ projectId const controller = new AbortController() const signal = controller.signal - ;(async () => { - if (CommonUtils.isNullOrUndefined(session)) return signOut() + void (async () => { + const session = await getSession() + if (CommonUtils.isNullOrUndefined(session)) + return signOut() try { const response = await ApiUtils.GET( `projects/${projectId}/summaryAdministration`, @@ -48,10 +50,10 @@ export default function CurrentProjectDetail({ projectId }: Readonly<{ projectId return notFound() } - const data = await response.json() + const data = await response.json() as SummaryDataType | AdministrationDataType - setSummaryData({ id: projectId, ...data }) - setAdministrationData(data) + setSummaryData({ ...data, id: projectId } as SummaryDataType) + setAdministrationData(data as AdministrationDataType) } catch (e) { console.error(e) } diff --git a/src/app/[locale]/requests/moderationRequest/[id]/components/currentRelease/CurrentReleaseDetail.tsx b/src/app/[locale]/requests/moderationRequest/[id]/components/currentRelease/CurrentReleaseDetail.tsx index 6fd96c7b..253d733f 100644 --- a/src/app/[locale]/requests/moderationRequest/[id]/components/currentRelease/CurrentReleaseDetail.tsx +++ b/src/app/[locale]/requests/moderationRequest/[id]/components/currentRelease/CurrentReleaseDetail.tsx @@ -30,8 +30,8 @@ import { ReleaseTabIds, } from '@/object-types' import { ApiUtils, CommonUtils } from '@/utils' -import { signOut, useSession } from 'next-auth/react' -import { useCallback, useEffect, useState } from 'react' +import { signOut, getSession } from 'next-auth/react' +import { useEffect, useState, ReactNode } from 'react' type EmbeddedChangelogs = Embedded @@ -39,8 +39,7 @@ interface Props { releaseId: string } -const CurrentReleaseDetail = ({ releaseId }: Props): JSX.Element => { - const { data: session } = useSession() +const CurrentReleaseDetail = ({ releaseId }: Props): ReactNode => { const [selectedTab, setSelectedTab] = useState(CommonTabIds.SUMMARY) const [release, setRelease] = useState() const [embeddedAttachments, setEmbeddedAttachments] = useState>([]) @@ -50,27 +49,29 @@ const CurrentReleaseDetail = ({ releaseId }: Props): JSX.Element => { const [linkProjectModalShow, setLinkProjectModalShow] = useState(false) const [tabList] = useState(ReleaseDetailTabs.MODERATION_REQUEST) - const fetchData = useCallback( - async (url: string) => { + const fetchData = async (url: string, signal: AbortSignal) => { + try { + const session = await getSession() if (CommonUtils.isNullOrUndefined(session)) return signOut() - const response = await ApiUtils.GET(url, session.user.access_token) - if (response.status == HttpStatus.OK) { - const data = await response.json() - return data - } else if (response.status == HttpStatus.UNAUTHORIZED) { - return signOut() - } else { - return null - } - }, - [session], - ) + const response = await ApiUtils.GET(url, session.user.access_token, signal) + if (response.status == HttpStatus.OK) { + const data = await response.json() as ReleaseDetail & EmbeddedChangelogs + return data + } else if (response.status == HttpStatus.UNAUTHORIZED) { + void signOut() + } + } catch(e) { + console.error(e) + } + } useEffect(() => { - fetchData(`releases/${releaseId}`) + const controller = new AbortController() + const signal = controller.signal + + fetchData(`releases/${releaseId}`, signal) .then((release: ReleaseDetail | undefined) => { setRelease(release) - if ( !CommonUtils.isNullOrUndefined(release?._embedded) && !CommonUtils.isNullOrUndefined(release._embedded['sw360:attachments']) @@ -81,7 +82,7 @@ const CurrentReleaseDetail = ({ releaseId }: Props): JSX.Element => { }) .catch((err) => console.error(err)) - fetchData(`changelog/document/${releaseId}`) + fetchData(`changelog/document/${releaseId}`, signal) .then((changeLogs: EmbeddedChangelogs | undefined) => { changeLogs && setChangeLogList( @@ -91,7 +92,9 @@ const CurrentReleaseDetail = ({ releaseId }: Props): JSX.Element => { ) }) .catch((err) => console.error(err)) - }, [fetchData, releaseId]) + + return () => controller.abort() + }, [releaseId]) return release ? (
diff --git a/src/app/[locale]/requests/moderationRequest/[id]/page.tsx b/src/app/[locale]/requests/moderationRequest/[id]/page.tsx index f8d767a6..acc4e129 100644 --- a/src/app/[locale]/requests/moderationRequest/[id]/page.tsx +++ b/src/app/[locale]/requests/moderationRequest/[id]/page.tsx @@ -18,7 +18,7 @@ export const metadata: Metadata = { title: 'Requests', } -const ModerationRequestDetailsPage = async ({ params }: Context) => { +const ModerationRequestDetailsPage = ({ params }: Context): JSX.Element => { return } diff --git a/src/object-types/ClearingRequestDetails.ts b/src/object-types/ClearingRequestDetails.ts index 6dbf1451..10e38199 100644 --- a/src/object-types/ClearingRequestDetails.ts +++ b/src/object-types/ClearingRequestDetails.ts @@ -7,7 +7,7 @@ // SPDX-License-Identifier: EPL-2.0 // License-Filename: LICENSE -import Project from './Project' +import { Project } from './Project' import { User } from './User' export default interface ClearingRequestDetails{
{t('Requesting User')}: {((data?.requestingUser) != null) - ? {data?.requestingUser} + ? {data.requestingUser} : ''}