Merge remote-tracking branch 'origin/develop' into export

# Conflicts:
#	src/admin/class-tainacan-admin.php
#	src/admin/tainacan-admin-i18n.php
This commit is contained in:
Jacson Passold 2018-08-07 20:58:27 -03:00
commit 0d64ed773a
163 changed files with 10042 additions and 9452 deletions

View File

@ -19,6 +19,7 @@ module.exports = {
},
globals: {
'tainacan_plugin': true,
'_': true
'_': true,
'jQuery': true
}
}

View File

@ -26,9 +26,9 @@ before_install:
- sudo apt-get update
- sudo apt-get install sshpass
- sudo service mysql restart
- mysql -e 'CREATE DATABASE IF NOT EXISTS test;'
- mysql -e 'CREATE DATABASE IF NOT EXISTS test;'
install:
- echo -e "Install"
- echo -e "Install"
- sudo mv ./tests/bootstrap-config-sample.php ./tests/bootstrap-config.php
- sudo ./tests/bin/install-wp-tests.sh test travis "" /tmp/wordpress localhost latest
true
@ -44,7 +44,7 @@ install:
- echo '#!/bin/bash' |sudo tee /usr/local/bin/phpunit > /dev/null
- echo 'if ( php -v|grep -q --only-matching --perl-regexp "5\.\\d+\.\\d+" );then /usr/local/bin/phpunit-5 $@;else /usr/local/bin/phpunit-6 $@;fi;exit $?' |sudo tee -a /usr/local/bin/phpunit > /dev/null
- sudo chmod +x /usr/local/bin/phpunit
script: /usr/local/bin/phpunit # phpunit
script: /usr/local/bin/phpunit # phpunit
before_deploy:
- echo "Seção executada antes do deploy!"
- openssl aes-256-cbc -K $encrypted_cb93ef43fcd2_key -iv $encrypted_cb93ef43fcd2_iv
@ -54,7 +54,6 @@ before_deploy:
- ssh-add /tmp/deploy_rsa
- echo -e "Host $ssh_host\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
- ssh-add -l
#teste Crontab
deploy:
- provider: script
script: sshpass -p '$ssh_password' ssh $ssh_user@$ssh_host sh /home/l3p/atualiza_git/atualiza_todos.sh #ssh $ssh_user@$ssh_host $script_deploy_tainacan

View File

@ -2,25 +2,50 @@
This page describes how Tainacan importer works and is a reference to write your own importer.
This documentation is still in construction. A very effective way to learn more on how to build an importer is to look at the source code of the Test Importer and the CSV Importer classes that are included in the tainacan package.
## Introduction
Importers can import items inside a collection, or even create a bunch of collections, taxonomies and items all at once.
In order to create an Importer, you have to extend the `\Tainacan\Importer` Class and register it using the global `Tainacan_Importer_Handler->register_importer()` method.
This method takes an array as argument, with the defintion of your importer. These are the expected attributes.
```
@type string $name The name of the importer. e.g. 'Example Importer'
@type string $slug A unique slug for the importer. e.g. 'This is an example importer description'
@type string $description The importer description. e.g. 'example-importer'
@type string $class_name The Importer Class. e.g. '\Tainacan\Importer\Test_Importer'
@type bool $manual_mapping Wether Tainacan must present the user with an interface to manually map
the metadata from the source to the target collection.
If set to true, Importer Class must implement the method
get_source_metadata() to return the metadata found in the source.
Note that this will only work when importing items to one single collection.
@type bool $manual_collection Wether Tainacan will let the user choose a destination collection.
If set to true, Tainacan will handle Collection creation and will assign it to
the importer object using add_collection() method.
Otherwise, the child importer class must create the collections and add them to the collections property also using add_collection()
```
Note that depending on the value of `manual_mapping` and `manual_collection` you will have to implement some methods in your importer class.
## Initializing a new importer
When the user starts a new import process, he/she first choose which import to use.
Once the Importer is chosen, the first thing that happens when is the creation of a new instance of the chosen Importer. This fires the `__construct()` method.
Once the Importer is chosen, the first thing that happens is the creation of a new instance of the chosen Importer. This fires the `__construct()` method.
## Choose a collection
## Choose a collection (if manual_mapping is true)
After choosing the importer, user will be given the choice to choose the destination collection.
If called from inside a collection, this step is skipped and the current collection is set as destination.
If the importer has the attribute `$import_structure_and_mapping` set to `true`, and the importer is called from repository level,
they will also be able to choose to create a new collection.
In that cases, a new collection is created, and the importer must implement a method called `create_fields_and_mapping()`, which, as the name says, will create all collections metadata and set the mapping for the importer.
## Set options
Now its time to set the importer options. Each importer may have its own set of options, that will be used during the import process. It could be anything, from the delimiter character in a CSV importer, to an API key for a importer that fetches something from an API.
@ -44,16 +69,17 @@ The Importer classes must also implement the `options_form` method, in which it
```
function options_form() {
?>
<label>Foo</label>
<input type="text" name="options[foo]" value="<?php echo $this->get_options('foo'); ?>" />
<?php
$form = '<div class="field">';
$form .= '<label class="label">' . __('My Importer Option 1', 'tainacan') . '</label>';
$form .= '<div class="control">';
$form .= '<input type="text" class="input" name="my_importer_option_1" value="' . $this->get_option('my_importer_option_1') . '" />';
$form .= '</div>';
$form .= '</div>';
return $form;
}
```
TODO: better html reference and validate_options() method.
## Fetch source
Next, users will choose the source. Each importer declares the kind of sources they accpet: URL, file, or both.
@ -70,22 +96,22 @@ Importers do this by calling the `add_import_method()` and `remove_import_method
}
```
If the Importer accepts the `file` method, user will be prompted with a file input to upload a file. The file will then be saved and will be accessible via the `$this->tmp_file` attribute.
If the Importer accepts the `file` method, user will be prompted with a file input to upload a file. The file will then be saved and will be accessible via the `$this->get_tmp_file()` method.
If the importer accepts the `url` method, user will be prompted with an text input to enter an URL.By default, the importer will fetch any given URL to a file. However, each importer may override the `fetch_from_remote()` method and do whatever it want to create the file. For example, it could make several paged requests.
If the importer accepts the `url` method, user will be prompted with an text input to enter an URL. By default, the importer will fetch any given URL to the same `file` attrribute, as if the user had uploaded it. However, each importer may override the `fetch_from_remote()` method and do whatever it want to create the file. For example, it could make several paged requests.
From that point forward, the importer will behave just as if it was using the file method.
## Mapping
At this point the user is presented with an interface to map the metadata from the source to the metadata present in the chosen collection.
At this point, if the Importer definition has `manual_mapping` set to `true`, the user is presented with an interface to map the metadata from the source to the metadata present in the chosen collection.
The Importer class must implement the `get_fields()` method, that will return an array of the metadata found in the source. It can either return an hard coded array or an array that is red from the source file. For example, an importer that fetches data from an api knows beforehand what are the metadata the api will return, however, an importer that reads from a csv, may want to return whatever is found in the first line of the array.
The Importer class must implement the `get_source_metadata()` method, that will return an array of the metadata found in the source. It can either return an hard coded array or an array that is read from the source file. For example, an importer that fetches data from an api knows beforehand what are the metadata the api will return, however, an importer that reads from a csv, may want to return whatever is found in the first line of the array.
```
// Example 1: returns a hard coded set of metadata
function get_fields() {
function get_source_metadata() {
return [
'title',
'description'
@ -94,71 +120,169 @@ function get_fields() {
}
// Example 2: returns the columns of the first line of a CSV file
public function get_fields(){
$file = new \SplFileObject( $this->tmp_file, 'r' );
$file->seek(0 );
public function get_source_metadata(){
$file = new \SplFileObject( $this->tmp_file, 'r' );
$file->seek(0);
return $file->fgetcsv( $this->get_option('delimiter') );
}
```
## Importing Collection Structure and Mapping
## Importer steps
Alternatively, an importer may also create all the metadata and mappings from the source. In that cases, the user does not have to map anything.
An Importer may have several steps, that will handle different parts of the process. Each step will be handled by a different callback in the Importer class.
First thing an Importer must do to accomplish this is to declare it does so in the `construct()`, by setting `$import_structure_and_mapping` to `true`.
First, lets have a look at a simple CSV importer, that only have one steps, in which it imports the items from the source into a chosen collection. After that we will have a look on how to create custom steps.
### Simple Importer - One step that imports items
By default, the only method an Importer class must implement to functino is the `process_item()` class.
This method gets two parameters, the `$index` of the item to be inserted, and the `$collection_definition`, with information on the target collection.
Inside this metho you must fetch the item from the source and format it according to the `mapping` definition of the collection.
The `mapping` defines how the item metadata from the source should be mapped to the metadata present in the target collection. It was created either manually, by the user, or programatically by the importer in an earlier step (see advanced importers below). This is an array where the keys are the `metadata IDs` and the values are the `identifers` found in source.
All this method should do is return the item as an associative array, where the keys are the metadata `identifiers`, and the values are the values tha should be stored.
And that's it. Behind the scenes the Importer super class is handling everyhting and it will call `process_item()` as many times as needed to import all items into the collection
### Advanced Importer - Many steps
By default, Tainacan Importer super class is registering one single step to the importer:
```
function __construct() {
parent::construct();
[
'name' => 'Import Items',
'progress_label' => 'Importing Items',
'callback' => 'process_collections'
]
```
This step will lopp though all the collections added to the importer (manuall or programatically) and add the items to it.
You may register as many steps and callbacks as you want in your importer, but you should consider keeping this default step at some point to handle the items insertion. For example, see how the Test Importer adds other steps before and after but keeps this default step in the middle:
```
class Test_Importer extends Importer {
protected $steps = [
[
'name' => 'Create Taxonomies',
'progress_label' => 'Creating taxonomies',
'callback' => 'create_taxonomies'
],
[
'name' => 'Create Collections',
'progress_label' => 'Creating Collections',
'callback' => 'create_collections'
],
// we keep the default step
[
'name' => 'Import Items',
'progress_label' => 'Importing items',
'callback' => 'process_collections'
],
[
'name' => 'Post-configure taxonomies',
'progress_label' => 'post processing taxonomies',
'callback' => 'close_taxonomies'
],
[
'name' => 'Finalize',
'progress_label' => 'Finalizing',
'callback' => 'finish_processing',
'total' => 5
]
];
//...
```
#### Steps callbacks
Each step has its own callback. The callback may do anything necessary, just keep in mind that you should allow the importer to break very long processes into several requests.
In order to that, your step callback might be called several times, and each time run a part of the process and returnt its current status, until its done.
When you run the importer, Tainacan will automatically iterate over your steps. If a step callback returns `false`, it assumes the step is over and it will pass to the next step in the next iteration. If the step callback returns an integer, it will keep the pointer in this step and call the same step again in the next iteration. The current position, which is the integer returned the last time the callback was invoked, will be accessible via the `$this->get_in_step_count()` method.
See this example found in the Test Importer:
```
public function finish_processing() {
// Lets just pretend we are doing something really important
$important_stuff = 5;
$current = $this->get_in_step_count();
if ($current <= $important_stuff) {
// This is very important
sleep(5);
$current ++;
return $current;
} else {
return false;
}
$this->import_structure_and_mapping = true;
}
```
Second, the importer must implement the `create_fields_and_mapping()` to populate the collection with metadata and set the mapping.
#### Adding collections
In order to do this, the Importer will use Tainacan internal API to create the metadata. Please refer to the documentation (TODO: write this documentation).
If your importer does not use the `manual_collection` option, you might have to create the collection on your own.
This method must be aware that even a brand new collection comes with two core metadata (title and description), and use them.
You will do this using the [Tainacan internal API](internal-api.md).
Again, this metadata can come from the file, the URL or may be hardcoded in the function.
After you've created one or more collections, you will have to add them to the importer queue, registering some information about them. This only if you want (and most likely you should) rely on the default step for processing items into the collections.
Example
```
function create_fields_and_mapping() {
$metadata_repository = \Tainacan\Repositories\Metadata::get_instance();
$newMetadatum1 = new \Tainacan\Entities\Metadatum();
$newMetadatum1->set_name = 'New Metadatum';
$newMetadatum1->set_field_type = 'Tainacan\Metadatum_Types\Text';
$newMetadatum1->set_collection($this->collection);
$newMetadatum1->validate(); // there is no user input here, so we can be sure it will validate.
To add or remove a collection from the queue, use the `add_collection()` and `remove_collection()` methods passing the collection definition.
$newMetadatum1 = $metadata_repository->insert($newMetadatum1);
The collection definition is an array with their IDs, an identifier from the source, the total number of items to be imported, the mapping array from the source structure to the ID of the metadata metadata in tainacan.
$source_fields = $this->get_fields();
$this->set_mapping([
$newMetadatum1->get_id() => $source_fields[0]
]);
}
The format of the map is an array where the keys are the metadata IDs of the destination collection and the values are the identifier from the source. This could be an ID or a string or whatever the importer finds appropriate to handle.
TODO: helpers and explanation on how to fetch the core metadata and map them
The source_id can be anyhting you like, that helps you relate this collection to your source. You will use it in you `process_item` method to know where to fetch the item from.
Example of the structure of this propery for one collection:
```
[
'id' => 12,
'mapping' => [
30 => 'column1'
31 => 'column2'
],
'total_items' => 1234,
'source_id' => 55
]
```
#### Handling user feedback
There are two information Tainacan Importers give to the user about the status of the process while it is running in feedback. the `progress label` and the `progress value`.
The `progress label` is a string that can be anything that tells the user what is going on. By default, it is the Step Name, but you can inform a specific `progress_label` attribute when registering the steps.
The `progress value` is a number between 0 and 100 that indicates the progress of the current step or the whole importer, Thats up to you. By default, it calculates it automatically using the `total` attribute registered with the steps, against the `$this->get_in_step_count()` value. In the case of the default Process Items callback, it calculates based on the number of items found in each collection.
Remember the `finish_processing` dummy callback we saw in the Test Importer. You might have also noticed that when we registered the step, we informed a `total` attribute to this step with the value of 5. This will tell Tainacan that the total number iterations this step need to complete is 5 and allow it to calculate the progress.
If it is no possible to know `total` of a step beforehand, you can set it at any time, even inside the step callback itself, using the `set_current_step_total($value)` or `set_step_total($step, $value)` methods.
#### Logs
There are two useful methods to write information to the logs: `add_log()` and `add_error_log()`. These are written into a log file related to the importer background process and a link to it will be presented to the user.
## Run importer
Finally, everything is ready. The importer runs.
The `run()` method is called, the importer runs a step of the import process, and returns the number of items imported so far. The client (browser) will repeat this request as many times as necessary to complete the process and will give feedback to the user about the progress.
In order to allow this, the importer must implement the `get_total_items_from_source()` method, which will inform the total number of items present in the source.
All the steps and insertion are handled by the Importer super class. The importer class only have to implement one method (`process_item()`) to handle one single item. It will receive the index of this item and it must return the item in as an array, where each key is the identifier of the source metadatum (the same used in the mapping array), and the values are each metadatum value.
In the end, a report is generated with all the logs generated in the process.
This will trigger a Background Process (documentation needed) and the importer will run through as many background requests as needed.

View File

@ -6,14 +6,20 @@ By default, when using this option to search, WordPress searches only inside the
There is'nt one silver bullet to solve this problem. In some cases, perhaps for small repositories, a simple change in the way WordPress queries for posts, including relation to metadata and taxonomies, can give users the results they were looking for. In other cases, repository managers may want to use sophisticated solutions such as Elastic Search or Solr to enable Full Text Search for their users.
An intermediary approach could be creating index tables and tokenizing strings. This would allow even to order results based on relevance.
An intermediary approach could be creating index tables and tokenizing strings. This would allow even to order results based on relevance. (There is at least one paid WordPress plugin that does that)
Considering all these options, our current approach is not to touch in the way WordPress handles the search, and let it be overtaken by plugins.
Considering all these options, our current approach was to filter the SQL query built by the WordPress WP_Query object and include all the joins and wheres needed to search also in metadata and taxonomies values. This approach is the same of the "Search Everything" plugin we mention below.
Eventually we will develop our own search engine plugins, to replace the limited native WordPress approach, but for now we are investigating existing plugins that could work well with Tainacan. Since we made sure to build things in the "WordPress way", and since Tainacan search uses the native `WP_Query` class to make it queries, any plugin that filters its behavior might work with Tainacan.
If you want to disable this change to the default WordPress behavior you can do this by adding the following line to you `wp-config.php`. You should do this if you are going to use another plugin for this purpose to avoid conflicts.
```
define('TAINACAN_DISABLE_DEFAULT_SEARCH_ENGINE', true);
```
Eventually we will develop our own search engine plugins, to replace this initial approach, but for now we are investigating existing plugins that could work well with Tainacan. Since we made sure to build things in the "WordPress way", and since Tainacan search uses the native `WP_Query` class to make it queries, any plugin that filters its behavior might work with Tainacan.
We are only starting this investigation, and we will keep this page updated with our findings. This is not (yet) a list of recommendation.
* [Search Everything](https://wordpress.org/plugins/search-everything/): Expands the native WordPress search to also search in taxonomies and metadata. It does so by joining tables in `WP_Query` and therefore might have performance issues for large repositories.
* [Search Everything](https://wordpress.org/plugins/search-everything/): Expands the native WordPress search to also search in taxonomies and metadata. It does so by joining tables in `WP_Query` and therefore might have performance issues for large repositories. Its core funcionality is already present in Tainacan, but it does work very well with our plugin.
* [ElasticPress](https://wordpress.org/plugins/elasticpress/): integrates WordPress with an Elastic Search server. We are starting to test Tainacan with this plugin.
* [ElasticPress](https://wordpress.org/plugins/elasticpress/): integrates WordPress with an Elastic Search server. We are starting to test Tainacan with this plugin.

6701
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -12,39 +12,39 @@
"bulma": "^0.7.1",
"mdi": "^2.2.43",
"moment": "^2.22.2",
"npm": "^6.1.0",
"qs": "^6.5.2",
"v-mask": "^1.3.2",
"v-tooltip": "^2.0.0-rc.33",
"vue": "^2.5.16",
"node-sass": "^4.9.2",
"qs": "^6.5.2",
"v-tooltip": "^2.0.0-rc.33",
"vue": "^2.5.17",
"vue-router": "^3.0.1",
"vue-the-mask": "^0.11.1",
"vue2-hammer": "^1.0.7",
"vue-masonry-css": "^1.0.2",
"vuedraggable": "^2.16.0",
"vuex": "^3.0.1"
},
"devDependencies": {
"autoprefixer": "^8.6.5",
"autoprefixer": "^9.1.0",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-preset-env": "^1.7.0",
"babel-preset-stage-3": "^6.24.1",
"cross-env": "^5.2.0",
"css-loader": "^1.0.0",
"cypress": "^3.0.2",
"element-theme-chalk": "^2.4.3",
"eslint": "^5.1.0",
"eslint-loader": "^2.0.0",
"eslint-plugin-vue": "^4.5.0",
"element-theme-chalk": "^2.4.5",
"eslint": "^5.3.0",
"eslint-loader": "^2.1.0",
"eslint-plugin-vue": "^4.7.1",
"file-loader": "^1.1.11",
"postcss-loader": "^2.1.6",
"sass-loader": "^7.0.3",
"style-loader": "^0.21.0",
"sass-loader": "^7.1.0",
"style-loader": "^0.22.0",
"uglifyjs-webpack-plugin": "^1.2.7",
"vue-custom-element": "^3.2.2",
"vue-loader": "^15.2.4",
"vue-template-compiler": "^2.5.16",
"webpack": "^4.16.0",
"webpack-cli": "^3.0.8",
"webpack-dev-server": "^3.1.4"
"vue-custom-element": "^3.2.3",
"vue-loader": "^15.2.7",
"vue-template-compiler": "^2.5.17",
"webpack": "^4.16.5",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5"
}
}

View File

@ -6,13 +6,19 @@
:active-route="activeRoute"
:is-menu-compressed="isMenuCompressed"/>
<button
class="is-hidden-mobile"
id="menu-compress-button"
@click="isMenuCompressed = !isMenuCompressed">
<b-icon :icon="isMenuCompressed ? 'menu-right' : 'menu-left'" />
</button>
<tainacan-header :is-menu-compressed="isMenuCompressed"/>
<div class="column is-main-content">
<router-view/>
<tainacan-header />
<tainacan-repository-subheader
:is-repository-level="isRepositoryLevel"
:is-menu-compressed="isMenuCompressed"/>
<div
id="repository-container"
class="column is-main-content">
<router-view />
</div>
</div>
</template>
@ -20,28 +26,33 @@
<script>
import PrimaryMenu from './components/navigation/primary-menu.vue';
import TainacanHeader from './components/navigation/tainacan-header.vue';
import TainacanRepositorySubheader from './components/navigation/tainacan-repository-subheader.vue';
export default {
name: "AdminPage",
data(){
return {
isMenuCompressed: false,
isRepositoryLevel : true,
activeRoute: '/collections'
}
},
components: {
PrimaryMenu,
TainacanHeader
TainacanHeader,
TainacanRepositorySubheader
},
created() {
this.$userPrefs.init();
this.isMenuCompressed = (this.$route.params.collectionId != undefined);
this.activeRoute = this.$route.name;
this.isRepositoryLevel = this.$route.params.collectionId == undefined;
},
watch: {
'$route' (to) {
this.isMenuCompressed = (to.params.collectionId != undefined);
this.activeRoute = to.name;
this.isRepositoryLevel = this.$route.params.collectionId == undefined;
}
}
}
@ -56,7 +67,6 @@
margin-bottom: 0px;
margin-top: 0px;
@media screen and (max-width: 769px) {
height: auto;
}
@ -80,15 +90,14 @@
.is-secondary-content {
padding: 0px;
margin: $header-height auto 0 auto;
margin: 94px auto 0 auto;
position: relative;
overflow-y: hidden;
height: calc(100% - 53px);
height: calc(100% - 94px);
@media screen and (max-width: 769px) {
overflow-y: visible;
margin: 0 auto;
margin: 40px auto 0 auto;
}
@ -101,20 +110,20 @@
#menu-compress-button {
position: absolute;
z-index: 99;
top: 70px;
max-width: 23px;
height: 21px;
width: 23px;
top: 192px;
max-width: 25px;
height: 20px;
width: 25px;
border: none;
background-color: #c1dae0;
color: $secondary;
background-color: $blue5;
color: white;
padding: 0px;
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
cursor: pointer;
.icon {
margin-top: -1px;
margin-top: -2px;
}
}

View File

@ -180,8 +180,9 @@ class Admin {
'admin_url' => admin_url(),
'custom_header_support' => get_theme_support('custom-header'),
'registered_view_modes' => \Tainacan\Theme_Helper::get_instance()->get_registered_view_modes(),
'exposer_mapper_param' => \Tainacan\Exposers\Exposers::MAPPER_PARAM,
'exposer_type_param' => \Tainacan\Exposers\Exposers::TYPE_PARAM
'exposer_mapper_param' => \Tainacan\Exposers\Exposers::MAPPER_PARAM,
'exposer_type_param' => \Tainacan\Exposers\Exposers::TYPE_PARAM,
'repository_name' => get_bloginfo('name')
];
$maps = [

View File

@ -1,21 +1,39 @@
<template>
<div>
<section
v-if="!metadata || metadata.length <= 0"
class="field is-grouped-centered section">
<div class="content has-text-gray has-text-centered">
<p>
<b-icon
icon="format-list-checks"
size="is-large"/>
</p>
<p>{{ isRepositoryLevel ?
$i18n.get('info_there_are_no_metadata_in_repository_level' ) :
$i18n.get('info_there_are_no_metadata_to_search' ) }}</p>
</div>
</section>
<div
v-else
:style="advancedSearchResults ? { 'padding-top': '0' } : { 'padding-top': '47px' }"
class="columns is-multiline tnc-advanced-search-container">
:class="{ 'padding-in-header': isHeader, 'padding-regular': !isHeader }"
class="tnc-advanced-search-container">
<div
v-show="!advancedSearchResults"
v-for="searchCriterion in searchCriteria"
:key="searchCriterion"
class="field column is-12 tainacan-form">
class="field is-12 tainacan-form">
<b-field
class="columns"
grouped>
<!-- Metadata (Search criteria) -->
<b-field class="column">
<b-field
:class="{'is-3': isHeader}"
class="column">
<b-select
:placeholder="$i18n.get('instruction_select_a_metadatum')"
:disabled="advancedSearchQuery.taxquery[searchCriterion] ||
@ -25,7 +43,8 @@
(advancedSearchQuery.taxquery[searchCriterion] ? advancedSearchQuery.taxquery[searchCriterion].originalMeta : undefined)"
@input="addToAdvancedSearchQuery($event, 'metadatum', searchCriterion)">
<option
v-for="metadatum in metadata"
v-for="(metadatum, metadatumIndex) in metadata"
v-if="isRelationship(metadatum, metadatumIndex)"
:value="`${metadatum.id}-${metadatum.metadata_type_options.taxonomy}-${metadatum.metadata_type_object.primitive_type}`"
:key="metadatum.id"
>{{ metadatum.name }}</option>
@ -33,8 +52,9 @@
</b-field>
<!-- Inputs -->
<b-field
class="column is-two-thirds">
<b-field
:class="{'is-two-thirds': !isHeader}"
class="column">
<b-input
v-if="advancedSearchQuery.metaquery[searchCriterion] &&
advancedSearchQuery.metaquery[searchCriterion].ptype != 'date'"
@ -67,10 +87,15 @@
@add="addValueToAdvancedSearchQuery($event, 'terms', searchCriterion)"
@typing="autoCompleteTerm($event, searchCriterion)"
/>
<b-input
v-else
type="text"
disabled />
</b-field>
<!-- Comparators -->
<b-field
<b-field
:class="{'is-3': isHeader}"
class="column">
<b-select
v-if="advancedSearchQuery.taxquery[searchCriterion] ||
@ -86,6 +111,10 @@
:value="key"
>{{ comparator }}</option>
</b-select>
<b-input
v-else
type="text"
disabled />
</b-field>
<div class="field">
@ -104,19 +133,22 @@
<!-- Add button -->
<div
v-show="!advancedSearchResults"
:style="{
'margin-top': '-15px !important',
'padding-left': '25px !important'
}"
:class="{'add-link-advanced-search-header': isHeader, 'add-link-advanced-search': !isHeader }"
class="field column is-12">
<a
@click="addSearchCriteria"
class="is-secondary is-small add-link">
style="font-size: 12px;"
class="is-secondary">
<b-icon
class="add-i"
icon="plus-circle"
size="is-small"
type="is-secondary"/>
{{ $i18n.get('add_another_search_criterion') }}</a>
{{ searchCriteria.length &lt;= 0 ?
$i18n.get('add_one_search_criterion') :
$i18n.get('add_another_search_criterion')
}}
</a>
</div>
<!-- Tags -->
@ -160,7 +192,10 @@
v-show="!advancedSearchResults"
class="column">
<div class="field is-grouped is-pulled-right">
<p class="control">
<p
v-if="Object.keys(this.advancedSearchQuery.taxquery).length > 0 ||
Object.keys(this.advancedSearchQuery.metaquery).length > 0"
class="control">
<button
@click="clearSearch"
class="button is-outlined">{{ $i18n.get('clear_search') }}</button>
@ -188,6 +223,7 @@
props: {
metadata: Array,
isRepositoryLevel: false,
isHeader: false,
advancedSearchResults: false,
openFormAdvancedSearch: false,
isDoSearch: false,
@ -328,6 +364,15 @@
throw error;
});
}, 300),
isRelationship(metadatum, metadatumIndex){
if(metadatum.metadata_type.includes('Relationship')){
this.metadata.splice(metadatumIndex, 1);
return false;
}
return true;
},
getComparators(searchCriterion){
if(this.advancedSearchQuery.taxquery[searchCriterion]){
return this.taxqueryOperators;
@ -406,7 +451,22 @@
addValueToAdvancedSearchQuery: _.debounce(function(value, type, searchCriterion) {
this.addToAdvancedSearchQuery(value, type, searchCriterion);
}, 900),
searchAdvanced(){
searchAdvanced(){
if(this.isHeader){
this.$root.$emit('closeAdvancedSearchShortcut', true);
if(this.$route.path == '/items') {
this.$root.$emit('openAdvancedSearch', true);
}
if(this.$route.path != '/items') {
this.$router.push({
path: '/items',
});
}
}
if(Object.keys(this.advancedSearchQuery.taxquery).length > 0 &&
Object.keys(this.advancedSearchQuery.metaquery).length > 0){
this.advancedSearchQuery.relation = 'AND';
@ -534,13 +594,21 @@
@import '../../scss/_variables.scss';
.tnc-advanced-search-container {
.padding-in-header {
padding-right: 3.3%;
padding-left: 3.7%;
}
.padding-regular {
padding-right: $page-side-padding;
padding-left: $page-side-padding;
}
.tnc-advanced-search-container {
padding-bottom: 47px;
.column {
padding: 0 0.3rem 0.3rem !important;
padding: 0 0.5rem 0.75rem !important;
}
.control {
@ -551,6 +619,71 @@
}
}
}
.add-link-advanced-search {
margin-top: -15px !important;
padding-left: 8px !important;
}
.add-link-advanced-search-header {
margin-top: -20px !important;
padding: 0 !important;
margin-left: -5px !important;
}
@media screen and (max-width: 768px) {
.is-12>.columns {
flex-wrap: wrap;
}
.is-two-thirds {
order: 3;
flex-basis: 100%;
}
}
}
.advanced-search-header-dropdown {
height: 27px !important;
.dropdown-content {
width: 800px !important;
}
.dropdown-item:hover {
background-color: unset !important;
}
@media screen and (min-width: 1087px) {
.dropdown-menu {
top: 0 !important;
}
}
.dropdown-item {
span.icon:not(.is-right) {
position: relative !important;
}
}
.advanced-search-text {
margin: 0 12px;
font-size: 12px;
color: $blue5;
}
.advanced-search-text-di {
font-size: 14px;
font-weight: 500;
color: #01295c;
margin-top: 4px;
}
.advanced-search-hr {
height: 1px;
margin: 8px 0;
background-color: #298596;
}
}
</style>

View File

@ -1,7 +1,7 @@
<template>
<div
class="page-container"
:class="{'primary-page' : isNewCollection }">
:class="{'repository-level-page' : isNewCollection }">
<tainacan-title />
<form
v-if="collection != null && collection != undefined"
@ -794,13 +794,6 @@ export default {
this.createNewCollection();
}
}
},
mounted() {
if (!this.$route.path.includes("new")) {
document.getElementById('collection-page-container').addEventListener('scroll', ($event) => {
this.$emit('onShrinkHeader', ($event.target.scrollTop > 53));
});
}
}
}
@ -818,7 +811,7 @@ export default {
.section-label {
font-size: 16px !important;
font-weight: 500 !important;
color: $tertiary !important;
color: $blue5 !important;
line-height: 1.2em;
}
@ -854,7 +847,7 @@ export default {
font-weight: bold;
z-index: 99;
text-align: center;
color: gray;
color: $gray4;
@media screen and (max-width: 769px) {
font-size: 1.2rem;
@ -892,7 +885,7 @@ export default {
font-weight: bold;
z-index: 99;
text-align: center;
color: gray;
color: $gray4;
}
.thumbnail-buttons-row {
position: relative;
@ -901,7 +894,7 @@ export default {
}
}
.selected-cover-page {
border: 1px solid $tainacan-input-background;
border: 1px solid $gray2;
padding: 8px;
font-size: .75rem;
.span { vertical-align: middle;}
@ -915,11 +908,14 @@ export default {
padding: 4px 6px;
.icon { font-size: 20px; }
&.disabled {
.icon { color: $tainacan-input-background; }
pointer-events: none;
cursor: not-allowed;
.icon { color: $gray2; }
}
}
.moderators-empty-list {
color: gray;
color: $gray4;
font-size: 0.85rem;
}

View File

@ -7,7 +7,7 @@
:addons="false"
:type="formErrors['name'] != undefined ? 'is-danger' : ''"
:message="formErrors['name'] != undefined ? formErrors['name'] : ''">
<label class="label is-inline">
<label class="label is-inline-block">
{{ $i18n.get('label_name') }}
<span
class="required-metadatum-asterisk"
@ -26,7 +26,7 @@
:addons="false"
:type="formErrors['description'] != undefined ? 'is-danger' : ''"
:message="formErrors['description'] != undefined ? formErrors['description'] : ''">
<label class="label is-inline">
<label class="label is-inline-block">
{{ $i18n.get('label_description') }}
<help-button
:title="$i18n.getHelperTitle('filters', 'description')"
@ -43,7 +43,7 @@
:addons="false"
:type="formErrors['status'] != undefined ? 'is-danger' : ''"
:message="formErrors['status'] != undefined ? formErrors['status'] : ''">
<label class="label is-inline">
<label class="label is-inline-block">
{{ $i18n.get('label_status') }}
<help-button
:title="$i18n.getHelperTitle('filters', 'status')"
@ -72,6 +72,60 @@
</div>
</b-field>
<b-field
:addons="false"
v-if="editForm.filter_type_object && editForm.filter_type_object.component.includes('checkbox')">
<label class="label is-inline-block">
{{ $i18n.get('label_max_options_to_show') }}
<help-button
:title="$i18n.getHelperTitle('filters', 'max_options')"
:message="$i18n.getHelperMessage('filters', 'max_options')"/>
</label>
<div
v-if="!showEditMaxOptions"
class="is-flex">
<b-select
name="max_options"
v-model="editForm.max_options"
:placeholder="$i18n.get('instruction_select_max_options_to_show')">
<option value="4">4</option>
<option value="8">8</option>
<option value="12">12</option>
<option
v-if="editForm.max_options && ![4,8,12].find( (element) => element == editForm.max_options )"
:value="editForm.max_options">
{{ editForm.max_options }}</option>
</b-select>
<button
class="button is-white is-pulled-right"
:aria-label="$i18n.getFrom('items','edit_item')"
@click.prevent="showEditMaxOptions = true">
<b-icon
size="is-small"
type="is-secondary"
icon="pencil"/>
</button>
</div>
<div
v-if="showEditMaxOptions"
class="is-flex">
<b-input
name="max_options"
v-model="editForm.max_options"
type="number"
step="1" />
<button
@click.prevent="showEditMaxOptions = false"
class="button is-white is-pulled-right">
<b-icon
size="is-small"
type="is-secondary"
icon="close"/>
</button>
</div>
</b-field>
<component
:errors="formErrors['filter_type_options']"
v-if="(editForm.filter_type_object && editForm.filter_type_object.form_component) || editForm.edit_form == ''"
@ -111,7 +165,8 @@ export default {
oldForm: {},
formErrors: {},
formErrorMessage: '',
closedByForm: false
closedByForm: false,
showEditMaxOptions: false,
}
},
props: {
@ -168,11 +223,12 @@ export default {
} else {
let formElement = document.getElementById('filterEditForm');
let formData = new FormData(formElement);
let formObj = {}
let formObj = {};
for (let [key, value] of formData.entries())
for (let [key, value] of formData.entries()) {
formObj[key] = value;
}
this.updateFilter({ filterId: filter.id, index: this.index, options: formObj})
.then(() => {
this.editForm = {};
@ -211,8 +267,8 @@ export default {
form {
padding: 1.0em 2.0em;
border-top: 1px solid $draggable-border-color;
border-bottom: 1px solid $draggable-border-color;
border-top: 1px solid $gray2;
border-bottom: 1px solid $gray2;
margin-top: 1.0em;
}

View File

@ -1,204 +1,112 @@
<template>
<div
class="primary-page page-container">
class="repository-level-page page-container">
<tainacan-title />
<form
class="tainacan-form"
label-width="120px"
v-if="importer != undefined && importer != null">
<!-- Target collection selection -------------------------------- -->
<b-field
v-if="importer.manual_collection"
:addons="false"
:label="$i18n.get('label_target_collection')">
<help-button
:title="$i18n.get('label_target_collection')"
:message="$i18n.get('info_target_collection_helper')"/>
<br>
<div class="is-inline">
<b-select
id="tainacan-select-target-collection"
:value="collectionId"
@input="onSelectCollection($event)"
:loading="isFetchingCollections"
:placeholder="$i18n.get('instruction_select_a_target_collection')">
<option
v-for="collection of collections"
:key="collection.id"
:value="collection.id">{{ collection.name }}
</option>
</b-select>
<router-link
tag="a"
class="is-inline add-link"
:to="{ path: $routerHelper.getNewCollectionPath(), query: { fromImporter: true }}">
<b-icon
icon="plus-circle"
size="is-small"
type="is-secondary"/>
{{ $i18n.get('new_blank_collection') }}</router-link>
</div>
</b-field>
<!-- Importer custom options -->
<form
id="importerOptionsForm"
v-if="importer.options_form != undefined && importer.options_form != null && importer.options_form != ''">
<div v-html="importer.options_form"/>
</form>
<!-- File Source input -->
<b-field
v-if="importer.accepts.file"
:addons="false">
<label class="label">{{ $i18n.get('label_source_file') }}</label>
<help-button
:title="$i18n.get('label_source_file')"
:message="$i18n.get('info_source_file_upload')"/>
<br>
<b-upload
v-if="importer.tmp_file == undefined"
:value="importerFile"
@input="onUploadFile($event)"
drag-drop>
<section class="drop-inner">
<div class="content has-text-centered">
<p>
<b-icon
icon="upload"
size="is-large"/>
</p>
<p>{{ $i18n.get('instruction_drop_file_or_click_to_upload') }}</p>
</div>
</section>
</b-upload>
<div v-if="importer.tmp_file != undefined">{{ importer.tmp_file }}</div>
</b-field>
<!-- URL source input -------------------------------- -->
<b-field
v-if="importer.accepts.url"
:addons="false"
:label="$i18n.get('label_url_source_link')">
<help-button
:title="$i18n.get('label_url_source_link')"
:message="$i18n.get('info_url_source_link_helper')"/>
<b-input
id="tainacan-url-link-source"
:value="url"
@input="onInputURL($event)"/>
</b-field>
<!-- Metadata Mapping -->
<b-field
v-if="importer.manual_mapping"
:addons="false"
:label="$i18n.get('label_metadata_mapping')">
<help-button
:title="$i18n.get('label_metadata_mapping')"
:message="$i18n.get('info_metadata_mapping_helper')"/>
<div class="columns is-gapless">
<div
v-if="importerSourceInfo != undefined &&
importerSourceInfo != null">
<p class="mapping-header-label is-inline">{{ $i18n.get('label_from_source_collection') }}</p>
<p class="mapping-header-label is-pulled-right">{{ $i18n.get('label_to_target_collection') }}</p>
<div
class="source-metadatum"
v-for="(source_metadatum, index) of importerSourceInfo.source_metadata"
:key="index"><p>{{ source_metadatum }}</p>
<b-select
v-if="collectionMetadata != undefined &&
collectionMetadata.length > 0 &&
!isFetchingCollectionMetadata"
:value="checkCurrentSelectedCollectionMetadatum(source_metadatum)"
@input="onSelectCollectionMetadata($event, source_metadatum)"
:placeholder="$i18n.get('label_select_metadatum')">
<option :value="undefined">
{{ $i18n.get('label_select_metadatum') }}
</option>
<option
v-for="(metadatum, index) of collectionMetadata"
:key="index"
:value="metadatum.id"
:disabled="checkIfMetadatumIsAvailable(metadatum.id)">
<span class="metadatum-name">
{{ metadatum.name }}
</span>
<span class="label-details">
({{ $i18n.get(metadatum.metadata_type_object.component) }}) <em>{{ (metadatum.collection_id != collectionId) ? $i18n.get('label_inherited') : '' }}</em>
</span>
</option>
</b-select>
<p v-if="collectionMetadata == undefined || collectionMetadata.length <= 0">{{ $i18n.get('info_select_collection_to_list_metadata') }}</p>
</div>
<b-modal
@close="onMetadatumEditionCanceled()"
:active.sync="isNewMetadatumModalActive">
<b-loading
:is-full-page="isFullPage"
:active.sync="isLoadingMetadatumTypes"/>
<div
v-if="selectedMetadatumType == undefined && !isEditingMetadatum"
class="tainacan-modal-content">
<div class="tainacan-modal-title">
<h2>{{ $i18n.get('instruction_select_metadatum_type') }}</h2>
<hr>
</div>
v-if="importer.options_form != undefined && importer.options_form != null && importer.options_form != ''"
class="column">
<!-- Importer custom options -->
<form id="importerOptionsForm">
<div v-html="importer.options_form"/>
</form>
</div>
<div class="column">
<!-- Target collection selection -------------------------------- -->
<b-field
v-if="importer.manual_collection"
:addons="false"
:label="$i18n.get('label_target_collection')">
<help-button
:title="$i18n.get('label_target_collection')"
:message="$i18n.get('info_target_collection_helper')"/>
<br>
<div class="is-inline">
<b-select
:value="selectedMetadatumType"
@input="onSelectMetadatumType($event)"
:placeholder="$i18n.get('label_select_metadatum_type')">
expanded
id="tainacan-select-target-collection"
:value="collectionId"
@input="onSelectCollection($event)"
:loading="isFetchingCollections"
:placeholder="$i18n.get('instruction_select_a_target_collection')">
<option
v-for="(metadatumType, index) of metadatumTypes"
:key="index"
:value="metadatumType">
{{ metadatumType.name }}
v-for="collection of collections"
:key="collection.id"
:value="collection.id">{{ collection.name }}
</option>
</b-select>
<router-link
tag="a"
class="is-inline add-link"
:to="{ path: $routerHelper.getNewCollectionPath(), query: { fromImporter: true }}">
<b-icon
icon="plus-circle"
size="is-small"
type="is-secondary"/>
{{ $i18n.get('new_blank_collection') }}</router-link>
</div>
</b-field>
<!-- File Source input -->
<b-field
v-if="importer.accepts.file"
:addons="false">
<label class="label">{{ $i18n.get('label_source_file') }}</label>
<help-button
:title="$i18n.get('label_source_file')"
:message="$i18n.get('info_source_file_upload')"/>
<br>
<b-upload
v-if="importer.tmp_file == undefined && (importerFile == undefined || importerFile == null || importerFile == '')"
v-model="importerFile"
drag-drop
class="source-file-upload">
<section class="drop-inner">
<div class="content has-text-centered">
<p>
<b-icon
icon="upload"
size="is-large"/>
</p>
<p>{{ $i18n.get('instruction_drop_file_or_click_to_upload') }}</p>
</div>
</section>
</b-upload>
<div
v-if="isEditingMetadatum"
class="tainacan-modal-content">
<div class="tainacan-modal-title">
<h2>{{ $i18n.get('instruction_configure_new_metadatum') }}</h2>
<hr>
</div>
<metadatum-edition-form
:collection-id="collectionId"
:is-repository-level="false"
@onEditionFinished="onMetadatumEditionFinished()"
@onEditionCanceled="onMetadatumEditionCanceled()"
:index="0"
:original-metadatum="metadatum"
:edited-metadatum="editedMetadatum"
:is-on-modal="true"/>
class="control selected-source-file"
v-if="importerFile != undefined">
<span>{{ importerFile[0].name }}</span>
<a
target="_blank"
@click.prevent="importerFile = undefined">
<span class="icon">
<i class="mdi mdi-18px mdi-close"/>
</span>
</a>
</div>
</b-modal>
<a
v-if="collectionId != null && collectionId != undefined"
class="is-inline is-pulled-right add-link"
@click="createNewMetadatum()">
<b-icon
icon="plus-circle"
size="is-small"
type="is-secondary"/>
{{ $i18n.get('label_add_more_metadata') }}</a>
</div>
<div
v-if="importerSourceInfo == undefined ||
importerSourceInfo == null">
<p>{{ $i18n.get('info_upload_a_source_to_see_metadata') }}</p>
</div>
</b-field>
</b-field>
<!-- URL source input -------------------------------- -->
<b-field
v-if="importer.accepts.url"
:addons="false"
:label="$i18n.get('label_url_source_link')">
<help-button
:title="$i18n.get('label_url_source_link')"
:message="$i18n.get('info_url_source_link_helper')"/>
<b-input
id="tainacan-url-link-source"
v-model="url"/>
</b-field>
</div>
</div>
<!-- Form submit -------------------------------- -->
<div class="field is-grouped form-submit">
<div class="columns is-gapless field is-grouped form-submit">
<div class="control">
<button
id="button-cancel-collection-creation"
@ -207,26 +115,39 @@
@click="cancelBack">{{ $i18n.get('cancel') }}</button>
</div>
<div
v-if="!hasRunImporter"
v-if="!importer.manual_mapping"
class="control">
<button
:disabled="sessionId == undefined || importer == undefined"
:disabled="
sessionId == undefined ||
importer == undefined ||
(importer.manual_collection && collectionId == undefined) ||
(importer.accepts.file && !importer.accepts.url && !importerFile) ||
(!importer.accepts.file && importer.accepts.url && !url) ||
(importer.accepts.file && importer.accepts.url && !importerFile && !url)"
id="button-submit-collection-creation"
@click.prevent="onRunImporter"
@click.prevent="onFinishImporter()"
:class="{'is-loading': isLoadingRun }"
class="button is-success">{{ $i18n.get('run') }}</button>
</div>
<div
v-if="hasRunImporter"
v-if="importer.manual_mapping"
class="control">
<button
:disabled="sessionId == undefined || importer == undefined"
:disabled="
sessionId == undefined ||
importer == undefined ||
(importer.manual_collection && collectionId == undefined) ||
(importer.accepts.file && !importer.accepts.url && !importerFile) ||
(!importer.accepts.file && importer.accepts.url && !url) ||
(importer.accepts.file && importer.accepts.url && !importerFile && !url)"
id="button-submit-collection-creation"
@click.prevent="onCheckBackgroundProcessStatus"
class="button is-success">Check Status</button>
@click.prevent="onFinishImporter()"
:class="{'is-loading': isLoadingUpload }"
class="button is-success">{{ $i18n.get('next') }}</button>
</div>
</div>
</form>
<b-loading
:active.sync="isLoading"
:can-cancel="false"/>
@ -234,8 +155,7 @@
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
import MetadatumEditionForm from './../edition/metadatum-edition-form.vue';
import { mapActions } from 'vuex';
export default {
name: 'ImporterEditionForm',
@ -244,6 +164,8 @@ export default {
importerId: Number,
importer: null,
isLoading: false,
isLoadingRun: false,
isLoadingUpload: false,
isFetchingCollections: false,
form: {
@ -255,30 +177,14 @@ export default {
},
importerTypes: [],
importerType: '',
importerFile: {},
importerFile: null,
importerSourceInfo: null,
collections: [],
collectionMetadata: [],
collectionId: undefined,
url: '',
isNewMetadatumModalActive: false,
isLoadingMetadatumTypes: false,
selectedMetadatumType: undefined,
isEditingMetadatum: false,
metadatum: {},
editedMetadatum: {},
hasRunImporter: false,
backgroundProcess: undefined
}
},
components: {
MetadatumEditionForm
},
computed: {
metadatumTypes() {
return this.getMetadatumTypes();
}
},
methods: {
...mapActions('importer', [
'fetchImporterTypes',
@ -295,116 +201,79 @@ export default {
...mapActions('collection', [
'fetchCollectionsForParent'
]),
...mapActions('bgprocess', [
'fetchProcess'
]),
...mapActions('metadata', [
'fetchMetadata',
'fetchMetadatumTypes',
'sendMetadatum'
]),
...mapGetters('metadata', [
'getMetadatumTypes'
]),
...mapGetters('bgprocess', [
'getProcess'
]),
createImporter() {
// Puts loading on Draft Importer creation
this.isLoading = true;
// Creates draft Importer
this.sendImporter(this.importerType)
.then(res => {
.then(res => {
this.sessionId = res.id;
this.importer = JSON.parse(JSON.stringify(res));
this.sessionId = res.id;
this.importer = JSON.parse(JSON.stringify(res));
this.form = this.importer.options;
this.isLoading = false;
this.form = this.importer.options;
this.isLoading = false;
if (this.importer.manual_collection)
this.loadCollections();
})
.catch(error => this.$console.error(error));
if (this.importer.manual_collection)
this.loadCollections();
})
.catch(error => this.$console.error(error));
},
loadImporter() {
// Puts loading on Draft Importer creation
this.isLoading = true;
// Creates draft Importer
this.fetchImporter(this.sessionId)
.then(res => {
this.sessionId = res.id;
this.importer = JSON.parse(JSON.stringify(res));
this.form = this.importer.options;
this.isLoading = false;
if (this.importer.manual_collection)
this.loadCollections();
})
.catch(error => this.$console.error(error));
},
cancelBack(){
this.$router.go(-1);
},
onUploadFile(file) {
this.updateImporterFile({ sessionId: this.sessionId, file: file[0] })
.then(updatedImporter => {
this.importer = updatedImporter;
this.importerFile = this.importer.tmp_file;
this.fetchImporterSourceInfo(this.sessionId)
.then(importerSourceInfo => {
this.importerSourceInfo = importerSourceInfo;
this.mappedCollection['total_items'] = this.importerSourceInfo.source_total_items;
onUploadFile() {
return new Promise((resolve, reject) => {
this.updateImporterFile({ sessionId: this.sessionId, file: this.importerFile[0] })
.then(updatedImporter => {
this.importer = updatedImporter;
resolve();
})
.catch((errors) => {
this.$console.log(errors);
reject(errors);
});
})
.catch((errors) => {
this.$console.log(errors);
});
},
checkIfMetadatumIsAvailable(metadatumId) {
return this.mappedCollection['mapping'][metadatumId] != undefined;
onInputURL() {
return new Promise((resolve, reject) => {
this.updateImporterURL({ sessionId: this.sessionId, url: this.url })
.then(updatedImporter => {
this.importer = updatedImporter;
resolve();
})
.catch((errors) => {
this.$console.log(errors);
reject(errors);
});
});
},
checkCurrentSelectedCollectionMetadatum(sourceMetadatum) {
for (let key in this.mappedCollection['mapping']) {
if(this.mappedCollection['mapping'][key] == sourceMetadatum)
return key;
}
return undefined;
},
onInputURL(event) {
this.url = event;
onUpdateOptions() {
return new Promise((resolve, reject) => {
this.updateImporterURL({ sessionId: this.sessionId, url: this.url })
.then(updatedImporter => {
this.importer = updatedImporter;
})
.catch((errors) => {
this.$console.log(errors);
});
},
onRunImporter() {
if (this.importer.manual_collection) {
this.updateImporterCollection({ sessionId: this.sessionId, collection: this.mappedCollection })
.then(updatedImporter => {
this.importer = updatedImporter;
if (this.importer.options_form != undefined && this.importer.options != null && this.importer.options_form != '') {
let formElement = document.getElementById('importerOptionsForm');
let formData = new FormData(formElement);
let formObj = {};
for (let [key, value] of formData.entries())
formObj[key] = value;
this.updateImporterOptions({ sessionId: this.sessionId, options: formObj })
.then(updatedImporter => {
this.importer = updatedImporter;
this.finishRunImporter();
})
.catch((errors) => {
this.$console.log(errors);
});
} else
this.finishRunImporter();
})
.catch((errors) => {
this.$console.log(errors);
});
} else {
if (this.importer.options_form != undefined && this.importer.options != null && this.importer.options_form != '') {
let formElement = document.getElementById('importerOptionsForm');
let formData = new FormData(formElement);
let formObj = {};
@ -412,38 +281,87 @@ export default {
for (let [key, value] of formData.entries())
formObj[key] = value;
this.updateImporterOptions({ sessionId: this.sessionId, optionsForm: formObj })
.then(updatedImporter => {
this.importer = updatedImporter;
this.finishRunImporter();
this.updateImporterOptions({ sessionId: this.sessionId, options: formObj })
.then(updatedImporter => {
this.importer = updatedImporter;
resolve();
})
.catch((errors) => {
this.$console.log(errors);
});
} else
this.finishRunImporter();
}
.catch((errors) => {
this.$console.log(errors);
reject(errors);
});
} else {
resolve();
}
});
},
finishRunImporter() {
this.runImporter(this.sessionId)
.then(backgroundProcess => {
this.hasRunImporter = true;
this.backgroundProcess = backgroundProcess;
})
.catch((errors) => {
this.$console.log(errors);
});
uploadSource() {
this.isLoadingUpload = true;
return new Promise((resolve, reject) => {
if (this.importer.accepts.file && !this.importer.accepts.url) {
this.onUploadFile()
.then(() => { this.isLoadingUpload = false; resolve(); })
.catch((errors) => { this.isLoadingUpload = false; this.$console.log(errors) });
} else if (!this.importer.accepts.file && this.importer.accepts.url) {
this.onInputURL()
.then(() => { this.isLoadingUpload = false; resolve() })
.catch((errors) => { this.isLoadingUpload = false; this.$console.log(errors); });
} else if (this.importer.accepts.file && this.importer.accepts.url) {
if (this.importerFile) {
this.onUploadFile()
.then(() => { this.isLoadingUpload = false; resolve(); })
.catch((errors) => { this.isLoadingUpload = false; this.$console.log(errors) });
} else if (this.url) {
this.onInputURL()
.then(() => { this.isLoadingUpload = false; resolve() })
.catch((errors) => { this.isLoadingUpload = false; this.$console.log(errors); });
} else {
this.isLoadingUpload = false;
reject('No source file given');
}
} else {
this.isLoadingUpload = false;
resolve();
}
});
},
onCheckBackgroundProcessStatus() {
this.fetchProcess(this.backgroundProcess.bg_process_id)
.then((backgroundProcess) => {
this.$console.log(JSON.stringify(backgroundProcess));
onFinishImporter() {
this.isLoadingRun = true;
this.onUpdateOptions().then(() => {
this.uploadSource()
.then(() => {
if (this.importer.manual_mapping) {
this.goToMappingPage();
this.isLoadingRun = false;
} else {
this.onRunImporter();
}
}).catch((errors) => {
this.isLoadingRun = false;
this.$console.log(errors);
});
})
.catch((error) => {
this.$console.error(error);
});
.catch((errors) => {
this.isLoadingRun = false;
this.$console.log(errors);
});
},
onRunImporter() {
this.runImporter(this.sessionId)
.then(backgroundProcess => {
this.backgroundProcess = backgroundProcess;
this.isLoadingRun = false;
this.$router.push(this.$routerHelper.getProcessesPage(backgroundProcess.bg_process_id));
})
.catch((errors) => {
this.isLoadingRun = false;
this.$console.log(errors);
});
},
goToMappingPage() {
this.$router.push(this.$routerHelper.getImporterMappingPath(this.importerType, this.sessionId, this.collectionId));
},
loadCollections() {
// Generates options for target collection
@ -460,104 +378,22 @@ export default {
},
onSelectCollection(collectionId) {
this.collectionId = collectionId;
this.mappedCollection['id'] = collectionId;
// Generates options for metadata listing
this.isFetchingCollectionMetadata = true;
this.fetchMetadata({collectionId: this.collectionId, isRepositoryLevel: false, isContextEdit: false })
.then((metadata) => {
this.collectionMetadata = JSON.parse(JSON.stringify(metadata));
this.isFetchingCollectionMetadata = false;
})
.catch((error) => {
this.$console.error(error);
this.isFetchingCollectionMetadata = false;
});
},
onSelectCollectionMetadata(selectedMetadatum, sourceMetadatum) {
if (selectedMetadatum)
this.mappedCollection['mapping'][selectedMetadatum] = sourceMetadatum;
else {
let removedKey = '';
for (let key in this.mappedCollection['mapping']) {
if(this.mappedCollection['mapping'][key] == sourceMetadatum)
removedKey = key;
}
if (removedKey != '')
delete this.mappedCollection['mapping'][removedKey];
}
// Necessary for causing reactivity to re-check if metadata remains available
this.collectionMetadata.push("");
this.collectionMetadata.pop();
},
onSelectMetadatumType(newMetadatum) {
this.sendMetadatum({
collectionId: this.collectionId,
name: newMetadatum.name, metadatumType:
newMetadatum.className,
status: 'auto-draft',
isRepositoryLevel: false,
newIndex: 0
})
.then((metadatum) => {
this.metadatum = metadatum;
this.editedMetadatum = JSON.parse(JSON.stringify(metadatum));
this.editedMetadatum.saved = false;
this.editedMetadatum.status = 'publish';
this.isEditingMetadatum = true;
})
.catch((error) => {
this.$console.error(error);
});
},
createNewMetadatum() {
this.fetchMetadatumTypes()
.then(() => {
this.isLoadingMetadatumTypes = false;
this.isNewMetadatumModalActive = true;
})
.catch(() => {
this.isLoadingMetadatumTypes = false;
});
},
onMetadatumEditionFinished() {
// Reset variables for metadatum creation
delete this.metadatum;
delete this.editedMetadatum;
this.isEditingMetadatum = false;
this.isNewMetadatumModalActive = false;
this.selectedMetadatumType = undefined;
// Generates options for metadata listing
this.isFetchingCollectionMetadata = true;
this.fetchMetadata({collectionId: this.collectionId, isRepositoryLevel: false, isContextEdit: false })
.then((metadata) => {
this.collectionMetadata = JSON.parse(JSON.stringify(metadata));
this.isFetchingCollectionMetadata = false;
})
.catch((error) => {
this.$console.error(error);
this.isFetchingCollectionMetadata = false;
});
},
onMetadatumEditionCanceled() {
// Reset variables for metadatum creation
if (this.metadatum)
delete this.metadatum;
if (this.editedMetadatum)
delete this.editedMetadatum;
this.isEditingMetadatum = false;
this.isNewMetadatumModalActive = false;
this.selectedMetadatumType = undefined;
this.mappedCollection['id'] = collectionId;
}
},
created() {
this.importerType = this.$route.params.importerSlug;
this.createImporter();
this.collectionId = this.$route.query.targetCollection;
this.sessionId = this.$route.params.sessionId;
if (this.collectionId != undefined) {
this.onSelectCollection(this.collectionId);
}
if (this.sessionId != undefined)
this.loadImporter();
else
this.createImporter();
}
}
@ -567,21 +403,33 @@ export default {
@import "../../scss/_variables.scss";
.columns.is-gapless {
padding-left: $page-side-padding;
padding-right: $page-side-padding;
.column:not(:first-child) {
margin-left: $page-side-padding;
}
}
.field {
position: relative;
}
.form-submit {
margin-top: 24px;
}
.section-label {
font-size: 16px !important;
font-weight: 500 !important;
color: $tertiary !important;
color: $blue5 !important;
line-height: 1.2em;
}
.source-metadatum {
padding: 2px 0;
border-bottom: 1px solid $tainacan-input-background;
border-bottom: 1px solid $gray2;
width: 100%;
margin-bottom: 6px;
display: flex;
@ -597,7 +445,7 @@ export default {
}
.mapping-header-label {
color: $gray-light;
color: $gray4;
margin: 12px 0 6px 0;
}
@ -610,6 +458,20 @@ export default {
}
}
.source-file-upload {
width: 100%;
display: grid;
}
.selected-source-file {
border: 1px solid $gray2;
padding: 2px 10px;
font-size: .75rem;
display: flex;
justify-content: space-between;
align-items: center;
}
</style>

View File

@ -0,0 +1,521 @@
<template>
<div
class="repository-level-page page-container">
<div class="tainacan-page-title">
<h1>{{ $i18n.get('label_metadata_mapping') }} </h1>
<a
@click="$router.go(-1)"
class="back-link has-text-secondary">
{{ $i18n.get('back') }}
</a>
<hr>
<nav class="breadcrumbs">
<router-link
tag="a"
:to="$routerHelper.getCollectionsPath()">{{ $i18n.get('repository') }}</router-link> >
<router-link
tag="a"
:to="$routerHelper.getAvailableImportersPath()">{{ $i18n.get('importers') }}</router-link> >
<router-link
tag="a"
:to="$routerHelper.getImporterPath(importerType, sessionId)">{{ importerType }}</router-link> >
<router-link
tag="a"
:to="$routerHelper.getImporterMappingPath(importerType, sessionId, collectionId)">{{ $i18n.get('label_metadata_mapping') }}</router-link>
</nav>
</div>
<form
class="tainacan-form"
label-width="120px"
v-if="importer != undefined && importer != null">
<!-- Metadata Mapping -->
<b-field
v-if="importer.manual_mapping"
:addons="false"
:label="$i18n.get('label_metadata_mapping')">
<help-button
:title="$i18n.get('label_metadata_mapping')"
:message="$i18n.get('info_metadata_mapping_helper')"/>
<div
v-if="importerSourceInfo != undefined &&
importerSourceInfo != null">
<p class="mapping-header-label is-inline">{{ $i18n.get('label_from_source_collection') }}</p>
<p class="mapping-header-label is-pulled-right">{{ $i18n.get('label_to_target_collection') }}</p>
<div
class="source-metadatum"
v-for="(source_metadatum, index) of importerSourceInfo.source_metadata"
:key="index"><p>{{ source_metadatum }}</p>
<b-select
v-if="collectionMetadata != undefined &&
collectionMetadata.length > 0 &&
!isFetchingCollectionMetadata"
:value="checkCurrentSelectedCollectionMetadatum(source_metadatum)"
@input="onSelectCollectionMetadata($event, source_metadatum)"
:placeholder="$i18n.get('label_select_metadatum')">
<option :value="undefined">
{{ $i18n.get('label_select_metadatum') }}
</option>
<option
v-for="(metadatum, index) of collectionMetadata"
:key="index"
:value="metadatum.id"
:disabled="checkIfMetadatumIsAvailable(metadatum.id)">
<span class="metadatum-name">
{{ metadatum.name }}
</span>
<span class="label-details">
({{ $i18n.get(metadatum.metadata_type_object.component) }}) <em>{{ (metadatum.collection_id != collectionId) ? $i18n.get('label_inherited') : '' }}</em>
</span>
</option>
</b-select>
<p v-if="collectionMetadata == undefined || collectionMetadata.length <= 0">{{ $i18n.get('info_select_collection_to_list_metadata') }}</p>
</div>
<b-modal
@close="onMetadatumEditionCanceled()"
:active.sync="isNewMetadatumModalActive">
<b-loading
:is-full-page="isFullPage"
:active.sync="isLoadingMetadatumTypes"/>
<div
v-if="selectedMetadatumType == undefined && !isEditingMetadatum"
class="tainacan-modal-content">
<div class="tainacan-modal-title">
<h2>{{ $i18n.get('instruction_select_metadatum_type') }}</h2>
<a
class="back-link"
@click="onMetadatumEditionCanceled(); isNewMetadatumModalActive = false">{{ $i18n.get('exit') }}</a>
<hr>
</div>
<section class="tainacan-form">
<div class="metadata-types-container">
<div
class="metadata-type"
v-for="(metadatumType, index) of metadatumTypes"
:key="index"
@click="onSelectMetadatumType(metadatumType)">
<h4>{{ metadatumType.name }}</h4>
</div>
</div>
</section>
</div>
<div
v-if="isEditingMetadatum"
class="tainacan-modal-content">
<div class="tainacan-modal-title">
<h2>{{ $i18n.get('instruction_configure_new_metadatum') }}</h2>
<hr>
</div>
<metadatum-edition-form
:collection-id="collectionId"
:is-repository-level="false"
@onEditionFinished="onMetadatumEditionFinished()"
@onEditionCanceled="onMetadatumEditionCanceled()"
:index="0"
:original-metadatum="metadatum"
:edited-metadatum="editedMetadatum"
:is-on-modal="true"/>
</div>
</b-modal>
<a
v-if="collectionId != null && collectionId != undefined"
class="is-inline is-pulled-right add-link has-text-secondary"
@click="createNewMetadatum()">
<b-icon
icon="plus-circle"
size="is-small"
type="is-secondary"/>
{{ $i18n.get('label_add_more_metadata') }}</a>
</div>
<div
v-if="importerSourceInfo == undefined ||
importerSourceInfo == null">
<p>{{ $i18n.get('info_upload_a_source_to_see_metadata') }}</p>
</div>
</b-field>
<!-- Form submit -------------------------------- -->
<div class="field is-grouped form-submit">
<div class="control">
<button
id="button-cancel-collection-creation"
class="button is-outlined"
type="button"
@click="cancelBack">{{ $i18n.get('cancel') }}</button>
</div>
<div class="control">
<button
:disabled="sessionId == undefined || importer == undefined"
id="button-submit-collection-creation"
@click.prevent="onRunImporter"
:class="{'is-loading': isLoadingRun }"
class="button is-success">{{ $i18n.get('run') }}</button>
</div>
</div>
</form>
<b-loading
:active.sync="isLoading"
:can-cancel="false"/>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
import MetadatumEditionForm from './../edition/metadatum-edition-form.vue';
export default {
name: 'ImporterEditionForm',
data(){
return {
importerId: Number,
importer: null,
isLoading: false,
isLoadingRun: false,
mappedCollection: {
'id': Number,
'mapping': {},
'total_items': Number
},
importerType: '',
importerSourceInfo: null,
collections: [],
collectionMetadata: [],
collectionId: undefined,
isNewMetadatumModalActive: false,
isLoadingMetadatumTypes: false,
selectedMetadatumType: undefined,
isEditingMetadatum: false,
metadatum: {},
editedMetadatum: {},
backgroundProcess: undefined
}
},
components: {
MetadatumEditionForm
},
computed: {
metadatumTypes() {
return this.getMetadatumTypes();
}
},
methods: {
...mapActions('importer', [
'fetchImporterTypes',
'fetchImporter',
'sendImporter',
'updateImporter',
'updateImporterFile',
'updateImporterURL',
'updateImporterOptions',
'fetchImporterSourceInfo',
'updateImporterCollection',
'runImporter'
]),
...mapActions('collection', [
'fetchCollectionsForParent'
]),
...mapActions('bgprocess', [
'fetchProcess'
]),
...mapActions('metadata', [
'fetchMetadata',
'fetchMetadatumTypes',
'sendMetadatum'
]),
...mapGetters('metadata', [
'getMetadatumTypes'
]),
...mapGetters('bgprocess', [
'getProcess'
]),
loadImporter() {
// Puts loading on Draft Importer creation
this.isLoading = true;
// Creates draft Importer
this.fetchImporter(this.sessionId)
.then(res => {
this.sessionId = res.id;
this.importer = JSON.parse(JSON.stringify(res));
this.isLoading = false;
this.fetchImporterSourceInfo(this.sessionId)
.then(importerSourceInfo => {
this.importerSourceInfo = importerSourceInfo;
this.mappedCollection['total_items'] = this.importerSourceInfo.source_total_items;
})
.catch((errors) => {
this.$console.log(errors);
});
})
.catch(error => this.$console.error(error));
},
loadMetadata() {
// Generates options for metadata listing
this.isFetchingCollectionMetadata = true;
this.fetchMetadata({collectionId: this.collectionId, isRepositoryLevel: false, isContextEdit: false })
.then((metadata) => {
this.collectionMetadata = JSON.parse(JSON.stringify(metadata));
this.isFetchingCollectionMetadata = false;
})
.catch((error) => {
this.$console.error(error);
this.isFetchingCollectionMetadata = false;
});
},
cancelBack(){
this.$router.go(-2);
},
checkIfMetadatumIsAvailable(metadatumId) {
return this.mappedCollection['mapping'][metadatumId] != undefined;
},
checkCurrentSelectedCollectionMetadatum(sourceMetadatum) {
for (let key in this.mappedCollection['mapping']) {
if(this.mappedCollection['mapping'][key] == sourceMetadatum)
return key;
}
return undefined;
},
onRunImporter() {
this.isLoadingRun = true;
this.updateImporterCollection({ sessionId: this.sessionId, collection: this.mappedCollection })
.then(updatedImporter => {
this.importer = updatedImporter;
this.finishRunImporter();
})
.catch((errors) => {
this.isLoadingRun = false;
this.$console.log(errors);
});
},
finishRunImporter() {
this.runImporter(this.sessionId)
.then(backgroundProcess => {
this.backgroundProcess = backgroundProcess;
this.isLoadingRun = false;
this.$router.push(this.$routerHelper.getProcessesPage());
})
.catch((errors) => {
this.isLoadingRun = false;
this.$console.log(errors);
});
},
onSelectCollectionMetadata(selectedMetadatum, sourceMetadatum) {
let removedKey = '';
for (let key in this.mappedCollection['mapping']) {
if(this.mappedCollection['mapping'][key] == sourceMetadatum)
removedKey = key;
}
if (removedKey != '')
delete this.mappedCollection['mapping'][removedKey];
this.mappedCollection['mapping'][selectedMetadatum] = sourceMetadatum;
// Necessary for causing reactivity to re-check if metadata remains available
this.collectionMetadata.push("");
this.collectionMetadata.pop();
},
onSelectMetadatumType(newMetadatum) {
this.sendMetadatum({
collectionId: this.collectionId,
name: newMetadatum.name, metadatumType:
newMetadatum.className,
status: 'auto-draft',
isRepositoryLevel: false,
newIndex: 0
})
.then((metadatum) => {
this.metadatum = metadatum;
this.editedMetadatum = JSON.parse(JSON.stringify(metadatum));
this.editedMetadatum.saved = false;
this.editedMetadatum.status = 'publish';
this.isEditingMetadatum = true;
})
.catch((error) => {
this.$console.error(error);
});
},
createNewMetadatum() {
this.fetchMetadatumTypes()
.then(() => {
this.isLoadingMetadatumTypes = false;
this.isNewMetadatumModalActive = true;
})
.catch(() => {
this.isLoadingMetadatumTypes = false;
});
},
onMetadatumEditionFinished() {
// Reset variables for metadatum creation
delete this.metadatum;
delete this.editedMetadatum;
this.isEditingMetadatum = false;
this.isNewMetadatumModalActive = false;
this.selectedMetadatumType = undefined;
// Generates options for metadata listing
this.isFetchingCollectionMetadata = true;
this.fetchMetadata({collectionId: this.collectionId, isRepositoryLevel: false, isContextEdit: false })
.then((metadata) => {
this.collectionMetadata = JSON.parse(JSON.stringify(metadata));
this.isFetchingCollectionMetadata = false;
})
.catch((error) => {
this.$console.error(error);
this.isFetchingCollectionMetadata = false;
});
},
onMetadatumEditionCanceled() {
// Reset variables for metadatum creation
if (this.metadatum)
delete this.metadatum;
if (this.editedMetadatum)
delete this.editedMetadatum;
this.isEditingMetadatum = false;
this.isNewMetadatumModalActive = false;
this.selectedMetadatumType = undefined;
}
},
created() {
this.importerType = this.$route.params.importerType;
this.sessionId = this.$route.params.sessionId;
this.collectionId = this.$route.params.collectionId;
this.mappedCollection['id'] = this.collectionId;
this.loadImporter();
this.loadMetadata();
}
}
</script>
<style lang="scss" scoped>
@import "../../scss/_variables.scss";
.tainacan-page-title {
margin-bottom: 40px;
h1, h2 {
font-size: 20px;
font-weight: 500;
color: $blue5;
display: inline-block;
}
a.back-link{
font-weight: 500;
float: right;
margin-top: 5px;
}
hr{
margin: 3px 0px 4px 0px;
height: 1px;
background-color: $secondary;
}
.breadcrumbs {
font-size: 12px;
}
.level-left {
.level-item {
display: inline-block;
margin-left: 268px;
}
}
@media screen and (max-width: 769px) {
.level-left {
margin-left: 0px !important;
.level-item {
margin-left: 30px;
}
}
.level-right {
display: none;
}
top: 206px;
margin-bottom: 0px !important;
}
}
.field {
position: relative;
}
.form-submit {
margin-top: 24px;
}
.section-label {
font-size: 16px !important;
font-weight: 500 !important;
color: $blue5 !important;
line-height: 1.2em;
}
.source-metadatum {
padding: 2px 0;
border-bottom: 1px solid $gray2;
width: 100%;
margin-bottom: 6px;
display: flex;
justify-content: space-between;
align-items: center;
}
.is-inline .control{
display: inline;
}
.drop-inner{
padding: 1rem 3rem;
}
.mapping-header-label {
color: $gray4;
margin: 12px 0 6px 0;
}
.modal .animation-content {
width: 100%;
z-index: 99999;
#metadatumEditForm {
background-color: white;
}
}
.metadata-types-container {
.metadata-type {
border-bottom: 1px solid $gray2;
padding: 15px 8.3333333%;
cursor: pointer;
&:first-child {
margin-top: 15px;
}
&:last-child {
border-bottom: none;
}
&:hover {
background-color: $gray1;
}
}
}
</style>

View File

@ -362,7 +362,7 @@
class="collapse-all"
@click="toggleCollapseAll()">
{{ collapseAll ? $i18n.get('label_collapse_all') : $i18n.get('label_expand_all') }}
<b-icon
<b-icon
type="is-gray"
:icon=" collapseAll ? 'menu-down' : 'menu-right'" />
</a>
@ -416,9 +416,9 @@
class="button is-outlined">{{ $i18n.get('label_send_to_trash') }}</button>
<button
v-if="form.status == 'auto-draft'"
@click="onDiscart()"
@click="onDiscard()"
type="button"
class="button is-outlined">{{ $i18n.get('label_discart') }}</button>
class="button is-outlined">{{ $i18n.get('label_discard') }}</button>
<button
@click="onSubmit('draft')"
type="button"
@ -581,7 +581,7 @@ export default {
this.isLoading = false;
});
},
onDiscart() {
onDiscard() {
this.$router.go(-1);
},
createNewItem() {
@ -857,11 +857,6 @@ export default {
});
this.cleanLastUpdated();
},
mounted() {
document.getElementById('collection-page-container').addEventListener('scroll', ($event) => {
this.$emit('onShrinkHeader', ($event.target.scrollTop > 53));
});
},
beforeRouteLeave ( to, from, next ) {
if (this.item.status == 'auto-draft') {
this.$modal.open({
@ -896,7 +891,7 @@ export default {
height: 36px;
width: 36px;
border: none;
background-color: $tainacan-input-background;
background-color: $gray2;
color: $secondary;
padding: 0px;
border-top-left-radius: 2px;
@ -909,10 +904,6 @@ export default {
}
}
.page-container-shrinked {
height: calc(100% - 118px) !important; // Bigger than the others due footer's height
}
.page-container {
padding: 25px 0px;
@ -954,7 +945,7 @@ export default {
label {
font-size: 16px !important;
font-weight: 500 !important;
color: $tertiary !important;
color: $blue5 !important;
line-height: 1.2em;
}
}
@ -983,11 +974,11 @@ export default {
height: 72px;
width: 72px;
border: none;
background-color: $tainacan-input-background;
background-color: $gray2;
color: $secondary;
margin-bottom: 6px;
&:hover {
background-color: $primary-light;
background-color: $turquoise2;
cursor: pointer;
}
}
@ -1001,12 +992,12 @@ export default {
margin-right: 24px;
.icon {
font-size: 18px !important;
color: $gray;
color: $gray3;
}
}
}
.section-attachments {
border: 1px solid $draggable-border-color;
border: 1px solid $gray2;
height: 250px;
max-width: 100%;
resize: vertical;
@ -1069,7 +1060,7 @@ export default {
font-weight: bold;
z-index: 99;
text-align: center;
color: gray;
color: $gray4;
top: 70px;
max-width: 90px;
}
@ -1086,7 +1077,7 @@ export default {
position: absolute;
bottom: 0;
z-index: 999999;
background-color: $primary-lighter;
background-color: $gray1;
width: 100%;
height: 65px;
display: flex;
@ -1101,12 +1092,12 @@ export default {
}
@keyframes blink {
from { color: $tertiary; }
to { color: $gray-light; }
from { color: $blue5; }
to { color: $gray4; }
}
.update-warning {
color: $tertiary;
color: $blue5;
animation-name: blink;
animation-duration: 0.5s;
animation-delay: 0.5s;
@ -1115,7 +1106,7 @@ export default {
}
.update-info-section {
color: $gray-light;
color: $gray4;
margin-right: auto;
}

View File

@ -9,7 +9,7 @@
:addons="false"
:type="formErrors['name'] != undefined ? 'is-danger' : ''"
:message="formErrors['name'] != undefined ? formErrors['name'] : ''">
<label class="label is-inline">
<label class="label is-inline-block">
{{ $i18n.get('label_name') }}
<span
class="required-metadatum-asterisk"
@ -28,7 +28,7 @@
:addons="false"
:type="formErrors['description'] != undefined ? 'is-danger' : ''"
:message="formErrors['description'] != undefined ? formErrors['description'] : ''">
<label class="label is-inline">
<label class="label is-inline-block">
{{ $i18n.get('label_description') }}
<help-button
:title="$i18n.getHelperTitle('metadata', 'description')"
@ -40,12 +40,27 @@
v-model="editForm.description"
@focus="clearErrors('description')"/>
</b-field>
<b-field
:addons="false">
<label class="label is-inline-block">
{{ $i18n.get('label_semantic_uri') }}
<help-button
:title="$i18n.getHelperTitle('metadata', 'semantic_uri')"
:message="$i18n.getHelperMessage('metadata', 'semantic_uri')"/>
</label>
<b-input
v-model="editForm.semantic_uri"
name="semantic_uri"
type="url"
@focus="clearErrors('semantic_uri')"/>
</b-field>
<b-field
:addons="false"
:type="formErrors['status'] != undefined ? 'is-danger' : ''"
:message="formErrors['status'] != undefined ? formErrors['status'] : ''">
<label class="label is-inline">
<label class="label is-inline-block">
{{ $i18n.get('label_status') }}
<help-button
:title="$i18n.getHelperTitle('metadata', 'status')"
@ -80,7 +95,7 @@
:type="formErrors['display'] != undefined ? 'is-danger' : ''"
:message="formErrors['display'] != undefined ? formErrors['display'] : ''"
:addons="false">
<label class="label is-inline">
<label class="label is-inline-block">
{{ $i18n.get('label_display') }}
<help-button
:title="$i18n.getHelperTitle('metadata', 'display')"
@ -124,7 +139,7 @@
</b-field>
<b-field :addons="false">
<label class="label is-inline">{{ $i18n.get('label_options') }}</label>
<label class="label is-inline-block">{{ $i18n.get('label_options') }}</label>
<b-field
:type="formErrors['required'] != undefined ? 'is-danger' : ''"
:message="formErrors['required'] != undefined ? formErrors['required'] : ''">
@ -134,7 +149,7 @@
v-model="editForm.required"
true-value="yes"
false-value="no"
class="is-inline"
class="is-inline-block"
name="required">
{{ $i18n.get('label_required') }}
<help-button
@ -153,7 +168,7 @@
v-model="editForm.multiple"
true-value="yes"
false-value="no"
class="is-inline"
class="is-inline-block"
name="multiple">
{{ $i18n.get('label_allow_multiple') }}
<help-button
@ -171,7 +186,7 @@
v-model="editForm.unique"
true-value="yes"
false-value="no"
class="is-inline"
class="is-inline-block"
name="collecion_key">
{{ $i18n.get('label_unique_value') }}
<help-button
@ -338,8 +353,8 @@
form.inCollapse {
padding: 1.0em 2.0em;
border-top: 1px solid $draggable-border-color;
border-bottom: 1px solid $draggable-border-color;
border-top: 1px solid $gray2;
border-bottom: 1px solid $gray2;
margin-top: 1.0em;
}

View File

@ -1,6 +1,6 @@
<template>
<div>
<div class="page-container primary-page">
<div class="page-container repository-level-page">
<tainacan-title />
<b-tabs v-model="activeTab">
<b-tab-item :label="$i18n.get('taxonomy')">

View File

@ -243,10 +243,24 @@
}
}
@keyframes enter {
from {
opacity: 0;
transform: translate(-40px,0);
}
to {
opacity: 1;
transform: translate(0px,0);
}
}
form {
padding: 2.0rem 0rem 1rem 3rem;
border-left: 1px solid $draggable-border-color;
margin-top: 1.0em;
padding: 1.7rem 0 1.5rem 1.5rem;
border-left: 1px solid $gray2;
margin-left: 0.75rem;
position: relative;
animation-name: enter;
animation-duration: 0.5s;
.tainacan-page-title {
margin-bottom: 40px;
@ -254,7 +268,7 @@
h2 {
font-size: 20px;
font-weight: 500;
color: $tertiary;
color: $blue5;
display: inline-block;
}
hr{
@ -283,7 +297,7 @@
font-weight: bold;
z-index: 99;
text-align: center;
color: gray;
color: $gray4;
}
#button-delete-header,
#button-edit-header {

View File

@ -64,7 +64,7 @@
</th>
<!-- Total Items -->
<th v-if="!isOnTrash">
<div class="th-wrap">{{ $i18n.get('label_total_items') }}</div>
<div class="th-wrap total-items-header">{{ $i18n.get('label_total_items') }}</div>
</th>
<th class="actions-header">
&nbsp;
@ -388,16 +388,16 @@ export default {
height: 40px;
.select-all {
color: $gray-light;
color: $gray4;
font-size: 14px;
&:hover {
color: $gray-light;
color: $gray4;
}
}
}
img.table-thumb {
border-radius: 50px !important;
.total-items-header {
text-align: right;
}
</style>

View File

@ -35,14 +35,20 @@
<div
class="active-filter-item"
:class="{
'not-sortable-item': filter.id == undefined || openedFilterId != '' || choosenMetadatum.name == filter.name,
'not-sortable-item': (filter.id == undefined || openedFilterId != '' || choosenMetadatum.name == filter.name || isUpdatingFiltersOrder == true),
'not-focusable-item': openedFilterId == filter.id,
'disabled-filter': filter.enabled == false
'disabled-filter': filter.enabled == false,
'inherited-filter': filter.collection_id != collectionId || isRepositoryLevel
}"
v-for="(filter, index) in activeFilterList"
:key="index">
<div class="handle">
<grip-icon/>
<span class="icon icon-level-identifier">
<i
:class="{ 'mdi-folder has-text-turquoise5': filter.collection_id == collectionId, 'mdi-folder-multiple has-text-blue5': filter.collection_id != collectionId }"
class="mdi" />
</span>
<span
class="filter-name"
:class="{'is-danger': formWithErrors == filter.id }">
@ -64,7 +70,8 @@
<span
class="controls"
v-if="filter.filter_type != undefined">
<b-switch
<b-switch
:disabled="isUpdatingFiltersOrder"
size="is-small"
:value="filter.enabled"
@input="onChangeEnable($event, index)"/>
@ -130,7 +137,7 @@
</div>
<div class="column available-metadata-area">
<div class="field" >
<h3 class="label"> {{ $i18n.get('label_available_metadata') }}</h3>
<h3 class="label has-text-secondary"> {{ $i18n.get('label_available_metadata') }}</h3>
<draggable
v-if="availableMetadatumList.length > 0"
v-model="availableMetadatumList"
@ -141,12 +148,18 @@
}">
<div
class="available-metadatum-item"
:class="{'inherited-metadatum': metadatum.collection_id != collectionId || isRepositoryLevel}"
v-if="metadatum.enabled"
v-for="(metadatum, index) in availableMetadatumList"
:key="index"
@click.prevent="addMetadatumViaButton(metadatum, index)">
<grip-icon/>
<span class="metadatum-name">{{ metadatum.name }}</span>
<span class="icon icon-level-identifier">
<i
:class="{ 'mdi-folder has-text-turquoise5': metadatum.collection_id == collectionId, 'mdi-folder-multiple has-text-blue5': metadatum.collection_id != collectionId }"
class="mdi" />
</span>
<span class="metadatum-name">{{ metadatum.name }}</span>
</div>
</draggable>
@ -191,6 +204,7 @@ export default {
isLoadingFilters: false,
isLoadingFilterTypes: false,
isLoadingFilter: false,
iisUpdatingFiltersOrder: false,
openedFilterId: '',
formWithErrors: '',
editForms: {},
@ -276,7 +290,10 @@ export default {
for (let filter of this.activeFilterList) {
filtersOrder.push({'id': filter.id, 'enabled': filter.enabled});
}
this.updateCollectionFiltersOrder({ collectionId: this.collectionId, filtersOrder: filtersOrder });
this.isUpdatingFiltersOrder = true;
this.updateCollectionFiltersOrder({ collectionId: this.collectionId, filtersOrder: filtersOrder })
.then(() => this.isUpdatingFiltersOrder = false)
.catch(() => this.isUpdatingFiltersOrder = false);
},
updateListOfMetadata() {
@ -299,7 +316,10 @@ export default {
filtersOrder.push({'id': filter.id, 'enabled': filter.enabled});
}
filtersOrder[index].enabled = $event;
this.updateCollectionFiltersOrder({ collectionId: this.collectionId, filtersOrder: filtersOrder });
this.isUpdatingFiltersOrder = true;
this.updateCollectionFiltersOrder({ collectionId: this.collectionId, filtersOrder: filtersOrder })
.then(() => { this.isUpdatingFiltersOrder = false; })
.catch(() => { this.isUpdatingFiltersOrder = false; });
},
addMetadatumViaButton(metadatumType, metadatumIndex) {
this.availableMetadatumList.splice(metadatumIndex, 1);
@ -458,13 +478,6 @@ export default {
.catch(() => {
this.isLoadingFilters = false;
});
},
mounted() {
if (!this.isRepositoryLevel) {
document.getElementById('collection-page-container').addEventListener('scroll', ($event) => {
this.$emit('onShrinkHeader', ($event.target.scrollTop > 53));
});
}
}
}
</script>
@ -473,15 +486,6 @@ export default {
@import "../../scss/_variables.scss";
.page-title {
border-bottom: 1px solid $secondary;
h2 {
color: $tertiary;
font-weight: 500;
}
margin: 1em 0em 2.0em 0em;
}
.loading-spinner {
animation: spinAround 500ms infinite linear;
border: 2px solid #dbdbdb;
@ -532,8 +536,8 @@ export default {
padding-right: 6em;
}
.grip-icon {
fill: $gray;
top: 2px;
fill: $gray3;
top: 1px;
position: relative;
}
.filter-name {
@ -550,7 +554,7 @@ export default {
}
.label-details {
font-weight: normal;
color: $gray;
color: $gray3;
}
.not-saved {
font-style: italic;
@ -574,8 +578,8 @@ export default {
form {
padding: 1.0em 2.0em;
border-top: 1px solid $draggable-border-color;
border-bottom: 1px solid $draggable-border-color;
border-top: 1px solid $gray2;
border-bottom: 1px solid $gray2;
margin-top: 1.0em;
}
&.not-sortable-item, &.not-sortable-item:hover {
@ -583,7 +587,7 @@ export default {
background-color: white !important;
.handle .label-details, .handle .icon {
color: $gray !important;
color: $gray3 !important;
}
}
&.not-focusable-item, &.not-focusable-item:hover {
@ -593,11 +597,11 @@ export default {
color: $secondary;
}
.handle .label-details, .handle .icon {
color: $gray !important;
color: $gray3 !important;
}
}
&.disabled-metadatum {
color: $gray;
color: $gray3;
}
}
.active-filter-item:hover:not(.not-sortable-item) {
@ -609,7 +613,7 @@ export default {
fill: $white;
}
.label-details, .icon {
.label-details, .icon, .icon-level-identifier>i {
color: white !important;
}
@ -630,7 +634,7 @@ export default {
}
}
.sortable-ghost {
border: 1px dashed $draggable-border-color;
border: 1px dashed $gray2;
display: block;
padding: 0.7em 0.9em;
margin: 4px;
@ -638,7 +642,7 @@ export default {
position: relative;
.grip-icon {
fill: $gray;
fill: $gray3;
top: 2px;
position: relative;
}
@ -664,7 +668,6 @@ export default {
}
h3 {
color: $secondary;
margin: 0.2em 0em 1em -1.2em;
font-weight: 500;
}
@ -678,12 +681,12 @@ export default {
line-height: 1.3em;
height: 40px;
position: relative;
border: 1px solid $draggable-border-color;
border: 1px solid $gray2;
border-radius: 1px;
transition: left 0.2s ease;
.grip-icon {
fill: $gray;
fill: $gray3;
top: -3px;
position: relative;
display: inline-block;
@ -699,7 +702,7 @@ export default {
font-weight: bold;
margin-left: 0.4em;
display: inline-block;
max-width: 200px;
max-width: 180px;
}
&:after,
&:before {
@ -721,7 +724,7 @@ export default {
}
&:before {
top: -1px;
border-color: transparent $draggable-border-color transparent transparent;
border-color: transparent $gray2 transparent transparent;
border-right-width: 16px;
border-top-width: 20px;
border-bottom-width: 20px;
@ -744,11 +747,45 @@ export default {
&:before {
border-color: transparent $secondary transparent transparent;
}
.icon-level-identifier>i {
color: white !important;
}
.grip-icon {
fill: white !important;
}
}
}
.inherited-filter {
&.active-filter-item:hover:not(.not-sortable-item) {
background-color: $blue5;
border-color: $blue5;
.switch.is-small {
input[type="checkbox"] + .check {
background-color: $blue5 !important;
}
&:hover input[type="checkbox"] + .check {
background-color: $blue5 !important;
}
}
}
}
.inherited-metadatum {
&.available-metadatum-item:hover {
background-color: $blue5 !important;
border-color: $blue5 !important;
&:after {
border-color: transparent $blue5 transparent transparent !important;
}
&:before {
border-color: transparent $blue5 transparent transparent !important;
}
}
}
</style>

View File

@ -59,17 +59,15 @@
<div class="metadata-title">
<p
v-tooltip="{
content: item.metadata != undefined ? renderMetadata(item.metadata, column) : '',
content: item.title != undefined ? item.title : '',
html: true,
autoHide: false,
placement: 'auto-start'
}"
v-for="(column, index) in tableMetadata"
:key="index"
v-if="column.display && column.metadata_type_object != undefined && (column.metadata_type_object.related_mapped_prop == 'title')"
@click="goToItemPage(item)"
v-html="item.metadata != undefined ? renderMetadata(item.metadata, column) : ''"/>
</div>
}"
@click="goToItemPage(item)">
{{ item.title != undefined ? item.title : '' }}
</p>
</div>
<!-- Thumbnail -->
<a
v-if="item.thumbnail != undefined"
@ -103,6 +101,71 @@
</div>
</div>
<!-- MASONRY VIEW MODE -->
<masonry
v-if="viewMode == 'masonry'"
:cols="{default: 7, 1919: 6, 1407: 5, 1215: 4, 1023: 3, 767: 2, 343: 1}"
:gutter="30"
class="tainacan-masonry-container">
<div
:key="index"
v-for="(item, index) of items"
:class="{ 'selected-masonry-item': selectedItems[index] }"
class="tainacan-masonry-item">
<!-- Checkbox -->
<div
:class="{ 'is-selecting': isSelectingItems }"
class="masonry-item-checkbox">
<label
tabindex="0"
class="b-checkbox checkbox is-small">
<input
type="checkbox"
v-model="selectedItems[index]">
<span class="check" />
<span class="control-label" />
</label>
</div>
<!-- Title -->
<div
@click="goToItemPage(item)"
class="metadata-title">
<p>{{ item.title != undefined ? item.title : '' }}</p>
</div>
<!-- Thumbnail -->
<img
@click="goToItemPage(item)"
v-if="item.thumbnail != undefined"
:src="item['thumbnail'].medium_large ? item['thumbnail'].medium_large : thumbPlaceholderPath">
<!-- Actions -->
<div
v-if="item.current_user_can_edit"
class="actions-area"
:label="$i18n.get('label_actions')">
<a
id="button-edit"
:aria-label="$i18n.getFrom('items','edit_item')"
@click.prevent.stop="goToItemEditPage(item)">
<b-icon
type="is-secondary"
icon="pencil"/>
</a>
<a
id="button-delete"
:aria-label="$i18n.get('label_button_delete')"
@click.prevent.stop="deleteOneItem(item.id)">
<b-icon
type="is-secondary"
:icon="!isOnTrash ? 'delete' : 'delete-forever'"/>
</a>
</div>
</div>
</masonry>
<!-- CARDS VIEW MODE -->
<div
class="tainacan-cards-container"
@ -126,16 +189,14 @@
<div class="metadata-title">
<p
v-tooltip="{
content: item.metadata != undefined ? renderMetadata(item.metadata, column) : '',
content: item.title != undefined ? item.title : '',
html: true,
autoHide: false,
placement: 'auto-start'
}"
v-for="(column, index) in tableMetadata"
:key="index"
v-if="column.display && column.metadata_type_object != undefined && (column.metadata_type_object.related_mapped_prop == 'title')"
@click="goToItemPage(item)"
v-html="item.metadata != undefined ? renderMetadata(item.metadata, column) : ''" />
}"
@click="goToItemPage(item)">
{{ item.title != undefined ? item.title : '' }}
</p>
</div>
<!-- Actions -->
<div
@ -167,38 +228,41 @@
<img
v-if="item.thumbnail != undefined"
:src="item['thumbnail'].medium_large ? item['thumbnail'].medium_large : thumbPlaceholderPath">
:src="item['thumbnail'].medium ? item['thumbnail'].medium : thumbPlaceholderPath">
<div class="list-metadata media-body">
<!-- Description -->
<p
v-tooltip="{
content: item.metadata != undefined ? renderMetadata(item.metadata, column) : '',
content: item.description != undefined ? item.description : '',
html: true,
autoHide: false,
placement: 'auto-start'
}"
v-if="
column.metadata_type_object != undefined &&
(column.metadata_type_object.related_mapped_prop == 'description')"
v-for="(column, index) in tableMetadata"
:key="index"
class="metadata-description"
v-html="(item.metadata != undefined && item.metadata[column.slug] != undefined) ? getLimitedDescription(item.metadata[column.slug].value_as_string) : ''" />
v-html="item.description != undefined ? getLimitedDescription(item.description) : ''" />
<br>
<!-- Author and Creation Date-->
<!-- Author-->
<p
v-tooltip="{
content: column.metadatum == 'row_author' || column.metadatum == 'row_creation',
content: item.author_name != undefined ? item.author_name : '',
html: false,
autoHide: false,
placement: 'auto-start'
}"
v-for="(column, index) in tableMetadata"
:key="index"
v-if="column.metadatum == 'row_author' || column.metadatum == 'row_creation'"
class="metadata-author-creation">
{{ column.metadatum == 'row_author' ? $i18n.get('info_created_by') + ' ' + item[column.slug] : $i18n.get('info_date') + ' ' + item[column.slug] }}
{{ $i18n.get('info_created_by') + ' ' + (item.author_name != undefined ? item.author_name : '') }}
</p>
<!-- Creation Date-->
<p
v-tooltip="{
content: item.creation_date != undefined ? item.creation_date : '',
html: false,
autoHide: false,
placement: 'auto-start'
}"
class="metadata-author-creation">
{{ $i18n.get('info_date') + ' ' + (item.creation_date != undefined ? item.creation_date : '') }}
</p>
</div>
</div>
@ -597,6 +661,7 @@ export default {
<style lang="scss" scoped>
@import "../../scss/_variables.scss";
@import "../../scss/_view-mode-masonry.scss";
@import "../../scss/_view-mode-grid.scss";
@import "../../scss/_view-mode-cards.scss";
@import "../../scss/_view-mode-records.scss";
@ -608,10 +673,10 @@ export default {
height: 40px;
.select-all {
color: $gray-light;
color: $gray4;
font-size: 14px;
&:hover {
color: $gray-light;
color: $gray4;
}
}
}

View File

@ -39,14 +39,20 @@
<div
class="active-metadatum-item"
:class="{
'not-sortable-item': metadatum.id == undefined || openedMetadatumId != '' ,
'not-sortable-item': metadatum.id == undefined || openedMetadatumId != '' || isUpdatingMetadataOrder,
'not-focusable-item': openedMetadatumId == metadatum.id,
'disabled-metadatum': metadatum.enabled == false
'disabled-metadatum': metadatum.enabled == false,
'inherited-metadatum': metadatum.collection_id != collectionId || isRepositoryLevel
}"
v-for="(metadatum, index) in activeMetadatumList"
:key="index">
<div class="handle">
<grip-icon/>
<span class="icon icon-level-identifier">
<i
:class="{ 'mdi-folder has-text-turquoise5': metadatum.collection_id == collectionId, 'mdi-folder-multiple has-text-blue5': metadatum.collection_id != collectionId }"
class="mdi" />
</span>
<span
class="metadatum-name"
:class="{'is-danger': formWithErrors == metadatum.id }">
@ -69,6 +75,7 @@
class="controls"
v-if="metadatum.id !== undefined">
<b-switch
:disabled="isUpdatingMetadataOrder"
size="is-small"
:value="metadatum.enabled"
@input="onChangeEnable($event, index)"/>
@ -113,7 +120,7 @@
<div class="column available-metadata-area" >
<div class="field">
<h3 class="label">{{ $i18n.get('label_available_metadata_types') }}</h3>
<h3 class="label has-text-secondary">{{ $i18n.get('label_available_metadata_types') }}</h3>
<draggable
v-model="availableMetadatumList"
:options="{
@ -124,10 +131,10 @@
<div
@click.prevent="addMetadatumViaButton(metadatum)"
class="available-metadatum-item"
:class="{ 'hightlighted-metadatum' : hightlightedMetadatum == metadatum.name }"
:class="{ 'hightlighted-metadatum' : hightlightedMetadatum == metadatum.name, 'inherited-metadatum': isRepositoryLevel }"
v-for="(metadatum, index) in availableMetadatumList"
:key="index">
<grip-icon/>
<grip-icon/>
<span class="metadatum-name">{{ metadatum.name }}</span>
<span
class="loading-spinner"
@ -345,6 +352,7 @@ export default {
isLoadingMetadatumTypes: true,
isLoadingMetadata: false,
isLoadingMetadatum: false,
isUpdatingMetadataOrder: false,
openedMetadatumId: '',
formWithErrors: '',
hightlightedMetadatum: '',
@ -443,7 +451,10 @@ export default {
for (let metadatum of this.activeMetadatumList) {
metadataOrder.push({'id': metadatum.id, 'enabled': metadatum.enabled});
}
this.updateCollectionMetadataOrder({ collectionId: this.collectionId, metadataOrder: metadataOrder });
this.isUpdatingMetadataOrder = true;
this.updateCollectionMetadataOrder({ collectionId: this.collectionId, metadataOrder: metadataOrder })
.then(() => this.isUpdatingMetadataOrder = false)
.catch(() => this.isUpdatingMetadataOrder = false);
},
onChangeEnable($event, index) {
let metadataOrder = [];
@ -451,7 +462,10 @@ export default {
metadataOrder.push({'id': metadatum.id, 'enabled': metadatum.enabled});
}
metadataOrder[index].enabled = $event;
this.updateCollectionMetadataOrder({ collectionId: this.collectionId, metadataOrder: metadataOrder });
this.isUpdatingMetadataOrder = true;
this.updateCollectionMetadataOrder({ collectionId: this.collectionId, metadataOrder: metadataOrder })
.then(() => this.isUpdatingMetadataOrder = false)
.catch(() => this.isUpdatingMetadataOrder = false);
},
addMetadatumViaButton(metadatumType) {
let lastIndex = this.activeMetadatumList.length;
@ -476,13 +490,24 @@ export default {
});
},
removeMetadatum(removedMetadatum) {
this.deleteMetadatum({ collectionId: this.collectionId, metadatumId: removedMetadatum.id, isRepositoryLevel: this.isRepositoryLevel})
.then(() => {
if (!this.isRepositoryLevel)
this.updateMetadataOrder();
})
.catch(() => {
});
this.$modal.open({
parent: this,
component: CustomDialog,
props: {
icon: 'alert',
title: this.$i18n.get('label_warning'),
message: this.$i18n.get('info_warning_metadatum_delete'),
onConfirm: () => {
this.deleteMetadatum({ collectionId: this.collectionId, metadatumId: removedMetadatum.id, isRepositoryLevel: this.isRepositoryLevel})
.then(() => {
if (!this.isRepositoryLevel)
this.updateMetadataOrder();
})
.catch(() => {
});
},
}
});
},
editMetadatum(metadatum) {
// Closing collapse
@ -734,13 +759,6 @@ export default {
.catch(() => {
this.isLoadingMetadatumMappers = false;
});
},
mounted() {
if (!this.isRepositoryLevel) {
document.getElementById('collection-page-container').addEventListener('scroll', ($event) => {
this.$emit('onShrinkHeader', ($event.target.scrollTop > 53));
});
}
}
}
</script>
@ -752,7 +770,7 @@ export default {
.page-title {
border-bottom: 1px solid $secondary;
h2 {
color: $tertiary;
color: $blue5;
font-weight: 500;
}
margin: 1em 0em 2.0em 0em;
@ -818,8 +836,8 @@ export default {
padding-right: 6em;
}
.grip-icon {
fill: $gray;
top: 2px;
fill: $gray3;
top: 1px;
position: relative;
}
.metadatum-name {
@ -836,7 +854,7 @@ export default {
}
.label-details {
font-weight: normal;
color: $gray;
color: $gray3;
}
.not-saved {
font-style: italic;
@ -862,8 +880,8 @@ export default {
cursor: default;
background-color: white !important;
.handle .label-details, .handle .icon {
color: $gray !important;
.handle .label-details, .handle .icon, {
color: $gray3 !important;
}
}
&.not-focusable-item, &.not-focusable-item:hover {
@ -873,11 +891,11 @@ export default {
color: $secondary;
}
.handle .label-details, .handle .icon {
color: $gray !important;
color: $gray3 !important;
}
}
&.disabled-metadatum {
color: $gray;
color: $gray3;
}
}
.active-metadatum-item:hover:not(.not-sortable-item) {
@ -885,7 +903,7 @@ export default {
border-color: $secondary;
color: white !important;
.label-details, .icon, .not-saved {
.label-details, .icon, .not-saved, .icon-level-identifier>i {
color: white !important;
}
@ -910,7 +928,7 @@ export default {
}
}
.sortable-ghost {
border: 1px dashed $draggable-border-color;
border: 1px dashed $gray2;
display: block;
padding: 0.7em 0.9em;
margin: 4px;
@ -942,7 +960,6 @@ export default {
}
h3 {
color: $secondary;
margin: 0.2em 0em 1em -1.2em;
font-weight: 500;
}
@ -956,12 +973,12 @@ export default {
line-height: 1.3em;
height: 40px;
position: relative;
border: 1px solid $draggable-border-color;
border: 1px solid $gray2;
border-radius: 1px;
transition: left 0.2s ease;
.grip-icon {
fill: $gray;
fill: $gray3;
top: -3px;
position: relative;
display: inline-block;
@ -999,7 +1016,7 @@ export default {
}
&:before {
top: -1px;
border-color: transparent $draggable-border-color transparent transparent;
border-color: transparent $gray2 transparent transparent;
border-right-width: 16px;
border-top-width: 20px;
border-bottom-width: 20px;
@ -1101,6 +1118,33 @@ export default {
}
}
.inherited-metadatum {
&.active-metadatum-item:hover:not(.not-sortable-item) {
background-color: $blue5;
border-color: $blue5;
.switch.is-small {
input[type="checkbox"] + .check {
background-color: $blue5 !important;
}
&:hover input[type="checkbox"] + .check {
background-color: $blue5 !important;
}
}
}
&.available-metadatum-item:hover {
background-color: $blue5 !important;
border-color: $blue5 !important;
&:after {
border-color: transparent $blue5 transparent transparent !important;
}
&:before {
border-color: transparent $blue5 transparent transparent !important;
}
}
}
#mappers-options-dropdown {
background-color: transparent;
color: #fff;

View File

@ -0,0 +1,402 @@
<template>
<div
v-if="processes.length > 0 && !isLoading"
class="table-container">
<!--
<div class="selection-control">
<div class="field select-all is-pulled-left">
<span>
<b-checkbox
@click.native="selectAllOnPage()"
:value="allOnPageSelected">{{ $i18n.get('label_select_all_processes_page') }}</b-checkbox>
</span>
</div>
<div class="field is-pulled-right">
<b-dropdown
position="is-bottom-left"
:disabled="!isSelecting"
id="bulk-actions-dropdown">
<button
class="button is-white"
slot="trigger">
<span>{{ $i18n.get('label_bulk_actions') }}</span>
<b-icon icon="menu-down"/>
</button>
<b-dropdown-item
id="item-delete-selected-items"
@click="deleteSelected()">
{{ $i18n.get('label_delete_selected_processes') }}
</b-dropdown-item>
<b-dropdown-item disabled>{{ $i18n.get('label_edit_selected_processes') + ' (Not ready)' }}
</b-dropdown-item>
</b-dropdown>
</div>
</div>
-->
<div class="table-wrapper">
<table class="tainacan-table">
<thead>
<tr>
<!-- Checking list -->
<!-- <th> -->
<!-- &nbsp; -->
<!-- nothing to show on header -->
<!-- </th> -->
<!-- Name -->
<th>
<div class="th-wrap">{{ $i18n.get('label_name') }}</div>
</th>
<!-- Progress -->
<th>
<div class="th-wrap">{{ $i18n.get('label_progress') }}</div>
</th>
<!-- Queued on -->
<th>
<div class="th-wrap">{{ $i18n.get('label_queued_on') }}</div>
</th>
<!-- Last Processed on -->
<th>
<div class="th-wrap">{{ $i18n.get('label_last_processed_on') }}</div>
</th>
<!-- Logs -->
<th>
<div class="th-wrap">{{ $i18n.get('label_log_file') }}</div>
</th>
<!-- Status -->
<th>
<div class="th-wrap">{{ $i18n.get('label_status') }}</div>
</th>
</tr>
</thead>
<tbody>
<tr
:class="{ 'selected-row': selected[index], 'highlighted-process': highlightedProcess == bgProcess.ID }"
:key="index"
v-for="(bgProcess, index) of processes">
<!-- Checking list -->
<!-- <td
:class="{ 'is-selecting': isSelecting }"
class="checkbox-cell">
<b-checkbox
size="is-small"
v-model="selected[index]"/>
</td> -->
<!-- Name -->
<td
class="column-default-width column-main-content"
:label="$i18n.get('label_name')"
:aria-label="$i18n.get('label_name') + ': ' + bgProcess.name">
<p
v-tooltip="{
content: bgProcess.name ? bgProcess.name : $i18n.get('label_unamed_process'),
autoHide: false,
placement: 'auto-start'
}">
{{ bgProcess.name ? bgProcess.name : $i18n.get('label_unamed_process') }}</p>
</td>
<!-- Progress -->
<td
class="column-default-width"
:label="$i18n.get('label_progress')"
:aria-label="$i18n.get('label_progress') + ': ' + bgProcess.progress_label ? bgProcess.progress_label + (bgProcess.progress_value ? ' (' + bgProcess.progress_value + '%)' : '') : $i18n.get('label_no_details_of_process')">
<p
v-tooltip="{
content: bgProcess.progress_label ? bgProcess.progress_label : $i18n.get('label_no_details_of_process'),
autoHide: false,
placement: 'auto-start'
}">
<span :class="{'occluding-content': bgProcess.progress_value }">{{ bgProcess.progress_label ? bgProcess.progress_label : $i18n.get('label_no_details_of_process') }}</span>
<span>{{ bgProcess.progress_value ? ' (' + bgProcess.progress_value + '%)' : '' }}</span>
</p>
</td>
<!-- Queued on -->
<td
class="column-small-width"
:label="$i18n.get('label_queued_on')"
:aria-label="$i18n.get('label_queued_on') + ' ' + getDate(bgProcess.queued_on)">
<p
v-tooltip="{
content: getDate(bgProcess.queued_on),
autoHide: false,
placement: 'auto-start'
}">
{{ getDate(bgProcess.queued_on) }}</p>
</td>
<!-- Last processed on -->
<td
class="column-small-width"
:label="$i18n.get('label_last_processed_on')"
:aria-label="$i18n.get('label_last_processed_on') + ' ' + getDate(bgProcess.processed_last)">
<p
v-tooltip="{
content: getDate(bgProcess.processed_last),
autoHide: false,
placement: 'auto-start'
}">
{{ getDate(bgProcess.processed_last) }}</p>
</td>
<!-- Logs -->
<td
class="column-needed-width"
:label="$i18n.get('label_log_file')"
:aria-label="$i18n.get('label_log_gile')">
<p>
<a
v-if="bgProcess.log"
:href="bgProcess.log">{{ $i18n.get('label_log_file') }}</a>
<span v-if="bgProcess.error_log"> | </span>
<a
v-if="bgProcess.error_log"
class="has-text-danger"
:href="bgProcess.error_log">{{ $i18n.get('label_error_log_file') }}</a>
</p>
</td>
<!-- Status-->
<td
class="actions-cell column-small-width"
:label="$i18n.get('label_status')">
<div class="actions-container">
<span
v-if="bgProcess.done <= 0"
class="icon has-text-success loading-icon">
<div class="control has-icons-right is-loading is-clearfix" />
</span>
<!-- <span
v-if="bgProcess.done <= 0"
class="icon has-text-gray action-icon"
@click="pauseProcess(index)">
<i class="mdi mdi-18px mdi-pause-circle"/>
</span>
<span
v-if="bgProcess.done <= 0"
class="icon has-text-gray action-icon"
@click="pauseProcess(index)">
<i class="mdi mdi-18px mdi-close-circle-outline"/>
</span> -->
<span
v-tooltip="{
content: $i18n.get('label_process_completed'),
autoHide: false,
placement: 'auto-start'
}"
v-if="bgProcess.done > 0 && !bgProcess.error_log"
class="icon has-text-success">
<i class="mdi mdi-18px mdi-checkbox-marked-circle"/>
</span>
<span
v-tooltip="{
content: $i18n.get('label_process_failed'),
autoHide: false,
placement: 'auto-start'
}"
v-if="bgProcess.done > 0 && bgProcess.error_log"
class="icon has-text-danger">
<i class="mdi mdi-18px mdi-sync-alert" />
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script>
import { mapActions } from 'vuex';
import CustomDialog from '../other/custom-dialog.vue';
export default {
name: 'List',
data() {
return {
selected: [],
allOnPageSelected: false,
isSelecting: false,
highlightedProcess: ''
}
},
props: {
isLoading: false,
total: 0,
page: 1,
processesPerPage: 12,
processes: Array
},
watch: {
processes() {
this.selected = [];
for (let i = 0; i < this.processes.length; i++)
this.selected.push(false);
},
selected() {
let allSelected = true;
let isSelecting = false;
for (let i = 0; i < this.selected.length; i++) {
if (this.selected[i] == false) {
allSelected = false;
} else {
isSelecting = true;
}
}
this.allOnPageSelected = allSelected;
this.isSelecting = isSelecting;
}
},
methods: {
...mapActions('bgprocess', [
'deleteProcess'
]),
selectAllOnPage() {
for (let i = 0; i < this.selected.length; i++)
this.selected.splice(i, 1, !this.allOnPageSelected);
},
deleteOneProcess(processId) {
this.$modal.open({
parent: this,
component: CustomDialog,
props: {
icon: 'alert',
title: this.$i18n.get('label_warning'),
message: this.$i18n.get('info_warning_Process_delete'),
onConfirm: () => {
this.deleteProcess({ processId: processId })
.then(() => {
// this.$toast.open({
// duration: 3000,
// message: this.$i18n.get('info_taxonomy_deleted'),
// position: 'is-bottom',
// type: 'is-secondary',
// queue: true
// });
for (let i = 0; i < this.selected.length; i++) {
if (this.selected[i].id === this.taxonomyId)
this.selected.splice(i, 1);
}
})
.catch(() => {
// this.$toast.open({
// duration: 3000,
// message: this.$i18n.get('info_error_deleting_taxonomy'),
// position: 'is-bottom',
// type: 'is-danger',
// queue: true
// });
});
}
}
});
},
deleteSelected() {
this.$modal.open({
parent: this,
component: CustomDialog,
props: {
icon: 'alert',
title: this.$i18n.get('label_warning'),
message: this.$i18n.get('info_warning_selected_processes_delete'),
onConfirm: () => {
for (let i = 0; i < this.processes.length; i++) {
if (this.selected[i]) {
this.deleteTaxonomy({ processId: this.processes[i].id })
.then(() => {
// this.load();
// this.$toast.open({
// duration: 3000,
// message: this.$i18n.get('info_taxonomy_deleted'),
// position: 'is-bottom',
// type: 'is-secondary',
// queue: false
// })
}).catch(() => {
// this.$toast.open({
// duration: 3000,
// message: this.$i18n.get('info_error_deleting_taxonomy'),
// position: 'is-bottom',
// type: 'is-danger',
// queue: false
// });
});
}
}
this.allOnPageSelected = false;
}
}
});
},
getDate(rawDate) {
let date = new Date(rawDate);
if (date instanceof Date && !isNaN(date))
return date.toLocaleString();
else
return this.$i18n.get('info_unknown_date');
},
pauseProcess() {
}
},
mounted() {
if (this.$route.query.highlight) {
this.highlightedProcess = this.$route.query.highlight;
}
}
}
</script>
<style lang="scss" scoped>
@import "../../scss/_variables.scss";
.selection-control {
padding: 6px 0px 0px 12px;
background: white;
height: 40px;
.select-all {
color: $gray4;
font-size: 14px;
&:hover {
color: $gray4;
}
}
}
.loading-icon .control.is-loading::after {
position: relative !important;
right: 0;
top: 0;
}
@keyframes highlight {
from {
background-color: $blue1;
}
to {
background-color: $white;
}
}
.highlighted-process {
td, .checkbox-cell .checkbox, .actions-cell .actions-container {
transition: background-color 0.5s;
animation-name: highlight;
animation-duration: 1s;
animation-iteration-count: 2;
}
}
.occluding-content {
width: calc(100% - 40px);
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
top: 4px;
position: relative;
}
</style>

View File

@ -275,10 +275,10 @@
height: 40px;
.select-all {
color: $gray-light;
color: $gray4;
font-size: 14px;
&:hover {
color: $gray-light;
color: $gray4;
}
}
}

View File

@ -1,40 +1,61 @@
<template>
<div>
<div class="terms-list-header">
<button
class="button is-secondary"
type="button"
@click="addNewTerm()"
:disabled="isEditingTerm">
{{ $i18n.get('label_new_term') }}
</button>
<b-field class="order-area">
<button
:disabled="orderedTermsList.length <= 0 || isLoadingTerms || isEditingTerm || order == 'asc'"
class="button is-white is-small"
@click="onChangeOrder('asc')">
<b-icon
class="gray-icon"
icon="sort-ascending"/>
</button>
<button
:disabled="orderedTermsList.length <= 0 || isLoadingTerms || isEditingTerm || order == 'desc'"
class="button is-white is-small"
@click="onChangeOrder('desc')">
<b-icon
class="gray-icon"
icon="sort-descending"/>
</button>
</b-field>
<div class="search-area is-hidden-mobile">
<div class="control has-icons-right is-small is-clearfix">
<input
class="input is-small"
:placeholder="$i18n.get('instruction_search')"
type="search"
autocomplete="on"
v-model="searchQuery"
@keyup.enter="loadTerms(0)"
:disabled="isEditingTerm">
<span
@click="loadTerms(0)"
class="icon is-right">
<i class="mdi mdi-magnify" />
</span>
</div>
</div>
</div>
<div class="columns">
<div class="column">
<button
class="button is-secondary"
type="button"
@click="addNewTerm()">
{{ $i18n.get('label_new_term') }}
</button>
<b-field class="order-area">
<button
:disabled="orderedTermsList.length <= 0 || isLoadingTerms || isEditingTerm"
class="button is-white is-small"
@click="onChangeOrder()">
<b-icon
class="gray-icon"
:icon="order === 'ASC' ? 'sort-ascending' : 'sort-descending'"/>
</button>
</b-field>
<br>
<br>
<div
class="term-item"
:class="{
'not-sortable-item': term.opened || !term.saved,
'not-focusable-item': term.opened
'opened-term': term.opened
}"
:style="{'margin-left': (term.depth * 40) + 'px'}"
v-for="(term, index) in orderedTermsList"
:key="term.id">
<a
class="is-medium"
type="button"
@click="addNewChildTerm(term, index)">
<b-icon icon="plus-circle"/>
</a>
<span
class="term-name"
:class="{'is-danger': formWithErrors == term.id }">
@ -42,7 +63,9 @@
</span>
<span
v-if="term.id != undefined"
class="label-details">
class="label-details"
@click.prevent="isEditingTerm && term.total_children > 0 ? null : loadTerms(term.id)">
{{ term.total_children > 0 ? term.total_children + ' ' + $i18n.get('label_children_terms') : '' }}
<span
class="not-saved"
v-if="!term.saved">
@ -51,15 +74,13 @@
</span>
<span class="controls" >
<!--
<button
class="button is-success is-small"
type="button"
:href="taxonomyPath + '/' + term.slug">
{{ $i18n.get('label_view_term') }}
</button>
-->
<a
@click="addNewChildTerm(term, index)"
:disabled="isEditingTerm">
<b-icon
size="is-small"
icon="plus-circle"/>
</a>
<a @click.prevent="editTerm(term, index)">
<b-icon
type="is-secondary"
@ -76,11 +97,12 @@
</div>
</div>
<div
class="column"
class="column edit-forms-list"
:key="index"
v-for="(term, index) in orderedTermsList"
v-show="term.opened">
<term-edition-form
:style="{ 'top': termEditionFormTop + 'px'}"
:taxonomy-id="taxonomyId"
@onEditionFinished="onTermEditionFinished()"
@onEditionCanceled="onTermEditionCanceled(term)"
@ -93,6 +115,7 @@
:active.sync="isLoadingTerms"
:can-cancel="false"/>
</div>
</div>
</template>
<script>
@ -108,7 +131,9 @@ export default {
isEditingTerm: false,
formWithErrors: '',
orderedTermsList: [],
order: 'asc'
order: 'asc',
termEditionFormTop: 0,
searchQuery: ''
}
},
props: {
@ -124,7 +149,7 @@ export default {
this.generateOrderedTerms();
},
taxonomyId() {
this.loadTerms();
this.loadTerms(0);
}
},
components: {
@ -134,16 +159,23 @@ export default {
...mapActions('taxonomy', [
'updateTerm',
'deleteTerm',
'fetchChildTerms',
'fetchTerms'
]),
...mapGetters('taxonomy',[
'getTerms'
]),
onChangeOrder() {
this.order == 'asc' ? this.order = 'desc' : this.order = 'asc';
this.loadTerms();
onChangeOrder(newOrder) {
this.order = newOrder;
this.loadTerms(0);
},
addNewTerm() {
if (this.isEditingTerm) {
let editingTermIndex = this.orderedTermsList.findIndex(anEditingTerm => anEditingTerm.opened == true);
if (editingTermIndex >= 0)
this.onTermEditionCanceled(this.orderedTermsList[editingTermIndex]);
}
let newTerm = {
taxonomyId: this.taxonomyId,
name: this.$i18n.get('label_term_without_name'),
@ -157,6 +189,12 @@ export default {
this.editTerm(newTerm, this.orderedTermsList.length - 1);
},
addNewChildTerm(parent, parentIndex) {
if (this.isEditingTerm) {
let editingTermIndex = this.orderedTermsList.findIndex(anEditingTerm => anEditingTerm.opened == true);
if (editingTermIndex >= 0)
this.onTermEditionCanceled(this.orderedTermsList[editingTermIndex]);
}
let newTerm = {
taxonomyId: this.taxonomyId,
name: this.$i18n.get('label_term_without_name'),
@ -170,7 +208,15 @@ export default {
this.editTerm(newTerm, parentIndex + 1);
},
editTerm(term, index) {
let container = document.getElementById('repository-container');
if (container && container.scrollTop && container.scrollTop > 80)
this.termEditionFormTop = container.scrollTop - 80;
else
this.termEditionFormTop = 0;
this.isEditingTerm = true;
if (!term.opened) {
for (let i = 0; i < this.orderedTermsList.length; i++) {
@ -201,18 +247,20 @@ export default {
} else {
let originalIndex = this.termsList.findIndex(anOriginalTerm => anOriginalTerm.id === term.id);
if (originalIndex >= 0) {
let originalTerm = JSON.parse(JSON.stringify(this.termsList[originalIndex]));
originalTerm.saved = term.saved;
originalTerm.opened = term.opened;
if (JSON.stringify(term) != JSON.stringify(originalTerm)) {
if (JSON.stringify(term) != JSON.stringify(originalTerm))
term.saved = false;
} else {
else
term.saved = true;
}
} else {
term.saved = false;
}
this.isEditingTerm = false;
}
term.opened = !term.opened;
@ -247,38 +295,49 @@ export default {
},
removeTerm(term) {
// If all checks passed, term can be deleted
if (term.id == 'new') {
let index = this.orderedTermsList.findIndex(deletedTerm => deletedTerm.id == 'new');
if (index >= 0) {
this.orderedTermsList.splice(index, 1);
}
} else {
this.deleteTerm({taxonomyId: this.taxonomyId, termId: term.id})
.then(() => {
this.$modal.open({
parent: this,
component: CustomDialog,
props: {
icon: 'alert',
title: this.$i18n.get('label_warning'),
message: this.$i18n.get('info_warning_selected_term_delete'),
onConfirm: () => {
// If all checks passed, term can be deleted
if (term.id == 'new') {
let index = this.orderedTermsList.findIndex(deletedTerm => deletedTerm.id == 'new');
if (index >= 0) {
this.orderedTermsList.splice(index, 1);
}
} else {
this.deleteTerm({taxonomyId: this.taxonomyId, termId: term.id})
.then(() => {
})
.catch((error) => {
this.$console.log(error);
});
})
.catch((error) => {
this.$console.log(error);
});
// Updates parent IDs for orphans
for (let orphanTerm of this.termsList) {
if (orphanTerm.parent == term.id) {
this.updateTerm({
taxonomyId: this.taxonomyId,
termId: orphanTerm.id,
name: orphanTerm.name,
description: orphanTerm.description,
parent: term.parent
})
.catch((error) => {
this.$console.log(error);
});
}
// Updates parent IDs for orphans
for (let orphanTerm of this.termsList) {
if (orphanTerm.parent == term.id) {
this.updateTerm({
taxonomyId: this.taxonomyId,
termId: orphanTerm.id,
name: orphanTerm.name,
description: orphanTerm.description,
parent: term.parent
})
.catch((error) => {
this.$console.log(error);
});
}
}
}
},
}
}
});
},
onTermEditionFinished() {
this.isEditingTerm = false;
@ -330,9 +389,11 @@ export default {
else
return term.name;
},
loadTerms() {
loadTerms(parentId) {
this.isLoadingTerms = true;
this.fetchTerms({ taxonomyId: this.taxonomyId, fetchOnly: '', search: '', all: '', order: this.order})
let search = (this.searchQuery != undefined && this.searchQuery != '') ? { searchterm: this.searchQuery } : '';
this.fetchChildTerms({ parentId: parentId, taxonomyId: this.taxonomyId, fetchOnly: '', search: search, all: '', order: this.order})
.then(() => {
// Fill this.form data with current data.
this.isLoadingTerms = false;
@ -345,7 +406,7 @@ export default {
},
created() {
if (this.taxonomyId !== String) {
this.loadTerms();
this.loadTerms(0);
}
}
@ -356,26 +417,69 @@ export default {
@import "../../scss/_variables.scss";
.order-area {
display: inline-block;
padding: 4px;
margin-left: 30px;
.terms-list-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
.gray-icon, .gray-icon .icon {
color: $tainacan-placeholder-color !important;
.order-area {
display: inline-flex !important;
padding: 4px;
margin-left: auto;
.gray-icon, .gray-icon .icon {
color: $gray4 !important;
}
.gray-icon .icon i::before, .gray-icon i::before {
font-size: 21px !important;
}
}
.gray-icon .icon i::before, .gray-icon i::before {
font-size: 21px !important;
.search-area {
display: inline-flex;
align-items: center;
.input {
border: 1px solid $gray2;
}
.control {
width: 100%;
.icon {
pointer-events: all;
cursor: pointer;
color: $blue5;
height: 27px;
font-size: 18px !important;
height: 2rem !important;
}
}
a {
margin-left: 12px;
white-space: nowrap;
}
}
}
.term-item {
font-size: 14px;
padding: 0.7em 0.9em;
margin: 4px;
padding: 0 0.75rem;
min-height: 40px;
display: block;
display: flex;
position: relative;
align-items: center;
&:hover {
background-color: $gray1 !important;
.controls {
visibility: visible;
opacity: 1.0;
}
&::before {
border-color: transparent transparent transparent $gray2 !important;
}
}
.handle {
padding-right: 6em;
@ -387,6 +491,8 @@ export default {
font-weight: bold;
margin-left: 0.4em;
margin-right: 0.4em;
display: inline-block;
max-width: 73%;
&.is-danger {
color: $danger !important;
@ -394,7 +500,7 @@ export default {
}
.label-details {
font-weight: normal;
color: $gray;
color: $gray3;
}
.not-saved {
font-style: italic;
@ -403,52 +509,57 @@ export default {
}
.controls {
position: absolute;
right: 5px;
top: 10px;
right: 0;
visibility: hidden;
opacity: 0.0;
background-color: $gray2;
padding: 0.4375rem 0.875rem;
margin-left: auto;
.icon {
bottom: 1px;
position: relative;
i, i:before { font-size: 20px; }
.mdi-plus-circle, .mdi-plus-circle:before{
font-size: 18px;
a {
margin: 0 0.375rem;
.icon {
bottom: 1px;
position: relative;
i, i:before { font-size: 20px; }
a {
margin-right: 8px;
}
}
a {
margin-right: 8px;
}
}
.button {
margin-right: 1em;
}
}
}
&.not-sortable-item, &.not-sortable-item:hover {
&.opened-term {
cursor: default;
background-color: white !important;
background-color: $blue1;
}
&.not-focusable-item, &.not-focusable-item:hover {
cursor: default;
.term-name {
color: $primary;
color: $blue3;
}
&:before {
content: '';
display: block;
position: absolute;
left: 100%;
right: -20px;
width: 0;
height: 0;
border-style: solid;
border-color: transparent transparent transparent $blue1;
border-left-width: 24px;
border-top-width: 20px;
border-bottom-width: 20px;
top: 0;
}
&:hover:before {
border-color: transparent transparent transparent $gray1;
}
}
}
// .term-item:hover:not(.not-sortable-item) {
// background-color: $secondary;
// border-color: $secondary;
// color: white !important;
// .label-details, .icon, .not-saved {
// color: white !important;
// }
// .grip-icon {
// fill: white;
// }
// }
.edit-forms-list {
padding-left: 0;
}
</style>

View File

@ -8,6 +8,7 @@
<aside class="menu">
<ul class="menu-list">
<li class="repository-label"><span>{{ $i18n.get('repository') }}</span></li>
<li>
<router-link
tag="a"
@ -36,9 +37,9 @@
tag="a"
to="/metadata"
:class="activeRoute == 'MetadataPage' ? 'is-active':''">
<b-icon
size="is-small"
icon="format-list-bulleted-type"/>
<span class="icon">
<i class="mdi mdi-format-list-bulleted-type"/>
</span>
<span class="menu-text">{{ $i18n.getFrom('metadata', 'name') }}</span>
</router-link>
</li>
@ -47,9 +48,9 @@
tag="a"
to="/filters"
:class="activeRoute == 'FiltersPage' ? 'is-active':''">
<b-icon
size="is-small"
icon="filter"/>
<span class="icon">
<i class="mdi mdi-filter"/>
</span>
<span class="menu-text">{{ $i18n.getFrom('filters', 'name') }}</span>
</router-link>
</li>
@ -58,9 +59,7 @@
tag="a"
to="/taxonomies"
:class="activeRoute == 'Page' ? 'is-active':''">
<b-icon
size="is-small"
icon="shape"/>
<taxonomies-icon />
<span class="menu-text">{{ $i18n.getFrom('taxonomies', 'name') }}</span>
</router-link>
</li>
@ -80,6 +79,8 @@
<script>
import ActivitiesIcon from '../other/activities-icon.vue';
import TaxonomiesIcon from '../other/taxonomies-icon.vue';
export default {
name: 'PrimaryMenu',
props: {
@ -87,7 +88,8 @@ export default {
activeRoute: '/collections'
},
components: {
ActivitiesIcon
ActivitiesIcon,
TaxonomiesIcon
},
}
</script>
@ -97,8 +99,8 @@ export default {
@import "../../scss/_variables.scss";
#primary-menu {
background-color: $primary;
padding: 100px 0px 0px 0px;
background-color: $blue4;
padding: 52px 0px 0px 0px;
-webkit-transition: max-width 0.2s linear; /* Safari */
transition: max-width 0.2s linear;
max-width: $side-menu-width;
@ -109,11 +111,24 @@ export default {
}
.menu {
padding-top: 10px;
padding-top: 0px;
}
.repository-label {
background-color: $blue5;
font-weight: bold;
font-size: 16px;
text-transform: uppercase;
color: white;
padding: 11px;
text-align: center;
opacity: 1;
visibility: visible;
transition: opacity 0.2s linear, visibility 0.2s linear;
-webkit-transition: opacity 0.2s linear, visibility 0.2s linear;
}
.separator {
height: 2px;
background-color: $separator-color;
background-color: transparent;
width: 100%;
margin: 24px 0;
}
@ -122,7 +137,7 @@ export default {
color: white;
white-space: nowrap;
overflow: hidden;
padding: 0.75em 1.8em;
padding: 9px 15px;
line-height: 1.5em;
border-radius: 0px;
-webkit-transition: padding 0.2s linear; /* Safari */
@ -130,16 +145,23 @@ export default {
.activities-icon {
fill: white;
margin-bottom: -4px;
}
.taxonomies-icon {
fill: white;
margin-bottom: -2px;
}
.icon {
height: auto;
width: auto;
i {
font-size: 18px !important;
}
}
}
a:hover, a.is-active {
background-color: $primary;
color: $tertiary;
.activities-icon {
fill: $tertiary;
}
background-color: $blue3;
}
a:focus {
box-shadow: none;
@ -154,12 +176,8 @@ export default {
}
&.is-compressed {
max-width: 45px;
a {
padding-left: 0.8em;
padding-right: 0.8em;
}
.menu-text {
max-width: 50px;
.menu-text, .repository-label>span {
visibility: hidden;
opacity: 0;
}
@ -168,7 +186,8 @@ export default {
@media screen and (max-width: 769px) {
width: 100% !important;
max-width: 100% !important;
padding-top: $header-height;
padding-top: 52px;
.menu {
padding-top: 0px;
}
@ -177,7 +196,7 @@ export default {
display: flex;
align-items: stretch;
justify-content: space-evenly;
.separator {
.separator, .repository-label {
display: none;
}
a {

View File

@ -0,0 +1,421 @@
<template>
<div
id="tainacan-subheader"
class="secondary-page">
<div class="back-button is-hidden-mobile">
<button
@click="$router.go(-1)"
class="button is-turquoise4">
<span class="icon">
<i class="mdi mdi-chevron-left"/>
</span>
</button>
</div>
<div class="level">
<div class="level-left">
<div class="back-button is-hidden-tablet level-item">
<button
@click="$router.go(-1)"
class="button is-turquoise4">
<span class="icon">
<i class="mdi mdi-chevron-left"/>
</span>
</button>
</div>
<div class="level-item">
<nav class="breadcrumbs">
<router-link
tag="a"
:to="$routerHelper.getCollectionsPath()">{{ $i18n.get('repository') }}</router-link> >
<span
v-for="(pathItem, index) in arrayRealPath"
:key="index">
<router-link
v-if="index < arrayRealPath.length - 1"
tag="a"
:to="'/' + arrayRealPath.slice(0, index + 1).join('/')">
{{ arrayViewPath[index] }}
</router-link>
<span v-if="index == arrayRealPath.length - 1">{{ arrayViewPath[index] }}</span>
<span v-if="index != arrayRealPath.length - 1 && arrayViewPath[index]"> > </span>
</span>
</nav>
</div>
</div>
<ul class="menu-list level-right">
<li
:class="activeRoute == 'ItemPage' || activeRoute == 'CollectionItemsPage' || activeRoute == 'ItemEditionForm' || activeRoute == 'ItemCreatePage' ? 'is-active':''"
class="level-item">
<router-link
tag="a"
:to="{ path: $routerHelper.getCollectionItemsPath(id, '') }"
:aria-label="$i18n.get('label_collection_items')">
<span class="icon">
<i class="mdi mdi-file-multiple"/>
</span>
<span class="menu-text">{{ $i18n.get('items') }}</span>
</router-link>
</li>
<li
:class="activeRoute == 'CollectionEditionForm' ? 'is-active':''"
class="level-item">
<router-link
tag="a"
:to="{ path: $routerHelper.getCollectionEditPath(id) }"
:aria-label="$i18n.get('label_settings')">
<span class="icon">
<i class="mdi mdi-settings"/>
</span>
<span class="menu-text">{{ $i18n.get('label_settings') }}</span>
</router-link>
</li>
<li
:class="activeRoute == 'MetadataList' ? 'is-active':''"
class="level-item">
<router-link
tag="a"
:to="{ path: $routerHelper.getCollectionMetadataPath(id) }"
:aria-label="$i18n.get('label_collection_metadata')">
<span class="icon">
<i class="mdi mdi-format-list-bulleted-type"/>
</span>
<span class="menu-text">{{ $i18n.getFrom('metadata', 'name') }}</span>
</router-link>
</li>
<li
:class="activeRoute == 'FiltersList' ? 'is-active':''"
class="level-item">
<router-link
tag="a"
:to="{ path: $routerHelper.getCollectionFiltersPath(id) }"
:aria-label="$i18n.get('label_collection_filters')">
<span class="icon">
<i class="mdi mdi-filter"/>
</span>
<span class="menu-text">{{ $i18n.getFrom('filters', 'name') }}</span>
</router-link>
</li>
<li
:class="activeRoute == 'CollectionEventsPage' ? 'is-active':''"
class="level-item">
<router-link
tag="a"
:to="{ path: $routerHelper.getCollectionEventsPath(id) }"
:aria-label="$i18n.get('label_collection_events')">
<activities-icon />
<span class="menu-text">{{ $i18n.get('events') }}</span>
</router-link>
</li>
</ul>
</div>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
import ActivitiesIcon from '../other/activities-icon.vue';
export default {
name: 'TainacanCollectionSubheader',
data(){
return {
activeRoute: 'ItemsList',
pageTitle: '',
arrayRealPath: [],
arrayViewPath: [],
activeRouteName: '',
}
},
components: {
ActivitiesIcon
},
props: {
id: Number,
},
watch: {
'$route' (to) {
this.activeRoute = to.name;
this.pageTitle = this.$route.meta.title;
this.arrayRealPath = to.path.split("/");
this.arrayRealPath = this.arrayRealPath.filter((item) => item.length != 0);
this.generateViewPath();
}
},
methods: {
...mapActions('collection', [
'fetchCollectionNameAndURL'
]),
...mapGetters('collection', [
'getCollectionName',
'getCollection'
]),
...mapActions('item', [
'fetchItemTitle'
]),
...mapGetters('item', [
'getItemTitle'
]),
...mapActions('taxonomy', [
'fetchTaxonomyName'
]),
...mapGetters('taxonomy', [
'getTaxonomyName'
]),
...mapActions('event', [
'fetchEventTitle'
]),
generateViewPath() {
for (let i = 0; i < this.arrayRealPath.length; i++) {
this.arrayViewPath.push('');
if (!isNaN(this.arrayRealPath[i]) && i > 0) {
switch(this.arrayRealPath[i-1]) {
case 'collections':
this.fetchCollectionNameAndURL(this.arrayRealPath[i])
.then(collection => this.arrayViewPath.splice(i, 1, collection.name))
.catch((error) => this.$console.error(error));
break;
case 'items':
this.fetchItemTitle(this.arrayRealPath[i])
.then(itemTitle => this.arrayViewPath.splice(i, 1, itemTitle))
.catch((error) => this.$console.error(error));
break;
case 'taxonomies':
this.fetchTaxonomyName(this.arrayRealPath[i])
.then(taxonomyName => this.arrayViewPath.splice(i, 1, taxonomyName))
.catch((error) => this.$console.error(error));
break;
case 'events':
this.fetchEventTitle(this.arrayRealPath[i])
.then(eventName => this.arrayViewPath.splice(i, 1, eventName))
.catch((error) => this.$console.error(error));
break;
}
} else {
if(this.arrayRealPath[i] == 'undefined'){
this.arrayViewPath.splice(i, 1, '');
} else {
this.arrayViewPath.splice(i, 1, this.$i18n.get(this.arrayRealPath[i]));
}
}
}
}
},
created() {
this.activeRoute = this.$route.name;
this.pageTitle = this.$route.meta.title;
this.arrayRealPath = this.$route.path.split("/");
this.arrayRealPath = this.arrayRealPath.filter((item) => item.length != 0);
this.generateViewPath();
}
}
</script>
<style lang="scss" scoped>
@import "../../scss/_variables.scss";
// Tainacan Header
#tainacan-subheader {
background-color: $gray1;
height: $subheader-height;
max-height: $subheader-height;
width: 100%;
overflow-y: hidden;
padding-top: 18px;
padding-bottom: 18px;
padding-right: $page-side-padding;
padding-left: 0;
margin: 0px;
vertical-align: middle;
left: 0;
right: 0;
z-index: 9;
display: flex;
align-items: center;
justify-content: space-between;
transition: padding 0.3s, height 0.3s;
h1 {
font-size: 18px;
font-weight: 500;
color: $blue5;
line-height: 22px;
margin-bottom: 12px;
max-width: 450px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.back-button {
padding: 0;
margin: 0;
height: 42px;
width: $page-side-padding;
min-width: $page-side-padding;
background-color: $gray1;
color: $turquoise4;
display: flex;
align-items: center;
button,
button:hover,
button:focus,
button:active {
width: 100%;
color: $turquoise4;
background-color: transparent !important;
border: none;
.icon i {
font-size: 34px;
}
}
}
.breadcrumbs {
font-size: 12px;
line-height: 12px;
color: #1d1d1d;
}
.level {
width: 100%;
}
li{
margin-right: 0px;
transition: background-color 0.2s ease;
// transition: max-width 0.4s ease-in , width 0.4s ease-in ;
// -webkit-transition: max-width 0.4s ease-in, width 0.4s ease-in ;
// overflow: hidden;
// max-width: 50px;
&.is-active {
background-color: $turquoise4;
a {
background-color: $turquoise4;
transition: color 0.2s ease;
color: white;
text-decoration: none;
}
svg.activities-icon {
transition: fill 0.2s ease;
fill: white !important;
}
}
&:hover:not(.is-active) {
// max-width: 100%;
// transition: max-width 0.4s ease-out 0.2s, width 0.4s ease-out 0.2s;
// -webkit-transition: max-width 0.4s ease-out 0.2s, width 0.4s ease-out 0.2s;
a {
background-color: transparent;
text-decoration: none;
color: $turquoise5;
}
svg.activities-icon {
fill: $turquoise5 !important;
}
// .menu-text {
// opacity: 1.0;
// width: 100%;
// right: 0%;
// visibility: visible;
// transition: opacity 0.4s ease-out 0.2s, visibility 0.4s ease-out 0.2s, width 0.4s ease-out 0.2s, right 0.4s ease-out 0.2s;
// -webkit-transition: opacity 0.4s ease-out 0.2s , visibility 0.4s ease-out 0.2s, width 0.4s ease-out 0.2s, right 0.4s ease-out 0.2s;
// }
}
a {
color: $gray4;
text-align: center;
white-space: nowrap;
padding: 10px;
min-width: 50px;
line-height: 22px;
border-radius: 0px;
position: relative;
align-items: center;
display: flex;
}
a:focus{
box-shadow: none;
}
.icon {
margin: 0;
padding: 0;
i {
font-size: 19px !important;
}
}
.menu-text {
margin-left: 8px;
font-size: 14px;
display: inline-flex;
// width: 0px;
// right: 100%;
// opacity: 0.0;
// visibility: hidden;
// transition: opacity 0.4s ease-in, visibility 0.4s ease-in , width 0.2s ease-in, right 0.2s ease-in;
// -webkit-transition: opacity 0.4s ease-in, visibility 0.4s ease-in, width 0.2s ease-in, right 0.2s ease-in;
}
}
@media screen and (max-width: 769px) {
width: 100% !important;
max-width: 100% !important;
height: 85px;
max-height: 85px;
padding: 0;
top: 206px;
margin-bottom: 0px !important;
.level-left {
margin-left: 0px !important;
display: flex;
padding: 0 1rem;
.level-item {
display: inline-flex;
}
}
.level-right {
margin-top: 0px;
flex-flow: wrap;
display: flex;
align-items: baseline;
justify-content: space-between;
.level-item {
margin-bottom: 0;
a {
padding: 0.5em 0.7em !important;
text-align: center;
}
.menu-text {
display: none;
}
}
}
}
}
</style>

View File

@ -1,8 +1,7 @@
<template>
<div
id="tainacan-header"
class="level"
:class="{'menu-compressed': isMenuCompressed}">
class="level is-mobile">
<div class="level-left">
<div class="level-item">
<router-link
@ -16,12 +15,21 @@
</div>
</div>
<div class="level-right">
<div class="search-area">
<div class="is-hidden-tablet">
<button
@click="$router.push($routerHelper.getItemsPath())"
class="button is-small is-white level-item">
<span class="icon is-right">
<i class="mdi mdi-24px mdi-magnify"/>
</span>
</button>
</div>
<div class="search-area is-hidden-mobile">
<div class="control has-icons-right is-small is-clearfix">
<input
autocomplete="on"
:placeholder="$i18n.get('instruction_search_in_repository')"
class="input is-small"
class="input is-small search-header"
type="search"
:value="searchQuery"
@input="futureSearchQuery = $event.target.value"
@ -31,31 +39,47 @@
@click="updateSearch()"
class="mdi mdi-magnify"/>
</span>
<!--<b-dropdown-->
<!--position="is-bottom-left">-->
<!--<b-icon-->
<!--class="is-right"-->
<!--slot="trigger"-->
<!--size="is-small"-->
<!--icon="menu-down"/>-->
<!--<b-dropdown-item>-->
<!--<p class="is-left">{{ $i18n.get('advanced_search') }}</p>-->
<!--<b-icon-->
<!--icon="menu-up"-->
<!--class="is-right" />-->
<!--</b-dropdown-item>-->
<!--<b-dropdown-item-->
<!--:custom="true">-->
<!--<advanced-search />-->
<!--</b-dropdown-item>-->
<!--</b-dropdown>-->
</div>
<a
:style="{color: 'white'}"
@click="toItemsPage">{{ $i18n.get('advanced_search') }}</a>
<b-dropdown
ref="advancedSearchShortcut"
class="advanced-search-header-dropdown"
position="is-bottom-left">
<a
class="advanced-search-text"
slot="trigger">
{{ $i18n.get('advanced_search') }}
</a>
<b-dropdown-item>
<div :style="{'height': '25px'}">
<p class="is-pulled-left advanced-search-text-di">{{ $i18n.get('advanced_search') }}</p>
<b-icon
style="margin-top: 2px"
type="is-secondary"
icon="menu-up"
class="is-pulled-right" />
</div>
<hr class="advanced-search-hr">
</b-dropdown-item>
<b-dropdown-item
style="padding-left: 0 !important; padding-right: 0 !important;"
:custom="true">
<advanced-search
:metadata="metadata"
:is-repository-level="true"
:is-header="true"/>
</b-dropdown-item>
</b-dropdown>
</div>
<button
@click="showProcesses = !showProcesses"
class="button is-small is-white level-item">
<b-icon icon="swap-vertical"/>
</button>
<processes-popup
v-if="showProcesses"
@closeProcessesPopup="showProcesses = false"/>
<a
:style="{color: 'white'}"
class="level-item"
:href="wordpressAdmin">
<b-icon icon="wordpress"/>
@ -65,37 +89,45 @@
</template>
<script>
import AdvancedSearch from '../advanced-search/advanced-search.vue';
import ProcessesPopup from '../other/processes-popup.vue';
import { mapActions } from 'vuex';
export default {
name: 'TainacanHeader',
data() {
return {
logoHeader: tainacan_plugin.base_url + '/admin/images/tainacan_logo_header.png',
logoHeader: tainacan_plugin.base_url + '/admin/images/tainacan_logo_header.svg',
wordpressAdmin: window.location.origin + window.location.pathname.replace('admin.php', ''),
searchQuery: '',
futureSearchQuery: '',
metadata: Array,
showProcesses: false,
hasNewProcess: false
}
},
components: {
AdvancedSearch,
ProcessesPopup
},
methods: {
toItemsPage() {
if(this.$route.path == '/items') {
this.$root.$emit('openAdvancedSearch', true);
}
if(this.$route.path != '/items') {
this.$router.push({
path: '/items',
query: {
advancedSearch: true
}
});
}
},
...mapActions('metadata', [
'fetchMetadata'
]),
// toItemsPage() {
// if(this.$route.path == '/items') {
// this.$root.$emit('openAdvancedSearch', true);
// }
//
// if(this.$route.path != '/items') {
// this.$router.push({
// path: '/items',
// query: {
// advancedSearch: true
// }
// });
// }
// },
updateSearch() {
if (this.$route.path != '/items') {
this.$router.push({
@ -106,19 +138,32 @@
this.$eventBusSearch.setSearchQuery(this.futureSearchQuery);
},
},
props: {
isMenuCompressed: false
}
created(){
this.$root.$on('closeAdvancedSearchShortcut', () => {
this.$refs.advancedSearchShortcut.toggle();
});
this.fetchMetadata({
collectionId: false,
isRepositoryLevel: true,
isContextEdit: false,
includeDisabled: false,
})
.then((metadata) => {
this.metadata = metadata;
});
},
}
</script>
<style lang="scss">
<style lang="scss" scoped>
@import "../../scss/_variables.scss";
// Tainacan Header
#tainacan-header {
background-color: $secondary;
background-color: white;
height: $header-height;
max-height: $header-height;
width: 100%;
@ -128,102 +173,80 @@
right: 0;
position: absolute;
z-index: 999;
color: white;
color: $blue5;
.level-left {
margin-left: -12px;
.level-item {
height: $header-height;
width: 180px;
transition: width 0.15s, background-color 0.2s;
-webkit-transition: width 0.15s background-color 0.2s;
width: $side-menu-width;
cursor: pointer;
background-color: #257787;
&:focus {
box-shadow: none;
}
.tainacan-logo {
max-height: 22px;
padding: 0px 24px;
transition: padding 0.15s;
-webkit-transition: padding linear 0.15s;
height: 24px;
padding: 0px;
margin-left: 19px;
}
}
}
.level-right {
padding-right: 12px;
padding-right: 14px;
.button, a {
color: $blue5 !important;
}
.button:hover, .button:active, .button:focus {
background-color: white !important;
}
.search-area {
display: flex;
align-items: center;
margin-right: 36px;
.control:not(.tnc-advanced-search-container) {
input {
border-width: 0 !important;
margin-right: 28px;
.control {
.search-header {
border: 1px solid $gray2 !important;
height: 27px;
font-size: 11px;
color: $gray-light;
transition: width linear 0.15s;
-webkit-transition: width linear 0.15s;
width: 160px;
width: 220px;
}
input:focus, input:active {
width: 220px !important;
.search-header:focus, .search-header:active {
width: 372px !important;
}
.icon {
.icon:not(.add-i) {
pointer-events: all;
color: $tertiary;
color: $blue5;
cursor: pointer;
height: 27px;
font-size: 18px;
width: 30px !important;
}
}
/*.dropdown-content {*/
/*width: 800px !important;*/
/*}*/
/*.dropdown-item:hover {*/
/*background-color: white;*/
/*}*/
a {
margin: 0px 12px;
font-size: 12px;
}
}
}
&.menu-compressed {
.level-left .level-item {
width: 220px;
background-color: $secondary;
.tainacan-logo {
padding: 0px 42px;
}
}
}
@media screen and (max-width: 769px) {
padding: 0px;
display: flex;
padding: 0;
height: 104px;
.level-left {
display: inline-block;
margin-left: 0px !important;
margin-left: 0 !important;
.level-item {
margin-left: 0px;
margin-left: 0;
}
}
.level-right {
margin-top: 0;
display: inline-block;
}
top: 0px;
margin-bottom: 0px !important;
top: 0;
margin-bottom: 0 !important;
}
}

View File

@ -0,0 +1,130 @@
<template>
<div
id="tainacan-repository-subheader"
class="level secondary-page"
:class="{'is-menu-compressed': isMenuCompressed, 'is-repository-level' : isRepositoryLevel}">
<h1 v-if="isRepositoryLevel">{{ repositoryName }}</h1>
<h1 v-else>{{ $i18n.get('collection') + '' }} <span class="has-text-weight-bold">{{ collectionName }}</span></h1>
<a
:href="collectionURL"
target="_blank"
v-if="!isRepositoryLevel"
class="button"
id="view-collection-button">
<eye-icon /> {{ $i18n.get('label_view_collection') }}
</a>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
import EyeIcon from '../other/eye-icon.vue';
export default {
name: 'TainacanRepositorySubheader',
data() {
return {
repositoryName: tainacan_plugin.repository_name,
collectionId: ''
}
},
components: {
EyeIcon
},
props: {
isMenuCompressed: false,
isRepositoryLevel: true
},
computed: {
collectionName() {
return this.getCollectionName();
},
collectionURL() {
return this.getCollectionURL();
}
},
methods: {
...mapActions('collection', [
'fetchCollectionNameAndURL'
]),
...mapGetters('collection', [
'getCollectionName',
'getCollectionURL'
])
},
mounted() {
if (!this.isRepositoryLevel) {
this.collectionId = this.$route.params.collectionId;
this.fetchCollectionNameAndURL(this.collectionId);
}
}
}
</script>
<style lang="scss" scoped>
@import "../../scss/_variables.scss";
// Tainacan Header
#tainacan-repository-subheader {
background-color: $turquoise5;
height: 42px;
max-height: 42px;
width: 100%;
overflow-y: hidden;
padding-top: 10px;
padding-bottom: 10px;
padding-right: 0;
padding-left: calc((4.166666667% - 6.666666667px) + 160px);
margin: 0px;
display: flex;
vertical-align: middle;
left: 0;
right: 0;
top: $header-height;
position: absolute;
z-index: 99;
transition: padding-left 0.2s linear, background-color 0.2s linear;
&.is-repository-level {
background-color: $blue5;
padding-right: $page-side-padding;
}
&.is-menu-compressed {
padding-left: calc((4.166666667% - 2.083333333px) + 50px);
}
h1 {
font-size: 1.125rem;
color: white;
line-height: 1.125rem;
max-width: 100%;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
transition: all 0.2s linear;
}
#view-collection-button {
border: none;
border-radius: 0px !important;
height: 42px !important;
right: 0;
position: relative;
background-color: $turquoise4;
color: white;
.eye-icon {
margin-right: 0.75rem;
}
}
@media screen and (max-width: 769px) {
top: 102px;
padding-left: 4.166666667% !important;
}
}
</style>

View File

@ -1,361 +0,0 @@
<template>
<div
id="tainacan-subheader"
class="level secondary-page">
<div class="level-left">
<div class="level-item">
<h1>{{ getCollectionName() }}</h1>
<nav class="breadcrumbs">
<router-link
tag="a"
:to="$routerHelper.getCollectionsPath()">{{ $i18n.get('repository') }}</router-link> >
<span
v-for="(pathItem, index) in arrayRealPath"
:key="index">
<router-link
v-if="index < arrayRealPath.length - 1"
tag="a"
:to="'/' + arrayRealPath.slice(0, index + 1).join('/')">
{{ arrayViewPath[index] }}
</router-link>
<span v-if="index == arrayRealPath.length - 1">{{ arrayViewPath[index] }}</span>
<span v-if="index != arrayRealPath.length - 1 && arrayViewPath[index]"> > </span>
</span>
</nav>
</div>
</div>
<ul class="menu-list level-right">
<li class="level-item">
<router-link
tag="a"
:to="{ path: $routerHelper.getCollectionItemsPath(id, '') }"
:class="activeRoute == 'ItemPage' || activeRoute == 'CollectionItemsPage' || activeRoute == 'ItemEditionForm' || activeRoute == 'ItemCreatePage' ? 'is-active':''"
:aria-label="$i18n.get('label_collection_items')">
<b-icon
size="is-small"
icon="file-multiple"/>
<br>
<span class="menu-text">{{ $i18n.get('items') }}</span>
</router-link>
</li>
<li class="level-item">
<router-link
tag="a"
:to="{ path: $routerHelper.getCollectionEditPath(id) }"
:class="activeRoute == 'CollectionEditionForm' ? 'is-active':''"
:aria-label="$i18n.get('label_settings')">
<b-icon
size="is-small"
icon="settings"/>
<br>
<span class="menu-text">{{ $i18n.get('label_settings') }}</span>
</router-link>
</li>
<li class="level-item">
<router-link
tag="a"
:to="{ path: $routerHelper.getCollectionMetadataPath(id) }"
:class="activeRoute == 'MetadataList' ? 'is-active':''"
:aria-label="$i18n.get('label_collection_metadata')">
<b-icon
size="is-small"
icon="format-list-bulleted-type"/>
<br>
<span class="menu-text">{{ $i18n.getFrom('metadata', 'name') }}</span>
</router-link>
</li>
<li class="level-item">
<router-link
tag="a"
:to="{ path: $routerHelper.getCollectionFiltersPath(id) }"
:class="activeRoute == 'FiltersList' ? 'is-active':''"
:aria-label="$i18n.get('label_collection_filters')">
<b-icon
size="is-small"
icon="filter"/>
<br>
<span class="menu-text">{{ $i18n.getFrom('filters', 'name') }}</span>
</router-link>
</li>
<li class="level-item">
<router-link
tag="a"
:to="{ path: $routerHelper.getCollectionEventsPath(id) }"
:class="activeRoute == 'CollectionEventsPage' ? 'is-active':''"
:aria-label="$i18n.get('label_collection_events')">
<activities-icon />
<br>
<span class="menu-text">{{ $i18n.get('events') }}</span>
</router-link>
</li>
</ul>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
import ActivitiesIcon from '../other/activities-icon.vue';
export default {
name: 'TainacanSubheader',
data(){
return {
activeRoute: 'ItemsList',
pageTitle: '',
arrayRealPath: [],
arrayViewPath: [],
activeRouteName: '',
}
},
components: {
ActivitiesIcon
},
props: {
id: Number,
},
watch: {
'$route' (to) {
this.activeRoute = to.name;
this.pageTitle = this.$route.meta.title;
this.arrayRealPath = to.path.split("/");
this.arrayRealPath = this.arrayRealPath.filter((item) => item.length != 0);
this.generateViewPath();
}
},
methods: {
...mapActions('collection', [
'fetchCollectionName'
]),
...mapGetters('collection', [
'getCollectionName',
'getCollection'
]),
...mapActions('item', [
'fetchItemTitle'
]),
...mapGetters('item', [
'getItemTitle'
]),
...mapActions('taxonomy', [
'fetchTaxonomyName'
]),
...mapGetters('taxonomy', [
'getTaxonomyName'
]),
...mapActions('event', [
'fetchEventTitle'
]),
generateViewPath() {
for (let i = 0; i < this.arrayRealPath.length; i++) {
this.arrayViewPath.push('');
if (!isNaN(this.arrayRealPath[i]) && i > 0) {
switch(this.arrayRealPath[i-1]) {
case 'collections':
this.fetchCollectionName(this.arrayRealPath[i])
.then(collectionName => this.arrayViewPath.splice(i, 1, collectionName))
.catch((error) => this.$console.error(error));
break;
case 'items':
this.fetchItemTitle(this.arrayRealPath[i])
.then(itemTitle => this.arrayViewPath.splice(i, 1, itemTitle))
.catch((error) => this.$console.error(error));
break;
case 'taxonomies':
this.fetchTaxonomyName(this.arrayRealPath[i])
.then(taxonomyName => this.arrayViewPath.splice(i, 1, taxonomyName))
.catch((error) => this.$console.error(error));
break;
case 'events':
this.fetchEventTitle(this.arrayRealPath[i])
.then(eventName => this.arrayViewPath.splice(i, 1, eventName))
.catch((error) => this.$console.error(error));
break;
}
} else {
if(this.arrayRealPath[i] == 'undefined'){
this.arrayViewPath.splice(i, 1, '');
} else {
this.arrayViewPath.splice(i, 1, this.$i18n.get(this.arrayRealPath[i]));
}
}
}
}
},
created() {
this.activeRoute = this.$route.name;
this.pageTitle = this.$route.meta.title;
this.arrayRealPath = this.$route.path.split("/");
this.arrayRealPath = this.arrayRealPath.filter((item) => item.length != 0);
this.generateViewPath();
}
}
</script>
<style lang="scss" scoped>
@import "../../scss/_variables.scss";
// Tainacan Header
#tainacan-subheader {
background-color: $primary-lighter;
height: $subheader-height;
max-height: $subheader-height;
width: 100%;
overflow-y: hidden;
padding-top: 18px;
padding-bottom: 18px;
padding-right: $page-side-padding;
padding-left: $page-side-padding;
margin: 0px;
vertical-align: middle;
left: 0;
right: 0;
z-index: 9;
transition: padding 0.3s, height 0.3s;
&.is-shrink {
height: $header-height;
max-height: $header-height;
padding-top: 12px;
padding-bottom: 12px;
h1 { margin-bottom: 4px; }
li a {
line-height: 20px;
.menu-text {
visibility: hidden;
opacity: 0;
font-size: 0;
line-height: 0;
display: block;
width: 0;
height: 0;
}
}
}
h1 {
font-size: 18px;
font-weight: 500;
color: $tertiary;
line-height: 22px;
margin-bottom: 12px;
max-width: 450px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
-webkit-transition: margin-bottom 0.2s linear; /* Safari */
transition: margin-bottom 0.2s linear;
}
.breadcrumbs {
font-size: 12px;
line-height: 12px;
color: #1d1d1d;
}
.level-left {
.level-item {
display: inline-block;
}
}
li{
margin-right: 0px;
transition: height 0.5s linear, padding 0.5s linear;
-webkit-transition: height 0.5s linear, padding 0.5s linear;
a {
color: $tertiary;
text-align: center;
white-space: nowrap;
overflow: hidden;
padding: 1.0em 10px;
min-width: 75px;
line-height: 1.5em;
border-radius: 0px;
position: relative;
overflow: inherit;
}
a:hover,
a.is-active {
background-color: #d1f1f2;
text-decoration: none;
}
a:focus{
box-shadow: none;
}
a.is-active:after {
position: absolute;
content: '';
width: 0;
height: 0;
bottom: -1px;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 11px solid white;
left: calc(50% - 10px);
-moz-transform: scale(0.999);
-webkit-backface-visibility: hidden;
}
.icon {
margin: 0;
padding: 0;
}
.menu-text {
font-size: 14px;
opacity: 1;
visibility: visible;
transition: opacity 0.5s linear, visibility 0.5s linear, height 0.5s linear;
-webkit-transition: opacity 0.5s linear, visibility 0.5s linear, height 0.5s linear;
}
}
@media screen and (max-width: 769px) {
width: 100% !important;
max-width: 100% !important;
height: 143px;
max-height: 143px;
ul {
margin-top: 12px;
flex-flow: wrap;
display: flex;
align-items: baseline;
justify-content: space-between;
a {
padding: 0.5em 0.7em !important;
text-align: center;
}
.menu-text {
padding-left: 0.3em !important;
}
}
.level-left {
margin-left: 0px !important;
}
top: 206px;
margin-bottom: 0px !important;
}
}
</style>

View File

@ -4,7 +4,7 @@
<h1>{{ pageTitle }} <span class="is-italic has-text-weight-semibold">{{ isRepositoryLevel ? '' : entityName }}</span></h1>
<a
@click="$router.go(-1)"
class="back-link is-secondary">
class="back-link has-text-secondary">
{{ $i18n.get('back') }}
</a>
<hr>
@ -46,7 +46,7 @@ export default {
},
methods: {
...mapActions('collection', [
'fetchCollectionName'
'fetchCollectionNameAndURL'
]),
...mapGetters('collection', [
'getCollectionName'
@ -79,8 +79,8 @@ export default {
switch(this.arrayRealPath[i-1]) {
case 'collections':
this.fetchCollectionName(this.arrayRealPath[i])
.then(collectionName => { this.arrayViewPath.splice(i, 1, collectionName); this.entityName = collectionName; })
this.fetchCollectionNameAndURL(this.arrayRealPath[i])
.then(collection => { this.arrayViewPath.splice(i, 1, collection.name); this.entityName = collection.name; })
.catch((error) => this.$console.error(error));
break;
case 'items':
@ -105,6 +105,8 @@ export default {
this.fetchAvailableImporters()
.then(importers => {
this.arrayViewPath.splice(i, 1, importers[this.arrayRealPath[i]].name);
if (i != this.arrayRealPath.length - 1)
this.arrayRealPath.pop();
})
.catch((error) => this.$console.error(error));
} else {
@ -128,7 +130,7 @@ export default {
this.isRepositoryLevel = (this.$route.params.collectionId == undefined);
document.title = this.$route.meta.title;
this.pageTitle = document.title;
this.arrayRealPath = this.$route.path.split("/");
this.arrayRealPath = this.arrayRealPath.filter((item) => item.length != 0);
@ -147,7 +149,7 @@ export default {
h1, h2 {
font-size: 20px;
font-weight: 500;
color: $tertiary;
color: $gray5;
display: inline-block;
}
a.back-link{

View File

@ -25,8 +25,7 @@ export default {
<style type="text/scss">
svg.activities-icon {
margin-bottom: -5px;
fill:#1E2F56;
fill: #898d8f;
}
</style>

View File

@ -0,0 +1,107 @@
<template>
<form action="">
<div
class="tainacan-modal-content"
style="width: auto">
<header class="tainacan-modal-title">
<h2>{{ this.$i18n.get('importers') }}</h2>
<hr>
</header>
<section class="tainacan-form">
<p>{{ $i18n.get('instruction_select_an_importer_type') }}</p>
<div class="importer-types-container">
<div
class="importer-type"
v-for="importerType in availableImporters"
:key="importerType.slug"
v-if="!(hideWhenManualCollection && !importerType.manual_collection)"
@click="onSelectImporter(importerType)">
<h4>{{ importerType.name }}</h4>
<p>{{ importerType.description }}</p>
</div>
</div>
<b-loading
:active.sync="isLoading"
:can-cancel="false"/>
<!-- <footer class="field is-grouped form-submit">
<div class="control">
<button
class="button is-outlined"
type="button"
@click="$parent.close()">Close</button>
</div>
<div class="control">
<button class="button is-success">Confirm</button>
</div>
</footer> -->
</section>
</div>
</form>
</template>
<script>
import { mapActions } from 'vuex';
export default {
name: 'AvailableImportersModal',
props: {
targetCollection: Number,
hideWhenManualCollection: false
},
data(){
return {
availableImporters: [],
isLoading: false
}
},
methods: {
...mapActions('importer', [
'fetchAvailableImporters'
]),
onSelectImporter(importerType) {
this.$router.push({ path: this.$routerHelper.getImporterEditionPath(importerType.slug), query: { targetCollection: this.targetCollection } });
this.$parent.close();
}
},
mounted() {
this.isLoading = true;
this.fetchAvailableImporters()
.then((res) => {
this.availableImporters = res;
this.isLoading = false;
}).catch((error) => {
this.$console.log(error);
this.isLoading = false;
});
}
}
</script>
<style lang="scss" scoped>
@import "../../scss/_variables.scss";
.importer-types-container {
.importer-type {
border-bottom: 1px solid $gray2;
padding: 15px 8.3333333%;
cursor: pointer;
&:first-child {
margin-top: 15px;
}
&:last-child {
border-bottom: none;
}
&:hover {
background-color: $gray2;
}
}
}
</style>

View File

@ -1,42 +1,738 @@
<template>
<form action="">
<div
class="tainacan-modal-content"
style="width: auto">
<header class="tainacan-modal-title">
<h2>{{ this.$i18n.get('filter') }} <em>{{ title }}</em></h2>
<hr>
</header>
<section class="tainacan-form">
<div class="tainacan-modal-content">
<header class="tainacan-modal-title">
<h2>{{ this.$i18n.get('filter') }} <em>{{ filter.name }}</em></h2>
<hr>
</header>
<div class="tainacan-form">
<div class="is-clearfix tainacan-checkbox-search-section">
<input
autocomplete="on"
:placeholder="$i18n.get('instruction_search')"
v-model="optionName"
@input="autoComplete"
class="input">
<span class="icon is-right">
<i
class="mdi mdi-magnify"/>
</span>
</div>
<div
v-if="!isSearching && !isTaxonomy"
class="modal-card-body tainacan-checkbox-list-container">
<a
v-if="checkboxListOffset"
role="button"
class="tainacan-checkbox-list-page-changer"
@click="beforePage">
<b-icon
icon="chevron-left"/>
</a>
<ul
:class="{
'tainacan-modal-checkbox-list-body-dynamic-m-l': !checkboxListOffset,
'tainacan-modal-checkbox-list-body-dynamic-m-r': noMorePage,
}"
class="tainacan-modal-checkbox-list-body">
<li
class="tainacan-li-checkbox-list"
v-for="(option, key) in options"
:key="key">
<b-checkbox
v-model="selected"
:native-value="option.value">
{{ `${ limitChars(option.label) }` }}
</b-checkbox>
</li>
<b-loading
:is-full-page="false"
:active.sync="isCheckboxListLoading"/>
</ul>
<a
v-if="!noMorePage"
role="button"
class="tainacan-checkbox-list-page-changer"
@click="nextPage">
<b-icon
icon="chevron-right"/>
</a>
</div>
<footer class="field is-grouped form-submit">
<div class="control">
<button
class="button is-outlined"
type="button"
@click="$parent.close()">Close</button>
</div>
<div class="control">
<button class="button is-success">Login</button>
</div>
</footer>
</section>
<div
v-if="!isSearching && isTaxonomy"
class="modal-card-body tainacan-finder-columns-container">
<ul
class="tainacan-finder-column"
v-for="(finderColumn, key) in finderColumns"
:key="key">
<b-field
role="li"
:addons="false"
v-if="finderColumn.length"
class="tainacan-li-checkbox-modal"
v-for="(option, index) in finderColumn"
:id="`${key}.${index}-tainacan-li-checkbox-model`"
:ref="`${key}.${index}-tainacan-li-checkbox-model`"
:key="index">
<b-checkbox
v-model="selected"
:native-value="option.id">
{{ `${option.name}` }}
</b-checkbox>
<a
v-if="option.total_children > 0"
@click="getOptionChildren(option, key, index)">
<b-icon
class="is-pulled-right"
icon="menu-right"
/>
</a>
</b-field>
<li v-if="finderColumn.length">
<div
v-if="finderColumn.length < totalRemaining[key].remaining"
@click="getMoreOptions(finderColumn, key)"
class="tainacan-show-more">
<b-icon
size="is-small"
icon="chevron-down"/>
</div>
</li>
<b-loading
:is-full-page="false"
:active.sync="isColumnLoading"/>
</ul>
</div>
<!--<pre>{{ hierarchicalPath }}</pre>-->
<!--<pre>{{ totalRemaining }}</pre>-->
<!--<pre>{{ selected }}</pre>-->
<!--<pre>{{ options }}</pre>-->
<!--<pre>{{ searchResults }}</pre>-->
<div
v-if="isSearching"
class="modal-card-body tainacan-search-results-container">
<ul class="tainacan-modal-checkbox-search-results-body">
<li
class="tainacan-li-search-results"
v-for="(option, key) in searchResults"
:key="key">
<b-checkbox
v-model="selected"
:native-value="option.id ? option.id : option.value">
{{ `${ option.name ? limitChars(option.name) : limitChars(option.label) }` }}
</b-checkbox>
</li>
<b-loading
:is-full-page="false"
:active.sync="isSearchingLoading"/>
</ul>
</div>
<footer class="field is-grouped form-submit">
<div class="control">
<button
class="button is-outlined"
type="button"
@click="$parent.close()">{{ $i18n.get('cancel') }}
</button>
</div>
<div class="control">
<button
@click="applyFilter"
type="button"
class="button is-success">{{ $i18n.get('apply') }}
</button>
</div>
</footer>
</div>
</form>
</div>
</template>
<script>
export default {
name: 'CheckboxFilterModal',
props: {
title: ''
import {tainacan as axios} from '../../../js/axios/axios';
import { filter_type_mixin } from '../../../classes/filter-types/filter-types-mixin';
export default {
name: 'CheckboxFilterModal',
mixins: [ filter_type_mixin ],
props: {
filter: '',
parent: Number,
taxonomy_id: Number,
taxonomy: String,
collection_id: Number,
metadatum_id: Number,
selected: Array,
isTaxonomy: false,
metadatum_type: String,
metadatum_object: Object,
isRepositoryLevel: Boolean,
},
data() {
return {
finderColumns: [],
itemActive: false,
isColumnLoading: false,
loadingComponent: undefined,
totalRemaining: {},
hierarchicalPath: [],
searchResults: [],
optionName: '',
isSearching: false,
options: [],
maxNumOptionsCheckboxList: 20,
maxNumSearchResultsShow: 20,
maxNumOptionsCheckboxFinderColumns: 100,
checkboxListOffset: 0,
collection: this.collection_id,
isCheckboxListLoading: false,
isSearchingLoading: false,
noMorePage: 0,
maxTextToShow: 47,
}
},
created() {
if(this.isTaxonomy) {
this.getOptionChildren();
} else {
this.isCheckboxListLoading = true;
this.getOptions(0);
}
},
methods: {
limitChars(label){
if(label.length > this.maxTextToShow){
return label.slice(0, this.maxTextToShow)+'...';
}
return label;
},
beforePage(){
this.checkboxListOffset -= this.maxNumOptionsCheckboxList;
this.noMorePage = 0;
if(this.checkboxListOffset < 0){
this.checkboxListOffset = 0;
}
this.isCheckboxListLoading = true;
this.getOptions(this.checkboxListOffset);
},
nextPage(){
if(!this.noMorePage) {
// LIMIT 0, 20 / LIMIT 19, 20 / LIMIT 39, 20 / LIMIT 59, 20
if(this.checkboxListOffset === this.maxNumOptionsCheckboxList){
this.checkboxListOffset += this.maxNumOptionsCheckboxList-1;
} else {
this.checkboxListOffset += this.maxNumOptionsCheckboxList;
}
}
this.isCheckboxListLoading = true;
this.getOptions(this.checkboxListOffset);
},
getOptions(offset){
let promise = '';
if ( this.metadatum_type === 'Tainacan\\Metadata_Types\\Relationship' ) {
let collectionTarget = ( this.metadatum_object && this.metadatum_object.metadata_type_options.collection_id ) ?
this.metadatum_object.metadata_type_options.collection_id : this.collection_id;
promise = this.getValuesRelationship( collectionTarget, this.optionName, [], offset, this.maxNumOptionsCheckboxList, true);
promise
.then(() => {
this.isCheckboxListLoading = false;
this.isSearchingLoading = false;
})
.catch(error => {
this.$console.log(error);
})
} else {
promise = this.getValuesPlainText( this.metadatum_id, this.optionName, this.isRepositoryLevel, [], offset, this.maxNumOptionsCheckboxList, true);
promise
.then(() => {
this.isCheckboxListLoading = false;
this.isSearchingLoading = false;
})
.catch(error => {
this.$console.log(error);
})
}
},
autoComplete: _.debounce( function () {
this.isSearching = !!this.optionName.length;
if(!this.isSearching){
return;
}
if(this.isTaxonomy) {
this.isSearchingLoading = true;
let query = `?hideempty=0&order=asc&number=${this.maxNumSearchResultsShow}&searchterm=${this.optionName}`;
axios.get(`/taxonomy/${this.taxonomy_id}/terms${query}`)
.then((res) => {
this.searchResults = res.data;
this.isSearchingLoading = false;
}).catch((error) => {
this.$console.log(error);
});
} else {
this.isSearchingLoading = true;
this.getOptions(0);
}
}, 300),
highlightHierarchyPath(){
for(let [index, el] of this.hierarchicalPath.entries()){
let htmlEl = this.$refs[`${el.column}.${el.element}-tainacan-li-checkbox-model`][0].$el;
if(index == this.hierarchicalPath.length-1){
htmlEl.classList.add('tainacan-li-checkbox-last-active')
} else {
htmlEl.classList.add('tainacan-li-checkbox-parent-active')
}
}
},
addToHierarchicalPath(column, element){
let found = undefined;
let toBeAdded = {
column: column,
element: element
};
for (let f in this.hierarchicalPath) {
if (this.hierarchicalPath[f].column == column) {
found = f;
break;
}
}
if (found != undefined) {
this.removeHighlightNotSelectedLevels();
this.hierarchicalPath.splice(found);
this.hierarchicalPath.splice(found, 1, toBeAdded);
} else {
this.hierarchicalPath.push(toBeAdded);
}
this.highlightHierarchyPath();
},
removeHighlightNotSelectedLevels(){
for(let el of this.hierarchicalPath){
if(!!this.$refs[`${el.column}.${el.element}-tainacan-li-checkbox-model`][0]) {
let htmlEl = this.$refs[`${el.column}.${el.element}-tainacan-li-checkbox-model`][0].$el;
htmlEl.classList.remove('tainacan-li-checkbox-last-active');
htmlEl.classList.remove('tainacan-li-checkbox-parent-active');
}
}
},
removeLevelsAfter(key){
if(key != undefined){
this.finderColumns.splice(key+1);
}
},
createColumn(res, column) {
let children = res.data;
this.totalRemaining = Object.assign({}, this.totalRemaining, {
[`${column == undefined ? 0 : column+1}`]: {
remaining: res.headers['x-wp-total'],
}
});
let first = undefined;
if (children.length > 0) {
for (let f in this.finderColumns) {
if (this.finderColumns[f][0].id == children[0].id) {
first = f;
break;
}
}
}
if (first != undefined) {
this.finderColumns.splice(first, 1, children);
} else {
this.finderColumns.push(children);
}
},
appendMore(options, key) {
for (let option of options) {
this.finderColumns[key].push(option)
}
},
getOptionChildren(option, key, index) {
if(key != undefined) {
this.addToHierarchicalPath(key, index);
}
let parent = 0;
if (option) {
parent = option.id;
}
let query = `?hideempty=0&order=asc&parent=${parent}&number=${this.maxNumOptionsCheckboxFinderColumns}&offset=0`;
this.isColumnLoading = true;
axios.get(`/taxonomy/${this.taxonomy_id}/terms${query}`)
.then(res => {
this.removeLevelsAfter(key);
this.createColumn(res, key);
this.isColumnLoading = false;
})
.catch(error => {
this.$console.log(error);
this.isColumnLoading = false;
});
},
getMoreOptions(finderColumn, key) {
if (finderColumn.length > 0) {
let parent = finderColumn[0].parent;
let offset = finderColumn.length;
let query = `?hideempty=0&order=asc&parent=${parent}&number=${this.maxNumOptionsCheckboxFinderColumns}&offset=${offset}`;
this.isColumnLoading = true;
axios.get(`/taxonomy/${this.taxonomy_id}/terms${query}`)
.then(res => {
this.appendMore(res.data, key);
this.isColumnLoading = false;
})
.catch(error => {
this.$console.log(error);
this.isColumnLoading = false;
});
}
},
applyFilter() {
this.$parent.close();
let onlyLabels = [];
if(this.isTaxonomy){
this.$eventBusSearch.$emit('input', {
filter: 'checkbox',
taxonomy: this.taxonomy,
compare: 'IN',
metadatum_id: this.metadatum_id,
collection_id: this.collection_id,
terms: this.selected
});
for (let selected of this.selected) {
for(let i in this.finderColumns){
let valueIndex = this.finderColumns[i].findIndex(option => option.id == selected);
if (valueIndex >= 0) {
onlyLabels.push(this.finderColumns[i][valueIndex].name);
}
}
}
this.$eventBusSearch.$emit('sendValuesToTags', {
filterId: this.filter.id,
value: onlyLabels,
});
} else {
this.$eventBusSearch.$emit('input', {
filter: 'checkbox',
compare: 'IN',
metadatum_id: this.metadatum_id,
collection_id: this.collection_id ? this.collection_id : this.filter.collection_id,
value: this.selected,
});
if(!isNaN(this.selected[0])){
for (let option of this.options) {
let valueIndex = this.selected.findIndex(item => item == option.value);
if (valueIndex >= 0) {
onlyLabels.push(this.options[valueIndex].label);
}
}
}
onlyLabels = onlyLabels.length ? onlyLabels : this.selected;
this.$eventBusSearch.$emit( 'sendValuesToTags', {
filterId: this.filter.id,
value: onlyLabels,
});
}
this.$root.$emit('appliedCheckBoxModal', onlyLabels);
}
}
}
}
</script>
<style lang="scss" scoped>
@import "../../scss/variables.scss";
@media screen and (max-width: 768px) {
.tainacan-modal-content {
flex-direction: column;
display: flex;
align-items: center;
justify-content: space-around;
}
.tainacan-modal-checkbox-list-body {
flex-wrap: nowrap !important;
}
.tainacan-modal-checkbox-search-results-body {
flex-wrap: nowrap !important;
}
.tainacan-li-search-results {
max-width: calc(100% - 8.3333333%) !important;
}
.tainacan-li-checkbox-list {
max-width: calc(100% - 8.3333333%) !important;
}
}
.tainacan-modal-content {
width: auto;
min-height: 600px;
border-radius: 10px;
}
.tainacan-modal-title {
align-self: baseline;
display: flex;
flex-direction: column;
width: 100%;
}
// In theme, the bootstrap removes the style of <a> without href
a {
cursor: pointer;
color: $turquoise5 !important;
}
.tainacan-form {
max-width: 100%;
}
.tainacan-show-more {
width: 100%;
display: flex;
justify-content: center;
cursor: pointer;
border: 1px solid $gray1;
margin-top: 10px;
margin-bottom: 0.2rem;
&:hover {
background-color: $blue1;
}
}
.tainacan-li-search-results {
flex-grow: 0;
flex-shrink: 1;
max-width: calc(50% - 8.3333333%);
.b-checkbox {
max-width: 86%;
margin-right: 10px;
}
&:hover {
background-color: $gray1;
}
}
.tainacan-li-checkbox-modal {
display: flex;
padding: 0;
.b-checkbox {
max-width: 86%;
margin-left: 0.7rem;
height: 24px;
}
&:hover {
background-color: $gray1;
}
}
.tainacan-li-checkbox-list {
flex-grow: 0;
flex-shrink: 1;
max-width: calc(50% - 8.3333333%);
.b-checkbox {
margin-right: 10px;
}
&:hover {
background-color: $gray1;
}
}
.tainacan-finder-columns-container {
background-color: white;
border: solid 1px $gray1;
display: flex;
overflow: auto;
padding: 0 !important;
min-height: 253px;
&:focus {
outline: none;
}
}
.tainacan-finder-column {
border-right: solid 1px $gray1;
max-height: 400px;
max-width: 25%;
min-height: inherit;
min-width: 200px;
overflow-y: auto;
list-style: none;
margin: 0;
padding: 0rem;
// For Safari
-webkit-margin-after: 0;
-webkit-margin-start: 0;
-webkit-margin-end: 0;
-webkit-padding-start: 0;
-webkit-margin-before: 0;
}
.tainacan-li-checkbox-modal:first-child {
margin-top: 0.7rem;
}
.field:not(:last-child) {
margin-bottom: 0 !important;
}
.tainacan-checkbox-search-section {
margin-bottom: 40px;
display: flex;
align-items: center;
position: relative;
.icon {
pointer-events: all;
color: $blue5;
cursor: pointer;
height: 27px;
font-size: 18px;
width: 30px !important;
position: absolute;
right: 0;
}
}
.tainacan-checkbox-list-container {
padding: 0 20px !important;
min-height: 253px;
display: flex;
align-items: center;
padding-right: 0 !important;
padding-left: 0 !important;
}
.tainacan-checkbox-list-page-changer {
height: 253px;
align-items: center;
display: flex;
background-color: $gray1;
&:hover {
background-color: $blue1;
}
}
.tainacan-modal-checkbox-list-body {
list-style: none;
width: 100%;
align-self: baseline;
margin: 0 10px;
display: flex;
flex-direction: column;
flex-wrap: wrap;
padding: 0 !important;
max-height: 253px;
overflow: auto;
}
.tainacan-modal-checkbox-list-body-dynamic-m-l {
margin-left: $page-side-padding !important;
}
.tainacan-modal-checkbox-list-body-dynamic-m-r {
margin-right: $page-side-padding !important;
}
.tainacan-search-results-container {
padding: 0 20px !important;
min-height: 253px;
}
.tainacan-modal-checkbox-search-results-body {
list-style: none;
display: flex;
flex-direction: column;
flex-wrap: wrap;
max-height: 253px;
// For Safari
-webkit-margin-after: 0;
-webkit-margin-start: 0;
-webkit-margin-end: 0;
-webkit-padding-start: 0;
-webkit-margin-before: 0;
}
.tainacan-li-no-children {
padding: 3rem 1.5rem 3rem 0.5rem;
}
.tainacan-li-checkbox-last-active {
background-color: $turquoise1;
}
.tainacan-li-checkbox-parent-active {
background-color: $turquoise2;
}
</style>

View File

@ -0,0 +1,163 @@
<template>
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xml:space="preserve"
viewBox="0 0 20 14"
y="0px"
x="0px"
width="20"
height="20"
version="1.1"
class="eye-icon">
<path
id="path56"
d="M 10,0 C 7.0316493,-0.05440347 4.0111777,1.1325791 2.0710468,3.4179754 1.1631135,4.4654257 0.43447312,5.681008 0,7 c 1.0982625,3.319095 3.9681881,6.044348 7.4282551,6.734139 3.3914659,0.723339 7.2342739,0.03321 9.7934699,-2.420502 C 18.475945,10.128872 19.453576,8.6385839 20,7 18.901737,3.6809051 16.031812,0.95565213 12.571745,0.26586056 11.727831,0.08190134 10.863219,-1.1439431e-4 10,0 Z m 0,2 c 2.617061,-0.050813 5.27673,1.0895398 6.849519,3.2199707 0.361792,0.6728511 1.318734,1.4471184 0.841243,2.2270081 C 16.483135,9.899037 13.995213,11.646083 11.272966,11.92392 8.5410704,12.281194 5.5668346,11.496655 3.6809516,9.4066345 3.0239343,8.7008905 2.483548,7.8849111 2.0996094,7 3.1988496,4.4005461 5.6997692,2.4563534 8.5098665,2.1053252 9.003048,2.0331183 9.5016597,1.9999846 10,2 Z" /><g
transform="translate(-2,-5)"
style="display:none"
class="st0"
id="g10">
<g
style="display:inline"
class="st1"
id="g8">
<g
id="g6">
<path
d="m 12,8 c 0.1,0 0.2,0 0.3,0 V 8 C 12.2,8 12.1,8 12,8 m 0,0 c -0.1,0 -0.2,0 -0.3,0 v 0 c 0.1,0 0.2,0 0.3,0 m 0.3,8 v 0 c -0.1,0 -0.2,0 -0.3,0 0.1,0 0.2,0 0.3,0 m -0.6,0 c 0.1,0 0.2,0 0.3,0 -0.1,0 -0.2,0 -0.3,0 v 0 M 12,6 C 5,6 2,12 2,12 c 0,0 3,6 10,6 7,0 10,-6 10,-6 0,0 -3,-6 -10,-6 z m 0.4,10 c 2,-0.2 3.6,-1.9 3.6,-4 0,-2.1 -1.6,-3.8 -3.6,-4 3.9,0.2 6.2,2.6 7.2,4 -1,1.4 -3.3,3.8 -7.2,4 z m -0.8,0 C 7.7,15.8 5.4,13.4 4.4,12 5.4,10.6 7.7,8.2 11.6,8 9.6,8.2 8,9.9 8,12 c 0,2.1 1.6,3.8 3.6,4 z M 12,14 c -1.1,0 -2,-0.9 -2,-2 0,-1.1 0.9,-2 2,-2 1.1,0 2,0.9 2,2 0,1.1 -0.9,2 -2,2 z"
id="path4" />
</g>
</g>
</g>
<g
transform="translate(-2,-5)"
style="display:none"
class="st0"
id="g18">
<circle
style="display:inline;fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:10"
class="st2"
cx="12"
cy="11.5"
r="3.5"
id="circle12" />
<g
style="display:inline"
class="st1"
id="g16">
<path
d="m 12,7 c 5.2,0 7.3,3.6 7.9,5 -0.6,1.4 -2.7,5 -7.9,5 C 6.8,17 4.7,13.4 4.1,12 4.7,10.6 6.8,7 12,7 M 12,5 C 4,5 2,12 2,12 c 0,0 2,7 10,7 8,0 10,-7 10,-7 0,0 -2,-7 -10,-7 z"
id="path14" />
</g>
</g>
<path
style="display:none"
class="st0"
d="m 14,7 c 0,2.2 -1.8,4 -4,4 C 7.8,11 6,9.2 6,7 6,6.7 6,6.4 6.1,6.1 6.3,6.6 6.9,7 7.5,7 8.3,7 9,6.3 9,5.5 9,4.7 8.3,4 7.5,4 7.4,4 7.4,4 7.3,4 8,3.4 9,3 10,3 c 2.2,0 4,1.8 4,4 z M 10,2 C 4.8,2 2.7,5.6 2.1,7 2.7,8.4 4.8,12 10,12 15.2,12 17.3,8.4 17.9,7 17.3,5.6 15.2,2 10,2 m 0,-2 c 8,0 10,7 10,7 0,0 -2,7 -10,7 C 2,14 0,7 0,7 0,7 2,0 10,0 Z"
id="path20" />
<g
transform="translate(-2,-5)"
style="display:none"
class="st0"
id="g42">
<g
style="display:inline"
class="st1"
id="g28">
<circle
cx="12"
cy="11.5"
r="4.5"
id="circle22" />
<g
id="g26">
<path
d="m 12,7 c 5.2,0 7.3,3.6 7.9,5 -0.6,1.4 -2.7,5 -7.9,5 C 6.8,17 4.7,13.4 4.1,12 4.7,10.6 6.8,7 12,7 M 12,5 C 4,5 2,12 2,12 c 0,0 2,7 10,7 8,0 10,-7 10,-7 0,0 -2,-7 -10,-7 z"
id="path24" />
</g>
</g>
<circle
style="display:inline;fill:#ffffff"
class="st3"
cx="9"
cy="10"
r="1"
id="circle30" />
<g
style="display:inline"
class="st1"
id="g38">
<circle
cx="12"
cy="11.5"
r="4.5"
id="circle32" />
<g
id="g36">
<path
d="m 12,7 c 5.2,0 7.3,3.6 7.9,5 -0.6,1.4 -2.7,5 -7.9,5 C 6.8,17 4.7,13.4 4.1,12 4.7,10.6 6.8,7 12,7 M 12,5 C 4,5 2,12 2,12 c 0,0 2,7 10,7 8,0 10,-7 10,-7 0,0 -2,-7 -10,-7 z"
id="path34" />
</g>
</g>
<circle
style="display:inline;fill:#ffffff"
class="st3"
cx="8.5"
cy="9.5"
r="1.5"
id="circle40" />
</g>
<path
style="display:none"
class="st0"
d="m 13,7 c 0,1.7 -1.3,3 -3,3 C 8.3,10 7,8.7 7,7 7,7 7,6.9 7,6.9 7.2,7 7.3,7 7.5,7 8.3,7 9,6.3 9,5.5 9,5.1 8.8,4.7 8.5,4.4 9,4.1 9.5,4 10,4 c 1.7,0 3,1.3 3,3 z M 10,2 C 4.8,2 2.7,5.6 2.1,7 2.7,8.4 4.8,12 10,12 15.2,12 17.3,8.4 17.9,7 17.3,5.6 15.2,2 10,2 m 0,-2 c 8,0 10,7 10,7 0,0 -2,7 -10,7 C 2,14 0,7 0,7 0,7 2,0 10,0 Z"
id="path44" />
<g
transform="translate(-2,-5)"
style="display:none"
class="st0"
id="g54">
<circle
style="display:inline"
class="st1"
cx="12"
cy="12"
r="3"
id="circle46" />
<g
style="display:inline"
class="st1"
id="g50">
<path
d="m 12,7 c 5.2,0 7.3,3.6 7.9,5 -0.6,1.4 -2.7,5 -7.9,5 C 6.8,17 4.7,13.4 4.1,12 4.7,10.6 6.8,7 12,7 M 12,5 C 4,5 2,12 2,12 c 0,0 2,7 10,7 8,0 10,-7 10,-7 0,0 -2,-7 -10,-7 z"
id="path48" />
</g>
<circle
style="fill:#ffffff"
class="st4"
cx="9.5"
cy="10.5"
r="1.5"
id="circle52" />
</g>
<path
id="path4779"
d="m 13,7 c 0.06529,1.6168429 -1.383157,3.065288 -3,3 C 8.3831571,10.065288 6.9347117,8.6168429 7,7 6.9347117,5.3831571 8.3831571,3.9347117 10,4 c 1.637418,-0.048194 3.04793,1.3597481 3,3 z" />
</svg>
</template>
<script>
export default {
name: 'EyeIcon'
}
</script>
<style type="text/scss">
svg.eye-icon {
fill: white;
}
</style>

View File

@ -34,21 +34,14 @@
<div class="tainacan-modal-content">
<div class="tainacan-modal-title">
<h2>{{ file.title.rendered }}</h2>
<a
@click="isPreviewModalActive = false"
class="back-link">{{ $i18n.get('exit') }}</a>
<hr>
</div>
<div
class="is-flex"
class="is-flex rendered-content"
v-html="file.description.rendered" />
<div class="field is-grouped form-submit">
<div class="control">
<button
id="button-cancel-url-link-selection"
class="button is-outlined"
type="button"
@click="isPreviewModalActive = false">
{{ $i18n.get('cancel') }}</button>
</div>
</div>
</div>
</b-modal>
</div>
@ -110,7 +103,7 @@ export default {
overflow: hidden;
position: relative;
display: inline-block;
background-color: $tainacan-input-background;
background-color: $gray2;
&.rounded {
border-bottom-left-radius: 5px;
@ -144,7 +137,7 @@ export default {
}
figcaption {
background-color: $tainacan-input-background;
background-color: $gray2;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
padding: 8px 15px;
@ -156,8 +149,8 @@ export default {
text-align: center;
}
}
.is-flex {
justify-content: center;
.rendered-content {
justify-content: center !important;
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<span class="help-wrapper">
<a class="help-button">
<a class="help-button has-text-secondary">
<b-icon
size="is-small"
icon="help-circle-outline"/></a>
@ -46,8 +46,8 @@ export default {
}
.help-tooltip {
z-index: 99999999999999999999;
color: $tertiary;
background-color: $primary-light;
color: $blue5;
background-color: $turquoise2;
border: none;
display: block;
border-radius: 5px;
@ -86,7 +86,7 @@ export default {
border-style: solid;
}
&:before {
border-color: $primary-light transparent transparent transparent;
border-color: $turquoise2 transparent transparent transparent;
border-right-width: 18px;
border-top-width: 12px;
border-left-width: 18px;

View File

@ -0,0 +1,372 @@
<template>
<div>
<div
@click="$emit('closeProcessesPopup')"
class="processes-popup-backdrop" />
<div class="processes-popup">
<div class="popup-header">
<span
@click="bgProcesses.length > 0 ? showProcessesList = !showProcessesList : null"
class="header-title">{{ getUnfinishedProcesses() + ' ' + $i18n.get('info_unfinished_processes') }}</span>
<a
v-if="bgProcesses.length > 0"
@click="showProcessesList = !showProcessesList">
<span class="icon has-text-blue5">
<i
:class="{ 'mdi-menu-up': showProcessesList,
'mdi-menu-down': !showProcessesList }"
class="mdi mdi-18px"/>
</span>
</a>
<a @click="$emit('closeProcessesPopup')">
<span class="icon has-text-blue5">
<i class="mdi mdi-close"/>
</span>
</a>
</div>
<div
v-if="showProcessesList"
class="popup-list">
<ul>
<li class="popup-list-subheader">
{{ $i18n.get('label_last_processed_on') + ' ' + getDate(bgProcesses[0].processed_last) }}
<router-link
tag="a"
:to="$routerHelper.getProcessesPage()"
class="is-secondary">
{{ $i18n.get('label_view_more') }}
</router-link>
</li>
<li
:key="index"
v-for="(bgProcess, index) of bgProcesses">
<div class="process-item">
<div
@click="toggleDetails(index)"
class="process-title">
<span class="icon has-text-gray">
<i
class="mdi mdi-18px"
:class="{ 'mdi-menu-down': processesColapses[index], 'mdi-menu-right': !processesColapses[index] }" />
</span>
<p>{{ bgProcess.name ? bgProcess.name : $i18n.get('label_unamed_process') }}</p>
</div>
<!-- <span
v-if="bgProcess.done <= 0"
class="icon has-text-gray action-icon"
@click="pauseProcess(index)">
<i class="mdi mdi-18px mdi-pause-circle"/>
</span>
<span
v-if="bgProcess.done <= 0"
class="icon has-text-gray action-icon"
@click="pauseProcess(index)">
<i class="mdi mdi-18px mdi-close-circle-outline"/>
</span> -->
<span
v-if="bgProcess.done > 0 && !bgProcess.error_log"
class="icon has-text-success">
<i class="mdi mdi-18px mdi-checkbox-marked-circle"/>
</span>
<span
v-if="bgProcess.done > 0 && bgProcess.error_log"
class="icon has-text-danger">
<i class="mdi mdi-18px mdi-sync-alert" />
</span>
<span
v-if="bgProcess.done <= 0"
class="icon has-text-success loading-icon">
<div class="control has-icons-right is-loading is-clearfix" />
</span>
</div>
<div
v-if="processesColapses[index]"
class="process-label">
{{ bgProcess.progress_label ? bgProcess.progress_label : $i18n.get('label_no_details_of_process') }}
<span class="process-label-value">{{ (bgProcesses[0].progress_value && bgProcesses[0].progress_value >= 0) ? '(' + bgProcesses[0].progress_value + '%)' : '' }}</span>
<br>
{{ $i18n.get('label_queued_on') + ' ' + getDate(bgProcess.queued_on) }}
<br>
{{ $i18n.get('label_last_processed_on') + ' ' + getDate(bgProcess.processed_last) }}
<br>
<a
v-if="bgProcess.log"
:href="bgProcess.log">{{ $i18n.get('label_log_file') }}</a>
<span v-if="bgProcess.error_log"> | </span>
<a
v-if="bgProcess.error_log"
class="has-text-danger"
:href="bgProcess.error_log">{{ $i18n.get('label_error_log_file') }}</a>
</div>
</li>
</ul>
</div>
<div
class="separator"
v-if="!showProcessesList" />
<div class="popup-footer">
<span
v-if="hasAnyProcessExecuting"
class="icon has-text-blue5"><i class="mdi mdi-18px mdi-autorenew"/></span>
<p class="footer-title">
{{ hasAnyProcessExecuting ?
(bgProcesses[0].progress_label ? bgProcesses[0].progress_label + ((bgProcesses[0].progress_value && bgProcesses[0].progress_value >= 0) ? ' - ' + bgProcesses[0].progress_value + '%' : '') : $i18n.get('label_no_details_of_process')):
$i18n.get('info_no_process')
}}
</p>
</div>
</div>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
export default {
name: 'ProcessesPopup',
data() {
return {
showProcessesList: false,
processesColapses: [],
hasAnyProcessExecuting: false
}
},
watch: {
bgProcesses() {
this.processesColapses = [];
this.hasAnyProcessExecuting = false;
for (let i = 0; i < this.bgProcesses.length; i++) {
this.$set(this.processesColapses, i , false);
if (this.bgProcesses[i].done <= 0)
this.hasAnyProcessExecuting = true;
}
}
},
computed: {
bgProcesses() {
return this.getProcesses();
}
},
methods: {
...mapActions('bgprocess', [
'fetchProcesses'
]),
...mapGetters('bgprocess', [
'getProcesses',
]),
toggleDetails(index) {
this.$set(this.processesColapses, index, !this.processesColapses[index]);
},
getUnfinishedProcesses() {
let nUnfinishedProcesses = 0
for(let i = 0; i < this.bgProcesses.length; i++) {
if (this.bgProcesses[i].done <= 0)
nUnfinishedProcesses++;
}
return nUnfinishedProcesses;
},
getDate(rawDate) {
let date = new Date(rawDate);
if (date instanceof Date && !isNaN(date))
return date.toLocaleString();
else
return this.$i18n.get('info_unknown_date');
},
pauseProcess() {
}
},
mounted() {
this.fetchProcesses({ page: 1, processesPerPage: 12 });
this.showProcessesList = false;
}
}
</script>
<style lang="scss">
@import "../../scss/_variables.scss";
@keyframes appear-from-top {
from {
top: 24px;
opacity: 0;
}
to {
top: 48px;
opacity: 1;
}
}
@keyframes expand {
from {
max-height: 0;
}
to {
max-height: 222px;
}
}
.control.is-loading::after {
border: 2px solid $success;
border-right-color: $gray2;
border-top-color: $gray2;
}
.processes-popup-backdrop {
position: absolute;
top: 0;
right: 0;
left: 0;
border: 0;
width: 100%;
height: 100vh;
right: 26px;
}
.processes-popup{
background-color: $blue2;
width: 320px;
max-width: 100%;
position: absolute;
top: 48px;
right: 26px;
border-radius: 5px;
animation-name: appear-from-top;
animation-duration: 0.3s;
font-size: 0.75rem;
.popup-header, .popup-footer {
display: flex;
align-items: center;
color: $blue5;
.header-title, .footer-title {
margin-right: auto;
}
}
.popup-header {
padding: 6px 12px 4px 12px;
.header-title {
margin-right: auto;
cursor: pointer;
}
}
.popup-footer {
padding: 4px 12px 6px 10px;
min-height: 29px;
.footer-title {
margin-right: auto;
font-size: 0.625rem;
}
}
.popup-list {
background-color: white;
color: black;
overflow-y: auto;
overflow-x: hidden;
max-height: 222px;
animation-name: expand;
animation-duration: 0.3s;
.popup-list-subheader {
background-color: white !important;
padding: 6px 12px 12px 12px;
color: $gray4;
font-size: 0.625rem;
a { float: right; }
}
li:hover {
background-color: $gray1;
.action-icon{
visibility: visible;
opacity: 1;
cursor: pointer;
}
.loading-icon {
display: none;
}
.process-item>.process-title .mdi-menu-left, .process-item>.process-title .mdi-menu-right {
color: $gray3 !important;
}
}
.process-item {
padding: 5px 12px 5px 5px;
display: flex;
justify-content: space-between;
width: 100%;
.process-title {
cursor: pointer;
margin-right: auto;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
max-width: calc(100% - 40px);
p {
display: inline-block;
position: relative;
top: -2px;
}
.mdi-menu-left, .mdi-menu-right {
color: $turquoise2;
}
}
.action-icon {
visibility: hidden;
opacity: 0;
}
.loading-icon .control.is-loading::after {
position: relative !important;
right: 0;
top: 0;
}
}
.process-label {
padding: 0px 12px 6px 32px;
margin-right: auto;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
max-width: calc(100% - 40px);
font-size: 0.625rem;
color: $gray4;
animation-name: expand;
animation-duration: 0.3s;
}
span.process-label-value {
font-style: italic;
font-weight: bold;
}
}
&:before {
content: "";
display: block;
position: absolute;
right: 47px;
width: 0;
height: 0;
border-style: solid;
}
&:before {
border-color: transparent transparent $blue2 transparent;
border-right-width: 8px;
border-bottom-width: 8px;
border-left-width: 8px;
top: -10px;
}
.separator {
margin: 0px 10px;
height: 1px;
background-color: $secondary;
}
}
</style>

View File

@ -0,0 +1,29 @@
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
height="16"
width="16"
xml:space="preserve"
viewBox="0 0 20 20"
y="0px"
x="0px"
class="taxonomies-icon">
<path
d="M 0,0 H 9 V 9 H 0 V 0 M 15.5,0 C 18,0 20,2 20,4.5 20,7 18,9 15.5,9 13,9 11,7 11,4.5 11,2 13,0 15.5,0 M 4.5,12 9,20 H 0 L 4.5,12 M 17,15 h 3 v 2 h -3 v 3 h -2 v -3 h -3 v -2 h 3 v -3 h 2 z"
/>
</svg>
</template>
<script>
export default {
name: 'TaxonomiesIcon'
}
</script>
<style type="text/scss">
svg.taxonomies-icon {
fill: #898d8f;
}
</style>

View File

@ -14,7 +14,7 @@
</label>
<div
class="block overflow-at">
class="block">
<div
v-for="(collection, key) in collections"
:key="key"
@ -87,11 +87,3 @@
}
}
</script>
<style scoped>
.overflow-at {
overflow: auto;
max-height: 125px;
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div class="pagination-area">
<div class="shown-items">
<div class="shown-items is-hidden-mobile">
{{
$i18n.get('info_showing_items') +
getFirstItem() +

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
height="63.328629"
width="368.00058"
version="1.1"
viewBox="0 0 368.00058 63.328629"
data-name="Camada 1"
id="Camada_1">
<metadata
id="metadata47">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>marca webPrancheta 1</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4">
<style
id="style2">.cls-1{fill:#a4ccd6;}.cls-2{fill:#7db6c4;}.cls-3{fill:#56a0b0;}.cls-4{fill:#1f2f56;}</style>
</defs>
<title
id="title6">marca webPrancheta 1</title>
<path
style="fill:#a4ccd6"
id="path8"
d="m 340.31269,27.701908 a 71.83,71.83 0 0 1 12.05,4.39 q 1.76,0.82 3.32,1.7 c 8.73,-9.71 9.7,-18.81 3.56,-24.9400005 v 0 c -6.14,-6.14 -15.24,-5.16 -25,3.5900005 q 0.84,1.51 1.64,3.21 a 71.83,71.83 0 0 1 4.43,12.05 z"
class="cls-1" />
<path
style="fill:#7db6c4"
id="path10"
d="m 315.73269,41.301908 a 46.91,46.91 0 0 0 -2,13.07 47,47 0 0 0 13.08,-2 57,57 0 0 1 -5.87,-5.29 57.05,57.05 0 0 1 -5.21,-5.78 z"
class="cls-2" />
<path
style="fill:#a4ccd6"
id="path12"
d="m 323.00269,25.671908 a 71.08,71.08 0 0 1 9.3,-11.38 q 1,-1 2,-1.86 c -6.09,-10.9400005 -14.11,-14.7000005 -21.8,-11.1200005 v 0 c -8.39,3.91 -10.34,13.7700005 -4.09,27.1600005 l 0.17,0.35 -0.19,-0.5 a 47.76,47.76 0 0 1 14.61,-2.65 z"
class="cls-1" />
<path
style="fill:#a4ccd6"
id="path14"
d="m 355.69269,33.801908 q -0.89,1 -1.88,2 a 70.85,70.85 0 0 1 -11.48,9.36 47.71,47.71 0 0 1 -2.66,14.51 l -0.5,-0.19 0.35,0.17 c 13.39,6.25 23.25,4.3 27.16,-4.09 v 0 c 3.58,-7.68 -0.15,-15.68 -10.99,-21.76 z"
class="cls-1" />
<path
style="fill:#7db6c4"
id="path16"
d="m 308.36269,28.341908 0.19,0.5 a 48.24,48.24 0 0 0 7.19,12.46 l 0.08,-0.27 a 58.82,58.82 0 0 1 7.18,-15.36 47.76,47.76 0 0 0 -14.64,2.67 z"
class="cls-2" />
<path
style="fill:#56a0b0"
id="path18"
d="m 340.31269,27.701908 a 60,60 0 0 0 -17.29,-2 58.82,58.82 0 0 0 -7.2,15.36 l -0.08,0.27 a 57.05,57.05 0 0 0 5.21,5.77 57,57 0 0 0 5.87,5.29 l 0.27,-0.08 a 59,59 0 0 0 15.24,-7.15 59.92,59.92 0 0 0 -2.02,-17.46 z"
class="cls-3" />
<path
style="fill:#7db6c4"
id="path20"
d="m 340.31269,27.701908 a 71.83,71.83 0 0 0 -4.39,-12.05 q -0.79,-1.7 -1.64,-3.21 -1,0.88 -2,1.86 a 71.08,71.08 0 0 0 -9.28,11.37 60,60 0 0 1 17.31,2.03 z"
class="cls-2" />
<path
style="fill:#7db6c4"
id="path22"
d="m 342.33269,45.161908 a 59,59 0 0 1 -15.24,7.13 l -0.27,0.08 a 48.19,48.19 0 0 0 12.36,7.11 v 0 l 0.5,0.19 a 47.71,47.71 0 0 0 2.65,-14.51 z"
class="cls-2" />
<path
style="fill:#7db6c4"
id="path24"
d="m 353.80269,35.781908 q 1,-1 1.88,-2 v 0 q -1.56,-0.88 -3.32,-1.7 a 71.83,71.83 0 0 0 -12.05,-4.39 59.92,59.92 0 0 1 2,17.44 70.85,70.85 0 0 0 11.49,-9.35 z"
class="cls-2" />
<path
style="fill:#1f2f56"
id="path26"
d="m 87.13269,12.421908 h -7.31 a 0.29,0.29 0 0 0 -0.32,0.28 v 41.25 c 0,0.19 0.11,0.28 0.32,0.28 h 7.31 c 0.21,0 0.32,-0.09 0.32,-0.28 v -41.25 c 0,-0.16 -0.11,-0.25 -0.32,-0.28 z"
class="cls-4" />
<path
style="fill:#1f2f56"
id="path28"
d="m 185.69269,27.661908 a 8,8 0 0 1 8.15,-8.09 h 11.56 a 0.28,0.28 0 0 0 0.32,-0.32 v -6.51 c 0,-0.18 -0.11,-0.29 -0.32,-0.32 h -11.56 c -10.3,0.7 -13.58,7.54 -15.08,13.15 v 0 c -0.11,0.11 -0.12,3.93 -0.12,7.88 0.08,3.06 -0.2,6 0.29,8.26 1.74,8 8,12.52 14.92,12.52 h 11.55 a 0.28,0.28 0 0 0 0.32,-0.32 v -6.52 c 0,-0.19 -0.11,-0.29 -0.32,-0.32 h -11.49 a 7.92,7.92 0 0 1 -8.23,-8 c 0,-3.43 0.01,-5.68 0.01,-11.41 z"
class="cls-4" />
<path
style="fill:#1f2f56"
id="path30"
d="m 95.56269,12.421908 h 18.78 c 6.13,0 14,6.1 14,13.94 v 27.55 a 0.28,0.28 0 0 1 -0.32,0.32 h -7.31 a 0.28,0.28 0 0 1 -0.32,-0.32 v -25.09 a 9.24,9.24 0 0 0 -9.47,-9.4 h -7.92 v 34.5 a 0.28,0.28 0 0 1 -0.32,0.32 h -7.15 a 0.28,0.28 0 0 1 -0.32,-0.32 v -41.18 c 0.05,-0.21 0.16,-0.32 0.35,-0.32 z"
class="cls-4" />
<path
style="fill:#1f2f56"
id="path32"
d="M 14.45269,12.421908 H 0.23268961 c -0.13,0 -0.21,0.08 -0.23,0.23 v 6.7 a 0.2,0.2 0 0 0 0.23,0.23 H 12.36269 v 34.42 a 0.2,0.2 0 0 0 0.22,0.23 h 7.5 a 0.2,0.2 0 0 0 0.22,-0.23 v -36.51 a 6.19,6.19 0 0 0 -0.79,-3.27 q -1.09,-1.8 -5.06,-1.8 z"
class="cls-4" />
<path
style="fill:#1f2f56"
id="path34"
d="m 32.43269,12.421908 h -21.8 v 0.23 a 2.71,2.71 0 0 1 1.6,0.53 2.35,2.35 0 0 1 0.85,1 2.7,2.7 0 0 1 0.26,1.08 5.31,5.31 0 0 1 0,0.6 c 0,1.76 0,3.69 0,3.69 h 19.09 a 0.2,0.2 0 0 0 0.23,-0.23 v -6.7 c 0,-0.1 -0.08,-0.18 -0.23,-0.2 z"
class="cls-4" />
<path
style="fill:#1f2f56"
id="path36"
d="m 255.00269,12.421908 h 18.78 c 6.13,0 14,6.1 14,13.94 v 27.55 a 0.28,0.28 0 0 1 -0.32,0.32 h -7.31 a 0.28,0.28 0 0 1 -0.32,-0.32 v -25.09 a 9.24,9.24 0 0 0 -9.47,-9.4 h -7.86 v 34.5 a 0.28,0.28 0 0 1 -0.32,0.32 h -7.18 a 0.28,0.28 0 0 1 -0.32,-0.32 v -41.18 c -0.01,-0.21 0.09,-0.32 0.32,-0.32 z"
class="cls-4" />
<path
style="fill:#1f2f56"
id="path38"
d="m 247.00269,23.231908 a 28,28 0 0 0 -0.48,-4 q -2.11,-6.83 -9.22,-6.84 h -20 c -0.19,0 -0.29,0.11 -0.32,0.32 v 6.55 a 0.28,0.28 0 0 0 0.32,0.32 h 18.87 c 3.61,0 4.11,5.53 0,6 -3.47,0.46 -6.89,0.89 -9.13,1 -7.85,0.47 -13.18,6 -13.71,13.05 v 0.45 a 16.8,16.8 0 0 0 1.27,6.36 c 2,4.56 6.33,7.82 13,7.82 h 19.08 a 0.28,0.28 0 0 0 0.32,-0.32 v -30.18 0 c 0,-0.18 0,-0.35 0,-0.53 z m -19.79,23.85 c -9.15,0 -8.78,-13.48 0,-13.48 8.78,0 10,-0.86 11.82,-1.13 v 14.61 z"
class="cls-4" />
<path
style="fill:#1f2f56"
id="path40"
d="m 72.64269,23.231908 a 28,28 0 0 0 -0.48,-4 q -2.11,-6.83 -9.22,-6.84 h -20 c -0.19,0 -0.29,0.11 -0.32,0.32 v 6.55 a 0.28,0.28 0 0 0 0.32,0.32 h 18.84 c 3.61,0 4.11,5.53 0,6 -3.47,0.46 -6.89,0.89 -9.13,1 -7.85,0.47 -13.18,6 -13.71,13.05 v 0.45 a 16.8,16.8 0 0 0 1.27,6.36 c 2,4.56 6.33,7.82 13,7.82 h 19.08 a 0.28,0.28 0 0 0 0.32,-0.32 v -30.18 0 c 0.02,-0.18 0.03,-0.35 0.03,-0.53 z m -19.77,23.85 c -9.15,0 -8.78,-13.48 0,-13.48 8.78,0 10,-0.86 11.82,-1.13 v 14.61 z"
class="cls-4" />
<path
style="fill:#1f2f56"
id="path42"
d="m 170.46269,23.231908 a 28,28 0 0 0 -0.48,-4 q -2.11,-6.83 -9.22,-6.84 h -20 c -0.19,0 -0.29,0.11 -0.32,0.32 v 6.55 a 0.28,0.28 0 0 0 0.32,0.32 h 18.84 c 3.61,0 4.11,5.53 0,6 -3.47,0.46 -6.89,0.89 -9.13,1 -7.85,0.47 -13.18,6 -13.71,13.05 v 0.45 a 16.8,16.8 0 0 0 1.24,6.33 c 2,4.56 6.33,7.82 13,7.82 h 19.08 a 0.28,0.28 0 0 0 0.32,-0.32 v -30.15 0 c 0.05,-0.18 0.06,-0.35 0.06,-0.53 z m -19.77,23.85 c -9.15,0 -8.78,-13.48 0,-13.48 8.78,0 10,-0.86 11.82,-1.13 v 14.61 z"
class="cls-4" />
</svg>

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -5,7 +5,9 @@
// Main imports
import Vue from 'vue';
import Buefy from 'buefy';
import VTooltip from 'v-tooltip'
import VTooltip from 'v-tooltip';
import { VueHammer } from 'vue2-hammer';
import VueMasonry from 'vue-masonry-css';
// Custom elements
import Text from '../../classes/metadata-types/text/Text.vue';
@ -42,17 +44,19 @@ import store from '../../js/store/store'
import router from './router'
import eventBusSearch from '../../js/event-bus-search';
import { I18NPlugin, UserPrefsPlugin, RouterHelperPlugin, ConsolePlugin, UserCapabilitiesPlugin } from './utilities';
import VueMask from 'v-mask';
import VueTheMask from 'vue-the-mask';
// Configure and Register Plugins
Vue.use(Buefy);
Vue.use(VTooltip);
Vue.use(VueHammer);
Vue.use(VueMasonry);
Vue.use(I18NPlugin);
Vue.use(UserPrefsPlugin);
Vue.use(RouterHelperPlugin);
Vue.use(UserCapabilitiesPlugin);
Vue.use(ConsolePlugin, {visual: false});
Vue.use(VueMask);
Vue.use(VueTheMask);
/* Metadata */
Vue.component('tainacan-text', Text);

View File

@ -18,6 +18,7 @@ import ExportPage from '../pages/singles/export-page.vue'
// Edition Form Components
import CollectionEditionForm from '../components/edition/collection-edition-form.vue'
import ImporterEditionForm from '../components/edition/importer-edition-form.vue'
import ImporterMappingForm from '../components/edition/importer-mapping-form.vue'
import ItemEditionForm from '../components/edition/item-edition-form.vue'
import TaxonomyEditionForm from '../components/edition/taxonomy-edition-form.vue'
import AvailableImportersPage from '../pages/lists/available-importers-page.vue';
@ -71,11 +72,13 @@ const routes = [
{ path: '/importers/', name: 'AvailableImportersPage', component: AvailableImportersPage, meta: {title: i18nGet('title_importers_page'), icon: 'file-multiple'} },
{ path: '/importers/:importerSlug', name: 'ImporterEditionForm', component: ImporterEditionForm, meta: {title: i18nGet('title_importer_page'), icon: 'file-multiple'} },
{ path: '/importers/:importerSlug/:sessionId', name: 'ImporterCreationForm', component: ImporterEditionForm, meta: { title: i18nGet('title_importer_page'), icon: 'file-multiple' } },
{ path: '/importers/:importerType/:sessionId/mapping/:collectionId', name: 'ImporterMappingForm', component: ImporterMappingForm, meta: {title: i18nGet('title_importer_mapping_page'), icon: 'file-multiple'} },
{ path: '/export/collection/:collectionId', name: 'ExportCollection', component: ExportPage, meta: {title: i18nGet('title_export_collection_page'), icon: 'export'} },
{ path: '/export/item/:itemId', name: 'ExportItem', component: ExportPage, meta: {title: i18nGet('title_export_item_page'), icon: 'export'} },
{ path: '/export', name: 'Export', component: ExportPage, meta: {title: i18nGet('title_export_page'), icon: 'export'} },
{ path: '*', redirect: '/'}
];

View File

@ -1,7 +1,9 @@
// Main imports
import Vue from 'vue';
import Buefy from 'buefy';
import VTooltip from 'v-tooltip'
import VTooltip from 'v-tooltip';
import { VueHammer } from 'vue2-hammer';
import VueMasonry from 'vue-masonry-css';
// Custom elements
import Text from '../../classes/metadata-types/text/Text.vue';
@ -32,6 +34,7 @@ import ItemsPage from '../pages/lists/items-page.vue';
import ViewModeTable from '../../theme-helper/view-mode-table.vue';
import ViewModeCards from '../../theme-helper/view-mode-cards.vue';
import ViewModeRecords from '../../theme-helper/view-mode-records.vue';
import ViewModeMasonry from '../../theme-helper/view-mode-masonry.vue';
// Remaining imports
import HelpButton from '../components/other/help-button.vue';
@ -43,7 +46,9 @@ import { I18NPlugin, UserPrefsPlugin, RouterHelperPlugin, ConsolePlugin } from '
// Configure and Register Plugins
Vue.use(Buefy);
Vue.use(VTooltip)
Vue.use(VTooltip);
Vue.use(VueHammer);
Vue.use(VueMasonry);
Vue.use(I18NPlugin);
Vue.use(UserPrefsPlugin);
Vue.use(RouterHelperPlugin);
@ -83,6 +88,7 @@ Vue.component('items-page', ItemsPage);
Vue.component('view-mode-table', ViewModeTable);
Vue.component('view-mode-cards', ViewModeCards);
Vue.component('view-mode-records', ViewModeRecords);
Vue.component('view-mode-masonry', ViewModeMasonry);
Vue.use(eventBusSearch, { store: store, router: routerTheme});

View File

@ -205,6 +205,12 @@ RouterHelperPlugin.install = function (Vue, options = {}) {
getAvailableImportersPath() {
return '/importers/new';
},
getProcessesPage(highlightedProcess) {
if (highlightedProcess)
return '/events?tab=processes&highlight=' + highlightedProcess;
else
return '/events?tab=processes';
},
// Singles
getCollectionPath(id) {
return '/collections/' + id;
@ -224,6 +230,9 @@ RouterHelperPlugin.install = function (Vue, options = {}) {
getEventPath(id) {
return '/events/' + id;
},
getImporterPath(importerType, sessionId) {
return '/importers/' + importerType + '/' + sessionId;
},
// New
getNewCollectionPath() {
return '/collections/new';
@ -277,6 +286,9 @@ RouterHelperPlugin.install = function (Vue, options = {}) {
getImporterEditionPath(importerType) {
return '/importers/' + importerType;
},
getImporterMappingPath(importerType, sessionId, collectionId) {
return '/importers/' + importerType + '/' + sessionId + '/mapping/' + collectionId;
},
}
}

View File

@ -1,5 +1,5 @@
<template>
<div class="primary-page page-container">
<div class="repository-level-page page-container">
<tainacan-title />
<h3>{{ $i18n.get('label_available_importers') }}</h3>
@ -66,7 +66,7 @@ export default {
flex: wrap;
.importer-type {
border: 1px solid $tainacan-input-background;
border: 1px solid $gray2;
padding: 15px;
margin: 20px;
cursor: pointer;

View File

@ -1,5 +1,5 @@
<template>
<div class="primary-page page-container">
<div class="repository-level-page page-container">
<b-loading :active.sync="isLoadingMetadatumMappers"/>
<tainacan-title />
<div
@ -34,6 +34,16 @@
{{ $i18n.get(metadatum_mapper.name) }}
</router-link>
</b-dropdown-item>
<b-dropdown-item>
<div
id="a-import-collection"
tag="div"
@click="onOpenImportersModal">
{{ $i18n.get('label_import_collection') }}
<br>
<small class="is-small">{{ $i18n.get('info_import_a_collection') }}</small>
</div>
</b-dropdown-item>
</b-dropdown>
</div>
</div>
@ -77,7 +87,7 @@
v-if="status == undefined || status == ''"
id="button-create-collection"
tag="button"
class="button is-primary"
class="button is-secondary"
:to="{ path: $routerHelper.getNewCollectionPath() }">
{{ $i18n.getFrom('collections', 'new_item') }}
</router-link>
@ -130,6 +140,7 @@
<script>
import CollectionsList from '../../components/lists/collections-list.vue';
import AvailableImportersModal from '../../components/other/available-importers-modal.vue';
import { mapActions, mapGetters } from 'vuex';
export default {
@ -194,6 +205,13 @@ export default {
let last = (Number(this.collectionsPerPage*(this.page - 1)) + Number(this.collectionsPerPage));
return last > this.totalCollections ? this.totalCollections : last;
},
onOpenImportersModal() {
this.$modal.open({
parent: this,
component: AvailableImportersModal,
hasModalCard: true
});
}
},
computed: {
@ -237,11 +255,9 @@ export default {
.sub-header {
min-height: $subheader-height;
height: $subheader-height;
height: $header-height;
margin-left: -$page-side-padding;
margin-right: -$page-side-padding;
margin-top: -$page-top-padding;
padding-top: $page-small-top-padding;
padding-left: $page-side-padding;
padding-right: $page-side-padding;
border-bottom: 1px solid #ddd;

View File

@ -2,29 +2,66 @@
<div>
<div
:class="{
'primary-page': isRepositoryLevel,
'repository-level-page': isRepositoryLevel,
'page-container': isRepositoryLevel
}">
<tainacan-title />
<div :class="{ 'above-subheader': isRepositoryLevel }">
<div
v-if="isRepositoryLevel"
class="tabs">
<ul>
<li
@click="onChangeTab('')"
:class="{ 'is-active': tab == undefined || tab == ''}"><a>{{ $i18n.get('events') }}</a></li>
<li
@click="onChangeTab('processes')"
:class="{ 'is-active': tab == 'processes'}"><a>{{ $i18n.get('processes') }}</a></li>
</ul>
</div>
<b-loading
:is-full-page="false"
:active.sync="isLoading"
:can-cancel="false"/>
<events-list
v-if="tab != 'processes'"
:is-loading="isLoading"
:total-events="totalEvents"
:page="page"
:page="eventsPage"
:events-per-page="eventsPerPage"
:events="events"/>
<processes-list
v-if="tab == 'processes'"
:is-loading="isLoading"
:total="total"
:page="processesPage"
:processes-per-page="processesPerPage"
:processes="processes"/>
<!-- Empty state processes image -->
<div v-if="tab == 'processes' && processes.length <= 0 && !isLoading">
<section class="section">
<div class="content has-text-grey has-text-centered">
<p>
<b-icon
icon="inbox"
size="is-large"/>
</p>
<p v-if="status == undefined || status == ''">{{ $i18n.get('info_no_process') }}</p>
</div>
</section>
</div>
<!-- Footer -->
<div
class="pagination-area"
v-if="totalEvents > 0">
v-if="tab != 'processes' && totalEvents > 0">
<div class="shown-items">
{{
$i18n.get('info_showing_events') +
(eventsPerPage * (page - 1) + 1) +
(eventsPerPage * (eventsPage - 1) + 1) +
$i18n.get('info_to') +
getLastEventNumber() +
$i18n.get('info_of') + totalEvents + '.'
@ -49,12 +86,49 @@
<b-pagination
@change="onPageChange"
:total="totalEvents"
:current.sync="page"
:current.sync="eventsPage"
order="is-centered"
size="is-small"
:per-page="eventsPerPage"/>
</div>
</div>
<div
class="pagination-area"
v-if="tab == 'processes' && processes.length > 0">
<div class="shown-items">
{{
$i18n.get('info_showing_processes') +
(processesPerPage * (processesPage - 1) + 1) +
$i18n.get('info_to') +
getLastProcessesNumber() +
$i18n.get('info_of') + total + '.'
}}
</div>
<div class="items-per-page">
<b-field
horizontal
:label="$i18n.get('label_processes_per_page')">
<b-select
:value="processesPerPage"
@input="onChangeProcessesPerPage"
:disabled="processes.length <= 0">
<option value="12">12</option>
<option value="24">24</option>
<option value="48">48</option>
<option value="96">96</option>
</b-select>
</b-field>
</div>
<div class="pagination">
<b-pagination
@change="onPageChange"
:total="total"
:current.sync="processesPage"
order="is-centered"
size="is-small"
:per-page="processesPerPage"/>
</div>
</div>
</div>
</div>
</div>
@ -62,6 +136,7 @@
<script>
import EventsList from "../../components/lists/events-list.vue";
import ProcessesList from "../../components/lists/processes-list.vue";
import { mapActions, mapGetters } from 'vuex';
import moment from 'moment'
@ -71,13 +146,17 @@
return {
isLoading: false,
totalEvents: 0,
page: 1,
eventsPage: 1,
processesPage: 1,
eventsPerPage: 12,
isRepositoryLevel: false
processesPerPage: 12,
isRepositoryLevel: false,
tab: ''
}
},
components: {
EventsList
EventsList,
ProcessesList
},
methods: {
...mapActions('event', [
@ -87,6 +166,22 @@
...mapGetters('event', [
'getEvents'
]),
...mapActions('bgprocess', [
'fetchProcesses',
]),
...mapGetters('bgprocess', [
'getProcesses'
]),
onChangeTab(tab) {
this.tab = tab;
if (this.tab == 'processes') {
this.loadProcesses();
this.$router.push({query: {tab: 'processes'}});
} else {
this.loadEvents();
this.$router.push({query: {}});
}
},
onChangeEventsPerPage(value) {
this.eventsPerPage = value;
this.$userPrefs.set('events_per_page', value)
@ -98,15 +193,32 @@
});
this.loadEvents();
},
onChangeProcessesPerPage(value) {
this.processesPerPage = value;
this.$userPrefs.set('processes_per_page', value)
.then((newValue) => {
this.processesPerPage = newValue;
})
.catch(() => {
this.$console.log("Error settings user prefs for processes per page")
});
this.loadProcesses();
},
onPageChange(page) {
this.page = page;
this.loadEvents();
if (this.tab == 'processes') {
this.processesPage = page;
this.loadProcesses();
} else {
this.eventsPage = page;
this.loadEvents();
}
},
loadEvents() {
this.isLoading = true;
if(this.isRepositoryLevel) {
this.fetchEvents({'page': this.page, 'eventsPerPage': this.eventsPerPage})
this.fetchEvents({'page': this.eventsPage, 'eventsPerPage': this.eventsPerPage})
.then((res) => {
this.isLoading = false;
this.totalEvents = res.total;
@ -115,7 +227,7 @@
this.isLoading = false;
});
} else {
this.fetchCollectionEvents({'page': this.page, 'eventsPerPage': this.eventsPerPage, 'collectionId': this.$route.params.collectionId})
this.fetchCollectionEvents({'page': this.eventsPage, 'eventsPerPage': this.eventsPerPage, 'collectionId': this.$route.params.collectionId})
.then((res) => {
this.isLoading = false;
this.totalEvents = res.total;
@ -125,9 +237,25 @@
});
}
},
loadProcesses() {
this.isLoading = true;
this.fetchProcesses({ 'page': this.processesPage, 'processesPerPage': this.processesPerPage })
.then((res) => {
this.isLoading = false;
this.total = res.total;
})
.catch(() => {
this.isLoading = false;
});
},
getLastEventNumber() {
let last = (Number(this.eventsPerPage * (this.page - 1)) + Number(this.eventsPerPage));
let last = (Number(this.eventsPerPage * (this.eventPage - 1)) + Number(this.eventsPerPage));
return last > this.totalEvents ? this.totalEvents : last;
},
getLastProcessesNumber() {
let last = (Number(this.processesPerPage * (this.processesPage - 1)) + Number(this.processesPerPage));
return last > this.total ? this.total : last;
}
},
computed: {
@ -140,26 +268,38 @@
moment(event['log_date'], 'YYYY-MM-DD h:mm:ss').format('DD/MM/YYYY, hh:mm:ss');
return eventsList;
},
processes(){
return this.getProcesses();
}
},
created() {
this.eventsPerPage = this.$userPrefs.get('events_per_page');
this.processesPerPage = this.$userPrefs.get('processes_per_page');
this.isRepositoryLevel = (this.$route.params.collectionId === undefined);
},
mounted(){
if (this.eventsPerPage != this.$userPrefs.get('events_per_page'))
this.eventsPerPage = this.$userPrefs.get('events_per_page');
if (this.$route.query.tab == 'processes' && this.isRepositoryLevel)
this.tab = 'processes';
if (!this.eventsPerPage) {
this.eventsPerPage = 12;
this.$userPrefs.set('events_per_page', 12);
}
this.loadEvents();
if (this.tab != 'processes') {
if (this.eventsPerPage != this.$userPrefs.get('events_per_page'))
this.eventsPerPage = this.$userPrefs.get('events_per_page');
if (!this.isRepositoryLevel) {
document.getElementById('collection-page-container').addEventListener('scroll', ($event) => {
this.$emit('onShrinkHeader', ($event.target.scrollTop > 53));
});
if (!this.eventsPerPage) {
this.eventsPerPage = 12;
this.$userPrefs.set('events_per_page', 12);
}
this.loadEvents();
} else {
if (this.processesPerPage != this.$userPrefs.get('processes_per_page'))
this.processesPerPage = this.$userPrefs.get('processes_per_page');
if (!this.processesPerPage) {
this.processesPerPage = 12;
this.$userPrefs.set('processes_per_page', 12);
}
this.loadProcesses();
}
}
}
@ -173,8 +313,6 @@
height: $header-height;
margin-left: -$page-small-side-padding;
margin-right: -$page-small-side-padding;
margin-top: -$page-small-top-padding;
padding-top: $page-small-top-padding;
padding-left: $page-small-side-padding;
padding-right: $page-small-side-padding;
border-bottom: 1px solid #ddd;

View File

@ -1,5 +1,5 @@
<template>
<div class="primary-page page-container">
<div class="repository-level-page page-container">
<tainacan-title />
<filters-list/>
</div>

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
<template>
<div class="primary-page page-container">
<div class="repository-level-page page-container">
<tainacan-title />
<metadata-list/>
</div>

View File

@ -1,6 +1,6 @@
<template>
<div>
<div class="primary-page page-container">
<div class="repository-level-page page-container">
<tainacan-title />
<div
class="sub-header"
@ -58,7 +58,7 @@
v-if="status == undefined || status == ''"
id="button-create-taxonomy"
tag="button"
class="button is-primary"
class="button is-secondary"
:to="{ path: $routerHelper.getNewTaxonomyPath() }">
{{ $i18n.getFrom('taxonomies', 'new_item') }}
</router-link>
@ -198,11 +198,9 @@
.sub-header {
max-height: $subheader-height;
height: $subheader-height;
height: $header-height;
margin-left: -$page-side-padding;
margin-right: -$page-side-padding;
margin-top: -$page-top-padding;
padding-top: $page-small-top-padding;
padding-left: $page-side-padding;
padding-right: $page-side-padding;
border-bottom: 1px solid #ddd;

View File

@ -1,44 +1,32 @@
<template>
<div class="columns is-fullheight">
<section class="column is-secondary-content">
<tainacan-subheader
:class="{ 'is-shrink': shouldShrinkHeader }"
:id="collectionId"/>
<tainacan-collection-subheader :id="collectionId"/>
<router-view
@onShrinkHeader="onUpdateShrinkHeader($event)"
id="collection-page-container"
:collection-id="collectionId"
class="page-container page-container-small"
:class="{'page-container-shrinked': shouldShrinkHeader }"/>
class="page-container page-container-small"/>
</section>
</div>
</template>
<script>
import TainacanSubheader from '../../components/navigation/tainacan-subheader.vue';
import TainacanCollectionSubheader from '../../components/navigation/tainacan-collection-subheader.vue';
export default {
name: 'CollectionPage',
data(){
return {
collectionId: Number,
shouldShrinkHeader: false
collectionId: Number
}
},
components: {
TainacanSubheader
TainacanCollectionSubheader
},
created(){
this.collectionId = parseInt(this.$route.params.collectionId);
this.$eventBusSearch.setCollectionId(this.collectionId);
},
methods: {
onUpdateShrinkHeader(event) {
if (this.shouldShrinkHeader != event)
this.shouldShrinkHeader = event;
}
}
}
</script>

View File

@ -1,7 +1,7 @@
<template>
<div>
<div class="is-fullheight">
<div class="page-container primary-page">
<div class="page-container repository-level-page">
<tainacan-title/>
<h1 class="event-titles">{{ event.description }}</h1>
<div

View File

@ -1,21 +1,17 @@
<template>
<div class="columns is-fullheight">
<section class="column is-secondary-content">
<tainacan-subheader
:class="{ 'is-shrink': shouldShrinkHeader }"
:id="collectionId"/>
<tainacan-collection-subheader :id="collectionId"/>
<router-view
@onShrinkHeader="onUpdateShrinkHeader($event)"
id="export-page-container"
:collection-id="collectionId"
class="page-container page-container-small"
:class="{'page-container-shrinked': shouldShrinkHeader }"/>
class="page-container page-container-small"/>
</section>
</div>
</template>
<script>
import TainacanSubheader from '../../components/navigation/tainacan-subheader.vue';
import TainacanCollectionSubheader from '../../components/navigation/tainacan-collection-subheader.vue';
export default {
name: 'ExportPage',
@ -23,24 +19,17 @@ export default {
return {
collectionId: Number,
itemId: Number,
selectedList: [],
shouldShrinkHeader: false
selectedList: []
}
},
components: {
TainacanSubheader
TainacanCollectionSubheader
},
created(){
this.collectionId = parseInt(this.$route.params.collectionId);
this.itemId = parseInt(this.$route.params.itemId);
this.selectedList = [],
this.$eventBusSearch.setCollectionId(this.collectionId);
},
methods: {
onUpdateShrinkHeader(event) {
if (this.shouldShrinkHeader != event)
this.shouldShrinkHeader = event;
}
}
}

View File

@ -358,9 +358,9 @@
height: 36px;
width: 36px;
border: none;
background-color: $tainacan-input-background;
background-color: $gray2;
color: $secondary;
padding: 0px;
padding: 0;
border-top-left-radius: 2px;
border-bottom-left-radius: 2px;
cursor: pointer;
@ -371,12 +371,8 @@
}
}
.page-container-shrinked {
height: calc(100% - 118px) !important; // Bigger than the others due footer's height
}
.page-container {
padding: 25px 0px;
padding: 25px 0;
.tainacan-page-title {
padding-left: $page-side-padding;
@ -404,7 +400,7 @@
transition: all 0.6s;
.field {
padding: 10px 0px 10px 30px;
padding: 10px 0 10px 30px;
}
@ -418,13 +414,15 @@
}
.field {
border-bottom: 1px solid $draggable-border-color;
border-bottom: 1px solid $gray2;
padding: 10px 25px;
.label {
font-size: 14px;
font-weight: 500;
margin-bottom: 0.5em;
display: inline-flex;
align-items: center;
span {
margin-right: 18px;
@ -437,13 +435,16 @@
label {
font-size: 16px !important;
font-weight: 500 !important;
color: $tertiary !important;
color: $blue5 !important;
line-height: 1.2em;
}
}
.collapse-all {
font-size: 12px;
display: inline-flex;
align-items: center;
.icon {
vertical-align: bottom;
}
@ -466,11 +467,11 @@
height: 72px;
width: 72px;
border: none;
background-color: $tainacan-input-background;
background-color: $gray2;
color: $secondary;
margin-bottom: 6px;
&:hover {
background-color: $primary-light;
background-color: $turquoise2;
cursor: pointer;
}
}
@ -489,12 +490,12 @@
.icon {
font-size: 18px !important;
color: $gray;
color: $gray3;
}
}
}
.section-attachments {
border: 1px solid $draggable-border-color;
border: 1px solid $gray2;
height: 250px;
max-width: 100%;
resize: vertical;
@ -528,7 +529,7 @@
font-weight: bold;
z-index: 99;
text-align: center;
color: gray;
color: $gray4;
top: 70px;
max-width: 90px;
}
@ -539,7 +540,7 @@
position: absolute;
bottom: 0;
z-index: 999999;
background-color: $primary-lighter;
background-color: $gray1;
width: 100%;
height: 65px;

View File

@ -1,6 +1,6 @@
<template>
<div class="columns is-fullheight">
<div class="page-container primary-page">
<div class="page-container repository-level-page">
<div class="card">
<div class="card-content">
<p class="title">

View File

@ -14,7 +14,7 @@
background: $secondary !important;
}
&.is-primary:hover, &.is-primary:focus {
background: $primary !important;
background: $turquoise3 !important;
}
&.is-success:hover, &.is-success:focus {
background: $success !important;
@ -27,9 +27,9 @@
transform: none !important;
}
&.is-outlined {
color: #150e38 !important;
color: $turquoise5 !important;
background-color: white !important;
border-color: $gray-light !important;
border-color: $gray4 !important;
}
&:focus {
outline: 0px;
@ -37,8 +37,8 @@
&[disabled], &:hover[disabled] {
border: none !important;
cursor: not-allowed !important;
color: $gray-light !important;
background-color: $tainacan-input-background !important;
color: $gray4 !important;
background-color: $gray2 !important;
}
&.is-white[disabled] {
background-color: white !important;

View File

@ -10,7 +10,7 @@
flex-shrink: 0;
border-radius: 0;
display: inline-block;
border: 1px solid $gray-light;
border: 1px solid $gray4;
transition: background 150ms ease-out;
box-shadow: none !important;
}
@ -19,10 +19,10 @@
&:active input[type="checkbox"] + .check,
&:hover input[type="checkbox"] + .check {
box-shadow: none !important;
border-color: $gray-light !important;
border-color: $gray4 !important;
}
input[type="checkbox"]:checked + .check {
background: white url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1 1'%3E%3Cpath style='fill:%23000' d='M 0.04038059,0.6267767 0.14644661,0.52071068 0.42928932,0.80355339 0.3232233,0.90961941 z M 0.21715729,0.80355339 0.85355339,0.16715729 0.95961941,0.2732233 0.3232233,0.90961941 z'%3E%3C/path%3E%3C/svg%3E") no-repeat center center !important;
border-color: $gray-light !important;
border-color: $gray4 !important;
}
}
}

View File

@ -28,13 +28,21 @@
label { margin-bottom: 0; }
&.control { font-size: 13px !important; }
.b-checkbox { width: 100% };
&:hover { background-color: $primary-lighter; }
.is-small { color: gray; }
&.is-active { background-color: $primary-light; }
&:hover { background-color: $gray1; }
.is-small { color: $gray4; }
&.is-active { background-color: $turquoise2; }
.media-content {
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 150px;
}
}
}
}
}
.taginput-container {
padding: 0 !important;
background-color: white !important;
@ -42,10 +50,13 @@
&:focus, &:active {
border: none !important;
}
.input { margin-bottom: 0px !important; }
.input {
margin-bottom: 0px !important;
height: 1.85rem !important;
}
.input.has-selected, .input:focus, .input:active {
background-color: white;
border: 1px solid $tainacan-input-background !important;
border: 1px solid $gray2 !important;
}
.tag {
background: white;
@ -53,7 +64,7 @@
padding-left: 0.5em;
&.is-delete {
color: $gray-light;
color: $gray4;
&::after {
height: 30% !important;
width: 1px !important;
@ -71,7 +82,7 @@
}
.selected-list-box {
padding: 4px 0px;
border: 1px solid $tainacan-input-background;
border: 1px solid $gray2;
background-color: white;
display: flex;
font-size: 12px;
@ -85,7 +96,7 @@
padding-left: 0.5em;
&.is-delete {
color: $gray-light;
color: $gray4;
&::after {
height: 30% !important;
width: 1px !important;

View File

@ -0,0 +1,27 @@
#filters-mobile-modal {
.modal-close {
right: calc(8.3333333% + 20px);
background-color: $gray1;
&:hover {
background-color: $gray1;
}
&::before, &::after {
background-color: $secondary;
}
}
.modal-content {
background-color: white;
margin: 0 8.3333333% 0 0;
padding: 24px $page-side-padding;
border-radius: 0;
height: 100%;
max-height: 100%;
overflow-y: auto;
h3 {
font-size: 100%;
}
}
}

View File

@ -7,10 +7,18 @@
&:focus, &:active {
box-shadow: none !important;
background-color: white;
border: 1px solid $tainacan-input-background !important;
border: 1px solid $gray2 !important;
}
&[disabled] {
color: $tainacan-placeholder-color;
background-color: $tainacan-input-background;
color: $gray4 !important;
background-color: $gray2 !important;
}
&::placeholder,
&::-ms-input-placeholder,
&:-ms-input-placeholder,
&:-moz-placeholder,
&::-moz-placeholder,
&::-webkit-input-placeholder {
color: $gray4 !important;
}
}

View File

@ -1,9 +1,17 @@
// Tainacan modals
.modal .animation-content {
width: 100%;
}
.modal {
display: inline-block;
}
.tainacan-modal-title {
h1, h2 {
font-size: 20px;
font-weight: 500;
color: $tertiary;
color: $blue5;
display: inline-block;
}
a.back-link{
@ -12,15 +20,17 @@
margin-top: 5px;
}
hr{
margin: 3px 0px 4px 0px;
margin: 3px 0 4px 0;
height: 1px;
background-color: $secondary;
border-top: 0;
}
margin-bottom: 40px;
}
.tainacan-modal-content {
background-color: white;
padding: 52px 80px;
padding: 52px 8.3333333%;
position: relative;
figure {
margin: 0;
@ -31,16 +41,16 @@
}
.form-submit {
padding: 80px 0em 0.4em 0em !important;
padding: 40px 0em 0.4em 0em !important;
}
}
// Bulma modals customized for Tainacan
.dialog{
.dialog {
.modal-background {
background-color: rgba(0, 0, 0, 0.70);
}
.modal-card {
background-color: $modal-backgound-color;
background-color: $turquoise2;
color: $secondary;
border-radius: 10px;
flex-wrap: wrap;
@ -49,7 +59,7 @@
margin: 0 auto !important;
.modal-card-head, .modal-card-body, .modal-card-foot {
background-color: $modal-backgound-color;
background-color: $turquoise2;
color: $secondary;
border: none;
padding-bottom: 12px;
@ -97,8 +107,8 @@
}
.button:not(.is-success) {
background-color: white;
color: $tertiary;
border: 1px solid $gray-light;
color: $blue5;
border: 1px solid $gray4;
}
}
}
@ -141,7 +151,7 @@
// h1, h2 {
// font-size: 20px;
// font-weight: 500;
// color: $tertiary;
// color: $blue5;
// display: inline-block;
// margin-bottom: 3px;
// }
@ -153,7 +163,7 @@
// border-top: none;
// border-left: none;
// border-right: none;
// border-bottom: 3px solid $primary;
// border-bottom: 3px solid $turquoise3;
// }
// }
@ -174,11 +184,11 @@
// padding: 12px;
// }
// .attachment.details {
// box-shadow: inset 0 0 0 3px #fff, inset 0 0 0 14px $primary-light;
// box-shadow: inset 0 0 0 3px #fff, inset 0 0 0 14px $turquoise2;
// }
// .attachment.details .check, .wp-core-ui .attachment.selected .check:focus, .wp-core-ui .media-frame.mode-grid .attachment.selected .check {
// background-color: $primary-light;
// box-shadow: 0 0 0 1px #fff,0 0 0 2px $primary-light;
// background-color: $turquoise2;
// box-shadow: 0 0 0 1px #fff,0 0 0 2px $turquoise2;
// }
// }
// .media-sidebar {
@ -217,7 +227,7 @@
// cursor: default;
// }
// .media-button.button-secondary {
// color: $tertiary;
// color: $blue5;
// border-color: #999;
// background: white;
// box-shadow: none;

View File

@ -4,8 +4,8 @@
box-shadow: none;
&.is-dark {
background-color: $tainacan-input-background;
color: $gray-light;
background-color: $gray2;
color: $gray4;
}
&.is-warning {
background-color: #e7dede;

View File

@ -4,12 +4,18 @@
align-items: center;
font-size: 0.85em !important;
font-weight: normal !important;
border-top: 1px solid $gray;
border-top: 1px solid $gray3;
padding-top: 0;
padding-bottom: 0;
padding-left: $page-side-padding;
padding-right: $page-side-padding;
color: $gray-light;
margin-left: $page-side-padding;
margin-right: $page-side-padding;
padding-left: 0.75rem;
padding-right: 0.75rem;
color: $gray4;
@media screen and (max-width: 768px) {
flex-wrap: wrap;
}
.shown-items {
flex-grow: 1;
@ -18,13 +24,24 @@
.items-per-page {
flex-grow: 5;
margin-top: 0.35em;
@media screen and (max-width: 768px) {
flex-grow: 2;
text-align: center;
.field {
display: inline-flex;
align-items: baseline;
}
}
.field-label {
flex-grow: 5;
margin-right: 0.5em;
.label {
font-size: 1em !important;
font-weight: normal !important;
color: $gray-light;
color: $gray4;
}
}
select {
@ -35,8 +52,17 @@
.pagination {
flex-grow: 1;
ul {
margin-bottom: 0px;
padding: 0px;
}
&.is-small {
font-size: 0.85em;
}
a[disabled="disabled"] {
color: $gray-light;
color: $gray4;
}
.pagination-link, .pagination-previous, .pagination-next {
background-color: transparent;
@ -44,11 +70,11 @@
border: none;
}
.pagination-link.is-current {
color: $gray-light;
color: $gray4;
}
.pagination-link::after:not(:last-child) {
content: ',';
color: $gray-light;
color: $gray4;
}
.mdi-chevron-left::before {
content: "\F40A";
@ -59,5 +85,11 @@
content: "\F40A";
font-size: 17px;
}
@media screen and (max-width: 768px) {
.pagination-list { order: 2; }
.pagination-next { order: 3; }
}
}
}

View File

@ -3,7 +3,7 @@
input[type="radio"] + .check {
width: 13px !important;
height: 13px !important;
border: 1px solid $gray-light !important;
border: 1px solid $gray4 !important;
}
input[type="radio"] + .check::before {
background: black !important;
@ -16,7 +16,7 @@
box-shadow: none !important;
}
input[type="radio"]:checked + .check {
border-color: $gray-light !important;
border-color: $gray4 !important;
}
&:focus input[type="radio"]:checked + .check {
box-shadow: none !important;

View File

@ -11,7 +11,7 @@
margin-bottom: 0px !important;
color: $tainacan-input-color;
option:checked, option:hover {
background-color: $primary-lighter !important;
background-color: $gray1 !important;
}
&:focus, &:active {
box-shadow: none !important;
@ -21,15 +21,18 @@
background-color: white !important;
}
}
&:not(.is-multiple)::after {
&:not(.is-loading)::after {
content: "\F35D" !important;
font: normal normal normal 24px/1 "Material Design Icons" !important;
border: none !important;
transform: none !important;
margin-top: -15px !important;
right: 15px !important;
color: $secondary;
color: $secondary !important;
display: flex !important;
align-items: initial;
}
}
&.is-loading.is-small::after {
font-size: 0.875rem;
}
}

View File

@ -1,8 +1,8 @@
.switch {
input[type="checkbox"] + .check {
background-color: $gray-light;
border: 2px solid $gray-light;
background-color: $gray4;
border: 2px solid $gray4;
width: 2.7em;
height: 1.7em;
transition: none;
@ -13,7 +13,7 @@
}
}
&:hover input[type="checkbox"]:checked + .check {
background-color: $primary-light;
background-color: $turquoise2;
}
input[type="checkbox"]:checked + .check {
@ -26,7 +26,7 @@
}
}
&:hover input[type="checkbox"] + .check {
background-color: $gray-light;
background-color: $gray4;
}
&:focus input[type="checkbox"] + .check,
@ -38,7 +38,7 @@
font-size: 9px;
input[type="checkbox"] + .check {
border: 1.5px solid $gray-light;
border: 1.5px solid $gray4;
width: 2.55em;
height: 1.7em;

View File

@ -9,10 +9,13 @@
width: 100%;
height: calc(100% - 40px);
border-collapse: separate;
overflow: auto;
overflow-x: auto;
overflow-y: hidden;
margin-bottom: 0px !important;
table.tainacan-table {
animation-name: appear;
animation-duration: 0.5s;
width: 100%;
border-collapse: separate;
border-spacing: 0;
@ -45,7 +48,7 @@
}
// Only to be used in case we can implement Column resizing
// th:not(:last-child) {
// border-right: 1px solid $tainacan-input-background !important;
// border-right: 1px solid $gray2 !important;
// }
.thumbnail-cell {
@ -57,7 +60,7 @@
min-width: 80px;
max-width: 80px;
p {
color: $gray-light;
color: $gray4;
font-size: 11px;
line-height: 1.5;
}
@ -66,7 +69,7 @@
min-width: 80px;
max-width: 160px;
p {
color: $gray-light;
color: $gray4;
font-size: 11px;
line-height: 1.5;
}
@ -75,7 +78,7 @@
min-width: 120px;
max-width: 200px;
p {
color: $gray-light;
color: $gray4;
font-size: 11px;
line-height: 1.5;
}
@ -84,7 +87,7 @@
min-width: 120px;
max-width: 240px;
p {
color: $gray-light;
color: $gray4;
font-size: 11px;
line-height: 1.5;
}
@ -109,7 +112,7 @@
position: sticky;
position: -webkit-sticky;
background-color: white;
border-bottom: 1px solid $tainacan-input-background;
border-bottom: 1px solid $gray2;
top: 0px;
z-index: 9;
padding: 10px;
@ -117,7 +120,7 @@
.th-wrap {
font-size: 12px !important;
color: $gray-light;
color: $gray4;
font-weight: normal !important;
text-overflow: ellipsis;
overflow-x: hidden;
@ -130,9 +133,9 @@
background-color: transparent;
&.selected-row {
background-color: $primary-lighter;
background-color: $turquoise1;
.checkbox-cell .checkbox, .actions-cell .actions-container {
background-color: $primary-lighter-hover;
background-color: $turquoise2;
}
}
td {
@ -171,6 +174,8 @@
z-index: 9;
background-color: white;
float: right;
justify-content: center;
align-items: center;
}
a {
@ -185,21 +190,21 @@
}
&:hover {
background-color: $tainacan-input-background !important;
background-color: $gray1 !important;
cursor: pointer;
.checkbox-cell {
position: sticky !important;
position: -webkit-sticky !important;
background-color: $gray-hover;
background-color: $gray2;
.checkbox {
background-color: $gray-hover !important;
background-color: $gray2 !important;
}
}
.actions-cell {
.actions-container {
background: $gray-hover !important;
background: $gray2 !important;
}
}
@ -209,3 +214,4 @@
}
}
}

View File

@ -9,7 +9,7 @@
}
}
li.is-active a {
border-bottom: 5px solid $primary;
color: $primary;
border-bottom: 5px solid $turquoise5;
color: $turquoise5;
}
}

View File

@ -1,5 +1,5 @@
.tags {
border: solid 1px $tainacan-input-background !important;
border: solid 1px $gray2 !important;
border-radius: 20px;
flex-wrap: nowrap;
margin-bottom: 0.375rem !important;
@ -7,17 +7,27 @@
max-width: 100%;
overflow: hidden;
&:hover{
background-color: $tainacan-input-background;
&:hover, &:hover .tag {
background-color: $gray1;
}
.tag {
background-color: white;
margin-bottom: 0 !important;
margin-right: 4px !important;
max-width: calc(100% - 21px);
justify-content: flex-start;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
&.is-delete {
border-radius: 50px !important;
border-radius: 50px !important;
&:hover {
background-color: white !important;
}
}
}
}

View File

@ -1,6 +1,7 @@
// Input components used in forms are gray in Tainacan
.tainacan-form {
color: $tainacan-input-color;
width: 100%;
.form-submit {
justify-content: space-between !important;
@ -16,6 +17,12 @@
justify-content: end !important;
}
}
.field:not(:last-child) {
margin-bottom: 1.125rem;
}
.field>.field:not(:last-child) {
margin-bottom: 0.5rem;
}
.label {
font-weight: bold;
font-size: 14px;
@ -25,14 +32,14 @@
overflow: hidden;
}
.required-metadatum-asterisk {
color: $gray;
color: $gray3;
&.is-danger {
color: $danger;
}
}
.input, .textarea {
background-color: white;
border: 1px solid $tainacan-input-background;
border: 1px solid $gray2;
color: $tainacan-input-color;
transition: background-color 0.1s;
@ -53,9 +60,11 @@
}
}
.radio, .checkbox {
margin-bottom: 5px;
align-items: baseline;
align-items: center;
margin-bottom: 0;
width: 100%;
&.is-danger {
border-color: $danger;
}
@ -64,15 +73,18 @@
color: $tainacan-input-color;
padding-left: 0.8em;
font-size: 12px;
text-overflow: ellipsis;
overflow-x: hidden;
white-space: nowrap;
}
.select {
select {
color: $tainacan-input-color;
background-color: white !important;
border: 1px solid $tainacan-input-background !important;
border: 1px solid $gray2 !important;
&:focus>option:checked, &:focus>option:hover {
background-color: $primary-lighter !important;
background-color: $turquoise1 !important;
}
}
}
@ -82,7 +94,7 @@
.button {
justify-content: space-between;
width: 100%;
border: 1px solid $tainacan-input-background !important;
border: 1px solid $gray2 !important;
border-radius: 0 !important;
padding: 2px 14px 2px 18px !important
}

View File

@ -9,8 +9,8 @@
}
.tooltip-inner {
background: $primary-lighter;
color: $gray-light;
background: $turquoise1;
color: $gray4;
font-size: 11px;
border-radius: 5px;
padding: 20px;
@ -24,7 +24,7 @@
border-style: solid;
position: absolute;
margin: 5px;
border-color: $primary-lighter;
border-color: $turquoise1;
z-index: 1;
}
&[x-placement^="top"] {

View File

View File

@ -2,38 +2,72 @@
@import "../../../node_modules/bulma/sass/utilities/initial-variables";
@import "../../../node_modules/bulma/sass/utilities/functions";
// Tainacan custom colors
$primary: #2cb4c1;
$primary-invert: findColorInvert($primary);
$secondary: #298596;
$secondary-invert: findColorInvert($secondary);
$tertiary: #01295c;
$tertiary-invert: findColorInvert($tertiary);
$primary-light:#c1dae0;
$primary-lighter: #e6f6f8;
$primary-lighter-hover: #d1e6e6;
$primary-dark: #55A0AF;
$primary-darker: darken($primary-dark, 5%);
$success: #25a189;
$success-invert: findColorInvert($success);
$modal-backgound-color: #bfd8dd;
$separator-color: #2b98a4;
// NEW TAINACAN CUSTOM COLORS ------------------
// Blue, used mainly for repository
$blue1: #e6f4ff;
$blue1-invert: findColorInvert($blue1);
$blue2: #cce3f2;
$blue2-invert: findColorInvert($blue2);
$blue3: #44638e;
$blue3-invert: findColorInvert($blue3);
$blue4: #284472;
$blue4-invert: findColorInvert($blue4);
$blue5: #01295c;
$blue5-invert: findColorInvert($blue5);
// Turquoise, used mainly for collection level
$turquoise1: #e6f6f8;
$turquoise1-invert: findColorInvert($turquoise1);
$turquoise2: #d9eced;
$turquoise2-invert: findColorInvert($turquoise2);
$turquoise3: #76c6cc;
$turquoise3-invert: findColorInvert($turquoise3);
$turquoise4: #4ea2ad;
$turquoise4-invert: findColorInvert($turquoise4);
$turquoise5: #298596;
$turquoise5-invert: findColorInvert($turquoise5);
// Gray, used mostyl for information
$gray1: #f2f2f2;
$gray1-invert: findColorInvert($gray1);
$gray2: #dbdbdb;
$gray2-invert: findColorInvert($gray2);
$gray3: #cbcbcb;
$gray3-invert: findColorInvert($gray3);
$gray4: #898d8f;
$gray4-invert: findColorInvert($gray4);
$gray5: #454647;
$gray5-invert: findColorInvert($gray5);
// Red, used for error messages
$red1: #eadadc;
$red1-invert: findColorInvert($red1);
$red2: #a23939;
$red2-invert: findColorInvert($red2);
// Green, used for success buttons
$green1: #daece6;
$green1-invert: findColorInvert($green1);
$green2: #25a189;
$green2-invert: findColorInvert($green2);
// Warning, used for warning messages
$yellow1: #fcebd9;
$yellow1-invert: findColorInvert($yellow1);
$yellow2: #e69810;
$yellow2-invert: findColorInvert($yellow2);
// Text, no quite black
$tainacan-input-color: #1d1d1d;
$tainacan-input-background: #e5e5e5;
$tainacan-placeholder-color: #898d8f;
$draggable-border-color: #d8d8d8;
$gray-hover: #dcdcdc;
$gray: #b1b1b1;
$gray-invert: findColorInvert($gray);
$gray-light: #898d8f;
$gray-light-invert: findColorInvert($gray-light);
$danger: #a23939;
// Maps some of bulma's colors to custom variables
$primary: $turquoise3;
$primary-invert: findColorInvert($turquoise3);
$secondary: $turquoise5;
$secondary-invert: findColorInvert($turquoise5);
$success: $green2;
$success-invert: findColorInvert($success);
$danger: $red2;
$danger-invert: findColorInvert($danger);
$warning: $yellow2;
$warning-invert: findColorInvert($warning);
$gray: $gray4;
$gray-invert: findColorInvert($gray4);
@import "../../../node_modules/bulma/sass/utilities/derived-variables.sass";
@ -43,17 +77,36 @@ $colors: (
"black": ($black, $white),
"light": ($light, $light-invert),
"dark": ($dark, $dark-invert),
"primary": ($primary, $primary-invert),
"secondary": ($secondary, $secondary-invert),
"primary": ($turquoise3, $turquoise3-invert),
"secondary": ($turquoise5, $turquoise5-invert),
"info": ($info, $info-invert),
"success": ($success, $success-invert),
"warning": ($warning, $warning-invert),
"danger": ($danger, $danger-invert)
);
$addColors: (
"gray": ($gray, $gray-invert),
"gray-light": ($gray-light, $gray-light-invert),
"tertiary": ($tertiary, $tertiary-invert),
"gray": ($gray4, $gray-invert),
"blue1": ($blue1, $blue1-invert),
"blue2": ($blue2, $blue2-invert),
"blue3": ($blue3, $blue3-invert),
"blue4": ($blue4, $blue4-invert),
"blue5": ($blue5, $blue5-invert),
"turquoise1": ($turquoise1, $turquoise1-invert),
"turquoise2": ($turquoise2, $turquoise2-invert),
"turquoise3": ($turquoise3, $turquoise3-invert),
"turquoise4": ($turquoise4, $turquoise4-invert),
"turquoise5": ($turquoise5, $turquoise5-invert),
"gray1": ($gray1, $gray1-invert),
"gray2": ($gray2, $gray2-invert),
"gray3": ($gray3, $gray3-invert),
"gray4": ($gray4, $gray4-invert),
"gray5": ($gray5, $gray5-invert),
"red1": ($red1, $red1-invert),
"red2": ($red2, $red2-invert),
"green1": ($green1, $green1-invert),
"green2": ($green2, $green2-invert),
"yellow1": ($yellow1, $yellow1-invert),
"yellow2": ($yellow2, $yellow2-invert)
);
$colors: map-merge($colors, $addColors);
@ -61,12 +114,12 @@ $colors: map-merge($colors, $addColors);
$size-small: 0.85em; // 0.75em on Bulma.
// Tainacan Header and side menus
$header-height: 53px;
$subheader-height: 82px;
$side-menu-width: 180px;
$header-height: 52px;
$subheader-height: 42px;
$side-menu-width: 160px;
$filter-menu-width: 16.666666667%;
$filter-menu-width-theme: 20.833333333%;
$page-height: calc(100% - 53px);
$page-height: calc(100% - 94px);
// Overall Pages padding:
$page-side-padding: 4.166666667%;//82px;
@ -84,13 +137,13 @@ $link-invert: $secondary;
$link-focus-border: $secondary;
// Placeholder
$text-light: $tainacan-placeholder-color;
$text-light: $gray4;
// Table
$table-head-cell-color: $gray-light;
$table-head-cell-color: $gray4;
$table-head-cell-border-width: 0 0 1px !important;
$table-row-active-color: #e5e5e5;
$table-foot-cell-color: $gray-light;
$table-foot-cell-color: $gray4;
$table-foot-cell-border-width: 1px 0 0 !important;
$table-cell-padding: 1.0em 0.75em;
@ -98,4 +151,91 @@ $table-cell-padding: 1.0em 0.75em;
$family-sans-serif: 'Roboto', sans-serif;
// Bulma's modal (needs to be greather than taincan-admin-app)
$modal-z: 9999999;
$modal-z: 9999999;
// Animations for Slide Menu
@keyframes slide-menu-in {
from {
-ms-transform: translate(-100%, 0); /* IE 9 */
-webkit-transform: translate(-100%, 0); /* Safari */
transform: translate(-100%, 0);
}
to {
-ms-transform: translate(0, 0); /* IE 9 */
-webkit-transform: translate(0, 0); /* Safari */
transform: translate(0, 0);
}
}
@keyframes slide-menu-out {
from {
-ms-transform: translate(0, 0); /* IE 9 */
-webkit-transform: translate(0, 0); /* Safari */
transform: translate(0, 0);
}
to {
-ms-transform: translate(-100%, 0); /* IE 9 */
-webkit-transform: translate(-100%, 0); /* Safari */
transform: translate(-100%, 0);
}
}
@keyframes appear {
from {
opacity: 0.0;
visibility: hidden;
}
to {
opacity: 1.0;
visibility: visible;
}
}
@keyframes disappear {
from {
opacity: 0.3;
visibility: visible;
}
to {
opacity: 0.0;
visibility: hidden;
}
}
.slide-menu-enter-active {
animation-name: slide-menu-in;
animation-duration: 0.3s;
animation-timing-function: ease-out;
.modal-background {
animation-name: appear;
animation-duration: 0.6s;
animation-timing-function: ease-out;
}
}
.slide-menu-leave-active {
animation-name: slide-menu-out;
animation-duration: 0.3s;
animation-timing-function: ease-in;
.modal-background {
opacity: 0.0;
animation-name: disappear;
animation-duration: 0.2s;
animation-timing-function: ease-in;
}
}
// Animations for Item Appear in Items List
@keyframes item-appear {
from {
opacity: 0;
visibility: hidden;
transform: translate(0, 12px);
}
to {
opacity: 1;
visibility: visible;
transform: translate(0, 0px);
}
}

View File

@ -1,16 +1,18 @@
.tainacan-cards-container {
min-height: 200px;
min-height: 50vh;
padding: 0;
display: flex;
flex-wrap: wrap;
flex-grow: 1;
flex-shrink: 1;
justify-content: center;
justify-content: space-evenly;
animation-name: item-appear;
animation-duration: 0.5s;
.selected-card {
background-color: $primary-lighter;
background-color: $turquoise1;
.metadata-title {
background-color: $primary-lighter-hover;
background-color: $turquoise2;
}
}
@ -21,10 +23,16 @@
max-width: 410px;
min-width: 410px;
min-height: 218px;
max-height: 218px;
cursor: pointer;
@media screen and (max-width: 768px) {
max-width: 100%;
min-width: 100%;
}
&:hover {
background-color: $tainacan-input-background !important;
background-color: #f2f2f2 !important;
}
.card-checkbox {
@ -51,7 +59,7 @@
.card-line {
height: 1px;
background-color: $tainacan-input-background;
background-color: $gray2;
margin-left: -44px;
margin-right: -44px;
opacity: 0;
@ -59,7 +67,7 @@
}
img {
width: 172px;
height: auto;
height: 172px;
border-radius: 2px;
}
&:hover img {
@ -79,10 +87,11 @@
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
margin-bottom: 0;
}
}
&:hover .metadata-title {
background-color: $gray-hover !important;
background-color: $gray2 !important;
}
.media {
@ -91,16 +100,19 @@
.list-metadata {
padding: 0.75rem 1.375rem;
flex: 1;
font-size: 0.6875rem;
color: gray;
overflow: hidden;
width: 100%;
height: 172px;
color: $gray4;
.metadata-description {
p.metadata-description {
font-size: 0.6875rem !important;
overflow: hidden;
margin-bottom: 1.5rem;
max-height: 152px;
}
.metadata-author-creation {
font-size: 0.6875rem !important;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;

View File

@ -1,14 +1,16 @@
.tainacan-grid-container {
min-height: 200px;
min-height: 50vh;
padding: 0;
display: flex;
flex-wrap: wrap;
flex-grow: 1;
flex-shrink: 1;
justify-content: center;
justify-content: space-evenly;
animation-name: item-appear;
animation-duration: 0.5s;
.selected-grid-item {
background-color: $primary-lighter;
background-color: $turquoise1;
}
.tainacan-grid-item {
@ -18,7 +20,7 @@
text-align: center;
&:hover {
background-color: $tainacan-input-background;
background-color: $gray2;
}
.grid-item-checkbox {
@ -37,7 +39,7 @@
padding: 8px;
transition: visibility 0.2s, opacity 0.2s;
margin-top: -43px;
background-color: $tainacan-input-background;
background-color: $gray2;
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
@ -51,7 +53,7 @@
}
&.selected-grid-item {
.actions-area {
background-color: $primary-lighter;
background-color: $turquoise1;
}
}

View File

@ -0,0 +1,92 @@
.tainacan-masonry-container {
min-height: 50vh;
padding: 0;
display: flex;
flex-wrap: wrap;
flex-grow: 1;
flex-shrink: 1;
justify-content: space-evenly;
animation-name: item-appear;
animation-duration: 0.5s;
.selected-masonry-item {
background-color: $turquoise1;
}
.tainacan-masonry-item {
display: block;
width: 100%;
flex-basis: 0;
margin-bottom: 30px;
text-align: center;
text-decoration: none;
&:hover {
background-color: $gray2;
}
.masonry-item-checkbox {
position: absolute;
margin-top: 8px;
margin-left: 1rem;
}
.actions-area {
position: relative;
float: right;
width: 100%;
display: flex;
justify-content: flex-end;
visibility: hidden;
opacity: 0;
padding: 8px;
transition: visibility 0.2s, opacity 0.2s;
margin-top: -43px;
background-color: $gray2;
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
a {
margin-left: 12px;
}
}
&:hover .actions-area {
visibility: visible;
opacity: 1.0;
}
&.selected-grid-item {
.actions-area {
background-color: $turquoise1;
}
}
img {
width: 100%;
height: auto;
border-radius: 2px;
margin-bottom: -5px;
&:hover {
cursor: pointer;
}
}
.metadata-title {
flex-shrink: 0;
margin: 0px 6px 0px 24px;
padding: 10px 1rem;
min-height: 41px;
cursor: pointer;
p {
font-size: 0.875rem !important;
color: black !important;
text-align: left !important;
margin-bottom: 0 !important;
word-break: break-word;
}
}
}
}

View File

@ -1,16 +1,18 @@
.tainacan-records-container {
min-height: 200px;
min-height: 50vh;
padding: 0;
display: flex;
flex-wrap: wrap;
flex-grow: 1;
flex-shrink: 1;
justify-content: center;
justify-content: space-evenly;
animation-name: item-appear;
animation-duration: 0.5s;
.selected-record {
background-color: $primary-lighter;
background-color: $turquoise1;
.metadata-title {
background-color: $primary-lighter-hover;
background-color: $turquoise2;
}
}
@ -23,8 +25,13 @@
min-height: 218px;
cursor: pointer;
@media screen and (max-width: 768px) {
max-width: 100%;
min-width: 100%;
}
&:hover {
background-color: $tainacan-input-background !important;
background-color: #f2f2f2 !important;
}
.record-checkbox {
@ -51,7 +58,7 @@
.record-line {
height: 1px;
background-color: $tainacan-input-background;
background-color: $gray2;
margin-left: -44px;
margin-right: -44px;
opacity: 0;
@ -82,7 +89,7 @@
}
}
&:hover .metadata-title {
background-color: $gray-hover !important;
background-color: $gray2 !important;
}
.media {
@ -92,7 +99,7 @@
padding: 0.75rem 1.375rem;
flex: 1;
font-size: 0.6875rem;
color: gray;
color: $gray4;
overflow: hidden;
width: 100%;
@ -103,7 +110,7 @@
white-space: nowrap;
overflow: hidden;
font-weight: 500;
color: $gray-light;
color: $gray4;
}
.metadata-value {

View File

@ -22,6 +22,7 @@
@import "../scss/_modals.scss";
@import "../scss/_tags.scss";
@import "../scss/_notices.scss";
@import "../scss/_filters-menu-modal.scss";
// Clears wordpress content
body.tainacan-admin-page #adminmenumain, body.tainacan-admin-page #wpfooter, body.tainacan-admin-page #wp-auth-check-wrap {
@ -56,21 +57,98 @@ a:hover {
&.disabled {
pointer-events: none;
cursor: default;
color: $tainacan-input-background;
color: $gray2 !important;
.icon {
color: $tainacan-input-background !important;
color: $gray2 !important;
}
}
}
// Page settings
.primary-page {
margin-top: $header-height;
// Repository-level pages
.repository-level-page {
margin-top: 94px;
height: $page-height !important;
@media screen and (max-width: 769px) {
margin-top: 0;
margin-top: 42px;
}
.is-primary:not(.upload-draggable), .is-primary:hover, .is-primary:focus {
background-color: $blue4 !important;
color: white !important;
}
.is-secondary, .is-secondary:hover, .is-secondary:focus {
background-color: $blue5 !important;
color: white !important;
}
.has-text-primary, .has-text-primary:hover, .is-has-text-primary:focus {
color: $blue4 !important;
}
a, a:hover,
.has-text-secondary, .has-text-secondary:hover, .is-has-text-secondary:focus {
color: $blue5 !important;
}
.tainacan-page-title {
h1 {
color: $blue5 !important;
}
}
.button[disabled]:not(.is-white), .button:hover[disabled]:not(.is-white) {
border: none !important;
cursor: not-allowed !important;
color: $gray4 !important;
background-color: $gray2 !important;
}
.button.is-outlined {
color: $blue5 !important;
}
.tabs {
li.is-active a {
border-bottom: 5px solid $blue5;
color: $blue5;
}
}
.select:not(.is-multiple)::after {
color: $blue5;
option:checked, option:hover {
background-color: $gray1 !important;
}
}
.tainacan-table {
tr.selected-row {
background-color: $blue1 !important;
.checkbox-cell .checkbox, .actions-cell .actions-container {
background-color: $blue2 !important;
}
}
}
.dropdown-trigger {
.button .icon {
color: $blue5;
}
}
.dropdown-menu .dropdown-content {
.dropdown-item.is-active { background-color: $blue2; }
}
.switch {
&:hover input[type="checkbox"]:checked + .check {
background-color: $blue2;
}
input[type="checkbox"]:checked + .check {
border: 2px solid $blue5;
&::before {
background-color: $blue5;
}
}
&.is-small {
input[type="checkbox"]:checked + .check {
border: 1.5px solid $blue5;
}
}
}
}
// Generic page container
@ -82,14 +160,10 @@ a:hover {
}
// Used for pages with collection subheader
.page-container-small {
height: calc(100% - 82px);
height: calc(100% - 42px);
overflow-y: auto;
transition: height 0.6s;
}
// Used for pages with shrinked collection subheader
.page-container-shrinked {
height: calc(100% - 53px) !important;
}
// Used for pages with subheader in mobile
.page-container-narrow{
padding: $page-small-top-padding $page-small-side-padding;
@ -102,4 +176,8 @@ a:hover {
// Buefy notices (toast, snackbar...)
.notices {
z-index: 99999999999999 !important;
}
}
audio, video {
width: 100%;
}

View File

@ -7,3 +7,4 @@
@import "../../../node_modules/bulma/sass/components/tabs.sass"
@import "../../../node_modules/bulma/sass/elements/button.sass"
@import "../../../node_modules/bulma/sass/grid/columns.sass"
@import "../../../node_modules/bulma/sass/components/modal.sass"

View File

@ -3,400 +3,434 @@
return apply_filters( 'tainacan-admin-i18n', [
// Advanced search comparators
'is_equal_to' => __( 'Equal', 'tainacan' ),
'is_not_equal_to' => __( 'Not equal', 'tainacan' ),
'contains' => __( 'Contains', 'tainacan' ),
'not_contains' => __( 'Not contains', 'tainacan' ),
'greater_than' => __( 'Greater than', 'tainacan' ),
'less_than' => __( 'Less than', 'tainacan' ),
'greater_than_or_equal_to' => __( 'Greater than or equal to', 'tainacan' ),
'less_than_or_equal_to' => __( 'Less than or equal to', 'tainacan' ),
'is_equal_to' => __( 'Equal', 'tainacan' ),
'is_not_equal_to' => __( 'Not equal', 'tainacan' ),
'contains' => __( 'Contains', 'tainacan' ),
'not_contains' => __( 'Not contains', 'tainacan' ),
'greater_than' => __( 'Greater than', 'tainacan' ),
'less_than' => __( 'Less than', 'tainacan' ),
'greater_than_or_equal_to' => __( 'Greater than or equal to', 'tainacan' ),
'less_than_or_equal_to' => __( 'Less than or equal to', 'tainacan' ),
// Tainacan common terms
'repository' => __( 'Repository', 'tainacan' ),
'collections' => __( 'Collections', 'tainacan' ),
'items' => __( 'Items', 'tainacan' ),
'metadata' => __( 'Metadata', 'tainacan' ),
'filters' => __( 'Filters', 'tainacan' ),
'taxonomies' => __( 'Taxonomies', 'tainacan' ),
'events' => __( 'Events', 'tainacan' ),
'collection' => __( 'Collection', 'tainacan' ),
'item' => __( 'Item', 'tainacan' ),
'metadatum' => __( 'Metadata', 'tainacan' ),
'filter' => __( 'Filter', 'tainacan' ),
'taxonomy' => __( 'Taxonomy', 'tainacan' ),
'event' => __( 'Event', 'tainacan' ),
'term' => __( 'Term', 'tainacan' ),
'terms' => __( 'Terms', 'tainacan' ),
'mapping' => __( 'Mapping', 'tainacan' ),
'importers' => __( 'Importers', 'tainacan' ),
'repository' => __( 'Repository', 'tainacan' ),
'collections' => __( 'Collections', 'tainacan' ),
'items' => __( 'Items', 'tainacan' ),
'metadata' => __( 'Metadata', 'tainacan' ),
'filters' => __( 'Filters', 'tainacan' ),
'taxonomies' => __( 'Taxonomies', 'tainacan' ),
'events' => __( 'Events', 'tainacan' ),
'collection' => __( 'Collection', 'tainacan' ),
'item' => __( 'Item', 'tainacan' ),
'metadatum' => __( 'Metadata', 'tainacan' ),
'filter' => __( 'Filter', 'tainacan' ),
'taxonomy' => __( 'Taxonomy', 'tainacan' ),
'event' => __( 'Event', 'tainacan' ),
'term' => __( 'Term', 'tainacan' ),
'terms' => __( 'Terms', 'tainacan' ),
'mapping' => __( 'Mapping', 'tainacan' ),
'importers' => __( 'Importers', 'tainacan' ),
'processes' => __( 'Processes', 'tainacan' ),
// Actions
'edit' => __( 'Edit', 'tainacan' ),
'settings' => __( 'Settings', 'tainacan' ),
'new' => __( 'New', 'tainacan' ),
'add' => __( 'Add', 'tainacan' ),
'import' => __( 'Import', 'tainacan' ),
'export' => __( 'Export', 'tainacan' ),
'cancel' => __( 'Cancel', 'tainacan' ),
'remove' => __( 'Remove', 'tainacan' ),
'save' => __( 'Save', 'tainacan' ),
'next' => __( 'Next', 'tainacan' ),
'back' => __( 'Back', 'tainacan' ),
'see' => __( 'View', 'tainacan' ),
'search' => __( 'Search', 'tainacan' ),
'advanced_search' => __( 'Advanced Search', 'tainacan' ),
'continue' => __( 'Continue', 'tainacan' ),
'approve_item' => __( 'Approve', 'tainacan' ),
'not_approve_item' => __( 'Not approve', 'tainacan' ),
'add_one_item' => __( 'Add one item', 'tainacan' ),
'add_items_bulk' => __( 'Add items in bulk', 'tainacan' ),
'add_items_external_source' => __( 'Add items from an external source', 'tainacan' ),
'new_mapped_item' => __( 'New mapped collection', 'tainacan' ),
'new_blank_collection' => __( 'New Blank Collection', 'tainacan' ),
'split' => __( 'Split', 'tainacan' ),
'unified' => __( 'Unified', 'tainacan' ),
'add_another_search_criterion' => __( 'Add another search criterion', 'tainacan' ),
'clear_search' => __( 'Clear search', 'tainacan' ),
'run' => __( 'Run', 'tainacan' ),
'edit_search' => __( 'Edit search', 'tainacan' ),
'exit' => __( 'Exit', 'tainacan' ),
'edit' => __( 'Edit', 'tainacan' ),
'settings' => __( 'Settings', 'tainacan' ),
'new' => __( 'New', 'tainacan' ),
'add' => __( 'Add', 'tainacan' ),
'import' => __( 'Import', 'tainacan' ),
'export' => __( 'Export', 'tainacan' ),
'cancel' => __( 'Cancel', 'tainacan' ),
'remove' => __( 'Remove', 'tainacan' ),
'save' => __( 'Save', 'tainacan' ),
'next' => __( 'Next', 'tainacan' ),
'back' => __( 'Back', 'tainacan' ),
'exit' => __( 'Exit', 'tainacan' ),
'see' => __( 'View', 'tainacan' ),
'search' => __( 'Search', 'tainacan' ),
'advanced_search' => __( 'Advanced Search', 'tainacan' ),
'continue' => __( 'Continue', 'tainacan' ),
'approve_item' => __( 'Approve', 'tainacan' ),
'not_approve_item' => __( 'Not approve', 'tainacan' ),
'add_one_item' => __( 'Add one item', 'tainacan' ),
'add_items_bulk' => __( 'Add items in bulk', 'tainacan' ),
'add_items_external_source' => __( 'Add items from an external source', 'tainacan' ),
'new_mapped_item' => __( 'New mapped collection', 'tainacan' ),
'new_blank_collection' => __( 'New Blank Collection', 'tainacan' ),
'split' => __( 'Split', 'tainacan' ),
'unified' => __( 'Unified', 'tainacan' ),
'add_another_search_criterion' => __( 'Add another search criterion', 'tainacan' ),
'add_one_search_criterion' => __( 'Add one search criterion', 'tainacan' ),
'clear_search' => __( 'Clear search', 'tainacan' ),
'run' => __( 'Run', 'tainacan' ),
'edit_search' => __( 'Edit search', 'tainacan' ),
'apply' => __( 'Apply', 'tainacan' ),
// Wordpress Status
'publish' => __( 'Publish', 'tainacan' ),
'draft' => __( 'Draft', 'tainacan' ),
'private' => __( 'Private', 'tainacan' ),
'trash' => __( 'Trash', 'tainacan' ),
'auto-draft' => __( 'Automatic Draft', 'tainacan' ),
'publish_visibility' => __( 'Visible to everyone', 'tainacan' ),
'private_visibility' => __( 'Visible only for editors', 'tainacan' ),
'publish' => __( 'Publish', 'tainacan' ),
'draft' => __( 'Draft', 'tainacan' ),
'private' => __( 'Private', 'tainacan' ),
'trash' => __( 'Trash', 'tainacan' ),
'auto-draft' => __( 'Automatic Draft', 'tainacan' ),
'publish_visibility' => __( 'Visible to everyone', 'tainacan' ),
'private_visibility' => __( 'Visible only for editors', 'tainacan' ),
// Page Titles (used mainly on Router)
'title_repository_collections_page' => __( 'Repository Collections', 'tainacan' ),
'title_items_page' => __( 'Items', 'tainacan' ),
'title_repository_metadata_page' => __( 'Repository Metadata', 'tainacan' ),
'title_repository_filters_page' => __( 'Repository Filters', 'tainacan' ),
'title_taxonomies_page' => __( 'Taxonomies Page', 'tainacan' ),
'title_terms_page' => __( 'Terms', 'tainacan' ),
'title_repository_events_page' => __( 'Repository Events', 'tainacan' ),
'title_collection_page' => __( 'Collection', 'tainacan' ),
'title_item_page' => __( 'Item', 'tainacan' ),
'title_metadatum_page' => __( 'Metadata', 'tainacan' ),
'title_collection_events' => __( 'Collection Events', 'tainacan' ),
'title_filter_page' => __( 'Filter', 'tainacan' ),
'title_taxonomy_page' => __( 'Taxonomy', 'tainacan' ),
'title_term_edition' => __( 'Term edition', 'tainacan' ),
'title_event_page' => __( 'Event', 'tainacan' ),
'title_create_collection' => __( 'Collection Creation', 'tainacan' ),
'title_create_taxonomy_page' => __( 'Taxonomy Creation', 'tainacan' ),
'title_create_item_collection' => __( 'Create Item on Collection', 'tainacan' ),
'title_create_filter' => __( 'Filter Creation', 'tainacan' ),
'title_collection_settings' => __( 'Settings of Collection', 'tainacan' ),
'title_edit_item' => __( 'Edit Item', 'tainacan' ),
'title_taxonomy_edition_page' => __( 'Taxonomy Edition', 'tainacan' ),
'title_filter_edition' => __( 'Filter Edition', 'tainacan' ),
'title_metadatum_edition' => __( 'Metadata Edition', 'tainacan' ),
'title_collection_metadata_edition' => __( 'Edit Metadata of', 'tainacan' ),
'title_collection_filters_edition' => __( 'Edit Filters of', 'tainacan' ),
'title_importer_page' => __( 'Importer', 'tainacan' ),
'title_importers_page' => __( 'Importers', 'tainacan' ),
'title_export_collection_page' => __( 'Export Collection Page', 'tainacan' ),
'title_export_item_page' => __( 'Export Item Page', 'tainacan' ),
'title_export_page' => __( 'Export Page', 'tainacan' ),
'title_repository_collections_page' => __( 'Repository Collections', 'tainacan' ),
'title_items_page' => __( 'Items', 'tainacan' ),
'title_repository_metadata_page' => __( 'Repository Metadata', 'tainacan' ),
'title_repository_filters_page' => __( 'Repository Filters', 'tainacan' ),
'title_taxonomies_page' => __( 'Taxonomies', 'tainacan' ),
'title_terms_page' => __( 'Terms', 'tainacan' ),
'title_repository_events_page' => __( 'Repository Events', 'tainacan' ),
'title_collection_page' => __( 'Collection', 'tainacan' ),
'title_item_page' => __( 'Item', 'tainacan' ),
'title_metadatum_page' => __( 'Metadata', 'tainacan' ),
'title_collection_events' => __( 'Collection Events', 'tainacan' ),
'title_filter_page' => __( 'Filter', 'tainacan' ),
'title_taxonomy_page' => __( 'Taxonomy', 'tainacan' ),
'title_term_edition' => __( 'Term edition', 'tainacan' ),
'title_event_page' => __( 'Event', 'tainacan' ),
'title_create_collection' => __( 'Collection Creation', 'tainacan' ),
'title_create_taxonomy_page' => __( 'Taxonomy Creation', 'tainacan' ),
'title_create_item_collection' => __( 'Create Item on Collection', 'tainacan' ),
'title_create_filter' => __( 'Filter Creation', 'tainacan' ),
'title_collection_settings' => __( 'Settings of Collection', 'tainacan' ),
'title_edit_item' => __( 'Edit Item', 'tainacan' ),
'title_taxonomy_edition_page' => __( 'Taxonomy Edition', 'tainacan' ),
'title_filter_edition' => __( 'Filter Edition', 'tainacan' ),
'title_metadatum_edition' => __( 'Metadata Edition', 'tainacan' ),
'title_collection_metadata_edition' => __( 'Edit Metadata of', 'tainacan' ),
'title_collection_filters_edition' => __( 'Edit Filters of', 'tainacan' ),
'title_importer_page' => __( 'Importer', 'tainacan' ),
'title_importer_mapping_page' => __( "Metadata Mapping", 'tainacan' ),
'title_importers_page' => __( 'Importers', 'tainacan' ),
'title_export_collection_page' => __( 'Export Collection Page', 'tainacan' ),
'title_export_item_page' => __( 'Export Item', 'tainacan' ),
'title_export_page' => __( 'Export', 'tainacan' ),
'title_processes_page' => __( 'Processes', 'tainacan' ),
// Labels (used mainly on Aria Labels and Inputs)
'label_clean' => __( 'Clear', 'tainacan' ),
'label_clear_filters' => __( 'Clear filters', 'tainacan' ),
'label_selected' => __( 'Selected', 'tainacan' ),
'label_relationship_new_search' => __( 'New Search', 'tainacan' ),
'label_relationship_items_found' => __( 'Items found', 'tainacan' ),
'label_menu' => __( 'Menu', 'tainacan' ),
'label_main_menu' => __( 'Main Menu', 'tainacan' ),
'label_collection_menu' => __( 'Collection Menu', 'tainacan' ),
'label_title' => __( 'Title', 'tainacan' ),
'label_settings' => __( 'Settings', 'tainacan' ),
'label_actions' => __( 'Actions', 'tainacan' ),
'label_name' => __( 'Name', 'tainacan' ),
'label_description' => __( 'Description', 'tainacan' ),
'label_status' => __( 'Status', 'tainacan' ),
'label_slug' => __( 'Slug', 'tainacan' ),
'label_image' => __( 'Image', 'tainacan' ),
'label_thumbnail' => __( 'Thumbnail', 'tainacan' ),
'label_empty_thumbnail' => __( 'Empty Thumbnail', 'tainacan' ),
'label_moderators' => __( 'Moderators', 'tainacan' ),
'label_parent_collection' => __( 'Parent collection', 'tainacan' ),
'label_no_parent_collection' => __( 'No parent collection', 'tainacan' ),
'label_button_view' => __( 'Button View', 'tainacan' ),
'label_button_edit' => __( 'Button Edit', 'tainacan' ),
'label_button_delete' => __( 'Button Delete', 'tainacan' ),
'label_button_delete_header_image' => __( 'Button Delete Header Image', 'tainacan' ),
'label_button_edit_thumb' => __( 'Button Edit Thumbnail', 'tainacan' ),
'label_button_edit_header_image' => __( 'Button Edit Header Image', 'tainacan' ),
'label_button_edit_document' => __( 'Button Edit Document', 'tainacan' ),
'label_button_delete_document' => __( 'Button Delete Document', 'tainacan' ),
'label_choose_thumb' => __( 'Choose Thumbnail', 'tainacan' ),
'label_button_delete_thumb' => __( 'Button Delete Thumbnail', 'tainacan' ),
'label_collections_per_page' => __( 'Collections per Page:', 'tainacan' ),
'label_taxonomies_per_page' => __( 'Taxonomies per Page:', 'tainacan' ),
'label_events_per_page' => __( 'Events per Page:', 'tainacan' ),
'label_items_per_page' => __( 'Items per Page:', 'tainacan' ),
'label_active_metadata' => __( 'Active Metadata', 'tainacan' ),
'label_available_metadata' => __( 'Available Metadata', 'tainacan' ),
'label_available_metadata_types' => __( 'Available Metadata Types', 'tainacan' ),
'label_active_filters' => __( 'Active Filters', 'tainacan' ),
'label_filter_type' => __( 'Filter Type', 'tainacan' ),
'label_available_filters' => __( 'Available Filters', 'tainacan' ),
'label_available_filter_types' => __( 'Available Filter Types', 'tainacan' ),
'label_per_page' => __( 'per Page', 'tainacan' ),
'label_displayed_metadata' => __( 'Displayed metadata', 'tainacan' ),
'label_required' => __( 'Required', 'tainacan' ),
'label_allow_multiple' => __( 'Allow multiple values', 'tainacan' ),
'label_default_value' => __( 'Default value', 'tainacan' ),
'label_unique_value' => __( 'Unique value', 'tainacan' ),
'label_yes' => __( 'Yes', 'tainacan' ),
'label_no' => __( 'No', 'tainacan' ),
'label_approved' => __( 'Approved', 'tainacan' ),
'label_collection_related' => __( 'Collection Related', 'tainacan' ),
'label_metadata_for_search' => __( 'Metadata for search', 'tainacan' ),
'label_allow_repeated_items' => __( 'Allow repeated items', 'tainacan' ),
'label_select_taxonomy' => __( 'Select taxonomy', 'tainacan' ),
'label_select_taxonomy_input_type' => __( 'Input type', 'tainacan' ),
'label_taxonomy_allow_new_terms' => __( 'Allow new terms', 'tainacan' ),
'label_selectbox_init' => __( 'Select', 'tainacan' ),
'label_options' => __( 'Insert options', 'tainacan' ),
'label_attachments' => __( 'Attachments', 'tainacan' ),
'label_attachment' => __( 'Attachment', 'tainacan' ),
'label_enabled' => __( 'Enabled', 'tainacan' ),
'label_disabled' => __( 'Disabled', 'tainacan' ),
'label_creation' => __( 'Creation', 'tainacan' ),
'label_creation_date' => __( 'Creation date', 'tainacan' ),
'label_collection_items' => __( 'Collection Items', 'tainacan' ),
'label_collection_metadata' => __( 'Collection Metadata', 'tainacan' ),
'label_collection_filters' => __( 'Collection Filters', 'tainacan' ),
'label_parent_term' => __( 'Parent Term', 'tainacan' ),
'label_new_term' => __( 'New Term', 'tainacan' ),
'label_new_child' => __( 'New Child', 'tainacan' ),
'label_taxonomy_terms' => __( 'Taxonomy Terms', 'tainacan' ),
'label_no_parent_term' => __( 'No parent term', 'tainacan' ),
'label_term_without_name' => __( 'Term without name', 'tainacan' ),
'label_inherited' => __( 'Inherited', 'tainacan' ),
'label_sorting' => __( 'Sorting', 'tainacan' ),
'label_event_date' => __( 'Event date', 'tainacan' ),
'label_event_title' => __( 'Event', 'tainacan' ),
'label_header_image' => __( 'Header Image', 'tainacan' ),
'label_empty_header_image' => __( 'Empty Header Image', 'tainacan' ),
'label_enable_cover_page' => __( 'Enable Cover Page', 'tainacan' ),
'label_cover_page' => __( 'Cover Page', 'tainacan' ),
'label_default_displayed_metadata' => __( 'Default Displayed Metadata', 'tainacan' ),
'label_display' => __( 'Display on Listing', 'tainacan' ),
'label_display_default' => __( 'Display by default', 'tainacan' ),
'label_display_never' => __( 'Never displayed', 'tainacan' ),
'label_not_display' => __( 'Not display by default', 'tainacan' ),
'label_attach_to_item' => __( 'Attach to item', 'tainacan' ),
'label_document' => __( 'Document', 'tainacan' ),
'label_document_empty' => __( 'Empty document', 'tainacan' ),
'label_file' => __( 'File', 'tainacan' ),
'label_text' => __( 'Text', 'tainacan' ),
'label_url' => __( 'URL', 'tainacan' ),
'label_select_file' => __( 'Select File', 'tainacan' ),
'label_expand_all' => __( 'Expand all', 'tainacan' ),
'label_collapse_all' => __( 'Collapse all', 'tainacan' ),
'label_view_term' => __( 'View Term', 'tainacan' ),
'label_all_items' => __( 'All items', 'tainacan' ),
'label_draft_items' => __( 'Draft', 'tainacan' ),
'label_trash_items' => __( 'Trash', 'tainacan' ),
'label_bulk_actions' => __( 'Bulk actions', 'tainacan' ),
'label_delete_selected_collections' => __( 'Delete selected collections', 'tainacan' ),
'label_edit_selected_collections' => __( 'Edit selected collections', 'tainacan' ),
'label_delete_permanently' => __( 'Delete permanently', 'tainacan' ),
'label_send_to_trash' => __( 'Send to trash', 'tainacan' ),
'label_delete_selected_taxonomies' => __( 'Delete selected taxonomies', 'tainacan' ),
'label_edit_selected_items' => __( 'Edit selected items', 'tainacan' ),
'label_edit_selected_taxonomies' => __( 'Edit selected taxonomies', 'tainacan' ),
'label_select_all_collections_page' => __( 'Select all collections on page', 'tainacan' ),
'label_select_all_items_page' => __( 'Select all items on page', 'tainacan' ),
'label_select_all_taxonomies_page' => __( 'Select all taxonomies on page', 'tainacan' ),
'label_edit_attachments' => __( 'Edit attachments', 'tainacan' ),
'label_blank_collection' => __( 'Blank collection', 'tainacan' ),
'label_dublin_core' => __( 'Dublin Core', 'tainacan' ),
'label_created_by' => __( 'Created by', 'tainacan' ),
'label_apply_changes' => __( 'Apply changes', 'tainacan' ),
'label_view_mode' => __( 'View mode', 'tainacan' ),
'label_default_view_mode' => __( 'Default view mode', 'tainacan' ),
'label_enabled_view_modes' => __( 'Enabled view modes', 'tainacan' ),
'label_view_modes_available' => __( 'View modes available on theme', 'tainacan' ),
'label_warning' => __( 'Warning', 'tainacan' ),
'label_error' => __( 'Erro', 'tainacan' ),
'label_grid' => __( 'Grid', 'tainacan' ),
'label_table' => __( 'Table', 'tainacan' ),
'label_cards' => __( 'Cards', 'tainacan' ),
'label_records' => __( 'Records', 'tainacan' ),
'label_visualization' => __( 'Visualization', 'tainacan' ),
'label_available_importers' => __( 'Available Importers', 'tainacan' ),
'label_target_collection' => __( 'Target Collection', 'tainacan' ),
'label_source_file' => __( 'Source file', 'tainacan' ),
'label_url_source_link' => __( 'URL Source link', 'tainacan' ),
'label_metadata_mapping' => __( 'Metadata mapping', 'tainacan' ),
'label_select_metadatum' => __( 'Select metadatum', 'tainacan' ),
'label_select_metadatum_type' => __( 'Select a metadatum type', 'tainacan' ),
'label_add_more_metadata' => __( 'Add more metadata', 'tainacan' ),
'label_from_source_collection' => __( 'From source collection', 'tainacan' ),
'label_to_target_collection' => __( 'To target collection', 'tainacan' ),
'label_add_value' => __( 'Add value', 'tainacan' ),
'label_remove_value' => __( 'Remove value', 'tainacan' ),
'label_create_new_page' => __( 'Create new page', 'tainacan' ),
'label_total_items' => __( 'Total items', 'tainacan' ),
'label_see_more' => __( 'See more', 'tainacan' ),
'label_until' => __( 'until', 'tainacan' ),
'label_visibility' => __( 'Visibility', 'tainacan' ),
'label_discart' => __( 'Discart', 'tainacan' ),
'label_save_as_draft' => __( 'Save as draft', 'tainacan' ),
'label_update_draft' => __( 'Update draft', 'tainacan' ),
'label_return_to_draft' => __( 'Return to draft', 'tainacan' ),
'label_publish' => __( 'Publish', 'tainacan' ),
'label_update' => __( 'Update', 'tainacan' ),
'label_mapper_metadata' => __( 'Mapper Metadata', 'tainacan' ),
'label_add_more_mapper_metadata' => __( 'Add more mapper\'s metadata', 'tainacan' ),
'label_exposer_urls' => __( 'Exposer URLs' ),
'label_exposer_mapper_values' => __( 'Values only, no metadata scheme' ),
'label_exposer' => __( 'exposer' ),
'label_mapper' => __( 'mapper' ),
'label_clean' => __( 'Clear', 'tainacan' ),
'label_clear_filters' => __( 'Clear filters', 'tainacan' ),
'label_selected' => __( 'Selected', 'tainacan' ),
'label_relationship_new_search' => __( 'New Search', 'tainacan' ),
'label_relationship_items_found' => __( 'Items found', 'tainacan' ),
'label_menu' => __( 'Menu', 'tainacan' ),
'label_main_menu' => __( 'Main Menu', 'tainacan' ),
'label_collection_menu' => __( 'Collection Menu', 'tainacan' ),
'label_title' => __( 'Title', 'tainacan' ),
'label_settings' => __( 'Settings', 'tainacan' ),
'label_actions' => __( 'Actions', 'tainacan' ),
'label_name' => __( 'Name', 'tainacan' ),
'label_description' => __( 'Description', 'tainacan' ),
'label_status' => __( 'Status', 'tainacan' ),
'label_slug' => __( 'Slug', 'tainacan' ),
'label_image' => __( 'Image', 'tainacan' ),
'label_thumbnail' => __( 'Thumbnail', 'tainacan' ),
'label_empty_thumbnail' => __( 'Empty Thumbnail', 'tainacan' ),
'label_moderators' => __( 'Moderators', 'tainacan' ),
'label_parent_collection' => __( 'Parent collection', 'tainacan' ),
'label_no_parent_collection' => __( 'No parent collection', 'tainacan' ),
'label_button_view' => __( 'Button View', 'tainacan' ),
'label_button_edit' => __( 'Button Edit', 'tainacan' ),
'label_button_delete' => __( 'Button Delete', 'tainacan' ),
'label_button_delete_header_image' => __( 'Button Delete Header Image', 'tainacan' ),
'label_button_edit_thumb' => __( 'Button Edit Thumbnail', 'tainacan' ),
'label_button_edit_header_image' => __( 'Button Edit Header Image', 'tainacan' ),
'label_button_edit_document' => __( 'Button Edit Document', 'tainacan' ),
'label_button_delete_document' => __( 'Button Delete Document', 'tainacan' ),
'label_choose_thumb' => __( 'Choose Thumbnail', 'tainacan' ),
'label_button_delete_thumb' => __( 'Button Delete Thumbnail', 'tainacan' ),
'label_collections_per_page' => __( 'Collections per Page:', 'tainacan' ),
'label_taxonomies_per_page' => __( 'Taxonomies per Page:', 'tainacan' ),
'label_events_per_page' => __( 'Events per Page:', 'tainacan' ),
'label_items_per_page' => __( 'Items per Page:', 'tainacan' ),
'label_processes_per_page' => __( 'Processes per Page:', 'tainacan' ),
'label_active_metadata' => __( 'Active Metadata', 'tainacan' ),
'label_available_metadata' => __( 'Available Metadata', 'tainacan' ),
'label_available_metadata_types' => __( 'Available Metadata Types', 'tainacan' ),
'label_active_filters' => __( 'Active Filters', 'tainacan' ),
'label_filter_type' => __( 'Filter Type', 'tainacan' ),
'label_available_filters' => __( 'Available Filters', 'tainacan' ),
'label_available_filter_types' => __( 'Available Filter Types', 'tainacan' ),
'label_per_page' => __( 'per Page', 'tainacan' ),
'label_displayed_metadata' => __( 'Displayed metadata', 'tainacan' ),
'label_required' => __( 'Required', 'tainacan' ),
'label_allow_multiple' => __( 'Allow multiple values', 'tainacan' ),
'label_default_value' => __( 'Default value', 'tainacan' ),
'label_unique_value' => __( 'Unique value', 'tainacan' ),
'label_yes' => __( 'Yes', 'tainacan' ),
'label_no' => __( 'No', 'tainacan' ),
'label_approved' => __( 'Approved', 'tainacan' ),
'label_collection_related' => __( 'Collection Related', 'tainacan' ),
'label_metadata_for_search' => __( 'Metadata for search', 'tainacan' ),
'label_allow_repeated_items' => __( 'Allow repeated items', 'tainacan' ),
'label_select_taxonomy' => __( 'Select taxonomy', 'tainacan' ),
'label_select_taxonomy_input_type' => __( 'Input type', 'tainacan' ),
'label_taxonomy_allow_new_terms' => __( 'Allow new terms', 'tainacan' ),
'label_selectbox_init' => __( 'Select', 'tainacan' ),
'label_options' => __( 'Insert options', 'tainacan' ),
'label_attachments' => __( 'Attachments', 'tainacan' ),
'label_attachment' => __( 'Attachment', 'tainacan' ),
'label_enabled' => __( 'Enabled', 'tainacan' ),
'label_disabled' => __( 'Disabled', 'tainacan' ),
'label_creation' => __( 'Creation', 'tainacan' ),
'label_creation_date' => __( 'Creation date', 'tainacan' ),
'label_collection_items' => __( 'Collection Items', 'tainacan' ),
'label_collection_metadata' => __( 'Collection Metadata', 'tainacan' ),
'label_collection_filters' => __( 'Collection Filters', 'tainacan' ),
'label_parent_term' => __( 'Parent Term', 'tainacan' ),
'label_children_terms' => __( 'children terms', 'tainacan' ),
'label_new_term' => __( 'New Term', 'tainacan' ),
'label_new_child' => __( 'New Child', 'tainacan' ),
'label_taxonomy_terms' => __( 'Taxonomy Terms', 'tainacan' ),
'label_no_parent_term' => __( 'No parent term', 'tainacan' ),
'label_term_without_name' => __( 'Term without name', 'tainacan' ),
'label_inherited' => __( 'Inherited', 'tainacan' ),
'label_sorting' => __( 'Sorting', 'tainacan' ),
'label_event_date' => __( 'Event date', 'tainacan' ),
'label_event_title' => __( 'Event', 'tainacan' ),
'label_header_image' => __( 'Header Image', 'tainacan' ),
'label_empty_header_image' => __( 'Empty Header Image', 'tainacan' ),
'label_enable_cover_page' => __( 'Enable Cover Page', 'tainacan' ),
'label_cover_page' => __( 'Cover Page', 'tainacan' ),
'label_default_displayed_metadata' => __( 'Default Displayed Metadata', 'tainacan' ),
'label_display' => __( 'Display on Listing', 'tainacan' ),
'label_display_default' => __( 'Display by default', 'tainacan' ),
'label_display_never' => __( 'Never displayed', 'tainacan' ),
'label_not_display' => __( 'Not display by default', 'tainacan' ),
'label_attach_to_item' => __( 'Attach to item', 'tainacan' ),
'label_document' => __( 'Document', 'tainacan' ),
'label_document_empty' => __( 'Empty document', 'tainacan' ),
'label_file' => __( 'File', 'tainacan' ),
'label_text' => __( 'Text', 'tainacan' ),
'label_url' => __( 'URL', 'tainacan' ),
'label_select_file' => __( 'Select File', 'tainacan' ),
'label_expand_all' => __( 'Expand all', 'tainacan' ),
'label_collapse_all' => __( 'Collapse all', 'tainacan' ),
'label_view_term' => __( 'View Term', 'tainacan' ),
'label_all_items' => __( 'All items', 'tainacan' ),
'label_draft_items' => __( 'Draft', 'tainacan' ),
'label_trash_items' => __( 'Trash', 'tainacan' ),
'label_bulk_actions' => __( 'Bulk actions', 'tainacan' ),
'label_delete_selected_collections' => __( 'Delete selected collections', 'tainacan' ),
'label_edit_selected_collections' => __( 'Edit selected collections', 'tainacan' ),
'label_delete_permanently' => __( 'Delete permanently', 'tainacan' ),
'label_send_to_trash' => __( 'Send to trash', 'tainacan' ),
'label_delete_selected_taxonomies' => __( 'Delete selected taxonomies', 'tainacan' ),
'label_edit_selected_items' => __( 'Edit selected items', 'tainacan' ),
'label_edit_selected_taxonomies' => __( 'Edit selected taxonomies', 'tainacan' ),
'label_select_all_collections_page' => __( 'Select all collections on page', 'tainacan' ),
'label_select_all_items_page' => __( 'Select all items on page', 'tainacan' ),
'label_select_all_taxonomies_page' => __( 'Select all taxonomies on page', 'tainacan' ),
'label_select_all_processes_page' => __( 'Select all processes on page', 'tainacan' ),
'label_edit_attachments' => __( 'Edit attachments', 'tainacan' ),
'label_blank_collection' => __( 'Blank collection', 'tainacan' ),
'label_dublin_core' => __( 'Dublin Core', 'tainacan' ),
'label_created_by' => __( 'Created by', 'tainacan' ),
'label_apply_changes' => __( 'Apply changes', 'tainacan' ),
'label_view_mode' => __( 'View mode', 'tainacan' ),
'label_default_view_mode' => __( 'Default view mode', 'tainacan' ),
'label_enabled_view_modes' => __( 'Enabled view modes', 'tainacan' ),
'label_view_modes_available' => __( 'View modes available on theme', 'tainacan' ),
'label_warning' => __( 'Warning', 'tainacan' ),
'label_error' => __( 'Error', 'tainacan' ),
'label_thumbnails' => __( 'Thumbnails', 'tainacan' ),
'label_table' => __( 'Table', 'tainacan' ),
'label_cards' => __( 'Cards', 'tainacan' ),
'label_records' => __( 'Records', 'tainacan' ),
'label_masonry' => __( 'Masonry', 'tainacan' ),
'label_visualization' => __( 'Visualization', 'tainacan' ),
'label_available_importers' => __( 'Available Importers', 'tainacan' ),
'label_target_collection' => __( 'Target Collection', 'tainacan' ),
'label_source_file' => __( 'Source file', 'tainacan' ),
'label_url_source_link' => __( 'URL Source link', 'tainacan' ),
'label_metadata_mapping' => __( 'Metadata mapping', 'tainacan' ),
'label_select_metadatum' => __( 'Select metadatum', 'tainacan' ),
'label_select_metadatum_type' => __( 'Select a metadatum type', 'tainacan' ),
'label_add_more_metadata' => __( 'Add more metadata', 'tainacan' ),
'label_from_source_collection' => __( 'From source collection', 'tainacan' ),
'label_to_target_collection' => __( 'To target collection', 'tainacan' ),
'label_add_value' => __( 'Add value', 'tainacan' ),
'label_remove_value' => __( 'Remove value', 'tainacan' ),
'label_create_new_page' => __( 'Create new page', 'tainacan' ),
'label_total_items' => __( 'Total items', 'tainacan' ),
'label_view_all' => __( 'View all', 'tainacan' ),
'label_until' => __( 'until', 'tainacan' ),
'label_visibility' => __( 'Visibility', 'tainacan' ),
'label_discard' => __( 'Discard', 'tainacan' ),
'label_save_as_draft' => __( 'Save as draft', 'tainacan' ),
'label_update_draft' => __( 'Update draft', 'tainacan' ),
'label_return_to_draft' => __( 'Return to draft', 'tainacan' ),
'label_publish' => __( 'Publish', 'tainacan' ),
'label_update' => __( 'Update', 'tainacan' ),
'label_mapper_metadata' => __( 'Mapper Metadata', 'tainacan' ),
'label_add_more_mapper_metadata' => __( 'Add more mapper\'s metadata', 'tainacan' ),
'label_exposer_urls' => __( 'Exposer URLs' ),
'label_exposer_mapper_values' => __( 'Values only, no metadata scheme' ),
'label_exposer' => __( 'exposer' ),
'label_mapper' => __( 'mapper' ),
'label_no_details_of_process' => __( 'There are no details about this process', 'tainacan' ),
'label_queued_on' => __( 'Queued on:', 'tainacan' ),
'label_last_processed_on' => __( 'Last processed on:', 'tainacan' ),
'label_progress' => __( 'Progress', 'tainacan' ),
'label_process_completed' => __( 'Process completed', 'tainacan' ),
'label_process_failed' => __( 'Process failed', 'tainacan' ),
'label_max_options_to_show' => __( 'Max options to show', 'tainacan' ),
'label_unamed_process' => __( 'Unamed process', 'tainacan' ),
'label_import_collection' => __( 'Import collection', 'tainacan' ),
'label_semantic_uri' => __( 'Semantic Uri', 'tainacan' ),
'label_view_collection' => __( 'View collection', 'tainacan' ),
'label_view_more' => __( 'View more', 'tainacan' ),
'label_log_file' => __( 'Log file', 'tainacan' ),
'label_error_log_file' => __( 'Error Log file', 'tainacan' ),
// Instructions. More complex sentences to guide user and placeholders
'instruction_delete_selected_collections' => __( 'Delete selected collections', 'tainacan' ),
'instruction_delete_selected_items' => __( 'Delete selected items', 'tainacan' ),
'instruction_delete_selected_taxonomies' => __( 'Delete selected taxonomies', 'tainacan' ),
'instruction_image_upload_box' => __( 'Drop an image here or click to upload.', 'tainacan' ),
'instruction_select_a_status' => __( 'Select a status:', 'tainacan' ),
'instruction_select_a_filter_type' => __( 'Select a filter type:', 'tainacan' ),
'instruction_select_a_parent_term' => __( 'Select a parent term:', 'tainacan' ),
'instruction_select_a_metadatum' => __( 'Select a metadatum', 'tainacan' ),
'instruction_cover_page' => __( 'Type to search a Page to choose.', 'tainacan' ),
'instruction_moderators' => __( 'Type to search a User to add.', 'tainacan' ),
'instruction_select_a_parent_collection' => __( 'Select a parent collection.', 'tainacan' ),
'instruction_select_collection_thumbnail' => __( 'Select a thumbnail image for collection', 'tainacan' ),
'instruction_select_item_thumbnail' => __( 'Select a thumbnail image for item', 'tainacan' ),
'instruction_select_collection_header_image' => __( 'Select a header image for collection', 'tainacan' ),
'instruction_select_term_header_image' => __( 'Select a header image for term', 'tainacan' ),
'instruction_select_files_to_attach_to_item' => __( 'Select files to attach to item', 'tainacan' ),
'instruction_select_document_file_for_item' => __( 'Select a document file for item', 'tainacan' ),
'instruction_insert_url' => __( 'Insert URL', 'tainacan' ),
'instruction_write_text' => __( 'Write Text', 'tainacan' ),
'instruction_search' => __( 'Search', 'tainacan' ),
'instruction_search_in_repository' => __( 'Search in repository', 'tainacan' ),
'instruction_select_a_target_collection' => __( 'Select a target collection', 'tainacan' ),
'instruction_select_a_mapper' => __( 'Select a mapper', 'tainacan' ),
'instruction_select_an_importer_type' => __( 'Select an importer type from the options above:', 'tainacan' ),
'instruction_drop_file_or_click_to_upload' => __( 'Drop your source file or click here to upload.', 'tainacan' ),
'instruction_select_metadatum_type' => __( 'Select a metadatum type.', 'tainacan' ),
'instruction_configure_new_metadatum' => __( 'Configure new metadatum.', 'tainacan' ),
'instruction_insert_mapper_metadatum_info' => __( 'Insert the new mapper\'s metadatum info', 'tainacan' ),
'instruction_delete_selected_collections' => __( 'Delete selected collections', 'tainacan' ),
'instruction_delete_selected_items' => __( 'Delete selected items', 'tainacan' ),
'instruction_delete_selected_taxonomies' => __( 'Delete selected taxonomies', 'tainacan' ),
'instruction_image_upload_box' => __( 'Drop an image here or click to upload.', 'tainacan' ),
'instruction_select_a_status' => __( 'Select a status:', 'tainacan' ),
'instruction_select_a_filter_type' => __( 'Select a filter type:', 'tainacan' ),
'instruction_select_a_parent_term' => __( 'Select a parent term:', 'tainacan' ),
'instruction_select_a_metadatum' => __( 'Select a metadatum', 'tainacan' ),
'instruction_cover_page' => __( 'Type to search a Page to choose.', 'tainacan' ),
'instruction_moderators' => __( 'Type to search a User to add.', 'tainacan' ),
'instruction_select_a_parent_collection' => __( 'Select a parent collection.', 'tainacan' ),
'instruction_select_collection_thumbnail' => __( 'Select a thumbnail image for collection', 'tainacan' ),
'instruction_select_item_thumbnail' => __( 'Select a thumbnail image for item', 'tainacan' ),
'instruction_select_collection_header_image' => __( 'Select a header image for collection', 'tainacan' ),
'instruction_select_term_header_image' => __( 'Select a header image for term', 'tainacan' ),
'instruction_select_files_to_attach_to_item' => __( 'Select files to attach to item', 'tainacan' ),
'instruction_select_document_file_for_item' => __( 'Select a document file for item', 'tainacan' ),
'instruction_insert_url' => __( 'Insert URL', 'tainacan' ),
'instruction_write_text' => __( 'Write Text', 'tainacan' ),
'instruction_search' => __( 'Search', 'tainacan' ),
'instruction_search_in_repository' => __( 'Search in repository', 'tainacan' ),
'instruction_select_a_target_collection' => __( 'Select a target collection', 'tainacan' ),
'instruction_select_a_mapper' => __( 'Select a mapper', 'tainacan' ),
'instruction_select_an_importer_type' => __( 'Select an importer type from the options above:', 'tainacan' ),
'instruction_drop_file_or_click_to_upload' => __( 'Drop your source file or click here to upload.', 'tainacan' ),
'instruction_select_metadatum_type' => __( 'Select a metadatum type', 'tainacan' ),
'instruction_configure_new_metadatum' => __( 'Configure new metadatum.', 'tainacan' ),
'instruction_insert_mapper_metadatum_info' => __( 'Insert the new mapper\'s metadatum info', 'tainacan' ),
'instruction_select_max_options_to_show' => __( 'Select max options to show', 'tainacan' ),
'instruction_select_collection_fetch_items' => __( 'Select a collection to fecth items', 'tainacan' ),
// Info. Other feedback to user.
'info_search_results' => __( 'Search Results', 'tainacan' ),
'info_search_criteria' => __( 'Search Criteria', 'tainacan' ),
'info_name_is_required' => __( 'Name is required.', 'tainacan' ),
'info_no_collection_created' => __( 'No collection was created in this repository.', 'tainacan' ),
'info_no_collection_draft' => __( 'No draft collection found.', 'tainacan' ),
'info_no_collection_trash' => __( 'No collection in trash.', 'tainacan' ),
'info_no_taxonomy_draft' => __( 'No draft taxonomy found.', 'tainacan' ),
'info_no_taxonomy_trash' => __( 'No taxonomy in trash.', 'tainacan' ),
'info_no_taxonomy_created' => __( 'No taxonomy was created in this repository.', 'tainacan' ),
'info_no_item_created' => __( 'No item was created in this collection.', 'tainacan' ),
'info_no_item_draft' => __( 'No draft item found.', 'tainacan' ),
'info_no_item_trash' => __( 'No item in trash.', 'tainacan' ),
'info_no_page_found' => __( 'No page was found with this name.', 'tainacan' ),
'info_no_user_found' => __( 'No user was found with this name.', 'tainacan' ),
'info_no_item_found' => __( 'No item was found here with these filters.', 'tainacan' ),
'info_item_not_saved' => __( 'Warning: Item not saved.', 'tainacan' ),
'info_no_moderator_on_collection' => __( "This collection doesn't have any moderator yet.", 'tainacan' ),
'info_error_deleting_collection' => __( 'Error on deleting collection.', 'tainacan' ),
'info_error_deleting_taxonomy' => __( 'Error on deleting taxonomy', 'tainacan' ),
'info_collection_deleted' => __( 'Collection deleted.', 'tainacan' ),
'info_item_deleted' => __( 'Item deleted.', 'tainacan' ),
'info_taxonomy_deleted' => __( 'Taxonomy deleted', 'tainacan' ),
'info_warning_collection_delete' => __( 'Do you really want to permanently delete this collection?', 'tainacan' ),
'info_warning_collection_trash' => __( 'Do you really want to trash this collection?', 'tainacan' ),
'info_warning_item_delete' => __( 'Do you really want to permanently delete this item?', 'tainacan' ),
'info_warning_item_trash' => __( 'Do you really want to trash this item?', 'tainacan' ),
'info_warning_taxonomy_delete' => __( 'Do you really want to delete this taxonomy?', 'tainacan' ),
'info_warning_selected_collections_delete' => __( 'Do you really want to permanently delete the selected collections?', 'tainacan' ),
'info_warning_selected_collections_trash' => __( 'Do you really want to trash the selected collections?', 'tainacan' ),
'info_warning_selected_items_delete' => __( 'Do you really want to permanently delete the selected items?', 'tainacan' ),
'info_warning_selected_items_trash' => __( 'Do you really want to trash the selected items?', 'tainacan' ),
'info_warning_selected_taxonomies_delete' => __( 'Do you really want to delete the selected taxonomies?', 'tainacan' ),
'info_warning_collection_related' => __( 'The metadata Collection related is required', 'tainacan' ),
'info_warning_no_metadata_found' => __( 'No metadata found in this collection', 'tainacan' ),
'info_showing_items' => __( 'Showing items ', 'tainacan' ),
'info_showing_collections' => __( 'Showing collections ', 'tainacan' ),
'info_showing_taxonomies' => __( 'Showing taxonomies ', 'tainacan' ),
'info_showing_events' => __( 'Showing events ', 'tainacan' ),
'info_to' => __( ' to ', 'tainacan' ),
'info_of' => __( ' of ', 'tainacan' ),
'info_created_by' => __( 'Created by: ', 'tainacan' ),
'info_by' => __( 'By: ', 'tainacan' ),
'info_date' => __( 'Date: ', 'tainacan' ),
'info_not_saved' => __( 'Not saved ', 'tainacan' ),
'info_warning_item_not_saved' => __( 'Are you sure? The item is not saved, changes will be lost.', 'tainacan' ),
'info_warning_metadata_not_saved' => __( 'Are you sure? There are metadata not saved, changes will be lost.', 'tainacan' ),
'info_warning_filters_not_saved' => __( 'Are you sure? There are filters not saved, changes will be lost.', 'tainacan' ),
'info_no_description_provided' => __( 'No description provided.', 'tainacan' ),
'info_warning_taxonomy_not_saved' => __( 'Are you sure? The metadata is not saved, changes will be lost.', 'tainacan' ),
'info_warning_terms_not_saved' => __( 'Are you sure? There are terms not saved, changes will be lost.', 'tainacan' ),
'info_warning_orphan_terms' => __( 'Are you sure? This term is parent of other terms. These will be converted to root terms.', 'tainacan' ),
'info_no_events' => __( 'No events', 'tainacan' ),
'info_logs_before' => __( 'Before updating', 'tainacan' ),
'info_logs_after' => __( 'What was updated', 'tainacan' ),
'info_there_is_no_metadatum' => __( 'There is no metadata here yet.', 'tainacan' ),
'info_there_is_no_filter' => __( 'There is no filter here yet.', 'tainacan' ),
'info_changes' => __( 'Changes', 'tainacan' ),
'info_possible_external_sources' => __( 'Possible external sources: CSV, Instagram, Youtube, etc.', 'tainacan' ),
'info_help_term_name' => __( 'The term name', 'tainacan' ),
'info_help_term_description' => __( 'The description of the Term.', 'tainacan' ),
'info_no_attachments_on_item_yet' => __( 'The are no attachments on this item so far.', 'tainacan' ),
'info_repository_metadata_inheritance' => __( 'Repository Metadata will be inherited by all collections.', 'tainacan' ),
'info_repository_filters_inheritance' => __( 'Repository Filters will be inherited by all collections.', 'tainacan' ),
'info_create_filters' => __( 'Click or Drag and Drop Metadata here for creating a new Filter.', 'tainacan' ),
'info_create_metadata' => __( 'Click or Drag and Drop Metadata Types here for creating a new Metadata.', 'tainacan' ),
'info_choose_your_metadata' => __( 'Choose your metadata.', 'tainacan' ),
'info_available_importers_helper' => __( 'The available importer type will affect the file or link that will provide your data besides deciding wich options are available to the importer.', 'tainacan' ),
'info_target_collection_helper' => __( 'The collection to which imported data will be send.', 'tainacan' ),
'info_source_file_upload' => __( 'The file containing the data to be imported.', 'tainacan' ),
'info_metadata_mapping_helper' => __( 'Map each file metadata with the corresponding one in selected collection.', 'tainacan' ),
'info_upload_a_source_to_see_metadata' => __( 'Upload a source file to load metadata.', 'tainacan' ),
'info_select_collection_to_list_metadata' => __( 'Select a target collection to list metadata.', 'tainacan' ),
'info_url_source_link_helper' => __( 'Link to file containing the data to be imported.', 'tainacan' ),
'info_updated_at' => __( 'Updated at', 'tainacan' ),
'info_editing_metadata_values' => __( 'Editing metadata values...', 'tainacan' ),
'info_updating_metadata_values' => __( 'Updating metadata values...', 'tainacan' ),
'info_type_to_add_items' => __( 'Add items...', 'tainacan' ),
'info_type_to_search_items' => __( 'Search items...', 'tainacan' ),
'info_type_to_add_terms' => __( 'Add terms...', 'tainacan' ),
'info_type_to_search_metadata' => __( 'Search metadata...', 'tainacan' ),
'info_type_to_add_metadata' => __( 'Add metadata...', 'tainacan' ),
'info_visibility_helper' => __( 'How the item will be available to visualization.', 'tainacan' ),
'info_errors_in_form' => __( 'There are errors in the form', 'tainacan' ),
'info_no_document_to_item' => __( 'No document was uploaded to this item.', 'tainacan' ),
'info_search_results' => __( 'Search Results', 'tainacan' ),
'info_search_criteria' => __( 'Search Criteria', 'tainacan' ),
'info_name_is_required' => __( 'Name is required.', 'tainacan' ),
'info_no_collection_created' => __( 'No collection was created in this repository.', 'tainacan' ),
'info_no_collection_draft' => __( 'No draft collection found.', 'tainacan' ),
'info_no_collection_trash' => __( 'No collection in trash.', 'tainacan' ),
'info_no_taxonomy_draft' => __( 'No draft taxonomy found.', 'tainacan' ),
'info_no_taxonomy_trash' => __( 'No taxonomy in trash.', 'tainacan' ),
'info_no_taxonomy_created' => __( 'No taxonomy was created in this repository.', 'tainacan' ),
'info_no_item_created' => __( 'No item was created in this collection.', 'tainacan' ),
'info_no_item_draft' => __( 'No draft item found.', 'tainacan' ),
'info_no_item_trash' => __( 'No item in trash.', 'tainacan' ),
'info_no_page_found' => __( 'No page was found with this name.', 'tainacan' ),
'info_no_user_found' => __( 'No user was found with this name.', 'tainacan' ),
'info_no_item_found_filter' => __( 'No item was found here with these filters.', 'tainacan' ),
'info_no_item_found' => __( 'No item was found.', 'tainacan' ),
'info_item_not_saved' => __( 'Warning: Item not saved.', 'tainacan' ),
'info_no_moderator_on_collection' => __( "This collection doesn't have any moderator yet.", 'tainacan' ),
'info_error_deleting_collection' => __( 'Error on deleting collection.', 'tainacan' ),
'info_error_deleting_taxonomy' => __( 'Error on deleting taxonomy', 'tainacan' ),
'info_collection_deleted' => __( 'Collection deleted.', 'tainacan' ),
'info_item_deleted' => __( 'Item deleted.', 'tainacan' ),
'info_taxonomy_deleted' => __( 'Taxonomy deleted', 'tainacan' ),
'info_warning_collection_delete' => __( 'Do you really want to permanently delete this collection?', 'tainacan' ),
'info_warning_collection_trash' => __( 'Do you really want to trash this collection?', 'tainacan' ),
'info_warning_item_delete' => __( 'Do you really want to permanently delete this item?', 'tainacan' ),
'info_warning_item_trash' => __( 'Do you really want to trash this item?', 'tainacan' ),
'info_warning_metadatum_delete' => __( 'Do you really want to permanently delete this metadatum?', 'tainacan' ),
'info_warning_taxonomy_delete' => __( 'Do you really want to delete this taxonomy?', 'tainacan' ),
'info_warning_selected_collections_delete' => __( 'Do you really want to permanently delete the selected collections?', 'tainacan' ),
'info_warning_selected_collections_trash' => __( 'Do you really want to trash the selected collections?', 'tainacan' ),
'info_warning_selected_items_delete' => __( 'Do you really want to permanently delete the selected items?', 'tainacan' ),
'info_warning_selected_term_delete' => __( 'Do you really want to permanently delete the selected term?', 'tainacan' ),
'info_warning_selected_items_trash' => __( 'Do you really want to trash the selected items?', 'tainacan' ),
'info_warning_selected_taxonomies_delete' => __( 'Do you really want to delete the selected taxonomies?', 'tainacan' ),
'info_warning_collection_related' => __( 'The metadata Collection related is required', 'tainacan' ),
'info_warning_no_metadata_found' => __( 'No metadata found in this collection', 'tainacan' ),
'info_showing_items' => __( 'Showing items ', 'tainacan' ),
'info_showing_collections' => __( 'Showing collections ', 'tainacan' ),
'info_showing_taxonomies' => __( 'Showing taxonomies ', 'tainacan' ),
'info_showing_events' => __( 'Showing events ', 'tainacan' ),
'info_showing_processes' => __( 'Showing processes ', 'tainacan' ),
'info_to' => __( ' to ', 'tainacan' ),
'info_of' => __( ' of ', 'tainacan' ),
'info_created_by' => __( 'Created by: ', 'tainacan' ),
'info_by' => __( 'By: ', 'tainacan' ),
'info_date' => __( 'Date: ', 'tainacan' ),
'info_not_saved' => __( 'Not saved ', 'tainacan' ),
'info_warning_item_not_saved' => __( 'Are you sure? The item is not saved, changes will be lost.', 'tainacan' ),
'info_warning_metadata_not_saved' => __( 'Are you sure? There are metadata not saved, changes will be lost.', 'tainacan' ),
'info_warning_filters_not_saved' => __( 'Are you sure? There are filters not saved, changes will be lost.', 'tainacan' ),
'info_no_description_provided' => __( 'No description provided.', 'tainacan' ),
'info_warning_taxonomy_not_saved' => __( 'Are you sure? The metadata is not saved, changes will be lost.', 'tainacan' ),
'info_warning_terms_not_saved' => __( 'Are you sure? There are terms not saved, changes will be lost.', 'tainacan' ),
'info_warning_orphan_terms' => __( 'Are you sure? This term is parent of other terms. These will be converted to root terms.', 'tainacan' ),
'info_no_events' => __( 'No events', 'tainacan' ),
'info_logs_before' => __( 'Before updating', 'tainacan' ),
'info_logs_after' => __( 'What was updated', 'tainacan' ),
'info_there_is_no_metadatum' => __( 'There is no metadata here yet.', 'tainacan' ),
'info_there_is_no_filter' => __( 'There is no filter here yet.', 'tainacan' ),
'info_changes' => __( 'Changes', 'tainacan' ),
'info_possible_external_sources' => __( 'Possible external sources: CSV, Instagram, Youtube, etc.', 'tainacan' ),
'info_help_term_name' => __( 'The term name', 'tainacan' ),
'info_help_term_description' => __( 'The description of the Term.', 'tainacan' ),
'info_no_attachments_on_item_yet' => __( 'The are no attachments on this item so far.', 'tainacan' ),
'info_repository_metadata_inheritance' => __( 'Repository Metadata will be inherited by all collections.', 'tainacan' ),
'info_repository_filters_inheritance' => __( 'Repository Filters will be inherited by all collections.', 'tainacan' ),
'info_create_filters' => __( 'Click or Drag and Drop Metadata here for creating a new Filter.', 'tainacan' ),
'info_create_metadata' => __( 'Click or Drag and Drop Metadata Types here for creating a new Metadata.', 'tainacan' ),
'info_choose_your_metadata' => __( 'Choose your metadata.', 'tainacan' ),
'info_available_importers_helper' => __( 'The available importer type will affect the file or link that will provide your data besides deciding wich options are available to the importer.', 'tainacan' ),
'info_target_collection_helper' => __( 'The collection to which imported data will be send.', 'tainacan' ),
'info_source_file_upload' => __( 'The file containing the data to be imported.', 'tainacan' ),
'info_metadata_mapping_helper' => __( 'Map each file metadata with the corresponding one in selected collection.', 'tainacan' ),
'info_upload_a_source_to_see_metadata' => __( 'Upload a source file to load metadata.', 'tainacan' ),
'info_select_collection_to_list_metadata' => __( 'Select a target collection to list metadata.', 'tainacan' ),
'info_url_source_link_helper' => __( 'Link to file containing the data to be imported.', 'tainacan' ),
'info_updated_at' => __( 'Updated at', 'tainacan' ),
'info_editing_metadata_values' => __( 'Editing metadata values...', 'tainacan' ),
'info_updating_metadata_values' => __( 'Updating metadata values...', 'tainacan' ),
'info_type_to_add_items' => __( 'Add items...', 'tainacan' ),
'info_type_to_search_items' => __( 'Search items...', 'tainacan' ),
'info_type_to_add_terms' => __( 'Add terms...', 'tainacan' ),
'info_type_to_search_metadata' => __( 'Search metadata...', 'tainacan' ),
'info_type_to_add_metadata' => __( 'Add metadata...', 'tainacan' ),
'info_visibility_helper' => __( 'How the item will be available to visualization.', 'tainacan' ),
'info_errors_in_form' => __( 'There are errors in the form', 'tainacan' ),
'info_no_document_to_item' => __( 'No document was uploaded to this item.', 'tainacan' ),
'info_unfinished_processes' => __( 'unfinished processes', 'tainacan' ),
'info_no_process' => __( 'There are no processes executing.', 'tainacan' ),
'info_unknown_date' => __( 'Unknown date.', 'tainacan' ),
'info_there_are_no_metadata_to_search' => __( 'There are no metadata to search', 'tainacan' ),
'info_there_are_no_metadata_in_repository_level' => __( 'There are no metadata in repository level', 'tainacan' ),
'info_import_a_collection' => __( 'Import a collection from external sources', 'tainacan' ),
// Tainacan Metadatum Types
'tainacan-text' => __( 'Text', 'tainacan' ),
'tainacan-textarea' => __( 'Text area', 'tainacan' ),
'tainacan-date' => __( 'Date', 'tainacan' ),
'tainacan-numeric' => __( 'Numeric', 'tainacan' ),
'tainacan-selectbox' => __( 'Select box', 'tainacan' ),
'tainacan-relationship' => __( 'Relationship', 'tainacan' ),
'tainacan-taxonomy' => __( 'Taxonomy', 'tainacan' ),
'tainacan-compound' => __( 'Compound', 'tainacan' ),
'tainacan-text' => __( 'Text', 'tainacan' ),
'tainacan-textarea' => __( 'Text area', 'tainacan' ),
'tainacan-date' => __( 'Date', 'tainacan' ),
'tainacan-numeric' => __( 'Numeric', 'tainacan' ),
'tainacan-selectbox' => __( 'Select box', 'tainacan' ),
'tainacan-relationship' => __( 'Relationship', 'tainacan' ),
'tainacan-taxonomy' => __( 'Taxonomy', 'tainacan' ),
'tainacan-compound' => __( 'Compound', 'tainacan' ),
// Tainacan Filter Types
'tainacan-filter-custom-interval' => __( 'Custom Interval', 'tainacan' ),
'tainacan-filter-selectbox' => __( 'Select Box', 'tainacan' ),
'tainacan-filter-autocomplete' => __( 'Autocomplete', 'tainacan' ),
'tainacan-filter-taginput' => __( 'Tag Input', 'tainacan' ),
'tainacan-filter-checkbox' => __( 'Check Box', 'tainacan' ),
'tainacan-filter-taxonomy-taginput' => __( 'Taxonomy Tag Input', 'tainacan' ),
'tainacan-filter-taxonomy-checkbox' => __( 'Taxonomy Check Box', 'tainacan' ),
'tainacan-filter-taxonomy-selectbox' => __( 'Taxonomy Select Box', 'tainacan' )
'tainacan-filter-custom-interval' => __( 'Custom Interval', 'tainacan' ),
'tainacan-filter-selectbox' => __( 'Select Box', 'tainacan' ),
'tainacan-filter-autocomplete' => __( 'Autocomplete', 'tainacan' ),
'tainacan-filter-taginput' => __( 'Tag Input', 'tainacan' ),
'tainacan-filter-checkbox' => __( 'Check Box', 'tainacan' ),
'tainacan-filter-taxonomy-taginput' => __( 'Taxonomy Tag Input', 'tainacan' ),
'tainacan-filter-taxonomy-checkbox' => __( 'Taxonomy Check Box', 'tainacan' ),
'tainacan-filter-taxonomy-selectbox' => __( 'Taxonomy Select Box', 'tainacan' )
] );
?>

View File

@ -24,25 +24,33 @@ export default {
// Buefy imports
@import "../../node_modules/buefy/src/scss/components/_datepicker.scss";
$speed-slow: 0.5s;
@import "../../node_modules/buefy/src/scss/utils/_functions.scss";
@import "../../node_modules/buefy/src/scss/utils/_all.scss";
@import "../../node_modules/buefy/src/scss/components/_checkbox.scss";
@import "../../node_modules/buefy/src/scss/components/_radio.scss";
@import "../../node_modules/buefy/src/scss/components/_tag.scss";
@import "../../node_modules/buefy/src/scss/components/_loading.scss";
@import "../../node_modules/buefy/src/scss/components/_dropdown.scss";
@import "../../node_modules/buefy/src/scss/components/_modal.scss";
// Tainacan imports
@import "../admin/scss/_tables.scss";
@import "../admin/scss/_modals.scss";
@import "../admin/scss/_buttons.scss";
@import "../admin/scss/_inputs.scss";
@import "../admin/scss/_checkboxes.scss";
@import "../admin/scss/_pagination.scss";
@import "../admin/scss/_tags.scss";
// @import "../admin/scss/_tabs.scss";
@import "../admin/scss/_selects.scss";
@import "../admin/scss/_dropdown-and-autocomplete.scss";
@import "../admin/scss/_tooltips.scss";
@import "../admin/scss/_tainacan-form.scss";
@import "../admin/scss/_filters-menu-modal.scss";
.theme-items-list {
position: relative;
display: flex;
-webkit-overflow-scrolling: touch;
a{ color: $secondary !important }
a:hover {
@ -53,66 +61,6 @@ export default {
list-style: none;
}
// Some components have a different style in listing pages
.button {
height: inherit !important;
box-shadow: none !important;
border: none;
border-radius: 6px;
padding: 2px 15px;
margin-top: 0px;
margin-bottom: 0px;
display: inline-flex;
font-weight: normal;
cursor: pointer;
&.is-secondary:hover, &.is-secondary:focus {
background: $secondary !important;
}
&.is-primary:hover, &.is-primary:focus {
background: $primary !important;
}
&.is-success:hover, &.is-success:focus {
background: $success !important;
}
&.is-white:hover, &.is-white:focus, &.is-outlined:hover, &.is-outlined:focus {
background: $white !important;
}
&:active {
-webkit-transform: none !important;
transform: none !important;
}
&.is-outlined {
color: #150e38 !important;
background-color: white;
border-color: $gray-light !important;
}
&:focus {
outline: 0px;
}
}
.button.is-small {
height: 26px !important;
line-height: 12px;
}
.button:not(.is-small):not(.is-medium):not(.is-large) {
height: 30px !important;
line-height: 20px !important;
font-size: 14px !important;
}
.input, .textarea {
font-size: 14px;
border: 1px solid $tainacan-input-background;
border-radius: 1px !important;
background-color: white;
box-shadow: none !important;
&:focus, &:active {
box-shadow: none !important;
background-color: white;
border: 1px solid $tainacan-input-background !important;
}
}
.dropdown {
display: inline-flex;
position: relative;
@ -121,41 +69,12 @@ export default {
.dropdown-menu {
display: block;
}
.b-checkbox.checkbox {
align-items: baseline;
margin-bottom: 5px;
input[type="checkbox"] {
box-shadow: none !important;
}
input[type="checkbox"] + .check {
width: 1.0em;
height: 1.0em;
flex-shrink: 0;
border-radius: 0;
border: 1px solid $gray-light;
transition: background 150ms ease-out;
box-shadow: none !important;
}
&:focus input[type="checkbox"] + .check,
&:active input[type="checkbox"] + .check,
&:hover input[type="checkbox"] + .check {
box-shadow: none !important;
border-color: $gray-light !important;
}
input[type="checkbox"]:checked + .check {
background: white url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1 1'%3E%3Cpath style='fill:%23000' d='M 0.04038059,0.6267767 0.14644661,0.52071068 0.42928932,0.80355339 0.3232233,0.90961941 z M 0.21715729,0.80355339 0.85355339,0.16715729 0.95961941,0.2732233 0.3232233,0.90961941 z'%3E%3C/path%3E%3C/svg%3E") no-repeat center center !important;
border-color: $gray-light !important;
}
}
.b-radio.radio {
input[type="radio"] + .check {
width: 13px !important;
height: 13px !important;
border: 1px solid $gray-light !important;
border: 1px solid $gray4 !important;
}
input[type="radio"] + .check::before {
background: black !important;
@ -168,7 +87,7 @@ export default {
box-shadow: none !important;
}
input[type="radio"]:checked + .check {
border-color: $gray-light !important;
border-color: $gray4 !important;
}
&:focus input[type="radio"]:checked + .check {
box-shadow: none !important;
@ -187,110 +106,16 @@ export default {
}
}
.pagination-area {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 0.85em !important;
font-weight: normal !important;
border-top: 1px solid $gray;
padding: 0em 1.0em;
color: $gray-light;
.shown-items {
flex-grow: 1;
}
.items-per-page {
flex-grow: 3;
margin-top: 0.35em;
.field-label {
flex-grow: 5;
margin-right: 0.5em;
.label {
font-size: 1em !important;
font-weight: normal !important;
color: $gray-light;
}
}
select {
font-size: 0.85em;
}
}
.pagination {
flex-grow: 1;
ul {
margin-bottom: 0px;
padding: 0px;
}
&.is-small {
font-size: 0.85em;
}
a[disabled="disabled"] {
color: $gray-light;
}
.pagination-link, .pagination-previous, .pagination-next {
background-color: transparent;
color: $secondary;
border: none;
}
.pagination-link.is-current {
color: $gray-light;
}
.pagination-link::after:not(:last-child) {
content: ',';
color: $gray-light;
}
.mdi-chevron-left::before {
content: "\F40A";
font-size: 17px;
transform: rotate(180deg);
}
.mdi-chevron-right::before {
content: "\F40A";
font-size: 17px;
}
}
}
// Tabs
.tabs {
a {
font-size: 13px;
margin-bottom: -3px;
&:hover{
border-bottom-color: transparent;
}
}
li.is-active a {
border-bottom: 5px solid $primary;
color: $primary;
}
}
.select select{
border-radius: 1;
padding: 4px 16px;
color: #1d1d1d;
font-size: 1.0em;
font-weight: normal;
cursor: pointer;
background-color: white;
}
#filter-menu-compress-button {
top: 70px !important;
}
.filters-menu {
height: auto;
// height: auto;
position: absolute !important;
min-width: $filter-menu-width-theme;
border-right: 0;
padding: 25px 12px 25px 4.1666667%;
padding: 25px 2.0833333% 25px 4.1666667%;
@media screen and (min-width: 769px) and (max-width: 1023px) {
min-width: 25% !important;
}
.columns {
display: flex;
@ -303,10 +128,26 @@ export default {
}
}
.search-control {
.search-control {
justify-content: flex-start !important;
@media screen and (min-width: 769px) {
margin-bottom: $page-small-top-padding !important;
.search-control-item {
margin-right: $page-side-padding !important;
}
}
@media screen and (max-width: 768px) {
justify-content: space-between !important;
}
.search-control-item:first-child>div {
margin-left: -8.3333333%;
}
.gray-icon, .gray-icon .icon {
color: $tainacan-placeholder-color !important;
color: $gray4 !important;
i::before {
font-size: 21px;
}
@ -317,6 +158,7 @@ export default {
.view-mode-icon {
margin-right: 0px !important;
margin-top: 1px;
margin-left: 4px;
&.icon i::before, .gray-icon i::before {
font-size: 19px !important;
@ -326,7 +168,16 @@ export default {
#items-list-area {
width: 100%;
overflow-y: unset;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
margin-left: 0;
&.spaced-to-right {
margin-left: $filter-menu-width-theme;
@media screen and (min-width: 769px) and (max-width: 1023px) {
margin-left: 25% !important;
}
}
}
}

View File

@ -79,6 +79,7 @@ class REST_Controller extends \WP_REST_Controller {
'hideempty' => 'hide_empty',
'perpage' => 'posts_per_page',
'number' => 'number',
'parent' => 'parent',
'paged' => 'paged',
'postin' => 'post__in',
'relation' => 'relation',
@ -140,90 +141,6 @@ class REST_Controller extends \WP_REST_Controller {
return $args;
}
/**
* @param $data
* @param $metadatum_name
* @param $request
*
* @return \WP_Error
*/
function gt_user_meta( $data, $metadatum_name, $request ) {
if( $data['id'] ){
$user_meta = get_user_meta( $data['id'] );
}
if ( !$user_meta ) {
return new \WP_Error( 'No user meta found', 'No user meta found', array( 'status' => 404 ) );
}
foreach ($user_meta as $key => $value) {
$data[$key] = $value;
}
return $data;
}
/**
* @param $meta
* @param $user
* @param $metadatum_name
*
* @param $request
*
* @return mixed|\WP_Error
*/
public function up_user_meta( $meta, $user, $metadatum_name, $request ) {
if ( !$user->ID ) {
return new \WP_Error( 'No user found', 'No user found', array( 'status' => 404 ) );
}
$user_id = $user->ID;
$metas = $metadatum_name === 'meta' ? $meta : [];
$map = [
'metakey',
'metavalue',
'prevvalue',
];
if ($request['delete'] === 'true'){
if($this->contains_array($metas, $map)){
foreach ($metas as $index => $meta){
if (isset($meta[$map[0]], $meta[$map[1]])){
delete_user_meta($user_id, $meta[$map[0]], $meta[$map[1]]);
}
}
} else {
foreach ($metas as $meta){
if (isset($meta[$map[0]], $meta[$map[1]])){
delete_user_meta($user_id, $meta[$map[0]], $meta[$map[1]]);
}
}
}
} elseif($this->contains_array($metas, $map)){
foreach ($metas as $index => $meta){
if(isset($meta[$map[0]], $meta[$map[1]], $meta[$map[2]])){
update_user_meta($user_id, $meta[$map[0]], $meta[$map[1]], $meta[$map[2]]);
} elseif (isset($meta[$map[0]], $meta[$map[1]])){
add_user_meta($user_id, $meta[$map[0]], $meta[$map[1]]);
}
}
} else {
foreach ($metas as $meta){
if(isset($meta[$map[0]], $meta[$map[1]], $meta[$map[2]])){
update_user_meta($user_id, $meta[$map[0]], $meta[$map[1]], $meta[$map[2]]);
} elseif (isset($meta[$map[0]], $meta[$map[1]])){
add_user_meta($user_id, $meta[$map[0]], $meta[$map[1]]);
}
}
}
}
/**
* @param $mapped
* @param $request

View File

@ -47,7 +47,15 @@ class REST_Background_Processes_Controller extends REST_Controller {
'status' => [
'type' => 'string',
'description' => __( '"open" returns only processes currently running. "closed" returns only finished or aborted. "all" returns all. Default "all"', 'tainacan' ),
]
],
'perpage' => [
'type' => 'integer',
'description' => __( 'Number of processes to return per page. Default 10', 'tainacan' ),
],
'paged' => [
'type' => 'integer',
'description' => __( 'Page to retrieve. Default 1', 'tainacan' ),
],
],
),
));
@ -106,14 +114,27 @@ class REST_Background_Processes_Controller extends REST_Controller {
public function get_items( $request ) {
global $wpdb;
$body = json_decode($request->get_body(), true);
//$body = json_decode($request->get_body(), true);
$perpage = isset($request['perpage']) && is_numeric($request['perpage']) ? $request['perpage'] : 10;
if ($perpage < 1) {
$perpage = 1;
}
$paged = isset($request['paged']) && is_numeric($request['paged']) ? $request['paged'] : 1;
if ($paged < 1) {
$paged = 1;
}
$offset = ($paged - 1) * $perpage;
$limit_q = "LIMIT $offset,$perpage";
$user_q = $wpdb->prepare("AND user_id = %d", get_current_user_id());
$status_q = "";
if (current_user_can('edit_users')) {
if (isset($body['user_id'])) {
$user_q = $wpdb->prepare("AND user_id = %d", $body['user_id']);
if (isset($request['user_id'])) {
$user_q = $wpdb->prepare("AND user_id = %d", $request['user_id']);
}
if ( isset($user_q['all_users']) && $user_q['all_users'] ) {
@ -130,11 +151,28 @@ class REST_Background_Processes_Controller extends REST_Controller {
}
}
$query = "SELECT * FROM $this->table WHERE 1=1 $status_q $user_q ORDER BY priority DESC, queued_on DESC";
$base_query = "FROM $this->table WHERE 1=1 $status_q $user_q ORDER BY priority DESC, queued_on DESC";
$query = "SELECT * $base_query $limit_q";
$count_query = "SELECT COUNT(ID) $base_query";
$result = $wpdb->get_results($query);
$total_items = $wpdb->get_var($count_query);
return new \WP_REST_Response( $result, 200 );
$response = [];
foreach ($result as $r) {
$response[] = $this->prepare_item_for_response($r, $request);
}
$rest_response = new \WP_REST_Response( $response, 200 );
$max_pages = ceil($total_items / (int) $perpage);
$rest_response->header('X-WP-Total', (int) $total_items);
$rest_response->header('X-WP-TotalPages', (int) $max_pages);
return $rest_response;
}
@ -156,13 +194,18 @@ class REST_Background_Processes_Controller extends REST_Controller {
$result = $wpdb->get_row($query);
$result->log = $this->get_log_url($id, $result->action);
$result->error_log = $this->get_log_url($id, $result->action, 'error');
$result = $this->prepare_item_for_response($result, $request);
return new \WP_REST_Response( $result, 200 );
}
public function prepare_item_for_response($item, $request) {
$item->log = $this->get_log_url($item->ID, $item->action);
$item->error_log = $this->get_log_url($item->ID, $item->action, 'error');
return $item;
}
public function update_item( $request ) {
global $wpdb;
$id = $request['id'];
@ -230,8 +273,13 @@ class REST_Background_Processes_Controller extends REST_Controller {
$filename = 'bg-' . $action . '-' . $id . $suffix . '.log';
$upload_url = wp_upload_dir();
$upload_url = trailingslashit( $upload_url['url'] );
$logs_url = $upload_url . 'tainacan';
if (!file_exists( $upload_url['basedir'] . '/tainacan/' . $filename )) {
return null;
}
$upload_url = trailingslashit( $upload_url['baseurl'] );
$logs_url = $upload_url . 'tainacan/' . $filename;
return $logs_url;

View File

@ -56,6 +56,33 @@ class REST_Bulkedit_Controller extends REST_Controller {
),
)
);
register_rest_route($this->namespace, '/collection/(?P<collection_id>[\d]+)/' . $this->rest_base . '/(?P<group_id>[0-9a-f]+)/trash',
array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array($this, 'trash_items'),
'permission_callback' => array($this, 'bulk_edit_permissions_check'),
),
)
);
register_rest_route($this->namespace, '/collection/(?P<collection_id>[\d]+)/' . $this->rest_base . '/(?P<group_id>[0-9a-f]+)/untrash',
array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array($this, 'untrash_items'),
'permission_callback' => array($this, 'bulk_edit_permissions_check'),
),
)
);
register_rest_route($this->namespace, '/collection/(?P<collection_id>[\d]+)/' . $this->rest_base . '/(?P<group_id>[0-9a-f]+)/delete_items',
array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array($this, 'delete_items'),
'permission_callback' => array($this, 'bulk_edit_permissions_check'),
),
)
);
register_rest_route($this->namespace, '/collection/(?P<collection_id>[\d]+)/' . $this->rest_base . '/(?P<group_id>[0-9a-f]+)/set',
array(
array(
@ -196,6 +223,63 @@ class REST_Bulkedit_Controller extends REST_Controller {
}
public function trash_items($request) {
$group_id = $request['group_id'];
$args = ['id' => $group_id];
$bulk = new \Tainacan\Bulk_Edit($args);
$action = $bulk->trash_items();
if ( is_wp_error($action) ) {
return new \WP_REST_Response([
'error_message' => $action->get_error_message(),
], 400);
} else {
return new \WP_REST_Response($action, 200);
}
}
public function untrash_items($request) {
$group_id = $request['group_id'];
$args = ['id' => $group_id];
$bulk = new \Tainacan\Bulk_Edit($args);
$action = $bulk->untrash_items();
if ( is_wp_error($action) ) {
return new \WP_REST_Response([
'error_message' => $action->get_error_message(),
], 400);
} else {
return new \WP_REST_Response($action, 200);
}
}
public function delete_items($request) {
$group_id = $request['group_id'];
$args = ['id' => $group_id];
$bulk = new \Tainacan\Bulk_Edit($args);
$action = $bulk->delete_items();
if ( is_wp_error($action) ) {
return new \WP_REST_Response([
'error_message' => $action->get_error_message(),
], 400);
} else {
return new \WP_REST_Response($action, 200);
}
}
private function generic_action($method, $request, $keys = ['value']) {
$body = json_decode($request->get_body(), true);

View File

@ -88,6 +88,16 @@ class REST_Importers_Controller extends REST_Controller {
));
register_rest_route($this->namespace, '/' . $this->rest_base . '/session/(?P<session_id>[0-9a-f]+)', array(
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array($this, 'get_item'),
'permission_callback' => array($this, 'import_permissions_check'),
),
));
register_rest_route($this->namespace, '/' . $this->rest_base . '/session/(?P<session_id>[0-9a-f]+)/run', array(
array(
@ -243,6 +253,22 @@ class REST_Importers_Controller extends REST_Controller {
}
public function get_item( $request ) {
$session_id = $request['session_id'];
$importer = $_SESSION['tainacan_importer'][$session_id];
if(!$importer) {
return new \WP_REST_Response([
'error_message' => __('Importer Session not found', 'tainacan' ),
'session_id' => $session_id
], 400);
}
$response = $importer->_to_Array();
return new \WP_REST_Response( $response, 200 );
}
public function add_file( $request ) {
$session_id = $request['session_id'];
$importer = $_SESSION['tainacan_importer'][$session_id];

View File

@ -217,9 +217,13 @@ class REST_Items_Controller extends REST_Controller {
if($request['collection_id']) {
$collection_id = $request['collection_id'];
}
$query_start = microtime(true);
$items = $this->items_repository->fetch($args, $collection_id, 'WP_Query');
$query_end = microtime(true);
$response = [];
$return_template = false;
@ -242,9 +246,9 @@ class REST_Items_Controller extends REST_Controller {
global $wp_query, $view_mode_displayed_metadata;
$wp_query = $items;
$displayed_metadata = array_map(function($el) { return (int) $el; }, $request['fetch_only']['meta']);
$view_mode_displayed_metadata = $request['fetch_only'];
$view_mode_displayed_metadata['meta'] = $displayed_metadata;
$view_mode_displayed_metadata['meta'] = array_map(function($el) { return (int) $el; }, array_key_exists('meta', $request['fetch_only']) ? $request['fetch_only']['meta'] : array());
include $view_mode['template'];
@ -275,6 +279,8 @@ class REST_Items_Controller extends REST_Controller {
$rest_response->header('X-WP-Total', (int) $total_items);
$rest_response->header('X-WP-TotalPages', (int) $max_pages);
$rest_response->header('X-Tainacan-Query-Time', $query_end - $query_start);
$rest_response->header('X-Tainacan-Elapsed-Time', microtime(true) - $query_start);
return $rest_response;
}

View File

@ -129,20 +129,27 @@ class REST_Metadata_Controller extends REST_Controller {
$collection_id = isset($request['collection_id']) ? $request['collection_id'] : false;
$metadatum_id = $request['metadatum_id'];
$offset = '';
$number = '';
if($request['offset'] >= 0 && $request['number'] >= 1){
$offset = $request['offset'];
$number = $request['number'];
}
if($request['fetch'] === 'all_metadatum_values' && $request['search']){
if($collection_id) {
$results = $this->metadatum_repository->fetch_all_metadatum_values( $collection_id, $metadatum_id, $request['search'] );
$results = $this->metadatum_repository->fetch_all_metadatum_values( $collection_id, $metadatum_id, $request['search'], $offset, $number );
} else {
$results = $this->metadatum_repository->fetch_all_metadatum_values( null, $metadatum_id, $request['search']);
$results = $this->metadatum_repository->fetch_all_metadatum_values( null, $metadatum_id, $request['search'], $offset, $number);
}
return new \WP_REST_Response($results, 200);
} elseif($request['fetch'] === 'all_metadatum_values') {
if($collection_id) {
$results = $this->metadatum_repository->fetch_all_metadatum_values( $collection_id, $metadatum_id );
$results = $this->metadatum_repository->fetch_all_metadatum_values( $collection_id, $metadatum_id, '', $offset, $number);
} else {
$results = $this->metadatum_repository->fetch_all_metadatum_values( null, $metadatum_id);
$results = $this->metadatum_repository->fetch_all_metadatum_values( null, $metadatum_id, '', $offset, $number);
}
return new \WP_REST_Response($results, 200);

View File

@ -261,6 +261,15 @@ class REST_Terms_Controller extends REST_Controller {
if ( $request['context'] === 'edit' ) {
$item_arr['current_user_can_edit'] = $item->can_edit();
}
$children = get_terms([
'taxonomy' => $item_arr['taxonomy'],
'parent' => $item_arr['id'],
'fields' => 'ids',
'hide_empty' => false,
]);
$item_arr['total_children'] = count($children);
} else {
$attributes_to_filter = $request['fetch_only'];
@ -277,6 +286,7 @@ class REST_Terms_Controller extends REST_Controller {
* @param \WP_REST_Request $request
*
* @return \WP_Error|\WP_REST_Response
* @throws \Exception
*/
public function get_items( $request ) {
$taxonomy_id = $request['taxonomy_id'];

View File

@ -50,13 +50,21 @@ abstract class Background_Process extends \WP_Background_Process {
/**
* Action
*
* (default value: 'background_process')
* (default value: 'process')
*
* @var string
* @access protected
*/
protected $action = 'process';
/**
* Name
*
* @var string
* @access protected
*/
protected $name = 'Background Process';
/**
* Initiate new background process
*/
@ -64,11 +72,35 @@ abstract class Background_Process extends \WP_Background_Process {
parent::__construct();
global $wpdb;
$this->table = $wpdb->prefix . 'tnc_bg_process';
$this->set_name( __('Background Process', 'tainacan') );
}
public function get_id() {
return $this->ID;
}
/**
* Gets the name of the process.
*
* Override this method to set a name to the process
*
* Default "Background Process"
*
* @return string
*/
public function get_name() {
return $this->name;
}
/**
* Set name
*
* @return $this
*/
public function set_name($name) {
$this->name = $name;
return $this;
}
/**
@ -87,6 +119,7 @@ abstract class Background_Process extends \WP_Background_Process {
'user_id' => get_current_user_id(),
'priority' => $priority,
'action' => $this->action,
'name' => $this->get_name(),
'queued_on' => date('Y-m-d H:i:s')
]
);
@ -221,33 +254,35 @@ abstract class Background_Process extends \WP_Background_Process {
// while we are debugging performance
$newRequest = true;
do {
$batch = $this->get_batch();
$batch = $this->get_batch();
if ($newRequest) {
$this->write_log($batch->key, ['New Request']);
$newRequest = false;
}
// TODO: find a way to catch and log PHP errors as
if ($newRequest) {
$this->write_log($batch->key, ['New Request']);
$newRequest = false;
}
// TODO: find a way to catch and log PHP errors as
$task = $batch;
do {
try {
$task = $this->task( $batch );
$task = $this->task( $task );
} catch (\Exception $e) {
// TODO: Add Stacktrace
$this->write_error_log($batch->key, ['Fatal Error: ' . $e->getMessage()]);
$this->write_error_log($batch->key, ['Process aborted']);
$task = false;
}
} while ( false !== $task && ! $this->time_exceeded() && ! $this->memory_exceeded() );
// Update or close current batch.
if ( false !== $task ) {
$this->update( $batch->key, $task );
} else {
$this->close( $batch->key );
}
} while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty() );
if ( false !== $task ) {
$this->update( $batch->key, $task );
} else {
$this->close( $batch->key );
}
$this->unlock_process();
@ -356,5 +391,5 @@ abstract class Background_Process extends \WP_Background_Process {
return $return;
}
}

View File

@ -75,14 +75,14 @@ class Bulk_Edit {
add_filter('posts_pre_query', '__return_empty_array');
// this adds the meta key and meta value to the SELECT query so it can be used directly in the INSERT below
add_filter('posts_fields_request', [&$this, 'add_fields_to_query'], 10, 2);
add_filter('posts_fields_request', [$this, 'add_fields_to_query'], 10, 2);
$itemsRepo = Repositories\Items::get_instance();
$params['query']['fields'] = 'ids';
$items_query = $itemsRepo->fetch($params['query'], $params['collection_id']);
remove_filter('posts_pre_query', '__return_empty_array');
remove_filter('posts_fields_request', [&$this, 'add_fields_to_query']);
remove_filter('posts_fields_request', [$this, 'add_fields_to_query']);
$wpdb->query( "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) {$items_query->request}" );
@ -261,6 +261,73 @@ class Bulk_Edit {
}
public function trash_items() {
if (!$this->get_id()) {
return new \WP_Error( 'no_id', __( 'Bulk Edit group not initialized', 'tainacan' ) );
}
global $wpdb;
$select_q = $this->_build_select( 'post_id' );
$select_insert = "SELECT ID, '_wp_trash_meta_status', post_status FROM $wpdb->posts WHERE ID IN ($select_q)";
$select_insert_time = $wpdb->prepare("SELECT ID, '_wp_trash_meta_time', %s FROM $wpdb->posts WHERE ID IN ($select_q)", time());
$query_original_status = "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) $select_insert";
$query_trash_time = "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) $select_insert_time";
$wpdb->query($query_original_status);
$wpdb->query($query_trash_time);
$query = "UPDATE $wpdb->posts SET post_status = 'trash' WHERE ID IN ($select_q)";
// TODO trash comments?
return $wpdb->query($query);
}
public function untrash_items() {
if (!$this->get_id()) {
return new \WP_Error( 'no_id', __( 'Bulk Edit group not initialized', 'tainacan' ) );
}
global $wpdb;
$select_q = $this->_build_select( 'post_id' );
// restore status
$query_restore = "UPDATE $wpdb->posts SET post_status = (SELECT meta_value FROM $wpdb->postmeta WHERE meta_key = '_wp_trash_meta_status' AND post_id = ID) WHERE ID IN ($select_q) AND post_status = 'trash'";
$query_delete_meta1 = "DELETE FROM $wpdb->postmeta WHERE meta_key = '_wp_trash_meta_status' AND post_id IN ( SELECT implicitTemp.post_id FROM ($select_q) implicitTemp )";
$query_delete_meta2 = "DELETE FROM $wpdb->postmeta WHERE meta_key = '_wp_trash_meta_time' AND post_id IN ( SELECT implicitTemp.post_id FROM ($select_q) implicitTemp )";
$affected = $wpdb->query( $query_restore );
$wpdb->query( $query_delete_meta1 );
$wpdb->query( $query_delete_meta2 );
// TODO untrash comments?
return $affected;
}
public function delete_items() {
if (!$this->get_id()) {
return new \WP_Error( 'no_id', __( 'Bulk Edit group not initialized', 'tainacan' ) );
}
global $wpdb;
$select_q = $this->_build_select( 'post_id' );
$query_delete = "DELETE FROM $wpdb->posts WHERE ID IN ($select_q)";
return $wpdb->query($query_delete);
}
/**
* Adds a value to the current group of items

View File

@ -0,0 +1,87 @@
<?php
/**
* This class implements the integration of Tainacan with ElasticPress, a WordPress plugin that connects your WordPress installation with Elastic Search
*
* https://github.com/10up/ElasticPress
* https://www.elasticpress.io/
*
*
*/
namespace Tainacan;
class Elastic_Press {
function __construct($ajax_query=false) {
add_action('init', [$this, 'init']);
}
function init() {
if (!class_exists('EP_API')) {
return; // ElasticPress not active
}
add_filter('tainacan_fetch_args', [$this, 'filter_args'], 10, 2);
}
function filter_args($args, $type) {
if ($type == 'items') {
$args['ep_integrate'] = true;
$args = $this->add_items_args($args);
}
return $args;
}
private function add_items_args($args) {
$Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance();
$Tainacan_Metadata = \Tainacan\Repositories\Metadata::get_instance();
if (is_array($args['post_type']) && isset($args['s']) && !empty($args['s'])) {
$meta_ids = [];
$taxonomies = [];
foreach ( $args['post_type'] as $cpt ) {
$col = $Tainacan_Collections->fetch_by_db_identifier($cpt);
$taxonomies = array_merge( $taxonomies, get_object_taxonomies($cpt) );
if ($col) {
$metadata = $Tainacan_Metadata->fetch_by_collection($col, ['posts_per_page' => -1], 'OBJECT');
foreach ($metadata as $meta) {
$meta_ids[] = $meta->get_id();
}
}
}
$search_fields = [
'post_title',
'post_content',
'post_excerpt'
];
if (!empty($meta_ids)) {
$search_fields['meta'] = array_unique($meta_ids);
}
if (!empty($taxonomies)) {
$search_fields['taxonomies'] = array_unique($taxonomies);
}
$args['search_fields'] = $search_fields;
}
return $args;
}
} // END

View File

@ -43,6 +43,23 @@ class Media {
return $this->insert_attachment_from_blob($response['body'], basename($url), $post_id);
}
/**
* Insert an attachment from a local file.
*
* @param String $filename The path to the file
* @param Int $post_id (optional) the post this attachement should be attached to. empty for none
* @return Int|false Attachment ID. False on failure
*/
public function insert_attachment_from_file($filename, $post_id = null) {
if( !file_exists($filename) ) {
return false;
}
return $this->insert_attachment_from_blob(file_get_contents($filename), basename($filename), $post_id);
}
/**
* Insert an attachment from an URL address.

View File

@ -0,0 +1,434 @@
<?php
/**
* This class implements the default Tainacan Search engine.
*
* It replaces the default WordPress behavior, which is search only in the title and content of posts, and searches every item metadata.
*
* This is a very basic and non-performatic approach. For better results, you should try other WordPress plugins for this task. We recommend integration with Elastic Search
*
*
* This class is a modification of the class found in the Search Everything plugin. All credits to the authors
* http://wordpress.org/plugins/search-everything/
* Author: Sovrn, zemanta
* Author URI: http://www.sovrn.com
*
*/
namespace Tainacan;
class Search_Engine {
var $logging = false;
var $options;
var $ajax_request;
private $query_instance;
private $taxonomies = [];
private $relationships = [];
private $is_tainacan_search = false;
private $is_inner_query = false;
function __construct($ajax_query=false) {
$this->ajax_request = $ajax_query ? true : false;
$this->options = [];
if (!defined('TAINACAN_DISABLE_DEFAULT_SEARCH_ENGINE') || TAINACAN_DISABLE_DEFAULT_SEARCH_ENGINE !== true) {
$this->search_hooks();
}
}
function search_hooks() {
add_filter( 'posts_join', array( &$this, 'terms_join' ) );
add_filter( 'posts_join', array( &$this, 'search_metadata_join' ) );
add_filter( 'posts_join', array( &$this, 'relationships_join' ) );
//add_filter( 'posts_where', array( &$this, 'search_attachments' ) );
add_filter( 'posts_join', array( &$this, 'search_authors_join' ) );
add_filter( 'posts_search', array( &$this, 'search_where' ), 10, 2 );
add_filter( 'posts_request', array( &$this, 'distinct' ) );
//add_filter( 'posts_request', array( &$this, 'log_query' ), 10, 2 );
}
// creates the list of search keywords from the 's' parameters.
function get_search_terms() {
global $wpdb;
$s = isset( $this->query_instance->query_vars['s'] ) ? $this->query_instance->query_vars['s'] : '';
$sentence = isset( $this->query_instance->query_vars['sentence'] ) ? $this->query_instance->query_vars['sentence'] : false;
$search_terms = array();
if ( !empty( $s ) ) {
// added slashes screw with quote grouping when done early, so done later
$s = stripslashes( $s );
if ( $sentence ) {
$search_terms = array( $s );
} else {
preg_match_all( '/".*?("|$)|((?<=[\\s",+])|^)[^\\s",+]+/', $s, $matches );
// The method create_function is deprecated in PHP 7.2, then it was changed to anonymous functions
$search_terms = array_filter(array_map(
function($a) {
return trim($a, '\\"\'\\n\\r ');
},
$matches[0]
));
}
}
return $search_terms;
}
function init_tainacan_search_vars() {
if (!$this->query_instance->is_search() || empty($this->query_instance->query_vars['s']) ) {
$this->is_tainacan_search = false;
return;
}
$post_types = $this->query_instance->get('post_type');
$taxonomies = [];
$relationships = [];
if (!$post_types || empty($post_types) || !is_array($post_types)) {
$this->is_tainacan_search = false;
} else {
foreach ($post_types as $pt) {
$pattern = '/^' . \Tainacan\Entities\Collection::$db_identifier_prefix . '(\d+)' . \Tainacan\Entities\Collection::$db_identifier_sufix . '$/';
if ( preg_match_all($pattern, $pt, $matches) ) {
$taxonomies = array_merge( $taxonomies, get_object_taxonomies($pt) );
if (isset($matches[1][0])) {
$this->is_inner_query = true;
$relationships = array_merge( $relationships, \Tainacan\Repositories\Metadata::get_instance()->fetch_ids_by_collection( (int) $matches[1][0], ['metadata_type' => 'Tainacan\Metadata_Types\Relationship'] ) );
$this->is_inner_query = false;
}
$this->is_tainacan_search = true;
} else {
$this->is_tainacan_search = false;
break;
}
}
}
if ( $this->is_tainacan_search ) {
$taxonomies = array_unique($taxonomies);
$relationships = array_unique($relationships);
$this->taxonomies = $taxonomies;
$this->relationships = $relationships;
}
}
// add where clause to the search query
function search_where( $where, $wp_query ) {
if ($this->is_inner_query) {
return $where;
}
$this->query_instance = &$wp_query;
$this->init_tainacan_search_vars();
if ( !$this->is_tainacan_search && !$this->ajax_request)
return $where;
global $wpdb;
$searchQuery = $this->search_default();
$searchQuery .= $this->build_search_categories();
$searchQuery .= $this->build_search_metadata();
$searchQuery .= $this->build_search_relationships();
$searchQuery .= $this->search_authors();
if ( $searchQuery != '' ) {
// lets use _OUR_ query instead of WP's, as we have posts already included in our query as well(assuming it's not empty which we check for)
$where = " AND ((" . $searchQuery . ")) ";
}
return $where;
}
// search for terms in default locations like title and content
// replacing the old search terms seems to be the best way to
// avoid issue with multiple terms
function search_default(){
global $wpdb;
$not_exact = empty($this->query_instance->query_vars['exact']);
$search_sql_query = '';
$seperator = '';
$terms = $this->get_search_terms();
// if it's not a sentance add other terms
$search_sql_query .= '(';
foreach ( $terms as $term ) {
$search_sql_query .= $seperator;
$esc_term = $wpdb->prepare("%s", $not_exact ? "%".$term."%" : $term);
$like_title = "($wpdb->posts.post_title LIKE $esc_term)";
$like_post = "($wpdb->posts.post_content LIKE $esc_term)";
$search_sql_query .= "($like_title OR $like_post)";
$seperator = ' AND ';
}
$search_sql_query .= ')';
return $search_sql_query;
}
//Duplicate fix provided by Tiago.Pocinho
function distinct( $query ) {
global $wpdb;
if ( !empty( $this->query_instance->query_vars['s'] ) ) {
if ( strstr( $query, 'DISTINCT' ) ) {}
else {
$query = str_replace( 'SELECT', 'SELECT DISTINCT', $query );
}
}
return $query;
}
//search attachments
function search_attachments( $where ) {
global $wpdb;
if ( !empty( $this->query_instance->query_vars['s'] ) ) {
$where = str_replace( '"', '\'', $where );
if ( !$this->wp_ver28 ) {
$where = str_replace( " AND (post_status = 'publish'", " AND (post_status = 'publish' OR post_type = 'attachment'", $where );
$where = str_replace( "AND post_type != 'attachment'", "", $where );
}
else {
$where = str_replace( " AND ($wpdb->posts.post_status = 'publish'", " AND ($wpdb->posts.post_status = 'publish' OR $wpdb->posts.post_type = 'attachment'", $where );
$where = str_replace( "AND $wpdb->posts.post_type != 'attachment'", "", $where );
}
}
return $where;
}
// Build the author search
function search_authors() {
global $wpdb;
$s = $this->query_instance->query_vars['s'];
$search_terms = $this->get_search_terms();
$exact = ( isset( $this->query_instance->query_vars['exact'] ) && $this->query_instance->query_vars['exact'] ) ? true : false;
$search = '';
$searchand = '';
if ( !empty( $search_terms ) ) {
// Building search query
foreach ( $search_terms as $term ) {
$term = $wpdb->prepare("%s", $exact ? $term : "%$term%");
$search .= "{$searchand}(u.display_name LIKE $term)";
$searchand = ' OR ';
}
$sentence_term = $wpdb->prepare("%s", $s);
if ( count( $search_terms ) > 1 && $search_terms[0] != $sentence_term ) {
$search .= " OR (u.display_name LIKE $sentence_term)";
}
if ( !empty( $search ) )
$search = " OR ({$search}) ";
}
return $search;
}
function build_search_relationships(){
if ( empty( $this->relationships ) ) {
return '';
}
global $wpdb;
$s = $this->query_instance->query_vars['s'];
$search_terms = $this->get_search_terms();
$exact = ( isset( $this->query_instance->query_vars['exact'] ) && $this->query_instance->query_vars['exact'] ) ? true : false;
$search = '';
if ( !empty( $search_terms ) ) {
// Building search query
$searchand = '';
foreach ( $search_terms as $term ) {
$term = $wpdb->prepare("%s", $exact ? $term : "%$term%");
$search .= "{$searchand}(p2.post_title LIKE $term)";
$searchand = ' AND ';
}
$sentence_term = $wpdb->prepare("%s", $s);
if ( count( $search_terms ) > 1 && $search_terms[0] != $sentence_term ) {
$search = "($search) OR (p2.post_title LIKE $sentence_term)";
}
if ( !empty( $search ) )
$search = " OR ({$search}) ";
}
return $search;
}
// create the search meta data query
function build_search_metadata() {
global $wpdb;
$s = $this->query_instance->query_vars['s'];
$search_terms = $this->get_search_terms();
$exact = ( isset( $this->query_instance->query_vars['exact'] ) && $this->query_instance->query_vars['exact'] ) ? true : false;
$search = '';
if ( !empty( $search_terms ) ) {
// Building search query
$searchand = '';
foreach ( $search_terms as $term ) {
$term = $wpdb->prepare("%s", $exact ? $term : "%$term%");
$search .= "{$searchand}(m.meta_value LIKE $term)";
$searchand = ' AND ';
}
$sentence_term = $wpdb->prepare("%s", $s);
if ( count( $search_terms ) > 1 && $search_terms[0] != $sentence_term ) {
$search = "($search) OR (m.meta_value LIKE $sentence_term)";
}
if ( !empty( $search ) )
$search = " OR ({$search}) ";
}
return $search;
}
// create the search categories query
function build_search_categories() {
global $wpdb;
$vars = $this->query_instance->query_vars;
if (empty($this->taxonomies)) {
return '';
}
$s = $vars['s'];
$search_terms = $this->get_search_terms();
$exact = isset( $vars['exact'] ) ? $vars['exact'] : '';
$search = '';
if ( !empty( $search_terms ) ) {
// Building search query for categories slug.
$searchand = '';
$searchSlug = '';
foreach ( $search_terms as $term ) {
$term = $wpdb->prepare("%s", $exact ? $term : "%". sanitize_title_with_dashes($term) . "%");
$searchSlug .= "{$searchand}(tter.slug LIKE $term)";
$searchand = ' AND ';
}
$term = $wpdb->prepare("%s", $exact ? $term : "%". sanitize_title_with_dashes($s) . "%");
if ( count( $search_terms ) > 1 && $search_terms[0] != $s ) {
$searchSlug = "($searchSlug) OR (tter.slug LIKE $term)";
}
if ( !empty( $searchSlug ) )
$search = " OR ({$searchSlug}) ";
// Building search query for categories description.
$searchand = '';
$searchDesc = '';
foreach ( $search_terms as $term ) {
$term = $wpdb->prepare("%s", $exact ? $term : "%$term%");
$searchDesc .= "{$searchand}(ttax.description LIKE $term)";
$searchand = ' AND ';
}
$sentence_term = $wpdb->prepare("%s", $s);
if ( count( $search_terms ) > 1 && $search_terms[0] != $sentence_term ) {
$searchDesc = "($searchDesc) OR (ttax.description LIKE $sentence_term)";
}
if ( !empty( $searchDesc ) )
$search = $search." OR ({$searchDesc}) ";
}
return $search;
}
//join for searching authors
function search_authors_join( $join ) {
if ($this->is_inner_query) {
return $join;
}
global $wpdb;
if ( $this->is_tainacan_search ) {
$join .= " LEFT JOIN $wpdb->users AS u ON ($wpdb->posts.post_author = u.ID) ";
}
return $join;
}
//join for searching metadata
function search_metadata_join( $join ) {
if ($this->is_inner_query) {
return $join;
}
global $wpdb;
if ( $this->is_tainacan_search ) {
$join .= " LEFT JOIN $wpdb->postmeta AS m ON ($wpdb->posts.ID = m.post_id) ";
}
return $join;
}
// join for relationship metadata
function relationships_join( $join ) {
if ($this->is_inner_query) {
return $join;
}
global $wpdb;
if ( $this->is_tainacan_search && !empty( $this->relationships ) ) {
$relationships = implode(',', $this->relationships);
$join .= " LEFT JOIN $wpdb->posts AS p2 ON (m.meta_value = p2.ID AND meta_key IN ($relationships)) ";
}
return $join;
}
//join for searching tags
function terms_join( $join ) {
if ($this->is_inner_query) {
return $join;
}
global $wpdb;
if ( $this->is_tainacan_search && !empty( $this->taxonomies ) ) {
foreach ( $this->taxonomies as $taxonomy ) {
$on[] = "ttax.taxonomy = '" . addslashes( $taxonomy )."'";
}
// build our final string
$on = ' ( ' . implode( ' OR ', $on ) . ' ) ';
$join .= " LEFT JOIN $wpdb->term_relationships AS trel ON ($wpdb->posts.ID = trel.object_id) LEFT JOIN $wpdb->term_taxonomy AS ttax ON ( " . $on . " AND trel.term_taxonomy_id = ttax.term_taxonomy_id) LEFT JOIN $wpdb->terms AS tter ON (ttax.term_id = tter.term_id) ";
}
return $join;
}
} // END

View File

@ -462,15 +462,8 @@ class Collection extends Entity {
function get_core_metadata() {
$repo = \Tainacan\Repositories\Metadata::get_instance();
return $repo->fetch_by_collection($this, [
'meta_query' => [
[
'key' => 'metadata_type',
'value' => ['Tainacan\Metadata_Types\Core_Title', 'Tainacan\Metadata_Types\Core_Description'],
'compare' => 'IN'
]
]
], 'OBJECT');
return $repo->get_core_metadata($this);
}
/**
@ -481,20 +474,7 @@ class Collection extends Entity {
function get_core_title_metadatum() {
$repo = \Tainacan\Repositories\Metadata::get_instance();
$results = $repo->fetch_by_collection($this, [
'meta_query' => [
[
'key' => 'metadata_type',
'value' => 'Tainacan\Metadata_Types\Core_Title',
]
],
'posts_per_page' => 1
], 'OBJECT');
if (is_array($results) && sizeof($results) == 1 && $results[0] instanceof \Tainacan\Entities\Metadatum) {
return $results[0];
}
return false;
return $repo->get_core_title_metadatum($this);
}
/**
@ -505,20 +485,7 @@ class Collection extends Entity {
function get_core_description_metadatum() {
$repo = \Tainacan\Repositories\Metadata::get_instance();
$results = $repo->fetch_by_collection($this, [
'meta_query' => [
[
'key' => 'metadata_type',
'value' => 'Tainacan\Metadata_Types\Core_Description',
]
],
'posts_per_page' => 1
], 'OBJECT');
if (is_array($results) && sizeof($results) == 1 && $results[0] instanceof \Tainacan\Entities\Metadatum) {
return $results[0];
}
return false;
return $repo->get_core_description_metadatum($this);
}
/**

View File

@ -16,6 +16,7 @@ class Filter extends Entity {
$order,
$color,
$metadatum,
$max_options,
$filter_type,
$filter_type_options;
@ -82,6 +83,23 @@ class Filter extends Entity {
return $this->get_mapped_property('color');
}
/**
* Return max number of options to be showed
* @return mixed|null
*/
function get_max_options(){
return $this->get_mapped_property('max_options');
}
/**
* Set max number of options to be showed
*
* @param $max_options
*/
function set_max_options($max_options){
$this->set_mapped_property('max_options', $max_options);
}
/**
* Return the metadatum
*

View File

@ -551,11 +551,12 @@ class Item extends Entity {
$post__not_in = [];
$post__name_in = [];
if (is_array($args['metadata__in'])) {
$post__in[] = -1; // If metadata__in is an empty array, this forces empty result
foreach ($args['metadata__in'] as $meta) {
if (is_string($meta)) {
$post__name_in[] = $meta;
} elseif (is_integer($meta)) {
if (is_numeric($meta)) {
$post__in[] = $meta;
} elseif (is_string($meta)) {
$post__name_in[] = $meta;
}
}
}

View File

@ -210,6 +210,15 @@ class Metadatum extends Entity {
public function get_exposer_mapping() {
return $this->get_mapped_property('exposer_mapping');
}
/**
* Return the semantic_uri
*
* @return string
*/
function get_semantic_uri(){
return $this->get_mapped_property('semantic_uri');
}
/**
* Set the metadatum name
@ -361,7 +370,16 @@ class Metadatum extends Entity {
public function set_exposer_mapping( $value ) {
$this->set_mapped_property('exposer_mapping', $value);
}
/**
* Set Semantic URI for the metadatum
*
* @param [string] $value
* @return void
*/
function set_semantic_uri( $value ){
$this->set_mapped_property('semantic_uri', $value);
}
/**
* Transient property used to store the status of the metadatum for a particular collection

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