Browse Source

Feat/support copy apikey and chat message (#62)

Joel 1 năm trước cách đây
mục cha
commit
74d954610f

+ 44 - 0
web/app/components/app/chat/copy-btn/index.tsx

@@ -0,0 +1,44 @@
+'use client'
+import React from 'react'
+import Tooltip from '@/app/components/base/tooltip'
+import { t } from 'i18next'
+import s from './style.module.css'
+import copy from 'copy-to-clipboard'
+
+
+type ICopyBtnProps = {
+  value: string
+  className?: string
+}
+
+const CopyBtn = ({
+  value,
+  className,
+}: ICopyBtnProps) => {
+  const [isCopied, setIsCopied] = React.useState(false)
+
+  return (
+    <div className={`${className}`}>
+      <Tooltip
+        selector="copy-btn-tooltip"
+        content={(isCopied ? t('appApi.copied') : t('appApi.copy')) as string}
+        className='z-10'
+      >
+          <div 
+            className={`box-border p-0.5 flex items-center justify-center rounded-md bg-white cursor-pointer`}
+            style={{
+              boxShadow: '0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06)'
+            }}
+            onClick={() => {
+              copy(value)
+              setIsCopied(true)
+            }}
+          >
+            <div className={`w-6 h-6 hover:bg-gray-50  ${s.copyIcon} ${isCopied ? s.copied : ''}`}></div>
+          </div>
+      </Tooltip>
+    </div>
+  )
+}
+
+export default CopyBtn

+ 15 - 0
web/app/components/app/chat/copy-btn/style.module.css

@@ -0,0 +1,15 @@
+.copyIcon {
+  background-image: url(~@/app/components/develop/secret-key/assets/copy.svg);
+  background-position: center;
+  background-repeat: no-repeat;
+}
+
+.copyIcon:hover {
+  background-image: url(~@/app/components/develop/secret-key/assets/copy-hover.svg);
+  background-position: center;
+  background-repeat: no-repeat;
+}
+
+.copyIcon.copied {
+  background-image: url(~@/app/components/develop/secret-key/assets/copied.svg);
+}

+ 5 - 0
web/app/components/app/chat/index.tsx

@@ -17,6 +17,7 @@ import AppContext from '@/context/app-context'
 import { Markdown } from '@/app/components/base/markdown'
 import LoadingAnim from './loading-anim'
 import { formatNumber } from '@/utils/format'
+import CopyBtn from './copy-btn'
 
 const stopIcon = (
   <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
@@ -346,6 +347,10 @@ const Answer: FC<IAnswerProps> = ({ item, feedbackDisabled = false, isHideFeedba
               }
             </div>
             <div className='absolute top-[-14px] right-[-14px] flex flex-row justify-end gap-1'>
+              <CopyBtn
+                value={content}
+                className={cn(s.copyBtn, 'mr-1')}
+              />
               {!feedbackDisabled && !item.feedbackDisabled && renderItemOperation(displayScene !== 'console')}
               {/* Admin feedback is displayed only in the background. */}
               {!feedbackDisabled && renderFeedbackRating(localAdminFeedback?.rating, false, false)}

+ 8 - 0
web/app/components/app/chat/style.module.css

@@ -38,6 +38,14 @@
   background: url(./icons/answer.svg) no-repeat;
 }
 
+.copyBtn {
+  display: none;
+}
+
+.answerWrap:hover .copyBtn {
+  display: block;
+}
+
 .answerWrap .itemOperation {
   display: none;
 }

+ 1 - 1
web/app/components/app/overview/customize/index.tsx

@@ -71,7 +71,7 @@ const CustomizeModal: FC<IShareLinkProps> = ({
         <div className='flex flex-col w-full'>
           <div className='text-gray-900'>{t(`${prefixCustomize}.way1.step2`)}</div>
           <div className='text-gray-500 text-xs mt-1 mb-2'>{t(`${prefixCustomize}.way1.step2Tip`)}</div>
-          <pre className='box-border py-3 px-4 bg-gray-100 text-xs font-medium rounded-lg'>
+          <pre className='box-border py-3 px-4 bg-gray-100 text-xs font-medium rounded-lg select-text'>
             export const APP_ID = '{appId}'<br />
             export const API_KEY = {`'<Web API Key From Dify>'`}
           </pre>