Feat: User can edit his keys combination for each shortcut
This commit is contained in:
parent
0cad2e1978
commit
604e579bed
5 changed files with 213 additions and 13 deletions
|
|
@ -754,3 +754,44 @@ export const NATIVE_CATEGORIES = [
|
||||||
];
|
];
|
||||||
|
|
||||||
export const SAVE_DEBOUNCE_TIME = 300;
|
export const SAVE_DEBOUNCE_TIME = 300;
|
||||||
|
|
||||||
|
export const defaultShortcuts = [
|
||||||
|
{
|
||||||
|
name: "Advanced Settings",
|
||||||
|
shortcut: "Ctrl + Shift + a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Minimize",
|
||||||
|
shortcut: "Ctrl + Shift + q"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Code",
|
||||||
|
shortcut: "Ctrl + Shift + c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Copy",
|
||||||
|
shortcut: "Ctrl + c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Duplicate",
|
||||||
|
shortcut: "Ctrl + d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Share",
|
||||||
|
shortcut: "Ctrl + Shift + s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Docs",
|
||||||
|
shortcut: "Ctrl + Shift + d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Save",
|
||||||
|
shortcut: "Ctrl + s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Delete",
|
||||||
|
shortcut: "Backspace"
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const unavailableShortcutss = ["Ctrl + Shift + a", "Ctrl + Shift + q", "Ctrl + Shift + c", "Ctrl + c", "Ctrl + d", "Ctrl + Shift + s", "Ctrl + Shift + d", "Ctrl + s", "Backspace"];
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
|
||||||
|
|
||||||
|
//TODO IMPLEMENT FORM LOGIC
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import useAlertStore from "../../../../../stores/alertStore";
|
||||||
|
import { useTypesStore } from "../../../../../stores/typesStore";
|
||||||
|
import { useGlobalVariablesStore } from "../../../../../stores/globalVariables";
|
||||||
|
import { registerGlobalVariable } from "../../../../../controllers/API";
|
||||||
|
import { ResponseErrorDetailAPI } from "../../../../../types/api";
|
||||||
|
import BaseModal from "../../../../../modals/baseModal";
|
||||||
|
import { Label } from "@radix-ui/react-select";
|
||||||
|
import { Input } from "../../../../../components/ui/input";
|
||||||
|
import InputComponent from "../../../../../components/inputComponent";
|
||||||
|
import { Textarea } from "../../../../../components/ui/textarea";
|
||||||
|
import { Button } from "../../../../../components/ui/button";
|
||||||
|
import ForwardedIconComponent from "../../../../../components/genericIconComponent";
|
||||||
|
import { defaultShortcuts } from "../../../../../constants/constants";
|
||||||
|
import { useShortcutsStore } from "../../../../../stores/shortcuts";
|
||||||
|
|
||||||
|
export default function EditShortcutButton({ children, shortcut, defaultShortcuts, defaultCombination, open, setOpen, }: {children: JSX.Element; shortcut: string[]; defaultShortcuts: Array<{name: string; shortcut: string;}>; defaultCombination: string; open: boolean; setOpen: (bool: boolean) => void;}): JSX.Element {
|
||||||
|
const setSuccessData = useAlertStore(state => state.setSuccessData)
|
||||||
|
const setShortcuts = useShortcutsStore(state => state.setShortcuts);
|
||||||
|
const unavaliableShortcuts = useShortcutsStore(state => state.unavailableShortcuts);
|
||||||
|
const isMac = navigator.userAgent.toUpperCase().includes("MAC");
|
||||||
|
const [fields, setFields] = useState<string[]>([]);
|
||||||
|
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||||
|
const componentFields = useTypesStore((state) => state.ComponentFields);
|
||||||
|
const unavaliableFields =new Set(Object.keys(useGlobalVariablesStore(
|
||||||
|
(state) => state.unavaliableFields
|
||||||
|
)));
|
||||||
|
|
||||||
|
const [key, setKey] = useState<string>(isMac ? "Meta" : 'Ctrl');
|
||||||
|
|
||||||
|
const availableFields = Array.from(componentFields).filter(
|
||||||
|
(field) => !unavaliableFields.has(field)
|
||||||
|
);
|
||||||
|
const addGlobalVariable = useGlobalVariablesStore(
|
||||||
|
(state) => state.addGlobalVariable
|
||||||
|
);
|
||||||
|
|
||||||
|
function canEditCombination(newCombination: string): boolean {
|
||||||
|
return !unavaliableShortcuts.includes(newCombination);
|
||||||
|
}
|
||||||
|
|
||||||
|
function editCombination(): void {
|
||||||
|
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 unavailable = unavaliableShortcuts.map((s) => {
|
||||||
|
if (s === defaultCombination) return s = key;
|
||||||
|
return s;
|
||||||
|
})
|
||||||
|
setShortcuts(newCombination, unavailable)
|
||||||
|
setOpen(false)
|
||||||
|
setSuccessData({title: `${shortcut[0]} shortcut successfully changed`})
|
||||||
|
setKey(isMac ? "Meta" : 'Ctrl')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setErrorData({title: "Error saving key combination", list: ["This combination already exists!"]})
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) setKey(isMac ? "Meta" : 'Ctrl')
|
||||||
|
}, [open, setOpen])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
function onKeyDown(e: KeyboardEvent) {
|
||||||
|
e.preventDefault()
|
||||||
|
console.log(e.key)
|
||||||
|
if (key.includes(e.key)) return;
|
||||||
|
setKey(oldKey => `${oldKey} + ${e.key}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("keydown", onKeyDown);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("keydown", onKeyDown)
|
||||||
|
}
|
||||||
|
}, [key, setKey])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BaseModal open={open} setOpen={setOpen} size="x-small">
|
||||||
|
<BaseModal.Header
|
||||||
|
description={
|
||||||
|
"Set your new key combination"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<span className="pr-2"> Key Combination </span>
|
||||||
|
<ForwardedIconComponent
|
||||||
|
name="Keyboard"
|
||||||
|
className="h-6 w-6 pl-1 text-primary "
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</BaseModal.Header>
|
||||||
|
<BaseModal.Trigger>{children}</BaseModal.Trigger>
|
||||||
|
<BaseModal.Content>
|
||||||
|
<div className="flex h-full w-full gap-4 align-center justify-center">
|
||||||
|
<div>
|
||||||
|
{key}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</BaseModal.Content>
|
||||||
|
<BaseModal.Footer>
|
||||||
|
<Button onClick={editCombination}>Edit Combination</Button>
|
||||||
|
</BaseModal.Footer>
|
||||||
|
</BaseModal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { ColDef, ColGroupDef } from "ag-grid-community";
|
import { ColDef, ColGroupDef } from "ag-grid-community";
|
||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import ForwardedIconComponent from "../../../../components/genericIconComponent";
|
import ForwardedIconComponent from "../../../../components/genericIconComponent";
|
||||||
import TableComponent from "../../../../components/tableComponent";
|
import TableComponent from "../../../../components/tableComponent";
|
||||||
import {
|
import {
|
||||||
|
|
@ -9,6 +9,9 @@ import {
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "../../../../components/ui/card";
|
} from "../../../../components/ui/card";
|
||||||
|
import { Button } from "../../../../components/ui/button";
|
||||||
|
import EditShortcutButton from "./EditShortcutButton";
|
||||||
|
import { useShortcutsStore } from "../../../../stores/shortcuts";
|
||||||
|
|
||||||
export default function ShortcutsPage() {
|
export default function ShortcutsPage() {
|
||||||
const advancedShortcut = "Ctrl + Shift + A";
|
const advancedShortcut = "Ctrl + Shift + A";
|
||||||
|
|
@ -24,9 +27,20 @@ export default function ShortcutsPage() {
|
||||||
const undoShortcut = "Ctrl + Z";
|
const undoShortcut = "Ctrl + Z";
|
||||||
const redoShortcut = "Ctrl + Y";
|
const redoShortcut = "Ctrl + Y";
|
||||||
|
|
||||||
|
const [selectedRows, setSelectedRows] = useState<string[]>([]);
|
||||||
|
const shortcuts = useShortcutsStore(state => state.shortcuts)
|
||||||
|
|
||||||
// Column Definitions: Defines the columns to be displayed.
|
// Column Definitions: Defines the columns to be displayed.
|
||||||
const [colDefs, setColDefs] = useState<(ColDef<any> | ColGroupDef<any>)[]>([
|
const [colDefs, setColDefs] = useState<(ColDef<any> | ColGroupDef<any>)[]>([
|
||||||
{ headerName: "Functionality", field: "name", flex: 1, editable: false }, //This column will be twice as wide as the others
|
{
|
||||||
|
headerName: "Functionality",
|
||||||
|
field: "name",
|
||||||
|
flex: 1,
|
||||||
|
editable: false,
|
||||||
|
headerCheckboxSelection: true,
|
||||||
|
checkboxSelection: true,
|
||||||
|
showDisabledCheckboxes: true,
|
||||||
|
}, //This column will be twice as wide as the others
|
||||||
{
|
{
|
||||||
field: "shortcut",
|
field: "shortcut",
|
||||||
flex: 2,
|
flex: 2,
|
||||||
|
|
@ -87,6 +101,14 @@ export default function ShortcutsPage() {
|
||||||
shortcut: redoShortcut,
|
shortcut: redoShortcut,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setNodesRowData(shortcuts)
|
||||||
|
}, [shortcuts])
|
||||||
|
|
||||||
|
const combinationToEdit = shortcuts.filter((s) => s.name === selectedRows[0])
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full flex-col gap-6">
|
<div className="flex h-full w-full flex-col gap-6">
|
||||||
<div className="flex w-full items-center justify-between gap-4 space-y-0.5">
|
<div className="flex w-full items-center justify-between gap-4 space-y-0.5">
|
||||||
|
|
@ -113,7 +135,27 @@ export default function ShortcutsPage() {
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
|
<div className="w-full flex justify-end align-end mb-4">
|
||||||
|
<div className="">
|
||||||
|
<EditShortcutButton
|
||||||
|
defaultCombination={combinationToEdit[0]?.shortcut}
|
||||||
|
shortcut={selectedRows}
|
||||||
|
defaultShortcuts={shortcuts}
|
||||||
|
open={open}
|
||||||
|
setOpen={setOpen}
|
||||||
|
>
|
||||||
|
<Button data-testid="api-key-button-store" variant="primary">
|
||||||
|
<ForwardedIconComponent name="Plus" className="mr-2 w-4" />
|
||||||
|
New key combination
|
||||||
|
</Button>
|
||||||
|
</EditShortcutButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<TableComponent
|
<TableComponent
|
||||||
|
onSelectionChanged={(event: SelectionChangedEvent) => {
|
||||||
|
setSelectedRows(event.api.getSelectedRows().map((row) => row.name));
|
||||||
|
}}
|
||||||
|
suppressRowClickSelection={true}
|
||||||
domLayout="autoHeight"
|
domLayout="autoHeight"
|
||||||
pagination={false}
|
pagination={false}
|
||||||
columnDefs={colDefs}
|
columnDefs={colDefs}
|
||||||
|
|
@ -128,6 +170,10 @@ export default function ShortcutsPage() {
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<TableComponent
|
<TableComponent
|
||||||
|
onSelectionChanged={(event: SelectionChangedEvent) => {
|
||||||
|
setSelectedRows(event.api.getSelectedRows().map((row) => row.name));
|
||||||
|
}}
|
||||||
|
suppressRowClickSelection={true}
|
||||||
domLayout="autoHeight"
|
domLayout="autoHeight"
|
||||||
pagination={false}
|
pagination={false}
|
||||||
columnDefs={colDefs}
|
columnDefs={colDefs}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,11 @@
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { shortcutsStoreType } from "../types/store";
|
import { shortcutsStoreType } from "../types/store";
|
||||||
|
import { defaultShortcuts, unavailableShortcutss } from "../constants/constants";
|
||||||
|
|
||||||
export const useShortcutsStore = create<shortcutsStoreType>((set, get) => ({
|
export const useShortcutsStore = create<shortcutsStoreType>((set, get) => ({
|
||||||
openCodeModalWShortcut: false,
|
unavailableShortcuts: unavailableShortcutss,
|
||||||
handleModalWShortcut: (modal) => {
|
shortcuts: defaultShortcuts,
|
||||||
switch (modal) {
|
setShortcuts: (newShortcuts, unavailable) => {
|
||||||
case "code":
|
set({shortcuts: newShortcuts, unavailableShortcuts: unavailable} );
|
||||||
set({
|
|
||||||
openCodeModalWShortcut: !get().openCodeModalWShortcut,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,10 @@ export type StoreComponentResponse = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type shortcutsStoreType = {
|
export type shortcutsStoreType = {
|
||||||
openCodeModalWShortcut: boolean;
|
shortcuts: Array<{
|
||||||
handleModalWShortcut: (str: string) => void;
|
name: string;
|
||||||
|
shortcut: string;
|
||||||
|
}>
|
||||||
|
unavailableShortcuts: string[];
|
||||||
|
setShortcuts: (newShortcuts: Array<{name: string; shortcut: string;}>, unavailable: string[]) => void;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue