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

Migrate Workbench to React #4637

Merged
merged 161 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from 89 commits
Commits
Show all changes
161 commits
Select commit Hold shift + click to select a range
8985bbb
Upgrade handsontable to 12.1.0 and add react wrapper
sharadsw Mar 11, 2024
b1fc448
Fix type errors after upgrading handsontable
sharadsw Mar 11, 2024
eaf1b88
Lint code with ESLint and Prettier
sharadsw Mar 11, 2024
aa1837b
Add component for workbench spreadsheet
sharadsw Mar 13, 2024
c48b039
Lint code with ESLint and Prettier
sharadsw Mar 13, 2024
b742993
Add ability to export to DataSetMeta components
sharadsw Mar 15, 2024
c663602
Add data as a prop to WbSpreadsheet
sharadsw Mar 18, 2024
400a833
Add component for workbench toolkit
sharadsw Mar 18, 2024
26b65d4
Add a React component that mirrors WbView
sharadsw Mar 18, 2024
10315f3
Merge remote-tracking branch 'origin/production' into issue-4611
sharadsw Mar 18, 2024
85d9e1e
Move upload plan into toolkit
sharadsw Mar 18, 2024
70a7e90
Add advanced search button
sharadsw Mar 18, 2024
8cc8012
Add rollback dialog box
sharadsw Mar 18, 2024
e2a757f
Add index file for Workbench
sharadsw Mar 19, 2024
2ba5158
Add upload button dialogs
sharadsw Mar 19, 2024
f529f04
Add status component
sharadsw Mar 19, 2024
8a1b1a0
Add a function for triggering WbView refresh
sharadsw Mar 19, 2024
4a3b9b9
Update routes to point to new index file
sharadsw Mar 19, 2024
95c2921
Refactor WbActions to make upload and rollback work
sharadsw Mar 19, 2024
97040ee
Fix context menu in WbSpreadsheet
sharadsw Mar 25, 2024
ad5b070
Refactor cellmeta
sharadsw Mar 29, 2024
8a99a07
Refactor disambiguation
sharadsw Mar 29, 2024
a5551b3
Refactor hot hooks
sharadsw Mar 29, 2024
6f27979
Refactor index.ts
sharadsw Mar 29, 2024
3cdb5c5
Refactor WbActions into smaller components
sharadsw Mar 29, 2024
bf13c57
Remove console statement
sharadsw Mar 29, 2024
830273a
Comment out setCellCount as it breaks error cells
sharadsw Mar 29, 2024
4bf6176
Add temporary workaround for error cells disappearing
sharadsw Mar 29, 2024
a2dd138
Add disambiguation dialogs to spreadsheet
sharadsw Mar 29, 2024
7270527
Add enable/disable behavior for Export/Change Owner
sharadsw Mar 29, 2024
16c1078
Refactor WbUtils to React
sharadsw Mar 29, 2024
31b8544
Refactor WbValidation
sharadsw Mar 29, 2024
2f4bc62
Add upload view, validation results and action components to WbView
sharadsw Mar 29, 2024
7fa4d8b
Refactor WbToolkit into smaller components
sharadsw Apr 1, 2024
8073da6
Refactor WbActions into smaller components
sharadsw Apr 2, 2024
0257f82
Clean up Action files
sharadsw Apr 2, 2024
ccb7dde
Update prop names in WbView
sharadsw Apr 2, 2024
bde9eb9
Improve hot typings
sharadsw Apr 3, 2024
78e23f5
Remove code smells
sharadsw Apr 3, 2024
336f425
Move components into WbActions and WbToolkit folders
sharadsw Apr 3, 2024
f94741a
Fix import paths
sharadsw Apr 3, 2024
fdbcbad
Fix cell count values not displaying correctly
sharadsw Apr 3, 2024
252f12d
Fix cell navigation position
sharadsw Apr 4, 2024
cb6a5ae
Remove old CellMeta code
sharadsw Apr 4, 2024
bbcd0ab
Remove old WbValidation code
sharadsw Apr 4, 2024
7b7d192
Remove old Disambiguation code
sharadsw Apr 4, 2024
08879db
Add loading screen to workbench
sharadsw Apr 5, 2024
78f3796
Remove unused class names
sharadsw Apr 5, 2024
9d8ced9
Improve UploadResult typing
sharadsw Apr 5, 2024
05b038f
Remove old WbView code
sharadsw Apr 5, 2024
e998794
Add old code back temporarily
sharadsw Apr 5, 2024
450251a
Add error boundaries to features
sharadsw Apr 11, 2024
e37343d
Add ErrorBoundary to results
sharadsw Apr 11, 2024
c0fd41b
Rename triggerRefresh to triggerDatasetRefresh
sharadsw Apr 11, 2024
9a67101
Refactor WbSpreadsheet to use a callback ref
sharadsw Apr 11, 2024
015c894
Add ReadOnlyContext to workbench
sharadsw Apr 12, 2024
467cdf8
Use readonly context for fillCellsContextMenuItem
sharadsw Apr 12, 2024
b0b35f0
Add improvements
sharadsw Apr 12, 2024
ceeca5b
Run prettier
sharadsw Apr 12, 2024
a6790a8
Suppress some type errors temporarily
sharadsw Apr 12, 2024
f570559
Add suggested improvements
sharadsw Apr 15, 2024
bf0f54c
Add minor improvements
sharadsw Apr 16, 2024
8116988
Move hot props into a different file
sharadsw Apr 16, 2024
a18cfea
Move show results logic into a hook
sharadsw Apr 16, 2024
73f8549
Complete all TODOs
sharadsw Apr 16, 2024
87b8bdd
Move disambiguate dialogs to WbView
sharadsw Apr 16, 2024
3e662f0
Rename dataSet to dataset in workbench folders
sharadsw Apr 16, 2024
d467f1f
prettier
sharadsw Apr 16, 2024
c8f773e
lint
sharadsw Apr 16, 2024
9717781
Remove flushedCellMeta
sharadsw Apr 16, 2024
1f1ac79
Remove flushedCellMeta in hooks.ts
sharadsw Apr 16, 2024
5d888f5
Use readonly context in hooks
sharadsw Apr 16, 2024
07a1e5b
prettier
sharadsw Apr 16, 2024
3d3eb1d
Move disambiguation dialogs to a hook
sharadsw Apr 17, 2024
e501576
Add suggestions
sharadsw Apr 17, 2024
59b7877
Rename WbToolkit to index.tsx
sharadsw Apr 18, 2024
1656f3e
Move utils components and logic to WbUtils
sharadsw Apr 18, 2024
b7280f9
Move utils stuff into WbUtils folder
sharadsw Apr 19, 2024
1f0bcf1
Fix workbench bugs
sharadsw Apr 22, 2024
1fa91d8
Show updated visual order when hot loads
sharadsw Apr 22, 2024
0c38297
Override default handsontable fonts
sharadsw Apr 22, 2024
49ff2b9
Refactor to remove spreadsheetContainerRef from workbench object
sharadsw Apr 22, 2024
ac8655d
Add unload protect to spreadsheet
sharadsw Apr 22, 2024
2f9a6d4
Rename DataSet to dataset
sharadsw Apr 22, 2024
8baea24
prettier
sharadsw Apr 22, 2024
b030e91
lint
sharadsw Apr 22, 2024
1ce437e
prettier + lint for WbUtils
sharadsw Apr 22, 2024
34f813c
Fix type errors
sharadsw Apr 22, 2024
aaf3d67
Refactor hot props to use userPreferences.use()
sharadsw Apr 22, 2024
8f12639
Make data prop mutable
sharadsw Apr 23, 2024
351876a
Fix loading bar when changing datasets
sharadsw Apr 23, 2024
bd4d4f3
Add error context
sharadsw Apr 23, 2024
6ef0b8d
prettier + lint
sharadsw Apr 23, 2024
beb0af8
update comments
sharadsw Apr 23, 2024
2082a62
Add searchCells with SettingsChange for WbUtils
sharadsw Apr 24, 2024
1ebb231
Lift searchRef up to WbView
sharadsw Apr 24, 2024
b79906c
prettier + lint
sharadsw Apr 24, 2024
b7ac0ff
Remove unused strings
CarolineDenis Apr 25, 2024
f2c2042
Merge branch 'production' into issue-4611
sharadsw May 6, 2024
b1dc3cd
re-add disambiguation fix
sharadsw May 6, 2024
d9ff45b
add back missed strings
sharadsw May 6, 2024
2489249
lint
sharadsw May 6, 2024
3d320f0
Lint code with ESLint and Prettier
sharadsw May 6, 2024
dd77753
Merge branch 'production' into issue-4611
sharadsw May 8, 2024
b0f18a0
Override readonly context set by upload
sharadsw May 8, 2024
85a1e67
Improve validation performance
sharadsw May 10, 2024
7ee6fc7
Fix handsontable text colors
sharadsw May 13, 2024
5497c85
Fix error cells disappearing on load
sharadsw May 13, 2024
a4a5a8a
Fix default values and error cells disappearing when toggling results
sharadsw May 13, 2024
8892a1d
Merge remote-tracking branch 'origin/production' into issue-4611
sharadsw May 14, 2024
298e0a8
Fix search results highlighting becoming inverted
sharadsw May 16, 2024
0ec6291
Rename rollback to confirmRollback
sharadsw May 16, 2024
612dc75
improve imports
sharadsw May 16, 2024
f7f0f3d
Merge remote-tracking branch 'origin/issue-4611' into issue-4611
sharadsw May 16, 2024
45771ff
destructure useWbActions
sharadsw May 16, 2024
cdbe9e3
remove extra promise chain
sharadsw May 16, 2024
720adba
add results return type
sharadsw May 16, 2024
2572218
add set type
sharadsw May 16, 2024
6049e05
change ref variable name
sharadsw May 16, 2024
b0c9d41
use triple equals
sharadsw May 16, 2024
8f2606b
make constructor public
sharadsw May 16, 2024
aadc396
improve function access modifiers
sharadsw May 16, 2024
90fd281
Remove extra loading indicator in save
sharadsw May 16, 2024
4a43a97
Add return type to useWbActions
sharadsw May 16, 2024
bf77135
Add return type to getMessage
sharadsw May 16, 2024
fc2c0d1
remove magic number in utils
sharadsw May 16, 2024
7c1f270
make conditional functional call clearer
sharadsw May 16, 2024
1dc80c8
cleaner condition
sharadsw May 16, 2024
355c99d
add return type to hook
sharadsw May 16, 2024
b7da4b4
rename getHotProps
sharadsw May 16, 2024
ce20615
rename getHotHooks
sharadsw May 16, 2024
7a32dc5
remove ternary in WbSave
sharadsw May 16, 2024
fa58922
remove ternary in WbNoUploadPlan
sharadsw May 16, 2024
4a0f0a6
remove ternary in WbUpload
sharadsw May 16, 2024
2526c69
make triggerDatasetRefresh a one-liner
sharadsw May 16, 2024
5e77c09
remove ternary for live validate
sharadsw May 16, 2024
065e2d2
use StringToJsx
sharadsw May 16, 2024
bbb2124
code golf for spreadsheetContainer
sharadsw May 16, 2024
214587f
use setHotData helper
sharadsw May 16, 2024
13bafa9
allow reordering columns on upload
sharadsw May 16, 2024
687fd7a
block column reorder in results view
sharadsw May 16, 2024
89b0d4d
remove ternary for rollback
sharadsw May 16, 2024
848bf5f
remove ternary in actions
sharadsw May 16, 2024
484c024
Lint code with ESLint and Prettier
sharadsw May 16, 2024
ee11564
Merge remote-tracking branch 'origin/issue-4611' into issue-4611
sharadsw May 16, 2024
02d367c
Lint code with ESLint and Prettier
sharadsw May 16, 2024
fea2d2b
add f.fastParseInt
sharadsw May 17, 2024
98e4331
Merge remote-tracking branch 'origin/issue-4611' into issue-4611
sharadsw May 17, 2024
2394d54
improve cellMeta types
sharadsw May 17, 2024
39a6597
Lint code with ESLint and Prettier
sharadsw May 17, 2024
196b15e
remove falsy checks for workbench.hot
sharadsw May 17, 2024
3dbe8aa
Improve method access in CellMeta, Disambiguation and Validation
sharadsw May 17, 2024
60f8121
Merge remote-tracking branch 'origin/issue-4611' into issue-4611
sharadsw May 17, 2024
3005137
remove ternary for showResults
sharadsw May 17, 2024
0901068
merge imports
sharadsw May 17, 2024
c1d37ca
Lint code with ESLint and Prettier
sharadsw May 17, 2024
2b4d619
Fix save button not triggering
sharadsw May 17, 2024
3fd6d6b
Lint code with ESLint and Prettier
sharadsw May 17, 2024
cc3ac8a
Add TODO for fastParseInt
sharadsw May 17, 2024
f08cfad
fix search
sharadsw May 19, 2024
8095d39
add search handler to callback
sharadsw May 20, 2024
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
10 changes: 10 additions & 0 deletions specifyweb/frontend/js_src/css/workbench.css
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@
--accent-color: var(--search-result);
}

