index.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. 'use client'
  2. import { useTranslation } from 'react-i18next'
  3. import { Fragment } from 'react'
  4. import { useSWRConfig } from 'swr'
  5. import {
  6. RiDeleteBinLine,
  7. RiLoopLeftLine,
  8. RiMoreFill,
  9. RiStickyNoteAddLine,
  10. } from '@remixicon/react'
  11. import { Menu, MenuButton, MenuItem, MenuItems, Transition } from '@headlessui/react'
  12. import { syncDataSourceNotion, updateDataSourceNotionAction } from '@/service/common'
  13. import Toast from '@/app/components/base/toast'
  14. import cn from '@/utils/classnames'
  15. type OperateProps = {
  16. payload: {
  17. id: string
  18. total: number
  19. }
  20. onAuthAgain: () => void
  21. }
  22. export default function Operate({
  23. payload,
  24. onAuthAgain,
  25. }: OperateProps) {
  26. const { t } = useTranslation()
  27. const { mutate } = useSWRConfig()
  28. const updateIntegrates = () => {
  29. Toast.notify({
  30. type: 'success',
  31. message: t('common.api.success'),
  32. })
  33. mutate({ url: 'data-source/integrates' })
  34. }
  35. const handleSync = async () => {
  36. await syncDataSourceNotion({ url: `/oauth/data-source/notion/${payload.id}/sync` })
  37. updateIntegrates()
  38. }
  39. const handleRemove = async () => {
  40. await updateDataSourceNotionAction({ url: `/data-source/integrates/${payload.id}/disable` })
  41. updateIntegrates()
  42. }
  43. return (
  44. <Menu as="div" className="relative inline-block text-left">
  45. {
  46. ({ open }) => (
  47. <>
  48. <MenuButton className={cn('flex h-8 w-8 items-center justify-center rounded-lg hover:bg-state-base-hover', open && 'bg-state-base-hover')}>
  49. <RiMoreFill className='h-4 w-4 text-text-secondary' />
  50. </MenuButton>
  51. <Transition
  52. as={Fragment}
  53. enter="transition ease-out duration-100"
  54. enterFrom="transform opacity-0 scale-95"
  55. enterTo="transform opacity-100 scale-100"
  56. leave="transition ease-in duration-75"
  57. leaveFrom="transform opacity-100 scale-100"
  58. leaveTo="transform opacity-0 scale-95"
  59. >
  60. <MenuItems className="absolute right-0 top-9 w-60 max-w-80 origin-top-right rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg backdrop-blur-sm">
  61. <div className="px-1 py-1">
  62. <MenuItem>
  63. <div
  64. className='flex cursor-pointer rounded-lg px-3 py-2 hover:bg-state-base-hover'
  65. onClick={onAuthAgain}
  66. >
  67. <RiStickyNoteAddLine className='mr-2 mt-[2px] h-4 w-4 text-text-tertiary' />
  68. <div>
  69. <div className='system-sm-semibold text-text-secondary'>{t('common.dataSource.notion.changeAuthorizedPages')}</div>
  70. <div className='system-xs-regular text-text-tertiary'>
  71. {payload.total} {t('common.dataSource.notion.pagesAuthorized')}
  72. </div>
  73. </div>
  74. </div>
  75. </MenuItem>
  76. <MenuItem>
  77. <div className='flex cursor-pointer rounded-lg px-3 py-2 hover:bg-state-base-hover' onClick={handleSync}>
  78. <RiLoopLeftLine className='mr-2 mt-[2px] h-4 w-4 text-text-tertiary' />
  79. <div className='system-sm-semibold text-text-secondary'>{t('common.dataSource.notion.sync')}</div>
  80. </div>
  81. </MenuItem>
  82. </div>
  83. <MenuItem>
  84. <div className='border-t border-divider-subtle p-1'>
  85. <div className='flex cursor-pointer rounded-lg px-3 py-2 hover:bg-state-base-hover' onClick={handleRemove}>
  86. <RiDeleteBinLine className='mr-2 mt-[2px] h-4 w-4 text-text-tertiary' />
  87. <div className='system-sm-semibold text-text-secondary'>{t('common.dataSource.notion.remove')}</div>
  88. </div>
  89. </div>
  90. </MenuItem>
  91. </MenuItems>
  92. </Transition>
  93. </>
  94. )
  95. }
  96. </Menu>
  97. )
  98. }