-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: use monaco for the script step (#1361)
* feat: use monaco for the script step * remove: language selector * Update source/javascripts/components/unified-editor/StepConfigDrawer/components/StepInputGroup.tsx Co-authored-by: Andras Eszes <[email protected]> * fix: check for $ char * fix: fine-tune source naming --------- Co-authored-by: Andras Eszes <[email protected]>
- Loading branch information
1 parent
bd66e62
commit d587ff6
Showing
11 changed files
with
221 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
source/javascripts/components/unified-editor/StepConfigDrawer/components/StepCodeEditor.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { useCallback, useEffect, useState } from 'react'; | ||
import { Box, Label } from '@bitrise/bitkit'; | ||
import { editor } from 'monaco-editor'; | ||
import { Editor, Monaco } from '@monaco-editor/react'; | ||
import { useEnvVarsAndSecretsCompletionProvider } from '@/hooks/useMonacoCompletionProvider'; | ||
|
||
const EDITOR_OPTIONS = { | ||
fontSize: 13, | ||
fontFamily: 'mono', | ||
roundedSelection: false, | ||
scrollBeyondLastLine: false, | ||
stickyScroll: { enabled: true }, | ||
}; | ||
|
||
type Props = { | ||
label?: string; | ||
value: string; | ||
onChange: (value: string | null) => void; | ||
}; | ||
|
||
const StepCodeEditor = ({ label, value, onChange }: Props) => { | ||
const [monacoInstance, setMonaco] = useState<Monaco>(); | ||
const [editorInstance, setEditor] = useState<editor.IStandaloneCodeEditor>(); | ||
|
||
useEnvVarsAndSecretsCompletionProvider({ | ||
monaco: monacoInstance, | ||
language: 'shell', | ||
}); | ||
|
||
const updateEditorHeight = useCallback(() => { | ||
if (!editorInstance) { | ||
return; | ||
} | ||
|
||
const contentHeight = editorInstance?.getContentHeight() || 0; | ||
requestAnimationFrame(() => | ||
editorInstance?.layout({ | ||
height: contentHeight, | ||
width: editorInstance?.getLayoutInfo().width, | ||
}), | ||
); | ||
}, [editorInstance]); | ||
|
||
useEffect(() => { | ||
editorInstance?.onDidChangeModelContent(updateEditorHeight); | ||
updateEditorHeight(); | ||
}, [editorInstance, updateEditorHeight]); | ||
|
||
return ( | ||
<Box display="flex" flexDir="column" gap="8px"> | ||
{label && <Label>{label}</Label>} | ||
<Editor | ||
height="initial" | ||
theme="vs-dark" | ||
defaultValue={value} | ||
options={EDITOR_OPTIONS} | ||
defaultLanguage="shell" | ||
onChange={(changedValue) => onChange(changedValue ?? null)} | ||
onMount={(edtr, mnco) => { | ||
setMonaco(mnco); | ||
setEditor(edtr); | ||
}} | ||
/> | ||
</Box> | ||
); | ||
}; | ||
|
||
export default StepCodeEditor; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { useMemo } from 'react'; | ||
import { useWorkflows } from '@/hooks/useWorkflows'; | ||
import useEnvVars from '@/hooks/useEnvVars'; | ||
import { useSecrets } from '@/hooks/useSecrets'; | ||
import { EnvVar } from '@/core/models/EnvVar'; | ||
import WindowUtils from '@/core/utils/WindowUtils'; | ||
|
||
const useEnvVarsAndSecrets = () => { | ||
const appSlug = WindowUtils.appSlug() ?? ''; | ||
const workflows = useWorkflows(); | ||
const ids = Object.keys(workflows); | ||
const { envs } = useEnvVars(ids, true); | ||
const { data: secrets = [] } = useSecrets({ appSlug }); | ||
|
||
return useMemo(() => [...envs, ...secrets].sort((a, b) => a.key.localeCompare(b.key)) as EnvVar[], [envs, secrets]); | ||
}; | ||
|
||
export default useEnvVarsAndSecrets; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { useEffect, useMemo } from 'react'; | ||
import { languages } from 'monaco-editor'; | ||
import { Monaco } from '@monaco-editor/react'; | ||
import useEnvVarsAndSecrets from '@/hooks/useEnvVarsAndSecrets'; | ||
|
||
type Props = { | ||
monaco: Monaco | undefined; | ||
language: string; | ||
}; | ||
|
||
const useEnvVarsAndSecretsCompletionProvider = ({ monaco, language }: Props) => { | ||
const items = useEnvVarsAndSecrets(); | ||
|
||
const provider: languages.CompletionItemProvider = useMemo( | ||
() => ({ | ||
triggerCharacters: ['$'], | ||
provideCompletionItems: (model, position) => { | ||
const textUntilPosition = model.getValueInRange({ | ||
startLineNumber: position.lineNumber, | ||
startColumn: 1, | ||
endLineNumber: position.lineNumber, | ||
endColumn: position.column, | ||
}); | ||
|
||
// Check if the last character is '$' | ||
if (!textUntilPosition.endsWith('$')) { | ||
return { suggestions: [] }; // Return empty suggestions if not triggered by '$' | ||
} | ||
|
||
const word = model.getWordUntilPosition(position); | ||
const range = { | ||
startLineNumber: position.lineNumber, | ||
startColumn: word.startColumn, | ||
endLineNumber: position.lineNumber, | ||
endColumn: word.endColumn, | ||
}; | ||
|
||
const suggestions: languages.CompletionItem[] = items.map((item) => ({ | ||
label: item.key, | ||
insertText: item.key, | ||
detail: item.source, | ||
kind: languages.CompletionItemKind.Variable, | ||
range, | ||
})); | ||
|
||
return { suggestions }; | ||
}, | ||
}), | ||
[items], | ||
); | ||
|
||
useEffect(() => { | ||
const disposable = monaco?.languages.registerCompletionItemProvider(language, provider); | ||
return disposable?.dispose; | ||
}, [monaco, language, provider]); | ||
}; | ||
|
||
export { useEnvVarsAndSecretsCompletionProvider }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { useEffect, useState } from 'react'; | ||
import { configureMonacoYaml, MonacoYaml } from 'monaco-yaml'; | ||
import { Monaco } from '@monaco-editor/react'; | ||
|
||
const MONACO_YAML_OPTIONS = { | ||
hover: true, | ||
format: true, | ||
validate: true, | ||
completion: true, | ||
enableSchemaRequest: true, | ||
schemas: [ | ||
{ | ||
uri: 'https://json.schemastore.org/bitrise.json', | ||
fileMatch: ['*'], | ||
}, | ||
], | ||
}; | ||
|
||
const useMonacoYaml = (monaco: Monaco | undefined) => { | ||
const [monacoYaml, setMonacoYaml] = useState<MonacoYaml>(); | ||
|
||
useEffect(() => { | ||
if (monaco) { | ||
setMonacoYaml(configureMonacoYaml(monaco, MONACO_YAML_OPTIONS)); | ||
} | ||
}, [monaco]); | ||
|
||
useEffect(() => monacoYaml?.dispose, [monacoYaml]); | ||
}; | ||
|
||
export default useMonacoYaml; |
Oops, something went wrong.