Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
8f752df
feat(backend): add matchingmode field to Spattachmentdataset
grantfitzsimmons Jul 14, 2026
c019079
feat(attachments): add MappingMode types and localization strings
grantfitzsimmons Jul 14, 2026
2f43c12
feat(attachments): add crossReferenceMappingFiles and prepareMappingF…
grantfitzsimmons Jul 14, 2026
bdaa197
feat(attachments): add MatchingModeDialog and MappingFileSetup compon…
grantfitzsimmons Jul 14, 2026
9f2e3cf
feat(attachments): integrate mapping-file mode into Import, ViewAttac…
grantfitzsimmons Jul 14, 2026
d912787
chore: improve descriptions
grantfitzsimmons Jul 14, 2026
e9b54a6
feat(attachments): match CSV columns against schema field names
grantfitzsimmons Jul 14, 2026
6e00a70
feat(attachments): add mapping file tests
grantfitzsimmons Jul 14, 2026
9456761
fix(attachments): remove spurious canceled for duplicates
grantfitzsimmons Jul 14, 2026
da57dc6
fix(attachments): show friendly prompt instead of misleading warnings…
grantfitzsimmons Jul 14, 2026
1a57240
feat(attachments): add icon to matching dialog
grantfitzsimmons Jul 14, 2026
29ad01b
fix(attachments): pass oldRows to seed effect and add isMappingMode t…
grantfitzsimmons Jul 14, 2026
acf35f2
feat(attachments): detect non-placeholder filename collisions in cros…
grantfitzsimmons Jul 14, 2026
0abf489
fix(attachments): reset column indices and dedup ref on new CSV load …
grantfitzsimmons Jul 14, 2026
de736b3
fix(attachments): prefer File instances in dedup safety net over firs…
grantfitzsimmons Jul 14, 2026
3a4a941
fix(attachments): preserve success/attached status in notInMappingFil…
grantfitzsimmons Jul 14, 2026
7f72e9d
fix(attachments): use mutable array for crossReferenceMappingFiles re…
grantfitzsimmons Jul 14, 2026
4eff842
fix(attachments): add mappingFileName to placeholder rows in crossRef…
grantfitzsimmons Jul 14, 2026
f94cd22
fix(backend): validate matchingmode values and add model-level choice…
grantfitzsimmons Jul 14, 2026
b4ae1bf
fix(attachments): clear headers and rows on CSV parse error in Mappin…
grantfitzsimmons Jul 14, 2026
a0383b2
fix(attachments): anchor fileNamePatterns to prevent substring matches
grantfitzsimmons Jul 14, 2026
feb6e25
refactor(attachments): treat null matchingmode as filename mode inste…
grantfitzsimmons Jul 14, 2026
2a9a02c
fix(attachments): fix dedup key
grantfitzsimmons Jul 14, 2026
4137c02
fix(atachments): show stale-row warnings
grantfitzsimmons Jul 14, 2026
e59b837
fix(attachments): fix dialog
grantfitzsimmons Jul 14, 2026
4fcb3a5
fix(attachments): fix tests
grantfitzsimmons Jul 15, 2026
1be4238
Merge branch 'main' into issue-8302
grantfitzsimmons Jul 15, 2026
dc2a98b
fix(attachments): remove unused local
grantfitzsimmons Jul 15, 2026
ed28a86
fix(attachments): make dialog appear on empty data sets
grantfitzsimmons Jul 15, 2026
5219b96
refactor(attachments): use isMappingFilePlaceholder to require both c…
grantfitzsimmons Jul 15, 2026
abef194
fix(attachments): prevent stale CSV parse
grantfitzsimmons Jul 15, 2026
ab40252
refactor(backend): remove unnecessary MATCHING_MODE_CHOICES
grantfitzsimmons Jul 15, 2026
4121f80
refactor(attachments): simplify reset effect since mode is fixed at d…
grantfitzsimmons Jul 15, 2026
dcd25e6
refactor(attachments): localize CSV error messages
grantfitzsimmons Jul 15, 2026
7302797
Lint code with ESLint and Prettier
grantfitzsimmons Jul 15, 2026
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
13 changes: 13 additions & 0 deletions specifyweb/backend/attachment_gw/dataset_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ class AttachmentDataSetPT(PermissionTarget):
upload = PermissionTargetAction()
rollback = PermissionTargetAction()

VALID_MATCHING_MODES = {'mappingFile'}

def _get_validated_matchingmode(data, existing=None):
"""Return a validated matchingmode value or raise ValueError."""
if 'matchingmode' not in data:
return existing
value = data['matchingmode']
if value is not None and value not in VALID_MATCHING_MODES:
raise ValueError(f"Invalid matchingmode: {value!r}")
return value

def datasets_view(request):
if request.method == 'GET':
return http.JsonResponse(Spattachmentdataset.get_meta_fields(request), safe=False)
Expand All @@ -28,6 +39,7 @@ def datasets_view(request):
createdbyagent=request.specify_user_agent,
modifiedbyagent=request.specify_user_agent,
uploaderstatus="main",
matchingmode=_get_validated_matchingmode(data),
# A bit more flexible than workbench. Handles creating datasets with an uploadplan from the start.
uploadplan=json.dumps(data['uploadplan']) if 'uploadplan' in data else None
)
Expand All @@ -49,6 +61,7 @@ def dataset_view(request, ds: Spattachmentdataset):
ds.name = attrs.get('name', ds.name)
ds.remarks = attrs.get('remarks', ds.remarks)
ds.data = attrs.get('rows', ds.data)
ds.matchingmode = _get_validated_matchingmode(attrs, ds.matchingmode)
ds.uploadplan = json.dumps(attrs['uploadplan'] if 'uploadplan' in attrs else ds.uploadplan)
# Never preserve uploaderstatus. Making it required for all requests.
old_status = ds.uploaderstatus
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated manually

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('attachment_gw', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='spattachmentdataset',

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Waiting a bit on the way we finalize creating schema captions for fields. I imagine we may want to have a schema config entry for this field? No real substantive benefit for it, but the sync fields command would create one, so maybe better to add here.

name='matchingmode',
field=models.CharField(max_length=32, null=True, default=None),
),
]
9 changes: 9 additions & 0 deletions specifyweb/backend/attachment_gw/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ class Spattachmentdataset(Dataset):

id = models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')

matchingmode = models.CharField(
max_length=32, null=True, default=None
)

object_response_fields = [
*Dataset.object_response_fields,
'matchingmode',
]

class Meta:
db_table = 'attachmentdataset'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,11 @@ export function AttachmentsImportOverlay(): JSX.Element | null {
/>
{attachmentDataSet.name}
</Link.Default>
{attachmentDataSet.matchingmode === 'mappingFile' && (
<div className="text-xs text-gray-500">
{attachmentsText.matchByMappingFile()}
</div>
)}
</td>
<td>
<DateElement date={attachmentDataSet.timestampcreated} />
Expand Down
Loading
Loading