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

Rename Notebook #22

Merged
merged 2 commits into from
Sep 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions gui/assets/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@
"Anonymization": "Anonymization",
"Changelog": "Changelog"
},
"Notebook": {
"AdminPanel": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need for active maintenance of this translation file. I would delete all GUI keys, keep developing the app, and finally extract all i18nMissingKeys from the chromium dev tools with console.log(JSON.stringify(window.i18nMissingKeys)). This is where the natural language keys shine, because you can keep viewing the English strings without having them written in the file.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 let's leave it up to the discussion in #11 and either delete or proceed in a follow-up PR

"Importing": "Importing"
},
"Sidebar": {
"NotebookNavSteps": {
"AdminPanelNavSteps": {
"CSV Import": "CSV Import",
"Load data from CSV": "Load data from CSV",
"Data Preview": "Data Preview",
Expand All @@ -65,7 +65,7 @@
},
"DataPreviewHelp": {
"Data Preview": "Data Preview",
"Use the data preview to confirm that the data was imported correctly.": "Use the data preview to confirm that the data was imported correctly."
"Use the data preview to confirm that the data was loaded correctly.": "Use the data preview to confirm that the data was loaded correctly."
},
"AidSelectionHelp": {
"ID Selection": "ID Selection",
Expand All @@ -74,14 +74,14 @@
}
},
"FileLoadStep": {
"Import data to anonymize": "Import data to anonymize",
"Import data from CSV file": "Import data from CSV file",
"Click or drag file to this area to import": "Click or drag file to this area to import"
"Import data": "Import data",
"From CSV file": "From CSV file",
"Click or drag file to this area": "Click or drag file to this area"
},
"SchemaLoadStep": {
"Loading schema": "Loading schema",
"Loaded {{fileName}}": "Loaded {{fileName}}",
"Successfully imported {{fileName}}": "Successfully imported {{fileName}}",
"Successfully loaded {{fileName}}": "Successfully loaded {{fileName}}",
"Here is what the data looks like:": "Here is what the data looks like:",
"(only the first 1000 rows are shown)": "(only the first 1000 rows are shown)",
"Schema discovery failed": "Schema discovery failed",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
.Notebook .notebook-step {
.AdminPanel .admin-panel-step {
margin: 32px 0;
}

.Notebook-content {
.AdminPanel-content {
padding: 0 32px 96px 32px;
overflow-y: scroll;
}
26 changes: 13 additions & 13 deletions gui/src/Notebook/Notebook.tsx → gui/src/AdminPanel/AdminPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,27 @@ import { AidSelectionStep } from '../AidSelectionStep';
import { FileLoadStep } from '../FileLoadStep';
import { SchemaLoadStep } from '../SchemaLoadStep';
import { useT, Layout } from '../shared';
import { NotebookHelp } from './notebook-help';
import { NotebookNav, NotebookNavProvider } from './notebook-nav';
import { AdminPanelHelp } from './admin-panel-help';
import { AdminPanelNav, AdminPanelNavProvider } from './admin-panel-nav';

import './Notebook.css';
import './AdminPanel.css';

export type NotebookProps = {
export type AdminPanelProps = {
isActive: boolean;
onTitleChange: (title: string) => void;
};

export const Notebook: FunctionComponent<NotebookProps> = ({ isActive, onTitleChange }) => {
const t = useT('Notebook');
export const AdminPanel: FunctionComponent<AdminPanelProps> = ({ isActive, onTitleChange }) => {
const t = useT('AdminPanel');
return (
<NotebookNavProvider isActive={isActive}>
<Layout className="Notebook">
<Layout.Sidebar className="Notebook-sidebar">
<NotebookNav />
<AdminPanelNavProvider isActive={isActive}>
<Layout className="AdminPanel">
<Layout.Sidebar className="AdminPanel-sidebar">
<AdminPanelNav />
<Divider style={{ margin: '16px 0' }} />
<NotebookHelp />
<AdminPanelHelp />
</Layout.Sidebar>
<Layout.Content className="Notebook-content">
<Layout.Content className="AdminPanel-content">
<FileLoadStep onLoad={(file) => onTitleChange(t('Importing') + ' ' + file.name)}>
{({ file }) => (
<SchemaLoadStep file={file}>
Expand All @@ -34,6 +34,6 @@ export const Notebook: FunctionComponent<NotebookProps> = ({ isActive, onTitleCh
</FileLoadStep>
</Layout.Content>
</Layout>
</NotebookNavProvider>
</AdminPanelNavProvider>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, { FunctionComponent } from 'react';
import { Trans } from 'react-i18next';
import { DocsLink } from '../Docs';
import { TFunc, useT as useBaseT } from '../shared';
import { NotebookNavStep, useNavState } from './notebook-nav';
import { AdminPanelNavStep, useNavState } from './admin-panel-nav';

const { Paragraph: ParagraphBase, Title } = Typography;

Expand Down Expand Up @@ -39,7 +39,7 @@ function DataPreviewHelp() {
return (
<div>
<Title level={4}>{t('Data Preview')}</Title>
<Paragraph t={t}>Use the data preview to confirm that the data was imported correctly.</Paragraph>
<Paragraph t={t}>Use the data preview to confirm that the data was loaded correctly.</Paragraph>
</div>
);
}
Expand All @@ -60,20 +60,20 @@ function AidSelectionHelp() {
);
}

const NotebookStepHelp = React.memo<{ step: NotebookNavStep }>(({ step }) => {
const AdminPanelStepHelp = React.memo<{ step: AdminPanelNavStep }>(({ step }) => {
switch (step) {
case NotebookNavStep.CsvImport:
case AdminPanelNavStep.CsvImport:
return <CsvImportHelp />;
case NotebookNavStep.DataPreview:
case AdminPanelNavStep.DataPreview:
return <DataPreviewHelp />;
case NotebookNavStep.AidSelection:
case AdminPanelNavStep.AidSelection:
return <AidSelectionHelp />;
default:
return null;
}
});

export const NotebookHelp: React.FunctionComponent = () => {
export const AdminPanelHelp: React.FunctionComponent = () => {
const { focusedStep } = useNavState();
return <NotebookStepHelp step={focusedStep} />;
return <AdminPanelStepHelp step={focusedStep} />;
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,69 +11,69 @@ const { Step } = Steps;

// Nav state

export enum NotebookNavStep {
export enum AdminPanelNavStep {
CsvImport,
DataPreview,
AidSelection,
}

export type NotebookNavStepStatus = 'inactive' | 'active' | 'loading' | 'done' | 'failed';
export type AdminPanelNavStepStatus = 'inactive' | 'active' | 'loading' | 'done' | 'failed';

type NotebookNavStepState = {
type AdminPanelNavStepState = {
htmlElement: HTMLElement | null;
status: NotebookNavStepStatus;
status: AdminPanelNavStepStatus;
};

type NotebookNavState = {
steps: NotebookNavStepState[];
focusedStep: NotebookNavStep;
type AdminPanelNavState = {
steps: AdminPanelNavStepState[];
focusedStep: AdminPanelNavStep;
};

const defaultNavState: NotebookNavState = {
steps: Array(NotebookNavStep.AidSelection + 1)
const defaultNavState: AdminPanelNavState = {
steps: Array(AdminPanelNavStep.AidSelection + 1)
.fill(null)
.map(() => ({ status: 'inactive', htmlElement: null })),
focusedStep: NotebookNavStep.CsvImport,
focusedStep: AdminPanelNavStep.CsvImport,
};

const defaultVisibility = Array(NotebookNavStep.AidSelection + 1).fill(false);
const defaultVisibility = Array(AdminPanelNavStep.AidSelection + 1).fill(false);

const NotebookNavStateContext = React.createContext<NotebookNavState>(defaultNavState);
const AdminPanelNavStateContext = React.createContext<AdminPanelNavState>(defaultNavState);

export function useNavState(): NotebookNavState {
return useContext(NotebookNavStateContext);
export function useNavState(): AdminPanelNavState {
return useContext(AdminPanelNavStateContext);
}

// Nav functions

type NotebookNavStepPatch =
type AdminPanelNavStepPatch =
| { htmlElement: null; status?: never }
| { htmlElement: HTMLElement; status: 'active' | 'loading' | 'done' | 'failed' }
| { htmlElement?: never; status: NotebookNavStepStatus };
| { htmlElement?: never; status: AdminPanelNavStepStatus };

type NotebookNavFunctions = {
updateStepStatus(step: NotebookNavStep, patch: NotebookNavStepPatch): void;
updateStepVisibility(step: NotebookNavStep, visible: boolean): void;
scrollToStep(step: NotebookNavStep): void;
type AdminPanelNavFunctions = {
updateStepStatus(step: AdminPanelNavStep, patch: AdminPanelNavStepPatch): void;
updateStepVisibility(step: AdminPanelNavStep, visible: boolean): void;
scrollToStep(step: AdminPanelNavStep): void;
};

const NotebookNavFunctionsContext = React.createContext<NotebookNavFunctions>({
const AdminPanelNavFunctionsContext = React.createContext<AdminPanelNavFunctions>({
updateStepStatus: noop,
updateStepVisibility: noop,
scrollToStep: noop,
});

function useNavFunctions(): NotebookNavFunctions {
return useContext(NotebookNavFunctionsContext);
function useNavFunctions(): AdminPanelNavFunctions {
return useContext(AdminPanelNavFunctionsContext);
}

// Context provider

export type NotebookNavProviderProps = {
export type AdminPanelNavProviderProps = {
isActive: boolean;
};

export const NotebookNavProvider: React.FunctionComponent<NotebookNavProviderProps> = ({ isActive, children }) => {
export const AdminPanelNavProvider: React.FunctionComponent<AdminPanelNavProviderProps> = ({ isActive, children }) => {
const [navState, updateNavState] = useImmer(defaultNavState);

// Refs are needed in `navFunctions` because we want it referentially stable.
Expand All @@ -83,15 +83,15 @@ export const NotebookNavProvider: React.FunctionComponent<NotebookNavProviderPro

const focusStep = useStaticValue(() =>
debounce(
(step?: NotebookNavStep) =>
(step?: AdminPanelNavStep) =>
updateNavState((draft) => {
if (typeof step !== 'undefined') {
draft.focusedStep = step;
return;
}

const maxStep = Math.max(
NotebookNavStep.CsvImport,
AdminPanelNavStep.CsvImport,
findLastIndex(draft.steps, (s) => s.status !== 'inactive'),
);
const visibleStep = visibilityRef.current.findIndex((visible) => visible);
Expand All @@ -101,10 +101,10 @@ export const NotebookNavProvider: React.FunctionComponent<NotebookNavProviderPro
),
);

const navFunctions = useStaticValue<NotebookNavFunctions>(() => ({
const navFunctions = useStaticValue<AdminPanelNavFunctions>(() => ({
updateStepStatus(step, patch) {
updateNavState((draft) => {
const { steps } = draft as NotebookNavState;
const { steps } = draft as AdminPanelNavState;
if (patch.htmlElement === null) {
steps[step] = {
htmlElement: null,
Expand All @@ -119,11 +119,11 @@ export const NotebookNavProvider: React.FunctionComponent<NotebookNavProviderPro

focusStep();
},
updateStepVisibility(step: NotebookNavStep, visible: boolean) {
updateStepVisibility(step: AdminPanelNavStep, visible: boolean) {
visibilityRef.current = produce(visibilityRef.current, (draft) => void (draft[step] = visible));
focusStep();
},
scrollToStep(step: NotebookNavStep) {
scrollToStep(step: AdminPanelNavStep) {
const { htmlElement } = navStateRef.current.steps[step];
if (htmlElement) {
htmlElement.scrollIntoView({
Expand All @@ -147,7 +147,7 @@ export const NotebookNavProvider: React.FunctionComponent<NotebookNavProviderPro
},
}));

// Prevents updates while notebook is not active.
// Prevents updates while adminPanel is not active.
useEffect(() => {
if (!isActive) {
focusStep.cancel();
Expand All @@ -162,20 +162,20 @@ export const NotebookNavProvider: React.FunctionComponent<NotebookNavProviderPro
}, [focusStep]);

return (
<NotebookNavStateContext.Provider value={navState}>
<NotebookNavFunctionsContext.Provider value={navFunctions}>{children}</NotebookNavFunctionsContext.Provider>
</NotebookNavStateContext.Provider>
<AdminPanelNavStateContext.Provider value={navState}>
<AdminPanelNavFunctionsContext.Provider value={navFunctions}>{children}</AdminPanelNavFunctionsContext.Provider>
</AdminPanelNavStateContext.Provider>
);
};

// Context consumers

export type NotebookNavAnchorProps = {
step: NotebookNavStep;
status?: NotebookNavStepStatus;
export type AdminPanelNavAnchorProps = {
step: AdminPanelNavStep;
status?: AdminPanelNavStepStatus;
};

export const NotebookNavAnchor: React.FunctionComponent<NotebookNavAnchorProps> = ({ step, status = 'active' }) => {
export const AdminPanelNavAnchor: React.FunctionComponent<AdminPanelNavAnchorProps> = ({ step, status = 'active' }) => {
const navFunctions = useNavFunctions();

const visibilityRef = useRef<HTMLDivElement>(null);
Expand All @@ -185,7 +185,7 @@ export const NotebookNavAnchor: React.FunctionComponent<NotebookNavAnchorProps>
navFunctions.updateStepStatus(step, {
htmlElement,
status,
} as NotebookNavStepPatch);
} as AdminPanelNavStepPatch);
},
[step, status, navFunctions],
);
Expand All @@ -207,7 +207,7 @@ export const NotebookNavAnchor: React.FunctionComponent<NotebookNavAnchorProps>
);
};

function mapStatus(status: NotebookNavStepStatus): 'error' | 'process' | 'finish' | 'wait' {
function mapStatus(status: AdminPanelNavStepStatus): 'error' | 'process' | 'finish' | 'wait' {
switch (status) {
case 'inactive':
return 'wait';
Expand All @@ -226,11 +226,11 @@ function mapText(text: string, focused: boolean) {
else return <>{text}</>;
}

const NotebookNavSteps = React.memo<{ steps: NotebookNavStepState[]; focusedStep: NotebookNavStep }>(
const AdminPanelNavSteps = React.memo<{ steps: AdminPanelNavStepState[]; focusedStep: AdminPanelNavStep }>(
({ steps, focusedStep }) => {
const t = useT('Sidebar::NotebookNavSteps');
const t = useT('Sidebar::AdminPanelNavSteps');
const navFunctions = useNavFunctions();
const status = (step: NotebookNavStep) => mapStatus(steps[step].status);
const status = (step: AdminPanelNavStep) => mapStatus(steps[step].status);

return (
<Steps
Expand Down Expand Up @@ -259,26 +259,26 @@ const NotebookNavSteps = React.memo<{ steps: NotebookNavStepState[]; focusedStep
size="small"
>
<Step
status={status(NotebookNavStep.CsvImport)}
title={mapText(t('CSV Import'), focusedStep === NotebookNavStep.CsvImport)}
status={status(AdminPanelNavStep.CsvImport)}
title={mapText(t('CSV Import'), focusedStep === AdminPanelNavStep.CsvImport)}
description={t('Load data from CSV')}
/>
<Step
status={status(NotebookNavStep.DataPreview)}
title={mapText(t('Data Preview'), focusedStep === NotebookNavStep.DataPreview)}
status={status(AdminPanelNavStep.DataPreview)}
title={mapText(t('Data Preview'), focusedStep === AdminPanelNavStep.DataPreview)}
description={t('Preview contents of file')}
/>
<Step
status={status(NotebookNavStep.AidSelection)}
title={mapText(t('ID Selection'), focusedStep === NotebookNavStep.AidSelection)}
status={status(AdminPanelNavStep.AidSelection)}
title={mapText(t('ID Selection'), focusedStep === AdminPanelNavStep.AidSelection)}
description={t('Select the entity identifier column')}
/>
</Steps>
);
},
);

export const NotebookNav: React.FunctionComponent = () => {
export const AdminPanelNav: React.FunctionComponent = () => {
const { steps, focusedStep } = useNavState();
return <NotebookNavSteps steps={steps} focusedStep={focusedStep} />;
return <AdminPanelNavSteps steps={steps} focusedStep={focusedStep} />;
};
2 changes: 2 additions & 0 deletions gui/src/AdminPanel/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './AdminPanel';
export { AdminPanelNavAnchor, AdminPanelNavStep } from './admin-panel-nav';
Loading