diff --git a/web/app/components/apps/app-card.tsx b/web/app/components/apps/app-card.tsx index 2983f80f58..bebeab17f9 100644 --- a/web/app/components/apps/app-card.tsx +++ b/web/app/components/apps/app-card.tsx @@ -11,7 +11,6 @@ import { useCallback, useMemo, useState, useTransition } from 'react' import { useTranslation } from 'react-i18next' import { AppTypeIcon } from '@/app/components/app/type-selector' import AppIcon from '@/app/components/base/app-icon' -import Divider from '@/app/components/base/divider' import TagSelector from '@/app/components/base/tag-management/selector' import { AlertDialog, @@ -23,16 +22,14 @@ import { AlertDialogTitle, } from '@/app/components/base/ui/alert-dialog' import { - Popover, - PopoverContent, - PopoverTrigger, -} from '@/app/components/base/ui/popover' + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from '@/app/components/base/ui/dropdown-menu' import { toast } from '@/app/components/base/ui/toast' -import { - Tooltip, - TooltipContent, - TooltipTrigger, -} from '@/app/components/base/ui/tooltip' +import { Tooltip, TooltipContent, TooltipTrigger } from '@/app/components/base/ui/tooltip' import { UserAvatarList } from '@/app/components/base/user-avatar-list' import { NEED_REFRESH_APP_LIST_KEY } from '@/config' import { useAppContext } from '@/context/app-context' @@ -72,12 +69,14 @@ const AccessControl = dynamic(() => import('@/app/components/app/app-access-cont type AppCardOperationsProps = { app: App + open: boolean webappAuthEnabled: boolean isCurrentWorkspaceEditor: boolean exporting: boolean secretEnvListLength: number isUpgradingRuntime: boolean popupClassName: string + onOpenChange: (open: boolean) => void onEdit: () => void onDuplicate: () => void onExport: () => void @@ -90,12 +89,14 @@ type AppCardOperationsProps = { const AppCardOperations = ({ app, + open, webappAuthEnabled, isCurrentWorkspaceEditor, exporting, secretEnvListLength, isUpgradingRuntime, popupClassName, + onOpenChange, onEdit, onDuplicate, onExport, @@ -106,67 +107,56 @@ const AppCardOperations = ({ onUpgradeRuntime, }: AppCardOperationsProps) => { const { t } = useTranslation() - const [open, setOpen] = useState(false) const { data: userCanAccessApp, isLoading: isGettingUserCanAccessApp } = useGetUserCanAccessApp({ appId: app.id, enabled: !!open && webappAuthEnabled, }) - const onMouseLeave = () => { - setOpen(false) - } - const onClickInstalledApp = async () => { onInstalledApp() - onMouseLeave() } const onClickUpgradeRuntime = async () => { onUpgradeRuntime() - onMouseLeave() } return ( - - - {t('operation.more', { ns: 'common' })} - - + + - + + + -
- - - - + {(app.mode === AppModeEnum.COMPLETION || app.mode === AppModeEnum.CHAT) && ( <> - - + )} { @@ -174,59 +164,54 @@ const AppCardOperations = ({ (!webappAuthEnabled) ? ( <> - - + ) : !(isGettingUserCanAccessApp || !userCanAccessApp?.result) && ( <> - - + ) ) } - + { webappAuthEnabled && isCurrentWorkspaceEditor && ( <> - - + + ) } {app.runtime_type !== 'sandboxed' && (app.mode === AppModeEnum.WORKFLOW || app.mode === AppModeEnum.ADVANCED_CHAT) && ( - + )} - +
- -
+ + ) } @@ -251,6 +236,7 @@ const AppCard = ({ app, onRefresh, onlineUsers = [] }: AppCardProps) => { const [confirmDeleteInput, setConfirmDeleteInput] = useState('') const [showAccessControl, setShowAccessControl] = useState(false) const [secretEnvList, setSecretEnvList] = useState([]) + const [isOperationsOpen, setIsOperationsOpen] = useState(false) const [exporting, startExport] = useTransition() const { mutateAsync: mutateDeleteApp, isPending: isDeleting } = useDeleteAppMutation() @@ -458,84 +444,81 @@ const AppCard = ({ app, onRefresh, onlineUsers = [] }: AppCardProps) => { return ( <>
{ - e.preventDefault() - getRedirection(isCurrentWorkspaceEditor, app, push) - }} - className="group relative col-span-1 inline-flex h-[160px] cursor-pointer flex-col rounded-xl border-[1px] border-solid border-components-card-border bg-components-card-bg shadow-sm transition-all duration-200 ease-in-out hover:shadow-lg" + className="group relative col-span-1 inline-flex h-[160px] flex-col rounded-xl border-[1px] border-solid border-components-card-border bg-components-card-bg shadow-sm transition-all duration-200 ease-in-out hover:shadow-lg" > -
-
- - -
-
-
-
{app.name}
+
{isCurrentWorkspaceEditor && ( <> -
{ - e.stopPropagation() - e.preventDefault() - }} - > -
+
+
{ />
-
-
+
+
{ ? 'w-[256px]' : 'w-[216px]' } + onOpenChange={setIsOperationsOpen} onEdit={handleOpenEditModal} onDuplicate={handleOpenDuplicateModal} onExport={handleExport}