@collabdt/core 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/README.md +29 -21
  2. package/dist/core/components/AppSidebarContent.d.ts.map +1 -1
  3. package/dist/core/components/AppSidebarContent.js +21 -27
  4. package/dist/core/components/AppSidebarContent.js.map +1 -1
  5. package/dist/core/components/authentication/AuthPage.d.ts.map +1 -1
  6. package/dist/core/components/authentication/AuthPage.js +32 -7
  7. package/dist/core/components/authentication/AuthPage.js.map +1 -1
  8. package/dist/core/components/authentication/SignInAuthHeader.d.ts +7 -0
  9. package/dist/core/components/authentication/SignInAuthHeader.d.ts.map +1 -0
  10. package/dist/core/components/authentication/SignInAuthHeader.js +32 -0
  11. package/dist/core/components/authentication/SignInAuthHeader.js.map +1 -0
  12. package/dist/core/components/authentication/Signin.d.ts.map +1 -1
  13. package/dist/core/components/authentication/Signin.js +308 -10
  14. package/dist/core/components/authentication/Signin.js.map +1 -1
  15. package/dist/core/components/settings/index.js +3 -3
  16. package/dist/core/components/settings/index.js.map +1 -1
  17. package/dist/core/components/settings/src/OrganizationSettingsPanel.d.ts.map +1 -1
  18. package/dist/core/components/settings/src/OrganizationSettingsPanel.js +5 -4
  19. package/dist/core/components/settings/src/OrganizationSettingsPanel.js.map +1 -1
  20. package/dist/core/components/settings/src/SettingsSidebar.d.ts.map +1 -1
  21. package/dist/core/components/settings/src/SettingsSidebar.js +12 -2
  22. package/dist/core/components/settings/src/SettingsSidebar.js.map +1 -1
  23. package/dist/core/components/support/BugReportDialog.d.ts.map +1 -1
  24. package/dist/core/components/support/BugReportDialog.js +94 -13
  25. package/dist/core/components/support/BugReportDialog.js.map +1 -1
  26. package/dist/core/components/support/FeatureRequestDialog.d.ts.map +1 -1
  27. package/dist/core/components/support/FeatureRequestDialog.js +33 -6
  28. package/dist/core/components/support/FeatureRequestDialog.js.map +1 -1
  29. package/dist/core/components/ui/AppSidebar.d.ts.map +1 -1
  30. package/dist/core/components/ui/AppSidebar.js +52 -9
  31. package/dist/core/components/ui/AppSidebar.js.map +1 -1
  32. package/dist/core/components/ui/DataTable.js +3 -3
  33. package/dist/core/components/ui/DataTable.js.map +1 -1
  34. package/dist/core/components/ui/Dialog.js +1 -1
  35. package/dist/core/components/ui/Dialog.js.map +1 -1
  36. package/dist/core/components/ui/InfoSidebar/Container.js +1 -1
  37. package/dist/core/components/ui/InfoSidebar/Container.js.map +1 -1
  38. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts.map +1 -1
  39. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js +2 -2
  40. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js.map +1 -1
  41. package/dist/core/components/ui/Sensors/SensorsSection.d.ts.map +1 -1
  42. package/dist/core/components/ui/Sensors/SensorsSection.js +2 -1
  43. package/dist/core/components/ui/Sensors/SensorsSection.js.map +1 -1
  44. package/dist/core/components/ui/Sensors/sensorUtils.d.ts +9 -0
  45. package/dist/core/components/ui/Sensors/sensorUtils.d.ts.map +1 -1
  46. package/dist/core/components/ui/Sensors/sensorUtils.js +6 -0
  47. package/dist/core/components/ui/Sensors/sensorUtils.js.map +1 -1
  48. package/dist/core/components/ui/Sidebar.d.ts +4 -0
  49. package/dist/core/components/ui/Sidebar.d.ts.map +1 -1
  50. package/dist/core/components/ui/Sidebar.js +11 -5
  51. package/dist/core/components/ui/Sidebar.js.map +1 -1
  52. package/dist/core/components/ui/Table.js +2 -2
  53. package/dist/core/components/ui/Table.js.map +1 -1
  54. package/dist/core/components/viewers/Data/DataMenu.d.ts.map +1 -1
  55. package/dist/core/components/viewers/Data/DataMenu.js +8 -8
  56. package/dist/core/components/viewers/Data/DataMenu.js.map +1 -1
  57. package/dist/core/components/viewers/Data/buildingDetails/BuildingDetails.d.ts.map +1 -1
  58. package/dist/core/components/viewers/Data/buildingDetails/BuildingDetails.js +26 -0
  59. package/dist/core/components/viewers/Data/buildingDetails/BuildingDetails.js.map +1 -1
  60. package/dist/core/components/viewers/Data/details/DetailHeader.js +14 -14
  61. package/dist/core/components/viewers/Data/details/DetailHeader.js.map +1 -1
  62. package/dist/core/components/viewers/Data/details/TabSidebar.d.ts.map +1 -1
  63. package/dist/core/components/viewers/Data/details/TabSidebar.js +22 -0
  64. package/dist/core/components/viewers/Data/details/TabSidebar.js.map +1 -1
  65. package/dist/core/components/viewers/Data/infrastructureDetails/InfrastructureDetails.d.ts.map +1 -1
  66. package/dist/core/components/viewers/Data/infrastructureDetails/InfrastructureDetails.js +19 -0
  67. package/dist/core/components/viewers/Data/infrastructureDetails/InfrastructureDetails.js.map +1 -1
  68. package/dist/core/components/viewers/Data/siteDetails/SiteDetails.d.ts.map +1 -1
  69. package/dist/core/components/viewers/Data/siteDetails/SiteDetails.js +19 -0
  70. package/dist/core/components/viewers/Data/siteDetails/SiteDetails.js.map +1 -1
  71. package/dist/core/components/viewers/Data/utils/Columns.js +2 -2
  72. package/dist/core/components/viewers/Data/utils/Columns.js.map +1 -1
  73. package/dist/core/components/viewers/Data/utils/positionParser.d.ts.map +1 -1
  74. package/dist/core/components/viewers/Data/utils/positionParser.js +6 -5
  75. package/dist/core/components/viewers/Data/utils/positionParser.js.map +1 -1
  76. package/dist/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.d.ts.map +1 -1
  77. package/dist/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.js +8 -1
  78. package/dist/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.js.map +1 -1
  79. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
  80. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js +7 -1
  81. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js.map +1 -1
  82. package/dist/core/components/viewers/map/datasets/RowActions.js +6 -6
  83. package/dist/core/components/viewers/map/datasets/RowActions.js.map +1 -1
  84. package/dist/core/components/viewers/map/datasets/data.js +1 -1
  85. package/dist/core/components/viewers/map/datasets/data.js.map +1 -1
  86. package/dist/core/components/viewers/map/datasets/index.d.ts.map +1 -1
  87. package/dist/core/components/viewers/map/datasets/index.js +28 -9
  88. package/dist/core/components/viewers/map/datasets/index.js.map +1 -1
  89. package/dist/core/components/viewers/pointcloud/src/PointCloudLoadingState/index.d.ts.map +1 -1
  90. package/dist/core/components/viewers/pointcloud/src/PointCloudLoadingState/index.js +54 -31
  91. package/dist/core/components/viewers/pointcloud/src/PointCloudLoadingState/index.js.map +1 -1
  92. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.js +1 -1
  93. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.js.map +1 -1
  94. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.d.ts +2 -1
  95. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.d.ts.map +1 -1
  96. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.js +5 -4
  97. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.js.map +1 -1
  98. package/dist/core/hooks/useCaptureScreenshot.d.ts.map +1 -1
  99. package/dist/core/hooks/useCaptureScreenshot.js +62 -31
  100. package/dist/core/hooks/useCaptureScreenshot.js.map +1 -1
  101. package/dist/core/hooks/useCurrentViewerPosition.d.ts +18 -0
  102. package/dist/core/hooks/useCurrentViewerPosition.d.ts.map +1 -0
  103. package/dist/core/hooks/useCurrentViewerPosition.js +66 -0
  104. package/dist/core/hooks/useCurrentViewerPosition.js.map +1 -0
  105. package/dist/core/hooks/useShareUrl.d.ts +2 -0
  106. package/dist/core/hooks/useShareUrl.d.ts.map +1 -0
  107. package/dist/core/hooks/useShareUrl.js +74 -0
  108. package/dist/core/hooks/useShareUrl.js.map +1 -0
  109. package/dist/core/i18n/index.d.ts +8 -0
  110. package/dist/core/i18n/index.d.ts.map +1 -0
  111. package/dist/core/i18n/index.js +8 -0
  112. package/dist/core/i18n/index.js.map +1 -0
  113. package/dist/core/i18n/messages/en.json +1873 -0
  114. package/dist/core/i18n/messages/es.json +1870 -0
  115. package/dist/core/i18n/messages/fr.json +1870 -0
  116. package/dist/core/styles/globals.css +46 -33
  117. package/package.json +9 -5
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/core/components/viewers/Data/utils/Columns.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\n// Dependencies\r\nimport * as React from 'react'\r\nimport { ColumnDef } from '@tanstack/react-table'\r\nimport { MenusContext } from '../../../../store'\r\nimport { useSession } from 'next-auth/react'\r\n\r\n// Shadcn Components\r\nimport { Button } from '../../../ui/Button'\r\nimport { Avatar, AvatarFallback, AvatarImage } from '../../../ui/Avatar'\r\nimport { Badge } from '../../../ui/Badge'\r\nimport {\r\n Select,\r\n SelectContent,\r\n SelectItem,\r\n SelectTrigger,\r\n SelectValue,\r\n} from '../../../ui/Select'\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\n\r\n// Utils\r\nimport { useUserRole } from '../../../../hooks/users/users'\r\nimport { UserAvatar } from '../../../ui/UserAvatar'\r\nimport { MapContext } from '../../../../store/Map/context'\r\n\r\nimport { useLocale, useTranslations } from 'next-intl'\r\nimport { Building, DbFile, Infrastructure, Site, User } from '../../../../types/dbTypes'\r\nimport { RoleNames } from '../../../../types/global'\r\n\r\nexport interface ColumnMeta {\r\n columnClasses: string\r\n}\r\n\r\nexport type BuildingDatumValue = {\r\n id: string\r\n buildingDatumId: string\r\n value: string\r\n date: string\r\n}\r\n\r\nexport type FileAttachment\r\n = | { type: 'building', buildingId: string }\r\n | { type: 'site', siteId: string }\r\n | { type: 'infrastructure', infrastructureId: string }\r\n\r\nexport function useColumns(buildings?: Building[]): ColumnDef<Building | Site | Infrastructure | DbFile>[] {\r\n // Translations\r\n const t = useTranslations('DataMenuColumns')\r\n const locale = useLocale()\r\n\r\n const { currentViewer } = React.useContext(MenusContext).state.menus\r\n const { state: mapState } = React.useContext(MapContext)\r\n const countrySubdivisionsData = mapState.map.countrySubdivisionsData\r\n\r\n const getSubdivisionName = React.useCallback((code: string | undefined | null): string => {\r\n if (!code) return ''\r\n if (!countrySubdivisionsData) return code\r\n // Exact match (e.g. \"CA-ON\")\r\n const exact = countrySubdivisionsData[code] as any\r\n if (exact) return (exact?.name ?? exact) || code\r\n // Suffix match — handles short codes stored by the geocoder (e.g. \"ON\" → \"CA-ON\")\r\n const entry = Object.entries(countrySubdivisionsData).find(([k]) => k.endsWith(`-${code}`))\r\n if (entry) return ((entry[1] as any)?.name ?? entry[1]) || code\r\n return code\r\n }, [countrySubdivisionsData])\r\n\r\n // Helper to check for duplicate names in the current data\r\n const hasDuplicateName = React.useCallback(\r\n <T extends { buildingName?: string; infrastructureName?: string }>(data: T[], name: string) => {\r\n if (!name) return false\r\n const namesCount = data.filter(\r\n b =>\r\n (b.buildingName === name) ||\r\n (b.infrastructureName === name)\r\n ).length\r\n return namesCount > 1\r\n },\r\n []\r\n )\r\n\r\n // Define column configurations for each viewer type\r\n const buildingsColumns: ColumnDef<Building | Site | Infrastructure | DbFile>[] = [\r\n {\r\n accessorKey: 'buildingName',\r\n accessorFn: (row) => {\r\n // If buildingName exists and is not empty, use it; otherwise, use address\r\n if ('buildingName' in row && row.buildingName) {\r\n return row.buildingName\r\n }\r\n if ('buildingAddress' in row && row.buildingAddress) {\r\n return row.buildingAddress\r\n }\r\n return ''\r\n },\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('buildingNameAdd')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n cell: ({ row, table }) => {\r\n const building = row.original as Building\r\n const buildingName = building.buildingName\r\n const buildingAddress = building.buildingAddress\r\n \r\n // Get all rows in the current page\r\n const currentPageData = table.getRowModel().rows.map(r => r.original as Building)\r\n \r\n // Check if this building name exists in the current page\r\n const isDuplicate = buildingName && hasDuplicateName(currentPageData, buildingName)\r\n \r\n if (!buildingName) {\r\n return buildingAddress || ''\r\n }\r\n \r\n if (isDuplicate) {\r\n return `${buildingName} - ${buildingAddress || ''}`\r\n }\r\n \r\n return buildingName\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: 'invisible absolute sm:visible sm:static sm:table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'buildingCountrySubdivision',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('buildingCountrySubdivision')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n cell: ({ getValue }) => getSubdivisionName(getValue() as string),\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'buildingMunicipality',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('buildingMunic')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'buildingType',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('buildingType')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n ]\r\n\r\n const sitesColumns: ColumnDef<Building | Site | DbFile>[] = [\r\n {\r\n accessorKey: 'siteName',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('siteName')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'siteCountrySubdivision',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('siteCountrySubdivision')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n cell: ({ getValue }) => getSubdivisionName(getValue() as string),\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'siteMunicipality',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('siteMunic')}\r\n\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: 'invisible absolute sm:visible sm:static sm:table-cell' } as ColumnMeta,\r\n },\r\n ]\r\n\r\n const infrastructureColumns: ColumnDef<Building | Site | Infrastructure | DbFile>[] = [\r\n {\r\n accessorKey: 'infrastructureName',\r\n accessorFn: (row) => {\r\n // Fallback logic: Name -> Address -> Empty String\r\n if ('infrastructureName' in row && row.infrastructureName) {\r\n return row.infrastructureName\r\n }\r\n if ('infrastructureAddress' in row && row.infrastructureAddress) {\r\n return row.infrastructureAddress\r\n }\r\n return ''\r\n },\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {/* Note: Ensure 'infrastructureName' or similar is in your translation file */}\r\n {t('infrastructureName')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n cell: ({ row, table }) => {\r\n const infra = row.original as Infrastructure\r\n const infraName = infra.infrastructureName\r\n const infraAddress = infra.infrastructureAddress\r\n\r\n // Get all rows in current page for duplicate checking\r\n const currentPageData = table.getRowModel().rows.map(r => r.original as Infrastructure)\r\n\r\n // Use the same helper function used in buildings for consistency\r\n const isDuplicate = infraName && hasDuplicateName(currentPageData, infraName)\r\n\r\n if (!infraName) {\r\n return infraAddress || ''\r\n }\r\n\r\n if (isDuplicate) {\r\n return `${infraName} - ${infraAddress || ''}`\r\n }\r\n\r\n return infraName\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: 'invisible absolute sm:visible sm:static sm:table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'infrastructureCountrySubdivision',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('infrastructureCountrySubdivision')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n cell: ({ getValue }) => getSubdivisionName(getValue() as string),\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'infrastructureMunicipality',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('infrastructureMunic')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'infrastructureType',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('infrastructureType')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n]\r\n\r\n const filesColumns: ColumnDef<Building | Site | DbFile>[] = [\r\n {\r\n accessorKey: 'name',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('fileName')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'site',\r\n accessorFn: (row) => {\r\n if ('attachedTo' in row && row.attachedTo) {\r\n const siteAttachments = (row.attachedTo as FileAttachment[]).filter(attachment => attachment.type === 'site')\r\n if (siteAttachments.length === 0) return ''\r\n if (siteAttachments.length === 1) return siteAttachments[0].siteId\r\n return `${siteAttachments[0].siteId} ${t('and')} ${siteAttachments.length - 1} ${t('fileMore')}`\r\n }\r\n return ''\r\n },\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('fileSite')}\r\n\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: 'invisible absolute sm:visible sm:static sm:table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'building',\r\n accessorFn: (row) => {\r\n if ('attachedTo' in row && row.attachedTo) {\r\n const buildingAttachments = (row.attachedTo as FileAttachment[]).filter(attachment => attachment.type === 'building')\r\n if (buildingAttachments.length === 0) return ''\r\n\r\n const buildingRef = buildingAttachments[0].buildingId\r\n const foundBuilding = buildings?.find(b => String(b.id) === String(buildingRef))\r\n const displayName = foundBuilding?.buildingName || foundBuilding?.buildingAddress || buildingRef\r\n\r\n if (buildingAttachments.length === 1) return displayName\r\n return `${displayName} ${t('and')} ${buildingAttachments.length - 1} ${t('fileMore')}`\r\n }\r\n return ''\r\n },\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('fileBuilding')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'dateUploaded',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('fileDate')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n cell: ({ row }) => {\r\n const original = row.original as DbFile\r\n const iso = 'dateUploaded' in original ? (original as any).dateUploaded : undefined\r\n if (!iso) return ''\r\n const date = new Date(iso)\r\n const dateStr = date.toLocaleDateString(locale, {\r\n month: 'long',\r\n day: 'numeric',\r\n year: 'numeric',\r\n })\r\n const timeStr = date.toLocaleTimeString(locale, {\r\n hour: 'numeric',\r\n minute: '2-digit',\r\n hour12: true,\r\n })\r\n return `${dateStr} ${t('dateAt')} ${timeStr}`\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'fileType',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('fileType')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n ]\r\n\r\n // Return the appropriate columns based on the current viewer\r\n switch (currentViewer) {\r\n case 'buildings':\r\n return buildingsColumns\r\n case 'sites':\r\n return sitesColumns\r\n case 'infrastructure':\r\n return infrastructureColumns\r\n case 'files':\r\n return filesColumns\r\n default:\r\n return buildingsColumns // Default to buildings if viewer type is unknown\r\n }\r\n}\r\n\r\nexport function useUserColumns(): ColumnDef<User>[] {\r\n const t = useTranslations('DataMenuColumns')\r\n\r\n return [\r\n {\r\n id: 'avatar',\r\n header: () => null,\r\n cell: ({ row }) => {\r\n const user = row.original\r\n return (\r\n <Avatar className=\"h-8 w-8 bg-white rounded-full overflow-hidden\">\r\n <UserAvatar imageFileId={user?.imageFileId} name={user?.name} />\r\n </Avatar>\r\n )\r\n },\r\n enableSorting: false,\r\n meta: { columnClasses: '!w-12 !pl-4 !pr-1 !py-0' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'name',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('userName')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n },\r\n {\r\n accessorKey: 'email',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('userEmail')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n },\r\n {\r\n accessorKey: 'userRole',\r\n header: t('userRole'),\r\n cell: ({ row }) => <UserRoleCell userId={row.original.id} />,\r\n enableSorting: false,\r\n },\r\n ]\r\n}\r\n\r\nconst roleFallbackOptions = Object.values(RoleNames)\r\n\r\nconst normalizeRoleName = (role?: string) => (role || '').toLowerCase()\r\n\r\nconst getRoleLabel = (t: ReturnType<typeof useTranslations>, role: string) => {\r\n const normalizedRole = normalizeRoleName(role)\r\n if (normalizedRole === RoleNames.admin) return t('roles.admin')\r\n if (normalizedRole === RoleNames.user) return t('roles.user')\r\n if (normalizedRole === RoleNames.viewer) return t('roles.viewer')\r\n return role\r\n}\r\n\r\nconst UserRoleCell = ({ userId }: { userId: number }) => {\r\n const t = useTranslations('DataMenuColumns')\r\n const { data: session } = useSession()\r\n const { userRole: currentUserRole } = useUserRole(session?.user?.id || '')\r\n const isAdmin = currentUserRole && normalizeRoleName(currentUserRole.name) === RoleNames.admin\r\n\r\n const { userRole } = useUserRole(String(userId))\r\n const roleName = userRole?.name || ''\r\n const normalizedRoleName = normalizeRoleName(roleName)\r\n const options = Array.from(new Set([...roleFallbackOptions, normalizedRoleName].filter(Boolean)))\r\n const [selectedRole, setSelectedRole] = React.useState(normalizedRoleName || options[0] || '')\r\n\r\n React.useEffect(() => {\r\n if (normalizedRoleName) {\r\n setSelectedRole(normalizedRoleName)\r\n }\r\n }, [normalizedRoleName])\r\n\r\n if (!isAdmin) {\r\n return (\r\n <div className=\"flex gap-2 flex-wrap\">\r\n {roleName ? (\r\n <Badge variant=\"secondary\" className=\"font-medium\">\r\n {getRoleLabel(t, roleName)}\r\n </Badge>\r\n ) : (\r\n <span className=\"text-muted-foreground text-sm\">{t('roleEmptyValue')}</span>\r\n )}\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <Select value={selectedRole} onValueChange={setSelectedRole}>\r\n <SelectTrigger className=\"h-8\">\r\n <SelectValue placeholder={t('roleSelectPlaceholder')} />\r\n </SelectTrigger>\r\n <SelectContent>\r\n {options.map(role => (\r\n <SelectItem key={role} value={role}>\r\n {getRoleLabel(t, role)}\r\n </SelectItem>\r\n ))}\r\n </SelectContent>\r\n </Select>\r\n )\r\n}\r\n\r\nexport function useAssociatedBuildingsColumns(): ColumnDef<Building>[] {\r\n // Translations\r\n const t = useTranslations('DataMenuColumns')\r\n\r\n return [\r\n {\r\n accessorKey: 'buildingName',\r\n accessorFn: (row) => {\r\n // If buildingName exists and is not empty, use it; otherwise, use address\r\n if (row.buildingName) {\r\n return row.buildingName\r\n }\r\n return ''\r\n },\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('associatedBuildingsName')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'buildingAddress',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('associatedBuildingsAddress')}\r\n {isSorted === false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown />}\r\n {isSorted === 'asc' && <LR.ArrowUp />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'buildingProjectType',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('associatedBuildingsProjectType')}\r\n {isSorted === false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown />}\r\n {isSorted === 'asc' && <LR.ArrowUp />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n ]\r\n}\r\n\r\nexport type PropertyFile = {\r\n name: string\r\n type: string\r\n createdAt: string\r\n}\r\n\r\nexport function usePropertyFilesColumns(): ColumnDef<DbFile>[] {\r\n // Translations\r\n const t = useTranslations('DataMenuColumns')\r\n\r\n return [\r\n {\r\n accessorKey: 'name',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('propertyFileName')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'extension',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('propertyFileType')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'dateUploaded',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('propertyFilesDateUp')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: 'invisible absolute sm:visible sm:static sm:table-cell' } as ColumnMeta,\r\n },\r\n ]\r\n}\r\n\r\nexport type filterFieldOptions = {\r\n id: string\r\n label: string\r\n type: 'boolean' | 'string' | 'number' | 'date'\r\n valueOptions?: string[]\r\n}\r\n\r\n// Requirement for using the filter:\r\nexport function useBuildingDataFilterFields(): filterFieldOptions[] {\r\n const t = useTranslations('DataMenuColumns')\r\n\r\n return [\r\n { id: 'buildingName', label: t('filterFields.buildingName'), type: 'string' },\r\n { id: 'buildingCountrySubdivision', label: t('filterFields.buildingCountrySubdivision'), type: 'string' },\r\n { id: 'buildingMunicipality', label: t('filterFields.buildingMunicipality'), type: 'string' },\r\n { id: 'buildingType', label: t('filterFields.buildingType'), type: 'string' },\r\n { id: 'buildingAddress', label: t('filterFields.buildingAddress'), type: 'string' },\r\n ]\r\n}\r\n\r\nexport function useSiteDataFilterFields(): filterFieldOptions[] {\r\n const t = useTranslations('DataMenuColumns')\r\n\r\n return [\r\n { id: 'siteName', label: t('filterFields.siteName'), type: 'string' },\r\n { id: 'siteCountrySubdivision', label: t('filterFields.siteCountrySubdivision'), type: 'string' },\r\n { id: 'siteMunicipality', label: t('filterFields.siteMunicipality'), type: 'string' },\r\n { id: 'siteAddress', label: t('filterFields.siteAddress'), type: 'string' },\r\n ]\r\n}\r\n\r\nexport function useInfrastructureDataFilterFields(): filterFieldOptions[] {\r\n const t = useTranslations('DataMenuColumns')\r\n\r\n return [\r\n { id: 'infrastructureName', label: t('filterFields.infrastructureName'), type: 'string' },\r\n { id: 'infrastructureCountrySubdivision', label: t('filterFields.infrastructureCountrySubdivision'), type: 'string' },\r\n { id: 'infrastructureMunicipality', label: t('filterFields.infrastructureMunicipality'), type: 'string' },\r\n { id: 'infrastructureType', label: t('filterFields.infrastructureType'), type: 'string' },\r\n { id: 'infrastructureAddress', label: t('filterFields.infrastructureAddress'), type: 'string' },\r\n ]\r\n}"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../../../src/core/components/viewers/Data/utils/Columns.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\n// Dependencies\r\nimport * as React from 'react'\r\nimport { ColumnDef } from '@tanstack/react-table'\r\nimport { MenusContext } from '../../../../store'\r\nimport { useSession } from 'next-auth/react'\r\n\r\n// Shadcn Components\r\nimport { Button } from '../../../ui/Button'\r\nimport { Avatar, AvatarFallback, AvatarImage } from '../../../ui/Avatar'\r\nimport { Badge } from '../../../ui/Badge'\r\nimport {\r\n Select,\r\n SelectContent,\r\n SelectItem,\r\n SelectTrigger,\r\n SelectValue,\r\n} from '../../../ui/Select'\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\n\r\n// Utils\r\nimport { useUserRole } from '../../../../hooks/users/users'\r\nimport { UserAvatar } from '../../../ui/UserAvatar'\r\nimport { MapContext } from '../../../../store/Map/context'\r\n\r\nimport { useLocale, useTranslations } from 'next-intl'\r\nimport { Building, DbFile, Infrastructure, Site, User } from '../../../../types/dbTypes'\r\nimport { RoleNames } from '../../../../types/global'\r\n\r\nexport interface ColumnMeta {\r\n columnClasses: string\r\n}\r\n\r\nexport type BuildingDatumValue = {\r\n id: string\r\n buildingDatumId: string\r\n value: string\r\n date: string\r\n}\r\n\r\nexport type FileAttachment\r\n = | { type: 'building', buildingId: string }\r\n | { type: 'site', siteId: string }\r\n | { type: 'infrastructure', infrastructureId: string }\r\n\r\nexport function useColumns(buildings?: Building[]): ColumnDef<Building | Site | Infrastructure | DbFile>[] {\r\n // Translations\r\n const t = useTranslations('DataMenuColumns')\r\n const locale = useLocale()\r\n\r\n const { currentViewer } = React.useContext(MenusContext).state.menus\r\n const { state: mapState } = React.useContext(MapContext)\r\n const countrySubdivisionsData = mapState.map.countrySubdivisionsData\r\n\r\n const getSubdivisionName = React.useCallback((code: string | undefined | null): string => {\r\n if (!code) return ''\r\n if (!countrySubdivisionsData) return code\r\n // Exact match (e.g. \"CA-ON\")\r\n const exact = countrySubdivisionsData[code] as any\r\n if (exact) return (exact?.name ?? exact) || code\r\n // Suffix match — handles short codes stored by the geocoder (e.g. \"ON\" → \"CA-ON\")\r\n const entry = Object.entries(countrySubdivisionsData).find(([k]) => k.endsWith(`-${code}`))\r\n if (entry) return ((entry[1] as any)?.name ?? entry[1]) || code\r\n return code\r\n }, [countrySubdivisionsData])\r\n\r\n // Helper to check for duplicate names in the current data\r\n const hasDuplicateName = React.useCallback(\r\n <T extends { buildingName?: string; infrastructureName?: string }>(data: T[], name: string) => {\r\n if (!name) return false\r\n const namesCount = data.filter(\r\n b =>\r\n (b.buildingName === name) ||\r\n (b.infrastructureName === name)\r\n ).length\r\n return namesCount > 1\r\n },\r\n []\r\n )\r\n\r\n // Define column configurations for each viewer type\r\n const buildingsColumns: ColumnDef<Building | Site | Infrastructure | DbFile>[] = [\r\n {\r\n accessorKey: 'buildingName',\r\n accessorFn: (row) => {\r\n // If buildingName exists and is not empty, use it; otherwise, use address\r\n if ('buildingName' in row && row.buildingName) {\r\n return row.buildingName\r\n }\r\n if ('buildingAddress' in row && row.buildingAddress) {\r\n return row.buildingAddress\r\n }\r\n return ''\r\n },\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('buildingNameAdd')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n cell: ({ row, table }) => {\r\n const building = row.original as Building\r\n const buildingName = building.buildingName\r\n const buildingAddress = building.buildingAddress\r\n \r\n // Get all rows in the current page\r\n const currentPageData = table.getRowModel().rows.map(r => r.original as Building)\r\n \r\n // Check if this building name exists in the current page\r\n const isDuplicate = buildingName && hasDuplicateName(currentPageData, buildingName)\r\n \r\n if (!buildingName) {\r\n return buildingAddress || ''\r\n }\r\n \r\n if (isDuplicate) {\r\n return `${buildingName} - ${buildingAddress || ''}`\r\n }\r\n \r\n return buildingName\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'buildingCountrySubdivision',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('buildingCountrySubdivision')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n cell: ({ getValue }) => getSubdivisionName(getValue() as string),\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'buildingMunicipality',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('buildingMunic')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'buildingType',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('buildingType')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n ]\r\n\r\n const sitesColumns: ColumnDef<Building | Site | DbFile>[] = [\r\n {\r\n accessorKey: 'siteName',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('siteName')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'siteCountrySubdivision',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('siteCountrySubdivision')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n cell: ({ getValue }) => getSubdivisionName(getValue() as string),\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'siteMunicipality',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('siteMunic')}\r\n\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: 'invisible absolute sm:visible sm:static sm:table-cell' } as ColumnMeta,\r\n },\r\n ]\r\n\r\n const infrastructureColumns: ColumnDef<Building | Site | Infrastructure | DbFile>[] = [\r\n {\r\n accessorKey: 'infrastructureName',\r\n accessorFn: (row) => {\r\n // Fallback logic: Name -> Address -> Empty String\r\n if ('infrastructureName' in row && row.infrastructureName) {\r\n return row.infrastructureName\r\n }\r\n if ('infrastructureAddress' in row && row.infrastructureAddress) {\r\n return row.infrastructureAddress\r\n }\r\n return ''\r\n },\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {/* Note: Ensure 'infrastructureName' or similar is in your translation file */}\r\n {t('infrastructureName')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n cell: ({ row, table }) => {\r\n const infra = row.original as Infrastructure\r\n const infraName = infra.infrastructureName\r\n const infraAddress = infra.infrastructureAddress\r\n\r\n // Get all rows in current page for duplicate checking\r\n const currentPageData = table.getRowModel().rows.map(r => r.original as Infrastructure)\r\n\r\n // Use the same helper function used in buildings for consistency\r\n const isDuplicate = infraName && hasDuplicateName(currentPageData, infraName)\r\n\r\n if (!infraName) {\r\n return infraAddress || ''\r\n }\r\n\r\n if (isDuplicate) {\r\n return `${infraName} - ${infraAddress || ''}`\r\n }\r\n\r\n return infraName\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'infrastructureCountrySubdivision',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('infrastructureCountrySubdivision')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n cell: ({ getValue }) => getSubdivisionName(getValue() as string),\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'infrastructureMunicipality',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('infrastructureMunic')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'infrastructureType',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('infrastructureType')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n]\r\n\r\n const filesColumns: ColumnDef<Building | Site | DbFile>[] = [\r\n {\r\n accessorKey: 'name',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('fileName')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'site',\r\n accessorFn: (row) => {\r\n if ('attachedTo' in row && row.attachedTo) {\r\n const siteAttachments = (row.attachedTo as FileAttachment[]).filter(attachment => attachment.type === 'site')\r\n if (siteAttachments.length === 0) return ''\r\n if (siteAttachments.length === 1) return siteAttachments[0].siteId\r\n return `${siteAttachments[0].siteId} ${t('and')} ${siteAttachments.length - 1} ${t('fileMore')}`\r\n }\r\n return ''\r\n },\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('fileSite')}\r\n\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: 'invisible absolute sm:visible sm:static sm:table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'building',\r\n accessorFn: (row) => {\r\n if ('attachedTo' in row && row.attachedTo) {\r\n const buildingAttachments = (row.attachedTo as FileAttachment[]).filter(attachment => attachment.type === 'building')\r\n if (buildingAttachments.length === 0) return ''\r\n\r\n const buildingRef = buildingAttachments[0].buildingId\r\n const foundBuilding = buildings?.find(b => String(b.id) === String(buildingRef))\r\n const displayName = foundBuilding?.buildingName || foundBuilding?.buildingAddress || buildingRef\r\n\r\n if (buildingAttachments.length === 1) return displayName\r\n return `${displayName} ${t('and')} ${buildingAttachments.length - 1} ${t('fileMore')}`\r\n }\r\n return ''\r\n },\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('fileBuilding')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'dateUploaded',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('fileDate')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n cell: ({ row }) => {\r\n const original = row.original as DbFile\r\n const iso = 'dateUploaded' in original ? (original as any).dateUploaded : undefined\r\n if (!iso) return ''\r\n const date = new Date(iso)\r\n const dateStr = date.toLocaleDateString(locale, {\r\n month: 'long',\r\n day: 'numeric',\r\n year: 'numeric',\r\n })\r\n const timeStr = date.toLocaleTimeString(locale, {\r\n hour: 'numeric',\r\n minute: '2-digit',\r\n hour12: true,\r\n })\r\n return `${dateStr} ${t('dateAt')} ${timeStr}`\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'fileType',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('fileType')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n ]\r\n\r\n // Return the appropriate columns based on the current viewer\r\n switch (currentViewer) {\r\n case 'buildings':\r\n return buildingsColumns\r\n case 'sites':\r\n return sitesColumns\r\n case 'infrastructure':\r\n return infrastructureColumns\r\n case 'files':\r\n return filesColumns\r\n default:\r\n return buildingsColumns // Default to buildings if viewer type is unknown\r\n }\r\n}\r\n\r\nexport function useUserColumns(): ColumnDef<User>[] {\r\n const t = useTranslations('DataMenuColumns')\r\n\r\n return [\r\n {\r\n id: 'avatar',\r\n header: () => null,\r\n cell: ({ row }) => {\r\n const user = row.original\r\n return (\r\n <Avatar className=\"h-8 w-8 bg-white rounded-full overflow-hidden\">\r\n <UserAvatar imageFileId={user?.imageFileId} name={user?.name} />\r\n </Avatar>\r\n )\r\n },\r\n enableSorting: false,\r\n meta: { columnClasses: '!w-12 !pl-4 !pr-1 !py-0' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'name',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('userName')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n },\r\n {\r\n accessorKey: 'email',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('userEmail')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n },\r\n {\r\n accessorKey: 'userRole',\r\n header: t('userRole'),\r\n cell: ({ row }) => <UserRoleCell userId={row.original.id} />,\r\n enableSorting: false,\r\n },\r\n ]\r\n}\r\n\r\nconst roleFallbackOptions = Object.values(RoleNames)\r\n\r\nconst normalizeRoleName = (role?: string) => (role || '').toLowerCase()\r\n\r\nconst getRoleLabel = (t: ReturnType<typeof useTranslations>, role: string) => {\r\n const normalizedRole = normalizeRoleName(role)\r\n if (normalizedRole === RoleNames.admin) return t('roles.admin')\r\n if (normalizedRole === RoleNames.user) return t('roles.user')\r\n if (normalizedRole === RoleNames.viewer) return t('roles.viewer')\r\n return role\r\n}\r\n\r\nconst UserRoleCell = ({ userId }: { userId: number }) => {\r\n const t = useTranslations('DataMenuColumns')\r\n const { data: session } = useSession()\r\n const { userRole: currentUserRole } = useUserRole(session?.user?.id || '')\r\n const isAdmin = currentUserRole && normalizeRoleName(currentUserRole.name) === RoleNames.admin\r\n\r\n const { userRole } = useUserRole(String(userId))\r\n const roleName = userRole?.name || ''\r\n const normalizedRoleName = normalizeRoleName(roleName)\r\n const options = Array.from(new Set([...roleFallbackOptions, normalizedRoleName].filter(Boolean)))\r\n const [selectedRole, setSelectedRole] = React.useState(normalizedRoleName || options[0] || '')\r\n\r\n React.useEffect(() => {\r\n if (normalizedRoleName) {\r\n setSelectedRole(normalizedRoleName)\r\n }\r\n }, [normalizedRoleName])\r\n\r\n if (!isAdmin) {\r\n return (\r\n <div className=\"flex gap-2 flex-wrap\">\r\n {roleName ? (\r\n <Badge variant=\"secondary\" className=\"font-medium\">\r\n {getRoleLabel(t, roleName)}\r\n </Badge>\r\n ) : (\r\n <span className=\"text-muted-foreground text-sm\">{t('roleEmptyValue')}</span>\r\n )}\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <Select value={selectedRole} onValueChange={setSelectedRole}>\r\n <SelectTrigger className=\"h-8\">\r\n <SelectValue placeholder={t('roleSelectPlaceholder')} />\r\n </SelectTrigger>\r\n <SelectContent>\r\n {options.map(role => (\r\n <SelectItem key={role} value={role}>\r\n {getRoleLabel(t, role)}\r\n </SelectItem>\r\n ))}\r\n </SelectContent>\r\n </Select>\r\n )\r\n}\r\n\r\nexport function useAssociatedBuildingsColumns(): ColumnDef<Building>[] {\r\n // Translations\r\n const t = useTranslations('DataMenuColumns')\r\n\r\n return [\r\n {\r\n accessorKey: 'buildingName',\r\n accessorFn: (row) => {\r\n // If buildingName exists and is not empty, use it; otherwise, use address\r\n if (row.buildingName) {\r\n return row.buildingName\r\n }\r\n return ''\r\n },\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('associatedBuildingsName')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'buildingAddress',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('associatedBuildingsAddress')}\r\n {isSorted === false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown />}\r\n {isSorted === 'asc' && <LR.ArrowUp />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'buildingProjectType',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('associatedBuildingsProjectType')}\r\n {isSorted === false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown />}\r\n {isSorted === 'asc' && <LR.ArrowUp />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n ]\r\n}\r\n\r\nexport type PropertyFile = {\r\n name: string\r\n type: string\r\n createdAt: string\r\n}\r\n\r\nexport function usePropertyFilesColumns(): ColumnDef<DbFile>[] {\r\n // Translations\r\n const t = useTranslations('DataMenuColumns')\r\n\r\n return [\r\n {\r\n accessorKey: 'name',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('propertyFileName')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'extension',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('propertyFileType')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: '!hidden sm:!table-cell' } as ColumnMeta,\r\n },\r\n {\r\n accessorKey: 'dateUploaded',\r\n header: ({ column }) => {\r\n const isSorted = column.getIsSorted()\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n onClick={column.getToggleSortingHandler()}\r\n className=\"hover:bg-transparent p-0\"\r\n >\r\n {t('propertyFilesDateUp')}\r\n {isSorted == false && <LR.ArrowUpDown />}\r\n {isSorted === 'desc' && <LR.ArrowDown className=\"text-black\" />}\r\n {isSorted === 'asc' && <LR.ArrowUp className=\"text-black\" />}\r\n </Button>\r\n )\r\n },\r\n enableSorting: true,\r\n meta: { columnClasses: 'invisible absolute sm:visible sm:static sm:table-cell' } as ColumnMeta,\r\n },\r\n ]\r\n}\r\n\r\nexport type filterFieldOptions = {\r\n id: string\r\n label: string\r\n type: 'boolean' | 'string' | 'number' | 'date'\r\n valueOptions?: string[]\r\n}\r\n\r\n// Requirement for using the filter:\r\nexport function useBuildingDataFilterFields(): filterFieldOptions[] {\r\n const t = useTranslations('DataMenuColumns')\r\n\r\n return [\r\n { id: 'buildingName', label: t('filterFields.buildingName'), type: 'string' },\r\n { id: 'buildingCountrySubdivision', label: t('filterFields.buildingCountrySubdivision'), type: 'string' },\r\n { id: 'buildingMunicipality', label: t('filterFields.buildingMunicipality'), type: 'string' },\r\n { id: 'buildingType', label: t('filterFields.buildingType'), type: 'string' },\r\n { id: 'buildingAddress', label: t('filterFields.buildingAddress'), type: 'string' },\r\n ]\r\n}\r\n\r\nexport function useSiteDataFilterFields(): filterFieldOptions[] {\r\n const t = useTranslations('DataMenuColumns')\r\n\r\n return [\r\n { id: 'siteName', label: t('filterFields.siteName'), type: 'string' },\r\n { id: 'siteCountrySubdivision', label: t('filterFields.siteCountrySubdivision'), type: 'string' },\r\n { id: 'siteMunicipality', label: t('filterFields.siteMunicipality'), type: 'string' },\r\n { id: 'siteAddress', label: t('filterFields.siteAddress'), type: 'string' },\r\n ]\r\n}\r\n\r\nexport function useInfrastructureDataFilterFields(): filterFieldOptions[] {\r\n const t = useTranslations('DataMenuColumns')\r\n\r\n return [\r\n { id: 'infrastructureName', label: t('filterFields.infrastructureName'), type: 'string' },\r\n { id: 'infrastructureCountrySubdivision', label: t('filterFields.infrastructureCountrySubdivision'), type: 'string' },\r\n { id: 'infrastructureMunicipality', label: t('filterFields.infrastructureMunicipality'), type: 'string' },\r\n { id: 'infrastructureType', label: t('filterFields.infrastructureType'), type: 'string' },\r\n { id: 'infrastructureAddress', label: t('filterFields.infrastructureAddress'), type: 'string' },\r\n ]\r\n}"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"positionParser.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/Data/utils/positionParser.ts"],"names":[],"mappings":"AAGA,KAAK,cAAc,GAAG;IACpB,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,KAAK,WAAW,GAAG;IACjB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV,CAAA;AAED,KAAK,QAAQ,GAAG,cAAc,GAAG,WAAW,CAAA;AAE5C,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ,GAAG,IAAI,CASlF;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAwB1E;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAG7E;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAG1E"}
1
+ {"version":3,"file":"positionParser.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/Data/utils/positionParser.ts"],"names":[],"mappings":"AAGA,KAAK,cAAc,GAAG;IACpB,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,KAAK,WAAW,GAAG;IACjB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV,CAAA;AAED,KAAK,QAAQ,GAAG,cAAc,GAAG,WAAW,CAAA;AAE5C,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ,GAAG,IAAI,CAalF;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAyB1E;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAI7E;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAI1E"}
@@ -3,14 +3,15 @@ function parsePosition(position) {
3
3
  try {
4
4
  const parsed = typeof position === "string" ? JSON.parse(position) : position;
5
5
  return parsed;
6
- } catch (e) {
6
+ } catch (err) {
7
+ console.error("Failed to parse position:", position, err);
7
8
  return null;
8
9
  }
9
10
  }
