Merge branch 'develop' into feature/794.

This commit is contained in:
mateuswetah 2023-12-04 11:19:45 -03:00
commit 7bb01d64e9
135 changed files with 4858 additions and 2993 deletions

View File

@ -11,7 +11,7 @@
}, },
"require-dev": { "require-dev": {
"squizlabs/php_codesniffer": "^2.2 || ^3.0.2", "squizlabs/php_codesniffer": "^2.2 || ^3.0.2",
"yoast/phpunit-polyfills": "^1.0.1" "yoast/phpunit-polyfills": "^1.1.0"
}, },
"prefer-stable" : true, "prefer-stable" : true,
"minimum-stability": "dev", "minimum-stability": "dev",

1325
composer.lock generated

File diff suppressed because it is too large Load Diff

2581
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -11,8 +11,8 @@
"@ntohq/buefy-next": "^0.1.2", "@ntohq/buefy-next": "^0.1.2",
"@vue-leaflet/vue-leaflet": "^0.10.1", "@vue-leaflet/vue-leaflet": "^0.10.1",
"another-vue3-blurhash": "^0.0.1", "another-vue3-blurhash": "^0.0.1",
"apexcharts": "^3.42.0", "apexcharts": "^3.44.1",
"axios": "^1.5.0", "axios": "^1.6.2",
"blurhash": "^2.0.5", "blurhash": "^2.0.5",
"bulma": "^0.9.4", "bulma": "^0.9.4",
"conditioner-core": "^2.3.3", "conditioner-core": "^2.3.3",
@ -25,48 +25,48 @@
"mitt": "^3.0.1", "mitt": "^3.0.1",
"moment": "^2.29.4", "moment": "^2.29.4",
"node-sass": "^7.0.3", "node-sass": "^7.0.3",
"photoswipe": "^5.4.1", "photoswipe": "^5.4.3",
"qs": "^6.11.2", "qs": "^6.11.2",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"sortablejs": "^1.15.0", "sortablejs": "^1.15.1",
"sortablejs-vue3": "^1.2.9", "sortablejs-vue3": "^1.2.11",
"swiper": "^10.2.0", "swiper": "^11.0.5",
"vue": "^3.3.4", "vue": "^3.3.10",
"vue-countup-v3": "^1.3.0", "vue-countup-v3": "^1.4.0",
"vue-router": "^4.2.4",
"vue-imask": "^7.1.3", "vue-imask": "^7.1.3",
"vue-router": "^4.2.5",
"vue3-apexcharts": "^1.4.4", "vue3-apexcharts": "^1.4.4",
"vuex": "^4.1.0" "vuex": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.21.0", "@babel/core": "^7.23.5",
"@babel/preset-env": "^7.20.2", "@babel/preset-env": "^7.23.5",
"@babel/preset-react": "^7.18.6", "@babel/preset-react": "^7.23.3",
"@types/leaflet": "^1.9.3", "@types/leaflet": "^1.9.8",
"@types/masonry-layout": "^4.2.5", "@types/masonry-layout": "^4.2.7",
"@vue/compiler-sfc": "3.3.4", "@vue/compiler-sfc": "3.3.10",
"acorn": "^8.8.2", "acorn": "^8.11.2",
"ajv": "^8.12.0", "ajv": "^8.12.0",
"autoprefixer": "^10.4.14", "autoprefixer": "^10.4.16",
"babel-loader": "^9.1.3", "babel-loader": "^9.1.3",
"circular-dependency-plugin": "5.2.2", "circular-dependency-plugin": "5.2.2",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"css-loader": "^6.7.3", "css-loader": "^6.8.1",
"eslint": "^8.35.0", "eslint": "^8.55.0",
"eslint-plugin-vue": "^9.15.1", "eslint-plugin-vue": "^9.19.2",
"eslint-webpack-plugin": "^4.0.0", "eslint-webpack-plugin": "^4.0.1",
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"moment-locales-webpack-plugin": "^1.2.0", "moment-locales-webpack-plugin": "^1.2.0",
"postcss-loader": "7.0.2", "postcss-loader": "7.3.3",
"sass-loader": "^13.2.0", "sass-loader": "^13.3.2",
"style-loader": "^3.3.1", "style-loader": "^3.3.3",
"terser-webpack-plugin": "5.3.7", "terser-webpack-plugin": "5.3.9",
"vue-loader": "^17.2.2", "vue-loader": "^17.3.1",
"webpack": "^5.76.0", "webpack": "^5.89.0",
"webpack-bundle-analyzer": "^4.8.0", "webpack-bundle-analyzer": "^4.10.1",
"webpack-cli": "^5.0.1", "webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.11.1", "webpack-dev-server": "^4.15.1",
"webpack-merge": "^5.8.0" "webpack-merge": "^5.10.0"
} }
} }

View File

