diff --git a/specifyweb/backend/context/data/viewset_5.xml b/specifyweb/backend/context/data/viewset_5.xml
index debd4b21ea9..6cda666b2ed 100644
--- a/specifyweb/backend/context/data/viewset_5.xml
+++ b/specifyweb/backend/context/data/viewset_5.xml
@@ -559,10 +559,6 @@
|
-
- |
- |
-
|
|
@@ -582,10 +578,6 @@
|
-
- |
- |
-
|
|
@@ -608,10 +600,6 @@
|
-
- |
- |
-
|
|
@@ -631,10 +619,6 @@
|
-
- |
- |
-
|
|
@@ -656,10 +640,6 @@
|
-
- |
- |
-
|
|
diff --git a/specifyweb/frontend/js_src/lib/components/DataModel/businessRules.ts b/specifyweb/frontend/js_src/lib/components/DataModel/businessRules.ts
index f7581eb2b30..868b11dac2a 100644
--- a/specifyweb/frontend/js_src/lib/components/DataModel/businessRules.ts
+++ b/specifyweb/frontend/js_src/lib/components/DataModel/businessRules.ts
@@ -7,7 +7,11 @@ import { softFail } from '../Errors/Crash';
import { isTreeResource } from '../InitialContext/treeRanks';
import type { BusinessRuleDefs } from './businessRuleDefs';
import { businessRuleDefs } from './businessRuleDefs';
-import { backboneFieldSeparator, backendFilter, djangoLookupSeparator } from './helpers';
+import {
+ backboneFieldSeparator,
+ backendFilter,
+ djangoLookupSeparator,
+} from './helpers';
import type {
AnySchema,
AnyTree,
@@ -316,10 +320,7 @@ export class BusinessRuleManager {
)
);
- const stringValuesAreEqual = (
- left: string,
- right: string
- ): boolean =>
+ const stringValuesAreEqual = (left: string, right: string): boolean =>
rule.isDatabaseConstraint
? left.localeCompare(right, undefined, { sensitivity: 'accent' }) === 0
: left === right;
diff --git a/specifyweb/frontend/js_src/lib/components/FormParse/__tests__/index.test.ts b/specifyweb/frontend/js_src/lib/components/FormParse/__tests__/index.test.ts
index 77693cf8d0a..859c98374e4 100644
--- a/specifyweb/frontend/js_src/lib/components/FormParse/__tests__/index.test.ts
+++ b/specifyweb/frontend/js_src/lib/components/FormParse/__tests__/index.test.ts
@@ -7,7 +7,6 @@ import { ensure, localized } from '../../../utils/types';
import { removeKey } from '../../../utils/utils';
import { strictParseXml } from '../../AppResources/parseXml';
import { tables } from '../../DataModel/tables';
-import { getPref } from '../../InitialContext/remotePrefs';
import { formatUrl } from '../../Router/queryString';
import type { SimpleXmlNode } from '../../Syncer/xmlToJson';
import { toSimpleXmlNode, xmlToJson } from '../../Syncer/xmlToJson';
@@ -471,25 +470,7 @@ describe('parseFormDefinition', () => {
describe('getColumnDefinitions', () => {
requireContext();
- test('can customize the column definition source', () =>
- expect(
- getColumnDefinitions(
- toSimpleXmlNode(
- xmlToJson(
- strictParseXml(
- `
- A
- B
- `
- )
- )
- )
- )
- ).toBe('B'));
-
- test('fall back to first definition available', () =>
+ test('uses the first column definition available', () =>
expect(
getColumnDefinitions(
xml(
diff --git a/specifyweb/frontend/js_src/lib/components/FormParse/index.ts b/specifyweb/frontend/js_src/lib/components/FormParse/index.ts
index 2ae4158a1fc..c7019c45b6c 100644
--- a/specifyweb/frontend/js_src/lib/components/FormParse/index.ts
+++ b/specifyweb/frontend/js_src/lib/components/FormParse/index.ts
@@ -34,7 +34,6 @@ import {
setLogContext,
} from '../Errors/logContext';
import { cacheableUrl } from '../InitialContext';
-import { getPref } from '../InitialContext/remotePrefs';
import { formatUrl } from '../Router/queryString';
import type { SimpleXmlNode } from '../Syncer/xmlToJson';
import { toSimpleXmlNode, xmlToJson } from '../Syncer/xmlToJson';
@@ -532,11 +531,7 @@ export async function parseFormDefinition(
}
function getColumnDefinitions(viewDefinition: SimpleXmlNode): string {
- const definition =
- getColumnDefinition(
- viewDefinition,
- getPref('form.definition.columnSource')
- ) ?? getColumnDefinition(viewDefinition, undefined);
+ const definition = getColumnDefinition(viewDefinition, undefined);
// Specify 7 handles forms without column definition fine, so no need to warn for this
return definition ?? getParsedAttribute(viewDefinition, 'colDef') ?? '';
}
diff --git a/specifyweb/frontend/js_src/lib/components/InitialContext/__tests__/__snapshots__/remotePrefs.test.ts.snap b/specifyweb/frontend/js_src/lib/components/InitialContext/__tests__/__snapshots__/remotePrefs.test.ts.snap
index 39fc488e115..0ba6373e6e3 100644
--- a/specifyweb/frontend/js_src/lib/components/InitialContext/__tests__/__snapshots__/remotePrefs.test.ts.snap
+++ b/specifyweb/frontend/js_src/lib/components/InitialContext/__tests__/__snapshots__/remotePrefs.test.ts.snap
@@ -50,13 +50,7 @@ exports[`fetches and parses remotePrefs correctly 1`] = `
"SubPaneMgr.MaxPanes": "12",
"SymbiotaTask.BaseUrlPref": "http\\\\://pinkava.asu.edu/symbiota/sandbox/webservices/dwc/dwcaingesthandler.php",
"SymbiotaTask.SHOW_TASK_PREF.fish": "false",
- "TaxonTreeEditor.DisplayAuthor": "true",
"Testing2": "",
- "TreeEditor.Rank.Threshold.Geography": "100",
- "TreeEditor.Rank.Threshold.GeologicTimePeriod": "0",
- "TreeEditor.Rank.Threshold.LithoStrat": "200",
- "TreeEditor.Rank.Threshold.Storage": "200",
- "TreeEditor.Rank.Threshold.Taxon": "100",
"TreeEditor.RestoreTreeExpansionState": "true",
"Treeeditor.SynonymyColor.Geography": "255, 0, 0",
"Treeeditor.SynonymyColor.GeologicTimePeriod": "0, 0, 255",
diff --git a/specifyweb/frontend/js_src/lib/components/InitialContext/__tests__/remotePrefs.test.ts b/specifyweb/frontend/js_src/lib/components/InitialContext/__tests__/remotePrefs.test.ts
index c36eb85956d..d545c838da1 100644
--- a/specifyweb/frontend/js_src/lib/components/InitialContext/__tests__/remotePrefs.test.ts
+++ b/specifyweb/frontend/js_src/lib/components/InitialContext/__tests__/remotePrefs.test.ts
@@ -17,8 +17,8 @@ describe('Parsing Remote Prefs', () => {
test('parses numeric value', () =>
expect(getPref('attachment.preview_size')).toBe(123));
test('uses default value if pref is not set', () =>
- expect(getPref('form.definition.columnSource')).toBe(
- remotePrefsDefinitions()['form.definition.columnSource'].defaultValue
+ expect(getPref('ui.formatting.scrmonthformat')).toBe(
+ remotePrefsDefinitions()['ui.formatting.scrmonthformat'].defaultValue
));
});
diff --git a/specifyweb/frontend/js_src/lib/components/InitialContext/remotePrefs.ts b/specifyweb/frontend/js_src/lib/components/InitialContext/remotePrefs.ts
index 2574f60f53d..0ab66f5601c 100644
--- a/specifyweb/frontend/js_src/lib/components/InitialContext/remotePrefs.ts
+++ b/specifyweb/frontend/js_src/lib/components/InitialContext/remotePrefs.ts
@@ -126,97 +126,6 @@ export const remotePrefsDefinitions = f.store(
defaultValue: 'MM/YYYY',
formatters: [formatter.trim, formatter.toUpperCase],
},
- 'GeologicTimePeriod.treeview_sort_field': {
- description: 'Sort order for nodes in the tree viewer',
- defaultValue: 'name',
- formatters: [formatter.trim],
- isLegacy: true,
- },
- 'Taxon.treeview_sort_field': {
- description: 'Sort order for nodes in the tree viewer',
- defaultValue: 'name',
- formatters: [formatter.trim],
- isLegacy: true,
- },
- 'Geography.treeview_sort_field': {
- description: 'Sort order for nodes in the tree viewer',
- defaultValue: 'name',
- formatters: [formatter.trim],
- isLegacy: true,
- },
- 'LithoStrat.treeview_sort_field': {
- description: 'Sort order for nodes in the tree viewer',
- defaultValue: 'name',
- formatters: [formatter.trim],
- isLegacy: true,
- },
- 'Storage.treeview_sort_field': {
- description: 'Sort order for nodes in the tree viewer',
- defaultValue: 'name',
- formatters: [formatter.trim],
- isLegacy: true,
- },
- 'TectonicUnit.treeview_sort_field': {
- description: 'Sort order for nodes in the tree viewer',
- defaultValue: 'name',
- formatters: [formatter.trim],
- isLegacy: false,
- },
- 'TreeEditor.Rank.Threshold.GeologicTimePeriod': {
- description:
- 'Show Collection Object count only for nodes with RankID >= than this value',
- defaultValue: 99_999,
- parser: 'java.lang.Long',
- isLegacy: true,
- },
- 'TreeEditor.Rank.Threshold.Taxon': {
- description:
- 'Show Collection Object count only for nodes with RankID >= than this value',
- defaultValue: 99_999,
- parser: 'java.lang.Long',
- isLegacy: true,
- },
- 'TreeEditor.Rank.Threshold.Geography': {
- description:
- 'Show Collection Object count only for nodes with RankID >= than this value',
- defaultValue: 99_999,
- parser: 'java.lang.Long',
- isLegacy: true,
- },
- 'TreeEditor.Rank.Threshold.LithoStrat': {
- description:
- 'Show Collection Object count only for nodes with RankID >= than this value',
- defaultValue: 99_999,
- parser: 'java.lang.Long',
- isLegacy: true,
- },
- 'TreeEditor.Rank.Threshold.Storage': {
- description:
- 'Show Collection Object count only for nodes with RankID >= than this value',
- defaultValue: 99_999,
- parser: 'java.lang.Long',
- isLegacy: true,
- },
- 'TreeEditor.Rank.Threshold.TectonicUnit': {
- description:
- 'Show Collection Object count only for nodes with RankID >= than this value',
- defaultValue: 99_999,
- parser: 'java.lang.Long',
- isLegacy: true,
- },
-
- /*
- * This pref was implemented in Specify 7 in https://github.com/specify/specify7/pull/2818
- * and went through many iterations and changes.
- * See the Pull Request for the full context and implementation/design decision.
- */
- 'TaxonTreeEditor.DisplayAuthor': {
- description:
- 'Display Authors of Taxons next to nodes in the Tree Viewer',
- defaultValue: false,
- parser: 'java.lang.Boolean',
- isLegacy: true,
- },
'attachment.is_public_default': {
description: 'Whether new Attachments are public by default',
defaultValue: true,
@@ -242,12 +151,6 @@ export const remotePrefsDefinitions = f.store(
parser: 'java.lang.Boolean',
isLegacy: true,
},
- 'form.definition.columnSource': {
- description: 'The platform to use as a source of columns',
- defaultValue: 'lnx',
- formatter: [formatter.trim],
- isLegacy: false,
- },
'sp7.allow_adding_child_to_synonymized_parent.GeologicTimePeriod': {
description:
'Allowed to add children to synopsized Geologic Time Period records',
diff --git a/specifyweb/frontend/js_src/lib/components/Preferences/UserDefinitions.tsx b/specifyweb/frontend/js_src/lib/components/Preferences/UserDefinitions.tsx
index 52d5f72b442..722657bfe27 100644
--- a/specifyweb/frontend/js_src/lib/components/Preferences/UserDefinitions.tsx
+++ b/specifyweb/frontend/js_src/lib/components/Preferences/UserDefinitions.tsx
@@ -1474,6 +1474,15 @@ export const userPreferenceDefinitions = {
renderer: ColorPickerPreferenceItem,
container: 'label',
}),
+ statsThreshold: definePref({
+ title: preferencesText.treeStatsThreshold(),
+ description: preferencesText.treeStatsThresholdDescription(),
+ requiresReload: false,
+ visible: false,
+ defaultValue: 99_999,
+ type: 'java.lang.Long',
+ container: 'label',
+ }),
},
},
taxon: {
@@ -1502,6 +1511,15 @@ export const userPreferenceDefinitions = {
defaultValue: true,
type: 'java.lang.Boolean',
}),
+ statsThreshold: definePref({
+ title: preferencesText.treeStatsThreshold(),
+ description: preferencesText.treeStatsThresholdDescription(),
+ requiresReload: false,
+ visible: false,
+ defaultValue: 99_999,
+ type: 'java.lang.Long',
+ container: 'label',
+ }),
},
},
storage: {
@@ -1523,6 +1541,15 @@ export const userPreferenceDefinitions = {
renderer: ColorPickerPreferenceItem,
container: 'label',
}),
+ statsThreshold: definePref({
+ title: preferencesText.treeStatsThreshold(),
+ description: preferencesText.treeStatsThresholdDescription(),
+ requiresReload: false,
+ visible: false,
+ defaultValue: 99_999,
+ type: 'java.lang.Long',
+ container: 'label',
+ }),
},
},
geologicTimePeriod: {
@@ -1544,6 +1571,15 @@ export const userPreferenceDefinitions = {
renderer: ColorPickerPreferenceItem,
container: 'label',
}),
+ statsThreshold: definePref({
+ title: preferencesText.treeStatsThreshold(),
+ description: preferencesText.treeStatsThresholdDescription(),
+ requiresReload: false,
+ visible: false,
+ defaultValue: 99_999,
+ type: 'java.lang.Long',
+ container: 'label',
+ }),
},
},
lithoStrat: {
@@ -1565,6 +1601,15 @@ export const userPreferenceDefinitions = {
renderer: ColorPickerPreferenceItem,
container: 'label',
}),
+ statsThreshold: definePref({
+ title: preferencesText.treeStatsThreshold(),
+ description: preferencesText.treeStatsThresholdDescription(),
+ requiresReload: false,
+ visible: false,
+ defaultValue: 99_999,
+ type: 'java.lang.Long',
+ container: 'label',
+ }),
},
},
tectonicUnit: {
@@ -1586,6 +1631,15 @@ export const userPreferenceDefinitions = {
renderer: ColorPickerPreferenceItem,
container: 'label',
}),
+ statsThreshold: definePref({
+ title: preferencesText.treeStatsThreshold(),
+ description: preferencesText.treeStatsThresholdDescription(),
+ requiresReload: false,
+ visible: false,
+ defaultValue: 99_999,
+ type: 'java.lang.Long',
+ container: 'label',
+ }),
},
},
},
diff --git a/specifyweb/frontend/js_src/lib/components/TreeView/Tree.tsx b/specifyweb/frontend/js_src/lib/components/TreeView/Tree.tsx
index 6b1402cbf11..6ebf98e5ab4 100644
--- a/specifyweb/frontend/js_src/lib/components/TreeView/Tree.tsx
+++ b/specifyweb/frontend/js_src/lib/components/TreeView/Tree.tsx
@@ -19,7 +19,6 @@ import { idFromUrl } from '../DataModel/resource';
import { deserializeResource } from '../DataModel/serializers';
import { softError } from '../Errors/assert';
import { ResourceView } from '../Forms/ResourceView';
-import { getPref } from '../InitialContext/remotePrefs';
import { hasTablePermission } from '../Permissions/helpers';
import { useHighContrast } from '../Preferences/Hooks';
import { userPreferences } from '../Preferences/userPreferences';
@@ -98,8 +97,10 @@ export function Tree<
'synonymColor'
);
- const statsThreshold = getPref(
- `TreeEditor.Rank.Threshold.${tableName as 'Geography'}`
+ const [statsThreshold] = userPreferences.use(
+ 'treeEditor',
+ treeToPref[tableName],
+ 'statsThreshold'
);
const getStats = React.useCallback(
async (nodeId: number | 'null', rankId: number): Promise =>
diff --git a/specifyweb/frontend/js_src/lib/components/TreeView/index.tsx b/specifyweb/frontend/js_src/lib/components/TreeView/index.tsx
index d068e22be85..8e8fbd15a26 100644
--- a/specifyweb/frontend/js_src/lib/components/TreeView/index.tsx
+++ b/specifyweb/frontend/js_src/lib/components/TreeView/index.tsx
@@ -27,7 +27,6 @@ import type { SpecifyTable } from '../DataModel/specifyTable';
import { genericTables, getTable } from '../DataModel/tables';
import { ErrorBoundary } from '../Errors/ErrorBoundary';
import { useMenuItem } from '../Header/MenuContext';
-import { getPref } from '../InitialContext/remotePrefs';
import type { TreeInformation } from '../InitialContext/treeRanks';
import {
getTreeDefinitions,
@@ -155,8 +154,12 @@ function TreeView({
useTitle(treeText.treeViewTitle({ treeName: table.label }));
- // Node sort order
- const sortField = getPref(`${tableName as 'Geography'}.treeview_sort_field`);
+ // Node sort order and author display are user preferences
+ const sortField = userPreferences.get(
+ 'treeEditor',
+ 'behavior',
+ 'orderByField'
+ );
const includeAuthor = userPreferences.get(
'treeEditor',
@@ -175,7 +178,7 @@ function TreeView({
includeAuthor: includeAuthor.toString(),
})
),
- [baseUrl, sortField]
+ [baseUrl, includeAuthor, sortField]
);
const [rows, setRows] = useAsyncState>(
diff --git a/specifyweb/frontend/js_src/lib/localization/preferences.ts b/specifyweb/frontend/js_src/lib/localization/preferences.ts
index d6a595fc932..7314c2cf328 100644
--- a/specifyweb/frontend/js_src/lib/localization/preferences.ts
+++ b/specifyweb/frontend/js_src/lib/localization/preferences.ts
@@ -1443,6 +1443,31 @@ export const preferencesText = createDictionary({
'ru-ru': 'Сортировать по полю',
'uk-ua': 'Сортувати за полем',
},
+ treeStatsThreshold: {
+ 'en-us': 'Minimum rank for Collection Object counts',
+ 'ru-ru': 'Минимальный ранг для подсчета коллекционных объектов',
+ 'es-es': 'Rango mínimo para recuentos de objetos de colección',
+ 'fr-fr': 'Rang minimal pour les comptes des objets de collection',
+ 'uk-ua': 'Мінімальний ранг для підрахунку колекційних об’єктів',
+ 'de-ch': 'Minimaler Rang für Sammlungsobjektzählungen',
+ 'pt-br': 'Classificação mínima para contagens de objetos de coleção',
+ },
+ treeStatsThresholdDescription: {
+ 'en-us':
+ 'Show Collection Object counts only for nodes with RankID greater than or equal to this value.',
+ 'ru-ru':
+ 'Показывать количество коллекционных объектов только для узлов с RankID больше или равным этому значению.',
+ 'es-es':
+ 'Mostrar recuentos de objetos de colección solo para nodos con RankID mayor o igual que este valor.',
+ 'fr-fr':
+ 'Afficher les comptes d’objets de collection uniquement pour les nœuds dont le RankID est supérieur ou égal à cette valeur.',
+ 'uk-ua':
+ 'Показувати кількість колекційних об’єктів лише для вузлів з RankID, що дорівнює або перевищує це значення.',
+ 'de-ch':
+ 'Zeige Zählungen von Sammlungsobjekten nur für Knoten mit einem RankID grösser oder gleich diesem Wert.',
+ 'pt-br':
+ 'Mostrar contagens de objetos de coleção apenas para nós com RankID maior ou igual a este valor.',
+ },
lineWrap: {
'en-us': 'Line wrap',
'ru-ru': 'Перенос строки',
diff --git a/specifyweb/frontend/js_src/lib/tests/ajax/static/context/remoteprefs.properties b/specifyweb/frontend/js_src/lib/tests/ajax/static/context/remoteprefs.properties
index 39b5e42ad97..e5c9ecce3df 100644
--- a/specifyweb/frontend/js_src/lib/tests/ajax/static/context/remoteprefs.properties
+++ b/specifyweb/frontend/js_src/lib/tests/ajax/static/context/remoteprefs.properties
@@ -15,7 +15,6 @@ Testing
Treeeditor.TreeColColor2.Taxon=151, 221, 255
settings.email.smtp=authsmtp.ku.edu
google.earth.secondaryurltitle=ad
-TreeEditor.Rank.Threshold.Taxon=100
Treeeditor.SynonymyColor.LithoStrat=0, 0, 255
CO_CREATE_COA_32678 = false
IPAD_REMOTE_IMAGE_URL_TYPE_32768=attmgr
@@ -37,7 +36,6 @@ ALL_YEAR_CATS_STAT=false
Exporttask.OnTaskbar=true
CO_CREATE_PREP_65536=false
recent_collection_id.abentley.KU_Fish_Tissue=4
-TreeEditor.Rank.Threshold.Geography=100
recent_collection_id.Vertnet.KU_Fish_Tissue=4
google.earth.useorigheaders=true
google.earth.fgcolor=255, 255, 255
@@ -59,12 +57,10 @@ StartupTask.OnTaskbar.fish=true
Treeeditor.TreeColColor1.LithoStrat=202, 238, 255
IPAD_REMOTE_IMAGE_URL_TYPE_4=attmgr
recent_collection_id.Abornstein.KU_Fish_Tissue=4
-TreeEditor.Rank.Threshold.Storage=200
settings.email.email=abentley@ku.edu
google.earth.primaryurltitle=KU BIodiversity Institute Ichthyology
ui.formatting.disciplineicon.KUFishtissue=colobj_backstop
loans.shipmeth=FedEx
-TreeEditor.Rank.Threshold.GeologicTimePeriod=0
attachment.url=http\://biwebdb.nhm.ku.edu/web_asset_store.xml
usage_tracking.send_isa_stats=true
SGR_SHOW_TASK_PREF.fish=true
@@ -86,7 +82,6 @@ IPAD_REMOTE_IMAGE_URL_4=http\://biimages.biodiversity.ku.edu/web_asset_store.xml
SGRTask.OnTaskbar=true
recent_collection_id.spfishadmin.KU_Fish_Tissue=32768
Treeeditor.TreeColColor2.LithoStrat=151, 221, 255
-TreeEditor.Rank.Threshold.LithoStrat=200
ui.formatting.disciplineicon.KUFishvoucher=colobj_backstop
recent_collection_id.testuser.kui_fish_dbo_6=32768
IPAD_COLMGR_NAME_4=Andrew Bentley
@@ -110,7 +105,6 @@ IPAD_CURATOR_NAME_4=William Leo Smith
ui.formatting.valtextcolor=255, 0, 0
bnrIconSizeCBX=20 x 20 pixels
attachment.key=c3wNpDBTLMedXWSb8w2TeSwHWVFLvBwiYmtU0CdOzLQtelcibV9sTXW7NxZlX68
-TaxonTreeEditor.DisplayAuthor=true
ui.formatting.formtype=Small Font Format (ideal for Windows)
Agent.Use.Variants.fish=false
Interactions.Using.Interactions.fish=true