Files
nocodb/packages/nc-gui/components/monaco/Editor.vue
Anbarasu 0bb5ab9982 feat: button field (#9144)
* feat: static button type

* fix: swagger

* fix: style corrections

* feat: webhook trigger

* fix: disables

* feat: Button icons fix: row Delete failing

* fix: expanded-form ux fix: disable buttons in forms fix: update PlainCell button handling fix: webhook delete, active change handling

* fix: disable case

* fix: disable case

* fix: update Button styles

* fix: refactor min/max with limit for columns fix: disable filter, groupby for Button Field fix: disable aggregation for Buttons

* fix: hide button field in Filters

* fix: fields menu corrections fix: update menu corrections

* fix: rebase

* feat: support webhook creation from ButtonOptions

* fix: sort related tests

* fix: keep webhook modal open

* fix: ui fixes

* fix: icon duplicate

* fix: syntax highlighing for handlebar fix: disable mascot fix: truncate selected webhook

* fix: sort disable tooltip

* test: button playwright test

* fix: button column duplication

* fix: add error fix: column options

* fix: EditOrAddProvider.vue

* fix: add invalid configuration

* fix: ux corrections

* fix: ux corrections

* fix: error handling fix: clear single query cache on hook delete

* fix: include button type in api

* fix: update overlay styles fix: webhook update

* fix: formula placeholder

* fix: playwright tests

* fix: playwright tests

* feat: refactor formula input

* fix: added more spacing

* fix: no icon text

* fix: lint

* fix: handle invalid url

* fix: handle sort by for button causes issue when button used as lookup

* fix: button field position

* docs: button field

* fix: tooltip correction

* fix: link

* fix: add btn href

* fix: handle some edge cases

* fix: handle some edge cases

* fix: update font color

* fix: add manual trigger docs

* fix: sqlite BaseModel fix

* docs: button share view info

* fix: rebase

* fix: reduce height and added resize support fix: added tooltip if label overflow

* fix: manual hook disable state

* docs: manual trigger details in webhook page

* fix: chevron grey shade to 500

* docs: sample payload for manual trigger

* fix: style update

* fix: pr review comments

* fix: pr review changes

* fix: reactivity issue

* fix: reactivity issue

* fix: filter enabled on button

* fix: reload meta on webhook change

* fix: error handling in formula filter

* fix: handle url error

---------

Co-authored-by: Raju Udava <86527202+dstala@users.noreply.github.com>
2024-08-14 15:32:19 +05:30

192 lines
4.6 KiB
Vue

<script setup lang="ts">
import type { editor as MonacoEditor } from 'monaco-editor'
import { languages, editor as monacoEditor } from 'monaco-editor'
import PlaceholderContentWidget from './Placeholder'
interface Props {
modelValue: string | Record<string, any>
hideMinimap?: boolean
lang?: string
validate?: boolean
disableDeepCompare?: boolean
placeholder?: string
readOnly?: boolean
autoFocus?: boolean
monacoConfig?: Partial<MonacoEditor.IStandaloneEditorConstructionOptions>
monacoCustomTheme?: Partial<MonacoEditor.IStandaloneThemeData>
}
const props = withDefaults(defineProps<Props>(), {
modelValue: '',
lang: 'json',
validate: true,
disableDeepCompare: false,
autoFocus: true,
monacoConfig: () => ({} as Partial<MonacoEditor.IStandaloneEditorConstructionOptions>),
monacoCustomTheme: () => ({} as Partial<MonacoEditor.IStandaloneThemeData>),
})
const emits = defineEmits(['update:modelValue'])
const { modelValue } = toRefs(props)
const { hideMinimap, lang, validate, disableDeepCompare, readOnly, autoFocus, monacoConfig, monacoCustomTheme, placeholder } =
props
const vModel = computed<string>({
get: () => {
if (typeof modelValue.value === 'object') {
return JSON.stringify(modelValue.value, null, 2)
} else {
return modelValue.value ?? ''
}
},
set: (newVal: string | Record<string, any>) => {
if (typeof modelValue.value === 'object') {
try {
emits('update:modelValue', typeof newVal === 'object' ? newVal : JSON.parse(newVal))
} catch (e) {
console.error(e)
}
} else {
emits('update:modelValue', newVal)
}
},
})
const isValid = ref(true)
const root = ref<HTMLDivElement>()
let editor: MonacoEditor.IStandaloneCodeEditor
const format = (space = monacoConfig.tabSize || 2) => {
try {
const parsedValue = JSON.parse(editor?.getValue() as string)
editor.setValue(JSON.stringify(parsedValue, null, space))
} catch (error: unknown) {
console.error('Failed to parse and format JSON:', error)
}
}
defineExpose({
format,
isValid,
})
onMounted(async () => {
if (root.value && lang) {
const model = monacoEditor.createModel(vModel.value, lang)
if (lang === 'json') {
// configure the JSON language support with schemas and schema associations
languages.json.jsonDefaults.setDiagnosticsOptions({
validate: validate as boolean,
})
}
let isCustomTheme = false
if (Object.keys(monacoCustomTheme).length) {
monacoEditor.defineTheme('custom', monacoCustomTheme)
isCustomTheme = true
}
editor = monacoEditor.create(root.value, {
model,
contextmenu: false,
theme: isCustomTheme ? 'custom' : 'vs',
foldingStrategy: 'indentation',
selectOnLineNumbers: true,
language: props.lang,
scrollbar: {
verticalScrollbarSize: 1,
horizontalScrollbarSize: 1,
},
lineNumbers: 'off',
tabSize: monacoConfig.tabSize || 2,
automaticLayout: true,
readOnly,
bracketPairColorization: {
enabled: true,
independentColorPoolPerBracketType: true,
},
minimap: {
enabled: !hideMinimap,
},
...(lang === 'json' ? { detectIndentation: false, insertSpaces: true } : {}),
...monacoConfig,
})
editor.onDidChangeModelContent(async () => {
try {
isValid.value = true
if (disableDeepCompare || lang !== 'json') {
vModel.value = editor.getValue()
} else {
const obj = JSON.parse(editor.getValue())
if (!obj || !deepCompare(vModel.value, obj)) vModel.value = obj
}
} catch (e) {
isValid.value = false
console.log(e)
}
})
if (placeholder) {
// eslint-disable-next-line no-new
new PlaceholderContentWidget(placeholder, editor)
}
if (!isDrawerOrModalExist() && autoFocus) {
// auto focus on json cells only
editor.focus()
}
if (lang === 'json') {
format()
}
}
})
watch(vModel, (v) => {
if (!editor || !v) return
const editorValue = editor?.getValue()
if (!disableDeepCompare && lang === 'json') {
if (!editorValue || !deepCompare(JSON.parse(v), JSON.parse(editorValue))) {
editor.setValue(v)
}
} else {
if (editorValue !== v) editor.setValue(v)
}
})
watch(
() => readOnly,
(v) => {
if (!editor) return
editor.updateOptions({ readOnly: v })
},
)
</script>
<template>
<div ref="root"></div>
</template>
<style scoped lang="scss">
:deep(.monaco-editor) {
background-color: transparent !important;
border-radius: 8px !important;
}
:deep(.overflow-guard) {
border-radius: 8px !important;
}
</style>