@collabdt/core 0.3.1 → 0.3.2
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.
- package/dist/core/components/authentication/ForgotPassword.d.ts.map +1 -1
- package/dist/core/components/authentication/ForgotPassword.js +0 -1
- package/dist/core/components/authentication/ForgotPassword.js.map +1 -1
- package/dist/core/components/ui/Comments/CollapsibleCommentItem.d.ts +12 -2
- package/dist/core/components/ui/Comments/CollapsibleCommentItem.d.ts.map +1 -1
- package/dist/core/components/ui/Comments/CollapsibleCommentItem.js +137 -139
- package/dist/core/components/ui/Comments/CollapsibleCommentItem.js.map +1 -1
- package/dist/core/components/ui/Comments/Comment.d.ts +18 -1
- package/dist/core/components/ui/Comments/Comment.d.ts.map +1 -1
- package/dist/core/components/ui/Comments/Comment.js +94 -23
- package/dist/core/components/ui/Comments/Comment.js.map +1 -1
- package/dist/core/components/ui/Comments/CommentActionButtons.d.ts +34 -0
- package/dist/core/components/ui/Comments/CommentActionButtons.d.ts.map +1 -0
- package/dist/core/components/ui/Comments/CommentActionButtons.js +106 -0
- package/dist/core/components/ui/Comments/CommentActionButtons.js.map +1 -0
- package/dist/core/components/ui/Comments/CommentInput.d.ts.map +1 -1
- package/dist/core/components/ui/Comments/CommentInput.js +5 -2
- package/dist/core/components/ui/Comments/CommentInput.js.map +1 -1
- package/dist/core/components/ui/Comments/CommentsSection.d.ts.map +1 -1
- package/dist/core/components/ui/Comments/CommentsSection.js +86 -42
- package/dist/core/components/ui/Comments/CommentsSection.js.map +1 -1
- package/dist/core/components/ui/Comments/commentUtils.d.ts.map +1 -1
- package/dist/core/components/ui/Comments/commentUtils.js +2 -1
- package/dist/core/components/ui/Comments/commentUtils.js.map +1 -1
- package/dist/core/components/ui/FilesManager/src/useFileUploadWithProgress.d.ts.map +1 -1
- package/dist/core/components/ui/FilesManager/src/useFileUploadWithProgress.js +0 -1
- package/dist/core/components/ui/FilesManager/src/useFileUploadWithProgress.js.map +1 -1
- package/dist/core/components/ui/InfoSidebar/Container.d.ts.map +1 -1
- package/dist/core/components/ui/InfoSidebar/Container.js +16 -12
- package/dist/core/components/ui/InfoSidebar/Container.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorInput.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorInput.js +0 -1
- package/dist/core/components/ui/Sensors/SensorInput.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorsSection.js +0 -2
- package/dist/core/components/ui/Sensors/SensorsSection.js.map +1 -1
- package/dist/core/components/ui/Sidebar.d.ts.map +1 -1
- package/dist/core/components/ui/Sidebar.js +27 -4
- package/dist/core/components/ui/Sidebar.js.map +1 -1
- package/dist/core/components/ui/ToolbarButton.d.ts.map +1 -1
- package/dist/core/components/ui/ToolbarButton.js +0 -1
- package/dist/core/components/ui/ToolbarButton.js.map +1 -1
- package/dist/core/components/viewers/Data/advancedFilter/FiltersDialog.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/advancedFilter/FiltersDialog.js +0 -2
- package/dist/core/components/viewers/Data/advancedFilter/FiltersDialog.js.map +1 -1
- package/dist/core/components/viewers/Data/details/EnergySourcesGrid.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/details/EnergySourcesGrid.js +0 -10
- package/dist/core/components/viewers/Data/details/EnergySourcesGrid.js.map +1 -1
- package/dist/core/components/viewers/Data/files/DatatableFileAdder.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/files/DatatableFileAdder.js +0 -1
- package/dist/core/components/viewers/Data/files/DatatableFileAdder.js.map +1 -1
- package/dist/core/components/viewers/Data/files/utils/fuzzySearch.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/files/utils/fuzzySearch.js +0 -1
- package/dist/core/components/viewers/Data/files/utils/fuzzySearch.js.map +1 -1
- package/dist/core/components/viewers/Data/userDetails/UserMoreOptions.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/userDetails/UserMoreOptions.js +0 -1
- package/dist/core/components/viewers/Data/userDetails/UserMoreOptions.js.map +1 -1
- package/dist/core/components/viewers/Data/utils/filterHelper.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/utils/filterHelper.js +0 -2
- package/dist/core/components/viewers/Data/utils/filterHelper.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.js +0 -3
- package/dist/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js +1 -7
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.js +1 -9
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/TabSelector.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/TabSelector.js +4 -3
- package/dist/core/components/viewers/bim/src/BimSidebar/src/TabSelector.js.map +1 -1
- package/dist/core/components/viewers/bim/src/ClippingPlane.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/ClippingPlane.js +0 -1
- package/dist/core/components/viewers/bim/src/ClippingPlane.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.d.ts +16 -10
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.js +26 -6
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.d.ts +23 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.d.ts.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.js +108 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.js.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.d.ts +44 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.d.ts.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.js +77 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.js.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.d.ts +24 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.d.ts.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.js +27 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.js.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/renderCSS2DMarkers.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/renderCSS2DMarkers.js +2 -2
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/renderCSS2DMarkers.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.js +242 -61
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/ClippingTool/ClippingTool.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/ClippingTool/ClippingTool.js +1 -5
- package/dist/core/components/viewers/bim/src/tools/ClippingTool/ClippingTool.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/ExplodeByLevelTool.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/ExplodeByLevelTool.js +0 -1
- package/dist/core/components/viewers/bim/src/tools/ExplodeByLevelTool.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/measureBimTool.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/measureBimTool.js +1 -2
- package/dist/core/components/viewers/bim/src/tools/measureBimTool.js.map +1 -1
- package/dist/core/components/viewers/map/MapViewer.d.ts.map +1 -1
- package/dist/core/components/viewers/map/MapViewer.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/arcGISDatasets.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/arcGISDatasets.js +11 -14
- package/dist/core/components/viewers/map/datasets/src/arcGISDatasets.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/ckanDatasets.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/ckanDatasets.js +2 -5
- package/dist/core/components/viewers/map/datasets/src/ckanDatasets.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/localDatasets.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/localDatasets.js +0 -3
- package/dist/core/components/viewers/map/datasets/src/localDatasets.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/opendatasoftDatasets.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/opendatasoftDatasets.js +0 -11
- package/dist/core/components/viewers/map/datasets/src/opendatasoftDatasets.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/DatabaseBuildingPopover/src/BuildingsTools.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/DatabaseBuildingPopover/src/BuildingsTools.js +0 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/DatabaseBuildingPopover/src/BuildingsTools.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.js +0 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/OpenDataFeaturePopover.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/OpenDataFeaturePopover.js +0 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/OpenDataFeaturePopover.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/CommentLayer/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/CommentLayer/index.js +174 -53
- package/dist/core/components/viewers/map/src/MapLayers/src/CommentLayer/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/components/MapFileManager.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/components/MapFileManager.js +2 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/components/MapFileManager.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js +0 -3
- package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/TabSelector.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/TabSelector.js +4 -3
- package/dist/core/components/viewers/map/src/MapSidebar/TabSelector.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.js +0 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.js +1 -5
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.js.map +1 -1
- package/dist/core/components/viewers/map/src/tools/AddTools/AddFile/utils/uploadToPresignedURLS.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/tools/AddTools/AddFile/utils/uploadToPresignedURLS.js +1 -3
- package/dist/core/components/viewers/map/src/tools/AddTools/AddFile/utils/uploadToPresignedURLS.js.map +1 -1
- package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.d.ts.map +1 -1
- package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.js +0 -1
- package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.js.map +1 -1
- package/dist/core/components/viewers/map/utils/flyToEach.d.ts.map +1 -1
- package/dist/core/components/viewers/map/utils/flyToEach.js +0 -1
- package/dist/core/components/viewers/map/utils/flyToEach.js.map +1 -1
- package/dist/core/components/viewers/map/utils/getOsmIdbyCoordinates.d.ts.map +1 -1
- package/dist/core/components/viewers/map/utils/getOsmIdbyCoordinates.js +0 -2
- package/dist/core/components/viewers/map/utils/getOsmIdbyCoordinates.js.map +1 -1
- package/dist/core/hooks/comments/comments.d.ts +11 -0
- package/dist/core/hooks/comments/comments.d.ts.map +1 -1
- package/dist/core/hooks/comments/comments.js +3 -1
- package/dist/core/hooks/comments/comments.js.map +1 -1
- package/dist/core/hooks/comments/createCommentHooks.d.ts +11 -0
- package/dist/core/hooks/comments/createCommentHooks.d.ts.map +1 -1
- package/dist/core/hooks/comments/createCommentHooks.js +30 -1
- package/dist/core/hooks/comments/createCommentHooks.js.map +1 -1
- package/dist/core/hooks/files/files.d.ts.map +1 -1
- package/dist/core/hooks/files/files.js +0 -1
- package/dist/core/hooks/files/files.js.map +1 -1
- package/dist/core/hooks/ui/useResizableSidebarWidth.d.ts +30 -0
- package/dist/core/hooks/ui/useResizableSidebarWidth.d.ts.map +1 -0
- package/dist/core/hooks/ui/useResizableSidebarWidth.js +75 -0
- package/dist/core/hooks/ui/useResizableSidebarWidth.js.map +1 -0
- package/dist/core/i18n/messages/en.json +5 -0
- package/dist/core/i18n/messages/es.json +6 -1
- package/dist/core/i18n/messages/fr.json +6 -1
- package/dist/core/store/Datasets/reducer.d.ts.map +1 -1
- package/dist/core/store/Datasets/reducer.js +0 -2
- package/dist/core/store/Datasets/reducer.js.map +1 -1
- package/dist/core/store/Files/reducer.js +0 -1
- package/dist/core/store/Files/reducer.js.map +1 -1
- package/dist/core/store/Menus/context.d.ts.map +1 -1
- package/dist/core/store/Menus/context.js +4 -1
- package/dist/core/store/Menus/context.js.map +1 -1
- package/dist/core/store/Menus/reducer.d.ts +20 -0
- package/dist/core/store/Menus/reducer.d.ts.map +1 -1
- package/dist/core/store/Menus/reducer.js +21 -3
- package/dist/core/store/Menus/reducer.js.map +1 -1
- package/dist/core/utils/markerUtils.d.ts +10 -0
- package/dist/core/utils/markerUtils.d.ts.map +1 -1
- package/dist/core/utils/markerUtils.js +9 -1
- package/dist/core/utils/markerUtils.js.map +1 -1
- package/dist/core/utils/memcache.d.ts.map +1 -1
- package/dist/core/utils/memcache.js +0 -7
- package/dist/core/utils/memcache.js.map +1 -1
- package/package.json +4 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ForgotPassword.d.ts","sourceRoot":"","sources":["../../../../src/core/components/authentication/ForgotPassword.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAU9B,wBAAgB,cAAc,
|
|
1
|
+
{"version":3,"file":"ForgotPassword.d.ts","sourceRoot":"","sources":["../../../../src/core/components/authentication/ForgotPassword.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAU9B,wBAAgB,cAAc,sBAiK7B"}
|
|
@@ -9,7 +9,6 @@ import { Input } from "../ui/Input";
|
|
|
9
9
|
import { AuthPage } from "./AuthPage";
|
|
10
10
|
import { PasswordError } from "./PasswordError";
|
|
11
11
|
function ForgotPassword() {
|
|
12
|
-
console.log("Executing ForgotPassword()");
|
|
13
12
|
const [password, setPassword] = React.useState("");
|
|
14
13
|
const [confirmPassword, setConfirmPassword] = React.useState("");
|
|
15
14
|
const [error, setError] = React.useState("");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/components/authentication/ForgotPassword.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 { Eye, EyeClosed } from 'lucide-react'\r\nimport Link from 'next/link'\r\nimport { useTranslations } from 'next-intl'\r\nimport * as React from 'react'\r\n\r\n// Direct file imports (not the ui barrel) — see Signin.tsx for rationale.\r\nimport { Button } from '../ui/Button'\r\nimport { Input } from '../ui/Input'\r\n\r\n\r\nimport { AuthPage } from './AuthPage'\r\nimport { PasswordError } from './PasswordError'\r\n\r\nexport function ForgotPassword() {\r\n console.log('Executing ForgotPassword()')\r\n const [password, setPassword] = React.useState('')\r\n const [confirmPassword, setConfirmPassword] = React.useState('')\r\n const [error, setError] = React.useState('')\r\n const [isLoading, setIsLoading] = React.useState(false)\r\n const t = useTranslations('forgotPassword')\r\n\r\n const [showPassword, setShowPassword] = React.useState(false)\r\n const [showConfirmPassword, setShowConfirmPassword] = React.useState(false)\r\n const [passwordErrors, setPasswordErrors] = React.useState<string[]>([])\r\n const [confirmPasswordError, setConfirmPasswordError] = React.useState('')\r\n const [hasAttemptedSubmit, setHasAttemptedSubmit] = React.useState(false)\r\n\r\n const validatePassword = (password: string): string[] => {\r\n const errors: string[] = []\r\n if (password.length < 12) errors.push('Password must be at least 12 characters')\r\n if (password.length > 65) errors.push('Password must be less than 65 characters')\r\n return errors\r\n }\r\n\r\n const handlePasswordChange = (e) => {\r\n const newPassword = e.target.value\r\n setPassword(newPassword)\r\n if (newPassword) setPasswordErrors(validatePassword(newPassword))\r\n else setPasswordErrors([])\r\n if (confirmPassword) {\r\n setConfirmPasswordError(newPassword === confirmPassword ? '' : 'Passwords do not match')\r\n }\r\n }\r\n\r\n const handleConfirmPasswordChange = (e) => {\r\n const newConfirmPassword = e.target.value\r\n setConfirmPassword(newConfirmPassword)\r\n if (newConfirmPassword && password) {\r\n setConfirmPasswordError(newConfirmPassword === password ? '' : 'Passwords do not match')\r\n } else {\r\n setConfirmPasswordError('')\r\n }\r\n }\r\n\r\n const handleSubmit = async (e) => {\r\n e.preventDefault()\r\n setHasAttemptedSubmit(true)\r\n const errors = validatePassword(password)\r\n setPasswordErrors(errors)\r\n if (password === confirmPassword) setConfirmPasswordError('')\r\n else setConfirmPasswordError('Passwords do not match')\r\n if (errors.length > 0 || password !== confirmPassword) return\r\n setError('')\r\n setIsLoading(true)\r\n // password reset logic here\r\n }\r\n\r\n return (\r\n <AuthPage>\r\n {/* Header */}\r\n <div className=\"space-y-2 text-left\">\r\n <h1\r\n className=\"font-display font-bold\"\r\n style={{\r\n fontSize: '1.75rem',\r\n lineHeight: '1.1',\r\n letterSpacing: '-0.02em',\r\n color: 'var(--hp-on-surface)',\r\n fontFamily: \"'Space Grotesk', sans-serif\",\r\n }}\r\n >\r\n {t('h1')}\r\n </h1>\r\n <p style={{ color: 'var(--hp-on-surface-variant)', fontSize: '0.9rem' }}>\r\n {t('subHeader')}\r\n </p>\r\n </div>\r\n\r\n {/* Form */}\r\n <form id=\"resetForm\" onSubmit={handleSubmit} className=\"space-y-4\">\r\n {/* Password */}\r\n <div className=\"space-y-2\">\r\n <div className=\"flex items-center gap-1\">\r\n <label htmlFor=\"password\" className=\"auth-label\">{t('inputLabel')}</label>\r\n {hasAttemptedSubmit && passwordErrors.length > 0 && (\r\n <div className=\"w-1.5 h-1.5 rounded-full\" style={{ background: '#ff6b6b' }} />\r\n )}\r\n </div>\r\n <div className=\"relative\">\r\n <Input\r\n id=\"password\"\r\n type={showPassword ? 'text' : 'password'}\r\n placeholder={t('placeholder1')}\r\n value={password}\r\n onChange={handlePasswordChange}\r\n required\r\n className={`auth-input pr-10 ${hasAttemptedSubmit && passwordErrors.length > 0 ? 'border-destructive' : ''}`}\r\n />\r\n <Button\r\n type=\"button\"\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n onClick={() => setShowPassword(!showPassword)}\r\n className=\"absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4\"\r\n style={{ color: 'var(--hp-on-surface-variant)' }}\r\n >\r\n {showPassword ? <EyeClosed className=\"h-4 w-4\" /> : <Eye className=\"h-4 w-4\" />}\r\n </Button>\r\n </div>\r\n {hasAttemptedSubmit && passwordErrors.map((err, i) => (\r\n <PasswordError key={i} message={err} />\r\n ))}\r\n {(!hasAttemptedSubmit || passwordErrors.length === 0) && (\r\n <p className=\"text-xs\" style={{ color: 'var(--hp-on-surface-variant)' }}>{t('lenError')}</p>\r\n )}\r\n </div>\r\n\r\n {/* Confirm Password */}\r\n <div className=\"space-y-2\">\r\n <div className=\"flex items-center gap-1\">\r\n <label htmlFor=\"confirmPassword\" className=\"auth-label\">{t('confirmInputLabel')}</label>\r\n {hasAttemptedSubmit && confirmPasswordError && (\r\n <div className=\"w-1.5 h-1.5 rounded-full\" style={{ background: '#ff6b6b' }} />\r\n )}\r\n </div>\r\n <div className=\"relative\">\r\n <Input\r\n id=\"confirmPassword\"\r\n type={showConfirmPassword ? 'text' : 'password'}\r\n placeholder={t('placeholder2')}\r\n value={confirmPassword}\r\n onChange={handleConfirmPasswordChange}\r\n required\r\n className={`auth-input pr-10 ${hasAttemptedSubmit && confirmPasswordError ? 'border-destructive' : ''}`}\r\n />\r\n <Button\r\n type=\"button\"\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n onClick={() => setShowConfirmPassword(!showConfirmPassword)}\r\n className=\"absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4\"\r\n style={{ color: 'var(--hp-on-surface-variant)' }}\r\n >\r\n {showConfirmPassword ? <EyeClosed className=\"h-4 w-4\" /> : <Eye className=\"h-4 w-4\" />}\r\n </Button>\r\n </div>\r\n {hasAttemptedSubmit && confirmPasswordError && (\r\n <PasswordError message={confirmPasswordError} />\r\n )}\r\n </div>\r\n </form>\r\n\r\n {/* Submit + link */}\r\n <div className=\"space-y-4 pt-2\">\r\n <Button type=\"submit\" form=\"resetForm\" className=\"auth-btn-primary w-full h-10\">\r\n {t('submit')}\r\n </Button>\r\n <p className=\"text-sm text-center\" style={{ color: 'var(--hp-on-surface-variant)' }}>\r\n <Link className=\"underline\" href=\"/cdt/auth/Signin\" style={{ color: 'var(--hp-primary-container)' }}>\r\n {t('linkSignin')}\r\n </Link>\r\n </p>\r\n </div>\r\n </AuthPage>\r\n )\r\n}\r\n"],"mappings":"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","names":["password"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/core/components/authentication/ForgotPassword.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 { Eye, EyeClosed } from 'lucide-react'\r\nimport Link from 'next/link'\r\nimport { useTranslations } from 'next-intl'\r\nimport * as React from 'react'\r\n\r\n// Direct file imports (not the ui barrel) — see Signin.tsx for rationale.\r\nimport { Button } from '../ui/Button'\r\nimport { Input } from '../ui/Input'\r\n\r\n\r\nimport { AuthPage } from './AuthPage'\r\nimport { PasswordError } from './PasswordError'\r\n\r\nexport function ForgotPassword() {\r\n const [password, setPassword] = React.useState('')\r\n const [confirmPassword, setConfirmPassword] = React.useState('')\r\n const [error, setError] = React.useState('')\r\n const [isLoading, setIsLoading] = React.useState(false)\r\n const t = useTranslations('forgotPassword')\r\n\r\n const [showPassword, setShowPassword] = React.useState(false)\r\n const [showConfirmPassword, setShowConfirmPassword] = React.useState(false)\r\n const [passwordErrors, setPasswordErrors] = React.useState<string[]>([])\r\n const [confirmPasswordError, setConfirmPasswordError] = React.useState('')\r\n const [hasAttemptedSubmit, setHasAttemptedSubmit] = React.useState(false)\r\n\r\n const validatePassword = (password: string): string[] => {\r\n const errors: string[] = []\r\n if (password.length < 12) errors.push('Password must be at least 12 characters')\r\n if (password.length > 65) errors.push('Password must be less than 65 characters')\r\n return errors\r\n }\r\n\r\n const handlePasswordChange = (e) => {\r\n const newPassword = e.target.value\r\n setPassword(newPassword)\r\n if (newPassword) setPasswordErrors(validatePassword(newPassword))\r\n else setPasswordErrors([])\r\n if (confirmPassword) {\r\n setConfirmPasswordError(newPassword === confirmPassword ? '' : 'Passwords do not match')\r\n }\r\n }\r\n\r\n const handleConfirmPasswordChange = (e) => {\r\n const newConfirmPassword = e.target.value\r\n setConfirmPassword(newConfirmPassword)\r\n if (newConfirmPassword && password) {\r\n setConfirmPasswordError(newConfirmPassword === password ? '' : 'Passwords do not match')\r\n } else {\r\n setConfirmPasswordError('')\r\n }\r\n }\r\n\r\n const handleSubmit = async (e) => {\r\n e.preventDefault()\r\n setHasAttemptedSubmit(true)\r\n const errors = validatePassword(password)\r\n setPasswordErrors(errors)\r\n if (password === confirmPassword) setConfirmPasswordError('')\r\n else setConfirmPasswordError('Passwords do not match')\r\n if (errors.length > 0 || password !== confirmPassword) return\r\n setError('')\r\n setIsLoading(true)\r\n // password reset logic here\r\n }\r\n\r\n return (\r\n <AuthPage>\r\n {/* Header */}\r\n <div className=\"space-y-2 text-left\">\r\n <h1\r\n className=\"font-display font-bold\"\r\n style={{\r\n fontSize: '1.75rem',\r\n lineHeight: '1.1',\r\n letterSpacing: '-0.02em',\r\n color: 'var(--hp-on-surface)',\r\n fontFamily: \"'Space Grotesk', sans-serif\",\r\n }}\r\n >\r\n {t('h1')}\r\n </h1>\r\n <p style={{ color: 'var(--hp-on-surface-variant)', fontSize: '0.9rem' }}>\r\n {t('subHeader')}\r\n </p>\r\n </div>\r\n\r\n {/* Form */}\r\n <form id=\"resetForm\" onSubmit={handleSubmit} className=\"space-y-4\">\r\n {/* Password */}\r\n <div className=\"space-y-2\">\r\n <div className=\"flex items-center gap-1\">\r\n <label htmlFor=\"password\" className=\"auth-label\">{t('inputLabel')}</label>\r\n {hasAttemptedSubmit && passwordErrors.length > 0 && (\r\n <div className=\"w-1.5 h-1.5 rounded-full\" style={{ background: '#ff6b6b' }} />\r\n )}\r\n </div>\r\n <div className=\"relative\">\r\n <Input\r\n id=\"password\"\r\n type={showPassword ? 'text' : 'password'}\r\n placeholder={t('placeholder1')}\r\n value={password}\r\n onChange={handlePasswordChange}\r\n required\r\n className={`auth-input pr-10 ${hasAttemptedSubmit && passwordErrors.length > 0 ? 'border-destructive' : ''}`}\r\n />\r\n <Button\r\n type=\"button\"\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n onClick={() => setShowPassword(!showPassword)}\r\n className=\"absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4\"\r\n style={{ color: 'var(--hp-on-surface-variant)' }}\r\n >\r\n {showPassword ? <EyeClosed className=\"h-4 w-4\" /> : <Eye className=\"h-4 w-4\" />}\r\n </Button>\r\n </div>\r\n {hasAttemptedSubmit && passwordErrors.map((err, i) => (\r\n <PasswordError key={i} message={err} />\r\n ))}\r\n {(!hasAttemptedSubmit || passwordErrors.length === 0) && (\r\n <p className=\"text-xs\" style={{ color: 'var(--hp-on-surface-variant)' }}>{t('lenError')}</p>\r\n )}\r\n </div>\r\n\r\n {/* Confirm Password */}\r\n <div className=\"space-y-2\">\r\n <div className=\"flex items-center gap-1\">\r\n <label htmlFor=\"confirmPassword\" className=\"auth-label\">{t('confirmInputLabel')}</label>\r\n {hasAttemptedSubmit && confirmPasswordError && (\r\n <div className=\"w-1.5 h-1.5 rounded-full\" style={{ background: '#ff6b6b' }} />\r\n )}\r\n </div>\r\n <div className=\"relative\">\r\n <Input\r\n id=\"confirmPassword\"\r\n type={showConfirmPassword ? 'text' : 'password'}\r\n placeholder={t('placeholder2')}\r\n value={confirmPassword}\r\n onChange={handleConfirmPasswordChange}\r\n required\r\n className={`auth-input pr-10 ${hasAttemptedSubmit && confirmPasswordError ? 'border-destructive' : ''}`}\r\n />\r\n <Button\r\n type=\"button\"\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n onClick={() => setShowConfirmPassword(!showConfirmPassword)}\r\n className=\"absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4\"\r\n style={{ color: 'var(--hp-on-surface-variant)' }}\r\n >\r\n {showConfirmPassword ? <EyeClosed className=\"h-4 w-4\" /> : <Eye className=\"h-4 w-4\" />}\r\n </Button>\r\n </div>\r\n {hasAttemptedSubmit && confirmPasswordError && (\r\n <PasswordError message={confirmPasswordError} />\r\n )}\r\n </div>\r\n </form>\r\n\r\n {/* Submit + link */}\r\n <div className=\"space-y-4 pt-2\">\r\n <Button type=\"submit\" form=\"resetForm\" className=\"auth-btn-primary w-full h-10\">\r\n {t('submit')}\r\n </Button>\r\n <p className=\"text-sm text-center\" style={{ color: 'var(--hp-on-surface-variant)' }}>\r\n <Link className=\"underline\" href=\"/cdt/auth/Signin\" style={{ color: 'var(--hp-primary-container)' }}>\r\n {t('linkSignin')}\r\n </Link>\r\n </p>\r\n </div>\r\n </AuthPage>\r\n )\r\n}\r\n"],"mappings":"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","names":["password"]}
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import type { Comment } from '../../../types/dbTypes';
|
|
3
3
|
type CommentAction = 'view' | 'edit' | 'delete' | 'reply';
|
|
4
|
+
/** Request from a 3D/map marker to auto-open a comment's editor or reply box. */
|
|
5
|
+
export interface PendingCommentAction {
|
|
6
|
+
commentId: number;
|
|
7
|
+
action: 'edit' | 'reply';
|
|
8
|
+
requestId: number;
|
|
9
|
+
}
|
|
4
10
|
interface CollapsibleCommentItemProps {
|
|
5
11
|
comment: Comment;
|
|
6
12
|
onAction?: (action: CommentAction, id: number) => void;
|
|
7
13
|
replies?: Comment[];
|
|
8
|
-
onReply?: (
|
|
14
|
+
onReply?: (comment: Comment, replyText: string) => void;
|
|
15
|
+
onEdit?: (id: number, text: string) => void;
|
|
9
16
|
onFileUpload?: (id: number, files: FileList) => void;
|
|
10
17
|
attachments?: Array<{
|
|
11
18
|
name: string;
|
|
@@ -14,9 +21,12 @@ interface CollapsibleCommentItemProps {
|
|
|
14
21
|
}>;
|
|
15
22
|
depth?: number;
|
|
16
23
|
isVisible?: boolean;
|
|
24
|
+
focused?: boolean;
|
|
25
|
+
onFocus?: () => void;
|
|
26
|
+
pendingAction?: PendingCommentAction;
|
|
17
27
|
onMouseEnter?: () => void;
|
|
18
28
|
onMouseLeave?: () => void;
|
|
19
29
|
}
|
|
20
|
-
export declare function CollapsibleCommentItem({ comment, onAction, replies, onReply,
|
|
30
|
+
export declare function CollapsibleCommentItem({ comment, onAction, replies, onReply, onEdit, onFileUpload, depth, isVisible, focused, onFocus, pendingAction, onMouseEnter, onMouseLeave, }: CollapsibleCommentItemProps): React.JSX.Element;
|
|
21
31
|
export {};
|
|
22
32
|
//# sourceMappingURL=CollapsibleCommentItem.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CollapsibleCommentItem.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/ui/Comments/CollapsibleCommentItem.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CollapsibleCommentItem.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/ui/Comments/CollapsibleCommentItem.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAe9B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAA;AAErD,KAAK,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAA;AAEzD,iFAAiF;AACjF,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,GAAG,OAAO,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,UAAU,2BAA2B;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACtD,OAAO,CAAC,EAAE,OAAO,EAAE,CAAA;IACnB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;IACvD,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3C,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAA;IACpD,WAAW,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAChE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,aAAa,CAAC,EAAE,oBAAoB,CAAA;IACpC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAA;CAC1B;AAED,wBAAgB,sBAAsB,CAAC,EACrC,OAAO,EACP,QAAQ,EACR,OAAY,EACZ,OAAO,EACP,MAAM,EACN,YAAY,EACZ,KAAS,EACT,SAAgB,EAChB,OAAe,EACf,OAAO,EACP,aAAa,EACb,YAAY,EACZ,YAAY,GACb,EAAE,2BAA2B,qBAsM7B"}
|
|
@@ -1,203 +1,201 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import { format } from "date-fns";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
3
|
import * as LR from "lucide-react";
|
|
5
4
|
import { useSession } from "next-auth/react";
|
|
6
5
|
import { useTranslations } from "next-intl";
|
|
7
6
|
import * as React from "react";
|
|
8
7
|
import { useUser } from "../../../hooks/users/users";
|
|
9
8
|
import { usePermissions } from "../../../store";
|
|
9
|
+
import { commentRingShadow } from "../../../utils/markerUtils";
|
|
10
|
+
import { formatTimestamp } from "../../../utils/timeUtils";
|
|
10
11
|
import { cn } from "../../../utils/utils";
|
|
11
12
|
import { Avatar } from "../Avatar";
|
|
12
13
|
import { Badge } from "../Badge";
|
|
13
14
|
import { Button } from "../Button";
|
|
14
15
|
import { Input } from "../Input";
|
|
15
16
|
import { UserAvatar } from "../UserAvatar";
|
|
17
|
+
import { CommentActionButtons } from "./CommentActionButtons";
|
|
16
18
|
function CollapsibleCommentItem({
|
|
17
19
|
comment,
|
|
18
20
|
onAction,
|
|
19
21
|
replies = [],
|
|
20
22
|
onReply,
|
|
23
|
+
onEdit,
|
|
21
24
|
onFileUpload,
|
|
22
|
-
attachments = [],
|
|
23
25
|
depth = 0,
|
|
24
26
|
isVisible = true,
|
|
27
|
+
focused = false,
|
|
28
|
+
onFocus,
|
|
29
|
+
pendingAction,
|
|
25
30
|
onMouseEnter,
|
|
26
31
|
onMouseLeave
|
|
27
32
|
}) {
|
|
28
33
|
var _a, _b;
|
|
29
34
|
const t = useTranslations("CommentsSection");
|
|
30
35
|
const { ability } = usePermissions();
|
|
36
|
+
const isReply = depth > 0;
|
|
31
37
|
const [isExpanded, setIsExpanded] = React.useState(false);
|
|
32
|
-
const [showReplyInput, setShowReplyInput] = React.useState(false);
|
|
33
38
|
const [replyText, setReplyText] = React.useState("");
|
|
34
|
-
const
|
|
39
|
+
const [isEditing, setIsEditing] = React.useState(false);
|
|
40
|
+
const [editText, setEditText] = React.useState(comment.text);
|
|
41
|
+
const containerRef = React.useRef(null);
|
|
42
|
+
const replyInputRef = React.useRef(null);
|
|
35
43
|
const prevVisibleRef = React.useRef(isVisible);
|
|
36
44
|
const user = (_a = useSession().data) == null ? void 0 : _a.user;
|
|
45
|
+
const isAuthor = (user == null ? void 0 : user.id) === String(comment.authorId);
|
|
46
|
+
const canReply = ability.can("create", "Comment");
|
|
47
|
+
const canEdit = ability.can("update", "Comment");
|
|
48
|
+
const canDelete = ability.can("delete", "Comment");
|
|
49
|
+
const { user: author } = useUser(String(comment.authorId));
|
|
50
|
+
const authorName = (_b = author == null ? void 0 : author.name) != null ? _b : "Unknown User";
|
|
37
51
|
React.useEffect(() => {
|
|
38
|
-
|
|
39
|
-
if (prevVisible && !isVisible) {
|
|
40
|
-
setIsExpanded(false);
|
|
41
|
-
}
|
|
52
|
+
if (prevVisibleRef.current && !isVisible) setIsExpanded(false);
|
|
42
53
|
prevVisibleRef.current = isVisible;
|
|
43
54
|
}, [isVisible]);
|
|
55
|
+
const handleEditStart = React.useCallback(() => {
|
|
56
|
+
setEditText(comment.text);
|
|
57
|
+
setIsEditing(true);
|
|
58
|
+
}, [comment.text]);
|
|
59
|
+
const openReply = React.useCallback(() => {
|
|
60
|
+
setIsExpanded(true);
|
|
61
|
+
requestAnimationFrame(() => {
|
|
62
|
+
var _a2;
|
|
63
|
+
return (_a2 = replyInputRef.current) == null ? void 0 : _a2.focus();
|
|
64
|
+
});
|
|
65
|
+
}, []);
|
|
66
|
+
React.useEffect(() => {
|
|
67
|
+
var _a2;
|
|
68
|
+
if (!pendingAction) return;
|
|
69
|
+
const matchesSelf = pendingAction.commentId === comment.id;
|
|
70
|
+
const matchesReply = replies.some((r) => r.id === pendingAction.commentId);
|
|
71
|
+
if (matchesSelf) {
|
|
72
|
+
if (pendingAction.action === "edit") handleEditStart();
|
|
73
|
+
else openReply();
|
|
74
|
+
(_a2 = containerRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
75
|
+
}
|
|
76
|
+
if (matchesReply) setIsExpanded(true);
|
|
77
|
+
}, [pendingAction == null ? void 0 : pendingAction.requestId]);
|
|
44
78
|
const handleReplySubmit = () => {
|
|
45
79
|
if (replyText.trim() && onReply) {
|
|
46
|
-
onReply(comment
|
|
80
|
+
onReply(comment, replyText);
|
|
47
81
|
setReplyText("");
|
|
48
|
-
setShowReplyInput(false);
|
|
49
82
|
}
|
|
50
83
|
};
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
84
|
+
const handleEditSubmit = () => {
|
|
85
|
+
const next = editText.trim();
|
|
86
|
+
if (next && next !== comment.text && onEdit) onEdit(comment.id, next);
|
|
87
|
+
setIsEditing(false);
|
|
56
88
|
};
|
|
57
|
-
const indentClass = depth > 0 ? `ml-${Math.min(depth * 4, 12)}` : "";
|
|
58
|
-
const { user: author } = useUser(String(comment.authorId));
|
|
59
|
-
const authorName = (_b = author == null ? void 0 : author.name) != null ? _b : "Unknown User";
|
|
60
89
|
return /* @__PURE__ */ jsxs(
|
|
61
90
|
"div",
|
|
62
91
|
{
|
|
92
|
+
ref: containerRef,
|
|
63
93
|
className: cn(
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
94
|
+
"transition-colors",
|
|
95
|
+
!isReply && "rounded-md border",
|
|
96
|
+
isReply && "pt-2"
|
|
67
97
|
),
|
|
98
|
+
style: focused ? { boxShadow: commentRingShadow({ focused: true }), borderColor: "transparent" } : void 0,
|
|
68
99
|
onMouseEnter,
|
|
69
100
|
onMouseLeave,
|
|
101
|
+
onDoubleClick: (e) => {
|
|
102
|
+
e.stopPropagation();
|
|
103
|
+
onFocus == null ? void 0 : onFocus();
|
|
104
|
+
},
|
|
105
|
+
title: onFocus ? t("doubleClickZoom") : void 0,
|
|
70
106
|
children: [
|
|
71
|
-
/* @__PURE__ */ jsxs("div", { className: "flex
|
|
72
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-
|
|
107
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1.5 p-3", !isReply && "hover:bg-accent/50 transition-colors rounded-md", onFocus && "cursor-pointer"), children: [
|
|
108
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
|
|
109
|
+
/* @__PURE__ */ jsx(Avatar, { className: cn("mt-0.5 rounded-full overflow-hidden shrink-0", isReply ? "h-6 w-6" : "h-8 w-8"), children: /* @__PURE__ */ jsx(UserAvatar, { imageFileId: author == null ? void 0 : author.imageFileId, name: authorName }) }),
|
|
110
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
111
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground truncate", children: authorName }),
|
|
112
|
+
comment.updatedAt !== comment.createdAt && /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "text-xs", children: t("edited") }),
|
|
113
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground ml-auto whitespace-nowrap", children: formatTimestamp(comment.createdAt) })
|
|
114
|
+
] }) }),
|
|
115
|
+
onAction && /* @__PURE__ */ jsx(
|
|
116
|
+
CommentActionButtons,
|
|
117
|
+
{
|
|
118
|
+
onReply: !isReply && onReply ? openReply : void 0,
|
|
119
|
+
onEdit: isAuthor ? handleEditStart : void 0,
|
|
120
|
+
onDelete: isAuthor ? () => onAction("delete", comment.id) : void 0,
|
|
121
|
+
canReply,
|
|
122
|
+
canEdit,
|
|
123
|
+
canDelete,
|
|
124
|
+
labels: { reply: t("replyToComment"), edit: t("editComment"), delete: t("deleteComment") }
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
] }),
|
|
128
|
+
isEditing ? /* @__PURE__ */ jsxs("div", { className: "flex gap-2", onDoubleClick: (e) => e.stopPropagation(), children: [
|
|
73
129
|
/* @__PURE__ */ jsx(
|
|
74
|
-
|
|
130
|
+
Input,
|
|
75
131
|
{
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
className:
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
"h-4 w-4 transition-transform",
|
|
85
|
-
isExpanded && "rotate-90"
|
|
86
|
-
)
|
|
132
|
+
value: editText,
|
|
133
|
+
onChange: (e) => setEditText(e.target.value),
|
|
134
|
+
className: "flex-1 h-8",
|
|
135
|
+
autoFocus: true,
|
|
136
|
+
onKeyDown: (e) => {
|
|
137
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
138
|
+
e.preventDefault();
|
|
139
|
+
handleEditSubmit();
|
|
87
140
|
}
|
|
88
|
-
|
|
141
|
+
if (e.key === "Escape") setIsEditing(false);
|
|
142
|
+
},
|
|
143
|
+
disabled: !canEdit
|
|
89
144
|
}
|
|
90
145
|
),
|
|
91
|
-
/* @__PURE__ */ jsx(
|
|
92
|
-
/* @__PURE__ */
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
146
|
+
/* @__PURE__ */ jsx(Button, { size: "icon", className: "h-8 w-8 p-0", onClick: handleEditSubmit, disabled: !editText.trim() || !canEdit, children: /* @__PURE__ */ jsx(LR.Check, { className: "h-4 w-4" }) }),
|
|
147
|
+
/* @__PURE__ */ jsx(Button, { size: "icon", variant: "ghost", className: "h-8 w-8 p-0", onClick: () => setIsEditing(false), children: /* @__PURE__ */ jsx(LR.X, { className: "h-4 w-4" }) })
|
|
148
|
+
] }) : /* @__PURE__ */ jsx("p", { className: "text-sm text-foreground whitespace-pre-wrap break-words", children: comment.text }),
|
|
149
|
+
!isReply && replies.length > 0 && /* @__PURE__ */ jsxs(
|
|
150
|
+
"button",
|
|
151
|
+
{
|
|
152
|
+
type: "button",
|
|
153
|
+
className: "flex items-center gap-1 w-fit text-xs text-muted-foreground hover:text-foreground transition-colors",
|
|
154
|
+
onClick: () => setIsExpanded((v) => !v),
|
|
155
|
+
children: [
|
|
156
|
+
/* @__PURE__ */ jsx(LR.ChevronRight, { className: cn("h-3.5 w-3.5 transition-transform", isExpanded && "rotate-90") }),
|
|
99
157
|
replies.length,
|
|
100
158
|
" ",
|
|
101
159
|
replies.length === 1 ? t("reply") : t("replies")
|
|
102
|
-
]
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
160
|
+
]
|
|
161
|
+
}
|
|
162
|
+
)
|
|
163
|
+
] }),
|
|
164
|
+
!isReply && isExpanded && /* @__PURE__ */ jsxs("div", { className: "ml-5 border-l border-border pl-1 pr-2 pb-2", children: [
|
|
165
|
+
replies.map((reply) => /* @__PURE__ */ jsx(
|
|
166
|
+
CollapsibleCommentItem,
|
|
167
|
+
{
|
|
168
|
+
comment: reply,
|
|
169
|
+
onAction,
|
|
170
|
+
onReply,
|
|
171
|
+
onEdit,
|
|
172
|
+
onFileUpload,
|
|
173
|
+
depth: depth + 1,
|
|
174
|
+
pendingAction
|
|
175
|
+
},
|
|
176
|
+
reply.id
|
|
177
|
+
)),
|
|
178
|
+
onReply && /* @__PURE__ */ jsxs("div", { className: "flex gap-2 px-1 pt-2", onDoubleClick: (e) => e.stopPropagation(), children: [
|
|
106
179
|
/* @__PURE__ */ jsx(
|
|
107
|
-
|
|
180
|
+
Input,
|
|
108
181
|
{
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
182
|
+
ref: replyInputRef,
|
|
183
|
+
value: replyText,
|
|
184
|
+
onChange: (e) => setReplyText(e.target.value),
|
|
185
|
+
placeholder: t("writeReply"),
|
|
186
|
+
className: "flex-1 h-8",
|
|
187
|
+
onKeyDown: (e) => {
|
|
188
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
189
|
+
e.preventDefault();
|
|
190
|
+
handleReplySubmit();
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
disabled: !canReply
|
|
116
194
|
}
|
|
117
195
|
),
|
|
118
|
-
(
|
|
119
|
-
/* @__PURE__ */ jsx(
|
|
120
|
-
Button,
|
|
121
|
-
{
|
|
122
|
-
variant: "ghost",
|
|
123
|
-
size: "icon",
|
|
124
|
-
className: "h-8 w-8 p-0",
|
|
125
|
-
onClick: () => onAction("edit", comment.id),
|
|
126
|
-
title: t("editComment"),
|
|
127
|
-
disabled: !ability.can("update", "Comment"),
|
|
128
|
-
children: /* @__PURE__ */ jsx(LR.Pencil, { className: "h-4 w-4" })
|
|
129
|
-
}
|
|
130
|
-
),
|
|
131
|
-
/* @__PURE__ */ jsx(
|
|
132
|
-
Button,
|
|
133
|
-
{
|
|
134
|
-
variant: "ghost",
|
|
135
|
-
size: "icon",
|
|
136
|
-
className: "h-8 w-8 p-0",
|
|
137
|
-
onClick: () => onAction("delete", comment.id),
|
|
138
|
-
title: t("deleteComment"),
|
|
139
|
-
disabled: !ability.can("delete", "Comment"),
|
|
140
|
-
children: /* @__PURE__ */ jsx(LR.Trash2, { className: "h-4 w-4" })
|
|
141
|
-
}
|
|
142
|
-
)
|
|
143
|
-
] })
|
|
196
|
+
/* @__PURE__ */ jsx(Button, { size: "icon", className: "h-8 w-8 p-0", onClick: handleReplySubmit, disabled: !replyText.trim() || !canReply, children: /* @__PURE__ */ jsx(LR.Send, { className: "h-4 w-4" }) })
|
|
144
197
|
] })
|
|
145
|
-
] })
|
|
146
|
-
isExpanded && /* @__PURE__ */ jsx("div", { className: "border-t bg-muted/30", children: /* @__PURE__ */ jsxs("div", { className: "p-4 space-y-4", children: [
|
|
147
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: format(new Date(comment.createdAt), "PPp") }),
|
|
148
|
-
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("p", { className: "text-sm text-foreground whitespace-pre-wrap", children: comment.text }) })
|
|
149
|
-
] }) }),
|
|
150
|
-
showReplyInput && onReply && /* @__PURE__ */ jsx("div", { className: "border-t p-3 bg-muted/20", children: /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
151
|
-
/* @__PURE__ */ jsx(
|
|
152
|
-
Input,
|
|
153
|
-
{
|
|
154
|
-
value: replyText,
|
|
155
|
-
onChange: (e) => setReplyText(e.target.value),
|
|
156
|
-
placeholder: t("writeReply"),
|
|
157
|
-
className: "flex-1",
|
|
158
|
-
onKeyDown: (e) => {
|
|
159
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
160
|
-
e.preventDefault();
|
|
161
|
-
handleReplySubmit();
|
|
162
|
-
}
|
|
163
|
-
},
|
|
164
|
-
disabled: !ability.can("create", "Comment")
|
|
165
|
-
}
|
|
166
|
-
),
|
|
167
|
-
/* @__PURE__ */ jsx(
|
|
168
|
-
Button,
|
|
169
|
-
{
|
|
170
|
-
size: "sm",
|
|
171
|
-
onClick: handleReplySubmit,
|
|
172
|
-
disabled: !replyText.trim() || !ability.can("create", "Comment"),
|
|
173
|
-
children: /* @__PURE__ */ jsx(LR.Send, { className: "h-4 w-4" })
|
|
174
|
-
}
|
|
175
|
-
),
|
|
176
|
-
/* @__PURE__ */ jsx(
|
|
177
|
-
Button,
|
|
178
|
-
{
|
|
179
|
-
size: "sm",
|
|
180
|
-
variant: "ghost",
|
|
181
|
-
onClick: () => {
|
|
182
|
-
setShowReplyInput(false);
|
|
183
|
-
setReplyText("");
|
|
184
|
-
},
|
|
185
|
-
disabled: !ability.can("create", "Comment"),
|
|
186
|
-
children: /* @__PURE__ */ jsx(LR.X, { className: "h-4 w-4" })
|
|
187
|
-
}
|
|
188
|
-
)
|
|
189
|
-
] }) }),
|
|
190
|
-
isExpanded && replies.length > 0 && /* @__PURE__ */ jsx("div", { className: "border-t", children: replies.map((reply) => /* @__PURE__ */ jsx(
|
|
191
|
-
CollapsibleCommentItem,
|
|
192
|
-
{
|
|
193
|
-
comment: reply,
|
|
194
|
-
onAction,
|
|
195
|
-
onReply,
|
|
196
|
-
onFileUpload,
|
|
197
|
-
depth: depth + 1
|
|
198
|
-
},
|
|
199
|
-
reply.id
|
|
200
|
-
)) })
|
|
198
|
+
] })
|
|
201
199
|
]
|
|
202
200
|
}
|
|
203
201
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/core/components/ui/Comments/CollapsibleCommentItem.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 { format } from 'date-fns'\r\nimport * as LR from 'lucide-react'\r\nimport { useSession } from 'next-auth/react'\r\nimport { useTranslations } from 'next-intl'\r\nimport * as React from 'react'\r\n\r\nimport { useUser } from '../../../hooks/users/users'\r\nimport { usePermissions } from '../../../store'\r\nimport { cn } from '../../../utils/utils'\r\nimport { Avatar } from '../Avatar'\r\nimport { Badge } from '../Badge'\r\nimport { Button } from '../Button'\r\nimport { Input } from '../Input'\r\nimport { UserAvatar } from '../UserAvatar'\r\n\r\nimport type { Comment } from '../../../types/dbTypes'\r\n\r\n\r\n\r\ntype CommentAction = 'view' | 'edit' | 'delete' | 'reply'\r\n\r\ninterface CollapsibleCommentItemProps {\r\n comment: Comment\r\n onAction?: (action: CommentAction, id: number) => void\r\n replies?: Comment[]\r\n onReply?: (id: number, replyText: string | number) => void\r\n onFileUpload?: (id: number, files: FileList) => void\r\n attachments?: Array<{ name: string; url: string; size: number }>\r\n depth?: number\r\n isVisible?: boolean\r\n onMouseEnter?: () => void\r\n onMouseLeave?: () => void\r\n}\r\n\r\nexport function CollapsibleCommentItem({\r\n comment,\r\n onAction,\r\n replies = [],\r\n onReply,\r\n onFileUpload,\r\n attachments = [],\r\n depth = 0,\r\n isVisible = true,\r\n onMouseEnter,\r\n onMouseLeave\r\n}: CollapsibleCommentItemProps) {\r\n const t = useTranslations('CommentsSection')\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n const [isExpanded, setIsExpanded] = React.useState(false)\r\n const [showReplyInput, setShowReplyInput] = React.useState(false)\r\n const [replyText, setReplyText] = React.useState('')\r\n const fileInputRef = React.useRef<HTMLInputElement>(null)\r\n const prevVisibleRef = React.useRef(isVisible)\r\n\r\n const user = useSession().data?.user\r\n\r\n // Auto-collapse when visibility turns off\r\n React.useEffect(() => {\r\n const prevVisible = prevVisibleRef.current\r\n\r\n if (prevVisible && !isVisible) {\r\n // Just turned invisible - collapse\r\n setIsExpanded(false)\r\n }\r\n\r\n prevVisibleRef.current = isVisible\r\n }, [isVisible])\r\n\r\n const handleReplySubmit = () => {\r\n if (replyText.trim() && onReply) {\r\n onReply(comment.id, replyText)\r\n setReplyText('')\r\n setShowReplyInput(false)\r\n }\r\n }\r\n\r\n const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n if (event.target.files && event.target.files.length > 0 && onFileUpload) {\r\n onFileUpload(comment.id, event.target.files)\r\n event.target.value = ''\r\n }\r\n }\r\n\r\n const indentClass = depth > 0 ? `ml-${Math.min(depth * 4, 12)}` : ''\r\n\r\n const { user: author } = useUser(String(comment.authorId))\r\n const authorName: string | undefined = author?.name ?? 'Unknown User'\r\n\r\n return (\r\n <div\r\n className={cn(\r\n \"border rounded-md overflow-hidden transition-opacity\",\r\n indentClass,\r\n // !isVisible && \"opacity-50\"\r\n )}\r\n onMouseEnter={onMouseEnter}\r\n onMouseLeave={onMouseLeave}\r\n >\r\n {/* Comment Header */}\r\n <div className=\"flex items-start justify-between p-3 hover:bg-accent/50 transition-colors\">\r\n <div className=\"flex items-start gap-3 flex-1 min-w-0\">\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n className={cn(\"h-6 w-6 p-0 mt-1\")}\r\n onClick={() => setIsExpanded(!isExpanded)}\r\n >\r\n <LR.ChevronRight\r\n className={cn(\r\n \"h-4 w-4 transition-transform\",\r\n isExpanded && \"rotate-90\"\r\n )}\r\n />\r\n </Button>\r\n\r\n <Avatar className={cn(\"h-8 w-8 mt-1 rounded-full overflow-hidden\")}>\r\n <UserAvatar imageFileId={author?.imageFileId} name={authorName} />\r\n </Avatar>\r\n\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className={cn(\"text-sm font-medium text-foreground \")}>\r\n {authorName}\r\n </span>\r\n {comment.updatedAt !== comment.createdAt && (\r\n <Badge variant=\"outline\" className=\"text-xs\">\r\n {t('edited')}\r\n </Badge>\r\n )}\r\n </div>\r\n <p className={cn(\"text-sm mt-1 line-clamp-1 text-foreground\")}>\r\n {comment.text}\r\n </p>\r\n {replies.length > 0 && !isExpanded && (\r\n <span className=\"text-xs text-muted-foreground mt-1\">\r\n {replies.length} {replies.length === 1 ? t('reply') : t('replies')}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Action Buttons */}\r\n {onAction && (\r\n <div className={cn(\"flex items-center gap-0 flex-shrink-0\")}>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"h-8 w-8 p-0\"\r\n onClick={() => setShowReplyInput(!showReplyInput)}\r\n title={t('replyToComment')}\r\n disabled={!ability.can('create', 'Comment')}\r\n >\r\n <LR.Reply className=\"h-4 w-4\" />\r\n </Button>\r\n {user?.id === String(comment.authorId) && (\r\n <>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"h-8 w-8 p-0\"\r\n onClick={() => onAction('edit', comment.id)}\r\n title={t('editComment')}\r\n disabled={!ability.can('update', 'Comment')}\r\n >\r\n <LR.Pencil className=\"h-4 w-4\" />\r\n </Button>\r\n {/* TODO: Need 2-step confirmation dialog for DELETE COMMENT */}\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"h-8 w-8 p-0\"\r\n onClick={() => onAction('delete', comment.id)}\r\n title={t('deleteComment')}\r\n disabled={!ability.can('delete', 'Comment')}\r\n\r\n >\r\n <LR.Trash2 className=\"h-4 w-4\" />\r\n </Button>\r\n </>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Expanded Content */ }\r\n {\r\n isExpanded && (\r\n <div className=\"border-t bg-muted/30\">\r\n <div className=\"p-4 space-y-4\">\r\n {/* Full Comment Text */}\r\n <span className=\"text-xs text-muted-foreground\">\r\n {format(new Date(comment.createdAt), 'PPp')}\r\n </span>\r\n <div>\r\n <p className=\"text-sm text-foreground whitespace-pre-wrap\">\r\n {comment.text}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n }\r\n\r\n {/* Reply Input */ }\r\n {\r\n showReplyInput && onReply && (\r\n <div className=\"border-t p-3 bg-muted/20\">\r\n <div className=\"flex gap-2\">\r\n <Input\r\n value={replyText}\r\n onChange={(e) => setReplyText(e.target.value)}\r\n placeholder={t('writeReply')}\r\n className=\"flex-1\"\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault()\r\n handleReplySubmit()\r\n }\r\n }}\r\n disabled={!ability.can('create', 'Comment')}\r\n />\r\n <Button\r\n size=\"sm\"\r\n onClick={handleReplySubmit}\r\n disabled={!replyText.trim() || !ability.can('create', 'Comment')}\r\n >\r\n <LR.Send className=\"h-4 w-4\" />\r\n </Button>\r\n <Button\r\n size=\"sm\"\r\n variant=\"ghost\"\r\n onClick={() => {\r\n setShowReplyInput(false)\r\n setReplyText('')\r\n }}\r\n disabled={!ability.can('create', 'Comment')}\r\n >\r\n <LR.X className=\"h-4 w-4\" />\r\n </Button>\r\n </div>\r\n </div>\r\n )\r\n }\r\n\r\n {/* Nested Replies */ }\r\n {\r\n isExpanded && replies.length > 0 && (\r\n <div className=\"border-t\">\r\n {replies.map((reply) => (\r\n <CollapsibleCommentItem\r\n key={reply.id}\r\n comment={reply}\r\n onAction={onAction}\r\n onReply={onReply}\r\n onFileUpload={onFileUpload}\r\n depth={depth + 1}\r\n />\r\n ))}\r\n </div>\r\n )\r\n }\r\n </div >\r\n )\r\n}\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/core/components/ui/Comments/CollapsibleCommentItem.tsx"],"sourcesContent":["'use client'\n\n// SPDX-License-Identifier: AGPL-3.0-or-later\n// Copyright (C) 2025 Collab Digital Twins\n\nimport * as LR from 'lucide-react'\nimport { useSession } from 'next-auth/react'\nimport { useTranslations } from 'next-intl'\nimport * as React from 'react'\n\nimport { useUser } from '../../../hooks/users/users'\nimport { usePermissions } from '../../../store'\nimport { commentRingShadow } from '../../../utils/markerUtils'\nimport { formatTimestamp } from '../../../utils/timeUtils'\nimport { cn } from '../../../utils/utils'\nimport { Avatar } from '../Avatar'\nimport { Badge } from '../Badge'\nimport { Button } from '../Button'\nimport { Input } from '../Input'\nimport { UserAvatar } from '../UserAvatar'\n\nimport { CommentActionButtons } from './CommentActionButtons'\n\nimport type { Comment } from '../../../types/dbTypes'\n\ntype CommentAction = 'view' | 'edit' | 'delete' | 'reply'\n\n/** Request from a 3D/map marker to auto-open a comment's editor or reply box. */\nexport interface PendingCommentAction {\n commentId: number\n action: 'edit' | 'reply'\n requestId: number\n}\n\ninterface CollapsibleCommentItemProps {\n comment: Comment\n onAction?: (action: CommentAction, id: number) => void\n replies?: Comment[]\n onReply?: (comment: Comment, replyText: string) => void\n onEdit?: (id: number, text: string) => void\n onFileUpload?: (id: number, files: FileList) => void\n attachments?: Array<{ name: string; url: string; size: number }>\n depth?: number\n isVisible?: boolean\n focused?: boolean\n onFocus?: () => void\n pendingAction?: PendingCommentAction\n onMouseEnter?: () => void\n onMouseLeave?: () => void\n}\n\nexport function CollapsibleCommentItem({\n comment,\n onAction,\n replies = [],\n onReply,\n onEdit,\n onFileUpload,\n depth = 0,\n isVisible = true,\n focused = false,\n onFocus,\n pendingAction,\n onMouseEnter,\n onMouseLeave,\n}: CollapsibleCommentItemProps) {\n const t = useTranslations('CommentsSection')\n const { ability } = usePermissions()\n\n const isReply = depth > 0\n const [isExpanded, setIsExpanded] = React.useState(false)\n const [replyText, setReplyText] = React.useState('')\n const [isEditing, setIsEditing] = React.useState(false)\n const [editText, setEditText] = React.useState(comment.text)\n const containerRef = React.useRef<HTMLDivElement>(null)\n const replyInputRef = React.useRef<HTMLInputElement>(null)\n const prevVisibleRef = React.useRef(isVisible)\n\n const user = useSession().data?.user\n const isAuthor = user?.id === String(comment.authorId)\n const canReply = ability.can('create', 'Comment')\n const canEdit = ability.can('update', 'Comment')\n const canDelete = ability.can('delete', 'Comment')\n\n const { user: author } = useUser(String(comment.authorId))\n const authorName: string = author?.name ?? 'Unknown User'\n\n // Auto-collapse when visibility turns off\n React.useEffect(() => {\n if (prevVisibleRef.current && !isVisible) setIsExpanded(false)\n prevVisibleRef.current = isVisible\n }, [isVisible])\n\n const handleEditStart = React.useCallback(() => {\n setEditText(comment.text)\n setIsEditing(true)\n }, [comment.text])\n\n // Reply happens in one place: the input at the end of the thread. The reply button just\n // expands the thread and focuses that input, so users never hunt for a per-comment control.\n const openReply = React.useCallback(() => {\n setIsExpanded(true)\n requestAnimationFrame(() => replyInputRef.current?.focus())\n }, [])\n\n // Open the editor / reply box when a marker requests it, then scroll into view.\n React.useEffect(() => {\n if (!pendingAction) return\n const matchesSelf = pendingAction.commentId === comment.id\n const matchesReply = replies.some((r) => r.id === pendingAction.commentId)\n if (matchesSelf) {\n if (pendingAction.action === 'edit') handleEditStart()\n else openReply()\n containerRef.current?.scrollIntoView({ behavior: 'smooth', block: 'nearest' })\n }\n if (matchesReply) setIsExpanded(true)\n }, [pendingAction?.requestId])\n\n const handleReplySubmit = () => {\n if (replyText.trim() && onReply) {\n onReply(comment, replyText)\n setReplyText('')\n }\n }\n\n const handleEditSubmit = () => {\n const next = editText.trim()\n if (next && next !== comment.text && onEdit) onEdit(comment.id, next)\n setIsEditing(false)\n }\n\n return (\n <div\n ref={containerRef}\n className={cn(\n 'transition-colors',\n !isReply && 'rounded-md border',\n isReply && 'pt-2'\n )}\n style={focused ? { boxShadow: commentRingShadow({ focused: true }), borderColor: 'transparent' } : undefined}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n onDoubleClick={(e) => {\n e.stopPropagation()\n onFocus?.()\n }}\n title={onFocus ? t('doubleClickZoom') : undefined}\n >\n <div className={cn('flex flex-col gap-1.5 p-3', !isReply && 'hover:bg-accent/50 transition-colors rounded-md', onFocus && 'cursor-pointer')}>\n {/* Header: avatar, author, timestamp, actions */}\n <div className=\"flex items-start gap-2\">\n <Avatar className={cn('mt-0.5 rounded-full overflow-hidden shrink-0', isReply ? 'h-6 w-6' : 'h-8 w-8')}>\n <UserAvatar imageFileId={author?.imageFileId} name={authorName} />\n </Avatar>\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-foreground truncate\">{authorName}</span>\n {comment.updatedAt !== comment.createdAt && (\n <Badge variant=\"outline\" className=\"text-xs\">{t('edited')}</Badge>\n )}\n <span className=\"text-xs text-muted-foreground ml-auto whitespace-nowrap\">\n {formatTimestamp(comment.createdAt)}\n </span>\n </div>\n </div>\n\n {onAction && (\n <CommentActionButtons\n // Replies are single-level, so only top-level comments expose a reply control.\n onReply={!isReply && onReply ? openReply : undefined}\n onEdit={isAuthor ? handleEditStart : undefined}\n onDelete={isAuthor ? () => onAction('delete', comment.id) : undefined}\n canReply={canReply}\n canEdit={canEdit}\n canDelete={canDelete}\n labels={{ reply: t('replyToComment'), edit: t('editComment'), delete: t('deleteComment') }}\n />\n )}\n </div>\n\n {/* Body: full text (shown once) or inline editor */}\n {isEditing ? (\n <div className=\"flex gap-2\" onDoubleClick={(e) => e.stopPropagation()}>\n <Input\n value={editText}\n onChange={(e) => setEditText(e.target.value)}\n className=\"flex-1 h-8\"\n autoFocus\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n handleEditSubmit()\n }\n if (e.key === 'Escape') setIsEditing(false)\n }}\n disabled={!canEdit}\n />\n <Button size=\"icon\" className=\"h-8 w-8 p-0\" onClick={handleEditSubmit} disabled={!editText.trim() || !canEdit}>\n <LR.Check className=\"h-4 w-4\" />\n </Button>\n <Button size=\"icon\" variant=\"ghost\" className=\"h-8 w-8 p-0\" onClick={() => setIsEditing(false)}>\n <LR.X className=\"h-4 w-4\" />\n </Button>\n </div>\n ) : (\n <p className=\"text-sm text-foreground whitespace-pre-wrap break-words\">{comment.text}</p>\n )}\n\n {/* Replies toggle (top-level only) */}\n {!isReply && replies.length > 0 && (\n <button\n type=\"button\"\n className=\"flex items-center gap-1 w-fit text-xs text-muted-foreground hover:text-foreground transition-colors\"\n onClick={() => setIsExpanded((v) => !v)}\n >\n <LR.ChevronRight className={cn('h-3.5 w-3.5 transition-transform', isExpanded && 'rotate-90')} />\n {replies.length} {replies.length === 1 ? t('reply') : t('replies')}\n </button>\n )}\n </div>\n\n {/* Nested replies thread + single reply input at the end */}\n {!isReply && isExpanded && (\n <div className=\"ml-5 border-l border-border pl-1 pr-2 pb-2\">\n {replies.map((reply) => (\n <CollapsibleCommentItem\n key={reply.id}\n comment={reply}\n onAction={onAction}\n onReply={onReply}\n onEdit={onEdit}\n onFileUpload={onFileUpload}\n depth={depth + 1}\n pendingAction={pendingAction}\n />\n ))}\n\n {onReply && (\n <div className=\"flex gap-2 px-1 pt-2\" onDoubleClick={(e) => e.stopPropagation()}>\n <Input\n ref={replyInputRef}\n value={replyText}\n onChange={(e) => setReplyText(e.target.value)}\n placeholder={t('writeReply')}\n className=\"flex-1 h-8\"\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n handleReplySubmit()\n }\n }}\n disabled={!canReply}\n />\n <Button size=\"icon\" className=\"h-8 w-8 p-0\" onClick={handleReplySubmit} disabled={!replyText.trim() || !canReply}>\n <LR.Send className=\"h-4 w-4\" />\n </Button>\n </div>\n )}\n </div>\n )}\n </div>\n )\n}\n"],"mappings":"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","names":["_a"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { type CommentActionLabels } from './CommentActionButtons';
|
|
2
3
|
export type CommentProps = {
|
|
3
4
|
userName: string;
|
|
4
5
|
userImage: number | null;
|
|
@@ -8,10 +9,26 @@ export type CommentProps = {
|
|
|
8
9
|
createdAt: string | Date;
|
|
9
10
|
onRemove?: () => void;
|
|
10
11
|
onClose?: () => void;
|
|
12
|
+
/** Called when the collapsed avatar is single-clicked (select the comment). */
|
|
13
|
+
onSelect?: () => void;
|
|
14
|
+
/** Called on double-click — used to zoom/focus the comment in the viewer. */
|
|
15
|
+
onFocus?: () => void;
|
|
16
|
+
/** Reply to the comment (in-viewer card opens the reply box in the sidebar). */
|
|
17
|
+
onReply?: () => void;
|
|
18
|
+
/** Edit the comment (in-viewer card opens the editor in the sidebar). */
|
|
19
|
+
onEdit?: () => void;
|
|
11
20
|
enableCollapse?: boolean;
|
|
12
21
|
defaultCollapsed?: boolean;
|
|
13
22
|
isPending?: boolean;
|
|
14
23
|
highlight?: boolean;
|
|
24
|
+
/** Double-clicked/zoomed comment: renders the thicker focus ring. */
|
|
25
|
+
focused?: boolean;
|
|
26
|
+
/** Render the close/reply/edit/delete action row (used by the in-viewer BIM card). */
|
|
27
|
+
showActions?: boolean;
|
|
28
|
+
canReply?: boolean;
|
|
29
|
+
canEdit?: boolean;
|
|
30
|
+
canDelete?: boolean;
|
|
31
|
+
actionLabels?: CommentActionLabels;
|
|
15
32
|
};
|
|
16
|
-
export default function Comment({ text, createdAt, userName, userImage, userImageFileId, onRemove, onClose, enableCollapse, defaultCollapsed, isPending, highlight, }: CommentProps): React.JSX.Element;
|
|
33
|
+
export default function Comment({ text, createdAt, userName, userImage, userImageFileId, onRemove, onClose, onSelect, onFocus, onReply, onEdit, enableCollapse, defaultCollapsed, isPending, highlight, focused, showActions, canReply, canEdit, canDelete, actionLabels, }: CommentProps): React.JSX.Element;
|
|
17
34
|
//# sourceMappingURL=Comment.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Comment.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/ui/Comments/Comment.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAU9B,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"Comment.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/ui/Comments/Comment.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAU9B,OAAO,EAAwB,KAAK,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAEvF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,qEAAqE;IACrE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,sFAAsF;IACtF,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,YAAY,CAAC,EAAE,mBAAmB,CAAA;CACnC,CAAA;AAED,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,EAC9B,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,SAAS,EACT,eAAe,EACf,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,OAAO,EACP,OAAO,EACP,MAAM,EACN,cAAsB,EACtB,gBAAwB,EACxB,SAAiB,EACjB,SAAiB,EACjB,OAAe,EACf,WAAmB,EACnB,QAAe,EACf,OAAc,EACd,SAAgB,EAChB,YAAY,GACb,EAAE,YAAY,qBAgKd"}
|