wip: show web app access control menu in app card and app detail
parent
1045f6db7a
commit
26f4f88ccc
@ -0,0 +1,59 @@
|
|||||||
|
import { Fragment, useCallback } from 'react'
|
||||||
|
import type { ReactNode } from 'react'
|
||||||
|
import { Dialog, Transition } from '@headlessui/react'
|
||||||
|
import { RiCloseLine } from '@remixicon/react'
|
||||||
|
import cn from '@/utils/classnames'
|
||||||
|
|
||||||
|
type DialogProps = {
|
||||||
|
className?: string
|
||||||
|
children: ReactNode
|
||||||
|
show: boolean
|
||||||
|
onClose?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const AccessControlDialog = ({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
show,
|
||||||
|
onClose,
|
||||||
|
}: DialogProps) => {
|
||||||
|
const close = useCallback(() => onClose?.(), [onClose])
|
||||||
|
return (
|
||||||
|
<Transition appear show={show} as={Fragment}>
|
||||||
|
<Dialog as="div" open={true} className="relative z-40" onClose={close}>
|
||||||
|
<Transition.Child
|
||||||
|
as={Fragment}
|
||||||
|
enter="ease-out duration-300"
|
||||||
|
enterFrom="opacity-0"
|
||||||
|
enterTo="opacity-100"
|
||||||
|
leave="ease-in duration-200"
|
||||||
|
leaveFrom="opacity-100"
|
||||||
|
leaveTo="opacity-0"
|
||||||
|
>
|
||||||
|
<div className="fixed inset-0 bg-background-overlay bg-opacity-25" />
|
||||||
|
</Transition.Child>
|
||||||
|
|
||||||
|
<div className="fixed inset-0 flex items-center justify-center">
|
||||||
|
<Transition.Child
|
||||||
|
as={Fragment}
|
||||||
|
enter="ease-out duration-300"
|
||||||
|
enterFrom="opacity-0 scale-95"
|
||||||
|
enterTo="opacity-100 scale-100"
|
||||||
|
leave="ease-in duration-200"
|
||||||
|
leaveFrom="opacity-100 scale-100"
|
||||||
|
leaveTo="opacity-0 scale-95"
|
||||||
|
>
|
||||||
|
<Dialog.Panel className={cn('w-[600px] min-h-[323px] h-auto bg-components-panel-bg shadow-xl rounded-2xl transition-all transform relative p-0 overflow-y-auto', className)}>
|
||||||
|
<div onClick={close} className="absolute top-5 right-5 w-8 h-8 flex items-center justify-center cursor-pointer z-10">
|
||||||
|
<RiCloseLine className='w-5 h-5' />
|
||||||
|
</div>
|
||||||
|
{children}
|
||||||
|
</Dialog.Panel>
|
||||||
|
</Transition.Child>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
</Transition >
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AccessControlDialog
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
'use client'
|
||||||
|
import { Dialog } from '@headlessui/react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import Button from '../../base/button'
|
||||||
|
import AccessControlDialog from './access-control-dialog'
|
||||||
|
|
||||||
|
type AccessControlProps = {
|
||||||
|
onClose: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AccessControl(props: AccessControlProps) {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
return <AccessControlDialog show onClose={props.onClose}>
|
||||||
|
<div className='flex flex-col gap-y-3'>
|
||||||
|
<div className='pt-6 pr-14 pb-3 pl-6'>
|
||||||
|
<Dialog.Title className='title-2xl-semi-bold text-text-primary'>{t('app.accessControlDialog.title')}</Dialog.Title>
|
||||||
|
<Dialog.Description className='mt-1 system-xs-regular text-text-tertiary'>{t('app.accessControlDialog.description')}</Dialog.Description>
|
||||||
|
</div>
|
||||||
|
<div className='px-6 pb-3 flex flex-col gap-y-1'>
|
||||||
|
<div className='leading-6'>
|
||||||
|
<p className='system-sm-medium'>{t('app.accessControlDialog.accessLabel')}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className='flex items-center justify-end p-6 pt-5 gap-x-2'>
|
||||||
|
<Button onClick={props.onClose}>{t('common.operation.cancel')}</Button>
|
||||||
|
<Button variant='primary'>{t('common.operation.confirm')}</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</AccessControlDialog>
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue