mirror of
https://github.com/harness/drone.git
synced 2025-05-04 16:52:22 +08:00
Merge branch 'code-213' of _OKE5H2PQKOUfzFFDuD4FA/default/CODE/gitness (#38)
This commit is contained in:
commit
47bca44bc0
@ -43,6 +43,7 @@ export interface AppProps {
|
||||
hooks: Partial<{
|
||||
useGetToken: Unknown
|
||||
usePermissionTranslate: Unknown
|
||||
useGenerateToken: Unknown
|
||||
}>
|
||||
|
||||
currentUser: Required<TypesUser>
|
||||
|
@ -13,8 +13,12 @@
|
||||
background-color: var(--grey-50) !important;
|
||||
border-radius: 4px;
|
||||
padding-left: var(--spacing-small) !important;
|
||||
|
||||
max-width: 300px;
|
||||
.url {
|
||||
width: 250px;
|
||||
white-space: nowrap !important;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: var(--font-size-small) !important;
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,17 @@
|
||||
import React from 'react'
|
||||
import { Container, Layout, Text } from '@harness/uicore'
|
||||
import React, { useState } from 'react'
|
||||
import {
|
||||
Button,
|
||||
ButtonVariation,
|
||||
Color,
|
||||
Container,
|
||||
FontVariation,
|
||||
Layout,
|
||||
Text,
|
||||
} from '@harness/uicore'
|
||||
import { useStrings } from 'framework/strings'
|
||||
import { CopyButton } from 'components/CopyButton/CopyButton'
|
||||
import { CodeIcon } from 'utils/GitUtils'
|
||||
import CloneCredentialDialog from 'components/CloneCredentialDialog/CloneCredentialDialog'
|
||||
import css from './CloneButtonTooltip.module.scss'
|
||||
|
||||
interface CloneButtonTooltipProps {
|
||||
@ -11,18 +20,36 @@ interface CloneButtonTooltipProps {
|
||||
|
||||
export function CloneButtonTooltip({ httpsURL }: CloneButtonTooltipProps) {
|
||||
const { getString } = useStrings()
|
||||
const [flag, setFlag] = useState(false)
|
||||
|
||||
return (
|
||||
<Container className={css.container} padding="xlarge">
|
||||
<Layout.Vertical spacing="small">
|
||||
<Text className={css.label}>{getString('cloneHTTPS')}</Text>
|
||||
<Text font={{ variation: FontVariation.H4 }}>{getString('cloneHTTPS')}</Text>
|
||||
<Text
|
||||
icon={'code-info'}
|
||||
iconProps={{ size: 16 }}
|
||||
color={Color.GREY_700}
|
||||
font={{ variation: FontVariation.BODY2_SEMI, size: 'small' }}>
|
||||
{getString('generateCloneText')}
|
||||
</Text>
|
||||
|
||||
<Container>
|
||||
<Layout.Horizontal className={css.layout}>
|
||||
<Text className={css.url}>{httpsURL}</Text>
|
||||
|
||||
<CopyButton content={httpsURL} id={css.cloneCopyButton} icon={CodeIcon.Copy} iconProps={{ size: 14 }} />
|
||||
</Layout.Horizontal>
|
||||
</Container>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setFlag(true)
|
||||
}}
|
||||
variation={ButtonVariation.SECONDARY}>
|
||||
{getString('generateCloneCred')}
|
||||
</Button>
|
||||
</Layout.Vertical>
|
||||
<CloneCredentialDialog flag={flag} setFlag={setFlag}/>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
.layout {
|
||||
height: 33px;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px solid var(--grey-200);
|
||||
background-color: var(--grey-50) !important;
|
||||
border-radius: 4px;
|
||||
padding-left: var(--spacing-small) !important;
|
||||
max-width: 100%;
|
||||
.url {
|
||||
// width: 80%;
|
||||
white-space: nowrap !important;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: var(--font-size-small) !important;
|
||||
}
|
||||
|
||||
button#cloneCopyButton {
|
||||
--button-height: 24px !important;
|
||||
border-radius: 0 !important;
|
||||
border-left: 1px solid var(--grey-200) !important;
|
||||
margin-left: var(--spacing-small) !important;
|
||||
}
|
||||
}
|
8
web/src/components/CloneCredentialDialog/CloneCredentialDialog.module.scss.d.ts
vendored
Normal file
8
web/src/components/CloneCredentialDialog/CloneCredentialDialog.module.scss.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
/* eslint-disable */
|
||||
// this is an auto-generated file
|
||||
declare const styles: {
|
||||
readonly layout: string
|
||||
readonly url: string
|
||||
readonly cloneCopyButton: string
|
||||
}
|
||||
export default styles
|
@ -0,0 +1,97 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import {
|
||||
Button,
|
||||
ButtonVariation,
|
||||
Container,
|
||||
Dialog,
|
||||
FlexExpander,
|
||||
FontVariation,
|
||||
Layout,
|
||||
Text,
|
||||
useToaster
|
||||
} from '@harness/uicore'
|
||||
import { useStrings } from 'framework/strings'
|
||||
import { CopyButton } from 'components/CopyButton/CopyButton'
|
||||
import { CodeIcon } from 'utils/GitUtils'
|
||||
import { useAppContext } from 'AppContext'
|
||||
import { generateAlphaNumericHash } from 'utils/Utils'
|
||||
import css from './CloneCredentialDialog.module.scss'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
|
||||
interface CloneCredentialDialogProps {
|
||||
setFlag: (val: boolean) => void
|
||||
flag: boolean
|
||||
}
|
||||
|
||||
const CloneCredentialDialog = (props: CloneCredentialDialogProps) => {
|
||||
const { setFlag, flag } = props
|
||||
const history = useHistory()
|
||||
const { getString } = useStrings()
|
||||
const { hooks, currentUser,currentUserProfileURL } = useAppContext()
|
||||
const [token, setToken] = useState('')
|
||||
const { showError } = useToaster()
|
||||
const hash = generateAlphaNumericHash(6)
|
||||
|
||||
const tokenData = hooks?.useGenerateToken(hash, currentUser.uid, flag)
|
||||
useEffect(() => {
|
||||
if (tokenData) {
|
||||
if (tokenData && tokenData?.status !== 400) {
|
||||
setToken(tokenData?.data)
|
||||
} else if (tokenData?.status === 400 && flag) {
|
||||
setToken('N/A')
|
||||
showError(tokenData?.data?.message || tokenData?.message)
|
||||
}
|
||||
}
|
||||
}, [flag, tokenData])
|
||||
return (
|
||||
<Dialog
|
||||
isOpen={flag}
|
||||
enforceFocus={false}
|
||||
onClose={() => {
|
||||
setFlag(false)
|
||||
}}
|
||||
title={
|
||||
<Text font={{ variation: FontVariation.H3 }} icon={'success-tick'} iconProps={{ size: 26 }}>
|
||||
{getString('getMyCloneTitle')}
|
||||
</Text>
|
||||
}
|
||||
style={{ width: 490, maxHeight: '95vh', overflow: 'auto' }}>
|
||||
<Layout.Vertical width={380}>
|
||||
<Text padding={{ bottom: 'small' }} font={{ variation: FontVariation.FORM_LABEL, size: 'small' }}>
|
||||
{getString('userName')}
|
||||
</Text>
|
||||
<Container padding={{ bottom: 'medium' }}>
|
||||
<Layout.Horizontal className={css.layout}>
|
||||
<Text className={css.url}>{currentUser.display_name}</Text>
|
||||
<FlexExpander />
|
||||
<CopyButton
|
||||
content={currentUser.display_name}
|
||||
id={css.cloneCopyButton}
|
||||
icon={CodeIcon.Copy}
|
||||
iconProps={{ size: 14 }}
|
||||
/>
|
||||
</Layout.Horizontal>
|
||||
</Container>
|
||||
<Text padding={{ bottom: 'small' }} font={{ variation: FontVariation.FORM_LABEL, size: 'small' }}>
|
||||
{getString('passwordApi')}
|
||||
</Text>
|
||||
|
||||
<Container padding={{ bottom: 'medium' }}>
|
||||
<Layout.Horizontal className={css.layout}>
|
||||
<Text className={css.url}>{token}</Text>
|
||||
<FlexExpander />
|
||||
<CopyButton content={token} id={css.cloneCopyButton} icon={CodeIcon.Copy} iconProps={{ size: 14 }} />
|
||||
</Layout.Horizontal>
|
||||
</Container>
|
||||
<Text padding={{ bottom: 'medium' }} font={{ variation: FontVariation.BODY2_SEMI, size: 'small' }}>
|
||||
{getString('cloneText')}
|
||||
</Text>
|
||||
<Button onClick={()=>{
|
||||
history.push(currentUserProfileURL)
|
||||
}} variation={ButtonVariation.TERTIARY} text={getString('manageApiToken')} />
|
||||
</Layout.Vertical>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
export default CloneCredentialDialog
|
@ -42,6 +42,7 @@ export interface StringsMap {
|
||||
checks: string
|
||||
clone: string
|
||||
cloneHTTPS: string
|
||||
cloneText: string
|
||||
closed: string
|
||||
comment: string
|
||||
commentDeleted: string
|
||||
@ -122,7 +123,11 @@ export interface StringsMap {
|
||||
findATag: string
|
||||
findBranch: string
|
||||
findOrCreateBranch: string
|
||||
firstTimeTitle: string
|
||||
general: string
|
||||
generateCloneCred: string
|
||||
generateCloneText: string
|
||||
getMyCloneTitle: string
|
||||
gitIgnore: string
|
||||
history: string
|
||||
in: string
|
||||
@ -133,6 +138,8 @@ export interface StringsMap {
|
||||
loading: string
|
||||
makeOptional: string
|
||||
makeRequired: string
|
||||
manageApiToken: string
|
||||
manageCredText: string
|
||||
merged: string
|
||||
missingPerms: string
|
||||
missingPermsContent: string
|
||||
@ -172,6 +179,7 @@ export interface StringsMap {
|
||||
pageLoading: string
|
||||
pageNotFound: string
|
||||
password: string
|
||||
passwordApi: string
|
||||
payloadUrl: string
|
||||
payloadUrlLabel: string
|
||||
pending: string
|
||||
@ -251,6 +259,7 @@ export interface StringsMap {
|
||||
repoDeleted: string
|
||||
repoEmptyMarkdown: string
|
||||
repoEmptyMarkdownClone: string
|
||||
repoEmptyMarkdownClonePush: string
|
||||
repoEmptyMarkdownExisting: string
|
||||
repoUpdate: string
|
||||
'repos.activities': string
|
||||
@ -292,6 +301,7 @@ export interface StringsMap {
|
||||
updateFile: string
|
||||
updateWebhook: string
|
||||
updated: string
|
||||
userName: string
|
||||
'validation.gitBranchNameInvalid': string
|
||||
'validation.repoNamePatternIsNotValid': string
|
||||
viewAllBranches: string
|
||||
|
@ -279,6 +279,7 @@ repoEmptyMarkdownClone: |
|
||||
```sh
|
||||
git clone REPO_URL
|
||||
```
|
||||
repoEmptyMarkdownClonePush: |
|
||||
Then push some content into it.
|
||||
|
||||
```sh
|
||||
@ -362,3 +363,12 @@ repoUpdate: Repository Updated
|
||||
deleteRepoText: Are you sure you want to delete the repository '{REPONAME}'?
|
||||
deleteRepoTitle: Delete the repository
|
||||
resolve: Resolve
|
||||
generateCloneCred: + Generate Clone Credential
|
||||
generateCloneText: "Please generate clone credential if it’s your first time"
|
||||
getMyCloneTitle: Get My Clone Credential
|
||||
cloneText: Your clone credentials have been generated. Please make sure to copy and store your password somewhere safe, you won't be able to see it again.
|
||||
manageApiToken: Manage Api Token
|
||||
userName: User Name
|
||||
passwordApi: Password (API Token)
|
||||
firstTimeTitle: Please generate Git Credentials if it’s your first time to clone the repository
|
||||
manageCredText: You can also manage your git credential {URL}
|
||||
|
@ -28,3 +28,33 @@
|
||||
margin: var(--spacing-small) var(--spacing-xlarge) !important;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.layout {
|
||||
height: 33px;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px solid var(--grey-200);
|
||||
background-color: var(--grey-50) !important;
|
||||
border-radius: 4px;
|
||||
padding-left: var(--spacing-small) !important;
|
||||
max-width: 100%;
|
||||
.url {
|
||||
// width: 80%;
|
||||
white-space: nowrap !important;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: var(--font-size-small) !important;
|
||||
}
|
||||
|
||||
button#cloneCopyButton {
|
||||
--button-height: 24px !important;
|
||||
border-radius: 0 !important;
|
||||
border-left: 1px solid var(--grey-200) !important;
|
||||
margin-left: var(--spacing-small) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
|
@ -6,5 +6,9 @@ declare const styles: {
|
||||
readonly divContainer: string
|
||||
readonly textContainer: string
|
||||
readonly bannerContainer: string
|
||||
readonly layout: string
|
||||
readonly url: string
|
||||
readonly cloneCopyButton: string
|
||||
readonly text: string
|
||||
}
|
||||
export default styles
|
||||
|
@ -4,6 +4,7 @@ import {
|
||||
Button,
|
||||
ButtonVariation,
|
||||
Container,
|
||||
FlexExpander,
|
||||
FontVariation,
|
||||
Layout,
|
||||
PageBody,
|
||||
@ -19,7 +20,7 @@ import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
|
||||
import { useStrings } from 'framework/strings'
|
||||
import type { OpenapiGetContentOutput, TypesRepository } from 'services/code'
|
||||
import { MarkdownViewer } from 'components/MarkdownViewer/MarkdownViewer'
|
||||
import type { GitInfoProps } from 'utils/GitUtils'
|
||||
import { CodeIcon, GitInfoProps } from 'utils/GitUtils'
|
||||
import { useDisableCodeMainLinks } from 'hooks/useDisableCodeMainLinks'
|
||||
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
|
||||
import { Images } from 'images'
|
||||
@ -27,6 +28,8 @@ import { RepositoryContent } from './RepositoryContent/RepositoryContent'
|
||||
import { RepositoryHeader } from './RepositoryHeader/RepositoryHeader'
|
||||
import { ContentHeader } from './RepositoryContent/ContentHeader/ContentHeader'
|
||||
import css from './Repository.module.scss'
|
||||
import { CopyButton } from 'components/CopyButton/CopyButton'
|
||||
import CloneCredentialDialog from 'components/CloneCredentialDialog/CloneCredentialDialog'
|
||||
|
||||
export default function Repository() {
|
||||
const { gitRef, resourcePath, repoMetadata, error, loading, refetch } = useGetRepositoryMetadata()
|
||||
@ -128,6 +131,7 @@ const EmptyRepositoryInfo: React.FC<Pick<GitInfoProps, 'repoMetadata' | 'resourc
|
||||
const { standalone } = useAppContext()
|
||||
const { hooks } = useAppContext()
|
||||
const space = useGetSpaceParam()
|
||||
const [flag, setFlag] = useState(false)
|
||||
|
||||
const permPushResult = hooks?.usePermissionTranslate?.(
|
||||
{
|
||||
@ -173,15 +177,58 @@ const EmptyRepositoryInfo: React.FC<Pick<GitInfoProps, 'repoMetadata' | 'resourc
|
||||
</Container>
|
||||
</Layout.Horizontal>
|
||||
</Container>
|
||||
<Container
|
||||
margin={{ bottom: 'xxlarge' }}
|
||||
padding={{ top: 'xxlarge', bottom: 'xxlarge', left: 'xxlarge', right: 'xxlarge' }}
|
||||
className={css.divContainer}>
|
||||
<Text font={{ variation: FontVariation.H4 }}>{getString('firstTimeTitle')}</Text>
|
||||
<Text className={css.text} padding={{ top: 'medium', bottom: 'small' }} font={{ variation: FontVariation.BODY }}>
|
||||
{getString('cloneHTTPS')}
|
||||
</Text>
|
||||
<Layout.Horizontal>
|
||||
<Container padding={{ bottom: 'medium' }} width={400} margin={{ right: 'small' }}>
|
||||
<Layout.Horizontal className={css.layout}>
|
||||
<Text className={css.url}>{repoMetadata.git_url}</Text>
|
||||
<FlexExpander />
|
||||
<CopyButton
|
||||
content={repoMetadata?.git_url as string}
|
||||
id={css.cloneCopyButton}
|
||||
icon={CodeIcon.Copy}
|
||||
iconProps={{ size: 14 }}
|
||||
/>
|
||||
</Layout.Horizontal>
|
||||
</Container>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setFlag(true)
|
||||
}}
|
||||
variation={ButtonVariation.SECONDARY}>
|
||||
{getString('generateCloneCred')}
|
||||
</Button>
|
||||
</Layout.Horizontal>
|
||||
<Text font={{ variation: FontVariation.BODY, size: 'small' }}>
|
||||
<StringSubstitute
|
||||
str={getString('manageCredText')}
|
||||
vars={{
|
||||
URL: (
|
||||
<a
|
||||
onClick={() => {
|
||||
history.push(currentUserProfileURL)
|
||||
}}>
|
||||
here
|
||||
</a>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</Text>
|
||||
</Container>
|
||||
<Container
|
||||
margin={{ bottom: 'xxlarge' }}
|
||||
padding={{ top: 'xxlarge', bottom: 'xxlarge', left: 'xxlarge', right: 'xxlarge' }}
|
||||
className={css.divContainer}>
|
||||
<MarkdownViewer
|
||||
getString={getString}
|
||||
source={getString('repoEmptyMarkdownClone')
|
||||
.replace(/REPO_URL/g, repoMetadata.git_url || '')
|
||||
.replace(/REPO_NAME/g, repoMetadata.uid || '')}
|
||||
source={getString('repoEmptyMarkdownClonePush').replace(/REPO_NAME/g, repoMetadata.uid || '')}
|
||||
/>
|
||||
</Container>
|
||||
<Container
|
||||
@ -196,6 +243,7 @@ const EmptyRepositoryInfo: React.FC<Pick<GitInfoProps, 'repoMetadata' | 'resourc
|
||||
.replace(/CREATE_API_TOKEN_URL/g, currentUserProfileURL || '')}
|
||||
/>
|
||||
</Container>
|
||||
<CloneCredentialDialog flag={flag} setFlag={setFlag} />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
@ -26,6 +26,19 @@ export function permissionProps(permResult: { disabled: boolean; tooltip: JSX.El
|
||||
return !perm ? permResult : undefined
|
||||
}
|
||||
|
||||
export function generateAlphaNumericHash(length: number) {
|
||||
let result = '';
|
||||
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
const charactersLength = characters.length;
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
export const dayAgoInMS = 86400000
|
||||
|
||||
export const getErrorMessage = (error: Unknown): string =>
|
||||
|
Loading…
Reference in New Issue
Block a user