Begins usage of inner blocks for related items

This commit is contained in:
mateuswetah 2021-06-15 16:03:23 -03:00
parent 36a30190e1
commit 61af25f99e
7 changed files with 89 additions and 1635 deletions

View File

@ -12,7 +12,7 @@ const TAINACAN_BLOCKS = [
'carousel-items-list' => [ 'has_theme_script' => true ], 'carousel-items-list' => [ 'has_theme_script' => true ],
'carousel-terms-list' => [ 'has_theme_script' => true ], 'carousel-terms-list' => [ 'has_theme_script' => true ],
'carousel-collections-list' => [ 'has_theme_script' => true ], 'carousel-collections-list' => [ 'has_theme_script' => true ],
'carousel-related-items' => [ 'has_theme_script' => true ], 'carousel-related-items' => [],
'terms-list' => [ 'extra_editor_script_deps' => array('undescore') ], 'terms-list' => [ 'extra_editor_script_deps' => array('undescore') ],
]; ];

View File

@ -12,20 +12,21 @@ export default class CarouselRelatedItemsModal extends React.Component {
// Initialize state // Initialize state
this.state = { this.state = {
collectionsPerPage: 24, collectionsPerPage: 24,
collectionId: undefined, collectionId: undefined,
collectionName: '', itemId: undefined,
collectionName: '',
isLoadingCollections: false, isLoadingCollections: false,
modalCollections: [], modalCollections: [],
totalModalCollections: 0, totalModalCollections: 0,
collectionOrderBy: 'date-desc', collectionOrderBy: 'date-desc',
collectionPage: 1, collectionPage: 1,
temporaryCollectionId: '', temporaryCollectionId: '',
temporaryItemId: '',
searchCollectionName: '', searchCollectionName: '',
collections: [], collections: [],
collectionsRequestSource: undefined, collectionsRequestSource: undefined,
searchURL: '', searchURL: '',
itemsPerPage: 12, itemsPerPage: 12
loadStrategy: 'search'
}; };
// Bind events // Bind events
@ -34,20 +35,21 @@ export default class CarouselRelatedItemsModal extends React.Component {
this.fetchCollections = this.fetchCollections.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.fetchCollection = this.fetchCollection.bind(this);
this.applySelectedSearchURL = this.applySelectedSearchURL.bind(this); this.applyRelatedItem = this.applyRelatedItem.bind(this);
this.applySelectedItems = this.applySelectedItems.bind(this);
} }
componentWillMount() { componentWillMount() {
this.setState({ this.setState({
collectionId: this.props.existingCollectionId collectionId: this.props.existingCollectionId,
itemId: this.props.existingItemId
}); });
if (this.props.existingCollectionId != null && this.props.existingCollectionId != undefined) { if (this.props.existingCollectionId != null && this.props.existingCollectionId != undefined) {
this.fetchCollection(this.props.existingCollectionId); this.fetchCollection(this.props.existingCollectionId);
this.setState({ this.setState({
searchURL: this.props.existingSearchURL ? this.props.existingSearchURL : tainacan_blocks.admin_url + 'admin.php?page=tainacan_admin#/collections/'+ this.props.existingCollectionId + (this.props.loadStrategy == 'search' ? '/items/?iframemode=true&readmode=true&status=publish' : '/items/?iframemode=true&status=publish') }); searchURL: tainacan_blocks.admin_url + 'admin.php?page=tainacan_admin#/collections/'+ this.props.existingCollectionId + '/items/?singleselectionmode=true&iframemode=true&status=publish'
});
} else { } else {
this.setState({ collectionPage: 1 }); this.setState({ collectionPage: 1 });
this.fetchModalCollections(); this.fetchModalCollections();
@ -114,7 +116,7 @@ export default class CarouselRelatedItemsModal extends React.Component {
selectCollection(selectedCollectionId) { selectCollection(selectedCollectionId) {
this.setState({ this.setState({
collectionId: selectedCollectionId, collectionId: selectedCollectionId,
searchURL: tainacan_blocks.admin_url + 'admin.php?page=tainacan_admin#/collections/' + selectedCollectionId + (this.props.loadStrategy == 'search' ? '/items/?iframemode=true&readmode=true&status=publish' : '/items/?iframemode=true&status=publish') searchURL: tainacan_blocks.admin_url + 'admin.php?page=tainacan_admin#/collections/' + selectedCollectionId + '/items/?singleselectionmode=true&iframemode=true&status=publish'
}); });
this.props.onSelectCollection(selectedCollectionId); this.props.onSelectCollection(selectedCollectionId);
@ -164,20 +166,13 @@ export default class CarouselRelatedItemsModal extends React.Component {
}); });
} }
applySelectedSearchURL() { applyRelatedItem() {
let iframe = document.getElementById("itemsFrame");
if (iframe) {
this.props.onApplySearchURL(iframe.contentWindow.location.href);
}
}
applySelectedItems() {
let iframe = document.getElementById("itemsFrame"); let iframe = document.getElementById("itemsFrame");
if (iframe) { if (iframe) {
let params = new URLSearchParams(iframe.contentWindow.location.search); let params = new URLSearchParams(iframe.contentWindow.location.search);
let selectedItems = params.getAll('selecteditems'); let selectedItems = params.getAll('selecteditems');
params.delete('selecteditems') params.delete('selecteditems')
this.props.onApplySelectedItems(selectedItems); this.props.onApplyRelatedItem(selectedItems[0]);
} }
} }
@ -205,10 +200,10 @@ export default class CarouselRelatedItemsModal extends React.Component {
// Items modal // Items modal
<Modal <Modal
className="wp-block-tainacan-modal dynamic-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')} title={ __('Select the item that has relations', 'tainacan') }
onRequestClose={ () => this.cancelSelection() } onRequestClose={ () => this.cancelSelection() }
shouldCloseOnClickOutside={ false } shouldCloseOnClickOutside={ false }
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')}> contentLabel={ __('Select the item that has relations', 'tainacan') }>
<iframe <iframe
id="itemsFrame" id="itemsFrame"
src={ this.state.searchURL } /> src={ this.state.searchURL } />
@ -218,23 +213,12 @@ export default class CarouselRelatedItemsModal extends React.Component {
onClick={ () => { this.resetCollections() }}> onClick={ () => { this.resetCollections() }}>
{__('Switch collection', 'tainacan')} {__('Switch collection', 'tainacan')}
</Button> </Button>
{ this.props.loadStrategy == 'selection' ? <Button
<Button style={{ marginLeft: 'auto' }}
style={{ marginLeft: 'auto' }} isPrimary
isPrimary onClick={ () => this.applyRelatedItem() }>
onClick={ () => this.applySelectedItems() }> {__('Add the selected items', 'tainacan')}
{__('Add the selected items', 'tainacan')} </Button>
</Button>
: null
}
{ this.props.loadStrategy == 'search' ?
<Button
isPrimary
onClick={ () => this.applySelectedSearchURL() }>
{__('Use this search', 'tainacan')}
</Button>
: null
}
</div> </div>
</Modal> </Modal>
) : ( ) : (
@ -354,7 +338,7 @@ export default class CarouselRelatedItemsModal extends React.Component {
isPrimary isPrimary
disabled={ this.state.temporaryCollectionId == undefined || this.state.temporaryCollectionId == null || this.state.temporaryCollectionId == ''} disabled={ this.state.temporaryCollectionId == undefined || this.state.temporaryCollectionId == null || this.state.temporaryCollectionId == ''}
onClick={ () => { this.selectCollection(this.state.temporaryCollectionId); } }> onClick={ () => { this.selectCollection(this.state.temporaryCollectionId); } }>
{ this.props.loadStrategy == 'selection' ? __('Select items', 'tainacan') : __('Configure search', 'tainacan')} { __('Select item', 'tainacan') }
</Button> </Button>
</div> </div>
</div> </div>

View File

@ -1,108 +0,0 @@
import Vue from 'vue';
import CarouselRelatedItemsTheme from './carousel-related-items-theme.vue';
import { ThumbnailHelperPlugin } from '../../../admin/js/utilities.js';
import VueBlurHash from 'vue-blurhash';
// Vue Dev Tools!
Vue.config.devtools = process && process.env && process.env.NODE_ENV === 'development';
// This is rendered on the theme side.
document.addEventListener("DOMContentLoaded", () => {
// Gets all divs with content created by our block;
let blocks = document.getElementsByClassName('wp-block-tainacan-carousel-items-list');
if (blocks) {
let blockIds = Object.values(blocks).map((block) => block.id);
// Creates a new Vue Instance to manage each block isolatelly
for (let blockId of blockIds) {
// Configure Vue logic before passing it to constructor:
let vueOptions = {
data: {
collectionId: '',
searchURL: '',
selectedItems: [],
loadStrategy: 'search',
maxItemsNumber: 12,
maxItemsPerScreen: 7,
arrowsPosition: 'around',
largeArrows: false,
autoPlay: false,
autoPlaySpeed: 3,
loopSlides: false,
hideTitle: true,
cropImagesToSquare: true,
showCollectionHeader: false,
showCollectionLabel: false,
collectionBackgroundColor: '#454647',
collectionTextColor: '#ffffff',
tainacanApiRoot: '',
tainacanBaseUrl: '',
className: ''
},
render(h){
return h(CarouselRelatedItemsTheme, {
props: {
blockId: blockId,
collectionId: this.collectionId,
searchURL: this.searchURL,
selectedItems: this.selectedItems,
loadStrategy: this.loadStrategy,
maxItemsNumber: this.maxItemsNumber,
maxItemsPerScreen: this.maxItemsPerScreen,
arrowsPosition: this.arrowsPosition,
largeArrows: this.largeArrows,
autoPlay: this.autoPlay,
autoPlaySpeed: this.autoPlaySpeed,
loopSlides: this.loopSlides,
hideTitle: this.hideTitle,
cropImagesToSquare: this.cropImagesToSquare,
showCollectionHeader: this.showCollectionHeader,
showCollectionLabel: this.showCollectionLabel,
collectionBackgroundColor: this.collectionBackgroundColor,
collectionTextColor: this.collectionTextColor,
tainacanApiRoot: this.tainacanApiRoot,
tainacanBaseUrl: this.tainacanBaseUrl,
className: this.className
}
});
},
beforeMount () {
this.className = this.$el.attributes.class != undefined ? this.$el.attributes.class.value : undefined;
this.searchURL = this.$el.attributes['search-url'] != undefined ? this.$el.attributes['search-url'].value : undefined;
this.selectedItems = this.$el.attributes['selected-items'] != undefined ? JSON.parse(this.$el.attributes['selected-items'].value) : undefined;
this.loadStrategy = this.$el.attributes['load-strategy'] != undefined ? this.$el.attributes['load-strategy'].value : undefined;
this.collectionId = this.$el.attributes['collection-id'] != undefined ? this.$el.attributes['collection-id'].value : undefined;
this.maxItemsNumber = this.$el.attributes['max-items-number'] != undefined ? this.$el.attributes['max-items-number'].value : undefined;
this.maxItemsPerScreen = this.$el.attributes['max-items-per-screen'] != undefined ? this.$el.attributes['max-items-per-screen'].value : 7;
this.arrowsPosition = this.$el.attributes['arrows-position'] != undefined ? this.$el.attributes['arrows-position'].value : undefined;
this.largeArrows = this.$el.attributes['large-arrows'] != undefined ? this.$el.attributes['large-arrows'].value == 'true' : false;
this.autoPlay = this.$el.attributes['auto-play'] != undefined ? this.$el.attributes['auto-play'].value == 'true' : false;
this.autoPlaySpeed = this.$el.attributes['auto-play-speed'] != undefined ? this.$el.attributes['auto-play-speed'].value : 3;
this.loopSlides = this.$el.attributes['loop-slides'] != undefined ? this.$el.attributes['loop-slides'].value == 'true' : false;
this.hideTitle = this.$el.attributes['hide-title'] != undefined ? this.$el.attributes['hide-title'].value == 'true' : false;
this.cropImagesToSquare = this.$el.attributes['crop-images-to-square'] != undefined ? this.$el.attributes['crop-images-to-square'].value == 'true' : true;
this.showCollectionHeader = this.$el.attributes['show-collection-header'] != undefined ? this.$el.attributes['show-collection-header'].value == 'true' : false;
this.showCollectionLabel = this.$el.attributes['show-collection-label'] != undefined ? this.$el.attributes['show-collection-label'].value == 'true' : false;
this.collectionBackgroundColor = this.$el.attributes['collection-background-color'] != undefined ? this.$el.attributes['collection-background-color'].value : undefined;
this.collectionTextColor = this.$el.attributes['collection-text-color'] != undefined ? this.$el.attributes['collection-text-color'].value : undefined;
this.tainacanApiRoot = this.$el.attributes['tainacan-api-root'] != undefined ? this.$el.attributes['tainacan-api-root'].value : undefined;
this.tainacanBaseUrl = this.$el.attributes['tainacan-base-url'] != undefined ? this.$el.attributes['tainacan-base-url'].value : undefined;
console.log(this.collectionId);
},
methods: {
__(text, domain) {
return wp.i18n.__(text, domain);
}
}
};
Vue.use(ThumbnailHelperPlugin);
Vue.use(VueBlurHash);
new Vue( Object.assign({ el: '#' + blockId }, vueOptions) );
}
}
});

View File

@ -1,372 +0,0 @@
<template>
<div :class="className">
<div v-if="showCollectionHeader">
<div
v-if="isLoadingCollection"
class="carousel-items-collection-header skeleton"
:style="{ height: '165px' }"/>
<a
v-else
target="_blank"
:href="collection.url ? collection.url : ''"
class="carousel-items-collection-header">
<div
:style="{
backgroundColor: collectionBackgroundColor ? collectionBackgroundColor : '',
paddingRight: collection && collection.thumbnail && (collection.thumbnail['tainacan-medium'] || collection.thumbnail['medium']) ? '' : '20px',
paddingTop: (!collection || !collection.thumbnail || (!collection.thumbnail['tainacan-medium'] && !collection.thumbnail['medium'])) ? '1em' : '',
width: collection && collection.header_image ? '' : '100%'
}"
:class="
'collection-name ' +
((!collection || !collection.thumbnail || (!collection.thumbnail['tainacan-medium'] && !collection.thumbnail['medium'])) && (!collection || !collection.header_image) ? 'only-collection-name' : '')
">
<h3 :style="{ color: collectionTextColor ? collectionTextColor : '' }">
<span
v-if="showCollectionLabel"
class="label">
{{ $root.__('Collection', 'tainacan') }}
<br>
</span>
{{ collection && collection.name ? collection.name : '' }}
</h3>
</div>
<div
v-if="collection && collection.thumbnail && (collection.thumbnail['tainacan-medium'] || collection.thumbnail['medium'])"
class="collection-thumbnail"
:style="{
backgroundImage: 'url(' + (collection.thumbnail['tainacan-medium'] != undefined ? (collection.thumbnail['tainacan-medium'][0]) : (collection.thumbnail['medium'][0])) + ')',
}"/>
<div
class="collection-header-image"
:style="{
backgroundImage: collection.header_image ? 'url(' + collection.header_image + ')' : '',
minHeight: collection && collection.header_image ? '' : '80px',
display: !(collection && collection.thumbnail && (collection.thumbnail['tainacan-medium'] || collection.thumbnail['medium'])) ? collection && collection.header_image ? '' : 'none' : ''
}"/>
</a>
</div>
<div v-if="!isLoading">
<div
:class="'tainacan-carousel ' + (arrowsPosition ? ' has-arrows-' + arrowsPosition : '') + (largeArrows ? ' has-large-arrows' : '') "
v-if="items.length > 0">
<swiper
role="list"
:options="swiperOptions"
ref="myItemSwiper"
:style="{
marginTop: showCollectionHeader ? '1.35em' : '0px'
}">
<swiper-slide
role="listitem"
ref="myItemSwiperSlide"
:key="index"
v-for="(item, index) of items"
class="item-list-item">
<a
:id="isNaN(item.id) ? item.id : 'item-id-' + item.id"
:href="item.url"
target="_blank">
<blur-hash-image
:height="$thumbHelper.getHeight(item['thumbnail'], (maxItemsPerScreen > 4 ? (!cropImagesToSquare ? 'tainacan-medium-full' : 'tainacan-medium') : 'large'))"
:width="$thumbHelper.getWidth(item['thumbnail'], (maxItemsPerScreen > 4 ? (!cropImagesToSquare ? 'tainacan-medium-full' : 'tainacan-medium') : 'large'))"
:src="$thumbHelper.getSrc(item['thumbnail'], (maxItemsPerScreen > 4 ? (!cropImagesToSquare ? 'tainacan-medium-full' : 'tainacan-medium') : 'large'), item['document_mimetype'])"
:srcset="$thumbHelper.getSrcSet(item['thumbnail'], (maxItemsPerScreen > 4 ? (!cropImagesToSquare ? 'tainacan-medium-full' : 'tainacan-medium') : 'large'), item['document_mimetype'])"
:hash="$thumbHelper.getBlurhashString(item['thumbnail'], (maxItemsPerScreen > 4 ? (!cropImagesToSquare ? 'tainacan-medium-full' : 'tainacan-medium') : 'large'))"
:alt="item.thumbnail_alt ? item.thumbnail_alt : (item && item.title ? item.title : $root.__( 'Thumbnail', 'tainacan' ))"
:transition-duration="500" />
<span v-if="!hideTitle">{{ item.title ? item.title : '' }}</span>
<div
v-if="maxItemsPerScreen <= 4"
class="swiper-lazy-preloader swiper-lazy-preloader-white"/>
</a>
</swiper-slide>
</swiper>
<button
class="swiper-button-prev"
:id="blockId + '-prev'"
slot="button-prev"
:style="hideTitle ? 'top: calc(50% - 21px)' : 'top: calc(50% - ' + (largeArrows ? '60' : '42') + 'px)'">
<svg
:width="largeArrows ? 60 : 42"
:height="largeArrows ? 60 : 42"
viewBox="0 0 24 24">
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>
<path
d="M0 0h24v24H0z"
fill="none"/>
</svg>
</button>
<button
class="swiper-button-next"
:id="blockId + '-next'"
slot="button-next"
:style="hideTitle ? 'top: calc(50% - 21px)' : 'top: calc(50% - ' + (largeArrows ? '60' : '42') + 'px)'">
<svg
:width="largeArrows ? 60 : 42"
:height="largeArrows ? 60 : 42"
viewBox="0 0 24 24">
<path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/>
<path
d="M0 0h24v24H0z"
fill="none"/>
</svg>
</button>
</div>
<div
v-else
class="spinner-container">
{{ $root.__(errorMessage, 'tainacan') }}
</div>
<!-- Swiper buttons are hidden as they actually swipe from slide to slide -->
</div>
<div v-else-if="isLoading && !autoPlay && !loopSlides">
<div :class="'tainacan-carousel ' + (arrowsPosition ? ' has-arrows-' + arrowsPosition : '') + (largeArrows ? ' has-large-arrows' : '') ">
<swiper
role="list"
:options="swiperOptions"
ref="myItemSwiperSkeleton"
:style="{
marginTop: showCollectionHeader ? '1.35em' : '0px'
}">
<swiper-slide
role="listitem"
:key="index"
ref="myItemSwiperSlideSkeleton"
v-for="(item, index) of 18"
class="item-list-item skeleton">
<a>
<img>
<span v-if="!hideTitle" />
</a>
</swiper-slide>
</swiper>
<button
class="swiper-button-prev"
:id="blockId + '-prev'"
slot="button-prev"
:style="hideTitle ? 'top: calc(50% - 21px)' : 'top: calc(50% - ' + (largeArrows ? '60' : '42') + 'px)'">
<svg
:width="largeArrows ? 60 : 42"
:height="largeArrows ? 60 : 42"
viewBox="0 0 24 24">
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>
<path
d="M0 0h24v24H0z"
fill="none"/>
</svg>
</button>
<button
class="swiper-button-next"
:id="blockId + '-next'"
slot="button-next"
:style="hideTitle ? 'top: calc(50% - 21px)' : 'top: calc(50% - ' + (largeArrows ? '60' : '42') + 'px)'">
<svg
:width="largeArrows ? 60 : 42"
:height="largeArrows ? 60 : 42"
viewBox="0 0 24 24">
<path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/>
<path
d="M0 0h24v24H0z"
fill="none"/>
</svg>
</button>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios';
import qs from 'qs';
import 'swiper/css/swiper.min.css';
import { Swiper, SwiperSlide } from 'vue-awesome-swiper';
export default {
name: "CarouselRelatedItemsTheme",
components: {
Swiper,
SwiperSlide
},
props: {
blockId: String,
collectionId: String,
searchURL: String,
selectedItems: Array,
loadStrategy: String,
maxItemsNumber: Number,
maxItemsPerScreen: Number,
arrowsPosition: String,
largeArrows: Boolean,
autoPlay: false,
autoPlaySpeed: Number,
loopSlides: Boolean,
hideTitle: Boolean,
cropImagesToSquare: Boolean,
showCollectionHeader: Boolean,
showCollectionLabel: Boolean,
collectionBackgroundColor: String,
collectionTextColor: String,
tainacanApiRoot: String,
tainacanBaseUrl: String,
className: String
},
data() {
return {
items: [],
collection: undefined,
itemsRequestSource: undefined,
isLoading: false,
isLoadingCollection: false,
localMaxItemsNumber: undefined,
localOrder: undefined,
tainacanAxios: undefined,
paged: undefined,
totalItems: 0,
swiperOptions: {
lazy: this.maxItemsPerScreen <= 4,
watchOverflow: true,
mousewheel: true,
observer: true,
preventInteractionOnTransition: true,
allowClick: true,
allowTouchMove: true,
slidesPerView: 1,
slidesPerGroup: 1,
spaceBetween: 32,
slideToClickedSlide: true,
navigation: {
nextEl: '#' + this.blockId + '-next',
prevEl: '#' + this.blockId + '-prev',
},
breakpoints: {
498: { slidesPerView: 2 },
768: { slidesPerView: 3 },
1024: { slidesPerView: 4 },
1366: { slidesPerView: 5 },
1600: { slidesPerView: 6 }
},
autoplay: this.autoPlay ? { delay: this.autoPlaySpeed*1000 } : false,
loop: this.loopSlides ? this.loopSlides : false
},
errorMessage: 'No items found.'
}
},
created() {
this.tainacanAxios = axios.create({ baseURL: this.tainacanApiRoot });
if (this.showCollectionHeader)
this.fetchCollectionForHeader();
this.fetchItems();
if (!isNaN(this.maxItemsPerScreen) && this.maxItemsPerScreen != 6) {
this.swiperOptions.breakpoints = {
498: { slidesPerView: this.maxItemsPerScreen - 4 > 0 ? this.maxItemsPerScreen - 4 : 1 },
768: { slidesPerView: this.maxItemsPerScreen - 3 > 0 ? this.maxItemsPerScreen - 3 : 1 },
1024: { slidesPerView: this.maxItemsPerScreen - 2 > 0 ? this.maxItemsPerScreen - 2 : 1 },
1366: { slidesPerView: this.maxItemsPerScreen - 1 > 0 ? this.maxItemsPerScreen - 1 : 1 },
1600: { slidesPerView: this.maxItemsPerScreen > 0 ? this.maxItemsPerScreen : 1 },
}
this.swiperOptions.slidesPerView = 1;
}
},
methods: {
fetchItems() {
this.isLoading = true;
this.errorMessage = 'No items found.';
if (this.itemsRequestSource != undefined && typeof this.itemsRequestSource == 'function')
this.itemsRequestSource.cancel('Previous items search canceled.');
this.itemsRequestSource = axios.CancelToken.source();
if (this.loadStrategy == 'selection') {
let endpoint = '/collection/' + this.collectionId + '/items?' + qs.stringify({ postin: this.selectedItems, perpage: this.selectedItems.length }) + '&fetch_only=title,url,thumbnail';
this.tainacanAxios.get(endpoint, { cancelToken: this.itemsRequestSource.token })
.then(response => {
for (let item of response.data.items)
this.items.push(item);
this.isLoading = false;
this.totalItems = response.headers['x-wp-total'];
}).catch((error) => {
this.isLoading = false;
if (error.response && error.response.status && error.response.status == 401)
this.errorMessage = 'Not allowed to see these items.'
});
} else {
this.items = [];
let endpoint = '/collection' + this.searchURL.split('#')[1].split('/collections')[1];
let query = endpoint.split('?')[1];
let queryObject = qs.parse(query);
// Set up max items to be shown
if (this.maxItemsNumber != undefined && Number(this.maxItemsNumber) > 0)
queryObject.perpage = this.maxItemsNumber;
else if (queryObject.perpage != undefined && queryObject.perpage > 0)
this.localMaxItemsNumber = queryObject.perpage;
else {
queryObject.perpage = 12;
this.localMaxItemsNumber = 12;
}
// Set up paging
if (this.paged != undefined)
queryObject.paged = this.paged;
else if (queryObject.paged != undefined)
this.paged = queryObject.paged;
else
this.paged = 1;
// Remove unecessary queries
delete queryObject.readmode;
delete queryObject.iframemode;
delete queryObject.admin_view_mode;
delete queryObject.fetch_only_meta;
endpoint = endpoint.split('?')[0] + '?' + qs.stringify(queryObject) + '&fetch_only=title,url,thumbnail';
this.tainacanAxios.get(endpoint, { cancelToken: this.itemsRequestSource.token })
.then(response => {
for (let item of response.data.items)
this.items.push(item);
this.isLoading = false;
this.totalItems = response.headers['x-wp-total'];
}).catch((error) => {
this.isLoading = false;
if (error.response && error.response.status && error.response.status == 401)
this.errorMessage = 'Not allowed to see these items.'
});
}
},
fetchCollectionForHeader() {
if (this.showCollectionHeader) {
this.isLoadingCollection = true;
this.tainacanAxios.get('/collections/' + this.collectionId + '?fetch_only=name,thumbnail,header_image')
.then(response => {
this.collection = response.data;
this.isLoadingCollection = false;
});
}
}
}
}
</script>
<style lang="scss">
@import './carousel-related-items.scss';
</style>

