Explicitely return not found page

This commit is contained in:
dominik-zeglen 2020-02-20 15:18:22 +01:00
parent 8ed641eee8
commit fa8231992f
22 changed files with 337 additions and 268 deletions

View file

@ -23,6 +23,7 @@ module.exports = api => {
const plugins = [
"@babel/plugin-proposal-numeric-separator",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-class-properties",
[
"@babel/plugin-proposal-decorators",
@ -49,6 +50,6 @@ module.exports = api => {
return {
ignore,
plugins,
presets,
presets
};
};

35
package-lock.json generated
View file

@ -849,6 +849,24 @@
"@babel/plugin-syntax-optional-catch-binding": "^7.2.0"
}
},
"@babel/plugin-proposal-optional-chaining": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz",
"integrity": "sha512-QIoIR9abkVn+seDE3OjA08jWcs3eZ9+wJCKSRgo3WdEU2csFYgdScb+8qHB3+WXsGJD55u+5hWCISI7ejXS+kg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.3",
"@babel/plugin-syntax-optional-chaining": "^7.8.0"
},
"dependencies": {
"@babel/helper-plugin-utils": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz",
"integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==",
"dev": true
}
}
},
"@babel/plugin-proposal-unicode-property-regex": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.0.tgz",
@ -940,6 +958,23 @@
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-syntax-optional-chaining": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
"integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.0"
},
"dependencies": {
"@babel/helper-plugin-utils": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz",
"integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==",
"dev": true
}
}
},
"@babel/plugin-syntax-top-level-await": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.0.tgz",

View file

@ -75,6 +75,7 @@
"@babel/plugin-proposal-decorators": "^7.4.4",
"@babel/plugin-proposal-numeric-separator": "^7.2.0",
"@babel/plugin-proposal-object-rest-spread": "^7.5.4",
"@babel/plugin-proposal-optional-chaining": "^7.8.3",
"@babel/preset-env": "^7.5.4",
"@babel/preset-react": "^7.7.4",
"@babel/preset-typescript": "^7.7.4",

View file

@ -14,6 +14,7 @@ import usePaginator, {
} from "@saleor/hooks/usePaginator";
import { commonMessages } from "@saleor/intl";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import NotFoundPage from "@saleor/components/NotFoundPage";
import { PAGINATE_BY } from "../../config";
import { maybe } from "../../misc";
import { TypedProductBulkDeleteMutation } from "../../products/mutations";
@ -67,10 +68,15 @@ export const CategoryDetails: React.FC<CategoryDetailsProps> = ({
const paginationState = createPaginationState(PAGINATE_BY, params);
const { data, loading, refetch } = useCategoryDetailsQuery({
displayLoader: true,
require: ["category"],
variables: { ...paginationState, id }
});
const category = data?.category;
if (category === null) {
return <NotFoundPage onBack={() => navigate(categoryListUrl())} />;
}
const handleCategoryDelete = (data: CategoryDelete) => {
if (data.categoryDelete.errors.length === 0) {
notify({

View file

@ -68,7 +68,6 @@ export const CategoryList: React.FC<CategoryListProps> = ({ params }) => {
);
const { data, loading, refetch } = useRootCategoriesQuery({
displayLoader: true,
require: ["categories"],
variables: queryVariables
});

View file

@ -16,6 +16,7 @@ import usePaginator, {
import { commonMessages } from "@saleor/intl";
import useProductSearch from "@saleor/searches/useProductSearch";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import NotFoundPage from "@saleor/components/NotFoundPage";
import { getMutationState, maybe } from "../../misc";
import { productUrl } from "../../products/urls";
import { CollectionInput } from "../../types/globalTypes";
@ -61,14 +62,19 @@ export const CollectionDetails: React.FC<CollectionDetailsProps> = ({
>(navigate, params => collectionUrl(id, params), params);
const paginationState = createPaginationState(PAGINATE_BY, params);
const handleBack = () => navigate(collectionListUrl());
return (
<TypedCollectionDetailsQuery
displayLoader
variables={{ id, ...paginationState }}
require={["collection"]}
>
{({ data, loading }) => {
const collection = data?.collection;
if (collection === null) {
return <NotFoundPage onBack={handleBack} />;
}
const handleCollectionUpdate = (data: CollectionUpdate) => {
if (data.collectionUpdate.errors.length === 0) {
notify({
@ -196,7 +202,7 @@ export const CollectionDetails: React.FC<CollectionDetailsProps> = ({
<WindowTitle title={maybe(() => data.collection.name)} />
<CollectionDetailsPage
onAdd={() => openModal("assign")}
onBack={() => navigate(collectionListUrl())}
onBack={handleBack}
disabled={loading}
collection={maybe(() => data.collection)}
isFeatured={maybe(

View file

@ -29,7 +29,6 @@ import { maybe } from "@saleor/misc";
import { staffMemberDetailsUrl } from "@saleor/staff/urls";
import Container from "../Container";
import ErrorPage from "../ErrorPage";
import NotFoundPage from "../NotFoundPage";
import AppActionContext from "./AppActionContext";
import AppHeaderContext from "./AppHeaderContext";
import { appLoaderHeight, drawerWidth, drawerWidthExpanded } from "./consts";
@ -507,15 +506,11 @@ const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
</Container>
</div>
<main className={classes.view}>
{appState.error ? (
appState.error === "not-found" ? (
<NotFoundPage onBack={handleErrorBack} />
) : (
{appState.error
? appState.error === "unhandled" && (
<ErrorPage onBack={handleErrorBack} />
)
) : (
children
)}
: children}
</main>
</div>
<div className={classes.appAction} ref={appActionAnchor} />

View file

@ -21,7 +21,7 @@ const AppStateProvider: React.FC = ({ children }) => {
if (!!state.error) {
dispatch({
payload: {
error: null
error: undefined
},
type: "displayError"
});

View file

@ -1,4 +1,4 @@
export type AppError = "unhandled" | "not-found";
export type AppError = "unhandled";
interface IAppState {
error: AppError | null;

View file

@ -7,6 +7,7 @@ import { WindowTitle } from "@saleor/components/WindowTitle";
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
import { commonMessages } from "@saleor/intl";
import NotFoundPage from "@saleor/components/NotFoundPage";
import { maybe } from "../../misc";
import { orderListUrl, orderUrl } from "../../orders/urls";
import CustomerDetailsPage from "../components/CustomerDetailsPage/CustomerDetailsPage";
@ -54,6 +55,9 @@ export const CustomerDetailsView: React.FC<CustomerDetailsViewProps> = ({
navigate(customerListUrl());
}
};
const handleBack = () => navigate(customerListUrl());
return (
<TypedRemoveCustomerMutation
variables={{ id }}
@ -62,12 +66,15 @@ export const CustomerDetailsView: React.FC<CustomerDetailsViewProps> = ({
{(removeCustomer, removeCustomerOpts) => (
<TypedUpdateCustomerMutation onCompleted={handleCustomerUpdateSuccess}>
{(updateCustomer, updateCustomerOpts) => (
<TypedCustomerDetailsQuery
displayLoader
variables={{ id }}
require={["user"]}
>
{customerDetails => (
<TypedCustomerDetailsQuery displayLoader variables={{ id }}>
{customerDetails => {
const user = customerDetails.data?.user;
if (user === null) {
return <NotFoundPage onBack={handleBack} />;
}
return (
<>
<WindowTitle
title={maybe(() => customerDetails.data.user.email)}
@ -86,7 +93,7 @@ export const CustomerDetailsView: React.FC<CustomerDetailsViewProps> = ({
onAddressManageClick={() =>
navigate(customerAddressesUrl(id))
}
onBack={() => navigate(customerListUrl())}
onBack={handleBack}
onRowClick={id => navigate(orderUrl(id))}
onSubmit={formData =>
updateCustomer({
@ -112,7 +119,9 @@ export const CustomerDetailsView: React.FC<CustomerDetailsViewProps> = ({
onViewAllOrdersClick={() =>
navigate(
orderListUrl({
customer: maybe(() => customerDetails.data.user.email)
customer: maybe(
() => customerDetails.data.user.email
)
})
)
}
@ -146,7 +155,8 @@ export const CustomerDetailsView: React.FC<CustomerDetailsViewProps> = ({
</DialogContentText>
</ActionDialog>
</>
)}
);
}}
</TypedCustomerDetailsQuery>
)}
</TypedUpdateCustomerMutation>

View file

@ -18,14 +18,13 @@ export interface LoadMore<TData, TVariables> {
export type UseQueryResult<TData, TVariables> = QueryResult<TData, TVariables> &
LoadMore<TData, TVariables>;
type UseQueryOpts<TData, TVariables> = Partial<{
type UseQueryOpts<TVariables> = Partial<{
displayLoader: boolean;
require: Array<keyof TData>;
skip: boolean;
variables: TVariables;
}>;
type UseQueryHook<TData, TVariables> = (
opts: UseQueryOpts<TData, TVariables>
opts: UseQueryOpts<TVariables>
) => UseQueryResult<TData, TVariables>;
function makeQuery<TData, TVariables>(
@ -33,10 +32,9 @@ function makeQuery<TData, TVariables>(
): UseQueryHook<TData, TVariables> {
function useQuery({
displayLoader,
require,
skip,
variables
}: UseQueryOpts<TData, TVariables>): UseQueryResult<TData, TVariables> {
}: UseQueryOpts<TVariables>): UseQueryResult<TData, TVariables> {
const notify = useNotifier();
const intl = useIntl();
const [, dispatchAppState] = useAppState();
@ -89,20 +87,6 @@ function makeQuery<TData, TVariables>(
variables: { ...variables, ...extraVariables }
});
if (
!queryData.loading &&
require &&
queryData.data &&
!require.reduce((acc, key) => acc && queryData.data[key] !== null, true)
) {
dispatchAppState({
payload: {
error: "not-found"
},
type: "displayError"
});
}
return {
...queryData,
loadMore

View file

@ -380,3 +380,7 @@ export function transformFormToAddress<T>(
country: findInEnum(address.country, CountryCode)
};
}
export function getStringOrPlaceholder(s: string | undefined): string {
return s || "...";
}

View file

@ -6,6 +6,7 @@ import useNavigator from "@saleor/hooks/useNavigator";
import useUser from "@saleor/hooks/useUser";
import useCustomerSearch from "@saleor/searches/useCustomerSearch";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import NotFoundPage from "@saleor/components/NotFoundPage";
import { customerUrl } from "../../../customers/urls";
import { getMutationState, maybe, transformAddressToForm } from "../../../misc";
import { productUrl } from "../../../products/urls";
@ -90,14 +91,17 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const handleBack = () => navigate(orderListUrl());
return (
<TypedOrderDetailsQuery
displayLoader
variables={{ id }}
require={["order"]}
>
<TypedOrderDetailsQuery displayLoader variables={{ id }}>
{({ data, loading }) => {
const order = maybe(() => data.order);
const order = data?.order;
if (order === null) {
return <NotFoundPage onBack={handleBack} />;
}
const [openModal, closeModal] = createDialogActionHandlers<
OrderUrlDialog,
OrderUrlQueryParams
@ -166,7 +170,7 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
order: id
})
}
onBack={() => navigate(orderListUrl())}
onBack={handleBack}
order={order}
shippingMethods={maybe(
() => data.order.availableShippingMethods,

View file

@ -13,6 +13,7 @@ import { maybe } from "@saleor/misc";
import AssignAttributeDialog from "@saleor/productTypes/components/AssignAttributeDialog";
import { ReorderEvent } from "@saleor/types";
import { AttributeTypeEnum } from "@saleor/types/globalTypes";
import NotFoundPage from "@saleor/components/NotFoundPage";
import ProductTypeAttributeUnassignDialog from "../../components/ProductTypeAttributeUnassignDialog";
import ProductTypeBulkAttributeUnassignDialog from "../../components/ProductTypeBulkAttributeUnassignDialog";
import ProductTypeDeleteDialog from "../../components/ProductTypeDeleteDialog";
@ -54,15 +55,19 @@ export const ProductTypeUpdate: React.FC<ProductTypeUpdateProps> = ({
}
});
const handleBack = () => navigate(productTypeListUrl());
return (
<ProductTypeUpdateErrors>
{({ errors, set: setErrors }) => (
<TypedProductTypeDetailsQuery
displayLoader
variables={{ id }}
require={["productType"]}
>
<TypedProductTypeDetailsQuery displayLoader variables={{ id }}>
{({ data, loading: dataLoading }) => {
const productType = data?.productType;
if (productType === null) {
return <NotFoundPage onBack={handleBack} />;
}
const closeModal = () => navigate(productTypeUrl(id), true);
const handleAttributeAssignSuccess = (data: AssignAttribute) => {
@ -242,7 +247,7 @@ export const ProductTypeUpdate: React.FC<ProductTypeUpdateProps> = ({
})
)
}
onBack={() => navigate(productTypeListUrl())}
onBack={handleBack}
onDelete={() =>
navigate(
productTypeUrl(id, {

View file

@ -5,6 +5,7 @@ import { FormattedMessage, useIntl } from "react-intl";
import ActionDialog from "@saleor/components/ActionDialog";
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
import NotFoundPage from "@saleor/components/NotFoundPage";
import { maybe } from "../../misc";
import ProductImagePage from "../components/ProductImagePage";
import {
@ -16,7 +17,8 @@ import { ProductImageUpdate } from "../types/ProductImageUpdate";
import {
productImageUrl,
ProductImageUrlQueryParams,
productUrl
productUrl,
productListUrl
} from "../urls";
interface ProductImageProps {
@ -47,9 +49,15 @@ export const ProductImage: React.FC<ProductImageProps> = ({
imageId,
productId
}}
require={["product"]}
>
{({ data, loading }) => (
{({ data, loading }) => {
const product = data?.product;
if (product === null) {
return <NotFoundPage onBack={() => navigate(productListUrl())} />;
}
return (
<TypedProductImageUpdateMutation onCompleted={handleUpdateSuccess}>
{(updateImage, updateResult) => (
<TypedProductImageDeleteMutation onCompleted={handleBack}>
@ -110,7 +118,8 @@ export const ProductImage: React.FC<ProductImageProps> = ({
</TypedProductImageDeleteMutation>
)}
</TypedProductImageUpdateMutation>
)}
);
}}
</TypedProductImageQuery>
);
};

View file

@ -18,6 +18,7 @@ import { ProductVariantBulkCreate } from "@saleor/products/types/ProductVariantB
import useCategorySearch from "@saleor/searches/useCategorySearch";
import useCollectionSearch from "@saleor/searches/useCollectionSearch";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import NotFoundPage from "@saleor/components/NotFoundPage";
import { getMutationState, maybe } from "../../../misc";
import ProductUpdatePage from "../../components/ProductUpdatePage";
import ProductUpdateOperations from "../../containers/ProductUpdateOperations";
@ -76,13 +77,17 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
ProductUrlQueryParams
>(navigate, params => productUrl(id, params), params);
const handleBack = () => navigate(productListUrl());
return (
<TypedProductDetailsQuery
displayLoader
require={["product"]}
variables={{ id }}
>
<TypedProductDetailsQuery displayLoader variables={{ id }}>
{({ data, loading, refetch }) => {
const product = data?.product;
if (product === null) {
return <NotFoundPage onBack={handleBack} />;
}
const handleDelete = () => {
notify({
text: intl.formatMessage({
@ -142,7 +147,6 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
}
};
const product = data ? data.product : undefined;
return (
<ProductUpdateOperations
product={product}
@ -233,9 +237,7 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
placeholderImage={placeholderImg}
product={product}
variants={maybe(() => product.variants)}
onBack={() => {
navigate(productListUrl());
}}
onBack={handleBack}
onDelete={() => openModal("remove")}
onProductShow={() => {
if (product) {

View file

@ -6,6 +6,7 @@ import { WindowTitle } from "@saleor/components/WindowTitle";
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
import { commonMessages } from "@saleor/intl";
import NotFoundPage from "@saleor/components/NotFoundPage";
import { decimal, maybe } from "../../misc";
import ProductVariantDeleteDialog from "../components/ProductVariantDeleteDialog";
import ProductVariantPage, {
@ -13,7 +14,10 @@ import ProductVariantPage, {
} from "../components/ProductVariantPage";
import ProductVariantOperations from "../containers/ProductVariantOperations";
import { TypedProductVariantQuery } from "../queries";
import { VariantUpdate } from "../types/VariantUpdate";
import {
VariantUpdate,
VariantUpdate_productVariantUpdate_productErrors
} from "../types/VariantUpdate";
import {
productUrl,
productVariantAddUrl,
@ -35,20 +39,24 @@ export const ProductVariant: React.FC<ProductUpdateProps> = ({
const navigate = useNavigator();
const notify = useNotifier();
const intl = useIntl();
const [errors, setErrors] = useState([]);
const [errors, setErrors] = useState<
VariantUpdate_productVariantUpdate_productErrors[]
>([]);
useEffect(() => {
setErrors([]);
}, [variantId]);
return (
<TypedProductVariantQuery
displayLoader
variables={{ id: variantId }}
require={["productVariant"]}
>
{({ data, loading }) => {
const variant = data ? data.productVariant : undefined;
const handleBack = () => navigate(productUrl(productId));
return (
<TypedProductVariantQuery displayLoader variables={{ id: variantId }}>
{({ data, loading }) => {
const variant = data?.productVariant;
if (variant === null) {
return <NotFoundPage onBack={handleBack} />;
}
const handleDelete = () => {
notify({
text: intl.formatMessage({

View file

@ -5,6 +5,7 @@ import { WindowTitle } from "@saleor/components/WindowTitle";
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
import useShop from "@saleor/hooks/useShop";
import NotFoundPage from "@saleor/components/NotFoundPage";
import { decimal, maybe } from "../../misc";
import ProductVariantCreatePage, {
ProductVariantCreatePageSubmitData
@ -12,7 +13,7 @@ import ProductVariantCreatePage, {
import { TypedVariantCreateMutation } from "../mutations";
import { TypedProductVariantCreateQuery } from "../queries";
import { VariantCreate } from "../types/VariantCreate";
import { productUrl, productVariantEditUrl } from "../urls";
import { productUrl, productVariantEditUrl, productListUrl } from "../urls";
interface ProductUpdateProps {
productId: string;
@ -25,12 +26,14 @@ export const ProductVariant: React.FC<ProductUpdateProps> = ({ productId }) => {
const intl = useIntl();
return (
<TypedProductVariantCreateQuery
displayLoader
variables={{ id: productId }}
require={["product"]}
>
<TypedProductVariantCreateQuery displayLoader variables={{ id: productId }}>
{({ data, loading: productLoading }) => {
const product = data?.product;
if (product === null) {
return <NotFoundPage onBack={() => navigate(productListUrl())} />;
}
const handleCreateSuccess = (data: VariantCreate) => {
if (data.productVariantCreate.productErrors.length === 0) {
notify({

View file

@ -28,7 +28,6 @@ export interface TypedQueryInnerProps<TData, TVariables> {
displayLoader?: boolean;
skip?: boolean;
variables?: TVariables;
require?: Array<keyof TData>;
}
interface QueryProgressProps {
@ -65,7 +64,7 @@ class QueryProgress extends React.Component<QueryProgressProps, {}> {
export function TypedQuery<TData, TVariables>(
query: DocumentNode
): React.FC<TypedQueryInnerProps<TData, TVariables>> {
return ({ children, displayLoader, skip, variables, require }) => {
return ({ children, displayLoader, skip, variables }) => {
const pushMessage = useNotifier();
const [, dispatchAppState] = useAppState();
const intl = useIntl();
@ -112,23 +111,6 @@ export function TypedQuery<TData, TVariables>(
variables: { ...variables, ...extraVariables }
});
if (
!queryData.loading &&
require &&
queryData.data &&
!require.reduce(
(acc, key) => acc && queryData.data[key] !== null,
true
)
) {
dispatchAppState({
payload: {
error: "not-found"
},
type: "displayError"
});
}
if (displayLoader) {
return (
<QueryProgress

View file

@ -22,6 +22,7 @@ import { ServiceTokenCreate } from "@saleor/services/types/ServiceTokenCreate";
import { ServiceTokenDelete } from "@saleor/services/types/ServiceTokenDelete";
import { ServiceUpdate } from "@saleor/services/types/ServiceUpdate";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import NotFoundPage from "@saleor/components/NotFoundPage";
import ServiceDetailsPage, {
ServiceDetailsPageFormData
} from "../../components/ServiceDetailsPage";
@ -77,12 +78,14 @@ export const ServiceDetails: React.FC<OrderListProps> = ({
const handleBack = () => navigate(serviceListUrl());
return (
<ServiceDetailsQuery
displayLoader
variables={{ id }}
require={["serviceAccount"]}
>
<ServiceDetailsQuery displayLoader variables={{ id }}>
{({ data, loading, refetch }) => {
const service = data?.serviceAccount;
if (service === null) {
return <NotFoundPage onBack={handleBack} />;
}
const onTokenCreate = (data: ServiceTokenCreate) => {
if (maybe(() => data.serviceAccountTokenCreate.errors.length === 0)) {
refetch();
@ -151,9 +154,7 @@ export const ServiceDetails: React.FC<OrderListProps> = ({
return (
<>
<WindowTitle
title={maybe(() => data.serviceAccount.name)}
/>
<WindowTitle title={service?.name || "..."} />
<ServiceDetailsPage
apiUri={API_URI}
disabled={loading}

View file

@ -9,6 +9,7 @@ import useNotifier from "@saleor/hooks/useNotifier";
import useShop from "@saleor/hooks/useShop";
import useUser from "@saleor/hooks/useUser";
import { commonMessages } from "@saleor/intl";
import NotFoundPage from "@saleor/components/NotFoundPage";
import { maybe } from "../../misc";
import StaffDetailsPage from "../components/StaffDetailsPage/StaffDetailsPage";
import {
@ -63,13 +64,17 @@ export const StaffDetails: React.FC<OrderListProps> = ({ id, params }) => {
onCompleted: handleChangePassword
});
const handleBack = () => navigate(staffListUrl());
return (
<TypedStaffMemberDetailsQuery
displayLoader
variables={{ id }}
require={["user"]}
>
<TypedStaffMemberDetailsQuery displayLoader variables={{ id }}>
{({ data, loading }) => {
const staffMember = data?.user;
if (staffMember === null) {
return <NotFoundPage onBack={handleBack} />;
}
const handleStaffMemberUpdate = (data: StaffMemberUpdate) => {
if (!maybe(() => data.staffUpdate.errors.length !== 0)) {
notify({
@ -100,6 +105,7 @@ export const StaffDetails: React.FC<OrderListProps> = ({ id, params }) => {
navigate(staffMemberDetailsUrl(id));
}
};
return (
<TypedStaffMemberUpdateMutation onCompleted={handleStaffMemberUpdate}>
{(updateStaffMember, updateResult) => (
@ -124,7 +130,7 @@ export const StaffDetails: React.FC<OrderListProps> = ({ id, params }) => {
return (
<>
<WindowTitle
title={maybe(() => data.user.email)}
title={staffMember?.email || "..."}
/>
<StaffDetailsPage
canEditAvatar={isUserSameAsViewer}
@ -132,7 +138,7 @@ export const StaffDetails: React.FC<OrderListProps> = ({ id, params }) => {
canEditStatus={!isUserSameAsViewer}
canRemove={!isUserSameAsViewer}
disabled={loading}
onBack={() => navigate(staffListUrl())}
onBack={handleBack}
onChangePassword={() =>
navigate(
staffMemberDetailsUrl(id, {
@ -176,7 +182,7 @@ export const StaffDetails: React.FC<OrderListProps> = ({ id, params }) => {
)
}
permissions={maybe(() => shop.permissions)}
staffMember={maybe(() => data.user)}
staffMember={staffMember}
saveButtonBarState={updateResult.status}
/>
<ActionDialog

View file

@ -12,7 +12,8 @@ import WebhookDeleteDialog from "@saleor/webhooks/components/WebhookDeleteDialog
import { WebhookDelete } from "@saleor/webhooks/types/WebhookDelete";
import { WebhookUpdate } from "@saleor/webhooks/types/WebhookUpdate";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import { maybe } from "../../misc";
import NotFoundPage from "@saleor/components/NotFoundPage";
import { maybe, getStringOrPlaceholder } from "../../misc";
import WebhooksDetailsPage from "../components/WebhooksDetailsPage";
import { TypedWebhookDelete, TypedWebhookUpdate } from "../mutations";
import { TypedWebhooksDetailsQuery } from "../queries";
@ -48,7 +49,7 @@ export const WebhooksDetails: React.FC<WebhooksDetailsProps> = ({
>(navigate, params => webhookUrl(id, params), params);
const onWebhookDelete = (data: WebhookDelete) => {
if (data.webhookDelete.errors.length === 0) {
if (data.webhookDelete?.errors.length === 0) {
notify({
text: intl.formatMessage(commonMessages.savedChanges)
});
@ -57,14 +58,19 @@ export const WebhooksDetails: React.FC<WebhooksDetailsProps> = ({
};
const onWebhookUpdate = (data: WebhookUpdate) => {
if (data.webhookUpdate.webhookErrors.length === 0) {
const errors = data.webhookUpdate?.webhookErrors;
const webhook = data.webhookUpdate?.webhook;
if (errors.length === 0 && webhook) {
notify({
text: intl.formatMessage(commonMessages.savedChanges)
});
navigate(webhookUrl(data.webhookUpdate.webhook.id));
navigate(webhookUrl(webhook.id));
}
};
const handleOnBack = () => navigate(webhookListUrl());
return (
<TypedWebhookUpdate onCompleted={onWebhookUpdate}>
{(webhookUpdate, webhookUpdateOpts) => (
@ -79,28 +85,33 @@ export const WebhooksDetails: React.FC<WebhooksDetailsProps> = ({
}
});
const formErrors = maybe(
() => webhookUpdateOpts.data.webhookUpdate.webhookErrors,
[]
);
const webhook = webhookDetails?.data?.webhook;
const formErrors =
webhookUpdateOpts.data?.webhookUpdate.webhookErrors || [];
if (webhook === null) {
return <NotFoundPage onBack={handleOnBack} />;
}
return (
<>
<WindowTitle
title={maybe(() => webhookDetails.data.webhook.name)}
title={getStringOrPlaceholder(
webhookDetails?.data?.webhook?.name
)}
/>
<WebhooksDetailsPage
disabled={webhookDetails.loading}
errors={formErrors}
saveButtonBarState={webhookUpdateOpts.status}
webhook={maybe(() => webhookDetails.data.webhook)}
webhook={webhook}
fetchServiceAccounts={searchServiceAccount}
services={maybe(() =>
searchServiceAccountOpt.data.search.edges.map(
edge => edge.node
)
)}
onBack={() => navigate(webhookListUrl())}
onBack={handleOnBack}
onDelete={() => openModal("remove")}
onSubmit={data => {
webhookUpdate({
@ -122,10 +133,7 @@ export const WebhooksDetails: React.FC<WebhooksDetailsProps> = ({
/>
<WebhookDeleteDialog
confirmButtonState={webhookDeleteOpts.status}
name={maybe(
() => webhookDetails.data.webhook.name,
"..."
)}
name={getStringOrPlaceholder(webhook?.name)}
onClose={closeModal}
onConfirm={handleRemoveConfirm}
open={params.action === "remove"}