feat: [CDE-22]: CDE Pages and Components (#2067)

ui/offscreen-diff-contents
Deepesh Kumar 2024-05-29 04:54:54 +00:00 committed by Harness
parent c035c53e4d
commit 5a4dd6274d
68 changed files with 4804 additions and 7 deletions

View File

@ -0,0 +1,52 @@
/*
* 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.
*/
const packageJSON = require('../../package.json')
const { pick, mapValues } = require('lodash')
/**
* These packages must be stricly shared with exact versions
*/
const ExactSharedPackages = [
'react-dom',
'react',
'react-router-dom',
'@blueprintjs/core',
'@blueprintjs/select',
'@blueprintjs/datetime',
'restful-react'
]
/**
* @type {import('webpack').ModuleFederationPluginOptions}
*/
module.exports = {
name: 'cdeRemote',
filename: 'remoteEntry.js',
exposes: {
'./App': './src/App.tsx',
'./Gitspaces': './src/cde/pages/Gitspaces/Gitspaces.tsx',
'./GitspaceDetail': './src/cde/pages/GitspaceDetail/GitspaceDetail.tsx',
'./GitspaceList': './src/cde/pages/GitspacesListing/GitspacesListing.tsx'
},
shared: {
formik: packageJSON.dependencies['formik'],
...mapValues(pick(packageJSON.dependencies, ExactSharedPackages), version => ({
singleton: true,
requiredVersion: version
}))
}
}

View File

@ -27,9 +27,26 @@ const GenerateStringTypesPlugin = require('../scripts/webpack/GenerateStringType
const { RetryChunkLoadPlugin } = require('webpack-retry-chunk-load-plugin')
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin')
const moduleFederationConfig = require('./moduleFederation.config')
const moduleFederationConfigCDE = require('./cde/moduleFederation.config')
const CONTEXT = process.cwd()
const DEV = process.env.NODE_ENV === 'development'
const getModuleFields = () => {
if (process.env.MODULE === 'cde') {
return {
moduleFederationConfigEntryName: moduleFederationConfigCDE.name,
moduleFederationPlugin: new ModuleFederationPlugin(moduleFederationConfigCDE)
}
} else {
return {
moduleFederationConfigEntryName: moduleFederationConfig.name,
moduleFederationPlugin: new ModuleFederationPlugin(moduleFederationConfig)
}
}
}
const { moduleFederationConfigEntryName, moduleFederationPlugin } = getModuleFields()
module.exports = {
target: 'web',
context: CONTEXT,
@ -38,7 +55,7 @@ module.exports = {
children: false
},
entry: {
[moduleFederationConfig.name]: './src/public-path'
[moduleFederationConfigEntryName]: './src/public-path'
},
output: {
publicPath: 'auto',
@ -203,7 +220,7 @@ module.exports = {
minify: false,
templateParameters: {}
}),
new ModuleFederationPlugin(moduleFederationConfig),
moduleFederationPlugin,
new DefinePlugin({
'process.env': '{}', // required for @blueprintjs/core
__DEV__: DEV

View File

@ -21,9 +21,18 @@ require('dotenv').config()
const { merge } = require('webpack-merge')
const commonConfig = require('./webpack.common')
const getPortByModule = () => {
const module = process.env.MODULE
if (module === 'cde') {
return process.env.CDE_PORT ?? 3021
} else {
return process.env.PORT ?? 3020
}
}
const API_URL = process.env.API_URL ?? 'http://localhost:3000'
const HOST = 'localhost'
const PORT = process.env.PORT ?? 3020
const PORT = getPortByModule()
const STANDALONE = process.env.STANDALONE === 'true'
const CONTEXT = process.cwd()
const prodConfig = require('./webpack.prod')

View File

@ -16,8 +16,10 @@
"keywords": [],
"scripts": {
"webpack": "NODE_ENV=development webpack serve --config config/webpack.dev.js",
"webpack:cde": "NODE_ENV=development MODULE=cde webpack serve --config config/webpack.dev.js",
"typed-scss": "typed-scss-modules src --watch",
"dev": "run-p webpack typed-scss",
"dev:cde": "MODULE=cde run-p webpack:cde typed-scss",
"test": "jest src --silent",
"test:watch": "jest --watch",
"build": "rm -rf dist && webpack --config config/webpack.prod.js",

View File

@ -80,4 +80,5 @@ export interface AppProps {
defaultSettingsURL: string
isPublicAccessEnabledOnResources: boolean
isCurrentSessionPublic: boolean
module?: string
}

View File

@ -14,6 +14,8 @@
* limitations under the License.
*/
import { CDERoutes, routes as cdeRoutes } from 'cde/RouteDefinitions'
export interface CODEProps {
space?: string
repoName?: string
@ -34,6 +36,7 @@ export interface CODEProps {
settingSection?: string
ruleId?: string
settingSectionMode?: string
gitspaceId?: string
}
export interface CODEQueryProps {
@ -56,10 +59,11 @@ export const pathProps: Readonly<Omit<Required<CODEProps>, 'repoPath' | 'branch'
secret: ':secret',
settingSection: ':settingSection',
ruleId: ':ruleId',
settingSectionMode: ':settingSectionMode'
settingSectionMode: ':settingSectionMode',
gitspaceId: ':gitspaceId'
}
export interface CODERoutes {
export interface CODERoutes extends CDERoutes {
toSignIn: () => string
toRegister: () => string
@ -166,5 +170,6 @@ export const routes: CODERoutes = {
toCODEExecutions: ({ repoPath, pipeline }) => `/${repoPath}/pipelines/${pipeline}`,
toCODEExecution: ({ repoPath, pipeline, execution }) => `/${repoPath}/pipelines/${pipeline}/execution/${execution}`,
toCODESecret: ({ space, secret }) => `/secrets/${space}/secret/${secret}`
toCODESecret: ({ space, secret }) => `/secrets/${space}/secret/${secret}`,
...cdeRoutes
}

View File

@ -51,6 +51,9 @@ import CodeSearchPage from 'pages/Search/CodeSearchPage'
import AddUpdatePipeline from 'pages/AddUpdatePipeline/AddUpdatePipeline'
import { useAppContext } from 'AppContext'
import PipelineSettings from 'components/PipelineSettings/PipelineSettings'
import GitspaceDetail from 'cde/pages/GitspaceDetail/GitspaceDetail'
import Gitspaces from 'cde/pages/Gitspaces/Gitspaces'
import GitspacesListing from 'cde/pages/GitspacesListing/GitspacesListing'
export const RouteDestinations: React.FC = React.memo(function RouteDestinations() {
const { getString } = useStrings()
@ -261,6 +264,30 @@ export const RouteDestinations: React.FC = React.memo(function RouteDestinations
</Route>
)}
{standalone && (
<Route path={routes.toCDEGitspaceDetail({ space: pathProps.space, gitspaceId: pathProps.gitspaceId })}>
<LayoutWithSideNav title={getString('cde.gitspaces')}>
<GitspaceDetail />
</LayoutWithSideNav>
</Route>
)}
{standalone && (
<Route path={routes.toCDEGitspaces({ space: pathProps.space })}>
<LayoutWithSideNav title={getString('cde.gitspaces')}>
<Gitspaces />
</LayoutWithSideNav>
</Route>
)}
{standalone && (
<Route path={routes.toCDEGitspacesCreate({ space: pathProps.space })}>
<LayoutWithSideNav title={getString('cde.gitspaces')}>
<GitspacesListing />
</LayoutWithSideNav>
</Route>
)}
<Route
path={routes.toCODECommit({
repoPath,

View File

@ -0,0 +1,37 @@
/*
* 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.
*/
export interface CDEProps {
space?: string
gitspaceId?: string
}
export const pathProps: Readonly<Required<CDEProps>> = {
space: ':space*',
gitspaceId: ':gitspaceId'
}
export interface CDERoutes {
toCDEGitspaces: (args: Required<Pick<CDEProps, 'space'>>) => string
toCDEGitspaceDetail: (args: Required<Pick<CDEProps, 'space' | 'gitspaceId'>>) => string
toCDEGitspacesCreate: (args: Required<Pick<CDEProps, 'space'>>) => string
}
export const routes: CDERoutes = {
toCDEGitspaces: ({ space }) => `/${space}/gitspaces`,
toCDEGitspaceDetail: ({ space, gitspaceId }) => `/${space}/gitspaces/${gitspaceId}`,
toCDEGitspacesCreate: ({ space }) => `/${space}/gitspaces/create`
}

View File

@ -0,0 +1,66 @@
/*
* 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.
*/
.main {
width: 50%;
.cardTitle {
text-align: left;
margin-bottom: var(--spacing-small);
}
}
.branchDropdown {
width: 65% !important;
}
.buttonPopover {
width: 50%;
:global(> .bp3-popover-target) {
width: 100%;
}
}
.formContainer {
:global {
.OverlaySpinner--overlaySpinner {
width: 100% !important;
}
}
}
.branchInput {
span[icon='git-branch'] {
top: 20%;
left: 2% !important;
}
input {
height: 50px;
border-radius: 7px;
border: 1px solid var(--grey-200) !important;
box-shadow: none !important;
background: var(--grey-100);
padding-left: 15% !important;
&:active {
background: white;
}
&:focus {
background: white;
}
}
}

View File

@ -0,0 +1,24 @@
/*
* 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 branchDropdown: string
export declare const branchInput: string
export declare const buttonPopover: string
export declare const cardTitle: string
export declare const formContainer: string
export declare const main: string

View File

@ -0,0 +1,101 @@
/*
* 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 * as yup from 'yup'
import { Button, ButtonVariation, Card, Formik, FormikForm, Layout, Text } from '@harnessio/uicore'
import { FontVariation } from '@harnessio/design-system'
import { useCreateGitspace, type EnumCodeRepoType, type EnumIDEType } from 'services/cde'
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
import { useStrings } from 'framework/strings'
import { IDEType } from 'cde/constants'
import { SelectIDE } from './components/SelectIDE/SelectIDE'
import { SelectRepository } from './components/SelectRepository/SelectRepository'
import { BranchInput } from './components/BranchInput/BranchInput'
import { SelectInfraProvider } from './components/SelectInfraProvider/SelectInfraProvider'
import css from './CreateGitspace.module.scss'
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 { getString } = useStrings()
return (
<Formik<GitspaceFormInterface>
onSubmit={async data => await onSubmit(data)}
formName={'createGitSpace'}
initialValues={initData}
validationSchema={yup.object().shape({
codeRepoId: yup.string().trim().required(),
branch: yup.string().trim().required(),
ide: yup.string().trim().required(),
region: yup.string().trim().required(),
infra_provider_resource_id: yup.string().trim().required()
})}>
{_ => {
return (
<FormikForm>
<Layout.Vertical spacing="medium">
<Layout.Horizontal spacing="medium">
<SelectRepository />
<BranchInput />
</Layout.Horizontal>
<SelectIDE />
<SelectInfraProvider />
<Button variation={ButtonVariation.PRIMARY} height={50} type="submit">
{getString('cde.createGitspace')}
</Button>
</Layout.Vertical>
</FormikForm>
)
}}
</Formik>
)
}
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} />
</Card>
)
}

View File

@ -0,0 +1,43 @@
/*
* 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.
*/
.branchInput {
span[icon='git-branch'] {
top: 20%;
left: 2% !important;
}
input {
height: 50px !important;
border-radius: 7px !important;
border: 1px solid var(--grey-200) !important;
box-shadow: none !important;
background: var(--grey-100);
padding-left: 15% !important;
&:active {
background: white;
}
&:focus {
background: white;
}
}
}
.branchDropdown {
width: 65% !important;
margin: 0 !important;
}

View File

@ -0,0 +1,20 @@
/*
* 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 branchDropdown: string
export declare const branchInput: string

View File

@ -0,0 +1,34 @@
/*
* 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 cx from 'classnames'
import { FormInput } from '@harnessio/uicore'
import { Color } from '@harnessio/design-system'
import { useStrings } from 'framework/strings'
import css from './BranchInput.module.scss'
export const BranchInput = () => {
const { getString } = useStrings()
return (
<FormInput.Text
name="branch"
inputGroup={{ leftIcon: 'git-branch', color: Color.GREY_500 }}
placeholder={getString('cde.branchPlaceholder')}
className={cx(css.branchDropdown, css.branchInput)}
/>
)
}

View File

@ -0,0 +1,82 @@
/*
* 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 { Menu, MenuItem } from '@blueprintjs/core'
import { Layout, Text, Container } from '@harnessio/uicore'
import { useFormikContext } from 'formik'
import { GitspaceSelect } from 'cde/components/GitspaceSelect/GitspaceSelect'
import { useStrings, type UseStringsReturn } from 'framework/strings'
import { IDEType } from 'cde/constants'
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 },
{ label: getString('cde.ide.browser'), value: IDEType.VSCODEWEB }
]
export const SelectIDE = () => {
const { values, errors, setFieldValue: onChange } = useFormikContext<GitspaceFormInterface>()
const { ide } = values
const { getString } = useStrings()
const IDESelectItems = getIDESelectItems(getString)
const IDELabel = IDESelectItems.find(item => item.value === ide)?.label
return (
<GitspaceSelect
text={
<Layout.Horizontal flex={{ alignItems: 'center', justifyContent: 'flex-start' }}>
<img src={VSCode} height={20} width={20} style={{ marginRight: '12px' }} />
<Layout.Vertical>
<Text font={ide ? 'small' : 'normal'}>
{ide ? getString('cde.ide.ide') : getString('cde.ide.selectIDE')}
</Text>
{ide && (
<Text font={{ size: 'normal', weight: 'bold' }}>
{`${getString('cde.ide.vsCode')} ${IDELabel}` || getString('cde.ide.ide')}
</Text>
)}
</Layout.Vertical>
</Layout.Horizontal>
}
formikName="ide"
errorMessage={errors.ide}
renderMenu={
<Container padding={{ top: 'small', bottom: 'small' }}>
<Menu>
{IDESelectItems.map(({ label, value }) => {
return (
<MenuItem
key={label}
active={value === ide}
text={
<Layout.Vertical spacing="small">
<Text font={{ size: 'normal', weight: 'bold' }}>{label}</Text>
<Text font="small">1.2.3</Text>
</Layout.Vertical>
}
onClick={() => {
onChange('ide', value)
}}
/>
)
})}
</Menu>
</Container>
}
/>
)
}

View File

@ -0,0 +1,58 @@
/*
* 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 { 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 { SelectRegion } from '../SelectRegion/SelectRegion'
import { SelectMachine } from '../SelectMachine/SelectMachine'
export const SelectInfraProvider = () => {
const { values } = useFormikContext<GitspaceFormInterface>()
const { accountIdentifier, orgIdentifier, projectIdentifier } = useGetCDEAPIParams() as CDEPathParams
const { data } = useListInfraProviderResources({
accountIdentifier,
orgIdentifier,
projectIdentifier,
infraProviderConfigIdentifier: 'HARNESS_GCP'
})
const optionsList = data && isObject(data) ? data : []
const regionOptions = optionsList
? optionsList.map(item => {
return { label: defaultTo(item?.region, ''), value: defaultTo(item?.region, '') }
})
: []
const machineOptions =
optionsList
?.filter(item => item?.region === values?.region)
?.map(item => {
return { ...item }
}) || []
return (
<Layout.Horizontal spacing="medium">
<SelectRegion options={regionOptions} />
<SelectMachine options={machineOptions} />
</Layout.Horizontal>
)
}

View File

@ -0,0 +1,121 @@
/*
* Copyright 2023 Harness, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useState } from 'react'
import { Layout, Text } from '@harnessio/uicore'
import { Menu, MenuItem } from '@blueprintjs/core'
import { Cpu } from 'iconoir-react'
import { useFormikContext } from 'formik'
import { GitspaceSelect } from 'cde/components/GitspaceSelect/GitspaceSelect'
import type { 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'
export const machineIdToLabel = {
'4core_8gb_32gb': 'Standard',
'8core_16gb_64gb': 'Large'
}
export const labelToMachineId = {
Standard: '4core_8gb_32gb',
Large: '8core_16gb_64gb'
}
interface SelectMachineInterface {
options: TypesInfraProviderResourceResponse[]
}
export const SelectMachine = ({ options }: SelectMachineInterface) => {
const { getString } = useStrings()
const { values, errors, setFieldValue: onChange } = useFormikContext<GitspaceFormInterface>()
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
return {
infra_provider_config_id,
id: `${cpu}_${disk}_${memory}`,
label: machineIdToLabel[`${cpu}_${disk}_${memory}` as keyof typeof machineIdToLabel]
}
})
return (
<GitspaceSelect
overridePopOverWidth
text={
<Layout.Horizontal spacing={'small'}>
<Cpu />
<Text font={'normal'}>{machine || getString('cde.machine')}</Text>
</Layout.Horizontal>
}
errorMessage={errors.infra_provider_resource_id}
formikName="infra_provider_resource_id"
renderMenu={
<Layout.Horizontal padding={{ top: 'small', bottom: 'small' }}>
<Menu>
{machineTypes.map(item => {
return (
<MenuItem
key={item.infra_provider_config_id}
active={machineState === item.id}
text={
<Text font={{ size: 'normal', weight: 'bold' }}>
{machineIdToLabel[item.id as keyof typeof machineIdToLabel]}
</Text>
}
onClick={() => {
onChange('infra_provider_resource_id', item.infra_provider_config_id || '')
}}
onMouseOver={(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
const dd = e.currentTarget.innerText as keyof typeof labelToMachineId
setMachineState(labelToMachineId[dd])
}}
/>
)
})}
</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

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 70 69"><rect x="8.5" y="7.5" width="53" height="53" rx="7.5" stroke="#6B6D85"/><rect x="13.5" y="12.5" width="19" height="19" rx="3.5" stroke="#6B6D85"/><rect x="37.5" y="12.5" width="19" height="19" rx="3.5" stroke="#6B6D85"/><rect x="13.5" y="36.5" width="19" height="19" rx="3.5" stroke="#6B6D85"/><rect x="37.5" y="36.5" width="19" height="19" rx="3.5" stroke="#6B6D85"/><path fill="#6B6D85" d="M0 20h8v1H0zM0 29h8v1H0zM0 38h8v1H0zM0 47h8v1H0zM62 20h8v1h-8zM62 29h8v1h-8zM62 38h8v1h-8zM62 47h8v1h-8zM21 69v-8h1v8zM30 69v-8h1v8zM39 69v-8h1v8zM48 69v-8h1v8zM21 8V0h1v8zM30 8V0h1v8zM39 8V0h1v8zM48 8V0h1v8z"/></svg>

After

Width:  |  Height:  |  Size: 681 B

View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 70 69"><rect x="8.5" y="7.5" width="53" height="53" rx="7.5" stroke="#6B6D85"/><rect x="13.5" y="12.5" width="19" height="7" rx="1.5" stroke="#6B6D85"/><rect x="37.5" y="12.5" width="19" height="7" rx="1.5" stroke="#6B6D85"/><rect x="13.5" y="24.5" width="19" height="7" rx="1.5" stroke="#6B6D85"/><rect x="37.5" y="24.5" width="19" height="7" rx="1.5" stroke="#6B6D85"/><rect x="13.5" y="36.5" width="19" height="7" rx="1.5" stroke="#6B6D85"/><rect x="37.5" y="36.5" width="19" height="7" rx="1.5" stroke="#6B6D85"/><rect x="13.5" y="48.5" width="19" height="7" rx="1.5" stroke="#6B6D85"/><rect x="37.5" y="48.5" width="19" height="7" rx="1.5" stroke="#6B6D85"/><path fill="#6B6D85" d="M0 20h8v1H0zM0 29h8v1H0zM0 38h8v1H0zM0 47h8v1H0zM62 20h8v1h-8zM62 29h8v1h-8zM62 38h8v1h-8zM62 47h8v1h-8zM21 69v-8h1v8zM30 69v-8h1v8zM39 69v-8h1v8zM48 69v-8h1v8zM21 8V0h1v8zM30 8V0h1v8zM39 8V0h1v8zM48 8V0h1v8z"/></svg>

After

Width:  |  Height:  |  Size: 969 B

View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 239 77"><g clip-path="url(#a)"><path stroke="#6B6D85" d="M11.5 52.5h151v11h-151z"/><path d="M41.112 19.5h-27.4A2.713 2.713 0 0 0 11 22.213v13.883a2.713 2.713 0 0 0 2.713 2.712h27.399a2.713 2.713 0 0 0 2.712-2.712V22.213a2.713 2.713 0 0 0-2.712-2.713Z" fill="#000" fill-opacity=".2"/><path d="M16.912 33.5v-8.76h2.772c.584 0 1.088.108 1.512.324.432.216.768.52 1.008.912.24.384.36.84.36 1.368 0 .576-.148 1.084-.444 1.524-.288.44-.68.752-1.176.936l1.74 3.696h-1.68l-1.524-3.48h-1.068v3.48h-1.5Zm1.5-4.8h1.272c.424 0 .756-.116.996-.348.24-.232.36-.552.36-.96 0-.416-.12-.74-.36-.972-.24-.24-.572-.36-.996-.36h-1.272v2.64Zm5.203 4.8 2.208-8.76h1.932l2.22 8.76H28.44l-.48-2.124h-2.328l-.48 2.124h-1.536Zm2.292-3.348h1.776l-.528-2.352a58.966 58.966 0 0 1-.228-1.056 24.78 24.78 0 0 1-.132-.696 24.78 24.78 0 0 1-.132.696c-.056.312-.132.66-.228 1.044l-.528 2.364Zm5.156 3.348v-8.76h1.776l.852 2.784c.088.28.16.536.216.768.056.232.092.4.108.504.016-.104.052-.272.108-.504.056-.232.124-.488.204-.768l.816-2.784h1.776v8.76h-1.404v-2.724c0-.4.012-.836.036-1.308.024-.472.052-.944.084-1.416.032-.472.068-.92.108-1.344.048-.424.088-.796.12-1.116l-1.176 4.14h-1.368l-1.212-4.14a44.266 44.266 0 0 1 .228 2.4c.04.464.072.936.096 1.416.024.48.036.936.036 1.368V33.5h-1.404Z" fill="#000"/><path d="M48.904 33.5v-.984h2.376V25.64l-2.376 1.776v-1.2l1.98-1.476h1.476v7.776h1.944v.984h-5.4Zm9.727.12c-.56 0-1.051-.116-1.475-.348a2.53 2.53 0 0 1-.972-.996c-.232-.424-.348-.916-.348-1.476 0-.44.06-.872.18-1.296a4.97 4.97 0 0 1 .564-1.224l2.196-3.54h1.2l-2.484 3.984.047.036a1.47 1.47 0 0 1 .624-.516c.265-.12.56-.18.889-.18.48 0 .895.112 1.248.336.352.224.623.54.816.948.191.408.288.892.288 1.452 0 .56-.117 1.052-.349 1.476a2.53 2.53 0 0 1-.971.996c-.409.232-.893.348-1.453.348Zm-.011-.96c.512 0 .924-.168 1.236-.504.311-.344.468-.796.468-1.356s-.157-1.008-.468-1.344c-.313-.344-.724-.516-1.236-.516s-.924.172-1.236.516c-.313.336-.468.784-.468 1.344s.156 1.012.468 1.356c.312.336.724.504 1.236.504Zm7.243.96c-.528 0-.988-.1-1.38-.3a2.178 2.178 0 0 1-.9-.864c-.208-.384-.312-.836-.312-1.356v-3.96c0-.528.104-.98.312-1.356.216-.376.516-.664.9-.864.392-.2.852-.3 1.38-.3.528 0 .984.104 1.368.312.384.2.68.488.888.864.208.376.312.824.312 1.344h-1.08c0-.496-.132-.876-.396-1.14-.256-.272-.62-.408-1.092-.408-.472 0-.844.132-1.116.396-.264.264-.396.644-.396 1.14V31.1c0 .496.132.88.396 1.152.272.272.644.408 1.116.408.472 0 .836-.136 1.092-.408.264-.272.396-.656.396-1.152v-1.08h-1.776v-.984h2.856V31.1c0 .512-.104.96-.312 1.344a2.178 2.178 0 0 1-.888.876c-.384.2-.84.3-1.368.3Zm4.663-.12v-8.76h2.484c.8 0 1.424.2 1.872.6.456.4.684.956.684 1.668 0 .4-.084.748-.252 1.044a1.7 1.7 0 0 1-.72.684c-.304.16-.672.236-1.104.228v-.18c.464-.008.864.08 1.2.264.344.184.608.448.792.792.192.344.288.752.288 1.224 0 .496-.104.928-.312 1.296a2.122 2.122 0 0 1-.888.852c-.384.192-.844.288-1.38.288h-2.664Zm1.056-.972h1.488c.504 0 .9-.132 1.188-.396.296-.272.444-.64.444-1.104 0-.48-.148-.868-.444-1.164-.288-.304-.684-.456-1.188-.456h-1.488v3.12Zm0-4.056h1.416c.464 0 .828-.124 1.092-.372.272-.248.408-.584.408-1.008 0-.424-.132-.76-.396-1.008s-.628-.372-1.092-.372h-1.428v2.76Z" fill="#6B6D85"/></g><rect x=".5" y="14" width="238" height="49" rx="3.5" stroke="#6B6D85"/><defs><clipPath id="a"><rect y="13.5" width="239" height="50" rx="4" fill="#fff"/></clipPath></defs></svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 77"><g clip-path="url(#a)"><path stroke="#6B6D85" d="M11.5 52.5h52v11h-52z"/><path d="M41.112 19.5h-27.4A2.713 2.713 0 0 0 11 22.213v13.883a2.713 2.713 0 0 0 2.713 2.712h27.399a2.713 2.713 0 0 0 2.712-2.712V22.213a2.713 2.713 0 0 0-2.712-2.713Z" fill="#000" fill-opacity=".2"/><path d="M16.912 33.5v-8.76h2.772c.584 0 1.088.108 1.512.324.432.216.768.52 1.008.912.24.384.36.84.36 1.368 0 .576-.148 1.084-.444 1.524-.288.44-.68.752-1.176.936l1.74 3.696h-1.68l-1.524-3.48h-1.068v3.48h-1.5Zm1.5-4.8h1.272c.424 0 .756-.116.996-.348.24-.232.36-.552.36-.96 0-.416-.12-.74-.36-.972-.24-.24-.572-.36-.996-.36h-1.272v2.64Zm5.203 4.8 2.208-8.76h1.932l2.22 8.76H28.44l-.48-2.124h-2.328l-.48 2.124h-1.536Zm2.292-3.348h1.776l-.528-2.352a58.966 58.966 0 0 1-.228-1.056 24.78 24.78 0 0 1-.132-.696 24.78 24.78 0 0 1-.132.696c-.056.312-.132.66-.228 1.044l-.528 2.364Zm5.156 3.348v-8.76h1.776l.852 2.784c.088.28.16.536.216.768.056.232.092.4.108.504.016-.104.052-.272.108-.504.056-.232.124-.488.204-.768l.816-2.784h1.776v8.76h-1.404v-2.724c0-.4.012-.836.036-1.308.024-.472.052-.944.084-1.416.032-.472.068-.92.108-1.344.048-.424.088-.796.12-1.116l-1.176 4.14h-1.368l-1.212-4.14a44.266 44.266 0 0 1 .228 2.4c.04.464.072.936.096 1.416.024.48.036.936.036 1.368V33.5h-1.404Z" fill="#000"/><path d="M51.424 33.62c-.536 0-1.004-.092-1.404-.276a2.154 2.154 0 0 1-.912-.816c-.216-.352-.324-.764-.324-1.236 0-.52.14-.968.42-1.344.288-.376.74-.712 1.356-1.008l1.164-.564c.352-.168.624-.388.816-.66.192-.272.288-.572.288-.9 0-.384-.128-.688-.384-.912-.248-.224-.588-.336-1.02-.336-.432 0-.776.116-1.032.348-.248.224-.372.528-.372.912 0 .32.092.616.276.888.192.272.452.488.78.648l1.164.552c.64.296 1.104.636 1.392 1.02.288.376.432.828.432 1.356 0 .712-.24 1.28-.72 1.704-.472.416-1.112.624-1.92.624Zm0-.96c.488 0 .872-.124 1.152-.372.288-.256.432-.596.432-1.02 0-.344-.092-.656-.276-.936a1.937 1.937 0 0 0-.792-.672l-1.152-.564c-.64-.312-1.104-.648-1.392-1.008-.288-.36-.432-.792-.432-1.296 0-.448.1-.836.3-1.164.2-.328.484-.58.852-.756.368-.176.804-.264 1.308-.264s.94.088 1.308.264c.368.176.652.428.852.756.2.328.3.716.3 1.164 0 .504-.144.936-.432 1.296-.288.352-.764.692-1.428 1.02l-1.152.564c-.328.16-.584.38-.768.66a1.643 1.643 0 0 0-.264.912c0 .432.14.776.42 1.032.288.256.676.384 1.164.384Zm7.243.96c-.528 0-.988-.1-1.38-.3a2.178 2.178 0 0 1-.9-.864c-.208-.384-.312-.836-.312-1.356v-3.96c0-.528.104-.98.313-1.356.215-.376.516-.664.9-.864.392-.2.852-.3 1.38-.3.528 0 .983.104 1.367.312.385.2.68.488.889.864.208.376.312.824.312 1.344h-1.08c0-.496-.133-.876-.396-1.14-.256-.272-.62-.408-1.093-.408-.471 0-.843.132-1.116.396-.264.264-.395.644-.395 1.14V31.1c0 .496.132.88.395 1.152.273.272.645.408 1.116.408.472 0 .837-.136 1.093-.408.264-.272.396-.656.396-1.152v-1.08H58.38v-.984h2.855V31.1c0 .512-.103.96-.312 1.344a2.178 2.178 0 0 1-.888.876c-.383.2-.84.3-1.367.3Zm4.664-.12v-8.76h2.484c.8 0 1.424.2 1.872.6.456.4.684.956.684 1.668 0 .4-.084.748-.252 1.044a1.7 1.7 0 0 1-.72.684c-.304.16-.672.236-1.104.228v-.18c.464-.008.864.08 1.2.264.344.184.608.448.792.792.192.344.288.752.288 1.224 0 .496-.104.928-.312 1.296a2.122 2.122 0 0 1-.888.852c-.384.192-.844.288-1.38.288H63.33Zm1.056-.972h1.488c.504 0 .9-.132 1.188-.396.296-.272.444-.64.444-1.104 0-.48-.148-.868-.444-1.164-.288-.304-.684-.456-1.188-.456h-1.488v3.12Zm0-4.056h1.416c.464 0 .828-.124 1.092-.372.272-.248.408-.584.408-1.008 0-.424-.132-.76-.396-1.008s-.628-.372-1.092-.372h-1.428v2.76Z" fill="#6B6D85"/></g><rect x=".5" y="14" width="125" height="49" rx="3.5" stroke="#6B6D85"/><defs><clipPath id="a"><rect y="13.5" width="126" height="50" rx="4" fill="#fff"/></clipPath></defs></svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -0,0 +1,81 @@
/*
* Copyright 2023 Harness, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useState } from 'react'
import { Layout, SelectOption, Text } from '@harnessio/uicore'
import { Menu, MenuItem } from '@blueprintjs/core'
import { Map } from 'iconoir-react'
import { useFormikContext } from 'formik'
import { GitspaceSelect } from 'cde/components/GitspaceSelect/GitspaceSelect'
import { useStrings } from 'framework/strings'
import { GitspaceRegion } from 'cde/constants'
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'
interface SelectRegionInterface {
options: SelectOption[]
}
export const SelectRegion = ({ options }: SelectRegionInterface) => {
const { getString } = useStrings()
const { values, errors, setFieldValue: onChange } = useFormikContext<GitspaceFormInterface>()
const { region = '' } = values
const [regionState, setRegionState] = useState<string>(region)
return (
<GitspaceSelect
overridePopOverWidth
text={
<Layout.Horizontal spacing={'small'}>
<Map />
<Text font={'normal'}>{region || getString('cde.region')}</Text>
</Layout.Horizontal>
}
formikName="region"
errorMessage={errors.region}
renderMenu={
<Layout.Horizontal padding={{ top: 'small', bottom: 'small' }}>
<Menu>
{options.map(({ label }) => {
return (
<MenuItem
key={label}
active={label === regionState}
text={<Text font={{ size: 'normal', weight: 'bold' }}>{label}</Text>}
onClick={() => {
onChange('region', label)
}}
onMouseOver={(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
setRegionState(e.currentTarget.innerText)
}}
/>
)
})}
</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} />}
</Menu>
</Layout.Horizontal>
}
/>
)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@ -0,0 +1,58 @@
/*
* 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.
*/
.formContainer {
:global {
.OverlaySpinner--overlaySpinner {
width: 100% !important;
}
}
[class*='OverlaySpinner--overlaySpinner'] {
width: 100% !important;
}
}
.urlInput {
width: 100%;
margin-bottom: 0 !important;
}
.repometadataCard {
width: 100%;
padding: 0 !important;
}
.repometadata {
min-height: 50px;
background: var(--primary-1);
}
.metadataItem {
min-height: 50px;
align-items: center;
}
.privateCard {
padding: var(--spacing-small) !important;
}
.publicTag {
padding: 3px 5px !important;
border-radius: 5px;
color: var(--green-700) !important;
background: var(--green-100) !important;
}

View File

@ -0,0 +1,25 @@
/*
* 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 formContainer: string
export declare const metadataItem: string
export declare const privateCard: string
export declare const publicTag: string
export declare const repometadata: string
export declare const repometadataCard: string
export declare const urlInput: string

View File

@ -0,0 +1,172 @@
/*
* Copyright 2023 Harness, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useState } from 'react'
import { Button, ButtonVariation, Card, FormInput, Formik, FormikForm, Layout, Text } from '@harnessio/uicore'
import { Menu, MenuItem } from '@blueprintjs/core'
import { Color, FontVariation } from '@harnessio/design-system'
import { Link } from 'react-router-dom'
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 { 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]
}
const RepositoryText = ({ repoURL }: { repoURL?: string }) => {
const { getString } = useStrings()
const repoName = getRepoNameFromURL(repoURL)
return repoURL ? (
<Layout.Vertical spacing="xsmall">
<Text font={'normal'}>{repoName || getString('cde.repository.repo')}</Text>
<Text font={'small'} lineClamp={1}>
{repoURL || getString('cde.repository.repositoryURL')}
</Text>
</Layout.Vertical>
) : (
<Text font={'normal'}>{getString('cde.repository.selectRepository')}</Text>
)
}
export const SelectRepository = () => {
const { getString } = useStrings()
const { values, errors, setFieldValue: onChange } = useFormikContext<GitspaceFormInterface>()
const { codeRepoUrl } = values
const space = useGetSpaceParam()
const [validatedOnce, setValidatedOnce] = useState(false)
const [repoMetadata, setRepoMetadata] = useState<OpenapiGetCodeRepositoryResponse | undefined>()
const { mutate, loading } = useGetCodeRepository({
accountIdentifier: space?.split('/')[0],
orgIdentifier: space?.split('/')[1],
projectIdentifier: space?.split('/')[2]
})
return (
<GitspaceSelect
text={<RepositoryText repoURL={codeRepoUrl} />}
icon={'code'}
errorMessage={errors.codeRepoId}
formikName="codeRepoId"
renderMenu={
<Menu>
<Layout.Vertical
className={css.formContainer}
flex={{ justifyContent: 'center', alignItems: 'center' }}
spacing="small"
padding={'large'}>
<Text font={{ variation: FontVariation.CARD_TITLE }}>{getString('cde.repository.pasteRepo')}</Text>
<Text font={{ variation: FontVariation.SMALL }} color={Color.GREY_450}>
{getString('cde.repository.pasterRepoSubtext')}
</Text>
<Formik
formLoading={loading}
onSubmit={() => noop()}
formName={'publicURL'}
initialValues={{ url: codeRepoUrl }}
validate={async ({ url }) => {
if (!url) {
return {}
}
let errorMessages = undefined
try {
const response = await mutate({ url })
if (response?.access_type === CodeRepoAccessType.PRIVATE) {
errorMessages = { url: getString('cde.repository.privateRepoWarning') }
}
setRepoMetadata(response)
} catch (error) {
errorMessages = { url: getErrorMessage(error) }
}
setValidatedOnce(true)
return errorMessages
}}>
{formikProps => {
if (!formikProps.touched.url && validatedOnce) {
formikProps.setFieldTouched('url', true)
}
return (
<FormikForm>
<FormInput.Text
name="url"
className={css.urlInput}
placeholder="e.g https://github.com/orkohunter/idp"
/>
{!!repoMetadata && (
<Card className={css.repometadataCard}>
{repoMetadata?.access_type === CodeRepoAccessType.PRIVATE ? (
<Layout.Vertical
className={css.privateCard}
flex={{ justifyContent: 'center', alignItems: 'center' }}
spacing="medium">
<Icon name="lock" size={20} />
<Text>{getString('cde.repository.privateRepoWarning')}</Text>
<Button variation={ButtonVariation.PRIMARY}>{`${getString('cde.repository.continueWith')} ${
repoMetadata?.repo_type
}`}</Button>
</Layout.Vertical>
) : (
<Menu className={css.repometadata}>
<MenuItem
className={css.metadataItem}
onClick={() => {
onChange('codeRepoUrl', repoMetadata?.url || '')
onChange('codeRepoType', repoMetadata?.repo_type || '')
onChange('codeRepoId', repoMetadata?.url || '')
}}
text={
<Layout.Horizontal
spacing="large"
flex={{ alignItems: 'center', justifyContent: 'flex-start' }}>
<Text font={'small'} lineClamp={1}>
{getRepoNameFromURL(repoMetadata?.url)}
</Text>
<Text className={css.publicTag} font={'xsmall'}>
{repoMetadata?.access_type}
</Text>
</Layout.Horizontal>
}
/>
</Menu>
)}
</Card>
)}
</FormikForm>
)
}}
</Formik>
<Text font={{ variation: FontVariation.FORM_LABEL }}>{getString('cde.or')}</Text>
<Text>
{getString('cde.noRepo')} <Link to={'#'}> {getString('cde.createRepo')} </Link>
</Text>
</Layout.Vertical>
</Menu>
}
/>
)
}

View File

@ -0,0 +1,39 @@
/*
* 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.
*/
.subText {
text-align: left;
}
.detailsBar {
background: var(--grey-100) !important;
padding: var(--spacing-medium) !important;
border-radius: var(--spacing-small);
}
.popover {
> div[class*='popover-arrow'] {
display: none;
}
:global {
a.bp3-menu-item:hover,
.bp3-active {
background: var(--primary-1) !important;
color: var(--grey-1000) !important;
}
}
}

View File

@ -0,0 +1,21 @@
/*
* 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 detailsBar: string
export declare const popover: string
export declare const subText: string

View File

@ -0,0 +1,159 @@
/*
* 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 { Text, Layout, Container, Button, ButtonVariation, PageError } 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 { 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 { GitspaceActionType, GitspaceStatus, IDEType } from 'cde/constants'
import { getErrorMessage } from 'utils/Utils'
import Gitspace from '../../icons/Gitspace.svg?url'
import css from './GitspaceDetails.module.scss'
interface QueryGitspace {
gitspaceId?: string
}
export const GitspaceDetails = () => {
const { getString } = useStrings()
const { accountIdentifier, orgIdentifier, projectIdentifier } = useGetCDEAPIParams() as CDEPathParams
const { gitspaceId } = useParams<QueryGitspace>()
const { data, loading, error, refetch } = useGetGitspace({
accountIdentifier,
orgIdentifier,
projectIdentifier,
gitspaceIdentifier: gitspaceId || ''
})
const { config, status } = data || {}
const { mutate } = useGitspaceAction({
accountIdentifier,
orgIdentifier,
projectIdentifier,
gitspaceIdentifier: gitspaceId || ''
})
const openEditorLabel =
config?.ide === IDEType.VSCODE ? getString('cde.details.openEditor') : getString('cde.details.openBrowser')
return (
<Layout.Vertical width={'30%'} spacing="large">
<Layout.Vertical spacing="medium">
<img src={Gitspace} width={42} height={42}></img>
{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>
)}
</Layout.Vertical>
<Container className={css.detailsBar}>
{error ? (
<Text>{getErrorMessage(error)}</Text>
) : (
<>
{isUndefined(config) ? (
<Text>{getString('cde.details.noData')}</Text>
) : (
<Layout.Horizontal flex={{ justifyContent: 'space-between' }}>
<Layout.Vertical spacing="small">
<Layout.Horizontal spacing="small">
<Circle color="#32CD32" fill="#32CD32" />
<Text font={'small'}>{config?.code_repo_id?.toUpperCase()}</Text>
</Layout.Horizontal>
<Layout.Horizontal spacing="small">
<Repository />
<Text font={'small'}>{config?.code_repo_id}</Text>
<Text> / </Text>
<GitFork />
<Text font={'small'}>{config?.branch}</Text>
</Layout.Horizontal>
</Layout.Vertical>
<Layout.Vertical spacing="small">
<Layout.Horizontal spacing="small">
<Cpu />
<Text font={'small'}>{config?.infra_provider_resource_id}</Text>
</Layout.Horizontal>
</Layout.Vertical>
</Layout.Horizontal>
)}
</>
)}
</Container>
<Layout.Horizontal spacing={'medium'}>
{status === GitspaceStatus.UNKNOWN && (
<>
<Button variation={ButtonVariation.SECONDARY} disabled>
{openEditorLabel}
</Button>
<Button variation={ButtonVariation.PRIMARY} onClick={() => mutate({ action: 'STOP' })}>
{getString('cde.details.stopProvising')}
</Button>
</>
)}
{status === GitspaceStatus.STOPPED && (
<>
<Button variation={ButtonVariation.PRIMARY} onClick={() => mutate({ action: GitspaceActionType.START })}>
{getString('cde.details.startGitspace')}
</Button>
<Button variation={ButtonVariation.TERTIARY}>{getString('cde.details.goToDashboard')}</Button>
</>
)}
{status === GitspaceStatus.RUNNING && (
<>
<Button variation={ButtonVariation.PRIMARY}>{openEditorLabel}</Button>
<Button
variation={ButtonVariation.TERTIARY}
rightIcon="chevron-down"
tooltipProps={
{
interactionKind: 'click',
position: PopoverPosition.BOTTOM_LEFT,
popoverClassName: css.popover
} as PopoverProps
}
tooltip={
<Menu>
<MenuItem
text={getString('cde.details.stopGitspace')}
onClick={() => mutate({ action: GitspaceActionType.STOP })}
/>
</Menu>
}>
{getString('cde.details.actions')}
</Button>
</>
)}
</Layout.Horizontal>
</Layout.Vertical>
)
}

View File

@ -0,0 +1,89 @@
/*
* 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 'src/utils/utils';
.consoleContainer {
min-height: 500px !important;
max-height: 500px !important;
overflow: scroll;
align-items: start !important;
padding-top: var(--spacing-large) !important;
padding-left: var(--spacing-xlarge) !important;
background-color: var(--black) !important;
color: var(--white) !important;
border-bottom-right-radius: 5%;
border-bottom-left-radius: 5%;
pre {
background-color: var(--black) !important;
color: var(--white) !important;
text-align: start !important;
font-size: 12px;
font-family: var(--font-family-mono) !important;
}
}
.logTitle {
color: var(--white) !important;
background: var(--black) !important;
border-top-left-radius: 50px;
border-top-right-radius: 50px;
padding-top: var(--spacing-medium) !important;
text-align: left;
padding-left: var(--spacing-xxlarge) !important;
padding-bottom: var(--spacing-large) !important;
font-size: 16px !important;
}
.mainLog {
flex-shrink: 0;
.line {
margin: 0;
padding: 0;
cursor: text;
min-height: 20px;
display: block;
@include mono-font;
color: var(--white);
word-wrap: break-word !important;
white-space: pre-wrap !important;
}
}
.stepLogContainer {
padding: var(--spacing-small) !important;
flex-shrink: 0;
.consoleLine {
color: var(--white);
@include mono-font;
word-wrap: break-word !important;
white-space: pre-wrap !important;
cursor: text;
margin: 0;
padding: 0;
&:empty {
display: inline-block;
min-height: 20px;
}
}
}

View File

@ -0,0 +1,24 @@
/*
* 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 consoleContainer: string
export declare const consoleLine: string
export declare const line: string
export declare const logTitle: string
export declare const mainLog: string
export declare const stepLogContainer: string

View File

@ -0,0 +1,105 @@
/*
* 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, { 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 { lineElement, type LogLine } from 'components/LogViewer/LogViewer'
import { useGetGitspaceInstanceLogs } from 'services/cde'
import { useGetCDEAPIParams, type CDEPathParams } from 'cde/hooks/useGetCDEAPIParams'
import { getErrorMessage } from 'utils/Utils'
import { useStrings } from 'framework/strings'
import css from './GitspaceLogs.module.scss'
export const GitspaceLogs = () => {
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}`)
)
})
logContainer.appendChild(fragment)
}
const scrollParent = logContainer.parentElement as HTMLDivElement
const autoScroll =
scrollParent && scrollParent.scrollTop === scrollParent.scrollHeight - scrollParent.offsetHeight
if (autoScroll || scrollParent.scrollTop === 0) {
scrollParent.scrollTop = scrollParent.scrollHeight
}
}
}, [data])
let logMessage = ''
if (loading) {
logMessage = getString('cde.details.fetchingLogs')
} else if (error) {
logMessage = getErrorMessage(error) || getString('cde.details.logsFailed')
} else {
logMessage = getString('cde.details.noLogsFound')
}
return (
<Container width={'45%'}>
<Text className={css.logTitle}>{getString('cde.logs')}</Text>
<Container className={css.consoleContainer}>
{data ? (
<Container key={`harnesslog`} ref={localRef} className={cx(css.mainLog, css.stepLogContainer)} />
) : (
<Container key={`harnesslog`} ref={localRef} className={cx(css.mainLog, css.stepLogContainer)}>
{error ? (
<PageError onClick={() => refetch()} message={getErrorMessage(error)} />
) : (
<Text>{logMessage}</Text>
)}
</Container>
)}
</Container>
</Container>
)
}

View File

@ -0,0 +1,87 @@
/*
* 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.
*/
.popover {
> div[class*='popover-arrow'] {
display: none;
}
.listContainer {
min-height: 50px;
overflow-y: auto;
:global {
.bp3-menu {
li {
padding: var(--spacing-small) !important;
}
}
a.bp3-menu-item:hover,
.bp3-active {
background: var(--primary-1) !important;
color: var(--grey-1000) !important;
}
}
}
}
.buttonDiv {
width: 100% !important;
height: auto !important;
:global {
[class*='FormError--errorDiv'] {
margin-left: var(--spacing-2) !important;
}
}
}
.button {
width: 100% !important;
height: 50px !important;
justify-content: space-between !important;
font-size: var(--font-size-normal);
--border: 1px solid var(--grey-200) !important;
--background-color-active: var(--white) !important;
--box-shadow: none !important;
white-space: nowrap !important;
&:active,
&:hover,
&[class*='bp3-active'] {
--border: 1px solid var(--primary-7) !important;
}
:global(> .bp3-button-text) {
width: 100%;
margin-left: var(--spacing-small);
}
}
.buttonWithoutIcon {
padding-left: var(--spacing-medium) !important;
:global(> .bp3-button-text) {
width: 100%;
margin-left: 0 !important;
}
}
.buttonPopoever {
width: 50%;
:global(> .bp3-popover-target) {
width: 100%;
}
}

View File

@ -0,0 +1,24 @@
/*
* 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 button: string
export declare const buttonDiv: string
export declare const buttonPopoever: string
export declare const buttonWithoutIcon: string
export declare const listContainer: string
export declare const popover: string

View File

@ -0,0 +1,94 @@
/*
* 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, { useEffect, useRef, useState } from 'react'
import cx from 'classnames'
import { Menu, PopoverInteractionKind, PopoverPosition } from '@blueprintjs/core'
import { Text, Button, Container, ButtonVariation, FormError } from '@harnessio/uicore'
import type { IconName } from '@harnessio/icons'
import { useStrings } from 'framework/strings'
import css from './GitspaceSelect.module.scss'
interface GitspaceSelectProps {
text: React.ReactElement
icon?: IconName
renderMenu?: React.ReactElement
disabled?: boolean
overridePopOverWidth?: boolean
errorMessage?: string
formikName?: string
}
export const GitspaceSelect = ({
text,
icon,
renderMenu,
disabled,
overridePopOverWidth,
errorMessage,
formikName
}: GitspaceSelectProps) => {
const { getString } = useStrings()
const buttonRef = useRef<HTMLDivElement | null>(null)
const [popoverWidth, setPopoverWidth] = useState(0)
const tooltipProps = {
tooltip: (
<Container className={css.listContainer} width={overridePopOverWidth ? '100%' : popoverWidth}>
{renderMenu ? (
renderMenu
) : (
<Menu>
<Text padding="small">{getString('cde.noData')}</Text>
</Menu>
)}
</Container>
),
tooltipProps: {
fill: true,
interactionKind: PopoverInteractionKind.CLICK,
position: PopoverPosition.BOTTOM_LEFT,
popoverClassName: cx(css.popover)
}
}
useEffect(() => {
if (
buttonRef?.current?.getBoundingClientRect()?.width &&
buttonRef?.current?.getBoundingClientRect()?.width !== popoverWidth
) {
setPopoverWidth(buttonRef?.current?.getBoundingClientRect()?.width)
}
}, [buttonRef?.current, popoverWidth])
const iconProp = icon ? { icon: icon as IconName } : {}
return (
<div className={css.buttonDiv} ref={buttonRef}>
<Button
className={cx(css.button, { [css.buttonWithoutIcon]: !icon })}
text={text}
rightIcon="chevron-down"
variation={ButtonVariation.TERTIARY}
iconProps={{ size: 14 }}
{...iconProp}
{...tooltipProps}
disabled={disabled}
/>
<FormError errorMessage={errorMessage} name={formikName || ''} />
</div>
)
}

View File

@ -0,0 +1,46 @@
/*
* 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.
*/
.table {
margin-top: var(--spacing-large);
div[class*='TableV2--cell'] {
width: auto !important;
}
div[class*='TableV2--cells'],
div[class*='TableV2--header'] {
display: grid !important;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 50px;
}
}
.popover {
> div[class*='popover-arrow'] {
display: none;
}
.listContainer {
:global {
a.bp3-menu-item:hover,
.bp3-active {
background: var(--primary-1) !important;
color: var(--grey-1000) !important;
}
}
}
}

View File

@ -0,0 +1,21 @@
/*
* 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 listContainer: string
export declare const popover: string
export declare const table: string

View File

@ -0,0 +1,278 @@
/*
* 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 { Container, Layout, TableV2, Text } 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 {
useGitspaceAction,
type EnumGitspaceStateType,
type OpenapiGetGitspaceResponse,
EnumIDEType
} from 'services/cde'
import { CDEPathParams, useGetCDEAPIParams } from 'cde/hooks/useGetCDEAPIParams'
import { GitspaceActionType, GitspaceStatus, IDEType } from 'cde/constants'
import { UseStringsReturn, useStrings } from 'framework/strings'
import VSCode from '../../icons/VSCode.svg?url'
import css from './ListGitspaces.module.scss'
export const getStatusColor = (status?: EnumGitspaceStateType) => {
switch (status) {
case GitspaceStatus.RUNNING:
return '#00FF00'
case GitspaceStatus.STOPPED:
case GitspaceStatus.ERROR:
return '#FF0000'
case GitspaceStatus.UNKNOWN:
return '#808080'
default:
return '#000000'
}
}
const getUsageTemplate = (
getString: UseStringsReturn['getString'],
icon: React.ReactNode,
resource_usage?: string,
total_time_used?: number
): React.ReactElement | null => {
return (
<Layout.Horizontal spacing={'small'} flex={{ alignItems: 'center', justifyContent: 'start' }}>
{icon}
<Text color={Color.GREY_500} font={{ align: 'left', size: 'normal' }}>
{getString('cde.used')} {resource_usage || 0}
</Text>
<Text>/</Text>
<Text color={Color.GREY_500} font={{ align: 'left', size: 'normal' }}>
{total_time_used || 0} {getString('cde.hours')}
</Text>
</Layout.Horizontal>
)
}
export const RenderGitspaceName: Renderer<CellProps<OpenapiGetGitspaceResponse>> = ({ row }) => {
const details = row.original
const { config, status } = details
const { name } = config || {}
const color = getStatusColor(status)
return (
<Layout.Horizontal spacing={'small'} flex={{ alignItems: 'center', justifyContent: 'start' }}>
<Circle height={10} width={10} color={color} fill={color} />
<img src={VSCode} height={20} width={20} />
<Text color={Color.BLACK} title={name} font={{ align: 'left', size: 'normal', weight: 'semi-bold' }}>
{name}
</Text>
</Layout.Horizontal>
)
}
export const RenderRepository: Renderer<CellProps<OpenapiGetGitspaceResponse>> = ({ row }) => {
const { getString } = useStrings()
const details = row.original
const { config, tracked_changes } = details
const { name, branch } = config || {}
return (
<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' }}>
{name}
</Text>
<Text>:</Text>
<GitBranch />
<Text color={Color.GREY_500} title={name} font={{ align: 'left', size: 'normal' }}>
{branch}
</Text>
</Layout.Horizontal>
<Text color={Color.GREY_500} font={{ align: 'left', size: 'small' }}>
{tracked_changes || getString('cde.noChange')}
</Text>
</Layout.Vertical>
)
}
export const RenderCPUUsage: Renderer<CellProps<OpenapiGetGitspaceResponse>> = ({ row }) => {
const { getString } = useStrings()
const details = row.original
const { resource_usage, total_time_used } = details
return getUsageTemplate(getString, <Cpu />, resource_usage, total_time_used)
}
export const RenderStorageUsage: Renderer<CellProps<OpenapiGetGitspaceResponse>> = ({ row }) => {
const { getString } = useStrings()
const details = row.original
const { resource_usage, total_time_used } = details
return getUsageTemplate(getString, <Db />, resource_usage, total_time_used)
}
export const RenderLastActivity: Renderer<CellProps<OpenapiGetGitspaceResponse>> = ({ row }) => {
const { getString } = useStrings()
const details = row.original
const { last_used } = details
return (
<Layout.Horizontal spacing={'small'} flex={{ alignItems: 'center', justifyContent: 'start' }}>
<Clock />
{last_used ? (
<ReactTimeago date={last_used} />
) : (
<Text color={Color.GREY_500} font={{ align: 'left', size: 'normal' }}>
{getString('cde.na')}
</Text>
)}
</Layout.Horizontal>
)
}
const StartStopButton = ({
gitspaceIdentifier,
status
}: {
gitspaceIdentifier: string
status?: EnumGitspaceStateType
}) => {
const { getString } = useStrings()
const { accountIdentifier, projectIdentifier, orgIdentifier } = useGetCDEAPIParams() as CDEPathParams
const { mutate } = useGitspaceAction({ accountIdentifier, projectIdentifier, orgIdentifier, gitspaceIdentifier })
const handleClick = () => {
mutate({ action: status === GitspaceStatus.RUNNING ? GitspaceActionType.STOP : GitspaceActionType.START })
}
return (
<Layout.Horizontal
onClick={handleClick}
spacing="small"
flex={{ alignItems: 'center', justifyContent: 'flex-start' }}>
{status === GitspaceStatus.RUNNING ? <Square /> : <Play />}
<Text>
{status === GitspaceStatus.RUNNING
? getString('cde.details.stopGitspace')
: getString('cde.details.startGitspace')}
</Text>
</Layout.Horizontal>
)
}
const OpenGitspaceButton = ({ ide, url }: { ide?: EnumIDEType; url: string }) => {
const { getString } = useStrings()
const handleClick = () => {
window.open(url, '_blank')
}
return (
<Layout.Horizontal
onClick={handleClick}
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>
</Layout.Horizontal>
)
}
const ActionMenu = ({ data }: { data: OpenapiGetGitspaceResponse }) => {
const { status, id, config, url = '' } = data
return (
<Container className={css.listContainer}>
<Menu>
<MenuItem
text={
<Layout.Horizontal spacing="small">
<StartStopButton status={status} gitspaceIdentifier={id || ''} />
</Layout.Horizontal>
}
/>
{config?.ide && (
<MenuItem
text={
<Layout.Horizontal spacing="small">
<OpenGitspaceButton ide={config?.ide} url={url} />
</Layout.Horizontal>
}
/>
)}
</Menu>
</Container>
)
}
export const RenderActions: Renderer<CellProps<OpenapiGetGitspaceResponse>> = ({ row }) => {
const details = row.original
return (
<Text
style={{ cursor: 'pointer' }}
icon={'Options'}
tooltip={<ActionMenu data={details} />}
tooltipProps={{
interactionKind: PopoverInteractionKind.HOVER,
position: Position.BOTTOM_RIGHT,
usePortal: false,
popoverClassName: css.popover
}}
/>
)
}
export const ListGitspaces = ({ data }: { data: OpenapiGetGitspaceResponse[] }) => {
return (
<Container>
{data && (
<TableV2<OpenapiGetGitspaceResponse>
className={css.table}
columns={[
{
id: 'gitspaces',
Header: 'Gitspaces',
Cell: RenderGitspaceName
},
{
id: 'repository',
Header: 'REPOSITORY & BRANCH',
Cell: RenderRepository
},
{
id: 'cpuusage',
Header: 'CPU Usage',
Cell: RenderCPUUsage
},
{
id: 'storageusage',
Header: 'Storage Usage',
Cell: RenderStorageUsage
},
{
id: 'lastactivity',
Header: 'Last Active',
Cell: RenderLastActivity
},
{
id: 'action',
Cell: RenderActions
}
]}
data={data}
/>
)}
</Container>
)
}

View File

@ -0,0 +1,60 @@
/*
* 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.
*/
/*
* 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.
*/
export enum GitspaceStatus {
RUNNING = 'RUNNING',
STOPPED = 'STOPPED',
UNKNOWN = 'UNKNOWN',
ERROR = 'ERROR'
}
export enum IDEType {
VSCODE = 'VSCODE',
VSCODEWEB = 'VSCODEWEB'
}
export enum GitspaceActionType {
START = 'START',
STOP = 'STOP'
}
export enum GitspaceRegion {
USEast = 'US East',
USWest = 'US West',
Europe = 'Europe',
Australia = 'Australia'
}
export enum CodeRepoAccessType {
PRIVATE = 'PRIVATE',
PUBLIC = 'PUBLIC'
}

View File

@ -0,0 +1,47 @@
/*
* 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 { useParams } from 'react-router-dom'
import { useAppContext } from 'AppContext'
import { useGetSpaceParam } from '../../hooks/useGetSpaceParam'
export interface CDEPathParams {
accountIdentifier: string
orgIdentifier: string
projectIdentifier: string
}
export const useGetCDEAPIParams = (): CDEPathParams | { space: string } => {
const space = useGetSpaceParam()
const { standalone } = useAppContext()
const {
accountId: accountIdentifier,
orgIdentifier,
projectIdentifier
} = useParams<{
accountId: string
orgIdentifier: string
projectIdentifier: string
}>()
return standalone
? { space }
: {
accountIdentifier,
orgIdentifier,
projectIdentifier
}
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 48 33"><path fill="url(#a)" fill-rule="evenodd" d="M36.677 33H9.075a9.075 9.075 0 0 1-1.797-17.972.182.182 0 0 0 .146-.178C7.424 6.649 14.073 0 22.274 0c7.134 0 13.094 5.03 14.524 11.738a.86.86 0 0 0 .771.672c5.295.435 9.457 4.87 9.457 10.277 0 5.558-4.397 10.09-9.902 10.305V33h-.447ZM20.963 20.743l2.285-5.712.047-.117.564-1.412.58-1.449.757-1.892a.888.888 0 0 1 1.65.66l-1.102 2.754-.58 1.45-.081.202-.038.094-2.351 5.88-.735 1.835-2.22 5.55a.888.888 0 1 1-1.65-.66l2.048-5.119.826-2.064Zm-2.143-5.326Zm4.708-4.427c.18.02.283.032.283.03l-.298-.047.015.017Zm-7.538 5.459a.888.888 0 1 0-1.257-1.257l-3.553 3.553a.888.888 0 0 0 0 1.257l3.553 3.553a.888.888 0 0 0 1.257-1.256l-2.925-2.925 2.925-2.925Zm14.212-1.257a.889.889 0 0 0-1.257 1.257l2.925 2.925-2.925 2.925a.888.888 0 0 0 1.257 1.256l3.553-3.553a.889.889 0 0 0 0-1.256l-3.553-3.553Z" clip-rule="evenodd"/><defs><linearGradient id="a" x1="10.45" x2="29.767" y1="2.613" y2="39.038" gradientUnits="userSpaceOnUse"><stop stop-color="#21D0E0"/><stop offset="1" stop-color="#7B5AFF"/></linearGradient></defs></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 16"><path fill="#383946" fill-rule="evenodd" d="M8.226.85a.533.533 0 0 0-.451 0l-6.4 2.987a.533.533 0 0 0-.308.483v7.36c0 .207.12.396.308.483l6.4 2.987a.533.533 0 0 0 .45 0l6.4-2.987a.533.533 0 0 0 .309-.483V4.32a.533.533 0 0 0-.308-.483L8.226.85ZM8 3.367l-1.62-.689L8 1.922l1.621.756-1.62.69Zm.209 1.07 2.712-1.152 2.17 1.012L8 6.461 2.91 4.297l2.17-1.012 2.712 1.153a.533.533 0 0 0 .417 0Zm.325 2.956 5.333-2.267v3.332L11.82 9.4c-.378.174-.62.553-.62.97v2.216L8.533 13.83V7.393Zm3.733 4.694 1.6-.747V9.632l-1.6.736v1.72Zm-4.8-4.694v6.436l-2.664-1.243v-2.218c0-.416-.243-.795-.621-.969l-2.048-.942v-3.33l5.333 2.266ZM2.134 11.34l1.602.748v-1.72l-1.602-.737v1.71Z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 760 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 100 100"><mask id="a" width="100" height="100" x="0" y="0" mask-type="alpha" maskUnits="userSpaceOnUse"><path fill="#fff" fill-rule="evenodd" d="M70.912 99.317a6.223 6.223 0 0 0 4.96-.19l20.589-9.907A6.25 6.25 0 0 0 100 83.587V16.413a6.25 6.25 0 0 0-3.54-5.632L75.874.874a6.226 6.226 0 0 0-7.104 1.21L29.355 38.04 12.187 25.01a4.162 4.162 0 0 0-5.318.236l-5.506 5.009a4.168 4.168 0 0 0-.004 6.162L16.247 50 1.36 63.583a4.168 4.168 0 0 0 .004 6.162l5.506 5.01a4.162 4.162 0 0 0 5.318.236l17.168-13.032L68.77 97.917a6.217 6.217 0 0 0 2.143 1.4ZM75.015 27.3 45.11 50l29.906 22.701V27.3Z" clip-rule="evenodd"/></mask><g mask="url(#a)"><path fill="#0065A9" d="M96.461 10.796 75.857.876a6.23 6.23 0 0 0-7.107 1.207l-67.451 61.5a4.167 4.167 0 0 0 .004 6.162l5.51 5.009a4.167 4.167 0 0 0 5.32.236l81.228-61.62c2.725-2.067 6.639-.124 6.639 3.297v-.24a6.25 6.25 0 0 0-3.539-5.63Z"/><g filter="url(#b)"><path fill="#007ACC" d="m96.461 89.204-20.604 9.92a6.229 6.229 0 0 1-7.107-1.207l-67.451-61.5a4.167 4.167 0 0 1 .004-6.162l5.51-5.009a4.167 4.167 0 0 1 5.32-.236l81.228 61.62c2.725 2.067 6.639.124 6.639-3.297v.24a6.25 6.25 0 0 1-3.539 5.63Z"/></g><g filter="url(#c)"><path fill="#1F9CF0" d="M75.858 99.126a6.232 6.232 0 0 1-7.108-1.21c2.306 2.307 6.25.674 6.25-2.588V4.672c0-3.262-3.944-4.895-6.25-2.589a6.232 6.232 0 0 1 7.108-1.21l20.6 9.908A6.25 6.25 0 0 1 100 16.413v67.174a6.25 6.25 0 0 1-3.541 5.633l-20.601 9.906Z"/></g><path fill="url(#d)" fill-rule="evenodd" d="M70.851 99.317a6.224 6.224 0 0 0 4.96-.19L96.4 89.22a6.25 6.25 0 0 0 3.54-5.633V16.413a6.25 6.25 0 0 0-3.54-5.632L75.812.874a6.226 6.226 0 0 0-7.104 1.21L29.294 38.04 12.126 25.01a4.162 4.162 0 0 0-5.317.236l-5.507 5.009a4.168 4.168 0 0 0-.004 6.162L16.186 50 1.298 63.583a4.168 4.168 0 0 0 .004 6.162l5.507 5.009a4.162 4.162 0 0 0 5.317.236l17.168-13.03 39.414 35.958a6.218 6.218 0 0 0 2.143 1.4ZM74.954 27.3 45.048 50l29.906 22.701V27.3Z" clip-rule="evenodd" opacity=".25" style="mix-blend-mode:overlay"/></g><defs><filter id="b" width="116.727" height="92.246" x="-8.394" y="15.829" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset/><feGaussianBlur stdDeviation="4.167"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/><feBlend in2="BackgroundImageFix" mode="overlay" result="effect1_dropShadow"/><feBlend in="SourceGraphic" in2="effect1_dropShadow" result="shape"/></filter><filter id="c" width="47.917" height="116.151" x="60.417" y="-8.076" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset/><feGaussianBlur stdDeviation="4.167"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/><feBlend in2="BackgroundImageFix" mode="overlay" result="effect1_dropShadow"/><feBlend in="SourceGraphic" in2="effect1_dropShadow" result="shape"/></filter><linearGradient id="d" x1="49.939" x2="49.939" y1=".258" y2="99.742" gradientUnits="userSpaceOnUse"><stop stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient></defs></svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -0,0 +1,23 @@
/*
* 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.
*/
.main {
display: flex !important;
justify-content: center;
align-items: center;
text-align: center;
height: 80vh;
}

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 main: string

View File

@ -0,0 +1,66 @@
/*
* 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 { Breadcrumbs, Layout, Page } 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 Gitspace from '../../icons/Gitspace.svg?url'
import css from './GitspaceDetail.module.scss'
const GitspaceDetail = () => {
const { getString } = useStrings()
const space = useGetSpaceParam()
const { routes } = useAppContext()
const { gitspaceId = '' } = useParams<{ gitspaceId?: string }>()
return (
<>
<Page.Header
title=""
breadcrumbs={
<Layout.Horizontal spacing="small" flex={{ alignItems: 'center' }}>
<img src={Gitspace} height={20} width={20} style={{ marginRight: '5px' }} />
<Breadcrumbs
links={[
{
url: routes.toCDEGitspaces({ space }),
label: getString('cde.cloudDeveloperExperience')
},
{
url: routes.toCDEGitspaceDetail({ space, gitspaceId }),
label: `${getString('cde.gitpsaceDetail')} ${gitspaceId}`
}
]}
/>
</Layout.Horizontal>
}
/>
<Page.Body>
<Layout.Horizontal className={css.main} spacing="medium">
<GitspaceDetails />
<GitspaceLogs />
</Layout.Horizontal>
</Page.Body>
</>
)
}
export default GitspaceDetail

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,33 @@
/*
* 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.
*/
.main {
display: flex !important;
justify-content: center;
align-items: center;
text-align: center;
height: 70vh;
}
.gitspaceTitle {
h1 {
font-weight: bold !important;
}
p {
font-size: 16px !important;
color: #383946 !important;
}
}

View File

@ -0,0 +1,20 @@
/*
* 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 gitspaceTitle: string
export declare const main: string

View File

@ -0,0 +1,73 @@
/*
* 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 { Breadcrumbs, Container, Heading, Layout, Page, Text } from '@harnessio/uicore'
import { Color } from '@harnessio/design-system'
import { CreateGitspace } from 'cde/components/CreateGitspace/CreateGitspace'
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
import { useAppContext } from 'AppContext'
import { useStrings } from 'framework/strings'
import Gitspace from '../../icons/Gitspace.svg?url'
import css from './Gitspaces.module.scss'
const CreateGitspaceTitle = () => {
const { getString } = useStrings()
return (
<Container className={css.gitspaceTitle}>
<img src={Gitspace} width={42} height={42}></img>
<Layout.Vertical spacing="small">
<Heading color={Color.BLACK} level={1}>
{getString('cde.introText1')}
</Heading>
<Text>{getString('cde.introText2')}</Text>
<Text>{getString('cde.introText3')}</Text>
</Layout.Vertical>
</Container>
)
}
const Gitspaces = () => {
const space = useGetSpaceParam()
const { getString } = useStrings()
const { routes } = useAppContext()
return (
<>
<Page.Header
title=""
breadcrumbs={
<Layout.Horizontal spacing="small" flex={{ alignItems: 'center' }}>
<img src={Gitspace} height={20} width={20} style={{ marginRight: '5px' }} />
<Breadcrumbs
links={[
{ url: routes.toCDEGitspaces({ space }), label: getString('cde.cloudDeveloperExperience') },
{ url: routes.toCDEGitspaces({ space }), label: getString('cde.createGitspace') }
]}
/>
</Layout.Horizontal>
}
/>
<Page.Body>
<Layout.Vertical className={css.main} spacing="medium">
<CreateGitspaceTitle />
<CreateGitspace />
</Layout.Vertical>
</Page.Body>
</>
)
}
export default Gitspaces

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.
*/
.main {
margin: var(--spacing-xxlarge) !important;
}

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 main: string

View File

@ -0,0 +1,110 @@
/*
* 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, { useEffect } from 'react'
import {
Breadcrumbs,
Text,
Button,
ButtonVariation,
ExpandingSearchInput,
Layout,
Page,
Container
} from '@harnessio/uicore'
import { FontVariation } from '@harnessio/design-system'
import { useHistory } from 'react-router-dom'
import { ListGitspaces } from 'cde/components/ListGitspaces/ListGitspaces'
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
import { OpenapiGetGitspaceResponse, useListGitspaces } from 'services/cde'
import { getErrorMessage } from 'utils/Utils'
import { useAppContext } from 'AppContext'
import { useStrings } from 'framework/strings'
import Gitspace from '../../icons/Gitspace.svg?url'
import noSpace from '../../images/no-gitspace.svg?url'
import css from './GitspacesListing.module.scss'
const GitspacesListing = () => {
const space = useGetSpaceParam()
const history = useHistory()
const { getString } = useStrings()
const { routes } = useAppContext()
const { data, loading, error, refetch } = useListGitspaces({
accountIdentifier: space?.split('/')[0],
orgIdentifier: space?.split('/')[1],
projectIdentifier: space?.split('/')[2]
})
useEffect(() => {
if (!data && !loading) {
history.push(routes.toCDEGitspacesCreate({ space }))
}
}, [data, loading])
return (
<>
<Page.Header
title=""
breadcrumbs={
<Layout.Horizontal spacing="small" flex={{ alignItems: 'center' }}>
<img src={Gitspace} height={20} width={20} style={{ marginRight: '5px' }} />
<Breadcrumbs
links={[
{ url: routes.toCDEGitspaces({ space }), label: getString('cde.cloudDeveloperExperience') },
{ url: routes.toCDEGitspaces({ space }), label: getString('cde.createGitspace') }
]}
/>
</Layout.Horizontal>
}
/>
<Container className={css.main}>
<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}>
{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>
}
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')}
/>
)
}}>
<ExpandingSearchInput width={'50%'} alwaysExpanded />
<ListGitspaces data={data as OpenapiGetGitspaceResponse[]} />
</Page.Body>
</Layout.Vertical>
</Container>
</>
)
}
export default GitspacesListing

View File

@ -0,0 +1,84 @@
/*
* 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.
*/
export const listingMock = [
{
id: 'gs8',
url: '',
status: 'STOPPED',
resource_usage: '',
created: 1716371699104,
last_used: 0,
total_time_used: 0,
tracked_changes: '',
access_key: '',
access_type: '',
machine_user: '',
config: {
id: 'gs8',
name: 'my test gitspace',
prebuild_repo_id: 'string',
ide: 'VSCODEWEB',
infra_provider_resource_id: 'gs8',
code_repo_id: '',
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',
created: 1716371699104,
updated: 1716371699104,
metadata: null,
status_code: ''
},
code_server_password: '',
ssh_key: ''
},
{
id: 'gs9',
url: '',
status: 'RUNNING',
resource_usage: '',
created: 1716371864123,
last_used: 0,
total_time_used: 0,
tracked_changes: '',
access_key: '',
access_type: '',
machine_user: '',
config: {
id: 'gs9',
name: 'my test gitspace',
prebuild_repo_id: 'string',
ide: 'VSCODE',
infra_provider_resource_id: 'gs9',
code_repo_id: '',
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',
created: 1716371864123,
updated: 1716371864123,
metadata: null,
status_code: ''
},
code_server_password: '',
ssh_key: ''
}
]

View File

@ -233,7 +233,7 @@ const LogTerminal: React.FC<LogViewerProps> = ({
)
}
const lineElement = (line = '') => {
export const lineElement = (line = '') => {
const element = document.createElement('pre')
element.className = css.line

View File

@ -136,6 +136,58 @@ export interface StringsMap {
cancelImport: string
cancelImportConfirm: string
cancelledImport: string
'cde.branchPlaceholder': string
'cde.cloudDeveloperExperience': string
'cde.createGitspace': string
'cde.createRepo': string
'cde.details.actions': string
'cde.details.fetchingGitspace': string
'cde.details.fetchingLogs': string
'cde.details.gitspaceRunning': string
'cde.details.gitspaceStopped': string
'cde.details.goToDashboard': string
'cde.details.logsFailed': string
'cde.details.noData': string
'cde.details.noLogsFound': string
'cde.details.openBrowser': string
'cde.details.openEditor': string
'cde.details.provisioningGitspace': string
'cde.details.startGitspace': string
'cde.details.stopGitspace': string
'cde.details.stopProvising': string
'cde.gitpsaceDetail': string
'cde.gitspaces': string
'cde.hours': string
'cde.ide.browser': string
'cde.ide.desktop': string
'cde.ide.ide': string
'cde.ide.openBrowser': string
'cde.ide.openVSCode': string
'cde.ide.selectIDE': string
'cde.ide.vsCode': string
'cde.introText1': string
'cde.introText2': string
'cde.introText3': string
'cde.logs': string
'cde.machine': string
'cde.manageGitspaces': string
'cde.na': string
'cde.newGitspace': string
'cde.noChange': string
'cde.noData': string
'cde.noGitspaces': string
'cde.noRepo': string
'cde.or': string
'cde.region': string
'cde.repository.continueWith': string
'cde.repository.pasteRepo': string
'cde.repository.pasterRepoSubtext': string
'cde.repository.privateRepoWarning': string
'cde.repository.publicRepo': string
'cde.repository.repo': string
'cde.repository.repositoryURL': string
'cde.repository.selectRepository': string
'cde.used': string
changePassword: string
changePasswordSuccesfully: string
changeRepoVis: string

1
web/src/global.d.ts vendored
View File

@ -67,6 +67,7 @@ declare interface Window {
apiUrl: string
harnessNameSpace: string
bugsnagClient?: any
STRIP_CDE_PREFIX?: boolean
STRIP_CODE_PREFIX?: boolean
Sanitizer: any
}

View File

@ -1052,3 +1052,59 @@ upload: Upload
unorderedList: Unordered list
checklist: Check list
code: Code
cde:
branchPlaceholder: Branch
introText1: Get ready to code in seconds
introText2: Isolated cloud development environments with your favorite editor
introText3: Connect in seconds with a repository
cloudDeveloperExperience: Cloud Developer Experience
createGitspace: Create Gitspace
gitspaces: Gitspaces
noRepo: Dont have a Git repo?
createRepo: Create a repo in Harness
newGitspace: + New Gitspace
manageGitspaces: Manage Gitspaces
noGitspaces: You have not created any Gitspace yet
gitpsaceDetail: Gitpsace Detail
machine: Machine
region: Region
or: OR
logs: Logs
noData: No Data
noChange: No Change
used: Used
hours: Hours
na: NA
details:
actions: More Actions
openEditor: Open VS Code Editor
openBrowser: Open VS Code Online
goToDashboard: Go To Dashboard
startGitspace: Start Gitspace
stopProvising: Stop Provising
noData: No Data for Gitspace
provisioningGitspace: Provisioning the Gitspace...
gitspaceStopped: Gitspace is stopped
gitspaceRunning: Gitspace is running
stopGitspace: Stop Gitspace
fetchingGitspace: Fetching Gitspace Details
fetchingLogs: Fetching gitspace logs
logsFailed: Gitspace logs api failed
noLogsFound: No gitspace logs found
repository:
repo: Repository
selectRepository: Select Repository
pasteRepo: Paste a Git URL to create Gitspace
pasterRepoSubtext: You can use any public Git repository to create a Gitspace
privateRepoWarning: Repo URL is of Private repository
publicRepo: You can use any public Git repository to create a Gitspace
continueWith: Continue with
repositoryURL: Repository URL
ide:
browser: Browser
desktop: Desktop
ide: IDE
selectIDE: Select IDE
vsCode: VS Code
openVSCode: Open in VS Code Desktop
openBrowser: Open in Browser

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
allowpaths: ['*']
operationIdOverrides: {}

View File

@ -0,0 +1,883 @@
openapi: 3.0.0
info:
title: API Specification
version: 0.0.0
servers:
- url: gateway/cde/api/v1
security:
- bearerAuth: []
x-api-key: []
paths:
/accounts/{accountIdentifier}/orgs/{orgIdentifier}/projects/{projectIdentifier}/coderepository:
post:
operationId: getCodeRepository
parameters:
- description: account identifier.
in: path
name: accountIdentifier
required: true
schema:
type: string
- description: org identifier.
in: path
name: orgIdentifier
required: true
schema:
type: string
- description: project identifier.
in: path
name: projectIdentifier
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/OpenapiGetCodeRepositoryRequest'
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/OpenapiGetCodeRepositoryResponse'
description: OK
summary: Get Code Repository
tags:
- coderepositories
/accounts/{accountIdentifier}/orgs/{orgIdentifier}/projects/{projectIdentifier}/gitspaces/{gitspaceIdentifier}:
delete:
operationId: deleteGitspace
parameters:
- description: account identifier.
in: path
name: accountIdentifier
required: true
schema:
type: string
- description: org identifier.
in: path
name: orgIdentifier
required: true
schema:
type: string
- description: project identifier.
in: path
name: projectIdentifier
required: true
schema:
type: string
- description: gitspace identifier.
in: path
name: gitspaceIdentifier
required: true
schema:
type: string
responses:
"204":
description: No Content
summary: Delete gitspace
tags:
- gitspaces
get:
operationId: getGitspace
parameters:
- description: account identifier.
in: path
name: accountIdentifier
required: true
schema:
type: string
- description: org identifier.
in: path
name: orgIdentifier
required: true
schema:
type: string
- description: project identifier.
in: path
name: projectIdentifier
required: true
schema:
type: string
- description: gitspace identifier.
in: path
name: gitspaceIdentifier
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/OpenapiGetGitspaceResponse'
description: OK
summary: Get gitspace
tags:
- gitspaces
/accounts/{accountIdentifier}/orgs/{orgIdentifier}/projects/{projectIdentifier}/gitspaces/{gitspaceIdentifier}/action:
post:
operationId: gitspaceAction
parameters:
- description: account identifier.
in: path
name: accountIdentifier
required: true
schema:
type: string
- description: org identifier.
in: path
name: orgIdentifier
required: true
schema:
type: string
- description: project identifier.
in: path
name: projectIdentifier
required: true
schema:
type: string
- description: gitspace identifier.
in: path
name: gitspaceIdentifier
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/OpenapiGitspaceActionRequest'
responses:
"200":
description: OK
summary: Gitspace action
tags:
- gitspaces
/accounts/{accountIdentifier}/orgs/{orgIdentifier}/projects/{projectIdentifier}/gitspaces/{gitspaceIdentifier}/events:
post:
operationId: createGitspaceEvent
parameters:
- description: account identifier.
in: path
name: accountIdentifier
required: true
schema:
type: string
- description: org identifier.
in: path
name: orgIdentifier
required: true
schema:
type: string
- description: project identifier.
in: path
name: projectIdentifier
required: true
schema:
type: string
- description: gitspace identifier.
in: path
name: gitspaceIdentifier
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/OpenapiCreateGitspaceInstanceEventRequest'
responses:
"200":
description: OK
summary: Create gitspace instance event
tags:
- gitspaces
/accounts/{accountIdentifier}/orgs/{orgIdentifier}/projects/{projectIdentifier}/gitspaces/{gitspaceIdentifier}/logs:
get:
operationId: getGitspaceInstanceLogs
parameters:
- description: account identifier.
in: path
name: accountIdentifier
required: true
schema:
type: string
- description: org identifier.
in: path
name: orgIdentifier
required: true
schema:
type: string
- description: project identifier.
in: path
name: projectIdentifier
required: true
schema:
type: string
- description: gitspace identifier.
in: path
name: gitspaceIdentifier
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/OpenapiGetGitspaceLogsResponse'
description: OK
summary: Get gitspace instance logs
tags:
- gitspaces
/accounts/{accountIdentifier}/orgs/{orgIdentifier}/projects/{projectIdentifier}/infraproviders:
get:
operationId: listInfraProviders
parameters:
- description: account identifier.
in: path
name: accountIdentifier
required: true
schema:
type: string
- description: org identifier.
in: path
name: orgIdentifier
required: true
schema:
type: string
- description: project identifier.
in: path
name: projectIdentifier
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/OpenapiCreateInfraProviderResponse'
type: array
description: OK
summary: List infraproviders
tags:
- infraproviders
post:
operationId: createInfraProvider
parameters:
- description: account identifier.
in: path
name: accountIdentifier
required: true
schema:
type: string
- description: org identifier.
in: path
name: orgIdentifier
required: true
schema:
type: string
- description: project identifier.
in: path
name: projectIdentifier
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/OpenapiCreateInfraProviderRequest'
responses:
"201":
content:
application/json:
schema:
$ref: '#/components/schemas/OpenapiCreateInfraProviderResponse'
description: Created
summary: Create InfraProvider
tags:
- infraproviders
/accounts/{accountIdentifier}/orgs/{orgIdentifier}/projects/{projectIdentifier}/infraproviders/{infraProviderConfigIdentifier}:
delete:
operationId: deleteInfraProvider
parameters:
- description: account identifier.
in: path
name: accountIdentifier
required: true
schema:
type: string
- description: org identifier.
in: path
name: orgIdentifier
required: true
schema:
type: string
- description: project identifier.
in: path
name: projectIdentifier
required: true
schema:
type: string
- description: infra Provider Config Identifier.
in: path
name: infraProviderConfigIdentifier
required: true
schema:
type: string
responses:
"204":
description: No Content
summary: Delete infraprovider
tags:
- infraproviders
? /accounts/{accountIdentifier}/orgs/{orgIdentifier}/projects/{projectIdentifier}/infraproviders/{infraProviderConfigIdentifier}/resources
: get:
operationId: listInfraProviderResources
parameters:
- description: account identifier.
in: path
name: accountIdentifier
required: true
schema:
type: string
- description: org identifier.
in: path
name: orgIdentifier
required: true
schema:
type: string
- description: project identifier.
in: path
name: projectIdentifier
required: true
schema:
type: string
- description: infra Provider Config Identifier.
in: path
name: infraProviderConfigIdentifier
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/OpenapiListInfraProviderResourceResponse'
description: OK
summary: List infraProvider Resources
tags:
- infraproviders
post:
operationId: createInfraProviderResource
parameters:
- description: account identifier.
in: path
name: accountIdentifier
required: true
schema:
type: string
- description: org identifier.
in: path
name: orgIdentifier
required: true
schema:
type: string
- description: project identifier.
in: path
name: projectIdentifier
required: true
schema:
type: string
- description: infra Provider Config Identifier.
in: path
name: infraProviderConfigIdentifier
required: true
schema:
type: string
responses:
"201":
content:
application/json:
schema:
$ref: '#/components/schemas/OpenapiCreateInfraProviderResourceResponse'
description: Created
summary: Create InfraProvider Resource
tags:
- infraproviders
? /accounts/{accountIdentifier}/orgs/{orgIdentifier}/projects/{projectIdentifier}/infraproviders/{infraProviderConfigIdentifier}/template
: post:
operationId: createInfraProviderTemplate
parameters:
- description: account identifier.
in: path
name: accountIdentifier
required: true
schema:
type: string
- description: org identifier.
in: path
name: orgIdentifier
required: true
schema:
type: string
- description: project identifier.
in: path
name: projectIdentifier
required: true
schema:
type: string
- description: infra Provider Config Identifier.
in: path
name: infraProviderConfigIdentifier
required: true
schema:
type: string
responses:
"201":
content:
application/json:
schema:
$ref: '#/components/schemas/OpenapiCreateInfraProviderTemplateResponse'
description: Created
summary: Create InfraProvider Template
tags:
- infraproviders
/accounts/{accountIdentifier}/orgs/{orgIdentifier}/projects/{projectIdentifier}gitspaces:
get:
operationId: listGitspaces
parameters:
- description: account identifier.
in: path
name: accountIdentifier
required: true
schema:
type: string
- description: org identifier.
in: path
name: orgIdentifier
required: true
schema:
type: string
- description: project identifier.
in: path
name: projectIdentifier
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/OpenapiGetGitspaceResponse'
type: array
description: OK
summary: List gitspaces
tags:
- gitspaces
post:
operationId: createGitspace
parameters:
- description: account identifier.
in: path
name: accountIdentifier
required: true
schema:
type: string
- description: org identifier.
in: path
name: orgIdentifier
required: true
schema:
type: string
- description: project identifier.
in: path
name: projectIdentifier
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/OpenapiCreateGitspaceRequest'
responses:
"201":
content:
application/json:
schema:
$ref: '#/components/schemas/OpenapiCreateGitspaceResponse'
description: Created
summary: Create gitspace
tags:
- gitspaces
/accounts/{accountIdentifier}gitspaces:
get:
operationId: listGitspacesForAccount
parameters:
- description: account identifier.
in: path
name: accountIdentifier
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/OpenapiGetGitspaceResponse'
type: array
description: OK
summary: List gitspaces for account
tags:
- gitspaces
components:
schemas:
EnumCodeRepoAccessType:
enum:
- PRIVATE
- PUBLIC
type: string
EnumCodeRepoType:
enum:
- GITHUB
- GITLAB
- HARNESS_CODE
- BITBUCKET
- UNKNOWN
type: string
EnumGitspaceAccessType:
enum:
- JWT_TOKEN
- PASSWORD
type: string
EnumGitspaceActionType:
enum:
- START
- STOP
type: string
EnumGitspaceStateType:
enum:
- RUNNING
- STOPPED
- UNKNOWN
- ERROR
type: string
EnumIDEType:
enum:
- VSCODE
- VSCODEWEB
type: string
EnumProviderType:
enum:
- HARNESS_GCP
- K8S
- HARNESS_OVHCLOUD
- DOCKER
type: string
OpenapiCreateGitspaceInstanceEventRequest:
properties:
state:
$ref: '#/components/schemas/EnumGitspaceStateType'
type: object
OpenapiCreateGitspaceRequest:
properties:
branch:
type: string
code_repo_id:
type: string
code_repo_type:
$ref: '#/components/schemas/EnumCodeRepoType'
code_repo_url:
type: string
devcontainer_path:
type: string
id:
type: string
ide:
$ref: '#/components/schemas/EnumIDEType'
infra_provider_resource_id:
type: string
metadata:
additionalProperties:
type: string
nullable: true
type: object
name:
type: string
prebuild_repo_id:
type: string
type: object
OpenapiCreateGitspaceResponse:
properties:
access_key:
type: string
access_type:
$ref: '#/components/schemas/EnumGitspaceAccessType'
code_server_password:
type: string
config:
$ref: '#/components/schemas/TypesGitspaceConfigResponse'
created:
type: integer
id:
type: string
last_used:
type: integer
machine_user:
type: string
resource_usage:
type: string
ssh_key:
type: string
status:
$ref: '#/components/schemas/EnumGitspaceStateType'
total_time_used:
type: integer
tracked_changes:
type: string
url:
type: string
type: object
OpenapiCreateInfraProviderRequest:
properties:
id:
type: string
metadata:
additionalProperties:
type: string
nullable: true
type: object
name:
type: string
type:
$ref: '#/components/schemas/EnumProviderType'
type: object
OpenapiCreateInfraProviderResourceResponse:
properties:
resources:
items:
$ref: '#/components/schemas/TypesInfraProviderResourceRequest'
nullable: true
type: array
type: object
OpenapiCreateInfraProviderResponse:
properties:
created:
type: integer
id:
type: string
metadata:
type: string
name:
type: string
scope:
type: string
type:
$ref: '#/components/schemas/EnumProviderType'
updated:
type: integer
type: object
OpenapiCreateInfraProviderTemplateResponse:
properties:
created:
type: integer
data:
type: string
description:
type: string
identifier:
type: string
space_id:
type: integer
updated:
type: integer
type: object
OpenapiGetCodeRepositoryRequest:
properties:
connector_ref:
type: string
url:
type: string
type: object
OpenapiGetCodeRepositoryResponse:
properties:
access_type:
$ref: '#/components/schemas/EnumCodeRepoAccessType'
branch:
type: string
repo_type:
$ref: '#/components/schemas/EnumCodeRepoType'
url:
type: string
type: object
OpenapiGetGitspaceLogsResponse:
nullable: true
type: string
OpenapiGetGitspaceResponse:
properties:
access_key:
type: string
access_type:
$ref: '#/components/schemas/EnumGitspaceAccessType'
code_server_password:
type: string
config:
$ref: '#/components/schemas/TypesGitspaceConfigResponse'
created:
type: integer
id:
type: string
last_used:
type: integer
machine_user:
type: string
resource_usage:
type: string
ssh_key:
type: string
status:
$ref: '#/components/schemas/EnumGitspaceStateType'
total_time_used:
type: integer
tracked_changes:
type: string
url:
type: string
type: object
OpenapiGitspaceActionRequest:
properties:
action:
$ref: '#/components/schemas/EnumGitspaceActionType'
type: object
OpenapiListInfraProviderResourceResponse:
items:
$ref: '#/components/schemas/TypesInfraProviderResourceResponse'
nullable: true
type: array
TypesGitspaceConfigResponse:
properties:
branch:
type: string
code_repo_id:
type: string
code_repo_type:
$ref: '#/components/schemas/EnumCodeRepoType'
code_repo_url:
type: string
created:
type: integer
devcontainer_path:
type: string
id:
type: string
ide:
$ref: '#/components/schemas/EnumIDEType'
infra_provider_resource_id:
type: string
metadata:
additionalProperties:
type: string
nullable: true
type: object
name:
type: string
prebuild_repo_id:
type: string
scope:
type: string
status_code:
type: string
updated:
type: integer
user_id:
type: string
type: object
TypesInfraProviderResourceRequest:
properties:
cpu:
type: string
disk:
type: string
gateway_host:
type: string
gateway_port:
type: string
id:
type: string
infra_provider_type:
$ref: '#/components/schemas/EnumProviderType'
memory:
type: string
name:
type: string
network:
type: string
opentofu_params:
additionalProperties:
type: string
nullable: true
type: object
region:
items:
type: string
nullable: true
type: array
scope:
type: string
template_id:
type: integer
type: object
TypesInfraProviderResourceResponse:
properties:
cpu:
type: string
created:
type: integer
disk:
type: string
gateway_host:
type: string
gateway_port:
type: string
id:
type: string
infra_provider_config_id:
type: string
infra_provider_type:
$ref: '#/components/schemas/EnumProviderType'
memory:
type: string
name:
type: string
network:
type: string
opentofu_params:
type: string
region:
type: string
scope:
type: string
template_id:
type: integer
updated:
type: integer
type: object
securitySchemes:
bearerAuth:
scheme: bearer
type: http
x-api-key:
in: header
name: x-api-key
type: apiKey

View File

@ -24,6 +24,10 @@ export const getConfig = (str: string): string => {
str = str.replace(/^code\//, '')
}
if (window.STRIP_CDE_PREFIX) {
str = str.replace(/^cde\//, '')
}
return window.apiUrl ? `${window.apiUrl}/${str}` : `${window.harnessNameSpace || ''}/${str}`
}