View File

@ -2,8 +2,6 @@
.wp-block-tainacan-carousel-related-items { .wp-block-tainacan-carousel-related-items {
margin: 2em auto; margin: 2em auto;
--swiper-navigation-color: var(--tainacan-block-primary, $primary);
--swiper-theme-color: var(--tainacan-block-primary, $primary);
// Spinner // Spinner
.spinner-container { .spinner-container {
@ -46,486 +44,12 @@
animation: skeleton-animation 1.8s ease infinite; animation: skeleton-animation 1.8s ease infinite;
} }
// Collection header // Placeholder on editor side ----------------------------------------------------
.carousel-items-collection-header { .carousel-related-items-edit-container {
display: flex;
width: 100%;
align-items: stretch;
text-decoration: none !important;
margin-bottom: 30px;
&:hover {
text-decoration: none;
}
.collection-name {
width: auto;
min-width: 350px;
flex-grow: 1;
padding: 1em 100px 1em 1em;
text-align: right;
line-height: 1.5em;
min-height: 165px;
display: flex;
justify-content: flex-end;
align-items: center;
background-color: var(--tainacan-block-gray5, $gray5);
h3 {
color: white;
text-decoration: none;
font-size: 1.3em;
margin: 0;
&:hover {
text-decoration: none;
}
}
span.label {
color: white;
font-weight: normal;
font-size: 0.75em;
}
&.only-collection-name {
justify-content: center;
padding: 1em;
h3 {
text-align: center;
font-size: 1.75em;
}
}
}
.collection-thumbnail {
height: 145px;
width: 145px;
background-size: cover;
background-position: center;
border-radius: 80px;
border: 4px solid white;
margin: 10px;
flex-shrink: 0;
position: relative;
margin-left: -155px;
left: 82px;
background-color: var(--tainacan-block-gray2, $gray2);
}
.collection-header-image {
width: auto;
min-width: 150px;
min-height: 165px;
flex-grow: 2;
background-size: cover;
background-position: center;
background-color: var(--tainacan-block-gray2, $gray2);
}
@media only screen and (max-width: 1024px) {
flex-wrap: wrap-reverse;
.collection-name {
width: 100% !important;
min-width: 100% !important;
justify-content: center !important;
text-align: center !important;
padding: 64px 1em 0em 1em;
h3 { margin-bottom: 1em; }
}
.collection-thumbnail {
left: calc(-50% + 78px) !important;
top: -78px !important;
}
.collection-header-image {
background-color: transparent;
}
}
}
// Tainacan Carousel
.tainacan-carousel {
position: relative;
width: calc(100% + 40px);
left: -20px;
.swiper-container {
margin: 0 50px;
a>span,
a:hover>span {
color: var(--tainacan-block-gray5, $gray5);
font-weight: bold;
text-decoration: none;
padding: 8px 16px;
display: block;
line-height: 1.2em;
word-break: break-word;
}
a>img {
width: 100%;
height: auto;
}
a:hover {
text-decoration: none;
}
}
}
.preview-warning {
width: 100%;
font-size: 0.875em;
font-style: italic;
color: var(--tainacan-block-gray4, $gray4);
text-align: center;
margin: 0 auto;
padding: 8px 2px 2px 2px;
}
// Next and previous buttons
.swiper-button-prev, .swiper-button-next {
top: calc(50% - 42px);
bottom: initial;
background: none;
border: none;
width: 42px;
height: 42px;
padding: 0;
margin: 0 -4px;
svg {
fill: var(--tainacan-block-primary, $primary);
}
&::after,
&::before {
content: none !important;
}
}
// Carousel placeholder on editor side ----------------------------------------------------
.items-list-edit-container,
.tainacan-carousel {
position: relative; position: relative;
& .skeleton { & .skeleton {
min-height: 150px; min-height: 150px;
} }
&.has-arrows-none .swiper-button-prev,
&.has-arrows-none .swiper-button-next {
display: none;
}
&.has-arrows-left .swiper-button-next {
left: 10px;
right: auto;
top: calc(50% + 12px) !important;
}
&.has-arrows-right .swiper-button-prev {
right: 10px;
left: auto;
}
&.has-arrows-right .swiper-button-next {
top: calc(50% + 12px) !important;
}
&.has-large-arrows .swiper-button-prev,
&.has-large-arrows .swiper-button-next {
top: calc(50% - 60px);
width: 60px;
height: 60px;
margin: 0 -24px;
}
&.has-large-arrows.has-arrows-left .swiper-button-next {
left: 30px;
right: auto;
top: calc(50% + 30px) !important;
}
&.has-large-arrows.has-arrows-right .swiper-button-prev {
right: 30px;
left: auto;
}
&.has-large-arrows.has-arrows-right .swiper-button-next {
top: calc(50% + 30px) !important;
}
} }
ul.items-list-edit {
display: flex;
align-items: flex-start;
overflow-x: scroll;
list-style: none;
margin: 0 36px;
scroll-snap-type: x mandatory;
scroll-padding-left: 10px;
li.item-list-item {
position: relative;
display: block;
margin: 16px;
width: calc(14.285% - 32px);
min-width: calc(14.285% - 32px);
scroll-snap-align: start;
scroll-margin: 0 16px;
a {
color: var(--tainacan-block-gray5, $gray5);
font-weight: bold;
line-height: normal;
}
img {
height: auto;
display: block;
padding: 0px;
margin-bottom: 0.5em;
}
&:hover a {
color: var(--tainacan-block-gray5, $gray5);
text-decoration: none;
}
button {
position: absolute !important;
background-color: rgba(255, 255, 255, 0.75);
color: var(--tainacan-block-gray5, $gray5);
padding: 2px;
margin-left: 5px;
min-width: 14px;
visibility: hidden;
position: relative;
opacity: 0;
right: -14px;
top: 0px;
justify-content: center;
z-index: 999;
.dashicon { margin: 0px; }
}
&:hover button {
height: auto;
visibility: visible;
background-color: rgba(255, 255, 255, 1) !important;
opacity: 1;
right: -8px;
top: -8px;
border: 1px solid var(--tainacan-block-gray3, $gray3);
border-radius: 12px;
transition: opacity linear 0.15s, right linear 0.15s;
}
&:hover button:hover {
background-color: rgba(255, 255, 255, 1) !important;
border: 1px solid var(--tainacan-block-gray3, $gray3) !important;
}
&.max-itens-per-screen-9 {
width: calc((100% / 9) - 32px);
min-width: calc((100% / 9) - 32px);
}
&.max-itens-per-screen-8 {
width: calc((100% / 8) - 32px);
min-width: calc((100% / 8) - 32px);
}
&.max-itens-per-screen-7 {
width: calc((100% / 7) - 32px);
min-width: calc((100% / 7) - 32px);
}
&.max-itens-per-screen-6 {
width: calc((100% / 6) - 32px);
min-width: calc((100% / 6) - 32px);
}
&.max-itens-per-screen-5 {
width: calc((100% / 5) - 32px);
min-width: calc((100% / 5) - 32px);
}
&.max-itens-per-screen-4 {
width: calc((100% / 4) - 32px);
min-width: calc((100% / 4) - 32px);
}
&.max-itens-per-screen-3 {
width: calc((100% / 3) - 32px);
min-width: calc((100% / 3) - 32px);
}
&.max-itens-per-screen-2 {
width: calc((100% / 2) - 32px);
min-width: calc((100% / 2) - 32px);
}
&.max-itens-per-screen-1 {
width: calc(100% - 32px);
min-width: calc(100% - 32px);
}
}
}
@media only screen and (max-width: 1686px) {
ul.items-list-edit li.item-list-item {
width: calc(16.666% - 32px);
min-width: calc(16.666% - 32px);
&.max-itens-per-screen-9 {
width: calc((100% / 8) - 32px);
min-width: calc((100% / 8) - 32px);
}
&.max-itens-per-screen-8 {
width: calc((100% / 7) - 32px);
min-width: calc((100% / 7) - 32px);
}
&.max-itens-per-screen-7 {
width: calc((100% / 6) - 32px);
min-width: calc((100% / 6) - 32px);
}
&.max-itens-per-screen-6 {
width: calc((100% / 5) - 32px);
min-width: calc((100% / 5) - 32px);
}
&.max-itens-per-screen-5 {
width: calc((100% / 4) - 32px);
min-width: calc((100% / 4) - 32px);
}
&.max-itens-per-screen-4 {
width: calc((100% / 3) - 32px);
min-width: calc((100% / 3) - 32px);
}
&.max-itens-per-screen-3 {
width: calc((100% / 2) - 32px);
min-width: calc((100% / 2) - 32px);
}
&.max-itens-per-screen-2,
&.max-itens-per-screen-1 {
width: calc(100% - 32px);
min-width: calc(100% - 32px);
}
}
}
@media only screen and (max-width: 1452px) {
ul.items-list-edit li.item-list-item {
width: calc(20% - 32px);
min-width: calc(20% - 32px);
&.max-itens-per-screen-9 {
width: calc((100% / 7) - 32px);
min-width: calc((100% / 7) - 32px);
}
&.max-itens-per-screen-8 {
width: calc((100% / 6) - 32px);
min-width: calc((100% / 6) - 32px);
}
&.max-itens-per-screen-7 {
width: calc((100% / 5) - 32px);
min-width: calc((100% / 5) - 32px);
}
&.max-itens-per-screen-6 {
width: calc((100% / 4) - 32px);
min-width: calc((100% / 4) - 32px);
}
&.max-itens-per-screen-5 {
width: calc((100% / 3) - 32px);
min-width: calc((100% / 3) - 32px);
}
&.max-itens-per-screen-4 {
width: calc((100% / 2) - 32px);
min-width: calc((100% / 2) - 32px);
}
&.max-itens-per-screen-3,
&.max-itens-per-screen-2,
&.max-itens-per-screen-1 {
width: calc(100% - 32px);
min-width: calc(100% - 32px);
}
}
}
@media only screen and (max-width: 1118px) {
ul.items-list-edit li.item-list-item {
width: calc(25% - 32px);
min-width: calc(25% - 32px);
&.max-itens-per-screen-9 {
width: calc((100% / 6) - 32px);
min-width: calc((100% / 6) - 32px);
}
&.max-itens-per-screen-8 {
width: calc((100% / 5) - 32px);
min-width: calc((100% / 5) - 32px);
}
&.max-itens-per-screen-7 {
width: calc((100% / 4) - 32px);
min-width: calc((100% / 4) - 32px);
}
&.max-itens-per-screen-6 {
width: calc((100% / 3) - 32px);
min-width: calc((100% / 3) - 32px);
}
&.max-itens-per-screen-5 {
width: calc((100% / 2) - 32px);
min-width: calc((100% / 2) - 32px);
}
&.max-itens-per-screen-4,
&.max-itens-per-screen-3,
&.max-itens-per-screen-2,
&.max-itens-per-screen-1 {
width: calc(100% - 32px);
min-width: calc(100% - 32px);
}
}
}
@media only screen and (max-width: 854px) {
ul.items-list-edit li.item-list-item {
width: calc(33.333% - 32px);
min-width: calc(33.333% - 32px);
&.max-itens-per-screen-9 {
width: calc((100% / 5) - 32px);
min-width: calc((100% / 5) - 32px);
}
&.max-itens-per-screen-8 {
width: calc((100% / 4) - 32px);
min-width: calc((100% / 4) - 32px);
}
&.max-itens-per-screen-7 {
width: calc((100% / 3) - 32px);
min-width: calc((100% / 3) - 32px);
}
&.max-itens-per-screen-6 {
width: calc((100% / 2) - 32px);
min-width: calc((100% / 2) - 32px);
}
&.max-itens-per-screen-5,
&.max-itens-per-screen-4,
&.max-itens-per-screen-3,
&.max-itens-per-screen-2,
&.max-itens-per-screen-1 {
width: calc(100% - 32px);
min-width: calc(100% - 32px);
}
}
}
@media only screen and (max-width: 584px) {
ul.items-list-edit li.item-list-item {
width: calc(50% - 32px);
min-width: calc(50% - 32px);
&.max-itens-per-screen-9 {
width: calc((100% / 4) - 32px);
min-width: calc((100% / 4) - 32px);
}
&.max-itens-per-screen-8 {
width: calc((100% / 3) - 32px);
min-width: calc((100% / 3) - 32px);
}
&.max-itens-per-screen-7 {
width: calc((100% / 2) - 32px);
min-width: calc((100% / 2) - 32px);
}
&.max-itens-per-screen-6,
&.max-itens-per-screen-5,
&.max-itens-per-screen-4,
&.max-itens-per-screen-3,
&.max-itens-per-screen-2,
&.max-itens-per-screen-1 {
width: calc(100% - 32px);
min-width: calc(100% - 32px);
}
}
}
} }

