diff --git a/apps/go.work b/apps/go.work
deleted file mode 100644
index 8c0bcc8c..00000000
--- a/apps/go.work
+++ /dev/null
@@ -1 +0,0 @@
-go 1.18
diff --git a/apps/rath-service/README.md b/apps/rath-service/README.md
new file mode 100644
index 00000000..ccfb69c6
--- /dev/null
+++ b/apps/rath-service/README.md
@@ -0,0 +1,3 @@
+## WIP RATH Service :construction:
+
+designed for RATH's server side persistent storage.
\ No newline at end of file
diff --git a/apps/testDatasets/sales.sql b/apps/test-datasets/sales.sql
similarity index 100%
rename from apps/testDatasets/sales.sql
rename to apps/test-datasets/sales.sql
diff --git a/buildspec.yml b/buildspec.yml
index 69a87b89..d11685ea 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -12,7 +12,6 @@ phases:
build:
commands:
- echo Building...
- - yarn workspace @kanaries/graphic-walker build
- yarn workspace rath-client build2
artifacts:
files:
diff --git a/package.json b/package.json
index f4fde654..c2d7f64b 100644
--- a/package.json
+++ b/package.json
@@ -1,19 +1,19 @@
{
- "name": "visual-insights",
+ "name": "Rath",
"private": true,
"version": "1.0.0",
- "description": " ",
+ "description": "",
"scripts": {
- "build": "yarn workspace graphic-walker build && yarn workspace frontend build",
- "test": "yarn workspace frontend test",
+ "build": "yarn workspace rath-client build",
+ "test": "yarn workspace rath-client test",
"ui": "npm run test && npm run build && node start.js",
- "devfront": "yarn workspace frontend start",
+ "devfront": "yarn workspace rath-client start",
"devback": "yarn workspace backend dev",
"count": "cloc --exclude-dir=$(tr '\n' ',' < .clocignore) ."
},
"repository": {
"type": "git",
- "url": "git+https://github.com/ObservedObserver/showme.git"
+ "url": "git+https://github.com/Kanaries/Rath.git"
},
"keywords": [
"insights",
@@ -22,7 +22,7 @@
],
"author": "Observed Observer",
"bugs": {
- "url": "https://github.com/ObservedObserver/showme/issues"
+ "url": "https://github.com/Kanaries/Rath/issues"
},
"workspaces": {
"packages": [
@@ -42,7 +42,7 @@
"@types/react-dom": "^17.x",
"vega-scenegraph": "4.10.1-kanaries-patch"
},
- "homepage": "https://github.com/ObservedObserver/showme#readme",
+ "homepage": "https://github.com/Kanaries/Rath#readme",
"devDependencies": {
"concurrently": "^4.1.2",
"yarn": "^1.19.0"
diff --git a/packages/connectors/app-config.default.json b/packages/olap-connector/app-config.default.json
similarity index 100%
rename from packages/connectors/app-config.default.json
rename to packages/olap-connector/app-config.default.json
diff --git a/packages/connectors/app-config.json b/packages/olap-connector/app-config.json
similarity index 100%
rename from packages/connectors/app-config.json
rename to packages/olap-connector/app-config.json
diff --git a/packages/connectors/app/constants.ts b/packages/olap-connector/app/constants.ts
similarity index 100%
rename from packages/connectors/app/constants.ts
rename to packages/olap-connector/app/constants.ts
diff --git a/packages/connectors/app/controllers/clickHouseProxy.ts b/packages/olap-connector/app/controllers/clickHouseProxy.ts
similarity index 100%
rename from packages/connectors/app/controllers/clickHouseProxy.ts
rename to packages/olap-connector/app/controllers/clickHouseProxy.ts
diff --git a/packages/connectors/app/controllers/connection.ts b/packages/olap-connector/app/controllers/connection.ts
similarity index 100%
rename from packages/connectors/app/controllers/connection.ts
rename to packages/olap-connector/app/controllers/connection.ts
diff --git a/packages/connectors/app/controllers/index.ts b/packages/olap-connector/app/controllers/index.ts
similarity index 100%
rename from packages/connectors/app/controllers/index.ts
rename to packages/olap-connector/app/controllers/index.ts
diff --git a/packages/connectors/app/interfaces.ts b/packages/olap-connector/app/interfaces.ts
similarity index 100%
rename from packages/connectors/app/interfaces.ts
rename to packages/olap-connector/app/interfaces.ts
diff --git a/packages/connectors/app/main.ts b/packages/olap-connector/app/main.ts
similarity index 100%
rename from packages/connectors/app/main.ts
rename to packages/olap-connector/app/main.ts
diff --git a/packages/connectors/app/router.ts b/packages/olap-connector/app/router.ts
similarity index 100%
rename from packages/connectors/app/router.ts
rename to packages/olap-connector/app/router.ts
diff --git a/packages/connectors/app/services/chmeta.ts b/packages/olap-connector/app/services/chmeta.ts
similarity index 100%
rename from packages/connectors/app/services/chmeta.ts
rename to packages/olap-connector/app/services/chmeta.ts
diff --git a/packages/connectors/app/services/chparser.ts b/packages/olap-connector/app/services/chparser.ts
similarity index 100%
rename from packages/connectors/app/services/chparser.ts
rename to packages/olap-connector/app/services/chparser.ts
diff --git a/packages/connectors/app/store.ts b/packages/olap-connector/app/store.ts
similarity index 100%
rename from packages/connectors/app/store.ts
rename to packages/olap-connector/app/store.ts
diff --git a/packages/connectors/app/utils.ts b/packages/olap-connector/app/utils.ts
similarity index 100%
rename from packages/connectors/app/utils.ts
rename to packages/olap-connector/app/utils.ts
diff --git a/packages/connectors/https.sh b/packages/olap-connector/https.sh
similarity index 100%
rename from packages/connectors/https.sh
rename to packages/olap-connector/https.sh
diff --git a/packages/connectors/package.json b/packages/olap-connector/package.json
similarity index 95%
rename from packages/connectors/package.json
rename to packages/olap-connector/package.json
index 0726df12..3b658cef 100644
--- a/packages/connectors/package.json
+++ b/packages/olap-connector/package.json
@@ -1,5 +1,5 @@
{
- "name": "connectors",
+ "name": "olap-connector",
"version": "1.0.0",
"description": "",
"scripts": {
diff --git a/packages/connectors/security/req.cnf b/packages/olap-connector/security/req.cnf
similarity index 100%
rename from packages/connectors/security/req.cnf
rename to packages/olap-connector/security/req.cnf
diff --git a/packages/connectors/tsconfig.json b/packages/olap-connector/tsconfig.json
similarity index 100%
rename from packages/connectors/tsconfig.json
rename to packages/olap-connector/tsconfig.json
diff --git a/packages/rath-client/public/locales/en-US.json b/packages/rath-client/public/locales/en-US.json
index 047f7b9d..0e9e3187 100644
--- a/packages/rath-client/public/locales/en-US.json
+++ b/packages/rath-client/public/locales/en-US.json
@@ -40,16 +40,16 @@
},
"menu": {
"dataSource": "DataSource",
- "editor": "Manual Exploration⭐️",
+ "editor": "Manual Exploration",
"vizPipe": "interactive Pipeline",
"support": "Support",
"megaAuto": "Mega-auto Exploration",
- "semiAuto": "Semi-auto Exploration⭐️",
+ "semiAuto": "Semi-auto Exploration",
"devCollection": "Insiders(α)",
"dashBoardDesigner": "Dashboard Designer",
- "painter": "Data Painter🚀",
+ "painter": "Data Painter",
"collection": "Collection",
- "dashboard": "Dashboard📋"
+ "dashboard": "Dashboard"
},
"preference": {
"title": "preference",
@@ -79,8 +79,8 @@
"analysis": {
"start": "Start Analysis",
"checkResult": "Check Existed Results",
- "pattern": "Data Copilot",
- "manual": "Manual Explore"
+ "pattern": "Semi-auto Exploration",
+ "manual": "Manual Exploration"
},
"importStorage": {
"title": "Import History Storage",
@@ -123,6 +123,7 @@
"databaseName": "Database",
"schemaName": "Schema",
"tableName": "Table",
+ "editName": "Edit Name",
"preview": "Data Preview",
"query": "SQL Query",
"connectorConfig": "Connector Settings",
diff --git a/packages/rath-client/public/locales/zh-CN.json b/packages/rath-client/public/locales/zh-CN.json
index 48ea5ac3..eb98d615 100644
--- a/packages/rath-client/public/locales/zh-CN.json
+++ b/packages/rath-client/public/locales/zh-CN.json
@@ -40,15 +40,15 @@
},
"menu": {
"dataSource": "数据源",
- "editor": "自助分析⭐️",
+ "editor": "自助分析",
"support": "帮助",
"megaAuto": "全自动分析",
- "semiAuto": "半自动探索⭐️",
+ "semiAuto": "半自动探索",
"devCollection": "实验特性(α)",
"dashBoardDesigner": "智能报表",
- "painter": "数据绘板🚀",
+ "painter": "数据绘板",
"collection": "收藏夹",
- "dashboard": "报表📋"
+ "dashboard": "报表"
},
"preference": {
"title": "个人偏好",
@@ -78,7 +78,7 @@
"analysis": {
"start": "开始分析",
"checkResult": "查看已有结果",
- "pattern": "半自动化分析",
+ "pattern": "半自动化探索",
"manual": "自助分析"
},
"importStorage": {
@@ -119,9 +119,10 @@
"charset": "字符集编码",
"databaseType": "选择数据库",
"connectUri": "连接 URI",
- "databaseName": "Database",
+ "databaseName": "数据库",
"schemaName": "Schema",
- "tableName": "Table",
+ "tableName": "表",
+ "editName": "编辑名称",
"preview": "数据预览",
"query": "SQL 查询",
"connectorConfig": "连接器设置",
diff --git a/packages/rath-client/src/App.tsx b/packages/rath-client/src/App.tsx
index e34947f3..80458371 100644
--- a/packages/rath-client/src/App.tsx
+++ b/packages/rath-client/src/App.tsx
@@ -18,59 +18,56 @@ import Painter from './pages/painter';
import Collection from './pages/collection';
import Dashboard from './pages/dashboard';
-
function App() {
- const { langStore, commonStore } = useGlobalStore();
- const { appKey, navMode } = commonStore;
+ const { langStore, commonStore } = useGlobalStore();
+ const { appKey, navMode } = commonStore;
- useEffect(() => {
- initRathWorker(commonStore.computationEngine);
- return () => {
- destroyRathWorker();
- };
- }, [commonStore]);
+ useEffect(() => {
+ initRathWorker(commonStore.computationEngine);
+ return () => {
+ destroyRathWorker();
+ };
+ }, [commonStore]);
- if (!langStore.loaded) {
+ if (!langStore.loaded) {
+ return (
+
+
+
+ );
+ }
return (
-
-
-
-)
- }
- return (
-
-
-
-
-
-
+
+
+
+
+
+
+
+ {appKey === PIVOT_KEYS.dataSource &&
}
+ {appKey === PIVOT_KEYS.editor &&
}
+ {appKey === PIVOT_KEYS.support &&
}
+ {appKey === PIVOT_KEYS.megaAuto &&
}
+ {appKey === PIVOT_KEYS.semiAuto &&
}
+ {appKey === PIVOT_KEYS.painter &&
}
+ {appKey === PIVOT_KEYS.dashBoardDesigner &&
}
+ {appKey === PIVOT_KEYS.collection &&
}
+ {appKey === PIVOT_KEYS.dashboard &&
}
+
+
+
- {appKey === PIVOT_KEYS.dataSource && (
-
- )}
- {appKey === PIVOT_KEYS.editor &&
}
- {appKey === PIVOT_KEYS.support &&
}
- {appKey === PIVOT_KEYS.megaAuto &&
}
- {appKey === PIVOT_KEYS.semiAuto &&
}
- {appKey === PIVOT_KEYS.painter &&
}
- {appKey === PIVOT_KEYS.dashBoardDesigner &&
}
- {appKey === PIVOT_KEYS.collection &&
}
- {appKey === PIVOT_KEYS.dashboard &&
}
-
-
-
-
- )
+ );
}
const OBApp = observer(App);
export default function WrappedApp(): JSX.Element {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/packages/rath-client/src/components/dbGraph/index.tsx b/packages/rath-client/src/components/dbGraph/index.tsx
index de8b6977..a92ac05d 100644
--- a/packages/rath-client/src/components/dbGraph/index.tsx
+++ b/packages/rath-client/src/components/dbGraph/index.tsx
@@ -69,27 +69,27 @@ export const DBBox = styled.span`
background-color: #f3f3f3;
}
`;
-const Output = styled.div({
- flexGrow: 1,
- flexShrink: 1,
- overflow: 'hidden',
- display: 'flex',
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'space-between',
- border: '1px solid',
- borderTop: 'none',
- marginBottom: '1em',
-
- '> span': {
- flexGrow: 1,
- flexShrink: 1,
- padding: '0 1em',
- overflow: 'hidden',
+const Output = styled.div`
+ flex-grow: 1;
+ flex-shrink: 1;
+ overflow: hidden;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-between;
+ border: 1px solid;
+ border-top: none;
+ margin-bottom: 1em;
+
+ > span {
+ flex-grow: 1;
+ flex-shrink: 1;
+ padding: 0 1em;
+ overflow: hidden;
// textOverflow: 'ellipsis',
- maxWidth: '30vw',
- },
-});
+ max-width: 30vw;
+ }
+`
const STROKE_RADIUS = 12;
diff --git a/packages/rath-client/src/components/fieldFilter/index.tsx b/packages/rath-client/src/components/fieldFilter/index.tsx
index 7d525a12..4904ea48 100644
--- a/packages/rath-client/src/components/fieldFilter/index.tsx
+++ b/packages/rath-client/src/components/fieldFilter/index.tsx
@@ -10,7 +10,6 @@ import { useGlobalStore } from '../../store';
import RangeSelection from './rangeSelection';
import SetSelection from './setSelection';
-
interface FieldFilterProps {
fid: string;
}
diff --git a/packages/rath-client/src/components/react-vega.tsx b/packages/rath-client/src/components/react-vega.tsx
index 9f492198..9cb0f269 100644
--- a/packages/rath-client/src/components/react-vega.tsx
+++ b/packages/rath-client/src/components/react-vega.tsx
@@ -5,87 +5,93 @@ import embed, { vega } from 'vega-embed';
import { EDITOR_URL } from '../constants';
interface ReactVegaProps {
- dataSource: any[];
- spec: any;
- actions?: boolean;
- signalHandler?: {
- [key: string]: (name: any, value: any, view: View) => void
- }
+ dataSource: any[];
+ spec: any;
+ actions?: boolean;
+ signalHandler?: {
+ [key: string]: (name: any, value: any, view: View) => void;
+ };
}
-const ReactVega: React.FC
= props => {
- const { spec, dataSource, signalHandler = {}, actions } = props
- const container = useRef(null);
- const viewRef = useRef();
- useEffect(() => {
- if (container.current) {
- const sspec = {
- ...spec,
- data: {
- ...spec.data,
+const ReactVega: React.FC = (props) => {
+ const { spec, dataSource, signalHandler = {}, actions } = props;
+ const container = useRef(null);
+ const viewRef = useRef();
+ useEffect(() => {
+ if (container.current) {
+ const sspec = {
+ ...spec,
+ data: {
+ ...spec.data,
+ },
+ };
+ if (spec.data) {
+ sspec.data = {
+ ...spec.data,
+ };
+ }
+ sspec.data.values = dataSource;
+ embed(container.current, sspec, {
+ editorUrl: EDITOR_URL,
+ timeFormatLocale: intl.get('time_format') as any,
+ actions,
+ }).then((res) => {
+ const view = res.view;
+ viewRef.current = view;
+ for (let key in signalHandler) {
+ try {
+ view.addSignalListener(key, (n, v) => signalHandler[key](n, v, view));
+ } catch (error) {
+ console.warn(error);
+ }
+ }
+ });
}
- };
- if (spec.data) {
- sspec.data = {
- ...spec.data
- }
- }
- sspec.data.values = dataSource;
- embed(container.current, sspec, {
- editorUrl: EDITOR_URL,
- timeFormatLocale: intl.get('time_format') as any,
- actions
- }).then(res => {
- const view = res.view;
- viewRef.current = view;
- for (let key in signalHandler) {
- try {
- view.addSignalListener(key, (n, v) => signalHandler[key](n, v, view));
- } catch (error) {
- console.warn(error);
- }
- }
- })
- }
- return () => {
- if (viewRef.current) {
- viewRef.current.finalize();
- }
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [spec, actions])
+ return () => {
+ if (viewRef.current) {
+ viewRef.current.finalize();
+ }
+ };
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [spec, actions]);
- useEffect(() => {
- if (viewRef.current && signalHandler) {
- for (let key in signalHandler) {
- try {
- viewRef.current.addSignalListener(key, (n, v) => signalHandler[key](n, v, viewRef.current!));
- } catch (error) {
- console.warn(error);
- }
- }
- }
- return () => {
- if (viewRef.current && signalHandler) {
- for (let key in signalHandler) {
- try {
- viewRef.current.removeSignalListener(key, (n, v) => signalHandler[key](n, v, viewRef.current!));
- } catch (error) {
- console.warn(error);
- }
+ useEffect(() => {
+ if (viewRef.current && signalHandler) {
+ for (let key in signalHandler) {
+ try {
+ viewRef.current.addSignalListener(key, (n, v) => signalHandler[key](n, v, viewRef.current!));
+ } catch (error) {
+ console.warn(error);
+ }
+ }
}
- }
- }
- }, [signalHandler])
+ return () => {
+ if (viewRef.current && signalHandler) {
+ for (let key in signalHandler) {
+ try {
+ viewRef.current.removeSignalListener(key, (n, v) => signalHandler[key](n, v, viewRef.current!));
+ } catch (error) {
+ console.warn(error);
+ }
+ }
+ }
+ };
+ }, [signalHandler]);
- useEffect(() => {
- if (viewRef.current) {
- viewRef.current.change('dataSource', vega.changeset().remove(() => true).insert(dataSource));
- viewRef.current.resize();
- viewRef.current.runAsync();
- }
- }, [dataSource])
- return
-}
+ useEffect(() => {
+ if (viewRef.current) {
+ viewRef.current.change(
+ 'dataSource',
+ vega
+ .changeset()
+ .remove(() => true)
+ .insert(dataSource)
+ );
+ viewRef.current.resize();
+ viewRef.current.runAsync();
+ }
+ }, [dataSource]);
+ return ;
+};
export default ReactVega;
diff --git a/packages/rath-client/src/components/simpleTick.tsx b/packages/rath-client/src/components/simpleTick.tsx
index 8bd53819..ebbd4833 100644
--- a/packages/rath-client/src/components/simpleTick.tsx
+++ b/packages/rath-client/src/components/simpleTick.tsx
@@ -3,58 +3,58 @@ import { IRow } from 'visual-insights';
import ReactVega from './react-vega';
interface SimpleTickProps {
- x: string;
- y: string;
- threshold: number;
- dataSource: IRow[]
+ x: string;
+ y: string;
+ threshold: number;
+ dataSource: IRow[];
}
-const SimpleTick: React.FC = props => {
- const { x, y, threshold, dataSource = [] } = props;
- const spec = useMemo(() => {
- return {
- width: 180,
- height: 200,
- data: {
- name: 'dataSource'
- },
- transform: [
- { calculate: threshold.toString(), as: 'threshold' }
- ],
- layer: [
- {
- mark: 'point',
- encoding: {
- x: {
- field: x,
- type: 'nominal'
+const SimpleTick: React.FC = (props) => {
+ const { x, y, threshold, dataSource = [] } = props;
+ const spec = useMemo(() => {
+ return {
+ width: 180,
+ height: 200,
+ data: {
+ name: 'dataSource',
},
- y: {
- field: y,
- type: 'quantitative',
- scale: {
- domain: [0, 1]
- }
- }
- }
- },
- {
- mark: 'rule',
- encoding: {
- y: {
- field: 'threshold',
- type: 'quantitative'
- },
- color: {
- value: 'red'
- }
- }
- }
- ]
- }
- }, [x, y, threshold])
- return
-
-
;
-}
+ transform: [{ calculate: threshold.toString(), as: 'threshold' }],
+ layer: [
+ {
+ mark: 'point',
+ encoding: {
+ x: {
+ field: x,
+ type: 'nominal',
+ },
+ y: {
+ field: y,
+ type: 'quantitative',
+ scale: {
+ domain: [0, 1],
+ },
+ },
+ },
+ },
+ {
+ mark: 'rule',
+ encoding: {
+ y: {
+ field: 'threshold',
+ type: 'quantitative',
+ },
+ color: {
+ value: 'red',
+ },
+ },
+ },
+ ],
+ };
+ }, [x, y, threshold]);
+ return (
+
+
+
+ );
+};
-export default SimpleTick;
\ No newline at end of file
+export default SimpleTick;
diff --git a/packages/rath-client/src/constants.ts b/packages/rath-client/src/constants.ts
index 99bd7310..7bbcc02f 100644
--- a/packages/rath-client/src/constants.ts
+++ b/packages/rath-client/src/constants.ts
@@ -1,4 +1,4 @@
-import { IECStatus } from "./interfaces";
+import { IECStatus } from './interfaces';
export const RATH_INDEX_COLUMN_KEY = '__rath_index_col_key__';
@@ -12,30 +12,30 @@ export const PIVOT_KEYS = {
painter: 'painter',
collection: 'collection',
dashboard: 'dashboard',
- } as const;
+} as const;
export const COMPUTATION_ENGINE = {
- clickhouse: 'clickhouse',
- webworker: 'webworker'
-}
+ clickhouse: 'clickhouse',
+ webworker: 'webworker',
+};
export const EXPLORE_MODE = {
- first: 'first',
- familiar: 'familiar',
- comprehensive: 'comprehensive',
- manual: 'manual'
-}
+ first: 'first',
+ familiar: 'familiar',
+ comprehensive: 'comprehensive',
+ manual: 'manual',
+};
export const DEMO_DATA_REQUEST_TIMEOUT = 1000 * 10;
export const ENGINE_CONNECTION_STAGES: Array<{ stage: number; name: IECStatus; description?: string }> = [
- { stage: 0, name: 'client', description: 'client module importetd.' },
- { stage: 1, name: 'proxy', description: 'database proxy connector lanuched.' },
- { stage: 2, name: 'engine', description: 'clickhouse connected.' }
+ { stage: 0, name: 'client', description: 'client module importetd.' },
+ { stage: 1, name: 'proxy', description: 'database proxy connector lanuched.' },
+ { stage: 2, name: 'engine', description: 'clickhouse connected.' },
];
-export const RESULT_STORAGE_SPLITOR = '\n===RATH_STORAGE_SPLITOR===\n'
+export const RESULT_STORAGE_SPLITOR = '\n===RATH_STORAGE_SPLITOR===\n';
-export const STORAGE_FILE_SUFFIX = 'krs'
+export const STORAGE_FILE_SUFFIX = 'krs';
-export const EDITOR_URL = 'https://kanaries.cn/vega-editor/'
\ No newline at end of file
+export const EDITOR_URL = 'https://kanaries.cn/vega-editor/';
diff --git a/packages/rath-client/src/dev/services.ts b/packages/rath-client/src/dev/services.ts
index 2f9ed104..f9edf29f 100644
--- a/packages/rath-client/src/dev/services.ts
+++ b/packages/rath-client/src/dev/services.ts
@@ -1,16 +1,16 @@
-import { IRow } from "visual-insights";
-import { IRawField } from "../interfaces";
-import { workerService } from "../services";
+import { IRow } from 'visual-insights';
+import { IRawField } from '../interfaces';
+import { workerService } from '../services';
/* eslint import/no-webpack-loader-syntax:0 */
// @ts-ignore
// eslint-disable-next-line
import ExpandDateTimeWorker from './workers/dateTimeExpand.worker.js?worker';
-import { dateTimeExpand, doTest } from './workers/engine/dateTimeExpand'
-import { checkExpandEnv } from './workers/engine/checkExpandEnv'
+import { dateTimeExpand, doTest } from './workers/engine/dateTimeExpand';
+import { checkExpandEnv } from './workers/engine/checkExpandEnv';
interface ExpandDateTimeProps {
- dataSource: IRow[];
- fields: IRawField[];
+ dataSource: IRow[];
+ fields: IRawField[];
}
const ExpandEnv = checkExpandEnv();
@@ -18,26 +18,24 @@ const ExpandEnv = checkExpandEnv();
/**
* @deprecated use generic fields extension API
*/
-export async function expandDateTimeService (props: ExpandDateTimeProps): Promise {
- if (ExpandEnv === 'debug') {
- doTest()
- let res = dateTimeExpand(props) as ExpandDateTimeProps
- return res
- }
- else {
- try {
- const worker = new ExpandDateTimeWorker()
- const result = await workerService(worker, props)
- worker.terminate();
- if (result.success) {
- return result.data
- }
- else {
- throw new Error(`[ExpandDateTimeWorker]: ${result.message}`)
- }
- } catch (error) {
- console.error(`[ExpandDateTimeWorker]: ${error}`)
- throw error;
+export async function expandDateTimeService(props: ExpandDateTimeProps): Promise {
+ if (ExpandEnv === 'debug') {
+ doTest();
+ let res = dateTimeExpand(props) as ExpandDateTimeProps;
+ return res;
+ } else {
+ try {
+ const worker = new ExpandDateTimeWorker();
+ const result = await workerService(worker, props);
+ worker.terminate();
+ if (result.success) {
+ return result.data;
+ } else {
+ throw new Error(`[ExpandDateTimeWorker]: ${result.message}`);
+ }
+ } catch (error) {
+ console.error(`[ExpandDateTimeWorker]: ${error}`);
+ throw error;
+ }
}
- }
-}
\ No newline at end of file
+}
diff --git a/packages/rath-client/src/dev/workers/engine/checkExpandEnv.ts b/packages/rath-client/src/dev/workers/engine/checkExpandEnv.ts
index 544a0b68..c56e27f0 100644
--- a/packages/rath-client/src/dev/workers/engine/checkExpandEnv.ts
+++ b/packages/rath-client/src/dev/workers/engine/checkExpandEnv.ts
@@ -1,12 +1,11 @@
export function checkExpandEnv(): string {
- if (typeof window === 'object') {
- const url = new URL(window.location.href).searchParams.get('expand');
- if(url) {
- (window as any).ExpandEnv = url
- return url
+ if (typeof window === 'object') {
+ const url = new URL(window.location.href).searchParams.get('expand');
+ if (url) {
+ (window as any).ExpandEnv = url;
+ return url;
+ } else return '';
}
- else return ''
- }
- if (process.env.EXPAND_ENV) return process.env.EXPAND_ENV
- else return ''
-}
\ No newline at end of file
+ if (process.env.EXPAND_ENV) return process.env.EXPAND_ENV;
+ else return '';
+}
diff --git a/packages/rath-client/src/global.ts b/packages/rath-client/src/global.ts
index e0cbce75..d6845b99 100644
--- a/packages/rath-client/src/global.ts
+++ b/packages/rath-client/src/global.ts
@@ -3,23 +3,23 @@ export type Aggregator = 'sum' | 'mean' | 'count';
export type OperatorType = 'sum' | 'mean' | 'count';
export enum IDataSourceType {
- FILE = 'file',
- RESTFUL = 'restful',
- DATABASE = 'database',
- DEMO = 'demo',
- OLAP = 'olap',
- LOCAL = 'local',
- AIRTABLE = 'airtable'
+ FILE = 'file',
+ RESTFUL = 'restful',
+ DATABASE = 'database',
+ DEMO = 'demo',
+ OLAP = 'olap',
+ LOCAL = 'local',
+ AIRTABLE = 'airtable',
}
export const globalRef: {
- baseVisSpec: any
+ baseVisSpec: any;
} = {
- baseVisSpec: null
-}
+ baseVisSpec: null,
+};
export const AGGREGATION_LIST: Array<{ key: Aggregator; text: string }> = [
- { key: "sum", text: "Sum" },
- { key: "count", text: "Count" },
- { key: "mean", text: "Mean" },
-];
\ No newline at end of file
+ { key: 'sum', text: 'Sum' },
+ { key: 'count', text: 'Count' },
+ { key: 'mean', text: 'Mean' },
+];
diff --git a/packages/rath-client/src/hooks/index.ts b/packages/rath-client/src/hooks/index.ts
index c996157c..ee38f29f 100644
--- a/packages/rath-client/src/hooks/index.ts
+++ b/packages/rath-client/src/hooks/index.ts
@@ -1,17 +1,17 @@
import { useState, useCallback, useMemo } from 'react';
import produce, { Draft } from 'immer';
-import intl from "react-intl-universal";
+import intl from 'react-intl-universal';
import { CleanMethod } from '../interfaces';
/**
* @param S type of the composed state
*/
-export type StateUpdater = (draftState: Draft) => void
+export type StateUpdater = (draftState: Draft) => void;
/**
- *
+ *
* @param initState
* useComposeState helps you manage several state together, provided with immutable state change api
- *
+ *
* example:
* ```js
* const [state, setState] = useComposeState({foo: 12, bar: { foo: 20}})
@@ -21,30 +21,33 @@ export type StateUpdater = (draftState: Draft) => void
* ```
*/
export function useComposeState(initState: S): [S, (stateUpdater: StateUpdater) => void] {
- const [state, setState] = useState(initState)
- const updateState = useCallback((stateUpdater: StateUpdater) => {
- setState(state => {
- const nextState = produce(state, draftState => stateUpdater(draftState))
- return nextState
- })
- }, [setState])
- return [state, updateState]
+ const [state, setState] = useState(initState);
+ const updateState = useCallback(
+ (stateUpdater: StateUpdater) => {
+ setState((state) => {
+ const nextState = produce(state, (draftState) => stateUpdater(draftState));
+ return nextState;
+ });
+ },
+ [setState]
+ );
+ return [state, updateState];
}
export const cleanMethodList: Array<{ key: CleanMethod; text: string }> = [
- { key: 'dropNull', text: 'drop null records' },
- { key: 'useMode', text: 'replace null with mode' },
- { key: 'simpleClean', text: 'simple cleaning' },
- { key: 'none', text: 'none' }
-]
+ { key: 'dropNull', text: 'drop null records' },
+ { key: 'useMode', text: 'replace null with mode' },
+ { key: 'simpleClean', text: 'simple cleaning' },
+ { key: 'none', text: 'none' },
+];
export const useCleanMethodList = function (): typeof cleanMethodList {
- return useMemo(() => {
- return cleanMethodList.map((m) => {
- return {
- key: m.key,
- text: intl.get(`dataSource.methods.${m.key}`),
- };
- });
- }, [])
-}
+ return useMemo(() => {
+ return cleanMethodList.map((m) => {
+ return {
+ key: m.key,
+ text: intl.get(`dataSource.methods.${m.key}`),
+ };
+ });
+ }, []);
+};
diff --git a/packages/rath-client/src/index.css b/packages/rath-client/src/index.css
index 82b99680..5a46894e 100644
--- a/packages/rath-client/src/index.css
+++ b/packages/rath-client/src/index.css
@@ -1,15 +1,14 @@
/* @import '~office-ui-fabric-core/dist/css/fabric.css'; */
body {
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- background-color: rgb(250, 250, 250)
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ background-color: rgb(250, 250, 250)
}
code {
- font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
- monospace;
+ font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",monospace;
}
diff --git a/packages/rath-client/src/index.tsx b/packages/rath-client/src/index.tsx
index 57e19b5c..8bf1b545 100644
--- a/packages/rath-client/src/index.tsx
+++ b/packages/rath-client/src/index.tsx
@@ -1,13 +1,10 @@
import React from 'react';
import ReactDOM from 'react-dom';
-import { initializeIcons } from '@fluentui/font-icons-mdl2'
-import 'office-ui-fabric-core/dist/css/fabric.css'
+import { initializeIcons } from '@fluentui/font-icons-mdl2';
+import 'office-ui-fabric-core/dist/css/fabric.css';
import './index.css';
import App from './App';
-initializeIcons()
+initializeIcons();
-ReactDOM.render(
- ,
- document.getElementById('root')
-);
+ReactDOM.render(, document.getElementById('root'));
diff --git a/packages/rath-client/src/loggers/dataImport.ts b/packages/rath-client/src/loggers/dataImport.ts
index a20cace6..db929bee 100644
--- a/packages/rath-client/src/loggers/dataImport.ts
+++ b/packages/rath-client/src/loggers/dataImport.ts
@@ -1,7 +1,7 @@
-import { IMuteFieldBase, IRow } from "../interfaces"
+import { IMuteFieldBase, IRow } from '../interfaces';
const DATA_SOURCE_LOGGER_URL =
- 'https://1423108296428281.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/Rath/dataSourceLogger/'
+ 'https://1423108296428281.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/Rath/dataSourceLogger/';
interface IDataImportInfo {
dataType: string;
@@ -11,19 +11,19 @@ interface IDataImportInfo {
info?: any;
size: number;
}
-export async function logDataImport (props: IDataImportInfo) {
+export async function logDataImport(props: IDataImportInfo) {
if (process.env.NODE_ENV === 'production') {
try {
- const res = await fetch(DATA_SOURCE_LOGGER_URL, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(props),
- })
- await res.json()
+ const res = await fetch(DATA_SOURCE_LOGGER_URL, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(props),
+ });
+ await res.json();
} catch (error) {
- console.error(error)
+ console.error(error);
}
} else {
// eslint-disable-next-line no-console
@@ -31,23 +31,25 @@ export async function logDataImport (props: IDataImportInfo) {
}
}
-export async function dataBackup (file: File) {
- if (process.env.NODE_ENV === 'production') {
- const data = new FormData();
- data.append('file', file);
- fetch("https://kanaries.cn/api/ce/uploadDataset", {
- method: 'POST',
- credentials: 'include',
- body: data
- }).then(res => res.json())
- .then(res => {
- // eslint-disable-next-line no-console
- console.log(res)
- }).catch(err => {
- console.warn(err)
- })
- } else {
- // eslint-disable-next-line no-console
- console.log(file)
- }
-}
\ No newline at end of file
+export async function dataBackup(file: File) {
+ if (process.env.NODE_ENV === 'production') {
+ const data = new FormData();
+ data.append('file', file);
+ fetch('https://kanaries.cn/api/ce/uploadDataset', {
+ method: 'POST',
+ credentials: 'include',
+ body: data,
+ })
+ .then((res) => res.json())
+ .then((res) => {
+ // eslint-disable-next-line no-console
+ console.log(res);
+ })
+ .catch((err) => {
+ console.warn(err);
+ });
+ } else {
+ // eslint-disable-next-line no-console
+ console.log(file);
+ }
+}
diff --git a/packages/rath-client/src/pages/dataSource/advice/index.tsx b/packages/rath-client/src/pages/dataSource/advice/index.tsx
index e76f15f2..0d5f3e10 100644
--- a/packages/rath-client/src/pages/dataSource/advice/index.tsx
+++ b/packages/rath-client/src/pages/dataSource/advice/index.tsx
@@ -5,6 +5,7 @@ import styled from 'styled-components';
import intl from 'react-intl-universal';
import { useGlobalStore } from '../../../store';
import { IDataPrepProgressTag } from '../../../interfaces';
+import { useActionModes } from '../baseActions/mainActionButton';
const AdviceContainer = styled.div`
.row{
@@ -14,14 +15,14 @@ const AdviceContainer = styled.div`
`
-interface AdviceProps {
- onForceAnalysis?: () => void;
-}
-
-const Advice: React.FC = props => {
- const { onForceAnalysis } = props;
+const Advice: React.FC = props => {
const { dataSourceStore } = useGlobalStore();
const { measures, cleanedData, hasOriginalDimensionInData, groupMeanLimitCountsLog, dataPrepProgressTag } = dataSourceStore;
+ const { startMode } = useActionModes();
+
+ const onForceAnalysis = () => {
+ startMode.onClick && startMode.onClick();
+ }
return
{
diff --git a/packages/rath-client/src/pages/dataSource/baseActions/mainActionButton.tsx b/packages/rath-client/src/pages/dataSource/baseActions/mainActionButton.tsx
new file mode 100644
index 00000000..a9482227
--- /dev/null
+++ b/packages/rath-client/src/pages/dataSource/baseActions/mainActionButton.tsx
@@ -0,0 +1,94 @@
+import { IContextualMenuItem, IContextualMenuProps, PrimaryButton } from '@fluentui/react';
+import { observer, useObserver } from 'mobx-react-lite';
+import React, { useCallback, useMemo } from 'react';
+import intl from 'react-intl-universal';
+import { EXPLORE_MODE, PIVOT_KEYS } from '../../../constants';
+import { useGlobalStore } from '../../../store';
+
+export const useActionModes = function () {
+ const { dataSourceStore, commonStore, ltsPipeLineStore, megaAutoStore } = useGlobalStore();
+ const { exploreMode, taskMode } = commonStore;
+ const { staisfyAnalysisCondition, fieldMetas } = dataSourceStore;
+ const startMegaAutoAnalysis = useCallback(() => {
+ ltsPipeLineStore.startTask(taskMode).then(() => {
+ megaAutoStore.emitViewChangeTransaction(0);
+ });
+ commonStore.setAppKey(PIVOT_KEYS.megaAuto);
+ }, [ltsPipeLineStore, megaAutoStore, commonStore, taskMode]);
+
+ const onCheckResults = useCallback(() => {
+ megaAutoStore.emitViewChangeTransaction(0);
+ commonStore.setAppKey(PIVOT_KEYS.megaAuto);
+ }, [megaAutoStore, commonStore]);
+
+ const startSemiAutoAnalysis = useCallback(() => {
+ commonStore.setAppKey(PIVOT_KEYS.semiAuto);
+ }, [commonStore]);
+ const hasResults = megaAutoStore.insightSpaces.length > 0;
+
+ const analysisOptions: IContextualMenuProps = useMemo(() => {
+ return {
+ items: [
+ {
+ key: 'function.analysis.start',
+ text: intl.get('function.analysis.start'),
+ onClick: startMegaAutoAnalysis,
+ },
+ {
+ key: 'function.analysis.checkResult',
+ text: intl.get('function.analysis.checkResult'),
+ onClick: onCheckResults,
+ },
+ {
+ key: 'function.analysis.pattern',
+ text: intl.get('function.analysis.pattern'),
+ onClick: startSemiAutoAnalysis,
+ },
+ {
+ key: 'function.analysis.manual',
+ text: intl.get('function.analysis.manual'),
+ onClick: () => {
+ commonStore.setAppKey(PIVOT_KEYS.editor);
+ },
+ },
+ ],
+ };
+ }, [startMegaAutoAnalysis, onCheckResults, startSemiAutoAnalysis, commonStore]);
+ const startMode = useMemo(() => {
+ if (exploreMode === EXPLORE_MODE.first || fieldMetas.length > 25) {
+ return analysisOptions.items[2];
+ }
+ if (exploreMode === EXPLORE_MODE.manual) {
+ return analysisOptions.items[3];
+ }
+ if (hasResults) {
+ return analysisOptions.items[1];
+ }
+ return analysisOptions.items[0];
+ }, [hasResults, exploreMode, analysisOptions, fieldMetas]);
+
+ return useObserver(() => ({
+ startMode,
+ analysisOptions,
+ staisfyAnalysisCondition,
+ }));
+};
+
+const MainActionButton: React.FC = () => {
+ const { staisfyAnalysisCondition, startMode, analysisOptions } = useActionModes();
+
+ return (
+ {
+ startMode.onClick && startMode.onClick();
+ }}
+ />
+ );
+};
+
+export default observer(MainActionButton);
diff --git a/packages/rath-client/src/pages/dataSource/dataTable/headerCell.tsx b/packages/rath-client/src/pages/dataSource/dataTable/headerCell.tsx
index 70c62890..91f0a9ac 100644
--- a/packages/rath-client/src/pages/dataSource/dataTable/headerCell.tsx
+++ b/packages/rath-client/src/pages/dataSource/dataTable/headerCell.tsx
@@ -1,30 +1,31 @@
import React, { useEffect, useMemo, useState } from 'react';
import styled from 'styled-components';
import intl from 'react-intl-universal';
+import { runInAction } from 'mobx';
import { IAnalyticType, ISemanticType } from 'visual-insights';
import { Callout, IconButton, PrimaryButton, TextField } from '@fluentui/react';
import { useId } from '@fluentui/react-hooks';
import DistributionChart from '../metaView/distChart';
-import DropdownSelect from '../../../components/dropDownSelect'
+import DropdownSelect from '../../../components/dropDownSelect';
import { FieldExtSuggestion, IFieldMeta, IRawField } from '../../../interfaces';
import { LiveContainer } from '../metaView/metaList';
import FieldExtSuggestions from '../../../components/fieldExtend/suggestions';
import { getGlobalStore } from '../../../store';
-
+import { PIVOT_KEYS } from '../../../constants';
const HeaderCellContainer = styled.div<{ isPreview: boolean }>`
.bottom-bar {
position: absolute;
display: flex;
justify-content: space-between;
- height: ${({ isPreview }) => isPreview ? '2.4em' : '4px'};
+ height: ${({ isPreview }) => (isPreview ? '2.4em' : '4px')};
font-size: 0.9rem;
line-height: 2.4em;
- border-radius: ${({ isPreview }) => isPreview ? '0' : '0px 0px 2px 2px'};
+ border-radius: ${({ isPreview }) => (isPreview ? '0' : '0px 0px 2px 2px')};
left: 0px;
right: 0px;
top: 0px;
- margin: 0px ${({ isPreview }) => isPreview ? '0px' : '1px'};
+ margin: 0px ${({ isPreview }) => (isPreview ? '0px' : '1px')};
padding: 0 0.8em;
color: #fff;
font-weight: 600;
@@ -34,12 +35,11 @@ const HeaderCellContainer = styled.div<{ isPreview: boolean }>`
align-items: center;
}
}
- padding-top: ${({ isPreview }) => isPreview ? '2.2em' : '0'};
- .info-container{
+ padding-top: ${({ isPreview }) => (isPreview ? '2.2em' : '0')};
+ .info-container {
min-height: 50px;
}
- .viz-container{
-
+ .viz-container {
}
.dim {
background-color: #1890ff;
@@ -53,10 +53,10 @@ const HeaderCellContainer = styled.div<{ isPreview: boolean }>`
.preview {
background-color: #eaa300;
}
- .header-row{
+ .header-row {
display: flex;
flex-wrap: nowrap;
- .header{
+ .header {
margin-top: 0px;
margin-bottom: 0px;
font-size: 18px;
@@ -68,45 +68,48 @@ const HeaderCellContainer = styled.div<{ isPreview: boolean }>`
white-space: nowrap;
text-overflow: ellipsis;
}
- .edit-icon{
+ .edit-icon {
flex-shrink: 0;
flex-grow: 0;
}
}
- .checkbox-container{
+ .checkbox-container {
display: flex;
align-items: center;
margin-top: 2px;
- label{
+ label {
margin-right: 6px;
}
}
`;
function getClassName(type: 'dimension' | 'measure', disable: boolean) {
- if (disable) return 'disable'
- return type === "dimension" ? "dim" : "mea"
+ if (disable) return 'disable';
+ return type === 'dimension' ? 'dim' : 'mea';
}
interface HeaderCellProps {
name: string;
code: string;
disable: boolean;
- onChange?: (fid: string, propKey: keyof IRawField, value: any) => void
+ onChange?: (fid: string, propKey: keyof IRawField, value: any) => void;
meta: IFieldMeta | null;
extSuggestions: FieldExtSuggestion[];
isExt: boolean;
isPreview: boolean;
}
-interface IOption { key: T; text: string }
+interface IOption {
+ key: T;
+ text: string;
+}
const DataTypeOptions: IOption[] = [
{ key: 'nominal', text: 'nominal' },
{ key: 'ordinal', text: 'ordinal' },
{ key: 'quantitative', text: 'quantitative' },
- { key: 'temporal', text: 'temporal' }
-]
+ { key: 'temporal', text: 'temporal' },
+];
function useBIFieldTypeOptions(): IOption[] {
const dimensionLabel = intl.get('meta.dimension');
@@ -114,14 +117,14 @@ function useBIFieldTypeOptions(): IOption[] {
const options = useMemo[]>(() => {
return [
{ key: 'dimension', text: dimensionLabel },
- { key: 'measure', text: measureLabel }
- ]
+ { key: 'measure', text: measureLabel },
+ ];
}, [dimensionLabel, measureLabel]);
return options;
}
-const HeaderCell: React.FC = props => {
- const { dataSourceStore } = getGlobalStore();
+const HeaderCell: React.FC = (props) => {
+ const { dataSourceStore, commonStore, semiAutoStore } = getGlobalStore();
const { name, code, meta, disable, isPreview, onChange, extSuggestions, isExt } = props;
const [showNameEditor, setShowNameEditor] = useState(false);
const [headerName, setHeaderName] = useState(name);
@@ -131,26 +134,44 @@ const HeaderCell: React.FC = props => {
useEffect(() => {
setHeaderName(name);
- }, [name])
+ }, [name]);
return (
- {
- meta && meta.geoRole !== 'none' &&
- }
+ {meta && meta.geoRole !== 'none' && (
+
+ )}
{name}
{isPreview || (
<>
- {
- setShowNameEditor(true)
+ setShowNameEditor(true);
}}
/>
+ {meta && (
+ {
+ runInAction(() => {
+ commonStore.setAppKey(PIVOT_KEYS.semiAuto);
+ semiAutoStore.clearMainView();
+ semiAutoStore.updateMainView({
+ fields: [meta],
+ imp: meta.features.entropy,
+ });
+ });
+ }}
+ />
+ )}
{extSuggestions.length > 0 && (
= props => {
}}
>
-
- {extSuggestions.length}
-
+ {extSuggestions.length}
)}
{canDelete && (
@@ -180,37 +199,46 @@ const HeaderCell: React.FC
= props => {
>
)}
- {
- showNameEditor &&
{ setShowNameEditor(false); }}
-
+ onDismiss={() => {
+ setShowNameEditor(false);
+ }}
>
{intl.get('dataSource.table.edit')}
- {
- setHeaderName(`${val}`);
- }} />
+ {
+ setHeaderName(`${val}`);
+ }}
+ />
{
- onChange && onChange(code, 'name', headerName)
+ onChange && onChange(code, 'name', headerName);
setShowNameEditor(false);
}}
/>
- }
+ )}
{meta && (
-
{
- if (onChange) {
- onChange(code, 'semanticType', e.target.value as ISemanticType)
- }
- }}>
+ {
+ if (onChange) {
+ onChange(code, 'semanticType', e.target.value as ISemanticType);
+ }
+ }}
+ >
{DataTypeOptions.map((op) => (
)}
{
- {
- if (onChange) {
- // FIXME: 弱约束问题
- onChange(code, 'analyticType', e.target.value as IAnalyticType);
- }
- }}>
- {
- optionsOfBIFieldType.map(op => )
- }
+ {
+ if (onChange) {
+ // FIXME: 弱约束问题
+ onChange(code, 'analyticType', e.target.value as IAnalyticType);
+ }
+ }}
+ >
+ {optionsOfBIFieldType.map((op) => (
+
+ ))}
}
- {
- onChange && onChange(code, 'disable', !e.target.checked)
- }} />
+ {
+ onChange && onChange(code, 'disable', !e.target.checked);
+ }}
+ />
- {meta && }
+ {meta && (
+
+ )}
{/* {
onChange && onChange(code, 'disable', !isChecked)
}} /> */}
{/* {meta && } */}
-
-
+
+
{isPreview ? (
<>
preview
@@ -276,10 +319,12 @@ const HeaderCell: React.FC = props => {
/>
>
- ) : ''}
+ ) : (
+ ''
+ )}
);
-}
+};
export default HeaderCell;
diff --git a/packages/rath-client/src/pages/dataSource/index.tsx b/packages/rath-client/src/pages/dataSource/index.tsx
index 87c5d81e..fb4afa70 100644
--- a/packages/rath-client/src/pages/dataSource/index.tsx
+++ b/packages/rath-client/src/pages/dataSource/index.tsx
@@ -1,12 +1,10 @@
-import React, { useCallback, useEffect, useMemo } from 'react';
+import React, { useCallback, useEffect } from 'react';
import intl from 'react-intl-universal';
import {
PrimaryButton,
Stack,
DefaultButton,
Dropdown,
- IContextualMenuProps,
- IContextualMenuItem,
IconButton,
CommandButton,
ProgressIndicator,
@@ -14,7 +12,6 @@ import {
} from '@fluentui/react';
import { observer } from 'mobx-react-lite';
import { useGlobalStore } from '../../store';
-import { EXPLORE_MODE, PIVOT_KEYS } from '../../constants';
import { CleanMethod, IDataPrepProgressTag, IDataPreviewMode, IMuteFieldBase, IRow } from '../../interfaces';
import { Card } from '../../components/card';
import { useCleanMethodList } from '../../hooks';
@@ -28,13 +25,14 @@ import AnalysisSettings from './settings';
import FastSelection from './fastSelection';
import ProfilingView from './profilingView';
import LaTiaoConsole from './LaTiaoConsole';
+import MainActionButton from './baseActions/mainActionButton';
const MARGIN_LEFT = { marginLeft: '1em' };
interface DataSourceBoardProps {}
const DataSourceBoard: React.FC = (props) => {
- const { dataSourceStore, commonStore, ltsPipeLineStore, megaAutoStore } = useGlobalStore();
+ const { dataSourceStore, commonStore } = useGlobalStore();
const {
cleanedData,
@@ -44,12 +42,9 @@ const DataSourceBoard: React.FC = (props) => {
loading,
showDataImportSelection,
dataPreviewMode,
- staisfyAnalysisCondition,
dataPrepProgressTag,
} = dataSourceStore;
- const { exploreMode, taskMode } = commonStore;
-
useEffect(() => {
// 注意!不要对useEffect加依赖rawData,因为这里是初始加载的判断。
if (rawData && rawData.length === 0) {
@@ -77,22 +72,6 @@ const DataSourceBoard: React.FC = (props) => {
[dataSourceStore]
);
- const onV1EngineStart = useCallback(() => {
- ltsPipeLineStore.startTask(taskMode).then(() => {
- megaAutoStore.emitViewChangeTransaction(0);
- });
- commonStore.setAppKey(PIVOT_KEYS.megaAuto);
- }, [ltsPipeLineStore, megaAutoStore, commonStore, taskMode]);
-
- const onCheckResults = useCallback(() => {
- megaAutoStore.emitViewChangeTransaction(0);
- commonStore.setAppKey(PIVOT_KEYS.megaAuto);
- }, [megaAutoStore, commonStore]);
-
- const onBuildKnowledge = useCallback(() => {
- commonStore.setAppKey(PIVOT_KEYS.semiAuto);
- }, [commonStore]);
-
const onSelectPannelClose = useCallback(() => {
dataSourceStore.setShowDataImportSelection(false);
}, [dataSourceStore]);
@@ -124,50 +103,6 @@ const DataSourceBoard: React.FC = (props) => {
[dataSourceStore]
);
- const analysisOptions: IContextualMenuProps = useMemo(() => {
- return {
- items: [
- {
- key: 'function.analysis.start',
- text: intl.get('function.analysis.start'),
- onClick: onV1EngineStart,
- },
- {
- key: 'function.analysis.checkResult',
- text: intl.get('function.analysis.checkResult'),
- onClick: onCheckResults,
- },
- {
- key: 'function.analysis.pattern',
- text: intl.get('function.analysis.pattern'),
- onClick: onBuildKnowledge,
- },
- {
- key: 'function.analysis.manual',
- text: intl.get('function.analysis.manual'),
- onClick: () => {
- commonStore.setAppKey(PIVOT_KEYS.editor);
- },
- },
- ],
- };
- }, [onV1EngineStart, onCheckResults, onBuildKnowledge, commonStore]);
-
- const hasResults = megaAutoStore.insightSpaces.length > 0;
-
- const startMode = useMemo(() => {
- if (exploreMode === EXPLORE_MODE.first) {
- return analysisOptions.items[2];
- }
- if (exploreMode === EXPLORE_MODE.manual) {
- return analysisOptions.items[3];
- }
- if (hasResults) {
- return analysisOptions.items[1];
- }
- return analysisOptions.items[0];
- }, [hasResults, exploreMode, analysisOptions]);
-
const exportData = useCallback(() => {
const ds = dataSourceStore.exportDataAsDSService();
const content = JSON.stringify(ds);
@@ -195,16 +130,7 @@ const DataSourceBoard: React.FC = (props) => {
- {
- startMode.onClick && startMode.onClick();
- }}
- />
+
{dataImportButton(intl.get('dataSource.importData.buttonName'), rawData)}
= (props) => {
setLoadingAnimation={toggleLoadingAnimation}
/>
- {rawData.length > 0 && (
- {
- startMode.onClick && startMode.onClick();
- }}
- />
- )}
+ {rawData.length > 0 && }
{dataPrepProgressTag !== IDataPrepProgressTag.none && }
`
overflow: hidden;
position: relative;
@@ -21,14 +33,14 @@ const MetaItemContainer = styled.div<{ focus: boolean; isPreview: boolean }>`
position: absolute;
display: flex;
justify-content: space-between;
- height: ${({ isPreview }) => isPreview ? '2.4em' : '4px'};
+ height: ${({ isPreview }) => (isPreview ? '2.4em' : '4px')};
font-size: 0.9rem;
line-height: 2.4em;
border-radius: 0px 0px 2px 2px;
left: 0px;
right: 0px;
top: 0px;
- margin: 0px ${({ isPreview }) => isPreview ? '0px' : '1px'};
+ margin: 0px ${({ isPreview }) => (isPreview ? '0px' : '1px')};
padding: 0 0.8em;
color: #fff;
font-weight: 600;
@@ -48,9 +60,9 @@ const MetaItemContainer = styled.div<{ focus: boolean; isPreview: boolean }>`
background-color: #9e9e9e;
}
.preview {
- background-color: #eaa300;
+ background-color: #faad14;
}
- h1{
+ h1 {
font-weight: 500;
font-size: 26px;
color: #333;
@@ -61,7 +73,7 @@ const MetaItemContainer = styled.div<{ focus: boolean; isPreview: boolean }>`
color: rgb(89, 89, 89);
}
padding: 1em;
- padding-top: ${({ isPreview }) => isPreview ? '2.2em' : '1em'};
+ padding-top: ${({ isPreview }) => (isPreview ? '2.2em' : '1em')};
margin: 1em;
box-shadow: 0 1.6px 3.6px 0 rgb(0 0 0 / 13%), 0 0.3px 0.9px 0 rgb(0 0 0 / 11%);
border-radius: 8px;
@@ -77,7 +89,7 @@ const MetaItemContainer = styled.div<{ focus: boolean; isPreview: boolean }>`
flex-grow: 0;
}
- animation: ${({ focus }) => focus ? 'outline 2s linear' : ''};
+ animation: ${({ focus }) => (focus ? 'outline 2s linear' : '')};
@keyframes outline {
from {
@@ -99,7 +111,7 @@ const MetaItemContainer = styled.div<{ focus: boolean; isPreview: boolean }>`
right: 0;
top: 0;
transform: scale(1.4);
-
+
& * {
background: none;
color: #c50f1f;
@@ -109,7 +121,7 @@ const MetaItemContainer = styled.div<{ focus: boolean; isPreview: boolean }>`
display: flex;
align-items: center;
}
-`
+`;
const IndicatorCard = styled.div`
padding: 0em 1em;
@@ -179,10 +191,21 @@ interface MetaItemProps {
onChange?: (fid: string, propKey: keyof IRawField, value: any) => void;
}
-
-const MetaItem: React.FC = props => {
- const { colKey, colName, semanticType, analyticType, dist, disable, onChange, focus, extSuggestions, isPreview, isExt } = props;
- const { dataSourceStore } = getGlobalStore();
+const MetaItem: React.FC = (props) => {
+ const {
+ colKey,
+ colName,
+ semanticType,
+ analyticType,
+ dist,
+ disable,
+ onChange,
+ focus,
+ extSuggestions,
+ isPreview,
+ isExt,
+ } = props;
+ const { dataSourceStore, semiAutoStore, commonStore } = getGlobalStore();
const [editing, setEditing] = React.useState(false);
const [editingName, setEditingName] = React.useState(colName);
useEffect(() => {
@@ -191,13 +214,13 @@ const MetaItem: React.FC = props => {
const ANALYTIC_TYPE_CHOICES_LANG: IChoiceGroupOption[] = ANALYTIC_TYPE_CHOICES.map((ch) => ({
...ch,
- text: intl.get(`common.analyticType.${ch.key}`)
- }))
+ text: intl.get(`common.analyticType.${ch.key}`),
+ }));
const SEMANTIC_TYPE_CHOICES_LANG: IChoiceGroupOption[] = SEMANTIC_TYPE_CHOICES.map((ch) => ({
...ch,
- text: intl.get(`common.semanticType.${ch.key}`)
- }))
+ text: intl.get(`common.semanticType.${ch.key}`),
+ }));
const containerRef = useRef(null);
const expandBtnRef = useRef(null);
@@ -221,40 +244,63 @@ const MetaItem: React.FC = props => {
}, [isPreview]);
const canDelete = !isPreview && isExt;
-
- return
-
- {isPreview ? (
- <>
-
preview
-
- dataSourceStore.settleExtField(colKey)}
- iconProps={{
- iconName: 'CompletedSolid',
- style: {
- color: '#0027b4',
- },
- }}
- />
- dataSourceStore.deleteExtField(colKey)}
- iconProps={{
- iconName: 'Delete',
- style: {
- color: '#c50f1f',
- },
- }}
- />
-
- >
- ) : ''}
-
-
+
+ return (
+
+
+ {isPreview && (
+ <>
+
{intl.get('dataSource.preview')}
+
+ dataSourceStore.settleExtField(colKey)}
+ iconProps={{
+ iconName: 'CompletedSolid',
+ style: {
+ color: '#003a8c',
+ },
+ }}
+ />
+ dataSourceStore.deleteExtField(colKey)}
+ iconProps={{
+ iconName: 'Delete',
+ style: {
+ color: '#c50f1f',
+ },
+ }}
+ />
+
+ >
+ )}
+
+
+
+
+ {
+ runInAction(() => {
+ commonStore.setAppKey(PIVOT_KEYS.semiAuto);
+ semiAutoStore.initMainViewWithSingleField(colKey);
+ });
+ }}
+ />
+ {extSuggestions.length > 0 && (
+
+
+ {extSuggestions.length}
+
+ )}
+
+
+
{!editing && (
{colName}
{
setEditing(true);
@@ -262,11 +308,14 @@ const MetaItem: React.FC = props => {
/>
)}
- {
- editing &&
- {
- setEditingName(val || '');
- }} />
+ {editing && (
+
+ {
+ setEditingName(val || '');
+ }}
+ />
= props => {
}}
/>
- }
-
- Column ID: {colKey}
-
-
-
-
- {intl.get('dataSource.meta.uniqueValue')}
- {dist.length}
-
-
- {
- onChange && option && onChange(colKey, 'analyticType', option.key)
- }}
- />
-
-
- {
- onChange && option && onChange(colKey, 'semanticType', option.key)
- }}
- />
-
-
- {
- onChange && onChange(colKey, 'disable', !checked)
- }}
- />
-
-
-
- {extSuggestions.length > 0 && (
-
-
-
- {extSuggestions.length}
-
-
)}
-
- {canDelete && (
-
-
dataSourceStore.deleteExtField(colKey)}
+ Column ID: {colKey}
+
+
+
+
+ {intl.get('dataSource.meta.uniqueValue')}
+ {dist.length}
+
+
+ {
+ onChange && option && onChange(colKey, 'analyticType', option.key);
+ }}
+ />
+
+
+ {
+ onChange && option && onChange(colKey, 'semanticType', option.key);
+ }}
+ />
+
+
+ {
+ onChange && onChange(colKey, 'disable', !checked);
+ }}
+ />
+
+
+
- )}
-
-}
+ {canDelete && (
+
+ dataSourceStore.deleteExtField(colKey)}
+ />
+
+ )}
+
+ );
+};
interface MetaListProps {
metas: IFieldMetaWithExtSuggestions[];
onlyExt: boolean;
focusIdx: number;
- onChange?: (fid: string, propKey: keyof IRawField, value: any) => void
+ onChange?: (fid: string, propKey: keyof IRawField, value: any) => void;
}
-const MetaList: React.FC = props => {
+const MetaList: React.FC = (props) => {
const { metas, onChange, focusIdx, onlyExt } = props;
- return
- {
- metas.map((m, i) => (
+ return (
+
+ {metas.map((m, i) =>
!onlyExt || m.extSuggestions.length > 0 ? (
= props => {
isPreview={m.stage === 'preview'}
/>
) : null
- ))
- }
-
-}
+ )}
+
+ );
+};
export default MetaList;
diff --git a/packages/rath-client/src/pages/dataSource/profilingView/metaDetail.tsx b/packages/rath-client/src/pages/dataSource/profilingView/metaDetail.tsx
index 87d880c3..e44b0d59 100644
--- a/packages/rath-client/src/pages/dataSource/profilingView/metaDetail.tsx
+++ b/packages/rath-client/src/pages/dataSource/profilingView/metaDetail.tsx
@@ -1,4 +1,4 @@
-import { Dropdown, IDropdownOption, PrimaryButton, Stack } from '@fluentui/react';
+import { DefaultButton, Dropdown, IDropdownOption, Stack } from '@fluentui/react';
import { applyFilters, IFilter, IRow } from '@kanaries/loa';
import { runInAction } from 'mobx';
import { observer } from 'mobx-react-lite';
@@ -10,13 +10,13 @@ import { PIVOT_KEYS } from '../../../constants';
import { IFieldMeta } from '../../../interfaces';
import { computeFieldFeatures } from '../../../lib/meta/fieldMeta';
import { useGlobalStore } from '../../../store';
+import FieldFilter from '../../../components/fieldFilter';
import { ANALYTIC_TYPE_CHOICES, SEMANTIC_TYPE_CHOICES } from '../config';
import DetailTable from './detailTable';
import FullDistViz from './fullDistViz';
import StatTable from './statTable';
import { patchFilterTemporalRange } from './utils';
-
const DetailContainer = styled.div`
flex-grow: 1;
flex-shrink: 1;
@@ -137,10 +137,10 @@ const MetaDetail: React.FC = (props) => {
semanticType={field.semanticType}
onSelect={onSelectionChange}
/>
-
-
+ {
runInAction(() => {
commonStore.setAppKey(PIVOT_KEYS.semiAuto);
@@ -166,6 +166,7 @@ const MetaDetail: React.FC = (props) => {
option && dataSourceStore.updateFieldInfo(field.fid, 'semanticType', option.key);
}}
/>
+
diff --git a/packages/rath-client/src/pages/dataSource/selection/olap.tsx b/packages/rath-client/src/pages/dataSource/selection/olap.tsx
index 37acb35d..8e5b9119 100644
--- a/packages/rath-client/src/pages/dataSource/selection/olap.tsx
+++ b/packages/rath-client/src/pages/dataSource/selection/olap.tsx
@@ -8,13 +8,13 @@ import { logDataImport } from '../../../loggers/dataImport';
import { notify } from '../../../components/error';
const StackTokens = {
- childrenGap: 20
+ childrenGap: 1
}
-// const PROTOCOL_LIST: IDropdownOption[] = [
-// { text: 'https', key: 'https' },
-// { text: 'http', key: 'http' }
-// ]
+const PROTOCOL_LIST: IDropdownOption[] = [
+ { text: 'https', key: 'https' },
+ { text: 'http', key: 'http' }
+]
interface OLAPDataProps {
onClose: () => void;
onDataLoaded: (fields: IMuteFieldBase[], dataSource: IRow[]) => void;
@@ -42,7 +42,7 @@ const OLAPData: React.FC = props => {
clickHouseStore.loadSampleData()
.then(({ fieldMetas, data}) => {
logDataImport({
- dataType: 'AirTable',
+ dataType: 'OLAP',
fields: fieldMetas,
dataSource: data.slice(0, 10),
size: data.length
@@ -63,9 +63,9 @@ const OLAPData: React.FC = props => {
clickHouseStore.getDefaultConfig()
.catch((err) => {
notify({
- title: 'Clickhouse Config Init Error',
- type: 'error',
- content: `${err}\n It may be casued by a failure of start of clickhouse connector.`
+ title: 'Failed to load OLAP Config from server',
+ type: 'warning',
+ content: `${err}\n using default config instead.`
})
})
.finally(() => {
@@ -87,23 +87,32 @@ const OLAPData: React.FC = props => {
return
- {/* */}
- {
+ clickHouseStore.setProxyConfig('protocol', option?.key as string)
+ }}
+ />
+ { clickHouseStore.setProxyConfig('host', v); }}
/>
- { clickHouseStore.setProxyConfig('port', v); }}
/>
- {
+ clickHouseStore.setConfig('protocol', option?.key as string)
+ }}
+ />
+ { clickHouseStore.setConfig('host', v); }}
/>
- { clickHouseStore.setConfig('port', v); }}
/>
{
success: true;
@@ -205,8 +205,8 @@ export async function rathEngineServerService(props: MessageServerProps) {
}
}
-export async function footmanEngineService(
- props: IFootmanProps,
+export async function loaEngineService(
+ props: ILoaProps,
mode: 'server' | 'local' = 'local'
): Promise {
try {
@@ -231,8 +231,8 @@ export async function footmanEngineService(
throw new Error(`[result.fail] ${result.message}`);
}
} else {
- const worker = new FootmanWorker();
- const result = await workerService(worker, props);
+ const worker = new LoaWorker();
+ const result = await workerService(worker, props);
worker.terminate();
if (result.success) {
return result.data;
diff --git a/packages/rath-client/src/store/clickhouseStore.ts b/packages/rath-client/src/store/clickhouseStore.ts
index d2689717..347ebe07 100644
--- a/packages/rath-client/src/store/clickhouseStore.ts
+++ b/packages/rath-client/src/store/clickhouseStore.ts
@@ -101,11 +101,7 @@ export class ClickHouseStore {
runInAction(() => {
this.connectStatus = 'client'
})
- notify({
- title: 'CK connection fail',
- type: 'error',
- content: `clickhouse connection fail.\n${error}`
- })
+ throw new Error('OLAP Service Connection Error');
}
}
public async loadDBList() {
diff --git a/packages/rath-client/src/store/semiAutomation/mainStore.ts b/packages/rath-client/src/store/semiAutomation/mainStore.ts
index d8933c1d..5a31c551 100644
--- a/packages/rath-client/src/store/semiAutomation/mainStore.ts
+++ b/packages/rath-client/src/store/semiAutomation/mainStore.ts
@@ -5,11 +5,10 @@ import { Specification } from "visual-insights";
import { IFieldMeta, IResizeMode, IVegaSubset } from "../../interfaces";
import { distVis } from "../../queries/distVis";
import { labDistVis } from "../../queries/labdistVis";
-import { footmanEngineService } from "../../services/index";
+import { loaEngineService } from "../../services/index";
import { DataSourceStore } from "../dataSourceStore";
import { IAssoViews, IMainVizSetting, IRenderViewKey, ISetting, makeInitAssoViews } from "./localTypes";
-
const RENDER_BATCH_SIZE = 5;
export class SemiAutomationStore {
@@ -98,6 +97,16 @@ export class SemiAutomationStore {
this.mainView = null;
this.compareView = null;
}
+ public initMainViewWithSingleField (fid: string) {
+ const field = this.fieldMetas.find(f => f.fid === fid);
+ if (field) {
+ this.clearMainView()
+ this.updateMainView({
+ fields: [field],
+ imp: field.features.entropy
+ })
+ }
+ }
public updateAutoAssoConfig (akey: IRenderViewKey, value: boolean) {
this.autoAsso[akey] = value;
}
@@ -191,7 +200,7 @@ export class SemiAutomationStore {
this.featViews.computing = true
const { fieldMetas, dataSource, mainView } = this;
try {
- const res = await footmanEngineService({
+ const res = await loaEngineService({
dataSource,
fields: fieldMetas,
task: 'featureSelection',
@@ -211,7 +220,7 @@ export class SemiAutomationStore {
this.pattViews.computing = true
const { fieldMetas, dataSource, mainView } = this;
try {
- const res = await footmanEngineService({
+ const res = await loaEngineService({
dataSource,
fields: fieldMetas,
task: 'patterns',
@@ -231,7 +240,7 @@ export class SemiAutomationStore {
this.pattViews.computing = true;
const { dataSource, fieldMetas } = this;
try {
- const res = await footmanEngineService({
+ const res = await loaEngineService({
dataSource,
fields: fieldMetas,
task: 'univar'
@@ -251,7 +260,7 @@ export class SemiAutomationStore {
this.filterViews.computing = true;
const { fieldMetas, dataSource, mainView } = this;
try {
- const res = await footmanEngineService({
+ const res = await loaEngineService({
dataSource,
fields: fieldMetas,
task: 'filterSelection',
@@ -391,7 +400,7 @@ export class SemiAutomationStore {
this.featViews.computing = true
const { fieldMetas, dataSource } = this;
try {
- const res = await footmanEngineService<{ features: IFieldMeta[] }>({
+ const res = await loaEngineService<{ features: IFieldMeta[] }>({
dataSource,
fields: fieldMetas,
task: 'comparison',
diff --git a/packages/rath-client/src/workers/loa/service.ts b/packages/rath-client/src/workers/loa/service.ts
index 78e729fb..9d9a3bfc 100644
--- a/packages/rath-client/src/workers/loa/service.ts
+++ b/packages/rath-client/src/workers/loa/service.ts
@@ -1,13 +1,13 @@
import { NextVICore, IPattern } from '@kanaries/loa'
import { IFieldMeta, IRow } from "../../interfaces";
-export interface IFootmanProps {
+export interface ILoaProps {
task: 'univar' | 'patterns' | 'featureSelection' | 'comparison' | 'filterSelection';
props?: any;
dataSource: IRow[];
fields: IFieldMeta[];
}
-export function serviceHandler(reqProps: IFootmanProps) {
+export function serviceHandler(reqProps: ILoaProps) {
const { task, props, dataSource, fields } = reqProps
try {
if (task === 'univar') return univarService(dataSource, fields, props);
@@ -16,7 +16,7 @@ export function serviceHandler(reqProps: IFootmanProps) {
if (task === 'comparison') return featureForComparison(dataSource, fields, props);
if (task === 'filterSelection') return filterSelection(dataSource, fields, props);
} catch (error: any) {
- throw new Error(`[footman][${task}]${error}\n${error.stack}`)
+ throw new Error(`[loa engine][${task}]${error}\n${error.stack}`)
}
}