mirror of
https://github.com/harness/drone.git
synced 2025-05-13 23:50:47 +08:00
Merge branch 'main' of github.com:harness/gitness
This commit is contained in:
commit
df76498bf5
@ -1,17 +1,17 @@
|
|||||||
const path = require('path');
|
const path = require('path')
|
||||||
|
|
||||||
const webpack = require('webpack')
|
const webpack = require('webpack')
|
||||||
const {
|
const {
|
||||||
container: { ModuleFederationPlugin },
|
container: { ModuleFederationPlugin },
|
||||||
DefinePlugin
|
DefinePlugin
|
||||||
} = require('webpack');
|
} = require('webpack')
|
||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||||
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
|
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin')
|
||||||
const GenerateStringTypesPlugin = require('../scripts/webpack/GenerateStringTypesPlugin').GenerateStringTypesPlugin
|
const GenerateStringTypesPlugin = require('../scripts/webpack/GenerateStringTypesPlugin').GenerateStringTypesPlugin
|
||||||
const { RetryChunkLoadPlugin } = require('webpack-retry-chunk-load-plugin')
|
const { RetryChunkLoadPlugin } = require('webpack-retry-chunk-load-plugin')
|
||||||
|
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin')
|
||||||
const moduleFederationConfig = require('./moduleFederation.config');
|
const moduleFederationConfig = require('./moduleFederation.config')
|
||||||
const CONTEXT = process.cwd();
|
const CONTEXT = process.cwd()
|
||||||
|
|
||||||
const DEV = process.env.NODE_ENV === 'development'
|
const DEV = process.env.NODE_ENV === 'development'
|
||||||
const ON_PREM = `${process.env.ON_PREM}` === 'true'
|
const ON_PREM = `${process.env.ON_PREM}` === 'true'
|
||||||
@ -150,8 +150,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.mjs', '.js', '.ts', '.tsx', '.json', '.ttf', '.scss'],
|
extensions: ['.mjs', '.js', '.ts', '.tsx', '.json', '.ttf', '.scss'],
|
||||||
plugins: [
|
plugins: [new TsconfigPathsPlugin()]
|
||||||
new TsconfigPathsPlugin()]
|
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new ModuleFederationPlugin(moduleFederationConfig),
|
new ModuleFederationPlugin(moduleFederationConfig),
|
||||||
@ -164,5 +163,71 @@ module.exports = {
|
|||||||
new RetryChunkLoadPlugin({
|
new RetryChunkLoadPlugin({
|
||||||
maxRetries: 2
|
maxRetries: 2
|
||||||
}),
|
}),
|
||||||
|
new MonacoWebpackPlugin({
|
||||||
|
// available options are documented at https://github.com/Microsoft/monaco-editor-webpack-plugin#options
|
||||||
|
languages: [
|
||||||
|
'abap',
|
||||||
|
'apex',
|
||||||
|
'azcli',
|
||||||
|
'bat',
|
||||||
|
'cameligo',
|
||||||
|
'clojure',
|
||||||
|
'coffee',
|
||||||
|
'cpp',
|
||||||
|
'csharp',
|
||||||
|
'csp',
|
||||||
|
'css',
|
||||||
|
'dockerfile',
|
||||||
|
'fsharp',
|
||||||
|
'go',
|
||||||
|
'graphql',
|
||||||
|
'handlebars',
|
||||||
|
'html',
|
||||||
|
'ini',
|
||||||
|
'java',
|
||||||
|
'javascript',
|
||||||
|
'json',
|
||||||
|
'kotlin',
|
||||||
|
'less',
|
||||||
|
'lua',
|
||||||
|
'markdown',
|
||||||
|
'mips',
|
||||||
|
'msdax',
|
||||||
|
'mysql',
|
||||||
|
'objective-c',
|
||||||
|
'pascal',
|
||||||
|
'pascaligo',
|
||||||
|
'perl',
|
||||||
|
'pgsql',
|
||||||
|
'php',
|
||||||
|
'postiats',
|
||||||
|
'powerquery',
|
||||||
|
'powershell',
|
||||||
|
'pug',
|
||||||
|
'python',
|
||||||
|
'r',
|
||||||
|
'razor',
|
||||||
|
'redis',
|
||||||
|
'redshift',
|
||||||
|
'restructuredtext',
|
||||||
|
'ruby',
|
||||||
|
'rust',
|
||||||
|
'sb',
|
||||||
|
'scheme',
|
||||||
|
'scss',
|
||||||
|
'shell',
|
||||||
|
'solidity',
|
||||||
|
'sophia',
|
||||||
|
'sql',
|
||||||
|
'st',
|
||||||
|
'swift',
|
||||||
|
'tcl',
|
||||||
|
'twig',
|
||||||
|
'typescript',
|
||||||
|
'vb',
|
||||||
|
'xml',
|
||||||
|
'yaml'
|
||||||
|
]
|
||||||
|
})
|
||||||
]
|
]
|
||||||
};
|
}
|
||||||
|
@ -12,7 +12,6 @@ const {
|
|||||||
WatchIgnorePlugin,
|
WatchIgnorePlugin,
|
||||||
container: { ModuleFederationPlugin }
|
container: { ModuleFederationPlugin }
|
||||||
} = require('webpack')
|
} = require('webpack')
|
||||||
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin')
|
|
||||||
const commonConfig = require('./webpack.common')
|
const commonConfig = require('./webpack.common')
|
||||||
|
|
||||||
const baseUrl = process.env.BASE_URL ?? 'https://qa.harness.io/gateway'
|
const baseUrl = process.env.BASE_URL ?? 'https://qa.harness.io/gateway'
|
||||||
@ -61,72 +60,6 @@ const devConfig = {
|
|||||||
new DefinePlugin({
|
new DefinePlugin({
|
||||||
'process.env': '{}', // required for @blueprintjs/core
|
'process.env': '{}', // required for @blueprintjs/core
|
||||||
__DEV__: DEV
|
__DEV__: DEV
|
||||||
}),
|
|
||||||
new MonacoWebpackPlugin({
|
|
||||||
// available options are documented at https://github.com/Microsoft/monaco-editor-webpack-plugin#options
|
|
||||||
languages: [
|
|
||||||
'abap',
|
|
||||||
'apex',
|
|
||||||
'azcli',
|
|
||||||
'bat',
|
|
||||||
'cameligo',
|
|
||||||
'clojure',
|
|
||||||
'coffee',
|
|
||||||
'cpp',
|
|
||||||
'csharp',
|
|
||||||
'csp',
|
|
||||||
'css',
|
|
||||||
'dockerfile',
|
|
||||||
'fsharp',
|
|
||||||
'go',
|
|
||||||
'graphql',
|
|
||||||
'handlebars',
|
|
||||||
'html',
|
|
||||||
'ini',
|
|
||||||
'java',
|
|
||||||
'javascript',
|
|
||||||
'json',
|
|
||||||
'kotlin',
|
|
||||||
'less',
|
|
||||||
'lua',
|
|
||||||
'markdown',
|
|
||||||
'mips',
|
|
||||||
'msdax',
|
|
||||||
'mysql',
|
|
||||||
'objective-c',
|
|
||||||
'pascal',
|
|
||||||
'pascaligo',
|
|
||||||
'perl',
|
|
||||||
'pgsql',
|
|
||||||
'php',
|
|
||||||
'postiats',
|
|
||||||
'powerquery',
|
|
||||||
'powershell',
|
|
||||||
'pug',
|
|
||||||
'python',
|
|
||||||
'r',
|
|
||||||
'razor',
|
|
||||||
'redis',
|
|
||||||
'redshift',
|
|
||||||
'restructuredtext',
|
|
||||||
'ruby',
|
|
||||||
'rust',
|
|
||||||
'sb',
|
|
||||||
'scheme',
|
|
||||||
'scss',
|
|
||||||
'shell',
|
|
||||||
'solidity',
|
|
||||||
'sophia',
|
|
||||||
'sql',
|
|
||||||
'st',
|
|
||||||
'swift',
|
|
||||||
'tcl',
|
|
||||||
'twig',
|
|
||||||
'typescript',
|
|
||||||
'vb',
|
|
||||||
'xml',
|
|
||||||
'yaml'
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
// new ForkTsCheckerWebpackPlugin()
|
// new ForkTsCheckerWebpackPlugin()
|
||||||
// new WatchIgnorePlugin({
|
// new WatchIgnorePlugin({
|
||||||
|
102
web/src/components/SourceCodeEditor/MonacoSourceCodeEditor.tsx
Normal file
102
web/src/components/SourceCodeEditor/MonacoSourceCodeEditor.tsx
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import React, { useEffect } from 'react'
|
||||||
|
import { Container } from '@harness/uicore'
|
||||||
|
import type monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'
|
||||||
|
import MonacoEditor from 'react-monaco-editor'
|
||||||
|
import { noop } from 'lodash-es'
|
||||||
|
import type { SourceCodeEditorProps } from 'utils/Utils'
|
||||||
|
|
||||||
|
export const MonacoEditorOptions = {
|
||||||
|
ignoreTrimWhitespace: true,
|
||||||
|
minimap: { enabled: false },
|
||||||
|
codeLens: false,
|
||||||
|
scrollBeyondLastLine: false,
|
||||||
|
smartSelect: false,
|
||||||
|
tabSize: 2,
|
||||||
|
insertSpaces: true,
|
||||||
|
overviewRulerBorder: false,
|
||||||
|
automaticLayout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const diagnosticsOptions = {
|
||||||
|
noSemanticValidation: true,
|
||||||
|
noSyntaxValidation: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const compilerOptions = {
|
||||||
|
jsx: 'react',
|
||||||
|
noLib: true,
|
||||||
|
allowNonTsExtensions: true
|
||||||
|
}
|
||||||
|
|
||||||
|
function autoAdjustEditorHeight(editor: monacoEditor.editor.IStandaloneCodeEditor) {
|
||||||
|
// Adjust editor height based on its content
|
||||||
|
// https://github.com/microsoft/monaco-editor/issues/794#issuecomment-427092969
|
||||||
|
const LINE_HEIGHT = 18
|
||||||
|
const CONTAINER_GUTTER = 10
|
||||||
|
const editorNode = editor.getDomNode() as HTMLElement
|
||||||
|
const codeContainer = editorNode.getElementsByClassName('view-lines')[0]
|
||||||
|
let prevLineCount = 0
|
||||||
|
const adjustHeight = (): void => {
|
||||||
|
const _height =
|
||||||
|
codeContainer.childElementCount > prevLineCount
|
||||||
|
? (codeContainer as HTMLElement).offsetHeight // unfold
|
||||||
|
: codeContainer.childElementCount * LINE_HEIGHT + CONTAINER_GUTTER // fold
|
||||||
|
prevLineCount = codeContainer.childElementCount
|
||||||
|
|
||||||
|
editorNode.style.height = Math.max(_height, 100) + 'px'
|
||||||
|
editor.layout()
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(adjustHeight, 0)
|
||||||
|
editor.onDidChangeModelDecorations(() => setTimeout(adjustHeight, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
const toOnOff = (flag: boolean) => (flag ? 'on' : 'off')
|
||||||
|
|
||||||
|
export default function MonacoSourceCodeEditor({
|
||||||
|
source,
|
||||||
|
language = 'plaintext',
|
||||||
|
lineNumbers = true,
|
||||||
|
readOnly = false,
|
||||||
|
className,
|
||||||
|
height,
|
||||||
|
autoHeight,
|
||||||
|
wordWrap = true,
|
||||||
|
onChange = noop
|
||||||
|
}: SourceCodeEditorProps) {
|
||||||
|
const scrollbar = autoHeight ? 'hidden' : 'auto'
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions?.(diagnosticsOptions)
|
||||||
|
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions?.(diagnosticsOptions)
|
||||||
|
monaco.languages.typescript.typescriptDefaults.setCompilerOptions(compilerOptions)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container className={className}>
|
||||||
|
<MonacoEditor
|
||||||
|
language={language}
|
||||||
|
theme="vs-light"
|
||||||
|
value={source}
|
||||||
|
height={height}
|
||||||
|
options={{
|
||||||
|
...MonacoEditorOptions,
|
||||||
|
readOnly,
|
||||||
|
wordWrap: toOnOff(wordWrap),
|
||||||
|
lineNumbers: toOnOff(lineNumbers),
|
||||||
|
scrollbar: {
|
||||||
|
vertical: scrollbar,
|
||||||
|
horizontal: scrollbar,
|
||||||
|
alwaysConsumeMouseWheel: false
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
editorDidMount={editor => {
|
||||||
|
if (autoHeight) {
|
||||||
|
autoAdjustEditorHeight(editor)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
}
|
@ -1,79 +1,17 @@
|
|||||||
import React, { useRef } from 'react'
|
import React, { lazy, Suspense } from 'react'
|
||||||
import { Container } from '@harness/uicore'
|
import { Text } from '@harness/uicore'
|
||||||
import MonacoEditor from 'react-monaco-editor'
|
import type { SourceCodeEditorProps } from 'utils/Utils'
|
||||||
import { MonacoEditorOptions } from 'utils/Utils'
|
import { useStrings } from 'framework/strings'
|
||||||
|
|
||||||
export interface SourceCodeEditorProps {
|
function Editor(props: SourceCodeEditorProps) {
|
||||||
source: string
|
const { getString } = useStrings()
|
||||||
language?: string
|
const MonacoSourceCodeEditor = lazy(() => import('./MonacoSourceCodeEditor'))
|
||||||
lineNumbers?: boolean
|
|
||||||
readOnly?: boolean
|
|
||||||
highlightLines?: string // i.e: {1,3-4}, TODO: not yet supported
|
|
||||||
className?: string
|
|
||||||
height?: number | string
|
|
||||||
autoHeight?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
function MonacoSourceCodeEditor({
|
|
||||||
source,
|
|
||||||
language = 'plaintext',
|
|
||||||
lineNumbers = true,
|
|
||||||
readOnly = false,
|
|
||||||
className,
|
|
||||||
height,
|
|
||||||
autoHeight
|
|
||||||
}: SourceCodeEditorProps) {
|
|
||||||
const inputContainerRef = useRef<HTMLDivElement>(null)
|
|
||||||
const scrollbar = autoHeight ? 'hidden' : 'auto'
|
|
||||||
|
|
||||||
// return <Container ref={inputContainerRef} className={className}> </Container>
|
|
||||||
return (
|
return (
|
||||||
<Container ref={inputContainerRef} className={className}>
|
<Suspense fallback={<Text>{getString('loading')}</Text>}>
|
||||||
<MonacoEditor
|
<MonacoSourceCodeEditor {...props} />
|
||||||
language={language}
|
</Suspense>
|
||||||
theme="vs-light"
|
|
||||||
value={source}
|
|
||||||
height={height}
|
|
||||||
options={{
|
|
||||||
...MonacoEditorOptions,
|
|
||||||
...(autoHeight ? {} : { scrollBeyondLastLine: false }),
|
|
||||||
automaticLayout: true,
|
|
||||||
readOnly,
|
|
||||||
wordWrap: 'on',
|
|
||||||
lineNumbers: lineNumbers ? 'on' : 'off',
|
|
||||||
scrollbar: {
|
|
||||||
vertical: scrollbar,
|
|
||||||
horizontal: scrollbar,
|
|
||||||
alwaysConsumeMouseWheel: false
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
editorDidMount={editor => {
|
|
||||||
if (autoHeight) {
|
|
||||||
// Aadjust editor height based on content
|
|
||||||
// https://github.com/microsoft/monaco-editor/issues/794#issuecomment-427092969
|
|
||||||
const LINE_HEIGHT = 18
|
|
||||||
const CONTAINER_GUTTER = 10
|
|
||||||
const editorNode = editor.getDomNode() as HTMLElement
|
|
||||||
const codeContainer = editorNode.getElementsByClassName('view-lines')[0]
|
|
||||||
let prevLineCount = 0
|
|
||||||
const adjustHeight = (): void => {
|
|
||||||
const _height =
|
|
||||||
codeContainer.childElementCount > prevLineCount
|
|
||||||
? (codeContainer as HTMLElement).offsetHeight // unfold
|
|
||||||
: codeContainer.childElementCount * LINE_HEIGHT + CONTAINER_GUTTER // fold
|
|
||||||
prevLineCount = codeContainer.childElementCount
|
|
||||||
|
|
||||||
editorNode.style.height = Math.max(_height, 100) + 'px'
|
|
||||||
editor.layout()
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(adjustHeight, 0)
|
|
||||||
editor.onDidChangeModelDecorations(() => setTimeout(adjustHeight, 0))
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Container>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SourceCodeEditor = React.memo(MonacoSourceCodeEditor)
|
export const SourceCodeEditor = React.memo(Editor)
|
||||||
|
@ -36,9 +36,12 @@ export interface StringsMap {
|
|||||||
failedToCreateRepo: string
|
failedToCreateRepo: string
|
||||||
files: string
|
files: string
|
||||||
history: string
|
history: string
|
||||||
|
identifier: string
|
||||||
|
in: string
|
||||||
inactiveBranches: string
|
inactiveBranches: string
|
||||||
loading: string
|
loading: string
|
||||||
name: string
|
name: string
|
||||||
|
nameYourFile: string
|
||||||
newFile: string
|
newFile: string
|
||||||
newFolder: string
|
newFolder: string
|
||||||
newRepo: string
|
newRepo: string
|
||||||
|
@ -32,6 +32,7 @@ create: Create
|
|||||||
clone: Clone
|
clone: Clone
|
||||||
copy: Copy
|
copy: Copy
|
||||||
defaultBranch: Default
|
defaultBranch: Default
|
||||||
|
in: in
|
||||||
ok: OK
|
ok: OK
|
||||||
loading: Loading...
|
loading: Loading...
|
||||||
addGitIgnore: Add a .gitignore
|
addGitIgnore: Add a .gitignore
|
||||||
@ -51,6 +52,7 @@ createBranch: + Create Branch
|
|||||||
searchBranches: Search branches
|
searchBranches: Search branches
|
||||||
updated: Updated
|
updated: Updated
|
||||||
cloneHTTPS: Clone with HTTPS
|
cloneHTTPS: Clone with HTTPS
|
||||||
|
nameYourFile: Name your file...
|
||||||
repos:
|
repos:
|
||||||
name: Repo Name
|
name: Repo Name
|
||||||
data: Repo Data
|
data: Repo Data
|
||||||
|
@ -129,9 +129,7 @@ export function ContentHeader({ repoMetadata, gitRef, resourcePath = '' }: Conte
|
|||||||
variation={ButtonVariation.SECONDARY}
|
variation={ButtonVariation.SECONDARY}
|
||||||
icon="main-clone"
|
icon="main-clone"
|
||||||
iconProps={{ size: 10 }}
|
iconProps={{ size: 10 }}
|
||||||
tooltip={
|
tooltip={<CloneButtonTooltip httpsURL={`http://localhost:3000/${repoMetadata.path}.git`} />}
|
||||||
<CloneButtonTooltip httpsURL={'https://localhost:8181/kmpySmUISimoRrJL6NL73w/default/scm1/policy-mgmt'} />
|
|
||||||
}
|
|
||||||
tooltipProps={{
|
tooltipProps={{
|
||||||
interactionKind: 'click',
|
interactionKind: 'click',
|
||||||
minimal: true,
|
minimal: true,
|
||||||
|
@ -7,13 +7,28 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
.heading {
|
.heading {
|
||||||
border-top-left-radius: 4px;
|
// border-top-left-radius: 4px;
|
||||||
border-top-right-radius: 4px;
|
// border-top-right-radius: 4px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 var(--spacing-xlarge) !important;
|
padding: 0 var(--spacing-xlarge) !important;
|
||||||
height: 52px;
|
height: 52px;
|
||||||
background-color: var(--grey-100);
|
background-color: var(--grey-100);
|
||||||
box-shadow: 0px 0px 1px rgba(40, 41, 61, 0.08), 0px 0.5px 2px rgba(96, 97, 112, 0.16);
|
box-shadow: 0px 0px 1px rgba(40, 41, 61, 0.08), 0px 0.5px 2px rgba(96, 97, 112, 0.16);
|
||||||
|
border-bottom: 1px solid var(--grey-200);
|
||||||
|
|
||||||
|
.path {
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.inputContainer {
|
||||||
|
margin-left: var(--spacing-small) !important;
|
||||||
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
input {
|
||||||
|
padding: var(--spacing-xsmall) var(--spacing-small);
|
||||||
|
height: 28px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
@ -21,8 +36,7 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
.editorContainer {
|
.editorContainer {
|
||||||
height: calc(100vh - 95px - 52px);
|
height: calc(100vh - 96px - 52px);
|
||||||
background-color: red;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
declare const styles: {
|
declare const styles: {
|
||||||
readonly container: string
|
readonly container: string
|
||||||
readonly heading: string
|
readonly heading: string
|
||||||
|
readonly path: string
|
||||||
|
readonly inputContainer: string
|
||||||
readonly content: string
|
readonly content: string
|
||||||
readonly editorContainer: string
|
readonly editorContainer: string
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,12 @@ import {
|
|||||||
FlexExpander,
|
FlexExpander,
|
||||||
Icon,
|
Icon,
|
||||||
Layout,
|
Layout,
|
||||||
Text
|
Text,
|
||||||
|
TextInput
|
||||||
} from '@harness/uicore'
|
} from '@harness/uicore'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import ReactJoin from 'react-join'
|
import ReactJoin from 'react-join'
|
||||||
|
import cx from 'classnames'
|
||||||
import { SourceCodeEditor } from 'components/SourceCodeEditor/SourceCodeEditor'
|
import { SourceCodeEditor } from 'components/SourceCodeEditor/SourceCodeEditor'
|
||||||
import type { OpenapiGetContentOutput, RepoFileContent, TypesRepository } from 'services/scm'
|
import type { OpenapiGetContentOutput, RepoFileContent, TypesRepository } from 'services/scm'
|
||||||
import { useAppContext } from 'AppContext'
|
import { useAppContext } from 'AppContext'
|
||||||
@ -22,7 +24,7 @@ import css from './FileEditor.module.scss'
|
|||||||
|
|
||||||
interface FileEditorProps {
|
interface FileEditorProps {
|
||||||
repoMetadata: TypesRepository
|
repoMetadata: TypesRepository
|
||||||
gitRef?: string
|
gitRef: string
|
||||||
resourcePath?: string
|
resourcePath?: string
|
||||||
contentInfo: OpenapiGetContentOutput
|
contentInfo: OpenapiGetContentOutput
|
||||||
}
|
}
|
||||||
@ -30,12 +32,13 @@ interface FileEditorProps {
|
|||||||
export function FileEditor({ contentInfo, repoMetadata, gitRef, resourcePath = '' }: FileEditorProps) {
|
export function FileEditor({ contentInfo, repoMetadata, gitRef, resourcePath = '' }: FileEditorProps) {
|
||||||
const { getString } = useStrings()
|
const { getString } = useStrings()
|
||||||
const { routes } = useAppContext()
|
const { routes } = useAppContext()
|
||||||
|
const language = filenameToLanguage(contentInfo?.name)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container className={css.container}>
|
<Container className={css.container}>
|
||||||
<Layout.Horizontal className={css.heading}>
|
<Layout.Horizontal className={css.heading}>
|
||||||
<Container>
|
<Container>
|
||||||
<Layout.Horizontal spacing="small">
|
<Layout.Horizontal spacing="small" className={css.path}>
|
||||||
<Link to={routes.toSCMRepository({ repoPath: repoMetadata.path as string, gitRef })}>
|
<Link to={routes.toSCMRepository({ repoPath: repoMetadata.path as string, gitRef })}>
|
||||||
<Icon name="main-folder" />
|
<Icon name="main-folder" />
|
||||||
</Link>
|
</Link>
|
||||||
@ -44,7 +47,7 @@ export function FileEditor({ contentInfo, repoMetadata, gitRef, resourcePath = '
|
|||||||
{resourcePath.split('/').map((_path, index, paths) => {
|
{resourcePath.split('/').map((_path, index, paths) => {
|
||||||
const pathAtIndex = paths.slice(0, index + 1).join('/')
|
const pathAtIndex = paths.slice(0, index + 1).join('/')
|
||||||
|
|
||||||
return (
|
return index < paths.length - 1 ? (
|
||||||
<Link
|
<Link
|
||||||
key={_path + index}
|
key={_path + index}
|
||||||
to={routes.toSCMRepository({
|
to={routes.toSCMRepository({
|
||||||
@ -54,9 +57,25 @@ export function FileEditor({ contentInfo, repoMetadata, gitRef, resourcePath = '
|
|||||||
})}>
|
})}>
|
||||||
<Text color={Color.GREY_900}>{_path}</Text>
|
<Text color={Color.GREY_900}>{_path}</Text>
|
||||||
</Link>
|
</Link>
|
||||||
|
) : (
|
||||||
|
<TextInput
|
||||||
|
key={_path + index}
|
||||||
|
autoFocus
|
||||||
|
value={_path || ''}
|
||||||
|
wrapperClassName={css.inputContainer}
|
||||||
|
placeholder={getString('nameYourFile')}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</ReactJoin>
|
</ReactJoin>
|
||||||
|
<Text color={Color.GREY_900}>{getString('in')}</Text>
|
||||||
|
<Link
|
||||||
|
to={routes.toSCMRepository({
|
||||||
|
repoPath: repoMetadata.path as string,
|
||||||
|
gitRef
|
||||||
|
})}>
|
||||||
|
{gitRef}
|
||||||
|
</Link>
|
||||||
</Layout.Horizontal>
|
</Layout.Horizontal>
|
||||||
</Container>
|
</Container>
|
||||||
<FlexExpander />
|
<FlexExpander />
|
||||||
@ -69,16 +88,14 @@ export function FileEditor({ contentInfo, repoMetadata, gitRef, resourcePath = '
|
|||||||
/>
|
/>
|
||||||
</Layout.Horizontal>
|
</Layout.Horizontal>
|
||||||
|
|
||||||
{(contentInfo?.content as RepoFileContent)?.data && (
|
<Container className={cx(css.content, language)}>
|
||||||
<Container className={css.content}>
|
<SourceCodeEditor
|
||||||
<SourceCodeEditor
|
className={css.editorContainer}
|
||||||
className={css.editorContainer}
|
height="100%"
|
||||||
height="100%"
|
language={language}
|
||||||
language={filenameToLanguage(contentInfo?.name)}
|
source={window.atob((contentInfo?.content as RepoFileContent)?.data || '')}
|
||||||
source={window.atob((contentInfo?.content as RepoFileContent)?.data || '')}
|
/>
|
||||||
/>
|
</Container>
|
||||||
</Container>
|
|
||||||
)}
|
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Container } from '@harness/uicore'
|
import { Container } from '@harness/uicore'
|
||||||
import type { TypesRepository } from 'services/scm'
|
import type { TypesRepository } from 'services/scm'
|
||||||
import { isFile } from 'utils/GitUtils'
|
|
||||||
import { useGetResourceContent } from 'hooks/useGetResourceContent'
|
import { useGetResourceContent } from 'hooks/useGetResourceContent'
|
||||||
import { FileEditor } from '../FileEditor/FileEditor'
|
import { FileEditor } from '../FileEditor/FileEditor'
|
||||||
import css from './RepositoryFileEditContent.module.scss'
|
import css from './RepositoryFileEditContent.module.scss'
|
||||||
@ -19,10 +18,10 @@ export function RepositoryFileEditContent({ repoMetadata, gitRef, resourcePath }
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container className={css.resourceContent}>
|
<Container className={css.resourceContent}>
|
||||||
{data && isFile(data) && (
|
{data && (
|
||||||
<FileEditor
|
<FileEditor
|
||||||
repoMetadata={repoMetadata}
|
repoMetadata={repoMetadata}
|
||||||
gitRef={gitRef || repoMetadata.defaultBranch}
|
gitRef={gitRef || (repoMetadata.defaultBranch as string)}
|
||||||
resourcePath={resourcePath}
|
resourcePath={resourcePath}
|
||||||
contentInfo={data}
|
contentInfo={data}
|
||||||
/>
|
/>
|
||||||
|
@ -26,15 +26,17 @@ export function showToaster(message: string, props?: Partial<IToastProps>): IToa
|
|||||||
export const getErrorMessage = (error: Unknown): string =>
|
export const getErrorMessage = (error: Unknown): string =>
|
||||||
get(error, 'data.error', get(error, 'data.message', error?.message))
|
get(error, 'data.error', get(error, 'data.message', error?.message))
|
||||||
|
|
||||||
export const MonacoEditorOptions = {
|
export interface SourceCodeEditorProps {
|
||||||
ignoreTrimWhitespace: true,
|
source: string
|
||||||
minimap: { enabled: false },
|
language?: string
|
||||||
codeLens: false,
|
lineNumbers?: boolean
|
||||||
scrollBeyondLastLine: false,
|
readOnly?: boolean
|
||||||
smartSelect: false,
|
highlightLines?: string // i.e: {1,3-4}, TODO: not yet supported
|
||||||
tabSize: 2,
|
className?: string
|
||||||
insertSpaces: true,
|
height?: number | string
|
||||||
overviewRulerBorder: false
|
autoHeight?: boolean
|
||||||
|
wordWrap?: boolean
|
||||||
|
onChange?: (value: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
// Monaco editor has a bug where when its value is set, the value
|
// Monaco editor has a bug where when its value is set, the value
|
||||||
@ -157,10 +159,16 @@ const MONACO_SUPPORTED_LANGUAGES = [
|
|||||||
'yaml'
|
'yaml'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const EXTENSION_TO_LANG: Record<string, string> = {
|
||||||
|
tsx: 'typescript',
|
||||||
|
jsx: 'typescript'
|
||||||
|
}
|
||||||
|
|
||||||
export const filenameToLanguage = (name?: string): string | undefined => {
|
export const filenameToLanguage = (name?: string): string | undefined => {
|
||||||
const map = langMap.languages(name?.split('.').pop() || '')
|
const extension = name?.split('.').pop() || ''
|
||||||
|
const map = langMap.languages(extension)
|
||||||
|
|
||||||
if (map?.length) {
|
if (map?.length) {
|
||||||
return MONACO_SUPPORTED_LANGUAGES.find(lang => map.includes(lang))
|
return MONACO_SUPPORTED_LANGUAGES.find(lang => map.includes(lang)) || EXTENSION_TO_LANG[extension]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user