diff --git a/web/app/components/app-sidebar/app-info.tsx b/web/app/components/app-sidebar/app-info.tsx index 7c41811ebd..16225dd6b3 100644 --- a/web/app/components/app-sidebar/app-info.tsx +++ b/web/app/components/app-sidebar/app-info.tsx @@ -14,14 +14,13 @@ import { } from '@remixicon/react' import AppIcon from '../base/app-icon' import SwitchAppModal from '../app/switch-app-modal' -import AccessControl from '../app/app-access-control' import cn from '@/utils/classnames' import Confirm from '@/app/components/base/confirm' import { useStore as useAppStore } from '@/app/components/app/store' import { ToastContext } from '@/app/components/base/toast' import AppsContext, { useAppContext } from '@/context/app-context' import { useProviderContext } from '@/context/provider-context' -import { copyApp, deleteApp, exportAppConfig, fetchAppDetail, updateAppInfo } from '@/service/apps' +import { copyApp, deleteApp, exportAppConfig, updateAppInfo } from '@/service/apps' import DuplicateAppModal from '@/app/components/app/duplicate-modal' import type { DuplicateAppModalProps } from '@/app/components/app/duplicate-modal' import CreateAppModal from '@/app/components/explore/create-app-modal' @@ -55,7 +54,6 @@ const AppInfo = ({ expand }: IAppInfoProps) => { const [showConfirmDelete, setShowConfirmDelete] = useState(false) const [showSwitchModal, setShowSwitchModal] = useState(false) const [showImportDSLModal, setShowImportDSLModal] = useState(false) - const [showAccessControl, setShowAccessControl] = useState(false) const [secretEnvList, setSecretEnvList] = useState([]) const mutateApps = useContextSelector( @@ -183,19 +181,6 @@ const AppInfo = ({ expand }: IAppInfoProps) => { setShowConfirmDelete(false) }, [appDetail, mutateApps, notify, onPlanInfoChanged, replace, setAppDetail, t]) - const handleClickAccessControl = useCallback(() => { - if (!appDetail) - return - setShowAccessControl(true) - setOpen(false) - }, [appDetail]) - const handleAccessControlUpdate = useCallback(() => { - fetchAppDetail({ url: '/apps', id: appDetail!.id }).then((res) => { - setAppDetail(res) - setShowAccessControl(false) - }) - }, [appDetail, setAppDetail]) - const { isCurrentWorkspaceEditor } = useAppContext() const [showMore, setShowMore] = useState(false) @@ -353,10 +338,6 @@ const AppInfo = ({ expand }: IAppInfoProps) => { /> - {/* TODO update style figma */} -
- {t('app.accessControl')} -
) } diff --git a/web/app/components/app/overview/appCard.tsx b/web/app/components/app/overview/appCard.tsx index 7c12f1edee..42ba5ef36f 100644 --- a/web/app/components/app/overview/appCard.tsx +++ b/web/app/components/app/overview/appCard.tsx @@ -1,11 +1,13 @@ 'use client' -import React, { useMemo, useState } from 'react' +import React, { useCallback, useEffect, useMemo, useState } from 'react' import { usePathname, useRouter } from 'next/navigation' import { useTranslation } from 'react-i18next' import { + RiArrowRightSLine, RiBookOpenLine, RiEqualizer2Line, RiExternalLinkLine, + RiLockLine, RiPaintBrushLine, RiWindowLine, } from '@remixicon/react' @@ -17,6 +19,7 @@ import type { ConfigParams } from './settings' import Tooltip from '@/app/components/base/tooltip' import AppBasic from '@/app/components/app-sidebar/basic' import { asyncRunSafe, randomString } from '@/utils' +import { useStore as useAppStore } from '@/app/components/app/store' import { basePath } from '@/utils/var' import Button from '@/app/components/base/button' import Switch from '@/app/components/base/switch' @@ -29,6 +32,11 @@ import type { AppDetailResponse } from '@/models/app' import { useAppContext } from '@/context/app-context' import type { AppSSO } from '@/types/app' import Indicator from '@/app/components/header/indicator' +import { fetchAppDetail } from '@/service/apps' +import { AccessMode } from '@/models/access-control' +import AccessControl from '../app-access-control' +import { useAppWhiteListSubjects } from '@/service/access-control' +import { useGlobalPublicStore } from '@/context/global-public-context' export type IAppCardProps = { className?: string @@ -54,13 +62,17 @@ function AppCard({ const router = useRouter() const pathname = usePathname() const { isCurrentWorkspaceManager, isCurrentWorkspaceEditor } = useAppContext() + const appDetail = useAppStore(state => state.appDetail) + const setAppDetail = useAppStore(state => state.setAppDetail) const [showSettingsModal, setShowSettingsModal] = useState(false) const [showEmbedded, setShowEmbedded] = useState(false) const [showCustomizeModal, setShowCustomizeModal] = useState(false) const [genLoading, setGenLoading] = useState(false) const [showConfirmDelete, setShowConfirmDelete] = useState(false) - + const [showAccessControl, setShowAccessControl] = useState(false) const { t } = useTranslation() + const systemFeatures = useGlobalPublicStore(s => s.systemFeatures) + const { data: appAccessSubjects } = useAppWhiteListSubjects(appDetail?.id, systemFeatures.webapp_auth.enabled && appDetail?.access_mode === AccessMode.SPECIFIC_GROUPS_MEMBERS) const OPERATIONS_MAP = useMemo(() => { const operationsMap = { @@ -128,6 +140,31 @@ function AppCard({ } } + const [isAppAccessSet, setIsAppAccessSet] = useState(true) + useEffect(() => { + if (appDetail && appAccessSubjects) { + if (appDetail.access_mode === AccessMode.SPECIFIC_GROUPS_MEMBERS && appAccessSubjects.groups?.length === 0 && appAccessSubjects.members?.length === 0) + setIsAppAccessSet(false) + else + setIsAppAccessSet(true) + } + else { + setIsAppAccessSet(true) + } + }, [appAccessSubjects, appDetail]) + + const handleClickAccessControl = useCallback(() => { + if (!appDetail) + return + setShowAccessControl(true) + }, [appDetail]) + const handleAccessControlUpdate = useCallback(() => { + fetchAppDetail({ url: '/apps', id: appDetail!.id }).then((res) => { + setAppDetail(res) + setShowAccessControl(false) + }) + }, [appDetail, setAppDetail]) + return (
+ {isApp && systemFeatures.webapp_auth.enabled && appDetail &&
+
{t('app.publishApp.title')}
+
+
+ + {appDetail?.access_mode === AccessMode.ORGANIZATION &&

{t('app.accessControlDialog.accessItems.organization')}

} + {appDetail?.access_mode === AccessMode.SPECIFIC_GROUPS_MEMBERS &&

{t('app.accessControlDialog.accessItems.specific')}

} + {appDetail?.access_mode === AccessMode.PUBLIC &&

{t('app.accessControlDialog.accessItems.anyone')}

} +
+ {!isAppAccessSet &&

{t('app.publishApp.notSet')}

} +
+ +
+
+
}
{!isApp && } @@ -264,6 +317,11 @@ function AppCard({ api_base_url={appInfo.api_base_url} mode={appInfo.mode} /> + { + showAccessControl && { setShowAccessControl(false) }} /> + } ) : null}