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": {
"squizlabs/php_codesniffer": "^2.2 || ^3.0.2",
"yoast/phpunit-polyfills": "^1.0.1"
"yoast/phpunit-polyfills": "^1.1.0"
},
"prefer-stable" : true,
"minimum-stability": "dev",

1329
composer.lock generated

File diff suppressed because it is too large Load Diff

2531
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",
"@vue-leaflet/vue-leaflet": "^0.10.1",
"another-vue3-blurhash": "^0.0.1",
"apexcharts": "^3.42.0",
"axios": "^1.5.0",
"apexcharts": "^3.44.1",
"axios": "^1.6.2",
"blurhash": "^2.0.5",
"bulma": "^0.9.4",
"conditioner-core": "^2.3.3",
@ -25,48 +25,48 @@
"mitt": "^3.0.1",
"moment": "^2.29.4",
"node-sass": "^7.0.3",
"photoswipe": "^5.4.1",
"photoswipe": "^5.4.3",
"qs": "^6.11.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"sortablejs": "^1.15.0",
"sortablejs-vue3": "^1.2.9",
"swiper": "^10.2.0",
"vue": "^3.3.4",
"vue-countup-v3": "^1.3.0",
"vue-router": "^4.2.4",
"sortablejs": "^1.15.1",
"sortablejs-vue3": "^1.2.11",
"swiper": "^11.0.5",
"vue": "^3.3.10",
"vue-countup-v3": "^1.4.0",
"vue-imask": "^7.1.3",
"vue-router": "^4.2.5",
"vue3-apexcharts": "^1.4.4",
"vuex": "^4.1.0"
},
"devDependencies": {
"@babel/core": "^7.21.0",
"@babel/preset-env": "^7.20.2",
"@babel/preset-react": "^7.18.6",
"@types/leaflet": "^1.9.3",
"@types/masonry-layout": "^4.2.5",
"@vue/compiler-sfc": "3.3.4",
"acorn": "^8.8.2",
"@babel/core": "^7.23.5",
"@babel/preset-env": "^7.23.5",
"@babel/preset-react": "^7.23.3",
"@types/leaflet": "^1.9.8",
"@types/masonry-layout": "^4.2.7",
"@vue/compiler-sfc": "3.3.10",
"acorn": "^8.11.2",
"ajv": "^8.12.0",
"autoprefixer": "^10.4.14",
"autoprefixer": "^10.4.16",
"babel-loader": "^9.1.3",
"circular-dependency-plugin": "5.2.2",
"cross-env": "^7.0.3",
"css-loader": "^6.7.3",
"eslint": "^8.35.0",
"eslint-plugin-vue": "^9.15.1",
"eslint-webpack-plugin": "^4.0.0",
"css-loader": "^6.8.1",
"eslint": "^8.55.0",
"eslint-plugin-vue": "^9.19.2",
"eslint-webpack-plugin": "^4.0.1",
"file-loader": "^6.2.0",
"moment-locales-webpack-plugin": "^1.2.0",
"postcss-loader": "7.0.2",
"sass-loader": "^13.2.0",
"style-loader": "^3.3.1",
"terser-webpack-plugin": "5.3.7",
"vue-loader": "^17.2.2",
"webpack": "^5.76.0",
"webpack-bundle-analyzer": "^4.8.0",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.11.1",
"webpack-merge": "^5.8.0"
"postcss-loader": "7.3.3",
"sass-loader": "^13.3.2",
"style-loader": "^3.3.3",
"terser-webpack-plugin": "5.3.9",
"vue-loader": "^17.3.1",
"webpack": "^5.89.0",
"webpack-bundle-analyzer": "^4.10.1",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1",
"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
* https://swiperjs.com
*
@ -7,7 +7,7 @@
*
* Released under the MIT License
*
* Released on: August 17, 2023
* Released on: November 22, 2023
*/
@font-face {
font-family: 'swiper-icons';
@ -32,7 +32,6 @@
margin-right: auto;
position: relative;
overflow: hidden;
overflow: clip;
list-style: none;
padding: 0;
/* 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
* https://swiperjs.com
*
@ -7,7 +7,7 @@
*
* Released under the MIT License
*
* Released on: August 17, 2023
* Released on: November 22, 2023
*/
@font-face {
font-family: 'swiper-icons';
@ -32,7 +32,6 @@
margin-right: auto;
position: relative;
overflow: hidden;
overflow: clip;
list-style: none;
padding: 0;
/* 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
* https://swiperjs.com
*
@ -7,7 +7,7 @@
*
* Released under the MIT License
*
* Released on: August 17, 2023
* Released on: November 22, 2023
*/
@font-face {
font-family: 'swiper-icons';
@ -32,7 +32,6 @@
margin-right: auto;
position: relative;
overflow: hidden;
overflow: clip;
list-style: none;
padding: 0;
/* 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
* https://swiperjs.com
*
@ -7,7 +7,7 @@
*
* Released under the MIT License
*
* Released on: August 17, 2023
* Released on: November 22, 2023
*/
@font-face {
font-family: 'swiper-icons';
@ -32,7 +32,6 @@
margin-right: auto;
position: relative;
overflow: hidden;
overflow: clip;
list-style: none;
padding: 0;
/* Fix of Webkit flickering */
@ -891,6 +890,10 @@
max-width: calc((90vh * 9) / 16); }
.tainacan-photoswipe-layer .pswp__container .tainacan-content-embed.tainacan-embed-aspect-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) {
margin-top: 60px; }
.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;
width: 18%;
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; }
.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));
height: 2.5em;
width: 100%;
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; }
.wp-block-tainacan-item-submission-form .item-submission-form-placeholder .fake-button {
background-color: var(--tainacan-secondary, rgba(200, 200, 200, 0.3));
@ -146,7 +146,7 @@
max-width: 3.45em;
min-width: 1em;
margin-left: 6px;
border-radius: 3px;
border-radius: var(--tainacan-button-border-radius, 4px);
display: flex;
align-items: center;
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 $request
@ -219,6 +230,7 @@ abstract class REST_Controller extends \WP_REST_Controller {
*/
private function prepare_meta($mapped, $request, $query, $mapped_v, $args){
$request_meta_query = $request[$mapped];
$query_field_scaped = ["value", "terms"];
// if the meta/date/taxquery has a root 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 ) {
if ( isset( $a[ $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,10 +260,16 @@ abstract class REST_Controller extends \WP_REST_Controller {
} else {
foreach ( $query as $mapped_meta => $meta_v ) {
if(isset($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 ];
}
}
}
}
return $args;
}
@ -405,55 +431,17 @@ abstract class REST_Controller extends \WP_REST_Controller {
* @return array
*/
protected function get_meta_queries_params(){
return array(
'metakey' => array(
'type' => ['integer', 'string'],
'description' => __('Custom metadata key.'),
),
'metavalue' => array(
'type' => ['string', 'array'],
'description' => __('Custom metadata value'),
),
'metavaluenum' => array(
'type' => 'number',
'description' => __('Custom metadata value'),
),
'metacompare' => array(
'type' => 'string',
'description' => __('Operator to test the metavalue'),
'default' => '=',
'enum' => array(
'=',
'!=',
'>',
'>=',
'<',
'<=',
'LIKE',
'NOT LIKE',
'IN',
'NOT IN',
'BETWEEN',
'NOT BETWEEN',
'NOT EXISTS',
'REGEXP',
'NOT REGEXP',
'RLIKE'
)
),
'metaquery' => array(
'description' => __('Limits result set to items that have specific custom metadata'),
'type' => ['array', 'object'],
'items' => array(
'keys' => array(
$metaquery_properties = array(
'key' => array(
'type' => 'string',
'type' => ['integer', '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\'.'),
'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',
@ -485,8 +473,52 @@ abstract class REST_Controller extends \WP_REST_Controller {
'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(
'metakey' => array(
'type' => ['integer', 'string'],
'description' => __('Custom metadata key.'),
),
'type' => ['array', 'object']
'metavalue' => array(
'type' => ['string', 'array'],
'description' => __('Custom metadata value'),
'sanitize_callback' => 'sanitize_text_field',
),
'metavaluenum' => array(
'type' => 'number',
'description' => __('Custom metadata value'),
),
'metacompare' => array(
'type' => 'string',
'description' => __('Operator to test the metavalue'),
'default' => '=',
'enum' => array(
'=',
'!=',
'>',
'>=',
'<',
'<=',
'LIKE',
'NOT LIKE',
'IN',
'NOT IN',
'BETWEEN',
'NOT BETWEEN',
'NOT EXISTS',
'REGEXP',
'NOT REGEXP',
'RLIKE'
)
),
'metaquery' => array(
'description' => __('Limits result set to items that have specific custom metadata'),
'type' => ['array', 'object',],
'properties' => $metaquery_properties,
'items' => array(
'type' => 'object',
'properties' => $metaquery_properties,
),
),
'datequery' => array(
@ -586,6 +618,7 @@ abstract class REST_Controller extends \WP_REST_Controller {
),
'terms' => array(
'type' => ['integer', 'string', 'array'],
'sanitize_callback' => 'sanitize_text_field',
'description' => __('Taxonomy term(s).'),
),
'operator' => array(

View File

@ -245,7 +245,7 @@ class REST_Facets_Controller extends REST_Controller {
],
'parent' => [
'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' => [
'type' => 'integer',

View File

@ -457,6 +457,7 @@ class REST_Items_Controller extends REST_Controller {
private function prepare_filters_arguments ( $args, $collection_id = false ) {
$filters_arguments = array();
$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'] : [];
foreach($tax_query as $tax) {

View File

@ -442,7 +442,7 @@ class REST_Reports_Controller extends REST_Controller {
'list' => array()
);
$collection_id = $request['collection_id'];
$taxonomy_metadata_id = $request['metadata_id'];;
$taxonomy_metadata_id = $request['metadata_id'];
$parent_id = 0;
if ( isset($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,
'callback' => array($this, 'get_item_in_sequence'),
'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']
)
@ -218,6 +218,30 @@ class REST_Sequence_Edit_Controller extends REST_Controller {
* @return array|mixed
*/
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 = [
'collection_id' => [
'type' => 'string',

View File

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

View File

@ -191,7 +191,7 @@ class Private_Files {
$upload_dir = wp_get_upload_dir();
$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 ) {
// Not uploads

View File

@ -177,9 +177,15 @@ class Search_Engine {
}
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()
? ''
: " 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 (
SELECT m.post_id
FROM $wpdb->postmeta m $join

View File

@ -40,7 +40,18 @@ class Collection extends Entity {
$hide_items_thumbnail_on_lists,
$submission_anonymous_user,
$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}
@ -607,14 +618,112 @@ class Collection extends Entity {
/**
* Get the default metadata section properties.
*
* @param [string] $value
*
* @return void
*/
function get_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
*
@ -888,6 +997,117 @@ class Collection extends Entity {
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
*

View File

@ -19,7 +19,8 @@ class Filter extends Entity {
$max_options,
$filter_type,
$filter_type_options,
$begin_with_filter_collapsed;
$begin_with_filter_collapsed,
$display_in_repository_level_lists;
static $post_type = 'tainacan-filter';
public $enabled_for_collection = true;
@ -179,6 +180,15 @@ class Filter extends Entity {
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
@ -252,6 +262,15 @@ class Filter extends Entity {
$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
*

View File

@ -307,7 +307,9 @@ class Item extends Entity {
* @return string "open"|"closed"
*/
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,6 +1185,7 @@ class Item extends Entity {
if ( $metadata_section->is_conditional_section() ) {
$rules = $metadata_section->get_conditional_section_rules();
if( !empty($rules) ) {
$item_id = $this->get_id();
foreach ( $rules as $meta_id => $meta_values_conditional ) {
@ -1192,6 +1195,7 @@ class Item extends Entity {
return $return;
}
}
}
$defaults = array(
'hide_name' => false,

View File

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

View File

@ -26,7 +26,7 @@ class Items extends Repository {
protected function __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_filter( 'map_meta_cap', array( $this, 'map_meta_cap' ), 10, 4 );
}
@ -103,7 +103,7 @@ class Items extends Repository {
'map' => 'meta',
'title' => __( 'Document', 'tainacan' ),
'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' ),
'default' => ''
],
@ -193,7 +193,8 @@ class Items extends Repository {
$Tainacan_Collections = \Tainacan\Repositories\Collections::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( [
'status' => [
'auto-draft',
@ -220,7 +221,7 @@ class Items extends Repository {
}
// 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
*
* @param string $open_comment
* @param bool $comments_open
* @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);
if($item != false && $item instanceof Entities\Item) {
$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.
$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) ) {
$statuses = array_merge( $statuses, get_post_stati( array( 'private' => true ) ) );
}

View File

@ -737,8 +737,8 @@ class Metadata extends Repository {
public function insert( $metadatum ) {
$this->pre_update_taxonomy_metadatum( $metadatum );
$new_metadatum = parent::insert( $metadatum );
$this->update_taxonomy_metadatum( $new_metadatum );
$this->update_metadata_type_index( $new_metadatum );
$this->update_taxonomy_metadatum( $new_metadatum );
return $new_metadatum;
}
@ -1426,6 +1426,7 @@ class Metadata extends Repository {
'parent' => $r->parent,
'total_items' => $total_items,
'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])
];

View File

@ -295,8 +295,11 @@ class Taxonomies extends Repository {
$id = $taxonomy_id;
if ( ! empty( $id ) && is_numeric( $id ) && is_numeric($collection_id) ) {
$tax = $this->fetch( (int) $id );
if ( $tax instanceof Entities\Taxonomy ) {
$tax->add_collection_id( $collection_id );
if ( $tax->validate() ) {
if ( $tax->validate() )
$this->insert( $tax );
}
}
@ -307,8 +310,11 @@ class Taxonomies extends Repository {
$id = $taxonomy_id;
if ( ! empty( $id ) && is_numeric( $id ) && is_numeric($collection_id) ) {
$tax = $this->fetch( (int) $id );
if ( $tax instanceof Entities\Taxonomy ) {
$tax->remove_collection_id( $collection_id );
if ( $tax->validate() ) {
if ( $tax->validate() )
$this->insert( $tax );
}
}
@ -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();
// 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 ) ) {
return;
}
// register taxonomies to other collections considering metadata inheritance
$taxonomies_res = $wpdb->get_results("
SELECT
meta.post_id as meta_id, meta.meta_value as tax_id, col.meta_value as collection_id
FROM
$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 ) {
$taxonomies = $this->fetch_by_collection($collection, ['nopaging' => true]);
foreach ( $taxonomies as $taxonomy ) {
register_taxonomy_for_object_type( $taxonomy->get_db_identifier(), $collection->get_db_identifier() );
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', [
'label' => __('Table', 'tainacan'),
'description' => 'The classic table display.',
'description' => __('The classic table display.', 'tainacan'),
'dynamic_metadata' => true,
'icon' => '<span class="icon"><i class="tainacan-icon tainacan-icon-viewtable tainacan-icon-1-25em"></i></span>',
'type' => 'component',
@ -79,7 +79,7 @@ class Theme_Helper {
$this->register_view_mode('cards', [
'label' => __('Cards', 'tainacan'),
'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>',
'type' => 'component',
'implements_skeleton' => true,
@ -88,7 +88,7 @@ class Theme_Helper {
$this->register_view_mode('records', [
'label' => __('Records', 'tainacan'),
'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>',
'type' => 'component',
'implements_skeleton' => true,
@ -97,7 +97,7 @@ class Theme_Helper {
$this->register_view_mode('masonry', [
'label' => __('Masonry', 'tainacan'),
'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>',
'type' => 'component',
'implements_skeleton' => true
@ -105,7 +105,7 @@ class Theme_Helper {
$this->register_view_mode('slideshow', [
'label' => __('Slides', 'tainacan'),
'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>',
'type' => 'component',
'show_pagination' => false,
@ -114,7 +114,7 @@ class Theme_Helper {
$this->register_view_mode('list', [
'label' => __('List', 'tainacan'),
'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>',
'type' => 'component',
'implements_skeleton' => true,
@ -123,7 +123,7 @@ class Theme_Helper {
$this->register_view_mode('map', [
'label' => __('Map', 'tainacan'),
'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">
<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">

View File

@ -1019,7 +1019,15 @@ function tainacan_get_the_mime_type_icon($mime_type, $image_size = 'medium') {
$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' )
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' )
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
Tags: museums, libraries, archives, GLAM, collections, repository
Requires at least: 5.9
Tested up to: 6.3
Tested up to: 6.4
Requires PHP: 7.0
Stable tag: 0.20.4
Stable tag: 0.20.5
License: GPLv2 or later
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.
Author: Tainacan.org
Author URI: https://tainacan.org/
Version: 0.20.4
Version: 0.20.5
Requires at least: 5.9
Tested up to: 6.3
Tested up to: 6.4
Requires PHP: 7.0
Stable tag: 0.20.4
Stable tag: 0.20.5
Text Domain: tainacan
License: GPLv2 or later
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!' );
$TAINACAN_BASE_URL = plugins_url('', __FILE__);

View File

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

View File

@ -51,7 +51,7 @@
<b-input
id="tainacan-text-description"
type="textarea"
rows="3"
rows="4"
:placeholder="$i18n.get('instruction_collection_description')"
v-model="form.description"
@focus="clearErrors('description')"/>
@ -75,6 +75,24 @@
:loading="isUpdatingSlug"/>
</b-field>
<!-- Items list options ------------------------ -->
<div
@click="showItemsListOptions = !showItemsListOptions;"
class="collection-form-section">
<span class="icon">
<i
class="tainacan-icon"
:class="showItemsListOptions ? 'tainacan-icon-arrowdown' : 'tainacan-icon-arrowright'" />
</span>
<strong>{{ $i18n.get('label_items_list_options') }}</strong>
<hr>
</div>
<transition name="filter-item">
<div
v-show="showItemsListOptions"
class="options-columns">
<!-- Change Default OrderBy Select and Order Button-->
<b-field
:addons="false"
@ -141,9 +159,9 @@
aria-role="list"
trap-focus
position="is-top-right">
<template #trigger>
<button
class="button is-white"
slot="trigger"
position="is-top-right"
type="button">
<span>{{ $i18n.get('label_enabled_view_modes') }}</span>
@ -151,7 +169,6 @@
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-arrowdown"/>
</span>
</button>
</template>
<b-dropdown-item
v-for="(viewMode, index) in Object.keys(registeredViewModes)"
:key="index"
@ -159,8 +176,8 @@
aria-role="listitem">
<b-checkbox
v-if="registeredViewModes[viewMode] != undefined"
@update:model-value="updateViewModeslist(viewMode)"
:model-value="checkIfViewModeEnabled(viewMode)"
@input="updateViewModeslist(viewMode)"
:value="checkIfViewModeEnabled(viewMode)"
:disabled="checkIfViewModeEnabled(viewMode) && form.enabled_view_modes.filter((aViewMode) => (registeredViewModes[aViewMode] && registeredViewModes[aViewMode].full_screen != true)).length <= 1">
<p>
<strong>
@ -222,6 +239,163 @@
:message="$i18n.getHelperMessage('collections', 'hide_items_thumbnail_on_lists')"/>
</b-field>
</div>
</transition>
<!-- Item edition form options ------------------------ -->
<div
@click="showItemEditionFormOptions = !showItemEditionFormOptions;"
class="collection-form-section">
<span class="icon">
<i
class="tainacan-icon"
:class="showItemEditionFormOptions ? 'tainacan-icon-arrowdown' : 'tainacan-icon-arrowright'" />
</span>
<strong>{{ $i18n.get('label_item_edition_form_options') }}</strong>
<hr>
</div>
<transition name="filter-item">
<div
v-show="showItemEditionFormOptions"
class="options-columns">
<!-- Allowed types of main document -------------------------------- -->
<div>
<b-field
:addons="false"
:label="$i18n.getHelperTitle('collections', 'item_enabled_document_types')">
<help-button
:title="$i18n.getHelperTitle('collections', 'item_enabled_document_types')"
:message="$i18n.getHelperMessage('collections', 'item_enabled_document_types')"/>
<div class="status-radios">
<b-checkbox
v-for="(documentType, slug) in form.item_enabled_document_types"
:key="slug"
v-model="documentType.enabled"
true-value="yes"
false-value="no">
<span class="icon">
<i :class="'tainacan-icon tainacan-icon-' + documentType.icon" />
</span>
{{ documentType.label }}
</b-checkbox>
</div>
</b-field>
<b-field
v-if="Object.values(form.item_enabled_document_types).some((aDocumentType) => aDocumentType.enabled === 'yes')"
:addons="false"
:label="$i18n.getHelperTitle('collections', 'item_document_label')">
<help-button
:title="$i18n.getHelperTitle('collections', 'item_document_label')"
:message="$i18n.getHelperMessage('collections', 'item_document_label')"/>
<b-input
id="tainacan-text-item-document-label"
v-model="form.item_document_label" />
</b-field>
</div>
<!-- Thumbnail Label -------------------------------- -->
<div>
<b-field
style="margin-top: 1.5rem; margin-bottom: 0rem;"
:addons="false"
:label="$i18n.getHelperTitle('collections', 'item_enable_thumbnail')">
&nbsp;
<b-switch
id="tainacan-checkbox-item-enable-thumbnail"
size="is-small"
true-value="yes"
false-value="no"
v-model="form.item_enable_thumbnail" />
<help-button
:title="$i18n.getHelperTitle('collections', 'item_enable_thumbnail')"
:message="$i18n.getHelperMessage('collections', 'item_enable_thumbnail')"/>
</b-field>
<b-field
v-if="form.item_enable_thumbnail === 'yes'"
:addons="false"
:label="$i18n.getHelperTitle('collections', 'item_thumbnail_label')">
<help-button
:title="$i18n.getHelperTitle('collections', 'item_thumbnail_label')"
:message="$i18n.getHelperMessage('collections', 'item_thumbnail_label')"/>
<b-input
id="tainacan-text-item-thumbnail-label"
v-model="form.item_thumbnail_label" />
</b-field>
</div>
<!-- Allow attachments ------------------------ -->
<div>
<b-field
style="margin-top: 1.5rem; margin-bottom: 0rem;"
:addons="false"
:label="$i18n.getHelperTitle('collections', 'item_enable_attachments')">
&nbsp;
<b-switch
id="tainacan-checkbox-item-enable-attachments"
size="is-small"
true-value="yes"
false-value="no"
v-model="form.item_enable_attachments" />
<help-button
:title="$i18n.getHelperTitle('collections', 'item_enable_attachments')"
:message="$i18n.getHelperMessage('collections', 'item_enable_attachments')"/>
</b-field>
<!-- Attachments Label -------------------------------- -->
<b-field
v-if="form.item_enable_attachments === 'yes'"
:addons="false"
:label="$i18n.getHelperTitle('collections', 'item_attachment_label')">
<help-button
:title="$i18n.getHelperTitle('collections', 'item_attachment_label')"
:message="$i18n.getHelperMessage('collections', 'item_attachment_label')"/>
<b-input
id="tainacan-text-item-attachment-label-singular"
v-model="form.item_attachment_label" />
</b-field>
</div>
<!-- Features related to how metadata are shown in the item edition form -------------------------------- -->
<b-field
:addons="false"
:label="$i18n.get('label_metadata_related_features')">
<div class="options-checkboxes">
<b-checkbox
v-model="form.item_enable_metadata_collapses"
true-value="yes"
false-value="no">
{{ $i18n.getHelperTitle('collections', 'item_enable_metadata_collapses') }}
</b-checkbox>
<b-checkbox
v-model="form.item_enable_metadata_focus_mode"
true-value="yes"
false-value="no">
{{ $i18n.getHelperTitle('collections', 'item_enable_metadata_focus_mode') }}
</b-checkbox>
<b-checkbox
v-model="form.item_enable_metadata_required_filter"
true-value="yes"
false-value="no">
{{ $i18n.getHelperTitle('collections', 'item_enable_metadata_required_filter') }}
</b-checkbox>
<b-checkbox
v-model="form.item_enable_metadata_searchbar"
true-value="yes"
false-value="no">
{{ $i18n.getHelperTitle('collections', 'item_enable_metadata_searchbar') }}
</b-checkbox>
<b-checkbox
v-model="form.item_enable_metadata_enumeration"
true-value="yes"
false-value="no">
{{ $i18n.getHelperTitle('collections', 'item_enable_metadata_enumeration') }}
</b-checkbox>
</div>
</b-field>
<!-- Comment Status ------------------------ -->
<b-field
:addons="false"
@ -238,6 +412,27 @@
:message="$i18n.getHelperMessage('collections', 'allow_comments')"/>
</b-field>
</div>
</transition>
<!-- Item submission options ------------------------ -->
<div
@click="showItemSubmissionOptions = !showItemSubmissionOptions;"
class="collection-form-section">
<span class="icon">
<i
class="tainacan-icon"
:class="showItemSubmissionOptions ? 'tainacan-icon-arrowdown' : 'tainacan-icon-arrowright'" />
</span>
<strong>{{ $i18n.get('label_item_submission_options') }}</strong>
<hr>
</div>
<transition name="filter-item">
<div
v-show="showItemSubmissionOptions"
class="options-columns">
<!-- Allows Submissions ------------------------ -->
<b-field
:addons="false"
@ -259,7 +454,7 @@
<transition name="filter-item">
<div
v-if="form.allows_submission === 'yes'"
class="item-submission-options">
class="item-submission-options field">
<!-- Allows Submissions by anonynmous user ------------------------ -->
<b-field
@ -288,7 +483,7 @@
<help-button
:title="$i18n.getHelperTitle('collections', 'submission_default_status')"
:message="$i18n.getHelperMessage('collections', 'submission_default_status')"/>
<div class="status-radios">
<div class="options-checkboxes">
<b-radio
v-model="form.submission_default_status"
v-for="(statusOption, index) of $statusHelper.getStatuses().filter((status) => status.slug != 'trash')"
@ -336,6 +531,9 @@
</div>
</transition>
</div>
</transition>
<!-- Hook for extra Form options -->
<template v-if="hasEndLeftForm">
<form
@ -510,6 +708,7 @@
<help-button
:title="$i18n.getHelperTitle('collections', 'cover_page_id')"
:message="$i18n.getHelperMessage('collections', 'cover_page_id')"/>
<template v-if="form.enable_cover_page == 'yes'">
<b-autocomplete
id="tainacan-text-cover-page"
:placeholder="$i18n.get('instruction_cover_page')"
@ -517,16 +716,15 @@
v-model="coverPageTitle"
@select="onSelectCoverPage($event)"
:loading="isFetchingPages"
@update:model-value="fecthCoverPages"
@input="fecthCoverPages"
@focus="clearErrors('cover_page_id')"
v-if="coverPage == undefined || coverPage.title == undefined"
:disabled="form.enable_cover_page != 'yes'"
check-infinite-scroll
@infinite-scroll="fetchMoreCoverPages">
<template #default="props">
<template slot-scope="props">
{{ props.option.title.rendered }}
</template>
<template #empty>{{ $i18n.get('info_no_page_found') }}</template>
<template slot="empty">{{ $i18n.get('info_no_page_found') }}</template>
</b-autocomplete>
<div
@ -564,7 +762,7 @@
popperClass: ['tainacan-tooltip', 'tooltip']
}"
class="icon is-small">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-see"/>
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-openurl"/>
</span>
</a>
&nbsp;&nbsp;
@ -593,7 +791,9 @@
<span class="icon is-small">
<i class="tainacan-icon tainacan-icon-add"/>
</span>
{{ $i18n.get('label_create_new_page') }}</a>
{{ $i18n.get('label_create_new_page') }}
</a>
</template>
</b-field>
<!-- Parent Collection -------------------------------- -->
@ -725,7 +925,34 @@ export default {
submission_default_status: 'draft',
submission_anonymous_user: 'no',
hide_items_thumbnail_on_lists: '',
submission_use_recaptcha: 'no'
submission_use_recaptcha: 'no',
item_enabled_document_types: {
attachment: {
enabled: 'yes',
label: this.$i18n.get( 'File', 'tainacan'),
icon: 'attachments'
},
url: {
enabled: 'yes',
label: this.$i18n.get( 'URL', 'tainacan'),
icon: 'url'
},
text: {
enabled: 'yes',
label: this.$i18n.get( 'Text', 'tainacan'),
icon: 'text'
}
},
item_document_label: this.$i18n.get( 'Document', 'tainacan' ),
item_thumbnail_label: this.$i18n.get( 'Thumbnail', 'tainacan' ),
item_enable_thumbnail: 'yes',
item_attachment_label: this.$i18n.get( 'Attachments', 'tainacan' ),
item_enable_attachments: 'yes',
item_enable_metadata_focus_mode: 'yes',
item_enable_metadata_required_filter: 'yes',
item_enable_metadata_searchbar: 'yes',
item_enable_metadata_collapses: 'yes',
item_enable_metadata_enumeration: 'yes',
},
thumbnail: {},
cover: {},
@ -756,7 +983,10 @@ export default {
metadataSearchCancel: undefined,
isLoadingMetadata: true,
sortingMetadata: [],
localDefaultOrderBy: 'date'
localDefaultOrderBy: 'date',
showItemsListOptions: true,
showItemEditionFormOptions: false,
showItemSubmissionOptions: false
}
},
computed: {
@ -846,6 +1076,17 @@ export default {
this.form.submission_default_status = this.collection.submission_default_status;
this.form.submission_use_recaptcha = this.collection.submission_use_recaptcha;
this.form.hide_items_thumbnail_on_lists = this.collection.hide_items_thumbnail_on_lists;
this.form.item_enabled_document_types = this.collection.item_enabled_document_types;
this.form.item_document_label = this.collection.item_document_label;
this.form.item_thumbnail_label = this.collection.item_thumbnail_label;
this.form.item_enable_thumbnail = this.collection.item_enable_thumbnail;
this.form.item_attachment_label = this.collection.item_attachment_label;
this.form.item_enable_attachments = this.collection.item_enable_attachments;
this.form.item_enable_metadata_focus_mode = this.collection.item_enable_metadata_focus_mode;
this.form.item_enable_metadata_required_filter = this.collection.item_enable_metadata_required_filter;
this.form.item_enable_metadata_searchbar = this.collection.item_enable_metadata_searchbar;
this.form.item_enable_metadata_collapses = this.collection.item_enable_metadata_collapses;
this.form.item_enable_metadata_enumeration = this.collection.item_enable_metadata_enumeration;
// Generates CoverPage from current cover_page_id info
if (this.form.cover_page_id != undefined && this.form.cover_page_id != '') {
@ -956,7 +1197,18 @@ export default {
submission_default_status: this.form.submission_default_status,
submission_use_recaptcha: this.form.submission_use_recaptcha,
allow_comments: this.form.allow_comments,
hide_items_thumbnail_on_lists: this.form.hide_items_thumbnail_on_lists
hide_items_thumbnail_on_lists: this.form.hide_items_thumbnail_on_lists,
item_enabled_document_types: this.form.item_enabled_document_types,
item_document_label: this.form.item_document_label,
item_thumbnail_label: this.form.item_thumbnail_label,
item_enable_thumbnail: this.form.item_enable_thumbnail,
item_attachment_label: this.form.item_attachment_label,
item_enable_attachments: this.form.item_enable_attachments,
item_enable_metadata_focus_mode: this.form.item_enable_metadata_focus_mode,
item_enable_metadata_required_filter: this.form.item_enable_metadata_required_filter,
item_enable_metadata_searchbar: this.form.item_enable_metadata_searchbar,
item_enable_metadata_collapses: this.form.item_enable_metadata_collapses,
item_enable_metadata_enumeration: this.form.item_enable_metadata_enumeration,
};
this.fillExtraFormData(data);
@ -985,6 +1237,17 @@ export default {
this.form.submission_default_status = this.collection.submission_default_status;
this.form.submission_use_recaptcha = this.collection.submission_use_recaptcha;
this.form.hide_items_thumbnail_on_lists = this.collection.hide_items_thumbnail_on_lists;
this.form.item_enabled_document_types = this.collection.item_enabled_document_types;
this.form.item_document_label = this.collection.item_document_label;
this.form.item_thumbnail_label = this.collection.item_thumbnail_label;
this.form.item_enable_thumbnail = this.collection.item_enable_thumbnail;
this.form.item_attachment_label = this.collection.item_attachment_label;
this.form.item_enable_attachments = this.collection.item_enable_attachments;
this.form.item_enable_metadata_focus_mode = this.collection.item_enable_metadata_focus_mode;
this.form.item_enable_metadata_required_filter = this.collection.item_enable_metadata_required_filter;
this.form.item_enable_metadata_searchbar = this.collection.item_enable_metadata_searchbar;
this.form.item_enable_metadata_collapses = this.collection.item_enable_metadata_collapses;
this.form.item_enable_metadata_enumeration = this.collection.item_enable_metadata_enumeration;
this.isLoading = false;
this.formErrorMessage = '';
@ -1045,6 +1308,17 @@ export default {
this.form.submission_default_status = this.collection.submission_default_status;
this.form.submission_use_recaptcha = this.collection.submission_use_recaptcha;
this.form.hide_items_thumbnail_on_lists = this.collection.hide_items_thumbnail_on_lists;
this.form.item_enabled_document_types = this.collection.item_enabled_document_types;
this.form.item_document_label = this.collection.item_document_label;
this.form.item_thumbnail_label = this.collection.item_thumbnail_label;
this.form.item_enable_thumbnail = this.collection.item_enable_thumbnail;
this.form.item_attachment_label = this.collection.item_attachment_label;
this.form.item_enable_attachments = this.collection.item_enable_attachments;
this.form.item_enable_metadata_focus_mode = this.collection.item_enable_metadata_focus_mode;
this.form.item_enable_metadata_required_filter = this.collection.item_enable_metadata_required_filter;
this.form.item_enable_metadata_searchbar = this.collection.item_enable_metadata_searchbar;
this.form.item_enable_metadata_collapses = this.collection.item_enable_metadata_collapses;
this.form.item_enable_metadata_enumeration = this.collection.item_enable_metadata_enumeration;
// Pre-fill status with publish to incentivate it
this.form.status = 'publish';
@ -1329,6 +1603,72 @@ export default {
color: var(--tainacan-white) !important;
}
}
.collection-form-section {
margin: 1.5em 0 0.5em -0.5em;
position: relative;
cursor: pointer;
.icon {
background: var(--tainacan-background-color);
z-index: 1;
position: relative;
}
strong {
background: var(--tainacan-background-color);
color: var(--tainacan-gray4);
font-size: 0.875em;
z-index: 1;
position: relative;
padding-right: 12px;
}
hr {
position: absolute;
top: -0.75em;
width: calc(100% - 42px);
height: 1px;
background-color: var(--tainacan-gray2);
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;
}
}
}
.options-columns {
margin-left: 0.25rem;
padding-left: 1.25em;
padding-right: 0.25em;
padding-bottom: 1.25em;border-left: 1px solid var(--tainacan-gray2);
& .field,
&>div {
break-inside: avoid;
}
&>div:not(.field) {
-moz-column-count: 2;
-moz-column-gap: 0;
-moz-column-rule: 1px solid var(--tainacan-gray1);
-webkit-column-count: 2;
-webkit-column-gap: 0;
-webkit-column-rule: 1px solid var(--tainacan-gray1);
column-count: 2;
column-gap: 4em;
column-rule: 1px solid var(--tainacan-gray1);
margin-bottom: 1.125rem;
}
}
.header-field {
padding-top: 1px;
@ -1442,8 +1782,23 @@ export default {
}
.status-radios {
display: flex;
margin: 5px 0;
.control-lable {
.control-label {
display: flex;
align-items: center;
}
}
.options-checkboxes {
display: flex;
margin: 5px 0;
flex-wrap: wrap;
gap: 0.5rem;
justify-content: space-between;
:deep(.b-checkbox.checkbox) {
width: auto
}
.control-label {
display: flex;
align-items: center;
}
@ -1474,7 +1829,7 @@ export default {
}
.item-submission-options {
padding-left: 1em;
padding-top: 1.25em;
padding-top: 1.0em;
margin-top: -1.5em;
border-left: 1px solid var(--tainacan-gray2);
}

View File

@ -173,6 +173,28 @@
</b-switch>
</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
:errors="formErrors['filter_type_options']"
v-if="(form.filter_type_object && form.filter_type_object.form_component) || form.edit_form == ''"
@ -280,11 +302,13 @@ export default {
this.isLoading = true;
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';
}
if (this.form['begin_with_filter_collapsed'] === undefined)
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 })
.then(() => {
@ -313,13 +337,15 @@ export default {
let formObj = {};
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';
else
formObj[key] = value;
}
if (formObj['begin_with_filter_collapsed'] === undefined)
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.isLoading = true;

View File

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

View File

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

View File

@ -142,19 +142,19 @@
<span>{{ $i18n.get('label_all_metadata') }}</span>
</button>
<button
v-if="!$adminOptions.hideItemEditionDocument"
v-if="shouldDisplayItemEditionDocument || shouldDisplayItemEditionThumbnail"
@click="activeTab = 'document'; isMobileSubheaderOpen = false;">
<span><i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-item" /></span>
<span>{{ $i18n.get('label_document_and_thumbnail') }}</span>
</button>
<button
v-if="!$adminOptions.hideItemEditionAttachments"
v-if="shouldDisplayItemEditionAttachments"
@click="activeTab = 'attachments'; isMobileSubheaderOpen = false;">
<span><i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-attachments" /></span>
<span>{{ $i18n.get('label_all_attachments') }}</span>
</button>
<button
v-if="!$adminOptions.hideItemEditionRequiredOnlySwitch"
v-if="!$adminOptions.hideItemEditionRequiredOnlySwitch && (collection && collection.item_enable_metadata_required_filter === 'yes')"
@click="showOnlyRequiredMetadata = true; isMobileSubheaderOpen = false;">
<span><i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-metadata" /></span>
<span>{{ $i18n.get('label_only_required_metadata') }}</span>
@ -177,8 +177,8 @@
<div
class="column main-column"
:class="
(( (!$adminOptions.hideItemEditionDocument || !$adminOptions.hideItemEditionThumbnail) && !$adminOptions.itemEditionDocumentInsideTabs) ||
(!$adminOptions.hideItemEditionAttachments && !$adminOptions.itemEditionAttachmentsInsideTabs)) ? 'is-7' : 'is-12'">
(( (shouldDisplayItemEditionDocument || shouldDisplayItemEditionThumbnail) && !$adminOptions.itemEditionDocumentInsideTabs) ||
(shouldDisplayItemEditionAttachments && !$adminOptions.itemEditionAttachmentsInsideTabs)) ? 'is-7' : 'is-12'">
<!-- Hook for extra Form options -->
<template v-if="hasBeginRightForm">
@ -261,10 +261,10 @@
<!-- Metadata navigation Progress -->
<div
v-if="isMetadataNavigation && itemMetadata && itemMetadata.length > 3"
v-if="isMetadataNavigation"
class="sequence-progress-background" />
<div
v-if="isMetadataNavigation && focusedMetadatum !== false && itemMetadata && itemMetadata.length > 3"
v-if="isMetadataNavigation && focusedMetadatum !== false"
:style="{ width: ((focusedMetadatum + 1)/itemMetadata.length)*100 + '%' }"
class="sequence-progress" />
@ -286,7 +286,7 @@
class="header-item metadata-navigation"
:style="$adminOptions.hideItemEditionCollapses ? 'padding-left: 0.35em !important;' : ''">
<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 });"
class="collapse-all has-text-secondary"
size="is-small">
@ -339,7 +339,7 @@
</span>
<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"
:style="'font-size: 0.625em;' + (isMobileScreen ? 'margin-right: 2rem;' : '')"
size="is-small"
@ -348,7 +348,7 @@
</b-switch>
<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">
<b-input
v-if="!isMobileScreen || openMetadataNameFilter"
@ -397,6 +397,12 @@
<span class="icon has-text-gray4">
<i class="tainacan-icon tainacan-icon-metadata"/>
</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;
<span
v-if="metadataSection.metadata_object_list && metadataSection.metadata_object_list.length"
@ -433,11 +439,12 @@
:item-metadatum="itemMetadatum"
:metadata-name-filter-string="metadataNameFilterString"
: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-help-buttons="false"
:help-info-bellow-label="false"
: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-focused="focusedMetadatum === index"
:is-metadata-navigation="isMetadataNavigation"
@ -496,6 +503,7 @@
<item-document-edition-form
:item="item"
:form="form"
:collection="collection"
@onSetDocument="setDocument"
@onRemoveDocument="removeDocument"
@onSetFileDocument="setFileDocument"
@ -504,6 +512,7 @@
<item-thumbnail-edition-form
:item="item"
:form="form"
:collection="collection"
:is-loading="isLoading"
@onDeleteThumbnail="deleteThumbnail"
@onUpdateThumbnailAlt="($event) => onUpdateThumbnailAlt($event)"
@ -512,7 +521,7 @@
<!-- Attachments on mobile modal -->
<div
v-if="activeTab === 'attachments' && $adminOptions.itemEditionAttachmentsInsideTabs"
v-if="activeTab === 'attachments' && shouldDisplayItemEditionAttachments && $adminOptions.itemEditionAttachmentsInsideTabs"
class="tab-item"
role="tabpanel"
aria-labelledby="attachments-tab-label"
@ -520,6 +529,7 @@
<item-attachments-edition-form
:item="item"
:form="form"
:collection="collection"
:is-loading="isLoading"
:total-attachments="totalAttachments"
:should-load-attachments="shouldLoadAttachments"
@ -533,8 +543,8 @@
</div>
<div
v-if="( (!$adminOptions.hideItemEditionDocument || !$adminOptions.hideItemEditionThumbnail) && !$adminOptions.itemEditionDocumentInsideTabs) ||
(!$adminOptions.hideItemEditionAttachments && !$adminOptions.itemEditionAttachmentsInsideTabs)"
v-if="( (shouldDisplayItemEditionDocument || shouldDisplayItemEditionThumbnail) && !$adminOptions.itemEditionDocumentInsideTabs) ||
(shouldDisplayItemEditionAttachments && !$adminOptions.itemEditionAttachmentsInsideTabs)"
class="column is-5">
<div
@ -551,33 +561,37 @@
<!-- Document -------------------------------- -->
<item-document-edition-form
v-if="!$adminOptions.itemEditionDocumentInsideTabs"
v-if="shouldDisplayItemEditionDocument && !$adminOptions.itemEditionDocumentInsideTabs"
:item="item"
:form="form"
:collection="collection"
@onSetDocument="setDocument"
@onRemoveDocument="removeDocument"
@onSetFileDocument="setFileDocument"
@onSetTextDocument="setTextDocument"
@onSetURLDocument="setURLDocument" />
<hr>
<hr v-if="shouldDisplayItemEditionDocument && shouldDisplayItemEditionThumbnail">
<!-- Thumbnail -------------------------------- -->
<item-thumbnail-edition-form
v-if="!$adminOptions.itemEditionDocumentInsideTabs"
v-if="shouldDisplayItemEditionThumbnail && !$adminOptions.itemEditionDocumentInsideTabs"
:item="item"
:form="form"
:collection="collection"
:is-loading="isLoading"
@onDeleteThumbnail="deleteThumbnail"
@onUpdateThumbnailAlt="($event) => onUpdateThumbnailAlt($event)"
@openThumbnailMediaFrame="thumbnailMediaFrame.openFrame($event)" />
<hr v-if="!$adminOptions.itemEditionAttachmentsInsideTabs || hasEndLeftForm">
<hr v-if="(shouldDisplayItemEditionAttachments && !$adminOptions.itemEditionAttachmentsInsideTabs) || hasEndLeftForm">
<!-- Attachments -->
<item-attachments-edition-form
v-if="!$adminOptions.itemEditionAttachmentsInsideTabs"
v-if="shouldDisplayItemEditionAttachments && !$adminOptions.itemEditionAttachmentsInsideTabs"
:item="item"
:form="form"
:collection="collection"
:is-loading="isLoading"
:total-attachments="totalAttachments"
:should-load-attachments="shouldLoadAttachments"
@ -831,7 +845,7 @@ export default {
},
itemMetadata() {
const realItemMetadata = JSON.parse(JSON.stringify(this.getItemMetadata()));
console.log(realItemMetadata)
const tweakedItemMetadata = realItemMetadata.map((anItemMetadatum) => {
// We need this because repository level metadata have an array of section IDs
@ -882,18 +896,18 @@ export default {
name: this.$i18n.get('metadata'),
total: this.itemMetadata.length
}];
if ( this.$adminOptions.itemEditionDocumentInsideTabs && (!this.$adminOptions.hideItemEditionDocument || !this.$adminOptions.hideItemEditionThumbnail) ) {
if ( this.$adminOptions.itemEditionDocumentInsideTabs && (this.shouldDisplayItemEditionDocument || this.shouldDisplayItemEditionThumbnail) ) {
pageTabs.push({
slug: 'document',
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({
slug: '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
});
}
@ -911,6 +925,21 @@ export default {
if (!this.isMetadataNavigation || !this.itemMetadata[this.focusedMetadatum])
return false;
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: {
@ -1326,7 +1355,7 @@ export default {
if (currentItemMetadatum) {
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];
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) {
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">
<i class="tainacan-icon tainacan-icon-image"/>
</span>
{{ $i18n.get('label_thumbnail') }}
{{ collection && collection.item_thumbnail_label ? collection.item_thumbnail_label : $i18n.get('label_thumbnail') }}
</label>
<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')"/>
</div>
@ -104,6 +104,7 @@ export default {
},
props: {
item: Object,
collection: Object,
form: Object
},
emits: [

View File

@ -10,7 +10,12 @@
v-if="form && Object.keys(form).length"
class="tainacan-modal-content">
<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>
</div>
<div class="tainacan-form">
@ -179,8 +184,9 @@
:extra-classes="isRepositoryLevel ? 'tainacan-repository-tooltip' : ''" />
</label>
<b-select
v-model="selectedConditionalMetadatum"
:placeholder="$i18n.get('label_select_metadatum')">
v-model="selectedConditionalMetadatumId"
:placeholder="$i18n.get('label_select_metadatum')"
@input="reloadConditionalValueComponent()">
<option
v-for="conditionalMetadatum of availableConditionalMetadata"
:key="conditionalMetadatum.id"
@ -192,22 +198,23 @@
</transition>
<transition name="filter-item">
<b-field
v-if="isConditionalSection && selectedConditionalMetadatum"
v-if="isConditionalSection && selectedConditionalMetadatumId && selectedConditionalMetadatum && selectedConditionalMetadatum.name"
:addons="false"
:type="formErrors['conditional_section_rules'] != undefined ? 'is-danger' : ''"
:message="formErrors['conditional_section_rules'] != undefined ? formErrors['conditional_section_rules'] : ''">
<label class="label is-inline">
{{ availableConditionalMetadata.find((availableMetadatum) => availableMetadatum.id == selectedConditionalMetadatum).name }}
{{ selectedConditionalMetadatum.name }}
</label>
<div style="overflow-y: auto; overflow-x: hidden; max-height: 100px;">
<b-checkbox
v-model="selectedConditionalValue"
v-for="(conditionalValue, conditionalValueIndex) of availableConditionalMetadata.find((availableMetadatum) => availableMetadatum.id == selectedConditionalMetadatum).metadata_type_object.options.options.split('\n')"
:key="conditionalValueIndex"
:native-value="conditionalValue">
{{ conditionalValue }}
</b-checkbox>
</div>
<component
v-if="shouldUpdateConditionalValue"
:is="selectedConditionalMetadatum.metadata_type_object.component"
:forced-component-type="selectedConditionalMetadatum.metadata_type_object.component.includes('taxonomy') ? 'tainacan-taxonomy-tag-input' : ''"
:item-metadatum="{ metadatum: selectedConditionalMetadatum }"
:value="Array.isArray(selectedConditionalValue) ? selectedConditionalValue[0] : selectedConditionalValue"
:allow-new="false"
:maxtags="1"
@input="selectConditionalValue"
/>
</b-field>
</transition>
</div>
@ -271,9 +278,10 @@
closedByForm: false,
entityName: 'metadataSection',
isUpdating: false,
selectedConditionalMetadatum: undefined,
selectedConditionalMetadatumId: undefined,
selectedConditionalValue: [],
hideConditionalSectionSettings: false
hideConditionalSectionSettings: false,
shouldUpdateConditionalValue: true
}
},
computed: {
@ -286,13 +294,16 @@
const availableMetadata = [];
for (let aMetadataSection of otherMetadataSections)
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() {
return this.form.is_conditional_section == 'yes';
}
},
selectedConditionalMetadatum() {
return this.availableConditionalMetadata.find(aMetadatum => aMetadatum.id == this.selectedConditionalMetadatumId)
},
},
created() {
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 ) {
const conditionalMetadatum = Object.keys(this.form.conditional_section_rules)[0];
this.selectedConditionalMetadatum = conditionalMetadatum;
this.selectedConditionalMetadatumId = conditionalMetadatum;
this.selectedConditionalValue = this.form.conditional_section_rules[conditionalMetadatum];
}
@ -321,10 +332,9 @@
'updateMetadataSection'
]),
saveEdition(metadataSection) {
if ( this.form.is_conditional_section == 'yes' && this.selectedConditionalMetadatum && this.selectedConditionalValue ) {
if ( this.form.is_conditional_section == 'yes' && this.selectedConditionalMetadatumId && this.selectedConditionalValue ) {
this.form.conditional_section_rules = {}
this.form.conditional_section_rules[this.selectedConditionalMetadatum] = this.selectedConditionalValue;
this.form.conditional_section_rules[this.selectedConditionalMetadatumId] = this.selectedConditionalValue;
} else
this.form.conditional_section_rules = null;
@ -364,6 +374,15 @@
this.closedByForm = true;
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>
@ -441,6 +460,18 @@
height: 1px;
background-color: var(--tainacan-gray2);
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 {
background-color: var(--tainacan-gray1);
position: sticky;

View File

@ -10,7 +10,12 @@
v-if="form && Object.keys(form).length"
class="tainacan-modal-content">
<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
class="back-link"
@click="onEditionCanceled()">
@ -616,6 +621,18 @@
height: 1px;
background-color: var(--tainacan-gray2);
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"
:href="themeTaxonomiesURL + taxonomy.slug">
<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>{{ $i18n.get('label_taxonomy_page_on_website') }}</span>
</a>
@ -556,7 +556,7 @@
.status-radios {
display: flex;
}
.status-radios .control-lable {
.status-radios .control-label {
display: flex;
align-items: center;
}

View File

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

View File

@ -71,7 +71,7 @@
@update:model-value="emitOnlyYear($event)"
v-model="yearsOnlyValue"/> -->
<b-datepicker
position="is-bottom-left"
position="is-bottom-right"
:aria-labelledby="'filter-label-id-' + filter.id"
:placeholder="$i18n.get('instruction_select_a_date')"
v-model="value"

View File

@ -236,27 +236,12 @@
}
.taginput-container {
border-radius: 1px !important;
border-radius: var(--tainacan-input-border-radius, 1px) !important;
box-shadow: none !important;
transition: background-color 0.1s;
}
.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 {
display: none !important;
}

View File

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

View File

@ -18,7 +18,7 @@
<span
v-if="form.document == attachment.id"
class="file-attachment-document-tag">
{{ $i18n.get('label_document') }}
{{ collection && collection.item_document_label ? collection.item_document_label : $i18n.get('label_document') }}
</span>
<file-item
:show-name="true"
@ -52,7 +52,7 @@
<i class="tainacan-icon tainacan-icon-30px tainacan-icon-attachments"/>
</span>
</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>
</section>
</div>
@ -63,7 +63,7 @@
v-if="attachments.length > 0">
<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) +
$i18n.get('info_to') +
getLastAttachmentsNumber() +
@ -99,6 +99,7 @@
props: {
item: Object,
form: Object,
collection: Object,
shouldLoadAttachments: Boolean,
isEditable: Boolean,
},

View File

@ -246,7 +246,7 @@
popperClass: ['tainacan-tooltip', 'tooltip']
}"
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>
</a>
</li>

View File

@ -8,8 +8,10 @@
<div class="field select-all is-pulled-left">
<span>
<b-checkbox
@click="selectAllCollectionsOnPage()"
:model-value="allCollectionsOnPageSelected">{{ $i18n.get('label_select_all_collections_page') }}</b-checkbox>
@click.native="selectAllCollectionsOnPage()"
:model-value="allCollectionsOnPageSelected">
{{ $i18n.get('label_select_all_collections_page') }}
</b-checkbox>
</span>
</div>
<div class="field is-pulled-right">
@ -348,6 +350,24 @@
class="tainacan-icon tainacan-icon-1-25em"/>
</span>
</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>
</td>
</tr>
@ -561,7 +581,7 @@ export default {
.selection-control {
padding: 6px 0px 0px 12px;
background: var(--tainacan-white);
background: var(--tainacan-background-color);
height: 40px;
.select-all {

View File

@ -302,6 +302,25 @@
class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/>
</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>
</div>
</div>
@ -447,6 +466,25 @@
class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/>
</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>
</div>
</div>
</li>
@ -578,6 +616,25 @@
class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/>
</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>
</div>
<!-- Remaining metadata -->
@ -801,6 +858,25 @@
class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/>
</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>
</div>
<!-- Remaining metadata -->
@ -1149,6 +1225,25 @@
class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/>
</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>
</div>
</td>
</tr>
@ -1304,6 +1399,25 @@
class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/>
</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>
</div>
<!-- Remaining metadata -->
@ -1778,6 +1892,25 @@
class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/>
</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>
</div>
<!-- Remaining metadata -->
@ -2239,10 +2372,9 @@ export default {
collectionId: this.collectionId,
itemId: itemId,
onConfirm: (newItems) => {
if (newItems != null && newItems != undefined && newItems.length > 0) {
if (newItems != null && newItems != undefined && newItems.length > 0)
this.$eventBusSearch.loadItems();
}
}
},
trapFocus: true,
customClass: 'tainacan-modal',
@ -2271,9 +2403,7 @@ export default {
this.untrashItemsInBulk({
collectionId: this.collectionId,
groupId: groupId
}).then(() => {
this.$eventBusSearch.loadItems();
});
}).then(() => this.$eventBusSearch.loadItems() );
});
}
},
@ -2296,9 +2426,7 @@ export default {
this.deleteItem({
itemId: itemId,
isPermanently: this.isOnTrash
}).then(() => {
this.$eventBusSearch.loadItems();
});
}).then(() => this.$eventBusSearch.loadItems() );
}
},
trapFocus: true,
@ -2569,7 +2697,7 @@ export default {
.selection-control {
margin-bottom: 6px;
padding: 6px 0px 0px 12px;
background: var(--tainacan-white);
background: var(--tainacan-background-color);
height: 40px;
display: flex;
align-items: center;

View File

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

View File

@ -9,8 +9,10 @@
<div class="field select-all is-pulled-left">
<span>
<b-checkbox
@click="selectAllOnPage()"
:model-value="allOnPageSelected">{{ $i18n.get('label_select_all_taxonomies_page') }}</b-checkbox>
@click.native="selectAllOnPage()"
:model-value="allOnPageSelected">
{{ $i18n.get('label_select_all_taxonomies_page') }}
</b-checkbox>
</span>
</div>
<div class="field is-pulled-right">
@ -234,6 +236,25 @@
class="has-text-secondary tainacan-icon tainacan-icon-1-25em"/>
</span>
</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>
</td>
</tr>
@ -262,7 +283,8 @@
selected: [],
allOnPageSelected: false,
isSelecting: false,
adminUrl: tainacan_plugin.admin_url
adminUrl: tainacan_plugin.admin_url,
themeTaxonomiesURL: tainacan_plugin.theme_taxonomy_list_url
}
},
computed: {
@ -421,7 +443,7 @@
.selection-control {
padding: 6px 0px 0px 12px;
background: var(--tainacan-white);
background: var(--tainacan-background-color);
height: 40px;
.select-all {

View File

@ -137,9 +137,23 @@
placement: 'bottom'
}"
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>
</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>
</label>
<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 ]);
errorMessage += ' ' + errors[0]['errors'][0]['name'];
this.$buefy.snackbar.open({
message: errorMessage,
message: this.$htmlSanitizer.sanitize(errorMessage),
type: 'is-danger',
position: 'is-bottom-right',
pauseOnHover: true,
@ -860,7 +874,10 @@ export default {
.tainacan-hierarchical-list-columns-container {
background-color: var(--tainacan-background-color);
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;
display: flex;
height: auto;

View File

@ -348,7 +348,10 @@ export default {
.tainacan-hierarchical-list-columns-container {
background-color: var(--tainacan-background-color);
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;
display: flex;
height: auto;

View File

@ -31,6 +31,12 @@
<i class="has-text-secondary tainacan-icon tainacan-icon-1-25em tainacan-icon-arrowdown" />
</span>
<label class="label has-tooltip">
<span
v-if="enumerateMetadatum"
style="opacity: 0.65;"
class="metadatum-section-enumeration">
{{ enumerateMetadatum }}.
</span>
{{ childItemMetadatum.metadatum.name }}
</label>
<span
@ -69,6 +75,7 @@
}"
:is-focused="(focusedGroupMetadatum === groupIndex) && (focusedChildMetadatum === childIndex)"
: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 }): ''"
@mousedown="isMetadataNavigation ? setMetadatumChildFocus({ groupIndex: groupIndex, childIndex: childIndex, scrollIntoView: false }) : ''"
@mobileSpecialFocus="setMetadatumChildFocus({ groupIndex: groupIndex, childIndex: childIndex, scrollIntoView: true })"
@ -129,6 +136,7 @@
metadataNameFilterString: '',
isMobileScreen: false,
isMetadataNavigation: false,
enumerateMetadatum: [Boolean|String],
isFocused: false
},
data() {
@ -161,7 +169,7 @@
},
watch: {
/* 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)
*/
'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())) {
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">
<?php echo esc_html($meta->get_metadatum()->get_name()); ?>
</h4>

View File

@ -19,11 +19,24 @@ class Core_Description extends Metadata_Type {
$this->set_core(true);
$this->set_related_mapped_prop('description');
$this->set_component('tainacan-textarea');
$this->set_form_component('tainacan-form-textarea');
$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_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
*/

View File

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

View File

@ -69,6 +69,32 @@
</button>
</div>
</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>
</template>
@ -81,15 +107,25 @@
data() {
return {
step: [Number, String],
min: [Number, null],
max: [Number, null],
showEditStepOptions: false
}
},
created() {
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: {
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,14 +1,16 @@
<template>
<b-input
<b-numberinput
: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) : '')"
:placeholder="itemMetadatum.metadatum.placeholder ? itemMetadatum.metadatum.placeholder : ''"
:model-value="value"
@update:model-value="onInput($event);"
@update:model-value="$event =>onInput($event)"
@blur="onBlur"
@focus="onMobileSpecialFocus"
type="number"
lang="en"
:min="getMin"
:max="getMax"
:step="getStep" />
</template>
@ -30,10 +32,26 @@
return this.itemMetadatum.metadatum.metadata_type_options.step;
else
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: {
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);
},
onBlur() {
@ -45,3 +63,10 @@
}
}
</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' => [
'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' ),
],
'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')"/>
</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>
</template>
@ -149,6 +164,7 @@
collectionMessage: '',
displayRelatedItemMetadata: [],
modelAcceptDraftItems: 'no',
modelAcceptOnlyItemsAuthoredByCurrentUser: 'no',
isMetaqueryRelationshipEnabled: tainacan_plugin && tainacan_plugin.tainacan_enable_relationship_metaquery == true ? tainacan_plugin.tainacan_enable_relationship_metaquery : false
}
},
@ -173,6 +189,7 @@
this.modelSearch = '';
this.modelDisplayInRelatedItems = 'no';
this.modelAcceptDraftItems = 'no';
this.modelAcceptOnlyItemsAuthoredByCurrentUser = 'no';
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.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.modelAcceptOnlyItemsAuthoredByCurrentUser = this.value && this.value.accept_only_items_authored_by_current_user ? this.value.accept_only_items_authored_by_current_user : 'no';
},
methods: {
setErrorsAttributes( type, message ){
@ -284,7 +302,8 @@
search: this.modelSearch,
display_in_related_items: this.modelDisplayInRelatedItems,
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

@ -54,7 +54,7 @@
<template
v-if="!isLoading"
#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
v-if="currentUserCanEditItems && (!$adminOptions.itemEditionMode || $adminOptions.allowItemEditionModalInsideModal)"
@ -212,6 +212,12 @@
this.itemMetadatum.metadatum &&
this.itemMetadatum.metadatum.metadata_type_options &&
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: {
@ -233,6 +239,7 @@
query['order'] = 'asc';
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 : '');
if ( this.isAcceptingDraftItems )
query['status'] = ['publish','private','draft'];
@ -400,6 +407,9 @@
if (this.isAcceptingDraftItems)
query['status'] = ['publish','private','draft'];
if ( this.isAcceptingOnlyItemsAuthoredByCurrentUser )
query['authorid'] = tainacan_plugin.user_data.ID;
if (this.selected.length > 0)
query['exclude'] = this.selected.map((item) => item.value);

View File

@ -71,6 +71,10 @@ class Relationship extends Metadata_Type {
'accept_draft_items' => [
'title' => __( 'List and accept draft items on the relation', '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 'accept_draft_items':
case 'accept_only_items_authored_by_current_user':
if ($option_value == 'yes')
$readable_option_value = __('Yes', 'tainacan');
else if ($option_value == 'no')
@ -177,13 +182,19 @@ class Relationship extends Metadata_Type {
// empty is ok
if ( !empty($this->get_option('display_in_related_items')) && !in_array($this->get_option('display_in_related_items'), ['yes', 'no']) ) {
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
if ( !empty($this->get_option('accept_draft_items')) && !in_array($this->get_option('accept_draft_items'), ['yes', 'no']) ) {
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

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

View File

@ -1,9 +1,8 @@
<template>
<div>
<taxonomy-tag-input
<tainacan-taxonomy-tag-input
v-if="getComponent == 'tainacan-taxonomy-tag-input'"
:disabled="disabled"
:is="getComponent"
:disabled="disabled || isFetchingTerms"
:maxtags="maxtags != undefined ? maxtags : (itemMetadatum.metadatum.multiple == 'yes' || allowNew === true ? (maxMultipleValues !== undefined ? maxMultipleValues : null) : '1')"
v-model:value="valueComponent"
:allow-select-to-create="allowSelectToCreate"
@ -47,10 +46,10 @@
&nbsp;{{ $i18n.get('label_create_new_term') }}
</a>
</div>
<template v-if="allowNewFromOptions && itemMetadatum.item">
<!-- Term creation modal, used on admin for a complete term creation -->
<b-modal
v-model="isTermCreationModalOpen"
:active.sync="isTermCreationModalOpen"
:width="768"
trap-focus
aria-role="dialog"
@ -59,6 +58,8 @@
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 : '' }"
@ -71,6 +72,8 @@
<!-- Term creation panel, used on item submission block for a simpler term creation -->
<transition name="filter-item">
<term-creation-panel
:metadatum-id="itemMetadatum.metadatum.id"
:item-id="itemMetadatum.item.id"
:is-hierarchical="isHierarchical"
v-if="isTermCreationPanelOpen"
:taxonomy-id="taxonomyId"
@ -79,17 +82,19 @@
@onEditionCanceled="() => isTermCreationPanelOpen = false"
@onErrorFound="($event) => $console.log('Form with errors: ' + $event)" />
</transition>
</template>
</div>
</template>
<script>
import TaxonomyTagInput from './TaxonomyTaginput.vue';
import TainacanTaxonomyTagInput from './TaxonomyTaginput.vue';
import CheckboxRadioMetadataInput from '../../other/checkbox-radio-metadata-input.vue';
import { tainacan as axios } from '../../../js/axios.js';
import { mapActions } from 'vuex';
export default {
components: {
TaxonomyTagInput,
TainacanTaxonomyTagInput,
CheckboxRadioMetadataInput
},
props: {
@ -99,7 +104,6 @@
forcedComponentType: '',
maxtags: '',
allowNew: false,
allowSelectToCreate: false,
isMobileScreen: false,
},
emits: [
@ -117,7 +121,8 @@
isTermCreationModalOpen: false,
isTermCreationPanelOpen: false,
newTermName: '',
allowNewFromOptions: false
allowNewFromOptions: false,
isFetchingTerms: false
}
},
computed: {
@ -170,20 +175,54 @@
this.taxonomyId = metadata_type_options.taxonomy_id;
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();
},
methods: {
...mapActions('taxonomy', [
'fetchTerms'
]),
getTermsId() {
let values = [];
if ( this.value && this.itemMetadatum.metadatum && this.getComponent != 'tainacan-taxonomy-tag-input' ) {
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;
} 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 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) {

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

View File

@ -14,6 +14,19 @@
:title="$i18n.getHelperTitle('tainacan-text', 'display_suggestions')"
:message="$i18n.getHelperMessage('tainacan-text', 'display_suggestions')"/>
</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>
</template>
@ -25,16 +38,22 @@
emits: ['input'],
data() {
return {
displaySuggestions: String
displaySuggestions: String,
mask: String
}
},
created() {
this.displaySuggestions = this.value && this.value.display_suggestions ? this.value.display_suggestions : 'no';
this.mask = this.value && this.value.mask ? this.value.mask : '';
},
methods: {
onUpdateDisplaySuggestions(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>
<div>
<b-input
<div
v-if="!getDisplayAutocomplete"
class="control is-clearfix">
<input
class="input"
:disabled="disabled"
:id="'tainacan-item-metadatum_id-' + itemMetadatum.metadatum.id + (itemMetadatum.parent_meta_id ? ('_parent_meta_id-' + itemMetadatum.parent_meta_id) : '')"
:model-value="value"
:placeholder="itemMetadatum.metadatum.placeholder ? itemMetadatum.metadatum.placeholder : ''"
@update:model-value="onInput($event)"
@blur="onBlur"
@focus="onMobileSpecialFocus" />
@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
v-else
:disabled="disabled"
@ -44,8 +50,12 @@
<script>
import { isCancel } from '../../../js/axios';
import { dynamicFilterTypeMixin } from '../../../js/filter-types-mixin';
import { IMaskDirective } from 'vue-imask';
export default {
directives: {
imask: IMaskDirective
},
mixins: [dynamicFilterTypeMixin],
props: {
itemMetadatum: Object,
@ -77,6 +87,15 @@
return this.itemMetadatum.metadatum.metadata_type_options.display_suggestions == 'yes';
else
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() {

View File

@ -35,6 +35,13 @@ class Text extends Metadata_Type {
'display_suggestions' => [
'title' => __( 'Display suggestions', '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>
<b-input
: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) : '')"
:placeholder="itemMetadatum.metadatum.placeholder ? itemMetadatum.metadatum.placeholder : ''"
:model-value="value"
@update:model-value="onInput($event)"
@blur="onBlur"
type="textarea"
@focus="onMobileSpecialFocus" />
@focus="onMobileSpecialFocus"
:maxlength="getMaxlength" />
</template>
<script>
@ -22,8 +24,20 @@
'blur',
'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: {
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);
},
onBlur() {

View File

@ -15,6 +15,7 @@ class Textarea extends Metadata_Type {
parent::__construct();
$this->set_primitive_type('long_string');
$this->set_component('tainacan-textarea');
$this->set_form_component('tainacan-form-textarea');
$this->set_name( __('Textarea', 'tainacan') );
$this->set_description( __('A textarea with multiple lines', 'tainacan') );
$this->set_preview_template('
@ -27,6 +28,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() {
return '<p>';
}

View File

@ -95,7 +95,6 @@
:forced-component-type="bulkEditionProcedures[criterion].metadatum.metadata_type_object.component.includes('taxonomy') ? 'tainacan-taxonomy-tag-input' : ''"
:item-metadatum="{ metadatum: bulkEditionProcedures[criterion].metadatum }"
:allow-new="false"
:allow-select-to-create="false"
:maxtags="1"
:class="{'is-field-history': 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' : ''"
:item-metadatum="{ metadatum: bulkEditionProcedures[criterion].metadatum }"
:allow-new="false"
:allow-select-to-create="bulkEditionProcedures[criterion].metadatum.metadata_type_options.allow_new_terms === 'yes'"
:maxtags="1"
:class="{'is-field-history': bulkEditionProcedures[criterion].isDone}"
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' : ''"
:item-metadatum="{ metadatum: bulkEditionProcedures[criterion].metadatum }"
:allow-new="false"
:allow-select-to-create="bulkEditionProcedures[criterion].metadatum.metadata_type_options.allow_new_terms === 'yes'"
:maxtags="1"
:class="{ 'is-field-history': bulkEditionProcedures[criterion].isDone }"
class="tainacan-bulk-edition-field tainacan-bulk-edition-field-last"
@ -216,7 +213,7 @@
:style="{
marginRight: !bulkEditionProcedures[criterion].isDone && !bulkEditionProcedures[criterion].isExecuting ? '-7.4px': 0
}"
class="field buttons-r-bulk">
class="field bulk-last-field">
<button
v-if="!bulkEditionProcedures[criterion].isDone && !bulkEditionProcedures[criterion].isExecuting"
@ -646,7 +643,7 @@
padding-left: 0 !important;
}
.buttons-r-bulk {
.bulk-last-field {
margin-left: 0 !important;
justify-content: center !important;
}
@ -789,9 +786,28 @@
&:not(:first-child) {
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;
align-items: center;
height: 32px;

View File

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

View File

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

View File

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

View File

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

View File

@ -78,7 +78,7 @@
class="button"
id="view-collection-button">
<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 class="is-hidden-mobile">{{ $i18n.get('label_view_collection_on_website') }}</span>
</a>
@ -91,7 +91,7 @@
class="button"
id="view-repository-button--taxonomies">
<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 class="is-hidden-mobile">{{ $i18n.get('label_view_taxonomies_on_website') }}</span>
</a>
@ -104,7 +104,7 @@
class="button"
id="view-repository-button">
<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 class="is-hidden-mobile">{{ $i18n.get('label_view_collections_on_website') }}</span>
</a>
@ -174,7 +174,7 @@ export default {
padding-top: 10px;
padding-bottom: 10px;
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;
display: flex;
vertical-align: middle;

View File

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

View File

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

View File

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

View File

@ -9,6 +9,7 @@
v-for="(searchCriterion, index) in searchCriteria"
:key="index + '-' + searchCriterion.index + '-' + searchCriterion.type"
grouped
group-multiline
class="tainacan-form">
<!-- Metadata (Search criteria) -->
@ -98,7 +99,7 @@
</b-field>
<!-- 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]">
<b-input
v-if="getAdvancedSearchQueryCriterionMetadataType(searchCriterion.index) == 'int' || getAdvancedSearchQueryCriterionMetadataType(searchCriterion.index) == 'float'"
@ -144,7 +145,7 @@
<div class="field">
<button
@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"
:aria-label="$i18n.get('remove_search_criterion')">
<span
@ -655,11 +656,11 @@
border: 1px solid var(--tainacan-input-border-color);
border-radius: 1px;
transition: height 0.2s ease;
}
.tnc-advanced-search-container {
position: relative;
padding: 1.25em;
border-radius: var(--tainacan-dropdownmenu-border-radius, 0px);
h3 {
font-size: 1em !important;
@ -692,7 +693,21 @@
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) {
border-left: none;
border-right: none;
.tnc-advanced-search-container {
padding-right: 0;
padding-left: 0;
}
.is-12>.columns {
flex-wrap: wrap;
}
@ -701,7 +716,6 @@
flex-basis: 100%;
}
}
}
</style>

View File

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

View File

@ -217,7 +217,7 @@
}
.filter-tag {
border-radius: 3px;
border-radius: 4px;
padding: 3px 8px 2px 8px;
position: relative;
background-color: var(--tainacan-input-background-color);
@ -244,9 +244,13 @@
right: 2px;
top: 2px;
border-radius: 50px;
&:not(:hover) {
background-color: transparent;
&:hover,
&:focus {
border: none;
background-color: var(--tainacan-item-hover-background-color);
color: var(--tainacan-secondary);
}
}
&.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 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 FormTaxonomy from '../components/metadata-types/taxonomy/FormTaxonomy.vue';
import FormSelectbox from '../components/metadata-types/selectbox/FormSelectbox.vue';
@ -78,7 +79,8 @@ import {
UserCapabilitiesPlugin,
StatusHelperPlugin,
CommentsStatusHelperPlugin,
AdminOptionsHelperPlugin
AdminOptionsHelperPlugin,
HtmlSanitizerPlugin
} from './admin-utilities';
import {
ThumbnailHelperPlugin,
@ -188,6 +190,7 @@ export default (element) => {
app.use(ThumbnailHelperPlugin);
app.use(OrderByHelperPlugin);
app.use(StatusHelperPlugin);
app.use(HtmlSanitizerPlugin);
app.use(ConsolePlugin, {visual: false});
app.use(CommentsStatusHelperPlugin);
app.use(AdminOptionsHelperPlugin, pageElement.dataset['options']);
@ -215,6 +218,7 @@ export default (element) => {
/* Metadata Option forms */
app.component('tainacan-form-text', FormText);
app.component('tainacan-form-textarea', FormTextarea);
app.component('tainacan-form-relationship', FormRelationship);
app.component('tainacan-form-taxonomy', FormTaxonomy);
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;
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.
export const ConsolePlugin = {};
ConsolePlugin.install = function (app, options = { visual: false }) {
@ -15,7 +30,7 @@ ConsolePlugin.install = function (app, options = { visual: false }) {
log(something) {
if (options.visual) {
app.config.globalProperties.$buefy.snackbar.open({
message: something,
message: tainacanSanitize(something),
type: 'is-secondary',
position: 'is-bottom-right',
indefinite: true,
@ -28,7 +43,7 @@ ConsolePlugin.install = function (app, options = { visual: false }) {
info(someInfo) {
if (options.visual) {
app.config.globalProperties.$buefy.snackbar.open({
message: someInfo,
message: tainacanSanitize(someInfo),
type: 'is-primary',
position: 'is-bottom-right',
duration: 5000,
@ -41,7 +56,7 @@ ConsolePlugin.install = function (app, options = { visual: false }) {
error(someError) {
if (options.visual) {
app.config.globalProperties.$buefy.snackbar.open({
message: someError,
message: tainacanSanitize(someError),
type: 'is-danger',
position: 'is-bottom-right',
indefinite: true,
@ -142,6 +157,7 @@ UserPrefsPlugin.install = function (app, options = {}) {
'taxonomies_order_by': 'title',
'collections_order': 'desc',
'collections_order_by': 'date',
'collections_author_filter': '',
'map_view_mode_selected_geocoordinate_metadatum': 0
},
init() {
@ -636,7 +652,7 @@ AdminOptionsHelperPlugin.install = function (app, options = {}) {
* hideItemEditionMetadataTypes
* allowItemEditionModalInsideModal // Not recommended!
* itemEditionDocumentInsideTabs
* itemEditionAttachmentInsideTabs
* itemEditionAttachmentsInsideTabs
* hideBulkEditionPageTitle

View File

@ -9,6 +9,10 @@ const i18nGet = function (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) {
if (error.response && error.response.status) {
// The request was made and the server responded with a status code
@ -37,7 +41,7 @@ export const tainacanErrorHandler = function(error) {
break;
}
Snackbar.open({
message: errorMessage,
message: tainacanSanitize(errorMessage),
type: 'is-danger',
duration: duration,
actionText: errorMessageDetail != '' ? i18nGet('label_know_more') : null,

View File

@ -105,7 +105,7 @@ export const itemMetadataMixin = {
for (let conditionalSectionId in updatedConditionalSections) {
if ( updatedConditionalSections[conditionalSectionId].metadatumId == metadatumId ) {
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;

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) => {
let endpoint = '/collections?paged='+page+'&perpage='+collectionsPerPage;
@ -188,6 +188,9 @@ export const fetchCollections = ({commit} , { page, collectionsPerPage, status,
endpoint = endpoint + '&' + qs.stringify(taxQuery);
}
if (authorid != '' && authorid != undefined)
endpoint = endpoint + '&authorid=' + authorid;
axios.tainacan.get(endpoint)
.then(res => {
let collections = res.data;
@ -237,7 +240,8 @@ export const fetchCollection = ({ commit, }, id) => {
export const fetchCollectionBasics = ({ commit }, {collectionId, isContextEdit }) => {
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)
endpoint += '&context=edit';
@ -307,7 +311,7 @@ export const fetchCollectionForExposer = ({ commit }, collectionId) => {
export const fetchCollectionForItemSubmission = ({ commit }, collectionId) => {
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)
.then(res => {
resolve( res.data );

View File

@ -165,7 +165,10 @@ export const fetchRepositoryCollectionFilters = ({ dispatch, commit } ) => {
commit('clearRepositoryCollectionFilters');
return new Promise((resolve, reject) => {
const source = axios.CancelToken.source();
return Object({
request: new Promise((resolve, reject) => {
dispatch('collection/fetchAllCollectionNames', { } ,{ root: true })
.then((resp) => {
@ -188,7 +191,7 @@ export const fetchRepositoryCollectionFilters = ({ dispatch, commit } ) => {
// 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]=!=')
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);
@ -201,9 +204,10 @@ export const fetchRepositoryCollectionFilters = ({ dispatch, commit } ) => {
.then((results) => {
let futureRepositoryCollectionFilters = {};
for (let resp of results)
for (let resp of results) {
if (resp.filters.length > 0)
futureRepositoryCollectionFilters[resp.collectionId != 'default' ? resp.collectionId : 'repository-filters'] = resp.filters;
}
commit('setRepositoryCollectionFilters', futureRepositoryCollectionFilters);
resolve();
@ -217,10 +221,9 @@ export const fetchRepositoryCollectionFilters = ({ dispatch, commit } ) => {
.catch(() => {
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
collectionsToSearch.forEach(collectionId => {
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 } })
.catch((error) => {
reject(error);
@ -268,6 +271,7 @@ export const fetchTaxonomyFilters = ({ dispatch, commit }, { taxonomyId, collect
let taxonomyFilters = resp.filters.filter((filter) => {
return filter.metadatum.metadata_type_object.options.taxonomy_id != taxonomyId
});
if (taxonomyFilters.length > 0)
futureTaxonomyFilters[resp.collectionId != 'default' ? resp.collectionId : 'repository-filters'] = taxonomyFilters;
}

View File

@ -123,7 +123,7 @@ export const fetchTaxonomyName = ({ commit }, taxonomyId) => {
};
// 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 = '';
@ -148,6 +148,9 @@ export const fetchTerms = ({}, {taxonomyId, fetchOnly, search, all, order, offse
if (exclude != undefined)
query += '&' + qs.stringify({ exclude: exclude });
if (include != undefined)
query += '&' + qs.stringify({ include: include });
return new Promise((resolve, reject) => {
axios.tainacan.get(`/taxonomy/${taxonomyId}/terms${query}`)
.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 ) => {
axios.tainacan.post(`/taxonomy/${taxonomyId}/terms/`, term)
.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 ) => {
axios.tainacan.patch(`/taxonomy/${taxonomyId}/terms/${term.id}`, term)
.then( res => {

View File

@ -72,7 +72,15 @@ export const ThumbnailHelperFunctions = () => {
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) {
switch(tainacanSize) {

View File

@ -21,7 +21,7 @@
target="_blank"
:href="themeItemsListURL">
<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 class="menu-text">{{ $i18n.get('label_view_items_on_theme') }}</span>
</a>
@ -131,7 +131,7 @@
:href="themeCollectionListURL"
style="position: relative">
<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 class="menu-text">{{ $i18n.get('label_view_collections_on_theme') }}</span>
</a>

View File

@ -652,7 +652,7 @@
.header-item {
margin-bottom: 0 !important;
min-height: 2em;
min-height: 1.875em;
display: flex;
align-items: center;
@ -671,7 +671,7 @@
.button {
display: flex;
align-items: center;
border-radius: 0px !important;
border-radius: var(--tainacan-button-border-radius, 4px) !important;
height: 100% !important;
}

View File

@ -199,10 +199,9 @@
top: calc(-1 * var(--tainacan-container-padding));
z-index: 2;
background: var(--tainacan-background-color);
min-height: $header-height;
min-height: 2.5em;
padding: 0.5em 0;
height: auto;
padding-left: 0;
padding-right: 0;
border-bottom: 1px solid #ddd;
display: inline-flex;
justify-content: space-between;
@ -212,7 +211,7 @@
.header-item {
margin-bottom: 0 !important;
min-height: 2em;
min-height: 1.875em;
&:first-child {
margin-right: auto;

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