View File

@ -4,7 +4,7 @@ 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, ColorPicker, ColorPalette, BaseControl, PanelBody } = wp.components;
const { InspectorControls, BlockControls } = ( tainacan_blocks.wp_version < '5.2' ? wp.editor : wp.blockEditor ); const { InspectorControls, BlockControls, InnerBlocks } = ( tainacan_blocks.wp_version < '5.2' ? wp.editor : wp.blockEditor );
import CarouselRelatedItemsModal from './carousel-related-items-modal.js'; import CarouselRelatedItemsModal from './carousel-related-items-modal.js';
import tainacan from '../../js/axios.js'; import tainacan from '../../js/axios.js';
@ -29,25 +29,20 @@ registerBlockType('tainacan/carousel-related-items', {
</svg>, </svg>,
category: 'tainacan-blocks', category: 'tainacan-blocks',
keywords: [ __( 'items', 'tainacan' ), __( 'carousel', 'tainacan' ), __( 'slider', 'tainacan' ), __( 'relationship', 'tainacan' ) ], keywords: [ __( 'items', 'tainacan' ), __( 'carousel', 'tainacan' ), __( 'slider', 'tainacan' ), __( 'relationship', 'tainacan' ) ],
description: __('A carousel do list items related to a certain item via relationship metadata.', 'tainacan'), description: __('A set of carousels to list items related to a certain item via relationship metadata.', 'tainacan'),
example: { example: {
attributes: { attributes: {
content: 'preview' content: 'preview'
} }
}, },
attributes: { attributes: {
content: {
type: 'array',
source: 'children',
selector: 'div'
},
collectionId: { collectionId: {
type: String, type: String,
default: undefined default: undefined
}, },
items: { itemId: {
type: Array, type: String,
default: [] default: undefined
}, },
isModalOpen: { isModalOpen: {
type: Boolean, type: Boolean,
@ -57,168 +52,31 @@ registerBlockType('tainacan/carousel-related-items', {
type: String, type: String,
default: undefined default: undefined
}, },
selectedItems: { relatedItems: {
type: Array, type: Array,
default: [] default: []
}, },
itemsRequestSource: { itemRequestSource: {
type: String, type: String,
default: undefined default: undefined
}, },
maxItemsNumber: {
type: Number,
value: undefined
},
maxItemsPerScreen: {
type: Number,
value: 7
},
isLoading: {
type: Boolean,
value: false
},
isLoadingCollection: {
type: Boolean,
value: false
},
loadStrategy: {
type: String,
value: 'search'
},
arrowsPosition: {
type: String,
value: 'search'
},
largeArrows: {
type: Boolean,
value: false
},
autoPlay: {
type: Boolean,
value: false
},
autoPlaySpeed: {
type: Number,
value: 3
},
loopSlides: {
type: Boolean,
value: false
},
hideTitle: {
type: Boolean,
value: true
},
showCollectionHeader: {
type: Boolean,
value: false
},
showCollectionLabel: {
type: Boolean,
value: false
},
cropImagesToSquare: {
type: Boolean,
value: true
},
collection: {
type: Object,
value: undefined
},
blockId: {
type: String,
default: undefined
},
collectionBackgroundColor: {
type: String,
default: "#454647"
},
collectionTextColor: {
type: String,
default: "#ffffff"
}
}, },
supports: { supports: {
align: ['full', 'wide'], align: ['full', 'wide'],
html: false, html: false,
multiple: true, multiple: true,
fontSize: true
}, },
edit({ attributes, setAttributes, className, isSelected, clientId }){ edit({ attributes, setAttributes, className, isSelected }){
let { let {
items,
content, content,
collectionId, collectionId,
itemId,
isModalOpen, isModalOpen,
searchURL, relatedItems,
itemsRequestSource,
maxItemsNumber,
maxItemsPerScreen,
selectedItems,
isLoading, isLoading,
loadStrategy, itemRequestSource
arrowsPosition,
largeArrows,
autoPlay,
autoPlaySpeed,
loopSlides,
hideTitle,
cropImagesToSquare,
showCollectionHeader,
showCollectionLabel,
isLoadingCollection,
collection,
collectionBackgroundColor,
collectionTextColor
} = attributes; } = attributes;
// Obtains block's client id to render it on save function
setAttributes({ blockId: clientId });
const thumbHelper = ThumbnailHelperFunctions();
// Sets some defaults that were not working
if (maxItemsPerScreen === undefined) {
maxItemsPerScreen = 7;
setAttributes({ maxItemsPerScreen: maxItemsPerScreen });
}
if (cropImagesToSquare === undefined) {
cropImagesToSquare = true;
setAttributes({ cropImagesToSquare: cropImagesToSquare });
}
function prepareItem(item) {
return (
<li
key={ item.id }
className={ 'item-list-item ' + (maxItemsPerScreen ? 'max-itens-per-screen-' + maxItemsPerScreen : '') }>
{ loadStrategy == 'selection' ?
( tainacan_blocks.wp_version < '5.4' ?
<IconButton
onClick={ () => removeItemOfId(item.id) }
icon="no-alt"
label={__('Remove', 'tainacan')}/>
:
<Button
onClick={ () => removeItemOfId(item.id) }
icon="no-alt"
label={__('Remove', 'tainacan')}/>
)
:null
}
<a
id={ isNaN(item.id) ? item.id : 'item-id-' + item.id }
href={ item.url }
target="_blank">
<img
src={ thumbHelper.getSrc(item['thumbnail'], (maxItemsPerScreen > 4 ? (!cropImagesToSquare ? 'tainacan-medium-full' : 'tainacan-medium') : 'large'), item['document_mimetype']) }
srcset={ thumbHelper.getSrcSet(item['thumbnail'], (maxItemsPerScreen > 4 ? (!cropImagesToSquare ? 'tainacan-medium-full' : 'tainacan-medium') : 'large'), item['document_mimetype']) }
alt={ item.thumbnail_alt ? item.thumbnail_alt : (item && item.title ? item.title : $root.__( 'Thumbnail', 'tainacan' )) }/>
{ !hideTitle ? <span>{ item.title ? item.title : '' }</span> : null }
</a>
</li>
);
}
function setContent(){ function setContent(){
isLoading = true; isLoading = true;
@ -226,130 +84,34 @@ registerBlockType('tainacan/carousel-related-items', {
isLoading: isLoading isLoading: isLoading
}); });
if (itemsRequestSource != undefined && typeof itemsRequestSource == 'function') if (itemRequestSource != undefined && typeof itemRequestSource == 'function')
itemsRequestSource.cancel('Previous items search canceled.'); itemRequestSource.cancel('Previous items search canceled.');
itemsRequestSource = axios.CancelToken.source(); itemRequestSource = axios.CancelToken.source();
items = []; let endpoint = '/collection/' + collectionId + '/items?'+ itemId;
if (loadStrategy == 'selection') { tainacan.get(endpoint, { cancelToken: itemRequestSource.token })
let endpoint = '/collection/' + collectionId + '/items?'+ qs.stringify({ postin: selectedItems, perpage: selectedItems.length }) + '&fetch_only=title,url,thumbnail'; .then(response => {
tainacan.get(endpoint, { cancelToken: itemsRequestSource.token }) let relatedItems = [];
.then(response => { //relatedItems = response.data.item.related_items;
for (let item of response.data.items) setAttributes({
items.push(prepareItem(item)); relatedItems: relatedItems,
isLoading: false,
setAttributes({ itemRequestSource: itemRequestSource
content: <div></div>,
items: items,
isLoading: false,
itemsRequestSource: itemsRequestSource
});
}); });
} else {
let endpoint = '/collection' + searchURL.split('#')[1].split('/collections')[1];
let query = endpoint.split('?')[1];
let queryObject = qs.parse(query);
// Set up max items to be shown
if (maxItemsNumber != undefined && maxItemsNumber > 0)
queryObject.perpage = maxItemsNumber;
else if (queryObject.perpage != undefined && queryObject.perpage > 0)
setAttributes({ maxItemsNumber: queryObject.perpage });
else {
queryObject.perpage = 12;
setAttributes({ maxItemsNumber: 12 });
}
// Remove unecessary queries
delete queryObject.readmode;
delete queryObject.iframemode;
delete queryObject.admin_view_mode;
delete queryObject.fetch_only_meta;
endpoint = endpoint.split('?')[0] + '?' + qs.stringify(queryObject) + '&fetch_only=title,url,thumbnail';
tainacan.get(endpoint, { cancelToken: itemsRequestSource.token })
.then(response => {
for (let item of response.data.items)
items.push(prepareItem(item));
setAttributes({
content: <div></div>,
items: items,
isLoading: false,
itemsRequestSource: itemsRequestSource
});
});
}
}
function fetchCollectionForHeader() {
if (showCollectionHeader) {
isLoadingCollection = true;
setAttributes({
isLoadingCollection: isLoadingCollection
}); });
tainacan.get('/collections/' + collectionId + '?fetch_only=name,thumbnail,header_image')
.then(response => {
collection = response.data;
isLoadingCollection = false;
if (collection.tainacan_theme_collection_background_color)
collectionBackgroundColor = collection.tainacan_theme_collection_background_color;
else
collectionBackgroundColor = '#454647';
if (collection.tainacan_theme_collection_color)
collectionTextColor = collection.tainacan_theme_collection_color;
else
collectionTextColor = '#ffffff';
setAttributes({
content: <div></div>,
collection: collection,
isLoadingCollection: isLoadingCollection,
collectionBackgroundColor: collectionBackgroundColor,
collectionTextColor: collectionTextColor
});
});
}
} }
function openCarouseltemsModal(aLoadStrategy) { function openRelatedItemsModal() {
loadStrategy = aLoadStrategy;
isModalOpen = true; isModalOpen = true;
setAttributes( { setAttributes( {
isModalOpen: isModalOpen, isModalOpen: isModalOpen
loadStrategy: loadStrategy
} ); } );
} }
function removeItemOfId(itemId) {
let existingItemIndex = items.findIndex((existingItem) => existingItem.key == itemId);
if (existingItemIndex >= 0)
items.splice(existingItemIndex, 1);
let existingSelectedItemIndex = selectedItems.findIndex((existingSelectedItem) => existingSelectedItem == itemId);
if (existingSelectedItemIndex >= 0)
selectedItems.splice(existingSelectedItemIndex, 1);
setAttributes({
selectedItems: selectedItems,
items: items,
content: <div></div>
});
}
// Executed only on the first load of page // Executed only on the first load of page
if(content && content.length && content[0].type) if(content && content.length && content[0].type)
setContent(); setContent();
@ -363,9 +125,9 @@ registerBlockType('tainacan/carousel-related-items', {
: ( : (
<div className={className}> <div className={className}>
{ items.length ? { relatedItems.length ?
<BlockControls> <BlockControls>
{ loadStrategy != 'search' ? {
TainacanBlocksCompatToolbar({ TainacanBlocksCompatToolbar({
label: __('Add more items', 'tainacan'), label: __('Add more items', 'tainacan'),
icon: <svg icon: <svg
@ -375,207 +137,14 @@ registerBlockType('tainacan/carousel-related-items', {
width="24px"> width="24px">
<path d="M16,6H12a2,2,0,0,0-2,2v6.52A6,6,0,0,1,12,19a6,6,0,0,1-.73,2.88A1.92,1.92,0,0,0,12,22h8a2,2,0,0,0,2-2V12Zm-1,6V7.5L19.51,12ZM15,2V4H8v9.33A5.8,5.8,0,0,0,6,13V4A2,2,0,0,1,8,2ZM10.09,19.05,7,22.11V16.05L8,17l2,2ZM5,16.05v6.06L2,19.11Z"/> <path d="M16,6H12a2,2,0,0,0-2,2v6.52A6,6,0,0,1,12,19a6,6,0,0,1-.73,2.88A1.92,1.92,0,0,0,12,22h8a2,2,0,0,0,2-2V12Zm-1,6V7.5L19.51,12ZM15,2V4H8v9.33A5.8,5.8,0,0,0,6,13V4A2,2,0,0,1,8,2ZM10.09,19.05,7,22.11V16.05L8,17l2,2ZM5,16.05v6.06L2,19.11Z"/>
</svg>, </svg>,
onClick: openCarouseltemsModal, onClick: openRelatedItemsModal
onClickParams: 'selection'
}) })
:
TainacanBlocksCompatToolbar({
label: __('Configure a search', 'tainacan'),
icon: <svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
height="24px"
width="24px">
<path d="M16,6H12a2,2,0,0,0-2,2v6.52A6,6,0,0,1,12,19a6,6,0,0,1-.73,2.88A1.92,1.92,0,0,0,12,22h8a2,2,0,0,0,2-2V12Zm-1,6V7.5L19.51,12ZM15,2V4H8v9.33A5.8,5.8,0,0,0,6,13V4A2,2,0,0,1,8,2ZM10.09,19.05,7,22.11V16.05L8,17l2,2ZM5,16.05v6.06L2,19.11Z"/>
</svg>,
onClick: openCarouseltemsModal,
onClickParams: 'search'
})
} }
</BlockControls> </BlockControls>
: null } : null }
<div> <div>
<InspectorControls> <InspectorControls>
SAY WHAAT
<PanelBody
title={__('Collection header', 'tainacan')}
initialOpen={ false }
>
<ToggleControl
label={__('Display header', 'tainacan')}
help={ !showCollectionHeader ? __('Toggle to show collection header', 'tainacan') : __('Do not show collection header', 'tainacan')}
checked={ showCollectionHeader }
onChange={ ( isChecked ) => {
showCollectionHeader = isChecked;
if (isChecked) fetchCollectionForHeader();
setAttributes({ showCollectionHeader: showCollectionHeader });
}
}
/>
{ showCollectionHeader ?
<div style={{ margin: '6px' }}>
<ToggleControl
label={__('Display "Collection" label', 'tainacan')}
help={ !showCollectionLabel ? __('Toggle to show "Collection" label above header', 'tainacan') : __('Do not show "Collection" label', 'tainacan')}
checked={ showCollectionLabel }
onChange={ ( isChecked ) => {
showCollectionLabel = isChecked;
setAttributes({ showCollectionLabel: showCollectionLabel });
}
}
/>
<BaseControl
id="colorpicker"
label={ __('Background color', 'tainacan')}>
<ColorPicker
color={ collectionBackgroundColor }
onChangeComplete={ ( value ) => {
collectionBackgroundColor = value.hex;
setAttributes({ collectionBackgroundColor: collectionBackgroundColor })
}}
disableAlpha
/>
</BaseControl>
<BaseControl
id="colorpallete"
label={ __('Collection name color', 'tainacan')}>
<ColorPalette
colors={ [{ name: __('Black', 'tainacan'), color: '#000000'}, { name: __('White', 'tainacan'), color: '#ffffff'} ] }
value={ collectionTextColor }
onChange={ ( color ) => {
collectionTextColor = color;
setAttributes({ collectionTextColor: collectionTextColor })
}}
/>
</BaseControl>
</div>
: null
}
</PanelBody>
<PanelBody
title={__('Carousel', 'tainacan')}
initialOpen={ true }
>
<div>
<RangeControl
label={ __('Maximum items per slide on a wide screen', 'tainacan') }
help={ maxItemsPerScreen <= 4 ? __('Warning: with such a small number of items per slide, the image size is greater, thus the cropped version of the thumbnail won\'t be used.', 'tainacan') : null }
value={ maxItemsPerScreen ? maxItemsPerScreen : 7 }
onChange={ ( aMaxItemsPerScreen ) => {
maxItemsPerScreen = aMaxItemsPerScreen;
setAttributes( { maxItemsPerScreen: aMaxItemsPerScreen } );
setContent();
}}
min={ 1 }
max={ 9 }
/>
<ToggleControl
label={__('Crop Images', 'tainacan')}
help={ cropImagesToSquare && maxItemsPerScreen > 4 ? __('Do not use square cropeed version of the item thumbnail.', 'tainacan') : __('Toggle to use square cropped version of the item thumbnail.', 'tainacan') }
checked={ cropImagesToSquare && maxItemsPerScreen > 4 }
onChange={ ( isChecked ) => {
cropImagesToSquare = isChecked;
setAttributes({ cropImagesToSquare: cropImagesToSquare });
setContent();
}
}
/>
<ToggleControl
label={__('Hide title', 'tainacan')}
help={ !hideTitle ? __('Toggle to hide item\'s title', 'tainacan') : __('Do not hide item\'s title', 'tainacan')}
checked={ hideTitle }
onChange={ ( isChecked ) => {
hideTitle = isChecked;
setAttributes({ hideTitle: hideTitle });
setContent();
}
}
/>
<ToggleControl
label={__('Loop slides', 'tainacan')}
help={ !loopSlides ? __('Toggle to make slides loop from first to last', 'tainacan') : __('Do not loop slides from first to last', 'tainacan')}
checked={ loopSlides }
onChange={ ( isChecked ) => {
loopSlides = isChecked;
setAttributes({ loopSlides: loopSlides });
}
}
/>
<ToggleControl
label={__('Auto play', 'tainacan')}
help={ !autoPlay ? __('Toggle to automatically slide to the next item', 'tainacan') : __('Do not automatically slide to the next item', 'tainacan')}
checked={ autoPlay }
onChange={ ( isChecked ) => {
autoPlay = isChecked;
setAttributes({ autoPlay: autoPlay });
}
}
/>
{
autoPlay ?
<RangeControl
label={__('Seconds before sliding to the next', 'tainacan')}
value={ autoPlaySpeed }
onChange={ ( aAutoPlaySpeed ) => {
autoPlaySpeed = aAutoPlaySpeed;
setAttributes( { autoPlaySpeed: aAutoPlaySpeed } )
}}
min={ 1 }
max={ 5 }
/>
: null
}
<SelectControl
label={__('Arrows', 'tainacan')}
value={ arrowsPosition }
options={ [
{ label: __('Around', 'tainacan'), value: 'around' },
{ label: __('Left', 'tainacan'), value: 'left' },
{ label: __('Right', 'tainacan'), value: 'right' }
] }
onChange={ ( aPosition ) => {
arrowsPosition = aPosition;
setAttributes({ arrowsPosition: arrowsPosition });
}}/>
<ToggleControl
label={__('Large arrows', 'tainacan')}
help={ !largeArrows ? __('Toggle to display arrows bigger than the default size.', 'tainacan') : __('Do not show arrows bigger than the default size.', 'tainacan')}
checked={ largeArrows }
onChange={ ( isChecked ) => {
largeArrows = isChecked;
setAttributes({ largeArrows: largeArrows });
}
}
/>
</div>
</PanelBody>
{ loadStrategy == 'search' ?
<PanelBody
title={__('Item\'s Search', 'tainacan')}
initialOpen={ true }
>
<div>
<RangeControl
label={__('Maximum number of items to load', 'tainacan')}
value={ maxItemsNumber }
onChange={ ( aMaxItemsNumber ) => {
maxItemsNumber = aMaxItemsNumber;
setAttributes( { maxItemsNumber: aMaxItemsNumber } )
setContent();
}}
min={ 1 }
max={ 96 }
/>
</div>
</PanelBody>
:null
}
</InspectorControls> </InspectorControls>
</div> </div>
@ -584,37 +153,25 @@ registerBlockType('tainacan/carousel-related-items', {
<div> <div>
{ isModalOpen ? { isModalOpen ?
<CarouselRelatedItemsModal <CarouselRelatedItemsModal
loadStrategy={ loadStrategy }
existingCollectionId={ collectionId } existingCollectionId={ collectionId }
existingSearchURL={ loadStrategy == 'search' ? searchURL : false } existingItemId={ itemId }
onSelectCollection={ (selectedCollectionId) => { onSelectCollection={ (selectedCollectionId) => {
if (collectionId != selectedCollectionId) { if (collectionId != selectedCollectionId)
items = []; relatedItems = [];
selectedItems = [];
}
collectionId = selectedCollectionId; collectionId = selectedCollectionId;
setAttributes({ setAttributes({
collectionId: collectionId, collectionId: collectionId,
items: items, relatedItems: relatedItems
selectedItems: selectedItems
}); });
}} }}
onApplySearchURL={ (aSearchURL) => { onApplyRelatedItem={ (selectedItemId) => {
searchURL = aSearchURL; if (itemId != selectedItemId)
loadStrategy = 'search'; relatedItems = [];
itemId = selectedItemId;
setAttributes({ setAttributes({
searchURL: searchURL, itemId: itemId,
loadStrategy: loadStrategy,
isModalOpen: false
});
setContent();
}}
onApplySelectedItems={ (aSelectionOfItems) => {
selectedItems = selectedItems.concat(aSelectionOfItems);
loadStrategy = 'selection';
setAttributes({
selectedItems: selectedItems,
loadStrategy: loadStrategy,
isModalOpen: false isModalOpen: false
}); });
setContent(); setContent();
@ -627,57 +184,7 @@ registerBlockType('tainacan/carousel-related-items', {
) : null ) : null
} }
{ { !relatedItems.length && !isLoading ? (
showCollectionHeader ?
<div> {
isLoadingCollection ?
<div class="spinner-container">
<Spinner />
</div>
:
<a
href={ collection.url ? collection.url : '' }
target="_blank"
class="carousel-items-collection-header">
<div
style={{
backgroundColor: collectionBackgroundColor ? collectionBackgroundColor : '',
paddingRight: collection && collection.thumbnail && (collection.thumbnail['tainacan-medium'] || collection.thumbnail['medium']) ? '' : '20px',
paddingTop: (!collection || !collection.thumbnail || (!collection.thumbnail['tainacan-medium'] && !collection.thumbnail['medium'])) ? '1rem' : '',
width: collection && collection.header_image ? '' : '100%'
}}
className={
'collection-name ' +
((!collection || !collection.thumbnail || (!collection.thumbnail['tainacan-medium'] && !collection.thumbnail['medium'])) && (!collection || !collection.header_image) ? 'only-collection-name' : '')
}>
<h3 style={{ color: collectionTextColor ? collectionTextColor : '' }}>
{ showCollectionLabel ? <span class="label">{ __('Collection', 'tainacan') }<br/></span> : null }
{ collection && collection.name ? collection.name : '' }
</h3>
</div>
{
collection && collection.thumbnail && (collection.thumbnail['tainacan-medium'] || collection.thumbnail['medium']) ?
<div
class="collection-thumbnail"
style={{
backgroundImage: 'url(' + (collection.thumbnail['tainacan-medium'] != undefined ? (collection.thumbnail['tainacan-medium'][0]) : (collection.thumbnail['medium'][0])) + ')',
}}/>
: null
}
<div
class="collection-header-image"
style={{
backgroundImage: collection.header_image ? 'url(' + collection.header_image + ')' : '',
minHeight: collection && collection.header_image ? '' : '80px',
display: !(collection && collection.thumbnail && (collection.thumbnail['tainacan-medium'] || collection.thumbnail['medium'])) ? collection && collection.header_image ? '' : 'none' : ''
}}/>
</a>
}
</div>
: null
}
{ !items.length && !isLoading ? (
<Placeholder <Placeholder
className="tainacan-block-placeholder" className="tainacan-block-placeholder"
icon={( icon={(
@ -699,16 +206,9 @@ registerBlockType('tainacan/carousel-related-items', {
<Button <Button
isPrimary isPrimary
type="button" type="button"
onClick={ () => openCarouseltemsModal('selection') }> onClick={ () => openRelatedItemsModal() }>
{__('Select Items', 'tainacan')} {__('Select Items', 'tainacan')}
</Button> </Button>
<p style={{ margin: '0 12px' }}>{__('or', 'tainacan')}</p>
<Button
isPrimary
type="button"
onClick={ () => openCarouseltemsModal('search') }>
{__('Configure a search', 'tainacan')}
</Button>
</Placeholder> </Placeholder>
) : null ) : null
} }
@ -718,106 +218,33 @@ registerBlockType('tainacan/carousel-related-items', {
<Spinner /> <Spinner />
</div> : </div> :
<div> <div>
{ isSelected && items.length ? { relatedItems.length ? (
<div class="preview-warning">{__('Warning: this is just a demonstration. To see the carousel in action, either preview or publish your post.', 'tainacan')}</div>
: null
}
{ items.length ? (
<div <div className={ 'carousel-related-items-edit-container' }>
className={'items-list-edit-container ' + (arrowsPosition ? ' has-arrows-' + arrowsPosition : '') + (largeArrows ? ' has-large-arrows' : '') }> <InnerBlocks
<button allowedBlocks={[
class="swiper-button-prev" 'core/heading',
slot="button-prev" 'core/paragraph',
style={{ cursor: 'not-allowed' }}> 'tainacan/carousel-items-list',
<svg 'core/buttons'
width={ largeArrows ? 60 : 42 } ]}
height={ largeArrows ? 60 : 42 } template={[
viewBox="0 0 24 24"> [ 'core/heading', { placeholder: 'Book Title' } ],
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/> [ 'core/paragraph', { placeholder: 'Summary' } ],
<path [ 'tainacan/carousel-items-list', { content: [{ type: 'innerblock' }], relatedItems: ['131051', '131516', '131228', '131517'], loadStrategy: 'selection', collectionId: '130957' } ],
d="M0 0h24v24H0z" [ 'core/buttons', {} ]
fill="none"/> ]} />
</svg>
</button>
<ul
style={{
marginTop: showCollectionHeader ? '1.5rem' : '0px'
}}
className={ 'items-list-edit' }>
{ items }
</ul>
<button
class="swiper-button-next"
slot="button-next"
style={{ cursor: 'not-allowed' }}>
<svg
width={ largeArrows ? 60 : 42 }
height={ largeArrows ? 60 : 42 }
viewBox="0 0 24 24">
<path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/>
<path
d="M0 0h24v24H0z"
fill="none"/>
</svg>
</button>
</div> </div>
):null ) : null
} }
</div> </div>
} }
</div> </div>
); );
}, },
save({ attributes, className }){ save({ className }){
const { return <div className={ className }><InnerBlocks.Content /></div>
content,
blockId,
collectionId,
searchURL,
selectedItems,
arrowsPosition,
largeArrows,
loadStrategy,
maxItemsNumber,
maxItemsPerScreen,
autoPlay,
autoPlaySpeed,
loopSlides,
hideTitle,
cropImagesToSquare,
showCollectionHeader,
showCollectionLabel,
collectionBackgroundColor,
collectionTextColor
} = attributes;
return <div
className={ className }
search-url={ searchURL }
selected-items={ JSON.stringify(selectedItems) }
arrows-position={ arrowsPosition }
load-strategy={ loadStrategy }
collection-id={ collectionId }
auto-play={ '' + autoPlay }
auto-play-speed={ autoPlaySpeed }
loop-slides={ '' + loopSlides }
hide-title={ '' + hideTitle }
large-arrows={ '' + largeArrows }
crop-images-to-square={ '' + cropImagesToSquare }
show-collection-header={ '' + showCollectionHeader }
show-collection-label={ '' + showCollectionLabel }
collection-background-color={ collectionBackgroundColor }
collection-text-color={ collectionTextColor }
max-items-number={ maxItemsNumber }
max-items-per-screen={ maxItemsPerScreen }
tainacan-api-root={ tainacan_blocks.root }
tainacan-base-url={ tainacan_blocks.base_url }
id={ 'wp-block-tainacan-carousel-items-list_' + blockId }>
{ content }
</div>
}, },
deprecated: DeprecatedBlocks deprecated: DeprecatedBlocks
}); });

View File

@ -30,8 +30,7 @@ module.exports = {
block_carousel_collections_list_theme: './src/views/gutenberg-blocks/tainacan-collections/carousel-collections-list/carousel-collections-list-theme.js', block_carousel_collections_list_theme: './src/views/gutenberg-blocks/tainacan-collections/carousel-collections-list/carousel-collections-list-theme.js',
block_carousel_related_items: './src/views/gutenberg-blocks/tainacan-items/carousel-related-items/index.js', block_carousel_related_items: './src/views/gutenberg-blocks/tainacan-items/carousel-related-items/index.js',
block_carousel_related_items_theme: './src/views/gutenberg-blocks/tainacan-items/carousel-related-items/carousel-related-items-theme.js',
block_facets_list: './src/views/gutenberg-blocks/tainacan-facets/facets-list/index.js', block_facets_list: './src/views/gutenberg-blocks/tainacan-facets/facets-list/index.js',
block_facets_list_theme: './src/views/gutenberg-blocks/tainacan-facets/facets-list/facets-list-theme.js', block_facets_list_theme: './src/views/gutenberg-blocks/tainacan-facets/facets-list/facets-list-theme.js',