diff --git a/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.stories.tsx b/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.stories.tsx
new file mode 100644
index 000000000..c43118c72
--- /dev/null
+++ b/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.stories.tsx
@@ -0,0 +1,19 @@
+import { storiesOf } from "@storybook/react";
+import React from "react";
+
+import Decorator from "@saleor/storybook/Decorator";
+import ServiceDeleteDialog, {
+ ServiceDeleteDialogProps
+} from "./ServiceDeleteDialog";
+
+const props: ServiceDeleteDialogProps = {
+ confirmButtonState: "default",
+ name: "Magento Importer",
+ onClose: () => undefined,
+ onConfirm: () => undefined,
+ open: true
+};
+
+storiesOf("Views / Services / Delete service", module)
+ .addDecorator(Decorator)
+ .add("default", () => );
diff --git a/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.tsx b/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.tsx
new file mode 100644
index 000000000..ec83a9494
--- /dev/null
+++ b/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.tsx
@@ -0,0 +1,50 @@
+import DialogContentText from "@material-ui/core/DialogContentText";
+import React from "react";
+import { FormattedMessage, useIntl } from "react-intl";
+
+import ActionDialog from "@saleor/components/ActionDialog";
+import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
+
+export interface ServiceDeleteDialogProps {
+ confirmButtonState: ConfirmButtonTransitionState;
+ open: boolean;
+ name: string;
+ onClose: () => void;
+ onConfirm: () => void;
+}
+
+const ServiceDeleteDialog: React.FC = ({
+ confirmButtonState,
+ open,
+ name,
+ onClose,
+ onConfirm
+}) => {
+ const intl = useIntl();
+
+ return (
+
+
+ {name}
+ }}
+ />
+
+
+ );
+};
+ServiceDeleteDialog.displayName = "ServiceDeleteDialog";
+export default ServiceDeleteDialog;
diff --git a/src/services/components/ServiceDeleteDialog/index.ts b/src/services/components/ServiceDeleteDialog/index.ts
new file mode 100644
index 000000000..b43358431
--- /dev/null
+++ b/src/services/components/ServiceDeleteDialog/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./ServiceDeleteDialog";
+export * from "./ServiceDeleteDialog";
diff --git a/src/services/components/ServiceList/ServiceList.tsx b/src/services/components/ServiceList/ServiceList.tsx
index 78b730396..9efeb2899 100644
--- a/src/services/components/ServiceList/ServiceList.tsx
+++ b/src/services/components/ServiceList/ServiceList.tsx
@@ -17,10 +17,9 @@ import EditIcon from "@material-ui/icons/Edit";
import React from "react";
import { FormattedMessage } from "react-intl";
-import Checkbox from "@saleor/components/Checkbox";
import Skeleton from "@saleor/components/Skeleton";
import TablePagination from "@saleor/components/TablePagination";
-import { maybe, renderCollection } from "@saleor/misc";
+import { maybe, renderCollection, stopPropagation } from "@saleor/misc";
import { ListProps } from "@saleor/types";
import { ServiceList_serviceAccounts_edges_node } from "../../types/ServiceList";
@@ -76,10 +75,15 @@ const ServiceList = withStyles(styles, {
}: ServiceListProps & WithStyles) => (
-
-
-
-
+
+
+
+
+
+
@@ -135,7 +139,11 @@ const ServiceList = withStyles(styles, {
onRemove(service.id) : undefined}
+ onClick={
+ service
+ ? stopPropagation(() => onRemove(service.id))
+ : undefined
+ }
>
diff --git a/src/services/mutations.ts b/src/services/mutations.ts
index cbec091e5..b28f0cdb3 100644
--- a/src/services/mutations.ts
+++ b/src/services/mutations.ts
@@ -1,10 +1,12 @@
import gql from "graphql-tag";
import { TypedMutation } from "../mutations";
-import { serviceFragment } from "./queries";
+import { serviceDetailsFragment, serviceFragment } from "./queries";
import { ServiceCreate, ServiceCreateVariables } from "./types/ServiceCreate";
+import { ServiceDelete, ServiceDeleteVariables } from "./types/ServiceDelete";
+import { ServiceUpdate, ServiceUpdateVariables } from "./types/ServiceUpdate";
-export const serviceCreateMutation = gql`
+const serviceCreateMutation = gql`
${serviceFragment}
mutation ServiceCreate($input: ServiceAccountInput!) {
serviceAccountCreate(input: $input) {
@@ -18,7 +20,43 @@ export const serviceCreateMutation = gql`
}
}
`;
+
export const ServiceCreateMutation = TypedMutation<
ServiceCreate,
ServiceCreateVariables
>(serviceCreateMutation);
+
+const serviceDeleteMutation = gql`
+ mutation ServiceDelete($id: ID!) {
+ serviceAccountDelete(id: $id) {
+ errors {
+ field
+ message
+ }
+ }
+ }
+`;
+export const ServiceDeleteMutation = TypedMutation<
+ ServiceDelete,
+ ServiceDeleteVariables
+>(serviceDeleteMutation);
+
+const serviceUpdateMutation = gql`
+ ${serviceDetailsFragment}
+ mutation ServiceUpdate($id: ID!, $input: ServiceAccountInput!) {
+ serviceAccountUpdate(id: $id, input: $input) {
+ errors {
+ field
+ message
+ }
+ serviceAccount {
+ ...ServiceDetailsFragment
+ }
+ }
+ }
+`;
+
+export const ServiceUpdateMutation = TypedMutation<
+ ServiceUpdate,
+ ServiceUpdateVariables
+>(serviceUpdateMutation);
diff --git a/src/services/queries.ts b/src/services/queries.ts
index f7327fc50..7263670d3 100644
--- a/src/services/queries.ts
+++ b/src/services/queries.ts
@@ -47,7 +47,7 @@ export const ServiceListQuery = TypedQuery(
serviceList
);
-const serviceDetailsFragment = gql`
+export const serviceDetailsFragment = gql`
${serviceFragment}
fragment ServiceDetailsFragment on ServiceAccount {
...ServiceFragment
diff --git a/src/services/types/ServiceDelete.ts b/src/services/types/ServiceDelete.ts
new file mode 100644
index 000000000..c339507d8
--- /dev/null
+++ b/src/services/types/ServiceDelete.ts
@@ -0,0 +1,26 @@
+/* tslint:disable */
+/* eslint-disable */
+// This file was automatically generated and should not be edited.
+
+// ====================================================
+// GraphQL mutation operation: ServiceDelete
+// ====================================================
+
+export interface ServiceDelete_serviceAccountDelete_errors {
+ __typename: "Error";
+ field: string | null;
+ message: string | null;
+}
+
+export interface ServiceDelete_serviceAccountDelete {
+ __typename: "ServiceAccountDelete";
+ errors: ServiceDelete_serviceAccountDelete_errors[] | null;
+}
+
+export interface ServiceDelete {
+ serviceAccountDelete: ServiceDelete_serviceAccountDelete | null;
+}
+
+export interface ServiceDeleteVariables {
+ id: string;
+}
diff --git a/src/services/types/ServiceUpdate.ts b/src/services/types/ServiceUpdate.ts
new file mode 100644
index 000000000..f267ca6c9
--- /dev/null
+++ b/src/services/types/ServiceUpdate.ts
@@ -0,0 +1,52 @@
+/* tslint:disable */
+/* eslint-disable */
+// This file was automatically generated and should not be edited.
+
+import { ServiceAccountInput, PermissionEnum } from "./../../types/globalTypes";
+
+// ====================================================
+// GraphQL mutation operation: ServiceUpdate
+// ====================================================
+
+export interface ServiceUpdate_serviceAccountUpdate_errors {
+ __typename: "Error";
+ field: string | null;
+ message: string | null;
+}
+
+export interface ServiceUpdate_serviceAccountUpdate_serviceAccount_permissions {
+ __typename: "PermissionDisplay";
+ code: PermissionEnum;
+ name: string;
+}
+
+export interface ServiceUpdate_serviceAccountUpdate_serviceAccount_tokens {
+ __typename: "ServiceAccountToken";
+ id: string;
+ name: string | null;
+ authToken: string | null;
+}
+
+export interface ServiceUpdate_serviceAccountUpdate_serviceAccount {
+ __typename: "ServiceAccount";
+ id: string;
+ name: string | null;
+ isActive: boolean | null;
+ permissions: (ServiceUpdate_serviceAccountUpdate_serviceAccount_permissions | null)[] | null;
+ tokens: (ServiceUpdate_serviceAccountUpdate_serviceAccount_tokens | null)[] | null;
+}
+
+export interface ServiceUpdate_serviceAccountUpdate {
+ __typename: "ServiceAccountUpdate";
+ errors: ServiceUpdate_serviceAccountUpdate_errors[] | null;
+ serviceAccount: ServiceUpdate_serviceAccountUpdate_serviceAccount | null;
+}
+
+export interface ServiceUpdate {
+ serviceAccountUpdate: ServiceUpdate_serviceAccountUpdate | null;
+}
+
+export interface ServiceUpdateVariables {
+ id: string;
+ input: ServiceAccountInput;
+}
diff --git a/src/services/urls.ts b/src/services/urls.ts
index 0c78289ee..3fb758a6d 100644
--- a/src/services/urls.ts
+++ b/src/services/urls.ts
@@ -3,7 +3,6 @@ import urlJoin from "url-join";
import {
ActiveTab,
- BulkAction,
Dialog,
Filters,
Pagination,
@@ -20,10 +19,10 @@ export enum ServiceListUrlFiltersEnum {
export type ServiceListUrlFilters = Filters;
export type ServiceListUrlDialog = "remove" | TabActionDialog;
export type ServiceListUrlQueryParams = ActiveTab &
- BulkAction &
ServiceListUrlFilters &
Dialog &
- Pagination;
+ Pagination &
+ SingleAction;
export const serviceListUrl = (params?: ServiceListUrlQueryParams) =>
serviceListPath + "?" + stringifyQs(params);
diff --git a/src/services/views/ServiceList/ServiceList.tsx b/src/services/views/ServiceList/ServiceList.tsx
index 9cd843fe6..6e102fd16 100644
--- a/src/services/views/ServiceList/ServiceList.tsx
+++ b/src/services/views/ServiceList/ServiceList.tsx
@@ -16,7 +16,10 @@ import { configurationMenuUrl } from "@saleor/configuration";
import useShop from "@saleor/hooks/useShop";
import { commonMessages } from "@saleor/intl";
import { getMutationState, maybe } from "@saleor/misc";
+import { ServiceDeleteMutation } from "@saleor/services/mutations";
+import { ServiceDelete } from "@saleor/services/types/ServiceDelete";
import { ListViews } from "@saleor/types";
+import ServiceDeleteDialog from "../../components/ServiceDeleteDialog";
import ServiceListPage from "../../components/ServiceListPage";
import { ServiceListQuery } from "../../queries";
import {
@@ -50,7 +53,6 @@ export const ServiceList: React.StatelessComponent = ({
ListViews.STAFF_MEMBERS_LIST
);
const intl = useIntl();
- const shop = useShop();
const tabs = getFilterTabs();
@@ -75,17 +77,17 @@ export const ServiceList: React.StatelessComponent = ({
serviceListUrl({
...params,
action: undefined,
- ids: undefined
+ id: undefined
}),
true
);
- const openModal = (action: ServiceListUrlDialog, ids?: string[]) =>
+ const openModal = (action: ServiceListUrlDialog, id?: string) =>
navigate(
serviceListUrl({
...params,
action,
- ids
+ id
})
);
@@ -119,7 +121,7 @@ export const ServiceList: React.StatelessComponent = ({
return (
- {({ data, loading }) => {
+ {({ data, loading, refetch }) => {
const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
maybe(() => data.serviceAccounts.pageInfo),
paginationState,
@@ -127,40 +129,95 @@ export const ServiceList: React.StatelessComponent = ({
);
const handleCreate = () => navigate(serviceAddUrl);
- const handleRemove = () =>
+ const handleRemove = (id: string) =>
navigate(
serviceListUrl({
...params,
- action: "remove"
+ action: "remove",
+ id
})
);
+ const onRemove = (data: ServiceDelete) => {
+ if (data.serviceAccountDelete.errors.length === 0) {
+ notify({
+ text: intl.formatMessage(commonMessages.savedChanges)
+ });
+ closeModal();
+ refetch();
+ }
+ };
return (
- <>
- changeFilterField({ query })}
- onAll={() => navigate(serviceListUrl())}
- onTabChange={handleTabChange}
- onTabDelete={() => openModal("delete-search")}
- onTabSave={() => openModal("save-search")}
- tabs={tabs.map(tab => tab.name)}
- disabled={loading}
- settings={settings}
- pageInfo={pageInfo}
- services={maybe(() =>
- data.serviceAccounts.edges.map(edge => edge.node)
- )}
- onAdd={handleCreate}
- onBack={() => navigate(configurationMenuUrl)}
- onNextPage={loadNextPage}
- onPreviousPage={loadPreviousPage}
- onUpdateListSettings={updateListSettings}
- onRowClick={id => () => navigate(serviceUrl(id))}
- onRemove={handleRemove}
- />
- >
+
+ {(deleteService, deleteServiceOpts) => {
+ const handleRemoveConfirm = () =>
+ deleteService({
+ variables: {
+ id: params.id
+ }
+ });
+
+ const removeTransitionState = getMutationState(
+ deleteServiceOpts.called,
+ deleteServiceOpts.loading,
+ maybe(() => deleteServiceOpts.data.serviceAccountDelete.errors)
+ );
+
+ return (
+ <>
+ changeFilterField({ query })}
+ onAll={() => navigate(serviceListUrl())}
+ onTabChange={handleTabChange}
+ onTabDelete={() => openModal("delete-search")}
+ onTabSave={() => openModal("save-search")}
+ tabs={tabs.map(tab => tab.name)}
+ disabled={loading}
+ settings={settings}
+ pageInfo={pageInfo}
+ services={maybe(() =>
+ data.serviceAccounts.edges.map(edge => edge.node)
+ )}
+ onAdd={handleCreate}
+ onBack={() => navigate(configurationMenuUrl)}
+ onNextPage={loadNextPage}
+ onPreviousPage={loadPreviousPage}
+ onUpdateListSettings={updateListSettings}
+ onRowClick={id => () => navigate(serviceUrl(id))}
+ onRemove={handleRemove}
+ />
+
+ data.serviceAccounts.edges.find(
+ edge => edge.node.id === params.id
+ ).node.name,
+ "..."
+ )}
+ onClose={closeModal}
+ onConfirm={handleRemoveConfirm}
+ open={params.action === "remove"}
+ />
+
+ tabs[currentTab - 1].name, "...")}
+ />
+ >
+ );
+ }}
+
);
}}