10
11
  function formatPosition(position) {
11
12
  const parsed = parsePosition(position);
12
13
  if (!parsed) return "";
13
- if ("lat" in parsed && "lng" in parsed) {
14
+ if ("lat" in parsed && "lng" in parsed && typeof parsed.lat === "number" && typeof parsed.lng === "number") {
14
15
  const parts = [
15
16
  `Longitude: ${parsed.lng.toFixed(5)}`,
16
17
  `Latitude: ${parsed.lat.toFixed(5)}`
@@ -20,18 +21,18 @@ function formatPosition(position) {
20
21
  }
21
22
  return parts.join(", ");
22
23
  }
23
- if ("x" in parsed && "y" in parsed && "z" in parsed) {
24
+ if ("x" in parsed && "y" in parsed && "z" in parsed && typeof parsed.x === "number" && typeof parsed.y === "number" && typeof parsed.z === "number") {
24
25
  return `X: ${parsed.x}, Y: ${parsed.y}, Z: ${parsed.z}`;
25
26
  }
26
27
  return "";
27
28
  }
28
29
  function isLatLngPosition(position) {
29
30
  const parsed = parsePosition(position);
30
- return parsed !== null && "lat" in parsed && "lng" in parsed;
31
+ return parsed !== null && "lat" in parsed && "lng" in parsed && typeof parsed.lat === "number" && typeof parsed.lng === "number";
31
32
  }
32
33
  function isXYZPosition(position) {
33
34
  const parsed = parsePosition(position);
34
- return parsed !== null && "x" in parsed && "y" in parsed && "z" in parsed;
35
+ return parsed !== null && "x" in parsed && "y" in parsed && "z" in parsed && typeof parsed.x === "number" && typeof parsed.y === "number" && typeof parsed.z === "number";
35
36
  }
36
37
  export {
37
38
  formatPosition,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/core/components/viewers/Data/utils/positionParser.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\ntype LatLngPosition = {\r\n lng: number\r\n lat: number\r\n rotation?: number\r\n elevation?: number\r\n}\r\n\r\ntype XYZPosition = {\r\n x: number\r\n y: number\r\n z: number\r\n}\r\n\r\ntype Position = LatLngPosition | XYZPosition\r\n\r\nexport function parsePosition(position: string | null | undefined): Position | null {\r\n if (!position) return null\r\n \r\n try {\r\n const parsed = typeof position === 'string' ? JSON.parse(position) : position\r\n return parsed\r\n } catch {\r\n return null\r\n }\r\n}\r\n\r\nexport function formatPosition(position: string | null | undefined): string {\r\n const parsed = parsePosition(position)\r\n if (!parsed) return ''\r\n \r\n // Check if it's lat/lng format\r\n if ('lat' in parsed && 'lng' in parsed) {\r\n const parts = [\r\n `Longitude: ${parsed.lng.toFixed(5)}`,\r\n `Latitude: ${parsed.lat.toFixed(5)}`\r\n ]\r\n \r\n if (parsed.elevation !== undefined) {\r\n parts.push(`Elevation: ${parsed.elevation}m`)\r\n }\r\n \r\n return parts.join(', ')\r\n }\r\n \r\n // Check if it's x/y/z format\r\n if ('x' in parsed && 'y' in parsed && 'z' in parsed) {\r\n return `X: ${parsed.x}, Y: ${parsed.y}, Z: ${parsed.z}`\r\n }\r\n \r\n return ''\r\n}\r\n\r\nexport function isLatLngPosition(position: string | null | undefined): boolean {\r\n const parsed = parsePosition(position)\r\n return parsed !== null && 'lat' in parsed && 'lng' in parsed\r\n}\r\n\r\nexport function isXYZPosition(position: string | null | undefined): boolean {\r\n const parsed = parsePosition(position)\r\n return parsed !== null && 'x' in parsed && 'y' in parsed && 'z' in parsed\r\n}\r\n"],"mappings":"AAkBO,SAAS,cAAc,UAAsD;AAClF,MAAI,CAAC,SAAU,QAAO;AAEtB,MAAI;AACF,UAAM,SAAS,OAAO,aAAa,WAAW,KAAK,MAAM,QAAQ,IAAI;AACrE,WAAO;AAAA,EACT,SAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,eAAe,UAA6C;AAC1E,QAAM,SAAS,cAAc,QAAQ;AACrC,MAAI,CAAC,OAAQ,QAAO;AAGpB,MAAI,SAAS,UAAU,SAAS,QAAQ;AACtC,UAAM,QAAQ;AAAA,MACZ,cAAc,OAAO,IAAI,QAAQ,CAAC,CAAC;AAAA,MACnC,aAAa,OAAO,IAAI,QAAQ,CAAC,CAAC;AAAA,IACpC;AAEA,QAAI,OAAO,cAAc,QAAW;AAClC,YAAM,KAAK,cAAc,OAAO,SAAS,GAAG;AAAA,IAC9C;AAEA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAGA,MAAI,OAAO,UAAU,OAAO,UAAU,OAAO,QAAQ;AACnD,WAAO,MAAM,OAAO,CAAC,QAAQ,OAAO,CAAC,QAAQ,OAAO,CAAC;AAAA,EACvD;AAEA,SAAO;AACT;AAEO,SAAS,iBAAiB,UAA8C;AAC7E,QAAM,SAAS,cAAc,QAAQ;AACrC,SAAO,WAAW,QAAQ,SAAS,UAAU,SAAS;AACxD;AAEO,SAAS,cAAc,UAA8C;AAC1E,QAAM,SAAS,cAAc,QAAQ;AACrC,SAAO,WAAW,QAAQ,OAAO,UAAU,OAAO,UAAU,OAAO;AACrE;","names":[]}
1
+ {"version":3,"sources":["../../../../../../src/core/components/viewers/Data/utils/positionParser.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\ntype LatLngPosition = {\r\n lng: number\r\n lat: number\r\n rotation?: number\r\n elevation?: number\r\n}\r\n\r\ntype XYZPosition = {\r\n x: number\r\n y: number\r\n z: number\r\n}\r\n\r\ntype Position = LatLngPosition | XYZPosition\r\n\r\nexport function parsePosition(position: string | null | undefined): Position | null {\r\n if (!position) return null\r\n\r\n try {\r\n const parsed = typeof position === 'string'\r\n ? JSON.parse(position)\r\n : position\r\n\r\n return parsed\r\n } catch (err) {\r\n console.error('Failed to parse position:', position, err)\r\n return null\r\n }\r\n}\r\n\r\nexport function formatPosition(position: string | null | undefined): string {\r\n const parsed = parsePosition(position)\r\n if (!parsed) return ''\r\n \r\n // Check if it's lat/lng format\r\n if ('lat' in parsed && 'lng' in parsed\r\n && typeof parsed.lat === 'number' && typeof parsed.lng === 'number') {\r\n const parts = [\r\n `Longitude: ${parsed.lng.toFixed(5)}`,\r\n `Latitude: ${parsed.lat.toFixed(5)}`\r\n ]\r\n\r\n if (parsed.elevation !== undefined) {\r\n parts.push(`Elevation: ${parsed.elevation}m`)\r\n }\r\n return parts.join(', ')\r\n }\r\n\r\n // Check if it's x/y/z format\r\n if ('x' in parsed && 'y' in parsed && 'z' in parsed\r\n && typeof parsed.x === 'number' && typeof parsed.y === 'number' && typeof parsed.z === 'number') {\r\n return `X: ${parsed.x}, Y: ${parsed.y}, Z: ${parsed.z}`\r\n }\r\n \r\n return ''\r\n}\r\n\r\nexport function isLatLngPosition(position: string | null | undefined): boolean {\r\n const parsed = parsePosition(position)\r\n return parsed !== null && 'lat' in parsed && 'lng' in parsed\r\n && typeof parsed.lat === 'number' && typeof parsed.lng === 'number'\r\n}\r\n\r\nexport function isXYZPosition(position: string | null | undefined): boolean {\r\n const parsed = parsePosition(position)\r\n return parsed !== null && 'x' in parsed && 'y' in parsed && 'z' in parsed\r\n && typeof parsed.x === 'number' && typeof parsed.y === 'number' && typeof parsed.z === 'number'\r\n}\r\n"],"mappings":"AAkBO,SAAS,cAAc,UAAsD;AAClF,MAAI,CAAC,SAAU,QAAO;AAEtB,MAAI;AACF,UAAM,SAAS,OAAO,aAAa,WAC/B,KAAK,MAAM,QAAQ,IACnB;AAEJ,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,YAAQ,MAAM,6BAA6B,UAAU,GAAG;AACxD,WAAO;AAAA,EACT;AACF;AAEO,SAAS,eAAe,UAA6C;AAC1E,QAAM,SAAS,cAAc,QAAQ;AACrC,MAAI,CAAC,OAAQ,QAAO;AAGpB,MAAI,SAAS,UAAU,SAAS,UAC3B,OAAO,OAAO,QAAQ,YAAY,OAAO,OAAO,QAAQ,UAAU;AACrE,UAAM,QAAQ;AAAA,MACZ,cAAc,OAAO,IAAI,QAAQ,CAAC,CAAC;AAAA,MACnC,aAAa,OAAO,IAAI,QAAQ,CAAC,CAAC;AAAA,IACpC;AAEA,QAAI,OAAO,cAAc,QAAW;AAClC,YAAM,KAAK,cAAc,OAAO,SAAS,GAAG;AAAA,IAC9C;AACA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAGA,MAAI,OAAO,UAAU,OAAO,UAAU,OAAO,UACxC,OAAO,OAAO,MAAM,YAAY,OAAO,OAAO,MAAM,YAAY,OAAO,OAAO,MAAM,UAAU;AACjG,WAAO,MAAM,OAAO,CAAC,QAAQ,OAAO,CAAC,QAAQ,OAAO,CAAC;AAAA,EACvD;AAEA,SAAO;AACT;AAEO,SAAS,iBAAiB,UAA8C;AAC7E,QAAM,SAAS,cAAc,QAAQ;AACrC,SAAO,WAAW,QAAQ,SAAS,UAAU,SAAS,UACjD,OAAO,OAAO,QAAQ,YAAY,OAAO,OAAO,QAAQ;AAC/D;AAEO,SAAS,cAAc,UAA8C;AAC1E,QAAM,SAAS,cAAc,QAAQ;AACrC,SAAO,WAAW,QAAQ,OAAO,UAAU,OAAO,UAAU,OAAO,UAC9D,OAAO,OAAO,MAAM,YAAY,OAAO,OAAO,MAAM,YAAY,OAAO,OAAO,MAAM;AAC3F;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"TopicsSection.d.ts","sourceRoot":"","sources":["../../../../../../../../../../src/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAe9B,wBAAgB,aAAa,sBAgO5B"}
1
+ {"version":3,"file":"TopicsSection.d.ts","sourceRoot":"","sources":["../../../../../../../../../../src/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAe9B,wBAAgB,aAAa,sBA0O5B"}
@@ -37,7 +37,14 @@ function TopicsSection() {
37
37
  const user = session == null ? void 0 : session.user;
38
38
  const { state: bimState, dispatch: bimDispatch } = React.useContext(BimContext);
39
39
  const { bimComponents, bcfTopics } = bimState.bim;
40
- const bcfTopicsManager = bimComponents == null ? void 0 : bimComponents.get(BCFTopicsManager);
40
+ let bcfTopicsManager;
41
+ if (bimComponents) {
42
+ try {
43
+ bcfTopicsManager = bimComponents.get(BCFTopicsManager);
44
+ } catch (e) {
45
+ bcfTopicsManager = new BCFTopicsManager(bimComponents);
46
+ }
47
+ }
41
48
  const { state: buildingState } = React.useContext(BuildingsContext);
42
49
  const { building } = buildingState.buildings;
43
50
  const [createDialogOpen, setCreateDialogOpen] = React.useState(false);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../../src/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from 'react'\r\nimport * as OBC from '@thatopen/components'\r\nimport { Button } from '../../../../../../../ui/Button'\r\nimport * as LR from 'lucide-react'\r\nimport { BimContext, BuildingsContext, usePermissions } from '../../../../../../../../store'\r\nimport { CollapsibleSection } from '../../../../../../../ui/CollapsibleSection'\r\nimport { useTranslations } from 'next-intl'\r\nimport { useSession } from 'next-auth/react'\r\nimport { BCFTopicsManager } from '../../../../BCFTopicsManager'\r\nimport { CreateTopicDialog, BCFTopicFormData } from './CreateTopicDialog'\r\nimport { CollapsibleTopicItem } from './CollapsibleTopicItem'\r\nimport { BcfIcon } from '../../../../../../../ui/Icons'\r\n\r\ntype TopicAction = 'view' | 'edit' | 'delete'\r\n\r\nexport function TopicsSection() {\r\n // Translation\r\n const t = useTranslations('TopicsSection')\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n // Get user session\r\n const { data: session } = useSession()\r\n const user = session?.user\r\n\r\n // Get BIM context\r\n const { state: bimState, dispatch: bimDispatch } = React.useContext(BimContext)\r\n const { bimComponents, bcfTopics } = bimState.bim\r\n const bcfTopicsManager = bimComponents?.get(BCFTopicsManager)\r\n\r\n // Get Buildings context\r\n const { state: buildingState } = React.useContext(BuildingsContext)\r\n const { building } = buildingState.buildings\r\n\r\n // Local state for dialog management\r\n const [createDialogOpen, setCreateDialogOpen] = React.useState(false)\r\n const [editingTopic, setEditingTopic] = React.useState<OBC.Topic | Partial<OBC.Topic> | null>(null)\r\n\r\n const handleAction = React.useCallback((action: TopicAction, id: string) => {\r\n const topic = bcfTopics.find(t => t.guid === id)\r\n if (!topic) {\r\n return\r\n }\r\n\r\n if (action === 'view') {\r\n bcfTopicsManager?.view(topic.guid)\r\n }\r\n else if (action === 'edit') {\r\n setEditingTopic(topic)\r\n setCreateDialogOpen(true)\r\n }\r\n else if (action === 'delete') {\r\n bcfTopicsManager?.remove(topic.guid)\r\n // Remove from BIM state\r\n bimDispatch({ \r\n type: 'REMOVE_BCF_TOPIC', \r\n payload: { bcfTopicId: id } \r\n })\r\n }\r\n }, [bcfTopics, bcfTopicsManager, bimDispatch])\r\n\r\n const handleAddTopic = React.useCallback(() => {\r\n setEditingTopic(null)\r\n setCreateDialogOpen(true)\r\n }, [])\r\n\r\n const handleCreateTopic = React.useCallback((formData: BCFTopicFormData) => {\r\n // Create BCF Topic using OBC.Topic interface\r\n const newTopic: OBC.Topic | Partial<OBC.Topic> = {\r\n guid: crypto.randomUUID(),\r\n title: formData.title,\r\n description: formData.description,\r\n status: formData.topicStatus,\r\n type: formData.topicType,\r\n priority: formData.priority,\r\n stage: formData.stage,\r\n assignedTo: formData.assignedTo || undefined,\r\n dueDate: formData.dueDate || undefined,\r\n creationDate: new Date(),\r\n creationAuthor: user?.email || 'anonymous@example.com',\r\n labels: new Set(formData.labels)\r\n }\r\n \r\n // Add to BCF manager\r\n const createdTopic = bcfTopicsManager?.create({\r\n ...newTopic,\r\n creationAuthor: user?.email || 'anonymous@example.com'\r\n })\r\n\r\n const topicToAdd = createdTopic || newTopic\r\n\r\n console.log('New topic to add:', topicToAdd)\r\n \r\n // Check if topic already exists in global state before adding\r\n const existingTopic = bcfTopics.find(existingTopic => existingTopic.guid === topicToAdd.guid)\r\n if (!existingTopic) {\r\n // Add to BIM state (use the created topic or fallback to newTopic)\r\n bimDispatch({ \r\n type: 'ADD_BCF_TOPIC', \r\n payload: { bcfTopic: topicToAdd } \r\n })\r\n } else {\r\n console.log(`BCF topic with ID ${topicToAdd.guid} already exists, skipping...`)\r\n }\r\n\r\n }, [bcfTopicsManager, bimDispatch, user?.email, bcfTopics])\r\n\r\n const handleEditTopic = React.useCallback((formData: BCFTopicFormData) => {\r\n if (!editingTopic) return\r\n\r\n try {\r\n // Update the existing topic with new data\r\n const updatedTopic: OBC.Topic | Partial<OBC.Topic> = {\r\n ...editingTopic,\r\n title: formData.title,\r\n description: formData.description,\r\n status: formData.topicStatus,\r\n type: formData.topicType,\r\n priority: formData.priority,\r\n stage: formData.stage,\r\n assignedTo: formData.assignedTo || undefined,\r\n dueDate: formData.dueDate || undefined,\r\n labels: new Set(formData.labels),\r\n modifiedDate: new Date(),\r\n modifiedAuthor: user?.email || 'anonymous@example.com'\r\n }\r\n\r\n // Update in BCF Manager first\r\n bcfTopicsManager?.edit(updatedTopic)\r\n\r\n // Update in BIM state\r\n bimDispatch({ \r\n type: 'EDIT_BCF_TOPIC', \r\n payload: { bcfTopic: updatedTopic } \r\n })\r\n\r\n // Clear editing state\r\n setEditingTopic(null)\r\n } catch (error) {\r\n console.error('Error editing topic:', error)\r\n }\r\n }, [editingTopic, bimDispatch, bcfTopicsManager, user?.email])\r\n\r\n const handleDialogSubmit = React.useCallback((formData: BCFTopicFormData) => {\r\n if (editingTopic) {\r\n handleEditTopic(formData)\r\n } else {\r\n handleCreateTopic(formData)\r\n }\r\n }, [editingTopic, handleEditTopic, handleCreateTopic])\r\n\r\n const handleDialogClose = React.useCallback((open: boolean) => {\r\n setCreateDialogOpen(open)\r\n if (!open) {\r\n setEditingTopic(null)\r\n }\r\n }, [])\r\n\r\n const handleExportBCF = React.useCallback(async () => {\r\n try {\r\n const buildingName = building?.buildingName || building?.buildingAddress || String(building.id) || 'Unknown Building'\r\n await bcfTopicsManager?.downloadBCF(buildingName)\r\n } catch (error) {\r\n console.error('Failed to export BCF:', error)\r\n }\r\n }, [bcfTopicsManager, building])\r\n\r\n const handleImportBCF = React.useCallback(async () => {\r\n try {\r\n const result = await bcfTopicsManager?.uploadBCF()\r\n const {topics, viewpoints} = result || {topics: [], viewpoints: []}\r\n topics.map((topic: OBC.Topic, index) => {\r\n // topic.viewpoints.add(viewpoints[index].guid) // I AM NOT GETTING THE VIEWPOINTS\r\n // console.log('Imported topic:', topic)\r\n bimDispatch({ \r\n type: 'ADD_BCF_TOPIC', \r\n payload: { bcfTopic: topic } \r\n })\r\n })\r\n } catch (error) {\r\n console.error('Failed to import BCF:', error)\r\n }\r\n }, [bcfTopicsManager, bimDispatch, bcfTopics])\r\n\r\n return (\r\n <>\r\n <CollapsibleSection\r\n title={t('topicsTitle')}\r\n icon={BcfIcon}\r\n className=\"overflow-y-auto\"\r\n itemCount={bcfTopics.length}\r\n onAddItem={handleAddTopic}\r\n addItemTitle={t('addTopicTitle')}\r\n >\r\n {/* BCF Operations */}\r\n <div className=\"flex gap-2 mb-3 mx-2 overflow-x-hidden \">\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={handleExportBCF}\r\n className=\"text-xs\"\r\n title={t('exportBCFTitle')}\r\n disabled={!ability.can('read', 'File')}\r\n >\r\n <LR.Download className=\"h-3 w-3 mr-1\" />\r\n {t('exportBCF')}\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={handleImportBCF}\r\n className=\"text-xs\"\r\n title={t('importBCFTitle')}\r\n disabled={!ability.can('create', 'File')}\r\n >\r\n <LR.Upload className=\"h-3 w-3 mr-1\" />\r\n {t('importBCF')}\r\n </Button>\r\n </div>\r\n\r\n <div className=\"space-y-2 mx-2 pr-2\">\r\n {bcfTopics.map((topic) => (\r\n <CollapsibleTopicItem\r\n key={topic.guid}\r\n topic={topic}\r\n onAction={handleAction}\r\n />\r\n ))}\r\n </div>\r\n </CollapsibleSection>\r\n\r\n <CreateTopicDialog\r\n open={createDialogOpen}\r\n onOpenChange={handleDialogClose}\r\n onSubmit={handleDialogSubmit}\r\n existingTopic={editingTopic}\r\n />\r\n </>\r\n )\r\n}"],"mappings":"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","names":["t","existingTopic"]}
1
+ {"version":3,"sources":["../../../../../../../../../../src/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from 'react'\r\nimport * as OBC from '@thatopen/components'\r\nimport { Button } from '../../../../../../../ui/Button'\r\nimport * as LR from 'lucide-react'\r\nimport { BimContext, BuildingsContext, usePermissions } from '../../../../../../../../store'\r\nimport { CollapsibleSection } from '../../../../../../../ui/CollapsibleSection'\r\nimport { useTranslations } from 'next-intl'\r\nimport { useSession } from 'next-auth/react'\r\nimport { BCFTopicsManager } from '../../../../BCFTopicsManager'\r\nimport { CreateTopicDialog, BCFTopicFormData } from './CreateTopicDialog'\r\nimport { CollapsibleTopicItem } from './CollapsibleTopicItem'\r\nimport { BcfIcon } from '../../../../../../../ui/Icons'\r\n\r\ntype TopicAction = 'view' | 'edit' | 'delete'\r\n\r\nexport function TopicsSection() {\r\n // Translation\r\n const t = useTranslations('TopicsSection')\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n // Get user session\r\n const { data: session } = useSession()\r\n const user = session?.user\r\n\r\n // Get BIM context\r\n const { state: bimState, dispatch: bimDispatch } = React.useContext(BimContext)\r\n const { bimComponents, bcfTopics } = bimState.bim\r\n // .get() throws if the component hasn't been registered yet (e.g. the BIM\r\n // engine is still initializing) — fall back to constructing it directly,\r\n // which self-registers (see BCFTopicsManager's constructor).\r\n let bcfTopicsManager: BCFTopicsManager | undefined\r\n if (bimComponents) {\r\n try {\r\n bcfTopicsManager = bimComponents.get(BCFTopicsManager)\r\n } catch {\r\n bcfTopicsManager = new BCFTopicsManager(bimComponents)\r\n }\r\n }\r\n\r\n // Get Buildings context\r\n const { state: buildingState } = React.useContext(BuildingsContext)\r\n const { building } = buildingState.buildings\r\n\r\n // Local state for dialog management\r\n const [createDialogOpen, setCreateDialogOpen] = React.useState(false)\r\n const [editingTopic, setEditingTopic] = React.useState<OBC.Topic | Partial<OBC.Topic> | null>(null)\r\n\r\n const handleAction = React.useCallback((action: TopicAction, id: string) => {\r\n const topic = bcfTopics.find(t => t.guid === id)\r\n if (!topic) {\r\n return\r\n }\r\n\r\n if (action === 'view') {\r\n bcfTopicsManager?.view(topic.guid)\r\n }\r\n else if (action === 'edit') {\r\n setEditingTopic(topic)\r\n setCreateDialogOpen(true)\r\n }\r\n else if (action === 'delete') {\r\n bcfTopicsManager?.remove(topic.guid)\r\n // Remove from BIM state\r\n bimDispatch({ \r\n type: 'REMOVE_BCF_TOPIC', \r\n payload: { bcfTopicId: id } \r\n })\r\n }\r\n }, [bcfTopics, bcfTopicsManager, bimDispatch])\r\n\r\n const handleAddTopic = React.useCallback(() => {\r\n setEditingTopic(null)\r\n setCreateDialogOpen(true)\r\n }, [])\r\n\r\n const handleCreateTopic = React.useCallback((formData: BCFTopicFormData) => {\r\n // Create BCF Topic using OBC.Topic interface\r\n const newTopic: OBC.Topic | Partial<OBC.Topic> = {\r\n guid: crypto.randomUUID(),\r\n title: formData.title,\r\n description: formData.description,\r\n status: formData.topicStatus,\r\n type: formData.topicType,\r\n priority: formData.priority,\r\n stage: formData.stage,\r\n assignedTo: formData.assignedTo || undefined,\r\n dueDate: formData.dueDate || undefined,\r\n creationDate: new Date(),\r\n creationAuthor: user?.email || 'anonymous@example.com',\r\n labels: new Set(formData.labels)\r\n }\r\n \r\n // Add to BCF manager\r\n const createdTopic = bcfTopicsManager?.create({\r\n ...newTopic,\r\n creationAuthor: user?.email || 'anonymous@example.com'\r\n })\r\n\r\n const topicToAdd = createdTopic || newTopic\r\n\r\n console.log('New topic to add:', topicToAdd)\r\n \r\n // Check if topic already exists in global state before adding\r\n const existingTopic = bcfTopics.find(existingTopic => existingTopic.guid === topicToAdd.guid)\r\n if (!existingTopic) {\r\n // Add to BIM state (use the created topic or fallback to newTopic)\r\n bimDispatch({ \r\n type: 'ADD_BCF_TOPIC', \r\n payload: { bcfTopic: topicToAdd } \r\n })\r\n } else {\r\n console.log(`BCF topic with ID ${topicToAdd.guid} already exists, skipping...`)\r\n }\r\n\r\n }, [bcfTopicsManager, bimDispatch, user?.email, bcfTopics])\r\n\r\n const handleEditTopic = React.useCallback((formData: BCFTopicFormData) => {\r\n if (!editingTopic) return\r\n\r\n try {\r\n // Update the existing topic with new data\r\n const updatedTopic: OBC.Topic | Partial<OBC.Topic> = {\r\n ...editingTopic,\r\n title: formData.title,\r\n description: formData.description,\r\n status: formData.topicStatus,\r\n type: formData.topicType,\r\n priority: formData.priority,\r\n stage: formData.stage,\r\n assignedTo: formData.assignedTo || undefined,\r\n dueDate: formData.dueDate || undefined,\r\n labels: new Set(formData.labels),\r\n modifiedDate: new Date(),\r\n modifiedAuthor: user?.email || 'anonymous@example.com'\r\n }\r\n\r\n // Update in BCF Manager first\r\n bcfTopicsManager?.edit(updatedTopic)\r\n\r\n // Update in BIM state\r\n bimDispatch({ \r\n type: 'EDIT_BCF_TOPIC', \r\n payload: { bcfTopic: updatedTopic } \r\n })\r\n\r\n // Clear editing state\r\n setEditingTopic(null)\r\n } catch (error) {\r\n console.error('Error editing topic:', error)\r\n }\r\n }, [editingTopic, bimDispatch, bcfTopicsManager, user?.email])\r\n\r\n const handleDialogSubmit = React.useCallback((formData: BCFTopicFormData) => {\r\n if (editingTopic) {\r\n handleEditTopic(formData)\r\n } else {\r\n handleCreateTopic(formData)\r\n }\r\n }, [editingTopic, handleEditTopic, handleCreateTopic])\r\n\r\n const handleDialogClose = React.useCallback((open: boolean) => {\r\n setCreateDialogOpen(open)\r\n if (!open) {\r\n setEditingTopic(null)\r\n }\r\n }, [])\r\n\r\n const handleExportBCF = React.useCallback(async () => {\r\n try {\r\n const buildingName = building?.buildingName || building?.buildingAddress || String(building.id) || 'Unknown Building'\r\n await bcfTopicsManager?.downloadBCF(buildingName)\r\n } catch (error) {\r\n console.error('Failed to export BCF:', error)\r\n }\r\n }, [bcfTopicsManager, building])\r\n\r\n const handleImportBCF = React.useCallback(async () => {\r\n try {\r\n const result = await bcfTopicsManager?.uploadBCF()\r\n const {topics, viewpoints} = result || {topics: [], viewpoints: []}\r\n topics.map((topic: OBC.Topic, index) => {\r\n // topic.viewpoints.add(viewpoints[index].guid) // I AM NOT GETTING THE VIEWPOINTS\r\n // console.log('Imported topic:', topic)\r\n bimDispatch({ \r\n type: 'ADD_BCF_TOPIC', \r\n payload: { bcfTopic: topic } \r\n })\r\n })\r\n } catch (error) {\r\n console.error('Failed to import BCF:', error)\r\n }\r\n }, [bcfTopicsManager, bimDispatch, bcfTopics])\r\n\r\n return (\r\n <>\r\n <CollapsibleSection\r\n title={t('topicsTitle')}\r\n icon={BcfIcon}\r\n className=\"overflow-y-auto\"\r\n itemCount={bcfTopics.length}\r\n onAddItem={handleAddTopic}\r\n addItemTitle={t('addTopicTitle')}\r\n >\r\n {/* BCF Operations */}\r\n <div className=\"flex gap-2 mb-3 mx-2 overflow-x-hidden \">\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={handleExportBCF}\r\n className=\"text-xs\"\r\n title={t('exportBCFTitle')}\r\n disabled={!ability.can('read', 'File')}\r\n >\r\n <LR.Download className=\"h-3 w-3 mr-1\" />\r\n {t('exportBCF')}\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={handleImportBCF}\r\n className=\"text-xs\"\r\n title={t('importBCFTitle')}\r\n disabled={!ability.can('create', 'File')}\r\n >\r\n <LR.Upload className=\"h-3 w-3 mr-1\" />\r\n {t('importBCF')}\r\n </Button>\r\n </div>\r\n\r\n <div className=\"space-y-2 mx-2 pr-2\">\r\n {bcfTopics.map((topic) => (\r\n <CollapsibleTopicItem\r\n key={topic.guid}\r\n topic={topic}\r\n onAction={handleAction}\r\n />\r\n ))}\r\n </div>\r\n </CollapsibleSection>\r\n\r\n <CreateTopicDialog\r\n open={createDialogOpen}\r\n onOpenChange={handleDialogClose}\r\n onSubmit={handleDialogSubmit}\r\n existingTopic={editingTopic}\r\n />\r\n </>\r\n )\r\n}"],"mappings":"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","names":["t","existingTopic"]}
@@ -1 +1 @@
1
- {"version":3,"file":"FilesSection.d.ts","sourceRoot":"","sources":["../../../../../../../../../../src/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAmB9B,OAAO,EAAE,MAAM,IAAI,KAAK,EAAE,MAAM,uCAAuC,CAAA;AAQvE,UAAU,iBAAiB;IACzB,KAAK,EAAE,KAAK,EAAE,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAUD,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,KAAU,EAAE,EAAE,iBAAiB,qBA+jBpE"}
1
+ {"version":3,"file":"FilesSection.d.ts","sourceRoot":"","sources":["../../../../../../../../../../src/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAmB9B,OAAO,EAAE,MAAM,IAAI,KAAK,EAAE,MAAM,uCAAuC,CAAA;AAQvE,UAAU,iBAAiB;IACzB,KAAK,EAAE,KAAK,EAAE,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAUD,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,KAAU,EAAE,EAAE,iBAAiB,qBAqkBpE"}
@@ -206,7 +206,13 @@ function FilesSection({ files, query = "" }) {
206
206
  }
207
207
  if (file.extension === "bcf") {
208
208
  menusDispatch({ type: "SET_SIDEBAR_SELECTED_TAB", payload: { selectedTab: "communication" } });
209
- const bcfManager = bimComponents == null ? void 0 : bimComponents.get(BCFTopicsManager);
209
+ if (!bimComponents) return;
210
+ let bcfManager;
211
+ try {
212
+ bcfManager = bimComponents.get(BCFTopicsManager);
213
+ } catch (e) {
214
+ bcfManager = new BCFTopicsManager(bimComponents);
215
+ }
210
216
  if (!bcfManager) return;
211
217
  try {
212
218
  const { topics } = await bcfManager.loadBCFFromUrl(file.url);