Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion frontend/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import pluginReactHooks from "eslint-plugin-react-hooks"
import pluginPrettier from "eslint-plugin-prettier"
import configPrettier from "eslint-config-prettier"
import unusedImports from "eslint-plugin-unused-imports"

import i18next from "eslint-plugin-i18next-no-undefined-translation-keys"
export default [
{
ignores: ["**/*.min.js", "src/media/**/*"]
Expand All @@ -29,6 +29,7 @@ export default [
react: pluginReact,
"react-hooks": pluginReactHooks,
"unused-imports": unusedImports,
"i18next-no-undefined-translation-keys": i18next,
prettier: pluginPrettier
},
settings: {
Expand Down Expand Up @@ -66,6 +67,8 @@ export default [
// Unused cleanup
"no-unused-vars": "off",
"unused-imports/no-unused-imports": "error",
"i18next-no-undefined-translation-keys/translation-key-string-literal":
"error",
"unused-imports/no-unused-vars": [
"warn",
{
Expand Down
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"eslint": "^9.39.2",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-ft-flow": "^3.0.0",
"eslint-plugin-i18next-no-undefined-translation-keys": "^3.4.0",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export default function SystemPrompts({ entity }) {
<>
<div className="w-full flex gap-x-2 items-center mb-3 -mt-8">
<h3 className="text-xl font-semibold text-theme-text-primary px-6 py-3">
{t(`community_hub.publish.system_prompt.modal_title`)}
{t("community_hub.publish.system_prompt.modal_title")}
</h3>
</div>
<form ref={formRef} className="flex" onSubmit={handleSubmit}>
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/components/KeyboardShortcutsHelp/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react";
import { X } from "@phosphor-icons/react";
import { useTranslation } from "react-i18next";
import {
SHORTCUTS,
getShortcuts,
isMac,
KEYBOARD_SHORTCUTS_HELP_EVENT,
} from "@/utils/keyboardShortcuts";
Expand All @@ -11,6 +11,8 @@ export default function KeyboardShortcutsHelp() {
const [isOpen, setIsOpen] = useState(false);
const { t } = useTranslation();

const shortcuts = getShortcuts(t);

useEffect(() => {
window.addEventListener(KEYBOARD_SHORTCUTS_HELP_EVENT, () =>
setIsOpen((prev) => !prev)
Expand Down Expand Up @@ -40,14 +42,12 @@ export default function KeyboardShortcutsHelp() {
</div>

<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{Object.entries(SHORTCUTS).map(([key, shortcut]) => (
{Object.entries(shortcuts).map(([key, shortcut]) => (
<div
key={key}
className="flex items-center justify-between p-3 bg-theme-bg-hover rounded-lg"
>
<span className="text-white">
{t(`keyboard-shortcuts.shortcuts.${shortcut.translationKey}`)}
</span>
<span className="text-white">{shortcut.translation}</span>
<kbd className="px-2 py-1 bg-theme-bg-secondary text-white rounded border border-gray-600">
{isMac ? key : key.replace("⌘", "Ctrl")}
</kbd>
Expand Down
34 changes: 21 additions & 13 deletions frontend/src/utils/keyboardShortcuts.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,52 @@ import { TOGGLE_LLM_SELECTOR_EVENT } from "@/components/WorkspaceChat/ChatContai

export const KEYBOARD_SHORTCUTS_HELP_EVENT = "keyboard-shortcuts-help";
export const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0;
export const SHORTCUTS = {

/**
* Returns an object mapping keyboard shortcuts to their translations and actions
* @param {import("i18next").TFunction} t - The translation function from react-i18next
*
*
*/
export const getShortcuts = (t) => ({
"⌘ + ,": {
translationKey: "settings",
translation: t?.("keyboard-shortcuts.shortcuts.settings"),
action: () => {
window.location.href = paths.settings.interface();
},
},
"⌘ + H": {
translationKey: "home",
translation: t?.("keyboard-shortcuts.shortcuts.home"),
action: () => {
window.location.href = paths.home();
},
},
"⌘ + I": {
translationKey: "workspaces",
translation: t?.("keyboard-shortcuts.shortcuts.workspaces"),
action: () => {
window.location.href = paths.settings.workspaces();
},
},
"⌘ + K": {
translationKey: "apiKeys",
translation: t?.("keyboard-shortcuts.shortcuts.apiKeys"),
action: () => {
window.location.href = paths.settings.apiKeys();
},
},
"⌘ + L": {
translationKey: "llmPreferences",
translation: t?.("keyboard-shortcuts.shortcuts.llmPreferences"),
action: () => {
window.location.href = paths.settings.llmPreference();
},
},
"⌘ + Shift + C": {
translationKey: "chatSettings",
translation: t?.("keyboard-shortcuts.shortcuts.chatSettings"),
action: () => {
window.location.href = paths.settings.chat();
},
},
"⌘ + Shift + ?": {
translationKey: "help",
translation: t?.("keyboard-shortcuts.shortcuts.help"),
action: () => {
window.dispatchEvent(
new CustomEvent(KEYBOARD_SHORTCUTS_HELP_EVENT, {
Expand All @@ -53,7 +60,7 @@ export const SHORTCUTS = {
},
},
F1: {
translationKey: "help",
translation: t?.("keyboard-shortcuts.shortcuts.help"),
action: () => {
window.dispatchEvent(
new CustomEvent(KEYBOARD_SHORTCUTS_HELP_EVENT, {
Expand All @@ -63,21 +70,22 @@ export const SHORTCUTS = {
},
},
"⌘ + Shift + L": {
translationKey: "showLLMSelector",
translation: t?.("keyboard-shortcuts.shortcuts.showLLMSelector"),
action: () => {
window.dispatchEvent(new Event(TOGGLE_LLM_SELECTOR_EVENT));
},
},
};
});

const LISTENERS = {};
const modifier = isMac ? "meta" : "ctrl";
for (const key in SHORTCUTS) {
const shortcuts = getShortcuts();
for (const key in shortcuts) {
const listenerKey = key
.replace("⌘", modifier)
.replaceAll(" ", "")
.toLowerCase();
LISTENERS[listenerKey] = SHORTCUTS[key].action;
LISTENERS[listenerKey] = shortcuts[key].action;
}

// Convert keyboard event to shortcut key
Expand Down
12 changes: 12 additions & 0 deletions frontend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2298,6 +2298,13 @@ eslint-plugin-ft-flow@^3.0.0:
lodash "^4.17.21"
string-natural-compare "^3.0.1"

eslint-plugin-i18next-no-undefined-translation-keys@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-i18next-no-undefined-translation-keys/-/eslint-plugin-i18next-no-undefined-translation-keys-3.4.0.tgz#ae385024aec44de606ecfa1d92cad0eae36080ab"
integrity sha512-XR1tiDAtzx4lAPz4owCXP9GoecAreyJNXxyH6KgsUIthKYwvNYPa9zoJp/5xDdheuRZpENc4ESXVvbM6oDsGmQ==
dependencies:
requireindex "^1.2.0"

eslint-plugin-prettier@^5.0.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz#d1c8f972d8f60e414c25465c163d16f209411f95"
Expand Down Expand Up @@ -4382,6 +4389,11 @@ require-directory@^2.1.1:
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==

requireindex@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.2.0.tgz#3463cdb22ee151902635aa6c9535d4de9c2ef1ef"
integrity sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==

resolve-from@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
Expand Down