Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import _ from 'underscore';

import {assert} from '../Errors/assert';
import {Backbone} from './backbone';
import {hasHierarchyField} from './schema';


const Base = Backbone.Collection.extend({
Expand Down Expand Up @@ -67,10 +66,8 @@ const Base = Backbone.Collection.extend({
options ||= {};
Base.call(this, null, options);
this.filters = options.filters || {};
this.domainfilter = Boolean(options.domainfilter) && (
typeof this.model?.specifyModel !== 'object'
|| hasHierarchyField(this.model.specifyModel)
);
this.domainfilter = Boolean(options.domainfilter) &&
this.model?.specifyModel.getScopingRelationship() !== undefined;
},
url() {
return `/api/specify/${ this.model.specifyModel.name.toLowerCase() }/`;
Expand Down
12 changes: 0 additions & 12 deletions specifyweb/frontend/js_src/lib/components/DataModel/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,3 @@ export const getModelById = <SCHEMA extends AnySchema>(
(Object.values(schema.models).find((model) => model.tableId === tableId) as
| SpecifyModel<SCHEMA>
| undefined) ?? error(`Model with id ${tableId} does not exist`);

// If this is true, then you can use {domainfilter:true} when fetching that model
export const hasHierarchyField = (model: SpecifyModel): boolean =>
[
'collectionObject',
'collection',
'discipline',
'division',
'institution',
].some((fieldName) =>
model.relationships.some(({ name }) => name === fieldName)
);
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ type CollectionConstructor<SCHEMA extends AnySchema> = new (
readonly filters?: Partial<
{
readonly orderby: string;
readonly domainfilter: boolean;
} & SCHEMA['fields'] &
CommonFields &
// This is required to allow for filters like leftSide__isnull
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React from 'react';

import { f } from '../../utils/functools';
import type { AnySchema } from '../DataModel/helperTypes';
import type { SpecifyResource } from '../DataModel/legacyTypes';
import { resourceOn } from '../DataModel/resource';
import { getModel } from '../DataModel/schema';
import type { Relationship } from '../DataModel/specifyField';
import type { Collection } from '../DataModel/specifyModel';
import type { PickList } from '../DataModel/types';
import { IntegratedRecordSelector } from '../FormSliders/IntegratedRecordSelector';
import { relationshipIsToMany } from '../WbPlanView/mappingHelpers';

export function PickListEditor({
resource,
relationship,
}: {
readonly resource: SpecifyResource<PickList>;
readonly relationship: Relationship;
}): JSX.Element | null {
const [tableName, setTableName] = React.useState<string | null>(null);
React.useEffect(
() =>
resourceOn(
resource,
'change:tableName',
() => setTableName(resource.get('tableName')),
true
),
[resource]
);

const table = tableName === null ? undefined : getModel(tableName);

const collection = React.useMemo(
() =>
(table === undefined
? undefined
: new table.LazyCollection({
domainfilter: true,
})) as Collection<AnySchema>,
[table]
);

return collection === undefined ? null : (
<IntegratedRecordSelector
collection={collection}
dialog={false}
formType="form"
// FEATURE: change to mode "edit" when #3125 is fixed
mode="view"
relationship={relationship}
sortField={undefined}
onAdd={
relationshipIsToMany(relationship) &&
relationship.type !== 'zero-to-one'
? undefined
: ([resource]): void =>
void resource.set(relationship.name, resource as never)
}
onClose={f.never}
/>
);
}
33 changes: 30 additions & 3 deletions specifyweb/frontend/js_src/lib/components/FormCells/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import { commonText } from '../../localization/common';
import { formsText } from '../../localization/forms';
import { f } from '../../utils/functools';
import { DataEntry } from '../Atoms/DataEntry';
import { toTable } from '../DataModel/helpers';
import type { AnySchema } from '../DataModel/helperTypes';
import type { SpecifyResource } from '../DataModel/legacyTypes';
import { resourceOn } from '../DataModel/resource';
import { schema } from '../DataModel/schema';
import type { Collection } from '../DataModel/specifyModel';
import { UiCommand } from '../FormCommands';
Expand All @@ -18,8 +20,10 @@ import type { cellAlign, CellTypes } from '../FormParse/cells';
import { SpecifyForm } from '../Forms/SpecifyForm';
import { SubView } from '../Forms/SubView';
import { TableIcon } from '../Molecules/TableIcon';
import { PickListTypes } from '../PickLists/definitions';
import { relationshipIsToMany } from '../WbPlanView/mappingHelpers';
import { FormTableInteraction } from './FormTableInteraction';
import { PickListEditor } from './PickListEditor';

const cellRenderers: {
readonly [KEY in keyof CellTypes]: (props: {
Expand Down Expand Up @@ -140,7 +144,7 @@ const cellRenderers: {
Collection<AnySchema> | false
>(
React.useCallback(
() =>
async () =>
typeof relationship === 'object' &&
relationshipIsToMany(relationship) &&
typeof data?.resource === 'object' &&
Expand All @@ -155,15 +159,38 @@ const cellRenderers: {
),
false
);
const currentResource = data?.resource;

const [showPickListForm, setShowPickListForm] =
React.useState<boolean>(false);
React.useEffect(
() =>
currentResource === undefined
? undefined
: resourceOn(
currentResource,
'change:type',
() =>
setShowPickListForm(
currentResource.get('type') !== PickListTypes.ITEMS
),
true
),
[currentResource]
);

const mode = rawResource === data?.resource ? rawMode : 'view';
if (
relationship === undefined ||
data?.resource === undefined ||
currentResource === undefined ||
interactionCollection === undefined ||
actualFormType === undefined
)
return null;
const pickList = toTable(currentResource, 'PickList');

if (typeof pickList === 'object' && showPickListForm)
return <PickListEditor relationship={relationship} resource={pickList} />;
else if (interactionCollection === false || actualFormType === 'form')
return (
<SubView
Expand All @@ -172,7 +199,7 @@ const cellRenderers: {
isButton={isButton}
mode={mode}
parentFormType={parentFormType}
parentResource={data.resource}
parentResource={currentResource}
relationship={relationship}
sortField={sortField}
viewName={viewName}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export function QueryComboBox({
typeof resource.getDependentResource(field.name) === 'object')
? resource
.rgetPromise<string, AnySchema>(field.name)
.then((resource) =>
.then(async (resource) =>
resource === undefined || resource === null
? {
label: '' as LocalizedString,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { PrintOnSave } from '../FormFields/Checkbox';
import type { ViewDescription } from '../FormParse';
import { SubViewContext } from '../Forms/SubView';
import { isTreeResource } from '../InitialContext/treeRanks';
import { interactionTables } from '../Interactions/config';
import { Dialog } from '../Molecules/Dialog';
import {
ProtectedAction,
Expand All @@ -33,7 +34,6 @@ import { QueryTreeUsages } from './QueryTreeUsages';
import { ReadOnlyMode } from './ReadOnlyMode';
import { ShareRecord } from './ShareRecord';
import { SubViewMeta } from './SubViewMeta';
import { interactionTables } from '../Interactions/config';

/**
* Form preferences host context aware user preferences and other meta-actions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { AnySchema } from '../DataModel/helperTypes';
import type { SpecifyResource } from '../DataModel/legacyTypes';
import { resourceOn } from '../DataModel/resource';
import { softFail } from '../Errors/Crash';
import { ErrorBoundary } from '../Errors/ErrorBoundary';
import { FormMeta } from '../FormMeta';
import type { FormMode } from '../FormParse';
import { LoadingScreen } from '../Molecules/Dialog';
Expand All @@ -19,7 +20,6 @@ import { displaySpecifyNetwork, SpecifyNetworkBadge } from '../SpecifyNetwork';
import { format } from './dataObjFormatters';
import { SpecifyForm } from './SpecifyForm';
import { useViewDefinition } from './useViewDefinition';
import { ErrorBoundary } from '../Errors/ErrorBoundary';

export type ResourceViewProps<SCHEMA extends AnySchema> = {
readonly isLoading?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export const treeRanksPromise = Promise.all([
import('../DataModel/schema').then(async ({ fetchContext }) => fetchContext),
fetchDomain,
])
.then(([{ hasTreeAccess, hasTablePermission }]) =>
.then(async ([{ hasTreeAccess, hasTablePermission }]) =>
hasTablePermission('Discipline', 'read')
? getDomainResource('discipline')
?.fetch()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ const layersPromise: Promise<Layers<SerializedLayer>> =
{ headers: { Accept: 'text/plain' } },
{ strict: false, expectedResponseCodes: [Http.OK, Http.NO_CONTENT] }
)
.then(({ data, status }) =>
.then(async ({ data, status }) =>
status === Http.NO_CONTENT
? ajax<Layers<SerializedLayer>>(
cachableUrl(leafletLayersEndpoint),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
treeRanksPromise,
} from '../InitialContext/treeRanks';
import { hasTablePermission, hasTreeAccess } from '../Permissions/helpers';
import { deflateLocalityData } from '../SpecifyNetwork/utils';
import { pathStartsWith } from '../WbPlanView/helpers';
import type { MappingPath } from '../WbPlanView/Mapper';
import {
Expand All @@ -36,7 +37,6 @@ import {
formatCoordinate,
getLocalityData,
} from './helpers';
import { deflateLocalityData } from '../SpecifyNetwork/utils';

const splitMappingPath = (
mappingPath: MappingPath,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { f } from '../../utils/functools';
import type { RA } from '../../utils/types';
import { ensure } from '../../utils/types';
import type { StatLayout } from '../Statistics/types';
import { GenericPreferences, defineItem } from './types';
import type { GenericPreferences } from './types';
import { defineItem } from './types';

export const collectionPreferenceDefinitions = {
statistics: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';

import { useLiveState } from '../../hooks/useLiveState';
import type { AppResourceTab } from '../AppResources/TabDefinitions';
import { PreferencesContent } from '../Preferences';
import { BasePreferences } from '../Preferences/BasePreferences';
import { userPreferenceDefinitions } from '../Preferences/UserDefinitions';
import { userPreferences } from '../Preferences/userPreferences';
import { AppResourceTab } from '../AppResources/TabDefinitions';
import { useLiveState } from '../../hooks/useLiveState';

export const UserPreferencesEditor: AppResourceTab = function ({
isReadOnly,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ import { rawMenuItemsPromise } from '../Header/menuItemDefinitions';
import { useMenuItems, useUserTools } from '../Header/menuItemProcessing';
import { AttachmentPicker } from '../Molecules/AttachmentPicker';
import { AutoComplete } from '../Molecules/AutoComplete';
import { userPreferences } from './userPreferences';
import { ListEdit } from '../Toolbar/QueryTablesEdit';
import { PreferenceItem, PreferenceItemComponent } from './types';
import type { PreferenceItem, PreferenceItemComponent } from './types';
import { userPreferences } from './userPreferences';

export const ColorPickerPreferenceItem: PreferenceItemComponent<string> =
function ColorPickerPreferenceItem({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export function getAuditRecordFormatter(
Promise.all(
resultRow
.filter((_, index) => index !== queryIdField)
.map((value, index, row) => {
.map(async (value, index, row) => {
if (value === null || value === '') return '';
const stringValue = value.toString();
if (fields[index]?.name === 'fieldName') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export function QueryResults(props: Props): JSX.Element {
async () =>
// Fetch all pick lists so that they are accessible synchronously later
Promise.all(
fieldSpecs.map((fieldSpec) =>
fieldSpecs.map(async (fieldSpec) =>
typeof fieldSpec.parser.pickListName === 'string'
? fetchPickList(fieldSpec.parser.pickListName)
: undefined
Expand Down Expand Up @@ -404,7 +404,7 @@ export function useFetchQueryResults({

// Prevent concurrent fetching in different places
fetchersRef.current[fetchIndex] ??= fetchResults(fetchIndex)
.then((newResults) => {
.then(async (newResults) => {
if (
process.env.NODE_ENV === 'development' &&
newResults.length > fetchSize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ function Row({
);
const [formattedValues] = useAsyncState(
React.useCallback(
() => recordFormatter?.(result),
async () => recordFormatter?.(result),
[result, recordFormatter]
),
false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import React from 'react';

import { commonText } from '../../localization/common';
import { headerText } from '../../localization/header';
import { interactionsText } from '../../localization/interactions';
Expand All @@ -8,9 +10,8 @@ import { userText } from '../../localization/user';
import { welcomeText } from '../../localization/welcome';
import { wbText } from '../../localization/workbench';
import type { RA } from '../../utils/types';
import type { EnhancedRoute } from './RouterUtils';
import { Redirect } from './Redirect';
import React from 'react';
import type { EnhancedRoute } from './RouterUtils';

/* eslint-disable @typescript-eslint/promise-function-async */
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export function SchemaConfigHeader({
<header className="flex gap-2">
<H2 className="flex items-center">
{schemaText.schemaConfig()} (
{languages[language]?.replaceAll(/[()]/g, '') ?? language})
{languages[language]?.replaceAll(/[()]/gu, '') ?? language})
</H2>
<Button.Small
onClick={(): void => navigate(`/specify/schema-config/${language}/`)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export function useMapData(
): BrokerData {
const [speciesName] = useAsyncState(
React.useCallback(
() =>
async () =>
brokerData?.speciesName ??
(typeof taxonId === 'number'
? fetchResource('Taxon', taxonId).then(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function useSpecies(
): RA<BrokerRecord> | undefined {
return useAsyncState(
React.useCallback(
() => (speciesName === undefined ? [] : fetchName(speciesName)),
async () => (speciesName === undefined ? [] : fetchName(speciesName)),
[speciesName]
),
false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import type { CollectionObject, Taxon } from '../DataModel/types';
import { Dialog } from '../Molecules/Dialog';
import { TableIcon } from '../Molecules/TableIcon';
import { hasTablePermission } from '../Permissions/helpers';
import { SpecifyNetworkOverlays } from './Overlay';
import { userPreferences } from '../Preferences/userPreferences';
import { SpecifyNetworkOverlays } from './Overlay';

export const displaySpecifyNetwork = (
resource: SpecifyResource<AnySchema> | undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export function useIdbLayers(
scientificName: string | undefined
): BrokerOverlay | undefined {
const [layers] = useAsyncState<BrokerOverlay>(
React.useCallback(() => {
React.useCallback(async () => {
const idbScientificName =
extractBrokerField(occurrence ?? [], 'idb', 'dwc:scientificName') ??
scientificName;
Expand Down
Loading