mirror of
https://github.com/harness/drone.git
synced 2025-05-17 01:20:13 +08:00
feat: [CODE-1072] Support for importing multiple repositories (#788)
This commit is contained in:
parent
972c7d6c67
commit
bd48d92ff5
@ -0,0 +1,370 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 Harness, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import { Intent } from '@blueprintjs/core'
|
||||||
|
import * as yup from 'yup'
|
||||||
|
import { Color } from '@harnessio/design-system'
|
||||||
|
import { Button, Container, Label, Layout, FlexExpander, Formik, FormikForm, FormInput, Text } from '@harnessio/uicore'
|
||||||
|
import { Icon } from '@harnessio/icons'
|
||||||
|
import { useStrings } from 'framework/strings'
|
||||||
|
import { type ImportSpaceFormData, GitProviders, getProviders, getOrgLabel, getOrgPlaceholder } from 'utils/GitUtils'
|
||||||
|
import css from '../../NewSpaceModalButton/NewSpaceModalButton.module.scss'
|
||||||
|
|
||||||
|
interface ImportReposProps {
|
||||||
|
handleSubmit: (data: ImportSpaceFormData) => void
|
||||||
|
loading: boolean
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
hideModal: any
|
||||||
|
spaceRef: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const getHostPlaceHolder = (gitProvider: string) => {
|
||||||
|
switch (gitProvider) {
|
||||||
|
case GitProviders.GITHUB:
|
||||||
|
case GitProviders.GITHUB_ENTERPRISE:
|
||||||
|
return 'enterGithubPlaceholder'
|
||||||
|
case GitProviders.GITLAB:
|
||||||
|
case GitProviders.GITLAB_SELF_HOSTED:
|
||||||
|
return 'enterGitlabPlaceholder'
|
||||||
|
case GitProviders.BITBUCKET:
|
||||||
|
case GitProviders.BITBUCKET_SERVER:
|
||||||
|
return 'enterBitbucketPlaceholder'
|
||||||
|
default:
|
||||||
|
return 'enterAddress'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ImportReposForm = (props: ImportReposProps) => {
|
||||||
|
const { handleSubmit, loading, hideModal, spaceRef } = props
|
||||||
|
const { getString } = useStrings()
|
||||||
|
const [auth, setAuth] = useState(false)
|
||||||
|
const [step, setStep] = useState(0)
|
||||||
|
const [buttonLoading, setButtonLoading] = useState(false)
|
||||||
|
|
||||||
|
const formInitialValues: ImportSpaceFormData = {
|
||||||
|
gitProvider: GitProviders.GITHUB,
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
name: spaceRef,
|
||||||
|
description: '',
|
||||||
|
organization: '',
|
||||||
|
host: ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const validationSchemaStepOne = yup.object().shape({
|
||||||
|
gitProvider: yup.string().trim().required(getString('importSpace.providerRequired'))
|
||||||
|
})
|
||||||
|
|
||||||
|
const validationSchemaStepTwo = yup.object().shape({
|
||||||
|
organization: yup.string().trim().required(getString('importSpace.orgRequired')),
|
||||||
|
name: yup.string().trim().required(getString('importSpace.spaceNameRequired'))
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Formik
|
||||||
|
initialValues={formInitialValues}
|
||||||
|
formName="importReposForm"
|
||||||
|
enableReinitialize={true}
|
||||||
|
validateOnBlur
|
||||||
|
onSubmit={handleSubmit}>
|
||||||
|
{formik => {
|
||||||
|
const { values } = formik
|
||||||
|
const handleValidationClick = async () => {
|
||||||
|
try {
|
||||||
|
if (step === 0) {
|
||||||
|
await validationSchemaStepOne.validate(formik.values, { abortEarly: false })
|
||||||
|
setStep(1)
|
||||||
|
} else if (step === 1) {
|
||||||
|
await validationSchemaStepTwo.validate(formik.values, { abortEarly: false })
|
||||||
|
setButtonLoading(true)
|
||||||
|
} // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
} catch (err: any) {
|
||||||
|
formik.setErrors(
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
err.inner.reduce((acc: { [x: string]: any }, current: { path: string | number; message: string }) => {
|
||||||
|
acc[current.path] = current.message
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const handleImport = async () => {
|
||||||
|
await handleSubmit(formik.values)
|
||||||
|
setButtonLoading(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container className={css.hideContainer} width={'97%'}>
|
||||||
|
<FormikForm>
|
||||||
|
{step === 0 ? (
|
||||||
|
<>
|
||||||
|
<Container width={'70%'}>
|
||||||
|
<Layout.Horizontal>
|
||||||
|
<Text padding={{ left: 'small' }} font={{ size: 'small' }}>
|
||||||
|
{getString('importRepos.content')}
|
||||||
|
</Text>
|
||||||
|
</Layout.Horizontal>
|
||||||
|
</Container>
|
||||||
|
<hr className={css.dividerContainer} />
|
||||||
|
<Container className={css.textContainer} width={'70%'}>
|
||||||
|
<FormInput.Select
|
||||||
|
name={'gitProvider'}
|
||||||
|
label={getString('importSpace.gitProvider')}
|
||||||
|
items={getProviders()}
|
||||||
|
className={css.selectBox}
|
||||||
|
/>
|
||||||
|
{formik.errors.gitProvider ? (
|
||||||
|
<Text
|
||||||
|
margin={{ top: 'small', bottom: 'small' }}
|
||||||
|
color={Color.RED_500}
|
||||||
|
icon="circle-cross"
|
||||||
|
iconProps={{ color: Color.RED_500 }}>
|
||||||
|
{formik.errors.gitProvider}
|
||||||
|
</Text>
|
||||||
|
) : null}
|
||||||
|
{![GitProviders.GITHUB, GitProviders.GITLAB, GitProviders.BITBUCKET].includes(
|
||||||
|
values.gitProvider
|
||||||
|
) && (
|
||||||
|
<FormInput.Text
|
||||||
|
name="host"
|
||||||
|
label={getString('importRepo.url')}
|
||||||
|
placeholder={getString(getHostPlaceHolder(values.gitProvider))}
|
||||||
|
tooltipProps={{
|
||||||
|
dataTooltipId: 'spaceUserTextField'
|
||||||
|
}}
|
||||||
|
className={css.hostContainer}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{formik.errors.host ? (
|
||||||
|
<Text
|
||||||
|
margin={{ top: 'small', bottom: 'small' }}
|
||||||
|
color={Color.RED_500}
|
||||||
|
icon="circle-cross"
|
||||||
|
iconProps={{ color: Color.RED_500 }}>
|
||||||
|
{formik.errors.host}
|
||||||
|
</Text>
|
||||||
|
) : null}
|
||||||
|
<Layout.Horizontal flex>
|
||||||
|
{getString('importSpace.authorization')}
|
||||||
|
<Container padding={{ left: 'small' }} width={'100%'}>
|
||||||
|
<hr className={css.dividerContainer} />
|
||||||
|
</Container>
|
||||||
|
</Layout.Horizontal>
|
||||||
|
{formik.values.gitProvider === GitProviders.BITBUCKET && (
|
||||||
|
<FormInput.Text
|
||||||
|
name="username"
|
||||||
|
label={getString('userName')}
|
||||||
|
placeholder={getString('importRepo.userPlaceholder')}
|
||||||
|
tooltipProps={{
|
||||||
|
dataTooltipId: 'spaceUserTextField'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{formik.errors.username ? (
|
||||||
|
<Text
|
||||||
|
margin={{ top: 'small', bottom: 'small' }}
|
||||||
|
color={Color.RED_500}
|
||||||
|
icon="circle-cross"
|
||||||
|
iconProps={{ color: Color.RED_500 }}>
|
||||||
|
{formik.errors.username}
|
||||||
|
</Text>
|
||||||
|
) : null}
|
||||||
|
<FormInput.Text
|
||||||
|
name="password"
|
||||||
|
label={
|
||||||
|
formik.values.gitProvider === GitProviders.BITBUCKET
|
||||||
|
? getString('importRepo.appPassword')
|
||||||
|
: getString('importRepo.passToken')
|
||||||
|
}
|
||||||
|
placeholder={
|
||||||
|
formik.values.gitProvider === GitProviders.BITBUCKET
|
||||||
|
? getString('importRepo.appPasswordPlaceholder')
|
||||||
|
: getString('importRepo.passTokenPlaceholder')
|
||||||
|
}
|
||||||
|
tooltipProps={{
|
||||||
|
dataTooltipId: 'spacePasswordTextField'
|
||||||
|
}}
|
||||||
|
inputGroup={{ type: 'password' }}
|
||||||
|
/>
|
||||||
|
{formik.errors.password ? (
|
||||||
|
<Text
|
||||||
|
margin={{ top: 'small', bottom: 'small' }}
|
||||||
|
color={Color.RED_500}
|
||||||
|
icon="circle-cross"
|
||||||
|
iconProps={{ color: Color.RED_500 }}>
|
||||||
|
{formik.errors.password}
|
||||||
|
</Text>
|
||||||
|
) : null}
|
||||||
|
</Container>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
{step === 1 ? (
|
||||||
|
<>
|
||||||
|
<Layout.Horizontal flex>
|
||||||
|
<Text className={css.detailsLabel} font={{ size: 'small' }} flex>
|
||||||
|
{getString('importSpace.details')}
|
||||||
|
</Text>
|
||||||
|
<Container padding={{ left: 'small' }} width={'100%'}>
|
||||||
|
<hr className={css.dividerContainer} />
|
||||||
|
</Container>
|
||||||
|
</Layout.Horizontal>
|
||||||
|
<Container className={css.textContainer} width={'70%'}>
|
||||||
|
<FormInput.Text
|
||||||
|
name="organization"
|
||||||
|
label={getString(getOrgLabel(values.gitProvider))}
|
||||||
|
placeholder={getString(getOrgPlaceholder(values.gitProvider))}
|
||||||
|
tooltipProps={{
|
||||||
|
dataTooltipId: 'importSpaceOrgName'
|
||||||
|
}}
|
||||||
|
onChange={event => {
|
||||||
|
const target = event.target as HTMLInputElement
|
||||||
|
formik.setFieldValue('organization', target.value)
|
||||||
|
if (target.value) {
|
||||||
|
formik.validateField('organization')
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{formik.errors.organization ? (
|
||||||
|
<Text
|
||||||
|
margin={{ bottom: 'small' }}
|
||||||
|
color={Color.RED_500}
|
||||||
|
icon="circle-cross"
|
||||||
|
iconProps={{ color: Color.RED_500 }}>
|
||||||
|
{formik.errors.organization}
|
||||||
|
</Text>
|
||||||
|
) : null}
|
||||||
|
<Layout.Horizontal>
|
||||||
|
<Label>{getString('importSpace.importLabel')}</Label>
|
||||||
|
<Icon padding={{ left: 'small' }} className={css.icon} name="code-info" size={16} />
|
||||||
|
</Layout.Horizontal>
|
||||||
|
|
||||||
|
<Container className={css.importContainer} padding={'medium'}>
|
||||||
|
<Layout.Horizontal>
|
||||||
|
<FormInput.CheckBox
|
||||||
|
name="repositories"
|
||||||
|
label={getString('pageTitle.repositories')}
|
||||||
|
tooltipProps={{
|
||||||
|
dataTooltipId: 'authorization'
|
||||||
|
}}
|
||||||
|
defaultChecked
|
||||||
|
onClick={() => {
|
||||||
|
setAuth(!auth)
|
||||||
|
}}
|
||||||
|
disabled
|
||||||
|
padding={{ right: 'small' }}
|
||||||
|
className={css.checkbox}
|
||||||
|
/>
|
||||||
|
<Container padding={{ left: 'xxxlarge' }}>
|
||||||
|
<FormInput.CheckBox
|
||||||
|
name="pipelines"
|
||||||
|
label={getString('pageTitle.pipelines')}
|
||||||
|
tooltipProps={{
|
||||||
|
dataTooltipId: 'pipelines'
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setAuth(!auth)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Container>
|
||||||
|
</Layout.Horizontal>
|
||||||
|
</Container>
|
||||||
|
<Container>
|
||||||
|
<hr className={css.dividerContainer} />
|
||||||
|
<FormInput.Text
|
||||||
|
name="name"
|
||||||
|
label={getString('importSpace.spaceName')}
|
||||||
|
placeholder={getString('enterName')}
|
||||||
|
tooltipProps={{
|
||||||
|
dataTooltipId: 'importSpaceName'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{formik.errors.name ? (
|
||||||
|
<Text
|
||||||
|
margin={{ bottom: 'small' }}
|
||||||
|
color={Color.RED_500}
|
||||||
|
icon="circle-cross"
|
||||||
|
iconProps={{ color: Color.RED_500 }}>
|
||||||
|
{formik.errors.name}
|
||||||
|
</Text>
|
||||||
|
) : null}
|
||||||
|
</Container>
|
||||||
|
</Container>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
<hr className={css.dividerContainer} />
|
||||||
|
|
||||||
|
<Layout.Horizontal
|
||||||
|
spacing="small"
|
||||||
|
padding={{ right: 'xxlarge', bottom: 'large' }}
|
||||||
|
style={{ alignItems: 'center' }}>
|
||||||
|
{step === 1 ? (
|
||||||
|
<Button
|
||||||
|
disabled={buttonLoading}
|
||||||
|
text={
|
||||||
|
buttonLoading ? (
|
||||||
|
<>
|
||||||
|
<Container className={css.loadingIcon} width={93.5} flex={{ alignItems: 'center' }}>
|
||||||
|
<Icon className={css.loadingIcon} name="steps-spinner" size={16} />
|
||||||
|
</Container>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
getString('importRepos.title')
|
||||||
|
)
|
||||||
|
}
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
onClick={() => {
|
||||||
|
handleValidationClick()
|
||||||
|
if (formik.values.name !== '' && formik.values.organization !== '') {
|
||||||
|
handleImport()
|
||||||
|
setButtonLoading(false)
|
||||||
|
}
|
||||||
|
formik.setErrors({})
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
text={getString('importSpace.next')}
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
onClick={() => {
|
||||||
|
handleValidationClick()
|
||||||
|
if (
|
||||||
|
(!formik.errors.gitProvider && formik.touched.gitProvider) ||
|
||||||
|
(!formik.errors.username && formik.touched.username) ||
|
||||||
|
(!formik.errors.password && formik.touched.password)
|
||||||
|
) {
|
||||||
|
formik.setErrors({})
|
||||||
|
setStep(1)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Button text={getString('cancel')} minimal onClick={hideModal} />
|
||||||
|
<FlexExpander />
|
||||||
|
|
||||||
|
{loading && <Icon intent={Intent.PRIMARY} name="steps-spinner" size={16} />}
|
||||||
|
</Layout.Horizontal>
|
||||||
|
</FormikForm>
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</Formik>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ImportReposForm
|
@ -59,15 +59,17 @@ import {
|
|||||||
import {
|
import {
|
||||||
GitProviders,
|
GitProviders,
|
||||||
ImportFormData,
|
ImportFormData,
|
||||||
|
ImportSpaceFormData,
|
||||||
RepoCreationType,
|
RepoCreationType,
|
||||||
RepoFormData,
|
RepoFormData,
|
||||||
RepoVisibility,
|
RepoVisibility,
|
||||||
isGitBranchNameValid,
|
isGitBranchNameValid,
|
||||||
getProviderTypeMapping
|
getProviderTypeMapping
|
||||||
} from 'utils/GitUtils'
|
} from 'utils/GitUtils'
|
||||||
import type { TypesRepository, OpenapiCreateRepositoryRequest } from 'services/code'
|
import type { TypesSpace, TypesRepository, OpenapiCreateRepositoryRequest } from 'services/code'
|
||||||
import { useAppContext } from 'AppContext'
|
import { useAppContext } from 'AppContext'
|
||||||
import ImportForm from './ImportForm/ImportForm'
|
import ImportForm from './ImportForm/ImportForm'
|
||||||
|
import ImportReposForm from './ImportReposForm/ImportReposForm'
|
||||||
import Private from '../../icons/private.svg'
|
import Private from '../../icons/private.svg'
|
||||||
import css from './NewRepoModalButton.module.scss'
|
import css from './NewRepoModalButton.module.scss'
|
||||||
|
|
||||||
@ -120,6 +122,10 @@ export const NewRepoModalButton: React.FC<NewRepoModalButtonProps> = ({
|
|||||||
space_path: space
|
space_path: space
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const { mutate: importMultipleRepositories, loading: submitImportLoading } = useMutate<TypesSpace>({
|
||||||
|
verb: 'POST',
|
||||||
|
path: `/api/v1/spaces/${space}/+/import`
|
||||||
|
})
|
||||||
const {
|
const {
|
||||||
data: gitignores,
|
data: gitignores,
|
||||||
loading: gitIgnoreLoading,
|
loading: gitIgnoreLoading,
|
||||||
@ -130,7 +136,7 @@ export const NewRepoModalButton: React.FC<NewRepoModalButtonProps> = ({
|
|||||||
loading: licenseLoading,
|
loading: licenseLoading,
|
||||||
error: licenseError
|
error: licenseError
|
||||||
} = useGet({ path: '/api/v1/resources/license' })
|
} = useGet({ path: '/api/v1/resources/license' })
|
||||||
const loading = submitLoading || gitIgnoreLoading || licenseLoading || importRepoLoading
|
const loading = submitLoading || gitIgnoreLoading || licenseLoading || importRepoLoading || submitImportLoading
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (gitIgnoreError || licenseError) {
|
if (gitIgnoreError || licenseError) {
|
||||||
@ -192,6 +198,36 @@ export const NewRepoModalButton: React.FC<NewRepoModalButtonProps> = ({
|
|||||||
showError(getErrorMessage(_error), 0, getString('importRepo.failedToImportRepo'))
|
showError(getErrorMessage(_error), 0, getString('importRepo.failedToImportRepo'))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleMultiRepoImportSubmit = async (formData: ImportSpaceFormData) => {
|
||||||
|
const type = getProviderTypeMapping(formData.gitProvider)
|
||||||
|
|
||||||
|
const provider = {
|
||||||
|
type,
|
||||||
|
username: formData.username,
|
||||||
|
password: formData.password,
|
||||||
|
host: ''
|
||||||
|
}
|
||||||
|
|
||||||
|
if (![GitProviders.GITHUB, GitProviders.GITLAB, GitProviders.BITBUCKET].includes(formData.gitProvider)) {
|
||||||
|
provider.host = formData.host
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const importPayload = {
|
||||||
|
description: (formData.description || '').trim(),
|
||||||
|
parent_ref: space,
|
||||||
|
uid: formData.name.trim(),
|
||||||
|
provider,
|
||||||
|
provider_space: formData.organization
|
||||||
|
}
|
||||||
|
const response = await importMultipleRepositories(importPayload)
|
||||||
|
hideModal()
|
||||||
|
onSubmit(response)
|
||||||
|
} catch (exception) {
|
||||||
|
showError(getErrorMessage(exception), 0, getString('failedToImportSpace'))
|
||||||
|
}
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
isOpen
|
isOpen
|
||||||
@ -204,12 +240,23 @@ export const NewRepoModalButton: React.FC<NewRepoModalButtonProps> = ({
|
|||||||
style={{ height: '100%' }}
|
style={{ height: '100%' }}
|
||||||
data-testid="add-target-to-flag-modal">
|
data-testid="add-target-to-flag-modal">
|
||||||
<Heading level={3} font={{ variation: FontVariation.H3 }} margin={{ bottom: 'xlarge' }}>
|
<Heading level={3} font={{ variation: FontVariation.H3 }} margin={{ bottom: 'xlarge' }}>
|
||||||
{repoOption.type === RepoCreationType.IMPORT ? getString('importRepo.title') : modalTitle}
|
{repoOption.type === RepoCreationType.IMPORT
|
||||||
|
? getString('importRepo.title')
|
||||||
|
: repoOption.type === RepoCreationType.IMPORT_MULTIPLE
|
||||||
|
? getString('importRepos.title')
|
||||||
|
: modalTitle}
|
||||||
</Heading>
|
</Heading>
|
||||||
|
|
||||||
<Container margin={{ right: 'xxlarge' }}>
|
<Container margin={{ right: 'xxlarge' }}>
|
||||||
{repoOption.type === RepoCreationType.IMPORT ? (
|
{repoOption.type === RepoCreationType.IMPORT ? (
|
||||||
<ImportForm hideModal={hideModal} handleSubmit={handleImportSubmit} loading={false} />
|
<ImportForm hideModal={hideModal} handleSubmit={handleImportSubmit} loading={false} />
|
||||||
|
) : repoOption.type === RepoCreationType.IMPORT_MULTIPLE ? (
|
||||||
|
<ImportReposForm
|
||||||
|
hideModal={hideModal}
|
||||||
|
handleSubmit={handleMultiRepoImportSubmit}
|
||||||
|
loading={false}
|
||||||
|
spaceRef={space}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={formInitialValues}
|
initialValues={formInitialValues}
|
||||||
@ -361,6 +408,11 @@ export const NewRepoModalButton: React.FC<NewRepoModalButtonProps> = ({
|
|||||||
type: RepoCreationType.IMPORT,
|
type: RepoCreationType.IMPORT,
|
||||||
title: getString('importGitRepo'),
|
title: getString('importGitRepo'),
|
||||||
desc: getString('importGitRepo')
|
desc: getString('importGitRepo')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: RepoCreationType.IMPORT_MULTIPLE,
|
||||||
|
title: getString('importGitRepos'),
|
||||||
|
desc: getString('importGitRepos')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
const [repoOption, setRepoOption] = useState<RepoCreationOption>(repoCreateOptions[0])
|
const [repoOption, setRepoOption] = useState<RepoCreationOption>(repoCreateOptions[0])
|
||||||
@ -399,14 +451,14 @@ export const NewRepoModalButton: React.FC<NewRepoModalButtonProps> = ({
|
|||||||
setRepoOption(repoCreateOptions[0])
|
setRepoOption(repoCreateOptions[0])
|
||||||
setTimeout(() => openModal(), 0)
|
setTimeout(() => openModal(), 0)
|
||||||
}}>
|
}}>
|
||||||
{[repoCreateOptions[1]].map(option => {
|
{[repoCreateOptions[1], repoCreateOptions[2]].map(option => {
|
||||||
return (
|
return (
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
className={css.menuItem}
|
className={css.menuItem}
|
||||||
key={option.type}
|
key={option.type}
|
||||||
text={<Text font={{ variation: FontVariation.BODY2 }}>{option.desc}</Text>}
|
text={<Text font={{ variation: FontVariation.BODY2 }}>{option.desc}</Text>}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setRepoOption(repoCreateOptions[1])
|
setRepoOption(option)
|
||||||
setTimeout(() => openModal(), 0)
|
setTimeout(() => openModal(), 0)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -321,6 +321,7 @@ export interface StringsMap {
|
|||||||
'imageUpload.title': string
|
'imageUpload.title': string
|
||||||
'imageUpload.upload': string
|
'imageUpload.upload': string
|
||||||
importGitRepo: string
|
importGitRepo: string
|
||||||
|
importGitRepos: string
|
||||||
importProgress: string
|
importProgress: string
|
||||||
'importRepo.appPassword': string
|
'importRepo.appPassword': string
|
||||||
'importRepo.appPasswordPlaceholder': string
|
'importRepo.appPasswordPlaceholder': string
|
||||||
@ -347,6 +348,8 @@ export interface StringsMap {
|
|||||||
'importRepo.validation': string
|
'importRepo.validation': string
|
||||||
'importRepo.workspace': string
|
'importRepo.workspace': string
|
||||||
'importRepo.workspacePlaceholder': string
|
'importRepo.workspacePlaceholder': string
|
||||||
|
'importRepos.content': string
|
||||||
|
'importRepos.title': string
|
||||||
'importSpace.authorization': string
|
'importSpace.authorization': string
|
||||||
'importSpace.content': string
|
'importSpace.content': string
|
||||||
'importSpace.createASpace': string
|
'importSpace.createASpace': string
|
||||||
|
@ -106,7 +106,7 @@ repos:
|
|||||||
activities: Monthly Activities
|
activities: Monthly Activities
|
||||||
updated: Updated Date
|
updated: Updated Date
|
||||||
lastChange: Last Change
|
lastChange: Last Change
|
||||||
noDataMessage: There are no repositories in this project. Create a new repository, or import an existing Git repository by clicking below
|
noDataMessage: There are no repositories in this project. Create a new repository, or import an existing Git repository by clicking below.
|
||||||
enterBranchName: Enter a branch name
|
enterBranchName: Enter a branch name
|
||||||
createRepoModal:
|
createRepoModal:
|
||||||
branchLabel: 'Your repository will be initialized with a '
|
branchLabel: 'Your repository will be initialized with a '
|
||||||
@ -748,6 +748,7 @@ pluginsPanel:
|
|||||||
ifNotExists: If not exists
|
ifNotExists: If not exists
|
||||||
createNewRepo: Create New repository
|
createNewRepo: Create New repository
|
||||||
importGitRepo: Import Repository
|
importGitRepo: Import Repository
|
||||||
|
importGitRepos: Import Repositories
|
||||||
importRepo:
|
importRepo:
|
||||||
title: Import Repository
|
title: Import Repository
|
||||||
url: Host URL
|
url: Host URL
|
||||||
@ -774,6 +775,9 @@ importRepo:
|
|||||||
spaceNameReq: Enter a name for the new project
|
spaceNameReq: Enter a name for the new project
|
||||||
usernameReq: Username is required
|
usernameReq: Username is required
|
||||||
passwordReq: Password is required
|
passwordReq: Password is required
|
||||||
|
importRepos:
|
||||||
|
title: Import Repositories
|
||||||
|
content: Import multiple repositories from GitLab Group, GitHub Org or Bitbucket Project to this project in Gitness.
|
||||||
importSpace:
|
importSpace:
|
||||||
title: Import Project
|
title: Import Project
|
||||||
createASpace: Create a project
|
createASpace: Create a project
|
||||||
|
@ -35,7 +35,7 @@ import { useHistory } from 'react-router-dom'
|
|||||||
import { useStrings } from 'framework/strings'
|
import { useStrings } from 'framework/strings'
|
||||||
import { voidFn, formatDate, getErrorMessage, LIST_FETCHING_LIMIT, PageBrowserProps } from 'utils/Utils'
|
import { voidFn, formatDate, getErrorMessage, LIST_FETCHING_LIMIT, PageBrowserProps } from 'utils/Utils'
|
||||||
import { NewRepoModalButton } from 'components/NewRepoModalButton/NewRepoModalButton'
|
import { NewRepoModalButton } from 'components/NewRepoModalButton/NewRepoModalButton'
|
||||||
import type { TypesRepository } from 'services/code'
|
import type { TypesRepository, SpaceImportRepositoriesOutput } from 'services/code'
|
||||||
import { usePageIndex } from 'hooks/usePageIndex'
|
import { usePageIndex } from 'hooks/usePageIndex'
|
||||||
import { useQueryParams } from 'hooks/useQueryParams'
|
import { useQueryParams } from 'hooks/useQueryParams'
|
||||||
import { useUpdateQueryParams } from 'hooks/useUpdateQueryParams'
|
import { useUpdateQueryParams } from 'hooks/useUpdateQueryParams'
|
||||||
@ -176,8 +176,14 @@ export default function RepositoriesListing() {
|
|||||||
onSubmit={repoInfo => {
|
onSubmit={repoInfo => {
|
||||||
if (repoInfo.importing) {
|
if (repoInfo.importing) {
|
||||||
refetch()
|
refetch()
|
||||||
|
} else if (repoInfo) {
|
||||||
|
const multipleImportRepoInfo = repoInfo as SpaceImportRepositoriesOutput
|
||||||
|
if (multipleImportRepoInfo.importing_repos) {
|
||||||
|
history.push(routes.toCODERepositories({ space: space as string }))
|
||||||
|
refetch()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
history.push(routes.toCODERepository({ repoPath: repoInfo.path as string }))
|
history.push(routes.toCODERepository({ repoPath: (repoInfo as TypesRepository).path as string }))
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -585,6 +585,11 @@ export interface SpaceExportProgressOutput {
|
|||||||
repos?: TypesJobProgress[] | null
|
repos?: TypesJobProgress[] | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SpaceImportRepositoriesOutput {
|
||||||
|
duplicate_repos?: TypesRepository[] | null
|
||||||
|
importing_repos?: TypesRepository[] | null
|
||||||
|
}
|
||||||
|
|
||||||
export interface SystemConfigOutput {
|
export interface SystemConfigOutput {
|
||||||
user_signup_allowed?: boolean
|
user_signup_allowed?: boolean
|
||||||
}
|
}
|
||||||
|
@ -7887,6 +7887,19 @@ components:
|
|||||||
nullable: true
|
nullable: true
|
||||||
type: array
|
type: array
|
||||||
type: object
|
type: object
|
||||||
|
SpaceImportRepositoriesOutput:
|
||||||
|
properties:
|
||||||
|
duplicate_repos:
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/TypesRepository'
|
||||||
|
nullable: true
|
||||||
|
type: array
|
||||||
|
importing_repos:
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/TypesRepository'
|
||||||
|
nullable: true
|
||||||
|
type: array
|
||||||
|
type: object
|
||||||
SystemConfigOutput:
|
SystemConfigOutput:
|
||||||
properties:
|
properties:
|
||||||
user_signup_allowed:
|
user_signup_allowed:
|
||||||
|
@ -88,7 +88,8 @@ export enum RepoVisibility {
|
|||||||
|
|
||||||
export enum RepoCreationType {
|
export enum RepoCreationType {
|
||||||
IMPORT = 'import',
|
IMPORT = 'import',
|
||||||
CREATE = 'create'
|
CREATE = 'create',
|
||||||
|
IMPORT_MULTIPLE = 'import_multiple'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum SpaceCreationType {
|
export enum SpaceCreationType {
|
||||||
|
Loading…
Reference in New Issue
Block a user