feat: uninstall

pull/198/head
金伟强 3 years ago
parent a2d2ca4348
commit daffb79180

@ -8,16 +8,20 @@ import s from './style.module.css'
export interface IItemOperationProps { export interface IItemOperationProps {
className?: string className?: string
onDelete: () => void
} }
const ItemOperation: FC<IItemOperationProps> = ({ const ItemOperation: FC<IItemOperationProps> = ({
className, className,
onDelete
}) => { }) => {
return ( return (
<Popover <Popover
htmlContent={ htmlContent={
<div className='w-full py-1'> <div className='w-full py-1' onClick={(e) => {
<div className={cn(s.actionItem, s.deleteActionItem, 'hover:bg-gray-50 group')} onClick={() => {}}> e.stopPropagation()
}}>
<div className={cn(s.actionItem, s.deleteActionItem, 'hover:bg-gray-50 group')} onClick={onDelete} >
<TrashIcon className={'w-4 h-4 stroke-current text-gray-500 stroke-2 group-hover:text-red-500'} /> <TrashIcon className={'w-4 h-4 stroke-current text-gray-500 stroke-2 group-hover:text-red-500'} />
<span className={cn(s.actionName, 'group-hover:text-red-500')}>{'Delete'}</span> <span className={cn(s.actionName, 'group-hover:text-red-500')}>{'Delete'}</span>
</div> </div>
@ -25,9 +29,9 @@ const ItemOperation: FC<IItemOperationProps> = ({
} }
trigger='click' trigger='click'
position='br' position='br'
btnElement={<div className={cn(s.actionIcon, s.commonIcon)} />} btnElement={<div />}
btnClassName={(open) => cn(className, 'h-6 w-6 rounded-md border-none p-1 bg-transparent hover:bg-gray-100', open && '!bg-gray-100 !shadow-none')} btnClassName={(open) => cn(className, s.btn, 'h-6 w-6 rounded-md border-none p-1', open && '!bg-gray-100 !shadow-none')}
className={`!w-[200px] h-fit !z-20`} className={`!w-[120px] h-fit !z-20`}
/> />
) )
} }

@ -17,4 +17,15 @@
.actionIcon { .actionIcon {
@apply bg-gray-500; @apply bg-gray-500;
mask-image: url(~@/app/components/datasets/documents/assets/action.svg); mask-image: url(~@/app/components/datasets/documents/assets/action.svg);
}
body .btn {
background: url(~@/app/components/datasets/documents/assets/action.svg) center center no-repeat transparent;
background-size: 16px 16px;
/* mask-image: ; */
}
body .btn:hover {
/* background-image: ; */
background-color: #F2F4F7;
} }

@ -1,6 +1,6 @@
'use client' 'use client'
import cn from 'classnames' import cn from 'classnames'
import Link from 'next/link' import { useRouter } from 'next/navigation'
import ItemOperation from '@/app/components/explore/item-operation' import ItemOperation from '@/app/components/explore/item-operation'
import s from './style.module.css' import s from './style.module.css'
@ -9,36 +9,49 @@ export default function NavLink({
name, name,
id, id,
isSelected, isSelected,
onDelete
}: { }: {
name: string name: string
id: string id: string
isSelected: boolean isSelected: boolean
onDelete: (id: string) => void
}) { }) {
const router = useRouter()
const url = `/explore/installed/${id}` const url = `/explore/installed/${id}`
return ( return (
<Link <div
prefetch key={id}
key={name}
href={url}
className={cn( className={cn(
s.item, s.item,
isSelected && s.active, isSelected ? s.active : 'hover:bg-gray-200',
'flex h-8 items-center px-2 rounded-lg text-sm font-normal hover:bg-gray-200', 'flex h-8 justify-between px-2 rounded-lg text-sm font-normal ',
)} )}
onClick={() => {
router.push(url) // use Link causes popup item always trigger jump. Can not be solved by e.stopPropagation().
}}
> >
<div <div className='flex items-center'>
className={cn( <div
'shrink-0 mr-2 h-6 w-6 rounded-md border bg-[#D5F5F6]', className={cn(
)} 'shrink-0 mr-2 h-6 w-6 rounded-md border bg-[#D5F5F6]',
style={{ )}
borderColor: '0.5px solid rgba(0, 0, 0, 0.05)' style={{
}} borderColor: '0.5px solid rgba(0, 0, 0, 0.05)'
/> }}
<div className='overflow-hidden text-ellipsis whitespace-nowrap'>{name}</div> />
<div onClick={e => e.stopPropagation()}> <div className='max-w-[110px] overflow-hidden text-ellipsis whitespace-nowrap'>{name}</div>
<ItemOperation className={s.opBtn} />
</div> </div>
</Link> {
!isSelected && (
<div className={cn(s.opBtn, 'shrink-0')} onClick={e => e.stopPropagation()}>
<ItemOperation
// isShowDelete={}
onDelete={() => onDelete(id)}
/>
</div>
)
}
</div>
) )
} }

@ -8,6 +8,10 @@
font-weight: 500; font-weight: 500;
} }
.opBtn {
visibility: hidden;
}
.item:hover .opBtn { .item:hover .opBtn {
background-color: #F2F4F7; visibility: visible;
} }

@ -7,7 +7,7 @@ import cn from 'classnames'
import { useSelectedLayoutSegments } from 'next/navigation' import { useSelectedLayoutSegments } from 'next/navigation'
import Link from 'next/link' import Link from 'next/link'
import Item from './app-nav-item' import Item from './app-nav-item'
import { fetchInstalledAppList as doFetchInstalledAppList } from '@/service/explore' import { fetchInstalledAppList as doFetchInstalledAppList, uninstallApp } from '@/service/explore'
const SelectedDiscoveryIcon = () => ( const SelectedDiscoveryIcon = () => (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
@ -37,6 +37,11 @@ const SideBar: FC<{
setInstalledApps(installed_apps) setInstalledApps(installed_apps)
} }
const handleDelete = async (id: string) => {
await uninstallApp(id)
fetchInstalledAppList()
}
useEffect(() => { useEffect(() => {
fetchInstalledAppList() fetchInstalledAppList()
}, []) }, [])
@ -63,7 +68,13 @@ const SideBar: FC<{
<div className='mt-3 space-y-1'> <div className='mt-3 space-y-1'>
{installedApps.map(({id, app : { name }}) => { {installedApps.map(({id, app : { name }}) => {
return ( return (
<Item key={id} name={name} id={id} isSelected={lastSegment?.toLowerCase() === id} /> <Item
key={id}
name={name}
id={id}
isSelected={lastSegment?.toLowerCase() === id}
onDelete={handleDelete}
/>
) )
})} })}
</div> </div>

@ -1,4 +1,4 @@
import { get, post } from './base' import { get, post, del } from './base'
export const fetchAppList = () => { export const fetchAppList = () => {
return get('/explore/apps') return get('/explore/apps')
@ -19,3 +19,7 @@ export const installApp = (id: string) => {
} }
}) })
} }
export const uninstallApp = (id: string) => {
return del(`/installed-apps/${id}`)
}

Loading…
Cancel
Save