diff --git a/src/app/[locale]/components/edit/[id]/release/add/releases/AddRelease.tsx b/src/app/[locale]/components/edit/[id]/release/add/releases/AddRelease.tsx index 371042cc..cc72d42f 100644 --- a/src/app/[locale]/components/edit/[id]/release/add/releases/AddRelease.tsx +++ b/src/app/[locale]/components/edit/[id]/release/add/releases/AddRelease.tsx @@ -35,6 +35,7 @@ import COTSDetails from '@/object-types/COTSDetails' import ToastData from '@/object-types/ToastData' import { ToastContainer } from 'react-bootstrap' import ToastMessage from '@/components/sw360/ToastContainer/Toast' +import CommonUtils from '@/utils/common.utils' interface Props { session?: Session @@ -161,16 +162,12 @@ const AddRelease = ({ session, componentId }: Props) => { }) }, [componentId, fetchData]) - const handleId = (id: string): string => { - return id.split('/').at(-1) - } - const submit = async () => { const response = await ApiUtils.POST('releases', releasePayload, session.user.access_token) if (response.status == HttpStatus.CREATED) { const data = await response.json() alert(true, 'Success', t('Release is created'), 'success') - const releaseId: string = handleId(data._links.self.href) + const releaseId: string = CommonUtils.getIdFromUrl(data._links.self.href) router.push('/components/releases/detail/' + releaseId) } else if (response.status == HttpStatus.CONFLICT) { alert(true, 'Duplicate', t('Release is Duplicate'), 'warning') diff --git a/src/app/[locale]/components/editRelease/[id]/releases/EditRelease.tsx b/src/app/[locale]/components/editRelease/[id]/releases/EditRelease.tsx index 68a625ca..5e70777a 100644 --- a/src/app/[locale]/components/editRelease/[id]/releases/EditRelease.tsx +++ b/src/app/[locale]/components/editRelease/[id]/releases/EditRelease.tsx @@ -12,13 +12,17 @@ import { PageButtonHeader, SideBar } from '@/components/sw360' import { Session } from '@/object-types/Session' import CommonTabIds from '@/object-types/enums/CommonTabsIds' -import { useState } from 'react' +import { useCallback, useEffect, useState } from 'react' import ReleaseEditTabs from './ReleaseEditTabs' import ReleaseEditSummary from './ReleaseEditSummary' import Vendor from '@/object-types/Vendor' import Licenses from '@/object-types/Licenses' import Moderators from '@/object-types/Moderators' import ReleasePayload from '@/object-types/ReleasePayload' +import ApiUtils from '@/utils/api/api.util' +import HttpStatus from '@/object-types/enums/HttpStatus' +import { signOut } from 'next-auth/react' +import ActionType from '@/object-types/enums/ActionType' interface Props { session?: Session @@ -28,6 +32,28 @@ interface Props { const EditRelease = ({ session, releaseId }: Props) => { const [selectedTab, setSelectedTab] = useState(CommonTabIds.SUMMARY) const [tabList, setTabList] = useState(ReleaseEditTabs.WITH_COMMERCIAL_DETAILS) + const [release, setRelease] = useState(undefined) + + const fetchData: any = useCallback( + async (url: string) => { + 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) { + signOut() + } else { + return null + } + }, + [session.user.access_token] + ) + + useEffect(() => { + fetchData(`releases/${releaseId}`).then((release: any) => { + setRelease(release) + }) + }, [releaseId]) const [releasePayload, setReleasePayload] = useState({ name: '', @@ -93,8 +119,7 @@ const EditRelease = ({ session, releaseId }: Props) => { } return ( - <> - {' '} + release && (
@@ -107,7 +132,9 @@ const EditRelease = ({ session, releaseId }: Props) => {
- + ) ) } diff --git a/src/app/[locale]/components/editRelease/[id]/releases/ReleaseEditSummary.tsx b/src/app/[locale]/components/editRelease/[id]/releases/ReleaseEditSummary.tsx index 78fdae41..b50d7cd9 100644 --- a/src/app/[locale]/components/editRelease/[id]/releases/ReleaseEditSummary.tsx +++ b/src/app/[locale]/components/editRelease/[id]/releases/ReleaseEditSummary.tsx @@ -10,17 +10,30 @@ 'use client' +import AddAdditionalRolesComponent from '@/components/AddAdditionalRoles' +import AddKeyValueComponent from '@/components/AddKeyValue' +import ReleaseRepository from '@/components/ReleaseRepository/ReleaseRepository' import ReleaseSummary from '@/components/ReleaseSummary/ReleaseSummary' +import { COMMON_NAMESPACE } from '@/object-types/Constants' import Licenses from '@/object-types/Licenses' import Moderators from '@/object-types/Moderators' import ReleasePayload from '@/object-types/ReleasePayload' import { Session } from '@/object-types/Session' import Vendor from '@/object-types/Vendor' +import DocumentTypes from '@/object-types/enums/DocumentTypes' +import HttpStatus from '@/object-types/enums/HttpStatus' +import ApiUtils from '@/utils/api/api.util' +import CommonUtils from '@/utils/common.utils' +import { signOut } from 'next-auth/react' +import { useTranslations } from 'next-intl' +import { notFound } from 'next/navigation' +import { useCallback, useEffect, useState } from 'react' interface Props { session?: Session release?: any releaseId?: string + actionType?: string releasePayload?: ReleasePayload setReleasePayload?: React.Dispatch> vendor?: Vendor @@ -37,7 +50,9 @@ interface Props { export default function ReleaseEditSummary({ session, + release, releaseId, + actionType, releasePayload, setReleasePayload, vendor, @@ -51,6 +66,229 @@ export default function ReleaseEditSummary({ moderator, setModerator, }: Props) { + const t = useTranslations(COMMON_NAMESPACE) + const [roles, setRoles] = useState([]) + const [externalIds, setExternalIds] = useState([]) + const [addtionalData, setAddtionalData] = useState([]) + + const setDataAddtionalData = (additionalDatas: Map) => { + const obj = Object.fromEntries(additionalDatas) + setReleasePayload({ + ...releasePayload, + additionalData: obj, + }) + } + + const setDataExternalIds = (externalIds: Map) => { + const obj = Object.fromEntries(externalIds) + setReleasePayload({ + ...releasePayload, + externalIds: obj, + }) + } + + const setDataRoles = (roles: Input[]) => { + const roleDatas = convertRoles(roles) + setReleasePayload({ + ...releasePayload, + roles: roleDatas, + }) + } + const convertRoles = (datas: Input[]) => { + if (datas === null) { + return null; + } + const contributors: string[] = [] + const commiters: string[] = [] + const expecters: string[] = [] + datas.forEach((data) => { + if (data.key === 'Contributor') { + contributors.push(data.value) + } else if (data.key === 'Committer') { + commiters.push(data.value) + } else if (data.key === 'Expert') { + expecters.push(data.value) + } + }) + const roles = { + Contributor: contributors, + Committer: commiters, + Expert: expecters, + } + return roles + } + + const fetchData: any = useCallback( + async (url: string) => { + 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) { + signOut() + } else { + notFound() + } + }, + [session.user.access_token] + ) + + const handlerModerators = (emails: any[]) => { + const fullNames: string[] = [] + const moderatorsEmail: string[] = [] + if (emails.length == 0) { + return + } + emails.forEach((item) => { + fullNames.push(item.fullName) + moderatorsEmail.push(item.email) + }) + const moderatorsName: string = fullNames.join(' , ') + const moderatorsResponse: Moderators = { + fullName: moderatorsName, + emails: moderatorsEmail, + } + return moderatorsResponse + } + + const handlerContributor = (emails: any[]) => { + const fullNames: string[] = [] + const contributorsEmail: string[] = [] + if (emails.length == 0) { + return + } + emails.forEach((item) => { + fullNames.push(item.fullName) + contributorsEmail.push(item.email) + }) + const contributorsName: string = fullNames.join(' , ') + const contributorsResponse: Moderators = { + fullName: contributorsName, + emails: contributorsEmail, + } + return contributorsResponse + } + + const getEmailsModerators = (emails: any[]) => { + const moderatorsEmail: string[] = [] + if (typeof emails === 'undefined') { + return + } + emails.forEach((item) => { + moderatorsEmail.push(item.email) + }) + + return moderatorsEmail + } + + const convertObjectToMap = (data: string) => { + const map = new Map(Object.entries(data)) + const inputs: Input[] = [] + map.forEach((value, key) => { + const input: Input = { + key: key, + value: value, + } + inputs.push(input) + }) + return inputs + } + + const convertObjectToMapRoles = (data: string) => { + if (data === undefined) { + return null + } + const inputRoles: Input[] = [] + const mapRoles = new Map(Object.entries(data)) + mapRoles.forEach((value, key) => { + for (let index = 0; index < value.length; index++) { + const input: Input = { + key: key, + value: value.at(index), + } + inputRoles.push(input) + } + }) + return inputRoles + } + + useEffect(() => { + if (typeof release.roles !== 'undefined') { + setRoles(convertObjectToMapRoles(release.roles)) + } + + if (typeof release.externalIds !== 'undefined') { + setExternalIds(convertObjectToMap(release.externalIds)) + } + + if (typeof release.additionalData !== 'undefined') { + setAddtionalData(convertObjectToMap(release.additionalData)) + } + + if (typeof release['_embedded']['sw360:moderators'] !== 'undefined') { + setModerator(handlerModerators(release['_embedded']['sw360:moderators'])) + } + + if (typeof release['_embedded']['sw360:contributors'] !== 'undefined') { + setContributor(handlerContributor(release['_embedded']['sw360:contributors'])) + } + + let vendorId = '' + if (typeof release['_embedded']['sw360:vendors'] !== 'undefined') { + vendorId = CommonUtils.getIdFromUrl(release['_embedded']['sw360:vendors'][0]._links.self.href) + const vendor: Vendor = { + id: vendorId, + fullName: release['_embedded']['sw360:vendors'][0].fullName, + } + setVendor(vendor) + } + + let modifiedBy = '' + if (typeof release['_embedded']['sw360:modifiedBy'] !== 'undefined') { + modifiedBy = release['_embedded']['sw360:modifiedBy']['fullName'] + } + + let createBy = '' + if (typeof release['_embedded']['sw360:createdBy'] !== 'undefined') { + createBy = release['_embedded']['sw360:createdBy']['fullName'] + } + + let componentId = '' + if (typeof release['_links']['sw360:component']['href'] !== 'undefined') { + componentId = CommonUtils.getIdFromUrl(release['_links']['sw360:component']['href']) + } + + const releasePayload: ReleasePayload = { + name: release.name, + cpeid: release.cpeId, + version: release.version, + componentId: componentId, + releaseDate: release.releaseDate, + externalIds: release.externalIds, + additionalData: release.additionalData, + clearingState: release.clearingState, + mainlineState: release.mainlineState, + contributors: getEmailsModerators(release['_embedded']['sw360:contributors']), + createdOn: release.createdOn, + createBy: createBy, + modifiedBy: modifiedBy, + modifiedOn: release.modifiedOn, + moderators: getEmailsModerators(release['_embedded']['sw360:moderators']), + roles:convertRoles(convertObjectToMapRoles(release.roles)), + mainLicenseIds: release.mainLicenseIds, + otherLicenseIds: release.otherLicenseIds, + vendorId: vendorId, + languages: release.languages, + operatingSystems: release.operatingSystems, + softwarePlatforms: release.softwarePlatforms, + sourceCodeDownloadurl: release.sourceCodeDownloadurl, + binaryDownloadurl: release.binaryDownloadurl, + repository: release.repository, + releaseIdToRelationship: release.releaseIdToRelationship, + } + setReleasePayload(releasePayload) + }, [releaseId, fetchData]) + return ( <>
+
+ +
+
+ +
+
+ +
+
diff --git a/src/components/ReleaseSummary/ReleaseSummary.tsx b/src/components/ReleaseSummary/ReleaseSummary.tsx index 56b6e03a..3d54f068 100644 --- a/src/components/ReleaseSummary/ReleaseSummary.tsx +++ b/src/components/ReleaseSummary/ReleaseSummary.tsx @@ -26,8 +26,10 @@ import { GiCancel } from 'react-icons/gi' import ContributorsDialog from '../sw360/SearchContributors/ContributorsDialog' import ModeratorsDialog from '../sw360/SearchModerators/ModeratorsDialog' import OtherLicensesDialog from '../sw360/SearchOtherLicenses/OtherLicensesDialog' +import ActionType from '@/object-types/enums/ActionType' interface Props { session?: Session + actionType?: string releasePayload?: ReleasePayload setReleasePayload?: React.Dispatch> vendor?: Vendor @@ -64,6 +66,7 @@ const ShowInfoOnHover = ({ text }: { text: string }) => { const ReleaseSummary = ({ session, + actionType, releasePayload, setReleasePayload, vendor, @@ -181,6 +184,14 @@ const ReleaseSummary = ({ }) } + const defaultValueCreatedOn = () => { + return actionType === ActionType.EDIT ? releasePayload.createdOn : currentDate + } + + const defaultValueClearingState = () => { + return actionType === ActionType.EDIT ? releasePayload.clearingState : 'NEW' + } + return ( <>
@@ -246,6 +257,7 @@ const ReleaseSummary = ({ required name='version' onChange={updateField} + value={releasePayload.version ?? ''} />
@@ -263,6 +275,7 @@ const ReleaseSummary = ({ aria-describedby='programming_languages' name='languages' onChange={setArrayData} + value={releasePayload.languages ?? ''} />
@@ -277,6 +290,7 @@ const ReleaseSummary = ({ aria-describedby='operating_systems' name='operatingSystems' onChange={setArrayData} + value={releasePayload.operatingSystems ?? ''} />
@@ -291,6 +305,7 @@ const ReleaseSummary = ({ aria-describedby='Tag' name='cpeid' onChange={updateField} + value={releasePayload.cpeid ?? ''} />
@@ -312,6 +327,7 @@ const ReleaseSummary = ({ aria-describedby='blog_url' name='softwarePlatforms' onChange={setArrayData} + value={releasePayload.softwarePlatforms ?? ''} />
@@ -326,6 +342,7 @@ const ReleaseSummary = ({ aria-describedby='releaseDate' name='releaseDate' onChange={updateField} + value={releasePayload.releaseDate ?? ''} />
@@ -391,6 +408,7 @@ const ReleaseSummary = ({ aria-describedby='wiki_url' name='sourceCodeDownloadurl' onChange={updateField} + value={releasePayload.sourceCodeDownloadurl ?? ''} />
@@ -405,6 +423,7 @@ const ReleaseSummary = ({ aria-describedby='wiki_url' name='binaryDownloadurl' onChange={updateField} + value={releasePayload.binaryDownloadurl ?? ''} />
@@ -420,7 +439,8 @@ const ReleaseSummary = ({ id='modified_on' aria-describedby='Modified on' readOnly={true} - value='NEW' + name='clearingState' + defaultValue={defaultValueClearingState()} />
@@ -434,6 +454,7 @@ const ReleaseSummary = ({ required name='mainlineState' onChange={updateField} + value={releasePayload.mainlineState ?? ''} > @@ -456,7 +477,7 @@ const ReleaseSummary = ({ id='createdOn' aria-describedby='Modified on' readOnly={true} - value={currentDate} + defaultValue={defaultValueCreatedOn()} />
@@ -471,8 +492,10 @@ const ReleaseSummary = ({ className='form-control' id='createdBy' placeholder='Will be set automatically' - aria-describedby='Modified on' + aria-describedby='Create by' readOnly={true} + name='createBy' + value={releasePayload.createBy ?? ''} />
@@ -536,6 +559,8 @@ const ReleaseSummary = ({ id='modified_on' aria-describedby='Modified on' readOnly={true} + name='modifiedOn' + value={releasePayload.modifiedOn ?? ''} />
@@ -549,6 +574,8 @@ const ReleaseSummary = ({ id='modified_by' aria-describedby='Modified By' readOnly={true} + name='modifiedBy' + value={releasePayload.modifiedBy ?? ''} />
diff --git a/src/components/sw360/SearchLinkedReleases/SelectTableLinkedReleases.tsx b/src/components/sw360/SearchLinkedReleases/SelectTableLinkedReleases.tsx index 0b9e781c..3aa53810 100644 --- a/src/components/sw360/SearchLinkedReleases/SelectTableLinkedReleases.tsx +++ b/src/components/sw360/SearchLinkedReleases/SelectTableLinkedReleases.tsx @@ -15,6 +15,7 @@ import React from 'react' import { _ } from '@/components/sw360' import LinkedRelease from '@/object-types/LinkedRelease' import LinkedReleasesTable from './LinkedReleasesTable' +import CommonUtils from '@/utils/common.utils' interface Props { releases?: any[] @@ -33,7 +34,7 @@ const SelectTableLinkedReleases = ({ releases, setLinkedReleases, linkedReleases const releaseLinks: LinkedRelease[] = [] linkedReleases.forEach((item: any) => { const releaseLink: LinkedRelease = { - id: handleId(item._links.self.href), + id: CommonUtils.getIdFromUrl(item._links.self.href), name: item.name, version: item.version, mainlineState: item.mainlineState, @@ -46,10 +47,6 @@ const SelectTableLinkedReleases = ({ releases, setLinkedReleases, linkedReleases setLinkedReleases(releaseLinks) } - const handleId = (id: string): string => { - return id.split('/').at(-1) - } - const columns = [ { id: 'releaseId', diff --git a/src/components/sw360/SearchMainLicenses/SelectTableMainLicenses.tsx b/src/components/sw360/SearchMainLicenses/SelectTableMainLicenses.tsx index 39c73ef9..89f6fcb0 100644 --- a/src/components/sw360/SearchMainLicenses/SelectTableMainLicenses.tsx +++ b/src/components/sw360/SearchMainLicenses/SelectTableMainLicenses.tsx @@ -16,6 +16,7 @@ import { Table, _ } from '@/components/sw360' import LicensesTable from './MainLicensesTable' import Licenses from '@/object-types/Licenses' import { LicensesType } from '@/object-types/LicensesType' +import CommonUtils from '@/utils/common.utils' interface Props { licenseDatas?: any[] @@ -35,7 +36,7 @@ const SelectTableMainLicenses = ({ licenseDatas, setLicenses, fullnames }: Props const licensesId: string[] = [] fullnames.forEach((item) => { fullNameLicenses.push(item.fullName) - licensesId.push(handleId(item._links.self.href)) + licensesId.push(CommonUtils.getIdFromUrl(item._links.self.href)) }) const licensesName: string = fullNameLicenses.join(' , ') const licensesResponse: Licenses = { @@ -45,10 +46,6 @@ const SelectTableMainLicenses = ({ licenseDatas, setLicenses, fullnames }: Props setLicenses(licensesResponse) } - const handleId = (id: string): string => { - return id.split('/').at(-1) - } - const columns = [ { id: 'licenseId', diff --git a/src/components/sw360/SearchOtherLicenses/SelectTableOtherLicenses.tsx b/src/components/sw360/SearchOtherLicenses/SelectTableOtherLicenses.tsx index d426b3b8..9a55b3e2 100644 --- a/src/components/sw360/SearchOtherLicenses/SelectTableOtherLicenses.tsx +++ b/src/components/sw360/SearchOtherLicenses/SelectTableOtherLicenses.tsx @@ -16,6 +16,7 @@ import { _ } from '@/components/sw360' import LicensesTable from './OtherLicensesTable' import { LicensesType } from '@/object-types/LicensesType' import Licenses from '@/object-types/Licenses' +import CommonUtils from '@/utils/common.utils' interface Props { licenseDatas?: any[] @@ -35,7 +36,7 @@ const SelectTableOtherLicenses = ({ licenseDatas, setLicenses, fullnames }: Prop const licensesId: string[] = [] fullnames.forEach((item) => { fullNameLicenses.push(item.fullName) - licensesId.push(handleId(item._links.self.href)) + licensesId.push(CommonUtils.getIdFromUrl(item._links.self.href)) }) const licensesName: string = fullNameLicenses.join(' , ') const licensesResponse: Licenses = { @@ -45,10 +46,6 @@ const SelectTableOtherLicenses = ({ licenseDatas, setLicenses, fullnames }: Prop setLicenses(licensesResponse) } - const handleId = (id: string): string => { - return id.split('/').at(-1) - } - const columns = [ { id: 'licenseId', diff --git a/src/components/sw360/SearchVendorsModal/SelectTableVendor.tsx b/src/components/sw360/SearchVendorsModal/SelectTableVendor.tsx index e0e3e32b..7a951bdc 100644 --- a/src/components/sw360/SearchVendorsModal/SelectTableVendor.tsx +++ b/src/components/sw360/SearchVendorsModal/SelectTableVendor.tsx @@ -15,6 +15,7 @@ import React from 'react' import { Table, _ } from '@/components/sw360' import Vendor from '@/object-types/Vendor' import { VendorType } from '@/object-types/VendorType' +import CommonUtils from '@/utils/common.utils' interface Props { vendors: any[] @@ -24,7 +25,7 @@ interface Props { const SelectTableVendor = ({ vendors, setVendor }: Props) => { // item._links.self.href const handlerRadioButton = (item: any) => { - const vendorId: string = handleId(item._links.self.href) + const vendorId: string = CommonUtils.getIdFromUrl(item._links.self.href) const vendorResponse: Vendor = { id: vendorId, fullName: item.fullName, @@ -32,10 +33,6 @@ const SelectTableVendor = ({ vendors, setVendor }: Props) => { setVendor(vendorResponse) } - const handleId = (id: string): string => { - return id.split('/').at(-1) - } - const columns = [ { id: 'vendorId', diff --git a/src/utils/common.utils.ts b/src/utils/common.utils.ts index 7a9d4b16..3148638e 100644 --- a/src/utils/common.utils.ts +++ b/src/utils/common.utils.ts @@ -36,11 +36,16 @@ const isNullEmptyOrUndefinedArray = (arr: Array) => { return false; } +const getIdFromUrl = (url: string): string => { + return url.split('/').at(-1) +} + const CommonUtils = { isNullOrUndefined, isNullEmptyOrUndefinedString, createUrlWithParams, isNullEmptyOrUndefinedArray, + getIdFromUrl } export default CommonUtils; \ No newline at end of file