Skip to content

Commit

Permalink
Merge pull request #6046 from specify/issue-6043
Browse files Browse the repository at this point in the history
Fix tree preferences and add an "Order By" field option
  • Loading branch information
grantfitzsimmons authored Jan 10, 2025
2 parents 2c68a85 + a0652ea commit 27476ea
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1103,7 +1103,8 @@ export const userPreferenceDefinitions = {
},
},
recordSet: {
title: '_recordSet' as LocalizedString,
title: () =>
tableLabel('RecordSet'),
items: {
recordToOpen: definePref<'first' | 'last'>({
title: preferencesText.recordSetRecordToOpen(),
Expand Down Expand Up @@ -1347,6 +1348,30 @@ export const userPreferenceDefinitions = {
defaultValue: false,
type: 'java.lang.Boolean',
}),
orderByField: definePref<'fullName' | 'name' | 'nodeNumber' | 'rankId'>({
title: preferencesText.sortByField(),
requiresReload: false,
visible: true,
defaultValue: 'rankId',
values: [
{
value: 'name',
title: localized('_name'),
},
{
value: 'fullName',
title: localized('_fullName'),
},
{
value: 'rankId',
title: localized('_rankId'),
},
{
value: 'nodeNumber',
title: localized('_nodeNumber'),
},
],
}),
searchField: definePref<'fullName' | 'name'>({
title: preferencesText.searchField(),
requiresReload: false,
Expand Down Expand Up @@ -1388,13 +1413,14 @@ export const userPreferenceDefinitions = {
* This would be replaced with labels from schema once
* schema is loaded
*/
title: '_Geography' as LocalizedString,
title: () =>
tableLabel('Geography'),
items: {
treeAccentColor: definePref({
title: preferencesText.treeAccentColor(),
requiresReload: false,
visible: true,
defaultValue: '#f79245',
defaultValue: '#662D91',
renderer: ColorPickerPreferenceItem,
container: 'label',
}),
Expand All @@ -1409,13 +1435,14 @@ export const userPreferenceDefinitions = {
},
},
taxon: {
title: '_Taxon' as LocalizedString,
title: () =>
tableLabel('Taxon'),
items: {
treeAccentColor: definePref({
title: preferencesText.treeAccentColor(),
requiresReload: false,
visible: true,
defaultValue: '#f79245',
defaultValue: '#C1272D',
renderer: ColorPickerPreferenceItem,
container: 'label',
}),
Expand All @@ -1430,13 +1457,14 @@ export const userPreferenceDefinitions = {
},
},
storage: {
title: '_Storage' as LocalizedString,
title: () =>
tableLabel('Storage'),
items: {
treeAccentColor: definePref({
title: preferencesText.treeAccentColor(),
requiresReload: false,
visible: true,
defaultValue: '#f79245',
defaultValue: '#0071BC',
renderer: ColorPickerPreferenceItem,
container: 'label',
}),
Expand All @@ -1451,13 +1479,14 @@ export const userPreferenceDefinitions = {
},
},
geologicTimePeriod: {
title: '_GeologicTimePeriod' as LocalizedString,
title: () =>
tableLabel('GeologicTimePeriod'),
items: {
treeAccentColor: definePref({
title: preferencesText.treeAccentColor(),
requiresReload: false,
visible: true,
defaultValue: '#f79245',
defaultValue: '#39B54A',
renderer: ColorPickerPreferenceItem,
container: 'label',
}),
Expand All @@ -1472,13 +1501,14 @@ export const userPreferenceDefinitions = {
},
},
lithoStrat: {
title: '_LithoStrat' as LocalizedString,
title: () =>
tableLabel('LithoStrat'),
items: {
treeAccentColor: definePref({
title: preferencesText.treeAccentColor(),
requiresReload: false,
visible: true,
defaultValue: '#f79245',
defaultValue: '#C1272D',
renderer: ColorPickerPreferenceItem,
container: 'label',
}),
Expand All @@ -1493,13 +1523,14 @@ export const userPreferenceDefinitions = {
},
},
tectonicUnit: {
title: '_TectonicUnit' as LocalizedString,
title: () =>
tableLabel('TectonicUnit'),
items: {
treeAccentColor: definePref({
title: preferencesText.treeAccentColor(),
requiresReload: false,
visible: true,
defaultValue: '#f79245',
defaultValue: '#FFB728',
renderer: ColorPickerPreferenceItem,
container: 'label',
}),
Expand Down Expand Up @@ -2001,43 +2032,6 @@ export const userPreferenceDefinitions = {
import('../DataModel/tables')
.then(async ({ fetchContext, tables }) =>
fetchContext.then(() => {
const trees = userPreferenceDefinitions.treeEditor.subCategories;
overwriteReadOnly(
trees.geography,
'title',
getField(tables.Geography, 'name').label
);
overwriteReadOnly(
trees.taxon,
'title',
getField(tables.Taxon, 'name').label
);
overwriteReadOnly(
trees.storage,
'title',
getField(tables.Storage, 'name').label
);
overwriteReadOnly(
trees.geologicTimePeriod,
'title',
getField(tables.Geography, 'name').label
);
overwriteReadOnly(
trees.lithoStrat,
'title',
getField(tables.LithoStrat, 'name').label
);
overwriteReadOnly(
trees.tectonicUnit,
'title',
getField(tables.TectonicUnit, 'name').label
);
overwriteReadOnly(
userPreferenceDefinitions.form.subCategories.recordSet,
'title',
getField(tables.RecordSet, 'name').label
);

const treeSearchBehavior =
userPreferenceDefinitions.treeEditor.subCategories.behavior.items
.searchField;
Expand All @@ -2058,15 +2052,79 @@ import('../DataModel/tables')
),
'Unable to find tree full name value'
);
overwriteReadOnly(name, 'title', getField(tables.Taxon, 'name').label);
overwriteReadOnly(
name,
'title',
getField(tables.Taxon, 'name').label);
overwriteReadOnly(
fullName,
'title',
getField(tables.Taxon, 'fullName').label
);
} else softError('Unable to replace the tree preferences item title');

// TODO: Refactor this with a helper function since this is largely the same as above

// Update titles for orderByField
const treeOrderByBehavior =
userPreferenceDefinitions.treeEditor.subCategories.behavior.items.orderByField;
if ('values' in treeOrderByBehavior) {
const orderByValues = treeOrderByBehavior.values as RA<{
readonly value: string;
readonly title: string;
}>;

const nameOrderBy = defined(
orderByValues.find(
(entry) => typeof entry === 'object' && entry.value === 'name'
),
'Unable to find tree name value for orderByField'
);
const fullNameOrderBy = defined(
orderByValues.find(
(entry) => typeof entry === 'object' && entry.value === 'fullName'
),
'Unable to find tree full name value for orderByField'
);
const rankId = defined(
orderByValues.find(
(entry) => typeof entry === 'object' && entry.value === 'rankId'
),
'Unable to find tree rankId value'
);
const nodeNumber = defined(
orderByValues.find(
(entry) => typeof entry === 'object' && entry.value === 'nodeNumber'
),
'Unable to find tree nodeNumber value'
);

overwriteReadOnly(
nameOrderBy,
'title',
getField(tables.Taxon, 'name').label
);
overwriteReadOnly(
fullNameOrderBy,
'title',
getField(tables.Taxon, 'fullName').label
);
overwriteReadOnly(
rankId,
'title',
getField(tables.Taxon,'rankId').label
);
overwriteReadOnly(
nodeNumber,
'title',
getField(tables.Taxon, 'nodeNumber').label
);
} else {
softError('Unable to replace the tree preferences item title for orderByField');
}
})
)

// Not using softFail here to avoid circular dependency
.catch(console.error);

Expand Down
24 changes: 20 additions & 4 deletions specifyweb/frontend/js_src/lib/components/TreeView/Row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useId } from '../../hooks/useId';
import { commonText } from '../../localization/common';
import { treeText } from '../../localization/tree';
import type { RA } from '../../utils/types';
import { sortFunction } from '../../utils/utils';
import { Button } from '../Atoms/Button';
import { className } from '../Atoms/className';
import { icons } from '../Atoms/Icons';
Expand Down Expand Up @@ -74,18 +75,33 @@ export function TreeRow<SCHEMA extends AnyTree>({
const isExpanded = Array.isArray(conformation);
const isLoading = isExpanded && !Array.isArray(rows);
const displayChildren = isExpanded && typeof rows?.[0] === 'object';
const orderByField = userPreferences.get(
'treeEditor',
'behavior',
'orderByField'
);

React.useEffect(() => {
if (!isLoading) return undefined;

void getRows(row.nodeId).then((rows) =>
destructorCalled ? undefined : setRows(rows)
);
void getRows(row.nodeId).then((fetchedRows: RA<Row>) => {
const sortedRows = Array.from(fetchedRows).sort(
sortFunction<Row, number | string>(
orderByField === 'rankId' ? (row) => row.rankId :
orderByField === 'nodeNumber' ? (row) => row.nodeNumber :
orderByField === 'name' ? (row) => row.name :
orderByField === 'fullName' ? (row) => row.fullName :
() => 0
)
);
destructorCalled ? undefined : setRows(sortedRows);
});

let destructorCalled = false;
return (): void => {
destructorCalled = true;
};
}, [isLoading, getRows, row]);
}, [isLoading, getRows, row, orderByField]);

// Fetch children stats
const isLoadingStats = displayChildren && childStats === undefined;
Expand Down
5 changes: 4 additions & 1 deletion specifyweb/frontend/js_src/lib/localization/preferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1412,6 +1412,9 @@ export const preferencesText = createDictionary({
gelangen
`,
},
sortByField: {
'en-us': 'Order By Field',
},
lineWrap: {
'en-us': 'Line wrap',
'ru-ru': 'Перенос строки',
Expand Down Expand Up @@ -1492,7 +1495,7 @@ export const preferencesText = createDictionary({
'ru-ru': 'Поиск с учетом регистра',
},
searchField: {
'en-us': 'Search field',
'en-us': 'Search Field',
'ru-ru': 'Поле поиска',
'es-es': 'Campo de búsqueda',
'fr-fr': 'Champ de recherche',
Expand Down

0 comments on commit 27476ea

Please sign in to comment.