feat: [CDE-42]: Gitspace UI changes (#2078)

This commit is contained in:
Deepesh Kumar 2024-06-05 17:35:31 +00:00 committed by Harness
parent 7c2431c652
commit a6894572a4
26 changed files with 1058 additions and 623 deletions

View File

@ -16,12 +16,15 @@
import React from 'react'
import * as yup from 'yup'
import { Button, ButtonVariation, Card, Formik, FormikForm, Layout, Text } from '@harnessio/uicore'
import { Button, ButtonVariation, Card, Formik, FormikForm, Layout, Text, useToaster } from '@harnessio/uicore'
import { FontVariation } from '@harnessio/design-system'
import { useCreateGitspace, type EnumCodeRepoType, type EnumIDEType } from 'services/cde'
import { useHistory } from 'react-router-dom'
import { useCreateGitspace, OpenapiCreateGitspaceRequest } from 'services/cde'
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
import { useStrings } from 'framework/strings'
import { IDEType } from 'cde/constants'
import { useAppContext } from 'AppContext'
import { getErrorMessage } from 'utils/Utils'
import { SelectIDE } from './components/SelectIDE/SelectIDE'
import { SelectRepository } from './components/SelectRepository/SelectRepository'
import { BranchInput } from './components/BranchInput/BranchInput'
@ -32,33 +35,53 @@ const initData = {
ide: IDEType.VSCODE
}
export interface GitspaceFormInterface {
ide?: EnumIDEType
branch?: string
codeRepoId?: string
codeRepoUrl?: string
codeRepoType?: EnumCodeRepoType
region?: string
infra_provider_resource_id?: string
}
interface GitspaceFormProps {
onSubmit: (data: GitspaceFormInterface) => void
}
const GitspaceForm = ({ onSubmit }: GitspaceFormProps) => {
const GitspaceForm = () => {
const { getString } = useStrings()
const { routes } = useAppContext()
const space = useGetSpaceParam()
const { showError } = useToaster()
const history = useHistory()
const { mutate, loading, error } = useCreateGitspace({
accountIdentifier: space?.split('/')[0],
orgIdentifier: space?.split('/')[1],
projectIdentifier: space?.split('/')[2]
})
if (error) {
showError(getErrorMessage(error))
}
return (
<Formik<GitspaceFormInterface>
onSubmit={async data => await onSubmit(data)}
<Formik<OpenapiCreateGitspaceRequest>
onSubmit={async data => {
try {
const createdGitspace = await mutate(data)
history.push(
`${routes.toCDEGitspaceDetail({
space,
gitspaceId: createdGitspace?.id || ''
})}?redirectFrom=login`
)
} catch (err) {
showError(getErrorMessage(err))
}
}}
formName={'createGitSpace'}
initialValues={initData}
validateOnMount={false}
validationSchema={yup.object().shape({
codeRepoId: yup.string().trim().required(),
branch: yup.string().trim().required(),
code_repo_id: yup.string().trim().required(),
code_repo_type: yup.string().trim().required(),
code_repo_url: yup.string().trim().required(),
id: yup.string().trim().required(),
ide: yup.string().trim().required(),
region: yup.string().trim().required(),
infra_provider_resource_id: yup.string().trim().required()
infra_provider_resource_id: yup.string().trim().required(),
name: yup.string().trim().required(),
metadata: yup.object().shape({
region: yup.string().trim().required()
})
})}>
{_ => {
return (
@ -70,7 +93,7 @@ const GitspaceForm = ({ onSubmit }: GitspaceFormProps) => {
</Layout.Horizontal>
<SelectIDE />
<SelectInfraProvider />
<Button variation={ButtonVariation.PRIMARY} height={50} type="submit">
<Button variation={ButtonVariation.PRIMARY} height={50} type="submit" loading={loading}>
{getString('cde.createGitspace')}
</Button>
</Layout.Vertical>
@ -82,20 +105,14 @@ const GitspaceForm = ({ onSubmit }: GitspaceFormProps) => {
}
export const CreateGitspace = () => {
const space = useGetSpaceParam()
const { getString } = useStrings()
const { mutate } = useCreateGitspace({
accountIdentifier: space?.split('/')[0],
orgIdentifier: space?.split('/')[1],
projectIdentifier: space?.split('/')[2]
})
return (
<Card className={css.main}>
<Text className={css.cardTitle} font={{ variation: FontVariation.CARD_TITLE }}>
{getString('cde.createGitspace')}
</Text>
<GitspaceForm onSubmit={mutate} />
<GitspaceForm />
</Card>
)
}

View File

@ -21,8 +21,8 @@ import { useFormikContext } from 'formik'
import { GitspaceSelect } from 'cde/components/GitspaceSelect/GitspaceSelect'
import { useStrings, type UseStringsReturn } from 'framework/strings'
import { IDEType } from 'cde/constants'
import type { OpenapiCreateGitspaceRequest } from 'services/cde'
import VSCode from '../../../../icons/VSCode.svg?url'
import type { GitspaceFormInterface } from '../../CreateGitspace'
export const getIDESelectItems = (getString: UseStringsReturn['getString']) => [
{ label: getString('cde.ide.desktop'), value: IDEType.VSCODE },
@ -30,7 +30,7 @@ export const getIDESelectItems = (getString: UseStringsReturn['getString']) => [
]
export const SelectIDE = () => {
const { values, errors, setFieldValue: onChange } = useFormikContext<GitspaceFormInterface>()
const { values, errors, setFieldValue: onChange } = useFormikContext<OpenapiCreateGitspaceRequest>()
const { ide } = values
const { getString } = useStrings()
const IDESelectItems = getIDESelectItems(getString)

View File

@ -19,13 +19,12 @@ import { defaultTo, isObject } from 'lodash-es'
import { Layout } from '@harnessio/uicore'
import { useFormikContext } from 'formik'
import { CDEPathParams, useGetCDEAPIParams } from 'cde/hooks/useGetCDEAPIParams'
import { useListInfraProviderResources } from 'services/cde'
import type { GitspaceFormInterface } from 'cde/components/CreateGitspace/CreateGitspace'
import { OpenapiCreateGitspaceRequest, useListInfraProviderResources } from 'services/cde'
import { SelectRegion } from '../SelectRegion/SelectRegion'
import { SelectMachine } from '../SelectMachine/SelectMachine'
export const SelectInfraProvider = () => {
const { values } = useFormikContext<GitspaceFormInterface>()
const { values } = useFormikContext<OpenapiCreateGitspaceRequest>()
const { accountIdentifier, orgIdentifier, projectIdentifier } = useGetCDEAPIParams() as CDEPathParams
const { data } = useListInfraProviderResources({
accountIdentifier,
@ -44,7 +43,7 @@ export const SelectInfraProvider = () => {
const machineOptions =
optionsList
?.filter(item => item?.region === values?.region)
?.filter(item => item?.region === values?.metadata?.region)
?.map(item => {
return { ...item }
}) || []

View File

@ -0,0 +1,4 @@
.tags {
background: var(--grey-100) !important;
border-radius: 10px;
}

View 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 tags: string

View File

@ -19,16 +19,11 @@ import { Layout, Text } from '@harnessio/uicore'
import { Menu, MenuItem } from '@blueprintjs/core'
import { Cpu } from 'iconoir-react'
import { useFormikContext } from 'formik'
import { FontVariation } from '@harnessio/design-system'
import { GitspaceSelect } from 'cde/components/GitspaceSelect/GitspaceSelect'
import type { TypesInfraProviderResourceResponse } from 'services/cde'
import type { OpenapiCreateGitspaceRequest, TypesInfraProviderResourceResponse } from 'services/cde'
import { useStrings } from 'framework/strings'
import RAM8 from './assests/RAM8.svg?url'
import RAM16 from './assests/RAM16.svg?url'
import Storage32 from './assests/Storage32.svg?url'
import Storage64 from './assests/Storage64.svg?url'
import CPU4Cores from './assests/CPU4Cores.svg?url'
import CPU8Cores from './assests/CPU8Cores.svg?url'
import type { GitspaceFormInterface } from '../../CreateGitspace'
import css from './SelectMachine.module.scss'
export const machineIdToLabel = {
'4core_8gb_32gb': 'Standard',
@ -46,26 +41,30 @@ interface SelectMachineInterface {
export const SelectMachine = ({ options }: SelectMachineInterface) => {
const { getString } = useStrings()
const { values, errors, setFieldValue: onChange } = useFormikContext<GitspaceFormInterface>()
const { values, errors, setFieldValue: onChange } = useFormikContext<OpenapiCreateGitspaceRequest>()
const { infra_provider_resource_id: machine } = values
const [machineState, setMachineState] = useState<string>(machine || '')
const machineTypes = options.map(item => {
const { cpu, disk, memory, infra_provider_config_id } = item
const { cpu, disk, memory, id, name } = item
return {
infra_provider_config_id,
id: `${cpu}_${disk}_${memory}`,
label: machineIdToLabel[`${cpu}_${disk}_${memory}` as keyof typeof machineIdToLabel]
id,
label: name,
cpu,
disk,
memory
}
})
const data = (machineTypes?.find(item => item.id === machine) || {}) as (typeof machineTypes)[0]
return (
<GitspaceSelect
overridePopOverWidth
text={
<Layout.Horizontal spacing={'small'}>
<Cpu />
<Text font={'normal'}>{machine || getString('cde.machine')}</Text>
<Text font={'normal'}>{data.label || getString('cde.machine')}</Text>
</Layout.Horizontal>
}
errorMessage={errors.infra_provider_resource_id}
@ -76,15 +75,26 @@ export const SelectMachine = ({ options }: SelectMachineInterface) => {
{machineTypes.map(item => {
return (
<MenuItem
key={item.infra_provider_config_id}
key={item.id}
active={machineState === item.id}
text={
<Text font={{ size: 'normal', weight: 'bold' }}>
{machineIdToLabel[item.id as keyof typeof machineIdToLabel]}
</Text>
<Layout.Vertical>
<Text font={{ size: 'normal', weight: 'bold' }}>{item.label?.toUpperCase()}</Text>
<Layout.Horizontal spacing={'small'}>
<Text padding={'small'} className={css.tags} font={{ variation: FontVariation.SMALL }}>
Cpu: {item.cpu}
</Text>
<Text padding={'small'} className={css.tags} font={{ variation: FontVariation.SMALL }}>
Disk: {item.disk}
</Text>
<Text padding={'small'} className={css.tags} font={{ variation: FontVariation.SMALL }}>
Memory: {item.memory}
</Text>
</Layout.Horizontal>
</Layout.Vertical>
}
onClick={() => {
onChange('infra_provider_resource_id', item.infra_provider_config_id || '')
onChange('infra_provider_resource_id', item.id || '')
}}
onMouseOver={(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
const dd = e.currentTarget.innerText as keyof typeof labelToMachineId
@ -94,26 +104,6 @@ export const SelectMachine = ({ options }: SelectMachineInterface) => {
)
})}
</Menu>
<Menu>
{machineState === labelToMachineId.Standard && (
<Layout.Vertical>
<Layout.Horizontal>
<img src={CPU4Cores} />
<img src={RAM8} />
</Layout.Horizontal>
<img src={Storage32} />
</Layout.Vertical>
)}
{machineState === labelToMachineId.Large && (
<Layout.Vertical>
<Layout.Horizontal>
<img src={CPU8Cores} />
<img src={RAM16} />
</Layout.Horizontal>
<img src={Storage64} />
</Layout.Vertical>
)}
</Menu>
</Layout.Horizontal>
}
/>

View File

@ -22,21 +22,37 @@ import { useFormikContext } from 'formik'
import { GitspaceSelect } from 'cde/components/GitspaceSelect/GitspaceSelect'
import { useStrings } from 'framework/strings'
import { GitspaceRegion } from 'cde/constants'
import type { OpenapiCreateGitspaceRequest } from 'services/cde'
import USWest from './assests/USWest.png'
import USEast from './assests/USEast.png'
import Australia from './assests/Aus.png'
import Europe from './assests/Europe.png'
import type { GitspaceFormInterface } from '../../CreateGitspace'
import Empty from './assests/Empty.png'
interface SelectRegionInterface {
options: SelectOption[]
}
export const getMapFromRegion = (region: string) => {
switch (region) {
case GitspaceRegion.USEast:
return USEast
case GitspaceRegion.USWest:
return USWest
case GitspaceRegion.Europe:
return Europe
case GitspaceRegion.Australia:
return Australia
default:
return Empty
}
}
export const SelectRegion = ({ options }: SelectRegionInterface) => {
const { getString } = useStrings()
const { values, errors, setFieldValue: onChange } = useFormikContext<GitspaceFormInterface>()
const { region = '' } = values
const [regionState, setRegionState] = useState<string>(region)
const { values, errors, setFieldValue: onChange } = useFormikContext<OpenapiCreateGitspaceRequest>()
const { metadata } = values
const [regionState, setRegionState] = useState<string | undefined>(metadata?.region)
return (
<GitspaceSelect
@ -44,11 +60,17 @@ export const SelectRegion = ({ options }: SelectRegionInterface) => {
text={
<Layout.Horizontal spacing={'small'}>
<Map />
<Text font={'normal'}>{region || getString('cde.region')}</Text>
<Text font={'normal'}>{metadata?.region || getString('cde.region')}</Text>
</Layout.Horizontal>
}
formikName="region"
errorMessage={errors.region}
formikName="metadata.region"
errorMessage={
(
errors['metadata'] as unknown as {
[key: string]: string
}
)?.region as unknown as string
}
renderMenu={
<Layout.Horizontal padding={{ top: 'small', bottom: 'small' }}>
<Menu>
@ -57,9 +79,9 @@ export const SelectRegion = ({ options }: SelectRegionInterface) => {
<MenuItem
key={label}
active={label === regionState}
text={<Text font={{ size: 'normal', weight: 'bold' }}>{label}</Text>}
text={<Text font={{ size: 'normal', weight: 'bold' }}>{label.toUpperCase()}</Text>}
onClick={() => {
onChange('region', label)
onChange('metadata.region', label.toLowerCase())
}}
onMouseOver={(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
setRegionState(e.currentTarget.innerText)
@ -69,10 +91,7 @@ export const SelectRegion = ({ options }: SelectRegionInterface) => {
})}
</Menu>
<Menu>
{regionState === GitspaceRegion.USEast && <img src={USEast} />}
{regionState === GitspaceRegion.USWest && <img src={USWest} />}
{regionState === GitspaceRegion.Europe && <img src={Europe} />}
{regionState === GitspaceRegion.Australia && <img src={Australia} />}
<img src={getMapFromRegion(regionState?.toLowerCase() || '')} />
</Menu>
</Layout.Horizontal>
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@ -23,17 +23,32 @@ import { noop } from 'lodash-es'
import { Icon } from '@harnessio/icons'
import { useFormikContext } from 'formik'
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
import { OpenapiGetCodeRepositoryResponse, useGetCodeRepository } from 'services/cde'
import { OpenapiCreateGitspaceRequest, OpenapiGetCodeRepositoryResponse, useGetCodeRepository } from 'services/cde'
import { GitspaceSelect } from 'cde/components/GitspaceSelect/GitspaceSelect'
import { useStrings } from 'framework/strings'
import { CodeRepoAccessType } from 'cde/constants'
import { getErrorMessage } from 'utils/Utils'
import type { GitspaceFormInterface } from '../../CreateGitspace'
import css from './SelectRepository.module.scss'
export const getRepoNameFromURL = (repoURL?: string) => {
const repoURLSplit = repoURL?.split('/')
return repoURLSplit?.[repoURLSplit?.length - 1]
?.replace(/-/g, '')
?.replace(/_/g, '')
.replace(/\./g, '')
?.toLowerCase()
}
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
}
const RepositoryText = ({ repoURL }: { repoURL?: string }) => {
@ -53,9 +68,9 @@ const RepositoryText = ({ repoURL }: { repoURL?: string }) => {
export const SelectRepository = () => {
const { getString } = useStrings()
const { values, errors, setFieldValue: onChange } = useFormikContext<GitspaceFormInterface>()
const { values, errors, setFormikState } = useFormikContext<OpenapiCreateGitspaceRequest>()
const { codeRepoUrl } = values
const { code_repo_url } = values
const space = useGetSpaceParam()
const [validatedOnce, setValidatedOnce] = useState(false)
@ -69,10 +84,10 @@ export const SelectRepository = () => {
return (
<GitspaceSelect
text={<RepositoryText repoURL={codeRepoUrl} />}
text={<RepositoryText repoURL={code_repo_url} />}
icon={'code'}
errorMessage={errors.codeRepoId}
formikName="codeRepoId"
errorMessage={errors.code_repo_url}
formikName="code_repo_url"
renderMenu={
<Menu>
<Layout.Vertical
@ -88,9 +103,9 @@ export const SelectRepository = () => {
formLoading={loading}
onSubmit={() => noop()}
formName={'publicURL'}
initialValues={{ url: codeRepoUrl }}
initialValues={{ url: code_repo_url }}
validate={async ({ url }) => {
if (!url) {
if (!url || loading) {
return {}
}
let errorMessages = undefined
@ -109,6 +124,7 @@ export const SelectRepository = () => {
{formikProps => {
if (!formikProps.touched.url && validatedOnce) {
formikProps.setFieldTouched('url', true)
setRepoMetadata(undefined)
}
return (
<FormikForm>
@ -135,9 +151,22 @@ export const SelectRepository = () => {
<MenuItem
className={css.metadataItem}
onClick={() => {
onChange('codeRepoUrl', repoMetadata?.url || '')
onChange('codeRepoType', repoMetadata?.repo_type || '')
onChange('codeRepoId', repoMetadata?.url || '')
setFormikState((prv: any) => {
const repoId = getRepoNameFromURL(repoMetadata?.url)
const hash = generateAlphaNumericHash(5)?.toLowerCase()
return {
...prv,
values: {
...prv.values,
id: `${repoId}${hash}`,
name: `${repoId} ${hash}`?.toLowerCase(),
code_repo_url: repoMetadata?.url || '',
code_repo_type: repoMetadata?.repo_type || '',
code_repo_id: repoId,
branch: repoMetadata?.branch
}
}
})
}}
text={
<Layout.Horizontal

View File

@ -15,49 +15,106 @@
*/
import React from 'react'
import { Text, Layout, Container, Button, ButtonVariation, PageError } from '@harnessio/uicore'
import { Text, Layout, Container, Button, ButtonVariation, PageError, useToaster } from '@harnessio/uicore'
import { FontVariation } from '@harnessio/design-system'
import type { PopoverProps } from '@harnessio/uicore/dist/components/Popover/Popover'
import { Menu, MenuItem, PopoverPosition } from '@blueprintjs/core'
import { useParams } from 'react-router-dom'
import { useHistory, useParams } from 'react-router-dom'
import { Cpu, Circle, GitFork, Repository } from 'iconoir-react'
import { isUndefined } from 'lodash-es'
import { useGetGitspace, useGitspaceAction } from 'services/cde'
import { CDEPathParams, useGetCDEAPIParams } from 'cde/hooks/useGetCDEAPIParams'
import { useStrings } from 'framework/strings'
import type { GetDataError, MutateMethod, UseGetProps } from 'restful-react'
import type {
EnumGitspaceStateType,
GitspaceActionPathParams,
OpenapiGetGitspaceLogsResponse,
OpenapiGetGitspaceResponse,
OpenapiGitspaceActionRequest
} from 'services/cde'
import { UseStringsReturn, useStrings } from 'framework/strings'
import { GitspaceActionType, GitspaceStatus, IDEType } from 'cde/constants'
import { getErrorMessage } from 'utils/Utils'
import { useAppContext } from 'AppContext'
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
import { useQueryParams } from 'hooks/useQueryParams'
import { CDEPathParams, useGetCDEAPIParams } from 'cde/hooks/useGetCDEAPIParams'
import Gitspace from '../../icons/Gitspace.svg?url'
import { getStatusColor } from '../ListGitspaces/ListGitspaces'
import css from './GitspaceDetails.module.scss'
interface QueryGitspace {
gitspaceId?: string
}
export const GitspaceDetails = () => {
export const getGitspaceDetailTitle = ({
getString,
status,
loading,
redirectFrom,
actionError
}: {
getString: UseStringsReturn['getString']
status?: EnumGitspaceStateType
loading?: boolean
redirectFrom?: string
actionError?: GetDataError<unknown> | null
}) => {
if (loading) {
return getString('cde.details.fetchingGitspace')
} else if (
status === GitspaceStatus.UNKNOWN ||
(status === GitspaceStatus.STOPPED && !!redirectFrom && !actionError)
) {
return getString('cde.details.provisioningGitspace')
} else if (status === GitspaceStatus.STOPPED) {
return getString('cde.details.gitspaceStopped')
} else if (status === GitspaceStatus.RUNNING) {
return getString('cde.details.gitspaceRunning')
} else if (!loading && isUndefined(status)) {
getString('cde.details.noData')
}
}
export const GitspaceDetails = ({
data,
error,
loading,
refetch,
mutate,
refetchLogs,
mutateLoading,
isfetchingInProgress,
actionError
}: {
data?: OpenapiGetGitspaceResponse | null
error?: GetDataError<unknown> | null
loading?: boolean
mutateLoading?: boolean
isfetchingInProgress?: boolean
refetch: (
options?: Partial<Omit<UseGetProps<OpenapiGetGitspaceResponse, unknown, void, unknown>, 'lazy'>> | undefined
) => Promise<void>
refetchLogs?: (
options?: Partial<Omit<UseGetProps<OpenapiGetGitspaceLogsResponse, unknown, void, unknown>, 'lazy'>> | undefined
) => Promise<void>
mutate: MutateMethod<void, OpenapiGitspaceActionRequest, void, GitspaceActionPathParams>
actionError?: GetDataError<unknown> | null
}) => {
const { getString } = useStrings()
const { accountIdentifier, orgIdentifier, projectIdentifier } = useGetCDEAPIParams() as CDEPathParams
const { gitspaceId } = useParams<QueryGitspace>()
const { routes } = useAppContext()
const space = useGetSpaceParam()
const { showError } = useToaster()
const history = useHistory()
const { projectIdentifier } = useGetCDEAPIParams() as CDEPathParams
const { redirectFrom = '' } = useQueryParams<{ redirectFrom?: string }>()
const { data, loading, error, refetch } = useGetGitspace({
accountIdentifier,
orgIdentifier,
projectIdentifier,
gitspaceIdentifier: gitspaceId || ''
})
const { config, status } = data || {}
const { mutate } = useGitspaceAction({
accountIdentifier,
orgIdentifier,
projectIdentifier,
gitspaceIdentifier: gitspaceId || ''
})
const { config, status, url } = data || {}
const openEditorLabel =
config?.ide === IDEType.VSCODE ? getString('cde.details.openEditor') : getString('cde.details.openBrowser')
const color = getStatusColor(status as EnumGitspaceStateType)
return (
<Layout.Vertical width={'30%'} spacing="large">
<Layout.Vertical spacing="medium">
@ -65,12 +122,11 @@ export const GitspaceDetails = () => {
{error ? (
<PageError onClick={() => refetch()} message={getErrorMessage(error)} />
) : (
<Text className={css.subText} font={{ variation: FontVariation.CARD_TITLE }}>
{status === GitspaceStatus.UNKNOWN && getString('cde.details.provisioningGitspace')}
{status === GitspaceStatus.STOPPED && getString('cde.details.gitspaceStopped')}
{status === GitspaceStatus.RUNNING && getString('cde.details.gitspaceRunning')}
{loading && getString('cde.details.fetchingGitspace')}
{!loading && isUndefined(status) && getString('cde.details.noData')}
<Text
icon={isfetchingInProgress ? 'loading' : undefined}
className={css.subText}
font={{ variation: FontVariation.CARD_TITLE }}>
{getGitspaceDetailTitle({ getString, status, loading, redirectFrom, actionError })}
</Text>
)}
</Layout.Vertical>
@ -85,7 +141,7 @@ export const GitspaceDetails = () => {
<Layout.Horizontal flex={{ justifyContent: 'space-between' }}>
<Layout.Vertical spacing="small">
<Layout.Horizontal spacing="small">
<Circle color="#32CD32" fill="#32CD32" />
<Circle color={color} fill={color} />
<Text font={'small'}>{config?.code_repo_id?.toUpperCase()}</Text>
</Layout.Horizontal>
<Layout.Horizontal spacing="small">
@ -110,10 +166,27 @@ export const GitspaceDetails = () => {
<Layout.Horizontal spacing={'medium'}>
{status === GitspaceStatus.UNKNOWN && (
<>
<Button variation={ButtonVariation.SECONDARY} disabled>
<Button
onClick={() => {
if (config?.ide === IDEType.VSCODE) {
window.open(`vscode://harness-inc.gitspaces/${projectIdentifier}/${gitspaceId}`, '_blank')
} else {
window.open(data?.url || '', '_blank')
}
}}
variation={ButtonVariation.SECONDARY}
disabled>
{openEditorLabel}
</Button>
<Button variation={ButtonVariation.PRIMARY} onClick={() => mutate({ action: 'STOP' })}>
<Button
variation={ButtonVariation.PRIMARY}
onClick={async () => {
try {
await mutate({ action: GitspaceActionType.STOP })
} catch (err) {
showError(getErrorMessage(err))
}
}}>
{getString('cde.details.stopProvising')}
</Button>
</>
@ -121,17 +194,46 @@ export const GitspaceDetails = () => {
{status === GitspaceStatus.STOPPED && (
<>
<Button variation={ButtonVariation.PRIMARY} onClick={() => mutate({ action: GitspaceActionType.START })}>
<Button
disabled={isfetchingInProgress}
variation={ButtonVariation.PRIMARY}
onClick={async () => {
try {
await mutate({ action: GitspaceActionType.START })
} catch (err) {
showError(getErrorMessage(err))
}
}}>
{getString('cde.details.startGitspace')}
</Button>
<Button variation={ButtonVariation.TERTIARY}>{getString('cde.details.goToDashboard')}</Button>
<Button
onClick={() => {
if (gitspaceId) {
history.push(routes.toCDEGitspaces({ space }))
}
}}
variation={ButtonVariation.TERTIARY}>
{getString('cde.details.goToDashboard')}
</Button>
</>
)}
{status === GitspaceStatus.RUNNING && (
<>
<Button variation={ButtonVariation.PRIMARY}>{openEditorLabel}</Button>
<Button
onClick={() => {
if (config?.ide === IDEType.VSCODE) {
window.open(`vscode://harness-inc.gitspaces/${projectIdentifier}/${gitspaceId}`, '_blank')
} else {
window.open(url, '_blank')
}
}}
variation={ButtonVariation.PRIMARY}>
{openEditorLabel}
</Button>
<Button
iconProps={mutateLoading ? { name: 'loading' } : {}}
disabled={mutateLoading}
variation={ButtonVariation.TERTIARY}
rightIcon="chevron-down"
tooltipProps={
@ -145,7 +247,21 @@ export const GitspaceDetails = () => {
<Menu>
<MenuItem
text={getString('cde.details.stopGitspace')}
onClick={() => mutate({ action: GitspaceActionType.STOP })}
onClick={async () => {
try {
await mutate({ action: GitspaceActionType.STOP })
await refetch()
await refetchLogs?.()
} catch (err) {
showError(getErrorMessage(err))
}
}}
/>
<MenuItem
text={getString('cde.details.goToDashboard')}
onClick={() => {
history.push(routes.toCDEGitspaces({ space }))
}}
/>
</Menu>
}>

View File

@ -18,7 +18,7 @@
.consoleContainer {
min-height: 500px !important;
max-height: 500px !important;
max-height: 70vh !important;
overflow: scroll;
align-items: start !important;
padding-top: var(--spacing-large) !important;
@ -87,3 +87,8 @@
}
}
}
.logContainer {
width: 60%;
max-width: 800px !important;
}

View File

@ -19,6 +19,7 @@
export declare const consoleContainer: string
export declare const consoleLine: string
export declare const line: string
export declare const logContainer: string
export declare const logTitle: string
export declare const mainLog: string
export declare const stepLogContainer: string

View File

@ -17,60 +17,61 @@
import React, { useRef, useEffect } from 'react'
import cx from 'classnames'
import { Text, Container, PageError } from '@harnessio/uicore'
import { useParams } from 'react-router-dom'
import { parseLogString } from 'pages/PullRequest/Checks/ChecksUtils'
import type { GetDataError, UseGetProps } from 'restful-react'
import { lineElement, type LogLine } from 'components/LogViewer/LogViewer'
import { useGetGitspaceInstanceLogs } from 'services/cde'
import { useGetCDEAPIParams, type CDEPathParams } from 'cde/hooks/useGetCDEAPIParams'
import type { OpenapiGetGitspaceLogsResponse } from 'services/cde'
import { getErrorMessage } from 'utils/Utils'
import { useStrings } from 'framework/strings'
import { parseLogString } from './GitspaceLogs.utils'
import css from './GitspaceLogs.module.scss'
export const GitspaceLogs = () => {
interface GitlogsProps {
data: OpenapiGetGitspaceLogsResponse
loading?: boolean
error?: GetDataError<unknown> | null
refetch: (
options?: Partial<Omit<UseGetProps<OpenapiGetGitspaceLogsResponse, unknown, void, unknown>, 'lazy'>> | undefined
) => Promise<void>
}
export const GitspaceLogs = ({ data, loading, error, refetch }: GitlogsProps) => {
const { getString } = useStrings()
const localRef = useRef<HTMLDivElement | null>()
const { accountIdentifier, orgIdentifier, projectIdentifier } = useGetCDEAPIParams() as CDEPathParams
const { gitspaceId } = useParams<{
gitspaceId: string
}>()
const { data, loading, error, refetch } = useGetGitspaceInstanceLogs({
accountIdentifier,
orgIdentifier,
projectIdentifier,
gitspaceIdentifier: gitspaceId
})
useEffect(() => {
if (data) {
const pipelineArr = parseLogString(data)
const fragment = new DocumentFragment()
const logContainer = localRef.current as HTMLDivElement
// Clear the container first
if (localRef.current) {
localRef.current.innerHTML = ''
}
if (pipelineArr) {
pipelineArr?.forEach((line: LogLine) => {
const linePos = line.pos + 1
const localDate = new Date(line.time)
// Format date to a more readable format (local time)
const formattedDate = localDate.toLocaleString()
fragment.appendChild(
lineElement(`${linePos} ${line.logLevel} ${formattedDate.replace(',', '')} ${line.message}`)
)
})
try {
if (data) {
const pipelineArr = parseLogString(data)
const fragment = new DocumentFragment()
const logContainer = localRef.current as HTMLDivElement
// Clear the container first
if (localRef.current) {
localRef.current.innerHTML = ''
}
if (pipelineArr) {
pipelineArr?.forEach((line: LogLine) => {
const linePos = line.pos + 1
const localDate = new Date(line.time)
// Format date to a more readable format (local time)
const formattedDate = localDate.toLocaleString()
fragment.appendChild(
lineElement(`${linePos} ${line.logLevel} ${formattedDate.replace(',', '')} ${line.message}`)
)
})
logContainer.appendChild(fragment)
}
logContainer.appendChild(fragment)
}
const scrollParent = logContainer.parentElement as HTMLDivElement
const autoScroll =
scrollParent && scrollParent.scrollTop === scrollParent.scrollHeight - scrollParent.offsetHeight
const scrollParent = logContainer.parentElement as HTMLDivElement
const autoScroll =
scrollParent && scrollParent.scrollTop === scrollParent.scrollHeight - scrollParent.offsetHeight
if (autoScroll || scrollParent.scrollTop === 0) {
scrollParent.scrollTop = scrollParent.scrollHeight
if (autoScroll || scrollParent.scrollTop === 0) {
scrollParent.scrollTop = scrollParent.scrollHeight
}
}
} catch (_err) {
// console.log('err', err)
}
}, [data])
@ -85,7 +86,7 @@ export const GitspaceLogs = () => {
}
return (
<Container width={'45%'}>
<Container className={css.logContainer}>
<Text className={css.logTitle}>{getString('cde.logs')}</Text>
<Container className={css.consoleContainer}>
{data ? (

View File

@ -0,0 +1,38 @@
export function parseLogString(logString: string) {
if (!logString) {
return ''
}
const logEntries = logString.trim().split('\n')
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const parsedLogs: any = []
logEntries.forEach((entry, lineIndex) => {
// Parse the entry as JSON
const jsonEntry = JSON.parse(entry)
// Apply the regex to the 'out' field
const parts = (jsonEntry?.message).match(/time="([^"]+)" level=([^ ]+) msg="([^"]+)"(.*)/)
if (parts) {
const [, time, level, message, details, out] = parts
const detailParts = details.trim().split(' ')
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const detailDict: any = {}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
detailParts.forEach((part: any) => {
if (part.includes('=')) {
const [key, value] = part.split('=')
detailDict[key.trim()] = value.trim()
}
})
parsedLogs.push({ time, level, message, out, details: detailDict, pos: jsonEntry.pos, logLevel: jsonEntry.level })
} else {
parsedLogs.push({
time: jsonEntry.time,
level: jsonEntry.level,
message: jsonEntry?.message,
pos: lineIndex,
logLevel: jsonEntry.level
})
}
})
return parsedLogs
}

View File

@ -25,7 +25,7 @@
div[class*='TableV2--header'] {
display: grid !important;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 50px;
grid-template-columns: 1fr 1.5fr 0.75fr 0.75fr 1fr 50px;
}
}
@ -44,3 +44,9 @@
}
}
}
.gitspaceURL {
white-space: nowrap !important;
overflow: hidden;
text-overflow: ellipsis;
}

View File

@ -16,6 +16,7 @@
/* eslint-disable */
// This is an auto-generated file
export declare const gitspaceUrl: string
export declare const listContainer: string
export declare const popover: string
export declare const table: string

View File

@ -14,13 +14,14 @@
* limitations under the License.
*/
import { Container, Layout, TableV2, Text } from '@harnessio/uicore'
import { Container, Layout, TableV2, Text, useToaster } from '@harnessio/uicore'
import React from 'react'
import { Color } from '@harnessio/design-system'
import type { Renderer, CellProps } from 'react-table'
import ReactTimeago from 'react-timeago'
import { Circle, GithubCircle, GitBranch, Cpu, Clock, Play, Square, Db, ModernTv, OpenInBrowser } from 'iconoir-react'
import { Menu, MenuItem, PopoverInteractionKind, Position } from '@blueprintjs/core'
import { useHistory } from 'react-router-dom'
import {
useGitspaceAction,
type EnumGitspaceStateType,
@ -30,6 +31,7 @@ import {
import { CDEPathParams, useGetCDEAPIParams } from 'cde/hooks/useGetCDEAPIParams'
import { GitspaceActionType, GitspaceStatus, IDEType } from 'cde/constants'
import { UseStringsReturn, useStrings } from 'framework/strings'
import { useAppContext } from 'AppContext'
import VSCode from '../../icons/VSCode.svg?url'
import css from './ListGitspaces.module.scss'
@ -93,7 +95,7 @@ export const RenderRepository: Renderer<CellProps<OpenapiGetGitspaceResponse>> =
<Layout.Vertical spacing={'small'}>
<Layout.Horizontal spacing={'small'} flex={{ alignItems: 'center', justifyContent: 'start' }}>
<GithubCircle />
<Text color={Color.GREY_500} title={name} font={{ align: 'left', size: 'normal' }}>
<Text className={css.gitspaceUrl} color={Color.GREY_500} title={name} font={{ align: 'left', size: 'normal' }}>
{name}
</Text>
<Text>:</Text>
@ -152,19 +154,30 @@ const StartStopButton = ({
}) => {
const { getString } = useStrings()
const { accountIdentifier, projectIdentifier, orgIdentifier } = useGetCDEAPIParams() as CDEPathParams
const { mutate } = useGitspaceAction({ accountIdentifier, projectIdentifier, orgIdentifier, gitspaceIdentifier })
const { mutate, loading } = useGitspaceAction({
accountIdentifier,
projectIdentifier,
orgIdentifier,
gitspaceIdentifier
})
const handleClick = () => {
mutate({ action: status === GitspaceStatus.RUNNING ? GitspaceActionType.STOP : GitspaceActionType.START })
const handleClick = async () => {
await mutate({ action: status === GitspaceStatus.RUNNING ? GitspaceActionType.STOP : GitspaceActionType.START })
}
return (
<Layout.Horizontal
onClick={handleClick}
spacing="small"
flex={{ alignItems: 'center', justifyContent: 'flex-start' }}>
<Layout.Horizontal spacing="small" flex={{ alignItems: 'center', justifyContent: 'flex-start' }}>
{loading}
{status === GitspaceStatus.RUNNING ? <Square /> : <Play />}
<Text>
<Text
icon={loading ? 'loading' : undefined}
onClick={e => {
if (!loading) {
e.preventDefault()
e.stopPropagation()
handleClick()
}
}}>
{status === GitspaceStatus.RUNNING
? getString('cde.details.stopGitspace')
: getString('cde.details.startGitspace')}
@ -173,25 +186,41 @@ const StartStopButton = ({
)
}
const OpenGitspaceButton = ({ ide, url }: { ide?: EnumIDEType; url: string }) => {
const OpenGitspaceButton = ({
ide,
url,
id = '',
projectIdentifier = ''
}: {
id: string
url: string
ide?: EnumIDEType
projectIdentifier?: string
}) => {
const { getString } = useStrings()
const handleClick = () => {
window.open(url, '_blank')
}
return (
<Layout.Horizontal
onClick={handleClick}
spacing="small"
flex={{ alignItems: 'center', justifyContent: 'flex-start' }}>
<Layout.Horizontal spacing="small" flex={{ alignItems: 'center', justifyContent: 'flex-start' }}>
{ide === IDEType.VSCODE ? <ModernTv /> : <OpenInBrowser />}
<Text>{ide === IDEType.VSCODE ? getString('cde.ide.openVSCode') : getString('cde.ide.openBrowser')}</Text>
<Text
onClick={e => {
e.preventDefault()
e.stopPropagation()
if (ide === IDEType.VSCODE) {
window.open(url, '_blank')
} else {
window.open(`vscode://harness-inc.gitspaces/${projectIdentifier}/${id}`, '_blank')
}
}}>
{ide === IDEType.VSCODE ? getString('cde.ide.openVSCode') : getString('cde.ide.openBrowser')}
</Text>
</Layout.Horizontal>
)
}
const ActionMenu = ({ data }: { data: OpenapiGetGitspaceResponse }) => {
const { status, id, config, url = '' } = data
const projectIdentifier = config?.scope?.split('/')[1] || ''
return (
<Container className={css.listContainer}>
<Menu>
@ -206,7 +235,12 @@ const ActionMenu = ({ data }: { data: OpenapiGetGitspaceResponse }) => {
<MenuItem
text={
<Layout.Horizontal spacing="small">
<OpenGitspaceButton ide={config?.ide} url={url} />
<OpenGitspaceButton
ide={config?.ide}
url={url}
id={config?.id || ''}
projectIdentifier={projectIdentifier}
/>
</Layout.Horizontal>
}
/>
@ -226,7 +260,7 @@ export const RenderActions: Renderer<CellProps<OpenapiGetGitspaceResponse>> = ({
tooltipProps={{
interactionKind: PopoverInteractionKind.HOVER,
position: Position.BOTTOM_RIGHT,
usePortal: false,
usePortal: true,
popoverClassName: css.popover
}}
/>
@ -234,11 +268,27 @@ export const RenderActions: Renderer<CellProps<OpenapiGetGitspaceResponse>> = ({
}
export const ListGitspaces = ({ data }: { data: OpenapiGetGitspaceResponse[] }) => {
const history = useHistory()
const { getString } = useStrings()
const { routes } = useAppContext()
const { showError } = useToaster()
return (
<Container>
{data && (
<TableV2<OpenapiGetGitspaceResponse>
className={css.table}
onRowClick={row => {
if (row?.config?.scope && row?.config?.id) {
history.push(
routes.toCDEGitspaceDetail({
space: row?.config?.scope,
gitspaceId: row?.config?.id
})
)
} else {
showError(getString('cde.details.wrongIdentifier'))
}
}}
columns={[
{
id: 'gitspaces',

View File

@ -48,8 +48,8 @@ export enum GitspaceActionType {
}
export enum GitspaceRegion {
USEast = 'US East',
USWest = 'US West',
USEast = 'us-east',
USWest = 'us-west',
Europe = 'Europe',
Australia = 'Australia'
}

View File

@ -16,8 +16,8 @@
.main {
display: flex !important;
justify-content: center;
justify-content: space-evenly;
align-items: center;
text-align: center;
height: 80vh;
margin-top: 5% !important;
}

View File

@ -14,22 +14,83 @@
* limitations under the License.
*/
import React from 'react'
import { Breadcrumbs, Layout, Page } from '@harnessio/uicore'
import React, { useEffect, useState } from 'react'
import { Breadcrumbs, Layout, Page, useToaster } from '@harnessio/uicore'
import { useParams } from 'react-router-dom'
import { GitspaceDetails } from 'cde/components/GitspaceDetails/GitspaceDetails'
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
import { useAppContext } from 'AppContext'
import { GitspaceLogs } from 'cde/components/GitspaceLogs/GitspaceLogs'
import { useStrings } from 'framework/strings'
import { CDEPathParams, useGetCDEAPIParams } from 'cde/hooks/useGetCDEAPIParams'
import { useQueryParams } from 'hooks/useQueryParams'
import { useGetGitspace, useGetGitspaceInstanceLogs, useGitspaceAction } from 'services/cde'
import { getErrorMessage } from 'utils/Utils'
import { GitspaceActionType, GitspaceStatus } from 'cde/constants'
import Gitspace from '../../icons/Gitspace.svg?url'
import css from './GitspaceDetail.module.scss'
const GitspaceDetail = () => {
const { showError } = useToaster()
const { getString } = useStrings()
const space = useGetSpaceParam()
const { routes } = useAppContext()
const { gitspaceId = '' } = useParams<{ gitspaceId?: string }>()
const { accountIdentifier, orgIdentifier, projectIdentifier } = useGetCDEAPIParams() as CDEPathParams
const { redirectFrom = '' } = useQueryParams<{ redirectFrom?: string }>()
const [startTriggred, setStartTriggred] = useState(false)
const { data, loading, error, refetch } = useGetGitspace({
accountIdentifier,
orgIdentifier,
projectIdentifier,
gitspaceIdentifier: gitspaceId || ''
})
const {
data: logsData,
loading: logsLoading,
error: logsError,
refetch: refetchLogs
} = useGetGitspaceInstanceLogs({
lazy: !!redirectFrom,
accountIdentifier,
orgIdentifier,
projectIdentifier,
gitspaceIdentifier: gitspaceId
})
const { status } = data || {}
const {
mutate,
loading: mutateLoading,
error: startError
} = useGitspaceAction({
accountIdentifier,
orgIdentifier,
projectIdentifier,
gitspaceIdentifier: gitspaceId || ''
})
useEffect(() => {
const startTrigger = async () => {
if (redirectFrom && !startTriggred && !mutateLoading) {
try {
setStartTriggred(true)
await mutate({ action: GitspaceActionType.START })
await refetch()
await refetchLogs()
} catch (err) {
showError(getErrorMessage(err))
}
}
}
startTrigger()
}, [redirectFrom, mutateLoading, startTriggred])
const isfetchingInProgress = (startTriggred && status === GitspaceStatus.STOPPED && !startError) || mutateLoading
return (
<>
@ -53,10 +114,24 @@ const GitspaceDetail = () => {
</Layout.Horizontal>
}
/>
<Page.Body>
<Page.Body
loading={loading}
loadingMessage="Fetching Gitspace Details ...."
error={getErrorMessage(error)}
retryOnError={() => refetch()}>
<Layout.Horizontal className={css.main} spacing="medium">
<GitspaceDetails />
<GitspaceLogs />
<GitspaceDetails
data={data}
error={error}
loading={loading}
refetch={refetch}
refetchLogs={refetchLogs}
mutate={mutate}
actionError={startError}
mutateLoading={mutateLoading}
isfetchingInProgress={isfetchingInProgress}
/>
<GitspaceLogs data={logsData} refetch={refetchLogs} loading={logsLoading} error={logsError} />
</Layout.Horizontal>
</Page.Body>
</>

View File

@ -42,7 +42,13 @@ const GitspacesListing = () => {
const history = useHistory()
const { getString } = useStrings()
const { routes } = useAppContext()
const { data, loading, error, refetch } = useListGitspaces({
const {
data = '',
loading = false,
error = undefined,
refetch
} = useListGitspaces({
accountIdentifier: space?.split('/')[0],
orgIdentifier: space?.split('/')[1],
projectIdentifier: space?.split('/')[2]
@ -74,31 +80,32 @@ const GitspacesListing = () => {
<Layout.Vertical spacing={'large'}>
<Layout.Horizontal flex={{ justifyContent: 'space-between', alignItems: 'center' }}>
<Text font={{ variation: FontVariation.H3 }}>{getString('cde.manageGitspaces')}</Text>
<Button onClick={() => history.push(routes.toCDEGitspaces({ space }))} variation={ButtonVariation.PRIMARY}>
<Button
onClick={() => history.push(routes.toCDEGitspacesCreate({ space }))}
variation={ButtonVariation.PRIMARY}>
{getString('cde.newGitspace')}
</Button>
</Layout.Horizontal>
<Page.Body
loading={loading}
error={
<Layout.Vertical spacing={'large'}>
<Text font={{ variation: FontVariation.FORM_MESSAGE_DANGER }}>{getErrorMessage(error)}</Text>
<Button onClick={() => refetch()} variation={ButtonVariation.PRIMARY} text={'Retry'} />
</Layout.Vertical>
error ? (
<Layout.Vertical spacing={'large'}>
<Text font={{ variation: FontVariation.FORM_MESSAGE_DANGER }}>{getErrorMessage(error)}</Text>
<Button
onClick={() => refetch?.()}
variation={ButtonVariation.PRIMARY}
text={getString('cde.retry')}
/>
</Layout.Vertical>
) : null
}
noData={{
when: () => data?.length === 0,
image: noSpace,
message: getString('cde.noGitspaces'),
button: (
<Button
onClick={() => history.push(routes.toCDEGitspaces({ space }))}
variation={ButtonVariation.PRIMARY}
text={getString('cde.newGitspace')}
/>
)
message: getString('cde.noGitspaces')
}}>
<ExpandingSearchInput width={'50%'} alwaysExpanded />
{Boolean(data) && <ExpandingSearchInput width={'50%'} alwaysExpanded autoFocus={false} />}
<ListGitspaces data={data as OpenapiGetGitspaceResponse[]} />
</Page.Body>
</Layout.Vertical>

View File

@ -16,9 +16,9 @@
export const listingMock = [
{
id: 'gs8',
id: 'vscode-remote-try-python.git_sdasda',
url: '',
status: 'STOPPED',
status: 'RUNNING',
resource_usage: '',
created: 1716371699104,
last_used: 0,
@ -28,18 +28,18 @@ export const listingMock = [
access_type: '',
machine_user: '',
config: {
id: 'gs8',
name: 'my test gitspace',
id: 'vscode-remote-try-python.git_sdasda',
name: 'vscode-remote-try-python_adsdsad',
prebuild_repo_id: 'string',
ide: 'VSCODEWEB',
infra_provider_resource_id: 'gs8',
code_repo_id: '',
code_repo_id: 'vscode-remote-try-python_adsdsad',
code_repo_url: 'https://github.com/microsoft/vscode-remote-try-python',
code_repo_type: 'GITHUB',
branch: 'main',
devcontainer_path: '.devcontainer/devcontainer.json',
user_id: 'userID',
scope: 'scope',
scope: '8mCyOduAQbejC4SmQPyRDg/default/deepesh',
created: 1716371699104,
updated: 1716371699104,
metadata: null,

View File

@ -141,6 +141,7 @@ export interface StringsMap {
'cde.createGitspace': string
'cde.createRepo': string
'cde.details.actions': string
'cde.details.fetchingDetails': string
'cde.details.fetchingGitspace': string
'cde.details.fetchingLogs': string
'cde.details.gitspaceRunning': string
@ -155,6 +156,7 @@ export interface StringsMap {
'cde.details.startGitspace': string
'cde.details.stopGitspace': string
'cde.details.stopProvising': string
'cde.details.wrongIdentifier': string
'cde.gitpsaceDetail': string
'cde.gitspaces': string
'cde.hours': string
@ -187,6 +189,7 @@ export interface StringsMap {
'cde.repository.repo': string
'cde.repository.repositoryURL': string
'cde.repository.selectRepository': string
'cde.retry': string
'cde.used': string
changePassword: string
changePasswordSuccesfully: string

View File

@ -1065,7 +1065,7 @@ cde:
newGitspace: + New Gitspace
manageGitspaces: Manage Gitspaces
noGitspaces: You have not created any Gitspace yet
gitpsaceDetail: Gitpsace Detail
gitpsaceDetail: Gitspace Detail
machine: Machine
region: Region
or: OR
@ -1075,6 +1075,7 @@ cde:
used: Used
hours: Hours
na: NA
retry: Retry
details:
actions: More Actions
openEditor: Open VS Code Editor
@ -1091,6 +1092,8 @@ cde:
fetchingLogs: Fetching gitspace logs
logsFailed: Gitspace logs api failed
noLogsFound: No gitspace logs found
wrongIdentifier: Invalid gitspace id or project params
fetchingDetails: Fetching Gitspace Details ....
repository:
repo: Repository
selectRepository: Select Repository

View File

@ -79,6 +79,15 @@ export interface OpenapiCreateInfraProviderResponse {
updated?: number
}
export interface OpenapiCreateInfraProviderTemplateRequest {
created?: number
data?: string
description?: string
identifier?: string
space_id?: number
updated?: number
}
export interface OpenapiCreateInfraProviderTemplateResponse {
created?: number
data?: string
@ -161,7 +170,7 @@ export interface TypesInfraProviderResourceRequest {
} | null
region?: string[] | null
scope?: string
template_id?: number
template_id?: string
}
export interface TypesInfraProviderResourceResponse {
@ -176,10 +185,12 @@ export interface TypesInfraProviderResourceResponse {
memory?: string
name?: string
network?: string
opentofu_params?: string
opentofu_params?: {
[key: string]: string
} | null
region?: string
scope?: string
template_id?: number
template_id?: string
updated?: number
}
@ -283,7 +294,7 @@ export type DeleteGitspaceProps = Omit<
DeleteGitspacePathParams
/**
* Delete gitspace
* Delete gitspace config
*/
export const DeleteGitspace = ({
accountIdentifier,
@ -306,7 +317,7 @@ export type UseDeleteGitspaceProps = Omit<
DeleteGitspacePathParams
/**
* Delete gitspace
* Delete gitspace config
*/
export const useDeleteGitspace = ({
accountIdentifier,
@ -963,7 +974,13 @@ export interface CreateInfraProviderTemplatePathParams {
}
export type CreateInfraProviderTemplateProps = Omit<
MutateProps<OpenapiCreateInfraProviderTemplateResponse, unknown, void, void, CreateInfraProviderTemplatePathParams>,
MutateProps<
OpenapiCreateInfraProviderTemplateResponse,
unknown,
void,
OpenapiCreateInfraProviderTemplateRequest,
CreateInfraProviderTemplatePathParams
>,
'path' | 'verb'
> &
CreateInfraProviderTemplatePathParams
@ -978,9 +995,15 @@ export const CreateInfraProviderTemplate = ({
infraProviderConfigIdentifier,
...props
}: CreateInfraProviderTemplateProps) => (
<Mutate<OpenapiCreateInfraProviderTemplateResponse, unknown, void, void, CreateInfraProviderTemplatePathParams>
<Mutate<
OpenapiCreateInfraProviderTemplateResponse,
unknown,
void,
OpenapiCreateInfraProviderTemplateRequest,
CreateInfraProviderTemplatePathParams
>
verb="POST"
path={`/accounts/${accountIdentifier}/orgs/${orgIdentifier}/projects/${projectIdentifier}/infraproviders/${infraProviderConfigIdentifier}/template`}
path={`/accounts/${accountIdentifier}/orgs/${orgIdentifier}/projects/${projectIdentifier}/infraproviders/${infraProviderConfigIdentifier}/templates`}
base={getConfig('cde/api/v1')}
{...props}
/>
@ -991,7 +1014,7 @@ export type UseCreateInfraProviderTemplateProps = Omit<
OpenapiCreateInfraProviderTemplateResponse,
unknown,
void,
void,
OpenapiCreateInfraProviderTemplateRequest,
CreateInfraProviderTemplatePathParams
>,
'path' | 'verb'
@ -1008,10 +1031,16 @@ export const useCreateInfraProviderTemplate = ({
infraProviderConfigIdentifier,
...props
}: UseCreateInfraProviderTemplateProps) =>
useMutate<OpenapiCreateInfraProviderTemplateResponse, unknown, void, void, CreateInfraProviderTemplatePathParams>(
useMutate<
OpenapiCreateInfraProviderTemplateResponse,
unknown,
void,
OpenapiCreateInfraProviderTemplateRequest,
CreateInfraProviderTemplatePathParams
>(
'POST',
(paramsInPath: CreateInfraProviderTemplatePathParams) =>
`/accounts/${paramsInPath.accountIdentifier}/orgs/${paramsInPath.orgIdentifier}/projects/${paramsInPath.projectIdentifier}/infraproviders/${paramsInPath.infraProviderConfigIdentifier}/template`,
`/accounts/${paramsInPath.accountIdentifier}/orgs/${paramsInPath.orgIdentifier}/projects/${paramsInPath.projectIdentifier}/infraproviders/${paramsInPath.infraProviderConfigIdentifier}/templates`,
{
base: getConfig('cde/api/v1'),
pathParams: { accountIdentifier, orgIdentifier, projectIdentifier, infraProviderConfigIdentifier },
@ -1073,7 +1102,7 @@ export const useListGitspaces = ({
}: UseListGitspacesProps) =>
useGet<OpenapiGetGitspaceResponse[], unknown, void, ListGitspacesPathParams>(
(paramsInPath: ListGitspacesPathParams) =>
`/accounts/${paramsInPath.accountIdentifier}/orgs/${paramsInPath.orgIdentifier}/projects/${paramsInPath.projectIdentifier}gitspaces`,
`/accounts/${paramsInPath.accountIdentifier}/orgs/${paramsInPath.orgIdentifier}/projects/${paramsInPath.projectIdentifier}/gitspaces`,
{ base: getConfig('cde/api/v1'), pathParams: { accountIdentifier, orgIdentifier, projectIdentifier }, ...props }
)
@ -1099,7 +1128,7 @@ export type CreateGitspaceProps = Omit<
CreateGitspacePathParams
/**
* Create gitspace
* Create gitspace config
*/
export const CreateGitspace = ({
accountIdentifier,
@ -1122,7 +1151,7 @@ export type UseCreateGitspaceProps = Omit<
CreateGitspacePathParams
/**
* Create gitspace
* Create gitspace config
*/
export const useCreateGitspace = ({
accountIdentifier,
@ -1133,7 +1162,7 @@ export const useCreateGitspace = ({
useMutate<OpenapiCreateGitspaceResponse, unknown, void, OpenapiCreateGitspaceRequest, CreateGitspacePathParams>(
'POST',
(paramsInPath: CreateGitspacePathParams) =>
`/accounts/${paramsInPath.accountIdentifier}/orgs/${paramsInPath.orgIdentifier}/projects/${paramsInPath.projectIdentifier}gitspaces`,
`/accounts/${paramsInPath.accountIdentifier}/orgs/${paramsInPath.orgIdentifier}/projects/${paramsInPath.projectIdentifier}/gitspaces`,
{ base: getConfig('cde/api/v1'), pathParams: { accountIdentifier, orgIdentifier, projectIdentifier }, ...props }
)

File diff suppressed because it is too large Load Diff