mirror of
https://github.com/harness/drone.git
synced 2025-05-21 19:39:59 +08:00
feat: [CODE-2819]: Archive Repo functionality (#3097)
This commit is contained in:
parent
f78f767ae2
commit
e9a7fd1e88
@ -44,6 +44,7 @@ import { getErrorMessage, timeDistance } from 'utils/Utils'
|
|||||||
import useLiveTimer from 'hooks/useLiveTimeHook'
|
import useLiveTimer from 'hooks/useLiveTimeHook'
|
||||||
import { CommitActions } from 'components/CommitActions/CommitActions'
|
import { CommitActions } from 'components/CommitActions/CommitActions'
|
||||||
import type { TypesExecution } from 'services/code'
|
import type { TypesExecution } from 'services/code'
|
||||||
|
import { RepoArchivedBanner } from 'components/RepositoryArchivedBanner/RepositoryArchivedBanner'
|
||||||
import css from './ExecutionPageHeader.module.scss'
|
import css from './ExecutionPageHeader.module.scss'
|
||||||
|
|
||||||
interface BreadcrumbLink {
|
interface BreadcrumbLink {
|
||||||
@ -99,6 +100,7 @@ export function ExecutionPageHeader({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<PageHeader
|
<PageHeader
|
||||||
className={css.pageHeader}
|
className={css.pageHeader}
|
||||||
title={title}
|
title={title}
|
||||||
@ -136,7 +138,12 @@ export function ExecutionPageHeader({
|
|||||||
{executionInfo.message}
|
{executionInfo.message}
|
||||||
</Text>
|
</Text>
|
||||||
<PipeSeparator height={7} />
|
<PipeSeparator height={7} />
|
||||||
<Avatar email={executionInfo.authorEmail} name={executionInfo.authorName} size="small" hoverCard={false} />
|
<Avatar
|
||||||
|
email={executionInfo.authorEmail}
|
||||||
|
name={executionInfo.authorName}
|
||||||
|
size="small"
|
||||||
|
hoverCard={false}
|
||||||
|
/>
|
||||||
<Text inline color={Color.GREY_500} font={{ size: 'small' }}>
|
<Text inline color={Color.GREY_500} font={{ size: 'small' }}>
|
||||||
{executionInfo.authorName}
|
{executionInfo.authorName}
|
||||||
</Text>
|
</Text>
|
||||||
@ -213,5 +220,7 @@ export function ExecutionPageHeader({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<RepoArchivedBanner isArchived={repoMetadata?.archived} updated={repoMetadata?.updated} />
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ const PipelineSettingsTab = ({ pipeline, repoPath, yamlPath }: SettingsContentPr
|
|||||||
<Container padding={'large'} className={css.generalContainer}>
|
<Container padding={'large'} className={css.generalContainer}>
|
||||||
<Layout.Vertical>
|
<Layout.Vertical>
|
||||||
<Text icon="main-trash" color={Color.GREY_600} font={{ size: 'normal' }}>
|
<Text icon="main-trash" color={Color.GREY_600} font={{ size: 'normal' }}>
|
||||||
{getString('dangerDeleteRepo')}
|
{getString('dangerDeletePipeline')}
|
||||||
</Text>
|
</Text>
|
||||||
<Layout.Horizontal padding={{ top: 'medium', left: 'medium' }} flex={{ justifyContent: 'space-between' }}>
|
<Layout.Horizontal padding={{ top: 'medium', left: 'medium' }} flex={{ justifyContent: 'space-between' }}>
|
||||||
<Container intent="warning" padding={'small'} className={css.yellowContainer}>
|
<Container intent="warning" padding={'small'} className={css.yellowContainer}>
|
||||||
|
@ -26,3 +26,8 @@
|
|||||||
padding: 0 9px !important;
|
padding: 0 9px !important;
|
||||||
display: inline-block !important;
|
display: inline-block !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.labelArchived {
|
||||||
|
color: rgb(128, 92, 67, 1) !important;
|
||||||
|
border-color: rgb(128, 92, 67, 1) !important;
|
||||||
|
}
|
@ -17,3 +17,4 @@
|
|||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
// This is an auto-generated file
|
// This is an auto-generated file
|
||||||
export declare const label: string
|
export declare const label: string
|
||||||
|
export declare const labelArchived: string
|
@ -15,19 +15,32 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import classNames from 'classnames'
|
||||||
import { Text, TextProps } from '@harnessio/uicore'
|
import { Text, TextProps } from '@harnessio/uicore'
|
||||||
import { useStrings } from 'framework/strings'
|
import { useStrings } from 'framework/strings'
|
||||||
import css from './RepoPublicLabel.module.scss'
|
import css from './RepoTypeLabel.module.scss'
|
||||||
|
|
||||||
export const RepoPublicLabel: React.FC<{ isPublic?: boolean; margin?: TextProps['margin'] }> = ({
|
export const RepoTypeLabel: React.FC<{ isPublic?: boolean; isArchived?: boolean; margin?: TextProps['margin'] }> = ({
|
||||||
isPublic,
|
isPublic,
|
||||||
|
isArchived,
|
||||||
margin
|
margin
|
||||||
}) => {
|
}) => {
|
||||||
const { getString } = useStrings()
|
const { getString } = useStrings()
|
||||||
|
|
||||||
|
const visibility = getString(isPublic ? 'public' : 'private')
|
||||||
|
const archiveStatus = isArchived ? ` ${getString('archived')}` : ''
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<Text inline className={css.label} margin={margin}>
|
<Text inline className={css.label} margin={margin}>
|
||||||
{getString(isPublic ? 'public' : 'private')}
|
{visibility}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
|
{isArchived && (
|
||||||
|
<Text inline className={classNames(css.label, css.labelArchived)} margin={margin}>
|
||||||
|
{archiveStatus}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.infoContainer {
|
||||||
|
background-color: var(--orange-100) !important;
|
||||||
|
padding: var(--spacing-small) var(--spacing-medium) !important;
|
||||||
|
width: 100% !important;
|
||||||
|
margin: 0 auto !important;
|
||||||
|
}
|
19
web/src/components/RepositoryArchivedBanner/RepositoryArchivedBanner.module.scss.d.ts
vendored
Normal file
19
web/src/components/RepositoryArchivedBanner/RepositoryArchivedBanner.module.scss.d.ts
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable */
|
||||||
|
// This is an auto-generated file
|
||||||
|
export declare const infoContainer: string
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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 from 'react'
|
||||||
|
import { Container, Text } from '@harnessio/uicore'
|
||||||
|
import { Color } from '@harnessio/design-system'
|
||||||
|
import { useStrings } from 'framework/strings'
|
||||||
|
import css from './RepositoryArchivedBanner.module.scss'
|
||||||
|
|
||||||
|
export const RepoArchivedBanner: React.FC<{ isArchived?: boolean; updated?: number }> = ({ isArchived, updated }) => {
|
||||||
|
const { getString } = useStrings()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isArchived && (
|
||||||
|
<Container className={css.infoContainer}>
|
||||||
|
<Text
|
||||||
|
icon="main-issue"
|
||||||
|
iconProps={{ size: 16, color: Color.ORANGE_700, margin: { right: 'small' } }}
|
||||||
|
color={Color.GREY_700}>
|
||||||
|
{getString('repoArchive.infoText', {
|
||||||
|
date: updated
|
||||||
|
? new Intl.DateTimeFormat('en-US', {
|
||||||
|
day: '2-digit',
|
||||||
|
month: 'short',
|
||||||
|
year: 'numeric'
|
||||||
|
}).format(new Date(updated))
|
||||||
|
: 'N/A'
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
@ -25,6 +25,7 @@ import { useAppContext } from 'AppContext'
|
|||||||
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
|
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
|
||||||
import type { CODEProps } from 'RouteDefinitions'
|
import type { CODEProps } from 'RouteDefinitions'
|
||||||
import type { GitInfoProps } from 'utils/GitUtils'
|
import type { GitInfoProps } from 'utils/GitUtils'
|
||||||
|
import { RepoArchivedBanner } from 'components/RepositoryArchivedBanner/RepositoryArchivedBanner'
|
||||||
import css from './RepositoryPageHeader.module.scss'
|
import css from './RepositoryPageHeader.module.scss'
|
||||||
|
|
||||||
interface BreadcrumbLink {
|
interface BreadcrumbLink {
|
||||||
@ -54,6 +55,7 @@ export function RepositoryPageHeader({
|
|||||||
const { routes, isCurrentSessionPublic } = useAppContext()
|
const { routes, isCurrentSessionPublic } = useAppContext()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<PageHeader
|
<PageHeader
|
||||||
className={className}
|
className={className}
|
||||||
content={content}
|
content={content}
|
||||||
@ -94,5 +96,7 @@ export function RepositoryPageHeader({
|
|||||||
</Container>
|
</Container>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<RepoArchivedBanner isArchived={repoMetadata?.archived} updated={repoMetadata?.updated} />
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,8 @@ export interface StringsMap {
|
|||||||
approve: string
|
approve: string
|
||||||
approved: string
|
approved: string
|
||||||
approvedBy: string
|
approvedBy: string
|
||||||
|
archive: string
|
||||||
|
archived: string
|
||||||
artifacts: string
|
artifacts: string
|
||||||
ascending: string
|
ascending: string
|
||||||
assignPeople: string
|
assignPeople: string
|
||||||
@ -151,6 +153,7 @@ export interface StringsMap {
|
|||||||
cancelImport: string
|
cancelImport: string
|
||||||
cancelImportConfirm: string
|
cancelImportConfirm: string
|
||||||
cancelledImport: string
|
cancelledImport: string
|
||||||
|
cautionZone: string
|
||||||
changePassword: string
|
changePassword: string
|
||||||
changePasswordSuccessfully: string
|
changePasswordSuccessfully: string
|
||||||
changeRepoVis: string
|
changeRepoVis: string
|
||||||
@ -300,7 +303,8 @@ export interface StringsMap {
|
|||||||
customSecond: string
|
customSecond: string
|
||||||
customTime: string
|
customTime: string
|
||||||
customizeMergeCommitMessage: string
|
customizeMergeCommitMessage: string
|
||||||
dangerDeleteRepo: string
|
dangerDeletePipeline: string
|
||||||
|
dangerDeleteProject: string
|
||||||
defaultBranch: string
|
defaultBranch: string
|
||||||
defaultBranchTitle: string
|
defaultBranchTitle: string
|
||||||
delete: string
|
delete: string
|
||||||
@ -312,6 +316,8 @@ export interface StringsMap {
|
|||||||
deleteFile: string
|
deleteFile: string
|
||||||
deleteImport: string
|
deleteImport: string
|
||||||
deleteNotAllowed: string
|
deleteNotAllowed: string
|
||||||
|
deleteRepo: string
|
||||||
|
deleteRepoMsg: string
|
||||||
deleteRepoText: string
|
deleteRepoText: string
|
||||||
deleteRepoTitle: string
|
deleteRepoTitle: string
|
||||||
deleteSpace: string
|
deleteSpace: string
|
||||||
@ -917,6 +923,16 @@ export interface StringsMap {
|
|||||||
replyAndReactivate: string
|
replyAndReactivate: string
|
||||||
replyAndResolve: string
|
replyAndResolve: string
|
||||||
replyHere: string
|
replyHere: string
|
||||||
|
'repoArchive.archive': string
|
||||||
|
'repoArchive.archiveInfo': string
|
||||||
|
'repoArchive.archiveWarning': string
|
||||||
|
'repoArchive.confirmButton': string
|
||||||
|
'repoArchive.infoText': string
|
||||||
|
'repoArchive.titleArchive': string
|
||||||
|
'repoArchive.titleUnarchive': string
|
||||||
|
'repoArchive.unarchive': string
|
||||||
|
'repoArchive.unarchiveInfo': string
|
||||||
|
'repoArchive.unarchiveWarning': string
|
||||||
repoCloneHeader: string
|
repoCloneHeader: string
|
||||||
repoCloneLabel: string
|
repoCloneLabel: string
|
||||||
'repoDelete.deleteConfirm1': string
|
'repoDelete.deleteConfirm1': string
|
||||||
@ -1109,6 +1125,7 @@ export interface StringsMap {
|
|||||||
'triggers.updateSuccess': string
|
'triggers.updateSuccess': string
|
||||||
turnOnSemanticSearch: string
|
turnOnSemanticSearch: string
|
||||||
unableToGetDivergence: string
|
unableToGetDivergence: string
|
||||||
|
unarchive: string
|
||||||
unorderedList: string
|
unorderedList: string
|
||||||
unrsolvedComment: string
|
unrsolvedComment: string
|
||||||
'unsavedChanges.leave': string
|
'unsavedChanges.leave': string
|
||||||
|
@ -163,6 +163,10 @@ createABranch: Create a branch
|
|||||||
createATag: Create a tag
|
createATag: Create a tag
|
||||||
delete: Delete
|
delete: Delete
|
||||||
edit: Edit
|
edit: Edit
|
||||||
|
archive: Archive
|
||||||
|
unarchive: Unarchive
|
||||||
|
archived: Archived
|
||||||
|
cautionZone: Caution Zone
|
||||||
editAsText: Edit as Text
|
editAsText: Edit as Text
|
||||||
branchName: Branch name
|
branchName: Branch name
|
||||||
enterBranchPlaceholder: Enter the branch name here
|
enterBranchPlaceholder: Enter the branch name here
|
||||||
@ -553,9 +557,12 @@ missingPerms: 'You are missing the following permission:'
|
|||||||
createRepoPerms: 'Create / Edit Repository'
|
createRepoPerms: 'Create / Edit Repository'
|
||||||
missingPermsContent: '"{PERMS}" in project "{PROJECT}"'
|
missingPermsContent: '"{PERMS}" in project "{PROJECT}"'
|
||||||
repositoryName: Repository name
|
repositoryName: Repository name
|
||||||
dangerDeleteRepo: Danger, are you sure you want to delete it?
|
deleteRepo: Delete this repository
|
||||||
|
deleteRepoMsg: Once a repository is deleted, it cannot be recovered. Proceed with caution.
|
||||||
|
dangerDeletePipeline: Danger, are you sure you want to delete this pipeline?
|
||||||
|
dangerDeleteProject: Danger, are you sure you want to delete this project?
|
||||||
repoUpdate: Repository Updated
|
repoUpdate: Repository Updated
|
||||||
deleteRepoText: Are you sure you want to delete the repository '{REPONAME}'?
|
deleteRepoText: Are you sure you want to delete repository '{REPONAME}'?
|
||||||
deleteRepoTitle: Delete the repository
|
deleteRepoTitle: Delete the repository
|
||||||
resolve: Resolve
|
resolve: Resolve
|
||||||
reactivate: Reactivate
|
reactivate: Reactivate
|
||||||
@ -738,6 +745,17 @@ repoDelete:
|
|||||||
deleteConfirm2: To confirm, type "{{repo}}" in the box below
|
deleteConfirm2: To confirm, type "{{repo}}" in the box below
|
||||||
deleteToastSuccess: Repository deleted successfully
|
deleteToastSuccess: Repository deleted successfully
|
||||||
deleteConfirmButton2: Delete this repository
|
deleteConfirmButton2: Delete this repository
|
||||||
|
repoArchive:
|
||||||
|
titleArchive: Archive Repository
|
||||||
|
titleUnarchive: Unarchive Repository
|
||||||
|
confirmButton: I understand, {archiveVerb} the repository.
|
||||||
|
archiveWarning: Archiving this repository will mark it as inactive and set it to read-only. Users can still view and clone the repository, but no new changes or contributions will be allowed.
|
||||||
|
unarchiveWarning: This repository will no longer be archived and will be restored to an active state. All users and groups with permissions can contribute as usual.
|
||||||
|
archive: Archive this repository
|
||||||
|
archiveInfo: Set this repository to archived and restrict it to read-only access.
|
||||||
|
unarchive: Unarchive this repository
|
||||||
|
unarchiveInfo: Set this repository to unarchived and make it read-write.
|
||||||
|
infoText: This repository has been archived on {{date}}. It is now read-only.
|
||||||
pipelines:
|
pipelines:
|
||||||
noData: There are no pipelines
|
noData: There are no pipelines
|
||||||
import: Import Pipelines
|
import: Import Pipelines
|
||||||
@ -964,7 +982,7 @@ enterGithubPlaceholder: https://api.github.com/
|
|||||||
enterBitbucketPlaceholder: https://bitbucket.org/
|
enterBitbucketPlaceholder: https://bitbucket.org/
|
||||||
changeRepoVis: Change repository visibility
|
changeRepoVis: Change repository visibility
|
||||||
changeRepoVisContent: Are you sure you want to make this repository {repoVis}?
|
changeRepoVisContent: Are you sure you want to make this repository {repoVis}?
|
||||||
confirmRepoVisButton: Yes, make the Repository {repoVis}
|
confirmRepoVisButton: Yes, make the repository {repoVis}
|
||||||
repoVisibility: Repository visibility
|
repoVisibility: Repository visibility
|
||||||
visibility: Visibility
|
visibility: Visibility
|
||||||
attachText: Attach images & videos by dragging & dropping, selecting or pasting them.
|
attachText: Attach images & videos by dragging & dropping, selecting or pasting them.
|
||||||
|
@ -49,7 +49,7 @@ import { useAppContext } from 'AppContext'
|
|||||||
import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
|
import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
|
||||||
import { NoResultCard } from 'components/NoResultCard/NoResultCard'
|
import { NoResultCard } from 'components/NoResultCard/NoResultCard'
|
||||||
import { ResourceListingPagination } from 'components/ResourceListingPagination/ResourceListingPagination'
|
import { ResourceListingPagination } from 'components/ResourceListingPagination/ResourceListingPagination'
|
||||||
import { RepoPublicLabel } from 'components/RepoPublicLabel/RepoPublicLabel'
|
import { RepoTypeLabel } from 'components/RepoTypeLabel/RepoTypeLabel'
|
||||||
import KeywordSearch from 'components/CodeSearch/KeywordSearch'
|
import KeywordSearch from 'components/CodeSearch/KeywordSearch'
|
||||||
import { OptionsMenuButton } from 'components/OptionsMenuButton/OptionsMenuButton'
|
import { OptionsMenuButton } from 'components/OptionsMenuButton/OptionsMenuButton'
|
||||||
import { useConfirmAct } from 'hooks/useConfirmAction'
|
import { useConfirmAct } from 'hooks/useConfirmAction'
|
||||||
@ -200,7 +200,11 @@ export default function RepositoriesListing() {
|
|||||||
<Layout.Vertical flex className={css.name} ref={rowContainerRef}>
|
<Layout.Vertical flex className={css.name} ref={rowContainerRef}>
|
||||||
<Text className={css.repoName} width={nameTextWidth} lineClamp={2}>
|
<Text className={css.repoName} width={nameTextWidth} lineClamp={2}>
|
||||||
<Keywords value={searchTerm}>{record.identifier}</Keywords>
|
<Keywords value={searchTerm}>{record.identifier}</Keywords>
|
||||||
<RepoPublicLabel isPublic={row.original.is_public} margin={{ left: 'small' }} />
|
<RepoTypeLabel
|
||||||
|
isPublic={row.original.is_public}
|
||||||
|
isArchived={row.original.archived}
|
||||||
|
margin={{ left: 'small' }}
|
||||||
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Text className={css.desc} width={nameTextWidth} lineClamp={1}>
|
<Text className={css.desc} width={nameTextWidth} lineClamp={1}>
|
||||||
|
@ -19,7 +19,7 @@ import { Layout, Text } from '@harnessio/uicore'
|
|||||||
import { BookmarkBook } from 'iconoir-react'
|
import { BookmarkBook } from 'iconoir-react'
|
||||||
|
|
||||||
import { FontVariation } from '@harnessio/design-system'
|
import { FontVariation } from '@harnessio/design-system'
|
||||||
import { RepoPublicLabel } from 'components/RepoPublicLabel/RepoPublicLabel'
|
import { RepoTypeLabel } from 'components/RepoTypeLabel/RepoTypeLabel'
|
||||||
import type { GitInfoProps } from 'utils/GitUtils'
|
import type { GitInfoProps } from 'utils/GitUtils'
|
||||||
import { RepositoryPageHeader } from 'components/RepositoryPageHeader/RepositoryPageHeader'
|
import { RepositoryPageHeader } from 'components/RepositoryPageHeader/RepositoryPageHeader'
|
||||||
import type { RepoRepositoryOutput } from 'services/code'
|
import type { RepoRepositoryOutput } from 'services/code'
|
||||||
@ -45,7 +45,7 @@ export function RepositoryHeader(props: RepositoryHeaderProps) {
|
|||||||
<Text inline className={css.repoDropdown} font={{ variation: FontVariation.H4 }}>
|
<Text inline className={css.repoDropdown} font={{ variation: FontVariation.H4 }}>
|
||||||
{repoMetadata.identifier}
|
{repoMetadata.identifier}
|
||||||
</Text>
|
</Text>
|
||||||
<RepoPublicLabel isPublic={repoMetadata.is_public} />
|
<RepoTypeLabel isPublic={repoMetadata.is_public} isArchived={repoMetadata.archived} />
|
||||||
</Layout.Horizontal>
|
</Layout.Horizontal>
|
||||||
}
|
}
|
||||||
dataTooltipId="repositoryTitle"
|
dataTooltipId="repositoryTitle"
|
||||||
|
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* 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 from 'react'
|
||||||
|
import {
|
||||||
|
Container,
|
||||||
|
Button,
|
||||||
|
ButtonVariation,
|
||||||
|
Dialog,
|
||||||
|
Layout,
|
||||||
|
Text,
|
||||||
|
useToaster,
|
||||||
|
StringSubstitute
|
||||||
|
} from '@harnessio/uicore'
|
||||||
|
import { Color, FontVariation } from '@harnessio/design-system'
|
||||||
|
import { useUpdateRepository } from 'services/code'
|
||||||
|
import { useModalHook } from 'hooks/useModalHook'
|
||||||
|
import { useStrings } from 'framework/strings'
|
||||||
|
import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata'
|
||||||
|
import { getErrorMessage } from 'utils/Utils'
|
||||||
|
import css from '../../RepositorySettings.module.scss'
|
||||||
|
|
||||||
|
interface ArchiveRepoModalProps {
|
||||||
|
refetch: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const useArchiveRepoModal = ({ refetch: refetchMetaData }: ArchiveRepoModalProps) => {
|
||||||
|
const { repoMetadata } = useGetRepositoryMetadata()
|
||||||
|
const { getString } = useStrings()
|
||||||
|
const { mutate: archiveRepository, loading: archivingRepository } = useUpdateRepository({
|
||||||
|
repo_ref: `${repoMetadata?.path as string}/+`
|
||||||
|
})
|
||||||
|
const { showSuccess, showError } = useToaster()
|
||||||
|
const [openModal, hideModal] = useModalHook(() => {
|
||||||
|
const onClose = () => {
|
||||||
|
hideModal()
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
className={css.dialogContainer}
|
||||||
|
isOpen
|
||||||
|
enforceFocus={false}
|
||||||
|
onClose={onClose}
|
||||||
|
title={
|
||||||
|
<Text font={{ variation: FontVariation.H4 }}>
|
||||||
|
{repoMetadata?.archived === true
|
||||||
|
? getString('repoArchive.titleUnarchive')
|
||||||
|
: getString('repoArchive.titleArchive')}
|
||||||
|
</Text>
|
||||||
|
}>
|
||||||
|
<Layout.Vertical spacing="xlarge">
|
||||||
|
<Container
|
||||||
|
intent="warning"
|
||||||
|
background="yellow100"
|
||||||
|
border={{
|
||||||
|
color: 'orange500'
|
||||||
|
}}
|
||||||
|
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}>
|
||||||
|
{repoMetadata?.archived === true
|
||||||
|
? getString('repoArchive.unarchiveWarning')
|
||||||
|
: getString('repoArchive.archiveWarning')}
|
||||||
|
</Text>
|
||||||
|
</Container>
|
||||||
|
<Layout.Horizontal className={css.buttonContainer}>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
variation={ButtonVariation.PRIMARY}
|
||||||
|
margin={{ right: 'small' }}
|
||||||
|
onClick={async () => {
|
||||||
|
try {
|
||||||
|
await archiveRepository({ state: repoMetadata?.archived ? 0 : 4 })
|
||||||
|
showSuccess(getString('repoUpdate'))
|
||||||
|
hideModal()
|
||||||
|
refetchMetaData()
|
||||||
|
} catch (exception) {
|
||||||
|
showError(getErrorMessage(exception), 0, 'failed to archive the repository')
|
||||||
|
}
|
||||||
|
refetchMetaData()
|
||||||
|
}}>
|
||||||
|
<StringSubstitute
|
||||||
|
str={getString('repoArchive.confirmButton')}
|
||||||
|
vars={{
|
||||||
|
archiveVerb: <span className={css.text}>{repoMetadata?.archived ? 'unarchive' : 'archive'}</span>
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
text={getString('cancel')}
|
||||||
|
variation={ButtonVariation.TERTIARY}
|
||||||
|
onClick={() => {
|
||||||
|
hideModal()
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Layout.Horizontal>
|
||||||
|
</Layout.Vertical>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}, [archivingRepository, repoMetadata])
|
||||||
|
|
||||||
|
return {
|
||||||
|
openModal,
|
||||||
|
hideModal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useArchiveRepoModal
|
@ -111,7 +111,6 @@ const useDeleteRepoModal = () => {
|
|||||||
margin={{ top: 'small' }}
|
margin={{ top: 'small' }}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
try {
|
try {
|
||||||
// this isn't implemented in the backend yet
|
|
||||||
await deleteRepo(`${repoMetadata?.path as string}/+/`)
|
await deleteRepo(`${repoMetadata?.path as string}/+/`)
|
||||||
setShowConfirmPage(false)
|
setShowConfirmPage(false)
|
||||||
setDeleteConfirmString('')
|
setDeleteConfirmString('')
|
||||||
|
@ -39,12 +39,13 @@ import { useStrings } from 'framework/strings'
|
|||||||
import type { RepoRepositoryOutput } from 'services/code'
|
import type { RepoRepositoryOutput } from 'services/code'
|
||||||
import { useAppContext } from 'AppContext'
|
import { useAppContext } from 'AppContext'
|
||||||
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
|
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
|
||||||
import { RepoVisibility } from 'utils/GitUtils'
|
import { RepoVisibility, RepoState } from 'utils/GitUtils'
|
||||||
import { BranchTagSelect } from 'components/BranchTagSelect/BranchTagSelect'
|
import { BranchTagSelect } from 'components/BranchTagSelect/BranchTagSelect'
|
||||||
import { useModalHook } from 'hooks/useModalHook'
|
import { useModalHook } from 'hooks/useModalHook'
|
||||||
import { usePublicResourceConfig } from 'hooks/usePublicResourceConfig'
|
import { usePublicResourceConfig } from 'hooks/usePublicResourceConfig'
|
||||||
import useDeleteRepoModal from './DeleteRepoModal/DeleteRepoModal'
|
import useDeleteRepoModal from './DeleteRepoModal/DeleteRepoModal'
|
||||||
import useDefaultBranchModal from './DefaultBranchModal/DefaultBranchModal'
|
import useDefaultBranchModal from './DefaultBranchModal/DefaultBranchModal'
|
||||||
|
import useArchiveRepoModal from './ArchiveRepoModal/ArchiveRepoModal'
|
||||||
import Private from '../../../icons/private.svg?url'
|
import Private from '../../../icons/private.svg?url'
|
||||||
import css from '../RepositorySettings.module.scss'
|
import css from '../RepositorySettings.module.scss'
|
||||||
|
|
||||||
@ -68,6 +69,8 @@ const GeneralSettingsContent = (props: GeneralSettingsProps) => {
|
|||||||
const { allowPublicResourceCreation } = usePublicResourceConfig()
|
const { allowPublicResourceCreation } = usePublicResourceConfig()
|
||||||
const { getString } = useStrings()
|
const { getString } = useStrings()
|
||||||
const currRepoVisibility = repoMetadata?.is_public === true ? RepoVisibility.PUBLIC : RepoVisibility.PRIVATE
|
const currRepoVisibility = repoMetadata?.is_public === true ? RepoVisibility.PUBLIC : RepoVisibility.PRIVATE
|
||||||
|
const repoState = repoMetadata?.archived === true ? RepoState.ARCHIVED : RepoState.UNARCHIVED
|
||||||
|
const { openModal: openArchiveRepoModal } = useArchiveRepoModal({ refetch })
|
||||||
const [repoVis, setRepoVis] = useState<RepoVisibility>(currRepoVisibility)
|
const [repoVis, setRepoVis] = useState<RepoVisibility>(currRepoVisibility)
|
||||||
|
|
||||||
const { mutate } = useMutate({
|
const { mutate } = useMutate({
|
||||||
@ -186,7 +189,7 @@ const GeneralSettingsContent = (props: GeneralSettingsProps) => {
|
|||||||
{formik => {
|
{formik => {
|
||||||
return (
|
return (
|
||||||
<Layout.Vertical padding={{ top: 'medium' }}>
|
<Layout.Vertical padding={{ top: 'medium' }}>
|
||||||
<Container padding="large" margin={{ bottom: 'medium' }} className={css.generalContainer}>
|
<Container padding="medium" margin={{ bottom: 'medium' }} className={css.generalContainer}>
|
||||||
<Layout.Horizontal padding={{ bottom: 'medium' }}>
|
<Layout.Horizontal padding={{ bottom: 'medium' }}>
|
||||||
<Container className={css.label}>
|
<Container className={css.label}>
|
||||||
<Text color={Color.GREY_600} className={css.textSize}>
|
<Text color={Color.GREY_600} className={css.textSize}>
|
||||||
@ -409,20 +412,51 @@ const GeneralSettingsContent = (props: GeneralSettingsProps) => {
|
|||||||
</Layout.Horizontal>
|
</Layout.Horizontal>
|
||||||
</Container>
|
</Container>
|
||||||
</Render>
|
</Render>
|
||||||
<Container padding="medium" className={css.generalContainer}>
|
<Container padding="medium" margin={{ bottom: 'medium' }} className={css.generalContainer}>
|
||||||
<Container className={css.deleteContainer}>
|
<Layout.Horizontal padding={{ bottom: 'medium' }}>
|
||||||
<Text icon="main-trash" color={Color.GREY_600} font={{ size: 'small' }}>
|
<Container className={css.label}>
|
||||||
{getString('dangerDeleteRepo')}
|
<Text color={Color.GREY_600} className={css.textSize} margin={{ top: 'medium' }}>
|
||||||
|
{getString('cautionZone')}
|
||||||
</Text>
|
</Text>
|
||||||
|
</Container>
|
||||||
|
<Layout.Vertical>
|
||||||
|
<Container className={css.cautionContainer}>
|
||||||
|
<Layout.Vertical spacing="small" padding={{ right: 'large' }}>
|
||||||
|
<Text font={{ size: 'small' }} className={css.textSize}>
|
||||||
|
{repoState === RepoState.ARCHIVED
|
||||||
|
? getString('repoArchive.unarchive')
|
||||||
|
: getString('repoArchive.archive')}
|
||||||
|
</Text>
|
||||||
|
<Text font={{ variation: FontVariation.TINY }}>
|
||||||
|
{repoState === RepoState.ARCHIVED
|
||||||
|
? getString('repoArchive.unarchiveInfo')
|
||||||
|
: getString('repoArchive.archiveInfo')}
|
||||||
|
</Text>
|
||||||
|
</Layout.Vertical>
|
||||||
|
<Button
|
||||||
|
onClick={openArchiveRepoModal}
|
||||||
|
variation={ButtonVariation.SECONDARY}
|
||||||
|
text={repoState === RepoState.ARCHIVED ? getString('unarchive') : getString('archive')}
|
||||||
|
{...permissionProps(permEditResult, standalone)}
|
||||||
|
/>
|
||||||
|
</Container>
|
||||||
|
<Container className={css.cautionContainer}>
|
||||||
|
<Layout.Vertical spacing="small" padding={{ right: 'large' }}>
|
||||||
|
<Text font={{ size: 'small' }} className={css.textSize}>
|
||||||
|
{getString('deleteRepo')}
|
||||||
|
</Text>
|
||||||
|
<Text font={{ variation: FontVariation.TINY }}>{getString('deleteRepoMsg')}</Text>
|
||||||
|
</Layout.Vertical>
|
||||||
<Button
|
<Button
|
||||||
intent={Intent.DANGER}
|
intent={Intent.DANGER}
|
||||||
onClick={() => {
|
onClick={openDeleteRepoModal}
|
||||||
openDeleteRepoModal()
|
|
||||||
}}
|
|
||||||
variation={ButtonVariation.SECONDARY}
|
variation={ButtonVariation.SECONDARY}
|
||||||
text={getString('delete')}
|
text={getString('delete')}
|
||||||
{...permissionProps(permDeleteResult, standalone)}></Button>
|
{...permissionProps(permDeleteResult, standalone)}
|
||||||
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
|
</Layout.Vertical>
|
||||||
|
</Layout.Horizontal>
|
||||||
</Container>
|
</Container>
|
||||||
</Layout.Vertical>
|
</Layout.Vertical>
|
||||||
)
|
)
|
||||||
|
@ -104,9 +104,13 @@
|
|||||||
width: 80%;
|
width: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.deleteContainer {
|
.cautionContainer {
|
||||||
display: flex;
|
display: flex !important;
|
||||||
justify-content: space-between;
|
justify-content: space-between !important;
|
||||||
|
align-items: center;
|
||||||
|
width: 100% !important;
|
||||||
|
padding: var(--spacing-medium) var(--spacing-small) !important;
|
||||||
|
white-space: nowrap !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text {
|
.text {
|
||||||
|
@ -18,9 +18,9 @@
|
|||||||
// This is an auto-generated file
|
// This is an auto-generated file
|
||||||
export declare const btn: string
|
export declare const btn: string
|
||||||
export declare const buttonContainer: string
|
export declare const buttonContainer: string
|
||||||
|
export declare const cautionContainer: string
|
||||||
export declare const content: string
|
export declare const content: string
|
||||||
export declare const contentContainer: string
|
export declare const contentContainer: string
|
||||||
export declare const deleteContainer: string
|
|
||||||
export declare const description: string
|
export declare const description: string
|
||||||
export declare const descText: string
|
export declare const descText: string
|
||||||
export declare const dialogContainer: string
|
export declare const dialogContainer: string
|
||||||
|
@ -479,7 +479,7 @@ export default function GeneralSpaceSettings() {
|
|||||||
<Container className={css.deleteContainer}>
|
<Container className={css.deleteContainer}>
|
||||||
<Layout.Vertical className={css.verticalContainer}>
|
<Layout.Vertical className={css.verticalContainer}>
|
||||||
<Text icon="main-trash" color={Color.GREY_600} font={{ size: 'small' }}>
|
<Text icon="main-trash" color={Color.GREY_600} font={{ size: 'small' }}>
|
||||||
{getString('dangerDeleteRepo')}
|
{getString('dangerDeleteProject')}
|
||||||
</Text>
|
</Text>
|
||||||
<Layout.Horizontal
|
<Layout.Horizontal
|
||||||
padding={{ top: 'medium', left: 'medium' }}
|
padding={{ top: 'medium', left: 'medium' }}
|
||||||
|
@ -667,6 +667,7 @@ export interface OpenapiUpdateRepoPublicAccessRequest {
|
|||||||
|
|
||||||
export interface OpenapiUpdateRepoRequest {
|
export interface OpenapiUpdateRepoRequest {
|
||||||
description?: string | null
|
description?: string | null
|
||||||
|
state?: number | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OpenapiUpdateRepoWebhookRequest {
|
export interface OpenapiUpdateRepoWebhookRequest {
|
||||||
@ -878,6 +879,7 @@ export interface RepoRepositoryOutput {
|
|||||||
importing?: boolean
|
importing?: boolean
|
||||||
is_empty?: boolean
|
is_empty?: boolean
|
||||||
is_public?: boolean
|
is_public?: boolean
|
||||||
|
archived?: boolean
|
||||||
num_closed_pulls?: number
|
num_closed_pulls?: number
|
||||||
num_forks?: number
|
num_forks?: number
|
||||||
num_merged_pulls?: number
|
num_merged_pulls?: number
|
||||||
|
@ -12758,6 +12758,8 @@ components:
|
|||||||
type: object
|
type: object
|
||||||
RepoRepositoryOutput:
|
RepoRepositoryOutput:
|
||||||
properties:
|
properties:
|
||||||
|
archived:
|
||||||
|
type: boolean
|
||||||
created:
|
created:
|
||||||
type: integer
|
type: integer
|
||||||
created_by:
|
created_by:
|
||||||
|
@ -103,6 +103,11 @@ export enum RepoVisibility {
|
|||||||
PRIVATE = 'private'
|
PRIVATE = 'private'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum RepoState {
|
||||||
|
ARCHIVED = 'archived',
|
||||||
|
UNARCHIVED = 'unarchived'
|
||||||
|
}
|
||||||
|
|
||||||
export enum RepoCreationType {
|
export enum RepoCreationType {
|
||||||
IMPORT = 'import',
|
IMPORT = 'import',
|
||||||
CREATE = 'create',
|
CREATE = 'create',
|
||||||
|
Loading…
Reference in New Issue
Block a user