|
import { useState, useEffect } from 'react' |
|
import { useTranslation } from 'react-i18next' |
|
import { |
|
Dialog, |
|
DialogContent, |
|
DialogHeader, |
|
DialogTitle, |
|
DialogFooter, |
|
DialogDescription |
|
} from '@/components/ui/Dialog' |
|
import Button from '@/components/ui/Button' |
|
|
|
interface PropertyEditDialogProps { |
|
isOpen: boolean |
|
onClose: () => void |
|
onSave: (value: string) => void |
|
propertyName: string |
|
initialValue: string |
|
isSubmitting?: boolean |
|
} |
|
|
|
|
|
|
|
|
|
|
|
const PropertyEditDialog = ({ |
|
isOpen, |
|
onClose, |
|
onSave, |
|
propertyName, |
|
initialValue, |
|
isSubmitting = false |
|
}: PropertyEditDialogProps) => { |
|
const { t } = useTranslation() |
|
const [value, setValue] = useState('') |
|
|
|
|
|
useEffect(() => { |
|
if (isOpen) { |
|
setValue(initialValue) |
|
} |
|
}, [isOpen, initialValue]) |
|
|
|
|
|
const getPropertyNameTranslation = (name: string) => { |
|
const translationKey = `graphPanel.propertiesView.node.propertyNames.${name}` |
|
const translation = t(translationKey) |
|
return translation === translationKey ? name : translation |
|
} |
|
|
|
|
|
const getTextareaConfig = (propertyName: string) => { |
|
switch (propertyName) { |
|
case 'description': |
|
return { |
|
|
|
className: 'max-h-[50vh] min-h-[10em] resize-y', |
|
style: { |
|
height: '70vh', |
|
minHeight: '20em', |
|
resize: 'vertical' as const |
|
} |
|
}; |
|
case 'entity_id': |
|
return { |
|
rows: 2, |
|
className: '', |
|
style: {} |
|
}; |
|
case 'keywords': |
|
return { |
|
rows: 4, |
|
className: '', |
|
style: {} |
|
}; |
|
default: |
|
return { |
|
rows: 5, |
|
className: '', |
|
style: {} |
|
}; |
|
} |
|
}; |
|
|
|
const handleSave = () => { |
|
if (value.trim() !== '') { |
|
onSave(value) |
|
onClose() |
|
} |
|
} |
|
|
|
return ( |
|
<Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}> |
|
<DialogContent className="sm:max-w-md"> |
|
<DialogHeader> |
|
<DialogTitle> |
|
{t('graphPanel.propertiesView.editProperty', { |
|
property: getPropertyNameTranslation(propertyName) |
|
})} |
|
</DialogTitle> |
|
<DialogDescription> |
|
{t('graphPanel.propertiesView.editPropertyDescription')} |
|
</DialogDescription> |
|
</DialogHeader> |
|
|
|
{/* Multi-line text input using textarea */} |
|
<div className="grid gap-4 py-4"> |
|
{(() => { |
|
const config = getTextareaConfig(propertyName); |
|
return propertyName === 'description' ? ( |
|
<textarea |
|
value={value} |
|
onChange={(e) => setValue(e.target.value)} |
|
className={`border-input focus-visible:ring-ring flex w-full rounded-md border bg-transparent px-3 py-2 text-sm shadow-sm transition-colors focus-visible:ring-1 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 ${config.className}`} |
|
style={config.style} |
|
disabled={isSubmitting} |
|
/> |
|
) : ( |
|
<textarea |
|
value={value} |
|
onChange={(e) => setValue(e.target.value)} |
|
rows={config.rows} |
|
className={`border-input focus-visible:ring-ring flex w-full rounded-md border bg-transparent px-3 py-2 text-sm shadow-sm transition-colors focus-visible:ring-1 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 ${config.className}`} |
|
disabled={isSubmitting} |
|
/> |
|
); |
|
})()} |
|
</div> |
|
|
|
<DialogFooter> |
|
<Button |
|
type="button" |
|
variant="outline" |
|
onClick={onClose} |
|
disabled={isSubmitting} |
|
> |
|
{t('common.cancel')} |
|
</Button> |
|
<Button |
|
type="button" |
|
onClick={handleSave} |
|
disabled={isSubmitting} |
|
> |
|
{t('common.save')} |
|
</Button> |
|
</DialogFooter> |
|
</DialogContent> |
|
</Dialog> |
|
) |
|
} |
|
|
|
export default PropertyEditDialog |
|
|