Skip to content

Batch edit for multiple trees #6196

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

Merged
merged 57 commits into from
Apr 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
419e37c
Enable trees in queries
sharadsw Feb 5, 2025
93e2a0a
Use query construct code from #4929
sharadsw Feb 7, 2025
cff6f56
Update unit test
sharadsw Feb 7, 2025
7e478b9
Merge branch 'issue-5413' into issue-6127
sharadsw Feb 7, 2025
7d7cdd0
Remove param_count
sharadsw Feb 13, 2025
b389372
Display tree name in query error
sharadsw Feb 14, 2025
536fe0c
Merge remote-tracking branch 'origin/issue-5413' into issue-6127
sharadsw Feb 18, 2025
aa81431
Update TreeRankQuery to fix implicit ORs
sharadsw Feb 20, 2025
52e312f
Allow removing last row in Batch Edit
sharadsw Feb 24, 2025
444eb32
Make a missing rank info dialog which proceeds to dataset creation
sharadsw Feb 25, 2025
65f7d21
Augment tree queries with missing ranks for batch edit
sharadsw Feb 25, 2025
46fe370
Lint code with ESLint and Prettier
sharadsw Feb 25, 2025
59eb7ff
Adjust apply_batch_edit_pack for multiple trees
sharadsw Feb 25, 2025
79bdb27
Add a discipline type in tests
sharadsw Feb 25, 2025
1720131
Un-enforce TreeRankRecord in upload plan
sharadsw Mar 3, 2025
4f161f5
Add loading action to missing ranks dialog
sharadsw Mar 3, 2025
18305a6
Move table name to same line in missing fields dialog
sharadsw Mar 3, 2025
78a6769
Handle case when rank name has spaces
sharadsw Mar 3, 2025
d65495f
Add a close button to missing ranks dialog
sharadsw Mar 3, 2025
7f70cb4
Fix frontend missing field calculation
sharadsw Mar 4, 2025
9407376
Fix frontend to many tree error
sharadsw Mar 4, 2025
937e865
Lint code with ESLint and Prettier
sharadsw Mar 4, 2025
ebd827f
Restrict to manys only for tree fields
sharadsw Mar 4, 2025
f666936
Merge remote-tracking branch 'origin/issue-6127' into issue-6127
sharadsw Mar 4, 2025
246d394
Merge remote-tracking branch 'origin/issue-5413' into issue-6127
sharadsw Mar 6, 2025
5e7d844
Merge branch 'issue-5413' into issue-6127
sharadsw Mar 6, 2025
bf153f9
Fix multiple rank in row error
sharadsw Mar 11, 2025
1550bb8
Merge remote-tracking branch 'origin/issue-6127' into issue-6127
sharadsw Mar 11, 2025
ae42fdd
Fix navigator
sharadsw Mar 12, 2025
2835687
Fix tests
sharadsw Mar 12, 2025
7f2149d
Group missing ranks by tree
sharadsw Mar 12, 2025
9c46e15
Lint code with ESLint and Prettier
sharadsw Mar 12, 2025
b1173ff
Pass filtered treedef ids to the backend
sharadsw Mar 13, 2025
1c29ec9
Merge remote-tracking branch 'origin/issue-6127' into issue-6127
sharadsw Mar 13, 2025
d09d325
Lint code with ESLint and Prettier
sharadsw Mar 13, 2025
e8d138e
Filter trees used when rewriting batch edit dataset
sharadsw Mar 13, 2025
1589ed8
Fix tests
sharadsw Mar 13, 2025
1382ed9
Merge remote-tracking branch 'origin/production' into issue-6127
sharadsw Mar 27, 2025
8ac0c4a
Use TreeRankRecord in upload plan
sharadsw Mar 11, 2025
06f5232
Remove unused string
sharadsw Mar 27, 2025
a8a2ad6
Fix visual order
sharadsw Mar 27, 2025
ca8b498
Revert "Fix visual order"
sharadsw Mar 28, 2025
a6e0d4e
Flag to-many in tree only queries
sharadsw Apr 15, 2025
f36521c
Merge branch 'production' into issue-6127
sharadsw Apr 15, 2025
b31b8a7
Lint code with ESLint and Prettier
sharadsw Apr 15, 2025
cc1f85b
Enable nested to-many in Workbench (#6216)
sharadsw Apr 15, 2025
a81c95f
Lint code with ESLint and Prettier
sharadsw Apr 15, 2025
1e393f0
Check for lowercase tree table names when rewriting tree rank row plan
sharadsw Apr 21, 2025
bcc4277
Merge remote-tracking branch 'origin/production' into issue-6127
sharadsw Apr 21, 2025
3be9e53
Merge branch 'production' into issue-6127
sharadsw Apr 22, 2025
e593bc0
Handle None rank
sharadsw Apr 23, 2025
5235f7b
Merge remote-tracking branch 'origin/issue-6127' into issue-6127
sharadsw Apr 23, 2025
8222246
Fix tree column order
sharadsw Apr 28, 2025
afe7be1
Fix tests
sharadsw Apr 28, 2025
9ad2984
Merge remote-tracking branch 'origin/production' into issue-6127
sharadsw Apr 28, 2025
b273a60
Revert back to sort columns
sharadsw Apr 28, 2025
bf3e055
Merge branch 'production' into issue-6127
sharadsw Apr 29, 2025
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
124 changes: 124 additions & 0 deletions specifyweb/frontend/js_src/lib/components/BatchEdit/MissingRanks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import React from 'react';

import { batchEditText } from '../../localization/batchEdit';
import { commonText } from '../../localization/common';
import { interactionsText } from '../../localization/interactions';
import type { RA, RR } from '../../utils/types';
import { H2, H3, Ul } from '../Atoms';
import { Button } from '../Atoms/Button';
import { Input, Label } from '../Atoms/Form';
import { dialogIcons } from '../Atoms/Icons';
import type { AnyTree } from '../DataModel/helperTypes';
import { strictGetTable } from '../DataModel/tables';
import { getTreeDefinitions } from '../InitialContext/treeRanks';
import { Dialog } from '../Molecules/Dialog';
import { TableIcon } from '../Molecules/TableIcon';

export type TreeDefinitionName = string;

export type MissingRanks = {
// Query can contain relationship to multiple trees
readonly [KEY in AnyTree['tableName']]: RR<TreeDefinitionName, RA<string>>;
};

export function MissingRanksDialog({
missingRanks,
onSelectTreeDef,
onContinue: handleContinue,
onClose: handleClose,
}: {
readonly missingRanks: MissingRanks;
readonly onSelectTreeDef: (
treeTableName: AnyTree['tableName'],
treeDefId: number
) => void;
readonly onContinue: () => void;
readonly onClose: () => void;
}): JSX.Element {
return (
<Dialog
buttons={
<>
<Button.DialogClose>{commonText.close()}</Button.DialogClose>
<Button.Info onClick={handleContinue}>
{interactionsText.continue()}
</Button.Info>
</>
}
header={batchEditText.missingRanksInQuery()}
icon={dialogIcons.info}
onClose={handleClose}
>
<ShowMissingRanks
missingRanks={missingRanks}
onSelectTreeDef={onSelectTreeDef}
/>
</Dialog>
);
}

function ShowMissingRanks({
missingRanks,
onSelectTreeDef: handleSelectTreeDef,
}: {
readonly missingRanks: MissingRanks;
readonly onSelectTreeDef: (
treeTableName: AnyTree['tableName'],
treeDefId: number
) => void;
}) {
return (
<div>
<div className="mt-2 flex gap-2">
<H2>{batchEditText.addTreeRank()}</H2>
</div>
{Object.entries(missingRanks).map(([treeTable, ranks]) => {
const hasMultipleTreeDefs = Object.values(ranks).length > 1;
const treeDefinitions = getTreeDefinitions(treeTable, 'all');

return (
<div key={treeTable}>
<div className="flex gap-2">
<TableIcon
label={strictGetTable(treeTable).label}
name={treeTable}
/>
<H2>{strictGetTable(treeTable).label}</H2>
</div>
{hasMultipleTreeDefs && (
<span>{batchEditText.pickTreesToFilter()}</span>
)}
<div>
{Object.entries(ranks).map(([treeDefName, rankNames]) => {
const treeDefId = treeDefinitions.find(
({ definition }) => definition.name === treeDefName
)?.definition.id;
return (
<div key={treeDefName}>
<Label.Inline>
{hasMultipleTreeDefs && treeDefId !== undefined ? (
<Input.Checkbox
onChange={() =>
handleSelectTreeDef(treeTable, treeDefId)
}
/>
) : undefined}
<H3>{`${treeDefName}:`}</H3>
</Label.Inline>
<Ul>
{rankNames.map((rank) => (
<li className="px-8" key={rank}>
{rank}
</li>
))}
</Ul>
</div>
);
})}
</div>
</div>
);
})}
</div>
);
}
49 changes: 49 additions & 0 deletions specifyweb/frontend/js_src/lib/components/BatchEdit/QueryError.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';

import { batchEditText } from '../../localization/batchEdit';
import { commonText } from '../../localization/common';
import type { RA } from '../../utils/types';
import { H2, H3 } from '../Atoms';
import { dialogIcons } from '../Atoms/Icons';
import { Dialog } from '../Molecules/Dialog';

export type QueryError = {
readonly invalidFields: RA<string>;
};

export function ErrorsDialog({
errors,
onClose: handleClose,
}: {
readonly errors: QueryError;
readonly onClose: () => void;
}): JSX.Element {
return (
<Dialog
buttons={commonText.close()}
header={batchEditText.errorInQuery()}
icon={dialogIcons.error}
onClose={handleClose}
>
<ShowInvalidFields error={errors.invalidFields} />
</Dialog>
);
}

function ShowInvalidFields({
error,
}: {
readonly error: QueryError['invalidFields'];
}) {
const hasErrors = error.length > 0;
return hasErrors ? (
<div>
<div>
<H2>{batchEditText.removeField()}</H2>
</div>
{error.map((singleError) => (
<H3>{singleError}</H3>
))}
</div>
) : null;
}
Loading
Loading