Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[feat] Dashboard Update #168

Merged
merged 26 commits into from
Nov 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4d71c99
refactor(dashboard): extend dashboard store
AntoineYANG Oct 31, 2022
691273b
feat(dashboard): add serialize & deserialize interface
AntoineYANG Nov 1, 2022
da26eb6
feat(dashboard): dashboard page router
AntoineYANG Nov 1, 2022
d2ee186
feat(dashboard): dashboard list
AntoineYANG Nov 1, 2022
ab632f6
feat(dashboard): list preview (popup only)
AntoineYANG Nov 1, 2022
0796c3e
feat(dashboard): card placeholder
AntoineYANG Nov 1, 2022
c47ad0f
feat(dashboard): divide renderer and editor
AntoineYANG Nov 2, 2022
db38213
feat(dashboard): editor
AntoineYANG Nov 2, 2022
ec3b38b
feat(dashboard): preview popup in list view
AntoineYANG Nov 2, 2022
83c9a4f
feat(dashboard): on-chart filters
AntoineYANG Nov 3, 2022
b595bfe
feat(dashboard): global filters
AntoineYANG Nov 3, 2022
2de13ba
feat(dashboard): highlight interaction in preview mode
AntoineYANG Nov 3, 2022
99b3d0e
perf(dashboard): use sample to render
AntoineYANG Nov 3, 2022
3fb2ab7
收藏支持配置
QiMeng7m Nov 3, 2022
2f65a23
feat(dashboard): init title & desc from collection
AntoineYANG Nov 3, 2022
0928d90
feat(dashboard): editor panel
AntoineYANG Nov 3, 2022
d465cc4
chore(dashboard): remove out-dated dependencies and file
AntoineYANG Nov 4, 2022
19b557b
fix(dashboard editor): editor mode does not work if there's no preset…
AntoineYANG Nov 18, 2022
92500bc
feat(dashboard): gallery mode
AntoineYANG Nov 18, 2022
d460d31
style(dashboard): opti code
AntoineYANG Nov 18, 2022
836b3c8
style(dashboard): remove deprecated api
AntoineYANG Nov 18, 2022
8e87597
style(dashboard): simply track all runInAction calls in DashboardStore
AntoineYANG Nov 18, 2022
d98e9e1
fix:删除tailwin,抽组件
QiMeng7m Nov 21, 2022
1c2fa59
fix: children warning
jojocys Nov 23, 2022
3bbce90
fix: sample bug
jojocys Nov 23, 2022
e9f41e9
fix(): conflict
AntoineYANG Nov 23, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/rath-client/config-overrides.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ module.exports = function override(config, env) {
},
}, 'ts-loader'],
})
config.stats = {
children: true
}
config.output.globalObject = 'self'
// config.module = config.module || {};
// config.module.unknownContextCritical = false
Expand Down
2 changes: 0 additions & 2 deletions packages/rath-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
"react": "^17.0.1",
"react-app-rewired": "^2.1.5",
"react-dom": "^17.0.1",
"react-grid-layout": "^1.3.4",
"react-intl-universal": "^2.6.6",
"react-json-view": "^1.19.1",
"react-scripts": "^5.0.1",
Expand All @@ -61,7 +60,6 @@
"@types/node": "^12.19.12",
"@types/react": "^17.0.2",
"@types/react-dom": "^17.0.1",
"@types/react-grid-layout": "^1.3.2",
"@types/styled-components": "^5.1.7",
"crypto-js": "^4.1.1",
"customize-cra": "^1.0.0",
Expand Down
6 changes: 4 additions & 2 deletions packages/rath-client/src/components/filterCreationPill.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ const Cont = styled.div`
interface FilterCreationPillProps {
fields: IFieldMeta[];
onFilterSubmit: (field: IFieldMeta, filter: IFilter) => void;
onRenderPill?: (text: string, handleClick: () => void) => void;
}
const DefaultPill: FilterCreationPillProps['onRenderPill'] = (text, handleClick) => <BasePillPlaceholder text={text} onClick={handleClick} />;
const FilterCreationPill: React.FC<FilterCreationPillProps> = (props) => {
const { fields, onFilterSubmit } = props;
const { fields, onFilterSubmit, onRenderPill = DefaultPill } = props;
const container = useRef<HTMLDivElement>(null);
const [show, setShow] = useState(false);
const [filter, setFilter] = useState<IFilter>({
Expand Down Expand Up @@ -92,7 +94,7 @@ const FilterCreationPill: React.FC<FilterCreationPillProps> = (props) => {
};
return (
<div ref={container}>
<BasePillPlaceholder text={intl.get('common.addFilter')} onClick={toggleShow} />
{onRenderPill(intl.get('common.addFilter'), toggleShow)}
{show && (
<Callout
target={container}
Expand Down
22 changes: 12 additions & 10 deletions packages/rath-client/src/components/viewInfo/textInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,18 @@ const ViewInfo: React.FC<ViewInfoProps> = (props) => {
return (
<Cont>
<div className="chart-desc">
{fields
.filter((f) => f.analyticType === 'dimension')
.map((f) => f.name || f.fid)
.join(', ')}{' '}
<br />
{fields
.filter((f) => f.analyticType === 'measure')
.map((f) => f.name || f.fid)
.join(', ')}{' '}
<br />
<div>
{fields
.filter((f) => f.analyticType === 'dimension')
.map((f) => f.name || f.fid)
.join(', ')}{' '}
</div>
<div>
{fields
.filter((f) => f.analyticType === 'measure')
.map((f) => f.name || f.fid)
.join(', ')}{' '}
</div>
{filters &&
filters.map((f) => {
const meta = metas.find((m) => m.fid === f.fid);
Expand Down
3 changes: 3 additions & 0 deletions packages/rath-client/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ export interface IVegaChannel {
type: ISemanticType;
aggregate?: string;
order?: any;
bin?: boolean;
[key: string]: any;
}

Expand All @@ -203,6 +204,8 @@ export interface IInsightVizView {
fields: IFieldMeta[];
filters: IFilter[];
score?: number;
title?: string;
desc?: string;
}

export enum PAINTER_MODE {
Expand Down
61 changes: 61 additions & 0 deletions packages/rath-client/src/lib/stat/sampling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { BIN_SIZE, getFreqMap } from "@kanaries/loa";
import { IFieldMeta, IRow } from "../../interfaces";

function getValueTuple (row: IRow, fields: IFieldMeta[]) {
let tuple = '';
for (let field of fields) {
if (field.semanticType === 'quantitative') {
let idx = Math.floor((field.features.max - row[field.fid]) / ((field.features.max - field.features.min) / BIN_SIZE))
idx = Math.min(idx, BIN_SIZE);
tuple += idx
} else {
tuple += row[field.fid]
}
tuple += '_'
}
return tuple
}

export function estimateDistribution (data: IRow[], fields: IFieldMeta[]) {
const encodedData: string[] = [];
for (let i = 0; i < data.length; i++) {
let tuple = getValueTuple(data[i], fields)
encodedData.push(tuple)
}
const freqMap = getFreqMap(encodedData)
for (let t of freqMap.keys()) {
freqMap.set(t, freqMap.get(t)! / data.length)
}
return freqMap;
}

export function viewSampling (data: IRow[], fields: IFieldMeta[], sampleSize: number): IRow[] {
const distProbMap = estimateDistribution(data, fields);
const sizeMap: Map<string, number> = new Map();
const counterMap: Map<string, number> = new Map();
const sampleMap: Map<string, IRow[]> = new Map();
for (let t of distProbMap.keys()) {
sizeMap.set(t, Math.round(distProbMap.get(t)! * sampleSize))
counterMap.set(t, 0)
sampleMap.set(t, [])
}
let samples: IRow[] = [];
for (let i = 0; i < data.length; i++) {
let tuple = getValueTuple(data[i], fields);
counterMap.set(tuple, counterMap.get(tuple)! + 1)
if (sampleMap.get(tuple)!.length < sizeMap.get(tuple)!) {
sampleMap.get(tuple)!.push(data[i])
} else {
let idx = Math.floor(Math.random() * counterMap.get(tuple)!)
if (idx < sizeMap.get(tuple)!) {
sampleMap.get(tuple)![idx] = data[i]
}
}
}
for (let [, values] of sampleMap.entries()) {
for (let val of values) {
samples.push(val);
}
}
return samples
}
2 changes: 1 addition & 1 deletion packages/rath-client/src/pages/causal/hooks/dataViews.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { applyFilters, IFilter } from '@kanaries/loa'
import { IRow } from "../../../interfaces";
import { focusedSample } from "../../../utils/sample";
import { useGlobalStore } from "../../../store";
import { baseDemoSample } from "../../painter/sample";
import { baseDemoSample } from "../../../utils/view-sample";

const VIZ_SUBSET_LIMIT = 2_000;
const SAMPLE_UPDATE_DELAY = 500;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,35 @@ const CollectContainer = styled.div`
border-radius: 1em;
padding: 1em;
margin: 0.5em;
cursor: pointer;
}
.collect-title {
width: 100%;
font-size: 1.125rem;
display: flex;
justify-content: center;
font-weight: bold;
margin-bottom: 2px;
}
.c-desc {
> div:first-child {
/* w-full text-gray-700 text-sm */
width: 100%;
color: rgba(55, 65, 81);
font-size: 0.875rem;
line-height: 1.25rem;
}
}
`;

interface CardViewProps {
data: IRow[];
metas: IFieldMeta[];
views: IInsightVizView[];
onConfig: (data: IInsightVizView) => void;
}
const CardView: React.FC<CardViewProps> = (props) => {
const { data, views, metas } = props;
const { data, views, metas, onConfig } = props;
const [pageIndex, setPageIndex] = useState<number>(0);
return (
<div>
Expand All @@ -46,7 +65,14 @@ const CardView: React.FC<CardViewProps> = (props) => {
<Divider style={{ marginBottom: '1em', marginTop: '1em' }} />
<CollectContainer>
{views.slice(pageIndex * VIEW_NUM_IN_PAGE, (pageIndex + 1) * VIEW_NUM_IN_PAGE).map((item, i) => (
<div className="chart-container" key={item.viewId}>
<div
className="chart-container"
key={item.viewId}
onClick={() => {
onConfig(item);
}}
>
<div className="collent-title">{item.title}</div>
<div className="c-vis">
<VisErrorBoundary>
<ReactVega
Expand All @@ -57,11 +83,8 @@ const CardView: React.FC<CardViewProps> = (props) => {
</VisErrorBoundary>
</div>
<div className="c-desc">
<ViewInfo
metas={metas}
fields={item.fields}
filters={item.filters}
/>
<div>{item.desc}</div>
<ViewInfo metas={metas} fields={item.fields} filters={item.filters} />
</div>
</div>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ interface ListViewProps {
data: IRow[];
metas: IFieldMeta[];
views: IInsightVizView[];
onConfig: (data: IInsightVizView) => void;
}
const ListView: React.FC<ListViewProps> = (props) => {
const { data, views, metas } = props;
const { data, views, metas, onConfig } = props;
const [pageIndex, setPageIndex] = useState<number>(0);
return (
<div>
Expand All @@ -56,8 +57,15 @@ const ListView: React.FC<ListViewProps> = (props) => {
<Divider style={{ marginBottom: '1em', marginTop: '1em' }} />
<CollectContainer>
{views.slice(pageIndex * VIEW_NUM_IN_PAGE, (pageIndex + 1) * VIEW_NUM_IN_PAGE).map((item, i) => (
<div className="chart-container" key={item.viewId}>
<div
className="chart-container cursor-pointer"
key={item.viewId}
onClick={() => {
onConfig(item);
}}
>
<div className="c-vis">
<div className="flex justify-center text-lg font-bold mb-2">{item.title}</div>
<VisErrorBoundary>
<ReactVega
dataSource={applyFilters(data, item.filters)}
Expand All @@ -67,11 +75,8 @@ const ListView: React.FC<ListViewProps> = (props) => {
</VisErrorBoundary>
</div>
<div className="c-desc">
<ViewInfo
metas={metas}
fields={item.fields}
filters={item.filters}
/>
<div className="w-full text-gray-700 text-sm">{item.desc}</div>
<ViewInfo metas={metas} fields={item.fields} filters={item.filters} />
</div>
</div>
))}
Expand Down