Merge branch 'main' into refactor-event-types-type-id-10419-cal-2264-cal-2296

This commit is contained in:
Peer Richelsen 2023-09-04 15:42:24 +02:00 committed by GitHub
commit b48934b126
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 141 additions and 89 deletions

View File

@ -1,6 +1,6 @@
# Contributing to Cal.com
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
Contributions are what makes the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
- Before jumping into a PR be sure to search [existing PRs](https://github.com/calcom/cal.com/pulls) or [issues](https://github.com/calcom/cal.com/issues) for an open or closed item that relates to your submission.
@ -37,7 +37,7 @@ Contributions are what make the open source community such an amazing place to l
</tr>
<tr>
<td>
Core Features (Booking page, availabilty, timezone calculation)
Core Features (Booking page, availability, timezone calculation)
</td>
<td>
<a href="https://github.com/calcom/cal.com/issues?q=is:issue+is:open+sort:updated-desc+label:%22High+priority%22">
@ -132,7 +132,6 @@ If you get errors, be sure to fix them before committing.
## Making a Pull Request
- Be sure to [check the "Allow edits from maintainers" option](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork) while creating you PR.
- If your PR refers to or fixes an issue, be sure to add `refs #XXX` or `fixes #XXX` to the PR description. Replacing `XXX` with the respective issue number. See more about [Linking a pull request to an issue
](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
- Be sure to [check the "Allow edits from maintainers" option](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork) while creating your PR.
- If your PR refers to or fixes an issue, be sure to add `refs #XXX` or `fixes #XXX` to the PR description. Replacing `XXX` with the respective issue number. See more about [Linking a pull request to an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
- Be sure to fill the PR Template accordingly.

View File

@ -423,7 +423,7 @@ yarn seed-app-store
```
You will need to complete a few more steps to activate Google Calendar App.
Make sure to complete section "Obtaining the Google API Credentials". After the do the
Make sure to complete section "Obtaining the Google API Credentials". After that do the
following
1. Add extra redirect URL `<Cal.com URL>/api/auth/callback/google`
@ -449,8 +449,8 @@ following
7. Click "Create".
8. Now copy the Client ID and Client Secret to your `.env` file into the `ZOOM_CLIENT_ID` and `ZOOM_CLIENT_SECRET` fields.
9. Set the Redirect URL for OAuth `<Cal.com URL>/api/integrations/zoomvideo/callback` replacing Cal.com URL with the URI at which your application runs.
10. Also add the redirect URL given above as a allow list URL and enable "Subdomain check". Make sure, it says "saved" below the form.
11. You don't need to provide basic information about your app. Instead click at "Scopes" and then at "+ Add Scopes". On the left, click the category "Meeting" and check the scope `meeting:write`.
10. Also add the redirect URL given above as an allow list URL and enable "Subdomain check". Make sure, it says "saved" below the form.
11. You don't need to provide basic information about your app. Instead click on "Scopes" and then on "+ Add Scopes". On the left, click the category "Meeting" and check the scope `meeting:write`.
12. Click "Done".
13. You're good to go. Now you can easily add your Zoom integration in the Cal.com settings.

View File

@ -13,7 +13,7 @@ import { Meta } from "@storybook/addon-docs";
<a href="https://www.figma.com/file/9MOufQNLtdkpnDucmNX10R/%E2%9D%96-Cal-DS" target="_blank">
Figma
</a>{" "}
library is avalible for anyone to view and use. If you have any questions or concerns, please reach out to
library is available for anyone to view and use. If you have any questions or concerns, please reach out to
the design team.
</p>
</div>

View File

@ -4,6 +4,7 @@ import { useEffect, useRef, useState } from "react";
import { z } from "zod";
import type { CredentialOwner } from "@calcom/app-store/types";
import classNames from "@calcom/lib/classNames";
import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { useTypedQuery } from "@calcom/lib/hooks/useTypedQuery";
@ -80,7 +81,13 @@ export default function AppListCard(props: AppListCardProps) {
return (
<div className={`${highlight ? "dark:bg-muted bg-yellow-100" : ""}`}>
<div className="flex items-center gap-x-3 px-5 py-4">
{logo ? <img className="h-10 w-10" src={logo} alt={`${title} logo`} /> : null}
{logo ? (
<img
className={classNames(logo.includes("-dark") && "dark:invert", "h-10 w-10")}
src={logo}
alt={`${title} logo`}
/>
) : null}
<div className="flex grow flex-col gap-y-1 truncate">
<div className="flex items-center gap-x-2">
<h3 className="text-emphasis truncate text-sm font-semibold">{title}</h3>

View File

@ -306,7 +306,7 @@ export const EventSetupTab = (
"h-4 w-4",
// invert all the icons except app icons
eventLocationType.iconUrl &&
!eventLocationType.iconUrl.startsWith("/app-store") &&
eventLocationType.iconUrl.includes("-dark") &&
"dark:invert"
)}
alt={`${eventLocationType.label} logo`}

View File

@ -66,6 +66,7 @@ type Props = {
formMethods: UseFormReturn<FormValues>;
isUpdateMutationLoading?: boolean;
availability?: AvailabilityOption;
isUserOrganizationAdmin: boolean;
};
function getNavigation(props: {
@ -133,6 +134,7 @@ function EventTypeSingleLayout({
isUpdateMutationLoading,
formMethods,
availability,
isUserOrganizationAdmin,
}: Props) {
const utils = trpc.useContext();
const { t } = useLocale();
@ -142,7 +144,8 @@ function EventTypeSingleLayout({
const hasPermsToDelete =
currentUserMembership?.role !== "MEMBER" ||
!currentUserMembership ||
eventType.schedulingType === SchedulingType.MANAGED;
eventType.schedulingType === SchedulingType.MANAGED ||
isUserOrganizationAdmin;
const deleteMutation = trpc.viewer.eventTypes.delete.useMutation({
onSuccess: async () => {

View File

@ -4,7 +4,6 @@ import { components } from "react-select";
import type { EventLocationType } from "@calcom/app-store/locations";
import type { CredentialDataWithTeamName } from "@calcom/app-store/utils";
import { classNames } from "@calcom/lib";
import cx from "@calcom/lib/classNames";
import { Select } from "@calcom/ui";
export type LocationOption = {
@ -28,7 +27,7 @@ const OptionWithIcon = ({ icon, label }: { icon?: string; label: string }) => {
src={icon}
alt="cover"
// invert all the icons except app icons
className={cx("h-3.5 w-3.5", icon && !icon.startsWith("/app-store") && "dark:invert")}
className={classNames(icon.includes("-dark") && "dark:invert", "h-3.5 w-3.5")}
/>
)}
<span className={classNames("text-sm font-medium")}>{label}</span>
@ -57,7 +56,13 @@ export default function LocationSelect(props: Props<LocationOption, false, Group
}}
formatOptionLabel={(e) => (
<div className="flex items-center gap-3">
{e.icon && <img src={e.icon} alt="app-icon" className="h-5 w-5" />}
{e.icon && (
<img
src={e.icon}
alt="app-icon"
className={classNames(e.icon.includes("-dark") && "dark:invert", "h-5 w-5")}
/>
)}
<span>{e.label}</span>
</div>
)}

View File

@ -12,7 +12,14 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import type { AppCategories } from "@calcom/prisma/enums";
import type { inferSSRProps } from "@calcom/types/inferSSRProps";
import type { HorizontalTabItemProps } from "@calcom/ui";
import { AllApps, AppStoreCategories, HorizontalTabs, TextField, PopularAppsSlider } from "@calcom/ui";
import {
AllApps,
AppStoreCategories,
HorizontalTabs,
TextField,
PopularAppsSlider,
RecentAppsSlider,
} from "@calcom/ui";
import { Search } from "@calcom/ui/components/icon";
import PageWrapper from "@components/PageWrapper";
@ -81,6 +88,7 @@ export default function Apps({
<>
<AppStoreCategories categories={categories} />
<PopularAppsSlider items={appStore} />
<RecentAppsSlider items={appStore} />
</>
)}
<AllApps

View File

@ -443,7 +443,8 @@ const EventTypePage = (props: EventTypeSetupProps) => {
isUpdateMutationLoading={updateMutation.isLoading}
formMethods={formMethods}
disableBorder={tabName === "apps" || tabName === "workflows" || tabName === "webhooks"}
currentUserMembership={currentUserMembership}>
currentUserMembership={currentUserMembership}
isUserOrganizationAdmin={props.isUserOrganizationAdmin}>
<Form
form={formMethods}
id="event-type-form"

View File

@ -674,6 +674,7 @@ export const EventTypeList = ({ data }: EventTypeListProps): JSX.Element => {
title={t(`delete${isManagedEventPrefix()}_event_type`)}
confirmBtnText={t(`confirm_delete_event_type`)}
loadingText={t(`confirm_delete_event_type`)}
isLoading={deleteMutation.isLoading}
onConfirm={(e) => {
e.preventDefault();
deleteEventTypeHandler(deleteDialogTypeId);

View File

@ -1074,7 +1074,7 @@
"event_cancelled": "تم إلغاء هذا الحدث",
"emailed_information_about_cancelled_event": "لقد أرسلنا إليك وإلى الحاضرين الآخرين بريداً إلكترونياً لإعلامهم.",
"this_input_will_shown_booking_this_event": "سيُعرَض هذا المُدخَل عند حجز هذا الحدث",
"meeting_url_in_conformation_email": "عنوان رابط الاجتماع موجود في رسالة التأكيد الإلكترونية",
"meeting_url_in_confirmation_email": "عنوان رابط الاجتماع موجود في رسالة التأكيد الإلكترونية",
"url_start_with_https": "يجب أن يبدأ العنوان بـ http:// أو https://",
"number_provided": "سيتم توفير رقم الهاتف",
"before_event_trigger": "قبل بدء الحدث",

View File

@ -1075,7 +1075,7 @@
"event_cancelled": "Tato událost je zrušena",
"emailed_information_about_cancelled_event": "Poslali jsme vám a ostatním účastníkům informační e-mail.",
"this_input_will_shown_booking_this_event": "Toto pole se zobrazí při rezervaci této události",
"meeting_url_in_conformation_email": "Adresa URL schůzky je v potvrzovacím e-mailu",
"meeting_url_in_confirmation_email": "Adresa URL schůzky je v potvrzovacím e-mailu",
"url_start_with_https": "Adresa URL musí začínat http:// nebo https://",
"number_provided": "Bude uvedeno telefonní číslo",
"before_event_trigger": "před zahájením události",

View File

@ -960,7 +960,7 @@
"reschedule_placeholder": "Lad andre vide, hvorfor du har brug for at omlægge",
"emailed_information_about_cancelled_event": "Vi har sendt en e-mail til dig og de andre deltagere for at give dem besked.",
"this_input_will_shown_booking_this_event": "Dette input vil blive vist ved booking af denne begivenhed",
"meeting_url_in_conformation_email": "Møde-url er i bekræftelses-mailen",
"meeting_url_in_confirmation_email": "Møde-url er i bekræftelses-mailen",
"url_start_with_https": "URL'en skal starte med http:// eller https://",
"number_provided": "Telefonnummer vil blive angivet",
"before_event_trigger": "før begivenheden starter",

View File

@ -1095,7 +1095,7 @@
"event_cancelled": "Dieser Termin ist abgesagt",
"emailed_information_about_cancelled_event": "Wir haben Ihnen und den anderen Teilnehmern eine E-Mail gesendet, damit alle Bescheid wissen.",
"this_input_will_shown_booking_this_event": "Diese Eingabe wird bei der Buchung dieses Termins angezeigt",
"meeting_url_in_conformation_email": "Termin-URL ist in der Bestätigungsmail",
"meeting_url_in_confirmation_email": "Termin-URL ist in der Bestätigungsmail",
"url_start_with_https": "URL muss mit http:// oder https:// beginnen",
"number_provided": "Telefonnummer wird angegeben",
"before_event_trigger": "vor Beginn des Termins",

View File

@ -1098,7 +1098,7 @@
"event_cancelled": "This event is canceled",
"emailed_information_about_cancelled_event": "We emailed you and the other attendees to let them know.",
"this_input_will_shown_booking_this_event": "This input will be shown when booking this event",
"meeting_url_in_conformation_email": "Meeting url is in the confirmation email",
"meeting_url_in_confirmation_email": "Meeting url is in the confirmation email",
"url_start_with_https": "URL needs to start with http:// or https://",
"number_provided": "Phone number will be provided",
"before_event_trigger": "before event starts",
@ -2037,5 +2037,6 @@
"team_no_event_types": "This team has no event types",
"seat_options_doesnt_multiple_durations": "Seat option doesn't support multiple durations",
"include_calendar_event": "Include calendar event",
"recently_added":"Recently added",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}

View File

@ -1075,7 +1075,7 @@
"event_cancelled": "Este evento se canceló",
"emailed_information_about_cancelled_event": "Le enviamos un correo electrónico a usted y a los demás asistentes para informarles.",
"this_input_will_shown_booking_this_event": "Esta entrada se mostrará al reservar este evento.",
"meeting_url_in_conformation_email": "La URL de la reunión está en el correo de confirmación",
"meeting_url_in_confirmation_email": "La URL de la reunión está en el correo de confirmación",
"url_start_with_https": "La URL debe empezar por http:// o https://",
"number_provided": "Se proporcionará el número de teléfono",
"before_event_trigger": "antes del inicio del evento",

View File

@ -1098,7 +1098,7 @@
"event_cancelled": "Cet événement est annulé",
"emailed_information_about_cancelled_event": "Nous vous avons envoyé un e-mail à vous et aux autres participants pour les en informer.",
"this_input_will_shown_booking_this_event": "Ce champ sera affiché lors de la réservation de cet événement.",
"meeting_url_in_conformation_email": "Le lien du rendez-vous est dans l'e-mail de confirmation",
"meeting_url_in_confirmation_email": "Le lien du rendez-vous est dans l'e-mail de confirmation",
"url_start_with_https": "Le lien doit commencer par http:// ou https://",
"number_provided": "Un numéro de téléphone sera fourni",
"before_event_trigger": "avant le début de l'événement",

View File

@ -1075,7 +1075,7 @@
"event_cancelled": "האירוע בוטל",
"emailed_information_about_cancelled_event": "שלחנו לך ולשאר המשתתפים הודעת דוא״ל כדי ליידע אותם על כך.",
"this_input_will_shown_booking_this_event": "הקלט יוצג בעת הזמנת אירוע זה",
"meeting_url_in_conformation_email": "כתובת ה-URL של הפגישה נמצאת בהודעת הדוא״ל שנשלחה לאישור הפגישה",
"meeting_url_in_confirmation_email": "כתובת ה-URL של הפגישה נמצאת בהודעת הדוא״ל שנשלחה לאישור הפגישה",
"url_start_with_https": "כתובת ה-URL צריכה להתחיל עם הקידומת http:// או https://",
"number_provided": "מספר הטלפון יסופק",
"before_event_trigger": "לפני שהאירוע מתחיל",

View File

@ -1075,7 +1075,7 @@
"event_cancelled": "Questo evento è stato cancellato",
"emailed_information_about_cancelled_event": "Abbiamo inviato un'e-mail di notifica a te e agli altri partecipanti.",
"this_input_will_shown_booking_this_event": "Questo input verrà mostrato durante la prenotazione di questo evento",
"meeting_url_in_conformation_email": "L'URL della riunione è riportato nell'e-mail di conferma",
"meeting_url_in_confirmation_email": "L'URL della riunione è riportato nell'e-mail di conferma",
"url_start_with_https": "L'URL deve iniziare con http:// o https://",
"number_provided": "Verrà fornito il numero di telefono",
"before_event_trigger": "prima dell'inizio dell'evento",

View File

@ -1075,7 +1075,7 @@
"event_cancelled": "このイベントはキャンセルされました",
"emailed_information_about_cancelled_event": "あなたと他の出席者に電子メールでお知らせしました。",
"this_input_will_shown_booking_this_event": "この入力は、このイベントを予約する際に表示されます",
"meeting_url_in_conformation_email": "ミーティングURLは確認メールに記載されています",
"meeting_url_in_confirmation_email": "ミーティングURLは確認メールに記載されています",
"url_start_with_https": "URLは、http://またはhttps://で始まる必要があります",
"number_provided": "電話番号が提供されます",
"before_event_trigger": "イベント開始前に",

View File

@ -1075,7 +1075,7 @@
"event_cancelled": "이 이벤트는 취소되었습니다",
"emailed_information_about_cancelled_event": "귀하와 다른 참석자들에게 이메일로 알려 드렸습니다.",
"this_input_will_shown_booking_this_event": "이 입력은 이 이벤트를 예약할 때 표시됩니다.",
"meeting_url_in_conformation_email": "회의 URL은 확인 이메일에 있습니다",
"meeting_url_in_confirmation_email": "회의 URL은 확인 이메일에 있습니다",
"url_start_with_https": "URL은 http:// 또는 https://로 시작해야 합니다",
"number_provided": "전화 번호는 제공됩니다",
"before_event_trigger": "이벤트 시작 전",

View File

@ -1079,7 +1079,7 @@
"event_cancelled": "Deze gebeurtenis is geannuleerd",
"emailed_information_about_cancelled_event": "We hebben u en de andere deelnemers een e-mail gestuurd om hen te informeren.",
"this_input_will_shown_booking_this_event": "Deze invoer wordt getoond tijdens het boeken van dit evenement",
"meeting_url_in_conformation_email": "De vergader-URL wordt vermeld in de bevestigings-e-mail",
"meeting_url_in_confirmation_email": "De vergader-URL wordt vermeld in de bevestigings-e-mail",
"url_start_with_https": "URL moet beginnen met http:// of https://",
"number_provided": "Telefoonnummer wordt verstrekt",
"before_event_trigger": "voordat de gebeurtenis begint",

View File

@ -941,7 +941,7 @@
"reschedule_placeholder": "Fortell andre hvorfor du må endre tidspunktet",
"emailed_information_about_cancelled_event": "Vi sendte deg og de andre deltakerne en e-post for å informere.",
"this_input_will_shown_booking_this_event": "Dette inputfeltet vil vises når man booker denne hendelsen",
"meeting_url_in_conformation_email": "Møte-url ligger i e-postbekreftelsen",
"meeting_url_in_confirmation_email": "Møte-url ligger i e-postbekreftelsen",
"url_start_with_https": "URL må begynne med http:// eller https://",
"number_provided": "Telefonnummer vil bli oppgitt",
"before_event_trigger": "før hendelsen starter",

View File

@ -1075,7 +1075,7 @@
"event_cancelled": "To wydarzenie zostało anulowane",
"emailed_information_about_cancelled_event": "Wysłaliśmy wiadomość e-mail Tobie i innym uczestnikom, aby ich o tym poinformować.",
"this_input_will_shown_booking_this_event": "To wejście zostanie wyświetlone podczas rezerwacji tego wydarzenia",
"meeting_url_in_conformation_email": "Adres URL spotkania znajduje się w wiadomości e-mail z potwierdzeniem",
"meeting_url_in_confirmation_email": "Adres URL spotkania znajduje się w wiadomości e-mail z potwierdzeniem",
"url_start_with_https": "Adres URL musi zaczynać się od http:// lub https://",
"number_provided": "Numer telefonu zostanie podany.",
"before_event_trigger": "przed rozpoczęciem wydarzenia",

View File

@ -1091,7 +1091,7 @@
"event_cancelled": "Este evento foi cancelado",
"emailed_information_about_cancelled_event": "Avisamos por e-mail aos outros participantes e a você.",
"this_input_will_shown_booking_this_event": "Este campo será mostrado na reserva deste evento",
"meeting_url_in_conformation_email": "O URL da reunião está no e-mail de confirmação",
"meeting_url_in_confirmation_email": "O URL da reunião está no e-mail de confirmação",
"url_start_with_https": "O URL precisa começar com http:// ou https://",
"number_provided": "O número de telefone será fornecido",
"before_event_trigger": "antes do início do evento",

View File

@ -1075,7 +1075,7 @@
"event_cancelled": "Este evento foi cancelado",
"emailed_information_about_cancelled_event": "Enviámos um email com o aviso para si e para os restantes participantes.",
"this_input_will_shown_booking_this_event": "Este campo será mostrado na reserva deste evento",
"meeting_url_in_conformation_email": "O URL da reunião está no email de confirmação",
"meeting_url_in_confirmation_email": "O URL da reunião está no email de confirmação",
"url_start_with_https": "O URL tem de começar por http:// ou https://",
"number_provided": "Será fornecido um número de telefone",
"before_event_trigger": "antes do evento iniciar",

View File

@ -1075,7 +1075,7 @@
"event_cancelled": "Acest eveniment este anulat",
"emailed_information_about_cancelled_event": "V-am trimis un e-mail de informare dvs. și celorlalți participanți.",
"this_input_will_shown_booking_this_event": "Datele introduse vor fi afișate la rezervarea acestui eveniment",
"meeting_url_in_conformation_email": "Adresa URL a întâlnirii este în e-mailul de confirmare",
"meeting_url_in_confirmation_email": "Adresa URL a întâlnirii este în e-mailul de confirmare",
"url_start_with_https": "Adresa URL trebuie să înceapă cu http:// or https://",
"number_provided": "Numărul de telefon va fi furnizat",
"before_event_trigger": "înainte de începerea evenimentului",

View File

@ -1075,7 +1075,7 @@
"event_cancelled": "Это событие отменено",
"emailed_information_about_cancelled_event": "Мы сообщили об этом вам и другим участникам по электронной почте.",
"this_input_will_shown_booking_this_event": "Этот вопрос будет показан при бронировании события по этому шаблону",
"meeting_url_in_conformation_email": "Ссылка на встречу находится в письме с подтверждением",
"meeting_url_in_confirmation_email": "Ссылка на встречу находится в письме с подтверждением",
"url_start_with_https": "URL-адрес должен начинаться с http:// или https://",
"number_provided": "Будет указан номер телефона",
"before_event_trigger": "до начала события",

View File

@ -1076,7 +1076,7 @@
"event_cancelled": "Ovaj događaj je otkazan",
"emailed_information_about_cancelled_event": "Poslali smo imejl vama i drugim polaznicima kao obaveštenje.",
"this_input_will_shown_booking_this_event": "Ovaj unos će biti prikazan kad se rezerviše ovaj događaj",
"meeting_url_in_conformation_email": "Url za sastanak je u imejlu za potvrdu",
"meeting_url_in_confirmation_email": "Url za sastanak je u imejlu za potvrdu",
"url_start_with_https": "Potrebno je URL da počinje sa http:// or https://",
"number_provided": "Broj telefona će biti dostavljen",
"before_event_trigger": "pre početka događaja",

View File

@ -1075,7 +1075,7 @@
"event_cancelled": "Den här händelsen är inställd",
"emailed_information_about_cancelled_event": "Vi mejlade dig och de andra deltagarna för att informera om detta.",
"this_input_will_shown_booking_this_event": "Detta visas vid bokning av denna händelse",
"meeting_url_in_conformation_email": "Mötets webbadress finns i bekräftelsemejlet",
"meeting_url_in_confirmation_email": "Mötets webbadress finns i bekräftelsemejlet",
"url_start_with_https": "Webbadress behöver inledas med http:// eller https://",
"number_provided": "Telefonnummer kommer att anges",
"before_event_trigger": "innan händelsen startar",

View File

@ -1075,7 +1075,7 @@
"event_cancelled": "Bu etkinlik iptal edildi",
"emailed_information_about_cancelled_event": "Sizi ve diğer katılımcıları bilgilendirmek için bir e-posta gönderdik.",
"this_input_will_shown_booking_this_event": "Bu girdi, bu etkinlik için rezervasyon yapılırken gösterilecek",
"meeting_url_in_conformation_email": "Toplantı URL'si onay e-postasında mevcut",
"meeting_url_in_confirmation_email": "Toplantı URL'si onay e-postasında mevcut",
"url_start_with_https": "URL'nin http:// veya https:// ile başlaması gerekiyor",
"number_provided": "Telefon numarası sağlanacaktır",
"before_event_trigger": "etkinlik başlamadan önce",

View File

@ -1075,7 +1075,7 @@
"event_cancelled": "Цей захід скасовано",
"emailed_information_about_cancelled_event": "Ми сповістили вас та інших учасників електронною поштою.",
"this_input_will_shown_booking_this_event": "Це поле введення буде показано під час бронювання часу для цього заходу",
"meeting_url_in_conformation_email": "URL-адресу наради вказано в листі з підтвердженням",
"meeting_url_in_confirmation_email": "URL-адресу наради вказано в листі з підтвердженням",
"url_start_with_https": "URL-адреса має починатися з http:// або https://",
"number_provided": "Номер телефону буде надано",
"before_event_trigger": "до початку заходу",

View File

@ -1075,7 +1075,7 @@
"event_cancelled": "Sự kiện này bị huỷ",
"emailed_information_about_cancelled_event": "Chúng tôi đã gửi email cho bạn và những người tham dự khác để cho họ biết.",
"this_input_will_shown_booking_this_event": "Trường này sẽ được hiển thị khi đặt sự kiện này",
"meeting_url_in_conformation_email": "Url cuộc họp nằm trong email xác nhận",
"meeting_url_in_confirmation_email": "Url cuộc họp nằm trong email xác nhận",
"url_start_with_https": "URL cần bắt đầu bằng http:// hoặc https://",
"number_provided": "Số điện thoại sẽ được cung ứng",
"before_event_trigger": "trước khi sự kiện bắt đầu",

View File

@ -1079,7 +1079,7 @@
"event_cancelled": "此活动已取消",
"emailed_information_about_cancelled_event": "我们已向您和其他参与者发送电子邮件来通知他们。",
"this_input_will_shown_booking_this_event": "在预约此活动时将显示该输入框",
"meeting_url_in_conformation_email": "会议链接含在确认电子邮件中",
"meeting_url_in_confirmation_email": "会议链接含在确认电子邮件中",
"url_start_with_https": "链接需要以 http:// 或 https:// 开头",
"number_provided": "将提供电话号码",
"before_event_trigger": "活动开始前",
@ -1945,5 +1945,6 @@
"insights_subtitle": "查看您活动的预约 insights",
"custom_plan": "自定义计划",
"include_calendar_event": "包括日历活动",
"recently_added": "最近添加",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ 在此上方添加您的新字符串 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}

View File

@ -1075,7 +1075,7 @@
"event_cancelled": "此活動已取消",
"emailed_information_about_cancelled_event": "我們已給您和其他與會者發送通知電子郵件。",
"this_input_will_shown_booking_this_event": "輸入欄會在預約此活動的時候顯示",
"meeting_url_in_conformation_email": "會議網址請參見確認電子郵件",
"meeting_url_in_confirmation_email": "會議網址請參見確認電子郵件",
"url_start_with_https": "URL 需要以 http:// 或 https:// 開頭",
"number_provided": "將提供電話號碼",
"before_event_trigger": "活動開始前",

View File

@ -207,16 +207,14 @@ html.todesktop nav a svg{
https://github.com/tailwindlabs/tailwindcss/pull/5732
*/
@layer utilities {
@layer responsive {
/* Chrome, Safari and Opera */
.no-scrollbar::-webkit-scrollbar {
display: none;
}
/* Chrome, Safari and Opera */
.no-scrollbar::-webkit-scrollbar {
display: none;
}
.no-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
.no-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
}

View File

@ -34,7 +34,7 @@ export async function getAppWithMetadata(app: { dirName: string } | { slug: stri
export async function getAppRegistry() {
const dbApps = await prisma.app.findMany({
where: { enabled: true },
select: { dirName: true, slug: true, categories: true, enabled: true },
select: { dirName: true, slug: true, categories: true, enabled: true, createdAt: true },
});
const apps = [] as App[];
const installCountPerApp = await getInstallCountPerApp();
@ -44,7 +44,7 @@ export async function getAppRegistry() {
// Skip if app isn't installed
/* This is now handled from the DB */
// if (!app.installed) return apps;
app.createdAt = dbapp.createdAt.toISOString();
apps.push({
...app,
category: app.category || "other",
@ -101,6 +101,7 @@ export async function getAppRegistryWithCredentials(userId: number, userAdminTea
// Skip if app isn't installed
/* This is now handled from the DB */
// if (!app.installed) return apps;
app.createdAt = dbapp.createdAt.toISOString();
let dependencyData: {
name?: string;
installed?: boolean;

View File

@ -403,7 +403,7 @@ export function getSuccessPageLocationMessage(
locationToDisplay == t("web_conference");
} else if (isConfirmed) {
locationToDisplay =
getHumanReadableLocationValue(location, t) + ": " + t("meeting_url_in_conformation_email");
getHumanReadableLocationValue(location, t) + ": " + t("meeting_url_in_confirmation_email");
} else {
locationToDisplay = t("web_conferencing_details_to_follow");
}

View File

@ -179,7 +179,7 @@ function isValidNamespace(ns: string | null | undefined) {
/**
* It handles any URL change done through Web history API as well
* History API is currenty being used by Booker/utils/query-param
* History API is currently being used by Booker/utils/query-param
*/
const useUrlChange = (callback: (newUrl: string) => void) => {
const currentFullUrl = isBrowser ? new URL(document.URL) : null;

View File

@ -22,9 +22,9 @@ function RenderIcon({
<img
src={eventLocationType.iconUrl}
className={classNames(
"me-[10px] h-4 w-4 opacity-70 dark:opacity-100",
!eventLocationType.iconUrl?.startsWith("/app-store") ? "dark:invert-[.65]" : "",
!eventLocationType.iconUrl?.startsWith("/app-store") && isTooltip && "invert"
"me-[10px] h-4 w-4 opacity-70 dark:opacity-100",
eventLocationType.iconUrl?.includes("-dark") ? "dark:invert-[.65]" : "",
eventLocationType.iconUrl?.includes("-dark") && isTooltip && "invert"
)}
alt={`${eventLocationType.label} icon`}
/>

View File

@ -1,7 +1,6 @@
import type { Payment } from "@prisma/client";
import type { EventType } from "@prisma/client";
import { Elements, PaymentElement, useElements, useStripe } from "@stripe/react-stripe-js";
import type stripejs from "@stripe/stripe-js";
import type { StripeElementLocale } from "@stripe/stripe-js";
import { useRouter, useSearchParams } from "next/navigation";
import type { SyntheticEvent } from "react";
@ -181,27 +180,14 @@ const PaymentForm = (props: Props) => {
);
};
const ELEMENT_STYLES: stripejs.Appearance = {
theme: "none",
};
const ELEMENT_STYLES_DARK: stripejs.Appearance = {
theme: "night",
variables: {
colorText: "#d6d6d6",
fontWeightNormal: "600",
borderRadius: "6px",
colorBackground: "#101010",
colorPrimary: "#d6d6d6",
},
};
export default function PaymentComponent(props: Props) {
const stripePromise = getStripe(props.payment.data.stripe_publishable_key as any);
const [darkMode, setDarkMode] = useState<boolean>(false);
const [theme, setTheme] = useState<"stripe" | "night">("stripe");
useEffect(() => {
setDarkMode(window.matchMedia("(prefers-color-scheme: dark)").matches);
if (document.documentElement.classList.contains("dark")) {
setTheme("night");
}
}, []);
return (
@ -209,7 +195,9 @@ export default function PaymentComponent(props: Props) {
stripe={stripePromise}
options={{
clientSecret: props.clientSecret,
appearance: darkMode ? ELEMENT_STYLES_DARK : ELEMENT_STYLES,
appearance: {
theme,
},
}}>
<PaymentForm {...props} />
</Elements>

View File

@ -437,9 +437,6 @@ function FieldEditDialog({
value={fieldTypesConfigMap[fieldForm.getValues("type")]}
options={fieldTypes.filter((f) => !f.systemOnly)}
label={t("input_type")}
classNames={{
menuList: () => "min-h-[27.25rem]",
}}
/>
{(() => {
if (!variantsConfig) {

View File

@ -21,6 +21,7 @@ interface getEventTypeByIdProps {
userId: number;
prisma: PrismaClient;
isTrpcCall?: boolean;
isUserOrganizationAdmin: boolean;
}
export default async function getEventTypeById({
@ -28,6 +29,7 @@ export default async function getEventTypeById({
userId,
prisma,
isTrpcCall = false,
isUserOrganizationAdmin,
}: getEventTypeByIdProps) {
const userSelect = Prisma.validator<Prisma.UserSelect>()({
name: true,
@ -408,6 +410,7 @@ export default async function getEventTypeById({
team: eventTypeObject.team || null,
teamMembers,
currentUserMembership,
isUserOrganizationAdmin,
};
return finalObj;
}

View File

@ -24,6 +24,7 @@ type CreateOptions = {
export const createHandler = async ({ ctx, input }: CreateOptions) => {
const { schedulingType, teamId, metadata, ...rest } = input;
const userId = ctx.user.id;
const isManagedEventType = schedulingType === SchedulingType.MANAGED;
// Get Users default conferencing app
@ -68,7 +69,9 @@ export const createHandler = async ({ ctx, input }: CreateOptions) => {
},
});
if (!hasMembership?.role || !["ADMIN", "OWNER"].includes(hasMembership.role)) {
const isOrgAdmin = !!ctx.user?.organization?.isOrgAdmin;
if (!hasMembership?.role || !(["ADMIN", "OWNER"].includes(hasMembership.role) || isOrgAdmin)) {
console.warn(`User ${userId} does not have permission to create this new event type`);
throw new TRPCError({ code: "UNAUTHORIZED" });
}

View File

@ -18,5 +18,6 @@ export const getHandler = ({ ctx, input }: GetOptions) => {
userId: ctx.user.id,
prisma: ctx.prisma,
isTrpcCall: true,
isUserOrganizationAdmin: !!ctx.user?.organization?.isOrgAdmin,
});
};

View File

@ -40,10 +40,13 @@ export const eventOwnerProcedure = authedProcedure
const isAuthorized = (function () {
if (event.team) {
return event.team.members
.filter((member) => member.role === MembershipRole.OWNER || member.role === MembershipRole.ADMIN)
.map((member) => member.userId)
.includes(ctx.user.id);
const isOrgAdmin = !!ctx.user?.organization?.isOrgAdmin;
return (
event.team.members
.filter((member) => member.role === MembershipRole.OWNER || member.role === MembershipRole.ADMIN)
.map((member) => member.userId)
.includes(ctx.user.id) || isOrgAdmin
);
}
return event.userId === ctx.user.id || event.users.find((user) => user.id === ctx.user.id);
})();

View File

@ -153,6 +153,8 @@ export interface App {
dependencies?: string[];
/** Enables video apps to be used for team events. Non Video/Conferencing apps don't honor this as they support team installation always. */
concurrentMeetings?: boolean;
createdAt?: string;
}
export type AppFrontendPayload = Omit<App, "key"> & {

View File

@ -0,0 +1,28 @@
import { useLocale } from "@calcom/lib/hooks/useLocale";
import type { AppFrontendPayload as App } from "@calcom/types/App";
import { AppCard } from "./AppCard";
import { Slider } from "./Slider";
export const RecentAppsSlider = <T extends App>({ items }: { items: T[] }) => {
const { t } = useLocale();
return (
<Slider<T>
title={t("recently_added")}
items={items.sort(
(a, b) => new Date(b?.createdAt || 0).valueOf() - new Date(a?.createdAt || 0).valueOf()
)}
itemKey={(app) => app.name}
options={{
perView: 3,
breakpoints: {
768 /* and below */: {
perView: 1,
},
},
}}
renderItem={(app) => <AppCard app={app} />}
/>
);
};

View File

@ -4,4 +4,5 @@ export { Slider } from "./Slider";
export { SkeletonLoader as AppSkeletonLoader } from "./SkeletonLoader";
export { SkeletonLoader } from "./SkeletonLoader";
export { PopularAppsSlider } from "./PopularAppsSlider";
export { RecentAppsSlider } from "./RecentAppsSlider";
export { AppStoreCategories } from "./Categories";

View File

@ -19,7 +19,7 @@ import { Badge } from "./Badge";
## Definition
Badges are small status descriptors for UI elements. A badge consists of a small circle, typically containing a number or other short set of characters, that appears in proximity to another object. We provide three different type of badge such as status, alert, and brand badge.
Badges are small status descriptors for UI elements. A badge consists of a small circle, typically containing a number or other short set of characters, that appears in proximity to another object. We provide three different types of badges such as status, alert, and brand badge.
Status badge communicate status information. It is generally used within a container such as accordion and tables to label status for easy scanning.
@ -58,7 +58,7 @@ Status badge communicate status information. It is generally used within a conta
## Usage
Alet badge is used in conjunction with an item, profile or label to indicate numeric value and messages assocciated with them.
Alert badge is used in conjunction with an item, profile or label to indicate numeric value and messages associated with them.
<Title offset title="Badge" suffix="Variants" />

View File

@ -12,7 +12,7 @@ const HorizontalTabs = function ({ tabs, linkShallow, linkScroll, actions, ...pr
return (
<div className="mb-4 h-9 max-w-full lg:mb-5">
<nav
className="no-scrollbar flex max-h-9 space-x-1 overflow-scroll rounded-md"
className="no-scrollbar flex max-h-9 space-x-1 overflow-x-scroll rounded-md"
aria-label="Tabs"
{...props}>
{tabs.map((tab, idx) => (

View File

@ -69,6 +69,7 @@ export {
SkeletonLoader,
Slider,
PopularAppsSlider,
RecentAppsSlider,
useShouldShowArrows,
AppStoreCategories,
} from "./components/apps";

View File

@ -40057,4 +40057,4 @@ __metadata:
resolution: "zwitch@npm:2.0.4"
checksum: f22ec5fc2d5f02c423c93d35cdfa83573a3a3bd98c66b927c368ea4d0e7252a500df2a90a6b45522be536a96a73404393c958e945fdba95e6832c200791702b6
languageName: node
linkType: hard
linkType: hard