Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: askv support #135

Merged
merged 11 commits into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/graphic-walker/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.vercel
4 changes: 2 additions & 2 deletions packages/graphic-walker/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@kanaries/graphic-walker",
"version": "0.3.16",
"version": "0.4.0-a",
"scripts": {
"dev:front_end": "vite --host",
"dev": "npm run dev:front_end",
Expand Down Expand Up @@ -29,7 +29,7 @@
},
"prettier": {
"tabWidth": 4,
"printWidth": 120,
"printWidth": 160,
"singleQuote": true
},
"types": "./dist/index.d.ts",
Expand Down
11 changes: 11 additions & 0 deletions packages/graphic-walker/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { useCurrentMediaTheme } from './utils/media';
import CodeExport from './components/codeExport';
import VisualConfig from './components/visualConfig';
import type { ToolbarItemProps } from './components/toolbar';
import AskViz from './components/askViz';
import { getComputation } from './computation/clientComputation';

export interface IGWProps {
Expand All @@ -43,6 +44,12 @@ export interface IGWProps {
extra?: ToolbarItemProps[];
exclude?: string[];
};
enhanceAPI?: {
header?: Record<string, string>;
features?: {
askviz?: string | boolean;
}
};
}

const App = observer<IGWProps>(function App(props) {
Expand All @@ -58,6 +65,7 @@ const App = observer<IGWProps>(function App(props) {
dark = 'media',
computation,
toolbar,
enhanceAPI,
} = props;
const { commonStore, vizStore } = useGlobalStore();

Expand Down Expand Up @@ -158,6 +166,9 @@ const App = observer<IGWProps>(function App(props) {
style={{ marginTop: '0em', borderTop: 'none' }}
className="m-4 p-4 border border-gray-200 dark:border-gray-700"
>
{enhanceAPI?.features?.askviz && (
<AskViz api={typeof enhanceAPI.features.askviz === 'string' ? enhanceAPI.features.askviz : ''} headers={enhanceAPI?.header} />
)}
<VisualSettings rendererHandler={rendererRef} darkModePreference={dark} exclude={toolbar?.exclude} extra={toolbar?.extra} />
<CodeExport />
<VisualConfig />
Expand Down
92 changes: 92 additions & 0 deletions packages/graphic-walker/src/components/askViz/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { observer } from 'mobx-react-lite';
import React, { useCallback, useState } from 'react';
import { useGlobalStore } from '../../store';
import { PaperAirplaneIcon } from '@heroicons/react/24/outline';
import Spinner from '../spinner';
import { IViewField } from '../../interfaces';
import { VisSpecWithHistory } from '../../models/visSpecHistory';

type VEGALite = any;

const api = import.meta.env.DEV ? 'http://localhost:2023/api/vis/text2gw' : 'https://enhanceai.kanaries.net/api/vis/text2gw'

async function vizQuery(api: string, metas: IViewField[], query: string, headers: Record<string, string>) {
const res = await fetch(api, {
headers: {
'Content-Type': 'application/json',
...headers,
},
credentials: 'include',
method: 'POST',
body: JSON.stringify({
metas,
messages: [
{
role: 'user',
content: query,
},
],
}),
});
const result: {
success: boolean;
data: VEGALite;
message?: string;
} = await res.json();
if (result.success) {
return result.data;
} else {
throw new Error(result.message);
}
}

const AskViz: React.FC<{api?: string; headers?: Record<string, string>}> = (props) => {
const [query, setQuery] = useState<string>('');
const [loading, setLoading] = useState<boolean>(false);
const { vizStore } = useGlobalStore();

const allFields = vizStore.allFields;

const startQuery = useCallback(() => {
setLoading(true);
vizQuery(props.api ?? api, allFields, query, props.headers ?? {})
.then((data) => {
vizStore.visList.push(new VisSpecWithHistory(data));
vizStore.selectVisualization(vizStore.visList.length - 1);
// const liteGW = parseGW(spec);
// vizStore.renderSpec(liteGW);
})
.finally(() => {
setLoading(false);
});
}, [query, allFields]);
return (
<div className="right-0 flex">
<input
type="text"
className="rounded-l-md px-4 block w-full border-0 py-1.5 text-gray-900 dark:text-gray-50 shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-600 placeholder:text-gray-400 focus:ring-1 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6 dark:bg-gray-900"
placeholder="What visualization your want to draw from the dataset"
value={query}
onChange={(e) => setQuery(e.target.value)}
onKeyDown={(e) => {
if (e.key === 'Enter' && loading === false && query.length > 0) {
startQuery();
}
}}
disabled={loading || allFields.length === 0}
/>
<button
type="button"
className="flex items-center grow-0 rounded-r-md bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500 px-4 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 disabled:opacity-50 disabled:cursor-not-allowed"
disabled={loading || query.length === 0 || allFields.length === 0}
onClick={startQuery}
>
Ask
{!loading && <PaperAirplaneIcon className="w-4 ml-1" />}
{loading && <Spinner />}
</button>
</div>
);
};

export default observer(AskViz);
38 changes: 38 additions & 0 deletions packages/graphic-walker/src/components/askViz/schemaTransform.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Specification } from "../../interfaces";

export function parseGW(vlSpec: any): Specification {
const spec: Specification = {};
if (vlSpec.encoding && vlSpec.mark) {
spec.geomType = [vlSpec.mark];
spec.position = [];
if (vlSpec.encoding.x && vlSpec.encoding.x.field) {
spec.position.push(vlSpec.encoding.x.field);
if (vlSpec.encoding.x.aggregate) {
spec.aggregate = true;
}
}
if (vlSpec.encoding.y && vlSpec.encoding.y.field) {
spec.position.push(vlSpec.encoding.y.field);
if (vlSpec.encoding.y.aggregate) {
spec.aggregate = true;
}
}
spec.facets = [];
if (vlSpec.encoding.row && vlSpec.encoding.row) {
spec.facets.push(vlSpec.encoding.row);
}
if (vlSpec.encoding.column && vlSpec.encoding.column) {
spec.facets.push(vlSpec.encoding.column);
}

['color', 'opacity', 'shape', 'size'].forEach((ch) => {
if (vlSpec.encoding[ch] && vlSpec.encoding[ch].field) {
spec[ch] = [vlSpec.encoding[ch].field];
if (vlSpec.encoding[ch].aggregate) {
spec.aggregate = true;
}
}
});
}
return spec;
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ const PivotTable: React.FC<PivotTableProps> = (props) => {
data
);
const metric = buildMetricTableFromNestTree(lt, tt, data);
// debugger
unstable_batchedUpdates(() => {
setLeftTree(lt);
setTopTree(tt);
Expand Down
14 changes: 14 additions & 0 deletions packages/graphic-walker/src/components/spinner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';

export default function Spinner() {
return (
<svg className="animate-spin ml-2 mr-2 h-5 w-5 text-white" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
);
}
3 changes: 2 additions & 1 deletion packages/graphic-walker/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export const GEMO_TYPES: Readonly<string[]> = [
export const STACK_MODE: Readonly<IStackMode[]> = [
'none',
'stack',
'normalize'
'normalize',
'center'
]

export const CHART_LAYOUT_TYPE: Readonly<string[]> = [
Expand Down
8 changes: 4 additions & 4 deletions packages/graphic-walker/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ export interface IField {
basename?: string;
path?: string[],
}

export type ISortMode = 'none' | 'ascending' | 'descending';
export interface IViewField extends IField {
dragId: string;
sort?: 'none' | 'ascending' | 'descending';
sort?: ISortMode;
}

export interface DataSet {
Expand Down Expand Up @@ -207,15 +207,15 @@ export type IFilterRule =
value: Set<string | number>;
};

export type IStackMode = 'none' | 'stack' | 'normalize';
export type IStackMode = 'none' | 'stack' | 'normalize' | 'zero' | 'center';

export interface IVisualConfig {
defaultAggregated: boolean;
geoms: string[];
stack: IStackMode;
showActions: boolean;
interactiveScale: boolean;
sorted: 'none' | 'ascending' | 'descending';
sorted: ISortMode;
zeroScale: boolean;
background?: string;
format: {
Expand Down
3 changes: 2 additions & 1 deletion packages/graphic-walker/src/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
"__enum__": "Stack Mode",
"none": "None",
"stack": "Stack",
"normalize": "Normalize"
"normalize": "Normalize",
"center": "Center"
},
"layout_type": {
"__enum__": "Layout Mode",
Expand Down
3 changes: 2 additions & 1 deletion packages/graphic-walker/src/locales/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
"__enum__": "スタックモード",
"none": "なし",
"stack": "スタック",
"normalize": "正規化"
"normalize": "正規化",
"center": "中央"
},
"layout_type": {
"__enum__": "レイアウトタイプ",
Expand Down
3 changes: 2 additions & 1 deletion packages/graphic-walker/src/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@
"__enum__": "堆叠模式",
"none": "关闭",
"stack": "堆叠",
"normalize": "归一化"
"normalize": "归一化",
"center": "中央"
},
"draggable_key": {
"fields": "字段",
Expand Down
2 changes: 1 addition & 1 deletion packages/graphic-walker/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ if (!import.meta.env.DEV) {
inject();
}

embedGraphicWalker(document.getElementById('root') as HTMLElement)
embedGraphicWalker(document.getElementById('root') as HTMLElement, {})
Loading