diff --git a/backend/src/baserow/contrib/database/airtable/registry.py b/backend/src/baserow/contrib/database/airtable/registry.py index a801072a5..e1e2783f8 100644 --- a/backend/src/baserow/contrib/database/airtable/registry.py +++ b/backend/src/baserow/contrib/database/airtable/registry.py @@ -727,17 +727,33 @@ class AirtableViewType(Instance): "The `baserow_view_type` must be implemented for the AirtableViewType." ) + view_id = raw_airtable_view["id"] view_name = raw_airtable_view["name"] view_name = self._check_personal_or_locked( view_name, raw_airtable_view, raw_airtable_table, import_report ) + # Extract the ordered views from the sections and put them in a flat list so + # that we can find the order for the Baserow view. + flattened_view_order = [] + for view in raw_airtable_table["viewOrder"]: + if view in raw_airtable_table["viewSectionsById"]: + section = raw_airtable_table["viewSectionsById"][view] + section_views = section["viewOrder"] + flattened_view_order.extend(section_views) + # Baserow doesn't support sections, but we can prepend the name of the + # section. + if view_id in section_views: + view_name = f"{section['name']} / {view_name}" + else: + flattened_view_order.append(view) + view_type = view_type_registry.get(self.baserow_view_type) view = view_type.model_class( id=raw_airtable_view["id"], pk=raw_airtable_view["id"], name=view_name, - order=raw_airtable_table["viewOrder"].index(raw_airtable_view["id"]) + 1, + order=flattened_view_order.index(raw_airtable_view["id"]) + 1, ) filters_object = raw_airtable_view_data.get("filters", None) diff --git a/backend/tests/baserow/contrib/database/airtable/test_airtable_view_types.py b/backend/tests/baserow/contrib/database/airtable/test_airtable_view_types.py index 92f7d9187..b12f94b73 100644 --- a/backend/tests/baserow/contrib/database/airtable/test_airtable_view_types.py +++ b/backend/tests/baserow/contrib/database/airtable/test_airtable_view_types.py @@ -1028,3 +1028,73 @@ def test_import_gallery_view_with_cover_column_type_fit(): assert import_report.items[0].scope == SCOPE_VIEW assert import_report.items[0].table == "Data" assert serialized_view["card_cover_image_field_id"] == "fldwSc9PqedIhTSqhi3" + + +def test_import_view_in_section_order(): + raw_airtable_table = deepcopy(RAW_AIRTABLE_TABLE) + raw_airtable_table["viewOrder"] = ["vsc0001", "vsc0002", "viw00005"] + raw_airtable_table["viewSectionsById"] = { + "vsc0001": { + "id": "vsc0001", + "name": "Section 1", + "createdByUserId": "usr0001", + "pinnedForUserId": None, + "viewOrder": ["viw00001", "viw00002"], + }, + "vsc0002": { + "id": "vsc0001", + "name": "Section 1", + "createdByUserId": "usr0001", + "pinnedForUserId": None, + "viewOrder": [RAW_AIRTABLE_VIEW["id"], "viw00004"], + }, + } + + airtable_view_type = airtable_view_type_registry.get("grid") + import_report = AirtableImportReport() + serialized_view = airtable_view_type.to_serialized_baserow_view( + FIELD_MAPPING, + ROW_ID_MAPPING, + raw_airtable_table, + RAW_AIRTABLE_VIEW, + RAW_AIRTABLE_GRID_VIEW_DATA, + AirtableImportConfig(), + import_report, + ) + + assert serialized_view["order"] == 3 + + +def test_import_view_in_section_name(): + raw_airtable_table = deepcopy(RAW_AIRTABLE_TABLE) + raw_airtable_table["viewOrder"] = ["vsc0001", "vsc0002", "viw00005"] + raw_airtable_table["viewSectionsById"] = { + "vsc0001": { + "id": "vsc0001", + "name": "Section 1", + "createdByUserId": "usr0001", + "pinnedForUserId": None, + "viewOrder": ["viw00001", "viw00002"], + }, + "vsc0002": { + "id": "vsc0001", + "name": "Section 2", + "createdByUserId": "usr0001", + "pinnedForUserId": None, + "viewOrder": [RAW_AIRTABLE_VIEW["id"], "viw00004"], + }, + } + + airtable_view_type = airtable_view_type_registry.get("grid") + import_report = AirtableImportReport() + serialized_view = airtable_view_type.to_serialized_baserow_view( + FIELD_MAPPING, + ROW_ID_MAPPING, + raw_airtable_table, + RAW_AIRTABLE_VIEW, + RAW_AIRTABLE_GRID_VIEW_DATA, + AirtableImportConfig(), + import_report, + ) + + assert serialized_view["name"] == "Section 2 / Grid view" diff --git a/changelog/entries/unreleased/bug/fix_airtable_view_section_import_order_problem.json b/changelog/entries/unreleased/bug/fix_airtable_view_section_import_order_problem.json new file mode 100644 index 000000000..6fca88c9a --- /dev/null +++ b/changelog/entries/unreleased/bug/fix_airtable_view_section_import_order_problem.json @@ -0,0 +1,8 @@ +{ + "type": "bug", + "message": "Fix bug where the Airtable import crashes if the table has sections.", + "domain": "database", + "issue_number": null, + "bullet_points": [], + "created_at": "2025-03-24" +}