index.tsx 4.0 KB

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