fix: nameless in sidebar for orgs (#10318)

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
This commit is contained in:
Hariom Balhara
2023-07-24 10:25:55 +00:00
committed by GitHub
co-authored by sean-brydon
parent 80a1458538
commit 4e1e586541
17 changed files with 58 additions and 56 deletions
@@ -7,7 +7,7 @@ import { useMemo, useState, Suspense } from "react";
import type { UseFormReturn } from "react-hook-form";
import useLockedFieldsManager from "@calcom/features/ee/managed-event-types/hooks/useLockedFieldsManager";
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
import Shell from "@calcom/features/shell/Shell";
import { classNames } from "@calcom/lib";
import { CAL_URL } from "@calcom/lib/constants";
@@ -234,7 +234,7 @@ function EventTypeSingleLayout({
formMethods,
]);
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
const isOrgEvent = orgBranding?.fullDomain;
const permalink = `${orgBranding?.fullDomain ?? CAL_URL}/${
team ? `${!isOrgEvent ? "team/" : ""}${team.slug}` : eventType.users[0].username
+19 -2
View File
@@ -1,5 +1,6 @@
import { TooltipProvider } from "@radix-ui/react-tooltip";
import { SessionProvider } from "next-auth/react";
import { useSession } from "next-auth/react";
import { EventCollectionProvider } from "next-collect/client";
import type { SSRConfig } from "next-i18next";
import { appWithTranslation } from "next-i18next";
@@ -10,7 +11,6 @@ import { useRouter } from "next/router";
import type { ComponentProps, PropsWithChildren, ReactNode } from "react";
import { OrgBrandingProvider } from "@calcom/features/ee/organizations/context/provider";
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import DynamicHelpscoutProvider from "@calcom/features/ee/support/lib/helpscout/providerDynamic";
import DynamicIntercomProvider from "@calcom/features/ee/support/lib/intercom/providerDynamic";
import { FeatureProvider } from "@calcom/features/flags/context/provider";
@@ -218,9 +218,26 @@ function FeatureFlagsProvider({ children }: { children: React.ReactNode }) {
return <FeatureProvider value={flags}>{children}</FeatureProvider>;
}
function useOrgBrandingValues() {
const session = useSession();
const res = trpc.viewer.organizations.getBrand.useQuery(undefined, {
// Only fetch if we have a session to avoid flooding logs with errors
enabled: session.status === "authenticated",
});
if (res.status === "loading") {
return undefined;
}
if (res.status === "error") return null;
return res.data;
}
function OrgBrandProvider({ children }: { children: React.ReactNode }) {
const orgBrand = useOrgBrandingValues();
return <OrgBrandingProvider value={orgBrand}>{children}</OrgBrandingProvider>;
return <OrgBrandingProvider value={{ orgBrand }}>{children}</OrgBrandingProvider>;
}
const AppProviders = (props: AppPropsWithChildren) => {
+7 -7
View File
@@ -7,7 +7,7 @@ import type { FC } from "react";
import { useEffect, useState, memo } from "react";
import { z } from "zod";
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
import useIntercom from "@calcom/features/ee/support/lib/intercom/useIntercom";
import { EventTypeDescriptionLazy as EventTypeDescription } from "@calcom/features/eventtypes/components";
import CreateEventTypeDialog from "@calcom/features/eventtypes/components/CreateEventTypeDialog";
@@ -102,7 +102,7 @@ const querySchema = z.object({
const MobileTeamsTab: FC<MobileTeamsTabProps> = (props) => {
const { eventTypeGroups } = props;
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
const tabs = eventTypeGroups.map((item) => ({
name: item.profile.name ?? "",
href: item.teamId ? `/event-types?teamId=${item.teamId}` : "/event-types",
@@ -200,7 +200,7 @@ const MemoizedItem = memo(Item);
export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeListProps): JSX.Element => {
const { t } = useLocale();
const router = useRouter();
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
const [parent] = useAutoAnimate<HTMLUListElement>();
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [deleteDialogTypeId, setDeleteDialogTypeId] = useState(0);
@@ -700,7 +700,7 @@ const EventTypeListHeading = ({
}: EventTypeListHeadingProps): JSX.Element => {
const { t } = useLocale();
const router = useRouter();
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
const publishTeamMutation = trpc.viewer.teams.publish.useMutation({
onSuccess(data) {
@@ -809,7 +809,7 @@ const Actions = () => {
const SetupProfileBanner = ({ closeAction }: { closeAction: () => void }) => {
const { t } = useLocale();
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
return (
<Alert
@@ -840,7 +840,7 @@ const Main = () => {
const router = useRouter();
const filters = getTeamsFiltersFromQuery(router.query);
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
// TODO: Maybe useSuspenseQuery to focus on success case only? Remember that it would crash the page when there is an error in query. Also, it won't support skeleton
const res = trpc.viewer.eventTypes.getByViewer.useQuery(filters && { filters });
@@ -906,7 +906,7 @@ const EventTypesPage = () => {
const { query } = router;
const { data: user } = useMeQuery();
const [showProfileBanner, setShowProfileBanner] = useState(false);
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
function closeBanner() {
setShowProfileBanner(false);
@@ -7,7 +7,7 @@ import { Controller } from "react-hook-form";
import { v4 as uuidv4 } from "uuid";
import { z } from "zod";
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
import { classNames } from "@calcom/lib";
import { CAL_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -402,7 +402,7 @@ export const FormAction = forwardRef(function FormAction<T extends typeof Button
const dropdownCtxValue = useContext(dropdownCtx);
const dropdown = dropdownCtxValue?.dropdown;
const embedLink = `forms/${routingForm?.id}`;
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
const formLink = `${orgBranding?.fullDomain ?? CAL_URL}/${embedLink}`;
let redirectUrl = `${orgBranding?.fullDomain ?? CAL_URL}/router?form=${routingForm?.id}`;
@@ -2,7 +2,7 @@ import { useState } from "react";
import { shallow } from "zustand/shallow";
import { useFilterQuery } from "@calcom/features/bookings/lib/useFilterQuery";
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
import {
TeamsFilter,
FilterCheckboxFieldsContainer,
@@ -29,7 +29,7 @@ import { EventTypeFilter } from "./EventTypeFilter";
const PeopleFilter = () => {
const { t } = useLocale();
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
const { data: query, pushItemToKey, removeItemByKeyAndValue, removeByKey } = useFilterQuery();
const [searchText, setSearchText] = useState("");
@@ -22,19 +22,19 @@ export type OrganizationBranding =
/**
* Allows you to access the flags from context
*/
const OrganizationBrandingContext = createContext<OrganizationBranding | null>(null);
const OrganizationBrandingContext = createContext<{ orgBrand: OrganizationBranding } | null>(null);
/**
* Accesses the branding for an organization from context.
*
* You need to render a <OrgBrandingProvider /> further up to be able to use
* this component.
*
* @returns `undefined` when data isn't available yet, `null` when there's an error, and the data(which can be `null`) when it's available
*/
export function useOrgBranding() {
const orgBrandingContext = useContext(OrganizationBrandingContext);
if (orgBrandingContext === null)
throw new Error("Error: useOrganizationBranding was used outside of OrgBrandingProvider.");
return orgBrandingContext as OrganizationBranding;
if (!orgBrandingContext) throw new Error("Error: useOrgBranding was used outside of OrgBrandingProvider.");
return orgBrandingContext.orgBrand;
}
/**
@@ -60,7 +60,7 @@ export function useOrgBranding() {
* `YourOwnComponent` or further down.
*
*/
export function OrgBrandingProvider<F extends OrganizationBranding>(props: {
export function OrgBrandingProvider<F extends { orgBrand: OrganizationBranding }>(props: {
value: F;
children: React.ReactNode;
}) {
@@ -1,14 +0,0 @@
import { useSession } from "next-auth/react";
import { trpc } from "@calcom/trpc/react";
export function useOrgBrandingValues() {
const session = useSession();
return trpc.viewer.organizations.getBrand.useQuery(undefined, {
// Only fetch if we have a session to avoid flooding logs with errors
enabled: session.status === "authenticated",
// This is important because usage of useOrgBrandingValues is spread across the app and there isn't going to be anything new on fetching on every new mount of a component
// We can just refetch the query only when org slug or logo changes which would be not frequent
staleTime: Infinity,
}).data;
}
@@ -7,7 +7,6 @@ import { Controller, useForm } from "react-hook-form";
import { z } from "zod";
import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired";
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import { subdomainSuffix } from "@calcom/features/ee/organizations/lib/orgDomains";
import { WEBAPP_URL } from "@calcom/lib/constants";
import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage";
@@ -30,6 +29,7 @@ import {
} from "@calcom/ui";
import { getLayout } from "../../../../settings/layouts/SettingsLayout";
import { useOrgBranding } from "../../../organizations/context/provider";
const orgProfileFormSchema = z.object({
name: z.string(),
@@ -42,7 +42,7 @@ const OrgProfileView = () => {
const router = useRouter();
const utils = trpc.useContext();
const [firstRender, setFirstRender] = useState(true);
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
useLayoutEffect(() => {
document.body.focus();
@@ -4,7 +4,6 @@ import { Controller, useForm } from "react-hook-form";
import { z } from "zod";
import { extractDomainFromWebsiteUrl } from "@calcom/ee/organizations/lib/utils";
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import slugify from "@calcom/lib/slugify";
@@ -13,6 +12,7 @@ import { trpc } from "@calcom/trpc/react";
import { Avatar, Button, Form, ImageUploader, TextField, Alert, Label } from "@calcom/ui";
import { ArrowRight, Plus } from "@calcom/ui/components/icon";
import { useOrgBranding } from "../../organizations/context/provider";
import type { NewTeamFormValues } from "../lib/types";
const querySchema = z.object({
@@ -26,7 +26,7 @@ export const CreateANewTeamForm = () => {
const telemetry = useTelemetry();
const parsedQuery = querySchema.safeParse(router.query);
const [serverErrorMessage, setServerErrorMessage] = useState<string | null>(null);
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
const returnToParam =
(parsedQuery.success ? getSafeRedirectUrl(parsedQuery.data.returnTo) : "/settings/teams") ||
@@ -2,7 +2,6 @@ import classNames from "classnames";
import { signIn } from "next-auth/react";
import { useState } from "react";
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import { WEBAPP_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { MembershipRole } from "@calcom/prisma/enums";
@@ -30,6 +29,7 @@ import {
} from "@calcom/ui";
import { ExternalLink, MoreHorizontal, Edit2, Lock, UserX } from "@calcom/ui/components/icon";
import { useOrgBranding } from "../../organizations/context/provider";
import MemberChangeRoleModal from "./MemberChangeRoleModal";
import TeamAvailabilityModal from "./TeamAvailabilityModal";
import TeamPill, { TeamRole } from "./TeamPill";
@@ -54,7 +54,7 @@ const checkIsOrg = (team: Props["team"]) => {
export default function MemberListItem(props: Props) {
const { t } = useLocale();
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
const utils = trpc.useContext();
const [showChangeMemberRoleModal, setShowChangeMemberRoleModal] = useState(false);
@@ -4,7 +4,6 @@ import { useState } from "react";
import InviteLinkSettingsModal from "@calcom/ee/teams/components/InviteLinkSettingsModal";
import MemberInvitationModal from "@calcom/ee/teams/components/MemberInvitationModal";
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import classNames from "@calcom/lib/classNames";
import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -40,6 +39,7 @@ import {
X,
} from "@calcom/ui/components/icon";
import { useOrgBranding } from "../../organizations/context/provider";
import { TeamRole } from "./TeamPill";
interface Props {
@@ -81,7 +81,7 @@ export default function TeamListItem(props: Props) {
const acceptInvite = () => acceptOrLeave(true);
const declineInvite = () => acceptOrLeave(false);
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
const isOwner = props.team.role === MembershipRole.OWNER;
const isInvitee = !props.team.accepted;
@@ -22,7 +22,7 @@ import {
} from "@calcom/ui";
import { Edit2, Link as LinkIcon, MoreHorizontal, Trash2 } from "@calcom/ui/components/icon";
import { useOrgBrandingValues } from "../../organizations/hooks";
import { useOrgBranding } from "../../organizations/context/provider";
import { subdomainSuffix } from "../../organizations/lib/orgDomains";
import { getActionIcon } from "../lib/getActionIcon";
import { DeleteDialog } from "./DeleteDialog";
@@ -58,7 +58,7 @@ export default function WorkflowListPage({ workflows }: Props) {
const [workflowToDeleteId, setwWorkflowToDeleteId] = useState(0);
const router = useRouter();
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
const urlPrefix = orgBranding ? `${orgBranding.slug}.${subdomainSuffix()}` : CAL_URL;
return (
@@ -6,7 +6,7 @@ import { useState } from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
import { useFlagMap } from "@calcom/features/flags/context/provider";
import { classNames } from "@calcom/lib";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -82,7 +82,7 @@ export default function CreateEventTypeDialog({
const { t } = useLocale();
const router = useRouter();
const [firstRender, setFirstRender] = useState(true);
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
const {
data: { teamId, eventPage: pageSlug },
+4 -3
View File
@@ -13,7 +13,6 @@ import { useIsEmbed } from "@calcom/embed-core/embed-iframe";
import UnconfirmedBookingBadge from "@calcom/features/bookings/UnconfirmedBookingBadge";
import ImpersonatingBanner from "@calcom/features/ee/impersonation/components/ImpersonatingBanner";
import { OrgUpgradeBanner } from "@calcom/features/ee/organizations/components/OrgUpgradeBanner";
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import HelpMenuItem from "@calcom/features/ee/support/components/HelpMenuItem";
import { TeamsUpgradeBanner } from "@calcom/features/ee/teams/components";
import { useFlagMap } from "@calcom/features/flags/context/provider";
@@ -79,6 +78,7 @@ import {
} from "@calcom/ui/components/icon";
import { Discord } from "@calcom/ui/components/icon/Discord";
import { useOrgBranding } from "../ee/organizations/context/provider";
import FreshChatProvider from "../ee/support/lib/freshchat/FreshChatProvider";
import { NProgressNextRouter } from "./NProgressPageIndicator";
import { TeamInviteBadge } from "./TeamInviteBadge";
@@ -801,7 +801,8 @@ const getOrganizationUrl = (slug: string) =>
function SideBar({ bannersHeight, user }: SideBarProps) {
const { t, isLocaleReady } = useLocale();
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
const isOrgBrandingDataFetched = orgBranding !== undefined;
const publicPageUrl = useMemo(() => {
if (!user?.organizationId) return `${process.env.NEXT_PUBLIC_WEBSITE_URL}/${user?.username}`;
@@ -839,7 +840,7 @@ function SideBar({ bannersHeight, user }: SideBarProps) {
className="desktop-transparent bg-muted border-muted fixed left-0 hidden h-full max-h-screen w-14 flex-col overflow-y-auto overflow-x-hidden border-r dark:bg-gradient-to-tr dark:from-[#2a2a2a] dark:to-[#1c1c1c] md:sticky md:flex lg:w-56 lg:px-3">
<div className="flex h-full flex-col justify-between py-3 lg:pt-4">
<header className="items-center justify-between md:hidden lg:flex">
{orgBranding ? (
{!isOrgBrandingDataFetched ? null : orgBranding ? (
<Link href="/event-types" className="px-1.5">
<div className="flex items-center gap-2 font-medium">
<Avatar
@@ -9,7 +9,7 @@ import type { MembershipRole } from "@calcom/prisma/enums";
import { trpc } from "@calcom/trpc";
import { Avatar, Badge, Button, DataTable } from "@calcom/ui";
import { useOrgBrandingValues } from "../../../ee/organizations/hooks";
import { useOrgBranding } from "../../../ee/organizations/context/provider";
import { ChangeUserRoleModal } from "./ChangeUserRoleModal";
import { DeleteMemberModal } from "./DeleteMemberModal";
import { ImpersonationMemberModal } from "./ImpersonationMemberModal";
@@ -97,7 +97,7 @@ export function UserListTable() {
const tableContainerRef = useRef<HTMLDivElement>(null);
const [state, dispatch] = useReducer(reducer, initialState);
const { t } = useLocale();
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
const { data, isLoading, fetchNextPage, isFetching } =
trpc.viewer.organizations.listMembers.useInfiniteQuery(
@@ -14,7 +14,6 @@ import {
DropdownMenuSeparator,
} from "@calcom/ui";
import { useOrgBrandingValues } from "../../../ee/organizations/hooks";
import type { Action } from "./UserListTable";
import type { User } from "./UserListTable";
@@ -34,7 +33,6 @@ export function TableActions({
};
}) {
const { t } = useLocale();
const orgBranding = useOrgBrandingValues();
const usersProfileUrl = domain + "/" + user.username;
+2 -2
View File
@@ -1,7 +1,7 @@
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
import { WEBAPP_URL } from "@calcom/lib/constants";
export const useBookerUrl = () => {
const orgBranding = useOrgBrandingValues();
const orgBranding = useOrgBranding();
return orgBranding?.fullDomain ?? WEBAPP_URL;
};