Commit d0ca8af0 authored by StyleZhang's avatar StyleZhang

fix: account-dropdown style

parent 0df135ea
'use client' 'use client'
import cn from 'classnames' import cn from 'classnames'
interface IAvatarProps { type AvatarProps = {
name: string name: string
avatar?: string avatar?: string
size?: number size?: number
className?: string className?: string
textClassName?: string
} }
const Avatar = ({ const Avatar = ({
name, name,
avatar, avatar,
size = 30, size = 30,
className className,
}: IAvatarProps) => { textClassName,
const avatarClassName = `shrink-0 flex items-center rounded-full bg-primary-600` }: AvatarProps) => {
const style = { width: `${size}px`, height:`${size}px`, fontSize: `${size}px`, lineHeight: `${size}px` } const avatarClassName = 'shrink-0 flex items-center rounded-full bg-primary-600'
const style = { width: `${size}px`, height: `${size}px`, fontSize: `${size}px`, lineHeight: `${size}px` }
if (avatar) { if (avatar) {
return ( return (
<img <img
className={cn(avatarClassName, className)} className={cn(avatarClassName, className)}
style={style} style={style}
alt={name} alt={name}
src={avatar} src={avatar}
/> />
) )
} }
return ( return (
<div <div
className={cn(avatarClassName, className)} className={cn(avatarClassName, className)}
style={style} style={style}
> >
<div <div
className={`text-center text-white scale-[0.4]`} className={cn(textClassName, 'text-center text-white scale-[0.4]')}
style={style} style={style}
> >
{name[0].toLocaleUpperCase()} {name[0].toLocaleUpperCase()}
...@@ -42,4 +44,4 @@ const Avatar = ({ ...@@ -42,4 +44,4 @@ const Avatar = ({
) )
} }
export default Avatar export default Avatar
\ No newline at end of file
<svg width="50" height="26" viewBox="0 0 50 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Dify">
<path d="M6.61784 2.064C8.37784 2.064 9.92184 2.408 11.2498 3.096C12.5938 3.784 13.6258 4.768 14.3458 6.048C15.0818 7.312 15.4498 8.784 15.4498 10.464C15.4498 12.144 15.0818 13.616 14.3458 14.88C13.6258 16.128 12.5938 17.096 11.2498 17.784C9.92184 18.472 8.37784 18.816 6.61784 18.816H0.761841V2.064H6.61784ZM6.49784 15.96C8.25784 15.96 9.61784 15.48 10.5778 14.52C11.5378 13.56 12.0178 12.208 12.0178 10.464C12.0178 8.72 11.5378 7.36 10.5778 6.384C9.61784 5.392 8.25784 4.896 6.49784 4.896H4.12184V15.96H6.49784Z" fill="#1D2939"/>
<path d="M20.869 3.936C20.277 3.936 19.781 3.752 19.381 3.384C18.997 3 18.805 2.528 18.805 1.968C18.805 1.408 18.997 0.944 19.381 0.576C19.781 0.192 20.277 0 20.869 0C21.461 0 21.949 0.192 22.333 0.576C22.733 0.944 22.933 1.408 22.933 1.968C22.933 2.528 22.733 3 22.333 3.384C21.949 3.752 21.461 3.936 20.869 3.936ZM22.525 5.52V18.816H19.165V5.52H22.525Z" fill="#1D2939"/>
<path d="M33.1407 8.28H30.8127V18.816H27.4047V8.28H25.8927V5.52H27.4047V4.848C27.4047 3.216 27.8687 2.016 28.7967 1.248C29.7247 0.48 31.1247 0.12 32.9967 0.168001V3C32.1807 2.984 31.6127 3.12 31.2927 3.408C30.9727 3.696 30.8127 4.216 30.8127 4.968V5.52H33.1407V8.28Z" fill="#1D2939"/>
<path d="M49.2381 5.52L41.0061 25.104H37.4301L40.3101 18.48L34.9821 5.52H38.7501L42.1821 14.808L45.6621 5.52H49.2381Z" fill="#1D2939"/>
</g>
</svg>
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="arrow-up-right">
<path id="Icon" d="M4.08325 9.91665L9.91659 4.08331M9.91659 4.08331H4.08325M9.91659 4.08331V9.91665" stroke="#667085" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="chevron-down">
<path id="Icon" d="M3 4.5L6 7.5L9 4.5" stroke="#344054" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="chevron-right">
<path id="Icon" d="M5.25 10.5L8.75 7L5.25 3.5" stroke="#667085" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="check">
<path id="Icon" d="M13.3334 4L6.00008 11.3333L2.66675 8" stroke="#155EEF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="log-out-01">
<path id="Icon" d="M9.33333 9.91667L12.25 7M12.25 7L9.33333 4.08333M12.25 7H5.25M5.25 1.75H4.55C3.56991 1.75 3.07986 1.75 2.70552 1.94074C2.37623 2.10852 2.10852 2.37623 1.94074 2.70552C1.75 3.07986 1.75 3.56991 1.75 4.55V9.45C1.75 10.4301 1.75 10.9201 1.94074 11.2945C2.10852 11.6238 2.37623 11.8915 2.70552 12.0593C3.07986 12.25 3.56991 12.25 4.55 12.25H5.25" stroke="#667085" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "50",
"height": "26",
"viewBox": "0 0 50 26",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "Dify"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"d": "M6.61784 2.064C8.37784 2.064 9.92184 2.408 11.2498 3.096C12.5938 3.784 13.6258 4.768 14.3458 6.048C15.0818 7.312 15.4498 8.784 15.4498 10.464C15.4498 12.144 15.0818 13.616 14.3458 14.88C13.6258 16.128 12.5938 17.096 11.2498 17.784C9.92184 18.472 8.37784 18.816 6.61784 18.816H0.761841V2.064H6.61784ZM6.49784 15.96C8.25784 15.96 9.61784 15.48 10.5778 14.52C11.5378 13.56 12.0178 12.208 12.0178 10.464C12.0178 8.72 11.5378 7.36 10.5778 6.384C9.61784 5.392 8.25784 4.896 6.49784 4.896H4.12184V15.96H6.49784Z",
"fill": "#1D2939"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M20.869 3.936C20.277 3.936 19.781 3.752 19.381 3.384C18.997 3 18.805 2.528 18.805 1.968C18.805 1.408 18.997 0.944 19.381 0.576C19.781 0.192 20.277 0 20.869 0C21.461 0 21.949 0.192 22.333 0.576C22.733 0.944 22.933 1.408 22.933 1.968C22.933 2.528 22.733 3 22.333 3.384C21.949 3.752 21.461 3.936 20.869 3.936ZM22.525 5.52V18.816H19.165V5.52H22.525Z",
"fill": "#1D2939"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M33.1407 8.28H30.8127V18.816H27.4047V8.28H25.8927V5.52H27.4047V4.848C27.4047 3.216 27.8687 2.016 28.7967 1.248C29.7247 0.48 31.1247 0.12 32.9967 0.168001V3C32.1807 2.984 31.6127 3.12 31.2927 3.408C30.9727 3.696 30.8127 4.216 30.8127 4.968V5.52H33.1407V8.28Z",
"fill": "#1D2939"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M49.2381 5.52L41.0061 25.104H37.4301L40.3101 18.48L34.9821 5.52H38.7501L42.1821 14.808L45.6621 5.52H49.2381Z",
"fill": "#1D2939"
},
"children": []
}
]
}
]
},
"name": "Dify"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './Dify.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
export default Icon
export { default as Dify } from './Dify'
export { default as Github } from './Github' export { default as Github } from './Github'
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "14",
"height": "14",
"viewBox": "0 0 14 14",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "arrow-up-right"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"id": "Icon",
"d": "M4.08325 9.91665L9.91659 4.08331M9.91659 4.08331H4.08325M9.91659 4.08331V9.91665",
"stroke": "currentColor",
"stroke-width": "1.25",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
}
]
}
]
},
"name": "ArrowUpRight"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './ArrowUpRight.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
export default Icon
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "12",
"height": "12",
"viewBox": "0 0 12 12",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "chevron-down"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"id": "Icon",
"d": "M3 4.5L6 7.5L9 4.5",
"stroke": "currentColor",
"stroke-width": "1.5",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
}
]
}
]
},
"name": "ChevronDown"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './ChevronDown.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
export default Icon
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "14",
"height": "14",
"viewBox": "0 0 14 14",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "chevron-right"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"id": "Icon",
"d": "M5.25 10.5L8.75 7L5.25 3.5",
"stroke": "currentColor",
"stroke-width": "1.25",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
}
]
}
]
},
"name": "ChevronRight"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './ChevronRight.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
export default Icon
export { default as ArrowNarrowLeft } from './ArrowNarrowLeft' export { default as ArrowNarrowLeft } from './ArrowNarrowLeft'
export { default as ArrowUpRight } from './ArrowUpRight'
export { default as ChevronDown } from './ChevronDown'
export { default as ChevronRight } from './ChevronRight'
export { default as RefreshCw05 } from './RefreshCw05' export { default as RefreshCw05 } from './RefreshCw05'
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "16",
"height": "16",
"viewBox": "0 0 16 16",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "check"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"id": "Icon",
"d": "M13.3334 4L6.00008 11.3333L2.66675 8",
"stroke": "currentColor",
"stroke-width": "1.5",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
}
]
}
]
},
"name": "Check"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './Check.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
export default Icon
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "14",
"height": "14",
"viewBox": "0 0 14 14",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "log-out-01"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"id": "Icon",
"d": "M9.33333 9.91667L12.25 7M12.25 7L9.33333 4.08333M12.25 7H5.25M5.25 1.75H4.55C3.56991 1.75 3.07986 1.75 2.70552 1.94074C2.37623 2.10852 2.10852 2.37623 1.94074 2.70552C1.75 3.07986 1.75 3.56991 1.75 4.55V9.45C1.75 10.4301 1.75 10.9201 1.94074 11.2945C2.10852 11.6238 2.37623 11.8915 2.70552 12.0593C3.07986 12.25 3.56991 12.25 4.55 12.25H5.25",
"stroke": "currentColor",
"stroke-width": "1.25",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
}
]
}
]
},
"name": "LogOut01"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './LogOut01.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
export default Icon
export { default as Check } from './Check'
export { default as Loading02 } from './Loading02' export { default as Loading02 } from './Loading02'
export { default as LogOut01 } from './LogOut01'
export { default as Trash03 } from './Trash03' export { default as Trash03 } from './Trash03'
export { default as XClose } from './XClose' export { default as XClose } from './XClose'
export { default as X } from './X' export { default as X } from './X'
.logo-icon { .logo-icon {
background: url(../assets/logo-icon.png) center center no-repeat; background: url(../assets/logo-icon.png) center center no-repeat;
background-size: 32px; background-size: 32px;
box-shadow: 0px 4px 6px -1px rgba(0, 0, 0, 0.05), 0px 2px 4px -2px rgba(0, 0, 0, 0.05); box-shadow: 0px 2px 4px -2px rgba(0, 0, 0, 0.05), 0px 4px 6px -1px rgba(0, 0, 0, 0.05);
} }
.logo-text { .logo-text {
......
'use client' 'use client'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { XMarkIcon } from '@heroicons/react/24/outline'
import classNames from 'classnames' import classNames from 'classnames'
import Link from 'next/link' import Link from 'next/link'
import s from './index.module.css' import s from './index.module.css'
import Modal from '@/app/components/base/modal' import Modal from '@/app/components/base/modal'
import { XClose } from '@/app/components/base/icons/src/vender/line/general'
import { Dify } from '@/app/components/base/icons/src/public/common'
import type { LangGeniusVersionResponse } from '@/models/common' import type { LangGeniusVersionResponse } from '@/models/common'
import { IS_CE_EDITION } from '@/config' import { IS_CE_EDITION } from '@/config'
...@@ -30,16 +31,15 @@ export default function AccountAbout({ ...@@ -30,16 +31,15 @@ export default function AccountAbout({
className={s.modal} className={s.modal}
> >
<div className='relative'> <div className='relative'>
<XMarkIcon className='absolute top-0 -right-2 w-4 h-4 cursor-pointer' onClick={onCancel} /> <div className='absolute -top-2 -right-4 flex justify-center items-center w-8 h-8 cursor-pointer' onClick={onCancel}>
<XClose className='w-4 h-4 text-gray-500' />
</div>
<div> <div>
<div className={classNames( <div className={classNames(
s['logo-icon'], s['logo-icon'],
'mx-auto mb-3 w-12 h-12 bg-white rounded-xl border border-gray-200', 'mx-auto mb-3 w-12 h-12 bg-white rounded-xl border-[0.5px] border-gray-200',
)} />
<div className={classNames(
s['logo-text'],
'mx-auto mb-2',
)} /> )} />
<Dify className='mx-auto mb-2' />
<div className='mb-3 text-center text-xs font-normal text-gray-500'>Version {langeniusVersionInfo?.current_version}</div> <div className='mb-3 text-center text-xs font-normal text-gray-500'>Version {langeniusVersionInfo?.current_version}</div>
<div className='mb-4 text-center text-xs font-normal text-gray-700'> <div className='mb-4 text-center text-xs font-normal text-gray-700'>
<div>© 2023 LangGenius, Inc., Contributors.</div> <div>© 2023 LangGenius, Inc., Contributors.</div>
...@@ -55,7 +55,7 @@ export default function AccountAbout({ ...@@ -55,7 +55,7 @@ export default function AccountAbout({
</div> </div>
</div> </div>
</div> </div>
<div className='mb-4 h-0 border-[0.5px] border-gray-200' /> <div className='mb-4 -mx-8 h-[0.5px] bg-gray-200' />
<div className='flex justify-between items-center'> <div className='flex justify-between items-center'>
<div className='text-xs font-medium text-gray-800'> <div className='text-xs font-medium text-gray-800'>
{ {
......
...@@ -5,7 +5,6 @@ import { useRouter } from 'next/navigation' ...@@ -5,7 +5,6 @@ import { useRouter } from 'next/navigation'
import { useContext } from 'use-context-selector' import { useContext } from 'use-context-selector'
import classNames from 'classnames' import classNames from 'classnames'
import Link from 'next/link' import Link from 'next/link'
import { ArrowRightOnRectangleIcon, ArrowTopRightOnSquareIcon, ChevronDownIcon } from '@heroicons/react/24/solid'
import { Menu, Transition } from '@headlessui/react' import { Menu, Transition } from '@headlessui/react'
import Indicator from '../indicator' import Indicator from '../indicator'
import AccountSetting from '../account-setting' import AccountSetting from '../account-setting'
...@@ -15,10 +14,12 @@ import I18n from '@/context/i18n' ...@@ -15,10 +14,12 @@ import I18n from '@/context/i18n'
import Avatar from '@/app/components/base/avatar' import Avatar from '@/app/components/base/avatar'
import { logout } from '@/service/common' import { logout } from '@/service/common'
import { useAppContext } from '@/context/app-context' import { useAppContext } from '@/context/app-context'
import { ArrowUpRight, ChevronDown } from '@/app/components/base/icons/src/vender/line/arrows'
import { LogOut01 } from '@/app/components/base/icons/src/vender/line/general'
export default function AppSelector() { export default function AppSelector() {
const itemClassName = ` const itemClassName = `
flex items-center w-full h-10 px-3 text-gray-700 text-[14px] flex items-center w-full h-9 px-3 text-gray-700 text-[14px]
rounded-lg font-normal hover:bg-gray-100 cursor-pointer rounded-lg font-normal hover:bg-gray-100 cursor-pointer
` `
const router = useRouter() const router = useRouter()
...@@ -40,90 +41,94 @@ export default function AppSelector() { ...@@ -40,90 +41,94 @@ export default function AppSelector() {
return ( return (
<div className=""> <div className="">
<Menu as="div" className="relative inline-block text-left"> <Menu as="div" className="relative inline-block text-left">
<div> {
<Menu.Button ({ open }) => (
className=" <>
inline-flex items-center h-[38px] <div>
rounded-xl pl-2 pr-2.5 text-[14px] font-normal <Menu.Button
text-gray-800 hover:bg-gray-200 className={`
" inline-flex items-center
> rounded-[20px] py-1 pr-2.5 pl-1 text-sm
<Avatar name={userProfile.name} className='mr-2' /> text-gray-700 hover:bg-gray-200
{userProfile.name} ${open && 'bg-gray-200'}
<ChevronDownIcon `}
className="w-3 h-3 ml-1"
aria-hidden="true"
/>
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items
className="
absolute right-0 mt-1.5 w-60 max-w-80
divide-y divide-gray-100 origin-top-right rounded-lg bg-white
shadow-[0_10px_15px_-3px_rgba(0,0,0,0.1),0_4px_6px_rgba(0,0,0,0.05)]
"
>
<Menu.Item>
<div className='flex flex-nowrap items-center px-4 py-[13px]'>
<Avatar name={userProfile.name} size={36} className='mr-3' />
<div className='grow'>
<div className='leading-5 font-normal text-[14px] text-gray-800 break-all'>{userProfile.name}</div>
<div className='leading-[18px] text-xs font-normal text-gray-500 break-all'>{userProfile.email}</div>
</div>
</div>
</Menu.Item>
<div className='px-1 py-1'>
<div className='mt-2 px-3 text-xs font-medium text-gray-500'>{t('common.userProfile.workspace')}</div>
<WorkplaceSelector />
</div>
<div className="px-1 py-1">
<Menu.Item>
<div className={itemClassName} onClick={() => setSettingVisible(true)}>
<div>{t('common.userProfile.settings')}</div>
</div>
</Menu.Item>
<Menu.Item>
<Link
className={classNames(itemClassName, 'group justify-between')}
href={
locale === 'zh-Hans' ? 'https://docs.dify.ai/v/zh-hans/' : 'https://docs.dify.ai/'
}
target='_blank'>
<div>{t('common.userProfile.helpCenter')}</div>
<ArrowTopRightOnSquareIcon className='hidden w-4 h-4 group-hover:flex' />
</Link>
</Menu.Item>
<Menu.Item>
<div className={classNames(itemClassName, 'justify-between')} onClick={() => setAboutVisible(true)}>
<div>{t('common.userProfile.about')}</div>
<div className='flex items-center'>
<div className='mr-2 text-xs font-normal text-gray-500'>{langeniusVersionInfo.current_version}</div>
<Indicator color={langeniusVersionInfo.current_version === langeniusVersionInfo.latest_version ? 'green' : 'orange'} />
</div>
</div>
</Menu.Item>
</div>
<Menu.Item>
<div className='p-1' onClick={() => handleLogout()}>
<div
className='flex items-center justify-between h-12 px-3 rounded-lg cursor-pointer group hover:bg-gray-100'
> >
<div className='font-normal text-[14px] text-gray-700'>{t('common.userProfile.logout')}</div> <Avatar name={userProfile.name} className='mr-2' size={32} />
<ArrowRightOnRectangleIcon className='hidden w-4 h-4 group-hover:flex' /> {userProfile.name}
</div> <ChevronDown className="w-3 h-3 ml-1 text-gray-700"/>
</Menu.Button>
</div> </div>
</Menu.Item> <Transition
</Menu.Items> as={Fragment}
</Transition> enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items
className="
absolute right-0 mt-1.5 w-60 max-w-80
divide-y divide-gray-100 origin-top-right rounded-lg bg-white
shadow-[0_10px_15px_-3px_rgba(0,0,0,0.1),0_4px_6px_rgba(0,0,0,0.05)]
"
>
<Menu.Item>
<div className='flex flex-nowrap items-center px-4 py-[13px]'>
<Avatar name={userProfile.name} size={36} className='mr-3' />
<div className='grow'>
<div className='leading-5 font-normal text-[14px] text-gray-800 break-all'>{userProfile.name}</div>
<div className='leading-[18px] text-xs font-normal text-gray-500 break-all'>{userProfile.email}</div>
</div>
</div>
</Menu.Item>
<div className='px-1 py-1'>
<div className='mt-2 px-3 text-xs font-medium text-gray-500'>{t('common.userProfile.workspace')}</div>
<WorkplaceSelector />
</div>
<div className="px-1 py-1">
<Menu.Item>
<div className={itemClassName} onClick={() => setSettingVisible(true)}>
<div>{t('common.userProfile.settings')}</div>
</div>
</Menu.Item>
<Menu.Item>
<Link
className={classNames(itemClassName, 'group justify-between')}
href={
locale === 'zh-Hans' ? 'https://docs.dify.ai/v/zh-hans/' : 'https://docs.dify.ai/'
}
target='_blank'>
<div>{t('common.userProfile.helpCenter')}</div>
<ArrowUpRight className='hidden w-4 h-4 text-gray-500 group-hover:flex' />
</Link>
</Menu.Item>
<Menu.Item>
<div className={classNames(itemClassName, 'justify-between')} onClick={() => setAboutVisible(true)}>
<div>{t('common.userProfile.about')}</div>
<div className='flex items-center'>
<div className='mr-2 text-xs font-normal text-gray-500'>{langeniusVersionInfo.current_version}</div>
<Indicator color={langeniusVersionInfo.current_version === langeniusVersionInfo.latest_version ? 'green' : 'orange'} />
</div>
</div>
</Menu.Item>
</div>
<Menu.Item>
<div className='p-1' onClick={() => handleLogout()}>
<div
className='flex items-center justify-between h-9 px-3 rounded-lg cursor-pointer group hover:bg-gray-100'
>
<div className='font-normal text-[14px] text-gray-700'>{t('common.userProfile.logout')}</div>
<LogOut01 className='hidden w-4 h-4 text-gray-500 group-hover:flex' />
</div>
</div>
</Menu.Item>
</Menu.Items>
</Transition>
</>
)
}
</Menu> </Menu>
{ {
settingVisible && <AccountSetting onCancel={() => setSettingVisible(false)} /> settingVisible && <AccountSetting onCancel={() => setSettingVisible(false)} />
......
import { Fragment } from 'react' import { Fragment } from 'react'
import { switchWorkspace } from '@/service/common'
import { Menu, Transition } from '@headlessui/react'
import { ChevronRightIcon, CheckIcon } from '@heroicons/react/24/outline'
import cn from 'classnames'
import s from './index.module.css'
import { useContext } from 'use-context-selector' import { useContext } from 'use-context-selector'
import { ToastContext } from '@/app/components/base/toast'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
import { Menu, Transition } from '@headlessui/react'
import cn from 'classnames'
import s from './index.module.css'
import { switchWorkspace } from '@/service/common'
import { useWorkspacesContext } from '@/context/workspace-context' import { useWorkspacesContext } from '@/context/workspace-context'
import { ChevronRight } from '@/app/components/base/icons/src/vender/line/arrows'
import { Check } from '@/app/components/base/icons/src/vender/line/general'
import { ToastContext } from '@/app/components/base/toast'
const itemClassName = ` const itemClassName = `
flex items-center px-3 py-2 h-10 cursor-pointer flex items-center px-3 py-2 h-10 cursor-pointer
` `
const itemIconClassName = ` const itemIconClassName = `
shrink-0 mr-2 w-6 h-6 bg-[#EFF4FF] rounded-md shrink-0 mr-2 flex items-center justify-center w-6 h-6 bg-[#EFF4FF] rounded-md text-xs font-medium text-primary-600
` `
const itemNameClassName = ` const itemNameClassName = `
grow mr-2 text-sm text-gray-700 text-left grow mr-2 text-sm text-gray-700 text-left
...@@ -32,12 +33,12 @@ const WorkplaceSelector = () => { ...@@ -32,12 +33,12 @@ const WorkplaceSelector = () => {
const handleSwitchWorkspace = async (tenant_id: string) => { const handleSwitchWorkspace = async (tenant_id: string) => {
try { try {
await switchWorkspace({ url: `/workspaces/switch`, body: { tenant_id } }) await switchWorkspace({ url: '/workspaces/switch', body: { tenant_id } })
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') }) notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
router.replace('/apps') router.replace('/apps')
} catch (e) { }
catch (e) {
notify({ type: 'error', message: t('common.provider.saveFailed') }) notify({ type: 'error', message: t('common.provider.saveFailed') })
} finally {
} }
} }
...@@ -49,12 +50,12 @@ const WorkplaceSelector = () => { ...@@ -49,12 +50,12 @@ const WorkplaceSelector = () => {
<Menu.Button className={cn( <Menu.Button className={cn(
` `
${itemClassName} w-full ${itemClassName} w-full
group hover:bg-gray-50 cursor-pointer ${open && 'bg-gray-50'} group hover:bg-gray-50 cursor-pointer ${open && 'bg-gray-50'} rounded-lg
` `,
)}> )}>
<div className={itemIconClassName} /> <div className={itemIconClassName}>{currentWrokspace?.name[0].toLocaleUpperCase()}</div>
<div className={`${itemNameClassName} truncate`}>{currentWrokspace?.name}</div> <div className={`${itemNameClassName} truncate`}>{currentWrokspace?.name}</div>
<ChevronRightIcon className='shrink-0 w-[14px] h-[14px]' /> <ChevronRight className='shrink-0 w-[14px] h-[14px] text-gray-500' />
</Menu.Button> </Menu.Button>
<Transition <Transition
as={Fragment} as={Fragment}
...@@ -71,16 +72,16 @@ const WorkplaceSelector = () => { ...@@ -71,16 +72,16 @@ const WorkplaceSelector = () => {
absolute top-[1px] min-w-[200px] z-10 bg-white border-[0.5px] border-gray-200 absolute top-[1px] min-w-[200px] z-10 bg-white border-[0.5px] border-gray-200
divide-y divide-gray-100 origin-top-right rounded-xl divide-y divide-gray-100 origin-top-right rounded-xl
`, `,
s.popup s.popup,
)} )}
> >
<div className="px-1 py-1"> <div className="px-1 py-1">
{ {
workspaces.map(workspace => ( workspaces.map(workspace => (
<div className={itemClassName} key={workspace.id} onClick={() => handleSwitchWorkspace(workspace.id)}> <div className={itemClassName} key={workspace.id} onClick={() => handleSwitchWorkspace(workspace.id)}>
<div className={itemIconClassName} /> <div className={itemIconClassName}>{workspace.name[0].toLocaleUpperCase()}</div>
<div className={itemNameClassName}>{workspace.name}</div> <div className={itemNameClassName}>{workspace.name}</div>
{workspace.current && <CheckIcon className={itemCheckClassName} />} {workspace.current && <Check className={itemCheckClassName} />}
</div> </div>
)) ))
} }
...@@ -94,4 +95,4 @@ const WorkplaceSelector = () => { ...@@ -94,4 +95,4 @@ const WorkplaceSelector = () => {
) )
} }
export default WorkplaceSelector export default WorkplaceSelector
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment