Skip to content

Commit

Permalink
Feat: support oceanbase monaco plugin (#1386)
Browse files Browse the repository at this point in the history
  • Loading branch information
HSunboy authored Apr 13, 2024
1 parent f3ece62 commit 53438a3
Show file tree
Hide file tree
Showing 8 changed files with 2,474 additions and 113 deletions.
39 changes: 34 additions & 5 deletions web/components/chat/db-editor.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ChangeEvent, Key, useEffect, useMemo, useState } from 'react';
import React, { ChangeEvent, Key, useEffect, useMemo, useState } from 'react';
import { useRequest } from 'ahooks';
import { Button, Select, Table, Tooltip } from 'antd';
import { Input, Tree } from 'antd';
import Icon from '@ant-design/icons';
import type { DataNode } from 'antd/es/tree';
import MonacoEditor from './monaco-editor';
import MonacoEditor, { ISession } from './monaco-editor';
import { sendGetRequest, sendSpacePostRequest } from '@/utils/request';
import { useSearchParams } from 'next/navigation';
import { OnChange } from '@monaco-editor/react';
Expand Down Expand Up @@ -45,6 +45,7 @@ interface IProps {
chartData?: any;
tableData?: ITableData;
layout?: 'TB' | 'LR';
tables?: any;
handleChange: OnChange;
}

Expand All @@ -58,7 +59,7 @@ interface ITableTreeItem {
children: Array<ITableTreeItem>;
}