/*
* Override default font properties: required for handsontable 10 and above
* See: https://github.com/handsontable/handsontable/pull/8681
*/
.handsontable {
@apply text-black dark:text-white;
font-family: inherit;
font-size: inherit;
}

sharadsw marked this conversation as resolved.
Show resolved Hide resolved
/* Handsontable dark mode */
.handsontable td,
.htContextMenu table tbody tr td {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ export const routes: RA<EnhancedRoute> = [
{
path: ':id',
element: () =>
import('../WorkBench/Template').then(({ WorkBench }) => WorkBench),
import('../WorkBench/index').then(({ WorkBench }) => WorkBench),
},
{
path: 'import',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';

import { commonText } from '../../localization/common';
import { wbPlanText } from '../../localization/wbPlan';
import { Button } from '../Atoms/Button';
import { Link } from '../Atoms/Link';
import { Dialog } from '../Molecules/Dialog';
import { hasPermission } from '../Permissions/helpers';
import type { WbMapping } from '../WorkBench/mapping';

export function WbNoUploadPlan({
isUploaded,
mappings,
datasetId,
noUploadPlan,
onOpenNoUploadPlan: handleOpenNoUploadPlan,
onCloseNoUploadPlan: handleCloseNoUploadPlan,
}: {
readonly isUploaded: boolean;
readonly mappings: WbMapping | undefined;
readonly datasetId: number;
readonly noUploadPlan: boolean;
readonly onOpenNoUploadPlan: () => void;
readonly onCloseNoUploadPlan: () => void;
}): JSX.Element {
React.useEffect(() => {
if (
!isUploaded &&
(mappings?.lines ?? []).length === 0 &&
hasPermission('/workbench/dataset', 'upload')
) {
handleOpenNoUploadPlan();
}
}, []);

return (
<>
{noUploadPlan ? (
<Dialog
buttons={
<>
<Button.DialogClose>{commonText.close()}</Button.DialogClose>
<Link.Info href={`/specify/workbench/plan/${datasetId}/`}>
{commonText.create()}
</Link.Info>
</>
}
header={wbPlanText.noUploadPlan()}
onClose={handleCloseNoUploadPlan}
>
{wbPlanText.noUploadPlanDescription()}
</Dialog>
) : undefined}
sharadsw marked this conversation as resolved.
Show resolved Hide resolved
</>
);
}
53 changes: 53 additions & 0 deletions specifyweb/frontend/js_src/lib/components/WbActions/WbRevert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from 'react';

import { useBooleanState } from '../../hooks/useBooleanState';
import { commonText } from '../../localization/common';
import { wbText } from '../../localization/workbench';
import { Button } from '../Atoms/Button';
import { Dialog } from '../Molecules/Dialog';

export function WbRevert({
hasUnsavedChanges,
onRefresh: handleRefresh,
onSpreadsheetUpToDate: handleSpreadsheetUpToDate,
}: {
readonly hasUnsavedChanges: boolean;
readonly onRefresh: () => void;
readonly onSpreadsheetUpToDate: () => void;
}): JSX.Element {
const [showRevert, openRevert, closeRevert] = useBooleanState();

const handleRevert = () => {
handleRefresh();
closeRevert();
handleSpreadsheetUpToDate();
};

return (
<>
<Button.Small
aria-haspopup="dialog"
disabled={!hasUnsavedChanges}
onClick={openRevert}
>
{wbText.revert()}
</Button.Small>
{showRevert && (
<Dialog
buttons={
<>
<Button.DialogClose>{commonText.cancel()}</Button.DialogClose>
<Button.Danger onClick={handleRevert}>
{wbText.revert()}
</Button.Danger>
</>
}
header={wbText.revertChanges()}
onClose={closeRevert}
>
{wbText.revertChangesDescription()}
</Dialog>
)}
</>
);
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,51 @@
import React from 'react';

import { useBooleanState } from '../../hooks/useBooleanState';
import { commonText } from '../../localization/common';
import { wbText } from '../../localization/workbench';
import { ping } from '../../utils/ajax/ping';
import { Button } from '../Atoms/Button';
import { LoadingContext } from '../Core/Contexts';
import { Dialog, dialogClassNames } from '../Molecules/Dialog';
import type { WbStatus } from '../WorkBench/WbView';

export function RollbackConfirmation({
dataSetId,
export function WbRollback({
datasetId,
triggerStatusComponent,
}: {
readonly datasetId: number;
readonly triggerStatusComponent: (mode: WbStatus) => void;
}): JSX.Element {
const [rollback, handleOpen, handleClose] = useBooleanState();
sharadsw marked this conversation as resolved.
Show resolved Hide resolved

const handleRollback = () => triggerStatusComponent('unupload');

return (
<>
<Button.Small
aria-haspopup="dialog"
aria-pressed={rollback}
onClick={handleOpen}
>
{wbText.rollback()}
</Button.Small>
{rollback ? (
<RollbackConfirmation
datasetId={datasetId}
onClose={handleClose}
onRollback={handleRollback}
/>
) : undefined}
sharadsw marked this conversation as resolved.
Show resolved Hide resolved
</>
);
}

function RollbackConfirmation({
datasetId,
onClose: handleClose,
onRollback: handleRollback,
}: {
readonly dataSetId: number;
readonly datasetId: number;
readonly onClose: () => void;
readonly onRollback: () => void;
}): JSX.Element {
Expand All @@ -25,7 +58,7 @@ export function RollbackConfirmation({
<Button.Danger
onClick={() =>
loading(
ping(`/api/workbench/unupload/${dataSetId}/`, {
ping(`/api/workbench/unupload/${datasetId}/`, {
method: 'POST',
})
.then(handleRollback)
Expand Down
81 changes: 81 additions & 0 deletions specifyweb/frontend/js_src/lib/components/WbActions/WbSave.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React from 'react';

import { useBooleanState } from '../../hooks/useBooleanState';
import { commonText } from '../../localization/common';
import { wbText } from '../../localization/workbench';
import { Http } from '../../utils/ajax/definitions';
import { ping } from '../../utils/ajax/ping';
import { overwriteReadOnly } from '../../utils/types';
import { Button } from '../Atoms/Button';
import { className } from '../Atoms/className';
import { LoadingContext } from '../Core/Contexts';
import { loadingBar } from '../Molecules';
import { Dialog } from '../Molecules/Dialog';
import type { Workbench } from '../WorkBench/WbView';

export function WbSave({
workbench,
hasUnsavedChanges,
checkDeletedFail,
onSpreadsheetUpToDate: handleSpreadsheetUpToDate,
}: {
readonly workbench: Workbench;
readonly hasUnsavedChanges: boolean;
readonly checkDeletedFail: (statusCode: number) => void;
readonly onSpreadsheetUpToDate: () => void;
}): JSX.Element {
const [showProgressBar, openProgressBar, closeProgressBar] =
useBooleanState();
const loading = React.useContext(LoadingContext);

const handleSave = () => {
// Clear validation
overwriteReadOnly(workbench.dataset, 'rowresults', null);
workbench.validation.stopLiveValidation();

// Show saving progress bar
openProgressBar();

// Send data
loading(
sharadsw marked this conversation as resolved.
Show resolved Hide resolved
ping(`/api/workbench/rows/${workbench.dataset.id}/`, {
method: 'PUT',
body: workbench.data,
expectedErrors: [Http.NO_CONTENT, Http.NOT_FOUND],
})
.then((status) => checkDeletedFail(status))
.then(() => {
handleSpreadsheetUpToDate();
workbench.cells.cellMeta = [];
/*
* TODO: Figure out how to rework searchCells for SettingsChange as input
* workbench.utils?.searchCells({ key: 'SettingsChange' });
*/
workbench.hot?.render();
closeProgressBar();
})
);
};

return (
<>
<Button.Small
aria-haspopup="dialog"
disabled={!hasUnsavedChanges}
variant={className.saveButton}
onClick={handleSave}
>
{commonText.save()}
</Button.Small>
{showProgressBar ? (
<Dialog
buttons={undefined}
header={wbText.saving()}
onClose={closeProgressBar}
>
{loadingBar}
</Dialog>
) : undefined}
sharadsw marked this conversation as resolved.
Show resolved Hide resolved
</>
);
}
74 changes: 74 additions & 0 deletions specifyweb/frontend/js_src/lib/components/WbActions/WbUpload.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React from 'react';

import { useBooleanState } from '../../hooks/useBooleanState';
import { commonText } from '../../localization/common';
import { wbText } from '../../localization/workbench';
import { Button } from '../Atoms/Button';
import { Dialog } from '../Molecules/Dialog';
import type { WbCellCounts } from '../WorkBench/CellMeta';
import type { WbMapping } from '../WorkBench/mapping';
import type { WbStatus } from '../WorkBench/WbView';

export function WbUpload({
hasUnsavedChanges,
mappings,
openNoUploadPlan,
startUpload,
cellCounts,
}: {
readonly hasUnsavedChanges: boolean;
readonly mappings: WbMapping | undefined;
readonly openNoUploadPlan: () => void;
readonly startUpload: (mode: WbStatus) => void;
readonly cellCounts: WbCellCounts;
}): JSX.Element {
const [showUpload, openUpload, closeUpload] = useBooleanState();

const handleUpload = (): void => {
if ((mappings?.lines ?? []).length > 0) {
openUpload();
} else {
openNoUploadPlan();
}
};

const handleConfirmUpload = (): void => {
startUpload('upload');
closeUpload();
};

return (
<>
<Button.Small
aria-haspopup="dialog"
disabled={hasUnsavedChanges || cellCounts.invalidCells > 0}
title={
hasUnsavedChanges
? wbText.unavailableWhileEditing()
: cellCounts.invalidCells > 0
? wbText.uploadUnavailableWhileHasErrors()
: ''
}
onClick={handleUpload}
>
{wbText.upload()}
</Button.Small>
{showUpload ? (
<Dialog
buttons={
<>
<Button.DialogClose>{commonText.cancel()}</Button.DialogClose>
<Button.Info onClick={handleConfirmUpload}>
{wbText.upload()}
</Button.Info>
</>
}
header={wbText.startUpload()}
onClose={closeUpload}
>
{wbText.startUploadDescription()}
</Dialog>
) : undefined}
sharadsw marked this conversation as resolved.
Show resolved Hide resolved
</>
);
}
Loading
Loading