Merge branch 'main' into chor/text-colors+weights

This commit is contained in:
Peer Richelsen 2023-01-14 00:33:48 +01:00 committed by GitHub
commit c5077f098f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 79 additions and 47 deletions

View File

@ -44,13 +44,15 @@ export default function InstalledAppsLayout({
children, children,
...rest ...rest
}: { children: React.ReactNode } & ComponentProps<typeof Shell>) { }: { children: React.ReactNode } & ComponentProps<typeof Shell>) {
const variant: typeof InstalledAppVariants[number] = "payment";
const query = trpc.viewer.integrations.useQuery({ const query = trpc.viewer.integrations.useQuery({
variant: InstalledAppVariants.payment, variant,
onlyInstalled: true, onlyInstalled: true,
}); });
let actualTabs = tabs; let actualTabs = tabs;
if (query.data?.items.length === 0) { if (query.data?.items.length === 0) {
actualTabs = tabs.filter((tab) => tab.name !== InstalledAppVariants.payment); actualTabs = tabs.filter((tab) => tab.name !== variant);
} }
return ( return (

View File

@ -1,3 +1,4 @@
// lets refactor and move this into packages/lib/hooks/
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
const useMediaQuery = (query: string) => { const useMediaQuery = (query: string) => {

View File

@ -1,10 +1,10 @@
import { IdentityProvider } from "@prisma/client"; import { IdentityProvider } from "@prisma/client";
import { NextApiRequest, NextApiResponse } from "next"; import { NextApiRequest, NextApiResponse } from "next";
import { hashPassword } from "@calcom/lib/auth";
import { closeComUpsertTeamUser } from "@calcom/lib/sync/SyncServiceManager"; import { closeComUpsertTeamUser } from "@calcom/lib/sync/SyncServiceManager";
import prisma from "@calcom/prisma"; import prisma from "@calcom/prisma";
import { hashPassword } from "@lib/auth";
import slugify from "@lib/slugify"; import slugify from "@lib/slugify";
export default async function handler(req: NextApiRequest, res: NextApiResponse) { export default async function handler(req: NextApiRequest, res: NextApiResponse) {

View File

@ -92,8 +92,8 @@ function ConnectOrDisconnectIntegrationButton(props: {
} }
interface IntegrationsContainerProps { interface IntegrationsContainerProps {
variant?: keyof typeof InstalledAppVariants; variant?: typeof InstalledAppVariants[number];
exclude?: (keyof typeof InstalledAppVariants)[]; exclude?: typeof InstalledAppVariants[number][];
} }
interface IntegrationsListProps { interface IntegrationsListProps {
@ -143,8 +143,10 @@ const IntegrationsContainer = ({ variant, exclude }: IntegrationsContainerProps)
automation: Icon.FiShare2, automation: Icon.FiShare2,
analytics: Icon.FiBarChart, analytics: Icon.FiBarChart,
payment: Icon.FiCreditCard, payment: Icon.FiCreditCard,
web3: Icon.FiBarChart,
other: Icon.FiGrid, other: Icon.FiGrid,
}; };
return ( return (
<QueryCell <QueryCell
query={query} query={query}
@ -198,31 +200,29 @@ const IntegrationsContainer = ({ variant, exclude }: IntegrationsContainerProps)
}; };
const querySchema = z.object({ const querySchema = z.object({
category: z.nativeEnum(InstalledAppVariants), category: z.enum(InstalledAppVariants),
}); });
type querySchemaType = z.infer<typeof querySchema>;
export default function InstalledApps() { export default function InstalledApps() {
const { t } = useLocale(); const { t } = useLocale();
const router = useRouter(); const router = useRouter();
const category = router.query.category; const category = router.query.category as querySchemaType["category"];
const categoryList: querySchemaType["category"][] = [
"payment",
"conferencing",
"automation",
"analytics",
"web3",
];
return ( return (
<InstalledAppsLayout heading={t("installed_apps")} subtitle={t("manage_your_connected_apps")}> <InstalledAppsLayout heading={t("installed_apps")} subtitle={t("manage_your_connected_apps")}>
{(category === InstalledAppVariants.payment || category === InstalledAppVariants.conferencing) && ( {categoryList.includes(category) && <IntegrationsContainer variant={category} />}
<IntegrationsContainer variant={category} /> {category === "calendar" && <CalendarListContainer />}
)} {category === "other" && (
{(category === InstalledAppVariants.automation || category === InstalledAppVariants.analytics) && ( <IntegrationsContainer variant={category} exclude={[...categoryList, "calendar"]} />
<IntegrationsContainer variant={category} />
)}
{category === InstalledAppVariants.calendar && <CalendarListContainer />}
{category === InstalledAppVariants.other && (
<IntegrationsContainer
exclude={[
InstalledAppVariants.conferencing,
InstalledAppVariants.calendar,
InstalledAppVariants.analytics,
InstalledAppVariants.automation,
]}
/>
)} )}
</InstalledAppsLayout> </InstalledAppsLayout>
); );

View File

@ -799,12 +799,14 @@
"no_category_apps_description_analytics": "Add an analytics app for your booking pages", "no_category_apps_description_analytics": "Add an analytics app for your booking pages",
"no_category_apps_description_automation": "Add an automation app to use", "no_category_apps_description_automation": "Add an automation app to use",
"no_category_apps_description_other": "Add any other type of app to do all sorts of things", "no_category_apps_description_other": "Add any other type of app to do all sorts of things",
"no_category_apps_description_web3": "Add a web3 app for your booking pages",
"installed_app_calendar_description": "Set the calendars to check for conflicts to prevent double bookings.", "installed_app_calendar_description": "Set the calendars to check for conflicts to prevent double bookings.",
"installed_app_conferencing_description": "Add your favourite video conferencing apps for your meetings", "installed_app_conferencing_description": "Add your favourite video conferencing apps for your meetings",
"installed_app_payment_description": "Configure which payment processing services to use when charging your clients.", "installed_app_payment_description": "Configure which payment processing services to use when charging your clients.",
"installed_app_analytics_description": "Configure which analytics apps to use for your booking pages", "installed_app_analytics_description": "Configure which analytics apps to use for your booking pages",
"installed_app_other_description": "All your installed apps from other categories.", "installed_app_other_description": "All your installed apps from other categories.",
"installed_app_automation_description": "Configure which automation apps to use", "installed_app_automation_description": "Configure which automation apps to use",
"installed_app_web3_description": "Configure which web3 apps to use for your booking pages",
"analytics": "Analytics", "analytics": "Analytics",
"empty_installed_apps_headline": "No apps installed", "empty_installed_apps_headline": "No apps installed",
"empty_installed_apps_description": "Apps enable you to enhance your workflow and improve your scheduling life significantly.", "empty_installed_apps_description": "Apps enable you to enhance your workflow and improve your scheduling life significantly.",
@ -1217,6 +1219,7 @@
"connect_automation_apps": "Connect automation apps", "connect_automation_apps": "Connect automation apps",
"connect_analytics_apps": "Connect analytics apps", "connect_analytics_apps": "Connect analytics apps",
"connect_other_apps": "Connect other apps", "connect_other_apps": "Connect other apps",
"connect_web3_apps": "Connect web3 apps",
"current_step_of_total": "Step {{currentStep}} of {{maxSteps}}", "current_step_of_total": "Step {{currentStep}} of {{maxSteps}}",
"add_variable": "Add variable", "add_variable": "Add variable",
"custom_phone_number": "Custom phone number", "custom_phone_number": "Custom phone number",

View File

@ -2,7 +2,7 @@ import z from "zod";
import { InstalledAppVariants } from "../utils"; import { InstalledAppVariants } from "../utils";
const variantSchema = z.nativeEnum(InstalledAppVariants); const variantSchema = z.enum(InstalledAppVariants);
export default function getInstalledAppPath( export default function getInstalledAppPath(
{ variant, slug }: { variant?: string; slug?: string }, { variant, slug }: { variant?: string; slug?: string },

View File

@ -273,7 +273,7 @@ export default class GoogleCalendarService implements Calendar {
auth: myGoogleAuth, auth: myGoogleAuth,
calendarId: calendarId ? calendarId : defaultCalendarId, calendarId: calendarId ? calendarId : defaultCalendarId,
eventId: uid, eventId: uid,
sendNotifications: true, sendNotifications: false,
sendUpdates: "all", sendUpdates: "all",
}, },
function (err: GoogleCalError | null, event) { function (err: GoogleCalError | null, event) {

View File

@ -31,14 +31,15 @@ const credentialData = Prisma.validator<Prisma.CredentialArgs>()({
export type CredentialData = Prisma.CredentialGetPayload<typeof credentialData>; export type CredentialData = Prisma.CredentialGetPayload<typeof credentialData>;
export enum InstalledAppVariants { export const InstalledAppVariants = [
"conferencing" = "conferencing", "conferencing",
"calendar" = "calendar", "calendar",
"payment" = "payment", "payment",
"analytics" = "analytics", "analytics",
"automation" = "automation", "automation",
"other" = "other", "other",
} "web3",
] as const;
export const ALL_APPS = Object.values(ALL_APPS_MAP); export const ALL_APPS = Object.values(ALL_APPS_MAP);

View File

@ -306,15 +306,16 @@ async function handler(req: NextApiRequest & { userId?: number }) {
) { ) {
bookingToDelete.user.credentials bookingToDelete.user.credentials
.filter((credential) => credential.type.endsWith("_calendar")) .filter((credential) => credential.type.endsWith("_calendar"))
.forEach((credential) => { .forEach(async (credential) => {
const calendar = getCalendar(credential); const calendar = getCalendar(credential);
updatedBookings.forEach((updBooking) => { for (const updBooking of updatedBookings) {
const bookingRef = updBooking.references.find((ref) => ref.type.includes("_calendar")); const bookingRef = updBooking.references.find((ref) => ref.type.includes("_calendar"));
if (bookingRef) { if (bookingRef) {
const { uid, externalCalendarId } = bookingRef; const { uid, externalCalendarId } = bookingRef;
apiDeletes.push(calendar?.deleteEvent(uid, evt, externalCalendarId) as Promise<unknown>); const deletedEvent = await calendar?.deleteEvent(uid, evt, externalCalendarId);
apiDeletes.push(deletedEvent);
} }
}); }
}); });
} else { } else {
apiDeletes.push(calendar?.deleteEvent(uid, evt, externalCalendarId) as Promise<unknown>); apiDeletes.push(calendar?.deleteEvent(uid, evt, externalCalendarId) as Promise<unknown>);

View File

@ -5,6 +5,7 @@ import { useEmbedStyles } from "@calcom/embed-core/embed-iframe";
import classNames from "@calcom/lib/classNames"; import classNames from "@calcom/lib/classNames";
import { daysInMonth, yyyymmdd } from "@calcom/lib/date-fns"; import { daysInMonth, yyyymmdd } from "@calcom/lib/date-fns";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import useMediaQuery from "@calcom/lib/hooks/useMediaQuery";
import { weekdayNames } from "@calcom/lib/weekday"; import { weekdayNames } from "@calcom/lib/weekday";
import { Button, Icon, SkeletonText } from "@calcom/ui"; import { Button, Icon, SkeletonText } from "@calcom/ui";
@ -135,6 +136,9 @@ const Days = ({
const date = browsingDate.set("date", day); const date = browsingDate.set("date", day);
days.push(date); days.push(date);
} }
const isMobile = useMediaQuery("(max-width: 768px)");
return ( return (
<> <>
{days.map((day, idx) => ( {days.map((day, idx) => (
@ -153,12 +157,13 @@ const Days = ({
date={day} date={day}
onClick={() => { onClick={() => {
props.onChange(day); props.onChange(day);
setTimeout(() => { isMobile &&
window.scrollTo({ setTimeout(() => {
top: 360, window.scrollTo({
behavior: "smooth", top: 360,
}); behavior: "smooth",
}, 500); });
}, 500);
}} }}
disabled={ disabled={
(includedDates && !includedDates.includes(yyyymmdd(day))) || (includedDates && !includedDates.includes(yyyymmdd(day))) ||

View File

@ -5,7 +5,7 @@ import { z } from "zod";
import MemberInvitationModal from "@calcom/features/ee/teams/components/MemberInvitationModal"; import MemberInvitationModal from "@calcom/features/ee/teams/components/MemberInvitationModal";
import { classNames } from "@calcom/lib"; import { classNames } from "@calcom/lib";
import { WEBAPP_URL } from "@calcom/lib/constants"; import { WEBAPP_URL, APP_NAME } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { RouterOutputs, trpc } from "@calcom/trpc/react"; import { RouterOutputs, trpc } from "@calcom/trpc/react";
import { Avatar, Badge, Button, Icon, showToast, SkeletonContainer, SkeletonText } from "@calcom/ui"; import { Avatar, Badge, Button, Icon, showToast, SkeletonContainer, SkeletonText } from "@calcom/ui";
@ -156,7 +156,7 @@ const PendingMemberItem = (props: { member: TeamMember; index: number; teamId: n
{member.username ? ( {member.username ? (
<p className="text-gray-600">{`${WEBAPP_URL}/${member.username}`}</p> <p className="text-gray-600">{`${WEBAPP_URL}/${member.username}`}</p>
) : ( ) : (
<p className="text-gray-600">{t("not_on_cal")}</p> <p className="text-gray-600">{t("not_on_cal", { appName: APP_NAME })}</p>
)} )}
</div> </div>
</div> </div>

View File

@ -0,0 +1,19 @@
import { useState, useEffect } from "react";
const useMediaQuery = (query: string) => {
const [matches, setMatches] = useState(false);
useEffect(() => {
const media = window.matchMedia(query);
if (media.matches !== matches) {
setMatches(media.matches);
}
const listener = () => setMatches(media.matches);
window.addEventListener("resize", listener);
return () => window.removeEventListener("resize", listener);
}, [matches, query]);
return matches;
};
export default useMediaQuery;

View File

@ -251,7 +251,7 @@ export const viewerTeamsRouter = router({
.input( .input(
z.object({ z.object({
teamId: z.number(), teamId: z.number(),
usernameOrEmail: z.string(), usernameOrEmail: z.string().transform((usernameOrEmail) => usernameOrEmail.toLowerCase()),
role: z.nativeEnum(MembershipRole), role: z.nativeEnum(MembershipRole),
language: z.string(), language: z.string(),
sendEmailInvitation: z.boolean(), sendEmailInvitation: z.boolean(),
@ -321,7 +321,7 @@ export const viewerTeamsRouter = router({
from: ctx.user.name, from: ctx.user.name,
to: input.usernameOrEmail, to: input.usernameOrEmail,
teamName: team.name, teamName: team.name,
joinLink: `${WEBAPP_URL}/signup?token=${token}&callbackUrl=/settings/teams`, joinLink: `${WEBAPP_URL}/signup?token=${token}&callbackUrl=/teams`,
}); });
} }
} else { } else {