@ -1,5 +1,5 @@
/** /**
* Swiper 10.2.0 * Swiper 11.0.5
* Most modern mobile touch slider and framework with hardware accelerated transitions * Most modern mobile touch slider and framework with hardware accelerated transitions
* https://swiperjs.com * https://swiperjs.com
* *
@ -7,7 +7,7 @@
* *
* Released under the MIT License * Released under the MIT License
* *
* Released on: August 17, 2023 * Released on: November 22, 2023
*/ */
@font-face { @font-face {
font-family: 'swiper-icons'; font-family: 'swiper-icons';
@ -32,7 +32,6 @@
margin-right: auto; margin-right: auto;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
overflow: clip;
list-style: none; list-style: none;
padding: 0; padding: 0;
/* Fix of Webkit flickering */ /* Fix of Webkit flickering */

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
/** /**
* Swiper 10.2.0 * Swiper 11.0.5
* Most modern mobile touch slider and framework with hardware accelerated transitions * Most modern mobile touch slider and framework with hardware accelerated transitions
* https://swiperjs.com * https://swiperjs.com
* *
@ -7,7 +7,7 @@
* *
* Released under the MIT License * Released under the MIT License
* *
* Released on: August 17, 2023 * Released on: November 22, 2023
*/ */
@font-face { @font-face {
font-family: 'swiper-icons'; font-family: 'swiper-icons';
@ -32,7 +32,6 @@
margin-right: auto; margin-right: auto;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
overflow: clip;
list-style: none; list-style: none;
padding: 0; padding: 0;
/* Fix of Webkit flickering */ /* Fix of Webkit flickering */

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
/** /**
* Swiper 10.2.0 * Swiper 11.0.5
* Most modern mobile touch slider and framework with hardware accelerated transitions * Most modern mobile touch slider and framework with hardware accelerated transitions
* https://swiperjs.com * https://swiperjs.com
* *
@ -7,7 +7,7 @@
* *
* Released under the MIT License * Released under the MIT License
* *
* Released on: August 17, 2023 * Released on: November 22, 2023
*/ */
@font-face { @font-face {
font-family: 'swiper-icons'; font-family: 'swiper-icons';
@ -32,7 +32,6 @@
margin-right: auto; margin-right: auto;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
overflow: clip;
list-style: none; list-style: none;
padding: 0; padding: 0;
/* Fix of Webkit flickering */ /* Fix of Webkit flickering */

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
/** /**
* Swiper 10.2.0 * Swiper 11.0.5
* Most modern mobile touch slider and framework with hardware accelerated transitions * Most modern mobile touch slider and framework with hardware accelerated transitions
* https://swiperjs.com * https://swiperjs.com
* *
@ -7,7 +7,7 @@
* *
* Released under the MIT License * Released under the MIT License
* *
* Released on: August 17, 2023 * Released on: November 22, 2023
*/ */
@font-face { @font-face {
font-family: 'swiper-icons'; font-family: 'swiper-icons';
@ -32,7 +32,6 @@
margin-right: auto; margin-right: auto;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
overflow: clip;
list-style: none; list-style: none;
padding: 0; padding: 0;
/* Fix of Webkit flickering */ /* Fix of Webkit flickering */
@ -891,6 +890,10 @@
max-width: calc((90vh * 9) / 16); } max-width: calc((90vh * 9) / 16); }
.tainacan-photoswipe-layer .pswp__container .tainacan-content-embed.tainacan-embed-aspect-1-2 { .tainacan-photoswipe-layer .pswp__container .tainacan-content-embed.tainacan-embed-aspect-1-2 {
max-width: calc((90vh * 1) / 2); } max-width: calc((90vh * 1) / 2); }
.tainacan-photoswipe-layer .pswp__container .pswp__content {
display: flex;
justify-content: center;
align-content: center; }
.tainacan-photoswipe-layer .pswp__container .pswp__content > .tainacan-content-embed:not(.attachment-without-image) { .tainacan-photoswipe-layer .pswp__container .pswp__content > .tainacan-content-embed:not(.attachment-without-image) {
margin-top: 60px; } margin-top: 60px; }
.tainacan-photoswipe-layer .pswp__container a:first-of-type, .tainacan-photoswipe-layer .pswp__container a:first-of-type,

File diff suppressed because one or more lines are too long

View File

@ -129,14 +129,14 @@
height: 1.5em; height: 1.5em;
width: 18%; width: 18%;
border: 2px solid var(--tainacan-input-border-color, rgba(200, 200, 200, 0.3)); border: 2px solid var(--tainacan-input-border-color, rgba(200, 200, 200, 0.3));
border-radius: 3px; border-radius: var(--tainacan-input-border-radius, 1px);
display: inline-block; } display: inline-block; }
.wp-block-tainacan-item-submission-form .item-submission-form-placeholder .fake-textarea { .wp-block-tainacan-item-submission-form .item-submission-form-placeholder .fake-textarea {
background-color: var(--tainacan-input-background-color, rgba(200, 200, 200, 0.3)); background-color: var(--tainacan-input-background-color, rgba(200, 200, 200, 0.3));
height: 2.5em; height: 2.5em;
width: 100%; width: 100%;
border: 2px solid var(--tainacan-input-border-color, rgba(200, 200, 200, 0.3)); border: 2px solid var(--tainacan-input-border-color, rgba(200, 200, 200, 0.3));
border-radius: 3px; border-radius: var(--tainacan-input-border-radius, 1px);
display: inline-block; } display: inline-block; }
.wp-block-tainacan-item-submission-form .item-submission-form-placeholder .fake-button { .wp-block-tainacan-item-submission-form .item-submission-form-placeholder .fake-button {
background-color: var(--tainacan-secondary, rgba(200, 200, 200, 0.3)); background-color: var(--tainacan-secondary, rgba(200, 200, 200, 0.3));
@ -146,7 +146,7 @@
max-width: 3.45em; max-width: 3.45em;
min-width: 1em; min-width: 1em;
margin-left: 6px; margin-left: 6px;
border-radius: 3px; border-radius: var(--tainacan-button-border-radius, 4px);
display: flex; display: flex;
align-items: center; align-items: center;
margin-right: auto; } margin-right: auto; }

File diff suppressed because one or more lines are too long

View File

@ -207,6 +207,17 @@ abstract class REST_Controller extends \WP_REST_Controller {
} }
protected function sanitize_value($value) {
if (is_numeric($value) || empty($value) ) {
return $value;
}
$allowed_html = wp_kses_allowed_html('post');
unset($allowed_html["a"]);
return trim(wp_kses($value, $allowed_html));
}
/** /**
* @param $mapped * @param $mapped
* @param $request * @param $request
@ -219,6 +230,7 @@ abstract class REST_Controller extends \WP_REST_Controller {
*/ */
private function prepare_meta($mapped, $request, $query, $mapped_v, $args){ private function prepare_meta($mapped, $request, $query, $mapped_v, $args){
$request_meta_query = $request[$mapped]; $request_meta_query = $request[$mapped];
$query_field_scaped = ["value", "terms"];
// if the meta/date/taxquery has a root relation // if the meta/date/taxquery has a root relation
if( isset( $request_meta_query['relation']) ) if( isset( $request_meta_query['relation']) )
@ -231,7 +243,15 @@ abstract class REST_Controller extends \WP_REST_Controller {
foreach ( $query as $mapped_meta => $meta_v ) { foreach ( $query as $mapped_meta => $meta_v ) {
if ( isset( $a[ $mapped_meta ] ) ) { if ( isset( $a[ $mapped_meta ] ) ) {
$args[ $mapped_v ][ $index1 ][ $meta_v ] = $request[ $mapped ][ $index1 ][ $mapped_meta ]; if( in_array($mapped_meta, $query_field_scaped) ) {
$valeu = is_array($request[ $mapped ][ $index1 ][ $mapped_meta ])
? array_map([$this, 'sanitize_value'], $request[ $mapped ][ $index1 ][ $mapped_meta ])
: $this->sanitize_value($request[ $mapped ][ $index1 ][ $mapped_meta ]);
$args[ $mapped_v ][ $index1 ][ $meta_v ] = $valeu;
} else {
$args[ $mapped_v ][ $index1 ][ $meta_v ] = $request[ $mapped ][ $index1 ][ $mapped_meta ];
}
} }
} }
@ -240,7 +260,13 @@ abstract class REST_Controller extends \WP_REST_Controller {
} else { } else {
foreach ( $query as $mapped_meta => $meta_v ) { foreach ( $query as $mapped_meta => $meta_v ) {
if(isset($request[$mapped][$mapped_meta])) { if(isset($request[$mapped][$mapped_meta])) {
$args[ $mapped_v ][ $meta_v ] = $request[ $mapped ][ $mapped_meta ]; if( in_array($mapped_meta, $query_field_scaped) ) {
$args[ $mapped_v ][ $meta_v ] = is_array($request[ $mapped ][ $mapped_meta ])
? array_map([$this, 'sanitize_value'], $request[ $mapped ][ $mapped_meta ])
: $this->sanitize_value($request[ $mapped ][ $mapped_meta ]);
} else {
$args[ $mapped_v ][ $meta_v ] = $request[ $mapped ][ $mapped_meta ];
}
} }
} }
} }
@ -405,6 +431,50 @@ abstract class REST_Controller extends \WP_REST_Controller {
* @return array * @return array
*/ */
protected function get_meta_queries_params(){ protected function get_meta_queries_params(){
$metaquery_properties = array(
'key' => array(
'type' => ['integer', 'string'],
'description' => __('Custom metadata key.'),
),
'value' => array(
'type' => ['string', 'array'],
'items' => array('type' => 'string'),
'description' => __('Custom metadata value. It can be an array only when compare is IN, NOT IN, BETWEEN, or NOT BETWEEN. You dont have to specify a value when using the EXISTS or NOT EXISTS comparisons in WordPress 3.9 and up. (Note: Due to bug #23268, value is required for NOT EXISTS comparisons to work correctly prior to 3.9. You must supply some string for the value parameter. An empty string or NULL will NOT work. However, any other string will do the trick and will NOT show up in your SQL when using NOT EXISTS. Need inspiration? How about \'bug #23268\'.'),
'sanitize_callback' => 'sanitize_text_field',
),
'compare' => array(
'type' => 'string',
'description' => __('Operator to test.'),
'default' => '=',
'enum' => array(
'=',
'!=',
'>',
'>=',
'<',
'<=',
'LIKE',
'NOT LIKE',
'IN',
'NOT IN',
'BETWEEN',
'NOT BETWEEN',
'EXISTS',
'NOT EXISTS'
)
),
'relation' => array(
'type' => 'string',
'description' => __('OR or AND, how the sub-arrays should be compared.'),
'default' => 'AND',
),
'metadatumtype' => array(
'type' => 'string',
'description' => __('Custom metadata type. Possible values are NUMERIC, BINARY, CHAR, DATE, DATETIME, DECIMAL, SIGNED, TIME, UNSIGNED. Default value is CHAR. You can also specify precision and scale for the DECIMAL and NUMERIC types (for example, DECIMAL(10,5) or NUMERIC(10) are valid). The type DATE works with the compare value BETWEEN only if the date is stored at the format YYYY-MM-DD and tested with this format.'),
),
);
return array( return array(
'metakey' => array( 'metakey' => array(
'type' => ['integer', 'string'], 'type' => ['integer', 'string'],
@ -413,6 +483,7 @@ abstract class REST_Controller extends \WP_REST_Controller {
'metavalue' => array( 'metavalue' => array(
'type' => ['string', 'array'], 'type' => ['string', 'array'],
'description' => __('Custom metadata value'), 'description' => __('Custom metadata value'),
'sanitize_callback' => 'sanitize_text_field',
), ),
'metavaluenum' => array( 'metavaluenum' => array(
'type' => 'number', 'type' => 'number',
@ -443,50 +514,11 @@ abstract class REST_Controller extends \WP_REST_Controller {
), ),
'metaquery' => array( 'metaquery' => array(
'description' => __('Limits result set to items that have specific custom metadata'), 'description' => __('Limits result set to items that have specific custom metadata'),
'type' => ['array', 'object'], 'type' => ['array', 'object',],
'properties' => $metaquery_properties,
'items' => array( 'items' => array(
'keys' => array( 'type' => 'object',
'key' => array( 'properties' => $metaquery_properties,
'type' => 'string',
'description' => __('Custom metadata key.'),
),
'value' => array(
'type' => ['string', 'array'],
'description' => __('Custom metadata value. It can be an array only when compare is IN, NOT IN, BETWEEN, or NOT BETWEEN. You dont have to specify a value when using the EXISTS or NOT EXISTS comparisons in WordPress 3.9 and up.
(Note: Due to bug #23268, value is required for NOT EXISTS comparisons to work correctly prior to 3.9. You must supply some string for the value parameter. An empty string or NULL will NOT work. However, any other string will do the trick and will NOT show up in your SQL when using NOT EXISTS. Need inspiration? How about \'bug #23268\'.'),
),
'compare' => array(
'type' => 'string',
'description' => __('Operator to test.'),
'default' => '=',
'enum' => array(
'=',
'!=',
'>',
'>=',
'<',
'<=',
'LIKE',
'NOT LIKE',
'IN',
'NOT IN',
'BETWEEN',
'NOT BETWEEN',
'EXISTS',
'NOT EXISTS'
)
),
'relation' => array(
'type' => 'string',
'description' => __('OR or AND, how the sub-arrays should be compared.'),
'default' => 'AND',
),
'metadatumtype' => array(
'type' => 'string',
'description' => __('Custom metadata type. Possible values are NUMERIC, BINARY, CHAR, DATE, DATETIME, DECIMAL, SIGNED, TIME, UNSIGNED. Default value is CHAR. You can also specify precision and scale for the DECIMAL and NUMERIC types (for example, DECIMAL(10,5) or NUMERIC(10) are valid). The type DATE works with the compare value BETWEEN only if the date is stored at the format YYYY-MM-DD and tested with this format.'),
),
),
'type' => ['array', 'object']
), ),
), ),
'datequery' => array( 'datequery' => array(
@ -586,6 +618,7 @@ abstract class REST_Controller extends \WP_REST_Controller {
), ),
'terms' => array( 'terms' => array(
'type' => ['integer', 'string', 'array'], 'type' => ['integer', 'string', 'array'],
'sanitize_callback' => 'sanitize_text_field',
'description' => __('Taxonomy term(s).'), 'description' => __('Taxonomy term(s).'),
), ),
'operator' => array( 'operator' => array(

View File

@ -245,7 +245,7 @@ class REST_Facets_Controller extends REST_Controller {
], ],
'parent' => [ 'parent' => [
'type' => 'string', 'type' => 'string',
'description' => __( 'Parent term id, if coming from a Taxonomy metadata type tha has hierarchy.', 'tainacan' ), 'description' => __( 'Parent term id, if coming from a Taxonomy metadata type that has hierarchy.', 'tainacan' ),
], ],
'total_items' => [ 'total_items' => [
'type' => 'integer', 'type' => 'integer',

View File

@ -132,7 +132,7 @@ class REST_Item_Metadata_Controller extends REST_Controller {
public function prepare_item_for_response( $item, $request ) { public function prepare_item_for_response( $item, $request ) {
$item_arr = $item->_toArray(true, true); $item_arr = $item->_toArray(true, true);
if($request['context'] === 'edit'){ if ($request['context'] === 'edit') {
$item_arr['current_user_can_edit'] = $item->can_edit(); $item_arr['current_user_can_edit'] = $item->can_edit();
$item_arr['current_user_can_delete'] = $item->can_delete(); $item_arr['current_user_can_delete'] = $item->can_delete();
} }

View File

@ -57,13 +57,13 @@ class REST_Items_Controller extends REST_Controller {
'callback' => array($this, 'get_items'), 'callback' => array($this, 'get_items'),
'permission_callback' => array($this, 'get_items_permissions_check'), 'permission_callback' => array($this, 'get_items_permissions_check'),
'args' => array_merge([ 'args' => array_merge([
'collection_id' => [ 'collection_id' => [
'description' => __( 'Collection ID', 'tainacan' ), 'description' => __( 'Collection ID', 'tainacan' ),
'required' => true, 'required' => true,
],
], ],
], $this->get_wp_query_params()
$this->get_wp_query_params() ),
),
), ),
array( array(
'methods' => \WP_REST_Server::CREATABLE, 'methods' => \WP_REST_Server::CREATABLE,
@ -457,6 +457,7 @@ class REST_Items_Controller extends REST_Controller {
private function prepare_filters_arguments ( $args, $collection_id = false ) { private function prepare_filters_arguments ( $args, $collection_id = false ) {
$filters_arguments = array(); $filters_arguments = array();
$meta_query = isset($args['meta_query']) ? $args['meta_query'] : []; $meta_query = isset($args['meta_query']) ? $args['meta_query'] : [];
if(isset($meta_query['value'])) $meta_query = [$meta_query];
$tax_query = isset($args['tax_query']) ? $args['tax_query'] : []; $tax_query = isset($args['tax_query']) ? $args['tax_query'] : [];
foreach($tax_query as $tax) { foreach($tax_query as $tax) {

View File

@ -442,7 +442,7 @@ class REST_Reports_Controller extends REST_Controller {
'list' => array() 'list' => array()
); );
$collection_id = $request['collection_id']; $collection_id = $request['collection_id'];
$taxonomy_metadata_id = $request['metadata_id'];; $taxonomy_metadata_id = $request['metadata_id'];
$parent_id = 0; $parent_id = 0;
if ( isset($request['parent']) ) { if ( isset($request['parent']) ) {
$parent_id = (int) $request['parent']; $parent_id = (int) $request['parent'];

View File

@ -56,7 +56,7 @@ class REST_Sequence_Edit_Controller extends REST_Controller {
'methods' => \WP_REST_Server::READABLE, 'methods' => \WP_REST_Server::READABLE,
'callback' => array($this, 'get_item_in_sequence'), 'callback' => array($this, 'get_item_in_sequence'),
'permission_callback' => array($this, 'sequence_edit_permissions_check'), 'permission_callback' => array($this, 'sequence_edit_permissions_check'),
'args' => $this->get_sequence_params() 'args' => $this->get_sequence_index_params()
), ),
'schema' => [$this, 'get_sequence_index_schema'] 'schema' => [$this, 'get_sequence_index_schema']
) )
@ -212,12 +212,36 @@ class REST_Sequence_Edit_Controller extends REST_Controller {
} }
/** /**
* @param string $method * @param string $method
* *
* @return array|mixed * @return array|mixed
*/ */
public function get_sequence_params() { public function get_sequence_params() {
$endpoint_args = [
'collection_id' => [
'type' => 'string',
'description' => __( 'Collection ID', 'tainacan' ),
'required' => true,
],
'group_id' => [
'type' => 'string',
'description' => __( 'Group ID', 'tainacan' ),
'required' => true,
]
];
return $endpoint_args;
}
/**
* @param string $method
*
* @return array|mixed
*/
public function get_sequence_index_params() {
$endpoint_args = [ $endpoint_args = [
'collection_id' => [ 'collection_id' => [
'type' => 'string', 'type' => 'string',

View File

@ -7,10 +7,11 @@ namespace Tainacan;
class Media { class Media {
private static $instance = null; private static $instance = null;
private static $file_handle = null;
private static $file_name = null; private static $file_name = null;
private $attachment_html_url_base = 'tainacan_attachment_html'; private $attachment_html_url_base = 'tainacan_attachment_html';
public static $content_index_meta = 'document_content_index';
public static function get_instance() { public static function get_instance() {
if(!isset(self::$instance)) { if(!isset(self::$instance)) {
self::$instance = new self(); self::$instance = new self();
@ -246,10 +247,8 @@ class Media {
return; return;
} }
$content_index_meta = 'document_content_index';
if ($file == null) { if ($file == null) {
$meta_id = update_post_meta( $item_id, $content_index_meta, null ); update_post_meta( $item_id, SELF::$content_index_meta, null );
return true; return true;
} }
@ -274,9 +273,8 @@ class Media {
$wp_charset = get_bloginfo('charset'); $wp_charset = get_bloginfo('charset');
$content_charset = mb_detect_encoding($content); $content_charset = mb_detect_encoding($content);
$content = mb_convert_encoding($content, $wp_charset, $content_charset); $content = mb_convert_encoding($content, $wp_charset, $content_charset);
update_post_meta( $item_id, SELF::$content_index_meta, $content );
$meta_id = update_post_meta( $item_id, $content_index_meta, $content ); } catch(\Exception $e) {
} catch(Exception $e) {
error_log('Caught exception: ' . $e->getMessage() . "\n"); error_log('Caught exception: ' . $e->getMessage() . "\n");
return false; return false;
} }

View File

@ -191,7 +191,7 @@ class Private_Files {
$upload_dir = wp_get_upload_dir(); $upload_dir = wp_get_upload_dir();
$base_upload_url = preg_replace('/^https?:\/\//', '', $upload_dir['baseurl']); $base_upload_url = preg_replace('/^https?:\/\//', '', $upload_dir['baseurl']);
$requested_uri = sanitize_text_field($_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']); $requested_uri = ($_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
if ( strpos($requested_uri, $base_upload_url) === false ) { if ( strpos($requested_uri, $base_upload_url) === false ) {
// Not uploads // Not uploads

View File

@ -176,10 +176,16 @@ class Search_Engine {
$seperator = ' OR '; $seperator = ' OR ';
} }
if ( empty($search_meta_query) ) return ''; if ( empty($search_meta_query) ) return '';
$content_index_meta = '';
if ( defined('TAINACAN_INDEX_PDF_CONTENT') && true === TAINACAN_INDEX_PDF_CONTENT ) {
$content_index_meta_meta_key = \TAINACAN\Media::$content_index_meta;
$content_index_meta = "OR (m.meta_key='{$content_index_meta_meta_key}')";
}
$join = \is_user_logged_in() $join = \is_user_logged_in()
? '' ? ''
: " INNER JOIN $wpdb->posts pmeta ON m.meta_key = pmeta.ID AND pmeta.post_status = 'publish'"; : " INNER JOIN $wpdb->posts pmeta ON (m.meta_key = pmeta.ID AND pmeta.post_status = 'publish') $content_index_meta";
return "EXISTS ( return "EXISTS (
SELECT m.post_id SELECT m.post_id
FROM $wpdb->postmeta m $join FROM $wpdb->postmeta m $join

View File

@ -40,7 +40,18 @@ class Collection extends Entity {
$hide_items_thumbnail_on_lists, $hide_items_thumbnail_on_lists,
$submission_anonymous_user, $submission_anonymous_user,
$submission_default_status, $submission_default_status,
$submission_use_recaptcha; $submission_use_recaptcha,
$item_enabled_document_types,
$item_document_label,
$item_thumbnail_label,
$item_enable_thubmnail,
$item_attachment_label,
$item_enable_attachments,
$item_enable_metadata_focus_mode,
$item_enable_metadata_required_filter,
$item_enable_metadata_searchbar,
$item_enable_metadata_collapses,
$item_enable_metadata_enumeration;
/** /**
* {@inheritDoc} * {@inheritDoc}
@ -607,14 +618,112 @@ class Collection extends Entity {
/** /**
* Get the default metadata section properties. * Get the default metadata section properties.
* *
* @param [string] $value
*
* @return void * @return void
*/ */
function get_default_metadata_section_properties( ) { function get_default_metadata_section_properties( ) {
return $this->get_mapped_property( 'default_metadata_section_properties' ); return $this->get_mapped_property( 'default_metadata_section_properties' );
} }
/**
* Get the enabled document types for this collection.
*
* @return array The enabled document types.
*/
function get_item_enabled_document_types() {
return $this->get_mapped_property('item_enabled_document_types');
}
/**
* Get the label for the section in this collection.
*
* @return string The label for the section.
*/
function get_item_document_label() {
return $this->get_mapped_property('item_document_label');
}
/**
* Get the label for the thumbnail section in this collection.
*
* @return string The label for the thumbnail section.
*/
function get_item_thumbnail_label() {
return $this->get_mapped_property('item_thumbnail_label');
}
/**
* Check if thumbnail are enabled for this collection.
*
* @return string 'yes' if thumbnail are enabled, 'no' otherwise.
*/
function get_item_enable_thumbnail() {
return $this->get_mapped_property('item_enable_thumbnail');
}
/**
* Get the label for the attachment section in this collection.
*
* @return string The label for the attachment section.
*/
function get_item_attachment_label() {
return $this->get_mapped_property('item_attachment_label');
}
/**
* Check if attachments are enabled for this collection.
*
* @return string 'yes' if attachments are enabled, 'no' otherwise.
*/
function get_item_enable_attachments() {
return $this->get_mapped_property('item_enable_attachments');
}
/**
* Check if metadata focus mode is enabled for this collection.
*
* @return string 'yes' if metadata focus mode is enabled, 'no' otherwise.
*/
function get_item_enable_metadata_focus_mode() {
return $this->get_mapped_property('item_enable_metadata_focus_mode');
}
/**
* Check if metadata required filter is enabled for this collection.
*
* @return string 'yes' if metadata required filter is enabled, 'no' otherwise.
*/
function get_item_enable_metadata_required_filter() {
return $this->get_mapped_property('item_enable_metadata_required_filter');
}
/**
* Check if metadata search bar is enabled for this collection.
*
* @return string 'yes' if metadata search bar is enabled, 'no' otherwise.
*/
function get_item_enable_metadata_searchbar() {
return $this->get_mapped_property('item_enable_metadata_searchbar');
}
/**
* Check if metadata collapses are enabled for this collection.
*
* @return bool 'yes' if metadata collapses are enabled, 'no' otherwise.
*/
function get_item_enable_metadata_collapses() {
return $this->get_mapped_property('item_enable_metadata_collapses');
}
/**
* Check if metadata and metadata section should be enumerated in the edition form.
*
* @return bool 'yes' if metadata are enumerated, 'no' otherwise.
*/
function get_item_enable_metadata_enumeration() {
return $this->get_mapped_property('item_enable_metadata_enumeration');
}
// Setters
/** /**
* Set the collection name * Set the collection name
* *
@ -750,7 +859,7 @@ class Collection extends Entity {
* @return void * @return void
*/ */
function set_metadata_section_order( $value ) { function set_metadata_section_order( $value ) {
if( !empty($value) ) { if( !empty( $value ) ) {
$metadata_order = array( ); $metadata_order = array( );
foreach($value as $section) { foreach($value as $section) {
$metadata_order = array_merge($metadata_order, $section['metadata_order']); $metadata_order = array_merge($metadata_order, $section['metadata_order']);
@ -888,6 +997,117 @@ class Collection extends Entity {
return $this->set_mapped_property( 'default_metadata_section_properties', $value); return $this->set_mapped_property( 'default_metadata_section_properties', $value);
} }
/**
* Set the enabled document types for this collection.
*
* @param array $value The enabled document types.
* @return void
*/
function set_item_enabled_document_types( $value ) {
$this->set_mapped_property('item_enabled_document_types', $value);
}
/**
* Set the label for the document section in this collection.
*
* @param string $value The label for the document section.
* @return void
*/
function set_item_document_label( $value ) {
$this->set_mapped_property('item_document_label', $value);
}
/**
* Set the label for the thumbnail section in this collection.
*
* @param string $value The label for the thumbnail section.
* @return void
*/
function set_item_thumbnail_label( $value ) {
$this->set_mapped_property('item_thumbnail_label', $value);
}
/**
* Enable or disable thumbnail for this collection.
*
* @param string $value 'yes' to enable thumbnail, 'no' to disable.
* @return void
*/
function set_item_enable_thumbnail( $value ) {
$this->set_mapped_property('item_enable_thumbnail', $value);
}
/**
* Set the label for the attachment section in this collection.
*
* @param string $value The label for the attachment section.
* @return void
*/
function set_item_attachment_label( $value ) {
$this->set_mapped_property('item_attachment_label', $value);
}
/**
* Enable or disable attachments for this collection.
*
* @param string $value 'yes' to enable attachments, 'no' to disable.
* @return void
*/
function set_item_enable_attachments( $value ) {
$this->set_mapped_property('item_enable_attachments', $value);
}
/**
* Enable or disable metadata focus mode for this collection.
*
* @param string $value 'yes' to enable metadata focus mode, 'no' to disable.
* @return void
*/
function set_item_enable_metadata_focus_mode( $value ) {
$this->set_mapped_property('item_enable_metadata_focus_mode', $value);
}
/**
* Enable or disable metadata required filter for this collection.
*
* @param string $value 'yes' to enable metadata required filter, 'no' to disable.
* @return void
*/
function set_item_enable_metadata_required_filter( $value ) {
$this->set_mapped_property('item_enable_metadata_required_filter', $value);
}
/**
* Enable or disable metadata search bar for this collection.
*
* @param string $value 'yes' to enable metadata search bar, 'no' to disable.
* @return void
*/
function set_item_enable_metadata_searchbar( $value ) {
$this->set_mapped_property('item_enable_metadata_searchbar', $value);
}
/**
* Enable or disable metadata collapses for this collection.
*
* @param string $value 'yes' to enable metadata collapses, 'no' to disable.
* @return void
*/
function set_item_enable_metadata_collapses( $value ) {
$this->set_mapped_property('item_enable_metadata_collapses', $value);
}
/**
* Enable or disable metadata and metadata sections enumeration for the item edition form this collection.
*
* @param string $value 'yes' to enable metadata enumeration, 'no' to disable.
* @return void
*/
function set_item_enable_metadata_enumeration( $value ) {
$this->set_mapped_property('item_enable_metadata_enumeration', $value);
}
/** /**
* Validate Collection * Validate Collection
* *

View File

@ -19,7 +19,8 @@ class Filter extends Entity {
$max_options, $max_options,
$filter_type, $filter_type,
$filter_type_options, $filter_type_options,
$begin_with_filter_collapsed; $begin_with_filter_collapsed,
$display_in_repository_level_lists;
static $post_type = 'tainacan-filter'; static $post_type = 'tainacan-filter';
public $enabled_for_collection = true; public $enabled_for_collection = true;
@ -179,6 +180,15 @@ class Filter extends Entity {
return $this->get_mapped_property('begin_with_filter_collapsed'); return $this->get_mapped_property('begin_with_filter_collapsed');
} }
/**
* Return 'yes' or 'no' to the option of display in repository level lists
*
* @return string
*/
public function get_display_in_repository_level_lists() {
return $this->get_mapped_property('display_in_repository_level_lists');
}
/** /**
* Define the filter name * Define the filter name
@ -252,6 +262,15 @@ class Filter extends Entity {
$this->set_mapped_property('begin_with_filter_collapsed', $begin_with_filter_collapsed); $this->set_mapped_property('begin_with_filter_collapsed', $begin_with_filter_collapsed);
} }
/**
* Tells if filter should appear in repository level lists, even belonging to a collection
*
* @param string $display_in_repository_level_lists
*/
public function set_display_in_repository_level_lists($display_in_repository_level_lists) {
$this->set_mapped_property('display_in_repository_level_lists', $display_in_repository_level_lists);
}
/** /**
* Transient property used to store the status of the filter for a particular collection * Transient property used to store the status of the filter for a particular collection
* *

View File

@ -307,7 +307,9 @@ class Item extends Entity {
* @return string "open"|"closed" * @return string "open"|"closed"
*/ */
public function get_comment_status() { public function get_comment_status() {
return apply_filters('tainacan-item-comments_open', $this->get_mapped_property('comment_status'), $this->get_id()); $comment_status = $this->get_mapped_property('comment_status');
$comment_status_filtered = apply_filters('comments_open', $comment_status == 'open', $this->get_id()) == true ? 'open' : 'closed';
return $comment_status_filtered;
} }
/** /**
@ -1183,13 +1185,15 @@ class Item extends Entity {
if ( $metadata_section->is_conditional_section() ) { if ( $metadata_section->is_conditional_section() ) {
$rules = $metadata_section->get_conditional_section_rules(); $rules = $metadata_section->get_conditional_section_rules();
$item_id = $this->get_id(); if( !empty($rules) ) {
$item_id = $this->get_id();
foreach ( $rules as $meta_id => $meta_values_conditional ) { foreach ( $rules as $meta_id => $meta_values_conditional ) {
$meta_values = get_post_meta( $item_id, $meta_id ); $meta_values = get_post_meta( $item_id, $meta_id );
if (!array_intersect($meta_values, $meta_values_conditional)) if (!array_intersect($meta_values, $meta_values_conditional))
return $return; return $return;
}
} }
} }

View File

@ -13,7 +13,7 @@ class CSV extends Exporter {
$this->accept_no_mapping = true; $this->accept_no_mapping = true;
if ($current_collection = $this->get_current_collection_object()) { if ($current_collection = $this->get_current_collection_object()) {
$name = $current_collection->get_name(); $name = $current_collection->get_name();
$this->collection_name = sanitize_title($name) . "_csv_export.csv";; $this->collection_name = sanitize_title($name) . "_csv_export.csv";
} else { } else {
$this->collection_name = "csv_export.csv"; $this->collection_name = "csv_export.csv";
} }
@ -285,13 +285,13 @@ class CSV extends Exporter {
$current_user = wp_get_current_user(); $current_user = wp_get_current_user();
$author_name = $current_user->user_login; $author_name = $current_user->user_login;
$message = __('target collections:', 'tainacan'); $message = __('Target collections:', 'tainacan');
$message .= " <b>" . implode(", ", $this->get_collections_names() ) . "</b><br/>"; $message .= " <b>" . implode(", ", $this->get_collections_names() ) . "</b><br/>";
$message .= __('Exported by:', 'tainacan'); $message .= __('Exported by:', 'tainacan');
$message .= " <b> $author_name </b><br/>"; $message .= " <b> $author_name </b><br/>";
$message .= __('Your CSV file is ready! Access it in the link below:', 'tainacan'); $message .= __('Your CSV file is ready! Access it in the link below:', 'tainacan');
$message .= '<br/><br/>'; $message .= '<br/><br/>';
$message .= '<a href="' . $file['url'] . '">Download</a>'; $message .= '<a target="_blank" href="' . $file['url'] . '">Download</a>';
return $message; return $message;

View File

@ -330,6 +330,141 @@ class Collections extends Repository {
] ]
] ]
], ],
'item_enabled_document_types' => [
'map' => 'meta',
'title' => __( 'Enabled document types', 'tainacan' ),
'type' => 'object',
'description' => __( 'The document types that are available in the item edition form.', 'tainacan' ),
'items' => [
'type' => 'object',
'properties' => [
'enabled' => [
'description' => __( 'Whether the document type is enabled or not.', 'tainacan' ),
'type' => 'string',
'enum' => [ 'yes', 'no' ],
],
'label' => [
'description' => __( 'The label that will represent the document type.', 'tainacan' ),
'type' => 'string',
],
'icon' => [
'description' => __( 'The slug of the icon that will represent the document type.', 'tainacan' ),
'type' => 'string',
],
]
],
'default' => [
'attachment' => [
'enabled' => 'yes',
'label' => __( 'File', 'tainacan' ),
'icon' => 'attachments'
],
'url' => [
'enabled' => 'yes',
'label' => __('URL', 'tainacan' ),
'icon' => 'url'
],
'text' => [
'enabled' => 'yes',
'label' => __('Text', 'tainacan' ),
'icon' => 'text'
]
]
],
'item_document_label' => [
'map' => 'meta',
'title' => __( 'Main document label', 'tainacan' ),
'type' => 'string',
'description' => __( 'The label for the main document section in the item edition form', 'tainacan' ),
'default' => __( 'Document', 'tainacan' ),
//'validation' => v::stringType(),
],
'item_thumbnail_label' => [
'map' => 'meta',
'title' => __( 'Thumbnail label', 'tainacan' ),
'type' => 'string',
'description' => __( 'The label for the thumbnail section in the item edition form', 'tainacan' ),
'default' => __( 'Thumbnail', 'tainacan' ),
//'validation' => v::stringType(),
],
'item_enable_thumbnail' => [
'map' => 'meta',
'title' => __( 'Item thumbnail', 'tainacan' ),
'type' => 'string',
'description' => __( 'If enabled, each item can have a thumbnail customized instead of the one automatically generated based on the item document.', 'tainacan' ),
'default' => 'yes',
'on_error' => __( 'Value should be yes or no', 'tainacan' ),
'enum' => [ 'yes', 'no' ],
'validation' => v::stringType()->in( [ 'yes', 'no' ] ), // yes or no
],
'item_attachment_label' => [
'map' => 'meta',
'title' => __( 'Attachments label', 'tainacan' ),
'type' => 'string',
'description' => __( 'The label for the attachments section in the item edition form', 'tainacan' ),
'default' => __( 'Attachments', 'tainacan' ),
//'validation' => v::stringType(),
],
'item_enable_attachments' => [
'map' => 'meta',
'title' => __( 'Item attachments', 'tainacan' ),
'type' => 'string',
'description' => __( 'If enabled, each item can have a set of files attached to it, complementary to the item document.', 'tainacan' ),
'default' => 'yes',
'on_error' => __( 'Value should be yes or no', 'tainacan' ),
'enum' => [ 'yes', 'no' ],
'validation' => v::stringType()->in( [ 'yes', 'no' ] ), // yes or no
],
'item_enable_metadata_focus_mode' => [
'map' => 'meta',
'title' => __( 'Metadata focus mode', 'tainacan' ),
'type' => 'string',
'description' => __( 'If enabled, a button can start a special navigation mode, that focus one metadatum per time in the item edition form.', 'tainacan' ),
'default' => 'yes',
'on_error' => __( 'Value should be yes or no', 'tainacan' ),
'enum' => [ 'yes', 'no' ],
'validation' => v::stringType()->in( [ 'yes', 'no' ] ), // yes or no
],
'item_enable_metadata_required_filter' => [
'map' => 'meta',
'title' => __( 'Metadata required filter', 'tainacan' ),
'type' => 'string',
'description' => __( 'If enabled, a switch can be toggled to display only required metadata in the item edition form.', 'tainacan' ),
'default' => 'yes',
'on_error' => __( 'Value should be yes or no', 'tainacan' ),
'enum' => [ 'yes', 'no' ],
'validation' => v::stringType()->in( [ 'yes', 'no' ] ), // yes or no
],
'item_enable_metadata_searchbar' => [
'map' => 'meta',
'title' => __( 'Metadata search bar', 'tainacan' ),
'type' => 'string',
'description' => __( 'If enabled, a search bar can be used for filtering the list of metadata in the item edition form.', 'tainacan' ),
'default' => 'yes',
'on_error' => __( 'Value should be yes or no', 'tainacan' ),
'enum' => [ 'yes', 'no' ],
'validation' => v::stringType()->in( [ 'yes', 'no' ] ), // yes or no
],
'item_enable_metadata_collapses' => [
'map' => 'meta',
'title' => __( 'Metadata collapses', 'tainacan' ),
'type' => 'string',
'description' => __( 'If enabled, each metadata in the item form will be wrapped in a collapsable component.', 'tainacan' ),
'default' => 'yes',
'on_error' => __( 'Value should be yes or no', 'tainacan' ),
'enum' => [ 'yes', 'no' ],
'validation' => v::stringType()->in( [ 'yes', 'no' ] ), // yes or no
],
'item_enable_metadata_enumeration' => [
'map' => 'meta',
'title' => __( 'Metadata enumeration', 'tainacan' ),
'type' => 'string',
'description' => __( 'If enabled, the metadata sections and their metadata in the item form will be enumerated automatically.', 'tainacan' ),
'default' => 'no',
'on_error' => __( 'Value should be yes or no', 'tainacan' ),
'enum' => [ 'yes', 'no' ],
'validation' => v::stringType()->in( [ 'yes', 'no' ] ), // yes or no
]
] ); ] );
} }

View File

@ -79,6 +79,16 @@ class Filters extends Repository {
'enum' => [ 'yes', 'no' ], 'enum' => [ 'yes', 'no' ],
'default' => 'no' 'default' => 'no'
], ],
'display_in_repository_level_lists' => [
'map' => 'meta',
'title' => __( 'Display in repository level lists', 'tainacan' ),
'type' => 'string',
'description' => __( 'With this option enabled, the filter will appear even in repository level items lists, such as the complete items list and the term items list.', 'tainacan' ),
'on_error' => __( 'Please set the "Display in repository level lists" value as "yes" or "no"', 'tainacan' ),
'validation' => v::stringType()->in( [ 'yes', 'no' ] ), // yes or no
'enum' => [ 'yes', 'no' ],
'default' => 'no'
],
'collection_id' => [ 'collection_id' => [
'map' => 'meta', 'map' => 'meta',
'title' => __( 'Collection', 'tainacan' ), 'title' => __( 'Collection', 'tainacan' ),

View File

@ -26,7 +26,7 @@ class Items extends Repository {
protected function __construct() { protected function __construct() {
parent::__construct(); parent::__construct();
add_filter( 'tainacan-item-comments_open', [$this, 'hook_comments_open'], 10, 2); add_filter( 'comments_open', [$this, 'hook_comments_open'], 10, 2);
add_action( 'tainacan-api-item-updated', array( &$this, 'hook_api_updated_item' ), 10, 2 ); add_action( 'tainacan-api-item-updated', array( &$this, 'hook_api_updated_item' ), 10, 2 );
add_filter( 'map_meta_cap', array( $this, 'map_meta_cap' ), 10, 4 ); add_filter( 'map_meta_cap', array( $this, 'map_meta_cap' ), 10, 4 );
} }
@ -103,7 +103,7 @@ class Items extends Repository {
'map' => 'meta', 'map' => 'meta',
'title' => __( 'Document', 'tainacan' ), 'title' => __( 'Document', 'tainacan' ),
'type' => 'string', 'type' => 'string',
'description' => __( 'The document itself. An ID in case of attachment, an URL in case of link or a text in the case of text.', 'tainacan' ), 'description' => __( 'The item main content. May be a file attached, an URL or a text depending on the type of the document.', 'tainacan' ),
'on_error' => __( 'Invalid document', 'tainacan' ), 'on_error' => __( 'Invalid document', 'tainacan' ),
'default' => '' 'default' => ''
], ],
@ -189,11 +189,12 @@ class Items extends Repository {
* @see \Tainacan\Repositories\Repository::register_post_type() * @see \Tainacan\Repositories\Repository::register_post_type()
*/ */
public function register_post_type() { public function register_post_type() {
$Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance(); $Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance();
$Tainacan_Taxonomies = \Tainacan\Repositories\Taxonomies::get_instance(); $Tainacan_Taxonomies = \Tainacan\Repositories\Taxonomies::get_instance();
$collections = $Tainacan_Collections->fetch( [], 'OBJECT' ); // TODO: This can be a problem in large repositories.
$collections = $Tainacan_Collections->fetch( ['nopaging' => true], 'OBJECT' );
$taxonomies = $Tainacan_Taxonomies->fetch( [ $taxonomies = $Tainacan_Taxonomies->fetch( [
'status' => [ 'status' => [
'auto-draft', 'auto-draft',
@ -220,7 +221,7 @@ class Items extends Repository {
} }
// register taxonomies to collections considering metadata inheritance // register taxonomies to collections considering metadata inheritance
$Tainacan_Taxonomies->register_taxonomies_for_all_collections(); $Tainacan_Taxonomies->register_taxonomies_for_all_collections($collections);
} }
@ -582,19 +583,19 @@ class Items extends Repository {
/** /**
* Return if comment are open for this item (post_id) and the collection too * Return if comment are open for this item (post_id) and the collection too
* *
* @param string $open_comment * @param bool $comments_open
* @param integer $post_id Item id * @param integer $post_id Item id
* @return string * @return bool
*/ */
public function hook_comments_open($open_comment, $post_id) { public function hook_comments_open($comments_open, $post_id) {
$item = self::get_entity_by_post($post_id); $item = self::get_entity_by_post($post_id);
if($item != false && $item instanceof Entities\Item) { if($item != false && $item instanceof Entities\Item) {
$collection = $item->get_collection(); $collection = $item->get_collection();
if( $collection != null && $collection->get_allow_comments() !== 'open' ) return 'closed'; if( $collection != null && $collection->get_allow_comments() !== 'open' ) return false;
} }
return $open_comment; return $comments_open;
} }
/** /**

View File

@ -285,7 +285,7 @@ class Metadata_Sections extends Repository {
// Add public states. // Add public states.
$statuses = get_post_stati( array( 'public' => true ) ); $statuses = get_post_stati( array( 'public' => true ) );
$read_private_cap = 'tnc_col_' . $parent_id . '_read_private_metadata_section'; $read_private_cap = 'tnc_col_' . $parent_id . '_read_private_metasection';
if ( current_user_can($read_private_cap) ) { if ( current_user_can($read_private_cap) ) {
$statuses = array_merge( $statuses, get_post_stati( array( 'private' => true ) ) ); $statuses = array_merge( $statuses, get_post_stati( array( 'private' => true ) ) );
} }

View File

@ -737,8 +737,8 @@ class Metadata extends Repository {
public function insert( $metadatum ) { public function insert( $metadatum ) {
$this->pre_update_taxonomy_metadatum( $metadatum ); $this->pre_update_taxonomy_metadatum( $metadatum );
$new_metadatum = parent::insert( $metadatum ); $new_metadatum = parent::insert( $metadatum );
$this->update_taxonomy_metadatum( $new_metadatum );
$this->update_metadata_type_index( $new_metadatum ); $this->update_metadata_type_index( $new_metadatum );
$this->update_taxonomy_metadatum( $new_metadatum );
return $new_metadatum; return $new_metadatum;
} }
@ -1426,6 +1426,7 @@ class Metadata extends Repository {
'parent' => $r->parent, 'parent' => $r->parent,
'total_items' => $total_items, 'total_items' => $total_items,
'type' => 'Taxonomy', 'type' => 'Taxonomy',
'description' => term_description($r->term_id),
'hierarchy_path' => get_term_parents_list($r->term_id, $taxonomy_slug, ['format'=>'name', 'separator'=>$separator, 'link'=>false, 'inclusive'=>false]) 'hierarchy_path' => get_term_parents_list($r->term_id, $taxonomy_slug, ['format'=>'name', 'separator'=>$separator, 'link'=>false, 'inclusive'=>false])
]; ];

View File

@ -295,9 +295,12 @@ class Taxonomies extends Repository {
$id = $taxonomy_id; $id = $taxonomy_id;
if ( ! empty( $id ) && is_numeric( $id ) && is_numeric($collection_id) ) { if ( ! empty( $id ) && is_numeric( $id ) && is_numeric($collection_id) ) {
$tax = $this->fetch( (int) $id ); $tax = $this->fetch( (int) $id );
$tax->add_collection_id( $collection_id );
if ( $tax->validate() ) { if ( $tax instanceof Entities\Taxonomy ) {
$this->insert( $tax ); $tax->add_collection_id( $collection_id );
if ( $tax->validate() )
$this->insert( $tax );
} }
} }
$this->update_taxonomy_registry_for_collection($taxonomy_id, $collection_id); $this->update_taxonomy_registry_for_collection($taxonomy_id, $collection_id);
@ -307,9 +310,12 @@ class Taxonomies extends Repository {
$id = $taxonomy_id; $id = $taxonomy_id;
if ( ! empty( $id ) && is_numeric( $id ) && is_numeric($collection_id) ) { if ( ! empty( $id ) && is_numeric( $id ) && is_numeric($collection_id) ) {
$tax = $this->fetch( (int) $id ); $tax = $this->fetch( (int) $id );
$tax->remove_collection_id( $collection_id );
if ( $tax->validate() ) { if ( $tax instanceof Entities\Taxonomy ) {
$this->insert( $tax ); $tax->remove_collection_id( $collection_id );
if ( $tax->validate() )
$this->insert( $tax );
} }
} }
$this->update_taxonomy_registry_for_collection($taxonomy_id, $collection_id); $this->update_taxonomy_registry_for_collection($taxonomy_id, $collection_id);
@ -336,21 +342,41 @@ class Taxonomies extends Repository {
} }
public function register_taxonomies_for_all_collections() { public function register_taxonomies_for_all_collections($all_collections = null) {
global $wpdb;
$Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance(); $Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance();
// TODO: This can be a problem in large repositories. // TODO: This can be a problem in large repositories.
$collections = $Tainacan_Collections->fetch( ['nopaging' => true], 'OBJECT' ); $collections = $all_collections != null ? $all_collections : $Tainacan_Collections->fetch( ['nopaging' => true], 'OBJECT' );
if ( ! is_array( $collections ) ) { if ( ! is_array( $collections ) ) {
return; return;
} }
// register taxonomies to other collections considering metadata inheritance $taxonomies_res = $wpdb->get_results("
foreach ( $collections as $collection ) { SELECT
$taxonomies = $this->fetch_by_collection($collection, ['nopaging' => true]); meta.post_id as meta_id, meta.meta_value as tax_id, col.meta_value as collection_id
foreach ( $taxonomies as $taxonomy ) { FROM
register_taxonomy_for_object_type( $taxonomy->get_db_identifier(), $collection->get_db_identifier() ); $wpdb->postmeta meta INNER JOIN (
SELECT post_id, meta_value FROM $wpdb->postmeta WHERE meta_key='collection_id'
) as col ON meta.post_id = col.post_id
WHERE
meta.meta_key='_option_taxonomy_id'
AND meta.post_id IN (SELECT post_id FROM $wpdb->postmeta WHERE meta_key='metadata_type' and meta_value='Tainacan\\\Metadata_Types\\\Taxonomy');
");
foreach ($taxonomies_res as $tax_res) {
// Aqui você pode acessar os valores de cada coluna
$tax_id = $tax_res->tax_id;
$collection_id = $tax_res->collection_id;
$tax_db_identifier_by_id = $this->get_db_identifier_by_id($tax_id);
if ($collection_id != 'default' ) {
$collection_slug = Entities\Collection::$db_identifier_prefix . $collection_id . Entities\Collection::$db_identifier_sufix;
register_taxonomy_for_object_type($tax_db_identifier_by_id ,$collection_slug);
} else {
foreach ( $collections as $collection ) {
register_taxonomy_for_object_type($tax_db_identifier_by_id, $collection->get_db_identifier());
}
} }
} }
} }

View File

@ -69,7 +69,7 @@ class Theme_Helper {
$this->register_view_mode('table', [ $this->register_view_mode('table', [
'label' => __('Table', 'tainacan'), 'label' => __('Table', 'tainacan'),
'description' => 'The classic table display.', 'description' => __('The classic table display.', 'tainacan'),
'dynamic_metadata' => true, 'dynamic_metadata' => true,
'icon' => '<span class="icon"><i class="tainacan-icon tainacan-icon-viewtable tainacan-icon-1-25em"></i></span>', 'icon' => '<span class="icon"><i class="tainacan-icon tainacan-icon-viewtable tainacan-icon-1-25em"></i></span>',
'type' => 'component', 'type' => 'component',
@ -79,7 +79,7 @@ class Theme_Helper {
$this->register_view_mode('cards', [ $this->register_view_mode('cards', [
'label' => __('Cards', 'tainacan'), 'label' => __('Cards', 'tainacan'),
'dynamic_metadata' => false, 'dynamic_metadata' => false,
'description' => 'A cards view, displaying cropped thumbnails, title and description.', 'description' => __('A cards view, displaying cropped thumbnails, title and description.', 'tainacan'),
'icon' => '<span class="icon"><i class="tainacan-icon tainacan-icon-viewcards tainacan-icon-1-25em"></i></span>', 'icon' => '<span class="icon"><i class="tainacan-icon tainacan-icon-viewcards tainacan-icon-1-25em"></i></span>',
'type' => 'component', 'type' => 'component',
'implements_skeleton' => true, 'implements_skeleton' => true,
@ -88,7 +88,7 @@ class Theme_Helper {
$this->register_view_mode('records', [ $this->register_view_mode('records', [
'label' => __('Records', 'tainacan'), 'label' => __('Records', 'tainacan'),
'dynamic_metadata' => true, 'dynamic_metadata' => true,
'description' => 'A records view, similiar to cards, but flexible for metadata.', 'description' => __('A records view, similiar to cards, but flexible for metadata.', 'tainacan'),
'icon' => '<span class="icon"><i class="tainacan-icon tainacan-icon-viewrecords tainacan-icon-1-25em"></i></span>', 'icon' => '<span class="icon"><i class="tainacan-icon tainacan-icon-viewrecords tainacan-icon-1-25em"></i></span>',
'type' => 'component', 'type' => 'component',
'implements_skeleton' => true, 'implements_skeleton' => true,
@ -97,7 +97,7 @@ class Theme_Helper {
$this->register_view_mode('masonry', [ $this->register_view_mode('masonry', [
'label' => __('Masonry', 'tainacan'), 'label' => __('Masonry', 'tainacan'),
'dynamic_metadata' => false, 'dynamic_metadata' => false,
'description' => 'A masonry view, similar to pinterest, which will display images without cropping.', 'description' => __('A masonry view, similar to pinterest, which will display images without cropping.', 'tainacan'),
'icon' => '<span class="icon"><i class="tainacan-icon tainacan-icon-viewmasonry tainacan-icon-1-25em"></i></span>', 'icon' => '<span class="icon"><i class="tainacan-icon tainacan-icon-viewmasonry tainacan-icon-1-25em"></i></span>',
'type' => 'component', 'type' => 'component',
'implements_skeleton' => true 'implements_skeleton' => true
@ -105,7 +105,7 @@ class Theme_Helper {
$this->register_view_mode('slideshow', [ $this->register_view_mode('slideshow', [
'label' => __('Slides', 'tainacan'), 'label' => __('Slides', 'tainacan'),
'dynamic_metadata' => false, 'dynamic_metadata' => false,
'description' => 'A fullscreen slideshow view, that shows the item document instead of just thumbnails.', 'description' => __('A fullscreen slideshow view, that shows the item document instead of just thumbnails.', 'tainacan'),
'icon' => '<span class="icon"><i class="tainacan-icon tainacan-icon-viewgallery tainacan-icon-1-25em"></i></span>', 'icon' => '<span class="icon"><i class="tainacan-icon tainacan-icon-viewgallery tainacan-icon-1-25em"></i></span>',
'type' => 'component', 'type' => 'component',
'show_pagination' => false, 'show_pagination' => false,
@ -114,7 +114,7 @@ class Theme_Helper {
$this->register_view_mode('list', [ $this->register_view_mode('list', [
'label' => __('List', 'tainacan'), 'label' => __('List', 'tainacan'),
'dynamic_metadata' => true, 'dynamic_metadata' => true,
'description' => 'A list view, similiar to the records, but full width.', 'description' => __('A list view, similiar to the records, but full width.', 'tainacan'),
'icon' => '<span class="icon"><i class="tainacan-icon tainacan-icon-viewlist tainacan-icon-1-25em"></i></span>', 'icon' => '<span class="icon"><i class="tainacan-icon tainacan-icon-viewlist tainacan-icon-1-25em"></i></span>',
'type' => 'component', 'type' => 'component',
'implements_skeleton' => true, 'implements_skeleton' => true,
@ -123,7 +123,7 @@ class Theme_Helper {
$this->register_view_mode('map', [ $this->register_view_mode('map', [
'label' => __('Map', 'tainacan'), 'label' => __('Map', 'tainacan'),
'dynamic_metadata' => true, 'dynamic_metadata' => true,
'description' => 'A map view, for displaying items that have geocoordinate metadata.', 'description' => __('A map view, for displaying items that have geocoordinate metadata.', 'tainacan'),
'icon' => '<span class="icon"> 'icon' => '<span class="icon">
<i> <i>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="var(--tainacan-info-color, #505253)" width="1.25em" height="1.25em"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="var(--tainacan-info-color, #505253)" width="1.25em" height="1.25em">

View File

@ -1019,7 +1019,15 @@ function tainacan_get_the_mime_type_icon($mime_type, $image_size = 'medium') {
$icon_file = 'placeholder_square'; $icon_file = 'placeholder_square';
} }
return $images_path . $icon_file . $image_size . '.png'; /**
* Filter the image source for the empty thumbnail placeholder.
*
* @param string src The image source for the empty thumbnail placeholder.
* Default is 'placeholder_square'.
* @param string mime_type The document type of the item.
* @param string image_size The size of the image to be loaded.
*/
return apply_filters('tainacan-get-the-mime-type-icon', $images_path . $icon_file . $image_size . '.png', $mime_type, $image_size);
} }
/** /**
@ -1468,7 +1476,7 @@ function tainacan_get_single_taxonomy_content($post, $args = []) {
if ( !$args['hide_term_items_count'] && $args['term_items_count_position'] === 'before' ) if ( !$args['hide_term_items_count'] && $args['term_items_count_position'] === 'before' )
echo '<span class="term-items-count">' . $term->count . '</span>&nbsp;'; echo '<span class="term-items-count">' . $term->count . '</span>&nbsp;';
echo ($term->count == 1 || $term->count == '1') ? __('Item', 'tainacan') : __('Itens', 'tainacan'); echo ($term->count == 1 || $term->count == '1') ? __('Item', 'tainacan') : __('Items', 'tainacan');
if ( !$args['hide_term_items_count'] && $args['term_items_count_position'] !== 'before' ) if ( !$args['hide_term_items_count'] && $args['term_items_count_position'] !== 'before' )
echo '&nbsp;<span class="term-items-count">(' . $term->count . ')</span>'; echo '&nbsp;<span class="term-items-count">(' . $term->count . ')</span>';

View File

@ -2,9 +2,9 @@
Contributors: andrebenedito, daltonmartins, fabianobn, jacsonp, leogermani, weryques, wetah, eduardohumberto, ravipassos, jessicafpx, marinagiolo, omarceloavila, vnmedeiros, tainacan, r-guimaraes, suelanesilva, ccaio, alanargomes, ateneagarcia123, rodrigo0freire, clarandreozzi Contributors: andrebenedito, daltonmartins, fabianobn, jacsonp, leogermani, weryques, wetah, eduardohumberto, ravipassos, jessicafpx, marinagiolo, omarceloavila, vnmedeiros, tainacan, r-guimaraes, suelanesilva, ccaio, alanargomes, ateneagarcia123, rodrigo0freire, clarandreozzi
Tags: museums, libraries, archives, GLAM, collections, repository Tags: museums, libraries, archives, GLAM, collections, repository
Requires at least: 5.9 Requires at least: 5.9
Tested up to: 6.3 Tested up to: 6.4
Requires PHP: 7.0 Requires PHP: 7.0
Stable tag: 0.20.4 Stable tag: 0.20.5
License: GPLv2 or later License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-3.0.html License URI: http://www.gnu.org/licenses/gpl-3.0.html

View File

@ -5,17 +5,17 @@ Plugin URI: https://tainacan.org/
Description: Open source, powerful and flexible repository platform for WordPress. Manage and publish you digital collections as easily as publishing a post to your blog, while having all the tools of a professional repository platform. Description: Open source, powerful and flexible repository platform for WordPress. Manage and publish you digital collections as easily as publishing a post to your blog, while having all the tools of a professional repository platform.
Author: Tainacan.org Author: Tainacan.org
Author URI: https://tainacan.org/ Author URI: https://tainacan.org/
Version: 0.20.4 Version: 0.20.5
Requires at least: 5.9 Requires at least: 5.9
Tested up to: 6.3 Tested up to: 6.4
Requires PHP: 7.0 Requires PHP: 7.0
Stable tag: 0.20.4 Stable tag: 0.20.5
Text Domain: tainacan Text Domain: tainacan
License: GPLv2 or later License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-3.0.html License URI: http://www.gnu.org/licenses/gpl-3.0.html
*/ */
const TAINACAN_VERSION = '0.20.4'; const TAINACAN_VERSION = '0.20.5';
defined( 'ABSPATH' ) or die( 'No script kiddies please!' ); defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
$TAINACAN_BASE_URL = plugins_url('', __FILE__); $TAINACAN_BASE_URL = plugins_url('', __FILE__);

View File

@ -178,7 +178,7 @@
--tainacan-sidebar-width: 3.0em; --tainacan-sidebar-width: 3.0em;
} }
#primary-menu:not(.is-compressed)~.is-main-content { #primary-menu:not(.is-compressed)~.is-main-content {
--tainacan-sidebar-width: 10em; --tainacan-sidebar-width: 11em;
} }
.is-secondary-content { .is-secondary-content {

View File

@ -152,7 +152,7 @@
</div> </div>
</b-field> </b-field>
<b-field <b-field
:addons="false" :addons="false"
:label="$i18n.getHelperTitle('filters', 'begin_with_filter_collapsed')" :label="$i18n.getHelperTitle('filters', 'begin_with_filter_collapsed')"
:type="formErrors['begin_with_filter_collapsed'] != undefined ? 'is-danger' : ''" :type="formErrors['begin_with_filter_collapsed'] != undefined ? 'is-danger' : ''"
@ -173,6 +173,28 @@
</b-switch> </b-switch>
</b-field> </b-field>
<b-field
v-if="form.collection_id && form.collection_id !== 'default'"
:addons="false"
:label="$i18n.getHelperTitle('filters', 'display_in_repository_level_lists')"
:type="formErrors['display_in_repository_level_lists'] != undefined ? 'is-danger' : ''"
:message="formErrors['display_in_repository_level_lists'] != undefined ? formErrors['display_in_repository_level_lists'] : ''">
&nbsp;
<b-switch
size="is-small"
@input="clearErrors('display_in_repository_level_lists')"
v-model="form.display_in_repository_level_lists"
:true-value="'yes'"
:false-value="'no'"
:native-value="form.display_in_repository_level_lists == 'yes' ? 'yes' : 'no'"
name="display_in_repository_level_lists">
<help-button
:title="$i18n.getHelperTitle('filters', 'display_in_repository_level_lists')"
:message="$i18n.getHelperMessage('filters', 'display_in_repository_level_lists')"
:extra-classes="isRepositoryLevel ? 'tainacan-repository-tooltip' : ''" />
</b-switch>
</b-field>
<component <component
:errors="formErrors['filter_type_options']" :errors="formErrors['filter_type_options']"
v-if="(form.filter_type_object && form.filter_type_object.form_component) || form.edit_form == ''" v-if="(form.filter_type_object && form.filter_type_object.form_component) || form.edit_form == ''"
@ -280,11 +302,13 @@ export default {
this.isLoading = true; this.isLoading = true;
for (let [key, value] of Object.entries(this.form)) { for (let [key, value] of Object.entries(this.form)) {
if (key === 'begin_with_filter_collapsed') if (key === 'begin_with_filter_collapsed' || key === 'display_in_repository_level_lists')
this.form[key] = (value == 'yes' || value == true) ? 'yes' : 'no'; this.form[key] = (value == 'yes' || value == true) ? 'yes' : 'no';
} }
if (this.form['begin_with_filter_collapsed'] === undefined) if (this.form['begin_with_filter_collapsed'] === undefined)
this.form['begin_with_filter_collapsed'] = 'no'; this.form['begin_with_filter_collapsed'] = 'no';
if (this.form['display_in_repository_level_lists'] === undefined)
this.form['display_in_repository_level_lists'] = 'no';
this.updateFilter({ filterId: filter.id, index: this.index, options: this.form }) this.updateFilter({ filterId: filter.id, index: this.index, options: this.form })
.then(() => { .then(() => {
@ -313,13 +337,15 @@ export default {
let formObj = {}; let formObj = {};
for (let [key, value] of formData.entries()) { for (let [key, value] of formData.entries()) {
if (key === 'begin_with_filter_collapsed') if (key === 'begin_with_filter_collapsed' || key === 'display_in_repository_level_lists')
formObj[key] = (value == 'yes' || value == true) ? 'yes' : 'no'; formObj[key] = (value == 'yes' || value == true) ? 'yes' : 'no';
else else
formObj[key] = value; formObj[key] = value;
} }
if (formObj['begin_with_filter_collapsed'] === undefined) if (formObj['begin_with_filter_collapsed'] === undefined)
formObj['begin_with_filter_collapsed'] = 'no'; formObj['begin_with_filter_collapsed'] = 'no';
if (formObj['display_in_repository_level_lists'] === undefined)
formObj['display_in_repository_level_lists'] = 'no';
this.fillExtraFormData(formObj); this.fillExtraFormData(formObj);
this.isLoading = true; this.isLoading = true;

View File

@ -8,7 +8,7 @@
<span class="icon has-text-gray4"> <span class="icon has-text-gray4">
<i class="tainacan-icon tainacan-icon-attachments"/> <i class="tainacan-icon tainacan-icon-attachments"/>
</span> </span>
{{ $i18n.get('label_attachments') }}&nbsp; {{ collection && collection.item_attachment_label ? collection.item_attachment_label : $i18n.get('label_attachments') }}&nbsp;
<span <span
v-if="totalAttachments" v-if="totalAttachments"
class="has-text-gray has-text-weight-normal" class="has-text-gray has-text-weight-normal"
@ -17,7 +17,7 @@
</span> </span>
</label> </label>
<help-button <help-button
:title="$i18n.get('label_attachments')" :title="collection && collection.item_attachment_label ? collection.item_attachment_label : $i18n.get('label_attachments')"
:message="$i18n.get('info_edit_attachments')"/> :message="$i18n.get('info_edit_attachments')"/>
<button <button
style="float: right; font-size: 0.875em; margin: 2px 5px;" style="float: right; font-size: 0.875em; margin: 2px 5px;"
@ -28,7 +28,7 @@
<span class="icon"> <span class="icon">
<i class="tainacan-icon tainacan-icon-edit"/> <i class="tainacan-icon tainacan-icon-edit"/>
</span> </span>
{{ $i18n.get('label_add_or_update_attachments') }} {{ $i18n.get('label_add_or_update') }}
</button> </button>
</div> </div>
<div <div
@ -38,6 +38,7 @@
<attachments-list <attachments-list
:item="item" :item="item"
:form="form" :form="form"
:collection="collection"
:is-editable="true" :is-editable="true"
:should-load-attachments="shouldLoadAttachments" :should-load-attachments="shouldLoadAttachments"
@onDeleteAttachment="($event) => $emit('onDeleteAttachment', $event)"/> @onDeleteAttachment="($event) => $emit('onDeleteAttachment', $event)"/>
@ -55,6 +56,7 @@ export default {
props: { props: {
item: Object, item: Object,
form: Object, form: Object,
collection: Object,
totalAttachments: Number, totalAttachments: Number,
isLoading: Boolean, isLoading: Boolean,
shouldLoadAttachments: Boolean shouldLoadAttachments: Boolean

View File

@ -1,21 +1,17 @@
<template> <template>
<div> <div v-if="!$adminOptions.hideItemEditionDocument && ( !$adminOptions.hideItemEditionDocumentFileInput && !$adminOptions.hideItemEditionDocumentTextInput && !$adminOptions.hideItemEditionDocumentUrlInput )">
<div <div class="section-label">
v-if="!$adminOptions.hideItemEditionDocument"
class="section-label">
<label> <label>
<span class="icon has-text-gray4"> <span class="icon has-text-gray4">
<i :class="'tainacan-icon tainacan-icon-' + ( (!form.document_type || form.document_type == 'empty' ) ? 'item' : (form.document_type == 'attachment' ? 'attachments' : form.document_type))"/> <i :class="'tainacan-icon tainacan-icon-' + ( (!form.document_type || form.document_type == 'empty' ) ? 'item' : (form.document_type == 'attachment' ? 'attachments' : form.document_type))"/>
</span> </span>
{{ form.document != undefined && form.document != null && form.document != '' ? $i18n.get('label_document') : $i18n.get('label_document_empty') }} {{ collection && collection.item_document_label ? collection.item_document_label : ( (form.document != undefined && form.document != null && form.document != '') ? $i18n.get('label_document') : $i18n.get('label_document_empty') ) }}
</label> </label>
<help-button <help-button
:title="$i18n.getHelperTitle('items', 'document')" :title="collection && collection.item_document_label ? collection.item_document_label : $i18n.getHelperTitle('items', 'document')"
:message="$i18n.getHelperMessage('items', 'document')"/> :message="$i18n.getHelperMessage('items', 'document')"/>
</div> </div>
<div <div class="section-box document-field">
v-if="!$adminOptions.hideItemEditionDocument"
class="section-box document-field">
<div <div
v-if="form.document != undefined && form.document != null && v-if="form.document != undefined && form.document != null &&
form.document_type != undefined && form.document_type != null && form.document_type != undefined && form.document_type != null &&
@ -63,7 +59,7 @@
<ul <ul
v-else v-else
class="document-field-placeholder"> class="document-field-placeholder">
<li v-if="!$adminOptions.hideItemEditionDocumentFileInput"> <li v-if="!$adminOptions.hideItemEditionDocumentFileInput && (collection && collection.item_enabled_document_types && collection.item_enabled_document_types['attachment'] && collection.item_enabled_document_types['attachment']['enabled'] === 'yes')">
<button <button
type="button" type="button"
@click.prevent="($event) => $emit('onSetFileDocument', $event)"> @click.prevent="($event) => $emit('onSetFileDocument', $event)">
@ -73,7 +69,7 @@
</button> </button>
<p>{{ $i18n.get('label_file') }}</p> <p>{{ $i18n.get('label_file') }}</p>
</li> </li>
<li v-if="!$adminOptions.hideItemEditionDocumentTextInput"> <li v-if="!$adminOptions.hideItemEditionDocumentTextInput && (collection && collection.item_enabled_document_types && collection.item_enabled_document_types['text'] && collection.item_enabled_document_types['text']['enabled'] === 'yes')">
<button <button
type="button" type="button"
@click.prevent="$emit('onSetTextDocument')"> @click.prevent="$emit('onSetTextDocument')">
@ -83,7 +79,7 @@
</button> </button>
<p>{{ $i18n.get('label_text') }}</p> <p>{{ $i18n.get('label_text') }}</p>
</li> </li>
<li v-if="!$adminOptions.hideItemEditionDocumentUrlInput"> <li v-if="!$adminOptions.hideItemEditionDocumentUrlInput && (collection && collection.item_enabled_document_types && collection.item_enabled_document_types['url'] && collection.item_enabled_document_types['url']['enabled'] === 'yes')">
<button <button
type="button" type="button"
@click.prevent="$emit('onSetURLDocument')"> @click.prevent="$emit('onSetURLDocument')">
@ -102,7 +98,8 @@
export default { export default {
props: { props: {
item: Object, item: Object,
form: Object form: Object,
collection: Object
}, },
emits: [ emits: [
'onSetFileDocument', 'onSetFileDocument',
@ -123,6 +120,11 @@ export default {
&.document-field-content--text { &.document-field-content--text {
padding-bottom: 2rem; padding-bottom: 2rem;
:deep(article) {
max-height: calc(32vh - 2rem);
overflow-y: auto;
}
} }
:deep(img), :deep(img),
@ -169,6 +171,7 @@ export default {
justify-content: space-evenly; justify-content: space-evenly;
padding: 1.5rem 1rem 2rem 1rem; padding: 1.5rem 1rem 2rem 1rem;
border: 1px solid var(--tainacan-input-border-color); border: 1px solid var(--tainacan-input-border-color);
border-radius: var(--tainacan-input-border-radius, 1px);
li { li {
text-align: center; text-align: center;

View File

@ -142,19 +142,19 @@
<span>{{ $i18n.get('label_all_metadata') }}</span> <span>{{ $i18n.get('label_all_metadata') }}</span>
</button> </button>
<button <button
v-if="!$adminOptions.hideItemEditionDocument" v-if="shouldDisplayItemEditionDocument || shouldDisplayItemEditionThumbnail"
@click="activeTab = 'document'; isMobileSubheaderOpen = false;"> @click="activeTab = 'document'; isMobileSubheaderOpen = false;">
<span><i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-item" /></span> <span><i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-item" /></span>
<span>{{ $i18n.get('label_document_and_thumbnail') }}</span> <span>{{ $i18n.get('label_document_and_thumbnail') }}</span>
</button> </button>
<button <button
v-if="!$adminOptions.hideItemEditionAttachments" v-if="shouldDisplayItemEditionAttachments"
@click="activeTab = 'attachments'; isMobileSubheaderOpen = false;"> @click="activeTab = 'attachments'; isMobileSubheaderOpen = false;">
<span><i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-attachments" /></span> <span><i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-attachments" /></span>
<span>{{ $i18n.get('label_all_attachments') }}</span> <span>{{ $i18n.get('label_all_attachments') }}</span>
</button> </button>
<button <button
v-if="!$adminOptions.hideItemEditionRequiredOnlySwitch" v-if="!$adminOptions.hideItemEditionRequiredOnlySwitch && (collection && collection.item_enable_metadata_required_filter === 'yes')"
@click="showOnlyRequiredMetadata = true; isMobileSubheaderOpen = false;"> @click="showOnlyRequiredMetadata = true; isMobileSubheaderOpen = false;">
<span><i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-metadata" /></span> <span><i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-metadata" /></span>
<span>{{ $i18n.get('label_only_required_metadata') }}</span> <span>{{ $i18n.get('label_only_required_metadata') }}</span>
@ -177,8 +177,8 @@
<div <div
class="column main-column" class="column main-column"
:class=" :class="
(( (!$adminOptions.hideItemEditionDocument || !$adminOptions.hideItemEditionThumbnail) && !$adminOptions.itemEditionDocumentInsideTabs) || (( (shouldDisplayItemEditionDocument || shouldDisplayItemEditionThumbnail) && !$adminOptions.itemEditionDocumentInsideTabs) ||
(!$adminOptions.hideItemEditionAttachments && !$adminOptions.itemEditionAttachmentsInsideTabs)) ? 'is-7' : 'is-12'"> (shouldDisplayItemEditionAttachments && !$adminOptions.itemEditionAttachmentsInsideTabs)) ? 'is-7' : 'is-12'">
<!-- Hook for extra Form options --> <!-- Hook for extra Form options -->
<template v-if="hasBeginRightForm"> <template v-if="hasBeginRightForm">
@ -261,10 +261,10 @@
<!-- Metadata navigation Progress --> <!-- Metadata navigation Progress -->
<div <div
v-if="isMetadataNavigation && itemMetadata && itemMetadata.length > 3" v-if="isMetadataNavigation"
class="sequence-progress-background" /> class="sequence-progress-background" />
<div <div
v-if="isMetadataNavigation && focusedMetadatum !== false && itemMetadata && itemMetadata.length > 3" v-if="isMetadataNavigation && focusedMetadatum !== false"
:style="{ width: ((focusedMetadatum + 1)/itemMetadata.length)*100 + '%' }" :style="{ width: ((focusedMetadatum + 1)/itemMetadata.length)*100 + '%' }"
class="sequence-progress" /> class="sequence-progress" />
@ -286,7 +286,7 @@
class="header-item metadata-navigation" class="header-item metadata-navigation"
:style="$adminOptions.hideItemEditionCollapses ? 'padding-left: 0.35em !important;' : ''"> :style="$adminOptions.hideItemEditionCollapses ? 'padding-left: 0.35em !important;' : ''">
<b-button <b-button
v-if="!$adminOptions.hideItemEditionFocusMode && !isMetadataNavigation && !showOnlyRequiredMetadata && !metadataNameFilterString" v-if="!$adminOptions.hideItemEditionFocusMode && (collection && collection.item_enable_metadata_focus_mode === 'yes') && !isMetadataNavigation && !showOnlyRequiredMetadata && !metadataNameFilterString"
@click="isMetadataNavigation = true; setMetadatumFocus({ index: 0, scrollIntoView: true });" @click="isMetadataNavigation = true; setMetadatumFocus({ index: 0, scrollIntoView: true });"
class="collapse-all has-text-secondary" class="collapse-all has-text-secondary"
size="is-small"> size="is-small">
@ -339,7 +339,7 @@
</span> </span>
<b-switch <b-switch
v-if="!isMetadataNavigation && !$adminOptions.hideItemEditionRequiredOnlySwitch && itemMetadata && itemMetadata.length > 3" v-if="!isMetadataNavigation && !$adminOptions.hideItemEditionRequiredOnlySwitch && (collection && collection.item_enable_metadata_required_filter === 'yes')"
id="tainacan-switch-required-metadata" id="tainacan-switch-required-metadata"
:style="'font-size: 0.625em;' + (isMobileScreen ? 'margin-right: 2rem;' : '')" :style="'font-size: 0.625em;' + (isMobileScreen ? 'margin-right: 2rem;' : '')"
size="is-small" size="is-small"
@ -348,7 +348,7 @@
</b-switch> </b-switch>
<b-field <b-field
v-if="!isMetadataNavigation && itemMetadata && itemMetadata.length > 5" v-if="!isMetadataNavigation && (collection && collection.item_enable_metadata_searchbar === 'yes')"
class="header-item metadata-name-search"> class="header-item metadata-name-search">
<b-input <b-input
v-if="!isMobileScreen || openMetadataNameFilter" v-if="!isMobileScreen || openMetadataNameFilter"
@ -397,6 +397,12 @@
<span class="icon has-text-gray4"> <span class="icon has-text-gray4">
<i class="tainacan-icon tainacan-icon-metadata"/> <i class="tainacan-icon tainacan-icon-metadata"/>
</span> </span>
<span
v-if="metadataSections.length > 1 && collection.item_enable_metadata_enumeration === 'yes'"
style="opacity: 0.65;"
class="metadata-section-enumeration">
{{ Number(sectionIndex) + 1 }}.
</span>
{{ metadataSection.name }}&nbsp; {{ metadataSection.name }}&nbsp;
<span <span
v-if="metadataSection.metadata_object_list && metadataSection.metadata_object_list.length" v-if="metadataSection.metadata_object_list && metadataSection.metadata_object_list.length"
@ -433,11 +439,12 @@
:item-metadatum="itemMetadatum" :item-metadatum="itemMetadatum"
:metadata-name-filter-string="metadataNameFilterString" :metadata-name-filter-string="metadataNameFilterString"
:is-collapsed="metadataCollapses[index]" :is-collapsed="metadataCollapses[index]"
:hide-collapses="$adminOptions.hideItemEditionCollapses || isMetadataNavigation" :hide-collapses="$adminOptions.hideItemEditionCollapses || isMetadataNavigation || (collection && collection.item_enable_metadata_collapses === 'no')"
:hide-metadata-types="hideMetadataTypes" :hide-metadata-types="hideMetadataTypes"
:hide-help-buttons="false" :hide-help-buttons="false"
:help-info-bellow-label="false" :help-info-bellow-label="false"
:is-mobile-screen="isMobileScreen" :is-mobile-screen="isMobileScreen"
:enumerate-metadatum="metadataSections.length > 1 && collection.item_enable_metadata_enumeration === 'yes' ? ( (Number(sectionIndex) + 1) + '.' + (Number(getMetadatumOrderInSection(sectionIndex, itemMetadatum.metadatum)) + 1) ) : false"
:is-last-metadatum="index > 2 && (index == itemMetadata.length - 1)" :is-last-metadatum="index > 2 && (index == itemMetadata.length - 1)"
:is-focused="focusedMetadatum === index" :is-focused="focusedMetadatum === index"
:is-metadata-navigation="isMetadataNavigation" :is-metadata-navigation="isMetadataNavigation"
@ -496,6 +503,7 @@
<item-document-edition-form <item-document-edition-form
:item="item" :item="item"
:form="form" :form="form"
:collection="collection"
@onSetDocument="setDocument" @onSetDocument="setDocument"
@onRemoveDocument="removeDocument" @onRemoveDocument="removeDocument"
@onSetFileDocument="setFileDocument" @onSetFileDocument="setFileDocument"
@ -504,6 +512,7 @@
<item-thumbnail-edition-form <item-thumbnail-edition-form
:item="item" :item="item"
:form="form" :form="form"
:collection="collection"
:is-loading="isLoading" :is-loading="isLoading"
@onDeleteThumbnail="deleteThumbnail" @onDeleteThumbnail="deleteThumbnail"
@onUpdateThumbnailAlt="($event) => onUpdateThumbnailAlt($event)" @onUpdateThumbnailAlt="($event) => onUpdateThumbnailAlt($event)"
@ -512,7 +521,7 @@
<!-- Attachments on mobile modal --> <!-- Attachments on mobile modal -->
<div <div
v-if="activeTab === 'attachments' && $adminOptions.itemEditionAttachmentsInsideTabs" v-if="activeTab === 'attachments' && shouldDisplayItemEditionAttachments && $adminOptions.itemEditionAttachmentsInsideTabs"
class="tab-item" class="tab-item"
role="tabpanel" role="tabpanel"
aria-labelledby="attachments-tab-label" aria-labelledby="attachments-tab-label"
@ -520,6 +529,7 @@
<item-attachments-edition-form <item-attachments-edition-form
:item="item" :item="item"
:form="form" :form="form"
:collection="collection"
:is-loading="isLoading" :is-loading="isLoading"
:total-attachments="totalAttachments" :total-attachments="totalAttachments"
:should-load-attachments="shouldLoadAttachments" :should-load-attachments="shouldLoadAttachments"
@ -533,8 +543,8 @@
</div> </div>
<div <div
v-if="( (!$adminOptions.hideItemEditionDocument || !$adminOptions.hideItemEditionThumbnail) && !$adminOptions.itemEditionDocumentInsideTabs) || v-if="( (shouldDisplayItemEditionDocument || shouldDisplayItemEditionThumbnail) && !$adminOptions.itemEditionDocumentInsideTabs) ||
(!$adminOptions.hideItemEditionAttachments && !$adminOptions.itemEditionAttachmentsInsideTabs)" (shouldDisplayItemEditionAttachments && !$adminOptions.itemEditionAttachmentsInsideTabs)"
class="column is-5"> class="column is-5">
<div <div
@ -551,33 +561,37 @@
<!-- Document -------------------------------- --> <!-- Document -------------------------------- -->
<item-document-edition-form <item-document-edition-form
v-if="!$adminOptions.itemEditionDocumentInsideTabs" v-if="shouldDisplayItemEditionDocument && !$adminOptions.itemEditionDocumentInsideTabs"
:item="item" :item="item"
:form="form" :form="form"
:collection="collection"
@onSetDocument="setDocument" @onSetDocument="setDocument"
@onRemoveDocument="removeDocument" @onRemoveDocument="removeDocument"
@onSetFileDocument="setFileDocument" @onSetFileDocument="setFileDocument"
@onSetTextDocument="setTextDocument" @onSetTextDocument="setTextDocument"
@onSetURLDocument="setURLDocument" /> @onSetURLDocument="setURLDocument" />
<hr>
<hr v-if="shouldDisplayItemEditionDocument && shouldDisplayItemEditionThumbnail">
<!-- Thumbnail -------------------------------- --> <!-- Thumbnail -------------------------------- -->
<item-thumbnail-edition-form <item-thumbnail-edition-form
v-if="!$adminOptions.itemEditionDocumentInsideTabs" v-if="shouldDisplayItemEditionThumbnail && !$adminOptions.itemEditionDocumentInsideTabs"
:item="item" :item="item"
:form="form" :form="form"
:collection="collection"
:is-loading="isLoading" :is-loading="isLoading"
@onDeleteThumbnail="deleteThumbnail" @onDeleteThumbnail="deleteThumbnail"
@onUpdateThumbnailAlt="($event) => onUpdateThumbnailAlt($event)" @onUpdateThumbnailAlt="($event) => onUpdateThumbnailAlt($event)"
@openThumbnailMediaFrame="thumbnailMediaFrame.openFrame($event)" /> @openThumbnailMediaFrame="thumbnailMediaFrame.openFrame($event)" />
<hr v-if="!$adminOptions.itemEditionAttachmentsInsideTabs || hasEndLeftForm"> <hr v-if="(shouldDisplayItemEditionAttachments && !$adminOptions.itemEditionAttachmentsInsideTabs) || hasEndLeftForm">
<!-- Attachments --> <!-- Attachments -->
<item-attachments-edition-form <item-attachments-edition-form
v-if="!$adminOptions.itemEditionAttachmentsInsideTabs" v-if="shouldDisplayItemEditionAttachments && !$adminOptions.itemEditionAttachmentsInsideTabs"
:item="item" :item="item"
:form="form" :form="form"
:collection="collection"
:is-loading="isLoading" :is-loading="isLoading"
:total-attachments="totalAttachments" :total-attachments="totalAttachments"
:should-load-attachments="shouldLoadAttachments" :should-load-attachments="shouldLoadAttachments"
@ -831,7 +845,7 @@ export default {
}, },
itemMetadata() { itemMetadata() {
const realItemMetadata = JSON.parse(JSON.stringify(this.getItemMetadata())); const realItemMetadata = JSON.parse(JSON.stringify(this.getItemMetadata()));
console.log(realItemMetadata)
const tweakedItemMetadata = realItemMetadata.map((anItemMetadatum) => { const tweakedItemMetadata = realItemMetadata.map((anItemMetadatum) => {
// We need this because repository level metadata have an array of section IDs // We need this because repository level metadata have an array of section IDs
@ -882,18 +896,18 @@ export default {
name: this.$i18n.get('metadata'), name: this.$i18n.get('metadata'),
total: this.itemMetadata.length total: this.itemMetadata.length
}]; }];
if ( this.$adminOptions.itemEditionDocumentInsideTabs && (!this.$adminOptions.hideItemEditionDocument || !this.$adminOptions.hideItemEditionThumbnail) ) { if ( this.$adminOptions.itemEditionDocumentInsideTabs && (this.shouldDisplayItemEditionDocument || this.shouldDisplayItemEditionThumbnail) ) {
pageTabs.push({ pageTabs.push({
slug: 'document', slug: 'document',
icon: 'item', icon: 'item',
name: this.$i18n.get('label_document') name: this.collection && this.collection.item_document_label ? this.collection.item_document_label : this.$i18n.get('label_document')
}); });
} }
if ( this.$adminOptions.itemEditionAttachmentsInsideTabs && !this.$adminOptions.hideItemEditionAttachments ) { if ( this.$adminOptions.itemEditionAttachmentsInsideTabs && this.shouldDisplayItemEditionAttachments ) {
pageTabs.push({ pageTabs.push({
slug: 'attachments', slug: 'attachments',
icon: 'attachments', icon: 'attachments',
name: this.$i18n.get('label_attachments'), name: this.collection && this.collection.item_attachment_label ? this.collection.item_attachment_label : this.$i18n.get('label_attachments'),
total: this.totalAttachments total: this.totalAttachments
}); });
} }
@ -911,6 +925,21 @@ export default {
if (!this.isMetadataNavigation || !this.itemMetadata[this.focusedMetadatum]) if (!this.isMetadataNavigation || !this.itemMetadata[this.focusedMetadatum])
return false; return false;
return this.itemMetadata[this.focusedMetadatum].metadatum && this.itemMetadata[this.focusedMetadatum].metadatum.metadata_type === 'Tainacan\\Metadata_Types\\Compound'; return this.itemMetadata[this.focusedMetadatum].metadatum && this.itemMetadata[this.focusedMetadatum].metadatum.metadata_type === 'Tainacan\\Metadata_Types\\Compound';
},
shouldDisplayItemEditionDocument() {
return !this.$adminOptions.hideItemEditionDocument &&
( this.collection && this.collection.item_enabled_document_types && (
( this.collection.item_enabled_document_types['attachment'] && this.collection.item_enabled_document_types['attachment']['enabled'] === 'yes' ) ||
( this.collection.item_enabled_document_types['text'] && this.collection.item_enabled_document_types['text']['enabled'] === 'yes' ) ||
( this.collection.item_enabled_document_types['url'] && this.collection.item_enabled_document_types['url']['enabled'] === 'yes' )
)
);
},
shouldDisplayItemEditionThumbnail() {
return !this.$adminOptions.hideItemEditionThumbnail && (this.collection && this.collection.item_enable_thumbnail === 'yes');
},
shouldDisplayItemEditionAttachments() {
return !this.$adminOptions.hideItemEditionAttachments && (this.collection && this.collection.item_enable_attachments === 'yes');
} }
}, },
watch: { watch: {
@ -1326,7 +1355,7 @@ export default {
if (currentItemMetadatum) { if (currentItemMetadatum) {
const itemMetadatumValues = Array.isArray(currentItemMetadatum.value) ? currentItemMetadatum.value : [ currentItemMetadatum.value ]; const itemMetadatumValues = Array.isArray(currentItemMetadatum.value) ? currentItemMetadatum.value : [ currentItemMetadatum.value ];
const conditionalValues = Array.isArray(this.conditionalSections[conditionalSectionId].metadatumValues) ? this.conditionalSections[conditionalSectionId].metadatumValues : [this.conditionalSections[conditionalSectionId].metadatumValues]; const conditionalValues = Array.isArray(this.conditionalSections[conditionalSectionId].metadatumValues) ? this.conditionalSections[conditionalSectionId].metadatumValues : [this.conditionalSections[conditionalSectionId].metadatumValues];
this.conditionalSections[conditionalSectionId].hide = itemMetadatumValues.every(aValue => conditionalValues.indexOf(aValue) < 0); this.conditionalSections[conditionalSectionId].hide = Array.isArray(itemMetadatumValues) ? itemMetadatumValues.every(aValue => conditionalValues.indexOf(aValue['id'] ? aValue['id'] : aValue) < 0) : conditionalValues.indexOf(itemMetadatumValues) < 0;
} }
} }
@ -1851,6 +1880,19 @@ export default {
}, },
isSectionHidden(sectionId) { isSectionHidden(sectionId) {
return this.conditionalSections[sectionId] && this.conditionalSections[sectionId].hide; return this.conditionalSections[sectionId] && this.conditionalSections[sectionId].hide;
},
getMetadatumOrderInSection(sectionIndex, metadatum) {
if ( !Array.isArray(this.collection['metadata_section_order']) || !this.collection['metadata_section_order'][sectionIndex] || !Array.isArray(this.collection['metadata_section_order'][sectionIndex]['metadata_order']) )
return -1;
let enabledMetadata = [];
for (let metadatum of this.collection['metadata_section_order'][sectionIndex]['metadata_order']) {
if ( metadatum.enabled )
enabledMetadata.push(metadatum.id);
}
return enabledMetadata.indexOf(metadatum.id);
} }
} }
} }

View File

@ -7,10 +7,10 @@
<span class="icon has-text-gray4"> <span class="icon has-text-gray4">
<i class="tainacan-icon tainacan-icon-image"/> <i class="tainacan-icon tainacan-icon-image"/>
</span> </span>
{{ $i18n.get('label_thumbnail') }} {{ collection && collection.item_thumbnail_label ? collection.item_thumbnail_label : $i18n.get('label_thumbnail') }}
</label> </label>
<help-button <help-button
:title="$i18n.getHelperTitle('items', '_thumbnail_id')" :title="collection && collection.item_thumbnail_label ? collection.item_thumbnail_label: $i18n.getHelperTitle('items', '_thumbnail_id')"
:message="$i18n.getHelperMessage('items', '_thumbnail_id')"/> :message="$i18n.getHelperMessage('items', '_thumbnail_id')"/>
</div> </div>
@ -104,6 +104,7 @@ export default {
}, },
props: { props: {
item: Object, item: Object,
collection: Object,
form: Object form: Object
}, },
emits: [ emits: [

View File

@ -10,7 +10,12 @@
v-if="form && Object.keys(form).length" v-if="form && Object.keys(form).length"
class="tainacan-modal-content"> class="tainacan-modal-content">
<div class="tainacan-modal-title"> <div class="tainacan-modal-title">
<h2 v-html="form.name ? ($i18n.get('instruction_configure_the_metadata_section') + ' <em>' + form.name + '</em>') : $i18n.get('instruction_configure_new_metadata_section')" /> <h2 v-if="form.name">
{{ $i18n.get('instruction_configure_the_metadata_section') }}&nbsp;<em>{{ form.name }}</em>
</h2>
<h2 v-else>
{{ $i18n.get('instruction_configure_new_metadata_section') }}
</h2>
<hr> <hr>
</div> </div>
<div class="tainacan-form"> <div class="tainacan-form">
@ -179,8 +184,9 @@
:extra-classes="isRepositoryLevel ? 'tainacan-repository-tooltip' : ''" /> :extra-classes="isRepositoryLevel ? 'tainacan-repository-tooltip' : ''" />
</label> </label>
<b-select <b-select
v-model="selectedConditionalMetadatum" v-model="selectedConditionalMetadatumId"
:placeholder="$i18n.get('label_select_metadatum')"> :placeholder="$i18n.get('label_select_metadatum')"
@input="reloadConditionalValueComponent()">
<option <option
v-for="conditionalMetadatum of availableConditionalMetadata" v-for="conditionalMetadatum of availableConditionalMetadata"
:key="conditionalMetadatum.id" :key="conditionalMetadatum.id"
@ -192,22 +198,23 @@
</transition> </transition>
<transition name="filter-item"> <transition name="filter-item">
<b-field <b-field
v-if="isConditionalSection && selectedConditionalMetadatum" v-if="isConditionalSection && selectedConditionalMetadatumId && selectedConditionalMetadatum && selectedConditionalMetadatum.name"
:addons="false" :addons="false"
:type="formErrors['conditional_section_rules'] != undefined ? 'is-danger' : ''" :type="formErrors['conditional_section_rules'] != undefined ? 'is-danger' : ''"
:message="formErrors['conditional_section_rules'] != undefined ? formErrors['conditional_section_rules'] : ''"> :message="formErrors['conditional_section_rules'] != undefined ? formErrors['conditional_section_rules'] : ''">
<label class="label is-inline"> <label class="label is-inline">
{{ availableConditionalMetadata.find((availableMetadatum) => availableMetadatum.id == selectedConditionalMetadatum).name }} {{ selectedConditionalMetadatum.name }}
</label> </label>
<div style="overflow-y: auto; overflow-x: hidden; max-height: 100px;"> <component
<b-checkbox v-if="shouldUpdateConditionalValue"
v-model="selectedConditionalValue" :is="selectedConditionalMetadatum.metadata_type_object.component"
v-for="(conditionalValue, conditionalValueIndex) of availableConditionalMetadata.find((availableMetadatum) => availableMetadatum.id == selectedConditionalMetadatum).metadata_type_object.options.options.split('\n')" :forced-component-type="selectedConditionalMetadatum.metadata_type_object.component.includes('taxonomy') ? 'tainacan-taxonomy-tag-input' : ''"
:key="conditionalValueIndex" :item-metadatum="{ metadatum: selectedConditionalMetadatum }"
:native-value="conditionalValue"> :value="Array.isArray(selectedConditionalValue) ? selectedConditionalValue[0] : selectedConditionalValue"
{{ conditionalValue }} :allow-new="false"
</b-checkbox> :maxtags="1"
</div> @input="selectConditionalValue"
/>
</b-field> </b-field>
</transition> </transition>
</div> </div>
@ -271,9 +278,10 @@
closedByForm: false, closedByForm: false,
entityName: 'metadataSection', entityName: 'metadataSection',
isUpdating: false, isUpdating: false,
selectedConditionalMetadatum: undefined, selectedConditionalMetadatumId: undefined,
selectedConditionalValue: [], selectedConditionalValue: [],
hideConditionalSectionSettings: false hideConditionalSectionSettings: false,
shouldUpdateConditionalValue: true
} }
}, },
computed: { computed: {
@ -281,18 +289,21 @@
'getMetadataSections' 'getMetadataSections'
]), ]),
availableConditionalMetadata() { availableConditionalMetadata() {
if (this.getMetadataSections.length) { if ( this.getMetadataSections.length ) {
const otherMetadataSections = this.getMetadataSections.filter(aMetadataSection => aMetadataSection.id != this.form.id); const otherMetadataSections = this.getMetadataSections.filter(aMetadataSection => aMetadataSection.id != this.form.id);
const availableMetadata = []; const availableMetadata = [];
for (let aMetadataSection of otherMetadataSections) for (let aMetadataSection of otherMetadataSections)
availableMetadata.push.apply(availableMetadata, aMetadataSection.metadata_object_list); availableMetadata.push.apply(availableMetadata, aMetadataSection.metadata_object_list);
return availableMetadata.filter(aMetadatum => aMetadatum.metadata_type === 'Tainacan\\Metadata_Types\\Selectbox'); return availableMetadata.filter(aMetadatum => aMetadatum.metadata_type === 'Tainacan\\Metadata_Types\\Selectbox' || aMetadatum.metadata_type === 'Tainacan\\Metadata_Types\\Taxonomy');
} }
return {}; return [];
}, },
isConditionalSection() { isConditionalSection() {
return this.form.is_conditional_section == 'yes'; return this.form.is_conditional_section == 'yes';
} },
selectedConditionalMetadatum() {
return this.availableConditionalMetadata.find(aMetadatum => aMetadatum.id == this.selectedConditionalMetadatumId)
},
}, },
created() { created() {
this.form = JSON.parse(JSON.stringify(this.originalMetadataSection)); this.form = JSON.parse(JSON.stringify(this.originalMetadataSection));
@ -302,7 +313,7 @@
if ( this.form.is_conditional_section == 'yes' && Object.keys(this.form.conditional_section_rules).length ) { if ( this.form.is_conditional_section == 'yes' && Object.keys(this.form.conditional_section_rules).length ) {
const conditionalMetadatum = Object.keys(this.form.conditional_section_rules)[0]; const conditionalMetadatum = Object.keys(this.form.conditional_section_rules)[0];
this.selectedConditionalMetadatum = conditionalMetadatum; this.selectedConditionalMetadatumId = conditionalMetadatum;
this.selectedConditionalValue = this.form.conditional_section_rules[conditionalMetadatum]; this.selectedConditionalValue = this.form.conditional_section_rules[conditionalMetadatum];
} }
@ -321,10 +332,9 @@
'updateMetadataSection' 'updateMetadataSection'
]), ]),
saveEdition(metadataSection) { saveEdition(metadataSection) {
if ( this.form.is_conditional_section == 'yes' && this.selectedConditionalMetadatumId && this.selectedConditionalValue ) {
if ( this.form.is_conditional_section == 'yes' && this.selectedConditionalMetadatum && this.selectedConditionalValue ) {
this.form.conditional_section_rules = {} this.form.conditional_section_rules = {}
this.form.conditional_section_rules[this.selectedConditionalMetadatum] = this.selectedConditionalValue; this.form.conditional_section_rules[this.selectedConditionalMetadatumId] = this.selectedConditionalValue;
} else } else
this.form.conditional_section_rules = null; this.form.conditional_section_rules = null;
@ -364,6 +374,15 @@
this.closedByForm = true; this.closedByForm = true;
this.$emit('onEditionCanceled'); this.$emit('onEditionCanceled');
}, },
selectConditionalValue(selected) {
const selectedValues = Array.isArray(selected) ? selected : [ selected ];
this.selectedConditionalValue = selectedValues.map( aSelected => aSelected.value ? aSelected.value : aSelected );
},
reloadConditionalValueComponent() {
this.shouldUpdateConditionalValue = false;
this.selectedConditionalValue = [];
this.$nextTick(() => this.shouldUpdateConditionalValue = true);
}
} }
} }
</script> </script>
@ -441,6 +460,18 @@
height: 1px; height: 1px;
background-color: var(--tainacan-gray2); background-color: var(--tainacan-gray2);
margin-left: 42px; margin-left: 42px;
transition: background-color 0.2s ease, height 0.2s ease;
}
&:hover {
.icon,
strong {
color: var(--tainacan-secondary);
}
hr {
background-color: var(--tainacan-primary);
height: 2px;
}
} }
} }
@ -452,6 +483,24 @@
} }
} }
} }
:deep(.is-special-hidden-for-mobile) {
&,
&:focus,
&:focus-visible {
opacity: 0;
width: 0;
height: 0 !important;
min-height: 0;
min-width: 0;
padding: 0 !important;
line-height: 0px !important;
border: none !important;
border-color: transparent !important;
border-width: 0px !important;
font-size: 0px !important;
display: block !important;
}
}
.form-submit { .form-submit {
background-color: var(--tainacan-gray1); background-color: var(--tainacan-gray1);
position: sticky; position: sticky;

View File

@ -10,7 +10,12 @@
v-if="form && Object.keys(form).length" v-if="form && Object.keys(form).length"
class="tainacan-modal-content"> class="tainacan-modal-content">
<div class="tainacan-modal-title"> <div class="tainacan-modal-title">
<h2 v-html="form.name ? ($i18n.get('instruction_configure_the_metadatum') + ' <em>' + form.name + '</em>') : $i18n.get('instruction_configure_new_metadatum')" /> <h2 v-if="form.name">
{{ $i18n.get('instruction_configure_the_metadatum') }}&nbsp;<em>{{ form.name }}</em>
</h2>
<h2 v-else>
{{ $i18n.get('instruction_configure_new_metadatum') }}
</h2>
<!-- <a <!-- <a
class="back-link" class="back-link"
@click="onEditionCanceled()"> @click="onEditionCanceled()">
@ -616,6 +621,18 @@
height: 1px; height: 1px;
background-color: var(--tainacan-gray2); background-color: var(--tainacan-gray2);
margin-left: 42px; margin-left: 42px;
transition: background-color 0.2s ease, height 0.2s ease;
}
&:hover {
.icon,
strong {
color: var(--tainacan-secondary);
}
hr {
background-color: var(--tainacan-primary);
height: 2px;
}
} }
} }

View File

@ -231,7 +231,7 @@
class="button link-button" class="button link-button"
:href="themeTaxonomiesURL + taxonomy.slug"> :href="themeTaxonomiesURL + taxonomy.slug">
<span class="icon is-large"> <span class="icon is-large">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-see"/> <i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-openurl"/>
</span> </span>
<span>{{ $i18n.get('label_taxonomy_page_on_website') }}</span> <span>{{ $i18n.get('label_taxonomy_page_on_website') }}</span>
</a> </a>
@ -556,7 +556,7 @@
.status-radios { .status-radios {
display: flex; display: flex;
} }
.status-radios .control-lable { .status-radios .control-label {
display: flex; display: flex;
align-items: center; align-items: center;
} }

View File

@ -15,7 +15,7 @@
target="_blank" target="_blank"
:href="form.url"> :href="form.url">
<span class="icon"> <span class="icon">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-see"/> <i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-openurl"/>
</span> </span>
<span class="menu-text">{{ $i18n.get('label_term_page_on_website') }}</span> <span class="menu-text">{{ $i18n.get('label_term_page_on_website') }}</span>
</a> </a>
@ -233,7 +233,9 @@
originalForm: Object, originalForm: Object,
taxonomyId: '', taxonomyId: '',
isHierarchical: Boolean, isHierarchical: Boolean,
isTermInsertionFlow: false isTermInsertionFlow: false,
metadatumId: [String, Number],
itemId: [String, Number]
}, },
emits: [ emits: [
'onEditionFinished' 'onEditionFinished'
@ -311,7 +313,9 @@
this.isLoading = true; this.isLoading = true;
this.sendChildTerm({ this.sendChildTerm({
taxonomyId: this.taxonomyId, taxonomyId: this.taxonomyId,
term: data term: data,
metadatumId: this.metadatumId,
itemId: this.itemId
}) })
.then((term) => { .then((term) => {
this.$emit('onEditionFinished', {term: term, hasChangedParent: this.hasChangedParent, initialParent: this.initialParentId }); this.$emit('onEditionFinished', {term: term, hasChangedParent: this.hasChangedParent, initialParent: this.initialParentId });
@ -345,7 +349,9 @@
this.isLoading = true; this.isLoading = true;
this.updateTerm({ this.updateTerm({
taxonomyId: this.taxonomyId, taxonomyId: this.taxonomyId,
term: data term: data,
metadatumId: this.metadatumId,
itemId: this.itemId
}) })
.then((term) => { .then((term) => {
this.formErrors = {}; this.formErrors = {};

View File

@ -71,7 +71,7 @@
@update:model-value="emitOnlyYear($event)" @update:model-value="emitOnlyYear($event)"
v-model="yearsOnlyValue"/> --> v-model="yearsOnlyValue"/> -->
<b-datepicker <b-datepicker
position="is-bottom-left" position="is-bottom-right"
:aria-labelledby="'filter-label-id-' + filter.id" :aria-labelledby="'filter-label-id-' + filter.id"
:placeholder="$i18n.get('instruction_select_a_date')" :placeholder="$i18n.get('instruction_select_a_date')"
v-model="value" v-model="value"
@ -104,7 +104,7 @@
$i18n.get('datepicker_month_october'), $i18n.get('datepicker_month_october'),
$i18n.get('datepicker_month_november'), $i18n.get('datepicker_month_november'),
$i18n.get('datepicker_month_december') $i18n.get('datepicker_month_december')
]"/> ]" />
<!-- filterTypeOptions FOR TYPE <!-- filterTypeOptions FOR TYPE
v-else v-else
:type="filterTypeOptions.type == 'month' ? 'month' : null" :type="filterTypeOptions.type == 'month' ? 'month' : null"

View File

@ -236,27 +236,12 @@
} }
.taginput-container { .taginput-container {
border-radius: 1px !important; border-radius: var(--tainacan-input-border-radius, 1px) !important;
box-shadow: none !important; box-shadow: none !important;
transition: background-color 0.1s; transition: background-color 0.1s;
} }
.taginput-container { .taginput-container {
border: none !important;
&.is-focused,
&.is-focused:active,
&.is-focused:focus,
&.is-focusable,
&.is-focusable:active
&.is-focusable:focus {
border: none !important;
input:active, input:focus {
border: 1px solid var(--tainacan-input-border-color) !important;
}
}
input{
border: 1px solid var(--tainacan-input-border-color) !important;
}
.tags { .tags {
display: none !important; display: none !important;
} }

View File

@ -271,7 +271,7 @@
this.selected.push(newSelected); this.selected.push(newSelected);
} }
}, },
width: 'calc(100% - (4 * var(--tainacan-one-column)))', width: 'max(768px, calc(100% - (4 * var(--tainacan-one-column))))',
trapFocus: true, trapFocus: true,
customClass: 'tainacan-modal', customClass: 'tainacan-modal',
closeButtonAriaLabel: this.$i18n.get('close') closeButtonAriaLabel: this.$i18n.get('close')

View File

@ -18,7 +18,7 @@
<span <span
v-if="form.document == attachment.id" v-if="form.document == attachment.id"
class="file-attachment-document-tag"> class="file-attachment-document-tag">
{{ $i18n.get('label_document') }} {{ collection && collection.item_document_label ? collection.item_document_label : $i18n.get('label_document') }}
</span> </span>
<file-item <file-item
:show-name="true" :show-name="true"
@ -52,7 +52,7 @@
<i class="tainacan-icon tainacan-icon-30px tainacan-icon-attachments"/> <i class="tainacan-icon tainacan-icon-30px tainacan-icon-attachments"/>
</span> </span>
</p> </p>
<p>{{ $i18n.get('info_no_attachments_on_item_yet') }}</p> <p>{{ $i18n.getWithVariables('info_no_%s_on_item_yet', [ collection && collection.item_attachment_label ? collection.item_attachment_label : $i18n.get('label_attachments') ]) }}</p>
</div> </div>
</section> </section>
</div> </div>
@ -63,7 +63,7 @@
v-if="attachments.length > 0"> v-if="attachments.length > 0">
<div class="shown-items"> <div class="shown-items">
{{ {{
$i18n.get('info_showing_attachments') + ' ' + $i18n.getWithVariables('info_showing_%s', [ collection && collection.item_attachment_label ? collection.item_attachment_label : $i18n.get('label_attachments') ]) + ' ' +
(attachmentsPerPage * (attachmentsPage - 1) + 1) + (attachmentsPerPage * (attachmentsPage - 1) + 1) +
$i18n.get('info_to') + $i18n.get('info_to') +
getLastAttachmentsNumber() + getLastAttachmentsNumber() +
@ -99,6 +99,7 @@
props: { props: {
item: Object, item: Object,
form: Object, form: Object,
collection: Object,
shouldLoadAttachments: Boolean, shouldLoadAttachments: Boolean,
isEditable: Boolean, isEditable: Boolean,
}, },

View File

@ -246,7 +246,7 @@
popperClass: ['tainacan-tooltip', 'tooltip'] popperClass: ['tainacan-tooltip', 'tooltip']
}" }"
class="icon"> class="icon">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-see"/> <i class="tainacan-icon tainacan-icon-1-125em tainacan-icon-openurl"/>
</span> </span>
</a> </a>
</li> </li>

View File

@ -8,8 +8,10 @@
<div class="field select-all is-pulled-left"> <div class="field select-all is-pulled-left">
<span> <span>
<b-checkbox <b-checkbox
@click="selectAllCollectionsOnPage()" @click.native="selectAllCollectionsOnPage()"
:model-value="allCollectionsOnPageSelected">{{ $i18n.get('label_select_all_collections_page') }}</b-checkbox> :model-value="allCollectionsOnPageSelected">
{{ $i18n.get('label_select_all_collections_page') }}
</b-checkbox>
</span> </span>
</div> </div>
<div class="field is-pulled-right"> <div class="field is-pulled-right">
@ -348,6 +350,24 @@
class="tainacan-icon tainacan-icon-1-25em"/> class="tainacan-icon tainacan-icon-1-25em"/>
</span> </span>
</a> </a>
<a
id="button-open-external"
:aria-label="$i18n.getFrom('collections','view_item')"
@click.stop=""
target="_blank"
:href="collection.url">
<span
v-tooltip="{
content: $i18n.get('label_view_collection_on_website'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', 'tainacan-repository-tooltip'],
placement: 'auto',
html: true
}"
class="icon">
<i class="tainacan-icon tainacan-icon-1-125em tainacan-icon-openurl"/>
</span>
</a>
</div> </div>
</td> </td>
</tr> </tr>
@ -561,7 +581,7 @@ export default {
.selection-control { .selection-control {
padding: 6px 0px 0px 12px; padding: 6px 0px 0px 12px;
background: var(--tainacan-white); background: var(--tainacan-background-color);
height: 40px; height: 40px;
.select-all { .select-all {

View File

@ -302,6 +302,25 @@
class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/> class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/>
</span> </span>
</a> </a>
<a
v-if="!isOnTrash"
id="button-open-external"
:aria-label="$i18n.getFrom('items','view_item')"
@click.stop=""
target="_blank"
:href="item.url">
<span
v-tooltip="{
content: $i18n.get('label_item_page_on_website'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', isRepositoryLevel ? 'tainacan-repository-tooltip' : ''],
placement: 'auto',
html: true
}"
class="icon">
<i class="tainacan-icon tainacan-icon-1-125em tainacan-icon-openurl"/>
</span>
</a>
</div> </div>
</div> </div>
@ -447,6 +466,25 @@
class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/> class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/>
</span> </span>
</a> </a>
<a
v-if="!isOnTrash"
id="button-open-external"
:aria-label="$i18n.getFrom('items','view_item')"
@click.stop=""
target="_blank"
:href="item.url">
<span
v-tooltip="{
content: $i18n.get('label_item_page_on_website'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', isRepositoryLevel ? 'tainacan-repository-tooltip' : ''],
placement: 'auto',
html: true
}"
class="icon">
<i class="tainacan-icon tainacan-icon-1-125em tainacan-icon-openurl"/>
</span>
</a>
</div> </div>
</div> </div>
</li> </li>
@ -578,6 +616,25 @@
class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/> class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/>
</span> </span>
</a> </a>
<a
v-if="!isOnTrash"
id="button-open-external"
:aria-label="$i18n.getFrom('items','view_item')"
@click.stop=""
target="_blank"
:href="item.url">
<span
v-tooltip="{
content: $i18n.get('label_item_page_on_website'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', isRepositoryLevel ? 'tainacan-repository-tooltip' : ''],
placement: 'auto',
html: true
}"
class="icon">
<i class="tainacan-icon tainacan-icon-1-125em tainacan-icon-openurl"/>
</span>
</a>
</div> </div>
<!-- Remaining metadata --> <!-- Remaining metadata -->
@ -801,6 +858,25 @@
class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/> class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/>
</span> </span>
</a> </a>
<a
v-if="!isOnTrash"
id="button-open-external"
:aria-label="$i18n.getFrom('items','view_item')"
@click.stop=""
target="_blank"
:href="item.url">
<span
v-tooltip="{
content: $i18n.get('label_item_page_on_website'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', isRepositoryLevel ? 'tainacan-repository-tooltip' : ''],
placement: 'auto',
html: true
}"
class="icon">
<i class="tainacan-icon tainacan-icon-1-125em tainacan-icon-openurl"/>
</span>
</a>
</div> </div>
<!-- Remaining metadata --> <!-- Remaining metadata -->
@ -1147,7 +1223,26 @@
<i <i
:class="{ 'tainacan-icon-delete': !isOnTrash, 'tainacan-icon-deleteforever': isOnTrash }" :class="{ 'tainacan-icon-delete': !isOnTrash, 'tainacan-icon-deleteforever': isOnTrash }"
class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/> class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/>
</span> </span>
</a>
<a
v-if="!isOnTrash"
id="button-open-external"
:aria-label="$i18n.getFrom('items','view_item')"
@click.stop=""
target="_blank"
:href="item.url">
<span
v-tooltip="{
content: $i18n.get('label_item_page_on_website'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', isRepositoryLevel ? 'tainacan-repository-tooltip' : ''],
placement: 'auto',
html: true
}"
class="icon">
<i class="tainacan-icon tainacan-icon-1-125em tainacan-icon-openurl"/>
</span>
</a> </a>
</div> </div>
</td> </td>
@ -1304,6 +1399,25 @@
class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/> class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/>
</span> </span>
</a> </a>
<a
v-if="!isOnTrash"
id="button-open-external"
:aria-label="$i18n.getFrom('items','view_item')"
@click.stop=""
target="_blank"
:href="item.url">
<span
v-tooltip="{
content: $i18n.get('label_item_page_on_website'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', isRepositoryLevel ? 'tainacan-repository-tooltip' : ''],
placement: 'auto',
html: true
}"
class="icon">
<i class="tainacan-icon tainacan-icon-1-125em tainacan-icon-openurl"/>
</span>
</a>
</div> </div>
<!-- Remaining metadata --> <!-- Remaining metadata -->
@ -1778,6 +1892,25 @@
class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/> class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/>
</span> </span>
</a> </a>
<a
v-if="!isOnTrash"
id="button-open-external"
:aria-label="$i18n.getFrom('items','view_item')"
@click.stop=""
target="_blank"
:href="item.url">
<span
v-tooltip="{
content: $i18n.get('label_item_page_on_website'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', isRepositoryLevel ? 'tainacan-repository-tooltip' : ''],
placement: 'auto',
html: true
}"
class="icon">
<i class="tainacan-icon tainacan-icon-1-125em tainacan-icon-openurl"/>
</span>
</a>
</div> </div>
<!-- Remaining metadata --> <!-- Remaining metadata -->
@ -2239,9 +2372,8 @@ export default {
collectionId: this.collectionId, collectionId: this.collectionId,
itemId: itemId, itemId: itemId,
onConfirm: (newItems) => { onConfirm: (newItems) => {
if (newItems != null && newItems != undefined && newItems.length > 0) { if (newItems != null && newItems != undefined && newItems.length > 0)
this.$eventBusSearch.loadItems(); this.$eventBusSearch.loadItems();
}
} }
}, },
trapFocus: true, trapFocus: true,
@ -2271,9 +2403,7 @@ export default {
this.untrashItemsInBulk({ this.untrashItemsInBulk({
collectionId: this.collectionId, collectionId: this.collectionId,
groupId: groupId groupId: groupId
}).then(() => { }).then(() => this.$eventBusSearch.loadItems() );
this.$eventBusSearch.loadItems();
});
}); });
} }
}, },
@ -2296,9 +2426,7 @@ export default {
this.deleteItem({ this.deleteItem({
itemId: itemId, itemId: itemId,
isPermanently: this.isOnTrash isPermanently: this.isOnTrash
}).then(() => { }).then(() => this.$eventBusSearch.loadItems() );
this.$eventBusSearch.loadItems();
});
} }
}, },
trapFocus: true, trapFocus: true,
@ -2569,7 +2697,7 @@ export default {
.selection-control { .selection-control {
margin-bottom: 6px; margin-bottom: 6px;
padding: 6px 0px 0px 12px; padding: 6px 0px 0px 12px;
background: var(--tainacan-white); background: var(--tainacan-background-color);
height: 40px; height: 40px;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -522,12 +522,16 @@
.sub-header { .sub-header {
@include logs-container(); @include logs-container();
.header-item {
min-height: 1.875em;
}
} }
.selection-control { .selection-control {
padding: 6px 0px 0px 12px; padding: 6px 0px 0px 12px;
background: var(--tainacan-white); background: var(--tainacan-background-color);
height: 40px; height: 40px;
.select-all { .select-all {

View File

@ -9,8 +9,10 @@
<div class="field select-all is-pulled-left"> <div class="field select-all is-pulled-left">
<span> <span>
<b-checkbox <b-checkbox
@click="selectAllOnPage()" @click.native="selectAllOnPage()"
:model-value="allOnPageSelected">{{ $i18n.get('label_select_all_taxonomies_page') }}</b-checkbox> :model-value="allOnPageSelected">
{{ $i18n.get('label_select_all_taxonomies_page') }}
</b-checkbox>
</span> </span>
</div> </div>
<div class="field is-pulled-right"> <div class="field is-pulled-right">
@ -234,6 +236,25 @@
class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/> class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/>
</span> </span>
</a> </a>
<a
v-if="!isOnTrash"
id="button-open-external"
:aria-label="$i18n.getFrom('taxonomies','view_item')"
@click.stop=""
target="_blank"
:href="themeTaxonomiesURL + taxonomy.slug">
<span
v-tooltip="{
content: $i18n.get('label_taxonomy_page_on_website'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', 'tainacan-repository-tooltip'],
placement: 'auto',
html: true
}"
class="icon">
<i class="tainacan-icon tainacan-icon-1-125em tainacan-icon-openurl"/>
</span>
</a>
</div> </div>
</td> </td>
</tr> </tr>
@ -262,7 +283,8 @@
selected: [], selected: [],
allOnPageSelected: false, allOnPageSelected: false,
isSelecting: false, isSelecting: false,
adminUrl: tainacan_plugin.admin_url adminUrl: tainacan_plugin.admin_url,
themeTaxonomiesURL: tainacan_plugin.theme_taxonomy_list_url
} }
}, },
computed: { computed: {
@ -421,7 +443,7 @@
.selection-control { .selection-control {
padding: 6px 0px 0px 12px; padding: 6px 0px 0px 12px;
background: var(--tainacan-white); background: var(--tainacan-background-color);
height: 40px; height: 40px;
.select-all { .select-all {

View File

@ -137,9 +137,23 @@
placement: 'bottom' placement: 'bottom'
}" }"
class="icon"> class="icon">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-delete"/> <i class="tainacan-icon tainacan-icon-1-125em tainacan-icon-delete"/>
</span> </span>
</button> </button>
<a
target="_blank"
:href="term.url">
<span
v-tooltip="{
content: $i18n.get('label_term_page_on_website'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', 'tainacan-repository-tooltip'],
placement: 'bottom'
}"
class="icon">
<i class="tainacan-icon tainacan-icon-1-125em tainacan-icon-openurl"/>
</span>
</a>
</div> </div>
</label> </label>
<button <button
@ -745,7 +759,7 @@ export default {
let errorMessage = errors.length > 1 ? this.$i18n.getWithVariables('info_terms_creation_failed_due_to_values_%s', [ wrongValues ]) : this.$i18n.getWithVariables('info_terms_creation_failed_due_to_value_%s', [ wrongValues ]); let errorMessage = errors.length > 1 ? this.$i18n.getWithVariables('info_terms_creation_failed_due_to_values_%s', [ wrongValues ]) : this.$i18n.getWithVariables('info_terms_creation_failed_due_to_value_%s', [ wrongValues ]);
errorMessage += ' ' + errors[0]['errors'][0]['name']; errorMessage += ' ' + errors[0]['errors'][0]['name'];
this.$buefy.snackbar.open({ this.$buefy.snackbar.open({
message: errorMessage, message: this.$htmlSanitizer.sanitize(errorMessage),
type: 'is-danger', type: 'is-danger',
position: 'is-bottom-right', position: 'is-bottom-right',
pauseOnHover: true, pauseOnHover: true,
@ -860,7 +874,10 @@ export default {
.tainacan-hierarchical-list-columns-container { .tainacan-hierarchical-list-columns-container {
background-color: var(--tainacan-background-color); background-color: var(--tainacan-background-color);
border: 1px solid var(--tainacan-gray2); border: 1px solid var(--tainacan-gray2);
border-radius: 2px; border-bottom-left-radius: var(--tainacan-dropdownmenu-border-radius);
border-bottom-right-radius: var(--tainacan-dropdownmenu-border-radius);
border-top-right-radius: 0px;
border-top-left-radius: 0px;
margin-top: 0px; margin-top: 0px;
display: flex; display: flex;
height: auto; height: auto;

View File

@ -348,7 +348,10 @@ export default {
.tainacan-hierarchical-list-columns-container { .tainacan-hierarchical-list-columns-container {
background-color: var(--tainacan-background-color); background-color: var(--tainacan-background-color);
border: 1px solid var(--tainacan-gray2); border: 1px solid var(--tainacan-gray2);
border-radius: 2px; border-bottom-left-radius: var(--tainacan-dropdownmenu-border-radius);
border-bottom-right-radius: var(--tainacan-dropdownmenu-border-radius);
border-top-right-radius: 0px;
border-top-left-radius: 0px;
margin-top: 0px; margin-top: 0px;
display: flex; display: flex;
height: auto; height: auto;

View File

@ -31,6 +31,12 @@
<i class="has-text-secondary tainacan-icon tainacan-icon-1-25em tainacan-icon-arrowdown" /> <i class="has-text-secondary tainacan-icon tainacan-icon-1-25em tainacan-icon-arrowdown" />
</span> </span>
<label class="label has-tooltip"> <label class="label has-tooltip">
<span
v-if="enumerateMetadatum"
style="opacity: 0.65;"
class="metadatum-section-enumeration">
{{ enumerateMetadatum }}.
</span>
{{ childItemMetadatum.metadatum.name }} {{ childItemMetadatum.metadatum.name }}
</label> </label>
<span <span
@ -69,6 +75,7 @@
}" }"
:is-focused="(focusedGroupMetadatum === groupIndex) && (focusedChildMetadatum === childIndex)" :is-focused="(focusedGroupMetadatum === groupIndex) && (focusedChildMetadatum === childIndex)"
:is-metadata-navigation="isMetadataNavigation" :is-metadata-navigation="isMetadataNavigation"
:enumerate-metadatum="enumerateMetadatum ? ( enumerateMetadatum + ( childItemMetadataGroups.length > 1 ? ( '.' + (Number(groupIndex) + 1) ) : '' ) + '.' + (Number(childIndex) + 1) ) : false"
@touchstart="isMetadataNavigation ? setMetadatumChildFocus({ groupIndex: groupIndex, childIndex: childIndex, scrollIntoView: false }): ''" @touchstart="isMetadataNavigation ? setMetadatumChildFocus({ groupIndex: groupIndex, childIndex: childIndex, scrollIntoView: false }): ''"
@mousedown="isMetadataNavigation ? setMetadatumChildFocus({ groupIndex: groupIndex, childIndex: childIndex, scrollIntoView: false }) : ''" @mousedown="isMetadataNavigation ? setMetadatumChildFocus({ groupIndex: groupIndex, childIndex: childIndex, scrollIntoView: false }) : ''"
@mobileSpecialFocus="setMetadatumChildFocus({ groupIndex: groupIndex, childIndex: childIndex, scrollIntoView: true })" @mobileSpecialFocus="setMetadatumChildFocus({ groupIndex: groupIndex, childIndex: childIndex, scrollIntoView: true })"
@ -129,6 +136,7 @@
metadataNameFilterString: '', metadataNameFilterString: '',
isMobileScreen: false, isMobileScreen: false,
isMetadataNavigation: false, isMetadataNavigation: false,
enumerateMetadatum: [Boolean|String],
isFocused: false isFocused: false
}, },
data() { data() {
@ -161,7 +169,7 @@
}, },
watch: { watch: {
/* This will create the input object structure for /* This will create the input object structure for
* <tainacan-item-form :item-metadatum="childItemMetadatum" /> * <tainacan-form-item :item-metadatum="childItemMetadatum" />
* looking at the values from the parent (this.itemMetadatum) * looking at the values from the parent (this.itemMetadatum)
*/ */
'itemMetadatum.value': { 'itemMetadatum.value': {

View File

@ -263,7 +263,7 @@ class Compound extends Metadata_Type {
if ($meta instanceof Item_Metadata_Entity && !empty($meta->get_value_as_html())) { if ($meta instanceof Item_Metadata_Entity && !empty($meta->get_value_as_html())) {
ob_start(); ob_start();
?> ?>
<div class="tainacan-metadatum metadata-type-<?php echo $meta->get_metadatum()->get_metadata_type_object()->get_slug() ?>"> <div class="tainacan-metadatum metadata-type-<?php echo $meta->get_metadatum()->get_metadata_type_object()->get_slug(); ?> metadata-slug-<?php echo $meta->get_metadatum()->get_slug(); ?>">
<h4 class="label"> <h4 class="label">
<?php echo esc_html($meta->get_metadatum()->get_name()); ?> <?php echo esc_html($meta->get_metadatum()->get_name()); ?>
</h4> </h4>

View File

@ -19,11 +19,24 @@ class Core_Description extends Metadata_Type {
$this->set_core(true); $this->set_core(true);
$this->set_related_mapped_prop('description'); $this->set_related_mapped_prop('description');
$this->set_component('tainacan-textarea'); $this->set_component('tainacan-textarea');
$this->set_form_component('tainacan-form-textarea');
$this->set_name( __('Core Description', 'tainacan') ); $this->set_name( __('Core Description', 'tainacan') );
$this->set_description( __('The "Core Description" is a compulsory metadata automatically created for all collections by default. This is the main description displayed in items lists and where the basic research tools will do their searches.', 'tainacan') ); $this->set_description( __('The "Core Description" is a compulsory metadata automatically created for all collections by default. This is the main description displayed in items lists and where the basic research tools will do their searches.', 'tainacan') );
$this->set_sortable( false ); $this->set_sortable( false );
} }
/**
* @inheritdoc
*/
public function get_form_labels(){
return [
'maxlength' => [
'title' => __( 'Maximum of characters', 'tainacan' ),
'description' => __( 'Limits the character input to a maximum value an displays a counter.', 'tainacan' ),
]
];
}
/** /**
* generate the metadata for this metadatum type * generate the metadata for this metadatum type
*/ */

View File

@ -26,7 +26,7 @@ class Metadata_Type_Helper {
private function __construct() { private function __construct() {
$this->registered_metadata_type = []; $this->registered_metadata_type = [];
$this->Tainacan_Metadata = \Tainacan\Repositories\Metadata::get_instance();; $this->Tainacan_Metadata = \Tainacan\Repositories\Metadata::get_instance();
$this->init(); $this->init();
} }

View File

@ -69,6 +69,32 @@
</button> </button>
</div> </div>
</b-field> </b-field>
<b-field :addons="false">
<label class="label is-inline">
{{ $i18n.getHelperTitle('tainacan-numeric', 'min') }}
<help-button
:title="$i18n.getHelperTitle('tainacan-numeric', 'min')"
:message="$i18n.getHelperMessage('tainacan-numeric', 'min')" />
</label>
<b-numberinput
v-model="min"
name="min"
step="1"
@input="onUpdateMin"/>
</b-field>
<b-field :addons="false">
<label class="label is-inline">
{{ $i18n.getHelperTitle('tainacan-numeric', 'max') }}
<help-button
:title="$i18n.getHelperTitle('tainacan-numeric', 'max')"
:message="$i18n.getHelperMessage('tainacan-numeric', 'max')" />
</label>
<b-numberinput
v-model="max"
name="max"
step="1"
@input="onUpdateMax"/>
</b-field>
</section> </section>
</template> </template>
@ -81,15 +107,25 @@
data() { data() {
return { return {
step: [Number, String], step: [Number, String],
min: [Number, null],
max: [Number, null],
showEditStepOptions: false showEditStepOptions: false
} }
}, },
created() { created() {
this.step = this.value && this.value.step ? this.value.step : 0.01; this.step = this.value && this.value.step ? this.value.step : 0.01;
this.min = this.value && this.value.min ? Number(this.value.min) : null;
this.max = this.value && this.value.max ? Number(this.value.max) : null;
}, },
methods: { methods: {
onUpdateStep(value) { onUpdateStep(value) {
this.$emit('input', { step: value }); this.$emit('input', { step: value, min: this.min, max: this.max });
},
onUpdateMin(value) {
this.$emit('input', { step: this.step, min: value, max: this.max });
},
onUpdateMax(value) {
this.$emit('input', { step: this.step, min: this.min, max: value });
} }
} }
} }

View File

@ -1,15 +1,17 @@
<template> <template>
<b-input <b-numberinput
:disabled="disabled" :disabled="disabled"
:ref="'tainacan-item-metadatum_id-' + itemMetadatum.metadatum.id + (itemMetadatum.parent_meta_id ? ('_parent_meta_id-' + itemMetadatum.parent_meta_id) : '')"
:id="'tainacan-item-metadatum_id-' + itemMetadatum.metadatum.id + (itemMetadatum.parent_meta_id ? ('_parent_meta_id-' + itemMetadatum.parent_meta_id) : '')" :id="'tainacan-item-metadatum_id-' + itemMetadatum.metadatum.id + (itemMetadatum.parent_meta_id ? ('_parent_meta_id-' + itemMetadatum.parent_meta_id) : '')"
:placeholder="itemMetadatum.metadatum.placeholder ? itemMetadatum.metadatum.placeholder : ''" :placeholder="itemMetadatum.metadatum.placeholder ? itemMetadatum.metadatum.placeholder : ''"
:model-value="value" :model-value="value"
@update:model-value="onInput($event);" @update:model-value="$event =>onInput($event)"
@blur="onBlur" @blur="onBlur"
@focus="onMobileSpecialFocus" @focus="onMobileSpecialFocus"
type="number"
lang="en" lang="en"
:step="getStep"/> :min="getMin"
:max="getMax"
:step="getStep" />
</template> </template>
<script> <script>
@ -30,10 +32,26 @@
return this.itemMetadatum.metadatum.metadata_type_options.step; return this.itemMetadatum.metadatum.metadata_type_options.step;
else else
return 0.01; return 0.01;
},
getMin() {
if (this.itemMetadatum && this.itemMetadatum.metadatum.metadata_type_options && this.itemMetadatum.metadatum.metadata_type_options.min !== null && this.itemMetadatum.metadatum.metadata_type_options.min !== undefined && this.itemMetadatum.metadatum.metadata_type_options.min !== '')
return Number(this.itemMetadatum.metadatum.metadata_type_options.min);
else
return undefined;
},
getMax() {
if (this.itemMetadatum && this.itemMetadatum.metadatum.metadata_type_options && this.itemMetadatum.metadatum.metadata_type_options.max !== null && this.itemMetadatum.metadatum.metadata_type_options.max !== undefined && this.itemMetadatum.metadatum.metadata_type_options.max !== '')
return Number(this.itemMetadatum.metadatum.metadata_type_options.max);
else
return undefined;
} }
}, },
methods: { methods: {
onInput(value) { onInput(value) {
const inputRef = this.$refs['tainacan-item-metadatum_id-' + this.itemMetadatum.metadatum.id + (this.itemMetadatum.parent_meta_id ? ('_parent_meta_id-' + this.itemMetadatum.parent_meta_id) : '')];
if ( inputRef && !inputRef.checkHtml5Validity())
return;
this.$emit('input', value); this.$emit('input', value);
}, },
onBlur() { onBlur() {
@ -45,3 +63,10 @@
} }
} }
</script> </script>
<style scoped>
.b-numberinput {
border-bottom-width: 0px !important;
margin-left: 0 !important;
}
</style>

View File

@ -34,6 +34,14 @@ class Numeric extends Metadata_Type {
'step' => [ 'step' => [
'title' => __( 'Step', 'tainacan' ), 'title' => __( 'Step', 'tainacan' ),
'description' => __( 'The amount to be increased or decreased when clicking on the metadatum control buttons. This also defines whether the input accepts decimal numbers.', 'tainacan' ), 'description' => __( 'The amount to be increased or decreased when clicking on the metadatum control buttons. This also defines whether the input accepts decimal numbers.', 'tainacan' ),
],
'min' => [
'title' => __( 'Minimum', 'tainacan' ),
'description' => __( 'The minimum value that the input will accept.', 'tainacan' ),
],
'max' => [
'title' => __( 'Maximum', 'tainacan' ),
'description' => __( 'The maximum value that the input will accept.', 'tainacan' ),
] ]
]; ];
} }

View File

@ -119,6 +119,21 @@
:message="$i18n.getHelperMessage('tainacan-relationship', 'accept_draft_items')"/> :message="$i18n.getHelperMessage('tainacan-relationship', 'accept_draft_items')"/>
</b-field> </b-field>
<b-field
:addons="false"
:label="$i18n.getHelperTitle('tainacan-relationship', 'accept_only_items_authored_by_current_user')">
&nbsp;
<b-switch
size="is-small"
v-model="modelAcceptOnlyItemsAuthoredByCurrentUser"
@input="emitValues()"
true-value="yes"
false-value="no" />
<help-button
:title="$i18n.getHelperTitle('tainacan-relationship', 'accept_only_items_authored_by_current_user')"
:message="$i18n.getHelperMessage('tainacan-relationship', 'accept_only_items_authored_by_current_user')"/>
</b-field>
</section> </section>
</template> </template>
@ -149,6 +164,7 @@
collectionMessage: '', collectionMessage: '',
displayRelatedItemMetadata: [], displayRelatedItemMetadata: [],
modelAcceptDraftItems: 'no', modelAcceptDraftItems: 'no',
modelAcceptOnlyItemsAuthoredByCurrentUser: 'no',
isMetaqueryRelationshipEnabled: tainacan_plugin && tainacan_plugin.tainacan_enable_relationship_metaquery == true ? tainacan_plugin.tainacan_enable_relationship_metaquery : false isMetaqueryRelationshipEnabled: tainacan_plugin && tainacan_plugin.tainacan_enable_relationship_metaquery == true ? tainacan_plugin.tainacan_enable_relationship_metaquery : false
} }
}, },
@ -173,6 +189,7 @@
this.modelSearch = ''; this.modelSearch = '';
this.modelDisplayInRelatedItems = 'no'; this.modelDisplayInRelatedItems = 'no';
this.modelAcceptDraftItems = 'no'; this.modelAcceptDraftItems = 'no';
this.modelAcceptOnlyItemsAuthoredByCurrentUser = 'no';
this.emitValues(); this.emitValues();
} }
}, },
@ -194,6 +211,7 @@
this.displayRelatedItemMetadata = this.value && this.value.display_related_item_metadata && Array.isArray(this.value.display_related_item_metadata) ? this.value.display_related_item_metadata : []; this.displayRelatedItemMetadata = this.value && this.value.display_related_item_metadata && Array.isArray(this.value.display_related_item_metadata) ? this.value.display_related_item_metadata : [];
this.modelDisplayInRelatedItems = this.value && this.value.display_in_related_items ? this.value.display_in_related_items : 'no'; this.modelDisplayInRelatedItems = this.value && this.value.display_in_related_items ? this.value.display_in_related_items : 'no';
this.modelAcceptDraftItems = this.value && this.value.accept_draft_items ? this.value.accept_draft_items : 'no'; this.modelAcceptDraftItems = this.value && this.value.accept_draft_items ? this.value.accept_draft_items : 'no';
this.modelAcceptOnlyItemsAuthoredByCurrentUser = this.value && this.value.accept_only_items_authored_by_current_user ? this.value.accept_only_items_authored_by_current_user : 'no';
}, },
methods: { methods: {
setErrorsAttributes( type, message ){ setErrorsAttributes( type, message ){
@ -284,7 +302,8 @@
search: this.modelSearch, search: this.modelSearch,
display_in_related_items: this.modelDisplayInRelatedItems, display_in_related_items: this.modelDisplayInRelatedItems,
display_related_item_metadata: this.displayRelatedItemMetadata, display_related_item_metadata: this.displayRelatedItemMetadata,
accept_draft_items: this.modelAcceptDraftItems accept_draft_items: this.modelAcceptDraftItems,
accept_only_items_authored_by_current_user: this.modelAcceptOnlyItemsAuthoredByCurrentUser
}); });
} }
} }

View File

@ -23,7 +23,7 @@
:placeholder="itemMetadatum.metadatum.placeholder ? itemMetadatum.metadatum.placeholder : $i18n.get('instruction_type_existing_item')" :placeholder="itemMetadatum.metadatum.placeholder ? itemMetadatum.metadatum.placeholder : $i18n.get('instruction_type_existing_item')"
:loading="isLoading" :loading="isLoading"
:aria-close-label="$i18n.get('remove_value')" :aria-close-label="$i18n.get('remove_value')"
:class="{'has-selected': selected != undefined && selected != []}" :class="{ 'has-selected': selected != undefined && selected != [] }"
field="label" field="label"
@typing="search" @typing="search"
check-infinite-scroll check-infinite-scroll
@ -54,7 +54,7 @@
<template <template
v-if="!isLoading" v-if="!isLoading"
#empty> #empty>
{{ $i18n.get('info_no_item_found') }} {{ isAcceptingOnlyItemsAuthoredByCurrentUser ? $i18n.get('info_no_item_authored_by_you_found') : $i18n.get('info_no_item_found') }}
</template> </template>
<template <template
v-if="currentUserCanEditItems && (!$adminOptions.itemEditionMode || $adminOptions.allowItemEditionModalInsideModal)" v-if="currentUserCanEditItems && (!$adminOptions.itemEditionMode || $adminOptions.allowItemEditionModalInsideModal)"
@ -212,6 +212,12 @@
this.itemMetadatum.metadatum && this.itemMetadatum.metadatum &&
this.itemMetadatum.metadatum.metadata_type_options && this.itemMetadatum.metadatum.metadata_type_options &&
this.itemMetadatum.metadatum.metadata_type_options.accept_draft_items === 'yes'; this.itemMetadatum.metadatum.metadata_type_options.accept_draft_items === 'yes';
},
isAcceptingOnlyItemsAuthoredByCurrentUser() {
return this.itemMetadatum &&
this.itemMetadatum.metadatum &&
this.itemMetadatum.metadatum.metadata_type_options &&
this.itemMetadatum.metadatum.metadata_type_options.accept_only_items_authored_by_current_user === 'yes';
} }
}, },
watch: { watch: {
@ -233,7 +239,8 @@
query['order'] = 'asc'; query['order'] = 'asc';
query['fetch_only'] = 'title,document_mimetype,thumbnail'; query['fetch_only'] = 'title,document_mimetype,thumbnail';
query['fetch_only_meta'] = this.isDisplayingRelatedItemMetadata ? (this.itemMetadatum.metadatum.metadata_type_options.display_related_item_metadata.filter(metadatumId => metadatumId !== 'thumbnail') + '') : (this.itemMetadatum.metadatum.metadata_type_options.search ? this.itemMetadatum.metadatum.metadata_type_options.search : ''); query['fetch_only_meta'] = this.isDisplayingRelatedItemMetadata ? (this.itemMetadatum.metadatum.metadata_type_options.display_related_item_metadata.filter(metadatumId => metadatumId !== 'thumbnail') + '') : (this.itemMetadatum.metadatum.metadata_type_options.search ? this.itemMetadatum.metadatum.metadata_type_options.search : '');
if (this.isAcceptingDraftItems)
if ( this.isAcceptingDraftItems )
query['status'] = ['publish','private','draft']; query['status'] = ['publish','private','draft'];
axios.get('/collection/' + this.collectionId + '/items?' + qs.stringify(query) ) axios.get('/collection/' + this.collectionId + '/items?' + qs.stringify(query) )
@ -400,6 +407,9 @@
if (this.isAcceptingDraftItems) if (this.isAcceptingDraftItems)
query['status'] = ['publish','private','draft']; query['status'] = ['publish','private','draft'];
if ( this.isAcceptingOnlyItemsAuthoredByCurrentUser )
query['authorid'] = tainacan_plugin.user_data.ID;
if (this.selected.length > 0) if (this.selected.length > 0)
query['exclude'] = this.selected.map((item) => item.value); query['exclude'] = this.selected.map((item) => item.value);

View File

@ -71,6 +71,10 @@ class Relationship extends Metadata_Type {
'accept_draft_items' => [ 'accept_draft_items' => [
'title' => __( 'List and accept draft items on the relation', 'tainacan' ), 'title' => __( 'List and accept draft items on the relation', 'tainacan' ),
'description' => __( 'Include draft items as possible options to the relationship metadata.', 'tainacan' ), 'description' => __( 'Include draft items as possible options to the relationship metadata.', 'tainacan' ),
],
'accept_only_items_authored_by_current_user' => [
'title' => __( 'Bind items only by current author', 'tainacan' ),
'description' => __( 'Accept stabelishing the replationship only with items authored by the current user editing the item.', 'tainacan' ),
] ]
]; ];
} }
@ -121,6 +125,7 @@ class Relationship extends Metadata_Type {
case 'display_in_related_items': case 'display_in_related_items':
case 'accept_draft_items': case 'accept_draft_items':
case 'accept_only_items_authored_by_current_user':
if ($option_value == 'yes') if ($option_value == 'yes')
$readable_option_value = __('Yes', 'tainacan'); $readable_option_value = __('Yes', 'tainacan');
else if ($option_value == 'no') else if ($option_value == 'no')
@ -177,13 +182,19 @@ class Relationship extends Metadata_Type {
// empty is ok // empty is ok
if ( !empty($this->get_option('display_in_related_items')) && !in_array($this->get_option('display_in_related_items'), ['yes', 'no']) ) { if ( !empty($this->get_option('display_in_related_items')) && !in_array($this->get_option('display_in_related_items'), ['yes', 'no']) ) {
return [ return [
'display_in_related_items' => __('Display in related items must be a option yes or no','tainacan') 'display_in_related_items' => __('Display in related items must be an option yes or no','tainacan')
]; ];
} }
// empty is ok // empty is ok
if ( !empty($this->get_option('accept_draft_items')) && !in_array($this->get_option('accept_draft_items'), ['yes', 'no']) ) { if ( !empty($this->get_option('accept_draft_items')) && !in_array($this->get_option('accept_draft_items'), ['yes', 'no']) ) {
return [ return [
'accept_draft_items' => __('Accept draft items must be a option yes or no','tainacan') 'accept_draft_items' => __('Accept draft items must be an option yes or no','tainacan')
];
}
// empty is ok
if ( !empty($this->get_option('accept_only_items_authored_by_current_user')) && !in_array($this->get_option('accept_only_items_authored_by_current_user'), ['yes', 'no']) ) {
return [
'accept_only_items_authored_by_current_user' => __('Bind items only by current author must be an option yes or no','tainacan')
]; ];
} }

View File

@ -37,7 +37,7 @@
'mobileSpecialFocus' 'mobileSpecialFocus'
], ],
computed: { computed: {
getOptions(){ getOptions() {
if (this.itemMetadatum && this.itemMetadatum.metadatum.metadata_type_options && this.itemMetadatum.metadatum.metadata_type_options.options ) { if (this.itemMetadatum && this.itemMetadatum.metadatum.metadata_type_options && this.itemMetadatum.metadatum.metadata_type_options.options ) {
const metadata = this.itemMetadatum.metadatum.metadata_type_options.options; const metadata = this.itemMetadatum.metadatum.metadata_type_options.options;
return ( metadata ) ? metadata.split("\n") : []; return ( metadata ) ? metadata.split("\n") : [];

View File

@ -20,6 +20,12 @@
class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/> class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/>
</span> </span>
<label class="label"> <label class="label">
<span
v-if="enumerateMetadatum"
style="opacity: 0.65;"
class="metadatum-section-enumeration">
{{ enumerateMetadatum }}.
</span>
{{ itemMetadatum.metadatum.name }} {{ itemMetadatum.metadatum.name }}
</label> </label>
<span <span
@ -152,7 +158,8 @@
:metadata-name-filter-string="metadataNameFilterString" :metadata-name-filter-string="metadataNameFilterString"
@mobileSpecialFocus="onMobileSpecialFocus" @mobileSpecialFocus="onMobileSpecialFocus"
:is-focused="isFocused" :is-focused="isFocused"
:is-metadata-navigation="isMetadataNavigation" /> :is-metadata-navigation="isMetadataNavigation"
:enumerate-metadatum="enumerateMetadatum" />
</div> </div>
</transition> </transition>
</b-field> </b-field>
@ -174,7 +181,8 @@
metadataNameFilterString: '', metadataNameFilterString: '',
isMobileScreen: false, isMobileScreen: false,
isFocused: false, isFocused: false,
isMetadataNavigation: false isMetadataNavigation: false,
enumerateMetadatum: [String, Boolean]
}, },
emits: [ emits: [
'input', 'input',

View File

@ -1,9 +1,8 @@
<template> <template>
<div> <div>
<taxonomy-tag-input <tainacan-taxonomy-tag-input
v-if="getComponent == 'tainacan-taxonomy-tag-input'" v-if="getComponent == 'tainacan-taxonomy-tag-input'"
:disabled="disabled" :disabled="disabled || isFetchingTerms"
:is="getComponent"
:maxtags="maxtags != undefined ? maxtags : (itemMetadatum.metadatum.multiple == 'yes' || allowNew === true ? (maxMultipleValues !== undefined ? maxMultipleValues : null) : '1')" :maxtags="maxtags != undefined ? maxtags : (itemMetadatum.metadatum.multiple == 'yes' || allowNew === true ? (maxMultipleValues !== undefined ? maxMultipleValues : null) : '1')"
v-model:value="valueComponent" v-model:value="valueComponent"
:allow-select-to-create="allowSelectToCreate" :allow-select-to-create="allowSelectToCreate"
@ -47,49 +46,55 @@
&nbsp;{{ $i18n.get('label_create_new_term') }} &nbsp;{{ $i18n.get('label_create_new_term') }}
</a> </a>
</div> </div>
<template v-if="allowNewFromOptions && itemMetadatum.item">
<!-- Term creation modal, used on admin for a complete term creation -->
<b-modal
:active.sync="isTermCreationModalOpen"
:width="768"
trap-focus
aria-role="dialog"
aria-modal
:can-cancel="['outside', 'escape']"
custom-class="tainacan-modal"
:close-button-aria-label="$i18n.get('close')">
<term-edition-form
:metadatum-id="itemMetadatum.metadatum.id"
:item-id="itemMetadatum.item.id"
:is-hierarchical="isHierarchical"
:taxonomy-id="taxonomyId"
:original-form="{ id: 'new', name: newTermName ? newTermName : '' }"
:is-term-insertion-flow="true"
@onEditionFinished="($event) => addRecentlyCreatedTerm($event.term)"
@onEditionCanceled="() => $console.log('Editing canceled')"
@onErrorFound="($event) => $console.log('Form with errors: ' + $event)" />
</b-modal>
<!-- Term creation modal, used on admin for a complete term creation --> <!-- Term creation panel, used on item submission block for a simpler term creation -->
<b-modal <transition name="filter-item">
v-model="isTermCreationModalOpen" <term-creation-panel
:width="768" :metadatum-id="itemMetadatum.metadatum.id"
trap-focus :item-id="itemMetadatum.item.id"
aria-role="dialog" :is-hierarchical="isHierarchical"
aria-modal v-if="isTermCreationPanelOpen"
:can-cancel="['outside', 'escape']" :taxonomy-id="taxonomyId"
custom-class="tainacan-modal" :original-form="{ id: 'new', name: newTermName ? newTermName : '' }"
:close-button-aria-label="$i18n.get('close')"> @onEditionFinished="($event) => addTermToBeCreated($event)"
<term-edition-form @onEditionCanceled="() => isTermCreationPanelOpen = false"
:is-hierarchical="isHierarchical" @onErrorFound="($event) => $console.log('Form with errors: ' + $event)" />
:taxonomy-id="taxonomyId" </transition>
:original-form="{ id: 'new', name: newTermName ? newTermName : '' }" </template>
:is-term-insertion-flow="true"
@onEditionFinished="($event) => addRecentlyCreatedTerm($event.term)"
@onEditionCanceled="() => $console.log('Editing canceled')"
@onErrorFound="($event) => $console.log('Form with errors: ' + $event)" />
</b-modal>
<!-- Term creation panel, used on item submission block for a simpler term creation -->
<transition name="filter-item">
<term-creation-panel
:is-hierarchical="isHierarchical"
v-if="isTermCreationPanelOpen"
:taxonomy-id="taxonomyId"
:original-form="{ id: 'new', name: newTermName ? newTermName : '' }"
@onEditionFinished="($event) => addTermToBeCreated($event)"
@onEditionCanceled="() => isTermCreationPanelOpen = false"
@onErrorFound="($event) => $console.log('Form with errors: ' + $event)" />
</transition>
</div> </div>
</template> </template>
<script> <script>
import TaxonomyTagInput from './TaxonomyTaginput.vue'; import TainacanTaxonomyTagInput from './TaxonomyTaginput.vue';
import CheckboxRadioMetadataInput from '../../other/checkbox-radio-metadata-input.vue'; import CheckboxRadioMetadataInput from '../../other/checkbox-radio-metadata-input.vue';
import { tainacan as axios } from '../../../js/axios.js'; import { tainacan as axios } from '../../../js/axios.js';
import { mapActions } from 'vuex';
export default { export default {
components: { components: {
TaxonomyTagInput, TainacanTaxonomyTagInput,
CheckboxRadioMetadataInput CheckboxRadioMetadataInput
}, },
props: { props: {
@ -99,7 +104,6 @@
forcedComponentType: '', forcedComponentType: '',
maxtags: '', maxtags: '',
allowNew: false, allowNew: false,
allowSelectToCreate: false,
isMobileScreen: false, isMobileScreen: false,
}, },
emits: [ emits: [
@ -117,7 +121,8 @@
isTermCreationModalOpen: false, isTermCreationModalOpen: false,
isTermCreationPanelOpen: false, isTermCreationPanelOpen: false,
newTermName: '', newTermName: '',
allowNewFromOptions: false allowNewFromOptions: false,
isFetchingTerms: false
} }
}, },
computed: { computed: {
@ -169,21 +174,55 @@
this.taxonomyId = metadata_type_options.taxonomy_id; this.taxonomyId = metadata_type_options.taxonomy_id;
this.taxonomy = metadata_type_options.taxonomy; this.taxonomy = metadata_type_options.taxonomy;
this.allowNewFromOptions = this.allowNew === false ? false : metadata_type_options.allow_new_terms == 'yes'; this.allowNewFromOptions = this.allowNew === false ? false : metadata_type_options.allow_new_terms == 'yes' && (!this.$userCaps || this.$userCaps.hasCapability('tnc_rep_edit_taxonomies'));
this.getTermsId(); this.getTermsId();
}, },
methods: { methods: {
...mapActions('taxonomy', [
'fetchTerms'
]),
getTermsId() { getTermsId() {
let values = []; let values = [];
if (this.value && this.itemMetadatum.metadatum && this.getComponent != 'tainacan-taxonomy-tag-input') {
if ( this.value && this.itemMetadatum.metadatum && this.getComponent != 'tainacan-taxonomy-tag-input' ) {
values = this.value.map(term => term.id).filter(term => term !== undefined); values = this.value.map(term => term.id).filter(term => term !== undefined);
this.valueComponent = (values.length > 0 && this.itemMetadatum.metadatum && this.itemMetadatum.metadatum.multiple === 'no') ? values[0] : values; this.valueComponent = (values.length > 0 && this.itemMetadatum.metadatum && this.itemMetadatum.metadatum.multiple === 'no') ? values[0] : values;
} else if (this.value && this.itemMetadatum.metadatum && this.getComponent == 'tainacan-taxonomy-tag-input') { } else if (this.value && this.itemMetadatum.metadatum && this.getComponent == 'tainacan-taxonomy-tag-input') {
values = this.value.map((term) => { return { label: term.name, value: term.id } });
this.valueComponent = values; // This first scenario happens in the item edition form, as the item metadata returns the terms as objects
const valuesInArray = Array.isArray(this.value) ? this.value : [this.value];
if ( valuesInArray[0] && valuesInArray[0] && valuesInArray[0].id ) {
values = valuesInArray.map((term) => { return { label: term.name, value: term.id } });
this.valueComponent = values;
// If the term is not returned as object, we're in bulk edition modal or in the metadata section condition metadata input, where value is a an array of IDs
} else if ( valuesInArray.length > 0 ) {
this.isFetchingTerms = true;
this.fetchTerms({
taxonomyId: this.taxonomyId,
fetchOnly: {
fetch_only: {
0: 'name',
1: 'id'
}
},
all: true,
include: valuesInArray
}).then((res) => {
values = res.terms.map((term) => { return { label: term.name, value: term.id } });
this.valueComponent = values;
this.isFetchingTerms = false;
}).catch((error) => {
this.isFetchingTerms = false;
throw error;
});
} else {
this.valueComponent = [];
}
} }
}, },
addRecentlyCreatedTerm(term) { addRecentlyCreatedTerm(term) {
@ -224,7 +263,7 @@
}, },
openTermCreationModal(newTerm) { openTermCreationModal(newTerm) {
this.newTermName = newTerm.name; this.newTermName = newTerm.name;
if (this.isOnItemSubmissionForm) if (this.isOnItemSubmissionForm)
this.isTermCreationPanelOpen = true; this.isTermCreationPanelOpen = true;
else else

View File

@ -5,12 +5,11 @@
:id="'tainacan-item-metadatum_id-' + itemMetadatum.metadatum.id + (itemMetadatum.parent_meta_id ? ('_parent_meta_id-' + itemMetadatum.parent_meta_id) : '')" :id="'tainacan-item-metadatum_id-' + itemMetadatum.metadatum.id + (itemMetadatum.parent_meta_id ? ('_parent_meta_id-' + itemMetadatum.parent_meta_id) : '')"
size="is-small" size="is-small"
icon="magnify" icon="magnify"
:allow-new="false"
@add="emitAdd" @add="emitAdd"
@remove="emitRemove" @remove="emitRemove"
v-model="selected" v-model="selected"
:data="labels" :data="options"
:maxtags="maxtags" :maxtags="maxtags != undefined ? maxtags : (itemMetadatum.metadatum.multiple == 'yes' || allowNew === true ? (maxMultipleValues !== undefined ? maxMultipleValues : null) : '1')"
field="label" field="label"
:remove-on-keys="[]" :remove-on-keys="[]"
:dropdown-position="isLastMetadatum ? 'top' :'auto'" :dropdown-position="isLastMetadatum ? 'top' :'auto'"
@ -21,10 +20,12 @@
:loading="isFetching" :loading="isFetching"
:class="{ 'has-selected': selected != undefined && selected != [] }" :class="{ 'has-selected': selected != undefined && selected != [] }"
autocomplete autocomplete
@typing="loadTerms" @typing="search"
check-infinite-scroll check-infinite-scroll
@infinite-scroll="loadMoreTerms" @infinite-scroll="searchMore"
:has-counter="false"> :has-counter="false"
:append-to-body="!itemMetadatum.item"
:open-on-focus="false">
<template #default="props"> <template #default="props">
<div class="media"> <div class="media">
<div class="media-content"> <div class="media-content">
@ -33,12 +34,12 @@
</div> </div>
</template> </template>
<template <template
v-if="!isFetching" v-if="!isFetching && options.length <= 0 && searchName.length > 0"
#empty> #empty>
{{ $i18n.get('info_no_terms_found') }} {{ $i18n.get('info_no_terms_found') }}
</template> </template>
<template <template
v-if="allowNew" v-if="allowNew && !isFetching && searchName.length > 0"
#footer> #footer>
<a @click="$emit('showAddNewTerm', { name: searchName })"> <a @click="$emit('showAddNewTerm', { name: searchName })">
{{ $i18n.get('label_create_new_term') + ' "' + searchName + '"' }} {{ $i18n.get('label_create_new_term') + ' "' + searchName + '"' }}
@ -57,7 +58,6 @@
allowNew: Boolean, allowNew: Boolean,
taxonomyId: Number, taxonomyId: Number,
disabled: false, disabled: false,
allowSelectToCreate: false,
maxtags: '', maxtags: '',
isLastMetadatum: false isLastMetadatum: false
}, },
@ -68,51 +68,58 @@
data() { data() {
return { return {
selected: [], selected: [],
labels: [], options: [],
isFetching: false, isFetching: false,
offset: 0, offset: 0,
searchName: '', searchName: '',
totalTerms: 0 totalTerms: 0
} }
}, },
computed: {
maxMultipleValues() {
return (
this.itemMetadatum &&
this.itemMetadatum.metadatum &&
this.itemMetadatum.metadatum.cardinality &&
!isNaN(this.itemMetadatum.metadatum.cardinality) &&
this.itemMetadatum.metadatum.cardinality > 1
) ? this.itemMetadatum.metadatum.cardinality : undefined;
},
},
watch: { watch: {
selected: { value() {
handler() { if ( this.value && this.value.length > 0 && this.value[0].label )
if (this.allowSelectToCreate && this.selected[0]) { this.selected = JSON.parse(JSON.stringify(this.value));
this.selected[0].label.includes(`(${this.$i18n.get('select_to_create')})`);
this.selected[0].label = this.selected[0].label.split('(')[0];
}
},
deep: true
} }
}, },
created() { mounted() {
if (this.value && this.value.length > 0) if ( this.value && this.value.length > 0 && this.value[0].label )
this.selected = this.value; this.selected = JSON.parse(JSON.stringify(this.value));
}, },
methods: { methods: {
...mapActions('taxonomy', [ ...mapActions('taxonomy', [
'fetchTerms' 'fetchTerms'
]), ]),
loadTerms: _.debounce( function(value) { search: _.debounce( function(value) {
// String update // String update
if (value != this.searchName) { if ( value != this.searchName ) {
this.searchName = value; this.searchName = value;
this.labels = []; this.options = [];
this.offset = 0; this.offset = 0;
} }
// String cleared // String cleared
if (!value.length) { if ( !value.length ) {
this.searchName = value; this.searchName = value;
this.labels = []; this.options = [];
this.offset = 0; this.offset = 0;
return;
} }
// No need to load more // No need to load more
if (this.offset > 0 && this.labels.length >= this.totalTerms) if ( this.offset > 0 && this.options.length >= this.totalTerms )
return return;
this.isFetching = true; this.isFetching = true;
@ -135,10 +142,7 @@
}).then((res) => { }).then((res) => {
for (let term of res.terms) for (let term of res.terms)
this.labels.push({ label: term.name, value: term.id }); this.options.push({ label: term.name, value: term.id });
if (res.terms.length <= 0 && this.allowSelectToCreate)
this.labels.push({ label: `${value} (${this.$i18n.get('select_to_create')})`, value: value })
this.offset += 12; this.offset += 12;
this.totalTerms = res.total; this.totalTerms = res.total;
@ -149,8 +153,8 @@
throw error; throw error;
}); });
}, 500), }, 500),
loadMoreTerms: _.debounce(function () { searchMore: _.debounce(function () {
this.loadTerms(this.searchName) this.search(this.searchName)
}, 250), }, 250),
updateSelectedValues(){ updateSelectedValues(){
let selected = []; let selected = [];
@ -163,7 +167,7 @@
emitAdd(){ emitAdd(){
let val = this.selected; let val = this.selected;
let results = []; let results = [];
if (val.length > 0) { if (val.length > 0) {
for (let term of val) for (let term of val)
results.push( term.value ); results.push( term.value );

View File

@ -14,6 +14,19 @@
:title="$i18n.getHelperTitle('tainacan-text', 'display_suggestions')" :title="$i18n.getHelperTitle('tainacan-text', 'display_suggestions')"
:message="$i18n.getHelperMessage('tainacan-text', 'display_suggestions')"/> :message="$i18n.getHelperMessage('tainacan-text', 'display_suggestions')"/>
</b-field> </b-field>
<b-field :addons="false">
<label class="label is-inline">
{{ $i18n.getHelperTitle('tainacan-text', 'mask') }}
<help-button
:title="$i18n.getHelperTitle('tainacan-text', 'mask')"
:message="$i18n.getHelperMessage('tainacan-text', 'mask')" />
</label>
<b-input
:value="displaySuggestions === 'yes' ? '' : mask"
:disabled="displaySuggestions === 'yes'"
name="mask"
@input="onUpdateMask" />
</b-field>
</section> </section>
</template> </template>
@ -25,16 +38,22 @@
emits: ['input'], emits: ['input'],
data() { data() {
return { return {
displaySuggestions: String displaySuggestions: String,
mask: String
} }
}, },
created() { created() {
this.displaySuggestions = this.value && this.value.display_suggestions ? this.value.display_suggestions : 'no'; this.displaySuggestions = this.value && this.value.display_suggestions ? this.value.display_suggestions : 'no';
this.mask = this.value && this.value.mask ? this.value.mask : '';
}, },
methods: { methods: {
onUpdateDisplaySuggestions(value) { onUpdateDisplaySuggestions(value) {
this.displaySuggestions = value; this.displaySuggestions = value;
this.$emit('input', { display_suggestions: value }); this.$emit('input', { display_suggestions: value, mask: value == 'yes' ? '' : this.mask });
},
onUpdateMask(value) {
this.mask = value;
this.$emit('input', { display_suggestions: this.displaySuggestions, mask: value });
} }
} }
} }

View File

@ -1,14 +1,20 @@
<template> <template>
<div> <div>
<b-input <div
v-if="!getDisplayAutocomplete" v-if="!getDisplayAutocomplete"
:disabled="disabled" class="control is-clearfix">
:id="'tainacan-item-metadatum_id-' + itemMetadatum.metadatum.id + (itemMetadatum.parent_meta_id ? ('_parent_meta_id-' + itemMetadatum.parent_meta_id) : '')" <input
:model-value="value" class="input"
:placeholder="itemMetadatum.metadatum.placeholder ? itemMetadatum.metadatum.placeholder : ''" :disabled="disabled"
@update:model-value="onInput($event)" :id="'tainacan-item-metadatum_id-' + itemMetadatum.metadatum.id + (itemMetadatum.parent_meta_id ? ('_parent_meta_id-' + itemMetadatum.parent_meta_id) : '')"
@blur="onBlur" :model-value="value"
@focus="onMobileSpecialFocus" /> :placeholder="itemMetadatum.metadatum.placeholder ? itemMetadatum.metadatum.placeholder : ''"
@focus="onMobileSpecialFocus"
v-imask="getMask"
@complete="($event) => getMask ? onInput($event.detail.value) : null"
@input="($event) => getMask ? null : onInput($event.target.value)"
@blur="onBlur" >
</div>
<b-autocomplete <b-autocomplete
v-else v-else
:disabled="disabled" :disabled="disabled"
@ -44,8 +50,12 @@
<script> <script>
import { isCancel } from '../../../js/axios'; import { isCancel } from '../../../js/axios';
import { dynamicFilterTypeMixin } from '../../../js/filter-types-mixin'; import { dynamicFilterTypeMixin } from '../../../js/filter-types-mixin';
import { IMaskDirective } from 'vue-imask';
export default { export default {
directives: {
imask: IMaskDirective
},
mixins: [dynamicFilterTypeMixin], mixins: [dynamicFilterTypeMixin],
props: { props: {
itemMetadatum: Object, itemMetadatum: Object,
@ -77,6 +87,15 @@
return this.itemMetadatum.metadatum.metadata_type_options.display_suggestions == 'yes'; return this.itemMetadatum.metadatum.metadata_type_options.display_suggestions == 'yes';
else else
return false; return false;
},
getMask() {
if (this.itemMetadatum && this.itemMetadatum.metadatum.metadata_type_options && this.itemMetadatum.metadatum.metadata_type_options.mask)
return {
mask: this.itemMetadatum.metadatum.metadata_type_options.mask,
lazy: false
};
else
return false;
} }
}, },
created() { created() {

View File

@ -35,6 +35,13 @@ class Text extends Metadata_Type {
'display_suggestions' => [ 'display_suggestions' => [
'title' => __( 'Display suggestions', 'tainacan' ), 'title' => __( 'Display suggestions', 'tainacan' ),
'description' => __( 'Show an autocomplete input suggesting values inserted previously on other items for this metadatum.', 'tainacan' ), 'description' => __( 'Show an autocomplete input suggesting values inserted previously on other items for this metadatum.', 'tainacan' ),
],
'mask' => [
'title' => __( 'Mask input', 'tainacan' ),
'description' => sprintf(
__( 'Define a pattern of fixed characters that will be used to mask the input. Learn how to build mask patterns <a target="_blank" href="%1$s">here</a>.', 'tainacan' ),
'https://imask.js.org/guide.html#masked-pattern'
)
] ]
]; ];
} }

View File

@ -0,0 +1,50 @@
<template>
<section>
<b-field :addons="false">
<label class="label is-inline">
{{ $i18n.getHelperTitle('tainacan-textarea', 'maxlength') }}
<help-button
:title="$i18n.getHelperTitle('tainacan-textarea', 'maxlength')"
:message="$i18n.getHelperMessage('tainacan-textarea', 'maxlength')" />
</label>
<b-numberinput
v-model="maxlength"
name="maxlength"
step="1"
min="0"
@input="onUpdateMaxlength"/>
</b-field>
</section>
</template>
<script>
export default {
props: {
value: [ String, Object, Array ]
},
data() {
return {
maxlength: [Number, null]
}
},
created() {
this.maxlength = this.value && this.value.maxlength ? Number(this.value.maxlength) : null;
},
methods: {
onUpdateMaxlength(value) {
if (value == 0) value = null;
this.$emit('input', { maxlength: value });
}
}
}
</script>
<style scoped>
section{
margin-bottom: 10px;
}
.tainacan-help-tooltip-trigger {
font-size: 1em;
}
</style>

View File

@ -1,13 +1,15 @@
<template> <template>
<b-input <b-input
:disabled="disabled" :disabled="disabled"
:ref="'tainacan-item-metadatum_id-' + itemMetadatum.metadatum.id + (itemMetadatum.parent_meta_id ? ('_parent_meta_id-' + itemMetadatum.parent_meta_id) : '')"
:id="'tainacan-item-metadatum_id-' + itemMetadatum.metadatum.id + (itemMetadatum.parent_meta_id ? ('_parent_meta_id-' + itemMetadatum.parent_meta_id) : '')" :id="'tainacan-item-metadatum_id-' + itemMetadatum.metadatum.id + (itemMetadatum.parent_meta_id ? ('_parent_meta_id-' + itemMetadatum.parent_meta_id) : '')"
:placeholder="itemMetadatum.metadatum.placeholder ? itemMetadatum.metadatum.placeholder : ''" :placeholder="itemMetadatum.metadatum.placeholder ? itemMetadatum.metadatum.placeholder : ''"
:model-value="value" :model-value="value"
@update:model-value="onInput($event)" @update:model-value="onInput($event)"
@blur="onBlur" @blur="onBlur"
type="textarea" type="textarea"
@focus="onMobileSpecialFocus" /> @focus="onMobileSpecialFocus"
:maxlength="getMaxlength" />
</template> </template>
<script> <script>
@ -22,8 +24,20 @@
'blur', 'blur',
'mobileSpecialFocus' 'mobileSpecialFocus'
], ],
computed: {
getMaxlength() {
if ( this.itemMetadatum && this.itemMetadatum.metadatum.metadata_type_options && this.itemMetadatum.metadatum.metadata_type_options.maxlength !== null && this.itemMetadatum.metadatum.metadata_type_options.maxlength !== undefined && this.itemMetadatum.metadatum.metadata_type_options.maxlength !== '' )
return Number(this.itemMetadatum.metadatum.metadata_type_options.maxlength);
else
return undefined;
}
},
methods: { methods: {
onInput(value) { onInput(value) {
const inputRef = this.$refs['tainacan-item-metadatum_id-' + this.itemMetadatum.metadatum.id + (this.itemMetadatum.parent_meta_id ? ('_parent_meta_id-' + this.itemMetadatum.parent_meta_id) : '')];
if ( inputRef && this.getMaxlength && !inputRef.checkHtml5Validity() )
return;
this.$emit('input', value); this.$emit('input', value);
}, },
onBlur() { onBlur() {

View File

@ -15,6 +15,7 @@ class Textarea extends Metadata_Type {
parent::__construct(); parent::__construct();
$this->set_primitive_type('long_string'); $this->set_primitive_type('long_string');
$this->set_component('tainacan-textarea'); $this->set_component('tainacan-textarea');
$this->set_form_component('tainacan-form-textarea');
$this->set_name( __('Textarea', 'tainacan') ); $this->set_name( __('Textarea', 'tainacan') );
$this->set_description( __('A textarea with multiple lines', 'tainacan') ); $this->set_description( __('A textarea with multiple lines', 'tainacan') );
$this->set_preview_template(' $this->set_preview_template('
@ -26,6 +27,18 @@ class Textarea extends Metadata_Type {
'); ');
} }
/**
* @inheritdoc
*/
public function get_form_labels(){
return [
'maxlength' => [
'title' => __( 'Maximum of characters', 'tainacan' ),
'description' => __( 'Limits the character input to a maximum value an displays a counter.', 'tainacan' ),
]
];
}
public function get_multivalue_prefix() { public function get_multivalue_prefix() {
return '<p>'; return '<p>';

View File

@ -95,7 +95,6 @@
:forced-component-type="bulkEditionProcedures[criterion].metadatum.metadata_type_object.component.includes('taxonomy') ? 'tainacan-taxonomy-tag-input' : ''" :forced-component-type="bulkEditionProcedures[criterion].metadatum.metadata_type_object.component.includes('taxonomy') ? 'tainacan-taxonomy-tag-input' : ''"
:item-metadatum="{ metadatum: bulkEditionProcedures[criterion].metadatum }" :item-metadatum="{ metadatum: bulkEditionProcedures[criterion].metadatum }"
:allow-new="false" :allow-new="false"
:allow-select-to-create="false"
:maxtags="1" :maxtags="1"
:class="{'is-field-history': bulkEditionProcedures[criterion].isDone}" :class="{'is-field-history': bulkEditionProcedures[criterion].isDone}"
:disabled="bulkEditionProcedures[criterion].isDone" :disabled="bulkEditionProcedures[criterion].isDone"
@ -114,7 +113,6 @@
:forced-component-type="bulkEditionProcedures[criterion].metadatum.metadata_type_object.component.includes('taxonomy') ? 'tainacan-taxonomy-tag-input' : ''" :forced-component-type="bulkEditionProcedures[criterion].metadatum.metadata_type_object.component.includes('taxonomy') ? 'tainacan-taxonomy-tag-input' : ''"
:item-metadatum="{ metadatum: bulkEditionProcedures[criterion].metadatum }" :item-metadatum="{ metadatum: bulkEditionProcedures[criterion].metadatum }"
:allow-new="false" :allow-new="false"
:allow-select-to-create="bulkEditionProcedures[criterion].metadatum.metadata_type_options.allow_new_terms === 'yes'"
:maxtags="1" :maxtags="1"
:class="{'is-field-history': bulkEditionProcedures[criterion].isDone}" :class="{'is-field-history': bulkEditionProcedures[criterion].isDone}"
class="tainacan-bulk-edition-field tainacan-bulk-edition-field-not-last" class="tainacan-bulk-edition-field tainacan-bulk-edition-field-not-last"
@ -200,7 +198,6 @@
:forced-component-type="bulkEditionProcedures[criterion].metadatum.metadata_type_object.component.includes('taxonomy') ? 'tainacan-taxonomy-tag-input' : ''" :forced-component-type="bulkEditionProcedures[criterion].metadatum.metadata_type_object.component.includes('taxonomy') ? 'tainacan-taxonomy-tag-input' : ''"
:item-metadatum="{ metadatum: bulkEditionProcedures[criterion].metadatum }" :item-metadatum="{ metadatum: bulkEditionProcedures[criterion].metadatum }"
:allow-new="false" :allow-new="false"
:allow-select-to-create="bulkEditionProcedures[criterion].metadatum.metadata_type_options.allow_new_terms === 'yes'"
:maxtags="1" :maxtags="1"
:class="{ 'is-field-history': bulkEditionProcedures[criterion].isDone }" :class="{ 'is-field-history': bulkEditionProcedures[criterion].isDone }"
class="tainacan-bulk-edition-field tainacan-bulk-edition-field-last" class="tainacan-bulk-edition-field tainacan-bulk-edition-field-last"
@ -216,7 +213,7 @@
:style="{ :style="{
marginRight: !bulkEditionProcedures[criterion].isDone && !bulkEditionProcedures[criterion].isExecuting ? '-7.4px': 0 marginRight: !bulkEditionProcedures[criterion].isDone && !bulkEditionProcedures[criterion].isExecuting ? '-7.4px': 0
}" }"
class="field buttons-r-bulk"> class="field bulk-last-field">
<button <button
v-if="!bulkEditionProcedures[criterion].isDone && !bulkEditionProcedures[criterion].isExecuting" v-if="!bulkEditionProcedures[criterion].isDone && !bulkEditionProcedures[criterion].isExecuting"
@ -646,7 +643,7 @@
padding-left: 0 !important; padding-left: 0 !important;
} }
.buttons-r-bulk { .bulk-last-field {
margin-left: 0 !important; margin-left: 0 !important;
justify-content: center !important; justify-content: center !important;
} }
@ -789,9 +786,28 @@
&:not(:first-child) { &:not(:first-child) {
padding-left: 13px; padding-left: 13px;
} }
:deep(.is-special-hidden-for-mobile) {
&,
&:focus,
&:focus-visible {
opacity: 0;
width: 0;
height: 0 !important;
min-height: 0;
min-width: 0;
padding: 0 !important;
line-height: 0px !important;
border: none !important;
border-color: transparent !important;
border-width: 0px !important;
font-size: 0px !important;
display: block !important;
}
}
} }
.buttons-r-bulk { .bulk-last-field {
display: flex; display: flex;
align-items: center; align-items: center;
height: 32px; height: 32px;

View File

@ -508,7 +508,7 @@ export default {
p { p {
font-size: 1em; font-size: 1em;
color: var(--tainacan-gray5); color: var(--tainacan-label-color);
padding: 0em 1.25em; padding: 0em 1.25em;
margin-top: 0.75em; margin-top: 0.75em;
margin-bottom: 0; margin-bottom: 0;
@ -542,13 +542,13 @@ export default {
} }
p { p {
font-size: 0.75em; font-size: 0.75em;
color: var(--tainacan-gray5); color: var(--tainacan-label-color);
padding: 0em 0.5em; padding: 0em 0.5em;
margin-bottom: 0; margin-bottom: 0;
} }
&:hover { &:hover {
border: 1px solid var(--tainacan-gray3); border: 1px solid var(--tainacan-item-hover-background-color);
} }
} }
} }
@ -566,7 +566,7 @@ export default {
} }
.collapse-handler:hover { .collapse-handler:hover {
cursor: pointer; cursor: pointer;
background-color: var(--tainacan-gray1); background-color: var(--tainacan-item-hover-background-color);
} }
.collapse-handle { .collapse-handle {
cursor: pointer; cursor: pointer;
@ -626,9 +626,9 @@ export default {
} }
} }
&:hover { &:hover {
background-color: var(--tainacan-gray1); background-color: var(--tainacan-item-hover-background-color);
.exposer-item-actions { .exposer-item-actions {
background-color: var(--tainacan-gray2); background-color: var(--tainacan-item-hover-background-color);
} }
} }
.exposer-item-actions { .exposer-item-actions {
@ -646,7 +646,7 @@ export default {
animation-name: appear-from-top-tooltip; animation-name: appear-from-top-tooltip;
animation-duration: 0.3s; animation-duration: 0.3s;
position: absolute; position: absolute;
background: var(--tainacan-gray1); background: var(--tainacan-item-hover-background-color);
padding: 0.5em 0.875em 0.75em 0.875em; padding: 0.5em 0.875em 0.75em 0.875em;
border-radius: 4px; border-radius: 4px;
top: 44px; top: 44px;
@ -660,8 +660,8 @@ export default {
} }
p { padding: 0 0 0.5em 0; } p { padding: 0 0 0.5em 0; }
input { input {
background-color: var(--tainacan-white); background-color: var(--tainacan-input-background-color);
border: 1px solid var(--tainacan-gray2); border: 1px solid var(--tainacan-input-border-color);
border-radius: 0; border-radius: 0;
padding: 2px 8px; padding: 2px 8px;
} }
@ -673,7 +673,7 @@ export default {
width: 0; width: 0;
height: 0; height: 0;
border-style: solid; border-style: solid;
border-color: transparent transparent var(--tainacan-gray1) transparent; border-color: transparent transparent var(--tainacan-item-hover-background-color) transparent;
border-right-width: 14px; border-right-width: 14px;
border-bottom-width: 16px; border-bottom-width: 16px;
border-left-width: 14px; border-left-width: 14px;

View File

@ -147,7 +147,7 @@ export default {
max-height: 100vh; max-height: 100vh;
overflow: auto; overflow: auto;
z-index: 9; z-index: 9;
max-width: 10em; max-width: 11em;
-webkit-transition: max-width 0.2s linear; /* Safari */ -webkit-transition: max-width 0.2s linear; /* Safari */
transition: max-width 0.2s linear; transition: max-width 0.2s linear;

View File

@ -258,7 +258,7 @@ export default {
} }
} }
a { a {
color: var(--tainacan-white) !important;; color: var(--tainacan-white) !important;
text-align: center; text-align: center;
white-space: nowrap; white-space: nowrap;
padding: 6px 11px; padding: 6px 11px;

View File

@ -190,7 +190,7 @@
} }
.logo-area { .logo-area {
height: $header-height; height: $header-height;
min-width: 10em; min-width: 11em;
cursor: pointer; cursor: pointer;
h1 { h1 {

View File

@ -78,7 +78,7 @@
class="button" class="button"
id="view-collection-button"> id="view-collection-button">
<span class="icon"> <span class="icon">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-see"/> <i class="tainacan-icon tainacan-icon-1-125em tainacan-icon-openurl"/>
</span> </span>
<span class="is-hidden-mobile">{{ $i18n.get('label_view_collection_on_website') }}</span> <span class="is-hidden-mobile">{{ $i18n.get('label_view_collection_on_website') }}</span>
</a> </a>
@ -91,7 +91,7 @@
class="button" class="button"
id="view-repository-button--taxonomies"> id="view-repository-button--taxonomies">
<span class="icon"> <span class="icon">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-see"/> <i class="tainacan-icon tainacan-icon-1-125em tainacan-icon-openurl"/>
</span> </span>
<span class="is-hidden-mobile">{{ $i18n.get('label_view_taxonomies_on_website') }}</span> <span class="is-hidden-mobile">{{ $i18n.get('label_view_taxonomies_on_website') }}</span>
</a> </a>
@ -104,7 +104,7 @@
class="button" class="button"
id="view-repository-button"> id="view-repository-button">
<span class="icon"> <span class="icon">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-see"/> <i class="tainacan-icon tainacan-icon-1-125em tainacan-icon-openurl"/>
</span> </span>
<span class="is-hidden-mobile">{{ $i18n.get('label_view_collections_on_website') }}</span> <span class="is-hidden-mobile">{{ $i18n.get('label_view_collections_on_website') }}</span>
</a> </a>
@ -174,7 +174,7 @@ export default {
padding-top: 10px; padding-top: 10px;
padding-bottom: 10px; padding-bottom: 10px;
padding-right: 0; padding-right: 0;
padding-left: calc((var(--tainacan-one-column) - 6.666666667px) + 10em); padding-left: calc((var(--tainacan-one-column) - 6.666666667px) + 11em);
margin: 0px; margin: 0px;
display: flex; display: flex;
vertical-align: middle; vertical-align: middle;

View File

@ -188,7 +188,9 @@
:id="`${key}.${index}-tainacan-li-checkbox-model`" :id="`${key}.${index}-tainacan-li-checkbox-model`"
:ref="`${key}.${index}-tainacan-li-checkbox-model`" :ref="`${key}.${index}-tainacan-li-checkbox-model`"
:key="index"> :key="index">
<label class="b-checkbox checkbox"> <label
@click="option.total_children > 0 && (!finderColumns[key + 1] || finderColumns[key + 1].label !== option.label) ? getOptionChildren(option, key, index) : null"
class="b-checkbox checkbox">
<input <input
@input="$emit('input', $event.target.value)" @input="$emit('input', $event.target.value)"
:value="(isNaN(Number(option.value)) ? option.value : Number(option.value))" :value="(isNaN(Number(option.value)) ? option.value : Number(option.value))"
@ -834,8 +836,8 @@
this.$emit('appliedCheckBoxModal'); this.$emit('appliedCheckBoxModal');
}, },
renderHierarchicalPath(hierachyPath, label) { renderHierarchicalPath(hierarchyPath, label) {
return '<span style="color: var(--tainacan-info-color);">' + hierachyPath.replace(/>/g, '&nbsp;<span class="hierarchy-separator"> &gt; </span>&nbsp;') + '</span>' + label; return '<span style="color: var(--tainacan-info-color);">' + hierarchyPath.replace(/>/g, '&nbsp;<span class="hierarchy-separator"> &gt; </span>&nbsp;') + '</span>' + label;
} }
} }
} }
@ -893,12 +895,12 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
cursor: pointer; cursor: pointer;
border: 1px solid var(--tainacan-gray1); border: 1px solid var(--tainacan-input-border-color);
margin-top: 10px; margin-top: 10px;
margin-bottom: 0.1em; margin-bottom: 0.1em;
&:hover { &:hover {
background-color: var(--tainacan-blue1); background-color: var(--tainacan-item-hover-background-color);
} }
} }
@ -927,7 +929,7 @@
} }
&:hover { &:hover {
background-color: var(--tainacan-gray1); background-color: var(--tainacan-input-border-color);
} }
} }
@ -949,7 +951,7 @@
} }
&:hover { &:hover {
background-color: var(--tainacan-gray1); background-color: var(--tainacan-item-hover-background-color);
} }
&.result-info { &.result-info {
padding: 0.5rem 0.25rem 0.25rem 0.25rem; padding: 0.5rem 0.25rem 0.25rem 0.25rem;
@ -963,8 +965,12 @@
} }
.tainacan-finder-columns-container { .tainacan-finder-columns-container {
background-color: var(--tainacan-white); background-color: var(--tainacan-background-color);
border: 1px solid var(--tainacan-gray1); border: 1px solid var(--tainacan-input-border-color);
border-bottom-left-radius: var(--tainacan-dropdownmenu-border-radius);
border-bottom-right-radius: var(--tainacan-dropdownmenu-border-radius);
border-top-right-radius: 0px;
border-top-left-radius: 0px;
border-top: 0px; border-top: 0px;
margin-top: -1px; margin-top: -1px;
height: auto; height: auto;
@ -980,7 +986,7 @@
} }
.tainacan-finder-column { .tainacan-finder-column {
border-right: solid 1px var(--tainacan-gray1); border-right: solid 1px var(--tainacan-input-border-color);
flex-basis: auto; flex-basis: auto;
flex-grow: 1; flex-grow: 1;
max-width: 600px; max-width: 600px;
@ -1041,7 +1047,7 @@
padding: 0.45em 0.75em; padding: 0.45em 0.75em;
margin: 0; margin: 0;
position: relative; position: relative;
border-bottom: 1px solid var(--tainacan-gray1); border-bottom: 1px solid var(--tainacan-input-border-color);
} }
&:not(:first-child) .column-label { &:not(:first-child) .column-label {
@ -1067,7 +1073,7 @@
} }
&::before { &::before {
top: 0px; top: 0px;
border-color: transparent transparent transparent var(--tainacan-gray1); border-color: transparent transparent transparent var(--tainacan-input-border-color);
border-left-width: 12px; border-left-width: 12px;
border-top-width: calc(1.2em + 1px); border-top-width: calc(1.2em + 1px);
border-bottom-width: calc(1.2em + 0px); border-bottom-width: calc(1.2em + 0px);
@ -1129,6 +1135,13 @@
} }
} }
.tainacan-finder-columns-container,
.tainacan-checkbox-list-container {
:deep(.b-checkbox.checkbox) {
font-size: 1em;
}
}
.tainacan-checkbox-list-page-changer { .tainacan-checkbox-list-page-changer {
height: 100%; height: 100%;
position: absolute; position: absolute;
@ -1136,7 +1149,7 @@
right: auto; right: auto;
align-items: center; align-items: center;
display: flex; display: flex;
background-color: var(--tainacan-gray1); background-color: var(--tainacan-item-hover-background-color);
&:hover { &:hover {
background-color: var(--tainacan-primary); background-color: var(--tainacan-primary);

View File

@ -81,6 +81,13 @@
<span class="check" /> <span class="check" />
<span class="control-label"> <span class="control-label">
<span <span
v-tooltip="{
content: option.description,
autoHide: true,
html: true,
placement: 'auto-start',
popperClass: ['tainacan-tooltip', 'tooltip']
}"
class="checkbox-label-text" class="checkbox-label-text"
v-html="`${ option.name ? option.name : (option.label ? (option.hierarchy_path ? renderHierarchicalPath(option.hierarchy_path, option.label) : option.label) : '') }`" /> v-html="`${ option.name ? option.name : (option.label ? (option.hierarchy_path ? renderHierarchicalPath(option.hierarchy_path, option.label) : option.label) : '') }`" />
</span> </span>
@ -147,7 +154,15 @@
:type="isCheckbox ? 'checkbox' : 'radio'"> :type="isCheckbox ? 'checkbox' : 'radio'">
<span class="check" /> <span class="check" />
<span class="control-label"> <span class="control-label">
<span class="checkbox-label-text">{{ `${ (option.label ? option.label : '') }` }}</span> <span
v-tooltip="{
content: option.description,
autoHide: true,
html: true,
placement: 'auto-start',
popperClass: ['tainacan-tooltip', 'tooltip']
}"
class="checkbox-label-text">{{ `${ (option.label ? option.label : '') }` }}</span>
</span> </span>
</label> </label>
</li> </li>
@ -197,7 +212,8 @@
'b-checkbox checkbox': isCheckbox, 'b-checkbox checkbox': isCheckbox,
'b-radio radio': !isCheckbox, 'b-radio radio': !isCheckbox,
'is-disabled': !isOptionSelected(option.value) && maxMultipleValues !== undefined && (maxMultipleValues - 1 < selected.length) 'is-disabled': !isOptionSelected(option.value) && maxMultipleValues !== undefined && (maxMultipleValues - 1 < selected.length)
}" > }"
@click="option.total_children > 0 && (!finderColumns[key + 1] || finderColumns[key + 1].label !== option.label) ? getOptionChildren(option, key, index) : null">
<input <input
:disabled="!isOptionSelected(option.value) && maxMultipleValues !== undefined && (maxMultipleValues - 1 < selected.length)" :disabled="!isOptionSelected(option.value) && maxMultipleValues !== undefined && (maxMultipleValues - 1 < selected.length)"
@input="updateLocalSelection($event.target.value)" @input="updateLocalSelection($event.target.value)"
@ -206,7 +222,15 @@
:type="isCheckbox ? 'checkbox' : 'radio'"> :type="isCheckbox ? 'checkbox' : 'radio'">
<span class="check" /> <span class="check" />
<span class="control-label"> <span class="control-label">
<span class="checkbox-label-text">{{ option.label }}</span> <span
v-tooltip="{
content: option.description,
autoHide: true,
html: true,
placement: 'auto-start',
popperClass: ['tainacan-tooltip', 'tooltip']
}"
class="checkbox-label-text">{{ option.label }}</span>
</span> </span>
</label> </label>
<a <a
@ -306,8 +330,8 @@
</div> </div>
</b-tab-item> </b-tab-item>
</b-tabs> </b-tabs>
<!-- <pre>{{ hierarchicalPath }}</pre> <!-- <pre>{{ hierarchicalPath }}</pre> -->
<pre>{{ finderColumns }}</pre> --> <!-- <pre>{{ finderColumns }}</pre> -->
<!--<pre>{{ totalRemaining }}</pre>--> <!--<pre>{{ totalRemaining }}</pre>-->
<!-- <pre>{{ selected }}</pre> --> <!-- <pre>{{ selected }}</pre> -->
<!--<pre>{{ options }}</pre>--> <!--<pre>{{ options }}</pre>-->
@ -454,7 +478,11 @@
axios.get(`/taxonomy/${this.taxonomy_id}/terms/?${qs.stringify({ hideempty: 0, include: selected})}`) axios.get(`/taxonomy/${this.taxonomy_id}/terms/?${qs.stringify({ hideempty: 0, include: selected})}`)
.then((res) => { .then((res) => {
for (const term of res.data) for (const term of res.data)
this.saveSelectedTagName(term.id, term.name, term.url); this.saveSelectedTagName(
term.id,
!this.isCheckbox && term.hierarchy_path ? ( term.hierarchy_path + term.name ) : term.name,
term.url
);
this.isSelectedTermsLoading = false; this.isSelectedTermsLoading = false;
}) })
@ -813,15 +841,15 @@
}); });
} }
}, },
renderHierarchicalPath(hierachyPath, label) { renderHierarchicalPath(hierarchyPath, label) {
return '<span style="color: var(--tainacan-info-color);">' + hierachyPath.replace(/>/g, '&nbsp;<span class="hierarchy-separator"> &gt; </span>&nbsp;') + '</span>' + label; return '<span style="color: var(--tainacan-info-color);">' + hierarchyPath.replace(/>/g, '&nbsp;<span class="hierarchy-separator"> &gt; </span>&nbsp;') + '</span>' + label;
}, },
onMobileSpecialFocus($event) { onMobileSpecialFocus($event) {
$event.target.blur(); $event.target.blur();
this.$emit('mobileSpecialFocus'); this.$emit('mobileSpecialFocus');
}, },
isOptionSelected(optionValue) { isOptionSelected(optionValue) {
if (Array.isArray(this.selected)) if ( Array.isArray(this.selected) )
return (this.selected.indexOf((isNaN(Number(optionValue)) ? optionValue : Number(optionValue))) >= 0) return (this.selected.indexOf((isNaN(Number(optionValue)) ? optionValue : Number(optionValue))) >= 0)
else else
return optionValue == this.selected; return optionValue == this.selected;
@ -1016,6 +1044,10 @@
.tainacan-finder-columns-container { .tainacan-finder-columns-container {
background-color: var(--tainacan-white); background-color: var(--tainacan-white);
border: 1px solid var(--tainacan-gray1); border: 1px solid var(--tainacan-gray1);
border-bottom-left-radius: var(--tainacan-dropdownmenu-border-radius);
border-bottom-right-radius: var(--tainacan-dropdownmenu-border-radius);
border-top-right-radius: 0px;
border-top-left-radius: 0px;
border-top: 0px; border-top: 0px;
margin-top: -1px; margin-top: -1px;
display: flex; display: flex;
@ -1221,7 +1253,7 @@
padding: 0px !important; padding: 0px !important;
display: inline; display: inline;
.control { .field.is-grouped > .control:not(:last-child) {
margin-bottom: 0.25rem; margin-bottom: 0.25rem;
margin-right: 0.25rem; margin-right: 0.25rem;
} }
@ -1233,6 +1265,11 @@
section p { section p {
font-size: 0.875em; font-size: 0.875em;
} }
:deep(.field) {
padding: 0.25rem !important;
margin: 0 !important;
}
} }
.tainacan-modal-checkbox-search-results-body { .tainacan-modal-checkbox-search-results-body {

View File

@ -19,7 +19,7 @@
<div class="field is-grouped form-submit"> <div class="field is-grouped form-submit">
<div class="control"> <div class="control">
<button <button
id="button-cancel-importer-edition" id="button-cancel-file-preview"
class="button is-outlined" class="button is-outlined"
type="button" type="button"
@click="$emit('close')"> @click="$emit('close')">

View File

@ -9,6 +9,7 @@
v-for="(searchCriterion, index) in searchCriteria" v-for="(searchCriterion, index) in searchCriteria"
:key="index + '-' + searchCriterion.index + '-' + searchCriterion.type" :key="index + '-' + searchCriterion.index + '-' + searchCriterion.type"
grouped grouped
group-multiline
class="tainacan-form"> class="tainacan-form">
<!-- Metadata (Search criteria) --> <!-- Metadata (Search criteria) -->
@ -98,7 +99,7 @@
</b-field> </b-field>
<!-- Inputs --> <!-- Inputs -->
<b-field class="column is-half"> <b-field class="column is-half is-10-mobile">
<template v-if="searchCriterion.type == 'metaquery' && advancedSearchQuery.metaquery[searchCriterion.index]"> <template v-if="searchCriterion.type == 'metaquery' && advancedSearchQuery.metaquery[searchCriterion.index]">
<b-input <b-input
v-if="getAdvancedSearchQueryCriterionMetadataType(searchCriterion.index) == 'int' || getAdvancedSearchQueryCriterionMetadataType(searchCriterion.index) == 'float'" v-if="getAdvancedSearchQueryCriterionMetadataType(searchCriterion.index) == 'int' || getAdvancedSearchQueryCriterionMetadataType(searchCriterion.index) == 'float'"
@ -144,7 +145,7 @@
<div class="field"> <div class="field">
<button <button
@click.prevent="removeCriterion(searchCriterion)" @click.prevent="removeCriterion(searchCriterion)"
class="button is-white is-pulled-right has-text-secondary" class="button button-remove-criterion is-pulled-right has-text-secondary"
type="button" type="button"
:aria-label="$i18n.get('remove_search_criterion')"> :aria-label="$i18n.get('remove_search_criterion')">
<span <span
@ -655,44 +656,58 @@
border: 1px solid var(--tainacan-input-border-color); border: 1px solid var(--tainacan-input-border-color);
border-radius: 1px; border-radius: 1px;
transition: height 0.2s ease; transition: height 0.2s ease;
}
.tnc-advanced-search-container { .tnc-advanced-search-container {
position: relative; position: relative;
padding: 1.25em; padding: 1.25em;
border-radius: var(--tainacan-dropdownmenu-border-radius, 0px);
h3 { h3 {
font-size: 1em !important; font-size: 1em !important;
padding-top: 0 !important; padding-top: 0 !important;
color: var(--tainacan-heading-color) !important; color: var(--tainacan-heading-color) !important;
margin-bottom: 1em !important; margin-bottom: 1em !important;
} }
.tainacan-form { .tainacan-form {
margin-bottom: 0.125em !important; margin-bottom: 0.125em !important;
} }
.column { .column {
padding: 0; padding: 0;
} }
.control { .control {
font-size: 1em; font-size: 1em;
margin-bottom: 0px !important; margin-bottom: 0px !important;
.select{ .select{
width: 100% !important;
select{
width: 100% !important; width: 100% !important;
select{
width: 100% !important;
}
} }
} }
}
.add-link-advanced-search a { .add-link-advanced-search a {
font-size: 0.8125em; font-size: 0.8125em;
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
margin-right: 1em; margin-right: 1em;
} }
.button-remove-criterion {
color: var(--tainacan-input-color);
background: transparent;
border: none;
border-radius: var(--tainacan-button-border-radius, 4px);
}
}
@media screen and (max-width: 768px) { @media screen and (max-width: 768px) {
border-left: none;
border-right: none;
.tnc-advanced-search-container {
padding-right: 0;
padding-left: 0;
}
.is-12>.columns { .is-12>.columns {
flex-wrap: wrap; flex-wrap: wrap;
} }
@ -701,7 +716,6 @@
flex-basis: 100%; flex-basis: 100%;
} }
} }
} }
</style> </style>

View File

@ -2,7 +2,6 @@
<aside <aside
aria-labelledby="filters-label-landmark" aria-labelledby="filters-label-landmark"
:aria-busy="isLoadingFilters"> :aria-busy="isLoadingFilters">
<b-loading <b-loading
:is-full-page="false" :is-full-page="false"
v-model="isLoadingFilters"/> v-model="isLoadingFilters"/>
@ -89,12 +88,6 @@
:filters-as-modal="filtersAsModal" :filters-as-modal="filtersAsModal"
:is-mobile-screen="isMobileScreen"/> :is-mobile-screen="isMobileScreen"/>
</template> </template>
<!-- <p
class="has-text-gray"
style="font-size: 0.75em;"
v-if="taxonomyFilter.length <= 0">
{{ $i18n.get('info_there_is_no_filter') }}
</p> -->
<hr v-if="taxonomyFilter.length > 1"> <hr v-if="taxonomyFilter.length > 1">
</div> </div>
</template> </template>
@ -138,12 +131,6 @@
:filters-as-modal="filtersAsModal" :filters-as-modal="filtersAsModal"
:is-mobile-screen="isMobileScreen" /> :is-mobile-screen="isMobileScreen" />
</template> </template>
<!-- <p
class="has-text-gray"
style="font-size: 0.75em;"
v-if="taxonomyFilter.length <= 0">
{{ $i18n.get('info_there_is_no_filter') }}
</p> -->
<hr v-if="taxonomyFilter.length > 1"> <hr v-if="taxonomyFilter.length > 1">
</div> </div>
</template> </template>
@ -191,12 +178,6 @@
:filters-as-modal="filtersAsModal" :filters-as-modal="filtersAsModal"
:is-mobile-screen="isMobileScreen" /> :is-mobile-screen="isMobileScreen" />
</template> </template>
<!-- <p
class="has-text-gray"
style="font-size: 0.75em;"
v-if="taxonomyFilter.length <= 0">
{{ $i18n.get('info_there_is_no_filter') }}
</p> -->
<hr v-if="repositoryCollectionFilters.length > 1"> <hr v-if="repositoryCollectionFilters.length > 1">
</div> </div>
</template> </template>
@ -240,12 +221,6 @@
:filters-as-modal="filtersAsModal" :filters-as-modal="filtersAsModal"
:is-mobile-screen="isMobileScreen" /> :is-mobile-screen="isMobileScreen" />
</template> </template>
<!-- <p
class="has-text-gray"
style="font-size: 0.75em;"
v-if="taxonomyFilter.length <= 0">
{{ $i18n.get('info_there_is_no_filter') }}
</p> -->
<hr v-if="repositoryCollectionFilters.length > 1"> <hr v-if="repositoryCollectionFilters.length > 1">
</div> </div>
</template> </template>
@ -266,9 +241,12 @@
</template> </template>
</div> </div>
<section <section
v-if="!isLoadingFilters && v-if="!isLoadingFilters && (
!((filters.length >= 0 && isRepositoryLevel) || filters.length > 0)" ( taxonomy && taxonomyFilters && Object.keys(taxonomyFilters).length <= 0 ) ||
class="is-grouped-centered section"> ( isRepositoryLevel && !taxonomy && repositoryCollectionFilters && Object.keys(repositoryCollectionFilters).length <= 0 ) ||
( !isRepositoryLevel && !taxonomy && filters && filters.length <= 0 )
)"
class="is-grouped-centered">
<div class="content has-text-gray has-text-centered"> <div class="content has-text-gray has-text-centered">
<p> <p>
<span class="icon is-large"> <span class="icon is-large">
@ -276,6 +254,7 @@
</span> </span>
</p> </p>
<p>{{ $i18n.get('info_there_is_no_filter' ) }}</p> <p>{{ $i18n.get('info_there_is_no_filter' ) }}</p>
<p v-if="isRepositoryLevel && $route.name != null">{{ $i18n.get('info_collection_filter_on_repository_level') }}</p>
<router-link <router-link
v-if="!$adminOptions.hideItemsListFilterCreationButton && $route.name != null && ((isRepositoryLevel && $userCaps.hasCapability('tnc_rep_edit_filters')) || (!isRepositoryLevel && collection && collection.current_user_can_edit_filters))" v-if="!$adminOptions.hideItemsListFilterCreationButton && $route.name != null && ((isRepositoryLevel && $userCaps.hasCapability('tnc_rep_edit_filters')) || (!isRepositoryLevel && collection && collection.current_user_can_edit_filters))"
:to="isRepositoryLevel && $routerHelper ? $routerHelper.getNewFilterPath() : $routerHelper.getNewCollectionFilterPath(collectionId)" :to="isRepositoryLevel && $routerHelper ? $routerHelper.getNewFilterPath() : $routerHelper.getNewCollectionFilterPath(collectionId)"
@ -441,7 +420,7 @@
this.isLoadingFilters = true; this.isLoadingFilters = true;
// Normal filter loading, only collection ones // Normal filter loading, only collection ones
if (!this.taxonomy) { if ( !this.taxonomy && !this.isRepositoryLevel ) {
this.fetchFilters({ this.fetchFilters({
collectionId: this.collectionId, collectionId: this.collectionId,
isRepositoryLevel: this.isRepositoryLevel, isRepositoryLevel: this.isRepositoryLevel,
@ -459,7 +438,7 @@
.catch(() => this.isLoadingFilters = false); .catch(() => this.isLoadingFilters = false);
// Custom filter loading, get's from collections that have items with that taxonomy // Custom filter loading, get's from collections that have items with that taxonomy
} else { } else if ( this.taxonomy ) {
let collectionsIds = []; let collectionsIds = [];
@ -476,20 +455,24 @@
this.fetchTaxonomyFilters({ taxonomyId: taxonomyId[taxonomyId.length - 1], collectionsIds: collectionsIds }) this.fetchTaxonomyFilters({ taxonomyId: taxonomyId[taxonomyId.length - 1], collectionsIds: collectionsIds })
.catch(() => this.isLoadingFilters = false); .catch(() => this.isLoadingFilters = false);
} else if ( this.isRepositoryLevel && !this.taxonomy ) {
// Cancels previous Request
if (this.repositoryFiltersSearchCancel != undefined)
this.repositoryFiltersSearchCancel.cancel('Repository Collection Filters search Canceled.');
this.fetchRepositoryCollectionFilters()
.then((anotherResp) => {
anotherResp.request
.then(() => this.isLoadingFilters = false)
.catch(() => this.isLoadingFilters = false);
this.repositoryFiltersSearchCancel = anotherResp.source;
})
.catch(() => this.isLoadingFilters = false);
} }
// On repository level we also fetch collection filters
if ( !this.taxonomy && this.isRepositoryLevel ) {
// Cancels previous Request
if (this.repositoryFiltersSearchCancel != undefined)
this.repositoryFiltersSearchCancel.cancel('Repository Collection Filters search Canceled.');
this.fetchRepositoryCollectionFilters()
.then((source) => {
this.repositoryFiltersSearchCancel = source;
});
}
}, },
updateIsLoadingItems(isLoadingItems) { updateIsLoadingItems(isLoadingItems) {
this.$emit('updateIsLoadingItemsState', isLoadingItems); this.$emit('updateIsLoadingItemsState', isLoadingItems);

View File

@ -217,7 +217,7 @@
} }
.filter-tag { .filter-tag {
border-radius: 3px; border-radius: 4px;
padding: 3px 8px 2px 8px; padding: 3px 8px 2px 8px;
position: relative; position: relative;
background-color: var(--tainacan-input-background-color); background-color: var(--tainacan-input-background-color);
@ -244,9 +244,13 @@
right: 2px; right: 2px;
top: 2px; top: 2px;
border-radius: 50px; border-radius: 50px;
background-color: transparent;
&:not(:hover) { &:hover,
background-color: transparent; &:focus {
border: none;
background-color: var(--tainacan-item-hover-background-color);
color: var(--tainacan-secondary);
} }
} }
&.is-readonly { &.is-readonly {

View File

@ -46,6 +46,7 @@ import User from '../components/metadata-types/user/User.vue';
import GeoCoordinate from '../components/metadata-types/geocoordinate/GeoCoordinate.vue' import GeoCoordinate from '../components/metadata-types/geocoordinate/GeoCoordinate.vue'
import FormText from '../components/metadata-types/text/FormText.vue'; import FormText from '../components/metadata-types/text/FormText.vue';
import FormTextarea from '../components/metadata-types/textarea/FormTextarea.vue';
import FormRelationship from '../components/metadata-types/relationship/FormRelationship.vue'; import FormRelationship from '../components/metadata-types/relationship/FormRelationship.vue';
import FormTaxonomy from '../components/metadata-types/taxonomy/FormTaxonomy.vue'; import FormTaxonomy from '../components/metadata-types/taxonomy/FormTaxonomy.vue';
import FormSelectbox from '../components/metadata-types/selectbox/FormSelectbox.vue'; import FormSelectbox from '../components/metadata-types/selectbox/FormSelectbox.vue';
@ -78,7 +79,8 @@ import {
UserCapabilitiesPlugin, UserCapabilitiesPlugin,
StatusHelperPlugin, StatusHelperPlugin,
CommentsStatusHelperPlugin, CommentsStatusHelperPlugin,
AdminOptionsHelperPlugin AdminOptionsHelperPlugin,
HtmlSanitizerPlugin
} from './admin-utilities'; } from './admin-utilities';
import { import {
ThumbnailHelperPlugin, ThumbnailHelperPlugin,
@ -188,6 +190,7 @@ export default (element) => {
app.use(ThumbnailHelperPlugin); app.use(ThumbnailHelperPlugin);
app.use(OrderByHelperPlugin); app.use(OrderByHelperPlugin);
app.use(StatusHelperPlugin); app.use(StatusHelperPlugin);
app.use(HtmlSanitizerPlugin);
app.use(ConsolePlugin, {visual: false}); app.use(ConsolePlugin, {visual: false});
app.use(CommentsStatusHelperPlugin); app.use(CommentsStatusHelperPlugin);
app.use(AdminOptionsHelperPlugin, pageElement.dataset['options']); app.use(AdminOptionsHelperPlugin, pageElement.dataset['options']);
@ -215,6 +218,7 @@ export default (element) => {
/* Metadata Option forms */ /* Metadata Option forms */
app.component('tainacan-form-text', FormText); app.component('tainacan-form-text', FormText);
app.component('tainacan-form-textarea', FormTextarea);
app.component('tainacan-form-relationship', FormRelationship); app.component('tainacan-form-relationship', FormRelationship);
app.component('tainacan-form-taxonomy', FormTaxonomy); app.component('tainacan-form-taxonomy', FormTaxonomy);
app.component('tainacan-form-selectbox', FormSelectbox); app.component('tainacan-form-selectbox', FormSelectbox);

View File

@ -7,6 +7,21 @@ const wpApi = axios.create({
wpApi.defaults.headers.common['X-WP-Nonce'] = tainacan_plugin.nonce; wpApi.defaults.headers.common['X-WP-Nonce'] = tainacan_plugin.nonce;
const tainacanSanitize = function(htmlString) {
return htmlString.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;').replace(/\//g, '&#x2F;')
}
// HTML SANITIZE PLUGIN - Helps sanitizing html string from javascript.
export const HtmlSanitizerPlugin = {};
HtmlSanitizerPlugin.install = function (app, options = {}) {
app.config.globalProperties.$htmlSanitizer = {
sanitize(htmlString) {
return tainacanSanitize(htmlString);
}
}
};
// CONSOLE PLUGIN - Allows custom use of console functions and avoids eslint warnings. // CONSOLE PLUGIN - Allows custom use of console functions and avoids eslint warnings.
export const ConsolePlugin = {}; export const ConsolePlugin = {};
ConsolePlugin.install = function (app, options = { visual: false }) { ConsolePlugin.install = function (app, options = { visual: false }) {
@ -15,7 +30,7 @@ ConsolePlugin.install = function (app, options = { visual: false }) {
log(something) { log(something) {
if (options.visual) { if (options.visual) {
app.config.globalProperties.$buefy.snackbar.open({ app.config.globalProperties.$buefy.snackbar.open({
message: something, message: tainacanSanitize(something),
type: 'is-secondary', type: 'is-secondary',
position: 'is-bottom-right', position: 'is-bottom-right',
indefinite: true, indefinite: true,
@ -28,7 +43,7 @@ ConsolePlugin.install = function (app, options = { visual: false }) {
info(someInfo) { info(someInfo) {
if (options.visual) { if (options.visual) {
app.config.globalProperties.$buefy.snackbar.open({ app.config.globalProperties.$buefy.snackbar.open({
message: someInfo, message: tainacanSanitize(someInfo),
type: 'is-primary', type: 'is-primary',
position: 'is-bottom-right', position: 'is-bottom-right',
duration: 5000, duration: 5000,
@ -41,7 +56,7 @@ ConsolePlugin.install = function (app, options = { visual: false }) {
error(someError) { error(someError) {
if (options.visual) { if (options.visual) {
app.config.globalProperties.$buefy.snackbar.open({ app.config.globalProperties.$buefy.snackbar.open({
message: someError, message: tainacanSanitize(someError),
type: 'is-danger', type: 'is-danger',
position: 'is-bottom-right', position: 'is-bottom-right',
indefinite: true, indefinite: true,
@ -142,6 +157,7 @@ UserPrefsPlugin.install = function (app, options = {}) {
'taxonomies_order_by': 'title', 'taxonomies_order_by': 'title',
'collections_order': 'desc', 'collections_order': 'desc',
'collections_order_by': 'date', 'collections_order_by': 'date',
'collections_author_filter': '',
'map_view_mode_selected_geocoordinate_metadatum': 0 'map_view_mode_selected_geocoordinate_metadatum': 0
}, },
init() { init() {
@ -636,7 +652,7 @@ AdminOptionsHelperPlugin.install = function (app, options = {}) {
* hideItemEditionMetadataTypes * hideItemEditionMetadataTypes
* allowItemEditionModalInsideModal // Not recommended! * allowItemEditionModalInsideModal // Not recommended!
* itemEditionDocumentInsideTabs * itemEditionDocumentInsideTabs
* itemEditionAttachmentInsideTabs * itemEditionAttachmentsInsideTabs
* hideBulkEditionPageTitle * hideBulkEditionPageTitle

View File

@ -9,6 +9,10 @@ const i18nGet = function (key) {
return (string !== undefined && string !== null && string !== '' ) ? string : "ERROR: Invalid i18n key!"; return (string !== undefined && string !== null && string !== '' ) ? string : "ERROR: Invalid i18n key!";
}; };
const tainacanSanitize = function(htmlString) {
return htmlString.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;').replace(/\//g, '&#x2F;')
}
export const tainacanErrorHandler = function(error) { export const tainacanErrorHandler = function(error) {
if (error.response && error.response.status) { if (error.response && error.response.status) {
// The request was made and the server responded with a status code // The request was made and the server responded with a status code
@ -37,7 +41,7 @@ export const tainacanErrorHandler = function(error) {
break; break;
} }
Snackbar.open({ Snackbar.open({
message: errorMessage, message: tainacanSanitize(errorMessage),
type: 'is-danger', type: 'is-danger',
duration: duration, duration: duration,
actionText: errorMessageDetail != '' ? i18nGet('label_know_more') : null, actionText: errorMessageDetail != '' ? i18nGet('label_know_more') : null,

View File

@ -105,7 +105,7 @@ export const itemMetadataMixin = {
for (let conditionalSectionId in updatedConditionalSections) { for (let conditionalSectionId in updatedConditionalSections) {
if ( updatedConditionalSections[conditionalSectionId].metadatumId == metadatumId ) { if ( updatedConditionalSections[conditionalSectionId].metadatumId == metadatumId ) {
const conditionalValues = Array.isArray(updatedConditionalSections[conditionalSectionId].metadatumValues) ? updatedConditionalSections[conditionalSectionId].metadatumValues : [ this.conditionalSections[conditionalSectionId].metadatumValues ]; const conditionalValues = Array.isArray(updatedConditionalSections[conditionalSectionId].metadatumValues) ? updatedConditionalSections[conditionalSectionId].metadatumValues : [ this.conditionalSections[conditionalSectionId].metadatumValues ];
updatedConditionalSections[conditionalSectionId].hide = values.every(aValue => conditionalValues.indexOf(aValue) < 0); updatedConditionalSections[conditionalSectionId].hide = Array.isArray(values) ? values.every(aValue => conditionalValues.indexOf(aValue['id'] ? aValue['id'] : aValue) < 0) : conditionalValues.indexOf(values) < 0 ;
} }
} }
this.conditionalSections = updatedConditionalSections; this.conditionalSections = updatedConditionalSections;

View File

@ -147,7 +147,7 @@ export const deleteItem = ({ commit }, { itemId, isPermanently }) => {
}); });
}; };
export const fetchCollections = ({commit} , { page, collectionsPerPage, status, contextEdit, order, orderby, search, collectionTaxonomies }) => { export const fetchCollections = ({commit} , { page, collectionsPerPage, status, contextEdit, order, orderby, search, collectionTaxonomies, authorid }) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let endpoint = '/collections?paged='+page+'&perpage='+collectionsPerPage; let endpoint = '/collections?paged='+page+'&perpage='+collectionsPerPage;
@ -188,6 +188,9 @@ export const fetchCollections = ({commit} , { page, collectionsPerPage, status,
endpoint = endpoint + '&' + qs.stringify(taxQuery); endpoint = endpoint + '&' + qs.stringify(taxQuery);
} }
if (authorid != '' && authorid != undefined)
endpoint = endpoint + '&authorid=' + authorid;
axios.tainacan.get(endpoint) axios.tainacan.get(endpoint)
.then(res => { .then(res => {
let collections = res.data; let collections = res.data;
@ -237,7 +240,8 @@ export const fetchCollection = ({ commit, }, id) => {
export const fetchCollectionBasics = ({ commit }, {collectionId, isContextEdit }) => { export const fetchCollectionBasics = ({ commit }, {collectionId, isContextEdit }) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let endpoint = '/collections/' + collectionId + '?fetch_only=name,url,status,allow_comments,hide_items_thumbnail_on_lists'; let endpoint = '/collections/' + collectionId + '?fetch_only=name,url,status,allow_comments,hide_items_thumbnail_on_lists,item_enabled_document_types,item_document_label,item_thumbnail_label,item_enable_thumbnail,item_attachment_label,item_enable_attachments,item_enable_metadata_focus_mode,item_enable_metadata_required_filter,item_enable_metadata_searchbar,item_enable_metadata_collapses,item_enable_metadata_enumeration,metadata_section_order';
if (isContextEdit) if (isContextEdit)
endpoint += '&context=edit'; endpoint += '&context=edit';
@ -307,7 +311,7 @@ export const fetchCollectionForExposer = ({ commit }, collectionId) => {
export const fetchCollectionForItemSubmission = ({ commit }, collectionId) => { export const fetchCollectionForItemSubmission = ({ commit }, collectionId) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let endpoint = '/collections/' + collectionId + '?fetch_only=name,allows_submission,submission_use_recaptcha'; let endpoint = '/collections/' + collectionId + '?fetch_only=name,allows_submission,submission_use_recaptcha,item_enable_metadata_enumeration,metadata_section_order';
axios.tainacan.get(endpoint) axios.tainacan.get(endpoint)
.then(res => { .then(res => {
resolve( res.data ); resolve( res.data );

View File

@ -144,15 +144,15 @@ export const updateCollectionFiltersOrder = ({ commit }, { collectionId, filters
export const fetchFilterTypes = ({ commit} ) => { export const fetchFilterTypes = ({ commit} ) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
axios.tainacan.get('/filter-types') axios.tainacan.get('/filter-types')
.then((res) => { .then((res) => {
let filterTypes = res.data; let filterTypes = res.data;
commit('setFilterTypes', filterTypes); commit('setFilterTypes', filterTypes);
resolve (filterTypes); resolve (filterTypes);
}) })
.catch((error) => { .catch((error) => {
console.log(error); console.log(error);
reject(error); reject(error);
}); });
}); });
}; };
@ -165,62 +165,65 @@ export const fetchRepositoryCollectionFilters = ({ dispatch, commit } ) => {
commit('clearRepositoryCollectionFilters'); commit('clearRepositoryCollectionFilters');
return new Promise((resolve, reject) => { const source = axios.CancelToken.source();
dispatch('collection/fetchAllCollectionNames', { } ,{ root: true }) return Object({
.then((resp) => { request: new Promise((resolve, reject) => {
resp.request
.then((res) => {
let collections = res;
if (collections != undefined && collections.length != undefined) {
let promises = []; dispatch('collection/fetchAllCollectionNames', { } ,{ root: true })
.then((resp) => {
resp.request
.then((res) => {
let collections = res;
if (collections != undefined && collections.length != undefined) {
// First, we add repository level filters let promises = [];
promises.push(
axios.tainacan.get('/filters/?include_control_metadata_types=true&nopaging=1&include_disabled=false')
.then((resp) => { return { filters: resp.data, collectionId: 'default' } })
.catch((error) => {
reject(error);
})
);
// Then we add collection level filters // First, we add repository level filters
collections.forEach(collection => {
promises.push( promises.push(
axios.tainacan.get('/collection/' + collection.id + '/filters/?include_control_metadata_types=true&nopaging=1&include_disabled=false&metaquery[0][key]=collection_id&metaquery[0][value]=default&metaquery[0][compare]=!=') axios.tainacan.get('/filters/?include_control_metadata_types=true&nopaging=1&include_disabled=false')
.then((resp) => { return { filters: resp.data, collectionId: collection.id } }) .then((resp) => { return { filters: resp.data, collectionId: 'default' } })
.catch((error) => { .catch((error) => {
reject(error); reject(error);
}) })
); );
});
// Process it all
axios.all(promises)
.then((results) => {
let futureRepositoryCollectionFilters = {};
for (let resp of results)
futureRepositoryCollectionFilters[resp.collectionId != 'default' ? resp.collectionId : 'repository-filters'] = resp.filters;
commit('setRepositoryCollectionFilters', futureRepositoryCollectionFilters); // Then we add collection level filters
collections.forEach(collection => {
promises.push(
axios.tainacan.get('/collection/' + collection.id + '/filters/?include_control_metadata_types=true&nopaging=1&include_disabled=false&metaquery[0][key]=collection_id&metaquery[0][value]=default&metaquery[0][compare]=!=&metaquery[1][key]=display_in_repository_level_lists&metaquery[1][value]=no&metaquery[1][compare]=!=')
.then((resp) => { return { filters: resp.data, collectionId: collection.id } })
.catch((error) => {
reject(error);
})
);
});
// Process it all
axios.all(promises)
.then((results) => {
let futureRepositoryCollectionFilters = {};
for (let resp of results) {
if (resp.filters.length > 0)
futureRepositoryCollectionFilters[resp.collectionId != 'default' ? resp.collectionId : 'repository-filters'] = resp.filters;
}
commit('setRepositoryCollectionFilters', futureRepositoryCollectionFilters);
resolve(); resolve();
}) })
.catch((error) => { .catch((error) => {
console.log(error); console.log(error);
reject(error); reject(error);
}) })
} }
}) })
.catch(() => { .catch(() => {
reject(); reject();
}); });
});
// Search Request Token for cancelling }),
resolve(resp.source); source: source
});
}); });
}; };
@ -251,7 +254,7 @@ export const fetchTaxonomyFilters = ({ dispatch, commit }, { taxonomyId, collect
const collectionsToSearch = collectionsIds.length ? collectionsIds : taxonomy.collections_ids const collectionsToSearch = collectionsIds.length ? collectionsIds : taxonomy.collections_ids
collectionsToSearch.forEach(collectionId => { collectionsToSearch.forEach(collectionId => {
promises.push( promises.push(
axios.tainacan.get('/collection/' + collectionId + '/filters/?include_control_metadata_types=true&nopaging=1&include_disabled=false&metaquery[0][key]=collection_id&metaquery[0][value]=default&metaquery[0][compare]=!=') axios.tainacan.get('/collection/' + collectionId + '/filters/?include_control_metadata_types=true&nopaging=1&include_disabled=false&metaquery[0][key]=collection_id&metaquery[0][value]=default&metaquery[0][compare]=!=&metaquery[1][key]=display_in_repository_level_lists&metaquery[1][value]=no&metaquery[1][compare]=!=')
.then((resp) => { return { filters: resp.data, collectionId: collectionId } }) .then((resp) => { return { filters: resp.data, collectionId: collectionId } })
.catch((error) => { .catch((error) => {
reject(error); reject(error);
@ -268,7 +271,8 @@ export const fetchTaxonomyFilters = ({ dispatch, commit }, { taxonomyId, collect
let taxonomyFilters = resp.filters.filter((filter) => { let taxonomyFilters = resp.filters.filter((filter) => {
return filter.metadatum.metadata_type_object.options.taxonomy_id != taxonomyId return filter.metadatum.metadata_type_object.options.taxonomy_id != taxonomyId
}); });
futureTaxonomyFilters[resp.collectionId != 'default' ? resp.collectionId : 'repository-filters'] = taxonomyFilters; if (taxonomyFilters.length > 0)
futureTaxonomyFilters[resp.collectionId != 'default' ? resp.collectionId : 'repository-filters'] = taxonomyFilters;
} }
commit('setTaxonomyFilters', futureTaxonomyFilters); commit('setTaxonomyFilters', futureTaxonomyFilters);

View File

@ -123,7 +123,7 @@ export const fetchTaxonomyName = ({ commit }, taxonomyId) => {
}; };
// TAXONOMY TERMS // TAXONOMY TERMS
export const fetchTerms = ({}, {taxonomyId, fetchOnly, search, all, order, offset, number, exclude }) => { export const fetchTerms = ({}, {taxonomyId, fetchOnly, search, all, order, offset, number, exclude, include }) => {
let query = ''; let query = '';
@ -148,6 +148,9 @@ export const fetchTerms = ({}, {taxonomyId, fetchOnly, search, all, order, offse
if (exclude != undefined) if (exclude != undefined)
query += '&' + qs.stringify({ exclude: exclude }); query += '&' + qs.stringify({ exclude: exclude });
if (include != undefined)
query += '&' + qs.stringify({ include: include });
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
axios.tainacan.get(`/taxonomy/${taxonomyId}/terms${query}`) axios.tainacan.get(`/taxonomy/${taxonomyId}/terms${query}`)
.then(res => { .then(res => {
@ -159,7 +162,14 @@ export const fetchTerms = ({}, {taxonomyId, fetchOnly, search, all, order, offse
}); });
}; };
export const sendChildTerm = ({ commit }, { taxonomyId, term }) => { export const sendChildTerm = ({ commit }, { taxonomyId, term, itemId, metadatumId }) => {
if ( itemId != undefined )
term['item_id'] = itemId;
if ( metadatumId != undefined )
term['metadatum_id'] = metadatumId;
return new Promise(( resolve, reject ) => { return new Promise(( resolve, reject ) => {
axios.tainacan.post(`/taxonomy/${taxonomyId}/terms/`, term) axios.tainacan.post(`/taxonomy/${taxonomyId}/terms/`, term)
.then( res => { .then( res => {
@ -172,7 +182,14 @@ export const sendChildTerm = ({ commit }, { taxonomyId, term }) => {
}); });
}; };
export const updateTerm = ({}, { taxonomyId, term }) => { export const updateTerm = ({}, { taxonomyId, term, itemId, metadatumId }) => {
if ( itemId != undefined )
term['item_id'] = itemId;
if ( metadatumId != undefined )
term['metadatum_id'] = metadatumId;
return new Promise(( resolve, reject ) => { return new Promise(( resolve, reject ) => {
axios.tainacan.patch(`/taxonomy/${taxonomyId}/terms/${term.id}`, term) axios.tainacan.patch(`/taxonomy/${taxonomyId}/terms/${term.id}`, term)
.then( res => { .then( res => {

View File

@ -72,7 +72,15 @@ export const ThumbnailHelperFunctions = () => {
imageSrc = 'placeholder_square'; imageSrc = 'placeholder_square';
} }
return this.getEmptyThumbnailPlaceholderBySize(imageSrc, tainacanSize); /**
* Filter the image source for the empty thumbnail placeholder.
*
* @param string imageSrc The image source for the empty thumbnail placeholder.
* Default is 'placeholder_square'.
* @param string documentType The document type of the item.
* @param string size The size of the image to be loaded.
*/
return wp.hooks.applyFilters('tainacan_get_the_mime_type_icon', this.getEmptyThumbnailPlaceholderBySize(imageSrc, tainacanSize), documentType, tainacanSize);
}, },
getEmptyThumbnailPlaceholderBySize(imageSrc, tainacanSize) { getEmptyThumbnailPlaceholderBySize(imageSrc, tainacanSize) {
switch(tainacanSize) { switch(tainacanSize) {

View File

@ -21,7 +21,7 @@
target="_blank" target="_blank"
:href="themeItemsListURL"> :href="themeItemsListURL">
<span class="icon"> <span class="icon">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-see"/> <i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-openurl"/>
</span> </span>
<span class="menu-text">{{ $i18n.get('label_view_items_on_theme') }}</span> <span class="menu-text">{{ $i18n.get('label_view_items_on_theme') }}</span>
</a> </a>
@ -131,7 +131,7 @@
:href="themeCollectionListURL" :href="themeCollectionListURL"
style="position: relative"> style="position: relative">
<span class="icon"> <span class="icon">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-see"/> <i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-openurl"/>
</span> </span>
<span class="menu-text">{{ $i18n.get('label_view_collections_on_theme') }}</span> <span class="menu-text">{{ $i18n.get('label_view_collections_on_theme') }}</span>
</a> </a>

Some files were not shown because too many files have changed in this diff Show More