mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-15 17:55:58 +08:00
wip: add webapp access control dialog
This commit is contained in:
parent
26f4f88ccc
commit
9368966d28
@ -0,0 +1,25 @@
|
|||||||
|
'use client'
|
||||||
|
import type { FC, PropsWithChildren } from 'react'
|
||||||
|
|
||||||
|
type AccessControlItemProps = PropsWithChildren<{
|
||||||
|
active: boolean
|
||||||
|
}>
|
||||||
|
|
||||||
|
const AccessControlItem: FC<AccessControlItemProps> = ({ active, children }) => {
|
||||||
|
if (!active) {
|
||||||
|
return <div className="rounded-[10px] border-[1px] cursor-pointer
|
||||||
|
border-components-option-card-option-border bg-components-option-card-option-bg
|
||||||
|
hover:border-components-option-card-option-border-hover hover:bg-components-option-card-option-bg-hover">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="rounded-[10px] border-[1.5px]
|
||||||
|
border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg shadow-sm">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
AccessControlItem.displayName = 'AccessControlItem'
|
||||||
|
|
||||||
|
export default AccessControlItem
|
@ -1,8 +1,11 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { Dialog } from '@headlessui/react'
|
import { Dialog } from '@headlessui/react'
|
||||||
|
import { RiBuildingLine, RiGlobalLine } from '@remixicon/react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import Button from '../../base/button'
|
import Button from '../../base/button'
|
||||||
import AccessControlDialog from './access-control-dialog'
|
import AccessControlDialog from './access-control-dialog'
|
||||||
|
import AccessControlItem from './access-control-item'
|
||||||
|
import SpecificGroupsOrMembers from './specific-groups-or-members'
|
||||||
|
|
||||||
type AccessControlProps = {
|
type AccessControlProps = {
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
@ -20,7 +23,21 @@ export default function AccessControl(props: AccessControlProps) {
|
|||||||
<div className='leading-6'>
|
<div className='leading-6'>
|
||||||
<p className='system-sm-medium'>{t('app.accessControlDialog.accessLabel')}</p>
|
<p className='system-sm-medium'>{t('app.accessControlDialog.accessLabel')}</p>
|
||||||
</div>
|
</div>
|
||||||
|
<AccessControlItem active={false}>
|
||||||
|
<div className='h-[40px] p-3 flex items-center gap-x-2'>
|
||||||
|
<RiBuildingLine className='w-4 h-4 text-text-primary' />
|
||||||
|
<p className='system-sm-medium text-text-primary'>{t('app.accessControlDialog.accessItems.organization')}</p>
|
||||||
|
</div>
|
||||||
|
</AccessControlItem>
|
||||||
|
<AccessControlItem active={true}>
|
||||||
|
<SpecificGroupsOrMembers active={true} />
|
||||||
|
</AccessControlItem>
|
||||||
|
<AccessControlItem active={false}>
|
||||||
|
<div className='h-[40px] p-3 flex items-center gap-x-2'>
|
||||||
|
<RiGlobalLine className='w-4 h-4 text-text-primary' />
|
||||||
|
<p className='system-sm-medium text-text-primary'>{t('app.accessControlDialog.accessItems.anyone')}</p>
|
||||||
|
</div>
|
||||||
|
</AccessControlItem>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex items-center justify-end p-6 pt-5 gap-x-2'>
|
<div className='flex items-center justify-end p-6 pt-5 gap-x-2'>
|
||||||
<Button onClick={props.onClose}>{t('common.operation.cancel')}</Button>
|
<Button onClick={props.onClose}>{t('common.operation.cancel')}</Button>
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
'use client'
|
||||||
|
import { RiAddCircleFill, RiCloseCircleFill, RiLockLine, RiOrganizationChart } from '@remixicon/react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import Avatar from '../../base/avatar'
|
||||||
|
import Button from '../../base/button'
|
||||||
|
|
||||||
|
type SpecificGroupsOrMembersProps = {
|
||||||
|
active: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function SpecificGroupsOrMembers(props: SpecificGroupsOrMembersProps) {
|
||||||
|
const { active } = props
|
||||||
|
const { t } = useTranslation()
|
||||||
|
if (!active) {
|
||||||
|
return <div className='h-[40px] p-3 flex items-center gap-x-2'>
|
||||||
|
<RiLockLine className='w-4 h-4 text-text-primary' />
|
||||||
|
<p className='system-sm-medium text-text-primary'>{t('app.accessControlDialog.accessItems.specific')}</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div>
|
||||||
|
<div className='flex items-center gap-x-1 p-3'>
|
||||||
|
<div className='grow flex items-center gap-x-1'>
|
||||||
|
<RiLockLine className='w-4 h-4 text-text-primary' />
|
||||||
|
<p className='system-sm-medium text-text-primary'>{t('app.accessControlDialog.accessItems.specific')}</p>
|
||||||
|
</div>
|
||||||
|
<Button variant='ghost-accent' size='small' className='shrink-0 flex items-center gap-x-0.5'>
|
||||||
|
<RiAddCircleFill className='w-4 h-4' />
|
||||||
|
<span>{t('common.operation.add')}</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className='px-1 pb-1'>
|
||||||
|
<div className='bg-background-section rounded-lg p-2 flex flex-col gap-y-2'>
|
||||||
|
<p className='system-2xs-medium-uppercase text-text-tertiary'>{t('app.accessControlDialog.groups', { count: 1 })}</p>
|
||||||
|
<div className='flex flex-row flex-wrap gap-1'>
|
||||||
|
<GroupItem />
|
||||||
|
</div>
|
||||||
|
<p className='system-2xs-medium-uppercase text-text-tertiary'>{t('app.accessControlDialog.members', { count: 4 })}</p>
|
||||||
|
<div className='flex flex-row flex-wrap gap-1'>
|
||||||
|
<MemberItem />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div >
|
||||||
|
}
|
||||||
|
function GroupItem() {
|
||||||
|
return <BaseItem icon={<RiOrganizationChart className='w-[14px] h-[14px] text-components-avatar-shape-fill-stop-0' />}>
|
||||||
|
<p className='system-xs-regular text-text-primary'>Group Name</p>
|
||||||
|
<p className='system-xs-regular text-text-tertiary'>7</p>
|
||||||
|
</BaseItem>
|
||||||
|
}
|
||||||
|
|
||||||
|
function MemberItem() {
|
||||||
|
return <BaseItem icon={<Avatar className='w-[14px] h-[14px]' textClassName='text-[12px]' avatar={null} name='M' />}>
|
||||||
|
<p className='system-xs-regular text-text-primary'>Member Name</p>
|
||||||
|
</BaseItem>
|
||||||
|
}
|
||||||
|
|
||||||
|
type BaseItemProps = {
|
||||||
|
icon: React.ReactNode
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
function BaseItem({ icon, children }: BaseItemProps) {
|
||||||
|
return <div className='rounded-full border-[0.5px] bg-components-badge-white-to-dark shadow-xs p-1 pr-1.5 group flex items-center flex-row gap-x-1'>
|
||||||
|
<div className='w-5 h-5 rounded-full bg-components-icon-bg-blue-solid overflow-hidden'>
|
||||||
|
<div className='w-full h-full flex items-center justify-center bg-access-app-icon-mask-bg'>
|
||||||
|
{icon}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{children}
|
||||||
|
<div className='flex items-center justify-center w-4 h-4 cursor-pointer'>
|
||||||
|
<RiCloseCircleFill className='w-[14px] h-[14px] text-text-quaternary' />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
@ -184,6 +184,10 @@ const translation = {
|
|||||||
specific: 'Specific groups or members',
|
specific: 'Specific groups or members',
|
||||||
organization: 'Only members within the organization',
|
organization: 'Only members within the organization',
|
||||||
},
|
},
|
||||||
|
groups_one: '{{count}} GROUP',
|
||||||
|
groups_other: '{{count}} GROUPS',
|
||||||
|
members_one: '{{count}} MEMBER',
|
||||||
|
members_other: '{{count}} MEMBERS',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,6 +185,10 @@ const translation = {
|
|||||||
specific: '特定组或用户',
|
specific: '特定组或用户',
|
||||||
organization: '组织内的任何人',
|
organization: '组织内的任何人',
|
||||||
},
|
},
|
||||||
|
groups_one: '{{count}} 个组',
|
||||||
|
groups_other: '{{count}} 个组',
|
||||||
|
members_one: '{{count}} 个人',
|
||||||
|
members_other: '{{count}} 个人',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,6 +107,7 @@ const config = {
|
|||||||
'dataset-option-card-purple-gradient': 'var(--color-dataset-option-card-purple-gradient)',
|
'dataset-option-card-purple-gradient': 'var(--color-dataset-option-card-purple-gradient)',
|
||||||
'dataset-option-card-orange-gradient': 'var(--color-dataset-option-card-orange-gradient)',
|
'dataset-option-card-orange-gradient': 'var(--color-dataset-option-card-orange-gradient)',
|
||||||
'dataset-chunk-list-mask-bg': 'var(--color-dataset-chunk-list-mask-bg)',
|
'dataset-chunk-list-mask-bg': 'var(--color-dataset-chunk-list-mask-bg)',
|
||||||
|
'access-app-icon-mask-bg': 'var(--color-access-app-icon-mask-bg)',
|
||||||
},
|
},
|
||||||
lineClamp: {
|
lineClamp: {
|
||||||
'20': '20',
|
'20': '20',
|
||||||
|
@ -1,24 +1,16 @@
|
|||||||
html[data-theme="dark"] {
|
html[data-theme="dark"] {
|
||||||
--color-chatbot-bg: linear-gradient(
|
--color-chatbot-bg: linear-gradient(180deg,
|
||||||
180deg,
|
|
||||||
rgba(34, 34, 37, 0.9) 0%,
|
rgba(34, 34, 37, 0.9) 0%,
|
||||||
rgba(29, 29, 32, 0.9) 90.48%
|
rgba(29, 29, 32, 0.9) 90.48%);
|
||||||
);
|
--color-chat-bubble-bg: linear-gradient(180deg,
|
||||||
--color-chat-bubble-bg: linear-gradient(
|
|
||||||
180deg,
|
|
||||||
rgba(200, 206, 218, 0.08) 0%,
|
rgba(200, 206, 218, 0.08) 0%,
|
||||||
rgba(200, 206, 218, 0.02) 100%
|
rgba(200, 206, 218, 0.02) 100%);
|
||||||
);
|
--color-workflow-process-bg: linear-gradient(90deg,
|
||||||
--color-workflow-process-bg: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
rgba(24, 24, 27, 0.25) 0%,
|
rgba(24, 24, 27, 0.25) 0%,
|
||||||
rgba(24, 24, 27, 0.04) 100%
|
rgba(24, 24, 27, 0.04) 100%);
|
||||||
);
|
--color-account-teams-bg: linear-gradient(271deg,
|
||||||
--color-account-teams-bg: linear-gradient(
|
|
||||||
271deg,
|
|
||||||
rgba(34, 34, 37, 0.9) -0.1%,
|
rgba(34, 34, 37, 0.9) -0.1%,
|
||||||
rgba(29, 29, 32, 0.9) 98.26%
|
rgba(29, 29, 32, 0.9) 98.26%);
|
||||||
);
|
|
||||||
--color-dataset-chunk-process-success-bg: linear-gradient(92deg, rgba(23, 178, 106, 0.30) 0%, rgba(0, 0, 0, 0.00) 100%);
|
--color-dataset-chunk-process-success-bg: linear-gradient(92deg, rgba(23, 178, 106, 0.30) 0%, rgba(0, 0, 0, 0.00) 100%);
|
||||||
--color-dataset-chunk-process-error-bg: linear-gradient(92deg, rgba(240, 68, 56, 0.30) 0%, rgba(0, 0, 0, 0.00) 100%);
|
--color-dataset-chunk-process-error-bg: linear-gradient(92deg, rgba(240, 68, 56, 0.30) 0%, rgba(0, 0, 0, 0.00) 100%);
|
||||||
--color-dataset-chunk-detail-card-hover-bg: linear-gradient(180deg, #1D1D20 0%, #222225 100%);
|
--color-dataset-chunk-detail-card-hover-bg: linear-gradient(180deg, #1D1D20 0%, #222225 100%);
|
||||||
@ -27,9 +19,8 @@ html[data-theme="dark"] {
|
|||||||
--color-dataset-option-card-purple-gradient: linear-gradient(90deg, #25242E 0%, #1E1E21 100%);
|
--color-dataset-option-card-purple-gradient: linear-gradient(90deg, #25242E 0%, #1E1E21 100%);
|
||||||
--color-dataset-option-card-orange-gradient: linear-gradient(90deg, #2B2322 0%, #1E1E21 100%);
|
--color-dataset-option-card-orange-gradient: linear-gradient(90deg, #2B2322 0%, #1E1E21 100%);
|
||||||
--color-dataset-chunk-list-mask-bg: linear-gradient(180deg, rgba(34, 34, 37, 0.00) 0%, #222225 100%);
|
--color-dataset-chunk-list-mask-bg: linear-gradient(180deg, rgba(34, 34, 37, 0.00) 0%, #222225 100%);
|
||||||
--mask-top2bottom-gray-50-to-transparent: linear-gradient(
|
--mask-top2bottom-gray-50-to-transparent: linear-gradient(180deg,
|
||||||
180deg,
|
|
||||||
rgba(24, 24, 27, 0.08) 0%,
|
rgba(24, 24, 27, 0.08) 0%,
|
||||||
rgba(0, 0, 0, 0) 100%
|
rgba(0, 0, 0, 0) 100%);
|
||||||
);
|
--color-access-app-icon-mask-bg: linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.03) 100%);
|
||||||
}
|
}
|
@ -1,24 +1,16 @@
|
|||||||
html[data-theme="light"] {
|
html[data-theme="light"] {
|
||||||
--color-chatbot-bg: linear-gradient(
|
--color-chatbot-bg: linear-gradient(180deg,
|
||||||
180deg,
|
|
||||||
rgba(249, 250, 251, 0.9) 0%,
|
rgba(249, 250, 251, 0.9) 0%,
|
||||||
rgba(242, 244, 247, 0.9) 90.48%
|
rgba(242, 244, 247, 0.9) 90.48%);
|
||||||
);
|
--color-chat-bubble-bg: linear-gradient(180deg,
|
||||||
--color-chat-bubble-bg: linear-gradient(
|
|
||||||
180deg,
|
|
||||||
#fff 0%,
|
#fff 0%,
|
||||||
rgba(255, 255, 255, 0.6) 100%
|
rgba(255, 255, 255, 0.6) 100%);
|
||||||
);
|
--color-workflow-process-bg: linear-gradient(90deg,
|
||||||
--color-workflow-process-bg: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
rgba(200, 206, 218, 0.2) 0%,
|
rgba(200, 206, 218, 0.2) 0%,
|
||||||
rgba(200, 206, 218, 0.04) 100%
|
rgba(200, 206, 218, 0.04) 100%);
|
||||||
);
|
--color-account-teams-bg: linear-gradient(271deg,
|
||||||
--color-account-teams-bg: linear-gradient(
|
|
||||||
271deg,
|
|
||||||
rgba(249, 250, 251, 0.9) -0.1%,
|
rgba(249, 250, 251, 0.9) -0.1%,
|
||||||
rgba(242, 244, 247, 0.9) 98.26%
|
rgba(242, 244, 247, 0.9) 98.26%);
|
||||||
);
|
|
||||||
--color-dataset-chunk-process-success-bg: linear-gradient(92deg, rgba(23, 178, 106, 0.25) 0%, rgba(255, 255, 255, 0.00) 100%);
|
--color-dataset-chunk-process-success-bg: linear-gradient(92deg, rgba(23, 178, 106, 0.25) 0%, rgba(255, 255, 255, 0.00) 100%);
|
||||||
--color-dataset-chunk-process-error-bg: linear-gradient(92deg, rgba(240, 68, 56, 0.25) 0%, rgba(255, 255, 255, 0.00) 100%);
|
--color-dataset-chunk-process-error-bg: linear-gradient(92deg, rgba(240, 68, 56, 0.25) 0%, rgba(255, 255, 255, 0.00) 100%);
|
||||||
--color-dataset-chunk-detail-card-hover-bg: linear-gradient(180deg, #F2F4F7 0%, #F9FAFB 100%);
|
--color-dataset-chunk-detail-card-hover-bg: linear-gradient(180deg, #F2F4F7 0%, #F9FAFB 100%);
|
||||||
@ -27,9 +19,8 @@ html[data-theme="light"] {
|
|||||||
--color-dataset-option-card-purple-gradient: linear-gradient(90deg, #F0EEFA 0%, #F9FAFB 100%);
|
--color-dataset-option-card-purple-gradient: linear-gradient(90deg, #F0EEFA 0%, #F9FAFB 100%);
|
||||||
--color-dataset-option-card-orange-gradient: linear-gradient(90deg, #F8F2EE 0%, #F9FAFB 100%);
|
--color-dataset-option-card-orange-gradient: linear-gradient(90deg, #F8F2EE 0%, #F9FAFB 100%);
|
||||||
--color-dataset-chunk-list-mask-bg: linear-gradient(180deg, rgba(255, 255, 255, 0.00) 0%, #FCFCFD 100%);
|
--color-dataset-chunk-list-mask-bg: linear-gradient(180deg, rgba(255, 255, 255, 0.00) 0%, #FCFCFD 100%);
|
||||||
--mask-top2bottom-gray-50-to-transparent: linear-gradient(
|
--mask-top2bottom-gray-50-to-transparent: linear-gradient(180deg,
|
||||||
180deg,
|
|
||||||
rgba(200, 206, 218, 0.2) 0%,
|
rgba(200, 206, 218, 0.2) 0%,
|
||||||
rgba(255, 255, 255, 0) 100%
|
rgba(255, 255, 255, 0) 100%);
|
||||||
);
|
--color-access-app-icon-mask-bg: linear-gradient(135deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.08) 100%);
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user