From 5640e2eb2510efb85da02f35b30be80c11146bf4 Mon Sep 17 00:00:00 2001 From: "GitStart-Cal.com" <121884634+gitstart-calcom@users.noreply.github.com> Date: Mon, 29 May 2023 12:57:34 -0600 Subject: [PATCH 001/100] fix: Change Detroit to New York as a default for EST time zone (#8218) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: gitstart-calcom Co-authored-by: Peer Richelsen Co-authored-by: alannnc Co-authored-by: Omar López --- apps/web/test/lib/getTimezone.test.ts | 2 +- packages/lib/timezone.ts | 3 ++- .../form/timezone-select/TimezoneSelect.tsx | 13 +++++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/apps/web/test/lib/getTimezone.test.ts b/apps/web/test/lib/getTimezone.test.ts index 2f5f5d0d58..5055eed8fe 100644 --- a/apps/web/test/lib/getTimezone.test.ts +++ b/apps/web/test/lib/getTimezone.test.ts @@ -77,5 +77,5 @@ it("should render city name as option label if cityData is not empty", () => { }); it("should return timezone as option label if cityData is empty", () => { - expect(handleOptionLabel(option, [])).toMatchInlineSnapshot(`"America/Los_Angeles GMT -8:00"`); + expect(handleOptionLabel(option, [])).toMatchInlineSnapshot(`"America/Los Angeles GMT -8:00"`); }); diff --git a/packages/lib/timezone.ts b/packages/lib/timezone.ts index c6e064e398..f9159e00ed 100644 --- a/packages/lib/timezone.ts +++ b/packages/lib/timezone.ts @@ -35,5 +35,6 @@ export const addCitiesToDropdown = (cities: ICity[]) => { export const handleOptionLabel = (option: ITimezoneOption, cities: ICity[]) => { const timezoneValue = option.label.split(")")[0].replace("(", " ").replace("T", "T "); const cityName = option.label.split(") ")[1]; - return cities.length > 0 ? `${cityName}${timezoneValue}` : `${option.value}${timezoneValue}`; + const refactoredOption = option.value.replace(/_/g, " "); + return cities.length > 0 ? `${cityName}${timezoneValue}` : `${refactoredOption}${timezoneValue}`; }; diff --git a/packages/ui/components/form/timezone-select/TimezoneSelect.tsx b/packages/ui/components/form/timezone-select/TimezoneSelect.tsx index cbf20559a0..2f05968518 100644 --- a/packages/ui/components/form/timezone-select/TimezoneSelect.tsx +++ b/packages/ui/components/form/timezone-select/TimezoneSelect.tsx @@ -34,6 +34,13 @@ export function TimezoneSelect({ }); }, [components]); + // We use modifiedTimezones in place of the allTimezones object replacing any underscores in the curly braces + // with spaces and removing the America/Detroit timezone, adding the America/New_York timezone instead. + const modifiedTimezones = useMemo(() => { + const { "America/Detroit": _, ...rest } = allTimezones; + return { ...rest, "America/New_York": "New York" }; + }, []); + return (

{(option as ITimezoneOption).value}

} + formatOptionLabel={(option) => ( +

{(option as ITimezoneOption).value.replace(/_/g, " ")}

+ )} getOptionLabel={(option) => handleOptionLabel(option as ITimezoneOption, cities)} classNames={{ ...timezoneClassNames, From d242145c0a2e5ce686c88664d141c8e708a66b79 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 29 May 2023 18:58:30 +0000 Subject: [PATCH 002/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/ja/common.json | 134 +++++++++--------- apps/web/public/static/locales/ko/common.json | 60 ++++---- .../public/static/locales/pt-BR/common.json | 8 +- apps/web/public/static/locales/tr/common.json | 6 +- 4 files changed, 106 insertions(+), 102 deletions(-) diff --git a/apps/web/public/static/locales/ja/common.json b/apps/web/public/static/locales/ja/common.json index ea468da241..b8af041c6f 100644 --- a/apps/web/public/static/locales/ja/common.json +++ b/apps/web/public/static/locales/ja/common.json @@ -408,7 +408,7 @@ "add_time_availability": "新しい時間帯を追加", "add_an_extra_layer_of_security": "パスワードが盗まれる場合に備えて、アカウントのセキュリティを強化します。", "2fa": "二要素認証", - "2fa_disabled": "二要素認証はメール認証とパスワード認証のみ有効にできます", + "2fa_disabled": "二要素認証は、メール認証とパスワード認証に対してのみ有効化できます", "enable_2fa": "二要素認証を有効にする", "disable_2fa": "二要素認証を無効にする", "disable_2fa_recommendation": "2FA を無効にする必要がある場合は、その必要がなくなった後すぐに有効にしなおすことをおすすめします。", @@ -589,20 +589,20 @@ "minutes": "分", "round_robin": "ラウンドロビン", "round_robin_description": "複数のチームメンバー間のミーティングを定期化する。", - "managed_event": "管理イベント", + "managed_event": "管理済みのイベント", "username_placeholder": "ユーザー名", - "managed_event_description": "イベントタイプを作成し、チームメンバーに一括配布する", - "managed": "管理", - "managed_event_url_clarification": "「ユーザー名」には、割り当てられたメンバーのユーザー名が入ります", + "managed_event_description": "イベントの種類を作成し、チームメンバーに一括配布する", + "managed": "管理済み", + "managed_event_url_clarification": "\"ユーザー名\" には割り当てられたメンバーのユーザー名が入ります", "assign_to": "割り当て先", "add_members": "メンバーを追加…", "count_members_one": "{{count}} 人のメンバー", "count_members_other": "{{count}} 人のメンバー", "no_assigned_members": "割り当てられたメンバーはいません", "assigned_to": "割り当て先", - "start_assigning_members_above": "上記のメンバーへの割り当てを開始する", - "locked_fields_admin_description": "メンバーはこれを編集することはできません", - "locked_fields_member_description": "このオプションはチーム管理者によってロックされました", + "start_assigning_members_above": "上記のメンバーに対する割り当てを開始する", + "locked_fields_admin_description": "メンバーがこれを編集することはできません", + "locked_fields_member_description": "このオプションはチームの管理者によってロックされました", "url": "URL", "hidden": "隠れている", "readonly": "読み込み専用", @@ -754,10 +754,10 @@ "minimum_booking_notice": "最低頻度の通知", "slot_interval": "時間帯の間隔", "slot_interval_default": "イベントの長さを使用する (デフォルト)", - "delete_event_type": "イベントタイプを削除しますか?", - "delete_managed_event_type": "管理イベントタイプを削除しますか?", - "delete_event_type_description": "これまでにこのリンクを共有したユーザーは、このリンクを使用して予約することができなくなります。", - "delete_managed_event_type_description": "
  • このイベントタイプに割り当てられたメンバーは、そのイベントタイプも削除されます。
  • リンクを共有した人は、そのリンクを使用して予約することができなくなります。
", + "delete_event_type": "イベントの種類を削除しますか?", + "delete_managed_event_type": "管理済みのイベントの種類を削除しますか?", + "delete_event_type_description": "これまでにこのリンクを共有したことがあるユーザーは、このリンクを使用して予約することができなくなります。", + "delete_managed_event_type_description": "
  • このイベントの種類に割り当てられているメンバーは、そのイベントの種類も削除されます。
  • リンクを共有したことがあるユーザーは、そのリンクを使用して予約することができなくなります。
", "confirm_delete_event_type": "はい、削除します", "delete_account": "アカウントを削除する", "confirm_delete_account": "はい。アカウントを削除します", @@ -1148,13 +1148,13 @@ "current_username": "現在のユーザー名", "example_1": "例 1", "example_2": "例 2", - "booking_question_identifier": "予約質問識別子", + "booking_question_identifier": "予約時質問識別子", "company_size": "会社の規模", "what_help_needed": "何かお困りですか?", "variable_format": "変数の形式", "webhook_subscriber_url_reserved": "ウェブフック購読者 URL は既に定義されています", "custom_input_as_variable_info": "追加の入力ラベルに含まれている特殊文字はすべて無視し (アルファベットと数字のみを使用)、アルファベットをすべて大文字に、そして空白をアンダースコアへと変換します。", - "using_booking_questions_as_variables": "予約時の質問を変数として使う方法は?", + "using_booking_questions_as_variables": "予約時の質問を変数として使うにはどうすればいいですか?", "download_desktop_app": "デスクトップアプリをダウンロード", "set_ping_link": "Ping リンクを設定", "rate_limit_exceeded": "試行回数の上限を超えました", @@ -1177,7 +1177,7 @@ "event_advanced_tab_title": "詳細設定", "event_setup_multiple_duration_error": "イベント設定:複数の期間には少なくとも1つのオプションが必要です。", "event_setup_multiple_duration_default_error": "イベント設定:有効なデフォルト期間を選択してください。", - "event_setup_booking_limits_error": "予約上限の日時表記は昇順にする必要があります。[日、週、月、年]", + "event_setup_booking_limits_error": "予約制限の日時表記は、昇順にする必要があります。[日、週、月、年]", "event_setup_duration_limits_error": "期間の上限は昇順にする必要があります。[日、週、月、年]", "select_which_cal": "予約を追加するカレンダーを選択してください", "custom_event_name": "カスタムイベント名", @@ -1326,7 +1326,7 @@ "exchange_version_2013_SP1": "2013 SP1", "exchange_version_2015": "2015", "exchange_version_2016": "2016", - "routing_forms_description": "作成したすべてのフォームとルートをここで確認できます。", + "routing_forms_description": "作成したすべてのフォームとルートをここで確認できます", "routing_forms_send_email_owner": "所有者にメールを送信", "routing_forms_send_email_owner_description": "フォームの送信時に所有者にメールを送信します", "add_new_form": "新しいフォームを追加", @@ -1380,7 +1380,7 @@ "add_limit": "上限を追加する", "team_name_required": "チーム名が必要です", "show_attendees": "ゲスト間で出席者情報を共有する", - "how_booking_questions_as_variables": "予約時の質問を変数として使う方法は?", + "how_booking_questions_as_variables": "予約時の質問を変数として使うにはどうすればいいですか?", "format": "書式", "uppercase_for_letters": "すべての文字に大文字を使用する", "replace_whitespaces_underscores": "空白をアンダーバー「 _ 」に置き換える", @@ -1395,7 +1395,7 @@ "billing_help_title": "他にもお手伝いできることはありませんか?", "billing_help_description": "請求に関してサポートが必要な場合には、サポートチームがお手伝いさせていただきます。", "billing_help_cta": "サポートに問い合わせる", - "ignore_special_characters_booking_questions": "予約質問識別子に含まれている特殊文字はすべて無視し、アルファベットと数字のみを使用してください", + "ignore_special_characters_booking_questions": "予約時質問識別子に含まれている特殊文字はすべて無視し、アルファベットと数字のみを使用してください", "retry": "再試行", "fetching_calendars_error": "カレンダーの取得中にエラーが発生しました。<1>もう一度お試しいただくか、カスタマーサポートまでお問い合わせください。", "calendar_connection_fail": "カレンダーの接続に失敗しました", @@ -1484,11 +1484,11 @@ "duration_limit_reached": "このイベントの種類の期間の上限に達しました", "admin_has_disabled": "管理者が {{appName}} を無効にしています", "disabled_app_affects_event_type": "管理者が {{appName}} を無効にしているため、あなたのイベントの種類 {{eventType}} に影響を与える可能性があります", - "event_replaced_notice": "管理者があなたのイベントタイプの1つを置き換えました", - "email_subject_slug_replacement": "チーム管理者があなたのイベントの /{{slug}} を置き換えました", - "email_body_slug_replacement_notice": "{{teamName}}チームの管理者が、あなたのイベントタイプの /{{slug}} を彼らが管理する管理イベントタイプに置き換えました。", - "email_body_slug_replacement_info": "あなたのリンクは引き続き機能しますが、リンクの設定の一部が変更された可能性があります。変更はイベントタイプで確認できます。", - "email_body_slug_replacement_suggestion": "イベントタイプについてご質問がある場合は、管理者までお問合せください。

スケジュール設定をお楽しみください、
Cal.comチーム", + "event_replaced_notice": "管理者があなたのイベントの種類の 1 つを置き換えました", + "email_subject_slug_replacement": "チームの管理者があなたのイベント /{{slug}} を置き換えました", + "email_body_slug_replacement_notice": "{{teamName}} チームの管理者が、あなたのイベントの種類 /{{slug}} を彼らが管理する管理済みのイベントの種類へと置き換えました。", + "email_body_slug_replacement_info": "あなたのリンクは引き続き機能しますが、リンクの設定の一部が変更された可能性があります。変更内容はイベントの種類で確認できます。", + "email_body_slug_replacement_suggestion": "イベントの種類について質問がある場合には、管理者までお問合せください。

それでは、スケジュール設定をお楽しみください。
Cal.com チーム", "disable_payment_app": "管理者が {{appName}} を無効にしたため、イベントの種類 {{title}} に影響を与える可能性があります。出席者がこの種類のイベントを予約することは可能ですが、支払いを促されることはありません。管理者が支払い方法を再度有効にするまでの間これを防ぐために、イベントの種類を非表示にすることができます。", "payment_disabled_still_able_to_book": "出席者がこの種類のイベントを予約することは可能ですが、支払いを促されることはありません。管理者が支払い方法を再度有効にするまでの間これを防ぐために、イベントの種類を非表示にすることができます。", "app_disabled_with_event_type": "管理者が {{appName}} を無効にしているため、あなたのイベントの種類 {{title}} に影響を与える可能性があります.", @@ -1537,7 +1537,7 @@ "date_overrides_update_btn": "上書きを更新", "event_type_duplicate_copy_text": "{{slug}}-copy", "set_as_default": "デフォルトとして設定", - "hide_eventtype_details": "イベントタイプの詳細を非表示にする", + "hide_eventtype_details": "イベントの種類の詳細を非表示にする", "show_navigation": "ナビゲーションを表示", "hide_navigation": "ナビゲーションを非表示にする", "verification_code_sent": "確認コードが送信されました", @@ -1551,7 +1551,7 @@ "create_your_first_team_webhook_description": "このチームイベントの種類の初めての webhook を作成します", "create_webhook_team_event_type": "このチームイベントの種類の webhook を作成します", "disable_success_page": "予約完了ページを無効化する (リダイレクト URL がある場合にのみ有効)", - "invalid_admin_password": "あなたは管理者ですが、パスワードの長さが15文字以上ではないか、二要素認証をまだしていません", + "invalid_admin_password": "あなたは管理者ですが、パスワードの長さが 15 文字以上になっていないか、二要素認証がまだ完了していません", "change_password_admin": "パスワードを変更して管理者アクセス権を取得する", "username_already_taken": "ユーザー名が既に使用されています", "assignment": "割り当て", @@ -1584,7 +1584,7 @@ "ee_enterprise_license": "\"/ee\" Enterprise ライセンス", "enterprise_booking_fee": "{{enterprise_booking_fee}}/月で開始する", "enterprise_license_includes": "商用ユースケースで必要となるすべてのもの", - "no_need_to_keep_your_code_open_source": "コードをオープンソースにしておく必要はありません", + "no_need_to_keep_your_code_open_source": "コードをオープンソースのままにしておく必要はありません", "repackage_rebrand_resell": "再パッケージ、リブランディング、再販売が簡単になります", "a_vast_suite_of_enterprise_features": "膨大な量の企業向け機能パッケージ", "free_license_fee": "0.00 ドル/月", @@ -1646,7 +1646,7 @@ "default_app_link_title": "デフォルトのアプリリンクを設定", "default_app_link_description": "デフォルトのアプリリンクを設定することで、新たに作成するすべてのイベントの種類が設定したアプリリンクを使用できるようになります。", "change_default_conferencing_app": "デフォルトとして設定", - "organizer_default_conferencing_app": "主催者のデフォルトアプリ", + "organizer_default_conferencing_app": "主催者のデフォルトのアプリ", "under_maintenance": "メンテナンスのため停止中", "under_maintenance_description": "{{appName}} チームが定期メンテナンスを行っています。質問がある場合には、サポートへとお問い合わせください。", "event_type_seats": "{{numberOfSeats}} 席", @@ -1685,14 +1685,14 @@ "add_1_option_per_line": "1 行に 1 つのオプションを追加する", "select_a_router": "ルーターを選択", "add_a_new_route": "新しいルートを追加", - "make_informed_decisions": "Insights を使って情報に基づいた決定をする", - "make_informed_decisions_description": "Insights ダッシュボードは、チーム内のすべてのアクティビティを表示し、チームのスケジューリングや意思決定をより良いものにするための傾向を示します。", + "make_informed_decisions": "Insights を使って情報に基づいた決定を行う", + "make_informed_decisions_description": "Insights ダッシュボードには、チーム内のすべてのアクティビティが表示され、チームのスケジュール設定や意思決定をより良いものにするための傾向が示されます。", "view_bookings_across": "メンバー全体の予約を表示", - "view_bookings_across_description": "誰が最も予約されているか確認し、チーム全体で最適な配分ができるようにします", + "view_bookings_across_description": "誰が最も予約されているかを確認し、チーム全体で最適な配分が行われるようにします", "identify_booking_trends": "予約の傾向を明らかにする", - "identify_booking_trends_description": "週のどの期間と1日のどの時間帯が予約者に人気か確認します", - "spot_popular_event_types": "人気のイベントタイプを見つける", - "spot_popular_event_types_description": "どのイベントタイプが最もクリックされ、予約されているのか確認します", + "identify_booking_trends_description": "1 週間の内のどの時間帯が、そして 1 日の内のどの時間帯が予約するユーザーに人気があるかを確認します", + "spot_popular_event_types": "人気のあるイベントの種類を見つける", + "spot_popular_event_types_description": "どのイベントの種類が最もクリックされ、予約されているのかを確認します", "no_responses_yet": "回答はまだありません", "this_will_be_the_placeholder": "これがプレースホルダーになります", "this_meeting_has_not_started_yet": "このミーティングはまだ開始されていません", @@ -1704,21 +1704,21 @@ "can_you_try_again": "別の時間帯でもう 1 度お試しください", "verify": "確認する", "timezone_variable": "タイムゾーン", - "timezone_info": "受け取る人のタイムゾーン", - "event_end_time_variable": "イベント終了時刻", - "event_end_time_info": "イベント終了時刻", + "timezone_info": "受信するユーザーのタイムゾーン", + "event_end_time_variable": "イベントの終了時刻", + "event_end_time_info": "イベントの終了時刻", "cancel_url_variable": "キャンセル URL", "cancel_url_info": "予約をキャンセルするための URL", "reschedule_url_variable": "スケジュール変更 URL", - "reschedule_url_info": "予約をスケジュール変更するための URL", + "reschedule_url_info": "予約のスケジュールを変更するための URL", "invalid_event_name_variables": "イベント名に無効な変数があります", "select_all": "すべて選択", "default_conferencing_bulk_title": "既存のイベントの種類を一括更新する", - "members_default_schedule": "メンバーのデフォルトスケジュール", - "set_by_admin": "チーム管理者による設定", + "members_default_schedule": "メンバーのデフォルトのスケジュール", + "set_by_admin": "チームの管理者による設定", "members_default_location": "メンバーのデフォルトの場所", - "members_default_schedule_description": "各メンバーのデフォルトの空き状況スケジュールを使用します。メンバーはスケジュールを編集したり、変更したりできます。", - "requires_at_least_one_schedule": "少なくとも 1 つのスケジュールが必要です", + "members_default_schedule_description": "各メンバーのデフォルトの空きスケジュールを使用します。メンバーはこのスケジュールを編集したり、変更したりできます。", + "requires_at_least_one_schedule": "少なくとも 1 件のスケジュールが必要です", "default_conferencing_bulk_description": "選択したイベントの種類の場所を更新します", "locked_for_members": "メンバーに対してロックされています", "locked_apps_description": "メンバーは有効なアプリを確認できますが、アプリの設定を編集することはできません", @@ -1732,36 +1732,36 @@ "managed_event_dialog_title_other": "{{count}} 人のメンバーには url/{{slug}} が既に存在します。置き換えますか?", "managed_event_dialog_information_one": "{{names}}は既に /{{slug}} url を使用しています。", "managed_event_dialog_information_other": "{{names}}は既に /{{slug}} url を使用しています。", - "managed_event_dialog_clarification": "置き換えを選択すると、通知が送られます。上書きしたくない場合は、戻って削除してください。", - "review_event_type": "イベントタイプを確認", - "looking_for_more_analytics": "詳しい分析をお探しですか?", - "looking_for_more_insights": "詳しい Insights をお探しですか?", + "managed_event_dialog_clarification": "置き換えを選択すると、通知が送られます。上書きしたくない場合には、戻って削除してください。", + "review_event_type": "イベントの種類を確認", + "looking_for_more_analytics": "詳しい分析情報をお探しですか?", + "looking_for_more_insights": "Insights をさらにお探しですか?", "add_filter": "フィルターを追加", "select_user": "ユーザーを選択", - "select_event_type": "イベントタイプを選択", - "select_date_range": "日付範囲を選択", + "select_event_type": "イベントの種類を選択", + "select_date_range": "日付の範囲を選択", "popular_events": "人気のイベント", - "no_event_types_found": "イベントタイプが見つかりません", + "no_event_types_found": "イベントの種類が見つかりません", "average_event_duration": "イベントの平均時間", - "most_booked_members": "最も予約が多いメンバー", - "least_booked_members": "最も予約が少ないメンバー", + "most_booked_members": "最も予約数が多いメンバー", + "least_booked_members": "最も予約数が少ないメンバー", "events_created": "イベントが作成されました", "events_completed": "イベントが完了しました", "events_cancelled": "イベントがキャンセルされました", - "events_rescheduled": "イベントがスケジュール変更されました", + "events_rescheduled": "イベントのスケジュールが変更されました", "from_last_period": "最後の期間から", - "from_to_date_period": "開始:{{startDate}} 終了:{{endDate}}", + "from_to_date_period": "開始: {{startDate}} 終了: {{endDate}}", "analytics_for_organisation": "Insights", "subtitle_analytics": "チームのアクティビティについてさらに詳しく知る", - "redirect_url_warning": "リダイレクトを追加すると予約完了ページが無効化されます。必ずカスタムの予約完了ページで「予約が確認されました」と伝えてください。", - "event_trends": "イベントのトレンド", + "redirect_url_warning": "リダイレクトを追加すると、予約完了ページが無効化されます。カスタム予約完了ページには、必ず \"予約が完了しました\" と記載してください。", + "event_trends": "イベントの傾向", "clear_filters": "フィルターをクリア", "hold": "保留", - "on_booking_option": "予約の支払いを受け取る", - "hold_option": "予約不参加料金を請求", - "card_held": "カードを保留", - "charge_card": "カードに請求", - "card_charged": "カードに請求されました", + "on_booking_option": "予約時に料金を徴収する", + "hold_option": "不参加費用を請求する", + "card_held": "カードを保留中", + "charge_card": "カードに請求する", + "card_charged": "カードに請求が行われました", "no_show_fee_amount": "{{amount, currency}} の予約不参加料金", "no_show_fee": "予約不参加料金", "submit_card": "カードを送信", @@ -1771,15 +1771,15 @@ "no_show_fee_charged_text_body": "予約不参加料金が請求されました", "no_show_fee_charged_subtitle": "次のイベントに {{amount, currency}} の予約不参加料金が請求されました", "error_charging_card": "予約不参加料金の請求に問題が発生しました。後でもう一度お試しください。", - "collect_no_show_fee": "予約不参加料金を受け取る", - "no_show_fee_charged": "予約不参加料金が請求されました", + "collect_no_show_fee": "不参加費用を徴収する", + "no_show_fee_charged": "不参加費用が請求されました", "insights": "Insights", - "testing_workflow_info_message": "このワークフローをテストする際は、少なくとも1時間前でないとメールとSMSをスケジュール設定できないことにご注意ください", - "insights_no_data_found_for_filter": "選択したフィルターまたは選択した日付のデータが見つかりません。", - "acknowledge_booking_no_show_fee": "このイベントに参加しない場合、{{amount, currency}} の予約不参加料金が私のカードに請求されることに同意します。", + "testing_workflow_info_message": "このワークフローをテストする場合、少なくとも 1 時間前でなければメールと SMS のスケジュール設定ができないことにご注意ください", + "insights_no_data_found_for_filter": "選択したフィルターまたは日付のデータが見つかりませんでした。", + "acknowledge_booking_no_show_fee": "このイベントに出席しなかった場合、不参加費用として {{amount, currency}} が私のカードに請求されることに同意します。", "card_details": "カードの詳細", - "seats_and_no_show_fee_error": "現在、座席の有効化と予約不参加料金の請求はできません", + "seats_and_no_show_fee_error": "現在、座席の有効化と不参加費用の請求はできません", "complete_your_booking": "予約を完了する", - "complete_your_booking_subject": "次の予約を完了する:{{date}} の {{title}}", - "email_invite_team": "{{email}} は招待されました" + "complete_your_booking_subject": "次の予約を完了する: {{date}} の {{title}}", + "email_invite_team": "{{email}} が招待されました" } diff --git a/apps/web/public/static/locales/ko/common.json b/apps/web/public/static/locales/ko/common.json index 01bc222676..0aa6cc353b 100644 --- a/apps/web/public/static/locales/ko/common.json +++ b/apps/web/public/static/locales/ko/common.json @@ -409,7 +409,7 @@ "add_time_availability": "새 타임 슬롯 추가", "add_an_extra_layer_of_security": "비밀번호가 도용될 경우에 대비하여 계정에 보안방법을 추가하십시오.", "2fa": "이중 인증", - "2fa_disabled": "이중 인증은 이메일 및 비밀번호 인증에만 사용할 수 있습니다.", + "2fa_disabled": "2단계 인증은 이메일 및 비밀번호 인증에만 사용할 수 있습니다.", "enable_2fa": "이중 인증 활성화", "disable_2fa": "이중 인증 비활성화", "disable_2fa_recommendation": "2FA를 비활성화해야 하는 경우, 가능한 한 빨리 다시 활성화하십시오.", @@ -593,17 +593,17 @@ "round_robin_description": "여러 팀 구성원 간의 주기적인 회의", "managed_event": "관리형 이벤트", "username_placeholder": "username", - "managed_event_description": "팀원들에게 대량으로 이벤트 유형 생성 및 배포", - "managed": "관리됨", + "managed_event_description": "팀원들에게 대량으로 이벤트 타입 생성 및 배포", + "managed": "관리형", "managed_event_url_clarification": "\"username\"은 할당된 회원의 사용자 이름으로 채워집니다", - "assign_to": "할당:", - "add_members": "회원 추가:", + "assign_to": "할당 대상", + "add_members": "회원 추가...", "count_members_one": "회원 {{count}}명", "count_members_other": "회원 {{count}}명", "no_assigned_members": "할당된 회원 없음", - "assigned_to": "할당된 이벤트 유형:", + "assigned_to": "할당된 이벤트 유형", "start_assigning_members_above": "위에서 회원 할당 시작", - "locked_fields_admin_description": "회원은 이 내용을 수정할 수 없게 됩니다", + "locked_fields_admin_description": "회원이 이 내용을 수정할 수 없게 됩니다", "locked_fields_member_description": "이 옵션은 팀 관리자에 의해 잠겼습니다", "url": "링크", "hidden": "숨기기", @@ -757,9 +757,9 @@ "slot_interval": "시간 슬롯 간격", "slot_interval_default": "이벤트 길이 사용(기본값)", "delete_event_type": "이벤트 타입을 삭제하시겠습니까?", - "delete_managed_event_type": "관리 이벤트 유형을 삭제하시겠습니까?", - "delete_event_type_description": "링크를 공유한 회원은 더 이상 링크를 사용하여 예약할 수 없게 됩니다.", - "delete_managed_event_type_description": "
  • 이 이벤트 유형에 할당된 회원은 이벤트 유형도 삭제됩니다.
  • 링크를 공유한 회원은 더 이상 링크를 사용하여 예약할 수 없게 됩니다.
", + "delete_managed_event_type": "관리형 이벤트 타입을 삭제하시겠습니까?", + "delete_event_type_description": "이 링크를 공유한 회원이 더 이상 링크를 사용하여 예약할 수 없게 됩니다.", + "delete_managed_event_type_description": "
  • 이 이벤트 타입에 할당된 회원은 이벤트 타입도 삭제됩니다.
  • 이 링크를 공유한 회원이 더 이상 링크를 사용하여 예약할 수 없게 됩니다.
", "confirm_delete_event_type": "네, 삭제합니다", "delete_account": "계정 삭제", "confirm_delete_account": "예, 계정을 삭제합니다", @@ -1157,7 +1157,7 @@ "variable_format": "변수 형식", "webhook_subscriber_url_reserved": "웹훅 구독자 URL이 이미 정의되었습니다", "custom_input_as_variable_info": "추가 입력 레이블의 모든 특수 문자는 무시하고(문자와 숫자만 사용) 모든 문자에 대문자를 사용하며 공백은 밑줄로 대체합니다.", - "using_booking_questions_as_variables": "예약 질문을 변수로 어떻게 사용합니까?", + "using_booking_questions_as_variables": "예약 질문을 어떻게 변수로 사용합니까?", "download_desktop_app": "데스크탑 앱 다운로드", "set_ping_link": "Ping 링크 설정", "rate_limit_exceeded": "요금 한도 초과됨", @@ -1180,7 +1180,7 @@ "event_advanced_tab_title": "고급", "event_setup_multiple_duration_error": "이벤트 설정: 복수 기간에는 최소 1개의 옵션이 필요합니다.", "event_setup_multiple_duration_default_error": "이벤트 설정: 유효한 기본 기간을 선택하십시오.", - "event_setup_booking_limits_error": "예약 한도는 오름차순이어야 합니다. [일,주,월,년]", + "event_setup_booking_limits_error": "예약 한도는 오름차순이어야 합니다. [일, 주, 월, 년]", "event_setup_duration_limits_error": "기간 한도는 오름차순이어야 합니다. [일, 주, 월, 년]", "select_which_cal": "예약을 추가할 캘린더 선택", "custom_event_name": "사용자 정의 이벤트 이름", @@ -1203,7 +1203,7 @@ "start_of_week": "주의 시작", "recordings_title": "녹음", "recording": "녹음", - "happy_scheduling": "즐거운 일정 관리 되세요", + "happy_scheduling": "즐겁게 일정 관리하세요", "select_calendars": "중복 예약을 방지하기 위해 충돌을 확인하려는 캘린더를 선택합니다.", "check_for_conflicts": "충돌 확인", "view_recordings": "녹음 보기", @@ -1280,11 +1280,11 @@ "attendee_name_info": "예약자 이름", "to": "대상", "workflow_turned_on_successfully": "{{workflowName}} 워크플로 {{offOn}} 설정 완료", - "download_responses": "다운로드 응답", + "download_responses": "응답 다운로드", "download_responses_description": "양식에 대한 모든 응답을 CSV 형식으로 다운로드합니다.", "download": "다운로드", "download_recording": "기록 다운로드", - "recording_from_your_recent_call": "Cal.com에서 최근 통화 내용 녹음 파일을 다운로드 할 준비가 되었습니다", + "recording_from_your_recent_call": "Cal.com에서 이루어진 최근 통화 녹음을 지금 바로 다운로드할 수 있습니다", "create_your_first_form": "첫 양식 작성", "create_your_first_form_description": "라우팅 양식을 사용하면 적격성 질문을 올리고 올바른 사람 또는 이벤트 유형으로 라우팅할 수 있습니다.", "create_your_first_webhook": "첫 웹훅 생성", @@ -1330,7 +1330,7 @@ "exchange_version_2013_SP1": "2013 SP1", "exchange_version_2015": "2015", "exchange_version_2016": "2016", - "routing_forms_description": "여기에서 생성했던 모든 양식과 경로를 볼 수 있습니다.", + "routing_forms_description": "참석자를 올바른 대상으로 안내하는 양식 만들기", "routing_forms_send_email_owner": "소유자에게 이메일 보내기", "routing_forms_send_email_owner_description": "양식이 제출되면 소유자에게 이메일을 발송합니다", "add_new_form": "새 양식 추가", @@ -1384,7 +1384,7 @@ "add_limit": "제한 추가", "team_name_required": "팀 이름 필수", "show_attendees": "게스트 간에 참석자 정보 공유", - "how_booking_questions_as_variables": "예약 질문을 변수로 어떻게 사용합니까?", + "how_booking_questions_as_variables": "예약 질문을 어떻게 변수로 사용합니까?", "format": "형식", "uppercase_for_letters": "모든 문자에 대문자 사용", "replace_whitespaces_underscores": "공백을 밑줄로 바꾸기", @@ -1399,7 +1399,7 @@ "billing_help_title": "또 필요한 것이 있나요?", "billing_help_description": "청구와 관련하여 추가적인 도움이 필요한 경우 지원 팀이 도와드리겠습니다.", "billing_help_cta": "지원 문의", - "ignore_special_characters_booking_questions": "예약 질문 ID의 특수 문자는 무시하십시오. 문자와 숫자만 사용하십시오", + "ignore_special_characters_booking_questions": "예약 질문 ID의 특수 문자는 무시합니다. 문자와 숫자만 사용하십시오", "retry": "재시도", "fetching_calendars_error": "캘린더를 가져오는 중 문제가 발생했습니다. <1>다시 시도하거나 고객 지원에 문의하십시오.", "calendar_connection_fail": "캘린더 연결 실패", @@ -1482,17 +1482,17 @@ "fixed_round_robin": "고정 라운드 로빈", "add_one_fixed_attendee": "한 명의 고정 참석자를 추가하고 여러 참석자를 라운드 로빈 방식으로 순환합니다.", "calcom_is_better_with_team": "Cal.com이 팀 기능으로 더욱 좋아졌습니다", - "the_calcom_team": "Cal.com 팀", + "the_calcom_team": "Cal.com 팀 드림", "add_your_team_members": "이벤트 타입에 팀원을 추가하세요. 집단 일정 관리를 사용해 모든 사람을 포함하거나 라운드 로빈 일정 관리로 가장 적합한 인원을 찾으세요.", "booking_limit_reached": "이 이벤트 타입에 대한 예약 한도에 도달했습니다", "duration_limit_reached": "이 이벤트 타입에 대한 기간 한도에 도달했습니다", "admin_has_disabled": "관리자가 {{appName}} 앱을 비활성화했습니다", "disabled_app_affects_event_type": "관리자가 이벤트 타입 {{eventType}}에 영향을 미치는 {{appName}} 앱을 비활성화했습니다", - "event_replaced_notice": "관리자가 이벤트 유형 중 하나를 바꿨습니다", - "email_subject_slug_replacement": "팀 관리자가 당신의 이벤트 /{{slug}}를 변경하였습니다", - "email_body_slug_replacement_notice": "{{teamName}} 팀의 관리자가 귀하의 이벤트 유형 /{{slug}}을(를) 관리 이벤트 유형으로 바꿨습니다.", + "event_replaced_notice": "관리자가 이벤트 타입 중 하나를 교체했습니다", + "email_subject_slug_replacement": "팀 관리자가 귀하의 이벤트 /{{slug}}를 교체했습니다", + "email_body_slug_replacement_notice": "{{teamName}} 팀의 관리자가 귀하의 이벤트 타입 /{{slug}}을(를) 제어 대상인 관리형 이벤트 타입으로 교체했습니다.", "email_body_slug_replacement_info": "링크는 계속 유효하지만 일부 설정이 변경될 수 있습니다. 이벤트 타입에서 이를 검토할 수 있습니다.", - "email_body_slug_replacement_suggestion": "이벤트 유형에 대해 질문이 있는 경우 관리자에게 문의하십시오.

즐거운 일정 되시기 바랍니다.
Cal.com 팀", + "email_body_slug_replacement_suggestion": "이벤트 타입에 대한 질문이 있는 경우, 관리자에게 문의하십시오.

즐겁게 일정 관리하세요!
Cal.com 팀 드림", "disable_payment_app": "관리자가 이벤트 타입 {{title}}에 영향을 미치는 {{appName}} 앱을 비활성화했습니다. 참석자는 여전히 이러한 타입의 이벤트를 예약할 수 있지만 결제하라는 메시지는 표시되지 않습니다. 관리자가 결제 수단을 다시 활성화할 때까지 이를 방지하기 위해 이벤트 타입을 숨길 수 있습니다.", "payment_disabled_still_able_to_book": "참석자는 여전히 이러한 타입의 이벤트를 예약할 수 있지만 결제하라는 메시지는 표시되지 않습니다. 관리자가 결제 수단을 다시 활성화할 때까지 이를 방지하기 위해 이벤트 타입을 숨길 수 있습니다.", "app_disabled_with_event_type": "관리자가 이벤트 타입 {{title}}에 영향을 미치는 {{appName}} 앱을 비활성화했습니다.", @@ -1764,24 +1764,24 @@ "events_rescheduled": "일정이 변경된 이벤트", "from_last_period": "마지막 기간부터", "from_to_date_period": "시작일: {{startDate}} 종료일: {{endDate}}", - "analytics_for_organisation": "인사이트", + "analytics_for_organisation": "Insights", "subtitle_analytics": "팀 활동에 대해 자세히 알아보기", - "redirect_url_warning": "리디렉션을 추가하면 성공 페이지가 비활성화됩니다. 사용자 지정 성공 페이지에 \"예약 확인됨\"을 언급해야 합니다.", + "redirect_url_warning": "리디렉션을 추가하면 성공 페이지가 비활성화됩니다. 사용자 지정 성공 페이지에 \"예약 확정\"을 언급해야 합니다.", "event_trends": "이벤트 트렌드", - "clear_filters": "필터 삭제", + "clear_filters": "필터 지우기", "hold": "보류", "on_booking_option": "예약 시 결제 징수", "hold_option": "노쇼 수수료 부과", "card_held": "카드 보류됨", - "charge_card": "카드 부과", - "card_charged": "카드 부과됨", + "charge_card": "카드에 요금 부과", + "card_charged": "카드에 요금 부과됨", "no_show_fee_amount": "{{amount, currency}} 노쇼 수수료", - "no_show_fee": "No-show 수수료", + "no_show_fee": "노쇼 수수료", "submit_card": "카드 제출", "submit_payment_information": "결제 정보 제출", "meeting_awaiting_payment_method": "회의에 대한 결제 수단을 기다리는 중입니다", "no_show_fee_charged_email_subject": "{{amount, currency}}에 대한 노쇼 수수료 부과됨: {{title}} 날짜 {{date}}", - "no_show_fee_charged_text_body": "No-show 수수료가 부과되었습니다", + "no_show_fee_charged_text_body": "노쇼 수수료가 부과되었습니다", "no_show_fee_charged_subtitle": "다음 이벤트에 대해 {{amount, currency}}에 대한 노쇼 수수료가 부과되었습니다", "error_charging_card": "No-show 수수료 청구 중 문제가 발생했습니다. 나중에 다시 시도해주세요.", "collect_no_show_fee": "No-show 수수료를 청구하세요", diff --git a/apps/web/public/static/locales/pt-BR/common.json b/apps/web/public/static/locales/pt-BR/common.json index 98fe55007a..546a57bd9f 100644 --- a/apps/web/public/static/locales/pt-BR/common.json +++ b/apps/web/public/static/locales/pt-BR/common.json @@ -1326,7 +1326,7 @@ "exchange_version_2013_SP1": "2013 SP1", "exchange_version_2015": "2015", "exchange_version_2016": "2016", - "routing_forms_description": "Você pode ver todos os formulários e rotas que criou aqui.", + "routing_forms_description": "Você pode ver todos os formulários e rotas que criou aqui", "routing_forms_send_email_owner": "Enviar e-mail ao proprietário", "routing_forms_send_email_owner_description": "Envia um e-mail ao proprietário após o envio do formulário", "add_new_form": "Adicionar novo formulário", @@ -1686,7 +1686,7 @@ "select_a_router": "Selecione um formulário de roteamento", "add_a_new_route": "Adicione uma nova Rota", "make_informed_decisions": "Tome decisões conscientes com o Insights", - "make_informed_decisions_description": "Nosso painel de informações do Insights traz à tona todas as atividades da sua equipe e mostra as tendências que permitem melhor tomada de decisão e agendamento da equipe.", + "make_informed_decisions_description": "Nosso painel de informações do Insights apresenta todas as atividades da sua equipe e mostra as tendências que permitem melhor tomada de decisão e agendamento da equipe.", "view_bookings_across": "Ver reservas em todos os membros", "view_bookings_across_description": "Veja quem está recebendo a maioria das reservas e garanta a melhor distribuição para a sua equipe", "identify_booking_trends": "Identificar tendências de reserva", @@ -1708,9 +1708,9 @@ "event_end_time_variable": "Horário de término do evento", "event_end_time_info": "O horário de término do evento", "cancel_url_variable": "Cancelar URL", - "cancel_url_info": "A URL para cancelar a reserva", + "cancel_url_info": "O URL para cancelar a reserva", "reschedule_url_variable": "URL de reagendamento", - "reschedule_url_info": "A URL para reagendar a reserva", + "reschedule_url_info": "O URL para reagendar a reserva", "invalid_event_name_variables": "Há uma variável inválida no seu nome do evento", "select_all": "Selecionar tudo", "default_conferencing_bulk_title": "Atualize em massa os tipos de evento existentes", diff --git a/apps/web/public/static/locales/tr/common.json b/apps/web/public/static/locales/tr/common.json index 1de3b1816e..b0112a16b6 100644 --- a/apps/web/public/static/locales/tr/common.json +++ b/apps/web/public/static/locales/tr/common.json @@ -1781,5 +1781,9 @@ "seats_and_no_show_fee_error": "Şu anda koltuklar etkinleştirilemiyor ve katılmama ücreti tahsil edilemiyor", "complete_your_booking": "Rezervasyonunuzu tamamlayın", "complete_your_booking_subject": "Rezervasyonunuzu tamamlayın: {{title}}, {{date}}", - "email_invite_team": "{{email}} davet edildi" + "confirm_your_details": "Bilgilerinizi onaylayın", + "currency_string": "{{amount, currency}}", + "email_invite_team": "{{email}} davet edildi", + "form_updated_successfully": "Form başarıyla güncellendi.", + "disable_attendees_confirmation_emails": "Katılımcılar için varsayılan onay e-postalarını devre dışı bırakın" } From 876584e132074da2edd6c4ecd17270e7a543acf6 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 29 May 2023 18:59:25 +0000 Subject: [PATCH 003/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/ko/common.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/web/public/static/locales/ko/common.json b/apps/web/public/static/locales/ko/common.json index 0aa6cc353b..e22a91652f 100644 --- a/apps/web/public/static/locales/ko/common.json +++ b/apps/web/public/static/locales/ko/common.json @@ -1783,10 +1783,10 @@ "no_show_fee_charged_email_subject": "{{amount, currency}}에 대한 노쇼 수수료 부과됨: {{title}} 날짜 {{date}}", "no_show_fee_charged_text_body": "노쇼 수수료가 부과되었습니다", "no_show_fee_charged_subtitle": "다음 이벤트에 대해 {{amount, currency}}에 대한 노쇼 수수료가 부과되었습니다", - "error_charging_card": "No-show 수수료 청구 중 문제가 발생했습니다. 나중에 다시 시도해주세요.", - "collect_no_show_fee": "No-show 수수료를 청구하세요", - "no_show_fee_charged": "No-show 수수료가 부과됩니다", - "insights": "인사이트", + "error_charging_card": "노쇼 수수료를 부과하는 중 문제가 발생했습니다. 나중에 다시 시도해주세요.", + "collect_no_show_fee": "노쇼 수수료 청구", + "no_show_fee_charged": "노쇼 수수료 부과됨", + "insights": "Insights", "testing_workflow_info_message": "이 워크플로를 테스트할 때 이메일 및 SMS는 최소 1시간 전에만 예약할 수 있다는 점에 유의하세요", "insights_no_data_found_for_filter": "선택한 필터 또는 날짜에 대한 데이터를 찾을 수 없습니다.", "acknowledge_booking_no_show_fee": "본인은 이 이벤트에 참석하지 않을 경우 {{amount, currency}}에 대한 노쇼 수수료가 내 카드에 부과됨을 인정합니다.", From bca4df677c5d915e2b0344d33df7d9696d3b4a30 Mon Sep 17 00:00:00 2001 From: zomars Date: Mon, 29 May 2023 12:03:32 -0700 Subject: [PATCH 004/100] Debugging API linting staleness --- apps/api/.eslintrc.js | 1 - apps/api/package.json | 2 -- 2 files changed, 3 deletions(-) delete mode 100644 apps/api/.eslintrc.js diff --git a/apps/api/.eslintrc.js b/apps/api/.eslintrc.js deleted file mode 100644 index 0e71ec1eae..0000000000 --- a/apps/api/.eslintrc.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require("@calcom/config/eslint-preset"); diff --git a/apps/api/package.json b/apps/api/package.json index af678fe46b..1a975d25fa 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -11,10 +11,8 @@ "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next", "dev": "PORT=3002 next dev", "lint": "eslint . --ignore-path .gitignore", - "lint:report": "eslint . --format json --output-file ../../lint-results/api.json", "lint:fix": "eslint . --ext .ts,.js,.tsx,.jsx --fix", "start": "PORT=3002 next start", - "test": "echo 'No tests yet' && exit 0", "type-check": "tsc --pretty --noEmit" }, "devDependencies": { From 414c616f039717ff1956d79dbd6bca70da9404a3 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 29 May 2023 19:05:35 +0000 Subject: [PATCH 005/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/ko/common.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/web/public/static/locales/ko/common.json b/apps/web/public/static/locales/ko/common.json index e22a91652f..29c2dee2d2 100644 --- a/apps/web/public/static/locales/ko/common.json +++ b/apps/web/public/static/locales/ko/common.json @@ -1541,7 +1541,7 @@ "date_overrides_update_btn": "재정의 업데이트", "event_type_duplicate_copy_text": "{{slug}}-카피", "set_as_default": "기본값으로 설정", - "hide_eventtype_details": "이벤트 타입 세부 정보 숨기기", + "hide_eventtype_details": "이벤트 타입 세부정보 숨기기", "show_navigation": "탐색 표시", "hide_navigation": "탐색 숨기기", "verification_code_sent": "인증 코드 발송됨", @@ -1555,7 +1555,7 @@ "create_your_first_team_webhook_description": "이 팀 이벤트 유형에 대한 첫 번째 웹훅 만들기", "create_webhook_team_event_type": "이 팀 이벤트 유형에 대한 웹훅 만들기", "disable_success_page": "예약 성공 페이지 비활성화(리디렉션 URL이 있는 경우에만 작동)", - "invalid_admin_password": "관리자이지만 비밀번호 길이가 15자 이상이 아니거나, 이중 인증이 설정되지 않았습니다", + "invalid_admin_password": "관리자이지만 비밀번호 길이가 15자 이상이 아니거나, 2단계 인증이 설정되지 않았습니다", "change_password_admin": "관리자 액세스를 위해 비밀번호 변경", "username_already_taken": "이미 사용 중인 사용자 이름입니다", "assignment": "할당", @@ -1690,7 +1690,7 @@ "add_1_option_per_line": "한 줄에 옵션 1개 추가", "select_a_router": "라우터 선택", "add_a_new_route": "새 경로 추가", - "make_informed_decisions": "인사이트를 활용하여 정보를 바탕으로 합리적인 결정을 내려보세요", + "make_informed_decisions": "Insights를 이용해 정확한 정보에 입각한 의사 결정 내리기", "make_informed_decisions_description": "Insights 대시보드는 팀의 모든 활동들을 보여주고, 일정 및 의사 결정을 개선하기 위한 트렌드를 보여줍니다.", "view_bookings_across": "모든 멤버들의 예약 내역을 조회해보세요", "view_bookings_across_description": "가장 많은 예약을 받고 있는 멤버를 확인하고, 멤버들 간 공정한 예약 분배가 이루어지도록 해보세요", @@ -1798,7 +1798,7 @@ "charge_card_dialog_body": "참석자에게 {{amount, currency}}을 청구하려고 합니다. 계속 진행하시겠습니까?", "charge_attendee": "참석자에게 {{amount, currency}}을 청구합니다.", "payment_app_commission": "결제가 필요합니다 (건당 수수료 {{paymentFeePercentage}}% + {{fee, currency}})", - "email_invite_team": "{{email}} 이 초대되었습니다.", + "email_invite_team": "{{email}}이(가) 초대되었습니다", "image_size_limit_exceed": "업로드되는 이미지의 크기는 5MB를 초과하면 안 됩니다.", "need_help_embedding": "도움이 필요하신가요? Wix, Squarespace, 또는 WordPress에서 Cal을 임베드하는 가이드를 참조하거나, 자주 묻는 질문을 확인하거나, 고급 임베드 옵션을 살펴보세요.", "disable_attendees_confirmation_emails": "참석자에 대한 기본 확인 이메일 비활성화", From d13eb455653acd1fd58994ad282384f4eeb7e109 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 29 May 2023 19:06:26 +0000 Subject: [PATCH 006/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/ko/common.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/public/static/locales/ko/common.json b/apps/web/public/static/locales/ko/common.json index 29c2dee2d2..54b0949e22 100644 --- a/apps/web/public/static/locales/ko/common.json +++ b/apps/web/public/static/locales/ko/common.json @@ -1691,8 +1691,8 @@ "select_a_router": "라우터 선택", "add_a_new_route": "새 경로 추가", "make_informed_decisions": "Insights를 이용해 정확한 정보에 입각한 의사 결정 내리기", - "make_informed_decisions_description": "Insights 대시보드는 팀의 모든 활동들을 보여주고, 일정 및 의사 결정을 개선하기 위한 트렌드를 보여줍니다.", - "view_bookings_across": "모든 멤버들의 예약 내역을 조회해보세요", + "make_informed_decisions_description": "Insights 대시보드는 팀의 모든 활동을 드러내고, 팀의 일정 관리와 의사 결정을 개선하기 위한 트렌드를 보여줍니다.", + "view_bookings_across": "모든 회원의 예약 내용 보기", "view_bookings_across_description": "가장 많은 예약을 받고 있는 멤버를 확인하고, 멤버들 간 공정한 예약 분배가 이루어지도록 해보세요", "identify_booking_trends": "예약 트렌드를 파악해보세요", "identify_booking_trends_description": "예약자에게 인기 있는 요일 및 시간을 확인해보세요", From 3bf23850a358829b581ef2a198c54a54747dbb43 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 29 May 2023 19:07:27 +0000 Subject: [PATCH 007/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/ko/common.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/public/static/locales/ko/common.json b/apps/web/public/static/locales/ko/common.json index 54b0949e22..3627274def 100644 --- a/apps/web/public/static/locales/ko/common.json +++ b/apps/web/public/static/locales/ko/common.json @@ -1693,7 +1693,7 @@ "make_informed_decisions": "Insights를 이용해 정확한 정보에 입각한 의사 결정 내리기", "make_informed_decisions_description": "Insights 대시보드는 팀의 모든 활동을 드러내고, 팀의 일정 관리와 의사 결정을 개선하기 위한 트렌드를 보여줍니다.", "view_bookings_across": "모든 회원의 예약 내용 보기", - "view_bookings_across_description": "가장 많은 예약을 받고 있는 멤버를 확인하고, 멤버들 간 공정한 예약 분배가 이루어지도록 해보세요", + "view_bookings_across_description": "가장 많은 예약을 받고 있는 회원을 확인하고, 전체 회원 사이에 최선의 분배가 이루어지도록 하세요", "identify_booking_trends": "예약 트렌드를 파악해보세요", "identify_booking_trends_description": "예약자에게 인기 있는 요일 및 시간을 확인해보세요", "spot_popular_event_types": "인기 있는 이벤트 타입을 찾아보세요", From b8a756f98d4e1d1a06f310daba17109ebf173495 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 29 May 2023 19:08:22 +0000 Subject: [PATCH 008/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/ko/common.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/web/public/static/locales/ko/common.json b/apps/web/public/static/locales/ko/common.json index 3627274def..ee0a33927a 100644 --- a/apps/web/public/static/locales/ko/common.json +++ b/apps/web/public/static/locales/ko/common.json @@ -1693,9 +1693,9 @@ "make_informed_decisions": "Insights를 이용해 정확한 정보에 입각한 의사 결정 내리기", "make_informed_decisions_description": "Insights 대시보드는 팀의 모든 활동을 드러내고, 팀의 일정 관리와 의사 결정을 개선하기 위한 트렌드를 보여줍니다.", "view_bookings_across": "모든 회원의 예약 내용 보기", - "view_bookings_across_description": "가장 많은 예약을 받고 있는 회원을 확인하고, 전체 회원 사이에 최선의 분배가 이루어지도록 하세요", - "identify_booking_trends": "예약 트렌드를 파악해보세요", - "identify_booking_trends_description": "예약자에게 인기 있는 요일 및 시간을 확인해보세요", + "view_bookings_across_description": "가장 많은 예약을 받고 있는 회원을 확인하고, 전체 회원 사이에 최선의 분배가 이루어지도록 보장", + "identify_booking_trends": "예약 트렌드 파악", + "identify_booking_trends_description": "예약자에게 인기 있는 요일과 시간 확인", "spot_popular_event_types": "인기 있는 이벤트 타입을 찾아보세요", "spot_popular_event_types_description": "어떤 이벤트 타입이 가장 많은 클릭을 받고 예약이 되고 있는지 확인해보세요", "no_responses_yet": "아직 응답 없음", From 75347b7a79d9225482d1e3f5364b47a829c3a0b5 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 29 May 2023 19:09:34 +0000 Subject: [PATCH 009/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/ko/common.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/public/static/locales/ko/common.json b/apps/web/public/static/locales/ko/common.json index ee0a33927a..a36eeaeedd 100644 --- a/apps/web/public/static/locales/ko/common.json +++ b/apps/web/public/static/locales/ko/common.json @@ -1696,8 +1696,8 @@ "view_bookings_across_description": "가장 많은 예약을 받고 있는 회원을 확인하고, 전체 회원 사이에 최선의 분배가 이루어지도록 보장", "identify_booking_trends": "예약 트렌드 파악", "identify_booking_trends_description": "예약자에게 인기 있는 요일과 시간 확인", - "spot_popular_event_types": "인기 있는 이벤트 타입을 찾아보세요", - "spot_popular_event_types_description": "어떤 이벤트 타입이 가장 많은 클릭을 받고 예약이 되고 있는지 확인해보세요", + "spot_popular_event_types": "인기 있는 이벤트 타입 찾기", + "spot_popular_event_types_description": "어떤 이벤트 타입이 가장 많은 클릭과 예약을 받고 있는지 확인", "no_responses_yet": "아직 응답 없음", "this_will_be_the_placeholder": "이것은 자리 표시자가 됩니다", "error_booking_event": "이벤트를 예약하는 도중 오류가 발생했습니다. 페이지를 새로고침한 후 다시 시도해주세요.", From a334415ff942a73045e51240da509c1ba4344941 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 29 May 2023 19:10:28 +0000 Subject: [PATCH 010/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/ko/common.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/public/static/locales/ko/common.json b/apps/web/public/static/locales/ko/common.json index a36eeaeedd..c5a95b6f1e 100644 --- a/apps/web/public/static/locales/ko/common.json +++ b/apps/web/public/static/locales/ko/common.json @@ -1721,7 +1721,7 @@ "event_end_time_variable": "이벤트 종료 시간", "event_end_time_info": "이벤트 종료 시간", "cancel_url_variable": "취소 URL", - "cancel_url_info": "예약 취소 URL", + "cancel_url_info": "예약 취소를 위한 URL", "reschedule_url_variable": "일정 변경 URL", "reschedule_url_info": "예약 일정 변경 URL", "invalid_event_name_variables": "이벤트 이름에 유효하지 않은 변수가 있습니다", From f0a9897dafd5785a18569c2e0be6f262dea1a5b4 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 29 May 2023 19:11:19 +0000 Subject: [PATCH 011/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/ko/common.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/public/static/locales/ko/common.json b/apps/web/public/static/locales/ko/common.json index c5a95b6f1e..fa32a1cd06 100644 --- a/apps/web/public/static/locales/ko/common.json +++ b/apps/web/public/static/locales/ko/common.json @@ -1719,11 +1719,11 @@ "timezone_variable": "시간대", "timezone_info": "예약 수신자의 시간대", "event_end_time_variable": "이벤트 종료 시간", - "event_end_time_info": "이벤트 종료 시간", + "event_end_time_info": "이벤트가 종료되는 시간", "cancel_url_variable": "취소 URL", "cancel_url_info": "예약 취소를 위한 URL", "reschedule_url_variable": "일정 변경 URL", - "reschedule_url_info": "예약 일정 변경 URL", + "reschedule_url_info": "예약 일정을 변경하기 위한 URL", "invalid_event_name_variables": "이벤트 이름에 유효하지 않은 변수가 있습니다", "select_all": "모두 선택", "default_conferencing_bulk_title": "기존 이벤트 타입을 일괄 업데이트", From 5534153d432a102f25a24427c54c5505958fc248 Mon Sep 17 00:00:00 2001 From: TachyonicBytes <97369296+tachyonicbytes@users.noreply.github.com> Date: Mon, 29 May 2023 22:11:45 +0300 Subject: [PATCH 012/100] Add the or operator to the emails package.json as well (#9013) Co-authored-by: TachyonicBytes Co-authored-by: Peer Richelsen --- packages/emails/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/emails/package.json b/packages/emails/package.json index 786d6ab25e..3ab4363bd4 100644 --- a/packages/emails/package.json +++ b/packages/emails/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "private": true, "scripts": { - "dx": "docker compose up -d" + "dx": "docker compose up -d || docker-compose up -d" }, "dependencies": { "@calcom/dayjs": "*", From 15e50fcd34fd20fbcae3d9099901d8103e49fc85 Mon Sep 17 00:00:00 2001 From: jemiluv8 <119384208+jemiluv8@users.noreply.github.com> Date: Mon, 29 May 2023 19:11:55 +0000 Subject: [PATCH 013/100] fix: Route Builder rules should be case insensitive (#9040) * override jsonLogic operators on string operands to allow for case insensitive comparisons. Affected Operators: "==", "===", "!=", "!==", "in" * disable no-explicit-any on jsonLogicOverrides file since most of the code there will be from jsonLogic and may not meet our coding style. Majority of overrides require us to copy over functions and their signatures from jsonLogic and then modify their implementation. The signature of functions implementing most operators take the operands typed as "any", which is intended, but doesn't adhere to our coding style. Hence the need to override the eslint rule * run linter to fix issues * Fix bug in in operator when second arg is an array * remove redundant indexOf check on overriden jsonLogic "in" operator. Note: this deviates from the original implementation in the jsonLogic library because our current useage ensures that the second operand is always a string or string[] and will therefore always have .index function. Whenever our invariants change in the future, make sure to modify this implementation to prevent any unexpected --------- Co-authored-by: Hariom Balhara --- .../routing-forms/lib/jsonLogicOverrides.ts | 53 +++++++++++++++++++ .../routing-forms/lib/processRoute.tsx | 2 +- playwright.config.ts | 6 +-- 3 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 packages/app-store/routing-forms/lib/jsonLogicOverrides.ts diff --git a/packages/app-store/routing-forms/lib/jsonLogicOverrides.ts b/packages/app-store/routing-forms/lib/jsonLogicOverrides.ts new file mode 100644 index 0000000000..5627a29df1 --- /dev/null +++ b/packages/app-store/routing-forms/lib/jsonLogicOverrides.ts @@ -0,0 +1,53 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import jsonLogic from "json-logic-js"; + +// converts input to lowercase if string +function normalize(input: T): T { + if (typeof input === "string") { + return input.toLowerCase() as T; + } + if (input instanceof Array) { + return input.map((item) => { + if (typeof item === "string") { + return item.toLowerCase(); + } + // if array item is not a string, return it as is + return item; + }) as T; + } + return input; +} + +/** + * Single Select equals and not equals uses it + * Short Text equals and not equals uses it + */ +jsonLogic.add_operation("==", function (a: any, b: any) { + return normalize(a) == normalize(b); +}); + +jsonLogic.add_operation("===", function (a: any, b: any) { + return normalize(a) === normalize(b); +}); + +jsonLogic.add_operation("!==", function (a: any, b: any) { + return normalize(a) !== normalize(b); +}); + +jsonLogic.add_operation("!=", function (a: any, b: any) { + return normalize(a) != normalize(b); +}); + +/** + * Multiselect "equals" and "not equals" uses it + * Singleselect "any in" and "not in" uses it + * Long Text/Short Text/Email/Phone "contains" also uses it. + */ +jsonLogic.add_operation("in", function (a: string, b: string | string[]) { + const first = normalize(a); + const second = normalize(b); + if (!second) return false; + return second.indexOf(first) !== -1; +}); + +export default jsonLogic; diff --git a/packages/app-store/routing-forms/lib/processRoute.tsx b/packages/app-store/routing-forms/lib/processRoute.tsx index d3268d2b43..6565da7af1 100644 --- a/packages/app-store/routing-forms/lib/processRoute.tsx +++ b/packages/app-store/routing-forms/lib/processRoute.tsx @@ -1,5 +1,4 @@ import type { App_RoutingForms_Form } from "@prisma/client"; -import jsonLogic from "json-logic-js"; import { Utils as QbUtils } from "react-awesome-query-builder"; import type { z } from "zod"; @@ -8,6 +7,7 @@ import type { zodNonRouterRoute } from "../zod"; import { getQueryBuilderConfig } from "./getQueryBuilderConfig"; import { isFallbackRoute } from "./isFallbackRoute"; import isRouter from "./isRouter"; +import jsonLogic from "./jsonLogicOverrides"; export function processRoute({ form, diff --git a/playwright.config.ts b/playwright.config.ts index e5255fb47a..0b5b248732 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -11,12 +11,12 @@ const outputDir = path.join(__dirname, "test-results"); // Dev Server on local can be slow to start up and process requests. So, keep timeouts really high on local, so that tests run reliably locally // So, if not in CI, keep the timers high, if the test is stuck somewhere and there is unnecessary wait developer can see in browser that it's stuck -const DEFAULT_NAVIGATION_TIMEOUT = process.env.CI ? 15000 : 50000; -const DEFAULT_EXPECT_TIMEOUT = process.env.CI ? 15000 : 50000; +const DEFAULT_NAVIGATION_TIMEOUT = process.env.CI ? 15000 : 120000; +const DEFAULT_EXPECT_TIMEOUT = process.env.CI ? 15000 : 120000; // Test Timeout can hit due to slow expect, slow navigation. // So, it should me much higher than sum of expect and navigation timeouts as there can be many async expects and navigations in a single test -const DEFAULT_TEST_TIMEOUT = process.env.CI ? 60000 : 120000; +const DEFAULT_TEST_TIMEOUT = process.env.CI ? 60000 : 240000; const headless = !!process.env.CI || !!process.env.PLAYWRIGHT_HEADLESS; From 37e6f18378451c6a5c7af9fdba70437ac4ea7afa Mon Sep 17 00:00:00 2001 From: Adithya Krishna Date: Tue, 30 May 2023 00:42:31 +0530 Subject: [PATCH 014/100] feat: Auto check PR titles if they follow conventional commits spec (#9109) Co-authored-by: Peer Richelsen --- .github/workflows/semantic-pull-requests.yml | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/semantic-pull-requests.yml diff --git a/.github/workflows/semantic-pull-requests.yml b/.github/workflows/semantic-pull-requests.yml new file mode 100644 index 0000000000..5585523eec --- /dev/null +++ b/.github/workflows/semantic-pull-requests.yml @@ -0,0 +1,21 @@ +name: "Validate PRs" + +on: + pull_request_target: + types: + - opened + - reopened + - edited + - synchronize + +permissions: + pull-requests: read + +jobs: + validate-pr: + name: Validate PR title + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From bfe0fb91f3dd91ddc2299dc9aeda0cb6c2f4085f Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 29 May 2023 19:14:49 +0000 Subject: [PATCH 015/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/ko/common.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/web/public/static/locales/ko/common.json b/apps/web/public/static/locales/ko/common.json index fa32a1cd06..fba50456e4 100644 --- a/apps/web/public/static/locales/ko/common.json +++ b/apps/web/public/static/locales/ko/common.json @@ -1730,14 +1730,14 @@ "members_default_schedule": "회원의 기본 일정", "set_by_admin": "팀 관리자에 의해 설정됨", "members_default_location": "회원의 기본 위치", - "members_default_schedule_description": "각 회원의 기본 사용 가능 일정을 사용합니다. 편집 또는 변경할 수 있습니다.", - "requires_at_least_one_schedule": "적어도 한 개 이상의 스케줄이 필요합니다", + "members_default_schedule_description": "각 회원의 기본 가용성 일정을 사용합니다. 편집 또는 변경할 수 있습니다.", + "requires_at_least_one_schedule": "적어도 하나 이상의 일정이 필요합니다", "default_conferencing_bulk_description": "선택한 이벤트 타입의 위치 업데이트", "locked_for_members": "회원에 대해 잠김", "locked_apps_description": "회원은 활성 앱을 볼 수 있지만 앱 설정을 편집할 수는 없습니다", "locked_webhooks_description": "회원은 활성 웹훅을 볼 수 있지만 웹훅 설정을 편집할 수는 없습니다", "locked_workflows_description": "회원은 활성 워크플로를 볼 수 있지만 워크플로 설정을 편집할 수는 없습니다", - "app_not_connected": "{{appName}} 계정을 연결하지 않으셨습니다.", + "app_not_connected": "{{appName}} 계정을 연결하지 않았습니다.", "connect_now": "지금 연결", "managed_event_dialog_confirm_button_one": "회원 {{count}}명 바꾸기 및 알림", "managed_event_dialog_confirm_button_other": "회원 {{count}}명 바꾸기 및 알림", @@ -1747,7 +1747,7 @@ "managed_event_dialog_information_other": "{{names}} 님이 이미 /{{slug}} url을 사용하는 중입니다.", "managed_event_dialog_clarification": "URL 바꾸기를 선택하면 회원에게 알려드립니다. 덮어쓰지 않으려면 돌아가서 제거하십시오.", "review_event_type": "이벤트 타입 검토", - "looking_for_more_analytics": "추가적인 분석을 원하시나요?", + "looking_for_more_analytics": "더 많은 분석 정보를 원합니까?", "looking_for_more_insights": "더 많은 인사이트를 찾고계신가요?", "add_filter": "필터 추가", "select_user": "사용자 선택", From 21cb2e56094e5334f3c3f033e35815cb5fae46df Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 29 May 2023 19:16:45 +0000 Subject: [PATCH 016/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/ko/common.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/web/public/static/locales/ko/common.json b/apps/web/public/static/locales/ko/common.json index fba50456e4..7158e8c1d0 100644 --- a/apps/web/public/static/locales/ko/common.json +++ b/apps/web/public/static/locales/ko/common.json @@ -1748,7 +1748,7 @@ "managed_event_dialog_clarification": "URL 바꾸기를 선택하면 회원에게 알려드립니다. 덮어쓰지 않으려면 돌아가서 제거하십시오.", "review_event_type": "이벤트 타입 검토", "looking_for_more_analytics": "더 많은 분석 정보를 원합니까?", - "looking_for_more_insights": "더 많은 인사이트를 찾고계신가요?", + "looking_for_more_insights": "더 많은 인사이트를 찾고 있습니까?", "add_filter": "필터 추가", "select_user": "사용자 선택", "select_event_type": "이벤트 타입 선택", @@ -1756,8 +1756,8 @@ "popular_events": "인기 이벤트", "no_event_types_found": "이벤트 타입을 찾을 수 없습니다", "average_event_duration": "평균 이벤트 기간", - "most_booked_members": "가장 많이 예약한 회원", - "least_booked_members": "가장 적게 예약한 회원", + "most_booked_members": "예약이 가장 많은 회원", + "least_booked_members": "예약이 가장 적은 회원", "events_created": "생성된 이벤트", "events_completed": "완료된 이벤트", "events_cancelled": "취소된 이벤트", From 9f881e9911cf94648be990dd272ea76ea9a4cd9f Mon Sep 17 00:00:00 2001 From: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Date: Tue, 30 May 2023 04:43:32 +0900 Subject: [PATCH 017/100] ci: Move linting to build jet (#9188) Co-authored-by: Peer Richelsen --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 2c2d5ebc69..b566168d0a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -3,7 +3,7 @@ on: workflow_call: jobs: lint: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 From be304738e7d02e826241090bdccfd76a341fdb57 Mon Sep 17 00:00:00 2001 From: zomars Date: Mon, 29 May 2023 12:54:02 -0700 Subject: [PATCH 018/100] Re-enables buildjet on PR blocking tasks --- .github/workflows/cache-clean.yml | 2 +- .github/workflows/check-types.yml | 2 +- .github/workflows/e2e-app-store.yml | 2 +- .github/workflows/e2e-embed-react.yml | 2 +- .github/workflows/e2e-embed.yml | 2 +- .github/workflows/e2e.yml | 2 +- .github/workflows/env-create-file.yml | 2 +- .github/workflows/nextjs-bundle-analysis.yml | 2 +- .github/workflows/pr.yml | 4 ++-- .github/workflows/production-build.yml | 2 +- .github/workflows/test.yml | 2 +- .github/workflows/yarn-install.yml | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/cache-clean.yml b/.github/workflows/cache-clean.yml index 99583c7e8e..dd0be43ec5 100644 --- a/.github/workflows/cache-clean.yml +++ b/.github/workflows/cache-clean.yml @@ -6,7 +6,7 @@ on: jobs: cleanup: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - name: Check out code uses: actions/checkout@v3 diff --git a/.github/workflows/check-types.yml b/.github/workflows/check-types.yml index 1628003b6c..644ca2e9d6 100644 --- a/.github/workflows/check-types.yml +++ b/.github/workflows/check-types.yml @@ -5,7 +5,7 @@ env: NODE_OPTIONS: "--max-old-space-size=8192" jobs: check-types: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - uses: ./.github/actions/dangerous-git-checkout diff --git a/.github/workflows/e2e-app-store.yml b/.github/workflows/e2e-app-store.yml index 8db02bc677..dd1b98953a 100644 --- a/.github/workflows/e2e-app-store.yml +++ b/.github/workflows/e2e-app-store.yml @@ -6,7 +6,7 @@ jobs: e2e-app-store: timeout-minutes: 20 name: E2E App-Store Apps - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 services: postgres: image: postgres:12.1 diff --git a/.github/workflows/e2e-embed-react.yml b/.github/workflows/e2e-embed-react.yml index 5ce70167e0..7b27cb7951 100644 --- a/.github/workflows/e2e-embed-react.yml +++ b/.github/workflows/e2e-embed-react.yml @@ -5,7 +5,7 @@ on: jobs: e2e-embed: timeout-minutes: 20 - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 services: postgres: image: postgres:12.1 diff --git a/.github/workflows/e2e-embed.yml b/.github/workflows/e2e-embed.yml index c60888f9f7..335471cbe6 100644 --- a/.github/workflows/e2e-embed.yml +++ b/.github/workflows/e2e-embed.yml @@ -5,7 +5,7 @@ on: jobs: e2e-embed: timeout-minutes: 20 - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 services: postgres: image: postgres:12.1 diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index f77708fc25..b5abb0559a 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -5,7 +5,7 @@ jobs: e2e: timeout-minutes: 20 name: E2E tests - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 services: postgres: image: postgres:12.1 diff --git a/.github/workflows/env-create-file.yml b/.github/workflows/env-create-file.yml index 79a4073b12..7e5d73bbd8 100644 --- a/.github/workflows/env-create-file.yml +++ b/.github/workflows/env-create-file.yml @@ -36,7 +36,7 @@ env: jobs: create_env_file: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - uses: ./.github/actions/dangerous-git-checkout diff --git a/.github/workflows/nextjs-bundle-analysis.yml b/.github/workflows/nextjs-bundle-analysis.yml index 1e5d821a01..972e8af225 100644 --- a/.github/workflows/nextjs-bundle-analysis.yml +++ b/.github/workflows/nextjs-bundle-analysis.yml @@ -15,7 +15,7 @@ jobs: analyze: needs: build if: always() - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - uses: ./.github/actions/dangerous-git-checkout diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index f8961b1755..c2fc266790 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -16,7 +16,7 @@ concurrency: jobs: changes: - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 permissions: pull-requests: read outputs: @@ -101,7 +101,7 @@ jobs: required: needs: [lint, type-check, test, build, e2e] if: always() - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - name: fail if conditional jobs failed if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'skipped') || contains(needs.*.result, 'cancelled') diff --git a/.github/workflows/production-build.yml b/.github/workflows/production-build.yml index ef75c7ac31..4bcc8ef71f 100644 --- a/.github/workflows/production-build.yml +++ b/.github/workflows/production-build.yml @@ -6,7 +6,7 @@ on: jobs: build: name: Build - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 timeout-minutes: 30 services: postgres: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e71506689f..fcc7c6ed1f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,7 +7,7 @@ on: jobs: test: timeout-minutes: 20 - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 steps: - uses: actions/checkout@v3 - uses: ./.github/actions/dangerous-git-checkout diff --git a/.github/workflows/yarn-install.yml b/.github/workflows/yarn-install.yml index 3ee08b3f48..5fbb5c0f1b 100644 --- a/.github/workflows/yarn-install.yml +++ b/.github/workflows/yarn-install.yml @@ -6,7 +6,7 @@ on: jobs: setup: name: Yarn install & cache - runs-on: ubuntu-latest + runs-on: buildjet-4vcpu-ubuntu-2204 timeout-minutes: 10 steps: - uses: actions/checkout@v3 From 285c122bdcc879e69c7181aa3760729d248f0f7e Mon Sep 17 00:00:00 2001 From: zomars Date: Mon, 29 May 2023 13:22:24 -0700 Subject: [PATCH 019/100] Uses buildjet cache action --- .github/actions/cache-build/action.yml | 2 +- .github/actions/cache-db/action.yml | 2 +- .github/actions/env-read-file/action.yml | 4 ++-- .github/actions/yarn-install/action.yml | 6 +++--- .github/workflows/env-create-file.yml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/actions/cache-build/action.yml b/.github/actions/cache-build/action.yml index 17b397cb53..1ef35a7831 100644 --- a/.github/actions/cache-build/action.yml +++ b/.github/actions/cache-build/action.yml @@ -8,7 +8,7 @@ runs: using: "composite" steps: - name: Cache production build - uses: actions/cache@v3 + uses: buildjet/cache@v3 id: cache-build env: cache-name: prod-build diff --git a/.github/actions/cache-db/action.yml b/.github/actions/cache-db/action.yml index a706e3260c..f69fd9513a 100644 --- a/.github/actions/cache-db/action.yml +++ b/.github/actions/cache-db/action.yml @@ -12,7 +12,7 @@ runs: steps: - name: Cache database id: cache-db - uses: actions/cache@v3 + uses: buildjet/cache@v3 env: cache-name: cache-db key-1: ${{ hashFiles('packages/prisma/schema.prisma', 'packages/prisma/migrations/**/**.sql', 'packages/prisma/*.ts') }} diff --git a/.github/actions/env-read-file/action.yml b/.github/actions/env-read-file/action.yml index 26ca4e0306..7caf7328ff 100644 --- a/.github/actions/env-read-file/action.yml +++ b/.github/actions/env-read-file/action.yml @@ -4,7 +4,7 @@ runs: using: "composite" steps: - name: Create env file - uses: actions/cache@v3 + uses: buildjet/cache@v3 id: env-cache with: path: gh.env @@ -13,4 +13,4 @@ runs: - name: Set Environment Variables uses: tw3lveparsecs/github-actions-setvars@latest with: - envFilePath: gh.env \ No newline at end of file + envFilePath: gh.env diff --git a/.github/actions/yarn-install/action.yml b/.github/actions/yarn-install/action.yml index 106298bfab..216cdce6de 100644 --- a/.github/actions/yarn-install/action.yml +++ b/.github/actions/yarn-install/action.yml @@ -20,7 +20,7 @@ runs: using: "composite" steps: - name: Use Node ${{ inputs.node_version }} - uses: actions/setup-node@v3 + uses: buildjet/setup-node@v3 with: node-version: ${{ inputs.node_version }} - name: Expose yarn config as "$GITHUB_OUTPUT" @@ -32,7 +32,7 @@ runs: # Yarn rotates the downloaded cache archives, @see https://github.com/actions/setup-node/issues/325 # Yarn cache is also reusable between arch and os. - name: Restore yarn cache - uses: actions/cache@v3 + uses: buildjet/cache@v3 id: yarn-download-cache with: path: ${{ steps.yarn-config.outputs.CACHE_FOLDER }} @@ -43,7 +43,7 @@ runs: # Invalidated on yarn.lock changes - name: Restore yarn install state id: yarn-install-state-cache - uses: actions/cache@v3 + uses: buildjet/cache@v3 with: path: .yarn/ci-cache/ key: ${{ runner.os }}-yarn-install-state-cache-${{ hashFiles('yarn.lock', '.yarnrc.yml') }} diff --git a/.github/workflows/env-create-file.yml b/.github/workflows/env-create-file.yml index 7e5d73bbd8..dadab15de9 100644 --- a/.github/workflows/env-create-file.yml +++ b/.github/workflows/env-create-file.yml @@ -43,7 +43,7 @@ jobs: - uses: ozaytsev86/create-env-file@v1 with: file-name: ${{ github.workspace }}/gh.env - - uses: actions/cache@v3 + - uses: buildjet/cache@v3 id: env-cache with: path: gh.env From 0075414c8b02c05df0f7c8f0a7b76553046e513a Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 29 May 2023 20:26:22 +0000 Subject: [PATCH 020/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/es/common.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/web/public/static/locales/es/common.json b/apps/web/public/static/locales/es/common.json index 5122e8a89f..52aa6ee4e9 100644 --- a/apps/web/public/static/locales/es/common.json +++ b/apps/web/public/static/locales/es/common.json @@ -591,7 +591,7 @@ "round_robin_description": "Ciclo de reuniones entre varios miembros del equipo.", "managed_event": "Evento gestionado", "username_placeholder": "nombre de usuario", - "managed_event_description": "Cree distribuya tipos de eventos de forma masiva a los miembros del equipo", + "managed_event_description": "Cree y distribuya tipos de eventos de forma masiva a los miembros del equipo", "managed": "Gestionado", "managed_event_url_clarification": "El \"nombre de usuario\" se completará con el nombre de usuario de los miembros asignados", "assign_to": "Asignar a", @@ -755,8 +755,8 @@ "slot_interval": "Intervalos de tiempo", "slot_interval_default": "Usar duración del evento (por defecto)", "delete_event_type": "¿Eliminar tipo de evento?", - "delete_managed_event_type": "¿Eliminar tipo de evento administrado?", - "delete_event_type_description": "Cualquier persona con la que hayas compartido este enlace ya no podrá reservar con él.", + "delete_managed_event_type": "¿Eliminar tipo de evento gestionado?", + "delete_event_type_description": "Cualquier persona con la que haya compartido este enlace ya no podrá reservar con él.", "delete_managed_event_type_description": "
  • Los miembros asignados a este tipo de evento también verán eliminados sus tipos de evento.
  • Cualquier persona con la que hayan compartido su enlace ya no podrá reservar mediante su uso.
", "confirm_delete_event_type": "Sí, eliminar", "delete_account": "Eliminar cuenta", @@ -1380,7 +1380,7 @@ "add_limit": "Agregue un límite", "team_name_required": "Nombre de equipo requerido", "show_attendees": "Comparta información de los asistentes entre los invitados", - "how_booking_questions_as_variables": "¿Cómo se utilizan las preguntas de reserva como variables?", + "how_booking_questions_as_variables": "¿Cómo utilizar las preguntas de reserva como variables?", "format": "Formato", "uppercase_for_letters": "Use mayúsculas para todas las letras", "replace_whitespaces_underscores": "Reemplace espacios en blanco con guiones bajos", @@ -1486,7 +1486,7 @@ "disabled_app_affects_event_type": "Un administrador desactivó {{appName}}, lo que afecta a su tipo de evento {{eventType}}", "event_replaced_notice": "Un administrador ha reemplazado uno de sus tipos de eventos", "email_subject_slug_replacement": "Un administrador del equipo ha reemplazado su evento /{{slug}}", - "email_body_slug_replacement_notice": "Un administrador del equipo {{teamName}} reemplazó su tipo de evento /{{slug}} con un tipo de evento administrado que él controla.", + "email_body_slug_replacement_notice": "Un administrador del equipo {{teamName}} reemplazó su tipo de evento /{{slug}} con un tipo de evento gestionado que él controla.", "email_body_slug_replacement_info": "Su enlace seguirá funcionando, pero algunas configuraciones pueden haber cambiado. Puede revisarlo en tipos de eventos.", "email_body_slug_replacement_suggestion": "Si tiene alguna pregunta sobre el tipo de evento, comuníquese con su administrador.

Feliz programación,
El equipo de Cal.com", "disable_payment_app": "El administrador ha deshabilitado {{appName}}, lo que afecta a su tipo de evento {{title}}. Los asistentes todavía pueden reservar este tipo de evento, pero no se les pedirá que paguen. Puede ocultar el tipo de evento para evitar esto hasta que su administrador habilite de nuevo su método de pago.", From 79e914b0fb5211d4f0104aa79de666f5201ebf6c Mon Sep 17 00:00:00 2001 From: zomars Date: Mon, 29 May 2023 18:28:40 -0700 Subject: [PATCH 021/100] Prevents page.pause reaching main --- apps/web/playwright/booking-pages.e2e.ts | 1 - apps/web/playwright/booking-seats.e2e.ts | 1 - apps/web/playwright/hash-my-url.e2e.ts | 1 - packages/config/eslint-preset.js | 1 + 4 files changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/web/playwright/booking-pages.e2e.ts b/apps/web/playwright/booking-pages.e2e.ts index 5c72236154..f35f871279 100644 --- a/apps/web/playwright/booking-pages.e2e.ts +++ b/apps/web/playwright/booking-pages.e2e.ts @@ -65,7 +65,6 @@ testBothBookers.describe("pro user", () => { }); test("pro user's page has at least 2 visible events", async ({ page }) => { - // await page.pause(); const $eventTypes = page.locator("[data-testid=event-types] > *"); expect(await $eventTypes.count()).toBeGreaterThanOrEqual(2); }); diff --git a/apps/web/playwright/booking-seats.e2e.ts b/apps/web/playwright/booking-seats.e2e.ts index 940d566d54..723c7866ad 100644 --- a/apps/web/playwright/booking-seats.e2e.ts +++ b/apps/web/playwright/booking-seats.e2e.ts @@ -427,7 +427,6 @@ testBothBookers.describe("Booking with Seats", (bookerVariant) => { 'p[data-testid="attendee-email-second+seats@cal.com"]' ); await expect(foundSecondAttendeeAsOwner).toHaveCount(1); - await page.pause(); await page.goto("auth/logout"); // Now we cancel the booking as the first attendee diff --git a/apps/web/playwright/hash-my-url.e2e.ts b/apps/web/playwright/hash-my-url.e2e.ts index b948019bd1..921a933c52 100644 --- a/apps/web/playwright/hash-my-url.e2e.ts +++ b/apps/web/playwright/hash-my-url.e2e.ts @@ -15,7 +15,6 @@ test.fixme("hash my url", () => { await users.deleteAll(); }); test("generate url hash", async ({ page }) => { - // await page.pause(); await page.goto("/event-types"); // We wait until loading is finished await page.waitForSelector('[data-testid="event-types"]'); diff --git a/packages/config/eslint-preset.js b/packages/config/eslint-preset.js index aae6eb0a93..0d364f0b73 100644 --- a/packages/config/eslint-preset.js +++ b/packages/config/eslint-preset.js @@ -22,6 +22,7 @@ module.exports = { "@next/next/no-img-element": "off", "@next/next/no-html-link-for-pages": "off", "jsx-a11y/role-supports-aria-props": "off", // @see https://github.com/vercel/next.js/issues/27989#issuecomment-897638654 + "playwright/no-page-pause": "error", "react/jsx-curly-brace-presence": ["error", { props: "never", children: "never" }], "react/self-closing-comp": ["error", { component: true, html: true }], "@typescript-eslint/no-unused-vars": [ From 46d46f9733bee475bf5d10bf1df8c1409fd1957b Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 01:40:02 +0000 Subject: [PATCH 022/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/es/common.json | 61 ++++++++++++++++++- apps/web/public/static/locales/ko/common.json | 34 ++++++++++- apps/web/public/static/locales/pt/common.json | 57 ++++++++++++++++- apps/web/public/static/locales/tr/common.json | 15 ++++- .../public/static/locales/zh-CN/common.json | 4 ++ 5 files changed, 165 insertions(+), 6 deletions(-) diff --git a/apps/web/public/static/locales/es/common.json b/apps/web/public/static/locales/es/common.json index 52aa6ee4e9..b99ca4179d 100644 --- a/apps/web/public/static/locales/es/common.json +++ b/apps/web/public/static/locales/es/common.json @@ -26,6 +26,8 @@ "rejection_confirmation": "Rechazar la reserva", "manage_this_event": "Administrar este evento", "invite_team_member": "Invite a un miembro del equipo", + "invite_team_individual_segment": "Invitar individualmente", + "invite_team_bulk_segment": "Importar en masa", "invite_team_notifcation_badge": "Inv.", "your_event_has_been_scheduled": "Tu evento ha sido reprogramado", "your_event_has_been_scheduled_recurring": "Su evento recurrente se ha programado", @@ -222,6 +224,7 @@ "go_back_login": "Volver a la página de inicio", "error_during_login": "Se ha producido un error al iniciar sesión. Vuelve a la pantalla de inicio de sesión e inténtalo de nuevo.", "request_password_reset": "Restablecer contraseña", + "send_invite": "Enviar invitación", "forgot_password": "Olvidé la contraseña", "forgot": "¿Olvidado?", "done": "Hecho", @@ -237,6 +240,8 @@ "set_availability": "Establecer Disponibilidad", "continue_without_calendar": "Continuar sin calendario", "connect_your_calendar": "Conecta tu calendario", + "connect_your_video_app": "Conecte sus aplicaciones favoritas", + "connect_your_video_app_instructions": "Conecte sus aplicaciones de vídeo para usarlas en sus tipos de eventos.", "connect_your_calendar_instructions": "Conecta tu calendario para comprobar automáticamente los horarios ocupados y los nuevos eventos a medida que se programan.", "set_up_later": "Configurar más tarde", "current_time": "Hora Actual", @@ -367,6 +372,7 @@ "create_webhook": "Crear Webhook", "booking_cancelled": "Reserva Cancelada", "booking_rescheduled": "Reserva habilitada", + "recording_ready": "Enlace de descarga de grabación listo", "booking_created": "Reserva Creada", "meeting_ended": "Reunión finalizada", "form_submitted": "Formulario enviado", @@ -465,6 +471,7 @@ "friday": "Viernes", "saturday": "Sábado", "sunday": "Domingo", + "all_booked_today": "Todo reservado.", "slots_load_fail": "No se pudo cargar el intervalo de tiempo disponible.", "additional_guests": "Añadir invitados", "your_name": "Tu Nombre", @@ -752,6 +759,10 @@ "new_event_type_to_book_description": "Crea un nuevo tipo de evento para que las personas reserven horarios.", "length": "Tamaño", "minimum_booking_notice": "Aviso de Reserva", + "offset_toggle": "Horas de inicio desplazadas", + "offset_toggle_description": "Intervalos de tiempo desplazados que se muestran a los que reservan por un número específico de minutos", + "offset_start": "Desplazar por", + "offset_start_description": "por ejemplo esto mostrará los intervalos de tiempo a quienes reservan a las {{ adjustedTime }} en lugar de {{ originalTime }}", "slot_interval": "Intervalos de tiempo", "slot_interval_default": "Usar duración del evento (por defecto)", "delete_event_type": "¿Eliminar tipo de evento?", @@ -904,6 +915,7 @@ "duplicate": "Duplicado", "offer_seats": "Ofrecer plazas", "offer_seats_description": "Ofrecer plazas para las reservas (desactiva las reservas de invitados y las optativas)", + "seats_available_one": "Plazas disponibles", "seats_available_other": "Plazas disponibles", "number_of_seats": "Número de plazas por reserva", "enter_number_of_seats": "Introduzca el número de plazas", @@ -1038,6 +1050,7 @@ "event_cancelled_trigger": "cuando se cancela el evento", "new_event_trigger": "cuando se reserva un nuevo evento", "email_host_action": "enviar correo electrónico al anfitrión", + "email_attendee_action": "enviar correo electrónico a los asistentes", "sms_attendee_action": "enviar SMS al asistente", "sms_number_action": "enviar SMS a un número específico", "workflows": "Flujos de trabajo", @@ -1190,6 +1203,7 @@ "create_workflow": "Crear un flujo de trabajo", "do_this": "Hacer esto", "turn_off": "Apagar", + "turn_on": "Activar", "settings_updated_successfully": "Configuración actualizada correctamente", "error_updating_settings": "Error al actualizar la configuración", "personal_cal_url": "Mi URL personal de {{appName}}", @@ -1246,6 +1260,7 @@ "calendars_description": "Configura cómo interactúan tus tipos de eventos con tus calendarios", "appearance_description": "Administra los ajustes para el aspecto de tu reserva", "conferencing_description": "Añada sus aplicaciones de videoconferencia favoritas para sus reuniones", + "add_conferencing_app": "Añadir aplicación de conferencia", "password_description": "Administra los ajustes para las contraseñas de tu cuenta", "2fa_description": "Administra los ajustes para las contraseñas de tu cuenta", "we_just_need_basic_info": "Solo necesitamos información básica para configurar tu perfil.", @@ -1551,7 +1566,7 @@ "create_your_first_team_webhook_description": "Cree su primer webhook para este tipo de evento de equipo", "create_webhook_team_event_type": "Crear un webhook para este tipo de evento de equipo", "disable_success_page": "Desactivar página de éxito (solo funciona si tiene una URL de redireccionamiento)", - "invalid_admin_password": "Usted es administrador pero no tiene una contraseña de al menos 15 caracteres o ni autenticación de 2 factores", + "invalid_admin_password": "Usted es administrador pero no tiene una contraseña de al menos 15 caracteres o una autenticación de 2 factores aún", "change_password_admin": "Cambie la contraseña para obtener acceso de administrador", "username_already_taken": "Este nombre de usuario ya está en uso", "assignment": "Asignación", @@ -1620,6 +1635,7 @@ "email_user_cta": "Ver la invitación", "email_no_user_invite_heading": "Lo han invitado a unirse a un equipo en {{appName}}", "email_no_user_invite_subheading": "{{invitedBy}} lo invitó a unirse a su equipo en {{appName}}. {{appName}} es el programador de eventos que les permite a usted y a su equipo programar reuniones sin necesidad de enviar correos electrónicos.", + "email_user_invite_subheading": "{{invitedBy}} lo ha invitado a unirse a su equipo \"{{teamName}}\" en {{appName}}. {{appName}} es el planificador de eventos que le permite a usted y a su equipo programar reuniones sin correos electrónicos de ida y vuelta.", "email_no_user_invite_steps_intro": "Lo guiaremos a través de unos pocos pasos y disfrutará de una programación con su equipo sin estresarse y empleando muy poco tiempo.", "email_no_user_step_one": "Elija su nombre de usuario", "email_no_user_step_two": "Conecte su cuenta de calendario", @@ -1686,7 +1702,7 @@ "select_a_router": "Seleccione un enrutador", "add_a_new_route": "Agregar una ruta nueva", "make_informed_decisions": "Tome decisiones informadas con Insights", - "make_informed_decisions_description": "Nuestro panel de Insights muestra toda la actividad de su equipo y le muestra las tendencias que permiten una mejor programación y toma de decisiones del equipo.", + "make_informed_decisions_description": "Nuestro panel de Insights muestra toda la actividad de su equipo y las tendencias que permiten una mejor programación y toma de decisiones.", "view_bookings_across": "Ver reservas entre todos los miembros", "view_bookings_across_description": "Vea quién recibe la mayor cantidad de reservas y garantice la mejor distribución en su equipo", "identify_booking_trends": "Identificar tendencias de reserva", @@ -1695,6 +1711,15 @@ "spot_popular_event_types_description": "Consulte cuál de sus tipos de eventos están recibiendo más clics y reservas", "no_responses_yet": "Aún no hay respuestas", "this_will_be_the_placeholder": "Este será el marcador de posición", + "error_booking_event": "Ocurrió un error al reservar el evento, actualice la página e intente nuevamente", + "timeslot_missing_title": "No hay intervalo de tiempo seleccionado", + "timeslot_missing_description": "Seleccione un intervalo de tiempo para reservar el evento.", + "timeslot_missing_cta": "Seleccionar intervalo de tiempo", + "switch_monthly": "Cambiar a la vista mensual", + "switch_weekly": "Cambiar a la vista semanal", + "switch_multiday": "Cambiar a la vista diaria", + "num_locations": "{{num}} opciones de ubicación", + "select_on_next_step": "Seleccionar en el siguiente paso", "this_meeting_has_not_started_yet": "Esta reunión aún no ha comenzado", "this_app_requires_connected_account": "{{appName}} requiere una cuenta {{dependencyName}} conectada", "connect_app": "Conectar {{dependencyName}}", @@ -1724,6 +1749,7 @@ "locked_apps_description": "Los miembros podrán ver las aplicaciones activas pero no podrán editar ninguna configuración de la aplicación", "locked_webhooks_description": "Los miembros podrán ver los webhooks activos, pero no podrán editar ninguna configuración de webhooks", "locked_workflows_description": "Los miembros podrán ver los flujos de trabajo activos, pero no podrán editar ninguna configuración de flujo de trabajo", + "locked_by_admin": "Bloqueado por el administrador del equipo", "app_not_connected": "No ha conectado una cuenta de {{appName}}.", "connect_now": "Conectar ahora", "managed_event_dialog_confirm_button_one": "Reemplazar y notificar a {{count}} miembro", @@ -1781,5 +1807,34 @@ "seats_and_no_show_fee_error": "Actualmente no se pueden habilitar cupos ni cobrar una tarifa por no presentarse", "complete_your_booking": "Complete su reserva", "complete_your_booking_subject": "Complete su reserva: {{title}} el {{date}}", - "email_invite_team": "Se ha invitado a {{email}}" + "confirm_your_details": "Confirme sus datos", + "currency_string": "{{amount, currency}}", + "charge_card_dialog_body": "Está a punto de cobrarle {{amount, currency}} al asistente. ¿Está seguro de que desea continuar?", + "charge_attendee": "Cobrarle al asistente {{amount, currency}}", + "payment_app_commission": "Solicitar pago ({{paymentFeePercentage}}% + {{fee, currency}} comisión por transacción)", + "email_invite_team": "Se ha invitado a {{email}}", + "email_invite_team_bulk": "Se han invitado {{userCount}} usuarios", + "error_collecting_card": "Error al recolectar la tarjeta", + "image_size_limit_exceed": "La imagen cargada no debe exceder el límite de tamaño de 5 Mb", + "inline_embed": "Incrustar en línea", + "load_inline_content": "Carga su tipo de evento directamente en línea con otro contenido de su sitio web.", + "floating_pop_up_button": "Botón emergente flotante", + "floating_button_trigger_modal": "Pone un botón flotante en su sitio que activa un modal con su tipo de evento.", + "pop_up_element_click": "Aparece mediante un clic en el elemento", + "open_dialog_with_element_click": "Abre su cuadro de diálogo Cal cuando alguien hace clic en un elemento.", + "need_help_embedding": "Necesita ayuda? Consulte nuestras guías para incrustar Cal en Wix, Squarespace o WordPress, consulte nuestras preguntas comunes o explore las opciones avanzadas de incrustación.", + "book_my_cal": "Reservar mi Cal", + "invite_as": "Invitar como", + "form_updated_successfully": "Formulario actualizado con éxito.", + "email_not_cal_member_cta": "Únase a su equipo", + "disable_attendees_confirmation_emails": "Desactivar los correos electrónicos de confirmación predeterminados para los asistentes", + "disable_attendees_confirmation_emails_description": "Al menos un flujo de trabajo está activo en este tipo de evento que envía un correo electrónico a los asistentes cuando se reserva el evento.", + "disable_host_confirmation_emails": "Desactivar los correos electrónicos de confirmación predeterminados para el anfitrión", + "disable_host_confirmation_emails_description": "Al menos un flujo de trabajo está activo en este tipo de evento que envía un correo electrónico al anfitrión cuando se reserva el evento.", + "add_an_override": "Agregar una anulación", + "import_from_google_workspace": "Importar usuarios de Google Workspace", + "connect_google_workspace": "Conectar Google Workspace", + "google_workspace_admin_tooltip": "Debe ser administrador del espacio de trabajo para usar esta función", + "first_event_type_webhook_description": "Cree su primer webhook para este tipo de evento", + "create_for": "Crear para" } diff --git a/apps/web/public/static/locales/ko/common.json b/apps/web/public/static/locales/ko/common.json index 7158e8c1d0..2e2f49bbad 100644 --- a/apps/web/public/static/locales/ko/common.json +++ b/apps/web/public/static/locales/ko/common.json @@ -26,6 +26,8 @@ "rejection_confirmation": "예약 취소", "manage_this_event": "이 이벤트 관리", "invite_team_member": "팀원 초대", + "invite_team_individual_segment": "개인 초대", + "invite_team_bulk_segment": "일괄 가져오기", "invite_team_notifcation_badge": "초대", "your_event_has_been_scheduled": "귀하의 이벤트가 예약되었습니다.", "your_event_has_been_scheduled_recurring": "되풀이 이벤트가 예약되었습니다", @@ -222,6 +224,7 @@ "go_back_login": "로그인 페이지로 돌아가기", "error_during_login": "로그인하는 과정에서 오류가 발생했습니다. 로그인 화면으로 돌아가서 다시 한 번 시도해 보세요.", "request_password_reset": "재설정 이메일 보내기", + "send_invite": "초대장 보내기", "forgot_password": "비밀번호를 잊었을 경우", "forgot": "잊어버리셨나요?", "done": "완료", @@ -237,6 +240,7 @@ "set_availability": "언제 여유가 있는지 설정하세요.", "continue_without_calendar": "캘린더 없이 계속하기", "connect_your_calendar": "캘린더 연결하기", + "connect_your_video_app": "비디오 앱 연결", "connect_your_video_app_instructions": "이벤트 타입에서 사용하기 위한 비디오 앱을 연결해주세요.", "connect_your_calendar_instructions": "바쁜 시간과 새 이벤트 일정을 자동으로 확인할 수 있도록 캘린더 연결", "set_up_later": "나중에 하기", @@ -368,6 +372,7 @@ "create_webhook": "웹훅 만들기", "booking_cancelled": "예약 취소", "booking_rescheduled": "예약 변경", + "recording_ready": "녹화 다운로드 링크 준비됨", "booking_created": "예약 생성", "meeting_ended": "회의 종료됨", "form_submitted": "양식 제출됨", @@ -754,6 +759,10 @@ "new_event_type_to_book_description": "사람들이 시간을 예약할 수 있는 새 이벤트 타입을 만듭니다.", "length": "길이", "minimum_booking_notice": "최소 고지", + "offset_toggle": "오프셋 시작 시간", + "offset_toggle_description": "지정된 시간(분)으로 예약자에게 표시되는 오프셋 시간 슬롯", + "offset_start": "오프셋 기준", + "offset_start_description": "예: 이렇게 하면 예약자에게 {{ adjustedTime }}에 {{ originalTime }} 대신 시간 슬롯이 표시됨", "slot_interval": "시간 슬롯 간격", "slot_interval_default": "이벤트 길이 사용(기본값)", "delete_event_type": "이벤트 타입을 삭제하시겠습니까?", @@ -906,6 +915,7 @@ "duplicate": "복제", "offer_seats": "좌석 제공", "offer_seats_description": "예약에 좌석 제공(게스트를 비활성화하고 예약을 선택함)", + "seats_available_one": "사용 가능한 좌석", "seats_available_other": "사용 가능한 좌석", "number_of_seats": "예약당 좌석 수", "enter_number_of_seats": "좌석 수 입력", @@ -1193,6 +1203,7 @@ "create_workflow": "워크플로를 만듭니다", "do_this": "이렇게 하세요", "turn_off": "끄기", + "turn_on": "켜기", "settings_updated_successfully": "설정이 업데이트되었습니다", "error_updating_settings": "설정 업데이트 중 오류 발생", "personal_cal_url": "내 개인 {{appName}} URL", @@ -1708,6 +1719,7 @@ "switch_weekly": "주간 보기로 전환", "switch_multiday": "일간 보기로 전환", "num_locations": "{{num}}개의 위치 옵션", + "select_on_next_step": "다음 단계에 대해 선택", "this_meeting_has_not_started_yet": "이 회의는 아직 시작되지 않았습니다", "this_app_requires_connected_account": "{{appName}}에 연결된 {{dependencyName}} 계정이 필요합니다", "connect_app": "{{dependencyName}} 연결", @@ -1737,6 +1749,7 @@ "locked_apps_description": "회원은 활성 앱을 볼 수 있지만 앱 설정을 편집할 수는 없습니다", "locked_webhooks_description": "회원은 활성 웹훅을 볼 수 있지만 웹훅 설정을 편집할 수는 없습니다", "locked_workflows_description": "회원은 활성 워크플로를 볼 수 있지만 워크플로 설정을 편집할 수는 없습니다", + "locked_by_admin": "팀 관리자에 의해 잠김", "app_not_connected": "{{appName}} 계정을 연결하지 않았습니다.", "connect_now": "지금 연결", "managed_event_dialog_confirm_button_one": "회원 {{count}}명 바꾸기 및 알림", @@ -1794,15 +1807,34 @@ "seats_and_no_show_fee_error": "현재 좌석을 활성화할 수 없으므로 노쇼 수수료를 부과할 수 없습니다", "complete_your_booking": "예약을 완료하세요", "complete_your_booking_subject": "예약 완료: {{title}} 날짜 {{date}}", + "confirm_your_details": "세부 정보 확인", "currency_string": "{{amount, currency}}", "charge_card_dialog_body": "참석자에게 {{amount, currency}}을 청구하려고 합니다. 계속 진행하시겠습니까?", "charge_attendee": "참석자에게 {{amount, currency}}을 청구합니다.", "payment_app_commission": "결제가 필요합니다 (건당 수수료 {{paymentFeePercentage}}% + {{fee, currency}})", "email_invite_team": "{{email}}이(가) 초대되었습니다", + "email_invite_team_bulk": "사용자 {{userCount}}명 초대됨", + "error_collecting_card": "카드 수집 중 오류 발생", "image_size_limit_exceed": "업로드되는 이미지의 크기는 5MB를 초과하면 안 됩니다.", + "inline_embed": "인라인 임베드", + "load_inline_content": "다른 웹 사이트 콘텐츠와 함께 이벤트 유형을 인라인으로 직접 로드합니다.", + "floating_pop_up_button": "플로팅 팝업 버튼", + "floating_button_trigger_modal": "이벤트 유형으로 모달을 트리거하는 플로팅 버튼을 사이트에 배치합니다.", + "pop_up_element_click": "요소 클릭을 통한 팝업", + "open_dialog_with_element_click": "누군가 요소를 클릭하면 Cal 대화 상자를 엽니다.", "need_help_embedding": "도움이 필요하신가요? Wix, Squarespace, 또는 WordPress에서 Cal을 임베드하는 가이드를 참조하거나, 자주 묻는 질문을 확인하거나, 고급 임베드 옵션을 살펴보세요.", + "book_my_cal": "내 Cal 예약", + "invite_as": "다른 이름으로 초대", + "form_updated_successfully": "양식이 성공적으로 업데이트되었습니다.", + "email_not_cal_member_cta": "팀 합류", "disable_attendees_confirmation_emails": "참석자에 대한 기본 확인 이메일 비활성화", "disable_attendees_confirmation_emails_description": "이 이벤트 유형에는 이벤트가 예약되었을 때 참석자들에게 이메일을 보내는 최소한 하나의 워크플로가 활성화되어 있습니다.", "disable_host_confirmation_emails": "호스트에 대한 기본 확인 이메일 비활성화", - "disable_host_confirmation_emails_description": "이 이벤트 유형에는 이벤트가 예약될 때 호스트에게 이메일을 보내는 최소한 하나의 워크플로가 활성화되어 있습니다." + "disable_host_confirmation_emails_description": "이 이벤트 유형에는 이벤트가 예약될 때 호스트에게 이메일을 보내는 최소한 하나의 워크플로가 활성화되어 있습니다.", + "add_an_override": "재정의 추가", + "import_from_google_workspace": "Google Workspace에서 사용자 가져오기", + "connect_google_workspace": "Google Workspace 연결", + "google_workspace_admin_tooltip": "이 기능을 사용하려면 Workspace 관리자여야 합니다", + "first_event_type_webhook_description": "이 이벤트 유형에 대한 첫 번째 웹훅 만들기", + "create_for": "작성 대상" } diff --git a/apps/web/public/static/locales/pt/common.json b/apps/web/public/static/locales/pt/common.json index b3eb0917ff..3d814a77a5 100644 --- a/apps/web/public/static/locales/pt/common.json +++ b/apps/web/public/static/locales/pt/common.json @@ -26,6 +26,8 @@ "rejection_confirmation": "Rejeitar a reserva", "manage_this_event": "Gerir este evento", "invite_team_member": "Convidar membro da equipa", + "invite_team_individual_segment": "Convidar indivíduo", + "invite_team_bulk_segment": "Importação em conjunto", "invite_team_notifcation_badge": "Conv.", "your_event_has_been_scheduled": "O seu evento foi agendado", "your_event_has_been_scheduled_recurring": "O seu evento recorrente foi agendado", @@ -222,6 +224,7 @@ "go_back_login": "Voltar à página de início de sessão", "error_during_login": "Ocorreu um erro ao iniciar sessão. Volte ao ecrã de início de sessão e tente de novo.", "request_password_reset": "Pedir restauro da palavra-passe", + "send_invite": "Enviar convite", "forgot_password": "Esqueceu a palavra-passe?", "forgot": "Esqueceu-se?", "done": "Concluído", @@ -237,6 +240,8 @@ "set_availability": "Definir disponibilidade", "continue_without_calendar": "Continuar sem calendário", "connect_your_calendar": "Ligar o seu calendário", + "connect_your_video_app": "Associar as suas aplicações de vídeo", + "connect_your_video_app_instructions": "Associe as suas aplicações de vídeo para utilizar as mesmas nos tipos de eventos.", "connect_your_calendar_instructions": "Ligue o seu calendário para verificar automaticamente as horas ocupadas e os novos eventos à medida que são agendados.", "set_up_later": "Configurar mais tarde", "current_time": "Hora atual", @@ -367,6 +372,7 @@ "create_webhook": "Criar Webhook", "booking_cancelled": "Reserva Cancelada", "booking_rescheduled": "Reserva Reagendada", + "recording_ready": "Ligação de transferência da gravação pronta", "booking_created": "Reserva Criada", "meeting_ended": "A reunião terminou", "form_submitted": "Formulário enviado", @@ -465,6 +471,7 @@ "friday": "Sexta-Feira", "saturday": "Sábado", "sunday": "Domingo", + "all_booked_today": "Tudo reservado.", "slots_load_fail": "Não foi possível carregar os horários disponíveis.", "additional_guests": "+ Convidados Adicionais", "your_name": "O seu nome", @@ -752,6 +759,10 @@ "new_event_type_to_book_description": "Crie um novo tipo de evento para as pessoas reservarem uma hora.", "length": "Comprimento", "minimum_booking_notice": "Aviso de mínimo", + "offset_toggle": "Desfasamento dos horários de início", + "offset_toggle_description": "Desfasar janelas horárias por um determinado número de minutos na apresentação das mesmas aos responsáveis pela reserva", + "offset_start": "Desfasamento de", + "offset_start_description": "por exemplo, irá mostrar as janelas horárias aos responsáveis pelas reservas às {{ adjustedTime }} em vez de {{ originalTime }}", "slot_interval": "Intervalos do horário", "slot_interval_default": "Usar duração do evento (por omissão)", "delete_event_type": "Eliminar tipo de evento?", @@ -904,6 +915,7 @@ "duplicate": "Duplicar", "offer_seats": "Oferecer lugares", "offer_seats_description": "Oferecer lugares para reservas (isto desactiva os convidados e confirmações nas reservas)", + "seats_available_one": "Lugar disponível", "seats_available_other": "Lugares disponíveis", "number_of_seats": "Número de lugares por reserva", "enter_number_of_seats": "Digite um número de lugares", @@ -1038,6 +1050,7 @@ "event_cancelled_trigger": "quando o evento for cancelado", "new_event_trigger": "quando um novo evento for reservado", "email_host_action": "enviar email ao anfitrião", + "email_attendee_action": "enviar e-mail aos participantes", "sms_attendee_action": "enviar SMS ao participante", "sms_number_action": "enviar SMS para um número específico", "workflows": "Fluxos de trabalho", @@ -1190,6 +1203,7 @@ "create_workflow": "Criar um fluxo de trabalho", "do_this": "Fazer isto", "turn_off": "Desligar", + "turn_on": "Ativar", "settings_updated_successfully": "Definições atualizadas com sucesso", "error_updating_settings": "Erro ao atualizar as definições", "personal_cal_url": "O meu endereço pessoal do {{appName}}", @@ -1246,6 +1260,7 @@ "calendars_description": "Configure como os tipos de evento devem interagir com os seus calendários", "appearance_description": "Faça a gestão das definições de aparência da sua reserva", "conferencing_description": "Adicione as suas aplicações de videoconferência para reuniões", + "add_conferencing_app": "Adicionar aplicação de conferência", "password_description": "Faça a gestão das definições para as palavras-passe da sua conta", "2fa_description": "Faça a gestão das definições para as palavras-passe da sua conta", "we_just_need_basic_info": "Precisamos apenas de algumas informações básicas para configurar o seu perfil.", @@ -1620,6 +1635,7 @@ "email_user_cta": "Ver convite", "email_no_user_invite_heading": "Recebeu um convite para fazer parte de uma equipa em {{appName}}", "email_no_user_invite_subheading": "Recebeu um convite de {{invitedBy}} para fazer parte da respetiva equipa em {{appName}}. {{appName}} é um ferramenta de conciliação e agendamento de eventos que lhe permite a si e à sua equipa agendar reuniões sem o pingue-pongue de e-mails.", + "email_user_invite_subheading": "Recebeu um convite de {{invitedBy}} para fazer parte da equipa `{{teamName}}` em {{appName}}. {{appName}} é uma ferramenta de conciliação e agendamento de eventos que lhe permite a si e à sua equipa agendar reuniões sem o pingue-pongue de mensagens eletrónicas.", "email_no_user_invite_steps_intro": "Vamos ajudar com alguns pequenos passos para que você e a sua equipa possam desfrutar rapidamente de uma gestão de agendamentos sem complicações.", "email_no_user_step_one": "Escolha o seu nome de utilizador", "email_no_user_step_two": "Associe a sua conta de calendário", @@ -1695,6 +1711,15 @@ "spot_popular_event_types_description": "Veja quais os tipos de eventos que estão a receber mais cliques e reservas", "no_responses_yet": "Ainda sem respostas", "this_will_be_the_placeholder": "Isto será o marcador de posição", + "error_booking_event": "Ocorreu um erro ao reservar o evento. Atualize a página e tente novamente", + "timeslot_missing_title": "Nenhuma janela horária selecionada", + "timeslot_missing_description": "Selecione uma janela horária para reservar o evento.", + "timeslot_missing_cta": "Selecionar janela horária", + "switch_monthly": "Mudar para a vista mensal", + "switch_weekly": "Mudar para a vista semanal", + "switch_multiday": "Mudar para a vista diária", + "num_locations": "{{num}} opções de localização", + "select_on_next_step": "Selecione no próximo passo", "this_meeting_has_not_started_yet": "Esta reunião ainda não começou", "this_app_requires_connected_account": "{{appName}} requer a associação de uma conta {{dependencyName}}", "connect_app": "Associar {{dependencyName}}", @@ -1724,6 +1749,7 @@ "locked_apps_description": "Os membros poderão ver as aplicações ativas, mas não poderão editar quaisquer configurações das aplicações", "locked_webhooks_description": "Os membros poderão ver os webhooks ativos, mas não poderão editar quaisquer configurações dos webhooks", "locked_workflows_description": "Os membros poderão ver os fluxos de trabalho ativos, mas não poderão editar quaisquer configurações dos fluxos de trabalho", + "locked_by_admin": "Bloqueado pelo administrador da equipa", "app_not_connected": "Não associou uma conta {{appName}}.", "connect_now": "Associar agora", "managed_event_dialog_confirm_button_one": "Substituir e notificar {{count}} membro", @@ -1781,5 +1807,34 @@ "seats_and_no_show_fee_error": "Atualmente, não é possível ativar lugares e cobrar uma taxa de não-comparência", "complete_your_booking": "Concluir a sua reserva", "complete_your_booking_subject": "Concluir a sua reserva: {{title}} a {{date}}", - "email_invite_team": "{{email}} foi convidado/a" + "confirm_your_details": "Confirme os seus dados", + "currency_string": "{{amount, currency}}", + "charge_card_dialog_body": "Está em vias de cobrar {{amount, currency}} ao participante. Tem a certeza que pretende continuar?", + "charge_attendee": "Cobrar {{amount, currency}} ao participante", + "payment_app_commission": "Exigir pagamento ({{paymentFeePercentage}}% + {{fee, currency}} de comissão por transação)", + "email_invite_team": "{{email}} foi convidado/a", + "email_invite_team_bulk": "Foram convidados {{userCount}} utilizadores", + "error_collecting_card": "Erro ao recolher o cartão", + "image_size_limit_exceed": "A imagem enviada não deve exceder o limite de tamanho de 5 mb", + "inline_embed": "Incorporação em linha", + "load_inline_content": "Carrega o seu tipo de evento diretamente e em linha, em conjunto com os conteúdos do seu outro site.", + "floating_pop_up_button": "Botão pop-up flutuante", + "floating_button_trigger_modal": "Coloca um botão flutuante no seu site que ativa uma modal com o seu tipo de evento.", + "pop_up_element_click": "Pop-up via clique no elemento", + "open_dialog_with_element_click": "Abra a sua janela do Cal quando alguém clicar num elemento.", + "need_help_embedding": "Precisa de ajuda? Consulte os nossos guias para incorporar o Cal no Wix, Squarespace, ou WordPress. Consulte ainda as nossas perguntas frequentes ou explore opções avançadas de incorporação.", + "book_my_cal": "Reservar o meu Cal", + "invite_as": "Convidar como", + "form_updated_successfully": "Formulário atualizado com sucesso.", + "email_not_cal_member_cta": "Inscreva a sua equipa", + "disable_attendees_confirmation_emails": "Desativar mensagens eletrónicas de confirmação predefinidas para participantes", + "disable_attendees_confirmation_emails_description": "Está ativo pelo menos um fluxo de trabalho neste tipo de evento que envia um e-mail para os participantes quando o evento é reservado.", + "disable_host_confirmation_emails": "Desativar mensagens eletrónicas de confirmação predefinidas para o anfitrião", + "disable_host_confirmation_emails_description": "Está ativo pelo menos um fluxo de trabalho neste tipo de evento que envia um e-mail para o anfitrião quando o evento é reservado.", + "add_an_override": "Adicionar uma sobreposição", + "import_from_google_workspace": "Importar utilizadores do Google Workspace", + "connect_google_workspace": "Associar o Google Workspace", + "google_workspace_admin_tooltip": "Deve ser um Administrador do Workspace para utilizar esta funcionalidade", + "first_event_type_webhook_description": "Crie o seu primeiro webhook para este tipo de evento", + "create_for": "Criar para" } diff --git a/apps/web/public/static/locales/tr/common.json b/apps/web/public/static/locales/tr/common.json index b0112a16b6..eb139781a3 100644 --- a/apps/web/public/static/locales/tr/common.json +++ b/apps/web/public/static/locales/tr/common.json @@ -26,6 +26,8 @@ "rejection_confirmation": "Rezervasyonu reddet", "manage_this_event": "Bu etkinliği yönet", "invite_team_member": "Ekip üyesi davet et", + "invite_team_individual_segment": "Kişiyi davet et", + "invite_team_bulk_segment": "Toplu içe aktarma", "invite_team_notifcation_badge": "Dvt.", "your_event_has_been_scheduled": "Etkinliğiniz planlandı", "your_event_has_been_scheduled_recurring": "Yinelenen etkinliğiniz planlandı", @@ -222,6 +224,7 @@ "go_back_login": "Giriş sayfasına geri dön", "error_during_login": "Giriş yapılırken bir hata oluştu. Giriş ekranına geri dönün ve tekrar deneyin.", "request_password_reset": "Sıfırlama e-postası gönder", + "send_invite": "Davet gönder", "forgot_password": "Şifremi Unuttum", "forgot": "Unuttunuz mu?", "done": "Tamam", @@ -237,6 +240,8 @@ "set_availability": "Müsaitlik durumunuzu ayarlayın", "continue_without_calendar": "Takvim olmadan devam et", "connect_your_calendar": "Takviminizi bağlayın", + "connect_your_video_app": "Video uygulamalarınızı bağlayın", + "connect_your_video_app_instructions": "Etkinlik türlerinizde kullanmak için video uygulamalarınızı bağlayın.", "connect_your_calendar_instructions": "Yeni etkinlikler planlanırken dolu zamanları otomatik olarak kontrol etmek için takviminizi bağlayın.", "set_up_later": "Daha sonra ayarla", "current_time": "Geçerli saat", @@ -367,6 +372,7 @@ "create_webhook": "Web kancası oluştur", "booking_cancelled": "Rezervasyon İptal Edildi", "booking_rescheduled": "Rezervasyon Yeniden Planlandı", + "recording_ready": "Kayıt İndirme Bağlantısı Hazır", "booking_created": "Rezervasyon Oluşturuldu", "meeting_ended": "Toplantı Sona Erdi", "form_submitted": "Form Gönderildi", @@ -465,6 +471,7 @@ "friday": "Cuma", "saturday": "Cumartesi", "sunday": "Pazar", + "all_booked_today": "Tümü rezerve edildi.", "slots_load_fail": "Kullanılabilir zaman aralıkları yüklenemedi.", "additional_guests": "Misafir ekle", "your_name": "Adınız", @@ -1784,6 +1791,12 @@ "confirm_your_details": "Bilgilerinizi onaylayın", "currency_string": "{{amount, currency}}", "email_invite_team": "{{email}} davet edildi", + "need_help_embedding": "Yardıma mı ihtiyacınız var? Cal'ı Wix, Squarespace veya WordPress'e yerleştirmek için kılavuzlarımıza göz atın. Ayrıca Sıkça Sorulan Sorular bölümümüze göz atın veya gelişmiş yerleştirme seçeneklerini keşfedin.", + "book_my_cal": "Cal'ımı rezerve et", "form_updated_successfully": "Form başarıyla güncellendi.", - "disable_attendees_confirmation_emails": "Katılımcılar için varsayılan onay e-postalarını devre dışı bırakın" + "disable_attendees_confirmation_emails": "Katılımcılar için varsayılan onay e-postalarını devre dışı bırakın", + "disable_attendees_confirmation_emails_description": "Bu etkinlik türünde etkinlik rezerve edildiğinde katılımcılara bir e-posta gönderen en az bir iş akışı etkin.", + "disable_host_confirmation_emails": "Organizatörler için varsayılan onay e-postalarını devre dışı bırakın", + "disable_host_confirmation_emails_description": "Bu etkinlik türündeki bir etkinlik rezerve edildiğinde organizatörlere e-posta gönderen en az bir iş akışı etkin.", + "connect_google_workspace": "Google Workspace'i bağlayın" } diff --git a/apps/web/public/static/locales/zh-CN/common.json b/apps/web/public/static/locales/zh-CN/common.json index 0595aa3f5c..b05aa4bff6 100644 --- a/apps/web/public/static/locales/zh-CN/common.json +++ b/apps/web/public/static/locales/zh-CN/common.json @@ -26,6 +26,8 @@ "rejection_confirmation": "拒绝预约", "manage_this_event": "管理此活动", "invite_team_member": "邀请团队成员", + "invite_team_individual_segment": "邀请个人", + "invite_team_bulk_segment": "批量导入", "invite_team_notifcation_badge": "邀请", "your_event_has_been_scheduled": "您的活动已预约", "your_event_has_been_scheduled_recurring": "您的定期活动已安排", @@ -222,6 +224,7 @@ "go_back_login": "返回登录页面", "error_during_login": "登录时发生错误,请返回登录界面,然后重试。", "request_password_reset": "请求重置电子邮件", + "send_invite": "发送邀请", "forgot_password": "忘记密码?", "forgot": "忘记了?", "done": "完成", @@ -237,6 +240,7 @@ "set_availability": "设置您的可预约状态", "continue_without_calendar": "无日历继续", "connect_your_calendar": "连接您的日历", + "connect_your_video_app": "连接您的视频应用", "connect_your_calendar_instructions": "连接您的日历以自动检查您繁忙的时间和同步新活动的预约。", "set_up_later": "稍后设置", "current_time": "当前时间", From 8e7080fc96ca64d37ce0039d1b0f5df87c2cfb5f Mon Sep 17 00:00:00 2001 From: zomars Date: Mon, 29 May 2023 19:05:34 -0700 Subject: [PATCH 023/100] Fix logout test URL discrepancy --- .github/workflows/env-create-file.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/env-create-file.yml b/.github/workflows/env-create-file.yml index dadab15de9..00b229c6da 100644 --- a/.github/workflows/env-create-file.yml +++ b/.github/workflows/env-create-file.yml @@ -20,7 +20,7 @@ env: INPUT_ENV_PAYMENT_FEE_FIXED: 10 INPUT_ENV_SAML_DATABASE_URL: postgresql://postgres:@localhost:5432/calendso INPUT_ENV_SAML_ADMINS: pro@example.com - INPUT_ENV_NEXTAUTH_URL: http://127.0.0.1:3000/api/auth + INPUT_ENV_NEXTAUTH_URL: http://localhost:3000 INPUT_ENV_NEXT_PUBLIC_IS_E2E: 1 # INPUT_ENV_EMAIL_FROM: e2e@cal.com # INPUT_ENV_EMAIL_SERVER_HOST: ${{ secrets.CI_EMAIL_SERVER_HOST }} From 1065108a42c26488ebf10b1e3757681336dfb0a0 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 02:06:22 +0000 Subject: [PATCH 024/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/zh-CN/common.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/apps/web/public/static/locales/zh-CN/common.json b/apps/web/public/static/locales/zh-CN/common.json index b05aa4bff6..b8f0d4f62b 100644 --- a/apps/web/public/static/locales/zh-CN/common.json +++ b/apps/web/public/static/locales/zh-CN/common.json @@ -241,6 +241,7 @@ "continue_without_calendar": "无日历继续", "connect_your_calendar": "连接您的日历", "connect_your_video_app": "连接您的视频应用", + "connect_your_video_app_instructions": "连接您的视频应用,以将它们用于您的活动类型。", "connect_your_calendar_instructions": "连接您的日历以自动检查您繁忙的时间和同步新活动的预约。", "set_up_later": "稍后设置", "current_time": "当前时间", @@ -1703,6 +1704,11 @@ "spot_popular_event_types_description": "查看获得最多点击和预约的活动类型", "no_responses_yet": "尚无回复", "this_will_be_the_placeholder": "这将是占位符", + "switch_monthly": "切换到每月视图", + "switch_weekly": "切换到每周视图", + "switch_multiday": "切换到日视图", + "num_locations": "{{num}} 个位置选项", + "select_on_next_step": "在下一步选择", "this_meeting_has_not_started_yet": "此会议尚未开始", "this_app_requires_connected_account": "{{appName}} 需要已连接的 {{dependencyName}} 账户", "connect_app": "连接 {{dependencyName}}", @@ -1790,12 +1796,21 @@ "seats_and_no_show_fee_error": "当前无法启用位置和收取失约费", "complete_your_booking": "完成您的预约", "complete_your_booking_subject": "完成您的预约: {{date}} 的 {{title}}", + "confirm_your_details": "确认您的详细信息", + "currency_string": "{{amount, currency}}", "email_invite_team": "{{email}} 已被邀请", + "book_my_cal": "预约我的 Cal", + "invite_as": "邀请为", + "form_updated_successfully": "表单更新成功。", + "email_not_cal_member_cta": "加入您的团队", "disable_attendees_confirmation_emails": "禁用参与者的默认确认电子邮件", "disable_attendees_confirmation_emails_description": "该活动类型中至少有一个工作流程处于活动状态,当该活动被预约时,将向参与者发送电子邮件。", "disable_host_confirmation_emails": "禁用主持人的默认确认电子邮件", "disable_host_confirmation_emails_description": "该活动类型中至少有一个工作流程处于活动状态,当该活动被预约时,将向主持人发送电子邮件。", "add_an_override": "添加替代", + "import_from_google_workspace": "从 Google Workspace 导入用户", + "connect_google_workspace": "连接 Google Workspace", + "google_workspace_admin_tooltip": "您必须是工作区管理员才能使用此功能", "first_event_type_webhook_description": "为此活动类型创建第一个 Webhook", "create_for": "创建" } From 0ed5ce229befc8cb3dd620640b029d4b6c6da134 Mon Sep 17 00:00:00 2001 From: zomars Date: Mon, 29 May 2023 19:44:20 -0700 Subject: [PATCH 025/100] Prevent flooding logs when no logo is available --- apps/web/pages/api/logo.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/apps/web/pages/api/logo.ts b/apps/web/pages/api/logo.ts index cece787251..00af5dba8d 100644 --- a/apps/web/pages/api/logo.ts +++ b/apps/web/pages/api/logo.ts @@ -79,10 +79,15 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) const filteredLogo = parsedQuery?.icon ? appIconLogo : appLogo; - const response = await fetch(filteredLogo); - const arrayBuffer = await response.arrayBuffer(); - const buffer = Buffer.from(arrayBuffer); - res.setHeader("Content-Type", response.headers.get("content-type") as string); - res.setHeader("Cache-Control", "s-maxage=86400"); - res.send(buffer); + try { + const response = await fetch(filteredLogo); + const arrayBuffer = await response.arrayBuffer(); + const buffer = Buffer.from(arrayBuffer); + res.setHeader("Content-Type", response.headers.get("content-type") as string); + res.setHeader("Cache-Control", "s-maxage=86400"); + res.send(buffer); + } catch (error) { + res.statusCode = 404; + res.json({ error: "Failed fetching logo" }); + } } From 67bb4cf5ca94d584315925bc20651686c44d48e0 Mon Sep 17 00:00:00 2001 From: zomars Date: Mon, 29 May 2023 20:12:07 -0700 Subject: [PATCH 026/100] Skip flaky tests for now --- apps/web/playwright/booking-seats.e2e.ts | 116 +++++++++++------------ 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/apps/web/playwright/booking-seats.e2e.ts b/apps/web/playwright/booking-seats.e2e.ts index 723c7866ad..f4ae4bb2e4 100644 --- a/apps/web/playwright/booking-seats.e2e.ts +++ b/apps/web/playwright/booking-seats.e2e.ts @@ -154,67 +154,67 @@ testBothBookers.describe("Booking with Seats", (bookerVariant) => { expect(oldBooking?.seatsReferences.length).toBe(2); }); - test("Should reschedule booking with seats and if everyone rescheduled it should be deleted", async ({ - page, - users, - bookings, - }) => { - const { booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [ - { name: "John First", email: "first+seats@cal.com", timeZone: "Europe/Berlin" }, - { name: "Jane Second", email: "second+seats@cal.com", timeZone: "Europe/Berlin" }, - ]); + // FIXME: https://github.com/calcom/cal.com/issues/9193 + test.fixme( + "Should reschedule booking with seats and if everyone rescheduled it should be deleted", + async ({ page, users, bookings }) => { + const { booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [ + { name: "John First", email: "first+seats@cal.com", timeZone: "Europe/Berlin" }, + { name: "Jane Second", email: "second+seats@cal.com", timeZone: "Europe/Berlin" }, + ]); - const bookingAttendees = await prisma.attendee.findMany({ - where: { bookingId: booking.id }, - select: { - id: true, - }, - }); - - const bookingSeats = [ - { bookingId: booking.id, attendeeId: bookingAttendees[0].id, referenceUid: uuidv4() }, - { bookingId: booking.id, attendeeId: bookingAttendees[1].id, referenceUid: uuidv4() }, - ]; - - await prisma.bookingSeat.createMany({ - data: bookingSeats, - }); - - const references = await prisma.bookingSeat.findMany({ - where: { bookingId: booking.id }, - }); - - await page.goto(`/reschedule/${references[0].referenceUid}`); - - await selectFirstAvailableTimeSlotNextMonth(page); - - await page.locator('[data-testid="confirm-reschedule-button"]').click(); - - await page.waitForURL(/.*booking/); - - await page.goto(`/reschedule/${references[1].referenceUid}`); - - await selectFirstAvailableTimeSlotNextMonth(page); - - await page.locator('[data-testid="confirm-reschedule-button"]').click(); - - // Using waitForUrl here fails the assertion `expect(oldBooking?.status).toBe(BookingStatus.CANCELLED);` probably because waitForUrl is considered complete before waitForNavigation and till that time the booking is not cancelled - await page.waitForNavigation({ url: /.*booking/ }); - - // Should expect old booking to be cancelled - const oldBooking = await prisma.booking.findFirst({ - where: { uid: booking.uid }, - include: { - seatsReferences: true, - attendees: true, - eventType: { - include: { users: true, hosts: true }, + const bookingAttendees = await prisma.attendee.findMany({ + where: { bookingId: booking.id }, + select: { + id: true, }, - }, - }); + }); - expect(oldBooking?.status).toBe(BookingStatus.CANCELLED); - }); + const bookingSeats = [ + { bookingId: booking.id, attendeeId: bookingAttendees[0].id, referenceUid: uuidv4() }, + { bookingId: booking.id, attendeeId: bookingAttendees[1].id, referenceUid: uuidv4() }, + ]; + + await prisma.bookingSeat.createMany({ + data: bookingSeats, + }); + + const references = await prisma.bookingSeat.findMany({ + where: { bookingId: booking.id }, + }); + + await page.goto(`/reschedule/${references[0].referenceUid}`); + + await selectFirstAvailableTimeSlotNextMonth(page); + + await page.locator('[data-testid="confirm-reschedule-button"]').click(); + + await page.waitForURL(/.*booking/); + + await page.goto(`/reschedule/${references[1].referenceUid}`); + + await selectFirstAvailableTimeSlotNextMonth(page); + + await page.locator('[data-testid="confirm-reschedule-button"]').click(); + + // Using waitForUrl here fails the assertion `expect(oldBooking?.status).toBe(BookingStatus.CANCELLED);` probably because waitForUrl is considered complete before waitForNavigation and till that time the booking is not cancelled + await page.waitForNavigation({ url: /.*booking/ }); + + // Should expect old booking to be cancelled + const oldBooking = await prisma.booking.findFirst({ + where: { uid: booking.uid }, + include: { + seatsReferences: true, + attendees: true, + eventType: { + include: { users: true, hosts: true }, + }, + }, + }); + + expect(oldBooking?.status).toBe(BookingStatus.CANCELLED); + } + ); test("Should cancel with seats and have no attendees and cancelled", async ({ page, From 4c854e00ca1a4fabd7d71b01ad98bfe97a5ba448 Mon Sep 17 00:00:00 2001 From: zomars Date: Mon, 29 May 2023 20:12:17 -0700 Subject: [PATCH 027/100] Fix tests flakyness --- apps/web/playwright/auth/delete-account.e2e.ts | 1 + apps/web/playwright/auth/forgot-password.e2e.ts | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/web/playwright/auth/delete-account.e2e.ts b/apps/web/playwright/auth/delete-account.e2e.ts index 73df266ac7..57d2b23a7f 100644 --- a/apps/web/playwright/auth/delete-account.e2e.ts +++ b/apps/web/playwright/auth/delete-account.e2e.ts @@ -13,6 +13,7 @@ test("Can delete user account", async ({ page, users }) => { await page.waitForSelector("[data-testid=dashboard-shell]"); await page.goto(`/settings/my-account/profile`); + await page.waitForLoadState("networkidle"); await page.click("[data-testid=delete-account]"); if (!user.username) throw Error(`Test user doesn't have a username`); diff --git a/apps/web/playwright/auth/forgot-password.e2e.ts b/apps/web/playwright/auth/forgot-password.e2e.ts index ead9e4e9da..e8d3eb224f 100644 --- a/apps/web/playwright/auth/forgot-password.e2e.ts +++ b/apps/web/playwright/auth/forgot-password.e2e.ts @@ -29,9 +29,7 @@ test("Can reset forgotten password", async ({ page, users }) => { // Click text=Submit await page.click('button[type="submit"]'); - await page.waitForSelector("text=Password updated", { - timeout: 3000, - }); + await page.waitForSelector("text=Password updated"); await expect(page.locator(`text=Password updated`)).toBeVisible(); // Click button:has-text("Login") From 6faa9c0b580d187417286b033f9fc9039b548c2a Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 03:13:26 +0000 Subject: [PATCH 028/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/zh-CN/common.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/public/static/locales/zh-CN/common.json b/apps/web/public/static/locales/zh-CN/common.json index b8f0d4f62b..76ddd66252 100644 --- a/apps/web/public/static/locales/zh-CN/common.json +++ b/apps/web/public/static/locales/zh-CN/common.json @@ -1810,7 +1810,7 @@ "add_an_override": "添加替代", "import_from_google_workspace": "从 Google Workspace 导入用户", "connect_google_workspace": "连接 Google Workspace", - "google_workspace_admin_tooltip": "您必须是工作区管理员才能使用此功能", + "google_workspace_admin_tooltip": "您必须是 Workspace 管理员才能使用此功能", "first_event_type_webhook_description": "为此活动类型创建第一个 Webhook", "create_for": "创建" } From d3ed637387b662009c266460593bb54e4e311d21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Efra=C3=ADn=20Roch=C3=ADn?= Date: Mon, 29 May 2023 20:29:07 -0700 Subject: [PATCH 029/100] remove cold starts log (#9137) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: alannnc Co-authored-by: Bailey Pumfleet Co-authored-by: Peer Richelsen Co-authored-by: Omar López --- apps/web/middleware.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/apps/web/middleware.ts b/apps/web/middleware.ts index 2d4cb61622..f9842960e0 100644 --- a/apps/web/middleware.ts +++ b/apps/web/middleware.ts @@ -7,16 +7,10 @@ import { CONSOLE_URL, WEBAPP_URL, WEBSITE_URL } from "@calcom/lib/constants"; import { isIpInBanlist } from "@calcom/lib/getIP"; import { extendEventData, nextCollectBasicSettings } from "@calcom/lib/telemetry"; -let cold = true; - const middleware: NextMiddleware = async (req) => { const url = req.nextUrl; const requestHeaders = new Headers(req.headers); - // This console.log is required to create a report in axios for hot and cold requests - console.log(cold ? "Cold Start" : "Hot Start"); - requestHeaders.set("x-cal-cold-start", cold ? "true" : "false"); - cold = false; if (!url.pathname.startsWith("/api")) { // // NOTE: When tRPC hits an error a 500 is returned, when this is received From dd94653a489efca80025c05d35a37bd884d078c0 Mon Sep 17 00:00:00 2001 From: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> Date: Tue, 30 May 2023 08:59:28 +0530 Subject: [PATCH 030/100] fix: confirm button not displayed (#9181) * fix: confirm button not displayed Signed-off-by: Udit Takkar * fix: use paymentAppData Signed-off-by: Udit Takkar --------- Signed-off-by: Udit Takkar Co-authored-by: Peer Richelsen --- apps/web/components/booking/BookingListItem.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/web/components/booking/BookingListItem.tsx b/apps/web/components/booking/BookingListItem.tsx index 3dc01a2dcb..d15741b516 100644 --- a/apps/web/components/booking/BookingListItem.tsx +++ b/apps/web/components/booking/BookingListItem.tsx @@ -123,7 +123,8 @@ function BookingListItem(booking: BookingItemProps) { disabled: mutation.isLoading, }, // For bookings with payment, only confirm if the booking is paid for - ...((isPending && !booking?.eventType?.price) || (!!booking?.eventType?.price && booking.paid) + ...((isPending && !paymentAppData.enabled) || + (paymentAppData.enabled && !!paymentAppData.price && booking.paid) ? [ { id: "confirm", From d5746ed277b67eb4e1f99e6a1764fd6ad42334f5 Mon Sep 17 00:00:00 2001 From: Hariom Balhara Date: Tue, 30 May 2023 09:00:02 +0530 Subject: [PATCH 031/100] Make trackingId begin with GTM- always (#8937) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Co-authored-by: Omar López --- packages/app-store/gtm/config.json | 2 +- packages/app-store/gtm/zod.ts | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/app-store/gtm/config.json b/packages/app-store/gtm/config.json index c691e6f7ef..b2faf7243d 100644 --- a/packages/app-store/gtm/config.json +++ b/packages/app-store/gtm/config.json @@ -14,7 +14,7 @@ "tag": { "scripts": [ { - "content": "(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-{TRACKING_ID}');" + "content": "(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','{TRACKING_ID}');" } ] } diff --git a/packages/app-store/gtm/zod.ts b/packages/app-store/gtm/zod.ts index 6f45d901cc..297950930c 100644 --- a/packages/app-store/gtm/zod.ts +++ b/packages/app-store/gtm/zod.ts @@ -4,7 +4,12 @@ import { eventTypeAppCardZod } from "@calcom/app-store/eventTypeAppCardZod"; export const appDataSchema = eventTypeAppCardZod.merge( z.object({ - trackingId: z.string(), + trackingId: z.string().transform((val) => { + let trackingId = val.trim(); + // Ensure that trackingId is transformed if needed to begin with "GTM-" always + trackingId = !trackingId.startsWith("GTM-") ? `GTM-${trackingId}` : trackingId; + return trackingId; + }), }) ); From 8922981012687a3de92e23a560a296389bc19c7e Mon Sep 17 00:00:00 2001 From: Hariom Balhara Date: Tue, 30 May 2023 09:00:52 +0530 Subject: [PATCH 032/100] fix: location for `@calcom/embed-react` types (#9090) * Use correct location for types * Release packages * Update versions --------- Co-authored-by: Peer Richelsen --- apps/web/CHANGELOG.md | 18 ++++++++++++++++++ packages/embeds/embed-core/CHANGELOG.md | 12 ++++++++++++ packages/embeds/embed-core/package.json | 2 +- packages/embeds/embed-react/CHANGELOG.md | 21 +++++++++++++++++++++ packages/embeds/embed-react/package.json | 4 ++-- packages/embeds/embed-snippet/CHANGELOG.md | 15 +++++++++++++++ packages/embeds/embed-snippet/package.json | 2 +- 7 files changed, 70 insertions(+), 4 deletions(-) diff --git a/apps/web/CHANGELOG.md b/apps/web/CHANGELOG.md index c4c7804863..795250d0df 100644 --- a/apps/web/CHANGELOG.md +++ b/apps/web/CHANGELOG.md @@ -1,5 +1,23 @@ # @calcom/web +## 2.9.4 + +### Patch Changes + +- Updated dependencies + - @calcom/embed-snippet@1.0.9 + - @calcom/embed-react@1.1.1 + - @calcom/embed-core@1.2.1 + +## 2.9.3 + +### Patch Changes + +- Updated dependencies + - @calcom/embed-react@1.1.0 + - @calcom/embed-core@1.2.0 + - @calcom/embed-snippet@1.0.8 + ## 2.7.16 ### Patch Changes diff --git a/packages/embeds/embed-core/CHANGELOG.md b/packages/embeds/embed-core/CHANGELOG.md index 2055b3019b..e01551960c 100644 --- a/packages/embeds/embed-core/CHANGELOG.md +++ b/packages/embeds/embed-core/CHANGELOG.md @@ -1,5 +1,17 @@ # @calcom/embed-core +## 1.2.1 + +### Patch Changes + +- Fix the build for embed-react + +## 1.2.0 + +### Minor Changes + +- Fix missing types for @calcom/embed-react. Also, release support for floatingButton config parameter. Though the support is available using embed.js already, for users using getCalApi the TypeScript types would report that config isn't supported. + ## 1.1.5 ### Patch Changes diff --git a/packages/embeds/embed-core/package.json b/packages/embeds/embed-core/package.json index d182a37faa..002962fab3 100644 --- a/packages/embeds/embed-core/package.json +++ b/packages/embeds/embed-core/package.json @@ -1,6 +1,6 @@ { "name": "@calcom/embed-core", - "version": "1.1.5", + "version": "1.2.1", "description": "This is the vanilla JS core script that embeds Cal Link", "main": "./dist/embed/embed.js", "types": "./dist/index.d.ts", diff --git a/packages/embeds/embed-react/CHANGELOG.md b/packages/embeds/embed-react/CHANGELOG.md index 161790a99a..3f7e69a25d 100644 --- a/packages/embeds/embed-react/CHANGELOG.md +++ b/packages/embeds/embed-react/CHANGELOG.md @@ -1,5 +1,26 @@ # @calcom/embed-react +## 1.1.1 + +### Patch Changes + +- Fix the build for embed-react +- Updated dependencies + - @calcom/embed-snippet@1.0.9 + - @calcom/embed-core@1.2.1 + +## 1.1.0 + +### Minor Changes + +- Fix missing types for @calcom/embed-react. Also, release support for floatingButton config parameter. Though the support is available using embed.js already, for users using getCalApi the TypeScript types would report that config isn't supported. + +### Patch Changes + +- Updated dependencies + - @calcom/embed-core@1.2.0 + - @calcom/embed-snippet@1.0.8 + ## 1.0.12 ### Patch Changes diff --git a/packages/embeds/embed-react/package.json b/packages/embeds/embed-react/package.json index 6424ed38c1..6703ae71b5 100644 --- a/packages/embeds/embed-react/package.json +++ b/packages/embeds/embed-react/package.json @@ -1,7 +1,7 @@ { "name": "@calcom/embed-react", "sideEffects": false, - "version": "1.0.12", + "version": "1.1.1", "description": "Embed Cal Link as a React Component", "license": "SEE LICENSE IN LICENSE", "repository": { @@ -27,7 +27,7 @@ }, "main": "./dist/Cal.umd.js", "module": "./dist/Cal.es.js", - "types": "./dist/index.d.ts", + "types": "./dist/embed-react/src/index.d.ts", "peerDependencies": { "react": "^18.2.0", "react-dom": "^18.2.0" diff --git a/packages/embeds/embed-snippet/CHANGELOG.md b/packages/embeds/embed-snippet/CHANGELOG.md index c43c154aaf..ff1fa62708 100644 --- a/packages/embeds/embed-snippet/CHANGELOG.md +++ b/packages/embeds/embed-snippet/CHANGELOG.md @@ -1,5 +1,20 @@ # @calcom/embed-snippet +## 1.0.9 + +### Patch Changes + +- Fix the build for embed-react +- Updated dependencies + - @calcom/embed-core@1.2.1 + +## 1.0.8 + +### Patch Changes + +- Updated dependencies + - @calcom/embed-core@1.2.0 + ## 1.0.7 ### Patch Changes diff --git a/packages/embeds/embed-snippet/package.json b/packages/embeds/embed-snippet/package.json index 61ed67a5f4..10e944325a 100644 --- a/packages/embeds/embed-snippet/package.json +++ b/packages/embeds/embed-snippet/package.json @@ -1,7 +1,7 @@ { "name": "@calcom/embed-snippet", "sideEffects": false, - "version": "1.0.7", + "version": "1.0.9", "main": "./dist/snippet.umd.js", "module": "./dist/snippet.es.js", "description": "Vanilla JS embed snippet that is responsible to fetch @calcom/embed-core and thus show Cal Link as an embed on a page.", From 04ff5f78a9301596cba3753c334745cdd8d40910 Mon Sep 17 00:00:00 2001 From: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> Date: Tue, 30 May 2023 09:01:55 +0530 Subject: [PATCH 033/100] fix: upgrade btn bug (#9104) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: upgrade btn bug Signed-off-by: Udit Takkar * fix: use border-subtle Signed-off-by: Udit Takkar --------- Signed-off-by: Udit Takkar Co-authored-by: Peer Richelsen Co-authored-by: Omar López --- .../ee/video/ViewRecordingsDialog.tsx | 20 ++++++------ .../components/UpgradeRecordingBanner.tsx | 31 ------------------- 2 files changed, 10 insertions(+), 41 deletions(-) delete mode 100644 packages/features/ee/video/components/UpgradeRecordingBanner.tsx diff --git a/packages/features/ee/video/ViewRecordingsDialog.tsx b/packages/features/ee/video/ViewRecordingsDialog.tsx index 15f14556f1..74563b35fd 100644 --- a/packages/features/ee/video/ViewRecordingsDialog.tsx +++ b/packages/features/ee/video/ViewRecordingsDialog.tsx @@ -1,3 +1,4 @@ +import { useRouter } from "next/navigation"; import { useState, Suspense } from "react"; import dayjs from "@calcom/dayjs"; @@ -8,14 +9,7 @@ import type { RecordingItemSchema } from "@calcom/prisma/zod-utils"; import type { RouterOutputs } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react"; import type { PartialReference } from "@calcom/types/EventManager"; -import { - Dialog, - DialogClose, - DialogContent, - DialogFooter, - DialogHeader, - UpgradeTeamsBadge, -} from "@calcom/ui"; +import { Dialog, DialogClose, DialogContent, DialogFooter, DialogHeader } from "@calcom/ui"; import { Button } from "@calcom/ui"; import { Download } from "@calcom/ui/components/icon"; @@ -101,6 +95,7 @@ const useRecordingDownload = () => { const ViewRecordingsList = ({ roomName, hasTeamPlan }: { roomName: string; hasTeamPlan: boolean }) => { const { t } = useLocale(); const { setRecordingId, isFetching, recordingId } = useRecordingDownload(); + const router = useRouter(); const { data: recordings } = trpc.viewer.getCalVideoRecordings.useQuery( { roomName }, @@ -121,7 +116,7 @@ const ViewRecordingsList = ({ roomName, hasTeamPlan }: { roomName: string; hasTe {recordings.data.map((recording: RecordingItemSchema, index: number) => { return (

@@ -138,7 +133,12 @@ const ViewRecordingsList = ({ roomName, hasTeamPlan }: { roomName: string; hasTe {t("download")} ) : ( - + )}

); diff --git a/packages/features/ee/video/components/UpgradeRecordingBanner.tsx b/packages/features/ee/video/components/UpgradeRecordingBanner.tsx deleted file mode 100644 index 83ac8d5100..0000000000 --- a/packages/features/ee/video/components/UpgradeRecordingBanner.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { useRouter } from "next/router"; - -import { WEBAPP_URL } from "@calcom/lib/constants"; -import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { Button } from "@calcom/ui"; -import { Users } from "@calcom/ui/components/icon"; - -export default function UpgradeRecordingBanner() { - const { t } = useLocale(); - const router = useRouter(); - - return ( -
- -
-
-

{t("upgrade_to_access_recordings_title")}

-

{t("upgrade_to_access_recordings_description")}

-
-
- -
-
-
- ); -} From feb31fae6e5aed7f484bb01d8b6e8dadb1461795 Mon Sep 17 00:00:00 2001 From: zomars Date: Mon, 29 May 2023 20:40:03 -0700 Subject: [PATCH 034/100] Update action.yml --- .github/actions/yarn-playwright-install/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/yarn-playwright-install/action.yml b/.github/actions/yarn-playwright-install/action.yml index 65a093bfe2..1e118e3099 100644 --- a/.github/actions/yarn-playwright-install/action.yml +++ b/.github/actions/yarn-playwright-install/action.yml @@ -5,7 +5,7 @@ runs: steps: - name: Cache playwright binaries id: playwright-cache - uses: actions/cache@v2 + uses: buildjet/cache@v2 with: path: | ~/Library/Caches/ms-playwright From 9b9defc0f1ae17faa3e869aee49b5e55e9db85bd Mon Sep 17 00:00:00 2001 From: Alex van Andel Date: Tue, 30 May 2023 15:52:07 +0200 Subject: [PATCH 035/100] ci: Fix fetch() error, improvements to booking-seats test (#9203) --- apps/web/playwright/booking-seats.e2e.ts | 645 +++++++++--------- .../playwright/embed-code-generator.e2e.ts | 2 +- apps/web/playwright/login.e2e.ts | 4 +- playwright.config.ts | 7 +- 4 files changed, 326 insertions(+), 332 deletions(-) diff --git a/apps/web/playwright/booking-seats.e2e.ts b/apps/web/playwright/booking-seats.e2e.ts index f4ae4bb2e4..6cb8918e0e 100644 --- a/apps/web/playwright/booking-seats.e2e.ts +++ b/apps/web/playwright/booking-seats.e2e.ts @@ -99,372 +99,367 @@ testBothBookers.describe("Booking with Seats", (bookerVariant) => { // todo("Attendee #1 should be able to reschedule his booking"); // TODO: Make E2E test: All attendees canceling should delete the booking for the User // todo("All attendees canceling should delete the booking for the User"); +}); - testBothBookers.describe("Reschedule for booking with seats", () => { - test("Should reschedule booking with seats", async ({ page, users, bookings }) => { - const { booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [ - { name: "John First", email: "first+seats@cal.com", timeZone: "Europe/Berlin" }, - { name: "Jane Second", email: "second+seats@cal.com", timeZone: "Europe/Berlin" }, - { name: "John Third", email: "third+seats@cal.com", timeZone: "Europe/Berlin" }, - ]); - const bookingAttendees = await prisma.attendee.findMany({ - where: { bookingId: booking.id }, - select: { - id: true, - }, - }); - - const bookingSeats = [ - { bookingId: booking.id, attendeeId: bookingAttendees[0].id, referenceUid: uuidv4() }, - { bookingId: booking.id, attendeeId: bookingAttendees[1].id, referenceUid: uuidv4() }, - { bookingId: booking.id, attendeeId: bookingAttendees[2].id, referenceUid: uuidv4() }, - ]; - - await prisma.bookingSeat.createMany({ - data: bookingSeats, - }); - - const references = await prisma.bookingSeat.findMany({ - where: { bookingId: booking.id }, - }); - - await page.goto(`/reschedule/${references[2].referenceUid}`); - - await selectFirstAvailableTimeSlotNextMonth(page); - - // expect input to be filled with attendee number 3 data - const thirdAttendeeElement = await page.locator("input[name=name]"); - const attendeeName = await thirdAttendeeElement.inputValue(); - expect(attendeeName).toBe("John Third"); - - await page.locator('[data-testid="confirm-reschedule-button"]').click(); - - await page.waitForLoadState("networkidle"); - - await expect(page).toHaveURL(/.*booking/); - - // Should expect old booking to be accepted with two attendees - const oldBooking = await prisma.booking.findFirst({ - where: { uid: booking.uid }, - include: { seatsReferences: true, attendees: true }, - }); - - expect(oldBooking?.status).toBe(BookingStatus.ACCEPTED); - expect(oldBooking?.attendees.length).toBe(2); - expect(oldBooking?.seatsReferences.length).toBe(2); +testBothBookers.describe("Reschedule for booking with seats", () => { + test("Should reschedule booking with seats", async ({ page, users, bookings }) => { + const { booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [ + { name: "John First", email: "first+seats@cal.com", timeZone: "Europe/Berlin" }, + { name: "Jane Second", email: "second+seats@cal.com", timeZone: "Europe/Berlin" }, + { name: "John Third", email: "third+seats@cal.com", timeZone: "Europe/Berlin" }, + ]); + const bookingAttendees = await prisma.attendee.findMany({ + where: { bookingId: booking.id }, + select: { + id: true, + }, }); - // FIXME: https://github.com/calcom/cal.com/issues/9193 - test.fixme( - "Should reschedule booking with seats and if everyone rescheduled it should be deleted", - async ({ page, users, bookings }) => { - const { booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [ - { name: "John First", email: "first+seats@cal.com", timeZone: "Europe/Berlin" }, - { name: "Jane Second", email: "second+seats@cal.com", timeZone: "Europe/Berlin" }, - ]); + const bookingSeats = [ + { bookingId: booking.id, attendeeId: bookingAttendees[0].id, referenceUid: uuidv4() }, + { bookingId: booking.id, attendeeId: bookingAttendees[1].id, referenceUid: uuidv4() }, + { bookingId: booking.id, attendeeId: bookingAttendees[2].id, referenceUid: uuidv4() }, + ]; - const bookingAttendees = await prisma.attendee.findMany({ - where: { bookingId: booking.id }, - select: { - id: true, - }, - }); + await prisma.bookingSeat.createMany({ + data: bookingSeats, + }); - const bookingSeats = [ - { bookingId: booking.id, attendeeId: bookingAttendees[0].id, referenceUid: uuidv4() }, - { bookingId: booking.id, attendeeId: bookingAttendees[1].id, referenceUid: uuidv4() }, - ]; + const references = await prisma.bookingSeat.findMany({ + where: { bookingId: booking.id }, + }); - await prisma.bookingSeat.createMany({ - data: bookingSeats, - }); + await page.goto(`/reschedule/${references[2].referenceUid}`); - const references = await prisma.bookingSeat.findMany({ - where: { bookingId: booking.id }, - }); + await selectFirstAvailableTimeSlotNextMonth(page); - await page.goto(`/reschedule/${references[0].referenceUid}`); + // expect input to be filled with attendee number 3 data + const thirdAttendeeElement = await page.locator("input[name=name]"); + const attendeeName = await thirdAttendeeElement.inputValue(); + expect(attendeeName).toBe("John Third"); - await selectFirstAvailableTimeSlotNextMonth(page); + await page.locator('[data-testid="confirm-reschedule-button"]').click(); - await page.locator('[data-testid="confirm-reschedule-button"]').click(); + await page.waitForLoadState("networkidle"); - await page.waitForURL(/.*booking/); + await expect(page).toHaveURL(/.*booking/); - await page.goto(`/reschedule/${references[1].referenceUid}`); + // Should expect old booking to be accepted with two attendees + const oldBooking = await prisma.booking.findFirst({ + where: { uid: booking.uid }, + include: { seatsReferences: true, attendees: true }, + }); - await selectFirstAvailableTimeSlotNextMonth(page); + expect(oldBooking?.status).toBe(BookingStatus.ACCEPTED); + expect(oldBooking?.attendees.length).toBe(2); + expect(oldBooking?.seatsReferences.length).toBe(2); + }); - await page.locator('[data-testid="confirm-reschedule-button"]').click(); + test("Should reschedule booking with seats and if everyone rescheduled it should be deleted", async ({ + page, + users, + bookings, + }) => { + const { booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [ + { name: "John First", email: "first+seats@cal.com", timeZone: "Europe/Berlin" }, + { name: "Jane Second", email: "second+seats@cal.com", timeZone: "Europe/Berlin" }, + ]); - // Using waitForUrl here fails the assertion `expect(oldBooking?.status).toBe(BookingStatus.CANCELLED);` probably because waitForUrl is considered complete before waitForNavigation and till that time the booking is not cancelled - await page.waitForNavigation({ url: /.*booking/ }); + const bookingAttendees = await prisma.attendee.findMany({ + where: { bookingId: booking.id }, + select: { + id: true, + }, + }); - // Should expect old booking to be cancelled - const oldBooking = await prisma.booking.findFirst({ - where: { uid: booking.uid }, - include: { - seatsReferences: true, - attendees: true, - eventType: { - include: { users: true, hosts: true }, - }, - }, - }); + const bookingSeats = [ + { bookingId: booking.id, attendeeId: bookingAttendees[0].id, referenceUid: uuidv4() }, + { bookingId: booking.id, attendeeId: bookingAttendees[1].id, referenceUid: uuidv4() }, + ]; - expect(oldBooking?.status).toBe(BookingStatus.CANCELLED); - } + await prisma.bookingSeat.createMany({ + data: bookingSeats, + }); + + const references = await prisma.bookingSeat.findMany({ + where: { bookingId: booking.id }, + }); + + await page.goto(`/reschedule/${references[0].referenceUid}`); + + await selectFirstAvailableTimeSlotNextMonth(page); + + await page.locator('[data-testid="confirm-reschedule-button"]').click(); + + await page.waitForURL(/.*booking/); + + await page.goto(`/reschedule/${references[1].referenceUid}`); + + await selectFirstAvailableTimeSlotNextMonth(page); + + await page.locator('[data-testid="confirm-reschedule-button"]').click(); + + // Using waitForUrl here fails the assertion `expect(oldBooking?.status).toBe(BookingStatus.CANCELLED);` probably because waitForUrl is considered complete before waitForNavigation and till that time the booking is not cancelled + await page.waitForNavigation({ url: /.*booking/ }); + + // Should expect old booking to be cancelled + const oldBooking = await prisma.booking.findFirst({ + where: { uid: booking.uid }, + include: { + seatsReferences: true, + attendees: true, + eventType: { + include: { users: true, hosts: true }, + }, + }, + }); + + expect(oldBooking?.status).toBe(BookingStatus.CANCELLED); + }); + + test("Should cancel with seats and have no attendees and cancelled", async ({ page, users, bookings }) => { + const { user, booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [ + { name: "John First", email: "first+seats@cal.com", timeZone: "Europe/Berlin" }, + { name: "Jane Second", email: "second+seats@cal.com", timeZone: "Europe/Berlin" }, + ]); + await user.login(); + + const oldBooking = await prisma.booking.findFirst({ + where: { uid: booking.uid }, + include: { seatsReferences: true, attendees: true }, + }); + + const bookingAttendees = await prisma.attendee.findMany({ + where: { bookingId: booking.id }, + select: { + id: true, + }, + }); + + const bookingSeats = [ + { bookingId: booking.id, attendeeId: bookingAttendees[0].id, referenceUid: uuidv4() }, + { bookingId: booking.id, attendeeId: bookingAttendees[1].id, referenceUid: uuidv4() }, + ]; + + await prisma.bookingSeat.createMany({ + data: bookingSeats, + }); + + // Now we cancel the booking as the organizer + await page.goto(`/booking/${booking.uid}?cancel=true`); + + await page.locator('[data-testid="cancel"]').click(); + + await page.waitForLoadState("networkidle"); + + await expect(page).toHaveURL(/.*booking/); + + // Should expect old booking to be cancelled + const updatedBooking = await prisma.booking.findFirst({ + where: { uid: booking.uid }, + include: { seatsReferences: true, attendees: true }, + }); + + expect(oldBooking?.startTime).not.toBe(updatedBooking?.startTime); + }); + + test("If rescheduled/cancelled booking with seats it should display the correct number of seats", async ({ + page, + users, + bookings, + }) => { + const { booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [ + { name: "John First", email: "first+seats@cal.com", timeZone: "Europe/Berlin" }, + { name: "Jane Second", email: "second+seats@cal.com", timeZone: "Europe/Berlin" }, + ]); + + const bookingAttendees = await prisma.attendee.findMany({ + where: { bookingId: booking.id }, + select: { + id: true, + }, + }); + + const bookingSeats = [ + { bookingId: booking.id, attendeeId: bookingAttendees[0].id, referenceUid: uuidv4() }, + { bookingId: booking.id, attendeeId: bookingAttendees[1].id, referenceUid: uuidv4() }, + ]; + + await prisma.bookingSeat.createMany({ + data: bookingSeats, + }); + + const references = await prisma.bookingSeat.findMany({ + where: { bookingId: booking.id }, + }); + + await page.goto( + `/booking/${references[0].referenceUid}?cancel=true&seatReferenceUid=${references[0].referenceUid}` ); - test("Should cancel with seats and have no attendees and cancelled", async ({ - page, - users, - bookings, - }) => { - const { user, booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [ - { name: "John First", email: "first+seats@cal.com", timeZone: "Europe/Berlin" }, - { name: "Jane Second", email: "second+seats@cal.com", timeZone: "Europe/Berlin" }, - ]); - await user.login(); + await page.locator('[data-testid="cancel"]').click(); - const oldBooking = await prisma.booking.findFirst({ - where: { uid: booking.uid }, - include: { seatsReferences: true, attendees: true }, - }); - - const bookingAttendees = await prisma.attendee.findMany({ - where: { bookingId: booking.id }, - select: { - id: true, - }, - }); - - const bookingSeats = [ - { bookingId: booking.id, attendeeId: bookingAttendees[0].id, referenceUid: uuidv4() }, - { bookingId: booking.id, attendeeId: bookingAttendees[1].id, referenceUid: uuidv4() }, - ]; - - await prisma.bookingSeat.createMany({ - data: bookingSeats, - }); - - // Now we cancel the booking as the organizer - await page.goto(`/booking/${booking.uid}?cancel=true`); - - await page.locator('[data-testid="cancel"]').click(); - - await page.waitForLoadState("networkidle"); - - await expect(page).toHaveURL(/.*booking/); - - // Should expect old booking to be cancelled - const updatedBooking = await prisma.booking.findFirst({ - where: { uid: booking.uid }, - include: { seatsReferences: true, attendees: true }, - }); - - expect(oldBooking?.startTime).not.toBe(updatedBooking?.startTime); + const oldBooking = await prisma.booking.findFirst({ + where: { uid: booking.uid }, + select: { + id: true, + status: true, + }, }); - test("If rescheduled/cancelled booking with seats it should display the correct number of seats", async ({ - page, - users, - bookings, - }) => { - const { booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [ - { name: "John First", email: "first+seats@cal.com", timeZone: "Europe/Berlin" }, - { name: "Jane Second", email: "second+seats@cal.com", timeZone: "Europe/Berlin" }, - ]); + expect(oldBooking?.status).toBe(BookingStatus.ACCEPTED); - const bookingAttendees = await prisma.attendee.findMany({ - where: { bookingId: booking.id }, - select: { - id: true, - }, - }); + await page.goto(`/reschedule/${references[1].referenceUid}`); - const bookingSeats = [ - { bookingId: booking.id, attendeeId: bookingAttendees[0].id, referenceUid: uuidv4() }, - { bookingId: booking.id, attendeeId: bookingAttendees[1].id, referenceUid: uuidv4() }, - ]; + await page.click('[data-testid="incrementMonth"]'); - await prisma.bookingSeat.createMany({ - data: bookingSeats, - }); + await page.locator('[data-testid="day"][data-disabled="false"]').nth(1).click(); - const references = await prisma.bookingSeat.findMany({ - where: { bookingId: booking.id }, - }); + // Validate that the number of seats its 10 + expect(await page.locator("text=9 / 10 Seats available").count()).toEqual(0); + }); - await page.goto( - `/booking/${references[0].referenceUid}?cancel=true&seatReferenceUid=${references[0].referenceUid}` - ); + test("Should cancel with seats but event should be still accesible and with one less attendee/seat", async ({ + page, + users, + bookings, + }) => { + const { user, booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [ + { name: "John First", email: "first+seats@cal.com", timeZone: "Europe/Berlin" }, + { name: "Jane Second", email: "second+seats@cal.com", timeZone: "Europe/Berlin" }, + ]); + await user.login(); - await page.locator('[data-testid="cancel"]').click(); - - const oldBooking = await prisma.booking.findFirst({ - where: { uid: booking.uid }, - select: { - id: true, - status: true, - }, - }); - - expect(oldBooking?.status).toBe(BookingStatus.ACCEPTED); - - await page.goto(`/reschedule/${references[1].referenceUid}`); - - await page.click('[data-testid="incrementMonth"]'); - - await page.locator('[data-testid="day"][data-disabled="false"]').nth(1).click(); - - // Validate that the number of seats its 10 - expect(await page.locator("text=9 / 10 Seats available").count()).toEqual(0); + const bookingAttendees = await prisma.attendee.findMany({ + where: { bookingId: booking.id }, + select: { + id: true, + }, }); - test("Should cancel with seats but event should be still accesible and with one less attendee/seat", async ({ - page, - users, - bookings, - }) => { - const { user, booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [ - { name: "John First", email: "first+seats@cal.com", timeZone: "Europe/Berlin" }, - { name: "Jane Second", email: "second+seats@cal.com", timeZone: "Europe/Berlin" }, - ]); - await user.login(); + const bookingSeats = [ + { bookingId: booking.id, attendeeId: bookingAttendees[0].id, referenceUid: uuidv4() }, + { bookingId: booking.id, attendeeId: bookingAttendees[1].id, referenceUid: uuidv4() }, + ]; - const bookingAttendees = await prisma.attendee.findMany({ - where: { bookingId: booking.id }, - select: { - id: true, - }, - }); - - const bookingSeats = [ - { bookingId: booking.id, attendeeId: bookingAttendees[0].id, referenceUid: uuidv4() }, - { bookingId: booking.id, attendeeId: bookingAttendees[1].id, referenceUid: uuidv4() }, - ]; - - await prisma.bookingSeat.createMany({ - data: bookingSeats, - }); - - // Now we cancel the booking as the first attendee - // booking/${bookingUid}?cancel=true&allRemainingBookings=false&seatReferenceUid={bookingSeat.referenceUid} - await page.goto( - `/booking/${booking.uid}?cancel=true&allRemainingBookings=false&seatReferenceUid=${bookingSeats[0].referenceUid}` - ); - - await page.locator('[data-testid="cancel"]').click(); - - await page.waitForLoadState("networkidle"); - - await expect(page).toHaveURL(/.*booking/); - - await page.goto( - `/booking/${booking.uid}?cancel=true&allRemainingBookings=false&seatReferenceUid=${bookingSeats[1].referenceUid}` - ); - - // Page should not be 404 - await page.locator('[data-testid="cancel"]').click(); - - await page.waitForLoadState("networkidle"); - - await expect(page).toHaveURL(/.*booking/); + await prisma.bookingSeat.createMany({ + data: bookingSeats, }); - test("Should book with seats and hide attendees info from showAttendees true", async ({ - page, - users, - bookings, - }) => { - const { user, booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [ - { name: "John First", email: "first+seats@cal.com", timeZone: "Europe/Berlin" }, - { name: "Jane Second", email: "second+seats@cal.com", timeZone: "Europe/Berlin" }, - ]); - await user.login(); - const bookingWithEventType = await prisma.booking.findFirst({ - where: { uid: booking.uid }, - select: { - id: true, - eventTypeId: true, - }, - }); + // Now we cancel the booking as the first attendee + // booking/${bookingUid}?cancel=true&allRemainingBookings=false&seatReferenceUid={bookingSeat.referenceUid} + await page.goto( + `/booking/${booking.uid}?cancel=true&allRemainingBookings=false&seatReferenceUid=${bookingSeats[0].referenceUid}` + ); - await prisma.eventType.update({ - data: { - seatsShowAttendees: false, - }, - where: { - id: bookingWithEventType?.eventTypeId || -1, - }, - }); + await page.locator('[data-testid="cancel"]').click(); - const bookingAttendees = await prisma.attendee.findMany({ - where: { bookingId: booking.id }, - select: { - id: true, - }, - }); + await page.waitForLoadState("networkidle"); - const bookingSeats = [ - { bookingId: booking.id, attendeeId: bookingAttendees[0].id, referenceUid: uuidv4() }, - { bookingId: booking.id, attendeeId: bookingAttendees[1].id, referenceUid: uuidv4() }, - ]; + await expect(page).toHaveURL(/.*booking/); - await prisma.bookingSeat.createMany({ - data: bookingSeats, - }); + await page.goto( + `/booking/${booking.uid}?cancel=true&allRemainingBookings=false&seatReferenceUid=${bookingSeats[1].referenceUid}` + ); - // Go to cancel page and see that attendees are listed and myself as I'm owner of the booking - await page.goto(`/booking/${booking.uid}?cancel=true&allRemainingBookings=false`); + // Page should not be 404 + await page.locator('[data-testid="cancel"]').click(); - const foundFirstAttendeeAsOwner = await page.locator( - 'p[data-testid="attendee-email-first+seats@cal.com"]' - ); - await expect(foundFirstAttendeeAsOwner).toHaveCount(1); - const foundSecondAttendeeAsOwner = await page.locator( - 'p[data-testid="attendee-email-second+seats@cal.com"]' - ); - await expect(foundSecondAttendeeAsOwner).toHaveCount(1); - await page.goto("auth/logout"); + await page.waitForLoadState("networkidle"); - // Now we cancel the booking as the first attendee - // booking/${bookingUid}?cancel=true&allRemainingBookings=false&seatReferenceUid={bookingSeat.referenceUid} - await page.goto( - `/booking/${booking.uid}?cancel=true&allRemainingBookings=false&seatReferenceUid=${bookingSeats[0].referenceUid}` - ); + await expect(page).toHaveURL(/.*booking/); + }); - // No attendees should be displayed only the one that it's cancelling - const notFoundSecondAttendee = await page.locator( - 'p[data-testid="attendee-email-second+seats@cal.com"]' - ); - - await expect(notFoundSecondAttendee).toHaveCount(0); - const foundFirstAttendee = await page.locator('p[data-testid="attendee-email-first+seats@cal.com"]'); - await expect(foundFirstAttendee).toHaveCount(1); - - await prisma.eventType.update({ - data: { - seatsShowAttendees: true, - }, - where: { - id: bookingWithEventType?.eventTypeId || -1, - }, - }); - - await page.goto( - `/booking/${booking.uid}?cancel=true&allRemainingBookings=false&seatReferenceUid=${bookingSeats[1].referenceUid}` - ); - - // Now attendees should be displayed - const foundSecondAttendee = await page.locator('p[data-testid="attendee-email-second+seats@cal.com"]'); - - await expect(foundSecondAttendee).toHaveCount(1); - const foundFirstAttendeeAgain = await page - .locator('p[data-testid="attendee-email-first+seats@cal.com"]') - .first(); - await expect(foundFirstAttendeeAgain).toHaveCount(1); + test("Should book with seats and hide attendees info from showAttendees true", async ({ + page, + users, + bookings, + }) => { + const { user, booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [ + { name: "John First", email: "first+seats@cal.com", timeZone: "Europe/Berlin" }, + { name: "Jane Second", email: "second+seats@cal.com", timeZone: "Europe/Berlin" }, + ]); + await user.login(); + const bookingWithEventType = await prisma.booking.findFirst({ + where: { uid: booking.uid }, + select: { + id: true, + eventTypeId: true, + }, }); + + await prisma.eventType.update({ + data: { + seatsShowAttendees: false, + }, + where: { + id: bookingWithEventType?.eventTypeId || -1, + }, + }); + + const bookingAttendees = await prisma.attendee.findMany({ + where: { bookingId: booking.id }, + select: { + id: true, + }, + }); + + const bookingSeats = [ + { bookingId: booking.id, attendeeId: bookingAttendees[0].id, referenceUid: uuidv4() }, + { bookingId: booking.id, attendeeId: bookingAttendees[1].id, referenceUid: uuidv4() }, + ]; + + await prisma.bookingSeat.createMany({ + data: bookingSeats, + }); + + // Go to cancel page and see that attendees are listed and myself as I'm owner of the booking + await page.goto(`/booking/${booking.uid}?cancel=true&allRemainingBookings=false`); + + const foundFirstAttendeeAsOwner = await page.locator( + 'p[data-testid="attendee-email-first+seats@cal.com"]' + ); + await expect(foundFirstAttendeeAsOwner).toHaveCount(1); + const foundSecondAttendeeAsOwner = await page.locator( + 'p[data-testid="attendee-email-second+seats@cal.com"]' + ); + await expect(foundSecondAttendeeAsOwner).toHaveCount(1); + + await page.goto("auth/logout"); + + // Now we cancel the booking as the first attendee + // booking/${bookingUid}?cancel=true&allRemainingBookings=false&seatReferenceUid={bookingSeat.referenceUid} + await page.goto( + `/booking/${booking.uid}?cancel=true&allRemainingBookings=false&seatReferenceUid=${bookingSeats[0].referenceUid}` + ); + + // No attendees should be displayed only the one that it's cancelling + const notFoundSecondAttendee = await page.locator('p[data-testid="attendee-email-second+seats@cal.com"]'); + + await expect(notFoundSecondAttendee).toHaveCount(0); + const foundFirstAttendee = await page.locator('p[data-testid="attendee-email-first+seats@cal.com"]'); + await expect(foundFirstAttendee).toHaveCount(1); + + await prisma.eventType.update({ + data: { + seatsShowAttendees: true, + }, + where: { + id: bookingWithEventType?.eventTypeId || -1, + }, + }); + + await page.goto( + `/booking/${booking.uid}?cancel=true&allRemainingBookings=false&seatReferenceUid=${bookingSeats[1].referenceUid}` + ); + + // Now attendees should be displayed + const foundSecondAttendee = await page.locator('p[data-testid="attendee-email-second+seats@cal.com"]'); + + await expect(foundSecondAttendee).toHaveCount(1); + const foundFirstAttendeeAgain = await page + .locator('p[data-testid="attendee-email-first+seats@cal.com"]') + .first(); + await expect(foundFirstAttendeeAgain).toHaveCount(1); }); }); diff --git a/apps/web/playwright/embed-code-generator.e2e.ts b/apps/web/playwright/embed-code-generator.e2e.ts index ab1a195bc7..12c2b437ec 100644 --- a/apps/web/playwright/embed-code-generator.e2e.ts +++ b/apps/web/playwright/embed-code-generator.e2e.ts @@ -178,7 +178,7 @@ test.describe("Embed Code Generator Tests", () => { test.beforeEach(async ({ page }) => { await page.goto(`/event-types`); await Promise.all([ - page.locator('[href*="/event-types/"]').first().click(), + page.locator('a[href*="/event-types/"]').first().click(), page.waitForURL((url) => url.pathname.startsWith("/event-types/")), ]); }); diff --git a/apps/web/playwright/login.e2e.ts b/apps/web/playwright/login.e2e.ts index 83d37beec7..b914a2cc4a 100644 --- a/apps/web/playwright/login.e2e.ts +++ b/apps/web/playwright/login.e2e.ts @@ -35,11 +35,9 @@ test.describe("user can login & logout succesfully", async () => { const signOutBtn = await page.locator(`text=${signOutLabel}`); await signOutBtn.click(); - // 2s of delay to assure the session is cleared - await page.waitForURL("/auth/logout"); + await page.locator('a[href="/auth/login"]').click(); // Reroute to the home page to check if the login form shows up - await page.goto("/"); await expect(page.locator(`[data-testid=login-form]`)).toBeVisible(); }); }); diff --git a/playwright.config.ts b/playwright.config.ts index 0b5b248732..098076c60f 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -11,8 +11,8 @@ const outputDir = path.join(__dirname, "test-results"); // Dev Server on local can be slow to start up and process requests. So, keep timeouts really high on local, so that tests run reliably locally // So, if not in CI, keep the timers high, if the test is stuck somewhere and there is unnecessary wait developer can see in browser that it's stuck -const DEFAULT_NAVIGATION_TIMEOUT = process.env.CI ? 15000 : 120000; -const DEFAULT_EXPECT_TIMEOUT = process.env.CI ? 15000 : 120000; +const DEFAULT_NAVIGATION_TIMEOUT = process.env.CI ? 30000 : 120000; +const DEFAULT_EXPECT_TIMEOUT = process.env.CI ? 30000 : 120000; // Test Timeout can hit due to slow expect, slow navigation. // So, it should me much higher than sum of expect and navigation timeouts as there can be many async expects and navigations in a single test @@ -25,7 +25,8 @@ const IS_EMBED_REACT_TEST = process.argv.some((a) => a.startsWith("--project=@ca const webServer: PlaywrightTestConfig["webServer"] = [ { - command: "NEXT_PUBLIC_IS_E2E=1 yarn workspace @calcom/web start -p 3000", + command: + "NEXT_PUBLIC_IS_E2E=1 NODE_OPTIONS='--dns-result-order=ipv4first' yarn workspace @calcom/web start -p 3000", port: 3000, timeout: 60_000, reuseExistingServer: !process.env.CI, From e37e07ab3b76f41220da2fb02663af040605fbc6 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 13:53:11 +0000 Subject: [PATCH 036/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/es/common.json | 24 +++---- apps/web/public/static/locales/ja/common.json | 16 ++--- apps/web/public/static/locales/sr/common.json | 34 +++++++++- apps/web/public/static/locales/sv/common.json | 57 ++++++++++++++++- apps/web/public/static/locales/tr/common.json | 27 +++++++- apps/web/public/static/locales/uk/common.json | 57 ++++++++++++++++- apps/web/public/static/locales/vi/common.json | 64 ++++++++++--------- .../public/static/locales/zh-CN/common.json | 21 ++++++ 8 files changed, 246 insertions(+), 54 deletions(-) diff --git a/apps/web/public/static/locales/es/common.json b/apps/web/public/static/locales/es/common.json index b99ca4179d..3224dc0698 100644 --- a/apps/web/public/static/locales/es/common.json +++ b/apps/web/public/static/locales/es/common.json @@ -607,7 +607,7 @@ "count_members_other": "{{count}} miembros", "no_assigned_members": "No hay miembros asignados", "assigned_to": "Asignado a", - "start_assigning_members_above": "Empezar a asignar miembros arriba", + "start_assigning_members_above": "Empezar a asignar miembros más arriba", "locked_fields_admin_description": "Los miembros no podrán editar esto", "locked_fields_member_description": "El administrador del equipo bloqueó esta opción", "url": "URL", @@ -768,7 +768,7 @@ "delete_event_type": "¿Eliminar tipo de evento?", "delete_managed_event_type": "¿Eliminar tipo de evento gestionado?", "delete_event_type_description": "Cualquier persona con la que haya compartido este enlace ya no podrá reservar con él.", - "delete_managed_event_type_description": "
  • Los miembros asignados a este tipo de evento también verán eliminados sus tipos de evento.
  • Cualquier persona con la que hayan compartido su enlace ya no podrá reservar mediante su uso.
", + "delete_managed_event_type_description": "
  • Los miembros asignados a este tipo de evento también verán eliminados sus tipos de evento.
  • Cualquier persona con la que hayan compartido su enlace ya no podrá reservar con él.
", "confirm_delete_event_type": "Sí, eliminar", "delete_account": "Eliminar cuenta", "confirm_delete_account": "Sí, eliminar cuenta", @@ -1341,7 +1341,7 @@ "exchange_version_2013_SP1": "2013 SP1", "exchange_version_2015": "2015", "exchange_version_2016": "2016", - "routing_forms_description": "Aquí puedes ver todos los formularios y rutas que has creado.", + "routing_forms_description": "Crea formularios para dirigir a los asistentes a sus destinos correctos", "routing_forms_send_email_owner": "Enviar correo electrónico al propietario", "routing_forms_send_email_owner_description": "Mande un correo electrónico al propietario cuando se envía el formulario", "add_new_form": "Añadir formulario nuevo", @@ -1703,10 +1703,10 @@ "add_a_new_route": "Agregar una ruta nueva", "make_informed_decisions": "Tome decisiones informadas con Insights", "make_informed_decisions_description": "Nuestro panel de Insights muestra toda la actividad de su equipo y las tendencias que permiten una mejor programación y toma de decisiones.", - "view_bookings_across": "Ver reservas entre todos los miembros", + "view_bookings_across": "Ver reservas de todos los miembros", "view_bookings_across_description": "Vea quién recibe la mayor cantidad de reservas y garantice la mejor distribución en su equipo", "identify_booking_trends": "Identificar tendencias de reserva", - "identify_booking_trends_description": "Consultar qué horas de la semana y qué horas durante el día son populares para sus reservas", + "identify_booking_trends_description": "Consultar cuáles son las horas de la semana y del día más populares para sus reservas", "spot_popular_event_types": "Detectar tipos de eventos populares", "spot_popular_event_types_description": "Consulte cuál de sus tipos de eventos están recibiendo más clics y reservas", "no_responses_yet": "Aún no hay respuestas", @@ -1729,7 +1729,7 @@ "can_you_try_again": "¿Puede intentarlo de nuevo con una hora diferente?", "verify": "Verificar", "timezone_variable": "Zona Horaria", - "timezone_info": "La zona horaria de la persona que recibe", + "timezone_info": "Zona horaria de la persona que recibe", "event_end_time_variable": "Hora de finalización del evento", "event_end_time_info": "La hora de finalización del evento", "cancel_url_variable": "URL de cancelación", @@ -1742,11 +1742,11 @@ "members_default_schedule": "Horario predeterminado del miembro", "set_by_admin": "Establecido por el administrador del equipo", "members_default_location": "Ubicación predeterminada del miembro", - "members_default_schedule_description": "Usaremos el horario de disponibilidad predeterminado de cada miembro. Podrán editarlo o cambiarlo.", + "members_default_schedule_description": "Usaremos el horario de disponibilidad predeterminado de cada miembro. Este se podrá editar o cambiar.", "requires_at_least_one_schedule": "Es necesario tener al menos un horario", "default_conferencing_bulk_description": "Actualizar las ubicaciones para los tipos de eventos seleccionados", "locked_for_members": "Bloqueado para miembros", - "locked_apps_description": "Los miembros podrán ver las aplicaciones activas pero no podrán editar ninguna configuración de la aplicación", + "locked_apps_description": "Los miembros podrán ver las aplicaciones activas, pero no podrán editar ninguna configuración de la aplicación", "locked_webhooks_description": "Los miembros podrán ver los webhooks activos, pero no podrán editar ninguna configuración de webhooks", "locked_workflows_description": "Los miembros podrán ver los flujos de trabajo activos, pero no podrán editar ninguna configuración de flujo de trabajo", "locked_by_admin": "Bloqueado por el administrador del equipo", @@ -1761,7 +1761,7 @@ "managed_event_dialog_clarification": "Si elige reemplazarlo, se lo notificaremos. Regrese y elimínelos si no desea sobrescribirlo.", "review_event_type": "Revisar tipo de evento", "looking_for_more_analytics": "¿Busca más datos de análisis?", - "looking_for_more_insights": "¿Busca más perspectivas?", + "looking_for_more_insights": "¿Quiere saber más sobre Insights?", "add_filter": "Añadir filtro", "select_user": "Seleccionar usuario", "select_event_type": "Seleccionar tipo de evento", @@ -1777,7 +1777,7 @@ "events_rescheduled": "Eventos reprogramados", "from_last_period": "desde el último período", "from_to_date_period": "Desde: {{startDate}} Hasta: {{endDate}}", - "analytics_for_organisation": "Perspectivas", + "analytics_for_organisation": "Insights", "subtitle_analytics": "Obtenga más información sobre la actividad de su equipo", "redirect_url_warning": "Agregar una redirección deshabilitará la página de éxito. Asegúrese de mencionar \"Reserva confirmada\" en su página de éxito personalizada.", "event_trends": "Tendencias del evento", @@ -1802,9 +1802,9 @@ "insights": "Insights", "testing_workflow_info_message": "Al probar este flujo de trabajo, tenga en cuenta que los correos electrónicos y los SMS solo se pueden programar con al menos 1 hora de anticipación", "insights_no_data_found_for_filter": "No se encontraron datos para el filtro seleccionado o las fechas seleccionadas.", - "acknowledge_booking_no_show_fee": "Reconozco que si no asisto a este evento, se aplicará a mi tarjeta una tarifa de {{amount, currency}} por no presentarse.", + "acknowledge_booking_no_show_fee": "Reconozco que si no asisto a este evento, se aplicará a mi tarjeta una tarifa de {{amount, currency}} por no presentarme.", "card_details": "Detalles de la tarjeta", - "seats_and_no_show_fee_error": "Actualmente no se pueden habilitar cupos ni cobrar una tarifa por no presentarse", + "seats_and_no_show_fee_error": "Actualmente, no se pueden habilitar cupos ni cobrar una tarifa por no presentarse", "complete_your_booking": "Complete su reserva", "complete_your_booking_subject": "Complete su reserva: {{title}} el {{date}}", "confirm_your_details": "Confirme sus datos", diff --git a/apps/web/public/static/locales/ja/common.json b/apps/web/public/static/locales/ja/common.json index b8af041c6f..b6b7468223 100644 --- a/apps/web/public/static/locales/ja/common.json +++ b/apps/web/public/static/locales/ja/common.json @@ -1762,15 +1762,15 @@ "card_held": "カードを保留中", "charge_card": "カードに請求する", "card_charged": "カードに請求が行われました", - "no_show_fee_amount": "{{amount, currency}} の予約不参加料金", - "no_show_fee": "予約不参加料金", + "no_show_fee_amount": "不参加費用 {{amount, currency}}", + "no_show_fee": "不参加費用", "submit_card": "カードを送信", - "submit_payment_information": "支払い情報を送信", - "meeting_awaiting_payment_method": "会議の支払いを待っています", - "no_show_fee_charged_email_subject": "{{date}} の {{title}} に {{amount, currency}} の予約不参加料金が請求されました", - "no_show_fee_charged_text_body": "予約不参加料金が請求されました", - "no_show_fee_charged_subtitle": "次のイベントに {{amount, currency}} の予約不参加料金が請求されました", - "error_charging_card": "予約不参加料金の請求に問題が発生しました。後でもう一度お試しください。", + "submit_payment_information": "お支払い情報を送信", + "meeting_awaiting_payment_method": "会議がお支払い方法の確定を待機しています", + "no_show_fee_charged_email_subject": "{{date}} の {{title}} について不参加費用 {{amount, currency}} が請求されました", + "no_show_fee_charged_text_body": "不参加費用が請求されました", + "no_show_fee_charged_subtitle": "次のイベントについて不参加費用 {{amount, currency}} が請求されました", + "error_charging_card": "不参加費用の請求時にエラーが発生しました。後でもう一度お試しください。", "collect_no_show_fee": "不参加費用を徴収する", "no_show_fee_charged": "不参加費用が請求されました", "insights": "Insights", diff --git a/apps/web/public/static/locales/sr/common.json b/apps/web/public/static/locales/sr/common.json index daaedbb2e9..254f21b5b4 100644 --- a/apps/web/public/static/locales/sr/common.json +++ b/apps/web/public/static/locales/sr/common.json @@ -26,6 +26,8 @@ "rejection_confirmation": "Odbij rezervaciju", "manage_this_event": "Upravljaj ovim dogadjajem", "invite_team_member": "Pozovite člana tima", + "invite_team_individual_segment": "Pozovite pojedinačno", + "invite_team_bulk_segment": "Pozovite grupno", "invite_team_notifcation_badge": "Poz.", "your_event_has_been_scheduled": "Vaš dogadjaj je odložen", "your_event_has_been_scheduled_recurring": "Vaš ponavljajući događaj je zakazan", @@ -222,6 +224,7 @@ "go_back_login": "Idite nazad na stranicu za prijavu", "error_during_login": "Došlo je do greške pri prijavi. Idite nazad na stranicu za prijavu i pokušajte ponovo.", "request_password_reset": "Zatražite imejl za ponovno postavljanje lozinke", + "send_invite": "Pošaljite pozivnicu", "forgot_password": "Zaboravili ste lozinku?", "forgot": "Zaboravili ste?", "done": "Urađeno", @@ -237,6 +240,8 @@ "set_availability": "Podesite svoju dostupnost", "continue_without_calendar": "Nastavite bez kalendara", "connect_your_calendar": "Povežite vaš kalendar", + "connect_your_video_app": "Povežite svoje video aplikacije", + "connect_your_video_app_instructions": "Povežite svoje video aplikacije da biste ih koristili u vašim tipovima događaja.", "connect_your_calendar_instructions": "Povežite vaš kalendar da automatski radi proveru zauzetih vremena i vidi nove dogadjaje kad se zakažu.", "set_up_later": "Postavi kasnije", "current_time": "Trenutno vreme", @@ -367,6 +372,7 @@ "create_webhook": "Napravite Webhook", "booking_cancelled": "Rezervacija Otkazana", "booking_rescheduled": "Rezervacija Odložena", + "recording_ready": "Link za preuzimanje snimka je spreman", "booking_created": "Rezervacija Napravljena", "meeting_ended": "Sastanak se završio", "form_submitted": "Formular poslat", @@ -465,6 +471,7 @@ "friday": "Petak", "saturday": "Subota", "sunday": "Nedelja", + "all_booked_today": "Sve je zakazano.", "slots_load_fail": "Problem pri učitavanju dostupnih termina.", "additional_guests": "+ Dodatni Gosti", "your_name": "Vaše ime", @@ -752,6 +759,10 @@ "new_event_type_to_book_description": "Napravi novi tip događaja preko koga će ljudi moći da naprave rezervacije.", "length": "Dužina", "minimum_booking_notice": "Minimalni rok za najavu sastanka", + "offset_toggle": "Pomeri vremena početka", + "offset_toggle_description": "Pomeri vremena termina prikazana polaznicima za određeni broj minuta", + "offset_start": "Pomeri za", + "offset_start_description": "npr. ovo će prikazati vremena termina vašim polaznicima u {{ adjustedTime }} umesto {{ originalTime }}", "slot_interval": "Intervali vremenskih slotova", "slot_interval_default": "Koristi dužinu događaja (uobičajeno podešavanje)", "delete_event_type": "Izbriši tip događaja?", @@ -904,6 +915,7 @@ "duplicate": "Dupliraj", "offer_seats": "Ponudi mesta", "offer_seats_description": "Ponudite mesta za zakazivanje. Ovo automatski onemogućava gostujuća i opciona zakazivanja.", + "seats_available_one": "Dostupno mesto", "seats_available_other": "Slobodnih mesta", "number_of_seats": "Broj mesta po zakazivanju", "enter_number_of_seats": "Unesite broj slobodnih mesta", @@ -1038,6 +1050,7 @@ "event_cancelled_trigger": "kada je događaj otkazan", "new_event_trigger": "kada je zakazan novi događaj", "email_host_action": "pošalji imejl domaćinu", + "email_attendee_action": "pošalji imejl polaznicima", "sms_attendee_action": "pošalji SMS polazniku", "sms_number_action": "pošalji SMS na određeni broj", "workflows": "Radni tokovi", @@ -1190,6 +1203,7 @@ "create_workflow": "Kreirajte radni tok", "do_this": "Uradi ovo", "turn_off": "Isključi", + "turn_on": "Uključi", "settings_updated_successfully": "Podešavanja su uspešno ažurirana", "error_updating_settings": "Greška pri ažuriranju podešavanja", "personal_cal_url": "Moj lični {{appName}} URL", @@ -1246,6 +1260,7 @@ "calendars_description": "Konfigurišite način na koji tipovi događaja vrše interakciju sa vašim kalendarima", "appearance_description": "Upravljajte podešavanjima za izgled vaše rezervacije", "conferencing_description": "Dodajte svoje omiljene aplikacije za video konferencije za vaše sastanke", + "add_conferencing_app": "Dodaj aplikaciju za konferenciju", "password_description": "Upravljajte podešavanjima za lozinke vašeg naloga", "2fa_description": "Upravljajte podešavanjima za lozinke vašeg naloga", "we_just_need_basic_info": "Trebaju nam neke osnovne informacije da bismo podesili vaš profil.", @@ -1620,6 +1635,7 @@ "email_user_cta": "Prikaži pozivnicu", "email_no_user_invite_heading": "Pozvani ste da se pridružite timu u {{appName}}", "email_no_user_invite_subheading": "{{invitedBy}} vas je pozvao/la da se pridružite njihovom timu u {{appName}}. {{appName}} je planer za koordinaciju događaja koji omogućava vama i vašem timu da zakazujete sastanke bez dopisivanja imejlovima.", + "email_user_invite_subheading": "{{invitedBy}} vas je pozvao/la da se pridružite njihovom timu `{{teamName}}` u {{appName}}. {{appName}} je planer za koordinaciju događaja koji omogućava vama i vašem timu da zakazujete sastanke bez dopisivanja imejlovima.", "email_no_user_invite_steps_intro": "Provešćemo vas kroz nekoliko kratkih koraka, i za tren oka ćete uživati u zakazivanju bez stresa sa svojim timom.", "email_no_user_step_one": "Izaberite korisničko ime", "email_no_user_step_two": "Povežite se sa nalogom kalendara", @@ -1695,6 +1711,15 @@ "spot_popular_event_types_description": "Pogledajte koji tipovi događaja dobijaju najviše klikova i zakazivanja", "no_responses_yet": "Još uvek nema odgovora", "this_will_be_the_placeholder": "Ovo će biti čuvar mesta", + "error_booking_event": "Došlo je do greške prilikom zakazivanja događaja, osvežite stranicu i pokušajte ponovo", + "timeslot_missing_title": "Nisu izabrani termini", + "timeslot_missing_description": "Izaberite termin da biste zakazali događaj.", + "timeslot_missing_cta": "Izaberite termin", + "switch_monthly": "Pređite na mesečni pregled", + "switch_weekly": "Pređite na nedeljni pregled", + "switch_multiday": "Pređite na dnevni pregled", + "num_locations": "{{num}} opcija lokacije", + "select_on_next_step": "Izaberite na sledećem koraku", "this_meeting_has_not_started_yet": "Ovaj sastanak još nije počeo", "this_app_requires_connected_account": "{{appName}} zahteva povezani {{dependencyName}} nalog", "connect_app": "Povežite {{dependencyName}}", @@ -1724,6 +1749,7 @@ "locked_apps_description": "Članovi će moći da vide aktivne aplikacije, ali neće moći da uređuju podešavanja aplikacije", "locked_webhooks_description": "Članovi će moći da vide aktivne webhook-ove, ali neće moći da uređuju podešavanja webhook-ova", "locked_workflows_description": "Članovi će moći da vide aktivne radne tokove, ali neće moći da uređuju podešavanja radnih tokova", + "locked_by_admin": "Zaključao administrator tima", "app_not_connected": "Niste povezali {{appName}} nalog.", "connect_now": "Povežite odmah", "managed_event_dialog_confirm_button_one": "Zameni i obavesti {{count}} člana", @@ -1781,10 +1807,16 @@ "seats_and_no_show_fee_error": "Trenutno nije moguće aktiviranje mesta i naplata naknade za izostanak", "complete_your_booking": "Završite svoje zakazivanje", "complete_your_booking_subject": "Završite svoje zakazivanje: {{title}} dana {{date}}", + "confirm_your_details": "Potvrdite svoje podatke", "currency_string": "{{amount, currency}}", "charge_card_dialog_body": "Upravo ćete naplatiti polazniku {{amount, currency}}. Jeste li sigurni da želite da nastavite?", "charge_attendee": "Naplatite polazniku {{amount, currency}}", "payment_app_commission": "Zahtevajte plaćanje ({{paymentFeePercentage}}% + {{fee, currency}} provizija po transakciji)", "email_invite_team": "{{email}} je pozvan/a", - "image_size_limit_exceed": "Otpremljena slika ne sme da prevazilazi ograničenje od 5mb" + "email_invite_team_bulk": "Pozvano je {{userCount}} korisnika", + "error_collecting_card": "Greška u sakupljanju kartice", + "image_size_limit_exceed": "Otpremljena slika ne sme da prevazilazi ograničenje od 5mb", + "inline_embed": "Ugradi neposredno", + "load_inline_content": "Direktno učitava vaš tip događaja neposredno sa vašim ostalim sadržajem na veb sajtu.", + "floating_pop_up_button": "Plutajuće iskačuće dugme" } diff --git a/apps/web/public/static/locales/sv/common.json b/apps/web/public/static/locales/sv/common.json index 8f0e6fd018..b34d1f652e 100644 --- a/apps/web/public/static/locales/sv/common.json +++ b/apps/web/public/static/locales/sv/common.json @@ -26,6 +26,8 @@ "rejection_confirmation": "Avböj bokningen", "manage_this_event": "Hantera denna bokning", "invite_team_member": "Bjud in teammedlem", + "invite_team_individual_segment": "Bjud in individ", + "invite_team_bulk_segment": "Importera i bulk", "invite_team_notifcation_badge": "Inbj.", "your_event_has_been_scheduled": "Din bokning har schemalagts", "your_event_has_been_scheduled_recurring": "Din återkommande händelseförfrågan har schemalagts", @@ -222,6 +224,7 @@ "go_back_login": "Gå tillbaka till inloggningssidan", "error_during_login": "Ett fel inträffade när du loggade in. Gå tillbaka till inloggningsskärmen och försök igen.", "request_password_reset": "Skicka e-postmeddelande om återställning", + "send_invite": "Skicka inbjudan", "forgot_password": "Glömt lösenordet?", "forgot": "Glömt?", "done": "Klar", @@ -237,6 +240,8 @@ "set_availability": "Ställ in din tillgänglighet", "continue_without_calendar": "Fortsätt utan kalender", "connect_your_calendar": "Anslut din kalender", + "connect_your_video_app": "Anslut dina videoappar", + "connect_your_video_app_instructions": "Anslut dina videoappar för att använda dem på dina evenemangstyper.", "connect_your_calendar_instructions": "Anslut din kalender för att automatiskt upptäcka uppbokade tider samt fylla på med nya bokningar.", "set_up_later": "Konfigurera senare", "current_time": "Aktuell tid", @@ -367,6 +372,7 @@ "create_webhook": "Skapa webhook", "booking_cancelled": "Bokning inställd", "booking_rescheduled": "Bokning ombokad", + "recording_ready": "Länk för nedladdning av inspelning klar", "booking_created": "Bokning skapad", "meeting_ended": "Mötet avslutat", "form_submitted": "Formulär skickat", @@ -465,6 +471,7 @@ "friday": "Fredag", "saturday": "Lördag", "sunday": "Söndag", + "all_booked_today": "Alla bokade.", "slots_load_fail": "Det gick inte att ladda tillgängliga tidsluckor.", "additional_guests": "Lägg till gäster", "your_name": "Ditt namn", @@ -752,6 +759,10 @@ "new_event_type_to_book_description": "Skapa en ny händelsetyp som personer kan boka tider med.", "length": "Längd", "minimum_booking_notice": "Senaste tid för att boka", + "offset_toggle": "Förskjutna starttider", + "offset_toggle_description": "Förskjutning av tidsluckor som visas för bokare med ett angivet antal minuter", + "offset_start": "Förskjutning av", + "offset_start_description": "detta visar t.ex. tidsluckor för dina bokare vid {{ adjustedTime }} istället för {{ originalTime }}", "slot_interval": "Tid mellan bokningar", "slot_interval_default": "Använd händelsens längd (standard)", "delete_event_type": "Radera händelsetyp?", @@ -904,6 +915,7 @@ "duplicate": "Duplicera", "offer_seats": "Erbjud platser", "offer_seats_description": "Erbjud platser till bokningar. Detta inaktiverar gäster och bokningar.", + "seats_available_one": "Tillgänglig plats", "seats_available_other": "Tillgängliga platser", "number_of_seats": "Antal platser per bokning", "enter_number_of_seats": "Ange antal platser", @@ -1038,6 +1050,7 @@ "event_cancelled_trigger": "när händelsen ställs in", "new_event_trigger": "när ny händelse bokas", "email_host_action": "skicka e-post till värd", + "email_attendee_action": "skicka e-post till deltagare", "sms_attendee_action": "skicka SMS till deltagare", "sms_number_action": "skicka SMS till ett specifikt nummer", "workflows": "Arbetsflöden", @@ -1190,6 +1203,7 @@ "create_workflow": "Skapa ett arbetsflöde", "do_this": "Gör detta", "turn_off": "Stäng av", + "turn_on": "Slå på", "settings_updated_successfully": "Inställningar har uppdaterats", "error_updating_settings": "Fel vid uppdatering av inställningar", "personal_cal_url": "Min personliga {{appName}}-URL", @@ -1246,6 +1260,7 @@ "calendars_description": "Ställ in hur dina händelsetyper interagerar med dina kalendrar", "appearance_description": "Hantera inställningar för ditt bokningsutseende", "conferencing_description": "Lägg till dina favoritappar för videokonferenser för möten", + "add_conferencing_app": "Lägg till konferensapp", "password_description": "Hantera inställningar för dina kontolösenord", "2fa_description": "Hantera inställningar för dina kontolösenord", "we_just_need_basic_info": "Vi behöver bara lite grundläggande information för att ställa in din profil.", @@ -1620,6 +1635,7 @@ "email_user_cta": "Visa inbjudan", "email_no_user_invite_heading": "Du är inbjuden att gå med i ett team på {{appName}}", "email_no_user_invite_subheading": "{{invitedBy}} har bjudit in dig att gå med i sitt team på {{appName}}. {{appName}} är en händelsejonglerande schemaläggare som du och ditt team kan använda för att planera möten utan att skicka e-post fram och tillbaka.", + "email_user_invite_subheading": "{{invitedBy}} har bjudit in dig att gå med i sitt team {{teamName}} den {{appName}}. {{appName}} är en händelsejonglerande schemaläggare som du och ditt team kan använda för att planera möten utan att skicka e-post fram och tillbaka.", "email_no_user_invite_steps_intro": "Vi går igenom några enkla steg så att du kan schemalägga utan stress med ditt team på nolltid.", "email_no_user_step_one": "Välj ditt användarnamn", "email_no_user_step_two": "Anslut ditt kalenderkonto", @@ -1695,6 +1711,15 @@ "spot_popular_event_types_description": "Se vilka av dina händelsetyper som får flest klick och bokningar", "no_responses_yet": "Inga svar ännu", "this_will_be_the_placeholder": "Det här blir platshållaren", + "error_booking_event": "Ett fel uppstod när du bokade evenemanget, uppdatera sidan och försök igen", + "timeslot_missing_title": "Ingen tidslucka vald", + "timeslot_missing_description": "Välj en tidslucka för att boka evenemanget.", + "timeslot_missing_cta": "Välj tidslucka", + "switch_monthly": "Växla till månatlig vy", + "switch_weekly": "Växla till veckovis vy", + "switch_multiday": "Växla till dagvy", + "num_locations": "{{num}} platsalternativ", + "select_on_next_step": "Välj i nästa steg", "this_meeting_has_not_started_yet": "Mötet har inte startat än", "this_app_requires_connected_account": "{{appName}} kräver ett anslutet {{dependencyName}}-konto", "connect_app": "Anslut {{dependencyName}}", @@ -1724,6 +1749,7 @@ "locked_apps_description": "Medlemmarna kan se de aktiva apparna men kan inte ändra appinställningarna", "locked_webhooks_description": "Medlemmarna kan se aktiva webhooks men kan inte redigera inställningar för webhooks", "locked_workflows_description": "Medlemmarna kan se aktiva arbetsflöden men kan inte ändra några arbetsflödesinställningar", + "locked_by_admin": "Låst av teamadministratör", "app_not_connected": "Du har inte anslutit ett {{appName}}-konto.", "connect_now": "Anslut nu", "managed_event_dialog_confirm_button_one": "Ersätt och meddela {{count}} medlem", @@ -1781,5 +1807,34 @@ "seats_and_no_show_fee_error": "För närvarande går det inte att aktivera platser och ta ut en avgift för utebliven närvaro", "complete_your_booking": "Slutför din bokning", "complete_your_booking_subject": "Slutför din bokning: {{title}} {{date}}", - "email_invite_team": "{{email}} har bjudits in" + "confirm_your_details": "Bekräfta dina uppgifter", + "currency_string": "{{amount, currency}}", + "charge_card_dialog_body": "Du är på väg att debitera deltagaren {{amount, currency}}. Är du säker på att du vill fortsätta?", + "charge_attendee": "Debitera deltagare {{amount, currency}}", + "payment_app_commission": "Kräv betalning ({{paymentFeePercentage}}% + {{fee, currency}} provision per transaktion)", + "email_invite_team": "{{email}} har bjudits in", + "email_invite_team_bulk": "{{userCount}} användare har blivit inbjudna", + "error_collecting_card": "Fel vid insamling av kort", + "image_size_limit_exceed": "Uppladdad bild bör inte överstiga 5 MB storleksgräns", + "inline_embed": "Inline Embed", + "load_inline_content": "Laddar din evenemangstyp direkt i linje med ditt övriga webbplatsinnehåll.", + "floating_pop_up_button": "Flytande popup-knapp", + "floating_button_trigger_modal": "Sätter en flytande knapp på din webbplats som utlöser en modal med din evenemangstyp.", + "pop_up_element_click": "Pop up via elementklick", + "open_dialog_with_element_click": "Öppna din Cal-dialogruta när någon klickar på ett element.", + "need_help_embedding": "Behöver du hjälp? Se våra guider för inbäddning av Cal på Wix, Squarespace eller WordPress, kolla våra vanliga frågor eller utforska avancerade inbäddningsalternativ.", + "book_my_cal": "Boka min Cal", + "invite_as": "Bjud in som", + "form_updated_successfully": "Formuläret har uppdaterats.", + "email_not_cal_member_cta": "Gå med i teamet", + "disable_attendees_confirmation_emails": "Inaktivera e-postbekräftelse som standard för deltagare", + "disable_attendees_confirmation_emails_description": "Minst ett arbetsflöde är aktivt på denna evenemangstyp som skickar ett e-postmeddelande till deltagarna när evenemanget är bokat.", + "disable_host_confirmation_emails": "Inaktivera e-postbekräftelse som standard för värdar", + "disable_host_confirmation_emails_description": "Minst ett arbetsflöde är aktivt för denna evenemangstyp som skickar ett e-postmeddelande till värden när evenemanget är bokat.", + "add_an_override": "Lägg till åsidosättning", + "import_from_google_workspace": "Importera användare från Google Workspace", + "connect_google_workspace": "Anslut Google Workspace", + "google_workspace_admin_tooltip": "Du måste vara Workspace-administratör för att kunna använda denna funktion", + "first_event_type_webhook_description": "Skapa din första webhook för denna evenemangstyp", + "create_for": "Skapa för" } diff --git a/apps/web/public/static/locales/tr/common.json b/apps/web/public/static/locales/tr/common.json index eb139781a3..23803b5274 100644 --- a/apps/web/public/static/locales/tr/common.json +++ b/apps/web/public/static/locales/tr/common.json @@ -759,6 +759,9 @@ "new_event_type_to_book_description": "İnsanların rezervasyon yapabileceği yeni bir etkinlik türü oluşturun.", "length": "Uzunluk", "minimum_booking_notice": "Minimum Bildirim", + "offset_toggle": "Ofset başlangıç ​​saatleri", + "offset_toggle_description": "Belirli bir dakika sayısına göre rezervasyon yapanlara gösterilen ofset zaman aralıkları", + "offset_start_description": "örneğin; bu işlem rezervasyon yapan kişinin zaman aralıklarını {{ originalTime }} yerine {{ adjustedTime }} olarak görmesine neden olur", "slot_interval": "Zaman dilimi aralıkları", "slot_interval_default": "Etkinlik uzunluğunu kullan (varsayılan)", "delete_event_type": "Etkinlik türü silinsin mi?", @@ -911,6 +914,7 @@ "duplicate": "Çoğalt", "offer_seats": "Yer teklif et", "offer_seats_description": "Rezervasyonlar için yer teklif edin. Bu işlem, misafirleri ve rezervasyon onaylarını devre dışı bırakır.", + "seats_available_one": "Koltuk mevcut", "seats_available_other": "Yer mevcut", "number_of_seats": "Rezervasyon başına yer sayısı", "enter_number_of_seats": "Yer sayısını girin", @@ -1045,6 +1049,7 @@ "event_cancelled_trigger": "etkinlik iptal edildiğinde", "new_event_trigger": "yeni bir etkinlik için rezervasyon yapıldığında", "email_host_action": "organizatöre e-posta gönder", + "email_attendee_action": "katılımcılara e-posta gönder", "sms_attendee_action": "katılımcıya SMS gönder", "sms_number_action": "belirli bir numaraya SMS gönder", "workflows": "İş akışları", @@ -1197,6 +1202,7 @@ "create_workflow": "Bir iş akışı oluşturun", "do_this": "Bunu yap", "turn_off": "Kapat", + "turn_on": "Aç", "settings_updated_successfully": "Ayarlar başarıyla güncellendi", "error_updating_settings": "Ayarlar güncellenirken bir hata oluştu", "personal_cal_url": "Kişisel {{appName}} URL'm", @@ -1253,6 +1259,7 @@ "calendars_description": "Etkinlik türlerinizin takvimlerinizle nasıl etkileşimde bulunacağını yapılandırın", "appearance_description": "Rezervasyon görünümünüz için ayarları yönetin", "conferencing_description": "Toplantılarınız için favori video konferans uygulamalarınızı yönetin", + "add_conferencing_app": "Konferans Uygulaması Ekle", "password_description": "Hesap şifreleriniz için ayarları yönetin", "2fa_description": "Hesap şifreleriniz için ayarları yönetin", "we_just_need_basic_info": "Profil kurulumunuzu almak için sadece bazı temel bilgilere ihtiyacımız var.", @@ -1627,6 +1634,7 @@ "email_user_cta": "Daveti görüntüle", "email_no_user_invite_heading": "{{appName}} uygulamasındaki bir ekibe katılmaya davet edildiniz", "email_no_user_invite_subheading": "{{invitedBy}}, sizi {{appName}} ekibine katılmaya davet etti. {{appName}}, size ve ekibinize e-posta iletişimine ihtiyaç duymadan toplantı planlama yapma olanağı sağlayan bir etkinlik planlayıcıdır.", + "email_user_invite_subheading": "{{invitedBy}}, sizi {{appName}} uygulamasındaki `{{teamName}}` ekibine katılmaya davet etti. {{appName}}, size ve ekibinize e-posta iletişimine ihtiyaç duymadan toplantı planlama yapma olanağı sağlayan bir etkinlik planlayıcıdır.", "email_no_user_invite_steps_intro": "Ekibinizle birlikte kısa sürede ve sorunsuz planlama yapmanın keyfini çıkarmanız için birkaç adımda size rehberlik edeceğiz.", "email_no_user_step_one": "Kullanıcı adınızı seçin", "email_no_user_step_two": "Takvim hesabınızı bağlayın", @@ -1702,6 +1710,15 @@ "spot_popular_event_types_description": "Hangi etkinlik türünüzün en çok tıklandığını ve rezervasyon aldığını görün", "no_responses_yet": "Henüz yanıt yok", "this_will_be_the_placeholder": "Bu, yer tutucu olacak", + "error_booking_event": "Etkinlik rezervasyonu yapılırken bir hata oluştu, lütfen sayfayı yenileyerek tekrar deneyin", + "timeslot_missing_title": "Zaman aralığı seçilmedi", + "timeslot_missing_description": "Etkinlik rezervasyonu için lütfen bir zaman aralığı seçin.", + "timeslot_missing_cta": "Zaman aralığını seçin", + "switch_monthly": "Aylık görünüme geç", + "switch_weekly": "Haftalık görünüme geç", + "switch_multiday": "Günlük görünüme geç", + "num_locations": "{{num}} konum seçenekleri", + "select_on_next_step": "Bir sonraki adımda seç", "this_meeting_has_not_started_yet": "Bu toplantı henüz başlamadı", "this_app_requires_connected_account": "{{appName}} bağlı bir {{dependencyName}} hesabı gerektirir", "connect_app": "{{dependencyName}} hesabını bağla", @@ -1731,6 +1748,7 @@ "locked_apps_description": "Üyeler aktif uygulamaları görebilir, ancak hiçbir uygulama ayarını düzenleyemez", "locked_webhooks_description": "Üyeler aktif web kancalarını görebilir, ancak hiçbir web kancası ayarını düzenleyemez", "locked_workflows_description": "Üyeler aktif iş akışlarını görebilir, ancak hiçbir iş akışı ayarını düzenleyemez", + "locked_by_admin": "Ekip yöneticisi tarafından kilitlendi", "app_not_connected": "Bir {{appName}} hesabı bağlamadınız.", "connect_now": "Hemen bağlan", "managed_event_dialog_confirm_button_one": "{{count}} üyeyi değiştirin ve bilgilendirin", @@ -1790,7 +1808,12 @@ "complete_your_booking_subject": "Rezervasyonunuzu tamamlayın: {{title}}, {{date}}", "confirm_your_details": "Bilgilerinizi onaylayın", "currency_string": "{{amount, currency}}", + "charge_card_dialog_body": "Katılımcıdan {{amount, currency}} tahsil etmek üzeresiniz. Devam etmek istediğinizden emin misiniz?", + "charge_attendee": "Katılımcıdan {{amount, currency}} ücret tahsil edin", + "payment_app_commission": "Ödeme talep edin (işlem başına %{{paymentFeePercentage}} + {{fee, currency}} komisyon)", "email_invite_team": "{{email}} davet edildi", + "email_invite_team_bulk": "{{userCount}} kullanıcı davet edildi", + "image_size_limit_exceed": "Yüklenen resim boyutu 5 MB boyut sınırını aşmamalıdır", "need_help_embedding": "Yardıma mı ihtiyacınız var? Cal'ı Wix, Squarespace veya WordPress'e yerleştirmek için kılavuzlarımıza göz atın. Ayrıca Sıkça Sorulan Sorular bölümümüze göz atın veya gelişmiş yerleştirme seçeneklerini keşfedin.", "book_my_cal": "Cal'ımı rezerve et", "form_updated_successfully": "Form başarıyla güncellendi.", @@ -1798,5 +1821,7 @@ "disable_attendees_confirmation_emails_description": "Bu etkinlik türünde etkinlik rezerve edildiğinde katılımcılara bir e-posta gönderen en az bir iş akışı etkin.", "disable_host_confirmation_emails": "Organizatörler için varsayılan onay e-postalarını devre dışı bırakın", "disable_host_confirmation_emails_description": "Bu etkinlik türündeki bir etkinlik rezerve edildiğinde organizatörlere e-posta gönderen en az bir iş akışı etkin.", - "connect_google_workspace": "Google Workspace'i bağlayın" + "connect_google_workspace": "Google Workspace'i bağlayın", + "google_workspace_admin_tooltip": "Bu özelliği kullanmak için Çalışma Alanı Yöneticisi olmalısınız", + "first_event_type_webhook_description": "Bu etkinlik türü için ilk web kancanızı oluşturun" } diff --git a/apps/web/public/static/locales/uk/common.json b/apps/web/public/static/locales/uk/common.json index 770f29bf04..7d8c846d06 100644 --- a/apps/web/public/static/locales/uk/common.json +++ b/apps/web/public/static/locales/uk/common.json @@ -26,6 +26,8 @@ "rejection_confirmation": "Відмовити в бронюванні", "manage_this_event": "Керувати цим заходом", "invite_team_member": "Запросити учасника команди", + "invite_team_individual_segment": "Запросити фізичну особу", + "invite_team_bulk_segment": "Пакетний імпорт", "invite_team_notifcation_badge": "Запр.", "your_event_has_been_scheduled": "Захід заплановано", "your_event_has_been_scheduled_recurring": "Періодичний захід заплановано", @@ -222,6 +224,7 @@ "go_back_login": "Повернутися на сторінку входу", "error_during_login": "Сталася помилка під час входу в систему. Поверніться на екран входу та повторіть спробу.", "request_password_reset": "Надіслати лист для скидання", + "send_invite": "Надіслати запрошення", "forgot_password": "Не пам’ятаєте пароль?", "forgot": "Забули?", "done": "Готово", @@ -237,6 +240,8 @@ "set_availability": "Укажіть, коли ви доступні", "continue_without_calendar": "Продовжити без календаря", "connect_your_calendar": "Підключити календар", + "connect_your_video_app": "Підключайте улюблені відеозастосунки", + "connect_your_video_app_instructions": "Підключайте свої відеозастосунки, щоб використовувати їх у своїх типах заходів.", "connect_your_calendar_instructions": "Підключіть свій календар, щоб автоматично перевіряти, коли ви зайняті, і стежити за новими запланованими заходами.", "set_up_later": "Налаштувати пізніше", "current_time": "Поточний час", @@ -367,6 +372,7 @@ "create_webhook": "Створити вебгук", "booking_cancelled": "Бронювання скасовано", "booking_rescheduled": "Бронювання перенесено", + "recording_ready": "Посилання для завантаження запису готове", "booking_created": "Бронювання створено", "meeting_ended": "Нарада завершилася", "form_submitted": "Форму надіслано", @@ -465,6 +471,7 @@ "friday": "П’ятниця", "saturday": "Субота", "sunday": "Неділя", + "all_booked_today": "Усі заброньовані.", "slots_load_fail": "Не вдалося завантажити доступні часові вікна.", "additional_guests": "Додати гостей", "your_name": "Ваше ім’я", @@ -752,6 +759,10 @@ "new_event_type_to_book_description": "Створіть новий тип заходу, на який люди зможуть бронювати час.", "length": "Тривалість", "minimum_booking_notice": "Мінімальний час до наступного заходу", + "offset_toggle": "Змістити час початку", + "offset_toggle_description": "Проміжки часу для зміщення (у хвилинах), показані користувачам, які здійснюють бронювання", + "offset_start": "Зміщення на", + "offset_start_description": "наприклад, вони бачитимуть часові проміжки о {{ adjustedTime }} замість {{ originalTime }}", "slot_interval": "Інтервали між бронюваннями", "slot_interval_default": "Використовувати тривалість заходу (за замовчуванням)", "delete_event_type": "Видалити тип заходу?", @@ -904,6 +915,7 @@ "duplicate": "Дублювати", "offer_seats": "Запропонувати місця", "offer_seats_description": "Пропонуйте місця під час бронювання (при цьому вимикається гостьовий режим і бронювання з підтвердженням).", + "seats_available_one": "Доступне місце", "seats_available_other": "Доступні місця", "number_of_seats": "Кількість місць на одне бронювання", "enter_number_of_seats": "Введіть кількість місць", @@ -1038,6 +1050,7 @@ "event_cancelled_trigger": "у момент скасування заходу", "new_event_trigger": "у момент бронювання нового заходу", "email_host_action": "надсилати електронний лист ведучому", + "email_attendee_action": "надсилати ел. лист учасникам", "sms_attendee_action": "надсилати SMS учаснику", "sms_number_action": "надсилати SMS на певний номер", "workflows": "Робочі процеси", @@ -1190,6 +1203,7 @@ "create_workflow": "Створити робочий процес", "do_this": "Зробити це", "turn_off": "Вимкнути", + "turn_on": "Увімкнути", "settings_updated_successfully": "Параметри оновлено", "error_updating_settings": "Помилка оновлення параметрів", "personal_cal_url": "Моя персональна URL-адреса {{appName}}", @@ -1246,6 +1260,7 @@ "calendars_description": "Налаштуйте, як типи заходів мають взаємодіяти з вашими календарями", "appearance_description": "Налаштуйте варіанти оформлення свого бронювання", "conferencing_description": "Керуйте додатками для відеоконференцій і нарад", + "add_conferencing_app": "Додати застосунок Conferencing", "password_description": "Налаштуйте параметри паролів облікових записів", "2fa_description": "Налаштуйте параметри паролів облікових записів", "we_just_need_basic_info": "Щоб налаштувати ваш профіль, нам потрібні базові дані.", @@ -1620,6 +1635,7 @@ "email_user_cta": "Переглянути запрошення", "email_no_user_invite_heading": "Вас запрошено приєднатися до команди в {{appName}}", "email_no_user_invite_subheading": "{{invitedBy}} запрошує вас приєднатися до команди в {{appName}}. {{appName}} — планувальник подій, який дає змогу вам і вашій команді планувати зустрічі без тривалої переписки електронною поштою.", + "email_user_invite_subheading": "{{invitedBy}} запрошує вас приєднатися до команди «{{teamName}}» в {{appName}}. {{appName}} — планувальник подій, який дає змогу вам і вашій команді планувати зустрічі без тривалої переписки електронною поштою.", "email_no_user_invite_steps_intro": "Ми ознайомимо вас із додатком, і вже скоро ви насолоджуватиметесь плануванням зі своєю командою без жодного клопоту.", "email_no_user_step_one": "Виберіть ім’я користувача", "email_no_user_step_two": "Підключіть обліковий запис календаря", @@ -1695,6 +1711,15 @@ "spot_popular_event_types_description": "Дізнайтеся, які типи заходів мають найбільшу кількість переходів і бронювань", "no_responses_yet": "Поки немає відповідей", "this_will_be_the_placeholder": "Це заповнювач", + "error_booking_event": "Сталася помилка під час бронювання заходу, оновіть сторінку й повторіть спробу", + "timeslot_missing_title": "Не вибрано проміжок часу", + "timeslot_missing_description": "Виберіть проміжок часу для бронювання заходу.", + "timeslot_missing_cta": "Вибрати проміжок часу", + "switch_monthly": "Переключитися на перегляд місяця", + "switch_weekly": "Переключитися на перегляд тижня", + "switch_multiday": "Переключитися на перегляд дня", + "num_locations": "Варіантів розташування: {{num}}", + "select_on_next_step": "Вибрати на наступному кроці", "this_meeting_has_not_started_yet": "Ця нарада ще не почалася", "this_app_requires_connected_account": "Щоб використовувати {{appName}}, потрібно підключити обліковий запис {{dependencyName}}", "connect_app": "Підключити {{dependencyName}}", @@ -1724,6 +1749,7 @@ "locked_apps_description": "Учасники бачитимуть активні додатки, але не зможуть змінювати їх налаштування", "locked_webhooks_description": "Учасники бачитимуть активні вебгуки, але не зможуть змінювати їх налаштування", "locked_workflows_description": "Учасники бачитимуть активні робочі процеси, але не зможуть змінювати їх налаштування", + "locked_by_admin": "Заблоковано адміністратором команди", "app_not_connected": "Ви не під’єднали обліковий запис {{appName}}.", "connect_now": "Під’єднати", "managed_event_dialog_confirm_button_one": "Замінити й повідомити {{count}} учасника", @@ -1781,5 +1807,34 @@ "seats_and_no_show_fee_error": "Зараз неможливо активувати місця і стягнути плату за відсутність", "complete_your_booking": "Завершіть бронювання", "complete_your_booking_subject": "Завершіть бронювання: {{title}} від {{date}}", - "email_invite_team": "{{email}} запрошено" + "confirm_your_details": "Підтвердьте ваші дані", + "currency_string": "{{amount, currency}}", + "charge_card_dialog_body": "Ви збираєтеся списати кошти з рахунку учасника: {{amount, currency}}. Бажаєте продовжити?", + "charge_attendee": "Списати з учасника {{amount, currency}}", + "payment_app_commission": "Потрібна оплата ({{paymentFeePercentage}}% + {{fee, currency}} комісія за транзакцію)", + "email_invite_team": "{{email}} запрошено", + "email_invite_team_bulk": "Запрошено стільки користувачів: {{userCount}}", + "error_collecting_card": "Не вдалося забрати картку", + "image_size_limit_exceed": "Розмір переданого зображення не повинен перевищувати 5 МБ", + "inline_embed": "Вбудовування", + "load_inline_content": "Завантажує ваш тип заходу, вбудовуючи його у ваш інший контент на вебсайті.", + "floating_pop_up_button": "Спливаюча кнопка", + "floating_button_trigger_modal": "Додає спливаючу кнопку на ваш сайт, яка викликає модальне вікно з вашим типом заходу.", + "pop_up_element_click": "Спливаюче вікно після натискання на елемент", + "open_dialog_with_element_click": "Відкриває ваш діалог з Cal, коли хтось натискає елемент.", + "need_help_embedding": "Потрібна допомога? Перегляньте наші посібники з вбудовування Cal на Wix, Squarespace або WordPress, ознайомтеся з поширеними запитаннями або розширеними параметрами вбудовування.", + "book_my_cal": "Забронювати мій Cal", + "invite_as": "Запросити як", + "form_updated_successfully": "Форму оновлено.", + "email_not_cal_member_cta": "Приєднатися до команди", + "disable_attendees_confirmation_emails": "Вимкнути листи підтвердження за замовчуванням для учасників", + "disable_attendees_confirmation_emails_description": "Принаймні один робочий процес активний у цьому типі заходів, який надсилає лист учасникам у разі бронювання події.", + "disable_host_confirmation_emails": "Вимкнути листи підтвердження за замовчуванням для ведучого", + "disable_host_confirmation_emails_description": "Принаймні один робочий процес активний у цьому типі заходів, який надсилає лист ведучому в разі бронювання події.", + "add_an_override": "Додати перевизначення", + "import_from_google_workspace": "Імпортувати користувачів із Google Workspace", + "connect_google_workspace": "Підключити Google Workspace", + "google_workspace_admin_tooltip": "Ви повинні бути адміністратором Workspace, щоб використовувати цю функцію", + "first_event_type_webhook_description": "Створіть свій перший вебгук для цього типу заходу", + "create_for": "Створити для" } diff --git a/apps/web/public/static/locales/vi/common.json b/apps/web/public/static/locales/vi/common.json index 027f020650..fad55fea26 100644 --- a/apps/web/public/static/locales/vi/common.json +++ b/apps/web/public/static/locales/vi/common.json @@ -1,5 +1,5 @@ { - "identity_provider": "Nhà cung cấp danh tính", + "identity_provider": "Đơn vị cung cấp danh tính", "trial_days_left": "Bạn có $t(day, {\"count\": {{days}} }) còn lại trên bản thử nghiệm PRO", "day_one": "{{count}} ngày", "day_other": "{{count}} ngày", @@ -26,6 +26,8 @@ "rejection_confirmation": "Từ chối lịch hẹn", "manage_this_event": "Quản lý sự kiện này", "invite_team_member": "Mời thành viên nhóm", + "invite_team_individual_segment": "Mời cá nhân", + "invite_team_bulk_segment": "Nhập hàng loạt", "invite_team_notifcation_badge": "Mời", "your_event_has_been_scheduled": "Sự kiện của bạn đã được lên lịch", "your_event_has_been_scheduled_recurring": "Sự kiện định kỳ của bạn đã được lên lịch", @@ -70,7 +72,7 @@ "event_awaiting_approval_subject": "Đang chờ phê duyệt: {{title}} lúc {{date}}", "event_still_awaiting_approval": "Một sự kiện vẫn đang chờ bạn phê duyệt", "booking_submitted_subject": "Lịch hẹn đã được gửi: {{title}} lúc {{date}}", - "download_recording_subject": "Tải xuống bản ghi: {{title}} vào ngày {{date}}", + "download_recording_subject": "Tải xuống bản ghi âm: {{title}} vào ngày {{date}}", "download_your_recording": "Tải xuống bản ghi âm của bạn", "your_meeting_has_been_booked": "Cuộc họp của bạn đã được đặt", "event_type_has_been_rescheduled_on_time_date": "{{title}} của bạn đã được chuyển sang ngày {{date}}.", @@ -222,6 +224,7 @@ "go_back_login": "Quay lại trang đăng nhập", "error_during_login": "Đã xảy ra lỗi khi đăng nhập. Bạn hãy quay lại màn hình đăng nhập và thử lại.", "request_password_reset": "Gửi email đặt lại", + "send_invite": "Gửi lời mời", "forgot_password": "Quên mật khẩu?", "forgot": "Quên?", "done": "Xong", @@ -237,6 +240,7 @@ "set_availability": "Đặt lịch khả dụng của bạn", "continue_without_calendar": "Tiếp tục mà không có lịch", "connect_your_calendar": "Kết nối lịch của bạn", + "connect_your_video_app": "Kết nối các video yêu thích của bạn", "connect_your_calendar_instructions": "Kết nối lịch của bạn để tự động kiểm tra thời gian bận và các sự kiện mới khi chúng được lên lịch.", "set_up_later": "Thiết lập sau", "current_time": "Thời gian hiện tại", @@ -408,7 +412,7 @@ "add_time_availability": "Thêm khoảng thời gian mới", "add_an_extra_layer_of_security": "Thêm một lớp bảo mật bổ sung cho tài khoản của bạn trong trường hợp mật khẩu của bạn bị đánh cắp.", "2fa": "Xác thực hai yếu tố", - "2fa_disabled": "Xác thực đa yếu tố chỉ được bật cho chức năng xác thực qua email và mật khẩu", + "2fa_disabled": "Xác thực hai yếu tố chỉ được bật cho chức năng xác thực qua email và mật khẩu", "enable_2fa": "Bật xác thực hai yếu tố", "disable_2fa": "Tắt xác thực hai yếu tố", "disable_2fa_recommendation": "Nếu bạn cần tắt xác thực hai yếu tố, chúng tôi khuyên bạn nên bật lại nó càng sớm càng tốt.", @@ -591,9 +595,9 @@ "round_robin_description": "Luân phiên những cuộc họp giữa các thành viên trong nhóm.", "managed_event": "Sự kiện được quản lý", "username_placeholder": "tên người dùng", - "managed_event_description": "Tạo & phân phối cả cụm nhiều loại sự kiện đến các thành viên nhóm", + "managed_event_description": "Tạo & phân phối hàng loạt nhiều loại sự kiện cho các thành viên nhóm", "managed": "Được quản lý", - "managed_event_url_clarification": "\"tên người dùng\" sẽ được điền vào theo tên người dùng của những thành viên được phân công", + "managed_event_url_clarification": "\"username\" sẽ được điền vào theo tên người dùng của những thành viên được phân công", "assign_to": "Phân công cho", "add_members": "Thêm thành viên...", "count_members_one": "{{count}} thành viên", @@ -602,7 +606,7 @@ "assigned_to": "Được phân công cho", "start_assigning_members_above": "Bắt đầu phân công những thành viên bên trên", "locked_fields_admin_description": "Các thành viên sẽ không sửa được phần này", - "locked_fields_member_description": "Tuỳ chọn này do quản trị nhóm khoá lại", + "locked_fields_member_description": "Tuỳ chọn này do quản trị nhóm khóa lại", "url": "URL", "hidden": "Ẩn giấu", "readonly": "Chỉ đọc", @@ -754,11 +758,11 @@ "minimum_booking_notice": "Thời gian đệm tối thiểu", "slot_interval": "Khoảng thời gian giữa các lịch hẹn", "slot_interval_default": "Sử dụng độ dài sự kiện (mặc định)", - "delete_event_type": "Xoá loại sự kiện?", - "delete_managed_event_type": "Xoá loại sự kiện được quản lý?", + "delete_event_type": "Xóa loại sự kiện?", + "delete_managed_event_type": "Xóa loại sự kiện được quản lý?", "delete_event_type_description": "Đối với những người mà bạn chia sẻ liên kết này, họ sẽ không thể đặt lịch hẹn bằng liên kết đó được nữa.", - "delete_managed_event_type_description": "
  • Những thành viên được phân công cho loại sự kiện này cũng sẽ khiến cho loại sự kiện của họ được xoá đi.
  • Đối với những người mà bạn chia sẻ liên kết này, họ sẽ không thể đặt lịch hẹn bằng liên kết đó được nữa.
", - "confirm_delete_event_type": "Có, hãy xoá", + "delete_managed_event_type_description": "
  • Những thành viên được phân công cho loại sự kiện này cũng sẽ khiến cho loại sự kiện của họ được xóa đi.
  • Đối với những người mà bạn chia sẻ liên kết này, họ sẽ không thể đặt lịch hẹn bằng liên kết đó được nữa.
", + "confirm_delete_event_type": "Có, hãy xóa", "delete_account": "Xóa tài khoản", "confirm_delete_account": "Có, xóa tài khoản", "delete_account_confirmation_message": "Bạn có chắc chắn muốn xóa tài khoản {{appName}} của mình không? Bất kỳ ai mà bạn đã chia sẻ liên kết tài khoản của mình sẽ không thể đặt trước bằng liên kết đó nữa và mọi tùy chọn bạn đã lưu sẽ bị mất.", @@ -1154,7 +1158,7 @@ "variable_format": "Định dạng biến số", "webhook_subscriber_url_reserved": "Url ghi danh Webhook đã được lập định", "custom_input_as_variable_info": "Bỏ qua tất cả các ký tự đặc biệt của nhãn thông tin đầu vào bổ sung (chỉ dùng chữ cái và con số), dùng chữ in hoa cho tất cả các chữ cái và thay thế khoảng trắng bằng dấu gạch dưới.", - "using_booking_questions_as_variables": "Làm cách nào tôi dùng những câu hỏi lịch hẹn ở dạng tham số?", + "using_booking_questions_as_variables": "Làm thế nào để tôi có thể dùng những câu hỏi lịch hẹn ở dạng tham số?", "download_desktop_app": "Tải ứng dụng trên máy tính bàn", "set_ping_link": "Đặt liên kết Ping", "rate_limit_exceeded": "Đã vượt quá giới hạn đăng nhập", @@ -1177,7 +1181,7 @@ "event_advanced_tab_title": "Nâng cao", "event_setup_multiple_duration_error": "Thiết lập sự kiện: Nhiều khoảng thời gian cần ít nhất 1 tuỳ chọn.", "event_setup_multiple_duration_default_error": "Thiết lập sự kiện: Vui lòng chọn một khoảng thời gian mặc định hợp lệ.", - "event_setup_booking_limits_error": "Giới hạn lịch hẹn phải theo thứ tự tăng dần. [ngày,tuần,tháng,năm]", + "event_setup_booking_limits_error": "Giới hạn lịch hẹn phải theo thứ tự tăng dần. [ngày, tuần, tháng, năm]", "event_setup_duration_limits_error": "Giới hạn thời gian phải được đặt theo thứ tự tăng dần. [ngày, tuần, tháng, năm]", "select_which_cal": "Chọn lịch nào cần thêm lịch hẹn vào", "custom_event_name": "Tên sự kiện tuỳ chỉnh", @@ -1200,7 +1204,7 @@ "start_of_week": "Khởi đầu tuần", "recordings_title": "Bản ghi âm", "recording": "Bản ghi âm", - "happy_scheduling": "Đặt lịch vui", + "happy_scheduling": "Chúc bạn đặt lịch vui vẻ", "select_calendars": "Chọn lịch nào mà bạn muốn kiểm tra xung đột nhằm tránh đặt lịch hẹn trùng.", "check_for_conflicts": "Kiểm tra xung đột", "view_recordings": "Xem các bản ghi âm", @@ -1276,7 +1280,7 @@ "attendee_name_info": "Tên người tham gia lịch hẹn", "to": "Đến", "workflow_turned_on_successfully": "Đã {{offOn}} thành công dòng công việc {{workflowName}}", - "download_responses": "Tải xuống Phản hồi", + "download_responses": "Tải xuống phản hồi", "download_responses_description": "Tải xuống tất cả phản hồi vào biểu mẫu của bạn ở định dạng CSV.", "download": "Tải về", "download_recording": "Tải xuống bản ghi âm", @@ -1326,7 +1330,7 @@ "exchange_version_2013_SP1": "2013 SP1", "exchange_version_2015": "2015", "exchange_version_2016": "2016", - "routing_forms_description": "Bạn có thể thấy tất cả các biểu mẫu và định hướng mà bạn đã tạo ra ở đây.", + "routing_forms_description": "Tạo các biểu mẫu để chuyển hướng người tham dự đến đúng địa điểm", "routing_forms_send_email_owner": "Gửi email đến chủ sở hữu", "routing_forms_send_email_owner_description": "Gửi một email đến chủ sở hữu khi biểu mẫu được gửi đi", "add_new_form": "Thêm biểu mẫu mới", @@ -1380,7 +1384,7 @@ "add_limit": "Thêm giới hạn", "team_name_required": "Cần có tên nhóm", "show_attendees": "Chia sẻ thông tin người tham gia cho khách", - "how_booking_questions_as_variables": "Làm cách nào dùng những câu hỏi lịch hẹn ở dạng tham số?", + "how_booking_questions_as_variables": "Làm thế nào để dùng những câu hỏi lịch hẹn ở dạng tham số?", "format": "Định dạng", "uppercase_for_letters": "In hoa hết tất cả các chữ cái", "replace_whitespaces_underscores": "Thay thế khoảng trắng bằng dấu gạch dưới", @@ -1395,7 +1399,7 @@ "billing_help_title": "Cần gì nữa không?", "billing_help_description": "Nếu bạn cần thêm bất kỳ trợ giúp nào về thanh toán, nhóm hỗ trợ của chúng tôi luôn sẵn sàng trợ giúp.", "billing_help_cta": "Liên hệ với bộ phận hỗ trợ", - "ignore_special_characters_booking_questions": "Bỏ qua những kí tự đặc biệt trong mã định danh câu hỏi lịch hẹn. Chỉ dùng chữ cái và số", + "ignore_special_characters_booking_questions": "Bỏ qua những ký tự đặc biệt trong mã định danh câu hỏi lịch hẹn. Chỉ dùng chữ cái và số", "retry": "Thử lại", "fetching_calendars_error": "Có vấn đề khi tìm dữ liệu của bạn. Vui lòng <1>thử lại hoặc liên hệ với bộ phận hỗ trợ khách hàng.", "calendar_connection_fail": "Kết nối lịch bất thành", @@ -1488,7 +1492,7 @@ "email_subject_slug_replacement": "Một quản trị viên của nhóm đã thay thế sự kiện của bạn /{{slug}}", "email_body_slug_replacement_notice": "Một quản trị viên trên nhóm {{teamName}} đã thay thế loại sự kiện của bạn /{{slug}} bằng một loại sự kiện được quản lý mà họ kiểm soát.", "email_body_slug_replacement_info": "Liên kết của bạn sẽ tiếp tục hoạt động nhưng một số thiết lập cho nó có thể thay đổi. Bạn có thể xem lại nó trong những loại sự kiện.", - "email_body_slug_replacement_suggestion": "Nếu bạn có thắc mắc gì về loại sự kiện này, vui lòng liên lạc với quản trị viên của bạn.

Đặt lịch vui,
Nhóm Cal.com", + "email_body_slug_replacement_suggestion": "Nếu bạn có thắc mắc gì về loại sự kiện này, vui lòng liên lạc với quản trị viên của bạn.

Chúc bạn đặt lịch vui vẻ,
Nhóm Cal.com", "disable_payment_app": "Một quản trị viên đã tắt {{appName}} vốn có ảnh hưởng đến loại sự kiện {{title}}. Người tham dự vẫn có thể đặt hẹn cho loại sự kiện này nhưng sẽ được nhắc trả phí. Bạn có thể ẩn loại sự kiện này để tránh điều này cho đến khi quản trị viên kích hoạt lại phương thức thanh toán của bạn.", "payment_disabled_still_able_to_book": "Người tham dự vẫn có thể đặt hẹn cho loại sự kiện này nhưng sẽ được nhắc trả phí. Bạn có thể ẩn loại sự kiện này để tránh điều này cho đến khi quản trị viên kích hoạt lại phương thức thanh toán của bạn.", "app_disabled_with_event_type": "Quản trị viên đã tắt {{appName}} vốn có ảnh hưởng đến loại sự kiện {{title}}.", @@ -1687,9 +1691,9 @@ "add_a_new_route": "Thêm một Định hướng mới", "make_informed_decisions": "Đưa ra những quyết định sáng suốt với Insights", "make_informed_decisions_description": "Bảng điều khiển Insights của chúng tôi nằm ở bề mặt xuyên suốt nhóm bạn và hiển thị cho bạn thấy những xu hướng giúp đặt lịch nhóm và ra quyết định tốt hơn.", - "view_bookings_across": "Xem lịch hẹn ở mọi thành viên", + "view_bookings_across": "Xem lịch hẹn cho mọi thành viên", "view_bookings_across_description": "Xem ai nhận được nhiều lịch hẹn nhất và bảo đảm việc phân phối tốt nhất cho khắp nhóm", - "identify_booking_trends": "Nhận diện xu hướng lịch hẹn", + "identify_booking_trends": "Xác định xu hướng lịch hẹn", "identify_booking_trends_description": "Xem thời điểm nào trong tuần và thời điểm nào trong ngày là thời điểm phổ biến cho người đặt lịch hẹn bên bạn", "spot_popular_event_types": "Nhận ra các loại sự kiện phổ biến", "spot_popular_event_types_description": "Xem loại sự kiện nào của bạn nhận được nhiều lần nhấp chuột và nhiều lịch hẹn nhất", @@ -1707,8 +1711,8 @@ "timezone_info": "Múi giờ của người nhận", "event_end_time_variable": "Thời gian kết thúc sự kiện", "event_end_time_info": "Thời gian kết thúc sự kiện", - "cancel_url_variable": "URL huỷ lịch", - "cancel_url_info": "URL để huỷ lịch hẹn", + "cancel_url_variable": "URL hủy lịch", + "cancel_url_info": "URL để hủy lịch hẹn", "reschedule_url_variable": "URL đặt lịch lại", "reschedule_url_info": "URL để đặt lịch hẹn lại", "invalid_event_name_variables": "Có biến số không hợp lệ trong tên sự kiện của bạn", @@ -1732,10 +1736,10 @@ "managed_event_dialog_title_other": "URL /{{slug}} đã có sẵn cho {{count}} thành viên. Bạn có muốn thay thế nó?", "managed_event_dialog_information_one": "{{names}} đã dùng URL /{{slug}} rồi.", "managed_event_dialog_information_other": "{{names}} đã dùng URL /{{slug}} rồi.", - "managed_event_dialog_clarification": "Nếu bạn chọn phương án thay thế nó, chúng tôi sẽ thông báo cho họ biết. Hãy quay lại và xoá bỏ họ nếu bạn không muốn ghi đè nó.", + "managed_event_dialog_clarification": "Nếu bạn chọn phương án thay thế nó, chúng tôi sẽ thông báo cho họ biết. Hãy quay lại và xóa bỏ họ nếu bạn không muốn ghi đè nó.", "review_event_type": "Xem lại loại sự kiện", - "looking_for_more_analytics": "Đang tìm thêm công cụ phân tích?", - "looking_for_more_insights": "Đang tìm thêm Insights?", + "looking_for_more_analytics": "Bạn muốn có thêm thông tin phân tích?", + "looking_for_more_insights": "Bạn muốn có thêm Insights?", "add_filter": "Thêm bộ lọc", "select_user": "Chọn người dùng", "select_event_type": "Chọn loại sự kiện", @@ -1747,7 +1751,7 @@ "least_booked_members": "Thành viên được đặt lịch hẹn ít nhất", "events_created": "Những sự kiện đã tạo", "events_completed": "Những sự kiện đã hoàn thành", - "events_cancelled": "Những sự kiện đã huỷ", + "events_cancelled": "Những sự kiện đã hủy", "events_rescheduled": "Những sự kiện đã đặt lịch lại", "from_last_period": "từ thời gian gần nhất", "from_to_date_period": "Từ: {{startDate}} Đến: {{endDate}}", @@ -1755,11 +1759,11 @@ "subtitle_analytics": "Tìm hiểu thêm về hoạt động của nhóm bạn", "redirect_url_warning": "Thêm mục chuyển hướng sẽ tắt đi trang thành công. Hãy bảo đảm có đề cập \"Lịch hẹn đã xác nhận\" trên trang thành công tuỳ chỉnh riêng của bạn.", "event_trends": "Xu hướng sự kiện", - "clear_filters": "Xoá bộ lọc", - "hold": "Giữ đó", + "clear_filters": "Xóa bộ lọc", + "hold": "Tạm giữ", "on_booking_option": "Thu tiền thanh toán cho lịch hẹn", "hold_option": "Tính phí vắng mặt", - "card_held": "Thẻ đã được giữ", + "card_held": "Thẻ đã được tạm giữ", "charge_card": "Tính phí cho thẻ", "card_charged": "Thẻ đã thu phí", "no_show_fee_amount": "Phí vắng mặt {{amount, currency}}", @@ -1776,7 +1780,7 @@ "insights": "Insights", "testing_workflow_info_message": "Khi kiểm tra tiến độ công việc này, hãy để ý rằng Email và SMS chỉ có thể được đặt lịch trước ít nhất 1 giờ", "insights_no_data_found_for_filter": "Không tìm thấy dữ liệu cho bộ lọc hay ngày đã chọn.", - "acknowledge_booking_no_show_fee": "Tôi công nhận là nếu tôi không tham dự sự kiện này thì một khoản phí vắng mặt gồm {{amount, currency}} sẽ được áp dụng cho thẻ của tôi.", + "acknowledge_booking_no_show_fee": "Tôi công nhận là nếu tôi không tham dự sự kiện này thì một khoản phí vắng mặt là {{amount, currency}} sẽ được áp dụng cho thẻ của tôi.", "card_details": "Chi tiết thẻ", "seats_and_no_show_fee_error": "Hiện không thể kích hoạt chỗ ngồi và tính khoản phí vắng mặt", "complete_your_booking": "Hoàn thành lịch hẹn của bạn", diff --git a/apps/web/public/static/locales/zh-CN/common.json b/apps/web/public/static/locales/zh-CN/common.json index 76ddd66252..1f01304dcd 100644 --- a/apps/web/public/static/locales/zh-CN/common.json +++ b/apps/web/public/static/locales/zh-CN/common.json @@ -372,6 +372,7 @@ "create_webhook": "创建 Webhook", "booking_cancelled": "预约已取消", "booking_rescheduled": "预约已重新安排", + "recording_ready": "录制内容下载链接就绪", "booking_created": "预约已创建", "meeting_ended": "会议已结束", "form_submitted": "表格已提交", @@ -470,6 +471,7 @@ "friday": "周五", "saturday": "周六", "sunday": "周日", + "all_booked_today": "全部已预约。", "slots_load_fail": "无法加载可用的时间段。", "additional_guests": "添加访客", "your_name": "您的姓名", @@ -757,6 +759,10 @@ "new_event_type_to_book_description": "新建一个活动类型以让他人预约。", "length": "时长", "minimum_booking_notice": "最小预约通知提前时间", + "offset_toggle": "偏移开始时间", + "offset_toggle_description": "将显示给预约者的时间段偏移指定的分钟数", + "offset_start": "偏移量", + "offset_start_description": "例如,这将向您的预约者显示时间段 {{ adjustedTime }},而不是 {{ originalTime }}", "slot_interval": "时间段间隔", "slot_interval_default": "使用活动时长 (默认)", "delete_event_type": "删除活动类型?", @@ -1629,6 +1635,7 @@ "email_user_cta": "查看邀请", "email_no_user_invite_heading": "您已被邀请在 {{appName}} 加入一个团队", "email_no_user_invite_subheading": "{{invitedBy}} 已邀请您加入他们在 {{appName}} 上的团队。{{appName}} 是一个活动安排调度程序,让您和您的团队无需通过电子邮件沟通即可安排会议。", + "email_user_invite_subheading": "{{invitedBy}} 已邀请您加入他们在 {{appName}} 上的团队“{{teamName}}”。{{appName}} 是一个活动安排调度程序,让您和您的团队无需通过电子邮件沟通即可安排会议。", "email_no_user_invite_steps_intro": "我们将引导您完成几个简短步骤,您将立即与您的团队一起享受无压力的日程安排。", "email_no_user_step_one": "选择您的用户名", "email_no_user_step_two": "连接您的日历账户", @@ -1704,6 +1711,10 @@ "spot_popular_event_types_description": "查看获得最多点击和预约的活动类型", "no_responses_yet": "尚无回复", "this_will_be_the_placeholder": "这将是占位符", + "error_booking_event": "预订活动时发生错误,请刷新页面并重试", + "timeslot_missing_title": "未选择时间段", + "timeslot_missing_description": "请选择要预约活动的时间段。", + "timeslot_missing_cta": "选择时间段", "switch_monthly": "切换到每月视图", "switch_weekly": "切换到每周视图", "switch_multiday": "切换到日视图", @@ -1798,7 +1809,17 @@ "complete_your_booking_subject": "完成您的预约: {{date}} 的 {{title}}", "confirm_your_details": "确认您的详细信息", "currency_string": "{{amount, currency}}", + "charge_card_dialog_body": "您即将向参与者收取费用 {{amount, currency}}。您确定要继续吗?", + "charge_attendee": "向参与者收取费用 {{amount, currency}}", + "payment_app_commission": "需要付款({{paymentFeePercentage}}% + 每笔交易 {{fee, currency}} 佣金)", "email_invite_team": "{{email}} 已被邀请", + "email_invite_team_bulk": "{{userCount}} 名用户已被邀请", + "error_collecting_card": "收集卡时出错", + "image_size_limit_exceed": "上传的图像不应超过 5mb 大小限制", + "inline_embed": "内联嵌入", + "floating_pop_up_button": "浮动弹出式按钮", + "pop_up_element_click": "通过点击元素弹出", + "open_dialog_with_element_click": "当有人点击元素时,打开您的 Cal 对话框。", "book_my_cal": "预约我的 Cal", "invite_as": "邀请为", "form_updated_successfully": "表单更新成功。", From 35144e6f4773abe38726a65be43016c16ec958bb Mon Sep 17 00:00:00 2001 From: VasuDevrani <101383635+VasuDevrani@users.noreply.github.com> Date: Tue, 30 May 2023 19:43:17 +0530 Subject: [PATCH 037/100] fixed: x button overlap (#9198) --- .../features/form-builder/FormBuilder.tsx | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/packages/features/form-builder/FormBuilder.tsx b/packages/features/form-builder/FormBuilder.tsx index 5328e935f2..b5c3b18ad3 100644 --- a/packages/features/form-builder/FormBuilder.tsx +++ b/packages/features/form-builder/FormBuilder.tsx @@ -185,6 +185,27 @@ export const FormBuilder = function FormBuilder({ }, ]); } + + const crossButton = (index: number) => { + return ( +
))} From cae1ca8dfbf99ccd14a80bda68ac24b41d98cd14 Mon Sep 17 00:00:00 2001 From: Keith Williams Date: Tue, 30 May 2023 11:15:09 -0300 Subject: [PATCH 038/100] Replace user email with ID in logs (#9115) --- packages/trpc/server/routers/viewer/eventTypes/_router.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/trpc/server/routers/viewer/eventTypes/_router.ts b/packages/trpc/server/routers/viewer/eventTypes/_router.ts index f84760a0d2..2e57337e94 100644 --- a/packages/trpc/server/routers/viewer/eventTypes/_router.ts +++ b/packages/trpc/server/routers/viewer/eventTypes/_router.ts @@ -40,7 +40,7 @@ export const eventTypesRouter = router({ throw new Error("Failed to load handler"); } - const timer = logP(`getByViewer(${ctx.user.email})`); + const timer = logP(`getByViewer(${ctx.user.id})`); const result = await UNSTABLE_HANDLER_CACHE.getByViewer({ ctx, From 24ee3401af6a8d4e1604aa6d2d6ec682310175ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Efra=C3=ADn=20Roch=C3=ADn?= Date: Tue, 30 May 2023 07:17:11 -0700 Subject: [PATCH 039/100] Avoid exec the getAvailability function when there are`t calendar selected (#9192) Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Co-authored-by: Hariom Balhara --- packages/core/CalendarManager.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/CalendarManager.ts b/packages/core/CalendarManager.ts index 075e7a203a..99bc55240e 100644 --- a/packages/core/CalendarManager.ts +++ b/packages/core/CalendarManager.ts @@ -151,6 +151,7 @@ export const getCachedResults = async ( * TODO: Migrate credential type or appId */ const passedSelectedCalendars = selectedCalendars.filter((sc) => sc.integration === type); + if (!passedSelectedCalendars.length) return []; /** We extract external Ids so we don't cache too much */ const selectedCalendarIds = passedSelectedCalendars.map((sc) => sc.externalId); /** If we don't then we actually fetch external calendars (which can be very slow) */ From 60a3bc583269cb05771b07779498be210e84528b Mon Sep 17 00:00:00 2001 From: VasuDevrani <101383635+VasuDevrani@users.noreply.github.com> Date: Tue, 30 May 2023 19:48:21 +0530 Subject: [PATCH 040/100] feat: sidebar nav item tooltips (#9160) Co-authored-by: Peer Richelsen --- packages/features/shell/Shell.tsx | 3 +++ packages/ui/components/tooltip/Tooltip.tsx | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/features/shell/Shell.tsx b/packages/features/shell/Shell.tsx index 9e85062717..89427593b3 100644 --- a/packages/features/shell/Shell.tsx +++ b/packages/features/shell/Shell.tsx @@ -41,6 +41,7 @@ import { HeadSeo, Logo, SkeletonText, + Tooltip, showToast, useCalcomTheme, } from "@calcom/ui"; @@ -618,6 +619,7 @@ const NavigationItem: React.FC<{ return ( + )} + {item.child && isCurrent({ router, isChild, item }) && item.child.map((item, index) => )} diff --git a/packages/ui/components/tooltip/Tooltip.tsx b/packages/ui/components/tooltip/Tooltip.tsx index 8bb744eda2..79162aa3ad 100644 --- a/packages/ui/components/tooltip/Tooltip.tsx +++ b/packages/ui/components/tooltip/Tooltip.tsx @@ -30,14 +30,15 @@ export function Tooltip({ {children} + align="center"> {content} From 6daa69cff9bdab2b2cb5dc2a597c7dafe353e98b Mon Sep 17 00:00:00 2001 From: VasuDevrani <101383635+VasuDevrani@users.noreply.github.com> Date: Tue, 30 May 2023 19:48:49 +0530 Subject: [PATCH 041/100] fix: loader animation in profile update button (#9162) Co-authored-by: Peer Richelsen --- apps/web/pages/settings/my-account/profile.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/web/pages/settings/my-account/profile.tsx b/apps/web/pages/settings/my-account/profile.tsx index 6116bcaa9d..a9dde1a8c8 100644 --- a/apps/web/pages/settings/my-account/profile.tsx +++ b/apps/web/pages/settings/my-account/profile.tsx @@ -203,6 +203,7 @@ const ProfileView = () => { { if (values.email !== user.email && isCALIdentityProviver) { setTempFormValues(values); @@ -314,10 +315,12 @@ const ProfileForm = ({ defaultValues, onSubmit, extraField, + isLoading = false, }: { defaultValues: FormValues; onSubmit: (values: FormValues) => void; extraField?: React.ReactNode; + isLoading: boolean; }) => { const { t } = useLocale(); const [firstRender, setFirstRender] = useState(true); @@ -390,7 +393,7 @@ const ProfileForm = ({ setFirstRender={setFirstRender} /> - From fba2a2e2ca445631bfee8347483877a5a9b92315 Mon Sep 17 00:00:00 2001 From: Hariom Balhara Date: Tue, 30 May 2023 19:53:49 +0530 Subject: [PATCH 042/100] test: Two Factor Auth (#9142) * Fix 2 Factor Auth * Add 2fa tests --- .../settings/DisableTwoFactorModal.tsx | 2 +- .../settings/EnableTwoFactorModal.tsx | 18 +- .../settings/security/two-factor-auth.tsx | 1 + apps/web/playwright/auth/auth-index.e2e.ts | 3 - apps/web/playwright/login.2fa.e2e.ts | 156 ++++++++++++++++++ 5 files changed, 172 insertions(+), 8 deletions(-) create mode 100644 apps/web/playwright/login.2fa.e2e.ts diff --git a/apps/web/components/settings/DisableTwoFactorModal.tsx b/apps/web/components/settings/DisableTwoFactorModal.tsx index fd427e368c..987d4d6e81 100644 --- a/apps/web/components/settings/DisableTwoFactorModal.tsx +++ b/apps/web/components/settings/DisableTwoFactorModal.tsx @@ -90,7 +90,7 @@ const DisableTwoFactorAuthModal = ({
-
-

{secret}

+

+ {secret} +

@@ -164,7 +166,11 @@ const EnableTwoFactorModal = ({ onEnable, onCancel, open, onOpenChange }: Enable
- {errorMessage &&

{errorMessage}

} + {errorMessage && ( +

+ {errorMessage} +

+ )}
@@ -178,12 +184,16 @@ const EnableTwoFactorModal = ({ onEnable, onCancel, open, onOpenChange }: Enable - - diff --git a/apps/web/pages/settings/security/two-factor-auth.tsx b/apps/web/pages/settings/security/two-factor-auth.tsx index 811f9d2d03..9c0e74dd46 100644 --- a/apps/web/pages/settings/security/two-factor-auth.tsx +++ b/apps/web/pages/settings/security/two-factor-auth.tsx @@ -40,6 +40,7 @@ const TwoFactorAuthView = () => { {!isCalProvider && }
diff --git a/apps/web/playwright/auth/auth-index.e2e.ts b/apps/web/playwright/auth/auth-index.e2e.ts index fac393621f..19c568bb14 100644 --- a/apps/web/playwright/auth/auth-index.e2e.ts +++ b/apps/web/playwright/auth/auth-index.e2e.ts @@ -1,5 +1,4 @@ import { test } from "../lib/fixtures"; -import { todo } from "../lib/testUtils"; test.describe("Can signup from a team invite", async () => { test.beforeEach(async ({ users }) => { @@ -96,5 +95,3 @@ test.describe("Can signup from a team invite", async () => { expect(createdUser.teams[0].accepted).toBe(true);*/ }); }); - -todo("Can login using 2FA"); diff --git a/apps/web/playwright/login.2fa.e2e.ts b/apps/web/playwright/login.2fa.e2e.ts new file mode 100644 index 0000000000..2a869e5763 --- /dev/null +++ b/apps/web/playwright/login.2fa.e2e.ts @@ -0,0 +1,156 @@ +import type { Page } from "@playwright/test"; +import { expect } from "@playwright/test"; +import { authenticator } from "otplib"; + +import { symmetricDecrypt } from "@calcom/lib/crypto"; + +import { test } from "./lib/fixtures"; + +test.describe.configure({ mode: "parallel" }); + +// a test to logout requires both a succesfull login as logout, to prevent +// a doubling of tests failing on logout & logout, we can group them. +test.describe("2FA Tests", async () => { + test.afterAll(async ({ users }) => { + await users.deleteAll(); + }); + test("should allow a user to enable 2FA and login using 2FA", async ({ page, users }) => { + // log in trail user + const user = await test.step("Enable 2FA", async () => { + const user = await users.create(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const userPassword = user.username!; + await user.login(); + + // expects the home page for an authorized user + await page.goto("/settings/security/two-factor-auth"); + await page.click(`[data-testid=two-factor-switch]`); + await page.fill('input[name="password"]', userPassword); + await page.press('input[name="password"]', "Enter"); + const secret = await page.locator(`[data-testid=two-factor-secret]`).textContent(); + expect(secret).toHaveLength(32); + await page.click('[data-testid="goto-otp-screen"]'); + + /** + * Try a wrong code and test that wrong code is rejected. + */ + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + await fillOtp({ page, secret: "123456", noRetry: true }); + await page.press('input[name="2fa6"]', "Enter"); + await expect(page.locator('[data-testid="error-submitting-code"]')).toBeVisible(); + + await fillOtp({ + page, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + secret: secret!, + }); + await page.press('input[name="2fa6"]', "Enter"); + + await expect(page.locator(`[data-testid=two-factor-switch][data-state="checked"]`)).toBeVisible(); + + return user; + }); + + await test.step("Logout", async () => { + await page.goto("/auth/logout"); + }); + + await test.step("Login with 2FA enabled", async () => { + await user.login(); + const userWith2FaSecret = await prisma?.user.findFirst({ + where: { + id: user.id, + }, + }); + + const secret = symmetricDecrypt( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + userWith2FaSecret!.twoFactorSecret!, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + process.env.CALENDSO_ENCRYPTION_KEY! + ); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + await fillOtp({ page, secret: secret! }); + await Promise.all([ + page.press('input[name="2fa6"]', "Enter"), + page.waitForResponse("**/api/auth/callback/credentials**"), + ]); + const shellLocator = page.locator(`[data-testid=dashboard-shell]`); + + // expects the home page for an authorized user + await page.goto("/"); + await expect(shellLocator).toBeVisible(); + }); + }); + + test("should allow a user to disable 2FA", async ({ page, users }) => { + // log in trail user + const user = await test.step("Enable 2FA", async () => { + const user = await users.create(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const userPassword = user.username!; + await user.login(); + + // expects the home page for an authorized user + await page.goto("/settings/security/two-factor-auth"); + await page.click(`[data-testid=two-factor-switch][data-state="unchecked"]`); + await page.fill('input[name="password"]', userPassword); + await page.press('input[name="password"]', "Enter"); + const secret = await page.locator(`[data-testid=two-factor-secret]`).textContent(); + expect(secret).toHaveLength(32); + await page.click('[data-testid="goto-otp-screen"]'); + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + await fillOtp({ page, secret: secret! }); + await page.click('[data-testid="enable-2fa"]'); + await expect(page.locator(`[data-testid=two-factor-switch][data-state="checked"]`)).toBeVisible(); + + return user; + }); + + await test.step("Disable 2FA", async () => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const userPassword = user.username!; + + // expects the home page for an authorized user + await page.goto("/settings/security/two-factor-auth"); + await page.click(`[data-testid=two-factor-switch][data-state="checked"]`); + await page.fill('input[name="password"]', userPassword); + + const userWith2FaSecret = await prisma?.user.findFirst({ + where: { + id: user.id, + }, + }); + + const secret = symmetricDecrypt( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + userWith2FaSecret!.twoFactorSecret!, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + process.env.CALENDSO_ENCRYPTION_KEY! + ); + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + await fillOtp({ page, secret: secret! }); + await page.click('[data-testid="disable-2fa"]'); + await expect(page.locator(`[data-testid=two-factor-switch][data-state="unchecked"]`)).toBeVisible(); + + return user; + }); + }); +}); + +async function fillOtp({ page, secret, noRetry }: { page: Page; secret: string; noRetry?: boolean }) { + let token = authenticator.generate(secret); + if (!noRetry && !authenticator.check(token, secret)) { + console.log("Token expired, Renerating."); + // Maybe token was just about to expire, try again just once more + token = authenticator.generate(secret); + } + await page.fill('input[name="2fa1"]', token[0]); + await page.fill('input[name="2fa2"]', token[1]); + await page.fill('input[name="2fa3"]', token[2]); + await page.fill('input[name="2fa4"]', token[3]); + await page.fill('input[name="2fa5"]', token[4]); + await page.fill('input[name="2fa6"]', token[5]); +} From a062b5a355459b393a34b2b6b6a4983a7f716651 Mon Sep 17 00:00:00 2001 From: Sai Deepesh Date: Tue, 30 May 2023 19:54:17 +0530 Subject: [PATCH 043/100] chore: translation for unauthorized workflow error (#8573) * fix: translation for unauthorized workflow error * change to dynamic string --------- Co-authored-by: Peer Richelsen Co-authored-by: alannnc Co-authored-by: Alex van Andel --- apps/web/public/static/locales/en/common.json | 1 + .../ee/workflows/components/EventWorkflowsTab.tsx | 9 ++++++--- packages/features/shell/Shell.tsx | 6 +++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index 4aecb5157e..489551a783 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -1816,6 +1816,7 @@ "email_invite_team_bulk": "{{userCount}} users have been invited", "error_collecting_card": "Error collecting card", "image_size_limit_exceed": "Uploaded image shouldn't exceed 5mb size limit", + "unauthorized_workflow_error_message": "{{errorCode}}: You are not authorized to enable or disable this workflow", "inline_embed": "Inline Embed", "load_inline_content": "Loads your event type directly inline with your other website content.", "floating_pop_up_button": "Floating pop-up button", diff --git a/packages/features/ee/workflows/components/EventWorkflowsTab.tsx b/packages/features/ee/workflows/components/EventWorkflowsTab.tsx index d8b018e71f..3ef8c58685 100644 --- a/packages/features/ee/workflows/components/EventWorkflowsTab.tsx +++ b/packages/features/ee/workflows/components/EventWorkflowsTab.tsx @@ -71,9 +71,12 @@ const WorkflowListItem = (props: ItemProps) => { showToast(message, "error"); } if (err.data?.code === "UNAUTHORIZED") { - // TODO: Add missing translation - const message = `${err.data.code}: You are not authorized to enable or disable this workflow`; - showToast(message, "error"); + showToast( + t("unauthorized_workflow_error_message", { + errorCode: err.data.code, + }), + "error" + ); } }, }); diff --git a/packages/features/shell/Shell.tsx b/packages/features/shell/Shell.tsx index 89427593b3..690ec1c50c 100644 --- a/packages/features/shell/Shell.tsx +++ b/packages/features/shell/Shell.tsx @@ -310,11 +310,11 @@ function UserDropdown({ small }: { small?: boolean }) { {!small && ( - - + + {user.name || "Nameless User"} - + {user.username ? process.env.NEXT_PUBLIC_WEBSITE_URL === "https://cal.com" ? `cal.com/${user.username}` From 5bca02bac28bed5451ed3fa01aa5f596aed6e0d5 Mon Sep 17 00:00:00 2001 From: Peer Richelsen Date: Tue, 30 May 2023 15:25:56 +0100 Subject: [PATCH 044/100] fix: full name of app authors and added correct urls (#9099) Co-authored-by: Hariom Balhara --- apps/web/components/apps/App.tsx | 7 +++++-- packages/app-store/amie/config.json | 2 +- packages/app-store/around/config.json | 2 +- packages/app-store/campfire/config.json | 2 +- packages/app-store/closecom/config.json | 4 ++-- packages/app-store/cron/config.json | 4 ++-- packages/app-store/eightxeight/config.json | 10 ++++------ packages/app-store/exchangecalendar/config.json | 2 +- packages/app-store/facetime/config.json | 4 ++-- packages/app-store/fathom/config.json | 2 +- packages/app-store/metapixel/config.json | 4 ++-- packages/app-store/mirotalk/config.json | 8 +++----- packages/app-store/n8n/config.json | 2 +- packages/app-store/plausible/config.json | 2 +- packages/app-store/qr_code/config.json | 2 +- packages/app-store/rainbow/config.json | 2 +- packages/app-store/raycast/config.json | 4 ++-- packages/app-store/riverside/config.json | 4 ++-- packages/app-store/routing-forms/config.json | 6 +++--- packages/app-store/salesforce/config.json | 4 ++-- packages/app-store/sendgrid/config.json | 4 ++-- packages/app-store/signal/config.json | 2 +- packages/app-store/sirius_video/config.json | 2 +- packages/app-store/sylapsvideo/config.json | 2 +- packages/app-store/telegram/config.json | 2 +- packages/app-store/typeform/config.json | 4 ++-- packages/app-store/vimcal/config.json | 2 +- .../app-store/weather_in_your_calendar/config.json | 4 ++-- packages/app-store/webex/config.json | 4 ++-- packages/app-store/whatsapp/config.json | 2 +- packages/app-store/whereby/config.json | 4 ++-- packages/app-store/zoho-bigin/config.json | 4 ++-- packages/app-store/zohocrm/config.json | 4 ++-- 33 files changed, 58 insertions(+), 59 deletions(-) diff --git a/apps/web/components/apps/App.tsx b/apps/web/components/apps/App.tsx index 3f866ebee5..2d74b26300 100644 --- a/apps/web/components/apps/App.tsx +++ b/apps/web/components/apps/App.tsx @@ -129,7 +129,10 @@ const Component = ({ className="bg-subtle text-emphasis rounded-md p-1 text-xs capitalize"> {categories[0]} {" "} - • {t("published_by", { author })} + •{" "} + + {t("published_by", { author })} + {isTemplate && ( @@ -257,7 +260,7 @@ const Component = ({ )} -

{t("learn_more")}

+

{t("contact")}

    {docs && (
  • diff --git a/packages/app-store/amie/config.json b/packages/app-store/amie/config.json index cd7c7d06b9..74a9210dc5 100644 --- a/packages/app-store/amie/config.json +++ b/packages/app-store/amie/config.json @@ -4,7 +4,7 @@ "slug": "amie", "type": "amie_other", "logo": "icon.svg", - "url": "https://cal.com/apps/amie", + "url": "https://cal.com", "variant": "other", "categories": ["calendar"], "publisher": "Cal.com, Inc.", diff --git a/packages/app-store/around/config.json b/packages/app-store/around/config.json index f678b8f317..a3e84f3fea 100644 --- a/packages/app-store/around/config.json +++ b/packages/app-store/around/config.json @@ -5,7 +5,7 @@ "slug": "around", "type": "around_video", "logo": "icon.svg", - "url": "https://cal.com/apps/around", + "url": "https://cal.com/", "variant": "conferencing", "categories": ["video"], "publisher": "Cal.com", diff --git a/packages/app-store/campfire/config.json b/packages/app-store/campfire/config.json index 54b32fa9a8..0397c12423 100644 --- a/packages/app-store/campfire/config.json +++ b/packages/app-store/campfire/config.json @@ -4,7 +4,7 @@ "slug": "campfire", "type": "campfire_video", "logo": "icon.svg", - "url": "https://cal.com/apps/campfire", + "url": "https://cal.com/", "variant": "conferencing", "categories": ["video"], "publisher": "Cal.com, Inc.", diff --git a/packages/app-store/closecom/config.json b/packages/app-store/closecom/config.json index dba31259e2..24d8e2ccf0 100644 --- a/packages/app-store/closecom/config.json +++ b/packages/app-store/closecom/config.json @@ -5,10 +5,10 @@ "slug": "closecom", "type": "closecom_other_calendar", "logo": "icon.svg", - "url": "https://cal.com/apps/closecom", + "url": "https://cal.com/", "variant": "other", "categories": ["other"], - "publisher": "Cal.com", + "publisher": "Cal.com, Inc.", "email": "help@cal.com", "description": "Close is the inside sales CRM of choice for startups and SMBs. Make more calls, send more emails and close more deals starting today.", "__createdUsingCli": true diff --git a/packages/app-store/cron/config.json b/packages/app-store/cron/config.json index 955e73e41b..8399314b1e 100644 --- a/packages/app-store/cron/config.json +++ b/packages/app-store/cron/config.json @@ -4,10 +4,10 @@ "slug": "cron", "type": "cron_other", "logo": "logo.png", - "url": "https://cal.com/apps/cron", + "url": "https://github.com/miguelnietoa", "variant": "other", "categories": ["calendar"], - "publisher": "miguelnietoa", + "publisher": "Miguel Nieto", "email": "support@cal.com", "description": "Cron is the next-generation calendar for professionals and teams.", "isTemplate": false, diff --git a/packages/app-store/eightxeight/config.json b/packages/app-store/eightxeight/config.json index 781a2a1348..3b6701edad 100644 --- a/packages/app-store/eightxeight/config.json +++ b/packages/app-store/eightxeight/config.json @@ -4,12 +4,10 @@ "slug": "eightxeight", "type": "eightxeight_video", "logo": "icon.svg", - "url": "https://cal.com/apps/eightxeight", + "url": "https://github.com/shivamklr", "variant": "conferencing", - "categories": [ - "video" - ], - "publisher": "shivamklr", + "categories": ["video"], + "publisher": "Shivam Kalra", "email": "shivamkalra98@gmail.com", "appData": { "location": { @@ -25,4 +23,4 @@ "__createdUsingCli": true, "__template": "event-type-location-video-static", "dirName": "eightxeight" -} \ No newline at end of file +} diff --git a/packages/app-store/exchangecalendar/config.json b/packages/app-store/exchangecalendar/config.json index d49c3e4de5..113fef68a6 100644 --- a/packages/app-store/exchangecalendar/config.json +++ b/packages/app-store/exchangecalendar/config.json @@ -6,7 +6,7 @@ "dirName": "exchangecalendar", "type": "exchange_calendar", "logo": "icon.svg", - "url": "https://cal.com/apps/exchange", + "url": "https://cal.com", "variant": "calendar", "categories": ["calendar"], "publisher": "Cal.com", diff --git a/packages/app-store/facetime/config.json b/packages/app-store/facetime/config.json index 671999675c..6e4e4177b6 100644 --- a/packages/app-store/facetime/config.json +++ b/packages/app-store/facetime/config.json @@ -5,10 +5,10 @@ "slug": "facetime", "type": "facetime_video", "logo": "icon.svg", - "url": "https://cal.com/apps/facetime", + "url": "https://github.com/Mythie", "variant": "conferencing", "categories": ["video"], - "publisher": "Mythie", + "publisher": "Lucas Smith", "email": "help@cal.com", "description": "Facetime makes it super simple for collaborating teams to jump on a video call.", "__createdUsingCli": true, diff --git a/packages/app-store/fathom/config.json b/packages/app-store/fathom/config.json index cf60fdfea1..b491e51160 100644 --- a/packages/app-store/fathom/config.json +++ b/packages/app-store/fathom/config.json @@ -4,7 +4,7 @@ "slug": "fathom", "type": "fathom_analytics", "logo": "icon.svg", - "url": "https://cal.com/apps/fathom", + "url": "https://cal.com", "variant": "analytics", "categories": ["analytics"], "publisher": "Cal.com, Inc.", diff --git a/packages/app-store/metapixel/config.json b/packages/app-store/metapixel/config.json index 7edc9dacb1..7d055c3b49 100644 --- a/packages/app-store/metapixel/config.json +++ b/packages/app-store/metapixel/config.json @@ -3,10 +3,10 @@ "slug": "metapixel", "type": "metapixel_analytics", "logo": "icon.svg", - "url": "https://developers.facebook.com/docs/metapixel/", + "url": "https://github.com/regexyl", "variant": "analytics", "categories": ["analytics"], - "publisher": "regexyl", + "publisher": "Regina Liu", "email": "info@regexyl.com", "description": "Add Meta Pixel to your bookings page to measure, optimize and build audiences for your ad campaigns.", "extendsFeature": "EventType", diff --git a/packages/app-store/mirotalk/config.json b/packages/app-store/mirotalk/config.json index 5732aa6408..6c1e05f86c 100644 --- a/packages/app-store/mirotalk/config.json +++ b/packages/app-store/mirotalk/config.json @@ -4,11 +4,9 @@ "slug": "mirotalk", "type": "mirotalk_video", "logo": "icon.svg", - "url": "https://cal.com/apps/mirotalk", + "url": "https://cal.com/", "variant": "conferencing", - "categories": [ - "video" - ], + "categories": ["video"], "publisher": "Cal.com, Inc.", "email": "support@cal.com", "appData": { @@ -25,4 +23,4 @@ "__createdUsingCli": true, "__template": "event-type-location-video-static", "dirName": "mirotalk" -} \ No newline at end of file +} diff --git a/packages/app-store/n8n/config.json b/packages/app-store/n8n/config.json index 6fbee1ccfd..1b6cec2091 100644 --- a/packages/app-store/n8n/config.json +++ b/packages/app-store/n8n/config.json @@ -4,7 +4,7 @@ "slug": "n8n", "type": "n8n_automation", "logo": "icon.svg", - "url": "https://cal.com/apps/n8n", + "url": "https://cal.com/", "variant": "automation", "categories": ["automation"], "publisher": "Cal.com, Inc.", diff --git a/packages/app-store/plausible/config.json b/packages/app-store/plausible/config.json index 5e41e7eb08..2fa2baee89 100644 --- a/packages/app-store/plausible/config.json +++ b/packages/app-store/plausible/config.json @@ -4,7 +4,7 @@ "slug": "plausible", "type": "plausible_analytics", "logo": "icon.svg", - "url": "https://cal.com/apps/plausible", + "url": "https://cal.com/", "variant": "analytics", "categories": ["analytics"], "publisher": "Cal.com, Inc.", diff --git a/packages/app-store/qr_code/config.json b/packages/app-store/qr_code/config.json index 27d32efdba..3597091bbd 100644 --- a/packages/app-store/qr_code/config.json +++ b/packages/app-store/qr_code/config.json @@ -4,7 +4,7 @@ "slug": "qr_code", "type": "qr_code_other", "logo": "icon.svg", - "url": "https://cal.com/apps/qr_code", + "url": "https://cal.com/", "variant": "other", "categories": ["other"], "extendsFeature": "EventType", diff --git a/packages/app-store/rainbow/config.json b/packages/app-store/rainbow/config.json index c02784d3d2..59bf088ed2 100644 --- a/packages/app-store/rainbow/config.json +++ b/packages/app-store/rainbow/config.json @@ -4,7 +4,7 @@ "slug": "rainbow", "type": "rainbow_web3", "logo": "icon.svg", - "url": "https://cal.com/apps/rainbow", + "url": "https://github.com/hexcowboy", "variant": "web3", "categories": ["web3"], "extendsFeature": "EventType", diff --git a/packages/app-store/raycast/config.json b/packages/app-store/raycast/config.json index 7cf2906ee3..860dcc3284 100644 --- a/packages/app-store/raycast/config.json +++ b/packages/app-store/raycast/config.json @@ -4,10 +4,10 @@ "slug": "raycast", "type": "raycast_other", "logo": "icon.svg", - "url": "https://cal.com/apps/raycast", + "url": "https://github.com/eluce2", "variant": "other", "categories": ["other"], - "publisher": "eluce2", + "publisher": "Eric Luce", "email": "info@restlessmindstech.com", "description": "Quickly share your Cal.com meeting links with Raycast", "__createdUsingCli": true diff --git a/packages/app-store/riverside/config.json b/packages/app-store/riverside/config.json index f32a84d95b..114ba75221 100644 --- a/packages/app-store/riverside/config.json +++ b/packages/app-store/riverside/config.json @@ -4,10 +4,10 @@ "slug": "riverside", "type": "riverside_video", "logo": "icon-dark.svg", - "url": "https://cal.com/apps/riverside", + "url": "https://cal.com/", "variant": "conferencing", "categories": ["video"], - "publisher": "Cal.com", + "publisher": "Cal.com, Inc.", "email": "help@cal.com", "description": "Your online recording studio. The easiest way to record podcasts and videos in studio quality from anywhere. All from the browser.", "__createdUsingCli": true, diff --git a/packages/app-store/routing-forms/config.json b/packages/app-store/routing-forms/config.json index 1dc24b1d2f..729c1d712a 100644 --- a/packages/app-store/routing-forms/config.json +++ b/packages/app-store/routing-forms/config.json @@ -5,15 +5,15 @@ "slug": "routing-forms", "type": "routing-forms_other", "logo": "icon-dark.svg", - "url": "https://cal.com/apps/routing-forms", + "url": "https://cal.com/resources/feature/routing-forms", "variant": "other", "categories": ["other"], - "publisher": "Cal.com", + "publisher": "Cal.com, Inc.", "email": "help@cal.com", "licenseRequired": true, "teamsPlanRequired": { "upgradeUrl": "/apps/routing-forms/forms" - }, + }, "description": "It would allow a booker to connect with the right person or choose the right event, faster. It would work by taking inputs from the booker and using that data to route to the correct booker/event as configured by Cal user", "__createdUsingCli": true } diff --git a/packages/app-store/salesforce/config.json b/packages/app-store/salesforce/config.json index 31a93fc0f5..1fd4591aee 100644 --- a/packages/app-store/salesforce/config.json +++ b/packages/app-store/salesforce/config.json @@ -4,10 +4,10 @@ "slug": "salesforce", "type": "salesforce_other_calendar", "logo": "icon.png", - "url": "https://cal.com/apps/salesforce", + "url": "https://cal.com/", "variant": "other_calendar", "categories": ["other"], - "publisher": "Cal.com", + "publisher": "Cal.com, Inc.", "email": "help@cal.com", "description": "Salesforce (Sales Cloud) is a cloud-based application designed to help your salespeople sell smarter and faster by centralizing customer information, logging their interactions with your company, and automating many of the tasks salespeople do every day.", "__createdUsingCli": true diff --git a/packages/app-store/sendgrid/config.json b/packages/app-store/sendgrid/config.json index a224a85480..3f15a92402 100644 --- a/packages/app-store/sendgrid/config.json +++ b/packages/app-store/sendgrid/config.json @@ -4,10 +4,10 @@ "slug": "sendgrid", "type": "sendgrid_other_calendar", "logo": "logo.png", - "url": "https://cal.com/apps/sendgrid", + "url": "https://cal.com/", "variant": "other_calendar", "categories": ["other"], - "publisher": "Cal.com", + "publisher": "Cal.com, Inc.", "email": "help@cal.com", "description": "SendGrid delivers your transactional and marketing emails through the world's largest cloud-based email delivery platform.", "__createdUsingCli": true diff --git a/packages/app-store/signal/config.json b/packages/app-store/signal/config.json index 087dab979e..d7df95a8e3 100644 --- a/packages/app-store/signal/config.json +++ b/packages/app-store/signal/config.json @@ -4,7 +4,7 @@ "slug": "signal", "type": "signal_video", "logo": "icon.svg", - "url": "https://cal.com/apps/signal", + "url": "https://cal.com/", "variant": "conferencing", "categories": ["video"], "publisher": "Cal.com, Inc.", diff --git a/packages/app-store/sirius_video/config.json b/packages/app-store/sirius_video/config.json index 4a4ef0c734..da8952fdae 100644 --- a/packages/app-store/sirius_video/config.json +++ b/packages/app-store/sirius_video/config.json @@ -4,7 +4,7 @@ "slug": "sirius_video", "type": "sirius_video_video", "logo": "icon-dark.svg", - "url": "https://cal.com/apps/sirius_video", + "url": "https://cal.com/", "variant": "conferencing", "categories": ["video"], "publisher": "Cal.com, Inc.", diff --git a/packages/app-store/sylapsvideo/config.json b/packages/app-store/sylapsvideo/config.json index e225795664..ad9a3f5ad9 100644 --- a/packages/app-store/sylapsvideo/config.json +++ b/packages/app-store/sylapsvideo/config.json @@ -5,7 +5,7 @@ "slug": "sylapsvideo", "type": "sylaps_video", "logo": "icon.svg", - "url": "https://cal.com/apps/sylaps", + "url": "https://sylaps.com", "variant": "conferencing", "categories": ["video"], "publisher": "Sylaps Inc", diff --git a/packages/app-store/telegram/config.json b/packages/app-store/telegram/config.json index f30ce1e7a7..69013fea3a 100644 --- a/packages/app-store/telegram/config.json +++ b/packages/app-store/telegram/config.json @@ -4,7 +4,7 @@ "slug": "telegram", "type": "telegram_video", "logo": "icon.svg", - "url": "https://cal.com/apps/telegram", + "url": "https://cal.com/", "variant": "conferencing", "categories": ["video"], "publisher": "Cal.com, Inc.", diff --git a/packages/app-store/typeform/config.json b/packages/app-store/typeform/config.json index 4dd2467ad4..8e42bcb56b 100644 --- a/packages/app-store/typeform/config.json +++ b/packages/app-store/typeform/config.json @@ -4,10 +4,10 @@ "slug": "typeform", "type": "typeform_other", "logo": "icon-dark.svg", - "url": "https://cal.com/apps/typeform", + "url": "https://cal.com/", "variant": "other", "categories": ["other"], - "publisher": "Cal.com", + "publisher": "Cal.com, Inc.", "email": "help@cal.com", "description": "Adds a link to copy Typeform Redirect URL", "__createdUsingCli": true, diff --git a/packages/app-store/vimcal/config.json b/packages/app-store/vimcal/config.json index 96c9d9ac7b..f38f25ad8f 100644 --- a/packages/app-store/vimcal/config.json +++ b/packages/app-store/vimcal/config.json @@ -4,7 +4,7 @@ "slug": "vimcal", "type": "vimcal_other", "logo": "icon.svg", - "url": "https://cal.com/apps/vimcal", + "url": "https://cal.com/", "variant": "other", "categories": ["calendar"], "publisher": "Cal.com, Inc.", diff --git a/packages/app-store/weather_in_your_calendar/config.json b/packages/app-store/weather_in_your_calendar/config.json index 751057a54c..e7769ebd57 100644 --- a/packages/app-store/weather_in_your_calendar/config.json +++ b/packages/app-store/weather_in_your_calendar/config.json @@ -4,10 +4,10 @@ "slug": "weather_in_your_calendar", "type": "weather_in_your_calendar_other", "logo": "icon.svg", - "url": "https://weather-in-calendar.com", + "url": "https://github.com/vejnoe", "variant": "other", "categories": ["other"], - "publisher": "vejnoe", + "publisher": "Andreas Vejnø Andersen", "email": "info@vejnoe.dk", "description": "Get the local weather forecast with icons in your calendar\r\r", "__createdUsingCli": true diff --git a/packages/app-store/webex/config.json b/packages/app-store/webex/config.json index c2737bad52..b9aaa61bcb 100644 --- a/packages/app-store/webex/config.json +++ b/packages/app-store/webex/config.json @@ -6,10 +6,10 @@ "type": "webex_video", "imageSrc": "/icon.ico", "logo": "/icon.ico", - "url": "https://cal.com/apps/webex", + "url": "https://github.com/aar2dee2", "variant": "conferencing", "categories": ["video"], - "publisher": "Cal.com, Inc.", + "publisher": "aar2dee2", "email": "support@cal.com", "description": "Create meetings with Cisco Webex", "appData": { diff --git a/packages/app-store/whatsapp/config.json b/packages/app-store/whatsapp/config.json index 7ac388cfd7..2d39976cea 100644 --- a/packages/app-store/whatsapp/config.json +++ b/packages/app-store/whatsapp/config.json @@ -4,7 +4,7 @@ "slug": "whatsapp", "type": "whatsapp_video", "logo": "icon.svg", - "url": "https://cal.com/apps/whatsapp", + "url": "https://cal.com/", "variant": "conferencing", "categories": ["video"], "publisher": "Cal.com, Inc.", diff --git a/packages/app-store/whereby/config.json b/packages/app-store/whereby/config.json index 6607fada11..c7787f97da 100644 --- a/packages/app-store/whereby/config.json +++ b/packages/app-store/whereby/config.json @@ -5,10 +5,10 @@ "slug": "whereby", "type": "whereby_video", "logo": "icon-dark.svg", - "url": "https://cal.com/apps/whereby", + "url": "https://cal.com/", "variant": "conferencing", "categories": ["video"], - "publisher": "Cal.com", + "publisher": "Cal.com, Inc.", "email": "help@cal.com", "description": "Whereby makes it super simple for collaborating teams to jump on a video call.", "__createdUsingCli": true, diff --git a/packages/app-store/zoho-bigin/config.json b/packages/app-store/zoho-bigin/config.json index 3425e1efaf..1f11350698 100644 --- a/packages/app-store/zoho-bigin/config.json +++ b/packages/app-store/zoho-bigin/config.json @@ -4,10 +4,10 @@ "slug": "zoho-bigin", "type": "zoho-bigin_other_calendar", "logo": "zohobigin.svg", - "url": "https://cal.com/apps/zoho-bigin", + "url": "https://github.com/ShaneMaglangit", "variant": "other", "categories": ["other"], - "publisher": "Cal.com", + "publisher": "Shane Maglangit", "email": "help@cal.com", "description": "Bigin easily transforms your day-to-day customer processes into actionable pipelines. From qualifying leads to closing deals to managing important after-sales operations—Bigin connects your different teams to work together so that you can offer the best possible experience to your customers. Say goodbye to missing follow-ups, manual data entry, lack of team communication, and information silos.", "isTemplate": false, diff --git a/packages/app-store/zohocrm/config.json b/packages/app-store/zohocrm/config.json index d369cbf03e..733a1fd2ea 100644 --- a/packages/app-store/zohocrm/config.json +++ b/packages/app-store/zohocrm/config.json @@ -4,10 +4,10 @@ "slug": "zohocrm", "type": "zohocrm_other_calendar", "logo": "icon.png", - "url": "https://cal.com/apps/zohocrm", + "url": "https://github.com/jatinsandilya", "variant": "other", "categories": ["other"], - "publisher": "Cal.com ", + "publisher": "Jatin Sandilya", "email": "help@cal.com", "description": "Zoho CRM is a cloud-based application designed to help your salespeople sell smarter and faster by centralizing customer information, logging their interactions with your company, and automating many of the tasks salespeople do every day", "isTemplate": false, From 1eb873bd35e53b40e30f1d28b6ff07fb65a72048 Mon Sep 17 00:00:00 2001 From: Vinoth Kumar V <123581387+VinoV1999@users.noreply.github.com> Date: Tue, 30 May 2023 20:02:15 +0530 Subject: [PATCH 045/100] fix: update button fix (#9106) * update button fix * Update appearance.tsx * fix linter --------- Co-authored-by: Vinoth Kumar V Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com> Co-authored-by: Peer Richelsen Co-authored-by: Hariom Balhara --- apps/web/pages/settings/my-account/appearance.tsx | 4 +++- .../server/routers/loggedInViewer/updateProfile.handler.ts | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/web/pages/settings/my-account/appearance.tsx b/apps/web/pages/settings/my-account/appearance.tsx index cff2e5901d..deadaaaaea 100644 --- a/apps/web/pages/settings/my-account/appearance.tsx +++ b/apps/web/pages/settings/my-account/appearance.tsx @@ -67,12 +67,14 @@ const AppearanceView = () => { const { formState: { isSubmitting, isDirty }, + reset, } = formMethods; const mutation = trpc.viewer.updateProfile.useMutation({ - onSuccess: async () => { + onSuccess: async (data) => { await utils.viewer.me.invalidate(); showToast(t("settings_updated_successfully"), "success"); + reset(data); }, onError: () => { showToast(t("error_updating_settings"), "error"); diff --git a/packages/trpc/server/routers/loggedInViewer/updateProfile.handler.ts b/packages/trpc/server/routers/loggedInViewer/updateProfile.handler.ts index 7d9debf1e4..67983b3b15 100644 --- a/packages/trpc/server/routers/loggedInViewer/updateProfile.handler.ts +++ b/packages/trpc/server/routers/loggedInViewer/updateProfile.handler.ts @@ -137,4 +137,5 @@ export const updateProfileHandler = async ({ ctx, input }: UpdateProfileOptions) .then(() => console.info("Booking pages revalidated")) .catch((e) => console.error(e)); } + return input; }; From 5bc6cbe7f5bb3110b6db151a79948e64e3b1b0d5 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 14:33:05 +0000 Subject: [PATCH 046/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/sr/common.json | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/apps/web/public/static/locales/sr/common.json b/apps/web/public/static/locales/sr/common.json index 254f21b5b4..49e6ce0e23 100644 --- a/apps/web/public/static/locales/sr/common.json +++ b/apps/web/public/static/locales/sr/common.json @@ -1818,5 +1818,21 @@ "image_size_limit_exceed": "Otpremljena slika ne sme da prevazilazi ograničenje od 5mb", "inline_embed": "Ugradi neposredno", "load_inline_content": "Direktno učitava vaš tip događaja neposredno sa vašim ostalim sadržajem na veb sajtu.", - "floating_pop_up_button": "Plutajuće iskačuće dugme" + "floating_pop_up_button": "Plutajuće iskačuće dugme", + "floating_button_trigger_modal": "Postavlja plutajuće dugme na vaš sajt koje pokreće modal sa vašim tipom događaja.", + "pop_up_element_click": "Iskačući prozor preko klika na element", + "open_dialog_with_element_click": "Otvara Cal dijalog prozor kada neko klikne na element.", + "need_help_embedding": "Potrebna vam je pomoć? Pogledajte naše vodiče za ugrađivanje Cal-a na Wix, Squarespace ili WordPress, pogledajte naša često postavljana pitanja, ili istražite napredne opcije za ugrađivanje.", + "book_my_cal": "Zakaži moj Cal", + "invite_as": "Pozovi kao", + "form_updated_successfully": "Formular je uspešno ažuriran.", + "email_not_cal_member_cta": "Pridružite se našem timu", + "disable_attendees_confirmation_emails": "Onemogući podrazumevane imejlove za potvrdu za polaznike", + "disable_attendees_confirmation_emails_description": "Najmanje jedan radni tok je aktivan na ovom tipu događaja koji šalje imejl polaznicima kada je događaj zakazan.", + "disable_host_confirmation_emails": "Onemogući podrazumevane imejlove za potvrdu za domaćina", + "disable_host_confirmation_emails_description": "Najmanje jedan radni tok je aktivan na ovom tipu događaja koji šalje imejl domaćinima kada je događaj zakazan.", + "add_an_override": "Dodaj zamenu", + "import_from_google_workspace": "Uvezi korisnike sa Google Workspace", + "connect_google_workspace": "Poveži Google Workspace", + "google_workspace_admin_tooltip": "Morate da budete Workspace administrator da biste koristili ovu opciju" } From 3426c17f16c42818858646851a4b83a92745c3fe Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 14:34:07 +0000 Subject: [PATCH 047/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/sr/common.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/web/public/static/locales/sr/common.json b/apps/web/public/static/locales/sr/common.json index 49e6ce0e23..fd883071c1 100644 --- a/apps/web/public/static/locales/sr/common.json +++ b/apps/web/public/static/locales/sr/common.json @@ -1834,5 +1834,7 @@ "add_an_override": "Dodaj zamenu", "import_from_google_workspace": "Uvezi korisnike sa Google Workspace", "connect_google_workspace": "Poveži Google Workspace", - "google_workspace_admin_tooltip": "Morate da budete Workspace administrator da biste koristili ovu opciju" + "google_workspace_admin_tooltip": "Morate da budete Workspace administrator da biste koristili ovu opciju", + "first_event_type_webhook_description": "Napravite svoj prvi webhook za ovaj tip događaja", + "create_for": "Napravi za" } From 317f59ba63d346ae22d31836e873655717a31752 Mon Sep 17 00:00:00 2001 From: Jeroen Reumkens Date: Tue, 30 May 2023 16:49:52 +0200 Subject: [PATCH 048/100] refactor: Show 404 page for new booker when event is not found. (#8946) * CAL-1653: Show 404 page for new booker when event is not found. * Fixed slack icon color on 404 page --------- Co-authored-by: Peer Richelsen Co-authored-by: Keith Williams --- apps/web/pages/404.tsx | 50 ++----------------- apps/web/pages/new-booker/[user]/[type].tsx | 20 +++++++- .../pages/new-booker/team/[slug]/[type].tsx | 12 ++++- apps/web/public/static/locales/en/common.json | 1 + packages/features/bookings/Booker/Booker.tsx | 6 ++- .../bookings/Booker/components/Away.tsx | 20 -------- .../Booker/components/Unavailable.tsx | 30 +++++++++++ packages/features/bookings/Booker/config.ts | 2 + 8 files changed, 70 insertions(+), 71 deletions(-) delete mode 100644 packages/features/bookings/Booker/components/Away.tsx create mode 100644 packages/features/bookings/Booker/components/Unavailable.tsx diff --git a/apps/web/pages/404.tsx b/apps/web/pages/404.tsx index dd119df042..5d461f1691 100644 --- a/apps/web/pages/404.tsx +++ b/apps/web/pages/404.tsx @@ -6,7 +6,7 @@ import { useEffect, useState } from "react"; import { DOCS_URL, JOIN_SLACK, WEBSITE_URL } from "@calcom/lib/constants"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { HeadSeo } from "@calcom/ui"; -import { BookOpen, Check, ChevronRight, FileText } from "@calcom/ui/components/icon"; +import { BookOpen, Check, ChevronRight, FileText, Slack } from "@calcom/ui/components/icon"; import PageWrapper from "@components/PageWrapper"; @@ -165,29 +165,7 @@ export default function Custom404() { className="relative flex items-start space-x-4 py-6 rtl:space-x-reverse">
    - - - - - - - - +
    @@ -313,29 +291,7 @@ export default function Custom404() { className="relative flex items-start space-x-4 py-6 rtl:space-x-reverse">
    - - - - - - - - +
    diff --git a/apps/web/pages/new-booker/[user]/[type].tsx b/apps/web/pages/new-booker/[user]/[type].tsx index d3003b8afe..b8997cc780 100644 --- a/apps/web/pages/new-booker/[user]/[type].tsx +++ b/apps/web/pages/new-booker/[user]/[type].tsx @@ -66,7 +66,15 @@ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) { booking = await getBookingByUidOrRescheduleUid(`${rescheduleUid}`); } - await ssr.viewer.public.event.prefetch({ username: user, eventSlug: slug }); + // We use this to both prefetch the query on the server, + // as well as to check if the event exist, so we c an show a 404 otherwise. + const eventData = await ssr.viewer.public.event.fetch({ username: user, eventSlug: slug }); + + if (!eventData) { + return { + notFound: true, + }; + } return { props: { @@ -107,7 +115,15 @@ async function getUserPageProps(context: GetServerSidePropsContext) { booking = await getBookingByUidOrRescheduleUid(`${rescheduleUid}`); } - await ssr.viewer.public.event.prefetch({ username, eventSlug: slug }); + // We use this to both prefetch the query on the server, + // as well as to check if the event exist, so we c an show a 404 otherwise. + const eventData = await ssr.viewer.public.event.fetch({ username, eventSlug: slug }); + + if (!eventData) { + return { + notFound: true, + }; + } return { props: { diff --git a/apps/web/pages/new-booker/team/[slug]/[type].tsx b/apps/web/pages/new-booker/team/[slug]/[type].tsx index 7ebaf2a55a..4e08fbca62 100644 --- a/apps/web/pages/new-booker/team/[slug]/[type].tsx +++ b/apps/web/pages/new-booker/team/[slug]/[type].tsx @@ -66,7 +66,17 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => if (rescheduleUid) { booking = await getBookingByUidOrRescheduleUid(`${rescheduleUid}`); } - await ssr.viewer.public.event.prefetch({ username: teamSlug, eventSlug: meetingSlug }); + + // We use this to both prefetch the query on the server, + // as well as to check if the event exist, so we c an show a 404 otherwise. + const eventData = await ssr.viewer.public.event.fetch({ username: teamSlug, eventSlug: meetingSlug }); + + if (!eventData) { + return { + notFound: true, + }; + } + return { props: { booking, diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index 489551a783..6762099912 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -195,6 +195,7 @@ "page_doesnt_exist": "This page does not exist.", "check_spelling_mistakes_or_go_back": "Check for spelling mistakes or go back to the previous page.", "404_page_not_found": "404: This page could not be found.", + "booker_event_not_found": "We could not find the event you are trying to book.", "getting_started": "Getting Started", "15min_meeting": "15 Min Meeting", "30min_meeting": "30 Min Meeting", diff --git a/packages/features/bookings/Booker/Booker.tsx b/packages/features/bookings/Booker/Booker.tsx index a25f9cc4f6..281b06c3ba 100644 --- a/packages/features/bookings/Booker/Booker.tsx +++ b/packages/features/bookings/Booker/Booker.tsx @@ -11,13 +11,13 @@ import { ToggleGroup } from "@calcom/ui"; import { Calendar, Columns, Grid } from "@calcom/ui/components/icon"; import { AvailableTimeSlots } from "./components/AvailableTimeSlots"; -import { Away } from "./components/Away"; import { BookEventForm } from "./components/BookEventForm"; import { BookFormAsModal } from "./components/BookEventForm/BookFormAsModal"; import { EventMeta } from "./components/EventMeta"; import { LargeCalendar } from "./components/LargeCalendar"; import { LargeViewHeader } from "./components/LargeViewHeader"; import { BookerSection } from "./components/Section"; +import { Away, NotFound } from "./components/Unavailable"; import { fadeInLeft, getBookerSizeClassNames, useBookerResizeAnimation } from "./config"; import { useBookerStore, useInitializeBookerStore } from "./store"; import type { BookerLayout, BookerProps } from "./types"; @@ -92,6 +92,10 @@ const BookerComponent = ({ } }, [layout]); + if (event.isSuccess && !event.data) { + return ; + } + return ( <> {/* diff --git a/packages/features/bookings/Booker/components/Away.tsx b/packages/features/bookings/Booker/components/Away.tsx deleted file mode 100644 index 45109cc97c..0000000000 --- a/packages/features/bookings/Booker/components/Away.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { useLocale } from "@calcom/lib/hooks/useLocale"; - -export const Away = () => { - const { t } = useLocale(); - - return ( -
    -
    -
    -
    -
    -

    😴{" " + t("user_away")}

    -

    {t("user_away_description")}

    -
    -
    -
    -
    -
    - ); -}; diff --git a/packages/features/bookings/Booker/components/Unavailable.tsx b/packages/features/bookings/Booker/components/Unavailable.tsx new file mode 100644 index 0000000000..329817076c --- /dev/null +++ b/packages/features/bookings/Booker/components/Unavailable.tsx @@ -0,0 +1,30 @@ +import { useLocale } from "@calcom/lib/hooks/useLocale"; + +const UnAvailableMessage = ({ children, title }: { children: React.ReactNode; title: string }) => ( +
    +
    +

    {title}

    + {children} +
    +
    +); + +export const Away = () => { + const { t } = useLocale(); + + return ( + +

    {t("user_away_description")}

    +
    + ); +}; + +export const NotFound = () => { + const { t } = useLocale(); + + return ( + +

    {t("booker_event_not_found")}

    +
    + ); +}; diff --git a/packages/features/bookings/Booker/config.ts b/packages/features/bookings/Booker/config.ts index 171d5bddbe..c659800c61 100644 --- a/packages/features/bookings/Booker/config.ts +++ b/packages/features/bookings/Booker/config.ts @@ -124,6 +124,8 @@ export const useBookerResizeAnimation = (layout: BookerLayout, state: BookerStat useEffect(() => { const animationConfig = resizeAnimationConfig[layout][state] || resizeAnimationConfig[layout].default; + if (!animationScope.current) return; + const animatedProperties = { height: animationConfig?.height || "auto", }; From 1fdd28b974416d0d5a7fbdb92e4df4380bdaff4a Mon Sep 17 00:00:00 2001 From: dolmasherpa123455 <110350254+dolmasherpa123455@users.noreply.github.com> Date: Tue, 30 May 2023 15:59:26 +0100 Subject: [PATCH 049/100] fix(readme): Update version requirements (#9158) Co-authored-by: Alex van Andel Co-authored-by: Bailey Pumfleet --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d7fc9c6244..e87c7d513e 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ To get a local copy up and running, please follow these simple steps. Here is what you need to be able to run Cal.com. -- Node.js (Version: >=15.x <17) +- Node.js (Version: >=18.x) - PostgreSQL - Yarn _(recommended)_ From ab6a7b537758f07cd9d8a92d2da39e74c83a2fe4 Mon Sep 17 00:00:00 2001 From: firefox341 <64374511+saurabbot@users.noreply.github.com> Date: Tue, 30 May 2023 20:30:32 +0530 Subject: [PATCH 050/100] fix: Skeleton Loader (#8925) * temp fix * removed isLoading declaration * final cleanup --------- Co-authored-by: firefox292 Co-authored-by: alannnc Co-authored-by: Peer Richelsen Co-authored-by: Keith Williams Co-authored-by: Alex van Andel --- .../app-store/routing-forms/pages/forms/[...appPages].tsx | 2 +- packages/features/tips/UpgradeTip.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/app-store/routing-forms/pages/forms/[...appPages].tsx b/packages/app-store/routing-forms/pages/forms/[...appPages].tsx index adbde12d54..4b6a1351e3 100644 --- a/packages/app-store/routing-forms/pages/forms/[...appPages].tsx +++ b/packages/app-store/routing-forms/pages/forms/[...appPages].tsx @@ -103,7 +103,7 @@ export default function RoutingForms({ description={t("routing_forms_are_a_great_way")} features={features} background="/tips/routing-forms" - isParentLoading={isLoading && } + isParentLoading={} buttons={
    diff --git a/packages/features/tips/UpgradeTip.tsx b/packages/features/tips/UpgradeTip.tsx index ea284f1654..a71f615959 100644 --- a/packages/features/tips/UpgradeTip.tsx +++ b/packages/features/tips/UpgradeTip.tsx @@ -29,8 +29,8 @@ export function UpgradeTip({ const { isLoading, hasTeamPlan } = useHasTeamPlan(); if (hasTeamPlan) return children; - - if (isParentLoading || isLoading) return <>{isParentLoading}; + + if (isLoading) return <>{isParentLoading}; return ( <> From dab01769383f727058a854c980c9834cf3a54144 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 15:33:40 +0000 Subject: [PATCH 051/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/fr/common.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/web/public/static/locales/fr/common.json b/apps/web/public/static/locales/fr/common.json index dd5a69e6d5..1cfaebefc7 100644 --- a/apps/web/public/static/locales/fr/common.json +++ b/apps/web/public/static/locales/fr/common.json @@ -1807,6 +1807,7 @@ "email_invite_team": "{{email}} a été invité", "error_collecting_card": "Erreur lors de la collecte de la carte", "image_size_limit_exceed": "L'image téléchargée ne doit pas dépasser 5 Mo", + "unauthorized_workflow_error_message": "{{errorCode}} : Vous n'êtes pas autorisé à activer ou désactiver ce workflow", "inline_embed": "Intégration en ligne", "load_inline_content": "Charge votre type d'événement directement en ligne avec le contenu de votre site web.", "floating_pop_up_button": "Bouton pop-up flottant", From 54271283af07eb37d08a0a9dd689e78ca6ef55e8 Mon Sep 17 00:00:00 2001 From: paridhi7 Date: Tue, 30 May 2023 20:35:46 +0530 Subject: [PATCH 052/100] fix: Adjust height of sidebar to fit on screen when top banner is visible (#8795) * Adjust height of sidebar to fit on screen when top banner is visible * Remove empty space on the bottom of the sidebar * Remove gap at bottom left of sidebar * fix: use layout effect and resize observer Signed-off-by: Udit Takkar --------- Signed-off-by: Udit Takkar Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> Co-authored-by: Udit Takkar Co-authored-by: Peer Richelsen Co-authored-by: Keith Williams --- packages/features/shell/Shell.tsx | 47 +++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/packages/features/shell/Shell.tsx b/packages/features/shell/Shell.tsx index 690ec1c50c..9799b031fa 100644 --- a/packages/features/shell/Shell.tsx +++ b/packages/features/shell/Shell.tsx @@ -5,7 +5,7 @@ import Link from "next/link"; import type { NextRouter } from "next/router"; import { useRouter } from "next/router"; import type { Dispatch, ReactNode, SetStateAction } from "react"; -import React, { Fragment, useEffect, useState } from "react"; +import React, { Fragment, useEffect, useState, useRef, useLayoutEffect } from "react"; import { Toaster } from "react-hot-toast"; import dayjs from "@calcom/dayjs"; @@ -140,6 +140,27 @@ function useRedirectToOnboardingIfNeeded() { const Layout = (props: LayoutProps) => { const pageTitle = typeof props.heading === "string" && !props.title ? props.heading : props.title; + const bannerRef = useRef(null); + const [bannersHeight, setBannersHeight] = useState(0); + + useLayoutEffect(() => { + const resizeObserver = new ResizeObserver((entries) => { + const { offsetHeight } = entries[0].target as HTMLElement; + setBannersHeight(offsetHeight); + }); + + const currentBannerRef = bannerRef.current; + + if (currentBannerRef) { + resizeObserver.observe(currentBannerRef); + } + + return () => { + if (currentBannerRef) { + resizeObserver.unobserve(currentBannerRef); + } + }; + }, [bannerRef]); return ( <> @@ -155,14 +176,14 @@ const Layout = (props: LayoutProps) => { {/* todo: only run this if timezone is different */} -
    -
    +
    +
    - {props.SidebarContainer || } + {props.SidebarContainer || }
    @@ -736,7 +757,15 @@ const MobileNavigationMoreItem: React.FC<{ ); }; -function SideBarContainer() { +type SideBarContainerProps = { + bannersHeight: number; +}; + +type SideBarProps = { + bannersHeight: number; +}; + +function SideBarContainer({ bannersHeight }: SideBarContainerProps) { const { status } = useSession(); const router = useRouter(); @@ -745,13 +774,15 @@ function SideBarContainer() { // Though when logged out, app store pages would temporarily show SideBar until session status is confirmed. if (status !== "loading" && status !== "authenticated") return null; if (router.route.startsWith("/v2/settings/")) return null; - return ; + return ; } -function SideBar() { +function SideBar({ bannersHeight }: SideBarProps) { return (
    -
    diff --git a/packages/ui/components/dialog/Dialog.tsx b/packages/ui/components/dialog/Dialog.tsx index eb5222ce27..04531e68f5 100644 --- a/packages/ui/components/dialog/Dialog.tsx +++ b/packages/ui/components/dialog/Dialog.tsx @@ -1,6 +1,6 @@ import * as DialogPrimitive from "@radix-ui/react-dialog"; import { useRouter } from "next/router"; -import type { PropsWithChildren, ReactNode } from "react"; +import type { ReactNode } from "react"; import React, { useState } from "react"; import classNames from "@calcom/lib/classNames"; @@ -93,7 +93,7 @@ export const DialogContent = React.forwardRef -
    {children}
    +
    {children}
    )} {type === "confirmation" && ( @@ -105,7 +105,7 @@ export const DialogContent = React.forwardRef -
    {children}
    +
    {children}
    )} @@ -134,10 +134,14 @@ export function DialogHeader(props: DialogHeaderProps) { ); } -// TODO: add divider -export function DialogFooter(props: PropsWithChildren<{ showDivider?: boolean }>) { +export function DialogFooter(props: { children: ReactNode; className?: string; showDivider?: boolean }) { return ( -
    {props.children}
    +
    + {props.showDivider &&
    } +
    + {props.children} +
    +
    ); } From a6330c0fc8573233ef3ab8bbfb72651fae4612bc Mon Sep 17 00:00:00 2001 From: "GitStart-Cal.com" <121884634+gitstart-calcom@users.noreply.github.com> Date: Tue, 30 May 2023 09:47:22 -0600 Subject: [PATCH 057/100] chore: Rounding, frames and radio buttons of the booking forms not consistent (#8705) * Rounding, frames and radio buttons of the booking forms not consistent * Updates --------- Co-authored-by: gitstart-calcom Co-authored-by: Peer Richelsen Co-authored-by: zomars Co-authored-by: Alex van Andel --- apps/web/package.json | 1 + apps/web/styles/globals.css | 14 +++- .../react-awesome-query-builder/widgets.tsx | 2 +- packages/features/form-builder/Components.tsx | 8 +-- .../settings/layouts/SettingsLayout.tsx | 4 +- packages/ui/components/form/inputs/Input.tsx | 6 +- packages/ui/components/form/select/Select.tsx | 2 +- packages/ui/form/PhoneInput.tsx | 60 ++++++++++------- packages/ui/form/radio-area/Radio.tsx | 4 +- yarn.lock | 65 +++++++++++++++---- 10 files changed, 118 insertions(+), 48 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index 003d767777..051e2a9129 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -109,6 +109,7 @@ "react-intl": "^5.25.1", "react-live-chat-loader": "^2.7.3", "react-multi-email": "^0.5.3", + "react-phone-input-2": "^2.15.1", "react-phone-number-input": "^3.2.7", "react-schemaorg": "^2.0.0", "react-select": "^5.7.0", diff --git a/apps/web/styles/globals.css b/apps/web/styles/globals.css index 005edb5e91..88ebb30d22 100644 --- a/apps/web/styles/globals.css +++ b/apps/web/styles/globals.css @@ -179,7 +179,7 @@ html.todesktop-platform-darwin.light main.bg-default{ background: rgba(255,255,255,0.8) !important } -/* +/* html.todesktop aside a { height: 28px; padding: 0px 8px; @@ -497,4 +497,16 @@ select:focus { -webkit-appearance: none; } +.react-tel-input .country-list .country:hover, +.react-tel-input .country-list .country.highlight { + @apply !bg-emphasis; +} +.react-tel-input .flag-dropdown .selected-flag, +.react-tel-input .flag-dropdown.open .selected-flag { + @apply !bg-default; +} + +.react-tel-input .flag-dropdown { + @apply !border-r-default !border-y-0 !border-l-0 left-0.5; +} diff --git a/packages/app-store/routing-forms/components/react-awesome-query-builder/widgets.tsx b/packages/app-store/routing-forms/components/react-awesome-query-builder/widgets.tsx index edfd451df4..66d230a7a8 100644 --- a/packages/app-store/routing-forms/components/react-awesome-query-builder/widgets.tsx +++ b/packages/app-store/routing-forms/components/react-awesome-query-builder/widgets.tsx @@ -129,7 +129,7 @@ function NumberWidget({ value, setValue, ...remainingProps }: TextLikeComponentP type="number" labelSrOnly={remainingProps.noLabel} containerClassName="w-full" - className="focus:border-brand-default bg-default dark:bg-muted border-default disabled:bg-emphasis focus:ring-brand block w-full rounded-md text-sm disabled:hover:cursor-not-allowed" + className="bg-default border-default disabled:bg-emphasis focus:ring-brand-default dark:focus:border-emphasis block w-full rounded-md text-sm focus:border-neutral-300 disabled:hover:cursor-not-allowed" value={value} onChange={(e) => { setValue(e.target.value); diff --git a/packages/features/form-builder/Components.tsx b/packages/features/form-builder/Components.tsx index 60fe399f1c..1b2d008765 100644 --- a/packages/features/form-builder/Components.tsx +++ b/packages/features/form-builder/Components.tsx @@ -134,7 +134,7 @@ export const Components: Record = { const { t } = useLocale(); value = value || []; const inputClassName = - "dark:placeholder:text-darkgray-600 focus:border-brand-default border-subtle block w-full rounded-md border-default text-sm focus:ring-black disabled:bg-emphasis disabled:hover:cursor-not-allowed dark:bg-transparent dark:selection:bg-green-500 disabled:dark:text-subtle"; + "dark:placeholder:text-muted focus:border-emphasis border-subtle block w-full rounded-md border-default text-sm focus:ring-black disabled:bg-emphasis disabled:hover:cursor-not-allowed dark:selection:bg-green-500 disabled:dark:text-subtle bg-default"; return ( <> {value.length ? ( @@ -148,11 +148,11 @@ export const Components: Record = { { value[index] = e.target.value; setValue(value); }} - className={inputClassName} placeholder={placeholder} label={<>} required @@ -251,7 +251,7 @@ export const Components: Record = { } setValue(newValue); }} - className="dark:bg-darkgray-300 border-subtle text-emphasis h-4 w-4 rounded focus:ring-black ltr:mr-2 rtl:ml-2" + className="border-default dark:border-default hover:bg-subtle checked:hover:bg-brand-default checked:bg-brand-default dark:checked:bg-brand-default dark:bg-darkgray-100 dark:hover:bg-subtle dark:checked:hover:bg-brand-default h-4 w-4 cursor-pointer rounded ltr:mr-2 rtl:ml-2" value={option.value} checked={value.includes(option.value)} /> @@ -310,7 +310,7 @@ export const Components: Record = { type="radio" disabled={readOnly} name={name} - className="dark:bg-darkgray-300 border-subtle text-emphasis h-4 w-4 focus:ring-black ltr:mr-2 rtl:ml-2" + className="dark:checked:bg-brand-default dark:bg-darkgray-100 dark:hover:bg-subtle dark:checked:hover:bg-brand-default focus:border-brand-default focus:ring-brand-default border-emphasis h-4 w-4 cursor-pointer text-[--cal-brand] focus:ring-2 ltr:mr-2 rtl:ml-2" value={option.value} onChange={(e) => { setValue({ diff --git a/packages/features/settings/layouts/SettingsLayout.tsx b/packages/features/settings/layouts/SettingsLayout.tsx index 258cede522..2d5a014bd2 100644 --- a/packages/features/settings/layouts/SettingsLayout.tsx +++ b/packages/features/settings/layouts/SettingsLayout.tsx @@ -201,7 +201,7 @@ const SettingsSidebarContainer = ({ alt="User Avatar" /> )} -

    {t(tab.name)}

    +

    {t(tab.name)}

    @@ -226,7 +226,7 @@ const SettingsSidebarContainer = ({ {tab && tab.icon && ( )} -

    {t(tab.name)}

    +

    {t(tab.name)}

    {teams && diff --git a/packages/ui/components/form/inputs/Input.tsx b/packages/ui/components/form/inputs/Input.tsx index c5dfbe5631..7fd9f2c2fb 100644 --- a/packages/ui/components/form/inputs/Input.tsx +++ b/packages/ui/components/form/inputs/Input.tsx @@ -23,7 +23,7 @@ export const Input = forwardRef(function Input( {...props} ref={ref} className={classNames( - "hover:border-emphasis border-default bg-default placeholder:text-muted text-emphasis disabled:hover:border-default disabled:bg-subtle mb-2 block h-9 rounded-md border py-2 px-3 text-sm leading-4 focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-neutral-800 focus:ring-offset-1 disabled:cursor-not-allowed", + "hover:border-emphasis dark:focus:border-emphasis border-default bg-default placeholder:text-muted text-emphasis disabled:hover:border-default disabled:bg-subtle focus:ring-brand-default mb-2 block h-9 rounded-md border py-2 px-3 text-sm leading-4 focus:border-neutral-300 focus:outline-none focus:ring-2 disabled:cursor-not-allowed", isFullWidth && "w-full", props.className )} @@ -129,7 +129,7 @@ export const InputField = forwardRef(function {addOnLeading || addOnSuffix ? (
    + className="focus-within:ring-brand-default group relative mb-1 flex items-center rounded-md focus-within:outline-none focus-within:ring-2"> {addOnLeading && ( {addOnLeading} @@ -280,7 +280,7 @@ export const TextArea = forwardRef(function ref={ref} {...props} className={classNames( - "hover:border-emphasis border-default bg-default placeholder:text-muted text-emphasis disabled:hover:border-default disabled:bg-subtle mb-2 block w-full rounded-md border py-2 px-3 text-sm focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-neutral-800 focus:ring-offset-1 disabled:cursor-not-allowed", + "hover:border-emphasis border-default bg-default placeholder:text-muted text-emphasis disabled:hover:border-default disabled:bg-subtle focus:ring-brand-default mb-2 block w-full rounded-md border py-2 px-3 text-sm focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-offset-1 disabled:cursor-not-allowed", props.className )} /> diff --git a/packages/ui/components/form/select/Select.tsx b/packages/ui/components/form/select/Select.tsx index 1a13a1295c..c5adf378e3 100644 --- a/packages/ui/components/form/select/Select.tsx +++ b/packages/ui/components/form/select/Select.tsx @@ -51,7 +51,7 @@ export const Select = < dropdownIndicator: () => "text-default", control: (state) => cx( - "bg-default border-default !min-h-9 h-9 text-sm leading-4 placeholder:text-sm placeholder:font-normal focus-within:ring-2 focus-within:ring-emphasis hover:border-emphasis rounded-md border ", + "bg-default border-default !min-h-9 h-9 text-sm leading-4 placeholder:text-sm placeholder:font-normal dark:focus:border-emphasis focus-within:outline-none focus-within:ring-2 focus-within:ring-brand-default hover:border-emphasis rounded-md border", state.isMulti ? variant === "checkbox" ? "px-3 py-2 h-fit" diff --git a/packages/ui/form/PhoneInput.tsx b/packages/ui/form/PhoneInput.tsx index 4e4f23902c..91656f576a 100644 --- a/packages/ui/form/PhoneInput.tsx +++ b/packages/ui/form/PhoneInput.tsx @@ -1,53 +1,69 @@ import { isSupportedCountry } from "libphonenumber-js"; import { useState } from "react"; -import BasePhoneInput from "react-phone-number-input"; -import type { Props, Country } from "react-phone-number-input"; -import "react-phone-number-input/style.css"; +import PhoneInput from "react-phone-input-2"; +import "react-phone-input-2/lib/style.css"; import { classNames } from "@calcom/lib"; import { trpc } from "@calcom/trpc/react"; -export type PhoneInputProps = Props<{ - value: string; +export type PhoneInputProps = { + value?: string; id?: string; placeholder?: string; required?: boolean; className?: string; name?: string; -}>; + disabled?: boolean; + onChange: (value: string) => void; +}; -function PhoneInput({ name, className = "", onChange, ...rest }: PhoneInputProps) { +function BasePhoneInput({ name, className = "", onChange, ...rest }: PhoneInputProps) { const defaultCountry = useDefaultCountry(); - return ( - onChange(value)} + containerClass={classNames( + "hover:border-emphasis dark:focus:border-emphasis border-default !bg-default rounded-md border focus-within:outline-none focus-within:ring-2 focus-within:ring-brand-default disabled:cursor-not-allowed", className )} + inputClass="text-sm focus:ring-0 !bg-default text-default" + buttonClass="text-emphasis !bg-default hover:!bg-emphasis" + searchClass="!text-default !bg-default hover:!bg-emphasis" + dropdownClass="!text-default !bg-default" + inputStyle={{ width: "inherit", border: 0 }} + searchStyle={{ + display: "flex", + flexDirection: "row", + alignItems: "center", + padding: "6px 12px", + gap: "8px", + width: "296px", + height: "28px", + marginLeft: "-4px", + }} + dropdownStyle={{ width: "max-content" }} /> ); } const useDefaultCountry = () => { - const [defaultCountry, setDefaultCountry] = useState("US"); + const [defaultCountry, setDefaultCountry] = useState("us"); trpc.viewer.public.countryCode.useQuery(undefined, { refetchOnWindowFocus: false, refetchOnReconnect: false, retry: false, onSuccess: (data) => { if (isSupportedCountry(data?.countryCode)) { - setDefaultCountry(data.countryCode as Country); + setDefaultCountry(data.countryCode); } }, }); @@ -55,4 +71,4 @@ const useDefaultCountry = () => { return defaultCountry; }; -export default PhoneInput; +export default BasePhoneInput; diff --git a/packages/ui/form/radio-area/Radio.tsx b/packages/ui/form/radio-area/Radio.tsx index f794fa0ef8..41c6018c14 100644 --- a/packages/ui/form/radio-area/Radio.tsx +++ b/packages/ui/form/radio-area/Radio.tsx @@ -11,7 +11,7 @@ export const Radio = (props: RadioGroupPrimitive.RadioGroupItemProps & { childre {props.children} @@ -21,7 +21,7 @@ export const Indicator = ({ disabled }: { disabled?: boolean }) => ( ); diff --git a/yarn.lock b/yarn.lock index 242bbf36c1..777139dd89 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4996,6 +4996,7 @@ __metadata: react-intl: ^5.25.1 react-live-chat-loader: ^2.7.3 react-multi-email: ^0.5.3 + react-phone-input-2: ^2.15.1 react-phone-number-input: ^3.2.7 react-schemaorg: ^2.0.0 react-select: ^5.7.0 @@ -17328,7 +17329,7 @@ __metadata: languageName: node linkType: hard -"classnames@npm:^2.2.5": +"classnames@npm:^2.2.5, classnames@npm:^2.2.6": version: 2.3.2 resolution: "classnames@npm:2.3.2" checksum: 2c62199789618d95545c872787137262e741f9db13328e216b093eea91c85ef2bfb152c1f9e63027204e2559a006a92eb74147d46c800a9f96297ae1d9f96f4e @@ -26976,6 +26977,13 @@ __metadata: languageName: node linkType: hard +"lodash.memoize@npm:^4.1.2": + version: 4.1.2 + resolution: "lodash.memoize@npm:4.1.2" + checksum: 9ff3942feeccffa4f1fafa88d32f0d24fdc62fd15ded5a74a5f950ff5f0c6f61916157246744c620173dddf38d37095a92327d5fd3861e2063e736a5c207d089 + languageName: node + linkType: hard + "lodash.merge@npm:^4.6.2": version: 4.6.2 resolution: "lodash.merge@npm:4.6.2" @@ -26997,6 +27005,13 @@ __metadata: languageName: node linkType: hard +"lodash.reduce@npm:^4.6.0": + version: 4.6.0 + resolution: "lodash.reduce@npm:4.6.0" + checksum: 81f2a1045440554f8427f895ef479f1de5c141edd7852dde85a894879312801efae0295116e5cf830c531c1a51cdab8f3628c3ad39fa21a9874bb9158d9ea075 + languageName: node + linkType: hard + "lodash.startcase@npm:^4.4.0": version: 4.4.0 resolution: "lodash.startcase@npm:4.4.0" @@ -27004,6 +27019,13 @@ __metadata: languageName: node linkType: hard +"lodash.startswith@npm:^4.2.1": + version: 4.2.1 + resolution: "lodash.startswith@npm:4.2.1" + checksum: 1847371cbf6f32c4125a555847aff8a1ff1a977f40882b0ad4e2656a32e364793cfa7602915c9165cc0bba61fbd802e561888126d242faadcf3fc77215bab19b + languageName: node + linkType: hard + "lodash.uniq@npm:4.5.0": version: 4.5.0 resolution: "lodash.uniq@npm:4.5.0" @@ -30827,21 +30849,23 @@ __metadata: languageName: node linkType: hard -"playwright-core@npm:1.34.0": - version: 1.34.0 - resolution: "playwright-core@npm:1.34.0" - checksum: 1821ab254b3c756e52c144c26cae7250dd5a1c779277cdd583bd289501d45cceaea40a8185ebf7eaa56b8291e4a042e3eef65f511da2306349c275794c9a582d +"playwright-core@npm:1.33.0": + version: 1.33.0 + resolution: "playwright-core@npm:1.33.0" + bin: + playwright: cli.js + checksum: 5fb7bda06a8b73b56b85b5a0b8f711211dde57a375d9379289e22239b2de879c6d93c8fdc9ba44b932bf100914ab1ca1a55697ad88440fdd0a39101fc020b77f languageName: node linkType: hard "playwright@npm:^1.31.2": - version: 1.34.0 - resolution: "playwright@npm:1.34.0" + version: 1.33.0 + resolution: "playwright@npm:1.33.0" dependencies: - playwright-core: 1.34.0 + playwright-core: 1.33.0 bin: playwright: cli.js - checksum: 5e5586e7c4e42f206526fe4306e35c68b7af353d6e3701c9e1045940aa3a916ac50b0b7c27a8eaeb3831ddc4f1146a367f98a5b6b841f977e9770b925e81877f + checksum: fb3934c56ed749cf412ea35b82052f013872d7f7b7747ab7042580af473dfc1b038956a31c132ee8c0098f74150c75e2073e9c737fd4c1ed54700a23fffc079f languageName: node linkType: hard @@ -32291,12 +32315,12 @@ __metadata: linkType: hard "react-fast-marquee@npm:^1.3.5": - version: 1.6.0 - resolution: "react-fast-marquee@npm:1.6.0" + version: 1.5.2 + resolution: "react-fast-marquee@npm:1.5.2" peerDependencies: react: ">= 16.8.0 || 18.0.0" react-dom: ">= 16.8.0 || 18.0.0" - checksum: f448341d30ef417292d8f7618d4931190a6d4aa353fbd276da4dcecc49bb6a7a32962f9cc74fe0af2ea9617d7b453ed3efccf7a0e8709a8b66e04ec04f4ae18c + checksum: 2db7a61470a9e02707aa5a80792ec009a8694ef7283b01e30ec516893297794d7f466ae3230c59773bab357684803767c1ffab875175471c41b28a5055345130 languageName: node linkType: hard @@ -32526,6 +32550,23 @@ __metadata: languageName: node linkType: hard +"react-phone-input-2@npm:^2.15.1": + version: 2.15.1 + resolution: "react-phone-input-2@npm:2.15.1" + dependencies: + classnames: ^2.2.6 + lodash.debounce: ^4.0.8 + lodash.memoize: ^4.1.2 + lodash.reduce: ^4.6.0 + lodash.startswith: ^4.2.1 + prop-types: ^15.7.2 + peerDependencies: + react: ^16.12.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 + react-dom: ^16.12.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 + checksum: 60cee455c7044da648a23312cae0077b4108dd24e26173a954904123decefae9875a1f8225a722a6c4d74c37b18ad3038ec6c302b64857f75089e544e8d48847 + languageName: node + linkType: hard + "react-phone-number-input@npm:^3.2.7": version: 3.2.7 resolution: "react-phone-number-input@npm:3.2.7" From 7c46d1b34847501759158be6ad8da80c441eeb34 Mon Sep 17 00:00:00 2001 From: Anwar Sadath <37188392+asadath1395@users.noreply.github.com> Date: Tue, 30 May 2023 22:00:19 +0530 Subject: [PATCH 058/100] chore: Cleanup full raw avatar responses from tRPC endpoints (#8901) * [CAL-1383] Cleanup full raw avatar responses from tRPC endpoints * Cleanup additional handlers where base64 images were sent through the response * Add 'image' correctly to the profiles array --------- Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Co-authored-by: alannnc Co-authored-by: Peer Richelsen Co-authored-by: Keith Williams Co-authored-by: Alex van Andel --- .../routers/viewer/eventTypes/getByViewer.handler.ts | 10 +++++++--- .../routers/viewer/webhook/getByViewer.handler.ts | 3 ++- .../routers/viewer/workflows/getByViewer.handler.ts | 3 ++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/trpc/server/routers/viewer/eventTypes/getByViewer.handler.ts b/packages/trpc/server/routers/viewer/eventTypes/getByViewer.handler.ts index 1760fce192..dfd9553b3d 100644 --- a/packages/trpc/server/routers/viewer/eventTypes/getByViewer.handler.ts +++ b/packages/trpc/server/routers/viewer/eventTypes/getByViewer.handler.ts @@ -172,13 +172,16 @@ export const getByViewerHandler = async ({ ctx }: GetByViewerOptions) => { const mergedEventTypes = Object.values(eventTypesHashMap) .map((eventType) => eventType) .filter((evType) => evType.schedulingType !== SchedulingType.MANAGED); + + const image = user?.username ? `${CAL_URL}/${user.username}/avatar.png` : undefined; + eventTypeGroups.push({ teamId: null, membershipRole: null, profile: { slug: user.username, name: user.name, - image: user.avatar || undefined, + image, }, eventTypes: orderBy(mergedEventTypes, ["position", "id"], ["desc", "asc"]), metadata: { @@ -214,10 +217,11 @@ export const getByViewerHandler = async ({ ctx }: GetByViewerOptions) => { eventTypeGroups: eventTypeGroups.filter((groupBy) => !!groupBy.eventTypes?.length), // so we can show a dropdown when the user has teams profiles: eventTypeGroups.map((group) => ({ - teamId: group.teamId, - membershipRole: group.membershipRole, ...group.profile, ...group.metadata, + teamId: group.teamId, + membershipRole: group.membershipRole, + image: `${CAL_URL}/${group.profile.slug}/avatar.png`, })), }; }; diff --git a/packages/trpc/server/routers/viewer/webhook/getByViewer.handler.ts b/packages/trpc/server/routers/viewer/webhook/getByViewer.handler.ts index 54436b6b91..6faaea5053 100644 --- a/packages/trpc/server/routers/viewer/webhook/getByViewer.handler.ts +++ b/packages/trpc/server/routers/viewer/webhook/getByViewer.handler.ts @@ -77,12 +77,13 @@ export const getByViewerHandler = async ({ ctx }: GetByViewerOptions) => { const userWebhooks = user.webhooks; let webhookGroups: WebhookGroup[] = []; + const image = user?.username ? `${CAL_URL}/${user.username}/avatar.png` : undefined; webhookGroups.push({ teamId: null, profile: { slug: user.username, name: user.name, - image: user.avatar || undefined, + image, }, webhooks: userWebhooks, metadata: { diff --git a/packages/trpc/server/routers/viewer/workflows/getByViewer.handler.ts b/packages/trpc/server/routers/viewer/workflows/getByViewer.handler.ts index efd0b67bbf..45050d8df1 100644 --- a/packages/trpc/server/routers/viewer/workflows/getByViewer.handler.ts +++ b/packages/trpc/server/routers/viewer/workflows/getByViewer.handler.ts @@ -80,12 +80,13 @@ export const getByViewerHandler = async ({ ctx }: GetByViewerOptions) => { let workflowGroups: WorkflowGroup[] = []; + const image = user?.username ? `${CAL_URL}/${user.username}/avatar.png` : undefined; workflowGroups.push({ teamId: null, profile: { slug: user.username, name: user.name, - image: user.avatar || undefined, + image, }, workflows: userWorkflows, metadata: { From 59f9cf8aa33d3d39b32ed387e5a3a85c32d4307a Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 16:45:20 +0000 Subject: [PATCH 059/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/vi/common.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/web/public/static/locales/vi/common.json b/apps/web/public/static/locales/vi/common.json index fad55fea26..1892909df7 100644 --- a/apps/web/public/static/locales/vi/common.json +++ b/apps/web/public/static/locales/vi/common.json @@ -241,6 +241,7 @@ "continue_without_calendar": "Tiếp tục mà không có lịch", "connect_your_calendar": "Kết nối lịch của bạn", "connect_your_video_app": "Kết nối các video yêu thích của bạn", + "connect_your_video_app_instructions": "Kết nối những ứng dụng video để dùng chúng ở những loại sự kiện của bạn.", "connect_your_calendar_instructions": "Kết nối lịch của bạn để tự động kiểm tra thời gian bận và các sự kiện mới khi chúng được lên lịch.", "set_up_later": "Thiết lập sau", "current_time": "Thời gian hiện tại", From 45418453409c13c50c6ee8d05db771a9c9935008 Mon Sep 17 00:00:00 2001 From: Rob Jackson Date: Tue, 30 May 2023 17:31:49 +0100 Subject: [PATCH 060/100] feat: Use team logos for various meta icons (#8955) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use team logos for various meta icons * Automatically resize team icons for different uses * Fix api/logo error when unable to find a team * Avoid loading image-optimizer in api/logo when not needed --------- Co-authored-by: Omar López Co-authored-by: alannnc Co-authored-by: Alex van Andel Co-authored-by: Bailey Pumfleet --- apps/web/pages/_document.tsx | 6 +- apps/web/pages/api/logo.ts | 117 ++++++++++++++++++++++++--- apps/web/public/browserconfig.xml | 2 +- apps/web/public/site.webmanifest | 4 +- packages/lib/constants.ts | 6 ++ packages/ui/components/logo/Logo.tsx | 2 +- 6 files changed, 119 insertions(+), 18 deletions(-) diff --git a/apps/web/pages/_document.tsx b/apps/web/pages/_document.tsx index dcc53b486c..0c9179f148 100644 --- a/apps/web/pages/_document.tsx +++ b/apps/web/pages/_document.tsx @@ -40,9 +40,9 @@ class MyDocument extends Document { return ( - - - + + + diff --git a/apps/web/pages/api/logo.ts b/apps/web/pages/api/logo.ts index 00af5dba8d..72dac999d7 100644 --- a/apps/web/pages/api/logo.ts +++ b/apps/web/pages/api/logo.ts @@ -1,7 +1,18 @@ import type { NextApiRequest, NextApiResponse } from "next"; import { z } from "zod"; -import { IS_SELF_HOSTED, LOGO, LOGO_ICON, WEBAPP_URL } from "@calcom/lib/constants"; +import { + ANDROID_CHROME_ICON_192, + ANDROID_CHROME_ICON_256, + APPLE_TOUCH_ICON, + FAVICON_16, + FAVICON_32, + IS_SELF_HOSTED, + LOGO, + LOGO_ICON, + MSTILE_ICON, + WEBAPP_URL, +} from "@calcom/lib/constants"; import logger from "@calcom/lib/logger"; const log = logger.getChildLogger({ prefix: ["[api/logo]"] }); @@ -20,11 +31,79 @@ function extractSubdomainAndDomain(hostname: string) { } const logoApiSchema = z.object({ - icon: z.coerce.boolean().optional(), + type: z.coerce.string().optional(), }); const SYSTEM_SUBDOMAINS = ["console", "app", "www"]; +type LogoType = + | "logo" + | "icon" + | "favicon-16" + | "favicon-32" + | "apple-touch-icon" + | "mstile" + | "android-chrome-192" + | "android-chrome-256"; + +type LogoTypeDefinition = { + fallback: string; + w?: number; + h?: number; + source: "appLogo" | "appIconLogo"; +}; + +const logoDefinitions: Record = { + logo: { + fallback: `${WEBAPP_URL}${LOGO}`, + source: "appLogo", + }, + icon: { + fallback: `${WEBAPP_URL}${LOGO_ICON}`, + source: "appIconLogo", + }, + "favicon-16": { + fallback: `${WEBAPP_URL}${FAVICON_16}`, + w: 16, + h: 16, + source: "appIconLogo", + }, + "favicon-32": { + fallback: `${WEBAPP_URL}${FAVICON_32}`, + w: 32, + h: 32, + source: "appIconLogo", + }, + "apple-touch-icon": { + fallback: `${WEBAPP_URL}${APPLE_TOUCH_ICON}`, + w: 180, + h: 180, + source: "appLogo", + }, + mstile: { + fallback: `${WEBAPP_URL}${MSTILE_ICON}`, + w: 150, + h: 150, + source: "appLogo", + }, + "android-chrome-192": { + fallback: `${WEBAPP_URL}${ANDROID_CHROME_ICON_192}`, + w: 192, + h: 192, + source: "appLogo", + }, + "android-chrome-256": { + fallback: `${WEBAPP_URL}${ANDROID_CHROME_ICON_256}`, + w: 256, + h: 256, + source: "appLogo", + }, +}; + +function isValidLogoType(type: string): type is LogoType { + return type in logoDefinitions; +} + async function getTeamLogos(subdomain: string) { try { if ( @@ -39,7 +118,7 @@ async function getTeamLogos(subdomain: string) { } // load from DB const { default: prisma } = await import("@calcom/prisma"); - const team = await prisma.team.findUniqueOrThrow({ + const team = await prisma.team.findUnique({ where: { slug: subdomain, }, @@ -48,16 +127,16 @@ async function getTeamLogos(subdomain: string) { appIconLogo: true, }, }); - // try to use team logos, otherwise default to LOGO/LOGO_ICON regardless + return { - appLogo: team.appLogo || `${WEBAPP_URL}${LOGO}`, - appIconLogo: team.appIconLogo || `${WEBAPP_URL}${LOGO_ICON}`, + appLogo: team?.appLogo, + appIconLogo: team?.appIconLogo, }; } catch (error) { if (error instanceof Error) log.debug(error.message); return { - appLogo: `${WEBAPP_URL}${LOGO}`, - appIconLogo: `${WEBAPP_URL}${LOGO_ICON}`, + appLogo: undefined, + appIconLogo: undefined, }; } } @@ -75,14 +154,30 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) if (!domains) throw new Error("No domains"); const [subdomain] = domains; - const { appLogo, appIconLogo } = await getTeamLogos(subdomain); + const teamLogos = await getTeamLogos(subdomain); - const filteredLogo = parsedQuery?.icon ? appIconLogo : appLogo; + // Resolve all icon types to team logos, falling back to Cal.com defaults. + const type: LogoType = parsedQuery?.type && isValidLogoType(parsedQuery.type) ? parsedQuery.type : "logo"; + const logoDefinition = logoDefinitions[type]; + const filteredLogo = teamLogos[logoDefinition.source] ?? logoDefinition.fallback; try { const response = await fetch(filteredLogo); const arrayBuffer = await response.arrayBuffer(); - const buffer = Buffer.from(arrayBuffer); + let buffer = Buffer.from(arrayBuffer); + + // If we need to resize the team logos (via Next.js' built-in image processing) + if (teamLogos[logoDefinition.source] && logoDefinition.w) { + const { detectContentType, optimizeImage } = await import("next/dist/server/image-optimizer"); + buffer = await optimizeImage({ + buffer, + contentType: detectContentType(buffer) ?? "image/jpeg", + quality: 100, + width: logoDefinition.w, + height: logoDefinition.h, // optional + }); + } + res.setHeader("Content-Type", response.headers.get("content-type") as string); res.setHeader("Cache-Control", "s-maxage=86400"); res.send(buffer); diff --git a/apps/web/public/browserconfig.xml b/apps/web/public/browserconfig.xml index 748e8459c5..5cd1b5f5ab 100644 --- a/apps/web/public/browserconfig.xml +++ b/apps/web/public/browserconfig.xml @@ -2,7 +2,7 @@ - + #ff0000 diff --git a/apps/web/public/site.webmanifest b/apps/web/public/site.webmanifest index 15a8e42abb..04adc4cba9 100644 --- a/apps/web/public/site.webmanifest +++ b/apps/web/public/site.webmanifest @@ -3,12 +3,12 @@ "short_name": "Cal.com", "icons": [ { - "src": "/android-chrome-192x192.png", + "src": "/api/logo?type=android-chrome-192", "sizes": "192x192", "type": "image/png" }, { - "src": "/android-chrome-256x256.png", + "src": "/api/logo?type=android-chrome-256", "sizes": "256x256", "type": "image/png" } diff --git a/packages/lib/constants.ts b/packages/lib/constants.ts index 19b47fb762..7b5997144f 100644 --- a/packages/lib/constants.ts +++ b/packages/lib/constants.ts @@ -40,6 +40,12 @@ export const HOSTED_CAL_FEATURES = process.env.NEXT_PUBLIC_HOSTED_CAL_FEATURES | export const NEXT_PUBLIC_BASE_URL = process.env.NEXT_PUBLIC_WEBAPP_URL || `https://${process.env.VERCEL_URL}`; export const LOGO = "/calcom-logo-white-word.svg"; export const LOGO_ICON = "/cal-com-icon-white.svg"; +export const FAVICON_16 = "/favicon-16x16.png"; +export const FAVICON_32 = "/favicon-32x32.png"; +export const APPLE_TOUCH_ICON = "/apple-touch-icon.png"; +export const MSTILE_ICON = "/mstile-150x150.png"; +export const ANDROID_CHROME_ICON_192 = "/android-chrome-192x192.png"; +export const ANDROID_CHROME_ICON_256 = "/android-chrome-256x256.png"; export const ROADMAP = "https://cal.com/roadmap"; export const DESKTOP_APP_LINK = "https://cal.com/download"; export const JOIN_SLACK = "https://cal.com/slack"; diff --git a/packages/ui/components/logo/Logo.tsx b/packages/ui/components/logo/Logo.tsx index 31e7e224cd..872e9ffb9c 100644 --- a/packages/ui/components/logo/Logo.tsx +++ b/packages/ui/components/logo/Logo.tsx @@ -15,7 +15,7 @@ export default function Logo({

    {icon ? ( - Cal + Cal ) : ( Date: Tue, 30 May 2023 14:31:21 -0300 Subject: [PATCH 061/100] chore: Shard E2E tests (#9206) * Shard E2E tests * Updated shards to 5 * Removed action triggers used for testing --- .github/workflows/e2e.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index b5abb0559a..d4b15286a0 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -4,7 +4,7 @@ on: jobs: e2e: timeout-minutes: 20 - name: E2E tests + name: E2E tests (${{ matrix.shard }}/${{ strategy.job-total }}) runs-on: buildjet-4vcpu-ubuntu-2204 services: postgres: @@ -14,6 +14,10 @@ jobs: POSTGRES_DB: calendso ports: - 5432:5432 + strategy: + fail-fast: false + matrix: + shard: [1, 2, 3, 4, 5] steps: - uses: actions/checkout@v3 - uses: ./.github/actions/dangerous-git-checkout @@ -23,13 +27,15 @@ jobs: - uses: ./.github/actions/env-read-file - uses: ./.github/actions/cache-db - uses: ./.github/actions/cache-build + - name: Seed Test DB + run: yarn db-seed - name: Run Tests - run: yarn test-e2e + run: yarn e2e --shard=${{ matrix.shard }}/${{ strategy.job-total }} env: DEPLOYSENTINEL_API_KEY: ${{ secrets.DEPLOYSENTINEL_API_KEY }} - name: Upload Test Results if: ${{ always() }} uses: actions/upload-artifact@v2 with: - name: test-results + name: test-results-${{ matrix.shard }}_${{ strategy.job-total }} path: test-results From 787edd28c7c120ab4a5dc80c2d23e9ca909f8d10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Omar=20L=C3=B3pez?= Date: Tue, 30 May 2023 11:36:48 -0700 Subject: [PATCH 062/100] fix: Popular Apps Slider (#9189) * Fixes Popular Apps Slider * Update PopularAppsSlider.tsx * Reverts env cache * Revert --------- Co-authored-by: Peer Richelsen Co-authored-by: Alex van Andel Co-authored-by: Keith Williams --- packages/app-store/_appRegistry.ts | 28 +++++++++++++++++++ packages/types/App.d.ts | 2 ++ .../ui/components/apps/PopularAppsSlider.tsx | 2 +- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/packages/app-store/_appRegistry.ts b/packages/app-store/_appRegistry.ts index 709b665ddb..81a4665d55 100644 --- a/packages/app-store/_appRegistry.ts +++ b/packages/app-store/_appRegistry.ts @@ -1,3 +1,5 @@ +import { z } from "zod"; + import { appStoreMetadata } from "@calcom/app-store/appStoreMetaData"; import { getAppFromSlug } from "@calcom/app-store/utils"; import prisma, { safeAppSelect, safeCredentialSelect } from "@calcom/prisma"; @@ -35,6 +37,7 @@ export async function getAppRegistry() { select: { dirName: true, slug: true, categories: true, enabled: true }, }); const apps = [] as App[]; + const mostPopularApps = await getMostPopularApps(); for await (const dbapp of dbApps) { const app = await getAppWithMetadata(dbapp); if (!app) continue; @@ -47,6 +50,7 @@ export async function getAppRegistry() { category: app.category || "other", installed: true /* All apps from DB are considered installed by default. @TODO: Add and filter our by `enabled` property */, + installCount: mostPopularApps[dbapp.slug] || 0, }); } return apps; @@ -82,6 +86,7 @@ export async function getAppRegistryWithCredentials(userId: number) { credentials: Credential[]; isDefault?: boolean; })[]; + const mostPopularApps = await getMostPopularApps(); for await (const dbapp of dbApps) { const app = await getAppWithMetadata(dbapp); if (!app) continue; @@ -108,6 +113,7 @@ export async function getAppRegistryWithCredentials(userId: number) { categories: dbapp.categories, credentials: dbapp.credentials, installed: true, + installCount: mostPopularApps[dbapp.slug] || 0, isDefault: usersDefaultApp === dbapp.slug, ...(app.dependencies && { dependencyData }), }); @@ -115,3 +121,25 @@ export async function getAppRegistryWithCredentials(userId: number) { return apps; } + +async function getMostPopularApps() { + const mostPopularApps = z.array(z.object({ appId: z.string(), installCount: z.number() })).parse( + await prisma.$queryRaw` + SELECT + c."appId", + COUNT(*)::integer AS "installCount" + FROM + "Credential" c + WHERE + c."appId" IS NOT NULL + GROUP BY + c."appId" + ORDER BY + "installCount" DESC + ` + ); + return mostPopularApps.reduce((acc, { appId, installCount }) => { + acc[appId] = installCount; + return acc; + }, {} as Record); +} diff --git a/packages/types/App.d.ts b/packages/types/App.d.ts index 56381f7386..31c39385b3 100644 --- a/packages/types/App.d.ts +++ b/packages/types/App.d.ts @@ -149,6 +149,8 @@ export type AppFrontendPayload = Omit & { name?: string; installed?: boolean; }[]; + /** Number of users who currently have this App installed */ + installCount?: number; }; export type AppMeta = App; diff --git a/packages/ui/components/apps/PopularAppsSlider.tsx b/packages/ui/components/apps/PopularAppsSlider.tsx index 260f60bb97..71fcfb3b61 100644 --- a/packages/ui/components/apps/PopularAppsSlider.tsx +++ b/packages/ui/components/apps/PopularAppsSlider.tsx @@ -10,7 +10,7 @@ export const PopularAppsSlider = ({ items }: { items: T[] }) => { return ( title={t("most_popular")} - items={items.filter((app) => !!app.trending)} + items={items.sort((a, b) => (b.installCount || 0) - (a.installCount || 0))} itemKey={(app) => app.name} options={{ perView: 3, From 8a96fc7905305a3d2079f12bb64649e297bbe0d1 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 18:51:53 +0000 Subject: [PATCH 063/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/pl/common.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/web/public/static/locales/pl/common.json b/apps/web/public/static/locales/pl/common.json index 160ded39c7..fbc09f8798 100644 --- a/apps/web/public/static/locales/pl/common.json +++ b/apps/web/public/static/locales/pl/common.json @@ -26,6 +26,7 @@ "rejection_confirmation": "Odrzuć prośbę o rezerwację", "manage_this_event": "Zarządzaj wydarzeniem", "invite_team_member": "Zaproś członka zespołu", + "invite_team_bulk_segment": "Import zbiorczy", "invite_team_notifcation_badge": "Zap.", "your_event_has_been_scheduled": "Zaplanowano wydarzenie", "your_event_has_been_scheduled_recurring": "Twoje wydarzenie cykliczne zostało zaplanowane", @@ -222,6 +223,7 @@ "go_back_login": "Wróć na stronę logowania", "error_during_login": "Wystąpił błąd podczas logowania. Wróć do ekranu logowania i spróbuj ponownie.", "request_password_reset": "Wyślij wiadomość e-mail umożliwiającą zresetowanie", + "send_invite": "Wyślij zaproszenie", "forgot_password": "Nie pamiętasz hasła?", "forgot": "Nie pamiętasz?", "done": "Gotowe", @@ -237,6 +239,8 @@ "set_availability": "Ustaw swoją dostępność", "continue_without_calendar": "Kontynuuj bez kalendarza", "connect_your_calendar": "Połącz swój kalendarz", + "connect_your_video_app": "Połącz aplikacje wideo", + "connect_your_video_app_instructions": "Podłącz aplikacje wideo, aby korzystać z ich w swoich typach wydarzeń.", "connect_your_calendar_instructions": "Podłącz swój kalendarz do automatycznego sprawdzania dostępności i nowych wydarzeń, zgodnie z planem.", "set_up_later": "Skonfiguruj później", "current_time": "Aktualny czas", @@ -367,6 +371,7 @@ "create_webhook": "Utwórz Webhook", "booking_cancelled": "Rezerwacja anulowana", "booking_rescheduled": "Rezerwacja Przełożona", + "recording_ready": "Link do pobrania nagrania gotowy", "booking_created": "Rezerwacja Utworzona", "meeting_ended": "Spotkanie zakończone", "form_submitted": "Przesłano formularz", @@ -465,6 +470,7 @@ "friday": "Piątek", "saturday": "Sobota", "sunday": "Niedziela", + "all_booked_today": "Wszystko zarezerwowane.", "slots_load_fail": "Nie można załadować dostępnych przedziałów czasu.", "additional_guests": "Dodaj gości", "your_name": "Twoje imię", @@ -752,6 +758,7 @@ "new_event_type_to_book_description": "Utwórz nowy typ wydarzenia, z którym ludzie mogą rezerwować czasy.", "length": "Długość", "minimum_booking_notice": "Minimalne powiadomienie", + "offset_toggle": "Opóźnij czasy rozpoczęcia", "slot_interval": "Przedziały czasowe", "slot_interval_default": "Użyj długości zdarzenia (domyślnie)", "delete_event_type": "Usunąć typ wydarzenia?", From d2af42431cf05d4ec870a69779bc1c538ab84026 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 18:52:45 +0000 Subject: [PATCH 064/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/pl/common.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/web/public/static/locales/pl/common.json b/apps/web/public/static/locales/pl/common.json index fbc09f8798..ead2f63359 100644 --- a/apps/web/public/static/locales/pl/common.json +++ b/apps/web/public/static/locales/pl/common.json @@ -759,6 +759,8 @@ "length": "Długość", "minimum_booking_notice": "Minimalne powiadomienie", "offset_toggle": "Opóźnij czasy rozpoczęcia", + "offset_toggle_description": "Przesuń przedziały czasowe wyświetlane rezerwującym o określoną liczbę minut", + "offset_start": "Przesuń o", "slot_interval": "Przedziały czasowe", "slot_interval_default": "Użyj długości zdarzenia (domyślnie)", "delete_event_type": "Usunąć typ wydarzenia?", From c87ada5646495105095917e1146756d9ee4b393c Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 18:53:41 +0000 Subject: [PATCH 065/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/pl/common.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/web/public/static/locales/pl/common.json b/apps/web/public/static/locales/pl/common.json index ead2f63359..7b54c77d8f 100644 --- a/apps/web/public/static/locales/pl/common.json +++ b/apps/web/public/static/locales/pl/common.json @@ -913,6 +913,7 @@ "duplicate": "Duplikat", "offer_seats": "Zaproponuj miejsca", "offer_seats_description": "Zaoferuj miejsca do zarezerwowania. To automatycznie wyłącza rezerwacje gości i rezerwacje wstępne.", + "seats_available_one": "Dostępne miejsce", "seats_available_other": "Dostępne miejsca", "number_of_seats": "Liczba miejsc na rezerwację", "enter_number_of_seats": "Wprowadź liczbę miejsc", @@ -1047,6 +1048,7 @@ "event_cancelled_trigger": "gdy wydarzenie zostanie odwołane", "new_event_trigger": "gdy nowe wydarzenie zostanie zarezerwowane", "email_host_action": "wyślij wiadomość e-mail do hosta", + "email_attendee_action": "wyślij wiadomość e-mail do uczestników", "sms_attendee_action": "wyślij SMS do uczestnika", "sms_number_action": "wyślij wiadomość SMS na określony numer", "workflows": "Przepływy pracy", @@ -1199,6 +1201,7 @@ "create_workflow": "Utwórz przepływ pracy", "do_this": "Zrób to", "turn_off": "Wyłącz", + "turn_on": "Włącz", "settings_updated_successfully": "Ustawienia zaktualizowane pomyślnie", "error_updating_settings": "Błąd podczas aktualizacji ustawień", "personal_cal_url": "Mój osobisty adres URL aplikacji {{appName}}", From 4e55b88ec9129a4f73baf669ade738e990042d51 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 18:54:27 +0000 Subject: [PATCH 066/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/pl/common.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/web/public/static/locales/pl/common.json b/apps/web/public/static/locales/pl/common.json index 7b54c77d8f..be66595825 100644 --- a/apps/web/public/static/locales/pl/common.json +++ b/apps/web/public/static/locales/pl/common.json @@ -1258,6 +1258,7 @@ "calendars_description": "Skonfiguruj sposoby interakcji typów wydarzeń z kalendarzami", "appearance_description": "Zarządzaj ustawieniami wyglądu rezerwacji", "conferencing_description": "Dodaj ulubione aplikacje do wideokonferencji, aby umożliwić korzystanie z nich podczas spotkań", + "add_conferencing_app": "Dodaj aplikację konferencyjną", "password_description": "Zarządzaj ustawieniami haseł do kont", "2fa_description": "Zarządzaj ustawieniami haseł do kont", "we_just_need_basic_info": "Potrzebujemy podstawowych informacji, aby skonfigurować Twój profil.", @@ -1707,6 +1708,7 @@ "spot_popular_event_types_description": "Zobacz, które typy wydarzeń są najczęściej klikane i rezerwowane", "no_responses_yet": "Nie ma jeszcze odpowiedzi", "this_will_be_the_placeholder": "To będzie symbol zastępczy", + "timeslot_missing_title": "Nie wybrano przedziału czasowego", "this_meeting_has_not_started_yet": "To spotkanie jeszcze się nie rozpoczęło", "this_app_requires_connected_account": "Aplikacja {{appName}} wymaga podłączonego konta {{dependencyName}}", "connect_app": "Podłącz {{dependencyName}}", From 1c9a549c1077fb9b446c2b9d9d39d13e0d5ff07a Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 18:55:26 +0000 Subject: [PATCH 067/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/pl/common.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/web/public/static/locales/pl/common.json b/apps/web/public/static/locales/pl/common.json index be66595825..637996b595 100644 --- a/apps/web/public/static/locales/pl/common.json +++ b/apps/web/public/static/locales/pl/common.json @@ -1709,6 +1709,12 @@ "no_responses_yet": "Nie ma jeszcze odpowiedzi", "this_will_be_the_placeholder": "To będzie symbol zastępczy", "timeslot_missing_title": "Nie wybrano przedziału czasowego", + "timeslot_missing_description": "Wybierz przedział czasowy, aby zarezerwować wydarzenie.", + "timeslot_missing_cta": "Wybierz przedział czasowy", + "switch_monthly": "Przełącz na widok miesięczny", + "switch_weekly": "Przełącz na widok tygodniowy", + "switch_multiday": "Przełącz na widok dzienny", + "num_locations": "Lokalizacje do wyboru: {{num}}", "this_meeting_has_not_started_yet": "To spotkanie jeszcze się nie rozpoczęło", "this_app_requires_connected_account": "Aplikacja {{appName}} wymaga podłączonego konta {{dependencyName}}", "connect_app": "Podłącz {{dependencyName}}", From ae52c83010125f329f409eeec499c520edb0336b Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 18:56:22 +0000 Subject: [PATCH 068/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/pl/common.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/web/public/static/locales/pl/common.json b/apps/web/public/static/locales/pl/common.json index 637996b595..f4f33ef6c8 100644 --- a/apps/web/public/static/locales/pl/common.json +++ b/apps/web/public/static/locales/pl/common.json @@ -1715,6 +1715,7 @@ "switch_weekly": "Przełącz na widok tygodniowy", "switch_multiday": "Przełącz na widok dzienny", "num_locations": "Lokalizacje do wyboru: {{num}}", + "select_on_next_step": "Wybierz następny krok", "this_meeting_has_not_started_yet": "To spotkanie jeszcze się nie rozpoczęło", "this_app_requires_connected_account": "Aplikacja {{appName}} wymaga podłączonego konta {{dependencyName}}", "connect_app": "Podłącz {{dependencyName}}", @@ -1744,6 +1745,7 @@ "locked_apps_description": "Członkowie będą mogli sprawdzić aktywne aplikacje, ale nie będą mogli edytować ich ustawień", "locked_webhooks_description": "Członkowie będą mogli sprawdzić aktywne webhooki, ale nie będą mogli edytować ich ustawień", "locked_workflows_description": "Członkowie będą mogli sprawdzić aktywne przepływy pracy, ale nie będą mogli edytować ich ustawień", + "locked_by_admin": "Zablokowane przez administratora zespołu", "app_not_connected": "Nie podłączono konta {{appName}}.", "connect_now": "Podłącz teraz", "managed_event_dialog_confirm_button_one": "Zastąp i poinformuj {{count}} członka", @@ -1801,5 +1803,8 @@ "seats_and_no_show_fee_error": "Obecnie nie można udostępnić miejsc ani naliczyć opłaty za niestawienie się.", "complete_your_booking": "Ukończ rezerwację", "complete_your_booking_subject": "Ukończ rezerwację: {{title}} dnia {{date}}", + "confirm_your_details": "Potwierdź swoje dane", + "currency_string": "{{amount, currency}}", + "charge_card_dialog_body": "Zamierzasz obciążyć uczestnika kwotą {{amount, currency}}. Czy na pewno chcesz kontynuować?", "email_invite_team": "Zaproszono {{email}}" } From 60bfdc0adcba035c3292bbb7e270b7d88ac5b7f4 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 18:57:09 +0000 Subject: [PATCH 069/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/pl/common.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/web/public/static/locales/pl/common.json b/apps/web/public/static/locales/pl/common.json index f4f33ef6c8..df7d313bd4 100644 --- a/apps/web/public/static/locales/pl/common.json +++ b/apps/web/public/static/locales/pl/common.json @@ -1806,5 +1806,6 @@ "confirm_your_details": "Potwierdź swoje dane", "currency_string": "{{amount, currency}}", "charge_card_dialog_body": "Zamierzasz obciążyć uczestnika kwotą {{amount, currency}}. Czy na pewno chcesz kontynuować?", + "charge_attendee": "Pobierz od uczestnika opłatę w wysokości {{amount, currency}}", "email_invite_team": "Zaproszono {{email}}" } From 92c015ec83887e01b43a4b260290cd0b045704ea Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 18:58:03 +0000 Subject: [PATCH 070/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/pl/common.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/web/public/static/locales/pl/common.json b/apps/web/public/static/locales/pl/common.json index df7d313bd4..6fdd5f12da 100644 --- a/apps/web/public/static/locales/pl/common.json +++ b/apps/web/public/static/locales/pl/common.json @@ -1807,5 +1807,8 @@ "currency_string": "{{amount, currency}}", "charge_card_dialog_body": "Zamierzasz obciążyć uczestnika kwotą {{amount, currency}}. Czy na pewno chcesz kontynuować?", "charge_attendee": "Pobierz od uczestnika opłatę w wysokości {{amount, currency}}", - "email_invite_team": "Zaproszono {{email}}" + "payment_app_commission": "Wymagaj płatności ({{paymentFeePercentage}}% + {{fee, currency}} prowizji od transakcji)", + "email_invite_team": "Zaproszono {{email}}", + "email_invite_team_bulk": "Zaproszono {{userCount}} użytkowników", + "error_collecting_card": "Błąd podczas pobierania karty" } From f785ab553a2172549ade54e2273209839e521f39 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 18:58:49 +0000 Subject: [PATCH 071/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/pl/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/web/public/static/locales/pl/common.json b/apps/web/public/static/locales/pl/common.json index 6fdd5f12da..b95d646bd1 100644 --- a/apps/web/public/static/locales/pl/common.json +++ b/apps/web/public/static/locales/pl/common.json @@ -1810,5 +1810,6 @@ "payment_app_commission": "Wymagaj płatności ({{paymentFeePercentage}}% + {{fee, currency}} prowizji od transakcji)", "email_invite_team": "Zaproszono {{email}}", "email_invite_team_bulk": "Zaproszono {{userCount}} użytkowników", - "error_collecting_card": "Błąd podczas pobierania karty" + "error_collecting_card": "Błąd podczas pobierania karty", + "image_size_limit_exceed": "Przesłany obraz nie powinien być większy niż 5 MB." } From dc02443a3321b013023297b1120cdff543773bf4 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 18:59:41 +0000 Subject: [PATCH 072/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/pl/common.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/web/public/static/locales/pl/common.json b/apps/web/public/static/locales/pl/common.json index b95d646bd1..b183a72079 100644 --- a/apps/web/public/static/locales/pl/common.json +++ b/apps/web/public/static/locales/pl/common.json @@ -1811,5 +1811,7 @@ "email_invite_team": "Zaproszono {{email}}", "email_invite_team_bulk": "Zaproszono {{userCount}} użytkowników", "error_collecting_card": "Błąd podczas pobierania karty", - "image_size_limit_exceed": "Przesłany obraz nie powinien być większy niż 5 MB." + "image_size_limit_exceed": "Przesłany obraz nie powinien być większy niż 5 MB.", + "floating_pop_up_button": "Pływający przycisk wyskakujący", + "invite_as": "Zaproś jako" } From 3fe32d2a9b58931bf6e28c3e24de84347bb42e81 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 19:00:26 +0000 Subject: [PATCH 073/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/pl/common.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/web/public/static/locales/pl/common.json b/apps/web/public/static/locales/pl/common.json index b183a72079..df49ba7ccb 100644 --- a/apps/web/public/static/locales/pl/common.json +++ b/apps/web/public/static/locales/pl/common.json @@ -1813,5 +1813,7 @@ "error_collecting_card": "Błąd podczas pobierania karty", "image_size_limit_exceed": "Przesłany obraz nie powinien być większy niż 5 MB.", "floating_pop_up_button": "Pływający przycisk wyskakujący", - "invite_as": "Zaproś jako" + "invite_as": "Zaproś jako", + "form_updated_successfully": "Formularz zaktualizowany pomyślnie.", + "email_not_cal_member_cta": "Dołącz do zespołu" } From 6cf8083b0268c873cb9689b3ce8804e01f47f28d Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 30 May 2023 19:01:13 +0000 Subject: [PATCH 074/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/pl/common.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/web/public/static/locales/pl/common.json b/apps/web/public/static/locales/pl/common.json index df49ba7ccb..791c1b1fb8 100644 --- a/apps/web/public/static/locales/pl/common.json +++ b/apps/web/public/static/locales/pl/common.json @@ -1815,5 +1815,8 @@ "floating_pop_up_button": "Pływający przycisk wyskakujący", "invite_as": "Zaproś jako", "form_updated_successfully": "Formularz zaktualizowany pomyślnie.", - "email_not_cal_member_cta": "Dołącz do zespołu" + "email_not_cal_member_cta": "Dołącz do zespołu", + "add_an_override": "Dodaj zastąpienie", + "import_from_google_workspace": "Importuj użytkowników z usługi Google Workspace", + "create_for": "Utwórz dla" } From 951709edefe741e993b64c2c234af5a519f3c1e5 Mon Sep 17 00:00:00 2001 From: Nafees Nazik <84864519+G3root@users.noreply.github.com> Date: Wed, 31 May 2023 00:56:29 +0530 Subject: [PATCH 075/100] fix: use ip address in forgot password rate limitation (#7832) * feat: use IP address for rate limiting * fix: use mail as the last choice * fix: fallback to ip * fix: endpoint * fix: endpoint --- apps/web/pages/api/auth/forgot-password.ts | 34 ++++++++++++++++------ 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/apps/web/pages/api/auth/forgot-password.ts b/apps/web/pages/api/auth/forgot-password.ts index 6282c11082..1d671e5b14 100644 --- a/apps/web/pages/api/auth/forgot-password.ts +++ b/apps/web/pages/api/auth/forgot-password.ts @@ -6,6 +6,7 @@ import dayjs from "@calcom/dayjs"; import { sendPasswordResetEmail } from "@calcom/emails"; import { PASSWORD_RESET_EXPIRY_HOURS } from "@calcom/emails/templates/forgot-password-email"; import rateLimit from "@calcom/lib/rateLimit"; +import { defaultHandler } from "@calcom/lib/server"; import { getTranslation } from "@calcom/lib/server/i18n"; import prisma from "@calcom/prisma"; @@ -13,28 +14,39 @@ const limiter = rateLimit({ intervalInMs: 60 * 1000, // 1 minute }); -export default async function handler(req: NextApiRequest, res: NextApiResponse) { +async function handler(req: NextApiRequest, res: NextApiResponse) { const t = await getTranslation(req.body.language ?? "en", "common"); + const email = z .string() .email() .transform((val) => val.toLowerCase()) - .parse(req.body?.email); + .safeParse(req.body?.email); - const { isRateLimited } = limiter.check(10, email); // 10 requests per minute - - if (isRateLimited) { - return res.status(429).json({ message: "Too Many Requests." }); + if (!email.success) { + return res.status(400).json({ message: "email is required" }); } - if (req.method !== "POST") { - return res.status(405).end(); + // fallback to email if ip is not present + let ip = (req.headers["x-real-ip"] as string) ?? email.data; + + const forwardedFor = req.headers["x-forwarded-for"] as string; + if (!ip && forwardedFor) { + ip = forwardedFor?.split(",").at(0) ?? email.data; + } + + // 10 requests per minute + + try { + limiter.check(10, ip); + } catch (e) { + return res.status(429).json({ message: "Too Many Requests." }); } try { const maybeUser = await prisma.user.findUnique({ where: { - email, + email: email.data, }, select: { name: true, @@ -97,3 +109,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) return res.status(500).json({ message: "Unable to create password reset request" }); } } + +export default defaultHandler({ + POST: Promise.resolve({ default: handler }), +}); From e6f142dc9ea9cd7b9acac32e5f1aa8caf2b84b7e Mon Sep 17 00:00:00 2001 From: Nafees Nazik <84864519+G3root@users.noreply.github.com> Date: Wed, 31 May 2023 01:08:17 +0530 Subject: [PATCH 076/100] fix: event editor not rendered (#9172) Co-authored-by: Keith Williams --- .../eventtypes/components/DuplicateDialog.tsx | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/packages/features/eventtypes/components/DuplicateDialog.tsx b/packages/features/eventtypes/components/DuplicateDialog.tsx index e856252b73..57ec7a9e8f 100644 --- a/packages/features/eventtypes/components/DuplicateDialog.tsx +++ b/packages/features/eventtypes/components/DuplicateDialog.tsx @@ -1,23 +1,16 @@ import { useRouter } from "next/router"; -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { z } from "zod"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useTypedQuery } from "@calcom/lib/hooks/useTypedQuery"; import { HttpError } from "@calcom/lib/http-error"; +import { md } from "@calcom/lib/markdownIt"; import slugify from "@calcom/lib/slugify"; +import turndown from "@calcom/lib/turndownService"; import { trpc } from "@calcom/trpc/react"; -import { - Button, - Dialog, - DialogClose, - DialogContent, - Form, - showToast, - TextAreaField, - TextField, -} from "@calcom/ui"; +import { Button, Dialog, DialogClose, DialogContent, Form, showToast, TextField, Editor } from "@calcom/ui"; const querySchema = z.object({ title: z.string(), @@ -31,7 +24,7 @@ const querySchema = z.object({ const DuplicateDialog = () => { const { t } = useLocale(); const router = useRouter(); - + const [firstRender, setFirstRender] = useState(true); const { data: { pageSlug, slug, ...defaultValues }, } = useTypedQuery(querySchema); @@ -125,10 +118,13 @@ const DuplicateDialog = () => { /> )} - md.render(form.getValues("description") || "")} + setText={(value: string) => form.setValue("description", turndown(value))} + excludedToolbarItems={["blockType", "link"]} placeholder={t("quick_video_meeting")} - {...register("description")} + firstRender={firstRender} + setFirstRender={setFirstRender} />
    From 451278b48efc6842d73021d74b2e4cc25ae89f3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Omar=20L=C3=B3pez?= Date: Tue, 30 May 2023 14:15:57 -0700 Subject: [PATCH 077/100] fix: routing-form flakyness (#9214) --- packages/app-store/routing-forms/components/SingleForm.tsx | 4 ++-- .../routing-forms/pages/route-builder/[...appPages].tsx | 2 +- .../app-store/routing-forms/playwright/tests/basic.e2e.ts | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/app-store/routing-forms/components/SingleForm.tsx b/packages/app-store/routing-forms/components/SingleForm.tsx index 8c1fba94e7..7a6bc17870 100644 --- a/packages/app-store/routing-forms/components/SingleForm.tsx +++ b/packages/app-store/routing-forms/components/SingleForm.tsx @@ -331,7 +331,7 @@ function SingleForm({ form, appUrl, Page }: SingleFormComponentProps) { {form.routers.map((router) => { return (
    - + {router.name}
    @@ -353,7 +353,7 @@ function SingleForm({ form, appUrl, Page }: SingleFormComponentProps) { {connectedForms.map((router) => { return (
    - + {router.name}
    diff --git a/packages/app-store/routing-forms/pages/route-builder/[...appPages].tsx b/packages/app-store/routing-forms/pages/route-builder/[...appPages].tsx index 2a6eda1fb7..e331ab9658 100644 --- a/packages/app-store/routing-forms/pages/route-builder/[...appPages].tsx +++ b/packages/app-store/routing-forms/pages/route-builder/[...appPages].tsx @@ -139,7 +139,7 @@ const Route = ({ } className="mb-6">
    - + {route.name} diff --git a/packages/app-store/routing-forms/playwright/tests/basic.e2e.ts b/packages/app-store/routing-forms/playwright/tests/basic.e2e.ts index a6af91f1c1..b2e6f9c6c6 100644 --- a/packages/app-store/routing-forms/playwright/tests/basic.e2e.ts +++ b/packages/app-store/routing-forms/playwright/tests/basic.e2e.ts @@ -344,6 +344,7 @@ test.describe("Routing Forms", () => { const routingForm = user.routingForms[0]; page.goto(`apps/routing-forms/form-edit/${routingForm.id}`); await page.click('[data-testid="test-preview"]'); + await page.waitForLoadState("networkidle"); // //event redirect await page.fill('[data-testid="form-field-Test field"]', "event-routing"); From 991167fb8b3be4edae22a19e56f30fe6dec7028a Mon Sep 17 00:00:00 2001 From: Keith Williams Date: Tue, 30 May 2023 21:13:28 -0300 Subject: [PATCH 078/100] Removed extra db-seed call since we use cache-db (#9212) --- .github/workflows/e2e.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index d4b15286a0..a8c8dfcc9e 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -27,8 +27,6 @@ jobs: - uses: ./.github/actions/env-read-file - uses: ./.github/actions/cache-db - uses: ./.github/actions/cache-build - - name: Seed Test DB - run: yarn db-seed - name: Run Tests run: yarn e2e --shard=${{ matrix.shard }}/${{ strategy.job-total }} env: From 7a9a2fc76fe70662f2859e0aabaab5e41aecc570 Mon Sep 17 00:00:00 2001 From: Rob Jackson Date: Wed, 31 May 2023 04:04:06 +0100 Subject: [PATCH 079/100] feat: Make database optional when building (#8561) * Make database optional when building Solves #3026 and #6780 We have a few app-store related pages that require a database connection at build time. This change adds try-catch blocks in getStaticPaths or getStaticProps for those pages, and when no database is available we either: - getStaticPaths: Respond with no paths, but fall back to rendering the pages on-demand - getStaticProps: Respond with no data, but enable revalidation until a future request does respond with data This makes Cal.com more compatible with typical Docker-based workflows, that do not expect external services to be available at build time. This includes Docker-based hosting providers, such as Cloudron (#3026). * Change apps/categories/index to be server-rendered * Update yarn.lock * Update yarn.lock * Update [category].tsx --------- Co-authored-by: zomars Co-authored-by: Peer Richelsen Co-authored-by: alannnc Co-authored-by: Keith Williams --- .github/workflows/pr.yml | 6 +++++ .../production-build-without-database.yml | 17 ++++++++++++ apps/web/pages/apps/[slug]/index.tsx | 15 +++++++++-- apps/web/pages/apps/categories/[category].tsx | 15 +++++++++++ apps/web/pages/apps/categories/index.tsx | 27 +++++++++++++++---- 5 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/production-build-without-database.yml diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index c2fc266790..e42cc70e91 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -66,6 +66,12 @@ jobs: uses: ./.github/workflows/production-build.yml secrets: inherit + build-without-database: + name: Production build (without database) + needs: env + uses: ./.github/workflows/production-build-without-database.yml + secrets: inherit + e2e: name: E2E tests needs: [changes, lint, build] diff --git a/.github/workflows/production-build-without-database.yml b/.github/workflows/production-build-without-database.yml new file mode 100644 index 0000000000..8f2891c278 --- /dev/null +++ b/.github/workflows/production-build-without-database.yml @@ -0,0 +1,17 @@ +name: Production Build (without database) + +on: + workflow_call: + +jobs: + build: + name: Build + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v3 + - uses: ./.github/actions/dangerous-git-checkout + - uses: ./.github/actions/yarn-install + - uses: ./.github/actions/env-read-file + - uses: ./.github/actions/cache-db + - uses: ./.github/actions/cache-build diff --git a/apps/web/pages/apps/[slug]/index.tsx b/apps/web/pages/apps/[slug]/index.tsx index 97a36bf74c..e50c1c061c 100644 --- a/apps/web/pages/apps/[slug]/index.tsx +++ b/apps/web/pages/apps/[slug]/index.tsx @@ -1,3 +1,4 @@ +import { Prisma } from "@prisma/client"; import fs from "fs"; import matter from "gray-matter"; import MarkdownIt from "markdown-it"; @@ -88,8 +89,18 @@ function SingleAppPage(props: inferSSRProps) { } export const getStaticPaths: GetStaticPaths<{ slug: string }> = async () => { - const appStore = await prisma.app.findMany({ select: { slug: true } }); - const paths = appStore.map(({ slug }) => ({ params: { slug } })); + let paths: { params: { slug: string } }[] = []; + + try { + const appStore = await prisma.app.findMany({ select: { slug: true } }); + paths = appStore.map(({ slug }) => ({ params: { slug } })); + } catch (e: unknown) { + if (e instanceof Prisma.PrismaClientInitializationError) { + // Database is not available at build time, but that's ok – we fall back to resolving paths on demand + } else { + throw e; + } + } return { paths, diff --git a/apps/web/pages/apps/categories/[category].tsx b/apps/web/pages/apps/categories/[category].tsx index 80e1bd9e1c..0d80c0002d 100644 --- a/apps/web/pages/apps/categories/[category].tsx +++ b/apps/web/pages/apps/categories/[category].tsx @@ -1,3 +1,4 @@ +import { Prisma } from "@prisma/client"; import type { GetStaticPropsContext, InferGetStaticPropsType } from "next"; import Link from "next/link"; import { useRouter } from "next/router"; @@ -54,6 +55,20 @@ Apps.PageWrapper = PageWrapper; export const getStaticPaths = async () => { const paths = Object.keys(AppCategories); + try { + await prisma.$queryRaw`SELECT 1`; + } catch (e: unknown) { + if (e instanceof Prisma.PrismaClientInitializationError) { + // Database is not available at build time. Make sure we fall back to building these pages on demand + return { + paths: [], + fallback: "blocking", + }; + } else { + throw e; + } + } + return { paths: paths.map((category) => ({ params: { category } })), fallback: false, diff --git a/apps/web/pages/apps/categories/index.tsx b/apps/web/pages/apps/categories/index.tsx index ec0f5ec22d..936e98804b 100644 --- a/apps/web/pages/apps/categories/index.tsx +++ b/apps/web/pages/apps/categories/index.tsx @@ -1,15 +1,19 @@ -import type { InferGetStaticPropsType } from "next"; +import type { GetServerSidePropsContext } from "next"; import Link from "next/link"; -import { getAppRegistry } from "@calcom/app-store/_appRegistry"; +import { getAppRegistry, getAppRegistryWithCredentials } from "@calcom/app-store/_appRegistry"; +import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; import Shell from "@calcom/features/shell/Shell"; import { useLocale } from "@calcom/lib/hooks/useLocale"; +import type { inferSSRProps } from "@calcom/types/inferSSRProps"; import { SkeletonText } from "@calcom/ui"; import { ArrowLeft, ArrowRight } from "@calcom/ui/components/icon"; import PageWrapper from "@components/PageWrapper"; -export default function Apps({ categories }: InferGetStaticPropsType) { +import { ssrInit } from "@server/lib/ssr"; + +export default function Apps({ categories }: inferSSRProps) { const { t, isLocaleReady } = useLocale(); return ( @@ -47,8 +51,20 @@ export default function Apps({ categories }: InferGetStaticPropsType { - const appStore = await getAppRegistry(); +export const getServerSideProps = async (context: GetServerSidePropsContext) => { + const { req, res } = context; + + const ssr = await ssrInit(context); + + const session = await getServerSession({ req, res }); + + let appStore; + if (session?.user?.id) { + appStore = await getAppRegistryWithCredentials(session.user.id); + } else { + appStore = await getAppRegistry(); + } + const categories = appStore.reduce((c, app) => { for (const category of app.categories) { c[category] = c[category] ? c[category] + 1 : 1; @@ -59,6 +75,7 @@ export const getStaticProps = async () => { return { props: { categories: Object.entries(categories).map(([name, count]) => ({ name, count })), + trpcState: ssr.dehydrate(), }, }; }; From 26f0a14ac2f418fe79faee07de66dc59478d4fea Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Wed, 31 May 2023 03:16:45 +0000 Subject: [PATCH 080/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/vi/common.json | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/apps/web/public/static/locales/vi/common.json b/apps/web/public/static/locales/vi/common.json index 1892909df7..44cc21f14e 100644 --- a/apps/web/public/static/locales/vi/common.json +++ b/apps/web/public/static/locales/vi/common.json @@ -372,6 +372,7 @@ "create_webhook": "Tạo Webhook", "booking_cancelled": "Lịch hẹn đã bị hủy", "booking_rescheduled": "Lịch hẹn đã được đổi", + "recording_ready": "Đã sẵn sàng liên kết tải xuống bản ghi", "booking_created": "Lịch hẹn đã được tạo", "meeting_ended": "Cuộc họp đã kết thúc", "form_submitted": "Biểu mẫu đã được gửi", @@ -470,6 +471,7 @@ "friday": "Thứ Sáu", "saturday": "Thứ Bảy", "sunday": "Chủ Nhật", + "all_booked_today": "Tất cả đã được đặt chỗ.", "slots_load_fail": "Không thể tải thời gian có thể đặt lịch.", "additional_guests": "Thêm khách", "your_name": "Tên của bạn", @@ -757,6 +759,10 @@ "new_event_type_to_book_description": "Tạo một loại sự kiện mới để mọi người đặt thời gian.", "length": "Thời gian", "minimum_booking_notice": "Thời gian đệm tối thiểu", + "offset_toggle": "Thời gian bắt đầu được bù lại", + "offset_toggle_description": "Suất thời gian bù lại được hiển thị cho những người đặt lịch theo số phút cụ thể", + "offset_start": "Bù lại", + "offset_start_description": "ví dụ cái này sẽ hiển thị những suất thời gian cho người đặt lịch vào lúc {{ adjustedTime }} thay vì {{ originalTime }}", "slot_interval": "Khoảng thời gian giữa các lịch hẹn", "slot_interval_default": "Sử dụng độ dài sự kiện (mặc định)", "delete_event_type": "Xóa loại sự kiện?", @@ -909,6 +915,7 @@ "duplicate": "Sao chép", "offer_seats": "Cung cấp ghế ngồi", "offer_seats_description": "Cung cấp ghế để đặt lịch. Việc này sẽ tự động vô hiệu hoá đặt lịch của khách & đặt lịch tham gia.", + "seats_available_one": "Số ghế trống", "seats_available_other": "Số ghế trống", "number_of_seats": "Số ghế cho mỗi lần đặt", "enter_number_of_seats": "Điền vào số lượng ghế", @@ -1043,6 +1050,7 @@ "event_cancelled_trigger": "khi sự kiện bị huỷ", "new_event_trigger": "khi sự kiện mới được đặt lịch hẹn", "email_host_action": "gửi email đến chủ sự kiện", + "email_attendee_action": "gửi email đến người tham gia", "sms_attendee_action": "gửi SMS đến người tham gia", "sms_number_action": "gửi SMS đến một số cụ thể", "workflows": "Tiến độ công việc", @@ -1195,6 +1203,7 @@ "create_workflow": "Tạo một tiến độ công việc", "do_this": "Làm cái này", "turn_off": "Tắt", + "turn_on": "Bật", "settings_updated_successfully": "Cập nhật thành công phần cài đặt", "error_updating_settings": "Lỗi khi cập nhật cài đặt", "personal_cal_url": "URL {{appName}} cá nhân của tôi", @@ -1251,6 +1260,7 @@ "calendars_description": "Cấu hình cách các loại sự kiện của bạn tương tác với lịch của bạn", "appearance_description": "Quản lí cài đặt cho giao diện lịch hẹn của bạn", "conferencing_description": "Quản lí ứng dụng hội nghị video dùng cho các cuộc họp", + "add_conferencing_app": "Thêm ứng dụng hội nghị", "password_description": "Quản lí cài đặt cho mật khẩu tài khoản", "2fa_description": "Quản lí cài đặt cho mật khẩu tài khoản", "we_just_need_basic_info": "Chúng tôi chỉ cần một số thông tin cơ bản để thiết lập hồ sơ của bạn.", @@ -1625,6 +1635,7 @@ "email_user_cta": "Xem lời mời", "email_no_user_invite_heading": "Bạn đã được mời gia nhập nhóm trên {{appName}}", "email_no_user_invite_subheading": "{{invitedBy}} đã mời bạn gia nhập nhóm của họ trên {{appName}}. {{appName}} là công cụ lên lịch sắp xếp sự kiện cho phép bạn và nhóm bạn lên lịch các cuộc gặp mà không cần trao đổi email nhiều.", + "email_user_invite_subheading": "{{invitedBy}} đã mời bạn gia nhập nhóm '{{teamName}}' của họ trên {{appName}}. {{appName}} là công cụ lên lịch sắp xếp sự kiện cho phép bạn và nhóm bạn lên lịch các cuộc gặp mà không cần trao đổi email nhiều.", "email_no_user_invite_steps_intro": "Chúng tôi sẽ hướng dẫn cho bạn qua vài bước nhỏ và bạn sẽ tận hưởng được ngay cảm giác thoải mái không căng thẳng trong việc lên lịch cùng nhóm của mình.", "email_no_user_step_one": "Chọn tên người dùng của bạn", "email_no_user_step_two": "Kết nối tài khoản lịch của bạn", @@ -1700,6 +1711,15 @@ "spot_popular_event_types_description": "Xem loại sự kiện nào của bạn nhận được nhiều lần nhấp chuột và nhiều lịch hẹn nhất", "no_responses_yet": "Chưa có hồi đáp", "this_will_be_the_placeholder": "Đây sẽ là mã giữ chỗ", + "error_booking_event": "Có lỗi khi đặt lịch sự kiện, hãy làm mới trang rồi thử lại", + "timeslot_missing_title": "Chưa chọn suất thời gian nào", + "timeslot_missing_description": "Vui lòng chọn một suất thời gian để đặt lịch sự kiện.", + "timeslot_missing_cta": "Chọn suất thời gian", + "switch_monthly": "Chuyển sang giao diện tháng", + "switch_weekly": "Chuyển sang giao diện tuần", + "switch_multiday": "Chuyển sang giao diện ngày", + "num_locations": "{{num}} lựa chọn vị trí", + "select_on_next_step": "Chọn ở bước kế tiếp", "this_meeting_has_not_started_yet": "Cuộc hẹn này chưa được bắt đầu", "this_app_requires_connected_account": "{{appName}} cần có một tài khoản {{dependencyName}} đã kết nối", "connect_app": "Kết nối {{dependencyName}}", @@ -1729,6 +1749,7 @@ "locked_apps_description": "Các thành viên có thể thấy được những ứng dụng đang hoạt động nhưng không thể sửa bất kỳ thiết lập nào của ứng dụng", "locked_webhooks_description": "Các thành viên có thể thấy được những webhook đang hoạt động nhưng không thể sửa bất kỳ thiết lập nào của webhook", "locked_workflows_description": "Các thành viên có thể thấy được những tiến độ công việc đang hoạt động nhưng không thể sửa bất kỳ thiết lập nào của tiến độ công việc", + "locked_by_admin": "Bị khoá bởi quản trị viên của nhóm", "app_not_connected": "Bạn không có tài khoản {{appName}} đã được kết nối.", "connect_now": "Kết nối ngay", "managed_event_dialog_confirm_button_one": "Thay thế & thông báo cho {{count}} thành viên", @@ -1786,5 +1807,10 @@ "seats_and_no_show_fee_error": "Hiện không thể kích hoạt chỗ ngồi và tính khoản phí vắng mặt", "complete_your_booking": "Hoàn thành lịch hẹn của bạn", "complete_your_booking_subject": "Hoàn thành lịch hẹn của bạn: {{title}} vào {{date}}", + "confirm_your_details": "Xác nhận các chi tiết của bạn", + "currency_string": "{{amount, currency}}", + "charge_card_dialog_body": "Bạn sắp sửa thu phí người tham gia một khoản {{amount, currency}}. Bạn có chắc chắn muốn tiếp tục?", + "charge_attendee": "Thu phí người tham gia một khoản {{amount, currency}}", + "payment_app_commission": "Yêu cầu thanh toán ({{paymentFeePercentage}}% + {{fee, currency}} hoa hồng cho mỗi giao dịch)", "email_invite_team": "{{email}} đã được mời" } From 92012dab091e0c657baa1e7b7758d10104175139 Mon Sep 17 00:00:00 2001 From: Soham Datta <78294692+sohamdata@users.noreply.github.com> Date: Wed, 31 May 2023 10:03:52 +0530 Subject: [PATCH 081/100] fix: wrong description in Calendar Invite after rescheduling meeting (#8576) * added instructions for setup on windows to avoid symbolic link issues * fixed wrong description after rescheduling * Update README.md --------- Co-authored-by: Hariom Balhara Co-authored-by: alannnc Co-authored-by: Peer Richelsen --- packages/features/bookings/lib/handleNewBooking.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/features/bookings/lib/handleNewBooking.ts b/packages/features/bookings/lib/handleNewBooking.ts index caf13c75e3..06c7f4ed02 100644 --- a/packages/features/bookings/lib/handleNewBooking.ts +++ b/packages/features/bookings/lib/handleNewBooking.ts @@ -1600,7 +1600,7 @@ async function handler( async function createBooking() { if (originalRescheduledBooking) { evt.title = originalRescheduledBooking?.title || evt.title; - evt.description = originalRescheduledBooking?.description || evt.additionalNotes; + evt.description = originalRescheduledBooking?.description || evt.description; evt.location = originalRescheduledBooking?.location || evt.location; } From e7ab400d29499b9dfc5bb8d1214e6d34709ad098 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Wed, 31 May 2023 04:46:32 +0000 Subject: [PATCH 082/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/zh-CN/common.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/web/public/static/locales/zh-CN/common.json b/apps/web/public/static/locales/zh-CN/common.json index 1f01304dcd..a1502944c7 100644 --- a/apps/web/public/static/locales/zh-CN/common.json +++ b/apps/web/public/static/locales/zh-CN/common.json @@ -1817,9 +1817,12 @@ "error_collecting_card": "收集卡时出错", "image_size_limit_exceed": "上传的图像不应超过 5mb 大小限制", "inline_embed": "内联嵌入", + "load_inline_content": "将您的活动类型直接与您的其他网站内容内联加载。", "floating_pop_up_button": "浮动弹出式按钮", + "floating_button_trigger_modal": "在您的网站上放置一个浮动按钮,用于根据您的活动类型触发模式。", "pop_up_element_click": "通过点击元素弹出", "open_dialog_with_element_click": "当有人点击元素时,打开您的 Cal 对话框。", + "need_help_embedding": "需要帮助?看一下在 Wix、Squarespace 或 WordPress 上嵌入 Cal 的指南,查看常见问题,或浏览高级嵌入选项。", "book_my_cal": "预约我的 Cal", "invite_as": "邀请为", "form_updated_successfully": "表单更新成功。", From 9394c092471b25b0b27e688b6921ab84764cbc2a Mon Sep 17 00:00:00 2001 From: Hariom Balhara Date: Wed, 31 May 2023 14:25:57 +0530 Subject: [PATCH 083/100] Remove cache-db from without database build (#9220) --- .github/workflows/production-build-without-database.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/production-build-without-database.yml b/.github/workflows/production-build-without-database.yml index 8f2891c278..a55f44e180 100644 --- a/.github/workflows/production-build-without-database.yml +++ b/.github/workflows/production-build-without-database.yml @@ -13,5 +13,4 @@ jobs: - uses: ./.github/actions/dangerous-git-checkout - uses: ./.github/actions/yarn-install - uses: ./.github/actions/env-read-file - - uses: ./.github/actions/cache-db - uses: ./.github/actions/cache-build From 3f736e8b805864eca633af22771ec1f3b8f88f3b Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Wed, 31 May 2023 08:56:49 +0000 Subject: [PATCH 084/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/uk/common.json | 22 +++++++++---------- apps/web/public/static/locales/vi/common.json | 9 +++++++- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/apps/web/public/static/locales/uk/common.json b/apps/web/public/static/locales/uk/common.json index 7d8c846d06..098207343a 100644 --- a/apps/web/public/static/locales/uk/common.json +++ b/apps/web/public/static/locales/uk/common.json @@ -471,7 +471,7 @@ "friday": "П’ятниця", "saturday": "Субота", "sunday": "Неділя", - "all_booked_today": "Усі заброньовані.", + "all_booked_today": "Усе заброньовано.", "slots_load_fail": "Не вдалося завантажити доступні часові вікна.", "additional_guests": "Додати гостей", "your_name": "Ваше ім’я", @@ -762,7 +762,7 @@ "offset_toggle": "Змістити час початку", "offset_toggle_description": "Проміжки часу для зміщення (у хвилинах), показані користувачам, які здійснюють бронювання", "offset_start": "Зміщення на", - "offset_start_description": "наприклад, вони бачитимуть часові проміжки о {{ adjustedTime }} замість {{ originalTime }}", + "offset_start_description": "наприклад, користувачі, які здійснюють бронювання, бачитимуть часові проміжки о {{ adjustedTime }} замість {{ originalTime }}", "slot_interval": "Інтервали між бронюваннями", "slot_interval_default": "Використовувати тривалість заходу (за замовчуванням)", "delete_event_type": "Видалити тип заходу?", @@ -915,7 +915,7 @@ "duplicate": "Дублювати", "offer_seats": "Запропонувати місця", "offer_seats_description": "Пропонуйте місця під час бронювання (при цьому вимикається гостьовий режим і бронювання з підтвердженням).", - "seats_available_one": "Доступне місце", + "seats_available_one": "Є доступне місце", "seats_available_other": "Доступні місця", "number_of_seats": "Кількість місць на одне бронювання", "enter_number_of_seats": "Введіть кількість місць", @@ -1050,7 +1050,7 @@ "event_cancelled_trigger": "у момент скасування заходу", "new_event_trigger": "у момент бронювання нового заходу", "email_host_action": "надсилати електронний лист ведучому", - "email_attendee_action": "надсилати ел. лист учасникам", + "email_attendee_action": "надсилати ел. листи учасникам", "sms_attendee_action": "надсилати SMS учаснику", "sms_number_action": "надсилати SMS на певний номер", "workflows": "Робочі процеси", @@ -1260,7 +1260,7 @@ "calendars_description": "Налаштуйте, як типи заходів мають взаємодіяти з вашими календарями", "appearance_description": "Налаштуйте варіанти оформлення свого бронювання", "conferencing_description": "Керуйте додатками для відеоконференцій і нарад", - "add_conferencing_app": "Додати застосунок Conferencing", + "add_conferencing_app": "Додати застосунок для проведення конференцій", "password_description": "Налаштуйте параметри паролів облікових записів", "2fa_description": "Налаштуйте параметри паролів облікових записів", "we_just_need_basic_info": "Щоб налаштувати ваш профіль, нам потрібні базові дані.", @@ -1810,8 +1810,8 @@ "confirm_your_details": "Підтвердьте ваші дані", "currency_string": "{{amount, currency}}", "charge_card_dialog_body": "Ви збираєтеся списати кошти з рахунку учасника: {{amount, currency}}. Бажаєте продовжити?", - "charge_attendee": "Списати з учасника {{amount, currency}}", - "payment_app_commission": "Потрібна оплата ({{paymentFeePercentage}}% + {{fee, currency}} комісія за транзакцію)", + "charge_attendee": "Списати з рахунку учасника {{amount, currency}}", + "payment_app_commission": "Потрібна оплата ({{paymentFeePercentage}}% + комісія за транзакцію в розмірі {{fee, currency}})", "email_invite_team": "{{email}} запрошено", "email_invite_team_bulk": "Запрошено стільки користувачів: {{userCount}}", "error_collecting_card": "Не вдалося забрати картку", @@ -1821,20 +1821,20 @@ "floating_pop_up_button": "Спливаюча кнопка", "floating_button_trigger_modal": "Додає спливаючу кнопку на ваш сайт, яка викликає модальне вікно з вашим типом заходу.", "pop_up_element_click": "Спливаюче вікно після натискання на елемент", - "open_dialog_with_element_click": "Відкриває ваш діалог з Cal, коли хтось натискає елемент.", + "open_dialog_with_element_click": "Відкриває ваш діалог із Cal, коли хтось натискає елемент.", "need_help_embedding": "Потрібна допомога? Перегляньте наші посібники з вбудовування Cal на Wix, Squarespace або WordPress, ознайомтеся з поширеними запитаннями або розширеними параметрами вбудовування.", "book_my_cal": "Забронювати мій Cal", "invite_as": "Запросити як", "form_updated_successfully": "Форму оновлено.", "email_not_cal_member_cta": "Приєднатися до команди", "disable_attendees_confirmation_emails": "Вимкнути листи підтвердження за замовчуванням для учасників", - "disable_attendees_confirmation_emails_description": "Принаймні один робочий процес активний у цьому типі заходів, який надсилає лист учасникам у разі бронювання події.", + "disable_attendees_confirmation_emails_description": "Принаймні один робочий процес активний у цьому типі заходів, який надсилає електронний лист учасникам у разі бронювання заходу.", "disable_host_confirmation_emails": "Вимкнути листи підтвердження за замовчуванням для ведучого", - "disable_host_confirmation_emails_description": "Принаймні один робочий процес активний у цьому типі заходів, який надсилає лист ведучому в разі бронювання події.", + "disable_host_confirmation_emails_description": "Принаймні один робочий процес активний у цьому типі заходів, який надсилає електронний лист ведучому в разі бронювання заходу.", "add_an_override": "Додати перевизначення", "import_from_google_workspace": "Імпортувати користувачів із Google Workspace", "connect_google_workspace": "Підключити Google Workspace", "google_workspace_admin_tooltip": "Ви повинні бути адміністратором Workspace, щоб використовувати цю функцію", - "first_event_type_webhook_description": "Створіть свій перший вебгук для цього типу заходу", + "first_event_type_webhook_description": "Створіть свій перший вебгук для цього типу заходів", "create_for": "Створити для" } diff --git a/apps/web/public/static/locales/vi/common.json b/apps/web/public/static/locales/vi/common.json index 44cc21f14e..b3b2004d85 100644 --- a/apps/web/public/static/locales/vi/common.json +++ b/apps/web/public/static/locales/vi/common.json @@ -1812,5 +1812,12 @@ "charge_card_dialog_body": "Bạn sắp sửa thu phí người tham gia một khoản {{amount, currency}}. Bạn có chắc chắn muốn tiếp tục?", "charge_attendee": "Thu phí người tham gia một khoản {{amount, currency}}", "payment_app_commission": "Yêu cầu thanh toán ({{paymentFeePercentage}}% + {{fee, currency}} hoa hồng cho mỗi giao dịch)", - "email_invite_team": "{{email}} đã được mời" + "email_invite_team": "{{email}} đã được mời", + "email_invite_team_bulk": "{{userCount}} người dùng đã được mời", + "error_collecting_card": "Lỗi khi thu thập thẻ", + "image_size_limit_exceed": "Ảnh tải lên không được vượt quá giới hạn kích cỡ 5mb", + "inline_embed": "Nội tuyến đã nhúng", + "load_inline_content": "Tải trực tiếp loại sự kiện của bạn ở dạng nội tuyến với nội dung khác trên website của bạn.", + "floating_pop_up_button": "Nút popup dạng nổi", + "floating_button_trigger_modal": "Đặt một nút dạng nổi trên website giúp kích hoạt chế độ với loại sự kiện này." } From 0d4e62504194c39e9d77ece5f17e62ed42c35af8 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Wed, 31 May 2023 08:57:40 +0000 Subject: [PATCH 085/100] New Crowdin translations by Github Action --- apps/web/public/static/locales/vi/common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/web/public/static/locales/vi/common.json b/apps/web/public/static/locales/vi/common.json index b3b2004d85..1a662d32a7 100644 --- a/apps/web/public/static/locales/vi/common.json +++ b/apps/web/public/static/locales/vi/common.json @@ -1819,5 +1819,6 @@ "inline_embed": "Nội tuyến đã nhúng", "load_inline_content": "Tải trực tiếp loại sự kiện của bạn ở dạng nội tuyến với nội dung khác trên website của bạn.", "floating_pop_up_button": "Nút popup dạng nổi", - "floating_button_trigger_modal": "Đặt một nút dạng nổi trên website giúp kích hoạt chế độ với loại sự kiện này." + "floating_button_trigger_modal": "Đặt một nút dạng nổi trên website giúp kích hoạt chế độ với loại sự kiện này.", + "pop_up_element_click": "Popup thông qua nhấp chuột trong phần tử" } From 220023f403e1f0758f292e1230547a362259674e Mon Sep 17 00:00:00 2001 From: Jeroen Reumkens Date: Wed, 31 May 2023 14:30:09 +0200 Subject: [PATCH 086/100] feat(UI): improvements booker (#9221) * Changed background from muted to default * Improved skelleton color for loading states. Also prevented scrollbar in available timeslots loading state by showing less skeletons. * Moved description to top, above other event meta, since this block doesnt have an icon and looks better this way. --- packages/features/bookings/Booker/Booker.tsx | 4 ++-- .../features/bookings/Booker/components/EventMeta.tsx | 7 ++++++- .../bookings/Booker/components/LargeCalendar.tsx | 2 +- .../bookings/Booker/components/Unavailable.tsx | 2 +- .../features/bookings/components/AvailableTimes.tsx | 6 +++--- .../bookings/components/event-meta/Details.tsx | 11 ----------- packages/features/bookings/types.ts | 1 - packages/features/calendars/DatePicker.tsx | 2 +- packages/ui/components/skeleton/index.tsx | 4 ++-- 9 files changed, 16 insertions(+), 23 deletions(-) diff --git a/packages/features/bookings/Booker/Booker.tsx b/packages/features/bookings/Booker/Booker.tsx index 281b06c3ba..a85b5468f9 100644 --- a/packages/features/bookings/Booker/Booker.tsx +++ b/packages/features/bookings/Booker/Booker.tsx @@ -103,7 +103,7 @@ const BookerComponent = ({ since that's not a valid option, so it would set the layout to null. */} {!isMobile && ( -
    +
    diff --git a/packages/features/bookings/Booker/components/EventMeta.tsx b/packages/features/bookings/Booker/components/EventMeta.tsx index 71315cc028..405d920072 100644 --- a/packages/features/bookings/Booker/components/EventMeta.tsx +++ b/packages/features/bookings/Booker/components/EventMeta.tsx @@ -35,7 +35,12 @@ export const EventMeta = () => { {!isLoading && !!event && ( - {event?.title} + {event?.title} + {event.description && ( + +
    + + )}
    {rescheduleBooking && ( diff --git a/packages/features/bookings/Booker/components/LargeCalendar.tsx b/packages/features/bookings/Booker/components/LargeCalendar.tsx index 155e9c6a94..9a2e2a668d 100644 --- a/packages/features/bookings/Booker/components/LargeCalendar.tsx +++ b/packages/features/bookings/Booker/components/LargeCalendar.tsx @@ -11,7 +11,7 @@ export const LargeCalendar = () => { ); return ( -
    +
    Something big is coming...