mirror of https://github.com/harness/drone.git
fix: [ritik/code-1773] Added Repository Setting for Public/Private Access (#2023)
parent
55f340ab7e
commit
ea205ff7ba
|
@ -48,7 +48,9 @@ const App: React.FC<AppProps> = React.memo(function App({
|
|||
hooks,
|
||||
customComponents,
|
||||
currentUserProfileURL = '',
|
||||
defaultSettingsURL = ''
|
||||
defaultSettingsURL = '',
|
||||
isPublicAccessEnabledOnResources = false,
|
||||
isCurrentSessionPublic = false
|
||||
}: AppProps) {
|
||||
const [strings, setStrings] = useState<LanguageRecord>()
|
||||
const getRequestOptions = useCallback(
|
||||
|
@ -90,7 +92,9 @@ const App: React.FC<AppProps> = React.memo(function App({
|
|||
currentUser: defaultCurrentUser,
|
||||
customComponents,
|
||||
currentUserProfileURL,
|
||||
defaultSettingsURL
|
||||
defaultSettingsURL,
|
||||
isPublicAccessEnabledOnResources,
|
||||
isCurrentSessionPublic
|
||||
}}>
|
||||
<IconoirProvider
|
||||
iconProps={{
|
||||
|
|
|
@ -53,7 +53,9 @@ const AppContext = React.createContext<AppContextProps>({
|
|||
},
|
||||
currentUserProfileURL: '',
|
||||
routingId: '',
|
||||
defaultSettingsURL: ''
|
||||
defaultSettingsURL: '',
|
||||
isPublicAccessEnabledOnResources: false,
|
||||
isCurrentSessionPublic: false
|
||||
})
|
||||
|
||||
export const AppContextProvider: React.FC<{ value: AppProps }> = React.memo(function AppContextProvider({
|
||||
|
|
|
@ -78,4 +78,6 @@ export interface AppProps {
|
|||
|
||||
currentUserProfileURL: string
|
||||
defaultSettingsURL: string
|
||||
isPublicAccessEnabledOnResources: boolean
|
||||
isCurrentSessionPublic: boolean
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@ ReactDOM.render(
|
|||
currentUserProfileURL=""
|
||||
routingId=""
|
||||
defaultSettingsURL=""
|
||||
isPublicAccessEnabledOnResources
|
||||
isCurrentSessionPublic={false}
|
||||
/>,
|
||||
document.getElementById('react-root')
|
||||
)
|
||||
|
|
|
@ -15,11 +15,13 @@
|
|||
*/
|
||||
|
||||
import React, { useState } from 'react'
|
||||
import { Render } from 'react-jsx-match'
|
||||
import cx from 'classnames'
|
||||
import { Button, ButtonVariation, Container, FlexExpander, Layout, Text } from '@harnessio/uicore'
|
||||
import { Color, FontVariation } from '@harnessio/design-system'
|
||||
import { Classes } from '@blueprintjs/core'
|
||||
import { Icon } from '@harnessio/icons'
|
||||
import { useAppContext } from 'AppContext'
|
||||
import { useStrings } from 'framework/strings'
|
||||
import { CopyButton } from 'components/CopyButton/CopyButton'
|
||||
import { CodeIcon } from 'utils/GitUtils'
|
||||
|
@ -33,7 +35,7 @@ interface CloneButtonTooltipProps {
|
|||
export function CloneButtonTooltip({ httpsURL }: CloneButtonTooltipProps) {
|
||||
const { getString } = useStrings()
|
||||
const [flag, setFlag] = useState(false)
|
||||
|
||||
const { isCurrentSessionPublic } = useAppContext()
|
||||
return (
|
||||
<Container className={css.container} padding="xlarge">
|
||||
<Layout.Vertical spacing="small">
|
||||
|
@ -58,24 +60,27 @@ export function CloneButtonTooltip({ httpsURL }: CloneButtonTooltipProps) {
|
|||
<CopyButton content={httpsURL} id={css.cloneCopyButton} icon={CodeIcon.Copy} iconProps={{ size: 14 }} />
|
||||
</Layout.Horizontal>
|
||||
</Container>
|
||||
<Button
|
||||
width={300}
|
||||
onClick={() => {
|
||||
setFlag(true)
|
||||
}}
|
||||
variation={ButtonVariation.SECONDARY}>
|
||||
{getString('generateCloneCred')}
|
||||
</Button>
|
||||
<Text
|
||||
padding={{ top: 'small' }}
|
||||
width={300}
|
||||
icon={'code-info'}
|
||||
className={css.codeText}
|
||||
iconProps={{ size: 16 }}
|
||||
color={Color.GREY_700}
|
||||
font={{ variation: FontVariation.BODY2_SEMI, size: 'xsmall' }}>
|
||||
{getString('generateCloneText')}
|
||||
</Text>
|
||||
|
||||
<Render when={!isCurrentSessionPublic}>
|
||||
<Button
|
||||
width={300}
|
||||
onClick={() => {
|
||||
setFlag(true)
|
||||
}}
|
||||
variation={ButtonVariation.SECONDARY}>
|
||||
{getString('generateCloneCred')}
|
||||
</Button>
|
||||
<Text
|
||||
padding={{ top: 'small' }}
|
||||
width={300}
|
||||
icon={'code-info'}
|
||||
className={css.codeText}
|
||||
iconProps={{ size: 16 }}
|
||||
color={Color.GREY_700}
|
||||
font={{ variation: FontVariation.BODY2_SEMI, size: 'xsmall' }}>
|
||||
{getString('generateCloneText')}
|
||||
</Text>
|
||||
</Render>
|
||||
</Layout.Vertical>
|
||||
<CloneCredentialDialog flag={flag} setFlag={setFlag} />
|
||||
</Container>
|
||||
|
|
|
@ -42,7 +42,7 @@ const KEYWORD_REGEX = /((?:(?:-{0,1})(?:repo|lang|file|case|count)):\S*|(?: or|a
|
|||
|
||||
const CodeSearchBar: FC<CodeSearchBarProps> = ({ value, onChange, onSearch, onKeyDown, searchMode, setSearchMode }) => {
|
||||
const { getString } = useStrings()
|
||||
const { hooks, routingId, defaultSettingsURL } = useAppContext()
|
||||
const { hooks, routingId, defaultSettingsURL, isCurrentSessionPublic } = useAppContext()
|
||||
const { SEMANTIC_SEARCH_ENABLED: isSemanticSearchFFEnabled } = hooks?.useFeatureFlags()
|
||||
const { orgIdentifier, projectIdentifier } = useParams<Identifier>()
|
||||
const { data: aidaSettingResponse, loading: isAidaSettingLoading } = hooks?.useGetSettingValue({
|
||||
|
@ -51,7 +51,9 @@ const CodeSearchBar: FC<CodeSearchBarProps> = ({ value, onChange, onSearch, onKe
|
|||
})
|
||||
const [enableSemanticSearch, setEnableSemanticSearch] = useState<boolean>(false)
|
||||
useEffect(() => {
|
||||
setEnableSemanticSearch(isSemanticSearchFFEnabled && aidaSettingResponse?.data?.value == 'true')
|
||||
setEnableSemanticSearch(
|
||||
isSemanticSearchFFEnabled && aidaSettingResponse?.data?.value == 'true' && !isCurrentSessionPublic
|
||||
)
|
||||
}, [isAidaSettingLoading, isSemanticSearchFFEnabled])
|
||||
const isSemanticMode = enableSemanticSearch && searchMode === SEARCH_MODE.SEMANTIC
|
||||
return (
|
||||
|
|
|
@ -26,3 +26,7 @@
|
|||
.breadcrumb {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.hideBreadcrumbs {
|
||||
display: none !important;
|
||||
}
|
||||
|
|
|
@ -18,3 +18,4 @@
|
|||
// This is an auto-generated file
|
||||
export declare const breadcrumb: string
|
||||
export declare const header: string
|
||||
export declare const hideBreadcrumbs: string
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
|
||||
import React, { Fragment } from 'react'
|
||||
import cx from 'classnames'
|
||||
import { Container, Layout, Text, PageHeader, PageHeaderProps } from '@harnessio/uicore'
|
||||
import { Icon } from '@harnessio/icons'
|
||||
import { Color, FontVariation } from '@harnessio/design-system'
|
||||
|
@ -50,7 +51,7 @@ export function RepositoryPageHeader({
|
|||
const { gitRef } = useParams<CODEProps>()
|
||||
const { getString } = useStrings()
|
||||
const space = useGetSpaceParam()
|
||||
const { routes } = useAppContext()
|
||||
const { routes, isCurrentSessionPublic } = useAppContext()
|
||||
|
||||
return (
|
||||
<PageHeader
|
||||
|
@ -59,7 +60,9 @@ export function RepositoryPageHeader({
|
|||
title=""
|
||||
breadcrumbs={
|
||||
<Container className={css.header}>
|
||||
<Layout.Horizontal spacing="small" className={css.breadcrumb}>
|
||||
<Layout.Horizontal
|
||||
spacing="small"
|
||||
className={cx(css.breadcrumb, { [css.hideBreadcrumbs]: isCurrentSessionPublic })}>
|
||||
<Link to={routes.toCODERepositories({ space })}>{getString('repositories')}</Link>
|
||||
<Icon name="main-chevron-right" size={8} color={Color.GREY_500} />
|
||||
<Link to={routes.toCODERepository({ repoPath: (repoMetadata?.path as string) || '', gitRef })}>
|
||||
|
|
|
@ -179,6 +179,7 @@ export interface StringsMap {
|
|||
confirmNewPassword: string
|
||||
confirmPassRequired: string
|
||||
confirmPassword: string
|
||||
confirmRepoVisButton: string
|
||||
confirmation: string
|
||||
content: string
|
||||
contents: string
|
||||
|
@ -206,6 +207,7 @@ export interface StringsMap {
|
|||
'createRepoModal.branchLabel': string
|
||||
'createRepoModal.privateLabel': string
|
||||
'createRepoModal.publicLabel': string
|
||||
'createRepoModal.publicWarning': string
|
||||
createRepoPerms: string
|
||||
createSpace: string
|
||||
createTag: string
|
||||
|
|
|
@ -122,6 +122,7 @@ createRepoModal:
|
|||
branch: ' branch.'
|
||||
publicLabel: Anyone with access to the Gitness environment can clone this repo.
|
||||
privateLabel: You choose who can see and commit to this repository.
|
||||
publicWarning: Please note that anyone with access to the Gitness environment can clone this repo.
|
||||
validation:
|
||||
repoNamePatternIsNotValid: "Name can only contain alphanumerics, '-', '_', '.', and '$'"
|
||||
gitBranchNameInvalid: Branch name is invalid.
|
||||
|
@ -893,7 +894,8 @@ enterGitlabPlaceholder: https://gitlab.com/
|
|||
enterGithubPlaceholder: https://api.github.com/
|
||||
enterBitbucketPlaceholder: https://bitbucket.org/
|
||||
changeRepoVis: Change repository visibility
|
||||
changeRepoVisContent: Are you sure you want to make this repository {repoVis}? {repoText}
|
||||
changeRepoVisContent: Are you sure you want to make this repository {repoVis}?
|
||||
confirmRepoVisButton: Yes, make the Repository {repoVis}
|
||||
repoVisibility: Repository visibility
|
||||
visibility: Visibility
|
||||
attachText: Attach images & videos by dragging & dropping, selecting or pasting them.
|
||||
|
|
|
@ -43,7 +43,7 @@ export function ContentHeader({
|
|||
resourceContent
|
||||
}: Pick<GitInfoProps, 'repoMetadata' | 'gitRef' | 'resourcePath' | 'resourceContent'>) {
|
||||
const { getString } = useStrings()
|
||||
const { routes, standalone, hooks } = useAppContext()
|
||||
const { routes, standalone, hooks, isCurrentSessionPublic } = useAppContext()
|
||||
const history = useHistory()
|
||||
const _isDir = isDir(resourceContent)
|
||||
const space = useGetSpaceParam()
|
||||
|
@ -164,7 +164,9 @@ export function ContentHeader({
|
|||
</>
|
||||
)}
|
||||
</Layout.Horizontal>
|
||||
<div className={css.searchBoxCtn}>{!standalone ? <CodeSearch repoMetadata={repoMetadata} /> : null}</div>
|
||||
<div className={css.searchBoxCtn}>
|
||||
{!standalone && !isCurrentSessionPublic ? <CodeSearch repoMetadata={repoMetadata} /> : null}
|
||||
</div>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -65,8 +65,7 @@ const GeneralSettingsContent = (props: GeneralSettingsProps) => {
|
|||
const { showError, showSuccess } = useToaster()
|
||||
|
||||
const space = useGetSpaceParam()
|
||||
const { standalone } = useAppContext()
|
||||
const { hooks } = useAppContext()
|
||||
const { standalone, hooks, isPublicAccessEnabledOnResources } = useAppContext()
|
||||
const { getString } = useStrings()
|
||||
const currRepoVisibility = repoMetadata?.is_public === true ? RepoVisibility.PUBLIC : RepoVisibility.PRIVATE
|
||||
|
||||
|
@ -77,6 +76,11 @@ const GeneralSettingsContent = (props: GeneralSettingsProps) => {
|
|||
path: `/api/v1/repos/${repoMetadata?.path}/+/`
|
||||
})
|
||||
|
||||
const { mutate: changeVisibility } = useMutate({
|
||||
verb: 'POST',
|
||||
path: `/api/v1/repos/${repoMetadata?.path}/+/public-access`
|
||||
})
|
||||
|
||||
const permEditResult = hooks?.usePermissionTranslate?.(
|
||||
{
|
||||
resource: {
|
||||
|
@ -109,50 +113,71 @@ const GeneralSettingsContent = (props: GeneralSettingsProps) => {
|
|||
return (
|
||||
<Dialog
|
||||
className={css.dialogContainer}
|
||||
style={{ width: 610, maxHeight: '95vh', overflow: 'auto' }}
|
||||
title={getString('changeRepoVis')}
|
||||
style={{ width: 585, maxHeight: '95vh', overflow: 'auto' }}
|
||||
title={<Text font={{ variation: FontVariation.H4 }}>{getString('changeRepoVis')}</Text>}
|
||||
isOpen
|
||||
onClose={hideModal}>
|
||||
<Text>
|
||||
<StringSubstitute
|
||||
str={getString('changeRepoVisContent')}
|
||||
vars={{
|
||||
repoVis: <span className={css.text}>{repoVis}</span>,
|
||||
repoText:
|
||||
repoVis === RepoVisibility.PUBLIC
|
||||
? getString('createRepoModal.publicLabel')
|
||||
: getString('createRepoModal.privateLabel')
|
||||
<Layout.Vertical spacing="xlarge">
|
||||
<Text>
|
||||
<StringSubstitute
|
||||
str={getString('changeRepoVisContent')}
|
||||
vars={{
|
||||
repoVis: <span className={css.text}>{repoVis}</span>
|
||||
}}
|
||||
/>
|
||||
</Text>
|
||||
<Container
|
||||
intent="warning"
|
||||
background="yellow100"
|
||||
border={{
|
||||
color: 'orange500'
|
||||
}}
|
||||
/>
|
||||
</Text>
|
||||
<hr className={css.dividerContainer} />
|
||||
<Layout.Horizontal className={css.buttonContainer}>
|
||||
<Button
|
||||
margin={{ right: 'medium' }}
|
||||
type="submit"
|
||||
text={getString('confirm')}
|
||||
variation={ButtonVariation.PRIMARY}
|
||||
onClick={() => {
|
||||
mutate({ is_public: repoVis === RepoVisibility.PUBLIC ? true : false })
|
||||
.then(() => {
|
||||
showSuccess(getString('repoUpdate'))
|
||||
hideModal()
|
||||
refetch()
|
||||
})
|
||||
.catch(err => {
|
||||
showError(getErrorMessage(err))
|
||||
})
|
||||
refetch()
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
text={getString('cancel')}
|
||||
variation={ButtonVariation.TERTIARY}
|
||||
onClick={() => {
|
||||
hideModal()
|
||||
}}
|
||||
/>
|
||||
</Layout.Horizontal>
|
||||
margin={{ top: 'medium', bottom: 'medium' }}>
|
||||
<Text
|
||||
icon="warning-outline"
|
||||
iconProps={{ size: 16, margin: { right: 'small' } }}
|
||||
padding={{ left: 'large', right: 'large', top: 'small', bottom: 'small' }}
|
||||
color={Color.WARNING}>
|
||||
{repoVis === RepoVisibility.PUBLIC
|
||||
? getString('createRepoModal.publicWarning')
|
||||
: getString('createRepoModal.privateLabel')}
|
||||
</Text>
|
||||
</Container>
|
||||
<Layout.Horizontal className={css.buttonContainer}>
|
||||
<Button
|
||||
margin={{ right: 'medium' }}
|
||||
type="submit"
|
||||
text={
|
||||
<StringSubstitute
|
||||
str={getString('confirmRepoVisButton')}
|
||||
vars={{
|
||||
repoVis: <span className={css.text}>{repoVis}</span>
|
||||
}}
|
||||
/>
|
||||
}
|
||||
variation={ButtonVariation.PRIMARY}
|
||||
onClick={() => {
|
||||
changeVisibility({ is_public: repoVis === RepoVisibility.PUBLIC ? true : false })
|
||||
.then(() => {
|
||||
showSuccess(getString('repoUpdate'))
|
||||
hideModal()
|
||||
refetch()
|
||||
})
|
||||
.catch(err => {
|
||||
showError(getErrorMessage(err))
|
||||
})
|
||||
refetch()
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
text={getString('cancel')}
|
||||
variation={ButtonVariation.TERTIARY}
|
||||
onClick={() => {
|
||||
hideModal()
|
||||
}}
|
||||
/>
|
||||
</Layout.Horizontal>
|
||||
</Layout.Vertical>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
@ -315,7 +340,7 @@ const GeneralSettingsContent = (props: GeneralSettingsProps) => {
|
|||
</Container>
|
||||
</Layout.Horizontal>
|
||||
</Container>
|
||||
<Render when={enablePublicRepo}>
|
||||
<Render when={enablePublicRepo && isPublicAccessEnabledOnResources}>
|
||||
<Container padding="large" margin={{ bottom: 'medium' }} className={css.generalContainer}>
|
||||
<Layout.Horizontal padding={{ bottom: 'medium' }}>
|
||||
<Container className={css.label}>
|
||||
|
@ -330,6 +355,7 @@ const GeneralSettingsContent = (props: GeneralSettingsProps) => {
|
|||
onChange={evt => {
|
||||
setRepoVis((evt.target as HTMLInputElement).value as RepoVisibility)
|
||||
}}
|
||||
{...permissionProps(permEditResult, standalone)}
|
||||
className={css.radioContainer}
|
||||
items={[
|
||||
{
|
||||
|
@ -391,6 +417,7 @@ const GeneralSettingsContent = (props: GeneralSettingsProps) => {
|
|||
setRepoVis(formik.values.isPublic)
|
||||
openModal()
|
||||
}}
|
||||
{...permissionProps(permEditResult, standalone)}
|
||||
/>
|
||||
) : null}
|
||||
</Layout.Horizontal>
|
||||
|
|
|
@ -122,8 +122,6 @@
|
|||
}
|
||||
|
||||
.dialogContainer {
|
||||
padding-bottom: 27px !important;
|
||||
|
||||
:global(.bp3-dialog-header) {
|
||||
margin-bottom: var(--spacing-medium) !important;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue