fix: make shortcut change work for shortcuts with two words, added sidebar shortcut, fix categories order (#4831)
* Removed sidebar shortcut * Fixed restore default shortcut * Added new shortcut and fixed the freezePath one * Added shortcut to sidebar opening * Added shortcut_mod for correct restore, added shortcut for sidebar * Fixed freezePath shortcut name * Refactored the shortcutName get to get the correct shortcut * Added new toggleSidebar and fixed freezePath name * Fix categories order * Fix custom_component not showing the correct empty results * Add toCamelCase function * Refactor shortcut to work with more than one word * Removed unused console.log * fix ctrl not appearing
This commit is contained in:
parent
eb46bd4606
commit
2f629c63a6
13 changed files with 115 additions and 94 deletions
|
|
@ -19,18 +19,20 @@ export default function RenderKey({
|
|||
/>
|
||||
) : check === "ctrl" && IS_MAC ? (
|
||||
<span>⌃</span>
|
||||
) : check === "mod" && !IS_MAC ? (
|
||||
<span>Ctrl</span>
|
||||
) : check === "alt" && IS_MAC ? (
|
||||
<ForwardedIconComponent
|
||||
name="OptionIcon"
|
||||
className={cn(tableRender ? "h-4 w-4" : "h-3 w-3")}
|
||||
/>
|
||||
) : check === "cmd" ? (
|
||||
) : (check === "mod" && IS_MAC) || check === "cmd" ? (
|
||||
<ForwardedIconComponent
|
||||
name="Command"
|
||||
className={cn(tableRender ? "h-4 w-4" : "h-3 w-3")}
|
||||
/>
|
||||
) : (
|
||||
<span>{value}</span>
|
||||
<span>{value.toUpperCase()}</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
|
|||
});
|
||||
};
|
||||
|
||||
const changes = useShortcutsStore((state) => state.changes);
|
||||
const changes = useShortcutsStore((state) => state.changesSave);
|
||||
useHotkeys(changes, handleSave, { preventDefault: true });
|
||||
|
||||
return currentFlow && onFlowPage ? (
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export default function FlowToolbar(): JSX.Element {
|
|||
setOpenShareModal((oldState) => !oldState);
|
||||
}
|
||||
|
||||
const openPlayground = useShortcutsStore((state) => state.open);
|
||||
const openPlayground = useShortcutsStore((state) => state.openPlayground);
|
||||
const api = useShortcutsStore((state) => state.api);
|
||||
const flow = useShortcutsStore((state) => state.flow);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import { PanelLeft } from "lucide-react";
|
|||
import * as React from "react";
|
||||
|
||||
import { useIsMobile } from "@/hooks/use-mobile";
|
||||
import { useHotkeys } from "react-hotkeys-hook";
|
||||
import isWrappedWithClass from "../../pages/FlowPage/components/PageComponent/utils/is-wrapped-with-class";
|
||||
import { useShortcutsStore } from "../../stores/shortcuts";
|
||||
import { cn } from "../../utils/utils";
|
||||
import ShadTooltip from "../common/shadTooltipComponent";
|
||||
import { Button } from "./button";
|
||||
|
|
@ -18,7 +21,6 @@ const SIDEBAR_COOKIE_NAME = "sidebar:state";
|
|||
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
||||
const SIDEBAR_WIDTH = "19rem";
|
||||
const SIDEBAR_WIDTH_ICON = "4rem";
|
||||
const SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
||||
|
||||
type SidebarContext = {
|
||||
state: "expanded" | "collapsed";
|
||||
|
|
@ -84,23 +86,7 @@ const SidebarProvider = React.forwardRef<
|
|||
// Helper to toggle the sidebar.
|
||||
const toggleSidebar = React.useCallback(() => {
|
||||
return setOpen((open) => !open);
|
||||
}, [setOpen]);
|
||||
|
||||
// Adds a keyboard shortcut to toggle the sidebar.
|
||||
React.useEffect(() => {
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (
|
||||
event.key === SIDEBAR_KEYBOARD_SHORTCUT &&
|
||||
(event.metaKey || event.ctrlKey)
|
||||
) {
|
||||
event.preventDefault();
|
||||
toggleSidebar();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("keydown", handleKeyDown);
|
||||
return () => window.removeEventListener("keydown", handleKeyDown);
|
||||
}, [toggleSidebar]);
|
||||
}, [setOpen, open]);
|
||||
|
||||
// We add a state so that we can do data-state="expanded" or "collapsed".
|
||||
// This makes it easier to style the sidebar with Tailwind classes.
|
||||
|
|
@ -117,6 +103,22 @@ const SidebarProvider = React.forwardRef<
|
|||
[state, open, setOpen, toggleSidebar, defaultOpen],
|
||||
);
|
||||
|
||||
const toggleSidebarShortcut = useShortcutsStore(
|
||||
(state) => state.toggleSidebar,
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
toggleSidebarShortcut,
|
||||
(e: KeyboardEvent) => {
|
||||
if (isWrappedWithClass(e, "noflow")) return;
|
||||
e.preventDefault();
|
||||
toggleSidebar();
|
||||
},
|
||||
{
|
||||
preventDefault: true,
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
<SidebarContext.Provider value={contextValue}>
|
||||
<TooltipProvider delayDuration={0}>
|
||||
|
|
|
|||
|
|
@ -761,103 +761,107 @@ export const IS_MAC = navigator.userAgent.toUpperCase().includes("MAC");
|
|||
export const defaultShortcuts = [
|
||||
{
|
||||
name: "Advanced Settings",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + Shift + A`,
|
||||
shortcut: "mod+shift+a",
|
||||
},
|
||||
{
|
||||
name: "Minimize",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + Q`,
|
||||
shortcut: "mod+q",
|
||||
},
|
||||
{
|
||||
name: "Code",
|
||||
shortcut: `Space`,
|
||||
shortcut: "space",
|
||||
},
|
||||
{
|
||||
name: "Copy",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + C`,
|
||||
shortcut: "mod+c",
|
||||
},
|
||||
{
|
||||
name: "Duplicate",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + D`,
|
||||
shortcut: "mod+d",
|
||||
},
|
||||
{
|
||||
name: "Component Share",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + Shift + S`,
|
||||
shortcut: "mod+shift+s",
|
||||
},
|
||||
{
|
||||
name: "Docs",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + Shift + D`,
|
||||
shortcut: "mod+shift+d",
|
||||
},
|
||||
{
|
||||
name: "Changes Save",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + S`,
|
||||
shortcut: "mod+s",
|
||||
},
|
||||
{
|
||||
name: "Save Component",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + Alt + S`,
|
||||
shortcut: "mod+alt+s",
|
||||
},
|
||||
{
|
||||
name: "Delete",
|
||||
shortcut: "Backspace",
|
||||
shortcut: "backspace",
|
||||
},
|
||||
{
|
||||
name: "Open playground",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + K`,
|
||||
shortcut: "mod+k",
|
||||
},
|
||||
{
|
||||
name: "Undo",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + Z`,
|
||||
shortcut: "mod+z",
|
||||
},
|
||||
{
|
||||
name: "Redo",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + Y`,
|
||||
shortcut: "mod+y",
|
||||
},
|
||||
{
|
||||
name: "Group",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + G`,
|
||||
shortcut: "mod+g",
|
||||
},
|
||||
{
|
||||
name: "Cut",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + X`,
|
||||
shortcut: "mod+x",
|
||||
},
|
||||
{
|
||||
name: "Paste",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + V`,
|
||||
shortcut: "mod+v",
|
||||
},
|
||||
{
|
||||
name: "API",
|
||||
shortcut: `R`,
|
||||
shortcut: "r",
|
||||
},
|
||||
{
|
||||
name: "Download",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + J`,
|
||||
shortcut: "mod+j",
|
||||
},
|
||||
{
|
||||
name: "Update",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + U`,
|
||||
shortcut: "mod+u",
|
||||
},
|
||||
{
|
||||
name: "Freeze",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + F`,
|
||||
shortcut: "mod+f",
|
||||
},
|
||||
{
|
||||
name: "Freeze Path",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + Shift + F`,
|
||||
shortcut: "mod+shift+f",
|
||||
},
|
||||
{
|
||||
name: "Flow Share",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + B`,
|
||||
shortcut: "mod+shift+b",
|
||||
},
|
||||
{
|
||||
name: "Play",
|
||||
shortcut: `P`,
|
||||
shortcut: "p",
|
||||
},
|
||||
{
|
||||
name: "Output Inspection",
|
||||
shortcut: `O`,
|
||||
shortcut: "o",
|
||||
},
|
||||
{
|
||||
name: "Tool Mode",
|
||||
shortcut: `${IS_MAC ? "Cmd" : "Ctrl"} + Shift + M`,
|
||||
shortcut: "mod+shift+m",
|
||||
},
|
||||
{
|
||||
name: "Toggle Sidebar",
|
||||
shortcut: "mod+b",
|
||||
},
|
||||
];
|
||||
|
||||
|
|
@ -915,7 +919,7 @@ export const TEXT_FIELD_TYPES: string[] = ["str", "SecretStr"];
|
|||
export const NODE_WIDTH = 384;
|
||||
export const NODE_HEIGHT = NODE_WIDTH * 3;
|
||||
|
||||
export const SHORTCUT_KEYS = ["cmd", "ctrl", "alt", "shift"];
|
||||
export const SHORTCUT_KEYS = ["cmd", "ctrl", "mod", "alt", "shift"];
|
||||
|
||||
export const SERVER_HEALTH_INTERVAL = 10000;
|
||||
export const REFETCH_SERVER_HEALTH_INTERVAL = 20000;
|
||||
|
|
|
|||
|
|
@ -156,8 +156,11 @@ export function FlowSidebarComponent() {
|
|||
}, [search, getFilterEdge]);
|
||||
|
||||
const hasResults = useMemo(() => {
|
||||
return Object.values(dataFilter).some(
|
||||
(category) => Object.keys(category).length > 0,
|
||||
return Object.entries(dataFilter).some(
|
||||
([category, items]) =>
|
||||
Object.keys(items).length > 0 &&
|
||||
(CATEGORIES.find((c) => c.name === category) ||
|
||||
BUNDLES.find((b) => b.name === category)),
|
||||
);
|
||||
}, [dataFilter]);
|
||||
const [sortedCategories, setSortedCategories] = useState<string[]>([]);
|
||||
|
|
@ -191,13 +194,13 @@ export function FlowSidebarComponent() {
|
|||
setSortedCategories(
|
||||
Object.keys(filteredData)
|
||||
.filter(
|
||||
(category) => Object.keys(filteredData[category]).length > 0,
|
||||
(category) =>
|
||||
Object.keys(filteredData[category]).length > 0 &&
|
||||
(CATEGORIES.find((c) => c.name === category) ||
|
||||
BUNDLES.find((b) => b.name === category)),
|
||||
)
|
||||
.toSorted(
|
||||
(a, b) =>
|
||||
fuseCategories.findIndex((value) => value === a) ??
|
||||
0 - fuseCategories.findIndex((value) => value === b) ??
|
||||
0,
|
||||
.toSorted((a, b) =>
|
||||
fuseCategories.indexOf(b) < fuseCategories.indexOf(a) ? 1 : -1,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,16 +35,16 @@ export default function useShortcuts({
|
|||
minimizeFunction?: () => void;
|
||||
activateToolMode?: () => void;
|
||||
}) {
|
||||
const advanced = useShortcutsStore((state) => state.advanced);
|
||||
const advancedSettings = useShortcutsStore((state) => state.advancedSettings);
|
||||
const minimize = useShortcutsStore((state) => state.minimize);
|
||||
const component = useShortcutsStore((state) => state.component);
|
||||
const save = useShortcutsStore((state) => state.save);
|
||||
const componentShare = useShortcutsStore((state) => state.componentShare);
|
||||
const save = useShortcutsStore((state) => state.saveComponent);
|
||||
const docs = useShortcutsStore((state) => state.docs);
|
||||
const code = useShortcutsStore((state) => state.code);
|
||||
const group = useShortcutsStore((state) => state.group);
|
||||
const download = useShortcutsStore((state) => state.download);
|
||||
const freeze = useShortcutsStore((state) => state.freeze);
|
||||
const freezeAll = useShortcutsStore((state) => state.FreezePath);
|
||||
const freezeAll = useShortcutsStore((state) => state.freezePath);
|
||||
const toolMode = useShortcutsStore((state) => state.toolMode);
|
||||
|
||||
function handleFreezeAll(e: KeyboardEvent) {
|
||||
|
|
@ -125,9 +125,11 @@ export default function useShortcuts({
|
|||
|
||||
useHotkeys(minimize, handleMinimizeWShortcut, { preventDefault: true });
|
||||
useHotkeys(group, handleGroupWShortcut, { preventDefault: true });
|
||||
useHotkeys(component, handleShareWShortcut, { preventDefault: true });
|
||||
useHotkeys(componentShare, handleShareWShortcut, { preventDefault: true });
|
||||
useHotkeys(code, handleCodeWShortcut, { preventDefault: true });
|
||||
useHotkeys(advanced, handleAdvancedWShortcut, { preventDefault: true });
|
||||
useHotkeys(advancedSettings, handleAdvancedWShortcut, {
|
||||
preventDefault: true,
|
||||
});
|
||||
useHotkeys(save, handleSaveWShortcut, { preventDefault: true });
|
||||
useHotkeys(docs, handleDocsWShortcut, { preventDefault: true });
|
||||
useHotkeys(download, handleDownloadWShortcut, { preventDefault: true });
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import ForwardedIconComponent from "../../../../../components/common/genericIcon
|
|||
import { Button } from "../../../../../components/ui/button";
|
||||
import BaseModal from "../../../../../modals/baseModal";
|
||||
import { useShortcutsStore } from "../../../../../stores/shortcuts";
|
||||
import { toTitleCase } from "../../../../../utils/utils";
|
||||
import { toCamelCase, toTitleCase } from "../../../../../utils/utils";
|
||||
|
||||
export default function EditShortcutButton({
|
||||
children,
|
||||
|
|
@ -28,9 +28,7 @@ export default function EditShortcutButton({
|
|||
let shortcutInitialValue =
|
||||
defaultShortcuts.length > 0
|
||||
? defaultShortcuts.find(
|
||||
(s) =>
|
||||
s.name.split(" ")[0].toLowerCase().toLowerCase() ===
|
||||
shortcut[0]?.split(" ")[0].toLowerCase(),
|
||||
(s) => toCamelCase(s.name) === toCamelCase(shortcut[0]),
|
||||
)?.shortcut
|
||||
: "";
|
||||
const [key, setKey] = useState<string | null>(null);
|
||||
|
|
@ -55,12 +53,6 @@ export default function EditShortcutButton({
|
|||
function editCombination(): void {
|
||||
if (key) {
|
||||
if (canEditCombination(key)) {
|
||||
const newCombination = defaultShortcuts.map((s) => {
|
||||
if (s.name === shortcut[0]) {
|
||||
return { name: s.name, shortcut: key };
|
||||
}
|
||||
return { name: s.name, shortcut: s.shortcut };
|
||||
});
|
||||
const fixCombination = key.split(" ");
|
||||
if (
|
||||
fixCombination[0].toLowerCase().includes("ctrl") ||
|
||||
|
|
@ -68,7 +60,16 @@ export default function EditShortcutButton({
|
|||
) {
|
||||
fixCombination[0] = "mod";
|
||||
}
|
||||
const shortcutName = shortcut[0].split(" ")[0].toLowerCase();
|
||||
const newCombination = defaultShortcuts.map((s) => {
|
||||
if (s.name === shortcut[0]) {
|
||||
return {
|
||||
name: s.name,
|
||||
shortcut: fixCombination.join("").toLowerCase(),
|
||||
};
|
||||
}
|
||||
return { name: s.name, shortcut: s.shortcut };
|
||||
});
|
||||
const shortcutName = toCamelCase(shortcut[0]);
|
||||
setUniqueShortcut(shortcutName, fixCombination.join("").toLowerCase());
|
||||
setShortcuts(newCombination);
|
||||
localStorage.setItem(
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { toCamelCase } from "@/utils/utils";
|
||||
import { ColDef } from "ag-grid-community";
|
||||
import { useEffect, useState } from "react";
|
||||
import ForwardedIconComponent from "../../../../components/common/genericIconComponent";
|
||||
|
|
@ -40,7 +41,6 @@ export default function ShortcutsPage() {
|
|||
setNodesRowData(shortcuts);
|
||||
}, [shortcuts]);
|
||||
|
||||
const combinationToEdit = shortcuts.filter((s) => s.name === selectedRows[0]);
|
||||
const [open, setOpen] = useState(false);
|
||||
const updateUniqueShortcut = useShortcutsStore(
|
||||
(state) => state.updateUniqueShortcut,
|
||||
|
|
@ -49,7 +49,7 @@ export default function ShortcutsPage() {
|
|||
function handleRestore() {
|
||||
setShortcuts(defaultShortcuts);
|
||||
defaultShortcuts.forEach(({ name, shortcut }) => {
|
||||
const fixedName = name.split(" ")[0].toLowerCase();
|
||||
const fixedName = toCamelCase(name);
|
||||
updateUniqueShortcut(fixedName, shortcut);
|
||||
});
|
||||
localStorage.removeItem("langflow-shortcuts");
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { toCamelCase } from "@/utils/utils";
|
||||
import { create } from "zustand";
|
||||
import { defaultShortcuts } from "../constants/constants";
|
||||
import { shortcutsStoreType } from "../types/store";
|
||||
|
|
@ -7,21 +8,21 @@ export const useShortcutsStore = create<shortcutsStoreType>((set, get) => ({
|
|||
setShortcuts: (newShortcuts) => {
|
||||
set({ shortcuts: newShortcuts });
|
||||
},
|
||||
output: "o",
|
||||
outputInspection: "o",
|
||||
play: "p",
|
||||
flow: "mod+b",
|
||||
flow: "mod+shift+b",
|
||||
undo: "mod+z",
|
||||
redo: "mod+y",
|
||||
open: "mod+k",
|
||||
advanced: "mod+shift+a",
|
||||
openPlayground: "mod+k",
|
||||
advancedSettings: "mod+shift+a",
|
||||
minimize: "mod+shift+q",
|
||||
code: "space",
|
||||
copy: "mod+c",
|
||||
duplicate: "mod+d",
|
||||
component: "mod+shift+s",
|
||||
componentShare: "mod+shift+s",
|
||||
docs: "mod+shift+d",
|
||||
changes: "mod+s",
|
||||
save: "mod+alt+s",
|
||||
changesSave: "mod+s",
|
||||
saveComponent: "mod+alt+s",
|
||||
delete: "backspace",
|
||||
group: "mod+g",
|
||||
cut: "mod+x",
|
||||
|
|
@ -30,8 +31,9 @@ export const useShortcutsStore = create<shortcutsStoreType>((set, get) => ({
|
|||
update: "mod+u",
|
||||
download: "mod+j",
|
||||
freeze: "mod+f",
|
||||
FreezePath: "mod+shift+f",
|
||||
freezePath: "mod+shift+f",
|
||||
toolMode: "mod+shift+m",
|
||||
toggleSidebar: "mod+b",
|
||||
updateUniqueShortcut: (name, combination) => {
|
||||
set({
|
||||
[name]: combination,
|
||||
|
|
@ -42,7 +44,7 @@ export const useShortcutsStore = create<shortcutsStoreType>((set, get) => ({
|
|||
const savedShortcuts = localStorage.getItem("langflow-shortcuts");
|
||||
const savedArr = JSON.parse(savedShortcuts!);
|
||||
savedArr.forEach(({ name, shortcut }) => {
|
||||
let shortcutName = name.split(" ")[0].toLowerCase();
|
||||
let shortcutName = toCamelCase(name);
|
||||
set({
|
||||
[shortcutName]: shortcut,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -21,30 +21,31 @@ export type StoreComponentResponse = {
|
|||
|
||||
export type shortcutsStoreType = {
|
||||
updateUniqueShortcut: (name: string, combination: string) => void;
|
||||
output: string;
|
||||
outputInspection: string;
|
||||
play: string;
|
||||
flow: string;
|
||||
group: string;
|
||||
cut: string;
|
||||
paste: string;
|
||||
api: string;
|
||||
open: string;
|
||||
openPlayground: string;
|
||||
undo: string;
|
||||
redo: string;
|
||||
advanced: string;
|
||||
advancedSettings: string;
|
||||
minimize: string;
|
||||
code: string;
|
||||
copy: string;
|
||||
duplicate: string;
|
||||
component: string;
|
||||
componentShare: string;
|
||||
docs: string;
|
||||
changes: string;
|
||||
save: string;
|
||||
changesSave: string;
|
||||
saveComponent: string;
|
||||
delete: string;
|
||||
update: string;
|
||||
download: string;
|
||||
freeze: string;
|
||||
FreezePath: string;
|
||||
toggleSidebar: string;
|
||||
freezePath: string;
|
||||
toolMode: string;
|
||||
shortcuts: Array<{
|
||||
name: string;
|
||||
|
|
|
|||
|
|
@ -200,9 +200,6 @@ export async function buildFlowVertices({
|
|||
ids.forEach((id) => verticesStartTimeMs.set(id, Date.now()));
|
||||
};
|
||||
|
||||
console.log("type", type);
|
||||
console.log("data", data);
|
||||
|
||||
switch (type) {
|
||||
case "vertices_sorted": {
|
||||
const verticesToRun = data.to_run;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,13 @@ export function cn(...inputs: ClassValue[]): string {
|
|||
return twMerge(clsx(inputs));
|
||||
}
|
||||
|
||||
export function toCamelCase(str: string): string {
|
||||
return str
|
||||
.split(" ")
|
||||
.map((s, index) => (index !== 0 ? toNormalCase(s) : s.toLowerCase()))
|
||||
.join("");
|
||||
}
|
||||
|
||||
export function toNormalCase(str: string): string {
|
||||
let result = str
|
||||
.split("_")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue