Add inline service remove

This commit is contained in:
dominik-zeglen 2019-09-27 15:57:54 +02:00
parent 8990940fc6
commit 9535563939
10 changed files with 296 additions and 45 deletions

View file

@ -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", () => <ServiceDeleteDialog {...props} />);

View file

@ -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<ServiceDeleteDialogProps> = ({
confirmButtonState,
open,
name,
onClose,
onConfirm
}) => {
const intl = useIntl();
return (
<ActionDialog
confirmButtonState={confirmButtonState}
open={open}
onClose={onClose}
onConfirm={onConfirm}
title={intl.formatMessage({
defaultMessage: "Delete Service Account",
description: "dialog header"
})}
variant="delete"
>
<DialogContentText>
<FormattedMessage
defaultMessage="Are you sure you want to delete {name}?"
description="delete service account"
values={{
name: <strong>{name}</strong>
}}
/>
</DialogContentText>
</ActionDialog>
);
};
ServiceDeleteDialog.displayName = "ServiceDeleteDialog";
export default ServiceDeleteDialog;

View file

@ -0,0 +1,2 @@
export { default } from "./ServiceDeleteDialog";
export * from "./ServiceDeleteDialog";

View file

@ -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<typeof styles>) => (
<Table className={classes.table}>
<TableHead>
<TableCell className={classes.colName}>
<FormattedMessage defaultMessage="Name" description="service name" />
</TableCell>
<TableCell />
<TableRow>
<TableCell className={classes.colName}>
<FormattedMessage
defaultMessage="Name"
description="service name"
/>
</TableCell>
<TableCell />
</TableRow>
</TableHead>
<TableFooter>
<TableRow>
@ -135,7 +139,11 @@ const ServiceList = withStyles(styles, {
</IconButton>
<IconButton
color="primary"
onClick={service ? () => onRemove(service.id) : undefined}
onClick={
service
? stopPropagation(() => onRemove(service.id))
: undefined
}
>
<DeleteIcon />
</IconButton>

View file

@ -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);

View file

@ -47,7 +47,7 @@ export const ServiceListQuery = TypedQuery<ServiceList, ServiceListVariables>(
serviceList
);
const serviceDetailsFragment = gql`
export const serviceDetailsFragment = gql`
${serviceFragment}
fragment ServiceDetailsFragment on ServiceAccount {
...ServiceFragment

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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<ServiceListUrlFiltersEnum>;
export type ServiceListUrlDialog = "remove" | TabActionDialog;
export type ServiceListUrlQueryParams = ActiveTab &
BulkAction &
ServiceListUrlFilters &
Dialog<ServiceListUrlDialog> &
Pagination;
Pagination &
SingleAction;
export const serviceListUrl = (params?: ServiceListUrlQueryParams) =>
serviceListPath + "?" + stringifyQs(params);

View file

@ -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<ServiceListProps> = ({
ListViews.STAFF_MEMBERS_LIST
);
const intl = useIntl();
const shop = useShop();
const tabs = getFilterTabs();
@ -75,17 +77,17 @@ export const ServiceList: React.StatelessComponent<ServiceListProps> = ({
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<ServiceListProps> = ({
return (
<ServiceListQuery displayLoader variables={queryVariables}>
{({ data, loading }) => {
{({ data, loading, refetch }) => {
const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
maybe(() => data.serviceAccounts.pageInfo),
paginationState,
@ -127,40 +129,95 @@ export const ServiceList: React.StatelessComponent<ServiceListProps> = ({
);
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 (
<>
<ServiceListPage
currentTab={currentTab}
initialSearch={params.query || ""}
onSearchChange={query => 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}
/>
</>
<ServiceDeleteMutation onCompleted={onRemove}>
{(deleteService, deleteServiceOpts) => {
const handleRemoveConfirm = () =>
deleteService({
variables: {
id: params.id
}
});
const removeTransitionState = getMutationState(
deleteServiceOpts.called,
deleteServiceOpts.loading,
maybe(() => deleteServiceOpts.data.serviceAccountDelete.errors)
);
return (
<>
<ServiceListPage
currentTab={currentTab}
initialSearch={params.query || ""}
onSearchChange={query => 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}
/>
<ServiceDeleteDialog
confirmButtonState={removeTransitionState}
name={maybe(
() =>
data.serviceAccounts.edges.find(
edge => edge.node.id === params.id
).node.name,
"..."
)}
onClose={closeModal}
onConfirm={handleRemoveConfirm}
open={params.action === "remove"}
/>
<SaveFilterTabDialog
open={params.action === "save-search"}
confirmButtonState="default"
onClose={closeModal}
onSubmit={handleTabSave}
/>
<DeleteFilterTabDialog
open={params.action === "delete-search"}
confirmButtonState="default"
onClose={closeModal}
onSubmit={handleTabDelete}
tabName={maybe(() => tabs[currentTab - 1].name, "...")}
/>
</>
);
}}
</ServiceDeleteMutation>
);
}}
</ServiceListQuery>