function DbEditorContent({ layout = 'LR', editorValue, chartData, tableData, handleChange }: IProps) {
function DbEditorContent({ layout = 'LR', editorValue, chartData, tableData, tables, handleChange }: IProps) {
const chartWrapper = useMemo(() => {
if (!chartData) return null;

Expand Down Expand Up @@ -86,9 +87,36 @@ function DbEditorContent({ layout = 'LR', editorValue, chartData, tableData, han
return {
columns: tbCols,
dataSource: tbDatas,

};
}, [tableData]);

const session: ISession = useMemo(() => {
const map: Record<string, { columnName: string; columnType: string; }[]> = {};
const db = tables?.data;
const tableList = db?.children;
tableList?.forEach((table: ITableTreeItem) => {
map[table.title] = table.children.map((column: ITableTreeItem) => {
return {
columnName: column.title,
columnType: column.type,
};
})
});
return {
async getTableList(schemaName) {
if (schemaName && schemaName!== db?.title) {
return [];
}
return tableList?.map((table: ITableTreeItem) => table.title) || [];
},
async getTableColumns(tableName) {
return map[tableName] || [];
},
async getSchemaList() {
return db?.title ? [db?.title] : [];
}
};
}, [tables])
return (
<div
className={classNames('flex w-full flex-1 h-full gap-2 overflow-hidden', {
Expand All @@ -97,7 +125,7 @@ function DbEditorContent({ layout = 'LR', editorValue, chartData, tableData, han
})}
>
<div className="flex-1 flex overflow-hidden rounded">
<MonacoEditor value={editorValue?.sql || ''} language="mysql" onChange={handleChange} thoughts={editorValue?.thoughts || ''} />
<MonacoEditor value={editorValue?.sql || ''} language="mysql" onChange={handleChange} thoughts={editorValue?.thoughts || ''} session={session} />
</div>
<div className="flex-1 h-full overflow-auto bg-white dark:bg-theme-dark-container rounded p-4">
{!!tableData?.values.length ? (
Expand Down Expand Up @@ -626,6 +654,7 @@ function DbEditor() {
}}
tableData={tableData}
chartData={undefined}
tables={tables}
/>
)}
</div>
Expand Down
49 changes: 41 additions & 8 deletions web/components/chat/monaco-editor.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,38 @@
import * as monaco from 'monaco-editor';
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js';
import Editor, { OnChange, loader } from '@monaco-editor/react';
import classNames from 'classnames';
import { useContext, useMemo } from 'react';
import { format } from 'sql-formatter';
import { ChatContext } from '@/app/chat-context';
import { formatSql } from '@/utils';
import { getModelService } from './ob-editor/service';
import { useLatest } from 'ahooks';
import { ChatContext } from '@/app/chat-context';
import { github, githubDark } from './ob-editor/theme';
import { register } from './ob-editor/ob-plugin';

loader.config({ monaco });

export interface ISession {
getTableList: (schemaName?: string) => Promise<string[]>;
getTableColumns: (tableName: string) => Promise<{ columnName: string; columnType: string }[]>;
getSchemaList: () => Promise<string[]>;
}

interface MonacoEditorProps {
className?: string;
value: string;
language: string;
onChange?: OnChange;
thoughts?: string;
session?: ISession;

}

export default function MonacoEditor({ className, value, language = 'mysql', onChange, thoughts }: MonacoEditorProps) {
// merge value and thoughts
const { mode } = useContext(ChatContext);
let plugin = null;
monaco.editor.defineTheme('github', github as any);
monaco.editor.defineTheme('githubDark', githubDark as any);

export default function MonacoEditor({ className, value, language = 'mysql', onChange, thoughts, session }: MonacoEditorProps) {
// merge value and thoughts
const editorValue = useMemo(() => {
if (language !== 'mysql') {
return value;
Expand All @@ -30,14 +43,34 @@ export default function MonacoEditor({ className, value, language = 'mysql', onC
return formatSql(value);
}, [value, thoughts]);

const sessionRef = useLatest(session);

const context = useContext(ChatContext);

async function pluginRegister(editor: monaco.editor.IStandaloneCodeEditor) {
const plugin = await register()
plugin.setModelOptions(
editor.getModel()?.id || '',
getModelService({
modelId: editor.getModel()?.id || '',
delimiter: ';',
}, () => sessionRef.current || null)
)
}


return (
<Editor
className={classNames(className)}
onMount={pluginRegister}
value={editorValue}
language={language}
defaultLanguage={language}
onChange={onChange}
theme={mode === 'dark' ? 'vs-dark' : 'light'}
theme={context?.mode !== "dark" ? "github" : "githubDark"}
options={{
minimap: {
enabled: false,
},
wordWrap: 'on',
}}
/>
Expand Down
31 changes: 31 additions & 0 deletions web/components/chat/ob-editor/ob-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

import type Plugin from '@oceanbase-odc/monaco-plugin-ob';

let plugin: Plugin;

export async function register(): Promise<Plugin> {
window.obMonaco = {
getWorkerUrl: (type: string) => {
switch (type) {
case 'mysql': {
return location.origin + '/_next/static/ob-workers/mysql.js'
}
case 'obmysql': {
return location.origin + '/_next/static/ob-workers/obmysql.js'
}
case 'oboracle': {
return location.origin + '/_next/static/ob-workers/oracle.js'
}
}
return "";
}
}
const module = await import('@oceanbase-odc/monaco-plugin-ob')
const Plugin = module.default;
if (plugin) {
return plugin;
}
plugin = new Plugin();
plugin.setup(["mysql"]);
return plugin;
}
21 changes: 21 additions & 0 deletions web/components/chat/ob-editor/service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { IModelOptions } from '@oceanbase-odc/monaco-plugin-ob/dist/type';
import { ISession } from '../monaco-editor';


export function getModelService(
{ modelId, delimiter }: { modelId: string; delimiter: string },
session?: () => ISession | null
): IModelOptions {
return {
delimiter,
async getTableList(schemaName?: string) {
return session?.()?.getTableList(schemaName) || []
},
async getTableColumns(tableName: string, dbName?: string) {
return session?.()?.getTableColumns(tableName) || []
},
async getSchemaList() {
return session?.()?.getSchemaList() || []
},
};
}
Loading

0 comments on commit 53438a3

Please sign in to comment.