index.tsx 4.0 KB

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