Explicitely return not found page
This commit is contained in:
parent
8ed641eee8
commit
fa8231992f
22 changed files with 337 additions and 268 deletions
|
@ -23,6 +23,7 @@ module.exports = api => {
|
||||||
|
|
||||||
const plugins = [
|
const plugins = [
|
||||||
"@babel/plugin-proposal-numeric-separator",
|
"@babel/plugin-proposal-numeric-separator",
|
||||||
|
"@babel/plugin-proposal-optional-chaining",
|
||||||
"@babel/plugin-proposal-class-properties",
|
"@babel/plugin-proposal-class-properties",
|
||||||
[
|
[
|
||||||
"@babel/plugin-proposal-decorators",
|
"@babel/plugin-proposal-decorators",
|
||||||
|
@ -49,6 +50,6 @@ module.exports = api => {
|
||||||
return {
|
return {
|
||||||
ignore,
|
ignore,
|
||||||
plugins,
|
plugins,
|
||||||
presets,
|
presets
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
35
package-lock.json
generated
35
package-lock.json
generated
|
@ -849,6 +849,24 @@
|
||||||
"@babel/plugin-syntax-optional-catch-binding": "^7.2.0"
|
"@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": {
|
"@babel/plugin-proposal-unicode-property-regex": {
|
||||||
"version": "7.7.0",
|
"version": "7.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.0.tgz",
|
"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/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": {
|
"@babel/plugin-syntax-top-level-await": {
|
||||||
"version": "7.7.0",
|
"version": "7.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.0.tgz",
|
||||||
|
|
|
@ -75,6 +75,7 @@
|
||||||
"@babel/plugin-proposal-decorators": "^7.4.4",
|
"@babel/plugin-proposal-decorators": "^7.4.4",
|
||||||
"@babel/plugin-proposal-numeric-separator": "^7.2.0",
|
"@babel/plugin-proposal-numeric-separator": "^7.2.0",
|
||||||
"@babel/plugin-proposal-object-rest-spread": "^7.5.4",
|
"@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-env": "^7.5.4",
|
||||||
"@babel/preset-react": "^7.7.4",
|
"@babel/preset-react": "^7.7.4",
|
||||||
"@babel/preset-typescript": "^7.7.4",
|
"@babel/preset-typescript": "^7.7.4",
|
||||||
|
|
|
@ -14,6 +14,7 @@ import usePaginator, {
|
||||||
} from "@saleor/hooks/usePaginator";
|
} from "@saleor/hooks/usePaginator";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
|
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||||
import { PAGINATE_BY } from "../../config";
|
import { PAGINATE_BY } from "../../config";
|
||||||
import { maybe } from "../../misc";
|
import { maybe } from "../../misc";
|
||||||
import { TypedProductBulkDeleteMutation } from "../../products/mutations";
|
import { TypedProductBulkDeleteMutation } from "../../products/mutations";
|
||||||
|
@ -67,10 +68,15 @@ export const CategoryDetails: React.FC<CategoryDetailsProps> = ({
|
||||||
const paginationState = createPaginationState(PAGINATE_BY, params);
|
const paginationState = createPaginationState(PAGINATE_BY, params);
|
||||||
const { data, loading, refetch } = useCategoryDetailsQuery({
|
const { data, loading, refetch } = useCategoryDetailsQuery({
|
||||||
displayLoader: true,
|
displayLoader: true,
|
||||||
require: ["category"],
|
|
||||||
variables: { ...paginationState, id }
|
variables: { ...paginationState, id }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const category = data?.category;
|
||||||
|
|
||||||
|
if (category === null) {
|
||||||
|
return <NotFoundPage onBack={() => navigate(categoryListUrl())} />;
|
||||||
|
}
|
||||||
|
|
||||||
const handleCategoryDelete = (data: CategoryDelete) => {
|
const handleCategoryDelete = (data: CategoryDelete) => {
|
||||||
if (data.categoryDelete.errors.length === 0) {
|
if (data.categoryDelete.errors.length === 0) {
|
||||||
notify({
|
notify({
|
||||||
|
|
|
@ -68,7 +68,6 @@ export const CategoryList: React.FC<CategoryListProps> = ({ params }) => {
|
||||||
);
|
);
|
||||||
const { data, loading, refetch } = useRootCategoriesQuery({
|
const { data, loading, refetch } = useRootCategoriesQuery({
|
||||||
displayLoader: true,
|
displayLoader: true,
|
||||||
require: ["categories"],
|
|
||||||
variables: queryVariables
|
variables: queryVariables
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import usePaginator, {
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import useProductSearch from "@saleor/searches/useProductSearch";
|
import useProductSearch from "@saleor/searches/useProductSearch";
|
||||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
|
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||||
import { getMutationState, maybe } from "../../misc";
|
import { getMutationState, maybe } from "../../misc";
|
||||||
import { productUrl } from "../../products/urls";
|
import { productUrl } from "../../products/urls";
|
||||||
import { CollectionInput } from "../../types/globalTypes";
|
import { CollectionInput } from "../../types/globalTypes";
|
||||||
|
@ -61,14 +62,19 @@ export const CollectionDetails: React.FC<CollectionDetailsProps> = ({
|
||||||
>(navigate, params => collectionUrl(id, params), params);
|
>(navigate, params => collectionUrl(id, params), params);
|
||||||
|
|
||||||
const paginationState = createPaginationState(PAGINATE_BY, params);
|
const paginationState = createPaginationState(PAGINATE_BY, params);
|
||||||
|
const handleBack = () => navigate(collectionListUrl());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TypedCollectionDetailsQuery
|
<TypedCollectionDetailsQuery
|
||||||
displayLoader
|
displayLoader
|
||||||
variables={{ id, ...paginationState }}
|
variables={{ id, ...paginationState }}
|
||||||
require={["collection"]}
|
|
||||||
>
|
>
|
||||||
{({ data, loading }) => {
|
{({ data, loading }) => {
|
||||||
|
const collection = data?.collection;
|
||||||
|
|
||||||
|
if (collection === null) {
|
||||||
|
return <NotFoundPage onBack={handleBack} />;
|
||||||
|
}
|
||||||
const handleCollectionUpdate = (data: CollectionUpdate) => {
|
const handleCollectionUpdate = (data: CollectionUpdate) => {
|
||||||
if (data.collectionUpdate.errors.length === 0) {
|
if (data.collectionUpdate.errors.length === 0) {
|
||||||
notify({
|
notify({
|
||||||
|
@ -196,7 +202,7 @@ export const CollectionDetails: React.FC<CollectionDetailsProps> = ({
|
||||||
<WindowTitle title={maybe(() => data.collection.name)} />
|
<WindowTitle title={maybe(() => data.collection.name)} />
|
||||||
<CollectionDetailsPage
|
<CollectionDetailsPage
|
||||||
onAdd={() => openModal("assign")}
|
onAdd={() => openModal("assign")}
|
||||||
onBack={() => navigate(collectionListUrl())}
|
onBack={handleBack}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
collection={maybe(() => data.collection)}
|
collection={maybe(() => data.collection)}
|
||||||
isFeatured={maybe(
|
isFeatured={maybe(
|
||||||
|
|
|
@ -29,7 +29,6 @@ import { maybe } from "@saleor/misc";
|
||||||
import { staffMemberDetailsUrl } from "@saleor/staff/urls";
|
import { staffMemberDetailsUrl } from "@saleor/staff/urls";
|
||||||
import Container from "../Container";
|
import Container from "../Container";
|
||||||
import ErrorPage from "../ErrorPage";
|
import ErrorPage from "../ErrorPage";
|
||||||
import NotFoundPage from "../NotFoundPage";
|
|
||||||
import AppActionContext from "./AppActionContext";
|
import AppActionContext from "./AppActionContext";
|
||||||
import AppHeaderContext from "./AppHeaderContext";
|
import AppHeaderContext from "./AppHeaderContext";
|
||||||
import { appLoaderHeight, drawerWidth, drawerWidthExpanded } from "./consts";
|
import { appLoaderHeight, drawerWidth, drawerWidthExpanded } from "./consts";
|
||||||
|
@ -507,15 +506,11 @@ const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
<main className={classes.view}>
|
<main className={classes.view}>
|
||||||
{appState.error ? (
|
{appState.error
|
||||||
appState.error === "not-found" ? (
|
? appState.error === "unhandled" && (
|
||||||
<NotFoundPage onBack={handleErrorBack} />
|
<ErrorPage onBack={handleErrorBack} />
|
||||||
) : (
|
)
|
||||||
<ErrorPage onBack={handleErrorBack} />
|
: children}
|
||||||
)
|
|
||||||
) : (
|
|
||||||
children
|
|
||||||
)}
|
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.appAction} ref={appActionAnchor} />
|
<div className={classes.appAction} ref={appActionAnchor} />
|
||||||
|
|
|
@ -21,7 +21,7 @@ const AppStateProvider: React.FC = ({ children }) => {
|
||||||
if (!!state.error) {
|
if (!!state.error) {
|
||||||
dispatch({
|
dispatch({
|
||||||
payload: {
|
payload: {
|
||||||
error: null
|
error: undefined
|
||||||
},
|
},
|
||||||
type: "displayError"
|
type: "displayError"
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export type AppError = "unhandled" | "not-found";
|
export type AppError = "unhandled";
|
||||||
|
|
||||||
interface IAppState {
|
interface IAppState {
|
||||||
error: AppError | null;
|
error: AppError | null;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { WindowTitle } from "@saleor/components/WindowTitle";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useNotifier from "@saleor/hooks/useNotifier";
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||||
import { maybe } from "../../misc";
|
import { maybe } from "../../misc";
|
||||||
import { orderListUrl, orderUrl } from "../../orders/urls";
|
import { orderListUrl, orderUrl } from "../../orders/urls";
|
||||||
import CustomerDetailsPage from "../components/CustomerDetailsPage/CustomerDetailsPage";
|
import CustomerDetailsPage from "../components/CustomerDetailsPage/CustomerDetailsPage";
|
||||||
|
@ -54,6 +55,9 @@ export const CustomerDetailsView: React.FC<CustomerDetailsViewProps> = ({
|
||||||
navigate(customerListUrl());
|
navigate(customerListUrl());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleBack = () => navigate(customerListUrl());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TypedRemoveCustomerMutation
|
<TypedRemoveCustomerMutation
|
||||||
variables={{ id }}
|
variables={{ id }}
|
||||||
|
@ -62,91 +66,97 @@ export const CustomerDetailsView: React.FC<CustomerDetailsViewProps> = ({
|
||||||
{(removeCustomer, removeCustomerOpts) => (
|
{(removeCustomer, removeCustomerOpts) => (
|
||||||
<TypedUpdateCustomerMutation onCompleted={handleCustomerUpdateSuccess}>
|
<TypedUpdateCustomerMutation onCompleted={handleCustomerUpdateSuccess}>
|
||||||
{(updateCustomer, updateCustomerOpts) => (
|
{(updateCustomer, updateCustomerOpts) => (
|
||||||
<TypedCustomerDetailsQuery
|
<TypedCustomerDetailsQuery displayLoader variables={{ id }}>
|
||||||
displayLoader
|
{customerDetails => {
|
||||||
variables={{ id }}
|
const user = customerDetails.data?.user;
|
||||||
require={["user"]}
|
|
||||||
>
|
if (user === null) {
|
||||||
{customerDetails => (
|
return <NotFoundPage onBack={handleBack} />;
|
||||||
<>
|
}
|
||||||
<WindowTitle
|
|
||||||
title={maybe(() => customerDetails.data.user.email)}
|
return (
|
||||||
/>
|
<>
|
||||||
<CustomerDetailsPage
|
<WindowTitle
|
||||||
customer={maybe(() => customerDetails.data.user)}
|
title={maybe(() => customerDetails.data.user.email)}
|
||||||
disabled={
|
/>
|
||||||
customerDetails.loading ||
|
<CustomerDetailsPage
|
||||||
updateCustomerOpts.loading ||
|
customer={maybe(() => customerDetails.data.user)}
|
||||||
removeCustomerOpts.loading
|
disabled={
|
||||||
}
|
customerDetails.loading ||
|
||||||
errors={maybe(
|
updateCustomerOpts.loading ||
|
||||||
() => updateCustomerOpts.data.customerUpdate.errors
|
removeCustomerOpts.loading
|
||||||
)}
|
}
|
||||||
saveButtonBar={updateCustomerOpts.status}
|
errors={maybe(
|
||||||
onAddressManageClick={() =>
|
() => updateCustomerOpts.data.customerUpdate.errors
|
||||||
navigate(customerAddressesUrl(id))
|
)}
|
||||||
}
|
saveButtonBar={updateCustomerOpts.status}
|
||||||
onBack={() => navigate(customerListUrl())}
|
onAddressManageClick={() =>
|
||||||
onRowClick={id => navigate(orderUrl(id))}
|
navigate(customerAddressesUrl(id))
|
||||||
onSubmit={formData =>
|
}
|
||||||
updateCustomer({
|
onBack={handleBack}
|
||||||
variables: {
|
onRowClick={id => navigate(orderUrl(id))}
|
||||||
id,
|
onSubmit={formData =>
|
||||||
input: {
|
updateCustomer({
|
||||||
email: formData.email,
|
variables: {
|
||||||
firstName: formData.firstName,
|
id,
|
||||||
isActive: formData.isActive,
|
input: {
|
||||||
lastName: formData.lastName,
|
email: formData.email,
|
||||||
note: formData.note
|
firstName: formData.firstName,
|
||||||
|
isActive: formData.isActive,
|
||||||
|
lastName: formData.lastName,
|
||||||
|
note: formData.note
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
onDelete={() =>
|
|
||||||
navigate(
|
|
||||||
customerUrl(id, {
|
|
||||||
action: "remove"
|
|
||||||
})
|
})
|
||||||
)
|
}
|
||||||
}
|
onDelete={() =>
|
||||||
onViewAllOrdersClick={() =>
|
navigate(
|
||||||
navigate(
|
customerUrl(id, {
|
||||||
orderListUrl({
|
action: "remove"
|
||||||
customer: maybe(() => customerDetails.data.user.email)
|
})
|
||||||
})
|
)
|
||||||
)
|
}
|
||||||
}
|
onViewAllOrdersClick={() =>
|
||||||
/>
|
navigate(
|
||||||
<ActionDialog
|
orderListUrl({
|
||||||
confirmButtonState={removeCustomerOpts.status}
|
customer: maybe(
|
||||||
onClose={() => navigate(customerUrl(id), true)}
|
() => customerDetails.data.user.email
|
||||||
onConfirm={() => removeCustomer()}
|
)
|
||||||
title={intl.formatMessage({
|
})
|
||||||
defaultMessage: "Delete Customer",
|
)
|
||||||
description: "dialog header"
|
}
|
||||||
})}
|
/>
|
||||||
variant="delete"
|
<ActionDialog
|
||||||
open={params.action === "remove"}
|
confirmButtonState={removeCustomerOpts.status}
|
||||||
>
|
onClose={() => navigate(customerUrl(id), true)}
|
||||||
<DialogContentText>
|
onConfirm={() => removeCustomer()}
|
||||||
<FormattedMessage
|
title={intl.formatMessage({
|
||||||
defaultMessage="Are you sure you want to delete {email}?"
|
defaultMessage: "Delete Customer",
|
||||||
description="delete customer, dialog content"
|
description: "dialog header"
|
||||||
values={{
|
})}
|
||||||
email: (
|
variant="delete"
|
||||||
<strong>
|
open={params.action === "remove"}
|
||||||
{maybe(
|
>
|
||||||
() => customerDetails.data.user.email,
|
<DialogContentText>
|
||||||
"..."
|
<FormattedMessage
|
||||||
)}
|
defaultMessage="Are you sure you want to delete {email}?"
|
||||||
</strong>
|
description="delete customer, dialog content"
|
||||||
)
|
values={{
|
||||||
}}
|
email: (
|
||||||
/>
|
<strong>
|
||||||
</DialogContentText>
|
{maybe(
|
||||||
</ActionDialog>
|
() => customerDetails.data.user.email,
|
||||||
</>
|
"..."
|
||||||
)}
|
)}
|
||||||
|
</strong>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</DialogContentText>
|
||||||
|
</ActionDialog>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}}
|
||||||
</TypedCustomerDetailsQuery>
|
</TypedCustomerDetailsQuery>
|
||||||
)}
|
)}
|
||||||
</TypedUpdateCustomerMutation>
|
</TypedUpdateCustomerMutation>
|
||||||
|
|
|
@ -18,14 +18,13 @@ export interface LoadMore<TData, TVariables> {
|
||||||
|
|
||||||
export type UseQueryResult<TData, TVariables> = QueryResult<TData, TVariables> &
|
export type UseQueryResult<TData, TVariables> = QueryResult<TData, TVariables> &
|
||||||
LoadMore<TData, TVariables>;
|
LoadMore<TData, TVariables>;
|
||||||
type UseQueryOpts<TData, TVariables> = Partial<{
|
type UseQueryOpts<TVariables> = Partial<{
|
||||||
displayLoader: boolean;
|
displayLoader: boolean;
|
||||||
require: Array<keyof TData>;
|
|
||||||
skip: boolean;
|
skip: boolean;
|
||||||
variables: TVariables;
|
variables: TVariables;
|
||||||
}>;
|
}>;
|
||||||
type UseQueryHook<TData, TVariables> = (
|
type UseQueryHook<TData, TVariables> = (
|
||||||
opts: UseQueryOpts<TData, TVariables>
|
opts: UseQueryOpts<TVariables>
|
||||||
) => UseQueryResult<TData, TVariables>;
|
) => UseQueryResult<TData, TVariables>;
|
||||||
|
|
||||||
function makeQuery<TData, TVariables>(
|
function makeQuery<TData, TVariables>(
|
||||||
|
@ -33,10 +32,9 @@ function makeQuery<TData, TVariables>(
|
||||||
): UseQueryHook<TData, TVariables> {
|
): UseQueryHook<TData, TVariables> {
|
||||||
function useQuery({
|
function useQuery({
|
||||||
displayLoader,
|
displayLoader,
|
||||||
require,
|
|
||||||
skip,
|
skip,
|
||||||
variables
|
variables
|
||||||
}: UseQueryOpts<TData, TVariables>): UseQueryResult<TData, TVariables> {
|
}: UseQueryOpts<TVariables>): UseQueryResult<TData, TVariables> {
|
||||||
const notify = useNotifier();
|
const notify = useNotifier();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [, dispatchAppState] = useAppState();
|
const [, dispatchAppState] = useAppState();
|
||||||
|
@ -89,20 +87,6 @@ function makeQuery<TData, TVariables>(
|
||||||
variables: { ...variables, ...extraVariables }
|
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 {
|
return {
|
||||||
...queryData,
|
...queryData,
|
||||||
loadMore
|
loadMore
|
||||||
|
|
|
@ -380,3 +380,7 @@ export function transformFormToAddress<T>(
|
||||||
country: findInEnum(address.country, CountryCode)
|
country: findInEnum(address.country, CountryCode)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getStringOrPlaceholder(s: string | undefined): string {
|
||||||
|
return s || "...";
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useUser from "@saleor/hooks/useUser";
|
import useUser from "@saleor/hooks/useUser";
|
||||||
import useCustomerSearch from "@saleor/searches/useCustomerSearch";
|
import useCustomerSearch from "@saleor/searches/useCustomerSearch";
|
||||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
|
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||||
import { customerUrl } from "../../../customers/urls";
|
import { customerUrl } from "../../../customers/urls";
|
||||||
import { getMutationState, maybe, transformAddressToForm } from "../../../misc";
|
import { getMutationState, maybe, transformAddressToForm } from "../../../misc";
|
||||||
import { productUrl } from "../../../products/urls";
|
import { productUrl } from "../../../products/urls";
|
||||||
|
@ -90,14 +91,17 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
|
||||||
variables: DEFAULT_INITIAL_SEARCH_DATA
|
variables: DEFAULT_INITIAL_SEARCH_DATA
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleBack = () => navigate(orderListUrl());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TypedOrderDetailsQuery
|
<TypedOrderDetailsQuery displayLoader variables={{ id }}>
|
||||||
displayLoader
|
|
||||||
variables={{ id }}
|
|
||||||
require={["order"]}
|
|
||||||
>
|
|
||||||
{({ data, loading }) => {
|
{({ data, loading }) => {
|
||||||
const order = maybe(() => data.order);
|
const order = data?.order;
|
||||||
|
|
||||||
|
if (order === null) {
|
||||||
|
return <NotFoundPage onBack={handleBack} />;
|
||||||
|
}
|
||||||
|
|
||||||
const [openModal, closeModal] = createDialogActionHandlers<
|
const [openModal, closeModal] = createDialogActionHandlers<
|
||||||
OrderUrlDialog,
|
OrderUrlDialog,
|
||||||
OrderUrlQueryParams
|
OrderUrlQueryParams
|
||||||
|
@ -166,7 +170,7 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
|
||||||
order: id
|
order: id
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
onBack={() => navigate(orderListUrl())}
|
onBack={handleBack}
|
||||||
order={order}
|
order={order}
|
||||||
shippingMethods={maybe(
|
shippingMethods={maybe(
|
||||||
() => data.order.availableShippingMethods,
|
() => data.order.availableShippingMethods,
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { maybe } from "@saleor/misc";
|
||||||
import AssignAttributeDialog from "@saleor/productTypes/components/AssignAttributeDialog";
|
import AssignAttributeDialog from "@saleor/productTypes/components/AssignAttributeDialog";
|
||||||
import { ReorderEvent } from "@saleor/types";
|
import { ReorderEvent } from "@saleor/types";
|
||||||
import { AttributeTypeEnum } from "@saleor/types/globalTypes";
|
import { AttributeTypeEnum } from "@saleor/types/globalTypes";
|
||||||
|
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||||
import ProductTypeAttributeUnassignDialog from "../../components/ProductTypeAttributeUnassignDialog";
|
import ProductTypeAttributeUnassignDialog from "../../components/ProductTypeAttributeUnassignDialog";
|
||||||
import ProductTypeBulkAttributeUnassignDialog from "../../components/ProductTypeBulkAttributeUnassignDialog";
|
import ProductTypeBulkAttributeUnassignDialog from "../../components/ProductTypeBulkAttributeUnassignDialog";
|
||||||
import ProductTypeDeleteDialog from "../../components/ProductTypeDeleteDialog";
|
import ProductTypeDeleteDialog from "../../components/ProductTypeDeleteDialog";
|
||||||
|
@ -54,15 +55,19 @@ export const ProductTypeUpdate: React.FC<ProductTypeUpdateProps> = ({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleBack = () => navigate(productTypeListUrl());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ProductTypeUpdateErrors>
|
<ProductTypeUpdateErrors>
|
||||||
{({ errors, set: setErrors }) => (
|
{({ errors, set: setErrors }) => (
|
||||||
<TypedProductTypeDetailsQuery
|
<TypedProductTypeDetailsQuery displayLoader variables={{ id }}>
|
||||||
displayLoader
|
|
||||||
variables={{ id }}
|
|
||||||
require={["productType"]}
|
|
||||||
>
|
|
||||||
{({ data, loading: dataLoading }) => {
|
{({ data, loading: dataLoading }) => {
|
||||||
|
const productType = data?.productType;
|
||||||
|
|
||||||
|
if (productType === null) {
|
||||||
|
return <NotFoundPage onBack={handleBack} />;
|
||||||
|
}
|
||||||
|
|
||||||
const closeModal = () => navigate(productTypeUrl(id), true);
|
const closeModal = () => navigate(productTypeUrl(id), true);
|
||||||
|
|
||||||
const handleAttributeAssignSuccess = (data: AssignAttribute) => {
|
const handleAttributeAssignSuccess = (data: AssignAttribute) => {
|
||||||
|
@ -242,7 +247,7 @@ export const ProductTypeUpdate: React.FC<ProductTypeUpdateProps> = ({
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
onBack={() => navigate(productTypeListUrl())}
|
onBack={handleBack}
|
||||||
onDelete={() =>
|
onDelete={() =>
|
||||||
navigate(
|
navigate(
|
||||||
productTypeUrl(id, {
|
productTypeUrl(id, {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { FormattedMessage, useIntl } from "react-intl";
|
||||||
import ActionDialog from "@saleor/components/ActionDialog";
|
import ActionDialog from "@saleor/components/ActionDialog";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useNotifier from "@saleor/hooks/useNotifier";
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
|
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||||
import { maybe } from "../../misc";
|
import { maybe } from "../../misc";
|
||||||
import ProductImagePage from "../components/ProductImagePage";
|
import ProductImagePage from "../components/ProductImagePage";
|
||||||
import {
|
import {
|
||||||
|
@ -16,7 +17,8 @@ import { ProductImageUpdate } from "../types/ProductImageUpdate";
|
||||||
import {
|
import {
|
||||||
productImageUrl,
|
productImageUrl,
|
||||||
ProductImageUrlQueryParams,
|
ProductImageUrlQueryParams,
|
||||||
productUrl
|
productUrl,
|
||||||
|
productListUrl
|
||||||
} from "../urls";
|
} from "../urls";
|
||||||
|
|
||||||
interface ProductImageProps {
|
interface ProductImageProps {
|
||||||
|
@ -47,70 +49,77 @@ export const ProductImage: React.FC<ProductImageProps> = ({
|
||||||
imageId,
|
imageId,
|
||||||
productId
|
productId
|
||||||
}}
|
}}
|
||||||
require={["product"]}
|
|
||||||
>
|
>
|
||||||
{({ data, loading }) => (
|
{({ data, loading }) => {
|
||||||
<TypedProductImageUpdateMutation onCompleted={handleUpdateSuccess}>
|
const product = data?.product;
|
||||||
{(updateImage, updateResult) => (
|
|
||||||
<TypedProductImageDeleteMutation onCompleted={handleBack}>
|
|
||||||
{(deleteImage, deleteResult) => {
|
|
||||||
const handleDelete = () =>
|
|
||||||
deleteImage({ variables: { id: imageId } });
|
|
||||||
const handleImageClick = (id: string) => () =>
|
|
||||||
navigate(productImageUrl(productId, id));
|
|
||||||
const handleUpdate = (formData: { description: string }) => {
|
|
||||||
updateImage({
|
|
||||||
variables: {
|
|
||||||
alt: formData.description,
|
|
||||||
id: imageId
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
const image = data && data.product && data.product.mainImage;
|
|
||||||
|
|
||||||
return (
|
if (product === null) {
|
||||||
<>
|
return <NotFoundPage onBack={() => navigate(productListUrl())} />;
|
||||||
<ProductImagePage
|
}
|
||||||
disabled={loading}
|
|
||||||
product={maybe(() => data.product.name)}
|
return (
|
||||||
image={image || null}
|
<TypedProductImageUpdateMutation onCompleted={handleUpdateSuccess}>
|
||||||
images={maybe(() => data.product.images)}
|
{(updateImage, updateResult) => (
|
||||||
onBack={handleBack}
|
<TypedProductImageDeleteMutation onCompleted={handleBack}>
|
||||||
onDelete={() =>
|
{(deleteImage, deleteResult) => {
|
||||||
navigate(
|
const handleDelete = () =>
|
||||||
productImageUrl(productId, imageId, {
|
deleteImage({ variables: { id: imageId } });
|
||||||
action: "remove"
|
const handleImageClick = (id: string) => () =>
|
||||||
})
|
navigate(productImageUrl(productId, id));
|
||||||
)
|
const handleUpdate = (formData: { description: string }) => {
|
||||||
|
updateImage({
|
||||||
|
variables: {
|
||||||
|
alt: formData.description,
|
||||||
|
id: imageId
|
||||||
}
|
}
|
||||||
onRowClick={handleImageClick}
|
});
|
||||||
onSubmit={handleUpdate}
|
};
|
||||||
saveButtonBarState={updateResult.status}
|
const image = data && data.product && data.product.mainImage;
|
||||||
/>
|
|
||||||
<ActionDialog
|
return (
|
||||||
onClose={() =>
|
<>
|
||||||
navigate(productImageUrl(productId, imageId), true)
|
<ProductImagePage
|
||||||
}
|
disabled={loading}
|
||||||
onConfirm={handleDelete}
|
product={maybe(() => data.product.name)}
|
||||||
open={params.action === "remove"}
|
image={image || null}
|
||||||
title={intl.formatMessage({
|
images={maybe(() => data.product.images)}
|
||||||
defaultMessage: "Delete Image",
|
onBack={handleBack}
|
||||||
description: "dialog header"
|
onDelete={() =>
|
||||||
})}
|
navigate(
|
||||||
variant="delete"
|
productImageUrl(productId, imageId, {
|
||||||
confirmButtonState={deleteResult.status}
|
action: "remove"
|
||||||
>
|
})
|
||||||
<DialogContentText>
|
)
|
||||||
<FormattedMessage defaultMessage="Are you sure you want to delete this image?" />
|
}
|
||||||
</DialogContentText>
|
onRowClick={handleImageClick}
|
||||||
</ActionDialog>
|
onSubmit={handleUpdate}
|
||||||
</>
|
saveButtonBarState={updateResult.status}
|
||||||
);
|
/>
|
||||||
}}
|
<ActionDialog
|
||||||
</TypedProductImageDeleteMutation>
|
onClose={() =>
|
||||||
)}
|
navigate(productImageUrl(productId, imageId), true)
|
||||||
</TypedProductImageUpdateMutation>
|
}
|
||||||
)}
|
onConfirm={handleDelete}
|
||||||
|
open={params.action === "remove"}
|
||||||
|
title={intl.formatMessage({
|
||||||
|
defaultMessage: "Delete Image",
|
||||||
|
description: "dialog header"
|
||||||
|
})}
|
||||||
|
variant="delete"
|
||||||
|
confirmButtonState={deleteResult.status}
|
||||||
|
>
|
||||||
|
<DialogContentText>
|
||||||
|
<FormattedMessage defaultMessage="Are you sure you want to delete this image?" />
|
||||||
|
</DialogContentText>
|
||||||
|
</ActionDialog>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</TypedProductImageDeleteMutation>
|
||||||
|
)}
|
||||||
|
</TypedProductImageUpdateMutation>
|
||||||
|
);
|
||||||
|
}}
|
||||||
</TypedProductImageQuery>
|
</TypedProductImageQuery>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { ProductVariantBulkCreate } from "@saleor/products/types/ProductVariantB
|
||||||
import useCategorySearch from "@saleor/searches/useCategorySearch";
|
import useCategorySearch from "@saleor/searches/useCategorySearch";
|
||||||
import useCollectionSearch from "@saleor/searches/useCollectionSearch";
|
import useCollectionSearch from "@saleor/searches/useCollectionSearch";
|
||||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
|
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||||
import { getMutationState, maybe } from "../../../misc";
|
import { getMutationState, maybe } from "../../../misc";
|
||||||
import ProductUpdatePage from "../../components/ProductUpdatePage";
|
import ProductUpdatePage from "../../components/ProductUpdatePage";
|
||||||
import ProductUpdateOperations from "../../containers/ProductUpdateOperations";
|
import ProductUpdateOperations from "../../containers/ProductUpdateOperations";
|
||||||
|
@ -76,13 +77,17 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
|
||||||
ProductUrlQueryParams
|
ProductUrlQueryParams
|
||||||
>(navigate, params => productUrl(id, params), params);
|
>(navigate, params => productUrl(id, params), params);
|
||||||
|
|
||||||
|
const handleBack = () => navigate(productListUrl());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TypedProductDetailsQuery
|
<TypedProductDetailsQuery displayLoader variables={{ id }}>
|
||||||
displayLoader
|
|
||||||
require={["product"]}
|
|
||||||
variables={{ id }}
|
|
||||||
>
|
|
||||||
{({ data, loading, refetch }) => {
|
{({ data, loading, refetch }) => {
|
||||||
|
const product = data?.product;
|
||||||
|
|
||||||
|
if (product === null) {
|
||||||
|
return <NotFoundPage onBack={handleBack} />;
|
||||||
|
}
|
||||||
|
|
||||||
const handleDelete = () => {
|
const handleDelete = () => {
|
||||||
notify({
|
notify({
|
||||||
text: intl.formatMessage({
|
text: intl.formatMessage({
|
||||||
|
@ -142,7 +147,6 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const product = data ? data.product : undefined;
|
|
||||||
return (
|
return (
|
||||||
<ProductUpdateOperations
|
<ProductUpdateOperations
|
||||||
product={product}
|
product={product}
|
||||||
|
@ -233,9 +237,7 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
|
||||||
placeholderImage={placeholderImg}
|
placeholderImage={placeholderImg}
|
||||||
product={product}
|
product={product}
|
||||||
variants={maybe(() => product.variants)}
|
variants={maybe(() => product.variants)}
|
||||||
onBack={() => {
|
onBack={handleBack}
|
||||||
navigate(productListUrl());
|
|
||||||
}}
|
|
||||||
onDelete={() => openModal("remove")}
|
onDelete={() => openModal("remove")}
|
||||||
onProductShow={() => {
|
onProductShow={() => {
|
||||||
if (product) {
|
if (product) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { WindowTitle } from "@saleor/components/WindowTitle";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useNotifier from "@saleor/hooks/useNotifier";
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||||
import { decimal, maybe } from "../../misc";
|
import { decimal, maybe } from "../../misc";
|
||||||
import ProductVariantDeleteDialog from "../components/ProductVariantDeleteDialog";
|
import ProductVariantDeleteDialog from "../components/ProductVariantDeleteDialog";
|
||||||
import ProductVariantPage, {
|
import ProductVariantPage, {
|
||||||
|
@ -13,7 +14,10 @@ import ProductVariantPage, {
|
||||||
} from "../components/ProductVariantPage";
|
} from "../components/ProductVariantPage";
|
||||||
import ProductVariantOperations from "../containers/ProductVariantOperations";
|
import ProductVariantOperations from "../containers/ProductVariantOperations";
|
||||||
import { TypedProductVariantQuery } from "../queries";
|
import { TypedProductVariantQuery } from "../queries";
|
||||||
import { VariantUpdate } from "../types/VariantUpdate";
|
import {
|
||||||
|
VariantUpdate,
|
||||||
|
VariantUpdate_productVariantUpdate_productErrors
|
||||||
|
} from "../types/VariantUpdate";
|
||||||
import {
|
import {
|
||||||
productUrl,
|
productUrl,
|
||||||
productVariantAddUrl,
|
productVariantAddUrl,
|
||||||
|
@ -35,20 +39,24 @@ export const ProductVariant: React.FC<ProductUpdateProps> = ({
|
||||||
const navigate = useNavigator();
|
const navigate = useNavigator();
|
||||||
const notify = useNotifier();
|
const notify = useNotifier();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [errors, setErrors] = useState([]);
|
const [errors, setErrors] = useState<
|
||||||
|
VariantUpdate_productVariantUpdate_productErrors[]
|
||||||
|
>([]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setErrors([]);
|
setErrors([]);
|
||||||
}, [variantId]);
|
}, [variantId]);
|
||||||
|
|
||||||
|
const handleBack = () => navigate(productUrl(productId));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TypedProductVariantQuery
|
<TypedProductVariantQuery displayLoader variables={{ id: variantId }}>
|
||||||
displayLoader
|
|
||||||
variables={{ id: variantId }}
|
|
||||||
require={["productVariant"]}
|
|
||||||
>
|
|
||||||
{({ data, loading }) => {
|
{({ data, loading }) => {
|
||||||
const variant = data ? data.productVariant : undefined;
|
const variant = data?.productVariant;
|
||||||
const handleBack = () => navigate(productUrl(productId));
|
|
||||||
|
if (variant === null) {
|
||||||
|
return <NotFoundPage onBack={handleBack} />;
|
||||||
|
}
|
||||||
|
|
||||||
const handleDelete = () => {
|
const handleDelete = () => {
|
||||||
notify({
|
notify({
|
||||||
text: intl.formatMessage({
|
text: intl.formatMessage({
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { WindowTitle } from "@saleor/components/WindowTitle";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useNotifier from "@saleor/hooks/useNotifier";
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
import useShop from "@saleor/hooks/useShop";
|
import useShop from "@saleor/hooks/useShop";
|
||||||
|
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||||
import { decimal, maybe } from "../../misc";
|
import { decimal, maybe } from "../../misc";
|
||||||
import ProductVariantCreatePage, {
|
import ProductVariantCreatePage, {
|
||||||
ProductVariantCreatePageSubmitData
|
ProductVariantCreatePageSubmitData
|
||||||
|
@ -12,7 +13,7 @@ import ProductVariantCreatePage, {
|
||||||
import { TypedVariantCreateMutation } from "../mutations";
|
import { TypedVariantCreateMutation } from "../mutations";
|
||||||
import { TypedProductVariantCreateQuery } from "../queries";
|
import { TypedProductVariantCreateQuery } from "../queries";
|
||||||
import { VariantCreate } from "../types/VariantCreate";
|
import { VariantCreate } from "../types/VariantCreate";
|
||||||
import { productUrl, productVariantEditUrl } from "../urls";
|
import { productUrl, productVariantEditUrl, productListUrl } from "../urls";
|
||||||
|
|
||||||
interface ProductUpdateProps {
|
interface ProductUpdateProps {
|
||||||
productId: string;
|
productId: string;
|
||||||
|
@ -25,12 +26,14 @@ export const ProductVariant: React.FC<ProductUpdateProps> = ({ productId }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TypedProductVariantCreateQuery
|
<TypedProductVariantCreateQuery displayLoader variables={{ id: productId }}>
|
||||||
displayLoader
|
|
||||||
variables={{ id: productId }}
|
|
||||||
require={["product"]}
|
|
||||||
>
|
|
||||||
{({ data, loading: productLoading }) => {
|
{({ data, loading: productLoading }) => {
|
||||||
|
const product = data?.product;
|
||||||
|
|
||||||
|
if (product === null) {
|
||||||
|
return <NotFoundPage onBack={() => navigate(productListUrl())} />;
|
||||||
|
}
|
||||||
|
|
||||||
const handleCreateSuccess = (data: VariantCreate) => {
|
const handleCreateSuccess = (data: VariantCreate) => {
|
||||||
if (data.productVariantCreate.productErrors.length === 0) {
|
if (data.productVariantCreate.productErrors.length === 0) {
|
||||||
notify({
|
notify({
|
||||||
|
|
|
@ -28,7 +28,6 @@ export interface TypedQueryInnerProps<TData, TVariables> {
|
||||||
displayLoader?: boolean;
|
displayLoader?: boolean;
|
||||||
skip?: boolean;
|
skip?: boolean;
|
||||||
variables?: TVariables;
|
variables?: TVariables;
|
||||||
require?: Array<keyof TData>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface QueryProgressProps {
|
interface QueryProgressProps {
|
||||||
|
@ -65,7 +64,7 @@ class QueryProgress extends React.Component<QueryProgressProps, {}> {
|
||||||
export function TypedQuery<TData, TVariables>(
|
export function TypedQuery<TData, TVariables>(
|
||||||
query: DocumentNode
|
query: DocumentNode
|
||||||
): React.FC<TypedQueryInnerProps<TData, TVariables>> {
|
): React.FC<TypedQueryInnerProps<TData, TVariables>> {
|
||||||
return ({ children, displayLoader, skip, variables, require }) => {
|
return ({ children, displayLoader, skip, variables }) => {
|
||||||
const pushMessage = useNotifier();
|
const pushMessage = useNotifier();
|
||||||
const [, dispatchAppState] = useAppState();
|
const [, dispatchAppState] = useAppState();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
@ -112,23 +111,6 @@ export function TypedQuery<TData, TVariables>(
|
||||||
variables: { ...variables, ...extraVariables }
|
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) {
|
if (displayLoader) {
|
||||||
return (
|
return (
|
||||||
<QueryProgress
|
<QueryProgress
|
||||||
|
|
|
@ -22,6 +22,7 @@ import { ServiceTokenCreate } from "@saleor/services/types/ServiceTokenCreate";
|
||||||
import { ServiceTokenDelete } from "@saleor/services/types/ServiceTokenDelete";
|
import { ServiceTokenDelete } from "@saleor/services/types/ServiceTokenDelete";
|
||||||
import { ServiceUpdate } from "@saleor/services/types/ServiceUpdate";
|
import { ServiceUpdate } from "@saleor/services/types/ServiceUpdate";
|
||||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
|
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||||
import ServiceDetailsPage, {
|
import ServiceDetailsPage, {
|
||||||
ServiceDetailsPageFormData
|
ServiceDetailsPageFormData
|
||||||
} from "../../components/ServiceDetailsPage";
|
} from "../../components/ServiceDetailsPage";
|
||||||
|
@ -77,12 +78,14 @@ export const ServiceDetails: React.FC<OrderListProps> = ({
|
||||||
const handleBack = () => navigate(serviceListUrl());
|
const handleBack = () => navigate(serviceListUrl());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ServiceDetailsQuery
|
<ServiceDetailsQuery displayLoader variables={{ id }}>
|
||||||
displayLoader
|
|
||||||
variables={{ id }}
|
|
||||||
require={["serviceAccount"]}
|
|
||||||
>
|
|
||||||
{({ data, loading, refetch }) => {
|
{({ data, loading, refetch }) => {
|
||||||
|
const service = data?.serviceAccount;
|
||||||
|
|
||||||
|
if (service === null) {
|
||||||
|
return <NotFoundPage onBack={handleBack} />;
|
||||||
|
}
|
||||||
|
|
||||||
const onTokenCreate = (data: ServiceTokenCreate) => {
|
const onTokenCreate = (data: ServiceTokenCreate) => {
|
||||||
if (maybe(() => data.serviceAccountTokenCreate.errors.length === 0)) {
|
if (maybe(() => data.serviceAccountTokenCreate.errors.length === 0)) {
|
||||||
refetch();
|
refetch();
|
||||||
|
@ -151,9 +154,7 @@ export const ServiceDetails: React.FC<OrderListProps> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<WindowTitle
|
<WindowTitle title={service?.name || "..."} />
|
||||||
title={maybe(() => data.serviceAccount.name)}
|
|
||||||
/>
|
|
||||||
<ServiceDetailsPage
|
<ServiceDetailsPage
|
||||||
apiUri={API_URI}
|
apiUri={API_URI}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
import useShop from "@saleor/hooks/useShop";
|
import useShop from "@saleor/hooks/useShop";
|
||||||
import useUser from "@saleor/hooks/useUser";
|
import useUser from "@saleor/hooks/useUser";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||||
import { maybe } from "../../misc";
|
import { maybe } from "../../misc";
|
||||||
import StaffDetailsPage from "../components/StaffDetailsPage/StaffDetailsPage";
|
import StaffDetailsPage from "../components/StaffDetailsPage/StaffDetailsPage";
|
||||||
import {
|
import {
|
||||||
|
@ -63,13 +64,17 @@ export const StaffDetails: React.FC<OrderListProps> = ({ id, params }) => {
|
||||||
onCompleted: handleChangePassword
|
onCompleted: handleChangePassword
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleBack = () => navigate(staffListUrl());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TypedStaffMemberDetailsQuery
|
<TypedStaffMemberDetailsQuery displayLoader variables={{ id }}>
|
||||||
displayLoader
|
|
||||||
variables={{ id }}
|
|
||||||
require={["user"]}
|
|
||||||
>
|
|
||||||
{({ data, loading }) => {
|
{({ data, loading }) => {
|
||||||
|
const staffMember = data?.user;
|
||||||
|
|
||||||
|
if (staffMember === null) {
|
||||||
|
return <NotFoundPage onBack={handleBack} />;
|
||||||
|
}
|
||||||
|
|
||||||
const handleStaffMemberUpdate = (data: StaffMemberUpdate) => {
|
const handleStaffMemberUpdate = (data: StaffMemberUpdate) => {
|
||||||
if (!maybe(() => data.staffUpdate.errors.length !== 0)) {
|
if (!maybe(() => data.staffUpdate.errors.length !== 0)) {
|
||||||
notify({
|
notify({
|
||||||
|
@ -100,6 +105,7 @@ export const StaffDetails: React.FC<OrderListProps> = ({ id, params }) => {
|
||||||
navigate(staffMemberDetailsUrl(id));
|
navigate(staffMemberDetailsUrl(id));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TypedStaffMemberUpdateMutation onCompleted={handleStaffMemberUpdate}>
|
<TypedStaffMemberUpdateMutation onCompleted={handleStaffMemberUpdate}>
|
||||||
{(updateStaffMember, updateResult) => (
|
{(updateStaffMember, updateResult) => (
|
||||||
|
@ -124,7 +130,7 @@ export const StaffDetails: React.FC<OrderListProps> = ({ id, params }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<WindowTitle
|
<WindowTitle
|
||||||
title={maybe(() => data.user.email)}
|
title={staffMember?.email || "..."}
|
||||||
/>
|
/>
|
||||||
<StaffDetailsPage
|
<StaffDetailsPage
|
||||||
canEditAvatar={isUserSameAsViewer}
|
canEditAvatar={isUserSameAsViewer}
|
||||||
|
@ -132,7 +138,7 @@ export const StaffDetails: React.FC<OrderListProps> = ({ id, params }) => {
|
||||||
canEditStatus={!isUserSameAsViewer}
|
canEditStatus={!isUserSameAsViewer}
|
||||||
canRemove={!isUserSameAsViewer}
|
canRemove={!isUserSameAsViewer}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
onBack={() => navigate(staffListUrl())}
|
onBack={handleBack}
|
||||||
onChangePassword={() =>
|
onChangePassword={() =>
|
||||||
navigate(
|
navigate(
|
||||||
staffMemberDetailsUrl(id, {
|
staffMemberDetailsUrl(id, {
|
||||||
|
@ -176,7 +182,7 @@ export const StaffDetails: React.FC<OrderListProps> = ({ id, params }) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
permissions={maybe(() => shop.permissions)}
|
permissions={maybe(() => shop.permissions)}
|
||||||
staffMember={maybe(() => data.user)}
|
staffMember={staffMember}
|
||||||
saveButtonBarState={updateResult.status}
|
saveButtonBarState={updateResult.status}
|
||||||
/>
|
/>
|
||||||
<ActionDialog
|
<ActionDialog
|
||||||
|
|
|
@ -12,7 +12,8 @@ import WebhookDeleteDialog from "@saleor/webhooks/components/WebhookDeleteDialog
|
||||||
import { WebhookDelete } from "@saleor/webhooks/types/WebhookDelete";
|
import { WebhookDelete } from "@saleor/webhooks/types/WebhookDelete";
|
||||||
import { WebhookUpdate } from "@saleor/webhooks/types/WebhookUpdate";
|
import { WebhookUpdate } from "@saleor/webhooks/types/WebhookUpdate";
|
||||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
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 WebhooksDetailsPage from "../components/WebhooksDetailsPage";
|
||||||
import { TypedWebhookDelete, TypedWebhookUpdate } from "../mutations";
|
import { TypedWebhookDelete, TypedWebhookUpdate } from "../mutations";
|
||||||
import { TypedWebhooksDetailsQuery } from "../queries";
|
import { TypedWebhooksDetailsQuery } from "../queries";
|
||||||
|
@ -48,7 +49,7 @@ export const WebhooksDetails: React.FC<WebhooksDetailsProps> = ({
|
||||||
>(navigate, params => webhookUrl(id, params), params);
|
>(navigate, params => webhookUrl(id, params), params);
|
||||||
|
|
||||||
const onWebhookDelete = (data: WebhookDelete) => {
|
const onWebhookDelete = (data: WebhookDelete) => {
|
||||||
if (data.webhookDelete.errors.length === 0) {
|
if (data.webhookDelete?.errors.length === 0) {
|
||||||
notify({
|
notify({
|
||||||
text: intl.formatMessage(commonMessages.savedChanges)
|
text: intl.formatMessage(commonMessages.savedChanges)
|
||||||
});
|
});
|
||||||
|
@ -57,14 +58,19 @@ export const WebhooksDetails: React.FC<WebhooksDetailsProps> = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
const onWebhookUpdate = (data: WebhookUpdate) => {
|
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({
|
notify({
|
||||||
text: intl.formatMessage(commonMessages.savedChanges)
|
text: intl.formatMessage(commonMessages.savedChanges)
|
||||||
});
|
});
|
||||||
navigate(webhookUrl(data.webhookUpdate.webhook.id));
|
navigate(webhookUrl(webhook.id));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleOnBack = () => navigate(webhookListUrl());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TypedWebhookUpdate onCompleted={onWebhookUpdate}>
|
<TypedWebhookUpdate onCompleted={onWebhookUpdate}>
|
||||||
{(webhookUpdate, webhookUpdateOpts) => (
|
{(webhookUpdate, webhookUpdateOpts) => (
|
||||||
|
@ -79,28 +85,33 @@ export const WebhooksDetails: React.FC<WebhooksDetailsProps> = ({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const formErrors = maybe(
|
const webhook = webhookDetails?.data?.webhook;
|
||||||
() => webhookUpdateOpts.data.webhookUpdate.webhookErrors,
|
const formErrors =
|
||||||
[]
|
webhookUpdateOpts.data?.webhookUpdate.webhookErrors || [];
|
||||||
);
|
|
||||||
|
if (webhook === null) {
|
||||||
|
return <NotFoundPage onBack={handleOnBack} />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<WindowTitle
|
<WindowTitle
|
||||||
title={maybe(() => webhookDetails.data.webhook.name)}
|
title={getStringOrPlaceholder(
|
||||||
|
webhookDetails?.data?.webhook?.name
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<WebhooksDetailsPage
|
<WebhooksDetailsPage
|
||||||
disabled={webhookDetails.loading}
|
disabled={webhookDetails.loading}
|
||||||
errors={formErrors}
|
errors={formErrors}
|
||||||
saveButtonBarState={webhookUpdateOpts.status}
|
saveButtonBarState={webhookUpdateOpts.status}
|
||||||
webhook={maybe(() => webhookDetails.data.webhook)}
|
webhook={webhook}
|
||||||
fetchServiceAccounts={searchServiceAccount}
|
fetchServiceAccounts={searchServiceAccount}
|
||||||
services={maybe(() =>
|
services={maybe(() =>
|
||||||
searchServiceAccountOpt.data.search.edges.map(
|
searchServiceAccountOpt.data.search.edges.map(
|
||||||
edge => edge.node
|
edge => edge.node
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
onBack={() => navigate(webhookListUrl())}
|
onBack={handleOnBack}
|
||||||
onDelete={() => openModal("remove")}
|
onDelete={() => openModal("remove")}
|
||||||
onSubmit={data => {
|
onSubmit={data => {
|
||||||
webhookUpdate({
|
webhookUpdate({
|
||||||
|
@ -122,10 +133,7 @@ export const WebhooksDetails: React.FC<WebhooksDetailsProps> = ({
|
||||||
/>
|
/>
|
||||||
<WebhookDeleteDialog
|
<WebhookDeleteDialog
|
||||||
confirmButtonState={webhookDeleteOpts.status}
|
confirmButtonState={webhookDeleteOpts.status}
|
||||||
name={maybe(
|
name={getStringOrPlaceholder(webhook?.name)}
|
||||||
() => webhookDetails.data.webhook.name,
|
|
||||||
"..."
|
|
||||||
)}
|
|
||||||
onClose={closeModal}
|
onClose={closeModal}
|
||||||
onConfirm={handleRemoveConfirm}
|
onConfirm={handleRemoveConfirm}
|
||||||
open={params.action === "remove"}
|
open={params.action === "remove"}
|
||||||
|
|
Loading…
Reference in a new issue