project-name-editable-label.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import { useEffect, useState, useRef } from 'react'
  2. import PropTypes from 'prop-types'
  3. import { OverlayTrigger, Tooltip } from 'react-bootstrap'
  4. import { useTranslation } from 'react-i18next'
  5. import classNames from 'classnames'
  6. import Icon from '../../../shared/components/icon'
  7. function ProjectNameEditableLabel({
  8. projectName,
  9. hasRenamePermissions,
  10. onChange,
  11. className,
  12. }) {
  13. const { t } = useTranslation()
  14. const [isRenaming, setIsRenaming] = useState(false)
  15. const canRename = hasRenamePermissions && !isRenaming
  16. const [inputContent, setInputContent] = useState(projectName)
  17. const inputRef = useRef(null)
  18. useEffect(() => {
  19. if (isRenaming) {
  20. inputRef.current.select()
  21. }
  22. }, [isRenaming])
  23. function startRenaming() {
  24. if (canRename) {
  25. setInputContent(projectName)
  26. setIsRenaming(true)
  27. }
  28. }
  29. function finishRenaming() {
  30. setIsRenaming(false)
  31. onChange(inputContent)
  32. }
  33. function handleKeyDown(event) {
  34. if (event.key === 'Enter') {
  35. event.preventDefault()
  36. finishRenaming()
  37. }
  38. }
  39. function handleOnChange(event) {
  40. setInputContent(event.target.value)
  41. }
  42. function handleBlur() {
  43. if (isRenaming) {
  44. finishRenaming()
  45. }
  46. }
  47. return (
  48. <div className={classNames('project-name', className)}>
  49. {!isRenaming && (
  50. <span className="name" onDoubleClick={startRenaming}>
  51. {projectName}
  52. </span>
  53. )}
  54. {isRenaming && (
  55. <input
  56. ref={inputRef}
  57. type="text"
  58. className="form-control"
  59. onKeyDown={handleKeyDown}
  60. onChange={handleOnChange}
  61. onBlur={handleBlur}
  62. value={inputContent}
  63. />
  64. )}
  65. {canRename && (
  66. <OverlayTrigger
  67. placement="bottom"
  68. trigger={['hover', 'focus']}
  69. overlay={<Tooltip id="tooltip-online-user">{t('rename')}</Tooltip>}
  70. >
  71. {/* eslint-disable-next-line jsx-a11y/anchor-is-valid, jsx-a11y/click-events-have-key-events, jsx-a11y/interactive-supports-focus */}
  72. <a className="rename" role="button" onClick={startRenaming}>
  73. <Icon type="pencil" fw />
  74. </a>
  75. </OverlayTrigger>
  76. )}
  77. </div>
  78. )
  79. }
  80. ProjectNameEditableLabel.propTypes = {
  81. projectName: PropTypes.string.isRequired,
  82. hasRenamePermissions: PropTypes.bool,
  83. onChange: PropTypes.func.isRequired,
  84. className: PropTypes.string,
  85. }
  86. export default ProjectNameEditableLabel