index.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. 'use client'
  2. import { useTranslation } from 'react-i18next'
  3. import { Fragment } from 'react'
  4. import Link from 'next/link'
  5. import { useSWRConfig } from 'swr'
  6. import { EllipsisHorizontalIcon } from '@heroicons/react/24/solid'
  7. import { Menu, Transition } from '@headlessui/react'
  8. import { apiPrefix } from '@/config'
  9. import { syncDataSourceNotion, updateDataSourceNotionAction } from '@/service/common'
  10. import Toast from '@/app/components/base/toast'
  11. import type { DataSourceNotion } from '@/models/common'
  12. import { FilePlus02 } from '@/app/components/base/icons/src/vender/line/files'
  13. import { RefreshCw05 } from '@/app/components/base/icons/src/vender/line/arrows'
  14. import { Trash03 } from '@/app/components/base/icons/src/vender/line/general'
  15. type OperateProps = {
  16. workspace: DataSourceNotion
  17. }
  18. export default function Operate({
  19. workspace,
  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-[0_10px_15px_-3px_rgba(0,0,0,0.1),0_4px_6px_rgba(0,0,0,0.05)]
  67. "
  68. >
  69. <div className="px-1 py-1">
  70. <Menu.Item>
  71. <Link
  72. className={itemClassName}
  73. href={`${apiPrefix}/oauth/data-source/notion`}>
  74. <FilePlus02 className={itemIconClassName} />
  75. <div>
  76. <div className='leading-5'>{t('common.dataSource.notion.changeAuthorizedPages')}</div>
  77. <div className='leading-5 text-xs text-gray-500'>
  78. {workspace.source_info.total} {t('common.dataSource.notion.pagesAuthorized')}
  79. </div>
  80. </div>
  81. </Link>
  82. </Menu.Item>
  83. <Menu.Item>
  84. <div className={itemClassName} onClick={handleSync}>
  85. <RefreshCw05 className={itemIconClassName} />
  86. <div className='leading-5'>{t('common.dataSource.notion.sync')}</div>
  87. </div>
  88. </Menu.Item>
  89. </div>
  90. <Menu.Item>
  91. <div className='p-1'>
  92. <div className={itemClassName} onClick={handleRemove}>
  93. <Trash03 className={itemIconClassName} />
  94. <div className='leading-5'>{t('common.dataSource.notion.remove')}</div>
  95. </div>
  96. </div>
  97. </Menu.Item>
  98. </Menu.Items>
  99. </Transition>
  100. </>
  101. )
  102. }
  103. </Menu>
  104. )
  105. }