-
- { computing && 'yes' }
+
{
discoveryMainStore.setShowSettings(true);
}}
/>
-
- {intl.get('discovery.main.mainView')}
-
-
- {
- pined !== null &&
- }
-
-
- {mergeView !== null &&
- {
- vizRecSys === 'lite' &&
- }
- {
- vizRecSys === 'strict' &&
- }
-
}
-
-
-
- {
- pined && pined.fields.map((f: IFieldMeta) => { removeFromPined(f.fid) }}
- />)
- }
-
-
- {
- pined && pined.filters && pined.filters.map(f => {
- removePinedFilter(f.field)
- }}
- />)
- }
-
-
-
{
- if (pined) {
- assViews(pined)
- }
- }}
- />
-
-
-
-
-
-
-
- {
- specs.slice(0, renderAmount).map((spec, i) =>
- {
- computing &&
-
-
- }
-
- {
- setPined(views[i])
- }}
- />
- {
- setMergeView(views[i])
- discoveryMainStore.updateMainVizSettings(s => {
- s.resize.mode = IResizeMode.auto
- })
- }}
- />
- {/* {
- setPined(views[i])
- }}
- />
- {
- setMergeView(views[i])
- discoveryMainStore.updateMainVizSettings(s => {
- s.resize.mode = IResizeMode.auto
- })
- }}
- /> */}
-
-
- {
- vizRecSys === 'lite' &&
- }
- {
- vizRecSys === 'strict' &&
- }
-
- {
- views[i].filters &&
-
filters
- {views[i].filters!.map(f => `${f.field.name || f.field.fid} = ${f.values.join(',')}`).join('\n')}
-
- }
-
)
- }
-
- = specs.length}
+
+ {/* = specs.length}
style={{ marginTop: '5px' }}
text={intl.get('discovery.main.loadMore')}
onClick={() => {
setRenderAmount(a => a + RENDER_BATCH_SIZE)
}}
- />
+ /> */}
+
}
diff --git a/packages/rath-client/src/pages/semiAutomation/predictZone/featSegment.tsx b/packages/rath-client/src/pages/semiAutomation/predictZone/featSegment.tsx
new file mode 100644
index 00000000..30072a1e
--- /dev/null
+++ b/packages/rath-client/src/pages/semiAutomation/predictZone/featSegment.tsx
@@ -0,0 +1,61 @@
+import React, { useCallback } from 'react';
+import { observer } from 'mobx-react-lite';
+import intl from 'react-intl-universal';
+import { CommandButton, DefaultButton, Spinner, Stack } from 'office-ui-fabric-react';
+
+import { useGlobalStore } from '../../../store';
+import { AssoContainer, LoadingLayer } from '../components';
+import ReactVega from '../../../components/react-vega';
+import { applyFilter } from '../utils';
+
+const FeatSegment: React.FC = () => {
+ const { discoveryMainStore } = useGlobalStore();
+ const { featSpecList, computing, featViews, mainVizSetting, dataSource } = discoveryMainStore;
+ const loadMore = useCallback(() => {
+ discoveryMainStore.increaseRenderAmount('featViews');
+ }, [discoveryMainStore])
+ if (featViews.views.length === 0) return
+ return
+
{intl.get('discovery.main.associate.features')}
+
+ {
+ featSpecList.map((spec, i) =>
+ {
+ computing &&
+
+
+ }
+
+ {
+ discoveryMainStore.updateMainView(featViews.views[i])
+ }}
+ />
+
+
+
+
+ {
+ featViews.views[i].filters &&
+
filters
+ {featViews.views[i].filters!.map(f => `${f.field.name || f.field.fid} = ${f.values.join(',')}`).join('\n')}
+
+ }
+
)
+ }
+
+
= featViews.views.length}
+ style={{ marginTop: '8px' }}
+ text={intl.get('discovery.main.loadMore')}
+ onClick={loadMore}
+ />
+
+}
+
+export default observer(FeatSegment);
diff --git a/packages/rath-client/src/pages/semiAutomation/predictZone/filterSegment.tsx b/packages/rath-client/src/pages/semiAutomation/predictZone/filterSegment.tsx
new file mode 100644
index 00000000..315d8dcb
--- /dev/null
+++ b/packages/rath-client/src/pages/semiAutomation/predictZone/filterSegment.tsx
@@ -0,0 +1,68 @@
+import React, { useCallback } from 'react';
+import { observer } from 'mobx-react-lite';
+import intl from 'react-intl-universal';
+import { CommandButton, DefaultButton, Spinner, Stack } from 'office-ui-fabric-react';
+
+import { useGlobalStore } from '../../../store';
+import { AssoContainer, LoadingLayer } from '../components';
+import ReactVega from '../../../components/react-vega';
+import { applyFilter } from '../utils';
+
+const FilterSegment: React.FC = () => {
+ const { discoveryMainStore } = useGlobalStore();
+ const { filterSpecList, computing, filterViews, mainVizSetting, dataSource } = discoveryMainStore;
+ const loadMore = useCallback(() => {
+ discoveryMainStore.increaseRenderAmount('featViews');
+ }, [discoveryMainStore])
+ if (filterViews.views.length === 0) return
+ return
+
{intl.get('discovery.main.associate.filters')}
+
+ {
+ filterSpecList.map((spec, i) =>
+ {
+ computing &&
+
+
+ }
+
+ {
+ discoveryMainStore.updateMainView(filterViews.views[i])
+ }}
+ />
+ {
+ discoveryMainStore.updateCompareView(filterViews.views[i])
+ }}
+ />
+
+
+
+
+ {
+ filterViews.views[i].filters &&
+
filters
+ {filterViews.views[i].filters!.map(f => `${f.field.name || f.field.fid} = ${f.values.join(',')}`).join('\n')}
+
+ }
+
)
+ }
+
+
= filterViews.views.length}
+ style={{ marginTop: '8px' }}
+ text={intl.get('discovery.main.loadMore')}
+ onClick={loadMore}
+ />
+
+}
+
+export default observer(FilterSegment);
diff --git a/packages/rath-client/src/pages/semiAutomation/predictZone/index.tsx b/packages/rath-client/src/pages/semiAutomation/predictZone/index.tsx
new file mode 100644
index 00000000..3309af71
--- /dev/null
+++ b/packages/rath-client/src/pages/semiAutomation/predictZone/index.tsx
@@ -0,0 +1,28 @@
+import React, { useEffect } from 'react';
+import { observer } from 'mobx-react-lite';
+
+import { useGlobalStore } from '../../../store';
+import PattSegment from './pattSegment';
+import FeatSegment from './featSegment';
+import FilterSegment from './filterSegment';
+
+
+const PredictZone: React.FC = props => {
+ const { discoveryMainStore } = useGlobalStore();
+ const { dataSource, fieldMetas, mainView, autoAsso } = discoveryMainStore;
+ const { pattViews: autoPatt, featViews: autoFeat, filterViews: autoFilter } = autoAsso;
+ useEffect(() => {
+ if (mainView) {
+ autoPatt && discoveryMainStore.pattAssociate();
+ autoFeat && discoveryMainStore.featAssociate();
+ autoFilter && discoveryMainStore.filterAssociate();
+ }
+ }, [dataSource, fieldMetas, mainView, autoFeat, autoPatt, autoFilter, discoveryMainStore])
+ return
+}
+
+export default observer(PredictZone);
diff --git a/packages/rath-client/src/pages/semiAutomation/predictZone/pattSegment.tsx b/packages/rath-client/src/pages/semiAutomation/predictZone/pattSegment.tsx
new file mode 100644
index 00000000..a1b4a0e4
--- /dev/null
+++ b/packages/rath-client/src/pages/semiAutomation/predictZone/pattSegment.tsx
@@ -0,0 +1,87 @@
+import React, { useCallback } from 'react';
+import { observer } from 'mobx-react-lite';
+import intl from 'react-intl-universal';
+import { CommandButton, DefaultButton, Spinner, Stack } from 'office-ui-fabric-react';
+
+import { useGlobalStore } from '../../../store';
+import { AssoContainer, LoadingLayer } from '../components';
+import ReactVega from '../../../components/react-vega';
+import { applyFilter } from '../utils';
+
+const PattSegment: React.FC = () => {
+ const { discoveryMainStore } = useGlobalStore();
+ const { pattSpecList, computing, pattViews, mainVizSetting, dataSource } = discoveryMainStore;
+ const loadMore = useCallback(() => {
+ discoveryMainStore.increaseRenderAmount('featViews');
+ }, [discoveryMainStore])
+ if (pattViews.views.length === 0) return
+ return
+
{intl.get('discovery.main.associate.patterns')}
+
+ {
+ pattSpecList.map((spec, i) =>
+ {
+ computing &&
+
+
+ }
+
+ {
+ discoveryMainStore.updateMainView(pattViews.views[i])
+ }}
+ />
+ {/* {
+ discoveryMainStore.updateMainView(pattViews.views[i])
+ setMergeView(views[i])
+ discoveryMainStore.updateMainVizSettings(s => {
+ s.resize.mode = IResizeMode.auto
+ })
+ }}
+ /> */}
+ {/* {
+ setPined(views[i])
+ }}
+ />
+ {
+ setMergeView(views[i])
+ discoveryMainStore.updateMainVizSettings(s => {
+ s.resize.mode = IResizeMode.auto
+ })
+ }}
+ /> */}
+
+
+
+
+ {
+ pattViews.views[i].filters &&
+
filters
+ {pattViews.views[i].filters!.map(f => `${f.field.name || f.field.fid} = ${f.values.join(',')}`).join('\n')}
+
+ }
+
)
+ }
+
+
= pattViews.views.length}
+ style={{ marginTop: '8px' }}
+ text={intl.get('discovery.main.loadMore')}
+ onClick={loadMore}
+ />
+
+}
+
+export default observer(PattSegment);
diff --git a/packages/rath-client/src/pages/semiAutomation/predictZone/tmp.txt b/packages/rath-client/src/pages/semiAutomation/predictZone/tmp.txt
new file mode 100644
index 00000000..2391aa41
--- /dev/null
+++ b/packages/rath-client/src/pages/semiAutomation/predictZone/tmp.txt
@@ -0,0 +1,313 @@
+import { observer } from 'mobx-react-lite';
+import React, { useCallback, useEffect, useMemo, useState } from 'react';
+import { IFilter, IPattern } from '../../dev';
+import { useGlobalStore } from '../../store';
+import { distVis } from '../../queries/distVis'
+import ReactVega from '../../components/react-vega';
+import { DefaultButton, Stack, PrimaryButton, ActionButton, CommandButton, Spinner } from 'office-ui-fabric-react';
+import { AssoContainer, LoadingLayer, MainViewContainer } from './components';
+import ViewField from '../megaAutomation/vizOperation/viewField';
+import { IFieldMeta, IResizeMode, IRow } from '../../interfaces';
+import { footmanEngineService } from '../../service';
+import Settings from './settings';
+import { labDistVis } from '../../queries/labdistVis';
+import { notify } from '../../components/error';
+import intl from 'react-intl-universal';
+import MainCanvas from './mainCanvas';
+
+const BUTTON_STYLE = { marginRight: '1em' }
+
+function applyFilter (dataSource: IRow[], filters?: IFilter[]): IRow[] {
+ if (!filters || filters.length === 0) return dataSource;
+ const subset: IRow[] = [];
+ const filterValueSetList: Array
> = [];
+ for (let i = 0; i < filters.length; i++) {
+ filterValueSetList.push(new Set(filters[i].values))
+ }
+ for (let i = 0; i < dataSource.length; i++) {
+ for (let j = 0; j < filters.length; j++) {
+ if (filterValueSetList[j].has(dataSource[i][filters[j].field.fid])) {
+ subset.push(dataSource[i])
+ }
+ }
+ }
+ return subset
+ // return dataSource.filter(row => {
+ // return filters.every(f => f.values.includes(row[f.field.fid]))
+ // })
+}
+
+const RENDER_BATCH_SIZE = 5;
+
+const PatternPage: React.FC = () => {
+ const { dataSourceStore, discoveryMainStore } = useGlobalStore();
+ // const { fieldMetas, cleanedData } = dataSourceStore;
+ const [views, setViews] = useState([]);
+ const [pined, setPined] = useState(null);
+ const [computing, setComputing] = useState(false);
+ const [renderAmount, setRenderAmount] = useState(RENDER_BATCH_SIZE);
+ const [mergeView, setMergeView] = useState(null);
+ const { mainVizSetting,
+ featViews,
+ filterViews,
+ pattViews,
+ fieldMetas,
+ dataSource,
+ featSpecList,
+ pattSpecList,
+ filterSpecList
+ } = discoveryMainStore;
+ const vizRecSys = discoveryMainStore.settings.vizAlgo;
+
+ useEffect(() => {
+ discoveryMainStore.initAssociate();
+ }, [fieldMetas, dataSource])
+
+ const assViews = useCallback((view: IPattern) => {
+ discoveryMainStore.pattAssociate();
+ discoveryMainStore.featAssociate();
+ }, [])
+
+ const adviceCompareFeature = useCallback(() => {
+ if (pined === null || mergeView === null) return;
+ // footmanEngineService({
+ // dataSource: cleanedData,
+ // fields: fieldMetas,
+ // task: 'featureSelection',
+ // props:
+ // })
+ footmanEngineService({
+ dataSource,
+ fields: fieldMetas,
+ task: 'comparison',
+ props: [pined, mergeView]
+ }).then(res => {
+ if (res !== null) {
+ setViews([
+ {
+ ...pined,
+ fields: [...pined.fields, ...res.features]
+ },
+ {
+ ...mergeView,
+ fields: [...mergeView.fields, ...res.features]
+ },
+ ])
+ }
+ }).catch(err => {
+ notify({
+ title: 'comparsion error',
+ type: 'error',
+ content: `${err}`
+ })
+ })
+ }, [pined, mergeView, dataSource, fieldMetas])
+
+ const advicePureFeature = useCallback(() => {
+ discoveryMainStore.featAssociate()
+ }, [])
+
+ const removeFromPined = useCallback((fid: string) => {
+ if (pined === null) return;
+ const fields: IFieldMeta[] = [...pined.fields];
+ const targetIndex = fields.findIndex(f => f.fid === fid);
+ if (targetIndex > -1) {
+ fields.splice(targetIndex, 1)
+ setPined({
+ ...pined,
+ fields: fields
+ })
+ }
+ }, [pined])
+
+ const recommandFilter = useCallback(() => {
+ discoveryMainStore.filterAssociate();
+ }, [])
+
+ const removePinedFilter = useCallback((filterField: IFieldMeta) => {
+ setPined(p => {
+ if (!p?.filters) return p;
+ return {
+ ...p,
+ filters: p.filters.filter(f => f.field.fid !== filterField.fid)
+ }
+ })
+ }, [])
+
+ useEffect(() => {
+ if (pined) {
+ assViews(pined)
+ setRenderAmount(RENDER_BATCH_SIZE)
+ }
+ }, [pined, assViews])
+
+ return
+
+
+
{
+ discoveryMainStore.setShowSettings(true);
+ }}
+ />
+
+ {intl.get('discovery.main.mainView')}
+
+
+ {
+ pined !== null &&
+ }
+
+
+ {mergeView !== null &&
+ {/* {
+ vizRecSys === 'lite' &&
+ } */}
+ {/* {
+ vizRecSys === 'strict' &&
+ } */}
+
}
+
+
+
+ {
+ ma && ma.fields.map((f: IFieldMeta) => { removeFromPined(f.fid) }}
+ />)
+ }
+
+
+ {
+ pined && pined.filters && pined.filters.map(f => {
+ removePinedFilter(f.field)
+ }}
+ />)
+ }
+
+
+
{
+ if (pined) {
+ assViews(pined)
+ }
+ }}
+ />
+
+
+
+
+
+
+
+ {
+ specs.slice(0, renderAmount).map((spec, i) =>
+ {
+ computing &&
+
+
+ }
+
+ {
+ setPined(views[i])
+ }}
+ />
+ {
+ setMergeView(views[i])
+ discoveryMainStore.updateMainVizSettings(s => {
+ s.resize.mode = IResizeMode.auto
+ })
+ }}
+ />
+ {/* {
+ setPined(views[i])
+ }}
+ />
+ {
+ setMergeView(views[i])
+ discoveryMainStore.updateMainVizSettings(s => {
+ s.resize.mode = IResizeMode.auto
+ })
+ }}
+ /> */}
+
+
+
+
+ {
+ views[i].filters &&
+
filters
+ {views[i].filters!.map(f => `${f.field.name || f.field.fid} = ${f.values.join(',')}`).join('\n')}
+
+ }
+
)
+ }
+
+ = specs.length}
+ style={{ marginTop: '5px' }}
+ text={intl.get('discovery.main.loadMore')}
+ onClick={() => {
+ setRenderAmount(a => a + RENDER_BATCH_SIZE)
+ }}
+ />
+
+
+}
+
+export default observer(PatternPage);
\ No newline at end of file
diff --git a/packages/rath-client/src/pages/semiAutomation/settings.tsx b/packages/rath-client/src/pages/semiAutomation/settings.tsx
index b80029e6..594f417b 100644
--- a/packages/rath-client/src/pages/semiAutomation/settings.tsx
+++ b/packages/rath-client/src/pages/semiAutomation/settings.tsx
@@ -1,5 +1,5 @@
import { observer } from 'mobx-react-lite';
-import { ChoiceGroup, IChoiceGroupOption, Panel } from 'office-ui-fabric-react';
+import { ChoiceGroup, IChoiceGroupOption, Label, Panel, Toggle } from 'office-ui-fabric-react';
import React, { useMemo } from 'react';
import { useGlobalStore } from '../../store';
import intl from 'react-intl-universal';
@@ -13,7 +13,7 @@ const PatternSetting: React.FC = () => {
{ text: intl.get('discovery.main.vizsys.strict'), key: 'strict' }
]
}, [])
- const { showSettings, settings } = discoveryMainStore;
+ const { showSettings, settings, autoAsso } = discoveryMainStore;
const { vizAlgo } = settings;
return {
selectedKey={vizAlgo}
options={options}
/>
+
+
+ {
+ discoveryMainStore.updateAutoAssoConfig('featViews', Boolean(checked))
+ }} />
+ {
+ discoveryMainStore.updateAutoAssoConfig('pattViews', Boolean(checked))
+ }} />
+ {
+ discoveryMainStore.updateAutoAssoConfig('filterViews', Boolean(checked))
+ }} />
diff --git a/packages/rath-client/src/store/discovery/localTypes.ts b/packages/rath-client/src/store/discovery/localTypes.ts
new file mode 100644
index 00000000..e75d76b4
--- /dev/null
+++ b/packages/rath-client/src/store/discovery/localTypes.ts
@@ -0,0 +1,32 @@
+import { IPattern } from "../../dev";
+import { IResizeMode } from "../../interfaces";
+
+export interface ISetting {
+ vizAlgo: 'lite' | 'strict'
+}
+export interface IMainVizSetting {
+ interactive: boolean;
+ debug: boolean;
+ resize: {
+ mode: IResizeMode;
+ width: number;
+ height: number;
+ };
+ nlg: boolean;
+}
+
+export type IRenderViewKey = 'pattViews' | 'featViews' | 'filterViews';
+
+export interface IAssoViews {
+ views: IPattern[];
+ amount: number;
+}
+
+export const RENDER_BATCH_SIZE = 5;
+
+export function makeInitAssoViews(initRenderAmount: number = 5): IAssoViews {
+ return {
+ views: [],
+ amount: initRenderAmount
+ }
+}
\ No newline at end of file
diff --git a/packages/rath-client/src/store/discovery/mainStore.ts b/packages/rath-client/src/store/discovery/mainStore.ts
index f72f9453..f3f8db2c 100644
--- a/packages/rath-client/src/store/discovery/mainStore.ts
+++ b/packages/rath-client/src/store/discovery/mainStore.ts
@@ -1,24 +1,36 @@
-import { makeAutoObservable, runInAction } from "mobx";
-import { IResizeMode } from "../../interfaces";
+import produce from "immer";
+import { makeAutoObservable, observable, runInAction } from "mobx";
+import { IPattern } from "../../dev";
+import { IFieldMeta, IResizeMode } from "../../interfaces";
+import { distVis } from "../../queries/distVis";
+import { labDistVis } from "../../queries/labdistVis";
+import { footmanEngineService } from "../../service";
+import { DataSourceStore } from "../dataSourceStore";
+import { IAssoViews, IMainVizSetting, IRenderViewKey, ISetting, makeInitAssoViews } from "./localTypes";
+
+const RENDER_BATCH_SIZE = 5;
-interface ISetting {
- vizAlgo: 'lite' | 'strict'
-}
-interface IMainVizSetting {
- interactive: boolean;
- debug: boolean;
- resize: {
- mode: IResizeMode;
- width: number;
- height: number;
- };
- nlg: boolean;
-}
export class DiscoveryMainStore {
public settings: ISetting;
public showSettings: boolean = false;
public mainVizSetting: IMainVizSetting;
- constructor () {
+ public pattViews: IAssoViews;
+ public featViews: IAssoViews;
+ public filterViews: IAssoViews;
+ private dataSourceStore: DataSourceStore;
+ public computing: boolean = false;
+ public mainView: IPattern | null = null;
+ public compareView: IPattern | null = null;
+ public showMiniFloatView: boolean = false;
+ public autoAsso: {
+ [key in IRenderViewKey]: boolean;
+ } = {
+ pattViews: true,
+ featViews: true,
+ filterViews: true
+ }
+ constructor (dataSourceStore: DataSourceStore) {
+ this.dataSourceStore = dataSourceStore;
this.mainVizSetting = {
interactive: false,
debug: false,
@@ -32,7 +44,17 @@ export class DiscoveryMainStore {
this.settings = {
vizAlgo: 'lite'
}
- makeAutoObservable(this);
+ this.pattViews = makeInitAssoViews(RENDER_BATCH_SIZE);
+ this.featViews = makeInitAssoViews(RENDER_BATCH_SIZE);
+ this.filterViews = makeInitAssoViews(RENDER_BATCH_SIZE);
+
+ makeAutoObservable(this, {
+ pattViews: observable.shallow,
+ featViews: observable.shallow,
+ filterViews: observable.shallow,
+ mainView: observable.ref,
+ compareView: observable.ref
+ });
}
public setShowSettings (show: boolean) {
this.showSettings = show;
@@ -40,9 +62,222 @@ export class DiscoveryMainStore {
public updateSettings (skey: keyof ISetting, value: any) {
this.settings[skey] = value;
}
+ public updateAutoAssoConfig (akey: IRenderViewKey, value: boolean) {
+ this.autoAsso[akey] = value;
+ }
public updateMainVizSettings (updater: (s: IMainVizSetting) => void) {
runInAction(() => {
updater(this.mainVizSetting);
})
}
+ public setShowMiniFloatView (show: boolean) {
+ this.showMiniFloatView = show;
+ }
+ public get dataSource () {
+ return this.dataSourceStore.cleanedData;
+ }
+ public get fieldMetas () {
+ return this.dataSourceStore.fieldMetas;
+ }
+ public get pattSpecList () {
+ // TODO: 这里的设计并不会带来性能上的优化,过去只会被计算一次的整体,现在反而要算的更多。
+ // 仅仅对于联想视图比较多的场景会有优化。
+ const { amount, views } = this.pattViews;
+ const renderedViews = views.slice(0, amount);
+ if (this.settings.vizAlgo === 'lite') {
+ return renderedViews.map(v => distVis({
+ pattern: v
+ }))
+ } else {
+ return renderedViews.map(v => labDistVis({
+ pattern: v,
+ dataSource: this.dataSource
+ }))
+ }
+ }
+ public get featSpecList () {
+ // TODO: 这里的设计并不会带来性能上的优化,过去只会被计算一次的整体,现在反而要算的更多。
+ // 仅仅对于联想视图比较多的场景会有优化。
+ const { amount, views } = this.featViews;
+ const renderedViews = views.slice(0, amount);
+ if (this.settings.vizAlgo === 'lite') {
+ return renderedViews.map(v => distVis({
+ pattern: v
+ }))
+ } else {
+ return renderedViews.map(v => labDistVis({
+ pattern: v,
+ dataSource: this.dataSource
+ }))
+ }
+ }
+ public get filterSpecList () {
+ // TODO: 这里的设计并不会带来性能上的优化,过去只会被计算一次的整体,现在反而要算的更多。
+ // 仅仅对于联想视图比较多的场景会有优化。
+ const { amount, views } = this.filterViews;
+ const renderedViews = views.slice(0, amount);
+ if (this.settings.vizAlgo === 'lite') {
+ return renderedViews.map(v => distVis({
+ pattern: v
+ }))
+ } else {
+ return renderedViews.map(v => labDistVis({
+ pattern: v,
+ dataSource: this.dataSource
+ }))
+ }
+ }
+
+ public changeRenderAmount (stateKey: IRenderViewKey, size: number) {
+ this[stateKey].amount = size;
+ }
+ // 为一个关联模块的渲染数量增加一个系统默认值
+ public increaseRenderAmount (stateKey: IRenderViewKey) {
+ const safeSize = Math.min(this[stateKey].amount + RENDER_BATCH_SIZE, this[stateKey].views.length)
+ this.changeRenderAmount(stateKey, safeSize)
+ }
+ public async featAssociate () {
+ this.computing = true;
+ const { fieldMetas, dataSource, mainView } = this;
+ try {
+ const res = await footmanEngineService({
+ dataSource,
+ fields: fieldMetas,
+ task: 'featureSelection',
+ props: mainView
+ }, 'local')
+ runInAction(() => {
+ this.featViews.views = res;
+ this.featViews.amount = RENDER_BATCH_SIZE;
+ this.computing = false;
+ })
+ } catch (error) {
+ console.error(error);
+ this.computing = false;
+ }
+ }
+ public async pattAssociate () {
+ this.computing = true;
+ const { fieldMetas, dataSource, mainView } = this;
+ try {
+ const res = await footmanEngineService({
+ dataSource,
+ fields: fieldMetas,
+ task: 'patterns',
+ props: mainView
+ }, 'local')
+ runInAction(() => {
+ this.pattViews.views = res;
+ this.pattViews.amount = RENDER_BATCH_SIZE;
+ this.computing = false;
+ })
+ } catch (error) {
+ console.error(error);
+ this.computing = false;
+ }
+ }
+ public async initAssociate () {
+ this.computing = false;
+ const { dataSource, fieldMetas } = this;
+ try {
+ const res = await footmanEngineService({
+ dataSource,
+ fields: fieldMetas,
+ task: 'univar'
+ }, 'local')
+ runInAction(() => {
+ this.computing = false;
+ this.pattViews.views = res;
+ this.pattViews.amount = RENDER_BATCH_SIZE;
+ })
+ } catch (error) {
+ console.error(error);
+ this.computing = false;
+ }
+ }
+ public async filterAssociate () {
+ if (this.mainView === null) return;
+ this.computing = true;
+ const { fieldMetas, dataSource, mainView } = this;
+ try {
+ const res = await footmanEngineService({
+ dataSource,
+ fields: fieldMetas,
+ task: 'filterSelection',
+ props: mainView
+ }, 'local')
+ runInAction(() => {
+ this.filterViews.views = res;
+ this.filterViews.amount = RENDER_BATCH_SIZE;
+ this.computing = false;
+ })
+ } catch (error) {
+ console.error(error);
+ this.computing = false;
+ }
+ }
+ public removeMainViewFilter (filterFieldId: string) {
+ if (!this.mainView?.filters) return;
+ this.mainView = produce(this.mainView, draft => {
+ draft.filters = draft.filters!.filter(f => f.field.fid !== filterFieldId)
+ })
+ }
+ public removeMainViewField (fieldId: string) {
+ if (this.mainView === null) return;
+ const targetFieldIndex = this.mainView.fields.findIndex(f => f.fid === fieldId);
+ this.mainView = produce(this.mainView, draft => {
+ draft.fields.splice(targetFieldIndex, 1)
+ })
+ console.log(this.mainView)
+ }
+ public clearViews () {
+ this.featViews = makeInitAssoViews();
+ this.pattViews = makeInitAssoViews();
+ this.filterViews = makeInitAssoViews();
+ }
+ public initRenderSize () {
+ this.featViews.amount = RENDER_BATCH_SIZE;
+ this.pattViews.amount = RENDER_BATCH_SIZE;
+ this.filterViews.amount = RENDER_BATCH_SIZE;
+ }
+ public updateMainView (view: IPattern) {
+ this.mainView = view;
+ this.initAssociate()
+ }
+ public updateCompareView (view: IPattern) {
+ this.compareView = view;
+ this.mainVizSetting.resize.mode = IResizeMode.auto;
+ }
+ public async explainViewDiff (view1: IPattern, view2: IPattern) {
+ if (this.mainView === null) return;
+ this.computing = true;
+ const { fieldMetas, dataSource } = this;
+ try {
+ const res = await footmanEngineService<{ features: IFieldMeta[] }>({
+ dataSource,
+ fields: fieldMetas,
+ task: 'filterSelection',
+ props: [view1, view2]
+ }, 'local')
+ runInAction(() => {
+ if (this.mainView) {
+ this.clearViews();
+ this.featViews.views = [
+ {
+ ...this.mainView,
+ fields: [...this.mainView!.fields, ...res.features]
+ },
+ {
+ ...this.mainView,
+ fields: [...this.mainView!.fields, ...res.features]
+ }
+ ]
+ }
+ this.computing = false;
+ })
+ } catch (error) {
+ console.error(error);
+ this.computing = false;
+ }
+ }
}
\ No newline at end of file
diff --git a/packages/rath-client/src/store/index.tsx b/packages/rath-client/src/store/index.tsx
index 83823f71..b8dd41b5 100644
--- a/packages/rath-client/src/store/index.tsx
+++ b/packages/rath-client/src/store/index.tsx
@@ -35,7 +35,7 @@ const galleryStore = new GalleryStore(litePipeStore);
const noteBookStore = new NoteBookStore(litePipeStore);
const dashBoardStore = new DashBoardStore(litePipeStore);
const exploreStore = new ExploreStore(ltsPipeLineStore);
-const discoveryMainStore = new DiscoveryMainStore();
+const discoveryMainStore = new DiscoveryMainStore(dataSourceStore);
const storeCol: StoreCollection = {
diff --git a/packages/rath-client/src/utils/index.ts b/packages/rath-client/src/utils/index.ts
index 9b3ee028..c61c1936 100644
--- a/packages/rath-client/src/utils/index.ts
+++ b/packages/rath-client/src/utils/index.ts
@@ -101,6 +101,18 @@ export function findRathSafeColumnIndex (fields: T[]):
return fields.findIndex(f => f.fid === RATH_INDEX_COLUMN_KEY);
}
+export function throttle (func: F, delay: number) {
+ let timer: number | null = null;
+ return function () {
+ if (timer === null) {
+ timer = window.setTimeout(() => {
+ func();
+ timer = null;
+ }, delay);
+ }
+ }
+}
+
export {
isASCII,
inferAnalyticType,
From 29100d155a52548ce7c429b4ca530421e3f2cede Mon Sep 17 00:00:00 2001
From: Hao Chen <270001151@qq.com>
Date: Fri, 15 Jul 2022 09:56:35 +0800
Subject: [PATCH 02/15] fix: auto asso bugs
---
.../rath-client/public/locales/en-US.json | 11 +-
.../rath-client/public/locales/zh-CN.json | 11 +-
packages/rath-client/src/App.css | 8 +
.../src/pages/semiAutomation/components.tsx | 7 +-
.../pages/semiAutomation/focusZone/index.tsx | 39 +--
.../focusZone/miniFloatCanvas.tsx | 4 +-
.../src/pages/semiAutomation/index.tsx | 134 +-------
.../predictZone/featSegment.tsx | 32 +-
.../predictZone/filterSegment.tsx | 29 +-
.../predictZone/pattSegment.tsx | 55 ++-
.../pages/semiAutomation/predictZone/tmp.txt | 313 ------------------
.../src/pages/semiAutomation/utils.ts | 22 +-
.../src/store/discovery/mainStore.ts | 6 +-
13 files changed, 127 insertions(+), 544 deletions(-)
delete mode 100644 packages/rath-client/src/pages/semiAutomation/predictZone/tmp.txt
diff --git a/packages/rath-client/public/locales/en-US.json b/packages/rath-client/public/locales/en-US.json
index a8609c4c..a397aa51 100644
--- a/packages/rath-client/public/locales/en-US.json
+++ b/packages/rath-client/public/locales/en-US.json
@@ -5,7 +5,9 @@
"name": "Name",
"home": "Home",
"settings": "Settings",
- "history": "History"
+ "history": "History",
+ "hide": "Hide",
+ "expand": "Expand"
},
"menu": {
"dataSource": "DataSource",
@@ -286,8 +288,8 @@
"discovery": {
"main": {
"mainView": "Main View",
- "relatePatterns": "relate patterns(default)",
- "relateFeatures": "relate features",
+ "relatePatterns": "associate patterns",
+ "relateFeatures": "associate features",
"explainDiff": "explain diff",
"pointInterests": "split",
"pin": "pin",
@@ -304,5 +306,8 @@
"filters": "Associated Subsets"
}
}
+ },
+ "desc": {
+ "dataViewInfo": "Pattern in {measures} by {dimensions} where {filters}."
}
}
\ No newline at end of file
diff --git a/packages/rath-client/public/locales/zh-CN.json b/packages/rath-client/public/locales/zh-CN.json
index 1399cc58..e09cb643 100644
--- a/packages/rath-client/public/locales/zh-CN.json
+++ b/packages/rath-client/public/locales/zh-CN.json
@@ -5,7 +5,9 @@
"name": "名称",
"home": "主页",
"settings": "设置",
- "history": "历史记录"
+ "history": "历史记录",
+ "hide": "隐藏",
+ "expand": "展开"
},
"menu": {
"dataSource": "数据源",
@@ -286,8 +288,8 @@
"discovery": {
"main": {
"mainView": "主视图",
- "relatePatterns": "关联规律(默认)",
- "relateFeatures": "特征推荐",
+ "relatePatterns": "关联规律",
+ "relateFeatures": "关联特征",
"explainDiff": "差异性分析",
"pointInterests": "拆分",
"pin": "深入分析",
@@ -304,5 +306,8 @@
"filters": "关联子集"
}
}
+ },
+ "desc": {
+ "dataViewInfo": "在 {dimensions} 中 {measures} 的表现, 限制条件 {filters}."
}
}
\ No newline at end of file
diff --git a/packages/rath-client/src/App.css b/packages/rath-client/src/App.css
index ece34a40..7167fac6 100644
--- a/packages/rath-client/src/App.css
+++ b/packages/rath-client/src/App.css
@@ -54,6 +54,14 @@ h2, h3 {
font-size: 12px;
color: #8a8886;
}
+
+.pure-card{
+ background-color: #fff;
+ padding: 28px;
+ border-radius: 2px;
+ box-shadow: 0 1.6px 3.6px 0 rgba(0,0,0,0.132), 0 0.3px 0.9px 0 rgba(0,0,0,0.108);
+ margin-bottom: 1em;
+}
.card{
background-color: #fff;
padding: 28px;
diff --git a/packages/rath-client/src/pages/semiAutomation/components.tsx b/packages/rath-client/src/pages/semiAutomation/components.tsx
index a10d7f93..f09ca6df 100644
--- a/packages/rath-client/src/pages/semiAutomation/components.tsx
+++ b/packages/rath-client/src/pages/semiAutomation/components.tsx
@@ -16,7 +16,10 @@ export const AssoContainer = styled.div`
padding: 10px;
position: relative;
.chart-container{
- min-height: 300px;
+ min-height: 280px;
+ }
+ .chart-desc{
+ font-size: 12px;
}
}
`
@@ -40,7 +43,7 @@ export const MainViewContainer = styled.div`
}
.fields-container{
display: flex;
- padding: 1em 0em;
+ padding: 1em 0em 0em 0em;
}
.action-buttons{
margin: 6px 0px;
diff --git a/packages/rath-client/src/pages/semiAutomation/focusZone/index.tsx b/packages/rath-client/src/pages/semiAutomation/focusZone/index.tsx
index 8cfc0544..60952944 100644
--- a/packages/rath-client/src/pages/semiAutomation/focusZone/index.tsx
+++ b/packages/rath-client/src/pages/semiAutomation/focusZone/index.tsx
@@ -1,5 +1,5 @@
import { observer } from 'mobx-react-lite';
-import { DefaultButton, PrimaryButton } from 'office-ui-fabric-react';
+import { PrimaryButton } from 'office-ui-fabric-react';
import React, { useCallback } from 'react';
import { IFieldMeta } from '../../../interfaces';
import { useGlobalStore } from '../../../store';
@@ -9,21 +9,12 @@ import MainCanvas from './mainCanvas';
import intl from 'react-intl-universal';
import MiniFloatCanvas from './miniFloatCanvas';
-const BUTTON_STYLE = { marginRight: '1em' }
+const BUTTON_STYLE = { marginRight: '1em', marginTop: '1em' }
const FocusZone: React.FC = props => {
const { discoveryMainStore } = useGlobalStore();
- const { mainView, compareView, showMiniFloatView, autoAsso } = discoveryMainStore;
- const advicePureFeature = useCallback(() => {
- discoveryMainStore.featAssociate()
- }, [discoveryMainStore])
- const assViews = useCallback(() => {
- discoveryMainStore.pattAssociate();
- discoveryMainStore.featAssociate();
- }, [discoveryMainStore])
- const recommandFilter = useCallback(() => {
- discoveryMainStore.filterAssociate();
- }, [discoveryMainStore])
+ const { mainView, compareView, showMiniFloatView } = discoveryMainStore;
+
const explainDiff = useCallback(() => {
if (mainView && compareView) {
discoveryMainStore.explainViewDiff(mainView, compareView);
@@ -39,6 +30,7 @@ const FocusZone: React.FC = props => {
{compareView && }
+