diff --git a/components/dashboard/src/Insights.tsx b/components/dashboard/src/Insights.tsx index 08b291341b629a..4db31ed2b8427c 100644 --- a/components/dashboard/src/Insights.tsx +++ b/components/dashboard/src/Insights.tsx @@ -26,7 +26,7 @@ import { useTemporaryState } from "./hooks/use-temporary-value"; import { DownloadIcon } from "lucide-react"; import { Button } from "@podkit/buttons/Button"; import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "@podkit/dropdown/DropDown"; -import { useInstallationConfiguration } from "./data/installation/default-workspace-image-query"; +import { useInstallationConfiguration } from "./data/installation/installation-config-query"; export const Insights = () => { const toDate = useMemo(() => Timestamp.fromDate(new Date()), []); diff --git a/components/dashboard/src/data/installation/default-workspace-image-query.ts b/components/dashboard/src/data/installation/default-workspace-image-query.ts index 6b866b19fb2743..1ed3be36fce7e8 100644 --- a/components/dashboard/src/data/installation/default-workspace-image-query.ts +++ b/components/dashboard/src/data/installation/default-workspace-image-query.ts @@ -17,14 +17,3 @@ export const useInstallationDefaultWorkspaceImageQuery = () => { }, }); }; - -export const useInstallationConfiguration = () => { - return useQuery({ - queryKey: ["installation-configuration"], - staleTime: 1000 * 60 * 10, // 10 minute - queryFn: async () => { - const response = await installationClient.getInstallationConfiguration({}); - return response.configuration; - }, - }); -}; diff --git a/components/dashboard/src/data/installation/installation-config-query.ts b/components/dashboard/src/data/installation/installation-config-query.ts new file mode 100644 index 00000000000000..4c3ed48c223224 --- /dev/null +++ b/components/dashboard/src/data/installation/installation-config-query.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2025 Gitpod GmbH. All rights reserved. + * Licensed under the GNU Affero General Public License (AGPL). + * See License.AGPL.txt in the project root for license information. + */ + +import { useQuery } from "@tanstack/react-query"; +import { installationClient } from "../../service/public-api"; + +export const useInstallationConfiguration = () => { + return useQuery({ + queryKey: ["installation-configuration"], + staleTime: 1000 * 60 * 30, // 30 minutes + cacheTime: 1000 * 60 * 60 * 24, // 24 hours + queryFn: async () => { + const response = await installationClient.getInstallationConfiguration({}); + return response.configuration; + }, + }); +}; diff --git a/components/dashboard/src/dedicated-setup/use-needs-setup.ts b/components/dashboard/src/dedicated-setup/use-needs-setup.ts index 3f77c89f64d56a..1d54244a8fcc4a 100644 --- a/components/dashboard/src/dedicated-setup/use-needs-setup.ts +++ b/components/dashboard/src/dedicated-setup/use-needs-setup.ts @@ -8,10 +8,10 @@ import { useQuery } from "@tanstack/react-query"; import { noPersistence } from "../data/setup"; import { installationClient } from "../service/public-api"; import { GetOnboardingStateRequest } from "@gitpod/public-api/lib/gitpod/v1/installation_pb"; -import { useInstallationConfiguration } from "../data/installation/default-workspace-image-query"; +import { useInstallationConfiguration } from "../data/installation/installation-config-query"; /** - * @description Returns a flage stating if the current installation still needs setup before it can be used. Also returns an isLoading indicator as the check is async + * @description Returns a flag stating if the current installation still needs setup before it can be used. Also returns an isLoading indicator as the check is async */ export const useNeedsSetup = () => { const { data: onboardingState, isLoading } = useOnboardingState(); diff --git a/components/dashboard/src/dedicated-setup/use-show-dedicated-setup.ts b/components/dashboard/src/dedicated-setup/use-show-dedicated-setup.ts index 4c329c360f2f3c..cefe864be0bf1a 100644 --- a/components/dashboard/src/dedicated-setup/use-show-dedicated-setup.ts +++ b/components/dashboard/src/dedicated-setup/use-show-dedicated-setup.ts @@ -7,7 +7,7 @@ import { useQueryParams } from "../hooks/use-query-params"; import { useCallback, useState } from "react"; import { isCurrentHostExcludedFromSetup, useNeedsSetup } from "./use-needs-setup"; -import { useInstallationConfiguration } from "../data/installation/default-workspace-image-query"; +import { useInstallationConfiguration } from "../data/installation/installation-config-query"; const FORCE_SETUP_PARAM = "dedicated-setup"; const FORCE_SETUP_PARAM_VALUE = "force"; diff --git a/components/dashboard/src/menu/Menu.tsx b/components/dashboard/src/menu/Menu.tsx index 8b8273ea372da3..773adef745f16e 100644 --- a/components/dashboard/src/menu/Menu.tsx +++ b/components/dashboard/src/menu/Menu.tsx @@ -15,13 +15,13 @@ import { Separator } from "../components/Separator"; import PillMenuItem from "../components/PillMenuItem"; import { PaymentContext } from "../payment-context"; import FeedbackFormModal from "../feedback-form/FeedbackModal"; -import { isGitpodIo } from "../utils"; import OrganizationSelector from "./OrganizationSelector"; import { getAdminTabs } from "../admin/admin.routes"; import classNames from "classnames"; import { User, RoleOrPermission } from "@gitpod/public-api/lib/gitpod/v1/user_pb"; import { getPrimaryEmail } from "@gitpod/public-api-common/lib/user-utils"; import { ConfigurationsMigrationCoachmark } from "../repositories/coachmarks/MigrationCoachmark"; +import { useInstallationConfiguration } from "../data/installation/installation-config-query"; interface Entry { title: string; @@ -35,6 +35,9 @@ export default function Menu() { const { setCurrency } = useContext(PaymentContext); const [isFeedbackFormVisible, setFeedbackFormVisible] = useState(false); + const { data: installationConfig, isLoading: isInstallationConfigLoading } = useInstallationConfiguration(); + const isGitpodIo = isInstallationConfigLoading ? false : !installationConfig?.isDedicatedInstallation; + useEffect(() => { const { server } = getGitpodService(); server.getClientRegion().then((v) => { @@ -95,7 +98,7 @@ export default function Menu() { /> )} - {isGitpodIo() && ( + {isGitpodIo && (
  • @@ -163,6 +166,9 @@ type UserMenuProps = { onFeedback?: () => void; }; const UserMenu: FC = ({ user, className, withAdminLink, withFeedbackLink, onFeedback }) => { + const { data: installationConfig, isLoading: isInstallationConfigLoading } = useInstallationConfiguration(); + const isGitpodIo = isInstallationConfigLoading ? false : !installationConfig?.isDedicatedInstallation; + const extraSection = useMemo(() => { const items: ContextMenuEntry[] = []; @@ -172,7 +178,7 @@ const UserMenu: FC = ({ user, className, withAdminLink, withFeedb link: "/admin", }); } - if (withFeedbackLink && isGitpodIo()) { + if (withFeedbackLink && isGitpodIo) { items.push({ title: "Feedback", onClick: onFeedback, @@ -185,7 +191,7 @@ const UserMenu: FC = ({ user, className, withAdminLink, withFeedb } return items; - }, [onFeedback, user?.rolesOrPermissions, withAdminLink, withFeedbackLink]); + }, [isGitpodIo, onFeedback, user?.rolesOrPermissions, withAdminLink, withFeedbackLink]); const menuEntries = useMemo(() => { return [ diff --git a/components/dashboard/src/menu/OrganizationSelector.tsx b/components/dashboard/src/menu/OrganizationSelector.tsx index cb8ee39433bc7d..b191572d4ccfe6 100644 --- a/components/dashboard/src/menu/OrganizationSelector.tsx +++ b/components/dashboard/src/menu/OrganizationSelector.tsx @@ -14,9 +14,9 @@ import { useOrgBillingMode } from "../data/billing-mode/org-billing-mode-query"; import { useIsOwner, useListOrganizationMembers, useHasRolePermission } from "../data/organizations/members-query"; import { isAllowedToCreateOrganization } from "@gitpod/public-api-common/lib/user-utils"; import { OrganizationRole } from "@gitpod/public-api/lib/gitpod/v1/organization_pb"; -import { useInstallationConfiguration } from "../data/installation/default-workspace-image-query"; import { useFeatureFlag } from "../data/featureflag-query"; import { PlusIcon } from "lucide-react"; +import { useInstallationConfiguration } from "../data/installation/installation-config-query"; export default function OrganizationSelector() { const user = useCurrentUser(); diff --git a/components/dashboard/src/teams/OrgSettingsPage.tsx b/components/dashboard/src/teams/OrgSettingsPage.tsx index ee7bad2fd6f75c..e2db644bfa9e39 100644 --- a/components/dashboard/src/teams/OrgSettingsPage.tsx +++ b/components/dashboard/src/teams/OrgSettingsPage.tsx @@ -15,7 +15,7 @@ import { useCurrentOrg } from "../data/organizations/orgs-query"; import { useFeatureFlag } from "../data/featureflag-query"; import { Organization } from "@gitpod/public-api/lib/gitpod/v1/organization_pb"; import { useIsOwner } from "../data/organizations/members-query"; -import { useInstallationConfiguration } from "../data/installation/default-workspace-image-query"; +import { useInstallationConfiguration } from "../data/installation/installation-config-query"; export interface OrgSettingsPageProps { children: React.ReactNode; diff --git a/components/dashboard/src/teams/policies/MaxParallelWorkspaces.tsx b/components/dashboard/src/teams/policies/MaxParallelWorkspaces.tsx index c1469615469216..a2ae56c5386d5f 100644 --- a/components/dashboard/src/teams/policies/MaxParallelWorkspaces.tsx +++ b/components/dashboard/src/teams/policies/MaxParallelWorkspaces.tsx @@ -13,7 +13,7 @@ import { NumberInput } from "../../components/forms/TextInputField"; import { LoadingButton } from "@podkit/buttons/LoadingButton"; import { MAX_PARALLEL_WORKSPACES_FREE, MAX_PARALLEL_WORKSPACES_PAID } from "@gitpod/gitpod-protocol"; import { PlainMessage } from "@bufbuild/protobuf"; -import { useInstallationConfiguration } from "../../data/installation/default-workspace-image-query"; +import { useInstallationConfiguration } from "../../data/installation/installation-config-query"; type Props = { isOwner: boolean; diff --git a/components/dashboard/src/user-settings/PageWithSettingsSubMenu.tsx b/components/dashboard/src/user-settings/PageWithSettingsSubMenu.tsx index a91f86513a688a..dbe1a44a1a10b0 100644 --- a/components/dashboard/src/user-settings/PageWithSettingsSubMenu.tsx +++ b/components/dashboard/src/user-settings/PageWithSettingsSubMenu.tsx @@ -5,6 +5,7 @@ */ import { PageWithSubMenu } from "../components/PageWithSubMenu"; +import { useInstallationConfiguration } from "../data/installation/installation-config-query"; import { settingsPathAccount, settingsPathIntegrations, @@ -23,7 +24,7 @@ export interface PageWithAdminSubMenuProps { } export function PageWithSettingsSubMenu({ children }: PageWithAdminSubMenuProps) { - const settingsMenu = getSettingsMenu(); + const settingsMenu = useUserSettingsMenu(); return ( {children} @@ -31,16 +32,23 @@ export function PageWithSettingsSubMenu({ children }: PageWithAdminSubMenuProps) ); } -function getSettingsMenu() { +function useUserSettingsMenu() { + const { data: installationConfig } = useInstallationConfiguration(); + const isGitpodIo = installationConfig?.isDedicatedInstallation === false; + return [ { title: "Account", link: [settingsPathAccount, settingsPathMain], }, - { - title: "Notifications", - link: [settingsPathNotifications], - }, + ...(isGitpodIo + ? [ + { + title: "Notifications", + link: [settingsPathNotifications], + }, + ] + : []), { title: "Variables", link: [settingsPathVariables], diff --git a/components/dashboard/src/workspaces/CreateWorkspacePage.tsx b/components/dashboard/src/workspaces/CreateWorkspacePage.tsx index e2aaa8252d489d..0e5c8944c2518a 100644 --- a/components/dashboard/src/workspaces/CreateWorkspacePage.tsx +++ b/components/dashboard/src/workspaces/CreateWorkspacePage.tsx @@ -59,7 +59,7 @@ import { flattenPagedConfigurations } from "../data/git-providers/unified-reposi import { Configuration } from "@gitpod/public-api/lib/gitpod/v1/configuration_pb"; import { useMemberRole } from "../data/organizations/members-query"; import { OrganizationPermission } from "@gitpod/public-api/lib/gitpod/v1/organization_pb"; -import { useInstallationConfiguration } from "../data/installation/default-workspace-image-query"; +import { useInstallationConfiguration } from "../data/installation/installation-config-query"; type NextLoadOption = "searchParams" | "autoStart" | "allDone"; diff --git a/components/dashboard/src/workspaces/EmptyWorkspacesContent.tsx b/components/dashboard/src/workspaces/EmptyWorkspacesContent.tsx index 131ac51705f2e1..593cd852e7b703 100644 --- a/components/dashboard/src/workspaces/EmptyWorkspacesContent.tsx +++ b/components/dashboard/src/workspaces/EmptyWorkspacesContent.tsx @@ -9,7 +9,7 @@ import { Heading2, Subheading } from "@podkit/typography/Headings"; import { StartWorkspaceModalKeyBinding } from "../App"; import { VideoSection } from "../onboarding/VideoSection"; import { trackVideoClick } from "../Analytics"; -import { useInstallationConfiguration } from "../data/installation/default-workspace-image-query"; +import { useInstallationConfiguration } from "../data/installation/installation-config-query"; export const EmptyWorkspacesContent = () => { const { data: installationConfig } = useInstallationConfiguration(); diff --git a/components/dashboard/src/workspaces/Workspaces.tsx b/components/dashboard/src/workspaces/Workspaces.tsx index 35378bea3eae30..b6f08a5057441d 100644 --- a/components/dashboard/src/workspaces/Workspaces.tsx +++ b/components/dashboard/src/workspaces/Workspaces.tsx @@ -32,11 +32,11 @@ import Modal, { ModalBaseFooter, ModalBody, ModalHeader } from "../components/Mo import { VideoSection } from "../onboarding/VideoSection"; import { trackVideoClick } from "../Analytics"; import { cn } from "@podkit/lib/cn"; -import { useInstallationConfiguration } from "../data/installation/default-workspace-image-query"; import { useUpdateCurrentUserMutation } from "../data/current-user/update-mutation"; import { useUserLoader } from "../hooks/use-user-loader"; import Tooltip from "../components/Tooltip"; import { useFeatureFlag } from "../data/featureflag-query"; +import { useInstallationConfiguration } from "../data/installation/installation-config-query"; import { SuggestedOrgRepository, useOrgSuggestedRepos } from "../data/organizations/suggested-repositories-query"; import { useSuggestedRepositories } from "../data/git-providers/suggested-repositories-query"; import PillLabel from "../components/PillLabel"; diff --git a/components/dashboard/src/workspaces/WorkspacesSearchBar.tsx b/components/dashboard/src/workspaces/WorkspacesSearchBar.tsx index da85b327c17a81..54e056a0644cf8 100644 --- a/components/dashboard/src/workspaces/WorkspacesSearchBar.tsx +++ b/components/dashboard/src/workspaces/WorkspacesSearchBar.tsx @@ -9,7 +9,7 @@ import { StartWorkspaceModalKeyBinding } from "../App"; import DropDown from "../components/DropDown"; import search from "../icons/search.svg"; import { LinkButton } from "@podkit/buttons/LinkButton"; -import { useInstallationConfiguration } from "../data/installation/default-workspace-image-query"; +import { useInstallationConfiguration } from "../data/installation/installation-config-query"; type WorkspacesSearchBarProps = { searchTerm: string;