2019-06-19 14:40:52 +00:00
import Button from "@material-ui/core/Button" ;
import DialogContentText from "@material-ui/core/DialogContentText" ;
import ActionDialog from "@saleor/components/ActionDialog" ;
import AssignProductDialog from "@saleor/components/AssignProductDialog" ;
2020-05-14 09:30:32 +00:00
import NotFoundPage from "@saleor/components/NotFoundPage" ;
2019-06-19 14:40:52 +00:00
import { WindowTitle } from "@saleor/components/WindowTitle" ;
2019-11-21 14:59:06 +00:00
import { DEFAULT_INITIAL_SEARCH_DATA , PAGINATE_BY } from "@saleor/config" ;
2019-06-19 14:40:52 +00:00
import useBulkActions from "@saleor/hooks/useBulkActions" ;
import useNavigator from "@saleor/hooks/useNavigator" ;
import useNotifier from "@saleor/hooks/useNotifier" ;
import usePaginator , {
createPaginationState
} from "@saleor/hooks/usePaginator" ;
2019-08-21 12:31:55 +00:00
import { commonMessages } from "@saleor/intl" ;
2019-11-19 16:50:40 +00:00
import useProductSearch from "@saleor/searches/useProductSearch" ;
2019-12-06 14:58:28 +00:00
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers" ;
2020-08-28 12:45:11 +00:00
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler" ;
import {
useMetadataUpdate ,
usePrivateMetadataUpdate
} from "@saleor/utils/metadata/updateMetadata" ;
2020-05-14 09:30:32 +00:00
import React from "react" ;
import { FormattedMessage , useIntl } from "react-intl" ;
2019-06-19 14:40:52 +00:00
import { getMutationState , maybe } from "../../misc" ;
import { productUrl } from "../../products/urls" ;
import { CollectionInput } from "../../types/globalTypes" ;
import CollectionDetailsPage , {
CollectionDetailsPageFormData
} from "../components/CollectionDetailsPage/CollectionDetailsPage" ;
2020-08-28 12:45:11 +00:00
import {
useCollectionAssignProductMutation ,
useCollectionRemoveMutation ,
useCollectionUpdateMutation ,
useCollectionUpdateWithHomepageMutation ,
useUnassignCollectionProductMutation
} from "../mutations" ;
2019-06-19 14:40:52 +00:00
import { TypedCollectionDetailsQuery } from "../queries" ;
import { CollectionUpdate } from "../types/CollectionUpdate" ;
import {
collectionListUrl ,
collectionUrl ,
2020-05-14 09:30:32 +00:00
CollectionUrlDialog ,
CollectionUrlQueryParams
2019-06-19 14:40:52 +00:00
} from "../urls" ;
interface CollectionDetailsProps {
id : string ;
params : CollectionUrlQueryParams ;
}
2019-11-07 11:34:54 +00:00
export const CollectionDetails : React.FC < CollectionDetailsProps > = ( {
id ,
params
} ) = > {
2019-06-19 14:40:52 +00:00
const navigate = useNavigator ( ) ;
const notify = useNotifier ( ) ;
const { isSelected , listElements , reset , toggle , toggleAll } = useBulkActions (
params . ids
) ;
const paginate = usePaginator ( ) ;
2019-08-21 12:31:55 +00:00
const intl = useIntl ( ) ;
2020-10-26 10:29:41 +00:00
const { search , loadMore , result } = useProductSearch ( {
2020-10-26 13:17:24 +00:00
variables : DEFAULT_INITIAL_SEARCH_DATA
2019-11-19 16:50:40 +00:00
} ) ;
2020-08-28 12:45:11 +00:00
const [ updateMetadata ] = useMetadataUpdate ( { } ) ;
const [ updatePrivateMetadata ] = usePrivateMetadataUpdate ( { } ) ;
const handleCollectionUpdate = ( data : CollectionUpdate ) = > {
if ( data . collectionUpdate . errors . length === 0 ) {
notify ( {
status : "success" ,
text : intl.formatMessage ( commonMessages . savedChanges )
} ) ;
navigate ( collectionUrl ( id ) ) ;
} else {
const backgroundImageError = data . collectionUpdate . errors . find (
error = > error . field === ( "backgroundImage" as keyof CollectionInput )
) ;
if ( backgroundImageError ) {
notify ( {
status : "error" ,
text : intl.formatMessage ( commonMessages . somethingWentWrong )
} ) ;
}
}
} ;
const [ updateCollection , updateCollectionOpts ] = useCollectionUpdateMutation ( {
onCompleted : handleCollectionUpdate
} ) ;
const [
updateCollectionWithHomepage ,
updateCollectionWithHomepageOpts
] = useCollectionUpdateWithHomepageMutation ( {
onCompleted : data = > {
if ( data . homepageCollectionUpdate . errors . length === 0 ) {
handleCollectionUpdate ( data ) ;
}
}
} ) ;
const [ assignProduct , assignProductOpts ] = useCollectionAssignProductMutation (
{
onCompleted : data = > {
if ( data . collectionAddProducts . errors . length === 0 ) {
notify ( {
status : "success" ,
text : intl.formatMessage ( {
defaultMessage : "Added product to collection"
} )
} ) ;
navigate ( collectionUrl ( id ) , true ) ;
}
}
}
) ;
const [
unassignProduct ,
unassignProductOpts
] = useUnassignCollectionProductMutation ( {
onCompleted : data = > {
if ( data . collectionRemoveProducts . errors . length === 0 ) {
notify ( {
status : "success" ,
text : intl.formatMessage ( {
defaultMessage : "Deleted product from collection"
} )
} ) ;
reset ( ) ;
closeModal ( ) ;
}
}
} ) ;
const [ removeCollection , removeCollectionOpts ] = useCollectionRemoveMutation ( {
onCompleted : data = > {
if ( data . collectionDelete . errors . length === 0 ) {
notify ( {
status : "success" ,
text : intl.formatMessage ( {
defaultMessage : "Deleted collection"
} )
} ) ;
navigate ( collectionListUrl ( ) ) ;
}
}
} ) ;
2019-06-19 14:40:52 +00:00
2019-12-06 14:58:28 +00:00
const [ openModal , closeModal ] = createDialogActionHandlers <
CollectionUrlDialog ,
CollectionUrlQueryParams
> ( navigate , params = > collectionUrl ( id , params ) , params ) ;
2019-06-19 14:40:52 +00:00
const paginationState = createPaginationState ( PAGINATE_BY , params ) ;
2020-02-20 14:18:22 +00:00
const handleBack = ( ) = > navigate ( collectionListUrl ( ) ) ;
2019-06-19 14:40:52 +00:00
return (
< TypedCollectionDetailsQuery
displayLoader
variables = { { id , . . . paginationState } }
>
{ ( { data , loading } ) = > {
2020-02-20 14:18:22 +00:00
const collection = data ? . collection ;
if ( collection === null ) {
return < NotFoundPage onBack = { handleBack } / > ;
}
2020-08-28 12:45:11 +00:00
const handleUpdate = async (
formData : CollectionDetailsPageFormData
2020-03-05 17:48:54 +00:00
) = > {
2020-08-28 12:45:11 +00:00
const input : CollectionInput = {
backgroundImageAlt : formData.backgroundImageAlt ,
descriptionJson : JSON.stringify ( formData . description ) ,
isPublished : formData.isPublished ,
name : formData.name ,
publicationDate : formData.publicationDate ,
seo : {
description : formData.seoDescription ,
title : formData.seoTitle
2020-09-21 10:47:03 +00:00
} ,
slug : formData.slug
2020-08-28 12:45:11 +00:00
} ;
const isFeatured = data . shop . homepageCollection
? data . shop . homepageCollection . id === data . collection . id
: false ;
2019-06-19 14:40:52 +00:00
2020-08-28 12:45:11 +00:00
if ( formData . isFeatured !== isFeatured ) {
const result = await updateCollectionWithHomepage ( {
variables : {
homepageId : formData.isFeatured ? id : null ,
id ,
input
}
2019-06-19 14:40:52 +00:00
} ) ;
2020-08-28 12:45:11 +00:00
return [
. . . result . data . collectionUpdate . errors ,
. . . result . data . homepageCollectionUpdate . errors
] ;
} else {
const result = await updateCollection ( {
variables : {
id ,
input
}
2019-06-19 14:40:52 +00:00
} ) ;
2020-08-28 12:45:11 +00:00
return result . data . collectionUpdate . errors ;
2019-06-19 14:40:52 +00:00
}
} ;
2020-08-28 12:45:11 +00:00
const handleSubmit = createMetadataUpdateHandler (
data ? . collection ,
handleUpdate ,
variables = > updateMetadata ( { variables } ) ,
variables = > updatePrivateMetadata ( { variables } )
) ;
2019-06-19 14:40:52 +00:00
2020-08-28 12:45:11 +00:00
const formTransitionState = getMutationState (
updateCollectionOpts . called ||
updateCollectionWithHomepageOpts . called ,
updateCollectionOpts . loading ||
updateCollectionWithHomepageOpts . loading ,
updateCollectionOpts . data ? . collectionUpdate . errors ,
updateCollectionWithHomepageOpts . data ? . collectionUpdate . errors ,
updateCollectionWithHomepageOpts . data ? . homepageCollectionUpdate . errors
) ;
2019-06-19 14:40:52 +00:00
2020-08-28 12:45:11 +00:00
const { loadNextPage , loadPreviousPage , pageInfo } = paginate (
data ? . collection ? . products ? . pageInfo ,
paginationState ,
params
) ;
2019-06-19 14:40:52 +00:00
2020-08-28 12:45:11 +00:00
return (
< >
< WindowTitle title = { maybe ( ( ) = > data . collection . name ) } / >
< CollectionDetailsPage
onAdd = { ( ) = > openModal ( "assign" ) }
onBack = { handleBack }
disabled = { loading }
collection = { data ? . collection }
errors = { updateCollectionOpts ? . data ? . collectionUpdate . errors || [ ] }
isFeatured = { maybe (
( ) = > data . shop . homepageCollection . id === data . collection . id ,
false
) }
onCollectionRemove = { ( ) = > openModal ( "remove" ) }
onImageDelete = { ( ) = > openModal ( "removeImage" ) }
onImageUpload = { file = >
updateCollection ( {
variables : {
id ,
input : {
backgroundImage : file
2019-11-19 16:50:40 +00:00
}
2020-08-28 12:45:11 +00:00
}
} )
}
onSubmit = { handleSubmit }
onNextPage = { loadNextPage }
onPreviousPage = { loadPreviousPage }
pageInfo = { pageInfo }
onProductUnassign = { ( productId , event ) = > {
event . stopPropagation ( ) ;
unassignProduct ( {
variables : {
collectionId : id ,
productIds : [ productId ] ,
. . . paginationState
}
} ) ;
} }
onRowClick = { id = > ( ) = > navigate ( productUrl ( id ) ) }
saveButtonBarState = { formTransitionState }
toolbar = {
< Button
color = "primary"
onClick = { ( ) = >
openModal ( "unassign" , {
ids : listElements
} )
}
>
< FormattedMessage
defaultMessage = "Unassign"
description = "unassign product from collection, button"
2019-11-19 16:50:40 +00:00
/ >
2020-08-28 12:45:11 +00:00
< / Button >
}
isChecked = { isSelected }
selected = { listElements . length }
toggle = { toggle }
toggleAll = { toggleAll }
/ >
< AssignProductDialog
confirmButtonState = { assignProductOpts . status }
2020-10-26 10:29:41 +00:00
hasMore = { result . data ? . search ? . pageInfo . hasNextPage }
2020-08-28 12:45:11 +00:00
open = { params . action === "assign" }
onFetch = { search }
2020-10-26 10:29:41 +00:00
onFetchMore = { loadMore }
2020-08-28 12:45:11 +00:00
loading = { result . loading }
onClose = { closeModal }
onSubmit = { products = >
assignProduct ( {
variables : {
. . . paginationState ,
collectionId : id ,
productIds : products.map ( product = > product . id )
}
} )
}
products = { maybe ( ( ) = >
result . data . search . edges
. map ( edge = > edge . node )
. filter ( suggestedProduct = > suggestedProduct . id )
) }
/ >
< ActionDialog
confirmButtonState = { removeCollectionOpts . status }
onClose = { closeModal }
onConfirm = { ( ) = >
removeCollection ( {
variables : { id }
} )
}
open = { params . action === "remove" }
title = { intl . formatMessage ( {
defaultMessage : "Delete Collection" ,
description : "dialog title"
} ) }
variant = "delete"
>
< DialogContentText >
< FormattedMessage
defaultMessage = "Are you sure you want to delete {collectionName}?"
values = { {
collectionName : (
< strong >
{ maybe ( ( ) = > data . collection . name , "..." ) }
< / strong >
)
} }
/ >
< / DialogContentText >
< / ActionDialog >
< ActionDialog
confirmButtonState = { unassignProductOpts . status }
onClose = { closeModal }
onConfirm = { ( ) = >
unassignProduct ( {
variables : {
. . . paginationState ,
collectionId : id ,
productIds : params.ids
}
} )
}
open = { params . action === "unassign" }
title = { intl . formatMessage ( {
defaultMessage : "Unassign products from collection" ,
description : "dialog title"
} ) }
>
< DialogContentText >
< FormattedMessage
defaultMessage = "{counter,plural,one{Are you sure you want to unassign this product?} other{Are you sure you want to unassign {displayQuantity} products?}}"
values = { {
counter : maybe ( ( ) = > params . ids . length ) ,
displayQuantity : (
< strong > { maybe ( ( ) = > params . ids . length ) } < / strong >
)
} }
/ >
< / DialogContentText >
< / ActionDialog >
< ActionDialog
confirmButtonState = { updateCollectionOpts . status }
onClose = { closeModal }
onConfirm = { ( ) = >
updateCollection ( {
variables : {
id ,
input : {
backgroundImage : null
2019-06-19 14:40:52 +00:00
}
2020-08-28 12:45:11 +00:00
}
} )
}
open = { params . action === "removeImage" }
title = { intl . formatMessage ( {
defaultMessage : "Delete image" ,
description : "dialog title"
} ) }
variant = "delete"
>
< DialogContentText >
< FormattedMessage defaultMessage = "Are you sure you want to delete collection's image?" / >
< / DialogContentText >
< / ActionDialog >
< / >
2019-06-19 14:40:52 +00:00
) ;
} }
< / TypedCollectionDetailsQuery >
) ;
} ;
export default CollectionDetails ;