From 17d4445ce70cd2a4870d12fa1b88ca90de707fc5 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Wed, 23 Aug 2023 15:54:14 +0800 Subject: [PATCH] Update warning on card buttons --- .../Home/ProjectList/ProjectCard.tsx | 109 ++++++++++-------- .../Home/ProjectList/ProjectCardWarnings.tsx | 49 ++++---- .../Home/ProjectList/ProjectList.tsx | 14 +-- .../layouts/ProjectLayout/ProjectLayout.tsx | 4 +- studio/components/ui/CardButton.tsx | 4 +- studio/data/usage/keys.ts | 2 +- studio/data/usage/resource-warnings-query.ts | 42 +++---- studio/pages/project/[ref]/index.tsx | 4 - 8 files changed, 110 insertions(+), 118 deletions(-) diff --git a/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx b/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx index 1c81df2fad7..68532417f5d 100644 --- a/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx +++ b/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx @@ -12,7 +12,7 @@ import { useProjectReadOnlyStatus } from 'hooks/misc/useProjectReadOnlyStatus' import { BASE_PATH, PROJECT_STATUS } from 'lib/constants' import { Project } from 'types' import { IntegrationProjectConnection } from 'data/integrations/integrations.types' -import { ResourceWarningResponse } from 'data/usage/resource-warnings-query' +import { ResourceWarning } from 'data/usage/resource-warnings-query' import ProjectCardWarnings from './ProjectCardWarnings' export interface ProjectCardProps { @@ -20,7 +20,7 @@ export interface ProjectCardProps { rewriteHref?: string githubIntegration?: IntegrationProjectConnection vercelIntegration?: IntegrationProjectConnection - resourceWarnings?: ResourceWarningResponse + resourceWarnings?: ResourceWarning } const ProjectCard = ({ @@ -34,10 +34,15 @@ const ProjectCard = ({ const desc = `${project.cloud_provider} | ${project.region}` const isReadonly = useProjectReadOnlyStatus(projectRef) - const isBranchingEnabled = project.preview_branch_refs.length > 0 - const isGithubIntegrated = githubIntegration !== undefined - const isVercelIntegrated = vercelIntegration !== undefined - const githubRepository = githubIntegration?.metadata.name ?? undefined + // const isBranchingEnabled = project.preview_branch_refs.length > 0 + // const isGithubIntegrated = githubIntegration !== undefined + // const isVercelIntegrated = vercelIntegration !== undefined + // const githubRepository = githubIntegration?.metadata.name ?? undefined + + const isBranchingEnabled = true + const isGithubIntegrated = true + const isVercelIntegrated = true + const githubRepository = 'supabase/supabase-js' // Project status should supersede its read only status const isHealthy = project.status === PROJECT_STATUS.ACTIVE_HEALTHY @@ -46,22 +51,21 @@ const ProjectCard = ({ const isPaused = project.status === PROJECT_STATUS.INACTIVE const isRestoring = project.status === PROJECT_STATUS.RESTORING - const checkProjectResourceWarnings = (resourceWarnings: ResourceWarningResponse) => { + const checkProjectResourceWarnings = (resourceWarnings: ResourceWarning) => { return Object.values(resourceWarnings).some( (value) => typeof value === 'boolean' && value === true ) } - // const projectHasResourceWarnings = - // resourceWarnings !== undefined ? checkProjectResourceWarnings(resourceWarnings) : false - const projectHasResourceWarnings = true + const projectHasResourceWarnings = + resourceWarnings !== undefined ? checkProjectResourceWarnings(resourceWarnings) : false return (
  • +

    {name}

    {isVercelIntegrated && ( @@ -87,61 +91,66 @@ const ProjectCard = ({ )}
    - {resourceWarnings && projectHasResourceWarnings && ( - - )}
    } footer={ -
    - {desc} +
    + {desc} - {isHealthy && isReadonly && ( -
    - -
    - - Read-only mode -
    -
    -
    + {isHealthy && ( + <> + {isReadonly ? ( + +
    + + Read-only mode +
    +
    + ) : ( + +
    + Active +
    +
    + )} + )} {isRestoring && ( -
    - -
    - - Restoring -
    -
    -
    + +
    + + Restoring +
    +
    )} {isPausing && ( -
    - -
    - - Pausing -
    -
    -
    + +
    + + Pausing +
    +
    )} {isPaused && ( -
    - -
    - - Paused -
    -
    -
    + +
    + + Paused +
    +
    )}
    } - /> + > + {resourceWarnings && projectHasResourceWarnings ? ( + + ) : ( +
    + )} +
  • ) } diff --git a/studio/components/interfaces/Home/ProjectList/ProjectCardWarnings.tsx b/studio/components/interfaces/Home/ProjectList/ProjectCardWarnings.tsx index 37fa3c17bd4..ec8f4af8e43 100644 --- a/studio/components/interfaces/Home/ProjectList/ProjectCardWarnings.tsx +++ b/studio/components/interfaces/Home/ProjectList/ProjectCardWarnings.tsx @@ -1,41 +1,36 @@ -import { ResourceWarningResponse } from 'data/usage/resource-warnings-query' +import { ResourceWarning } from 'data/usage/resource-warnings-query' import { Alert_Shadcn_, AlertDescription_Shadcn_, AlertTitle_Shadcn_, IconAlertTriangle } from 'ui' -export type ResourceWarningResponses = Omit< - Omit, - 'is_readonly_mode_enabled' -> - export interface ProjectCardWarningsProps { - resourceWarnings: ResourceWarningResponses + resourceWarnings: ResourceWarning } // reference for message wording // www.notion.so/supabase/Notify-users-on-resource-exhaustion-on-the-dashboard-4bb7b9a990104720b179b7a37d07f41c?pvs=4#a79798b5ac72402e8bfea4c4715e7439 const RESOURCE_WARNING_MESSAGES = { is_readonly_mode_enabled: { - title: 'Project in readonly mode', - description: 'This database will no longer accept write requests.', + title: 'Project is in readonly mode', + description: 'Database is no longer accept write requests.', }, is_disk_io_budget_below_threshold: { - title: 'Your project is depleting its Disk IO Budget', - description: 'Your instance may become unresponsive if fully exhausted.', + title: 'Project is depleting its Disk IO Budget', + description: 'Instance may become unresponsive if fully exhausted.', }, is_disk_space_usage_beyond_threshold: { - title: 'Project has exhausted disk space budget', - description: 'Your instance may become unresponsive if fully exhausted.', + title: 'Project is exhausting disk space budget', + description: 'Instance may become unresponsive if fully exhausted.', }, is_cpu_load_beyond_threshold: { - title: 'Your project has high CPU usage', - description: `Your instance's performance is affected`, + title: 'Project has high CPU usage', + description: `Instance's performance is affected`, }, is_memory_and_swap_usage_beyond_threshold: { - title: 'Your project has high memory usage', - description: `Your instance's performance is affected.`, + title: 'Project has high memory usage', + description: `Instance's performance is affected.`, }, multiple_resource_warnings: { - title: 'Your project is burning up', - description: `Your instance's performance is affected.`, + title: 'Project is exhausting multiple resources', + description: `Instance's performance is affected.`, }, } @@ -43,20 +38,26 @@ export default function ProjectCardWarnings({ resourceWarnings }: ProjectCardWar const activeWarnings = Object.keys(resourceWarnings).filter( (property) => resourceWarnings[property as keyof typeof resourceWarnings] === true ) + const hasHighPriorityWarning = activeWarnings.includes('is_readonly_mode_enabled') return (
    - + - + + {activeWarnings.length > 1 ? RESOURCE_WARNING_MESSAGES.multiple_resource_warnings.title - : RESOURCE_WARNING_MESSAGES[activeWarnings[0] as keyof typeof resourceWarnings]?.title} + : RESOURCE_WARNING_MESSAGES[activeWarnings[0] as keyof typeof RESOURCE_WARNING_MESSAGES] + ?.title} - + {activeWarnings.length > 1 ? RESOURCE_WARNING_MESSAGES.multiple_resource_warnings.description - : RESOURCE_WARNING_MESSAGES[activeWarnings[0] as keyof typeof resourceWarnings] + : RESOURCE_WARNING_MESSAGES[activeWarnings[0] as keyof typeof RESOURCE_WARNING_MESSAGES] ?.description} diff --git a/studio/components/interfaces/Home/ProjectList/ProjectList.tsx b/studio/components/interfaces/Home/ProjectList/ProjectList.tsx index ef5eff5de8e..a297da6c18d 100644 --- a/studio/components/interfaces/Home/ProjectList/ProjectList.tsx +++ b/studio/components/interfaces/Home/ProjectList/ProjectList.tsx @@ -12,7 +12,7 @@ import { import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useProjectsQuery } from 'data/projects/projects-query' -import { useResourceWarningQuery } from 'data/usage/resource-warnings-query' +import { ResourceWarning, useResourceWarningsQuery } from 'data/usage/resource-warnings-query' import { useCheckPermissions } from 'hooks' import { IS_PLATFORM } from 'lib/constants' import { makeRandomString } from 'lib/helpers' @@ -37,6 +37,7 @@ const ProjectList = ({ rewriteHref }: ProjectListProps) => { isError: isErrorPermissions, error: permissionsError, } = usePermissionsQuery() + const { data: resourceWarnings } = useResourceWarningsQuery() const { data: allOverdueInvoices } = useOverdueInvoicesQuery({ enabled: IS_PLATFORM }) const projectsByOrg = groupBy(allProjects, 'organization_id') const isLoadingPermissions = IS_PLATFORM ? _isLoadingPermissions : false @@ -52,6 +53,7 @@ const ProjectList = ({ rewriteHref }: ProjectListProps) => { overdueInvoices={(allOverdueInvoices ?? []).filter( (it) => it.organization_id === organization.id )} + resourceWarnings={resourceWarnings ?? []} rewriteHref={rewriteHref} isLoadingPermissions={isLoadingPermissions} isErrorPermissions={isErrorPermissions} @@ -72,6 +74,7 @@ type OrganizationProjectsProps = { organization: Organization projects: Project[] overdueInvoices: OverdueInvoicesResponse[] + resourceWarnings: ResourceWarning[] isLoadingPermissions: boolean isErrorPermissions: boolean permissionsError: ResponseError | null @@ -82,9 +85,10 @@ type OrganizationProjectsProps = { } const OrganizationProjects = ({ - organization: { id, name, slug, subscription_id }, + organization: { id, name, slug }, projects, overdueInvoices, + resourceWarnings, isLoadingPermissions, isErrorPermissions, permissionsError, @@ -95,10 +99,6 @@ const OrganizationProjects = ({ }: OrganizationProjectsProps) => { const isEmpty = !projects || projects.length === 0 const canReadProjects = useCheckPermissions(PermissionAction.READ, 'projects', undefined, id) - const { data: resourceWarnings } = useResourceWarningQuery() - - console.log(resourceWarnings) - console.log('one render') return (
    @@ -166,7 +166,7 @@ const OrganizationProjects = ({ key={makeRandomString(5)} project={project} rewriteHref={rewriteHref ? rewriteHref(project.ref) : undefined} - resourceWarnings={resourceWarnings?.find( + resourceWarnings={resourceWarnings.find( (resourceWarning) => resourceWarning.project === project.ref )} /> diff --git a/studio/components/layouts/ProjectLayout/ProjectLayout.tsx b/studio/components/layouts/ProjectLayout/ProjectLayout.tsx index 7a1cd41cb61..586022bfbec 100644 --- a/studio/components/layouts/ProjectLayout/ProjectLayout.tsx +++ b/studio/components/layouts/ProjectLayout/ProjectLayout.tsx @@ -18,7 +18,7 @@ import RestoringState from './RestoringState' import UpgradingState from './UpgradingState' import AppLayout from '../AppLayout/AppLayout' import UsageWarningBanner from 'components/ui/UsageWarnings/UsageWarningBanner' -import { useResourceWarningQuery } from 'data/usage/resource-warnings-query' +import { useResourceWarningsQuery } from 'data/usage/resource-warnings-query' // [Joshen] This is temporary while we unblock users from managing their project // if their project is not responding well for any reason. Eventually needs a bit of an overhaul @@ -179,7 +179,7 @@ const ContentWrapper = ({ isLoading, children }: ContentWrapperProps) => { selectedProject?.status === PROJECT_STATUS.PAUSING const isProjectOffline = selectedProject?.postgrestStatus === 'OFFLINE' - const { data: resourceWarnings } = useResourceWarningQuery() + const { data: resourceWarnings } = useResourceWarningsQuery() console.log(resourceWarnings) return ( <> diff --git a/studio/components/ui/CardButton.tsx b/studio/components/ui/CardButton.tsx index f374f6cef82..9c0690af6ac 100644 --- a/studio/components/ui/CardButton.tsx +++ b/studio/components/ui/CardButton.tsx @@ -27,7 +27,7 @@ const CardButton = ({ imgAlt, onClick, icon, - containerHeightClassName = 'h-48', + containerHeightClassName = '', loading = false, }: PropsWithChildren) => { const LinkContainer = ({ children }: { children: React.ReactNode }) => ( @@ -47,7 +47,7 @@ const CardButton = ({ 'group relative text-left', 'bg-panel-header-light dark:bg-panel-header-dark', 'border border-panel-border-light dark:border-panel-border-dark', - 'rounded-md py-4 px-6 flex flex-row', + 'rounded-md py-4 flex flex-row', 'transition ease-in-out duration-150', containerHeightClassName, ] diff --git a/studio/data/usage/keys.ts b/studio/data/usage/keys.ts index b5aca6f8298..54be56a1858 100644 --- a/studio/data/usage/keys.ts +++ b/studio/data/usage/keys.ts @@ -1,5 +1,5 @@ export const usageKeys = { usage: (projectRef: string | undefined) => ['projects', projectRef, 'usage'] as const, orgUsage: (orgSlug: string | undefined) => ['organizations', orgSlug, 'usage'] as const, - resourceWarnings: () => ['project', 'resource-warnings'] as const, + resourceWarnings: () => ['projects', 'resource-warnings'] as const, } diff --git a/studio/data/usage/resource-warnings-query.ts b/studio/data/usage/resource-warnings-query.ts index 82be8e7f1eb..19a92acbe8d 100644 --- a/studio/data/usage/resource-warnings-query.ts +++ b/studio/data/usage/resource-warnings-query.ts @@ -1,40 +1,26 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { get, isResponseOk } from 'lib/common/fetch' -import { API_URL } from 'lib/constants' -import { usageKeys } from './keys' -export type ResourceWarningResponse = { - project: string - is_readonly_mode_enabled: boolean - is_disk_io_budget_below_threshold: boolean - is_disk_space_usage_beyond_threshold: boolean - is_cpu_load_beyond_threshold: boolean - is_memory_and_swap_usage_beyond_threshold: boolean -} +import { get } from 'data/fetchers' +import { usageKeys } from './keys' +import { ResponseError } from 'types' +import { components } from 'data/api' export async function getResourceWarnings(signal?: AbortSignal) { - const response = await get(`${API_URL}/projects-resource-warnings`, { - signal, - }) - if (!isResponseOk(response)) { - throw response.error - } - - return response + const { data, error } = await get(`/platform/projects-resource-warnings`, { signal }) + if (error) throw error + return data } -export type ResourceWarningData = Awaited> -export type ResourceError = unknown +export type ResourceWarning = components['schemas']['ProjectResourceWarningsResponse'] +export type ResourceWarningsData = Awaited> +export type ResourceWarningsError = ResponseError -export const useResourceWarningQuery = ({ +export const useResourceWarningsQuery = ({ enabled = true, ...options -}: UseQueryOptions = {}) => - useQuery( +}: UseQueryOptions = {}) => + useQuery( usageKeys.resourceWarnings(), ({ signal }) => getResourceWarnings(signal), - { - enabled: enabled, - ...options, - } + { enabled, ...options } ) diff --git a/studio/pages/project/[ref]/index.tsx b/studio/pages/project/[ref]/index.tsx index 727d5789606..06b56fd2a10 100644 --- a/studio/pages/project/[ref]/index.tsx +++ b/studio/pages/project/[ref]/index.tsx @@ -4,7 +4,6 @@ import ProjectUsageSection from 'components/interfaces/Home/ProjectUsageSection' import { ProjectLayoutWithAuth } from 'components/layouts' import ProjectPausedState from 'components/layouts/ProjectLayout/ProjectPausedState' import ProjectUpgradeFailedBanner from 'components/ui/ProjectUpgradeFailedBanner' -import { useResourceWarningQuery } from 'data/usage/resource-warnings-query' import { useSelectedProject } from 'hooks' import { IS_PLATFORM, PROJECT_STATUS } from 'lib/constants' import { NextPageWithLayout } from 'types' @@ -17,9 +16,6 @@ const Home: NextPageWithLayout = () => { ? project?.name : 'Welcome to your project' - const { data: resourceWarnings } = useResourceWarningQuery() - - console.log(resourceWarnings) return (