index.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. 'use client'
  2. import { useTranslation } from 'react-i18next'
  3. import { Fragment } from 'react'
  4. import { useSWRConfig } from 'swr'
  5. import { EllipsisHorizontalIcon } from '@heroicons/react/24/solid'
  6. import { Menu, Transition } from '@headlessui/react'
  7. import { syncDataSourceNotion, updateDataSourceNotionAction } from '@/service/common'
  8. import Toast from '@/app/components/base/toast'
  9. import type { DataSourceNotion } from '@/models/common'
  10. import { FilePlus02 } from '@/app/components/base/icons/src/vender/line/files'
  11. import { RefreshCw05 } from '@/app/components/base/icons/src/vender/line/arrows'
  12. import { Trash03 } from '@/app/components/base/icons/src/vender/line/general'
  13. type OperateProps = {
  14. workspace: DataSourceNotion
  15. onAuthAgain: () => void
  16. }
  17. export default function Operate({
  18. workspace,
  19. onAuthAgain,
  20. }: OperateProps) {
  21. const itemClassName = `
  22. flex px-3 py-2 hover:bg-gray-50 text-sm text-gray-700
  23. cursor-pointer
  24. `
  25. const itemIconClassName = `
  26. mr-2 mt-[2px] w-4 h-4 text-gray-500
  27. `
  28. const { t } = useTranslation()
  29. const { mutate } = useSWRConfig()
  30. const updateIntegrates = () => {
  31. Toast.notify({
  32. type: 'success',
  33. message: t('common.api.success'),
  34. })
  35. mutate({ url: 'data-source/integrates' })
  36. }
  37. const handleSync = async () => {
  38. await syncDataSourceNotion({ url: `/oauth/data-source/notion/${workspace.id}/sync` })
  39. updateIntegrates()
  40. }
  41. const handleRemove = async () => {
  42. await updateDataSourceNotionAction({ url: `/data-source/integrates/${workspace.id}/disable` })
  43. updateIntegrates()
  44. }
  45. return (
  46. <Menu as="div" className="relative inline-block text-left">
  47. {
  48. ({ open }) => (
  49. <>
  50. <Menu.Button className={`flex items-center justify-center w-8 h-8 rounded-lg hover:bg-gray-100 ${open && 'bg-gray-100'}`}>
  51. <EllipsisHorizontalIcon className='w-4 h-4' />
  52. </Menu.Button>
  53. <Transition
  54. as={Fragment}
  55. enter="transition ease-out duration-100"
  56. enterFrom="transform opacity-0 scale-95"
  57. enterTo="transform opacity-100 scale-100"
  58. leave="transition ease-in duration-75"
  59. leaveFrom="transform opacity-100 scale-100"
  60. leaveTo="transform opacity-0 scale-95"
  61. >
  62. <Menu.Items
  63. className="
  64. absolute right-0 top-9 w-60 max-w-80
  65. divide-y divide-gray-100 origin-top-right rounded-lg bg-white
  66. shadow-lg
  67. "
  68. >
  69. <div className="px-1 py-1">
  70. <Menu.Item>
  71. <div
  72. className={itemClassName}
  73. onClick={onAuthAgain}
  74. >
  75. <FilePlus02 className={itemIconClassName} />
  76. <div>
  77. <div className='leading-5'>{t('common.dataSource.notion.changeAuthorizedPages')}</div>
  78. <div className='leading-5 text-xs text-gray-500'>
  79. {workspace.source_info.total} {t('common.dataSource.notion.pagesAuthorized')}
  80. </div>
  81. </div>
  82. </div>
  83. </Menu.Item>
  84. <Menu.Item>
  85. <div className={itemClassName} onClick={handleSync}>
  86. <RefreshCw05 className={itemIconClassName} />
  87. <div className='leading-5'>{t('common.dataSource.notion.sync')}</div>
  88. </div>
  89. </Menu.Item>
  90. </div>
  91. <Menu.Item>
  92. <div className='p-1'>
  93. <div className={itemClassName} onClick={handleRemove}>
  94. <Trash03 className={itemIconClassName} />
  95. <div className='leading-5'>{t('common.dataSource.notion.remove')}</div>
  96. </div>
  97. </div>
  98. </Menu.Item>
  99. </Menu.Items>
  100. </Transition>
  101. </>
  102. )
  103. }
  104. </Menu>
  105. )
  106. }