diff --git a/compile-sass.sh b/compile-sass.sh
index 88be95d24..24fd5c724 100644
--- a/compile-sass.sh
+++ b/compile-sass.sh
@@ -40,7 +40,9 @@ sass -E 'UTF-8' --cache-location .tmp/sass-cache-15 src/views/gutenberg-blocks/t
sass -E 'UTF-8' --cache-location .tmp/sass-cache-16 src/views/gutenberg-blocks/tainacan-items/item-submission-form/item-submission-form.scss:src/assets/css/tainacan-gutenberg-block-item-submission-form.css
-sass -E 'UTF-8' --cache-location .tmp/sass-cache-17 src/views/gutenberg-blocks/gutenberg-blocks-style.scss:src/assets/css/tainacan-gutenberg-block-common-styles.css
+sass -E 'UTF-8' --cache-location .tmp/sass-cache-17 src/views/gutenberg-blocks/tainacan-items/carousel-related-items/carousel-related-items.scss:src/assets/css/tainacan-gutenberg-block-carousel-related-items.css
+
+sass -E 'UTF-8' --cache-location .tmp/sass-cache-18 src/views/gutenberg-blocks/gutenberg-blocks-style.scss:src/assets/css/tainacan-gutenberg-block-common-styles.css
echo "Compilação do Sass Concluído!"
exit 0
diff --git a/src/assets/css/tainacan-gutenberg-block-carousel-collections-list.css b/src/assets/css/tainacan-gutenberg-block-carousel-collections-list.css
index 2e79500dc..0f7a64ac2 100644
--- a/src/assets/css/tainacan-gutenberg-block-carousel-collections-list.css
+++ b/src/assets/css/tainacan-gutenberg-block-carousel-collections-list.css
@@ -122,7 +122,7 @@
color: var(--tainacan-block-gray5, #454647);
font-weight: bold;
text-decoration: none;
- padding: 8px 16px;
+ padding: 8px 12px;
display: block;
line-height: 1.2em;
word-break: break-word; }
diff --git a/src/assets/css/tainacan-gutenberg-block-carousel-items-list.css b/src/assets/css/tainacan-gutenberg-block-carousel-items-list.css
index de71369db..9f374daac 100644
--- a/src/assets/css/tainacan-gutenberg-block-carousel-items-list.css
+++ b/src/assets/css/tainacan-gutenberg-block-carousel-items-list.css
@@ -129,7 +129,7 @@
color: var(--tainacan-block-gray5, #454647);
font-weight: bold;
text-decoration: none;
- padding: 8px 16px;
+ padding: 8px 12px;
display: block;
line-height: 1.2em;
word-break: break-word; }
diff --git a/src/assets/css/tainacan-gutenberg-block-carousel-related-items.css b/src/assets/css/tainacan-gutenberg-block-carousel-related-items.css
new file mode 100644
index 000000000..ea7dfd802
--- /dev/null
+++ b/src/assets/css/tainacan-gutenberg-block-carousel-related-items.css
@@ -0,0 +1,51 @@
+.wp-block-tainacan-carousel-related-items {
+ margin: 0.5em auto;
+ width: 100%; }
+ .wp-block-tainacan-carousel-related-items .spinner-container {
+ min-height: 56px;
+ padding: 1em;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ color: var(--tainacan-block-gray4, #555758); }
+@-webkit-keyframes skeleton-animation {
+ 0% {
+ opacity: 1.0; }
+ 50% {
+ opacity: 0.2; }
+ 100% {
+ opacity: 1.0; } }
+@-moz-keyframes skeleton-animation {
+ 0% {
+ opacity: 1.0; }
+ 50% {
+ opacity: 0.2; }
+ 100% {
+ opacity: 1.0; } }
+@-o-keyframes skeleton-animation {
+ 0% {
+ opacity: 1.0; }
+ 50% {
+ opacity: 0.2; }
+ 100% {
+ opacity: 1.0; } }
+@keyframes skeleton-animation {
+ 0% {
+ opacity: 1.0; }
+ 50% {
+ opacity: 0.2; }
+ 100% {
+ opacity: 1.0; } }
+ .wp-block-tainacan-carousel-related-items .skeleton {
+ border-radius: 2px;
+ background: var(--tainacan-block-gray1, #f2f2f2);
+ -webkit-animation: skeleton-animation 1.8s ease infinite;
+ -moz-animation: skeleton-animation 1.8s ease infinite;
+ -o-animation: skeleton-animation 1.8s ease infinite;
+ animation: skeleton-animation 1.8s ease infinite; }
+ .wp-block-tainacan-carousel-related-items .carousel-related-items-edit-container {
+ position: relative; }
+ .wp-block-tainacan-carousel-related-items .carousel-related-items-edit-container .skeleton {
+ min-height: 150px; }
+
+/*# sourceMappingURL=tainacan-gutenberg-block-carousel-related-items.css.map */
diff --git a/src/assets/css/tainacan-gutenberg-block-carousel-related-items.css.map b/src/assets/css/tainacan-gutenberg-block-carousel-related-items.css.map
new file mode 100644
index 000000000..a62d01597
--- /dev/null
+++ b/src/assets/css/tainacan-gutenberg-block-carousel-related-items.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "AAEA,yCAA0C;EACtC,MAAM,EAAE,UAAU;EAClB,KAAK,EAAE,IAAI;EAGX,4DAAmB;IACf,UAAU,EAAE,IAAI;IAChB,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,IAAI;IACb,eAAe,EAAE,MAAM;IACvB,WAAW,EAAE,MAAM;IACnB,KAAK,EAAE,oCAAmC;AAI9C,qCAIC;EAHG,EAAE;IAAC,OAAO,EAAE,GAAG;EACf,GAAG;IAAC,OAAO,EAAE,GAAG;EAChB,IAAI;IAAC,OAAO,EAAE,GAAG;AAErB,kCAIC;EAHG,EAAE;IAAC,OAAO,EAAE,GAAG;EACf,GAAG;IAAC,OAAO,EAAE,GAAG;EAChB,IAAI;IAAC,OAAO,EAAE,GAAG;AAErB,gCAIC;EAHG,EAAE;IAAC,OAAO,EAAE,GAAG;EACf,GAAG;IAAC,OAAO,EAAE,GAAG;EAChB,IAAI;IAAC,OAAO,EAAE,GAAG;AAErB,6BAIC;EAHG,EAAE;IAAC,OAAO,EAAE,GAAG;EACf,GAAG;IAAC,OAAO,EAAE,GAAG;EAChB,IAAI;IAAC,OAAO,EAAE,GAAG;EAErB,mDAAU;IACN,aAAa,EAAE,GAAG;IAClB,UAAU,EAAE,oCAAmC;IAE/C,iBAAiB,EAAE,qCAAqC;IACxD,cAAc,EAAE,qCAAqC;IACrD,YAAY,EAAE,qCAAqC;IACnD,SAAS,EAAE,qCAAqC;EAIpD,gFAAuC;IACnC,QAAQ,EAAE,QAAQ;IAElB,0FAAY;MACR,UAAU,EAAE,KAAK",
+"sources": ["../../views/gutenberg-blocks/tainacan-items/carousel-related-items/carousel-related-items.scss"],
+"names": [],
+"file": "tainacan-gutenberg-block-carousel-related-items.css"
+}
diff --git a/src/assets/css/tainacan-gutenberg-block-carousel-terms-list.css b/src/assets/css/tainacan-gutenberg-block-carousel-terms-list.css
index 3d3b861ce..507137817 100644
--- a/src/assets/css/tainacan-gutenberg-block-carousel-terms-list.css
+++ b/src/assets/css/tainacan-gutenberg-block-carousel-terms-list.css
@@ -122,7 +122,7 @@
color: var(--tainacan-block-gray5, #454647);
font-weight: bold;
text-decoration: none;
- padding: 8px 16px;
+ padding: 8px 12px;
display: block;
line-height: 1.2em;
word-break: break-word; }
diff --git a/src/classes/api/endpoints/class-tainacan-rest-items-controller.php b/src/classes/api/endpoints/class-tainacan-rest-items-controller.php
index 5b7c7ba9c..e54f976f5 100644
--- a/src/classes/api/endpoints/class-tainacan-rest-items-controller.php
+++ b/src/classes/api/endpoints/class-tainacan-rest-items-controller.php
@@ -189,6 +189,24 @@ class REST_Items_Controller extends REST_Controller {
return $item_array;
}
+ /**
+ * @param \Tainacan\Entities\Item $item|int
+ *
+ * @return array
+ */
+ public function get_context_edit($item) {
+ if(is_numeric($item))
+ $item = new Entities\Item($item);
+
+ return array(
+ 'current_user_can_edit' => $item->can_edit(),
+ 'current_user_can_delete' => $item->can_delete(),
+ 'nonces' => array(
+ 'update-post_' . $item->get_id() => wp_create_nonce('update-post_' . $item->get_id())
+ )
+ );
+ }
+
/**
* @param mixed $item
* @param \WP_REST_Request $request
@@ -256,6 +274,12 @@ class REST_Items_Controller extends REST_Controller {
$attributes_to_filter .= ',id,collection_id';
}
+ if ( $request['context'] === 'edit' ) {
+ add_filter( 'taiancan_add_related_item', function( $related_item ) {
+ return array_merge($related_item, $this->get_context_edit($related_item['id']));
+ }, 10, 2 );
+ }
+
$item_arr = $this->filter_object_by_attributes($item, $attributes_to_filter);
$item_arr = array_merge($extra_metadata_values, $item_arr);
@@ -274,11 +298,7 @@ class REST_Items_Controller extends REST_Controller {
}
if ( $request['context'] === 'edit' ) {
- $item_arr['current_user_can_edit'] = $item->can_edit();
- $item_arr['current_user_can_delete'] = $item->can_delete();
- $item_arr['nonces'] = array(
- 'update-post_' . $item->get_id() => wp_create_nonce('update-post_' . $item->get_id())
- );
+ $item_arr = array_merge($item_arr, $this->get_context_edit($item));
}
if( isset($item_arr['thumbnail']) ) {
$item_arr['thumbnail_alt'] = get_post_meta( $item->get__thumbnail_id(), '_wp_attachment_image_alt', true );
diff --git a/src/classes/entities/class-tainacan-item.php b/src/classes/entities/class-tainacan-item.php
index a79253022..66f9743e7 100644
--- a/src/classes/entities/class-tainacan-item.php
+++ b/src/classes/entities/class-tainacan-item.php
@@ -816,4 +816,15 @@ class Item extends Entity {
return $link;
}
+
+ /**
+ * Return related items withs the item
+ *
+ * @return array
+ */
+ public function get_related_items($args = []) {
+ $Tainacan_Items = \Tainacan\Repositories\Items::get_instance();
+ $related_items = $Tainacan_Items->fetch_related_items($this, $args);
+ return $related_items;
+ }
}
diff --git a/src/classes/importer/class-tainacan-test-importer.php b/src/classes/importer/class-tainacan-test-importer.php
index effcbff1c..8494244c1 100644
--- a/src/classes/importer/class-tainacan-test-importer.php
+++ b/src/classes/importer/class-tainacan-test-importer.php
@@ -523,7 +523,6 @@ class Test_Importer extends Importer {
'type' => 'Tainacan\Metadata_Types\Relationship',
'options' => [
'collection_id' => $col2->get_id(),
- 'repeated' => 'yes',
'search' => $col2_core_title->get_id()
]
], $col1 );
diff --git a/src/classes/repositories/class-tainacan-items.php b/src/classes/repositories/class-tainacan-items.php
index 776c627ce..cbee28804 100644
--- a/src/classes/repositories/class-tainacan-items.php
+++ b/src/classes/repositories/class-tainacan-items.php
@@ -116,7 +116,7 @@ class Items extends Repository {
'description' => __( 'Item comment status: "open" means comments are allowed, "closed" means comments are not allowed.', 'tainacan' ),
'default' => get_default_comment_status(Entities\Collection::get_post_type()),
'validation' => v::optional(v::stringType()->in( [ 'open', 'closed' ] )),
- ]
+ ],
] );
}
@@ -573,5 +573,95 @@ class Items extends Repository {
return $caps;
}
+ private function get_related_items_by_collection($item, $collection, $metadata, $args=[]) {
+ $Tainacan_Metadata = \Tainacan\Repositories\Metadata::get_instance();
+ if (!$collection instanceof \Tainacan\Entities\Collection || !$metadata instanceof \Tainacan\Entities\Metadatum || !$Tainacan_Metadata->metadata_is_enabled($collection, $metadata))
+ return false;
+
+ $prepared_items = array();
+ $items = $this->fetch(array_merge([
+ 'meta_query' => [
+ [
+ 'key' => $metadata->get_id(),
+ 'value' => $item->get_id()
+ ]
+ ]
+ ], $args), $collection->get_id(), 'WP_Query');
+
+ if ($items->have_posts()) {
+ while ( $items->have_posts() ) {
+ $items->the_post();
+ $item_related = new \Tainacan\Entities\Item($items->post);
+ $item_arr = $item_related->_toArray();
+ $item_arr['thumbnail'] = $item_related->get_thumbnail();
+ array_push($prepared_items, apply_filters( 'taiancan_add_related_item', $item_arr ) );
+ }
+ wp_reset_postdata();
+ }
+
+ return array(
+ "found_posts" => $items->found_posts,
+ 'items' => $prepared_items
+ );
+ }
+
+ public function fetch_related_items($item, $args=[]) {
+ $Tainacan_Metadata = \Tainacan\Repositories\Metadata::get_instance();
+ $Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance();
+ $current_collection = $item->get_collection();
+ $metadatas = $Tainacan_Metadata->fetch([
+ 'meta_query' => [
+ [
+ 'key' => 'metadata_type',
+ 'value' => 'Tainacan\Metadata_Types\Relationship'
+ ],
+ [
+ 'key' => '_option_collection_id',
+ 'value' => $current_collection->get_id()
+ ],
+ [
+ 'key' => '_option_display_in_related_items',
+ 'value' => 'yes'
+ ]
+ ]
+ ], 'OBJECT');
+
+ $response = array();
+ foreach($metadatas as $metadata) {
+ if($metadata->get_collection_id() == $Tainacan_Metadata->get_default_metadata_attribute()) {
+ $collections = $Tainacan_Collections->fetch([], 'OBJECT');
+ foreach($collections as $collection) {
+ $related_items = $this->get_related_items_by_collection($item, $collection, $metadata, $args);
+ if($related_items == false) continue;
+ $response[$metadata->get_id() . '_' . $collection->get_id()] = array(
+ 'collection_id' => $collection->get_id(),
+ 'collection_name' => $collection->get_name(),
+ 'collection_url' => $collection->get_url(),
+ 'collection_slug' => $collection->get_slug(),
+ 'metadata_id' => $metadata->get_id(),
+ 'metadata_name' => $metadata->get_name(),
+ 'total_items' => $related_items['found_posts'],
+ 'items' => $related_items['items']
+ );
+ }
+ } else {
+ $collection = $metadata->get_collection();
+ $related_items = $this->get_related_items_by_collection($item, $collection, $metadata, $args);
+ if($related_items == false) continue;
+ $response[$metadata->get_id()] = array(
+ 'collection_id' => $collection->get_id(),
+ 'collection_name' => $collection->get_name(),
+ 'collection_url' => $collection->get_url(),
+ 'collection_slug' => $collection->get_slug(),
+ 'metadata_id' => $metadata->get_id(),
+ 'metadata_name' => $metadata->get_name(),
+ 'total_items' => $related_items['found_posts'],
+ 'items' => $related_items['items']
+ );
+ }
+ }
+
+ return $response;
+ }
}
diff --git a/src/classes/repositories/class-tainacan-metadata.php b/src/classes/repositories/class-tainacan-metadata.php
index 26f78d289..52902fd92 100644
--- a/src/classes/repositories/class-tainacan-metadata.php
+++ b/src/classes/repositories/class-tainacan-metadata.php
@@ -87,7 +87,7 @@ class Metadata extends Repository {
'map' => 'post_content',
'title' => __( 'Description', 'tainacan' ),
'type' => 'string',
- 'description' => __( 'The metadata description', 'tainacan' ),
+ 'description' => __( 'The metadatum description. This may provide information on how to fill this metadatum, which will appear inside a tooltip alongside the input label.', 'tainacan' ),
'default' => '',
//'on_error' => __('The description should be a text value', 'tainacan'),
//'validation' => v::stringType()->notEmpty(),
@@ -134,7 +134,7 @@ class Metadata extends Repository {
'type' => ['string', 'number'],
'description' => __( 'Number of multiples possible metadata', 'tainacan' ),
'on_error' => __( 'This number of multiples metadata is not allowed', 'tainacan' ),
- 'validation' => v::numeric()->positive(),
+ //'validation' => v::numeric()->positive(),
'default' => 1
],
'mask' => [
@@ -1681,4 +1681,28 @@ class Metadata extends Repository {
}
+ /**
+ * Test if a metadata is enabled on collection.
+ *
+ * @param \Tainacan\Entities\Collection $collection
+ * @param \Tainacan\Entities\Metadatum $metadata
+ *
+ * @return boolean
+ */
+ public function metadata_is_enabled($collection, $metadata) {
+ $order = $collection->get_metadata_order();
+ if($order == false) return true;
+ $order = ( is_array( $order ) ) ? $order : unserialize( $order );
+ if( is_array($order) ) {
+ foreach ($order as $metadata_order) {
+ if( $metadata_order['id'] == $metadata->get_id() || $metadata_order['id'] == $metadata->get_parent() ) {
+ if($metadata_order['enabled'] == false)
+ return false;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
}
diff --git a/src/classes/theme-helper/class-tainacan-theme-helper.php b/src/classes/theme-helper/class-tainacan-theme-helper.php
index e0e93efb5..b41c969e9 100644
--- a/src/classes/theme-helper/class-tainacan-theme-helper.php
+++ b/src/classes/theme-helper/class-tainacan-theme-helper.php
@@ -50,6 +50,8 @@ class Theme_Helper {
add_shortcode( 'tainacan-search', array($this, 'search_shortcode'));
add_shortcode( 'tainacan-item-submission', array($this, 'item_submission_shortcode'));
+ add_shortcode( 'tainacan-items-carousel', array($this, 'get_tainacan_items_carousel'));
+ add_shortcode( 'tainacan-related-items-carousel', array($this, 'get_tainacan_related_items_carousel'));
add_action( 'generate_rewrite_rules', array( &$this, 'rewrite_rules' ), 10, 1 );
add_filter( 'query_vars', array( &$this, 'rewrite_rules_query_vars' ) );
@@ -122,6 +124,49 @@ class Theme_Helper {
wp_localize_script('tainacan-search', 'tainacan_plugin', \Tainacan\Admin::get_instance()->get_admin_js_localization_params());
}
}
+
+ public function enqueue_items_carousel_scripts() {
+ global $post;
+ global $TAINACAN_BASE_URL;
+ global $TAINACAN_VERSION;
+ global $wp_version;
+
+ $settings = [
+ 'wp_version' => $wp_version,
+ 'root' => esc_url_raw( rest_url() ) . 'tainacan/v2',
+ 'nonce' => is_user_logged_in() ? wp_create_nonce( 'wp_rest' ) : false,
+ 'base_url' => $TAINACAN_BASE_URL,
+ 'admin_url' => admin_url(),
+ 'site_url' => site_url(),
+ 'theme_items_list_url' => esc_url_raw( get_site_url() ) . '/' . \Tainacan\Theme_Helper::get_instance()->get_items_list_slug()
+ ];
+
+ wp_enqueue_script(
+ 'carousel-items-list-theme',
+ $TAINACAN_BASE_URL . '/assets/js/block_carousel_items_list_theme.js',
+ array('wp-components')
+ );
+ wp_enqueue_style(
+ 'carousel-items-list',
+ $TAINACAN_BASE_URL . '/assets/css/tainacan-gutenberg-block-' . 'carousel-items-list' . '.css',
+ array('tainacan-blocks-common-styles'),
+ $TAINACAN_VERSION
+ );
+ wp_set_script_translations('carousel-items-list-theme', 'tainacan');
+ wp_localize_script('carousel-items-list-theme', 'tainacan_blocks', $settings);
+ }
+
+ public function enqueue_related_items_carousel_scripts() {
+ global $TAINACAN_BASE_URL;
+ global $TAINACAN_VERSION;
+
+ wp_enqueue_style(
+ 'carousel-related-items',
+ $TAINACAN_BASE_URL . '/assets/css/tainacan-gutenberg-block-' . 'carousel-related-items' . '.css',
+ array('tainacan-blocks-common-styles'),
+ $TAINACAN_VERSION
+ );
+ }
public function is_post_an_item(\WP_Post $post) {
$post_type = $post->post_type;
@@ -428,7 +473,6 @@ class Theme_Helper {
public function search_shortcode($args) {
return $this->get_tainacan_items_list($args, true);
}
-
public function get_tainacan_items_list($args, $force_enqueue = false) {
$props = ' ';
@@ -828,5 +872,175 @@ class Theme_Helper {
return $adjacent_items;
}
+ /**
+ * Returns the div used by Vue to render the Carousel of Related Items
+ *
+ * @param array $args {
+ * Optional. Array of arguments.
+ * @type string $collection_id The Collection ID
+ * @type string $search_URL A query string to fetch items from, if load strategy is 'search'
+ * @type array $selected_items An array of item IDs to fetch items from, if load strategy is 'selection' and an array of items, if the load strategy is 'parent'
+ * @type string $load_strategy Either 'search' or 'selection', to determine how items will be fetch
+ * @type integer $max_items_number Maximum number of items to be fetch
+ * @type integer $max_tems_per_screen Maximum columns of items to be displayed on a row of the carousel
+ * @type string $arrows_position How the arrows will be positioned regarding the carousel ('around', 'left', 'right')
+ * @type bool $large_arrows Should large arrows be displayed?
+ * @type bool $auto_play Should the Caroulsel start automatically to slide?
+ * @type integer $auto_play_speed The time in s to translate to the next slide automatically
+ * @type bool $loop_slides Should slides loop when reached the end of the Carousel?
+ * @type bool $hide_title Should the title of the items be displayed?
+ * @type bool $crop_images_to_square Should it use the `tainacan-medium-size` instead of the `tainacan-medium-large-size`?
+ * @type bool $show_collection_header Should it display a small version of the collection header?
+ * @type bool $show_collection_label Should it displar a 'Collection' label before the collection name on the collection header?
+ * @type string $collection_background_color Color of the collection header background
+ * @type string $collection_text_color Color of the collection header text
+ * @type string $tainacan_api_root Path of the Tainacan api root (to make the items request)
+ * @type string $tainacan_base_url Path of the Tainacan base URL (to make the links to the items)
+ * @type string $class_name Extra class to add to the wrapper, besides the default wp-block-tainacan-carousel-items-list
+ * @return string The HTML div to be used for rendering the items carousel vue component
+ */
+ public function get_tainacan_items_carousel($args = []) {
+ if (!is_array($args))
+ return __('There are missing parameters for Tainacan Items Carousel shortcode', 'tainacan');
+
+ $defaults = array(
+ 'max_items_number' => 12,
+ 'max_items_per_screen' => 7,
+ 'arrows_position' => 'around',
+ 'large_arrows' => false,
+ 'auto_play' => false,
+ 'auto_play_speed' => 3,
+ 'loop_slides' => false,
+ 'hide_title' => false,
+ 'crop_images_to_square' => true,
+ 'show_collection_header' => false,
+ 'show_collection_label' => false,
+ 'collection_background_color' => '#454647',
+ 'collection_text_color' => '#ffffff',
+ 'tainacan_api_root' => '',
+ 'tainacan_base_url' => '',
+ 'class_name' => '',
+ );
+ $args = wp_parse_args($args, $defaults);
+
+ $props = ' ';
+
+ // Always pass the class needed by Vue to mount the component;
+ $args['class'] = $args['class_name'] . ' wp-block-tainacan-carousel-items-list';
+ unset($args['class_name']);
+
+ // Builds parameters to the html div rendered by Vue
+ foreach ($args as $key => $value) {
+ if (is_bool($value))
+ $value = $value ? 'true' : 'false';
+ // Changes from PHP '_' notation to HTML '-' notation
+ $props .= (str_replace('_', '-', $key) . "='" . $value . "' ");
+ }
+
+ $this->enqueue_items_carousel_scripts();
+
+ return "
";
+ }
+
+ /**
+ * Returns a group of related items carousels
+ * For each metatada, the collection name, the metadata name and a button linking
+ * the items list filtered is presented
+ *
+ * @param array $args {
+ * Optional. Array of arguments.
+ * @type string $item_id The Item ID
+ * @type string $class_name Extra class to add to the wrapper, besides the default wp-block-tainacan-carousel-related-items
+ * @type string $collection_heading_class_name Extra class to add to the collection name wrapper. Defaults to ''
+ * @type string $collection_heading_tag Tag to be used as wrapper of the collection name. Defaults to h2
+ * @type string $metadata_label_class_name Extra class to add to the metadata label wrapper. Defaults to ''
+ * @type string $metadata_label_tag Tag to be used as wrapper of the metadata label. Defaults to p
+ * @type array $carousel_args Array of arguments to be passed to the get_tainacan_items_carousel function
+ * @return string The HTML div to be used for rendering the related items vue component
+ */
+ public function get_tainacan_related_items_carousel($args = []) {
+
+ $defaults = array(
+ 'class_name' => '',
+ 'collection_heading_class_name' => '',
+ 'collection_heading_tag' => 'h2',
+ 'metadata_label_class_name' => '',
+ 'metadata_label_tag' => 'p',
+ 'carousel_args' => []
+ );
+ $args = wp_parse_args($args, $defaults);
+
+ // Gets the current Item
+ $item = isset($args['item_id']) ? $this->tainacan_get_item($args['item_id']) : $this->tainacan_get_item();
+ if (!$item)
+ return;
+
+ // Then fetches related ones
+ $related_items = $item->get_related_items();
+ if (!count($related_items))
+ return;
+
+ // Enqueues necessary CSS
+ $this->enqueue_related_items_carousel_scripts();
+
+ // Always pass the default class;
+ $output = '
';
+
+ foreach($related_items as $collection_id => $related_group) {
+
+ if ( isset($related_group['items']) && isset($related_group['total_items']) && $related_group['total_items'] ) {
+
+ // Adds a heading with the collection name
+ $collection_heading = '';
+ if ( isset($related_group['collection_name']) ) {
+ $collection_heading = '<' . $args['collection_heading_tag'] . ' class="' . $args['collection_heading_class_name'] . '">' . $related_group['collection_name'] . '' . $args['collection_heading_tag'] . '>';
+ }
+
+ // Adds a paragraph with the metadata name
+ $metadata_label = '';
+ if ( isset($related_group['metadata_name']) ) {
+ $metadata_label = '<' . $args['metadata_label_tag'] . ' class="' . $args['metadata_label_class_name'] . '">' . $related_group['metadata_name'] . '' . $args['metadata_label_tag'] . '>';
+ }
+
+ // Sets the carousel, from the items carousel template tag.
+ $carousel_div = '';
+ if ( isset($related_group['collection_id']) ) {
+
+ $carousel_args = wp_parse_args([
+ 'collection_id' => $related_group['collection_id'],
+ 'load_strategy' => 'parent',
+ 'selected_items' => json_encode($related_group['items'])
+ ], $args['carousel_args']);
+
+ $carousel_div = $this->get_tainacan_items_carousel($carousel_args);
+ }
+
+ $output .= '
';
+
+ return $output;
+ }
}
diff --git a/src/classes/theme-helper/template-tags.php b/src/classes/theme-helper/template-tags.php
index f3a4bc4aa..42fdc285d 100644
--- a/src/classes/theme-helper/template-tags.php
+++ b/src/classes/theme-helper/template-tags.php
@@ -998,3 +998,70 @@ function tainacan_get_the_mime_type_icon($mime_type, $image_size = 'medium') {
return $images_path . $icon_file . $image_size . '.png';
}
+
+/**
+ * Displays a carousel of items, the same of the gutenberg block
+ *
+ * @param array $args {
+ * Optional. Array of arguments.
+ * @type string $collection_id The Collection ID
+ * @type string $search_URL A query string to fetch items from, if load strategy is 'search'
+ * @type array $selected_items An array of item IDs to fetch items from, if load strategy is 'selection' and an array of items, if the load strategy is 'parent'
+ * @type string $load_strategy Either 'search' or 'selection', to determine how items will be fetch
+ * @type integer $max_items_number Maximum number of items to be fetch
+ * @type integer $max_tems_per_screen Maximum columns of items to be displayed on a row of the carousel
+ * @type string $arrows_position How the arrows will be positioned regarding the carousel ('around', 'left', 'right')
+ * @type bool $large_arrows Should large arrows be displayed?
+ * @type bool $auto_play Should the Caroulsel start automatically to slide?
+ * @type integer $auto_play_speed The time in s to translate to the next slide automatically
+ * @type bool $loop_slides Should slides loop when reached the end of the Carousel?
+ * @type bool $hide_title Should the title of the items be displayed?
+ * @type bool $crop_images_to_square Should it use the `tainacan-medium-size` instead of the `tainacan-medium-large-size`?
+ * @type bool $show_collection_header Should it display a small version of the collection header?
+ * @type bool $show_collection_label Should it displar a 'Collection' label before the collection name on the collection header?
+ * @type string $collection_background_color Color of the collection header background
+ * @type string $collection_text_color Color of the collection header text
+ * @type string $tainacan_api_root Path of the Tainacan api root (to make the items request)
+ * @type string $tainacan_base_url Path of the Tainacan base URL (to make the links to the items)
+ * @type string $class_name Extra class to add to the wrapper, besides the default wp-block-tainacan-carousel-items-list
+ * @return void The HTML div to be used for rendering the items carousel vue component
+*/
+function tainacan_the_items_carousel($args = []) {
+ echo \Tainacan\Theme_Helper::get_instance()->get_tainacan_items_carousel($args);
+}
+
+/**
+ * Displays a group of related items carousels
+ * For each metatada, the collection name, the metadata name and a button linking
+ * the items list filtered is presented
+ *
+ * @param array $args {
+ * Optional. Array of arguments.
+ * @type string $item_id The Item ID
+ * @return void
+ */
+function tainacan_the_related_items_carousel($args = []) {
+ echo \Tainacan\Theme_Helper::get_instance()->get_tainacan_related_items_carousel($args);
+}
+
+/**
+ * Checks if the current item has or not related items
+ */
+function tainacan_has_related_items($item_id = false) {
+ // Gets the current Item
+ $item = $item_id ? \Tainacan\Theme_Helper::get_instance()->tainacan_get_item($item_id) : \Tainacan\Theme_Helper::get_instance()->tainacan_get_item();
+ if (!$item)
+ return;
+
+ // Then fetches related ones
+ $related_items = $item->get_related_items();// TODO: handle this inside the item so we don't have to load things here.
+ if ( !$related_items || !is_array($related_items) || !count($related_items) )
+ return false;
+
+ // If we have at least one total_items, there are related items
+ foreach($related_items as $related_group) {
+ if ( isset($related_group['total_items']) && (int)$related_group['total_items'] > 0 )
+ return true;
+ }
+ return false;
+}
\ No newline at end of file
diff --git a/src/views/admin/admin.vue b/src/views/admin/admin.vue
index 0a504c205..1e82706af 100644
--- a/src/views/admin/admin.vue
+++ b/src/views/admin/admin.vue
@@ -3,39 +3,40 @@
id="tainacan-admin-app"
class="columns is-fullheight"
:class="{
- 'tainacan-admin-iframe-mode': $route.query.iframemode,
- 'tainacan-admin-read-mode': $route.query.readmode
+ 'tainacan-admin-iframe-mode': isIframeMode,
+ 'tainacan-admin-read-mode': isReadMode
}">
-
-
-
-
+
+
+
+
+
+