Skip to content

Commit 52c1bf3

Browse files
authored
Merge pull request #138 from diffix/edon/notebook-nav
Implement notebook side navigation
2 parents f7207b4 + 6a59d95 commit 52c1bf3

File tree

9 files changed

+274
-38
lines changed

9 files changed

+274
-38
lines changed

CHANGELOG.md

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
1-
### Version 0.1.4
2-
3-
- Added UI feedback on data export.
4-
- Added support for column generalization.
5-
- Removed anonymized count value in low count rows.
6-
- Added relative noise column in combined view.
7-
8-
### Version 0.1.3
9-
10-
- Keep detected column types in anonymization output.
11-
- Include .NET libraries in deployment.
12-
- Added anonymization summary to notebooks.
13-
14-
### Version 0.1.2
15-
16-
- Fix `reference` CLI executable binary generation on MacOS.
17-
18-
### Version 0.1.1
19-
20-
- Added application icon.
21-
- Made path resolution for reference CLI absolute in production builds.
22-
- Dropped noise magnitude limiting.
23-
- Noisy `count` aggregator doesn't return `NULL` anymore on insufficient data.
24-
- Reduced the amount of rows used for data / result preview.
25-
- Added notice about rows limit in data / result preview.
1+
### Version 0.1.4
2+
3+
- Added UI feedback on data export.
4+
- Added support for column generalization.
5+
- Removed anonymized count value in low count rows.
6+
- Added relative noise column in combined view.
7+
- Added side navigation in Notebooks.
8+
9+
### Version 0.1.3
10+
11+
- Keep detected column types in anonymization output.
12+
- Include .NET libraries in deployment.
13+
- Added anonymization summary to notebooks.
14+
15+
### Version 0.1.2
16+
17+
- Fix `reference` CLI executable binary generation on MacOS.
18+
19+
### Version 0.1.1
20+
21+
- Added application icon.
22+
- Made path resolution for reference CLI absolute in production builds.
23+
- Dropped noise magnitude limiting.
24+
- Noisy `count` aggregator doesn't return `NULL` anymore on insufficient data.
25+
- Reduced the amount of rows used for data / result preview.
26+
- Added notice about rows limit in data / result preview.

src/AnonymizationStep/AnonymizationStep.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { FunctionComponent, useEffect, useState } from 'react';
22
import { Button, Descriptions, Divider, message, Result, Typography } from 'antd';
33
import { DownloadOutlined } from '@ant-design/icons';
44

