Begins adjustments to Carousel Collections Modal.

This commit is contained in:
Mateus Machado Luna 2019-08-12 16:02:07 -03:00
parent f61f8ef550
commit 5bc06c7150
2 changed files with 196 additions and 213 deletions

View File

@ -3,135 +3,180 @@ import axios from 'axios';
const { __ } = wp.i18n; const { __ } = wp.i18n;
const { TextControl, Button, Modal, RadioControl, Spinner } = wp.components; const { TextControl, Button, Modal, CheckboxControl, Spinner } = wp.components;
export default class CarouselCollectionsModal extends React.Component { export default class CollectionsModal extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
// Initialize state // Initialize state
this.state = { this.state = {
collectionsPerPage: 24, searchCollectionName: '',
collectionId: undefined, collectionsRequestSource: undefined,
collectionName: '', collections: [],
temporarySelectedCollections: [],
isLoadingCollections: false, isLoadingCollections: false,
modalCollections: [], modalCollections: [],
totalModalCollections: 0, totalModalCollections: 0,
collectionPage: 1, collectionsPerPage: 24,
temporaryCollectionId: '', collectionsPage: 1,
searchCollectionName: '',
collections: [],
collectionsRequestSource: undefined,
searchURL: '',
itemsPerPage: 12,
loadStrategy: 'search'
}; };
// Bind events // Bind events
this.resetCollections = this.resetCollections.bind(this); this.selectTemporaryCollection = this.selectTemporaryCollection.bind(this);
this.removeTemporaryCollectionOfId = this.removeTemporaryCollectionOfId.bind(this);
this.applySelectedCollections = this.applySelectedCollections.bind(this);
this.isTemporaryCollectionSelected = this.isTemporaryCollectionSelected.bind(this);
this.toggleSelectTemporaryCollection = this.toggleSelectTemporaryCollection.bind(this);
this.cancelSelection = this.cancelSelection.bind(this);
this.selectCollection = this.selectCollection.bind(this); this.selectCollection = this.selectCollection.bind(this);
this.fetchCollections = this.fetchCollections.bind(this);
this.fetchModalCollections = this.fetchModalCollections.bind(this); this.fetchModalCollections = this.fetchModalCollections.bind(this);
this.fetchCollection = this.fetchCollection.bind(this); this.fetchCollections = this.fetchCollections.bind(this);
this.applySelectedSearchURL = this.applySelectedSearchURL.bind(this);
this.applySelectedItems = this.applySelectedItems.bind(this);
} }
componentWillMount() { componentWillMount() {
this.fetchModalCollections();
this.setState( { this.setState( {
collectionId: this.props.existingCollectionId collections: [],
collectionsPage: 1,
temporarySelectedCollections: JSON.parse(JSON.stringify(this.props.selectedCollectionsObject))
} );
}
selectTemporaryCollection(collection) {
let existingCollectionIndex = this.state.temporarySelectedCollections.findIndex((existingCollection) => (existingCollection.id == 'collection-id-' + collection.id) || (existingCollection.id == collection.id));
if (existingCollectionIndex < 0) {
let collectionId = isNaN(collection.id) ? collection.id : 'collection-id-' + collection.id;
let aTemporarySelectedCollections = this.state.temporarySelectedCollections;
aTemporarySelectedCollections.push({
id: collectionId,
name: collection.name,
url: collection.url,
thumbnail: collection.thumbnail
});
this.setState({ temporarySelectedCollections: aTemporarySelectedCollections });
}
}
removeTemporaryCollectionOfId(collectionId) {
let existingCollectionIndex = this.state.temporarySelectedCollections.findIndex((existingCollection) => ((existingCollection.id == 'collection-id-' + collectionId) || (existingCollection.id == collectionId)));
if (existingCollectionIndex >= 0) {
let aTemporarySelectedCollections = this.state.temporarySelectedCollections;
aTemporarySelectedCollections.splice(existingCollectionIndex, 1);
this.setState({ temporarySelectedCollections: aTemporarySelectedCollections });
}
}
applySelectedCollections() {
let aSelectedCollectionsObject = JSON.parse(JSON.stringify(this.state.temporarySelectedCollections));
this.props.onApplySelection(aSelectedCollectionsObject);
}
isTemporaryCollectionSelected(collectionId) {
return this.state.temporarySelectedCollections.findIndex(collection => (collection.id == collectionId) || (collection.id == 'collection-id-' + collectionId)) >= 0;
}
toggleSelectTemporaryCollection(collection, isChecked) {
if (isChecked)
this.selectTemporaryCollection(collection);
else
this.removeTemporaryCollectionOfId(collection.id);
}
cancelSelection() {
this.setState({
collectionsPage: 1,
modalCollections: []
}); });
if (this.props.existingCollectionId != null && this.props.existingCollectionId != undefined) { this.props.onCancelSelection();
this.fetchCollection(this.props.existingCollectionId); }
selectCollection(selectedCollectionId) {
this.setState({ this.setState({
searchURL: this.props.existingSearchURL ? this.props.existingSearchURL : tainacan_plugin.admin_url + 'admin.php?page=tainacan_admin#/collections/'+ this.props.existingCollectionId + (this.props.loadStrategy == 'search' ? '/items/?iframemode=true&readmode=true' : '/items/?iframemode=true') }); collectionId: selectedCollectionId
} else { });
this.setState({ collectionPage: 1 }); this.fetchCollection();
this.fetchModalCollections(); this.fetchModalCollections();
} }
}
// COLLECTIONS RELATED --------------------------------------------------
fetchModalCollections() { fetchModalCollections() {
let someModalCollections = this.state.modalCollections; let currentModalCollections = this.state.modalCollections;
if (this.state.collectionPage <= 1) if (this.state.collectionsPage <= 1)
someModalCollections = []; currentModalCollections = [];
let endpoint = '/collections/?orderby=title&order=asc&perpage=' + this.state.collectionsPerPage + '&paged=' + this.state.collectionPage; let endpoint = '/collections/?orderby=title&order=asc&perpage=' + this.state.collectionsPerPage + '&paged=' + this.state.collectionsPage;
this.setState({ this.setState({
isLoadingCollections: true, isLoadingCollections: true,
collectionPage: this.state.collectionPage + 1, modalCollections: currentModalCollections,
modalCollections: someModalCollections
}); });
tainacan.get(endpoint) tainacan.get(endpoint)
.then(response => { .then(response => {
let otherModalCollections = this.state.modalCollections;
for (let collection of response.data) { for (let collection of response.data) {
otherModalCollections.push({ currentModalCollections.push({
name: collection.name, name: collection.name,
id: collection.id id: collection.id,
url: collection.url,
thumbnail: [{
src: collection.thumbnail['tainacan-medium'] != undefined ? collection.thumbnail['tainacan-medium'][0] : collection.thumbnail['medium'][0],
alt: collection.name
}]
}); });
} }
this.setState({ this.setState({
collectionsPage: this.state.collectionsPage + 1,
isLoadingCollections: false, isLoadingCollections: false,
modalCollections: otherModalCollections, modalCollections: currentModalCollections,
totalModalCollections: response.headers['x-wp-total'] totalModalCollections: response.headers['x-wp-total']
}); });
return otherModalCollections; return currentModalCollections;
}) })
.catch(error => { .catch(error => {
console.log('Error trying to fetch collections: ' + error); console.log('Error trying to fetch collections: ' + error);
}); });
} }
fetchCollection(collectionId) {
tainacan.get('/collections/' + collectionId)
.then((response) => {
this.setState({ collectionName: response.data.name });
}).catch(error => {
console.log('Error trying to fetch collection: ' + error);
});
}
selectCollection(selectedCollectionId) {
this.setState({
collectionId: selectedCollectionId,
searchURL: tainacan_plugin.admin_url + 'admin.php?page=tainacan_admin#/collections/' + selectedCollectionId + (this.props.loadStrategy == 'search' ? '/items/?iframemode=true&readmode=true' : '/items/?iframemode=true')
});
this.props.onSelectCollection(selectedCollectionId);
this.fetchCollection(selectedCollectionId);
}
fetchCollections(name) { fetchCollections(name) {
if (this.state.collectionsRequestSource != undefined) if (this.state.collectionsRequestSource != undefined)
this.state.collectionsRequestSource.cancel('Previous collections search canceled.'); this.state.collectionsRequestSource.cancel('Previous collections search canceled.');
let aCollectionRequestSource = axios.CancelToken.source(); let aCollectionRequestSource = axios.CancelToken.source();
this.setState({ this.setState({
collectionsRequestSource: aCollectionRequestSource, collectionsRequestSource: aCollectionRequestSource,
isLoadingCollections: true, isLoadingCollections: true
collections: [],
items: []
}); });
let endpoint = '/collections/?orderby=title&order=asc&perpage=' + this.state.collectionsPerPage; let endpoint = '/collections/?orderby=title&order=asc&perpage=' + this.state.collectionsPerPage;
if (name != undefined && name != '') if (name != undefined && name != '')
endpoint += '&search=' + name; endpoint += '&search=' + name;
tainacan.get(endpoint, { cancelToken: aCollectionRequestSource.token }) tainacan.get(endpoint, { cancelToken: aCollectionRequestSource.token })
.then(response => { .then(response => {
let someCollections = response.data.map((collection) => ({ name: collection.name, id: collection.id + '' }));
let someCollections = this.state.collections;
someCollections = response.data.map((collection) => ({
name: collection.name,
id: collection.id,
url: collection.url,
thumbnail: [{
src: collection.thumbnail['tainacan-medium'] != undefined ? collection.thumbnail['tainacan-medium'][0] : collection.thumbnail['medium'][0],
alt: collection.name
}]
}));
this.setState({ this.setState({
isLoadingCollections: false, isLoadingCollections: false,
@ -145,142 +190,87 @@ export default class CarouselCollectionsModal extends React.Component {
}); });
} }
applySelectedSearchURL() {
let iframe = document.getElementById("itemsFrame");
if (iframe) {
this.props.onApplySearchURL(iframe.contentWindow.location.href);
}
}
applySelectedItems() {
let iframe = document.getElementById("itemsFrame");
if (iframe) {
let params = new URLSearchParams(iframe.contentWindow.location.search);
let selectedItems = params.getAll('selecteditems');
params.delete('selecteditems')
this.props.onApplySelectedItems(selectedItems);
}
}
resetCollections() {
this.setState({
collectionId: null,
collectionPage: 1,
modalCollections: []
});
this.fetchModalCollections();
}
cancelSelection() {
this.setState({
modalCollections: []
});
this.props.onCancelSelection();
}
render() { render() {
return this.state.collectionId != null && this.state.collectionId != undefined ? ( return (
// Items modal
<Modal
className="wp-block-tainacan-modal dynamic-modal"
title={ this.props.loadStrategy == 'selection' ? __('Select items to add on block', 'tainacan') : __('Configure the items search to be used on block', 'tainacan')}
onRequestClose={ () => this.cancelSelection() }
contentLabel={ this.props.loadStrategy == 'selection' ? __('Select items that will be added on block', 'tainacan') : __('Configure your items search that will load items on block', 'tainacan')}>
<iframe
id="itemsFrame"
src={ this.state.searchURL } />
<div className="modal-footer-area">
<Button
isDefault
onClick={ () => { this.resetCollections() }}>
{__('Switch collection', 'tainacan')}
</Button>
{ this.props.loadStrategy == 'selection' ?
<Button
style={{ marginLeft: 'auto' }}
isPrimary
onClick={ () => this.applySelectedItems() }>
{__('Add the selected items', 'tainacan')}
</Button>
: null
}
{ this.props.loadStrategy == 'search' ?
<Button
isPrimary
onClick={ () => this.applySelectedSearchURL() }>
{__('Use this search', 'tainacan')}
</Button>
: null
}
</div>
</Modal>
) : (
// Collections modal
<Modal <Modal
className="wp-block-tainacan-modal" className="wp-block-tainacan-modal"
title={__('Select a collection to fetch items from', 'tainacan')} title={__('Select the desired collections from your repository', 'tainacan')}
onRequestClose={ () => this.cancelSelection() } onRequestClose={ () => this.cancelSelection() }
contentLabel={__('Select items', 'tainacan')}> contentLabel={__('Select collections', 'tainacan')}>
<div> <div>
<div className="modal-search-area"> <div className="modal-search-area">
<TextControl <TextControl
label={__('Search for a collection', 'tainacan')} label={__('Search for a collection', 'tainacan')}
value={ this.state.searchCollectionName } value={ this.state.searchCollectionName }
onChange={(value) => { onInput={(value) => {
this.setState({ this.setState({
searchCollectionName: value searchCollectionName: value.target.value
}); });
_.debounce(this.fetchCollections(value), 300); }}
}}/> onChange={(value) => this.fetchCollections(value)}/>
</div> </div>
{( {(
this.state.searchCollectionName != '' ? ( this.state.searchCollectionName != '' ? (
this.state.collections.length > 0 ? this.state.collections.length > 0 ?
( (
<div> <div>
<div className="modal-radio-list"> <ul className="modal-checkbox-list">
{ {
<RadioControl this.state.collections.map((collection) =>
selected={ this.state.temporaryCollectionId } <li
options={ key={ collection.id }
this.state.collections.map((collection) => { className="modal-checkbox-list-item">
return { label: collection.name, value: '' + collection.id } { collection.thumbnail ?
}) <img
aria-hidden
src={ collection.thumbnail && collection.thumbnail[0] && collection.thumbnail[0].src ? collection.thumbnail[0].src : `${tainacan_plugin.base_url}/admin/images/placeholder_square.png`}
alt={ collection.thumbnail && collection.thumbnail[0] ? collection.thumbnail[0].alt : collection.name }/>
: null
} }
onChange={ ( aCollectionId ) => { <CheckboxControl
this.setState({ temporaryCollectionId: aCollectionId }); label={ collection.name }
} } /> checked={ this.isTemporaryCollectionSelected(collection.id) }
onChange={ ( isChecked ) => { this.toggleSelectTemporaryCollection(collection, isChecked) } }
/>
</li>
)
} }
</ul>
{ this.state.isLoadingCollections ? <div class="spinner-container"><Spinner /></div> : null }
</div> </div>
</div> )
) : : this.state.isLoadingCollections ? <div class="spinner-container"><Spinner /></div> :
this.state.isLoadingCollections ? (
<Spinner />
) :
<div className="modal-loadmore-section"> <div className="modal-loadmore-section">
<p>{ __('Sorry, no collection found.', 'tainacan') }</p> <p>{ __('Sorry, no collections found.', 'tainacan') }</p>
</div> </div>
) : ) :
this.state.modalCollections.length > 0 ? this.state.modalCollections.length > 0 ?
( (
<div> <div>
<div className="modal-radio-list"> <ul className="modal-checkbox-list">
{ {
<RadioControl this.state.modalCollections.map((collection) =>
selected={ this.state.temporaryCollectionId } <li
options={ key={ collection.id }
this.state.modalCollections.map((collection) => { className="modal-checkbox-list-item">
return { label: collection.name, value: '' + collection.id } { collection.thumbnail ?
}) <img
aria-hidden
src={ collection.thumbnail && collection.thumbnail[0] && collection.thumbnail[0].src ? collection.thumbnail[0].src : `${tainacan_plugin.base_url}/admin/images/placeholder_square.png`}
alt={ collection.thumbnail && collection.thumbnail[0] ? collection.thumbnail[0].alt : collection.name }/>
: null
} }
onChange={ ( aCollectionId ) => { <CheckboxControl
this.setState({ temporaryCollectionId: aCollectionId }); label={ collection.name }
} } /> checked={ this.isTemporaryCollectionSelected(collection.id) }
onChange={ ( isChecked ) => { this.toggleSelectTemporaryCollection(collection, isChecked) } } />
</li>
)
} }
</div> { this.state.isLoadingCollections ? <div class="spinner-container"><Spinner /></div> : null }
</ul>
<div className="modal-loadmore-section"> <div className="modal-loadmore-section">
<p>{ __('Showing', 'tainacan') + " " + this.state.modalCollections.length + " " + __('of', 'tainacan') + " " + this.state.totalModalCollections + " " + __('collections', 'tainacan') + "."}</p> <p>{ __('Showing', 'tainacan') + " " + this.state.modalCollections.length + " " + __('of', 'tainacan') + " " + this.state.totalModalCollections + " " + __('collections', 'tainacan') + "."}</p>
{ {
@ -297,20 +287,20 @@ export default class CarouselCollectionsModal extends React.Component {
</div> </div>
) : this.state.isLoadingCollections ? <Spinner /> : ) : this.state.isLoadingCollections ? <Spinner /> :
<div className="modal-loadmore-section"> <div className="modal-loadmore-section">
<p>{ __('Sorry, no collection found.', 'tainacan') }</p> <p>{ __('Sorry, no collections found.', 'tainacan') }</p>
</div> </div>
)} )}
<div className="modal-footer-area"> <div className="modal-footer-area">
<Button <Button
isDefault isDefault
onClick={ () => { this.cancelSelection() }}> onClick={ () => this.cancelSelection() }>
{__('Cancel', 'tainacan')} {__('Cancel', 'tainacan')}
</Button> </Button>
<Button <Button
isPrimary isPrimary
disabled={ this.state.temporaryCollectionId == undefined || this.state.temporaryCollectionId == null || this.state.temporaryCollectionId == ''} type="submit"
onClick={ () => { this.selectCollection(this.state.temporaryCollectionId); } }> onClick={ () => this.applySelectedCollections() }>
{ this.props.loadStrategy == 'selection' ? __('Select items', 'tainacan') : __('Configure search', 'tainacan')} {__('Finish', 'tainacan')}
</Button> </Button>
</div> </div>
</div> </div>

View File

@ -2,11 +2,11 @@ const { registerBlockType } = wp.blocks;
const { __ } = wp.i18n; const { __ } = wp.i18n;
const { RangeControl, Spinner, Button, ToggleControl, SelectControl, Placeholder, IconButton, ColorPicker, ColorPalette, BaseControl, PanelBody } = wp.components; const { RangeControl, Spinner, Button, ToggleControl, SelectControl, Placeholder, IconButton, PanelBody } = wp.components;
const { InspectorControls } = wp.editor; const { InspectorControls } = wp.editor;
import CarouselCollectionsModal from './carousel-collections-modal.js'; import CarouselCollectionsModal from '../collections-list/carousel-collections-modal.js';
import tainacan from '../../api-client/axios.js'; import tainacan from '../../api-client/axios.js';
import axios from 'axios'; import axios from 'axios';
import qs from 'qs'; import qs from 'qs';
@ -31,10 +31,6 @@ registerBlockType('tainacan/carousel-collections-list', {
source: 'children', source: 'children',
selector: 'div' selector: 'div'
}, },
collectionId: {
type: String,
default: undefined
},
collections: { collections: {
type: Array, type: Array,
default: [] default: []
@ -121,7 +117,6 @@ registerBlockType('tainacan/carousel-collections-list', {
let { let {
collections, collections,
content, content,
collectionId,
isModalOpen, isModalOpen,
itemsRequestSource, itemsRequestSource,
selectedCollections, selectedCollections,
@ -182,7 +177,7 @@ registerBlockType('tainacan/carousel-collections-list', {
collections = []; collections = [];
let endpoint = '/collection/' + collectionId + '/collections?'+ qs.stringify({ postin: selectedCollections }) + '&fetch_only=title,url,thumbnail'; let endpoint = '/collections?'+ qs.stringify({ postin: selectedCollections }) + '&fetch_only=title,url,thumbnail';
tainacan.get(endpoint, { cancelToken: itemsRequestSource.token }) tainacan.get(endpoint, { cancelToken: itemsRequestSource.token })
.then(response => { .then(response => {
@ -221,7 +216,6 @@ registerBlockType('tainacan/carousel-collections-list', {
collections: collections, collections: collections,
content: <div></div> content: <div></div>
}); });
} }
// Executed only on the first load of page // Executed only on the first load of page
@ -306,9 +300,10 @@ registerBlockType('tainacan/carousel-collections-list', {
( (
<div> <div>
{ isModalOpen ? { isModalOpen ?
<CarouselCollectionsModal <CollectionsModal
onApplySelectedCollections={ (aSelectionOfCollections) => { selectedCollectionsObject={ selectedCollections }
selectedCollections = selectedCollections.concat(aSelectionOfCollections); onApplySelection={ (aSelectionOfCollections) => {
selectedCollections = selectedCollections.concat(aSelectionOfCollections.map((collection) => { return collection.id; }));
setAttributes({ setAttributes({
selectedCollections: selectedCollections, selectedCollections: selectedCollections,
isModalOpen: false isModalOpen: false
@ -427,7 +422,6 @@ registerBlockType('tainacan/carousel-collections-list', {
const { const {
content, content,
blockId, blockId,
collectionId,
selectedCollections, selectedCollections,
arrowsPosition, arrowsPosition,
maxCollectionsNumber, maxCollectionsNumber,
@ -441,7 +435,6 @@ registerBlockType('tainacan/carousel-collections-list', {
className={ className } className={ className }
selected-collections={ JSON.stringify(selectedCollections) } selected-collections={ JSON.stringify(selectedCollections) }
arrows-position={ arrowsPosition } arrows-position={ arrowsPosition }
collection-id={ collectionId }
auto-play={ '' + autoPlay } auto-play={ '' + autoPlay }
auto-play-speed={ autoPlaySpeed } auto-play-speed={ autoPlaySpeed }
loop-slides={ '' + loopSlides } loop-slides={ '' + loopSlides }