(
return (
- {mode === "orders" && #}
+ {mode !== "default" && (
+
+ {mode === "orders" ? "#" : ">"}
+
+ )}
(
defaultMessage: "Order Number",
description: "navigator placeholder"
})
+ : mode === "commands"
+ ? intl.formatMessage({
+ defaultMessage: "Type Command",
+ description: "navigator placeholder"
+ })
: intl.formatMessage({
defaultMessage: "Use Navigator to move through Saleor",
description: "navigator placeholder"
diff --git a/src/components/Navigator/modes/commands/actions.ts b/src/components/Navigator/modes/commands/actions.ts
new file mode 100644
index 000000000..2d00ab69d
--- /dev/null
+++ b/src/components/Navigator/modes/commands/actions.ts
@@ -0,0 +1,75 @@
+import { score } from "fuzzaldrin";
+import { IntlShape } from "react-intl";
+
+import { categoryAddUrl } from "@saleor/categories/urls";
+import { collectionAddUrl } from "@saleor/collections/urls";
+import { customerAddUrl } from "@saleor/customers/urls";
+import { voucherAddUrl } from "@saleor/discounts/urls";
+import { UseNavigatorResult } from "@saleor/hooks/useNavigator";
+import { OrderDraftCreate } from "@saleor/orders/types/OrderDraftCreate";
+import { productAddUrl } from "@saleor/products/urls";
+import { MutationFunction } from "react-apollo";
+import { QuickSearchAction } from "../../types";
+import messages from "../messages";
+
+const threshold = 0.05;
+const maxActions = 5;
+
+interface Command {
+ label: string;
+ onClick: () => void;
+}
+export function searchInCommands(
+ search: string,
+ intl: IntlShape,
+ navigate: UseNavigatorResult,
+ createOrder: MutationFunction
+): QuickSearchAction[] {
+ const actions: Command[] = [
+ {
+ label: intl.formatMessage(messages.addCategory),
+ onClick: () => navigate(categoryAddUrl())
+ },
+ {
+ label: intl.formatMessage(messages.addCollection),
+ onClick: () => navigate(collectionAddUrl)
+ },
+ {
+ label: intl.formatMessage(messages.addProduct),
+ onClick: () => navigate(productAddUrl)
+ },
+ {
+ label: intl.formatMessage(messages.addCustomer),
+ onClick: () => navigate(customerAddUrl)
+ },
+ {
+ label: intl.formatMessage(messages.addVoucher),
+ onClick: () => navigate(voucherAddUrl)
+ },
+ {
+ label: intl.formatMessage(messages.createOrder),
+ onClick: createOrder
+ }
+ ];
+
+ return actions.map(action => ({
+ label: action.label,
+ onClick: action.onClick,
+ score: score(action.label, search),
+ type: "action"
+ }));
+}
+
+function getCommandModeActions(
+ query: string,
+ intl: IntlShape,
+ navigate: UseNavigatorResult,
+ createOrder: MutationFunction
+): QuickSearchAction[] {
+ return [...searchInCommands(query, intl, navigate, createOrder)]
+ .filter(action => action.score >= threshold)
+ .sort((a, b) => (a.score <= b.score ? 1 : -1))
+ .slice(0, maxActions);
+}
+
+export default getCommandModeActions;
diff --git a/src/components/Navigator/modes/commands/index.ts b/src/components/Navigator/modes/commands/index.ts
new file mode 100644
index 000000000..9600b6455
--- /dev/null
+++ b/src/components/Navigator/modes/commands/index.ts
@@ -0,0 +1,2 @@
+export * from "./actions";
+export { default } from "./actions";
diff --git a/src/components/Navigator/modes/default/actions.ts b/src/components/Navigator/modes/default/actions.ts
deleted file mode 100644
index ee7c489bd..000000000
--- a/src/components/Navigator/modes/default/actions.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { QuickSearchAction } from "../../types";
-
-export function getActions(actions: QuickSearchAction[]): QuickSearchAction[] {
- return actions.filter(action => action.type === "action");
-}
-export function hasActions(actions: QuickSearchAction[]): boolean {
- return getActions(actions).length > 0;
-}
diff --git a/src/components/Navigator/modes/default/default.ts b/src/components/Navigator/modes/default/default.ts
index 41f1c3e09..d56a44e79 100644
--- a/src/components/Navigator/modes/default/default.ts
+++ b/src/components/Navigator/modes/default/default.ts
@@ -1,16 +1,25 @@
+import { MutationFunction } from "react-apollo";
import { IntlShape } from "react-intl";
+import { UseNavigatorResult } from "@saleor/hooks/useNavigator";
+import { OrderDraftCreate } from "@saleor/orders/types/OrderDraftCreate";
import { QuickSearchAction } from "../../types";
+import { searchInCommands } from "../commands";
import searchInViews from "./views";
const threshold = 0.05;
-const maxActions = 10;
+const maxActions = 5;
function getDefaultModeActions(
query: string,
- intl: IntlShape
+ intl: IntlShape,
+ navigate: UseNavigatorResult,
+ createOrder: MutationFunction
): QuickSearchAction[] {
- return [...searchInViews(query, intl)]
+ return [
+ ...searchInViews(query, intl, navigate),
+ ...searchInCommands(query, intl, navigate, createOrder)
+ ]
.filter(action => action.score >= threshold)
.sort((a, b) => (a.score <= b.score ? 1 : -1))
.slice(0, maxActions);
diff --git a/src/components/Navigator/modes/default/index.ts b/src/components/Navigator/modes/default/index.ts
index 445c4ca3d..86fa704d4 100644
--- a/src/components/Navigator/modes/default/index.ts
+++ b/src/components/Navigator/modes/default/index.ts
@@ -1,4 +1,3 @@
-export * from "./actions";
export * from "./default";
export { default } from "./default";
export * from "./views";
diff --git a/src/components/Navigator/modes/default/views.ts b/src/components/Navigator/modes/default/views.ts
index 8b6819967..6ae6980f0 100644
--- a/src/components/Navigator/modes/default/views.ts
+++ b/src/components/Navigator/modes/default/views.ts
@@ -6,6 +6,7 @@ import { categoryListUrl } from "@saleor/categories/urls";
import { collectionListUrl } from "@saleor/collections/urls";
import { customerListUrl } from "@saleor/customers/urls";
import { saleListUrl, voucherListUrl } from "@saleor/discounts/urls";
+import { UseNavigatorResult } from "@saleor/hooks/useNavigator";
import { sectionNames } from "@saleor/intl";
import { menuListUrl } from "@saleor/navigation/urls";
import { orderDraftListUrl, orderListUrl } from "@saleor/orders/urls";
@@ -26,7 +27,11 @@ interface View {
label: string;
url: string;
}
-function searchInViews(search: string, intl: IntlShape): QuickSearchAction[] {
+function searchInViews(
+ search: string,
+ intl: IntlShape,
+ navigate: UseNavigatorResult
+): QuickSearchAction[] {
const views: View[] = [
{
label: intl.formatMessage(sectionNames.attributes),
@@ -116,17 +121,10 @@ function searchInViews(search: string, intl: IntlShape): QuickSearchAction[] {
return views.map(view => ({
label: view.label,
+ onClick: () => navigate(view.url),
score: score(view.label, search),
- type: "view",
- url: view.url
+ type: "view"
}));
}
-export function getViews(actions: QuickSearchAction[]): QuickSearchAction[] {
- return actions.filter(action => action.type === "view");
-}
-export function hasViews(actions: QuickSearchAction[]): boolean {
- return getViews(actions).length > 0;
-}
-
export default searchInViews;
diff --git a/src/components/Navigator/modes/index.ts b/src/components/Navigator/modes/index.ts
index 65164eb7d..4bd08f23d 100644
--- a/src/components/Navigator/modes/index.ts
+++ b/src/components/Navigator/modes/index.ts
@@ -1,10 +1,10 @@
import { IntlShape } from "react-intl";
-import {
- CheckIfOrderExists,
- CheckIfOrderExistsVariables
-} from "../queries/types/CheckIfOrderExists";
+import { UseNavigatorResult } from "@saleor/hooks/useNavigator";
+import { OrderDraftCreate } from "@saleor/orders/types/OrderDraftCreate";
+import { MutationFunction } from "react-apollo";
import { QuickSearchAction, QuickSearchMode } from "../types";
+import getCommandModeActions from "./commands";
import getDefaultModeActions from "./default";
import getOrdersModeActions from "./orders";
import { ActionQueries } from "./types";
@@ -13,13 +13,19 @@ function getModeActions(
mode: QuickSearchMode,
query: string,
intl: IntlShape,
- queries: ActionQueries
+ queries: ActionQueries,
+ cbs: {
+ navigate: UseNavigatorResult;
+ createOrder: MutationFunction;
+ }
): QuickSearchAction[] {
switch (mode) {
+ case "commands":
+ return getCommandModeActions(query, intl, cbs.navigate, cbs.createOrder);
case "orders":
- return getOrdersModeActions(query, intl, queries.order);
+ return getOrdersModeActions(query, intl, cbs.navigate, queries.order);
default:
- return getDefaultModeActions(query, intl);
+ return getDefaultModeActions(query, intl, cbs.navigate, cbs.createOrder);
}
}
diff --git a/src/components/Navigator/modes/messages.ts b/src/components/Navigator/modes/messages.ts
index 0fce6090f..07c6df3d0 100644
--- a/src/components/Navigator/modes/messages.ts
+++ b/src/components/Navigator/modes/messages.ts
@@ -1,6 +1,30 @@
import { defineMessages } from "react-intl";
const messages = defineMessages({
+ addCategory: {
+ defaultMessage: "Add Category",
+ description: "button"
+ },
+ addCollection: {
+ defaultMessage: "Add Collection",
+ description: "button"
+ },
+ addCustomer: {
+ defaultMessage: "Add Customer",
+ description: "button"
+ },
+ addProduct: {
+ defaultMessage: "Add Product",
+ description: "button"
+ },
+ addVoucher: {
+ defaultMessage: "Add Voucher",
+ description: "button"
+ },
+ createOrder: {
+ defaultMessage: "Create Order",
+ description: "button"
+ },
goToOrder: {
defaultMessage: "Go to order #{orderNumber}",
description: "navigator action"
diff --git a/src/components/Navigator/modes/orders.ts b/src/components/Navigator/modes/orders.ts
index 4525b72f0..0156d68c6 100644
--- a/src/components/Navigator/modes/orders.ts
+++ b/src/components/Navigator/modes/orders.ts
@@ -1,5 +1,6 @@
import { IntlShape } from "react-intl";
+import { UseNavigatorResult } from "@saleor/hooks/useNavigator";
import { maybe } from "@saleor/misc";
import { orderUrl } from "@saleor/orders/urls";
import { CheckIfOrderExists_order } from "../queries/types/CheckIfOrderExists";
@@ -17,6 +18,7 @@ export function getGqlOrderId(orderNumber: string): string {
function getOrdersModeActions(
query: string,
intl: IntlShape,
+ navigate: UseNavigatorResult,
order: CheckIfOrderExists_order
): QuickSearchAction[] {
const gqlId = getGqlOrderId(query);
@@ -27,9 +29,9 @@ function getOrdersModeActions(
label: intl.formatMessage(messages.goToOrder, {
orderNumber: query
}),
+ onClick: () => navigate(orderUrl(gqlId)),
score: 1,
- type: "action",
- url: orderUrl(gqlId)
+ type: "action"
}
];
}
diff --git a/src/components/Navigator/modes/utils.ts b/src/components/Navigator/modes/utils.ts
new file mode 100644
index 000000000..ceabc81ca
--- /dev/null
+++ b/src/components/Navigator/modes/utils.ts
@@ -0,0 +1,15 @@
+import { QuickSearchAction } from "../types";
+
+export function getActions(actions: QuickSearchAction[]): QuickSearchAction[] {
+ return actions.filter(action => action.type === "action");
+}
+export function hasActions(actions: QuickSearchAction[]): boolean {
+ return getActions(actions).length > 0;
+}
+
+export function getViews(actions: QuickSearchAction[]): QuickSearchAction[] {
+ return actions.filter(action => action.type === "view");
+}
+export function hasViews(actions: QuickSearchAction[]): boolean {
+ return getViews(actions).length > 0;
+}
diff --git a/src/components/Navigator/types.ts b/src/components/Navigator/types.ts
index 3646a7ce9..12279daf5 100644
--- a/src/components/Navigator/types.ts
+++ b/src/components/Navigator/types.ts
@@ -4,7 +4,7 @@ export interface QuickSearchAction {
label: string;
score: number;
type: QuickSearchActionType;
- url: string;
+ onClick: () => void;
}
-export type QuickSearchMode = "default" | "orders" | "customers";
+export type QuickSearchMode = "default" | "commands" | "orders" | "customers";
diff --git a/src/components/Navigator/useQuickSearch.ts b/src/components/Navigator/useQuickSearch.ts
index f1b333e1a..fee527cf5 100644
--- a/src/components/Navigator/useQuickSearch.ts
+++ b/src/components/Navigator/useQuickSearch.ts
@@ -3,7 +3,10 @@ import { useIntl } from "react-intl";
import { ChangeEvent, FormChange } from "@saleor/hooks/useForm";
import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen";
+import useNavigator from "@saleor/hooks/useNavigator";
import { maybe } from "@saleor/misc";
+import { useOrderDraftCreateMutation } from "@saleor/orders/mutations";
+import { orderUrl } from "@saleor/orders/urls";
import getModeActions from "./modes";
import { getGqlOrderId, isQueryValidOrderNumber } from "./modes/orders";
import useCheckIfOrderExists from "./queries/useCheckIfOrderExists";
@@ -22,7 +25,15 @@ function useQuickSearch(
const [query, setQuery] = useState("");
const [mode, setMode] = useState("default");
const intl = useIntl();
+ const navigate = useNavigator();
const [{ data: orderData }, getOrderData] = useCheckIfOrderExists();
+ const [createOrder] = useOrderDraftCreateMutation({
+ onCompleted: result => {
+ if (result.draftOrderCreate.errors.length === 0) {
+ navigate(orderUrl(result.draftOrderCreate.order.id));
+ }
+ }
+ });
useModalDialogOpen(open, {
onClose: () => {
@@ -58,8 +69,12 @@ function useQuickSearch(
if (mode === "default") {
switch (value) {
+ case "> ":
+ setMode("commands");
+ break;
case "# ":
setMode("orders");
+ break;
default:
setQuery(value);
}
@@ -75,9 +90,18 @@ function useQuickSearch(
query,
mode,
change,
- getModeActions(mode, query, intl, {
- order: maybe(() => orderData.order)
- })
+ getModeActions(
+ mode,
+ query,
+ intl,
+ {
+ order: maybe(() => orderData.order)
+ },
+ {
+ createOrder,
+ navigate
+ }
+ )
];
}
diff --git a/src/hooks/makeMutation.ts b/src/hooks/makeMutation.ts
index b6cfd4a91..0ec08736c 100644
--- a/src/hooks/makeMutation.ts
+++ b/src/hooks/makeMutation.ts
@@ -11,15 +11,15 @@ import { commonMessages } from "@saleor/intl";
import { maybe } from "@saleor/misc";
import useNotifier from "./useNotifier";
-type UseMutation = [
+export type UseMutation = [
MutationFunction,
MutationResult
];
-type UseMutationCbs = Partial<{
+export type UseMutationCbs = Partial<{
onCompleted: (data: TData) => void;
onError: (error: ApolloError) => void;
}>;
-type UseMutationHook = (
+export type UseMutationHook = (
cbs: UseMutationCbs
) => UseMutation;
diff --git a/src/orders/mutations.ts b/src/orders/mutations.ts
index 8ab8f659b..4a68ab6ba 100644
--- a/src/orders/mutations.ts
+++ b/src/orders/mutations.ts
@@ -1,5 +1,6 @@
import gql from "graphql-tag";
+import makeMutation from "@saleor/hooks/makeMutation";
import { TypedMutation } from "../mutations";
import {
fragmentAddress,
@@ -409,10 +410,9 @@ const orderDraftCreateMutation = gql`
}
}
`;
-export const TypedOrderDraftCreateMutation = TypedMutation<
- OrderDraftCreate,
- {}
->(orderDraftCreateMutation);
+export const useOrderDraftCreateMutation = makeMutation(
+ orderDraftCreateMutation
+);
const orderLineDeleteMutation = gql`
${fragmentOrderDetails}