feat: Trigger cmd+k from sidebar (#3149)
* feat: Trigger cmd+k from sidebar * Add hint when opening command bar from sidebar
This commit is contained in:
@@ -19,14 +19,19 @@ import {
|
|||||||
githubIssuesUrl,
|
githubIssuesUrl,
|
||||||
} from "@shared/utils/urlHelpers";
|
} from "@shared/utils/urlHelpers";
|
||||||
import stores from "~/stores";
|
import stores from "~/stores";
|
||||||
|
import SearchQuery from "~/models/SearchQuery";
|
||||||
import KeyboardShortcuts from "~/scenes/KeyboardShortcuts";
|
import KeyboardShortcuts from "~/scenes/KeyboardShortcuts";
|
||||||
import { createAction } from "~/actions";
|
import { createAction } from "~/actions";
|
||||||
import { NavigationSection } from "~/actions/sections";
|
import {
|
||||||
|
NavigationSection,
|
||||||
|
NoSection,
|
||||||
|
RecentSearchesSection,
|
||||||
|
} from "~/actions/sections";
|
||||||
import history from "~/utils/history";
|
import history from "~/utils/history";
|
||||||
import {
|
import {
|
||||||
settingsPath,
|
settingsPath,
|
||||||
homePath,
|
homePath,
|
||||||
searchUrl,
|
searchPath,
|
||||||
draftsPath,
|
draftsPath,
|
||||||
templatesPath,
|
templatesPath,
|
||||||
archivePath,
|
archivePath,
|
||||||
@@ -42,14 +47,24 @@ export const navigateToHome = createAction({
|
|||||||
visible: ({ location }) => location.pathname !== homePath(),
|
visible: ({ location }) => location.pathname !== homePath(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const navigateToSearch = createAction({
|
export const navigateToRecentSearchQuery = (searchQuery: SearchQuery) =>
|
||||||
name: ({ t }) => t("Search"),
|
createAction({
|
||||||
section: NavigationSection,
|
section: RecentSearchesSection,
|
||||||
shortcut: ["/"],
|
name: searchQuery.query,
|
||||||
icon: <SearchIcon />,
|
icon: <SearchIcon />,
|
||||||
perform: () => history.push(searchUrl()),
|
perform: () => history.push(searchPath(searchQuery.query)),
|
||||||
visible: ({ location }) => location.pathname !== searchUrl(),
|
});
|
||||||
});
|
|
||||||
|
export const navigateToSearchQuery = (searchQuery: string) =>
|
||||||
|
createAction({
|
||||||
|
id: "search",
|
||||||
|
section: NoSection,
|
||||||
|
name: ({ t }) =>
|
||||||
|
t(`Search documents for "{{searchQuery}}"`, { searchQuery }),
|
||||||
|
icon: <SearchIcon />,
|
||||||
|
perform: () => history.push(searchPath(searchQuery)),
|
||||||
|
visible: ({ location }) => location.pathname !== searchPath(),
|
||||||
|
});
|
||||||
|
|
||||||
export const navigateToDrafts = createAction({
|
export const navigateToDrafts = createAction({
|
||||||
name: ({ t }) => t("Drafts"),
|
name: ({ t }) => t("Drafts"),
|
||||||
@@ -70,6 +85,7 @@ export const navigateToTemplates = createAction({
|
|||||||
export const navigateToArchive = createAction({
|
export const navigateToArchive = createAction({
|
||||||
name: ({ t }) => t("Archive"),
|
name: ({ t }) => t("Archive"),
|
||||||
section: NavigationSection,
|
section: NavigationSection,
|
||||||
|
shortcut: ["g", "a"],
|
||||||
icon: <ArchiveIcon />,
|
icon: <ArchiveIcon />,
|
||||||
perform: () => history.push(archivePath()),
|
perform: () => history.push(archivePath()),
|
||||||
visible: ({ location }) => location.pathname !== archivePath(),
|
visible: ({ location }) => location.pathname !== archivePath(),
|
||||||
@@ -145,7 +161,6 @@ export const logout = createAction({
|
|||||||
|
|
||||||
export const rootNavigationActions = [
|
export const rootNavigationActions = [
|
||||||
navigateToHome,
|
navigateToHome,
|
||||||
navigateToSearch,
|
|
||||||
navigateToDrafts,
|
navigateToDrafts,
|
||||||
navigateToTemplates,
|
navigateToTemplates,
|
||||||
navigateToArchive,
|
navigateToArchive,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { flattenDeep } from "lodash";
|
import { flattenDeep } from "lodash";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { $Diff } from "utility-types";
|
import { Optional } from "utility-types";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
import {
|
import {
|
||||||
Action,
|
Action,
|
||||||
@@ -10,17 +10,10 @@ import {
|
|||||||
MenuItemWithChildren,
|
MenuItemWithChildren,
|
||||||
} from "~/types";
|
} from "~/types";
|
||||||
|
|
||||||
export function createAction(
|
export function createAction(definition: Optional<Action, "id">): Action {
|
||||||
definition: $Diff<
|
|
||||||
Action,
|
|
||||||
{
|
|
||||||
id?: string;
|
|
||||||
}
|
|
||||||
>
|
|
||||||
): Action {
|
|
||||||
return {
|
return {
|
||||||
id: uuidv4(),
|
|
||||||
...definition,
|
...definition,
|
||||||
|
id: uuidv4(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,3 +11,8 @@ export const SettingsSection = ({ t }: ActionContext) => t("Settings");
|
|||||||
export const NavigationSection = ({ t }: ActionContext) => t("Navigation");
|
export const NavigationSection = ({ t }: ActionContext) => t("Navigation");
|
||||||
|
|
||||||
export const UserSection = ({ t }: ActionContext) => t("People");
|
export const UserSection = ({ t }: ActionContext) => t("People");
|
||||||
|
|
||||||
|
export const RecentSearchesSection = ({ t }: ActionContext) =>
|
||||||
|
t("Recent searches");
|
||||||
|
|
||||||
|
export const NoSection = "";
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import Sidebar from "~/components/Sidebar";
|
|||||||
import SettingsSidebar from "~/components/Sidebar/Settings";
|
import SettingsSidebar from "~/components/Sidebar/Settings";
|
||||||
import history from "~/utils/history";
|
import history from "~/utils/history";
|
||||||
import {
|
import {
|
||||||
searchUrl,
|
searchPath,
|
||||||
matchDocumentSlug as slug,
|
matchDocumentSlug as slug,
|
||||||
newDocumentPath,
|
newDocumentPath,
|
||||||
settingsPath,
|
settingsPath,
|
||||||
@@ -49,7 +49,7 @@ class AuthenticatedLayout extends React.Component<Props> {
|
|||||||
if (!ev.metaKey && !ev.ctrlKey) {
|
if (!ev.metaKey && !ev.ctrlKey) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
history.push(searchUrl());
|
history.push(searchPath());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
import { useKBar, KBarPositioner, KBarAnimator, KBarSearch } from "kbar";
|
import { useKBar, KBarPositioner, KBarAnimator, KBarSearch } from "kbar";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
|
import { QuestionMarkIcon } from "outline-icons";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Portal } from "react-portal";
|
import { Portal } from "react-portal";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import breakpoint from "styled-components-breakpoint";
|
import breakpoint from "styled-components-breakpoint";
|
||||||
import CommandBarResults from "~/components/CommandBarResults";
|
import CommandBarResults from "~/components/CommandBarResults";
|
||||||
|
import SearchActions from "~/components/SearchActions";
|
||||||
import rootActions from "~/actions/root";
|
import rootActions from "~/actions/root";
|
||||||
import useCommandBarActions from "~/hooks/useCommandBarActions";
|
import useCommandBarActions from "~/hooks/useCommandBarActions";
|
||||||
|
import useStores from "~/hooks/useStores";
|
||||||
import { CommandBarAction } from "~/types";
|
import { CommandBarAction } from "~/types";
|
||||||
|
import { metaDisplay } from "~/utils/keyboard";
|
||||||
export const CommandBarOptions = {
|
import Text from "./Text";
|
||||||
animations: {
|
|
||||||
enterMs: 250,
|
|
||||||
exitMs: 200,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
function CommandBar() {
|
function CommandBar() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { ui } = useStores();
|
||||||
|
|
||||||
useCommandBarActions(rootActions);
|
useCommandBarActions(rootActions);
|
||||||
|
|
||||||
const { rootAction } = useKBar((state) => ({
|
const { rootAction } = useKBar((state) => ({
|
||||||
@@ -30,6 +30,8 @@ function CommandBar() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
<SearchActions />
|
||||||
<KBarPortal>
|
<KBarPortal>
|
||||||
<Positioner>
|
<Positioner>
|
||||||
<Animator>
|
<Animator>
|
||||||
@@ -41,9 +43,21 @@ function CommandBar() {
|
|||||||
}…`}
|
}…`}
|
||||||
/>
|
/>
|
||||||
<CommandBarResults />
|
<CommandBarResults />
|
||||||
|
{ui.showModKHint && (
|
||||||
|
<Hint size="small" type="tertiary">
|
||||||
|
<QuestionMarkIcon size={18} color="currentColor" />
|
||||||
|
{t(
|
||||||
|
"Open search from anywhere with the {{ shortcut }} shortcut",
|
||||||
|
{
|
||||||
|
shortcut: `${metaDisplay} + k`,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</Hint>
|
||||||
|
)}
|
||||||
</Animator>
|
</Animator>
|
||||||
</Positioner>
|
</Positioner>
|
||||||
</KBarPortal>
|
</KBarPortal>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,6 +73,20 @@ function KBarPortal({ children }: { children: React.ReactNode }) {
|
|||||||
return <Portal>{children}</Portal>;
|
return <Portal>{children}</Portal>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Hint = styled(Text)`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
background: ${(props) => props.theme.secondaryBackground};
|
||||||
|
border-top: 1px solid ${(props) => props.theme.background};
|
||||||
|
margin: 1px 0 0;
|
||||||
|
padding: 6px 16px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
`;
|
||||||
|
|
||||||
const Positioner = styled(KBarPositioner)`
|
const Positioner = styled(KBarPositioner)`
|
||||||
z-index: ${(props) => props.theme.depths.commandBar};
|
z-index: ${(props) => props.theme.depths.commandBar};
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
import { useMatches, KBarResults } from "kbar";
|
import { useMatches, KBarResults } from "kbar";
|
||||||
|
import { orderBy } from "lodash";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import CommandBarItem from "~/components/CommandBarItem";
|
import CommandBarItem from "~/components/CommandBarItem";
|
||||||
|
import { NoSection } from "~/actions/sections";
|
||||||
|
|
||||||
export default function CommandBarResults() {
|
export default function CommandBarResults() {
|
||||||
const { results, rootActionId } = useMatches();
|
const { results, rootActionId } = useMatches();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KBarResults
|
<KBarResults
|
||||||
items={results}
|
items={orderBy(results, (item) =>
|
||||||
|
typeof item !== "string" && item.section === NoSection ? -1 : 1
|
||||||
|
)}
|
||||||
maxHeight={400}
|
maxHeight={400}
|
||||||
onRender={({ item, active }) =>
|
onRender={({ item, active }) =>
|
||||||
typeof item === "string" ? (
|
typeof item === "string" ? (
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import styled, { useTheme } from "styled-components";
|
|||||||
import useBoolean from "~/hooks/useBoolean";
|
import useBoolean from "~/hooks/useBoolean";
|
||||||
import useKeyDown from "~/hooks/useKeyDown";
|
import useKeyDown from "~/hooks/useKeyDown";
|
||||||
import { isModKey } from "~/utils/keyboard";
|
import { isModKey } from "~/utils/keyboard";
|
||||||
import { searchUrl } from "~/utils/routeHelpers";
|
import { searchPath } from "~/utils/routeHelpers";
|
||||||
import Input from "./Input";
|
import Input from "./Input";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -51,7 +51,7 @@ function InputSearchPage({
|
|||||||
if (ev.key === "Enter") {
|
if (ev.key === "Enter") {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
history.push(
|
history.push(
|
||||||
searchUrl(ev.currentTarget.value, {
|
searchPath(ev.currentTarget.value, {
|
||||||
collectionId,
|
collectionId,
|
||||||
ref: source,
|
ref: source,
|
||||||
})
|
})
|
||||||
|
|||||||
26
app/components/SearchActions.ts
Normal file
26
app/components/SearchActions.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { useKBar } from "kbar";
|
||||||
|
import * as React from "react";
|
||||||
|
import {
|
||||||
|
navigateToRecentSearchQuery,
|
||||||
|
navigateToSearchQuery,
|
||||||
|
} from "~/actions/definitions/navigation";
|
||||||
|
import useCommandBarActions from "~/hooks/useCommandBarActions";
|
||||||
|
import useStores from "~/hooks/useStores";
|
||||||
|
|
||||||
|
export default function SearchActions() {
|
||||||
|
const { searches } = useStores();
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
searches.fetchPage({});
|
||||||
|
}, [searches]);
|
||||||
|
|
||||||
|
const { searchQuery } = useKBar((state) => ({
|
||||||
|
searchQuery: state.searchQuery,
|
||||||
|
}));
|
||||||
|
|
||||||
|
useCommandBarActions(searchQuery ? [navigateToSearchQuery(searchQuery)] : []);
|
||||||
|
|
||||||
|
useCommandBarActions(searches.recent.map(navigateToRecentSearchQuery));
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { useKBar } from "kbar";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import {
|
import {
|
||||||
EditIcon,
|
EditIcon,
|
||||||
@@ -10,6 +11,7 @@ import * as React from "react";
|
|||||||
import { DndProvider } from "react-dnd";
|
import { DndProvider } from "react-dnd";
|
||||||
import { HTML5Backend } from "react-dnd-html5-backend";
|
import { HTML5Backend } from "react-dnd-html5-backend";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useHistory, useLocation } from "react-router-dom";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import Bubble from "~/components/Bubble";
|
import Bubble from "~/components/Bubble";
|
||||||
import Flex from "~/components/Flex";
|
import Flex from "~/components/Flex";
|
||||||
@@ -21,10 +23,10 @@ import useStores from "~/hooks/useStores";
|
|||||||
import AccountMenu from "~/menus/AccountMenu";
|
import AccountMenu from "~/menus/AccountMenu";
|
||||||
import {
|
import {
|
||||||
homePath,
|
homePath,
|
||||||
searchUrl,
|
|
||||||
draftsPath,
|
draftsPath,
|
||||||
templatesPath,
|
templatesPath,
|
||||||
settingsPath,
|
settingsPath,
|
||||||
|
searchPath,
|
||||||
} from "~/utils/routeHelpers";
|
} from "~/utils/routeHelpers";
|
||||||
import Sidebar from "./Sidebar";
|
import Sidebar from "./Sidebar";
|
||||||
import ArchiveLink from "./components/ArchiveLink";
|
import ArchiveLink from "./components/ArchiveLink";
|
||||||
@@ -38,9 +40,12 @@ import TrashLink from "./components/TrashLink";
|
|||||||
|
|
||||||
function MainSidebar() {
|
function MainSidebar() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { policies, documents } = useStores();
|
const { ui, policies, documents } = useStores();
|
||||||
const team = useCurrentTeam();
|
const team = useCurrentTeam();
|
||||||
const user = useCurrentUser();
|
const user = useCurrentUser();
|
||||||
|
const { query } = useKBar();
|
||||||
|
const location = useLocation();
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
documents.fetchDrafts();
|
documents.fetchDrafts();
|
||||||
@@ -57,6 +62,16 @@ function MainSidebar() {
|
|||||||
);
|
);
|
||||||
const can = policies.abilities(team.id);
|
const can = policies.abilities(team.id);
|
||||||
|
|
||||||
|
const handleSearch = React.useCallback(() => {
|
||||||
|
const isSearching = location.pathname.startsWith(searchPath());
|
||||||
|
if (isSearching) {
|
||||||
|
history.push(searchPath());
|
||||||
|
} else {
|
||||||
|
ui.enableModKHint();
|
||||||
|
query.toggle();
|
||||||
|
}
|
||||||
|
}, [ui, location, history, query]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sidebar ref={handleSidebarRef}>
|
<Sidebar ref={handleSidebarRef}>
|
||||||
{dndArea && (
|
{dndArea && (
|
||||||
@@ -81,12 +96,7 @@ function MainSidebar() {
|
|||||||
label={t("Home")}
|
label={t("Home")}
|
||||||
/>
|
/>
|
||||||
<SidebarLink
|
<SidebarLink
|
||||||
to={{
|
onClick={handleSearch}
|
||||||
pathname: searchUrl(),
|
|
||||||
state: {
|
|
||||||
fromMenu: true,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
icon={<SearchIcon color="currentColor" />}
|
icon={<SearchIcon color="currentColor" />}
|
||||||
label={t("Search")}
|
label={t("Search")}
|
||||||
exact={false}
|
exact={false}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { Router } from "react-router-dom";
|
|||||||
import { initI18n } from "@shared/i18n";
|
import { initI18n } from "@shared/i18n";
|
||||||
import stores from "~/stores";
|
import stores from "~/stores";
|
||||||
import Analytics from "~/components/Analytics";
|
import Analytics from "~/components/Analytics";
|
||||||
import { CommandBarOptions } from "~/components/CommandBar";
|
|
||||||
import Dialogs from "~/components/Dialogs";
|
import Dialogs from "~/components/Dialogs";
|
||||||
import ErrorBoundary from "~/components/ErrorBoundary";
|
import ErrorBoundary from "~/components/ErrorBoundary";
|
||||||
import PageTheme from "~/components/PageTheme";
|
import PageTheme from "~/components/PageTheme";
|
||||||
@@ -53,6 +52,17 @@ if ("serviceWorker" in window.navigator) {
|
|||||||
// Make sure to return the specific export containing the feature bundle.
|
// Make sure to return the specific export containing the feature bundle.
|
||||||
const loadFeatures = () => import("./utils/motion").then((res) => res.default);
|
const loadFeatures = () => import("./utils/motion").then((res) => res.default);
|
||||||
|
|
||||||
|
const commandBarOptions = {
|
||||||
|
animations: {
|
||||||
|
enterMs: 250,
|
||||||
|
exitMs: 200,
|
||||||
|
},
|
||||||
|
callbacks: {
|
||||||
|
onClose: () => stores.ui.disableModKHint(),
|
||||||
|
onQueryChange: () => stores.ui.disableModKHint(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
if (element) {
|
if (element) {
|
||||||
const App = () => (
|
const App = () => (
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
@@ -60,7 +70,7 @@ if (element) {
|
|||||||
<Analytics>
|
<Analytics>
|
||||||
<Theme>
|
<Theme>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<KBarProvider actions={[]} options={CommandBarOptions}>
|
<KBarProvider actions={[]} options={commandBarOptions}>
|
||||||
<LazyMotion features={loadFeatures}>
|
<LazyMotion features={loadFeatures}>
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import RegisterKeyDown from "~/components/RegisterKeyDown";
|
|||||||
import Scene from "~/components/Scene";
|
import Scene from "~/components/Scene";
|
||||||
import Text from "~/components/Text";
|
import Text from "~/components/Text";
|
||||||
import withStores from "~/components/withStores";
|
import withStores from "~/components/withStores";
|
||||||
import { searchUrl } from "~/utils/routeHelpers";
|
import { searchPath } from "~/utils/routeHelpers";
|
||||||
import { decodeURIComponentSafe } from "~/utils/urls";
|
import { decodeURIComponentSafe } from "~/utils/urls";
|
||||||
import CollectionFilter from "./components/CollectionFilter";
|
import CollectionFilter from "./components/CollectionFilter";
|
||||||
import DateFilter from "./components/DateFilter";
|
import DateFilter from "./components/DateFilter";
|
||||||
@@ -247,7 +247,7 @@ class Search extends React.Component<Props> {
|
|||||||
|
|
||||||
updateLocation = (query: string) => {
|
updateLocation = (query: string) => {
|
||||||
this.props.history.replace({
|
this.props.history.replace({
|
||||||
pathname: searchUrl(query),
|
pathname: searchPath(query),
|
||||||
search: this.props.location.search,
|
search: this.props.location.search,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import NudeButton from "~/components/NudeButton";
|
|||||||
import Tooltip from "~/components/Tooltip";
|
import Tooltip from "~/components/Tooltip";
|
||||||
import useStores from "~/hooks/useStores";
|
import useStores from "~/hooks/useStores";
|
||||||
import { hover } from "~/styles";
|
import { hover } from "~/styles";
|
||||||
import { searchUrl } from "~/utils/routeHelpers";
|
import { searchPath } from "~/utils/routeHelpers";
|
||||||
|
|
||||||
function RecentSearches() {
|
function RecentSearches() {
|
||||||
const { searches } = useStores();
|
const { searches } = useStores();
|
||||||
@@ -26,7 +26,7 @@ function RecentSearches() {
|
|||||||
<List>
|
<List>
|
||||||
{searches.recent.map((searchQuery) => (
|
{searches.recent.map((searchQuery) => (
|
||||||
<ListItem key={searchQuery.id}>
|
<ListItem key={searchQuery.id}>
|
||||||
<RecentSearch to={searchUrl(searchQuery.query)}>
|
<RecentSearch to={searchPath(searchQuery.query)}>
|
||||||
{searchQuery.query}
|
{searchQuery.query}
|
||||||
<Tooltip tooltip={t("Remove search")} delay={150}>
|
<Tooltip tooltip={t("Remove search")} delay={150}>
|
||||||
<RemoveButton
|
<RemoveButton
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ class UiStore {
|
|||||||
@observable
|
@observable
|
||||||
observingUserId: string | undefined;
|
observingUserId: string | undefined;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
showModKHint = false;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
progressBarVisible = false;
|
progressBarVisible = false;
|
||||||
|
|
||||||
@@ -211,6 +214,16 @@ class UiStore {
|
|||||||
this.mobileSidebarVisible = !this.mobileSidebarVisible;
|
this.mobileSidebarVisible = !this.mobileSidebarVisible;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@action
|
||||||
|
enableModKHint = () => {
|
||||||
|
this.showModKHint = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
@action
|
||||||
|
disableModKHint = () => {
|
||||||
|
this.showModKHint = false;
|
||||||
|
};
|
||||||
|
|
||||||
@action
|
@action
|
||||||
hideMobileSidebar = () => {
|
hideMobileSidebar = () => {
|
||||||
this.mobileSidebarVisible = false;
|
this.mobileSidebarVisible = false;
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ export function newDocumentPath(
|
|||||||
return `/collection/${collectionId}/new?${queryString.stringify(params)}`;
|
return `/collection/${collectionId}/new?${queryString.stringify(params)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function searchUrl(
|
export function searchPath(
|
||||||
query?: string,
|
query?: string,
|
||||||
params: {
|
params: {
|
||||||
collectionId?: string;
|
collectionId?: string;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
"Create template": "Create template",
|
"Create template": "Create template",
|
||||||
"Home": "Home",
|
"Home": "Home",
|
||||||
"Search": "Search",
|
"Search": "Search",
|
||||||
|
"Search documents for \"{{searchQuery}}\"": "Search documents for \"{{searchQuery}}\"",
|
||||||
"Drafts": "Drafts",
|
"Drafts": "Drafts",
|
||||||
"Templates": "Templates",
|
"Templates": "Templates",
|
||||||
"Archive": "Archive",
|
"Archive": "Archive",
|
||||||
@@ -49,6 +50,7 @@
|
|||||||
"Document": "Document",
|
"Document": "Document",
|
||||||
"Navigation": "Navigation",
|
"Navigation": "Navigation",
|
||||||
"People": "People",
|
"People": "People",
|
||||||
|
"Recent searches": "Recent searches",
|
||||||
"currently editing": "currently editing",
|
"currently editing": "currently editing",
|
||||||
"currently viewing": "currently viewing",
|
"currently viewing": "currently viewing",
|
||||||
"previously edited": "previously edited",
|
"previously edited": "previously edited",
|
||||||
@@ -59,6 +61,7 @@
|
|||||||
"Collapse": "Collapse",
|
"Collapse": "Collapse",
|
||||||
"Expand": "Expand",
|
"Expand": "Expand",
|
||||||
"Type a command or search": "Type a command or search",
|
"Type a command or search": "Type a command or search",
|
||||||
|
"Open search from anywhere with the {{ shortcut }} shortcut": "Open search from anywhere with the {{ shortcut }} shortcut",
|
||||||
"Server connection lost": "Server connection lost",
|
"Server connection lost": "Server connection lost",
|
||||||
"Edits you make will sync once you’re online": "Edits you make will sync once you’re online",
|
"Edits you make will sync once you’re online": "Edits you make will sync once you’re online",
|
||||||
"Submenu": "Submenu",
|
"Submenu": "Submenu",
|
||||||
@@ -364,11 +367,8 @@
|
|||||||
"Add groups to {{ collectionName }}": "Add groups to {{ collectionName }}",
|
"Add groups to {{ collectionName }}": "Add groups to {{ collectionName }}",
|
||||||
"Add people to {{ collectionName }}": "Add people to {{ collectionName }}",
|
"Add people to {{ collectionName }}": "Add people to {{ collectionName }}",
|
||||||
"Document updated by {{userName}}": "Document updated by {{userName}}",
|
"Document updated by {{userName}}": "Document updated by {{userName}}",
|
||||||
"This template will be permanently deleted in <2></2> unless restored.": "This template will be permanently deleted in <2></2> unless restored.",
|
|
||||||
"This document will be permanently deleted in <2></2> unless restored.": "This document will be permanently deleted in <2></2> unless restored.",
|
|
||||||
"You have unsaved changes.\nAre you sure you want to discard them?": "You have unsaved changes.\nAre you sure you want to discard them?",
|
"You have unsaved changes.\nAre you sure you want to discard them?": "You have unsaved changes.\nAre you sure you want to discard them?",
|
||||||
"Images are still uploading.\nAre you sure you want to discard them?": "Images are still uploading.\nAre you sure you want to discard them?",
|
"Images are still uploading.\nAre you sure you want to discard them?": "Images are still uploading.\nAre you sure you want to discard them?",
|
||||||
"Untitled template": "Untitled template",
|
|
||||||
"Type '/' to insert, or start writing…": "Type '/' to insert, or start writing…",
|
"Type '/' to insert, or start writing…": "Type '/' to insert, or start writing…",
|
||||||
"Hide contents": "Hide contents",
|
"Hide contents": "Hide contents",
|
||||||
"Show contents": "Show contents",
|
"Show contents": "Show contents",
|
||||||
@@ -382,7 +382,10 @@
|
|||||||
"Publish": "Publish",
|
"Publish": "Publish",
|
||||||
"Publishing": "Publishing",
|
"Publishing": "Publishing",
|
||||||
"Sorry, it looks like you don’t have permission to access the document": "Sorry, it looks like you don’t have permission to access the document",
|
"Sorry, it looks like you don’t have permission to access the document": "Sorry, it looks like you don’t have permission to access the document",
|
||||||
"You’re editing a template. Highlight some text and use the <2></2> control to add placeholders that can be filled out when creating new documents from this template.": "You’re editing a template. Highlight some text and use the <2></2> control to add placeholders that can be filled out when creating new documents from this template.",
|
"This template will be permanently deleted in <2></2> unless restored.": "This template will be permanently deleted in <2></2> unless restored.",
|
||||||
|
"This document will be permanently deleted in <2></2> unless restored.": "This document will be permanently deleted in <2></2> unless restored.",
|
||||||
|
"Highlight some text and use the <2></2> control to add placeholders that can be filled out when creating new documents": "Highlight some text and use the <2></2> control to add placeholders that can be filled out when creating new documents",
|
||||||
|
"You’re editing a template": "You’re editing a template",
|
||||||
"Archived by {{userName}}": "Archived by {{userName}}",
|
"Archived by {{userName}}": "Archived by {{userName}}",
|
||||||
"Deleted by {{userName}}": "Deleted by {{userName}}",
|
"Deleted by {{userName}}": "Deleted by {{userName}}",
|
||||||
"Observing {{ userName }}": "Observing {{ userName }}",
|
"Observing {{ userName }}": "Observing {{ userName }}",
|
||||||
@@ -506,7 +509,6 @@
|
|||||||
"Past week": "Past week",
|
"Past week": "Past week",
|
||||||
"Past month": "Past month",
|
"Past month": "Past month",
|
||||||
"Past year": "Past year",
|
"Past year": "Past year",
|
||||||
"Recent searches": "Recent searches",
|
|
||||||
"Remove search": "Remove search",
|
"Remove search": "Remove search",
|
||||||
"Active documents": "Active documents",
|
"Active documents": "Active documents",
|
||||||
"Documents in collections you are able to access": "Documents in collections you are able to access",
|
"Documents in collections you are able to access": "Documents in collections you are able to access",
|
||||||
|
|||||||
Reference in New Issue
Block a user