cal.pub0.org/packages/features/kbar/Kbar.tsx

329 lines
9.9 KiB
TypeScript
Raw Normal View History

import {
KBarAnimator,
KBarPortal,
KBarPositioner,
KBarProvider,
KBarResults,
KBarSearch,
useKBar,
useMatches,
useRegisterActions,
} from "kbar";
import type { Action } from "kbar";
import { useRouter } from "next/navigation";
import { useMemo } from "react";
import { appStoreMetadata } from "@calcom/app-store/appStoreMetaData";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { isMac } from "@calcom/lib/isMac";
import type { RouterOutputs } from "@calcom/trpc/react";
import { trpc } from "@calcom/trpc/react";
import { Tooltip } from "@calcom/ui";
import { Search, ArrowUp, ArrowDown, CornerDownLeft, Command } from "@calcom/ui/components/icon";
type shortcutArrayType = {
shortcuts?: string[];
};
2023-01-07 17:06:53 +00:00
type EventTypeGroups = RouterOutputs["viewer"]["eventTypes"]["getByViewer"]["eventTypeGroups"];
type EventTypeGroup = EventTypeGroups[number];
const getApps = Object.values(appStoreMetadata).map(({ name, slug }) => ({
id: slug,
name,
section: "Installable Apps",
keywords: `app ${name}`,
}));
const useEventTypesAction = () => {
const router = useRouter();
2023-01-07 17:06:53 +00:00
const { data } = trpc.viewer.eventTypes.getByViewer.useQuery();
const eventTypeActions = data?.eventTypeGroups.reduce<Action[]>((acc: Action[], group: EventTypeGroup) => {
const item: Action[] = group.eventTypes.map((item) => ({
id: `event-type-${item.id}`,
name: item.title,
section: "event_types_page_title",
keywords: "event types",
perform: () => router.push(`/event-types/${item.id}`),
}));
acc.push(...item);
return acc;
}, []);
const actions = eventTypeActions?.length ? eventTypeActions : [];
return useRegisterActions(actions);
};
export const KBarRoot = ({ children }: { children: React.ReactNode }) => {
const router = useRouter();
2023-01-07 17:06:53 +00:00
// grab link to events
// quick nested actions would be extremely useful
2023-01-07 17:06:53 +00:00
const actions = useMemo(() => {
const appStoreActions = getApps.map((item) => ({
...item,
perform: () => router.push(`/apps/${item.id}`),
}));
return [
{
id: "workflows",
name: "workflows",
section: "workflows",
shortcut: ["w", "f"],
keywords: "workflows automation",
perform: () => router.push("/workflows"),
},
{
id: "event-types",
name: "event_types_page_title",
2023-01-07 17:06:53 +00:00
section: "event_types_page_title",
shortcut: ["e", "t"],
2023-01-07 17:06:53 +00:00
keywords: "event types",
perform: () => router.push("/event-types"),
},
{
id: "app-store",
name: "app_store",
section: "apps",
shortcut: ["a", "s"],
keywords: "app store",
perform: () => router.push("/apps"),
},
{
id: "upcoming-bookings",
name: "upcoming",
section: "bookings",
shortcut: ["u", "b"],
keywords: "upcoming bookings",
perform: () => router.push("/bookings/upcoming"),
},
{
id: "recurring-bookings",
name: "recurring",
section: "bookings",
shortcut: ["r", "b"],
keywords: "recurring bookings",
perform: () => router.push("/bookings/recurring"),
},
{
id: "past-bookings",
name: "past",
section: "bookings",
shortcut: ["p", "b"],
keywords: "past bookings",
perform: () => router.push("/bookings/past"),
},
{
id: "cancelled-bookings",
name: "cancelled",
section: "bookings",
shortcut: ["c", "b"],
keywords: "cancelled bookings",
perform: () => router.push("/bookings/cancelled"),
},
{
id: "schedule",
name: "availability",
section: "availability",
shortcut: ["s", "a"],
keywords: "schedule availability",
perform: () => router.push("/availability"),
},
{
id: "profile",
name: "profile",
section: "profile",
shortcut: ["p", "s"],
keywords: "setting profile",
perform: () => router.push("/settings/my-account/profile"),
},
{
id: "avatar",
name: "change_avatar",
section: "profile",
shortcut: ["c", "a"],
keywords: "remove change modify avatar",
perform: () => router.push("/settings/my-account/profile"),
},
{
id: "timezone",
name: "timezone",
section: "profile",
shortcut: ["c", "t"],
keywords: "change modify timezone",
perform: () => router.push("/settings/my-account/general"),
},
{
id: "brand-color",
name: "brand_color",
section: "profile",
shortcut: ["b", "c"],
keywords: "change modify brand color",
perform: () => router.push("/settings/my-account/appearance"),
},
{
id: "teams",
name: "teams",
shortcut: ["t", "s"],
keywords: "add manage modify team",
perform: () => router.push("/settings/teams"),
},
{
id: "password",
name: "change_password",
section: "security",
shortcut: ["c", "p"],
keywords: "change modify password",
perform: () => router.push("/settings/security/password"),
},
{
id: "two-factor",
name: "two_factor_auth",
section: "security",
shortcut: ["t", "f", "a"],
keywords: "two factor authentication",
perform: () => router.push("/settings/security/two-factor-auth"),
},
{
id: "impersonation",
name: "user_impersonation_heading",
section: "security",
shortcut: ["u", "i"],
keywords: "user impersonation",
perform: () => router.push("/settings/security/impersonation"),
},
{
id: "license",
name: "choose_a_license",
section: "admin",
shortcut: ["u", "l"],
keywords: "license",
perform: () => router.push("/auth/setup?step=1"),
},
{
id: "webhooks",
name: "Webhooks",
section: "developer",
shortcut: ["w", "h"],
keywords: "webhook automation",
perform: () => router.push("/settings/developer/webhooks"),
},
{
id: "api-keys",
name: "api_keys",
section: "developer",
shortcut: ["a", "p", "i"],
keywords: "api keys",
perform: () => router.push("/settings/developer/api-keys"),
},
{
id: "billing",
name: "manage_billing",
section: "billing",
shortcut: ["m", "b"],
keywords: "billing view manage",
perform: () => router.push("/settings/billing"),
},
...appStoreActions,
];
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return <KBarProvider actions={actions}>{children}</KBarProvider>;
};
export const KBarContent = () => {
const { t } = useLocale();
useEventTypesAction();
return (
<KBarPortal>
<KBarPositioner>
<KBarAnimator className="bg-default z-10 w-full max-w-screen-sm overflow-hidden rounded-md shadow-lg">
<div className="border-subtle flex items-center justify-center border-b">
<Search className="text-default mx-3 h-4 w-4" />
Allows brand customization (#5329) * adjustments for each language json file: - changed every Cal or Cal.com with a variable to make it possible to change that with a custom brand - fix and renamed ATTENDEE with attendeeName * added two new variables for appName and support mail address. so everybody can change it via env * changed static Cal or Cal.com with new defined constants * Using useLocal to modify static text to make it multilingual, and passing the correct variables for brand and mail * adding new readable variables for brand, website domain and mail address * fixed search routes * made static text multilingual and fixed german translations * Revert "fixed search routes" moved changes in another pr This reverts commit e6ba11a1ec7821d8c16c502d0357f6d5fcdb1958. * revert non whitelabel changes and moved it into another pr * revert attendeeName fix * reverted translation fixes and moved them in another pr * changed back to "Cal.com Logo" * changed back to "https://console.cal.com" * added new env variable for company name and replaced some domainName variables in language files * changed default for COMPANY_NAME to Cal.com, Inc. * changed Cal.com to APP_NAME for mail templates * Dropped website domain in favor of app name * Update .env.example * Apply suggestions from code review * Code review feedback * Delete App.tsx * Update packages/ui/Kbar.tsx * added meta.CTA back it was mistakenly removed * updated add members test Co-authored-by: maxi <maximilian.oehrlein@clicksports.de> Co-authored-by: Peer Richelsen <peeroke@gmail.com> Co-authored-by: zomars <zomars@me.com>
2022-11-30 21:52:56 +00:00
<KBarSearch
defaultPlaceholder={t("kbar_search_placeholder")}
className="bg-default placeholder:text-subtle text-default w-full rounded-sm py-2.5 focus-visible:outline-none"
Allows brand customization (#5329) * adjustments for each language json file: - changed every Cal or Cal.com with a variable to make it possible to change that with a custom brand - fix and renamed ATTENDEE with attendeeName * added two new variables for appName and support mail address. so everybody can change it via env * changed static Cal or Cal.com with new defined constants * Using useLocal to modify static text to make it multilingual, and passing the correct variables for brand and mail * adding new readable variables for brand, website domain and mail address * fixed search routes * made static text multilingual and fixed german translations * Revert "fixed search routes" moved changes in another pr This reverts commit e6ba11a1ec7821d8c16c502d0357f6d5fcdb1958. * revert non whitelabel changes and moved it into another pr * revert attendeeName fix * reverted translation fixes and moved them in another pr * changed back to "Cal.com Logo" * changed back to "https://console.cal.com" * added new env variable for company name and replaced some domainName variables in language files * changed default for COMPANY_NAME to Cal.com, Inc. * changed Cal.com to APP_NAME for mail templates * Dropped website domain in favor of app name * Update .env.example * Apply suggestions from code review * Code review feedback * Delete App.tsx * Update packages/ui/Kbar.tsx * added meta.CTA back it was mistakenly removed * updated add members test Co-authored-by: maxi <maximilian.oehrlein@clicksports.de> Co-authored-by: Peer Richelsen <peeroke@gmail.com> Co-authored-by: zomars <zomars@me.com>
2022-11-30 21:52:56 +00:00
/>
</div>
<RenderResults />
<div className="text-subtle border-subtle hidden items-center space-x-1 border-t px-2 py-1.5 text-xs sm:flex">
<ArrowUp className="h-4 w-4" />
<ArrowDown className="h-4 w-4" /> <span className="pr-2">{t("navigate")}</span>
<CornerDownLeft className="h-4 w-4" />
<span className="pr-2">{t("open")}</span>
{isMac ? <Command className="h-3 w-3" /> : "CTRL"}
<span className="pr-1">+ K </span>
<span className="pr-2">{t("close")}</span>
</div>
</KBarAnimator>
<div className="z-1 fixed inset-0 bg-neutral-800 bg-opacity-70" />
</KBarPositioner>
</KBarPortal>
);
};
export const KBarTrigger = () => {
const { query } = useKBar();
return query ? (
<>
<Tooltip side="right" content={isMac ? "⌘ + K" : "CTRL + K"}>
<button
color="minimal"
onClick={query.toggle}
className="text-default hover:bg-subtle lg:hover:bg-emphasis lg:hover:text-emphasis group flex rounded-md px-3 py-2 text-sm font-medium lg:px-2">
<Search className="h-4 w-4 flex-shrink-0 text-inherit" />
</button>
</Tooltip>
</>
) : null;
};
const DisplayShortcuts = (item: shortcutArrayType) => {
const shortcuts = item.shortcuts;
return (
<span className="space-x-1">
{shortcuts?.map((shortcut) => {
return (
<kbd
key={shortcut}
className="bg-default hover:bg-subtle text-emphasis rounded-sm border px-2 py-1">
{shortcut}
</kbd>
);
})}
</span>
);
};
function RenderResults() {
const { results } = useMatches();
Improve multilingualism and fix search routes (#5334) * fixed search routes * made static text multilingual and fixed german translations # Conflicts: # apps/web/components/availability/Schedule.tsx * delete empty file created by fixing merge conflicts * fixing TextField placeholder by passing attendeeName and fixed json variable * Using useLocal to modify static text to make it multilingual, and passing the correct variables for brand and mail * seperated whitelabel and improved translations * added missing translation * added missing translation for webhooks * Updated AdminAppsView with dynamic translations. Added translations for german and english files only. * changed back to one liner * updated german and english translations for impersonation.tsx * updated german and english translations for impersonation.tsx and users.tsx. added missing german translation for timeformat_profile_hint * updated german and english translations for team-billing-view.tsx * updated german and english translations for LicenseRequired.tsx * updated routes for profile and avatar * yarn.lock updated from newer changes * Revert " yarn.lock updated from newer changes" This reverts commit efd9a90bf774371a331861e4fb441ab4f4d0b7fd. * sanitize dangerouslySetInnerHTML to prevent xss attacks * tried to fix window title flicker * changed ssdInit to ssrInit for getServerSideProps. Serverside translation works but current route still set as a window title * flicker with route in window title is caused here. It is not necessary to check if isPublic and session is false because it already gets checked in useRedirectToLoginIfUnauthenticated hook. * fixed window title translation flicker for availability page * fixed window title translation flicker for teams page * fixed window title translation flicker for workflow page * fixed error that div may not be rendered within p element * fixed window title translation flicker for booking page * fixed window title translation flicker by adding getServerSideProps * Only set HeadSeo if an page title exists. If window title is set by the Meta component, shell is causing a flicker because it overwrites the title which is set by Meta. It is a problem especially for settings pages. * fixed window title translation flicker by adding the Meta component to the skeleton * fixed condition * removed condition and added withoutSeo for settings pages * using translations for create team page further fixed flicker for window title * fixed flicker for window title for event-type creation page * fixed flicker for window title for availability creation page * fixed flicker for window title for sso page * updated conferencing en translation * added meta.CTA back it was mistakenly removed * fixed flicker for workflows page * fixed missing variable * Update packages/ui/v2/core/Shell.tsx * Delete index.tsx * Update sso.tsx * Updates subdmoules Co-authored-by: maxi <maximilian.oehrlein@clicksports.de> Co-authored-by: Peer Richelsen <peeroke@gmail.com> Co-authored-by: Omar López <zomars@me.com>
2022-12-07 20:53:44 +00:00
const { t } = useLocale();
return (
<KBarResults
items={results}
onRender={({ item, active }) =>
typeof item === "string" ? (
<div className="bg-default text-emphasis p-4 text-xs font-bold uppercase">{t(item)}</div>
) : (
<div
// For seeing keyboard up & down navigation in action, we need visual feedback based on "active" prop
style={{
background: active ? "var(--cal-bg-subtle)" : `var(--cal-bg-default)`,
borderLeft: active ? "2px solid var(--cal-border-default)" : "2px solid transparent",
color: "var(--cal-text)",
}}
className="flex items-center justify-between px-4 py-2.5 text-sm hover:cursor-pointer">
Improve multilingualism and fix search routes (#5334) * fixed search routes * made static text multilingual and fixed german translations # Conflicts: # apps/web/components/availability/Schedule.tsx * delete empty file created by fixing merge conflicts * fixing TextField placeholder by passing attendeeName and fixed json variable * Using useLocal to modify static text to make it multilingual, and passing the correct variables for brand and mail * seperated whitelabel and improved translations * added missing translation * added missing translation for webhooks * Updated AdminAppsView with dynamic translations. Added translations for german and english files only. * changed back to one liner * updated german and english translations for impersonation.tsx * updated german and english translations for impersonation.tsx and users.tsx. added missing german translation for timeformat_profile_hint * updated german and english translations for team-billing-view.tsx * updated german and english translations for LicenseRequired.tsx * updated routes for profile and avatar * yarn.lock updated from newer changes * Revert " yarn.lock updated from newer changes" This reverts commit efd9a90bf774371a331861e4fb441ab4f4d0b7fd. * sanitize dangerouslySetInnerHTML to prevent xss attacks * tried to fix window title flicker * changed ssdInit to ssrInit for getServerSideProps. Serverside translation works but current route still set as a window title * flicker with route in window title is caused here. It is not necessary to check if isPublic and session is false because it already gets checked in useRedirectToLoginIfUnauthenticated hook. * fixed window title translation flicker for availability page * fixed window title translation flicker for teams page * fixed window title translation flicker for workflow page * fixed error that div may not be rendered within p element * fixed window title translation flicker for booking page * fixed window title translation flicker by adding getServerSideProps * Only set HeadSeo if an page title exists. If window title is set by the Meta component, shell is causing a flicker because it overwrites the title which is set by Meta. It is a problem especially for settings pages. * fixed window title translation flicker by adding the Meta component to the skeleton * fixed condition * removed condition and added withoutSeo for settings pages * using translations for create team page further fixed flicker for window title * fixed flicker for window title for event-type creation page * fixed flicker for window title for availability creation page * fixed flicker for window title for sso page * updated conferencing en translation * added meta.CTA back it was mistakenly removed * fixed flicker for workflows page * fixed missing variable * Update packages/ui/v2/core/Shell.tsx * Delete index.tsx * Update sso.tsx * Updates subdmoules Co-authored-by: maxi <maximilian.oehrlein@clicksports.de> Co-authored-by: Peer Richelsen <peeroke@gmail.com> Co-authored-by: Omar López <zomars@me.com>
2022-12-07 20:53:44 +00:00
<span>{t(item.name)}</span>
<DisplayShortcuts shortcuts={item.shortcut} />
</div>
)
}
/>
);
}