diff --git a/specifyweb/frontend/js_src/lib/components/DataModel/resource.ts b/specifyweb/frontend/js_src/lib/components/DataModel/resource.ts index f415260d004..d1d0e9fef0e 100644 --- a/specifyweb/frontend/js_src/lib/components/DataModel/resource.ts +++ b/specifyweb/frontend/js_src/lib/components/DataModel/resource.ts @@ -25,7 +25,7 @@ import type { import type { SpecifyResource } from './legacyTypes'; import { schema } from './schema'; import { serializeResource } from './serializers'; -import { SpecifyTable } from './specifyTable'; +import type { SpecifyTable } from './specifyTable'; import { genericTables, getTable, tables } from './tables'; import type { Tables } from './types'; import { getUniquenessRules } from './uniquenessRules'; @@ -343,9 +343,11 @@ export const exportsForTests = { }; setDevelopmentGlobal('_getUniqueFields', (): void => { - // Batch-editor clones records in independent-to-one no-match cases. It needs to be aware of the fields to not clone. It's fine if it doesn't respect user preferences (for now), but needs to be replicate - // front-end logic. So, the "fields to not clone" must be identical. This is done by storing them as a static file, which frontend and backend both access + a unit test to make sure the file is up-to-date. - // In the case where the user is really doesn't want to carry-over some fields, they can simply add those fields in batch-edit query (and then set them to null) so it handles general use case pretty well. + /* + * Batch-editor clones records in independent-to-one no-match cases. It needs to be aware of the fields to not clone. It's fine if it doesn't respect user preferences (for now), but needs to be replicate + * front-end logic. So, the "fields to not clone" must be identical. This is done by storing them as a static file, which frontend and backend both access + a unit test to make sure the file is up-to-date. + * In the case where the user is really doesn't want to carry-over some fields, they can simply add those fields in batch-edit query (and then set them to null) so it handles general use case pretty well. + */ const allTablesResult = Object.fromEntries( Object.values(tables).map((table) => [ table.name.toLowerCase(), diff --git a/specifyweb/frontend/js_src/lib/components/Router/OverlayRoutes.tsx b/specifyweb/frontend/js_src/lib/components/Router/OverlayRoutes.tsx index 6516db38c46..0dd82a1e8f0 100644 --- a/specifyweb/frontend/js_src/lib/components/Router/OverlayRoutes.tsx +++ b/specifyweb/frontend/js_src/lib/components/Router/OverlayRoutes.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { attachmentsText } from '../../localization/attachments'; +import { batchEditText } from '../../localization/batchEdit'; import { commonText } from '../../localization/common'; import { headerText } from '../../localization/header'; import { interactionsText } from '../../localization/interactions'; @@ -15,7 +16,6 @@ import { wbText } from '../../localization/workbench'; import type { RA } from '../../utils/types'; import { Redirect } from './Redirect'; import type { EnhancedRoute } from './RouterUtils'; -import { batchEditText } from '../../localization/batchEdit'; /* eslint-disable @typescript-eslint/promise-function-async */ /** diff --git a/specifyweb/frontend/js_src/lib/components/WbUtils/index.tsx b/specifyweb/frontend/js_src/lib/components/WbUtils/index.tsx index ebeac2923ff..fd89adca043 100644 --- a/specifyweb/frontend/js_src/lib/components/WbUtils/index.tsx +++ b/specifyweb/frontend/js_src/lib/components/WbUtils/index.tsx @@ -131,7 +131,7 @@ export function WbUtilsComponent({ /> { // Only show these cells if batch-edit - isUpdate === true && ( + isUpdate && ( <> >; -// just to make things manageable +// Just to make things manageable type RecordCountsKey = keyof Pick< UploadResult['UploadResult']['record_result'], 'Deleted' | 'MatchedAndChanged' | 'Updated' | 'Uploaded' diff --git a/specifyweb/frontend/js_src/lib/components/WorkBench/batchEditHelpers.ts b/specifyweb/frontend/js_src/lib/components/WorkBench/batchEditHelpers.ts index fa82ab2cfb0..8773fcd6533 100644 --- a/specifyweb/frontend/js_src/lib/components/WorkBench/batchEditHelpers.ts +++ b/specifyweb/frontend/js_src/lib/components/WorkBench/batchEditHelpers.ts @@ -1,5 +1,5 @@ -import { R, RA } from '../../utils/types'; -import { MappingPath } from '../WbPlanView/Mapper'; +import type { R, RA } from '../../utils/types'; +import type { MappingPath } from '../WbPlanView/Mapper'; import { getNumberFromToManyIndex, valueIsToManyIndex, @@ -12,7 +12,7 @@ export const BATCH_EDIT_NULL_RECORD = 'null_record'; export const BATCH_EDIT_KEY = 'batch_edit'; type BatchEditRecord = { - readonly id: typeof BATCH_EDIT_NULL_RECORD | number | undefined; + readonly id: number | typeof BATCH_EDIT_NULL_RECORD | undefined; readonly ordernumber: number | undefined; readonly version: number | undefined; }; @@ -34,13 +34,13 @@ export const isBatchEditNullRecord = ( // FEAT: Remove this if (valueIsTreeRank(node)) return false; - // it may actually not be a to-many + // It may actually not be a to-many const isToMany = rest[0] !== undefined && valueIsToManyIndex(rest[0]); - // batch-edit pack is strictly lower-case + // Batch-edit pack is strictly lower-case const lookUpNode = node.toLowerCase(); if (isToMany) { - // id starts with 1... + // Id starts with 1... const toManyId = getNumberFromToManyIndex(rest[0]) - 1; const toMany = batchEditPack?.to_many?.[lookUpNode]?.[toManyId]; return isBatchEditNullRecord(toMany, rest.slice(1)); diff --git a/specifyweb/frontend/js_src/lib/components/WorkBench/hooks.ts b/specifyweb/frontend/js_src/lib/components/WorkBench/hooks.ts index 9fcaa9c6461..a5ed8be0fab 100644 --- a/specifyweb/frontend/js_src/lib/components/WorkBench/hooks.ts +++ b/specifyweb/frontend/js_src/lib/components/WorkBench/hooks.ts @@ -14,9 +14,9 @@ import { overwriteReadOnly } from '../../utils/types'; import { sortFunction } from '../../utils/utils'; import { LoadingContext } from '../Core/Contexts'; import { schema } from '../DataModel/schema'; +import type { WbMeta } from './CellMeta'; import { getHotPlugin } from './handsontable'; import type { Workbench } from './WbView'; -import { WbMeta } from './CellMeta'; export function useHotHooks({ workbench, diff --git a/specifyweb/frontend/js_src/lib/components/WorkBench/hotHelpers.ts b/specifyweb/frontend/js_src/lib/components/WorkBench/hotHelpers.ts index e6a4eed9911..5bac1a6f206 100644 --- a/specifyweb/frontend/js_src/lib/components/WorkBench/hotHelpers.ts +++ b/specifyweb/frontend/js_src/lib/components/WorkBench/hotHelpers.ts @@ -1,8 +1,8 @@ import type Handsontable from 'handsontable'; import type { RA, RR, WritableArray } from '../../utils/types'; -import { WbMapping } from './mapping'; -import { Dataset } from '../WbPlanView/Wrapped'; +import type { Dataset } from '../WbPlanView/Wrapped'; +import type { WbMapping } from './mapping'; export function getSelectedRegions(hot: Handsontable): RA<{ readonly startRow: number; diff --git a/specifyweb/frontend/js_src/lib/components/WorkBench/resultsParser.ts b/specifyweb/frontend/js_src/lib/components/WorkBench/resultsParser.ts index 0f753275e73..e6dc78fb01e 100644 --- a/specifyweb/frontend/js_src/lib/components/WorkBench/resultsParser.ts +++ b/specifyweb/frontend/js_src/lib/components/WorkBench/resultsParser.ts @@ -154,18 +154,18 @@ type PropagatedFailure = State<'PropagatedFailure'>; type MatchedAndChanged = State<'MatchedAndChanged', Omit>; type RecordResultTypes = + | Deleted | FailedBusinessRule | Matched + | MatchedAndChanged | MatchedMultiple + | NoChange | NoMatch | NullRecord | ParseFailures | PropagatedFailure - | Uploaded | Updated - | NoChange - | Deleted - | MatchedAndChanged; + | Uploaded; // Records the specific result of attempting to upload a particular record type WbRecordResult = { diff --git a/specifyweb/patches/__init__.py b/specifyweb/patches/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/specifyweb/patches/admin.py b/specifyweb/patches/admin.py new file mode 100644 index 00000000000..8c38f3f3dad --- /dev/null +++ b/specifyweb/patches/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/specifyweb/patches/apps.py b/specifyweb/patches/apps.py new file mode 100644 index 00000000000..303b063df40 --- /dev/null +++ b/specifyweb/patches/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class PatchesConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'specifyweb.patches' diff --git a/specifyweb/patches/migrations/0001_restore_separators.py b/specifyweb/patches/migrations/0001_restore_separators.py new file mode 100644 index 00000000000..363ee2d5055 --- /dev/null +++ b/specifyweb/patches/migrations/0001_restore_separators.py @@ -0,0 +1,25 @@ +# Generated by Django 3.2.15 on 2025-01-17 18:10 + +from django.db import migrations + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.RunSQL( + """ + UPDATE spappresourcedata spard + SET spard.data = REPLACE(spard.data, 'separator=""', 'separator="; "') + WHERE spard.SpAppResourceID IN ( + SELECT spar.SpAppResourceID + FROM spappresource spar + WHERE spar.Name = 'DataObjFormatters' + ); + """, + reverse_sql='' # This should not be reversed + ) + ] diff --git a/specifyweb/patches/migrations/__init__.py b/specifyweb/patches/migrations/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/specifyweb/patches/models.py b/specifyweb/patches/models.py new file mode 100644 index 00000000000..71a83623907 --- /dev/null +++ b/specifyweb/patches/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/specifyweb/patches/tests.py b/specifyweb/patches/tests.py new file mode 100644 index 00000000000..7ce503c2dd9 --- /dev/null +++ b/specifyweb/patches/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/specifyweb/patches/views.py b/specifyweb/patches/views.py new file mode 100644 index 00000000000..91ea44a218f --- /dev/null +++ b/specifyweb/patches/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/specifyweb/settings/__init__.py b/specifyweb/settings/__init__.py index 6d90abf82d1..544012492f3 100644 --- a/specifyweb/settings/__init__.py +++ b/specifyweb/settings/__init__.py @@ -222,6 +222,7 @@ def get_sa_db_url(db_name): 'specifyweb.attachment_gw', 'specifyweb.frontend', 'specifyweb.barvis', + 'specifyweb.patches', 'specifyweb.report_runner', 'specifyweb.interactions', 'specifyweb.workbench',