5+
import { NotebookNavAnchor, NotebookNavStep } from '../Notebook';
56
import { anonymizer, computeAnonymizationStats, formatPercentage, useCachedData } from '../shared';
67
import { AnonymizationStats, AnonymizedQueryResult, BucketColumn, TableSchema } from '../types';
78
import { AnonymizedResultsTable } from './AnonymizedResultsTable';
@@ -34,6 +35,7 @@ function AnonymizationSummary({ result, loading }: CommonProps) {
3435

3536
return (
3637
<div className="AnonymizationSummary loading notebook-step">
38+
<NotebookNavAnchor step={NotebookNavStep.AnonymizationSummary} status={loading ? 'loading' : 'done'} />
3739
<Title level={3}>Anonymization summary</Title>
3840
{result.rows.length === MAX_ROWS && (
3941
<div className="mb-1">
@@ -78,21 +80,34 @@ async function exportResult(schema: TableSchema, bucketColumns: BucketColumn[])
7880
}
7981

8082
function AnonymizationResults({ schema, bucketColumns, result, loading }: CommonProps) {
83+
const [exported, setExported] = useState(false);
84+
useEffect(() => {
85+
setExported(false);
86+
}, [bucketColumns]);
87+
8188
return (
8289
<div className="AnonymizationResults notebook-step">
90+
<NotebookNavAnchor step={NotebookNavStep.AnonymizedResults} status={loading ? 'loading' : 'done'} />
8391
<Title level={3}>Anonymized data</Title>
8492
<div className="mb-1">
8593
<Text>Here is what the result looks like:</Text>
8694
{result.rows.length === MAX_ROWS && <Text type="secondary"> (only the first {MAX_ROWS} rows are shown)</Text>}
8795
</div>
8896
<AnonymizedResultsTable loading={loading} result={result} />
97+
<NotebookNavAnchor
98+
step={NotebookNavStep.CsvExport}
99+
status={loading ? 'inactive' : exported ? 'done' : 'active'}
100+
/>
89101
<Button
90102
icon={<DownloadOutlined />}
91103
className="AnonymizationResults-export-button"
92104
type="primary"
93105
size="large"
94106
disabled={loading || !result.rows.length}
95-
onClick={() => exportResult(schema, bucketColumns)}
107+
onClick={() => {
108+
exportResult(schema, bucketColumns);
109+
setExported(true);
110+
}}
96111
>
97112
Export anonymized data to CSV
98113
</Button>
@@ -125,6 +140,8 @@ export const AnonymizationStep: FunctionComponent<AnonymizationStepProps> = ({ b
125140
case 'failed':
126141
return (
127142
<div className="AnonymizationStep notebook-step failed">
143+
<NotebookNavAnchor step={NotebookNavStep.AnonymizationSummary} status="failed" />
144+
<NotebookNavAnchor step={NotebookNavStep.AnonymizedResults} status="failed" />
128145
<Result status="error" title="Anonymization failed" subTitle="Something went wrong." />
129146
</div>
130147
);

src/ColumnSelectionStep/ColumnSelectionStep.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { CloseCircleOutlined } from '@ant-design/icons';
44
import { useImmer } from 'use-immer';
55
import { assign } from 'lodash';
66

7+
import { NotebookNavAnchor, NotebookNavStep } from '../Notebook';
78
import { useMemoStable } from '../shared';
89
import { BucketColumn, ColumnType, NumericGeneralization, StringGeneralization, TableSchema } from '../types';
910

@@ -140,6 +141,7 @@ export const ColumnSelectionStep: FunctionComponent<ColumnSelectionStepProps> =
140141
return (
141142
<>
142143
<div className="ColumnSelectionStep notebook-step">
144+
<NotebookNavAnchor step={NotebookNavStep.ColumnSelection} status={anySelected ? 'done' : 'active'} />
143145
<Title level={3}>Select columns for anonymization</Title>
144146
<table className="ColumnSelectionStep-table">
145147
<thead>

src/FileLoadStep/FileLoadStep.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { FunctionComponent, useCallback, useState } from 'react';
22
import { Divider, Typography, Upload } from 'antd';
33
import { FileOutlined } from '@ant-design/icons';
44

5+
import { NotebookNavAnchor, NotebookNavStep } from '../Notebook';
56
import { File } from '../types';
67

78
const { Dragger } = Upload;
@@ -24,6 +25,7 @@ export const FileLoadStep: FunctionComponent<FileLoadStepProps> = ({ children, o
2425
return (
2526
<>
2627
<div className="FileLoadStep notebook-step">
28+
<NotebookNavAnchor step={NotebookNavStep.CsvImport} status={file ? 'done' : 'active'} />
2729
<Title level={3}>Import data to anonymize</Title>
2830
<Dragger
2931
accept=".csv"

src/Notebook/Notebook.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,14 @@
55
.Notebook .notebook-step {
66
margin: 32px 0;
77
}
8+
9+
.Notebook-nav {
10+
position: fixed;
11+
top: 60px;
12+
left: 24px;
13+
max-width: 300px;
14+
}
15+
16+
.Notebook-content {
17+
margin-left: 316px;
18+
}

src/Notebook/Notebook.tsx

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import React, { FunctionComponent } from 'react';
2+
23
import { FileLoadStep } from '../FileLoadStep';
34
import { SchemaLoadStep } from '../SchemaLoadStep';
45
import { ColumnSelectionStep } from '../ColumnSelectionStep';
56
import { AnonymizationStep } from '../AnonymizationStep';
7+
import { NotebookNavProvider, NotebookNav } from './notebook-nav';
68

79
import './Notebook.css';
810

@@ -12,18 +14,25 @@ export type NotebookProps = {
1214

1315
export const Notebook: FunctionComponent<NotebookProps> = ({ onTitleChange }) => {
1416
return (
15-
<div className="Notebook">
16-
<FileLoadStep onLoad={(file) => onTitleChange(file.name)}>
17-
{({ file }) => (
18-
<SchemaLoadStep file={file}>
19-
{({ schema }) => (
20-
<ColumnSelectionStep schema={schema}>
21-
{({ bucketColumns }) => <AnonymizationStep bucketColumns={bucketColumns} schema={schema} />}
22-
</ColumnSelectionStep>
17+
<NotebookNavProvider>
18+
<div className="Notebook">
19+
<div className="Notebook-nav">
20+
<NotebookNav />
21+
</div>
22+
<div className="Notebook-content">
23+
<FileLoadStep onLoad={(file) => onTitleChange(file.name)}>
24+
{({ file }) => (
25+
<SchemaLoadStep file={file}>
26+
{({ schema }) => (
27+
<ColumnSelectionStep schema={schema}>
28+
{({ bucketColumns }) => <AnonymizationStep bucketColumns={bucketColumns} schema={schema} />}
29+
</ColumnSelectionStep>
30+
)}
31+
</SchemaLoadStep>
2332
)}
24-
</SchemaLoadStep>
25-
)}
26-
</FileLoadStep>
27-
</div>
33+
</FileLoadStep>
34+
</div>
35+
</div>
36+
</NotebookNavProvider>
2837
);
2938
};

src/Notebook/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from './Notebook';
2+
export * from './notebook-nav';

0 commit comments

Comments
 (0)