diff --git a/.babelrc b/.babelrc
index 65b4a2cb8..1622c6b29 100644
--- a/.babelrc
+++ b/.babelrc
@@ -4,6 +4,7 @@
{
"modules": false
}
- ]
+ ],
+ "@babel/react"
]
}
\ No newline at end of file
diff --git a/build.sh b/build.sh
index fdff82b00..81e916207 100755
--- a/build.sh
+++ b/build.sh
@@ -13,12 +13,12 @@ current_OS=`uname`
# For macOS (Darwin)
if [ $current_OS == "Darwin" ]; then
find src ./webpack.config.js -type f \( -name "*.js" -or -name "*.vue" -or -name "webpack.config.js" \) -exec md5 {} \; | sort -k 2 | md5 > last-js-build.md5
- find ./src/scss/ ./src/admin/scss/ -type f \( -name "*.scss" \) -exec md5 {} \; | sort -k 2 | md5 > last-sass-build.md5
+ find ./src/scss/ ./src/admin/scss/ ./src/gutenberg-blocks -type f \( -name "*.scss" \) -exec md5 {} \; | sort -k 2 | md5 > last-sass-build.md5
find ./composer.json -type f \( -name "composer.json" \) -exec md5 {} \; | sort -k 2 | md5 > last-composer-build.md5
find ./package.json -type f \( -name "package.json" -or -name "package-lock.json" \) -exec md5 {} \; | sort -k 2 | md5 > last-package-build.md5
else
find src ./webpack.config.js -type f \( -name "*.js" -or -name "*.vue" -or -name "webpack.config.js" \) -exec md5sum {} \; | sort -k 2 | md5sum > last-js-build.md5
- find ./src/scss/ ./src/admin/scss/ -type f \( -name "*.scss" \) -exec md5sum {} \; | sort -k 2 | md5sum > last-sass-build.md5
+ find ./src/scss/ ./src/admin/scss/ ./src/gutenberg-blocks -type f \( -name "*.scss" \) -exec md5sum {} \; | sort -k 2 | md5sum > last-sass-build.md5
find ./composer.json -type f \( -name "composer.json" \) -exec md5sum {} \; | sort -k 2 | md5sum > last-composer-build.md5
find ./package.json -type f \( -name "package.json" -or -name "package-lock.json" \) -exec md5sum {} \; | sort -k 2 | md5sum > last-package-build.md5
fi
diff --git a/compile-sass.sh b/compile-sass.sh
index 33ba72987..b8c475440 100644
--- a/compile-sass.sh
+++ b/compile-sass.sh
@@ -8,13 +8,12 @@ command -v sass >/dev/null 2>&1 || {
# Define o caminho.
echo "Compilando Sass..."
-cd src/scss
-
-sass -E 'UTF-8' --cache-location ../../.tmp/sass-cache-1 tainacan-embeds.scss:../assets/css/tainacan-embeds.css
-cd ../admin/scss
-sass -E 'UTF-8' --cache-location ../../../.tmp/sass-cache-2 tainacan-admin.scss:../../assets/css/tainacan-admin.css
+sass -E 'UTF-8' --cache-location .tmp/sass-cache-1 src/scss/tainacan-embeds.scss:src/assets/css/tainacan-embeds.css
+sass -E 'UTF-8' --cache-location .tmp/sass-cache-2 src/admin/scss/tainacan-admin.scss:src/assets/css/tainacan-admin.css
+
+sass -E 'UTF-8' --cache-location .tmp/sass-cache-3 src/gutenberg-blocks/gutenberg-blocks-style.scss:src/assets/css/tainacan-gutenberg-blocks-style.css
echo "Compilação do Sass Concluído!"
exit 0
diff --git a/docs/assets/vocabulary-importer-sample.png b/docs/assets/vocabulary-importer-sample.png
new file mode 100644
index 000000000..e805219d2
Binary files /dev/null and b/docs/assets/vocabulary-importer-sample.png differ
diff --git a/docs/csv-importer.md b/docs/csv-importer.md
new file mode 100644
index 000000000..c3d348bf5
--- /dev/null
+++ b/docs/csv-importer.md
@@ -0,0 +1,100 @@
+# CSV Importer
+
+The CSV importer allows user to import items to a collection from a CSV (comma separated values) file.
+
+The input file is a standard CSV file, where each line will hold one item information, and each column will hold the value for one specific metadata. Also, the first line brings the column titles.
+
+When the user starts the importer process, he/she must choose the right file encoding the CSV was saved in (usually UTF-8), the column separator and the cell enclosure. All this options are set when the user generates the CSV file using a spreadsheet editor.
+
+In this section user will also inform the character (or characters) used to separate values in a multi-valued cell.
+
+After configuring the importer and choosing the target collection, the CSV file is uploaded and the user has the chance to map the columns present in the CSV to the metadata present in the target collection.
+
+If the metadata was not created beforehand, user can create and map metadata in this screen, or choose the "Create metadatum" option in the mapper. If this option is selected, Tainacan will automatically create a metadatum when the importer runs (see "Creating metadata on the fly" section below to learn how to tell tainacan the type and other attributes of the metadatum that will be created).
+
+
+## Special Columns
+
+Each column of the CSV must be mapped to a metadatum in the target collection. However, there are special columns that can be used to set the value for other aspects of the item. For example, the item status can be set to say the item is public to everyone, in draft or private to editors.
+
+The special columns that can be used are:
+
+* **special_item_status** - Inform the item status. Possible values are draft, private or publish.
+* **special_item_id** - Inform the item ID in the Tainacan database. This is useful when re-importing items and let the user decide wether to update existing items or ignore them and only add new items.
+* **special_document** - let the user inform the item document. See "Importing files and attachments"
+* **special_attachments** - let the user inform the attachments. See "Importing files and attachments"
+
+
+## Importing files and attachments
+
+If you also have files you want to import, that are related to the items in your CSV, you can use some special columns in your csv to do so.
+
+There are two special columns you can use: `special_document`, which will set the Document of your item, and `special_attachments` to add one or many attachments.
+
+The values for the special_document must be prepended with 'url:'', 'file:'' or 'text:'. This will indicate the Document Type.
+
+Example:
+
+```
+name, special_document
+An image,file:http://example.com/image.jpg
+A youtube video,url:http://youtube.com/?w=123456
+A text,text:This is a sample text
+```
+
+The values for the special_attachments is just a list of files. If you want to add many attachments, use the separator you set in the Multivalued Delimiter option.
+
+In either case, you can point to a file using a full URL, or just a file name. In this last case, you should set the option below to tell Tainacan where to find the files in your server. You can then upload them directly (via FTP for example) and tainacan will add them to your items.
+
+Example:
+
+```
+name, special_attachments
+An image,http://example.com/image.jpg
+Many images,http://example.com/image.jpg||http://example.com/image2.jpg||http://example.com/image3.jpg
+Images uploaded via FTP,myfolder/image.jpg||myfolder/image2.jpg
+```
+
+## Creating metadata on the fly
+
+When the user maps the columns found in the CSV file to the metadata present in the collection, he/she has can choose the "Create metadatum" option, so the importer will automatically create the metadata as it process the file.
+
+By default, it will create a public text metadatum, but you can inform tainacan the type and other features of the metadata in the header of the CSV.
+
+In the first line, where you declare the name of each column, you can add some information that will be used by the importer to create the metadatum_id.
+
+Each information about the metadatum will be separated by a pipe "|" character.
+
+The first information must be the metadata name, and the second, the metadata type.
+
+For example:
+
+```
+Name,Subject|taxonomy,Date of creation|date
+```
+
+The natively supported types right now are:
+
+* text
+* textarea
+* taxonomy - when this type is used, a new taxonomy will be created
+* date - Values must be informed in YYYY-MM-DD format
+* numeric
+* relationship - Values must be the ID of the related item
+
+After the type, you can use keywords to inform other features:
+
+* multiple - can have multiple values
+* required - is required
+* display_yes - display in lists: yes
+* display_no - display in lists: not by default
+* display_never - display in lists: never
+* status_public - visible to everyone
+* status_private - visible only to editors
+* collection_key_yes - set this meta as a collection key (there cannot be two items with the same value).
+
+Examples combining multiple features:
+
+```
+Name,Subject|taxonomy|multiple|required,Internal code|numeric|required|collection_key_yes|status_private
+```
diff --git a/docs/faceted-search.md b/docs/faceted-search.md
new file mode 100644
index 000000000..fb0fd0c3b
--- /dev/null
+++ b/docs/faceted-search.md
@@ -0,0 +1,21 @@
+# Faceted Search
+
+Tainacan implements a faceted search for your collections.
+
+Filters are displayed in the left side of the screen and allow users to filter the results.
+
+By default, tainacan will filter the available values in each facet depending on the current filters selected. It means it will only display values that will bring at least one item in the results. Everytime the user selects on value from one filter, all the other values from all other filters are reduced. This helps users to refine their filters.
+
+If you want to disable this behavior, and always display all possible values for a filter, even if there is no items that will meet the criteria, add this to you `wp-config.php`:
+
+```
+define('TAINACAN_FACETS_DISABLE_FILTER_ITEMS', true);
+```
+
+Tainacan will also add the number of items found for each value of each filter. This, when used without a Elastic Search* integration, might have performance issues. So if you want to remove the items count from the filters, add this to your `wp-config.php`:
+
+```
+define('TAINACAN_FACETS_DISABLE_COUNT_ITEMS', true);
+```
+
+\* Note: Elastic Search integration for this feature is still under development
\ No newline at end of file
diff --git a/docs/release.md b/docs/release.md
index 0a13247ac..06fca2650 100644
--- a/docs/release.md
+++ b/docs/release.md
@@ -21,7 +21,7 @@ git pull
### Edit version numbers
-Edit `src/readme.txt` and 'src/tainacan.php' and change the version numbers to `$NEW_VERSION`.
+Edit `src/readme.txt` and `src/tainacan.php` and change the version numbers to `$NEW_VERSION`.
### Set build to production mode
@@ -38,7 +38,7 @@ git commit -am "Releasing verion $NEW_VERSION"
```
./build.sh
cd $BUILD_PATH
-rm admin/scss/.sass-cache
+rm -r admin/scss/.sass-cache
```
### Prepare SVN repo
@@ -106,6 +106,6 @@ git push --tags
### Set build back to development mode
-Once you go back to develop branch, remember editing `webpack.config.js` to set production mode.
+Once you go back to develop branch, remember editing `webpack.config.js` to set production mode to false.
diff --git a/docs/search-engine.md b/docs/search-engine.md
index 832abc890..cd4d7a630 100644
--- a/docs/search-engine.md
+++ b/docs/search-engine.md
@@ -1,6 +1,6 @@
# Search engine
-In addition to the faceted search, which allows users to filter items by specific metadata, Tainacan also offers a free textual search.
+In addition to the [faceted search](faceted-search.md), which allows users to filter items by specific metadata, Tainacan also offers a free textual search.
By default, when using this option to search, WordPress searches only inside the Title (post_title) and Description (post_content). This, of course, is very limited, and this article presents and discusses the approach Tainacan will take to face this issue.
@@ -8,18 +8,18 @@ There is'nt one silver bullet to solve this problem. In some cases, perhaps for
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 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.
+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](https://wordpress.org/plugins/search-everything/)" plugin.
+
+This approach might slow down search queries, specially the open keyword search input.
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);
```
+Our efforts right now are to improve the compatibility with [ElasticPress](https://wordpress.org/plugins/elasticpress/) plugin. Its already working for searches and most parts of the plugin. We are now starting to make it work to build the facets.
-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.
+Our understanding is that, if a reposiory gets too big, it might need a more robust infrastructure and Elastic Search is our call. Therefore we are working to better integrate it with the ElasticPress plugin.
-* [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.
+However, 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. So feel free to try other search plugins for WordPress and please let us know how well they work!
diff --git a/docs/vocabulary-importer.md b/docs/vocabulary-importer.md
new file mode 100644
index 000000000..679bd4f7e
--- /dev/null
+++ b/docs/vocabulary-importer.md
@@ -0,0 +1,35 @@
+# Vocabulary Importer
+
+This importer allows user to add terms to a given taxonomy. It's useful to import controlled vocabularies to a Tainacan installation.
+
+The file format used to import vocabularies is a CSV - comma separated values. Each line of the file will represent one term.
+
+For each term, you can inform the name of the term and it's definition.
+
+For example:
+
+```
+Term 1,Definition of term 1
+Term 2,Definition of term 2
+Term 3,Definition of term 3
+```
+
+It's also possible to inform hierarchy. You do so by leaving empty cells to the left, indicating the level in the hierarchy the term is in.
+
+Your spreadsheet will look like this:
+
+![Vocabulary spreadsheet](assets/vocabulary-importer-sample.png)
+
+This same spreadsheet, saved in CSV format, will look like this:
+
+```
+Term 1,Definition of term 1,,
+Term 2,Definition of term 2,,
+,1st Child of term 2,Definition of this term,
+,2nd Child of term 2,Definition of this term,
+,,Gran child,Definition of grand child
+Term 3,Definition of term 3,,
+Term 4,Definition of term 4,,
+```
+
+Once you have your CSV ready, fire the Vocabulary CSV Importer, choose the target Taxonomy (or create one), and hit "Run".
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 640ed3d71..1d2f7b809 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -123,6 +123,16 @@
"@babel/types": "^7.0.0"
}
},
+ "@babel/helper-builder-react-jsx": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.0.0.tgz",
+ "integrity": "sha512-ebJ2JM6NAKW0fQEqN8hOLxK84RbRz9OkUhGS/Xd5u56ejMfVbayJ4+LykERZCOUM6faa6Fp3SZNX3fcT16MKHw==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.0.0",
+ "esutils": "^2.0.0"
+ }
+ },
"@babel/helper-call-delegate": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz",
@@ -491,6 +501,15 @@
"@babel/helper-plugin-utils": "^7.0.0"
}
},
+ "@babel/plugin-syntax-jsx": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.0.0.tgz",
+ "integrity": "sha512-PdmL2AoPsCLWxhIr3kG2+F9v4WH06Q3z+NoGVpQgnUNGcagXHq5sB3OXxkSahKq9TLdNMN/AJzFYSOo8UKDMHg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
"@babel/plugin-syntax-object-rest-spread": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0.tgz",
@@ -719,6 +738,46 @@
"@babel/helper-plugin-utils": "^7.0.0"
}
},
+ "@babel/plugin-transform-react-display-name": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.0.0.tgz",
+ "integrity": "sha512-BX8xKuQTO0HzINxT6j/GiCwoJB0AOMs0HmLbEnAvcte8U8rSkNa/eSCAY+l1OA4JnCVq2jw2p6U8QQryy2fTPg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-react-jsx": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.0.0.tgz",
+ "integrity": "sha512-0TMP21hXsSUjIQJmu/r7RiVxeFrXRcMUigbKu0BLegJK9PkYodHstaszcig7zxXfaBji2LYUdtqIkHs+hgYkJQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-builder-react-jsx": "^7.0.0",
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-syntax-jsx": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-react-jsx-self": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.0.0.tgz",
+ "integrity": "sha512-pymy+AK12WO4safW1HmBpwagUQRl9cevNX+82AIAtU1pIdugqcH+nuYP03Ja6B+N4gliAaKWAegIBL/ymALPHA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-syntax-jsx": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-react-jsx-source": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.0.0.tgz",
+ "integrity": "sha512-OSeEpFJEH5dw/TtxTg4nijl4nHBbhqbKL94Xo/Y17WKIf2qJWeIk/QeXACF19lG1vMezkxqruwnTjVizaW7u7w==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-syntax-jsx": "^7.0.0"
+ }
+ },
"@babel/plugin-transform-regenerator": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0.tgz",
@@ -835,6 +894,19 @@
"semver": "^5.3.0"
}
},
+ "@babel/preset-react": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.0.0.tgz",
+ "integrity": "sha512-oayxyPS4Zj+hF6Et11BwuBkmpgT/zMxyuZgFrMeZID6Hdh3dGlk4sHCAhdBCpuCKW2ppBfl2uCCetlrUIJRY3w==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-transform-react-display-name": "^7.0.0",
+ "@babel/plugin-transform-react-jsx": "^7.0.0",
+ "@babel/plugin-transform-react-jsx-self": "^7.0.0",
+ "@babel/plugin-transform-react-jsx-source": "^7.0.0"
+ }
+ },
"@babel/template": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.0.tgz",
@@ -890,6 +962,11 @@
}
}
},
+ "@brainhubeu/react-carousel": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/@brainhubeu/react-carousel/-/react-carousel-1.10.1.tgz",
+ "integrity": "sha512-W8BdG9mWsU9c9F4GKBcQH1R7QiLmn9KELJdCIXop6Fkc6GT9gk7o8SPVfvdBLTQF3h/DpOtJTIUSjtTucIKDMg=="
+ },
"@vue/component-compiler-utils": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-2.2.0.tgz",
@@ -1979,7 +2056,7 @@
},
"camelcase-keys": {
"version": "2.1.0",
- "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
"integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
"requires": {
"camelcase": "^2.0.0",
@@ -5043,7 +5120,7 @@
},
"is-builtin-module": {
"version": "1.0.0",
- "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
"integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
"requires": {
"builtin-modules": "^1.0.0"
@@ -5295,8 +5372,7 @@
"js-tokens": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
- "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
- "dev": true
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
},
"js-yaml": {
"version": "3.12.0",
@@ -5401,7 +5477,7 @@
},
"load-json-file": {
"version": "1.1.0",
- "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
"requires": {
"graceful-fs": "^4.1.2",
@@ -5531,7 +5607,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
- "dev": true,
"requires": {
"js-tokens": "^3.0.0 || ^4.0.0"
}
@@ -5601,13 +5676,22 @@
}
},
"md5.js": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
- "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=",
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+ "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
"dev": true,
"requires": {
"hash-base": "^3.0.0",
- "inherits": "^2.0.1"
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ },
+ "dependencies": {
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ }
}
},
"mdi": {
@@ -5661,7 +5745,7 @@
"dependencies": {
"minimist": {
"version": "1.2.0",
- "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
}
}
@@ -5962,7 +6046,7 @@
"dependencies": {
"semver": {
"version": "5.3.0",
- "resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
"integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
}
}
@@ -6273,7 +6357,7 @@
},
"os-locale": {
"version": "1.4.0",
- "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
"requires": {
"lcid": "^1.0.0"
@@ -6810,6 +6894,15 @@
"integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
"dev": true
},
+ "prop-types": {
+ "version": "15.6.2",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz",
+ "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==",
+ "requires": {
+ "loose-envify": "^1.3.1",
+ "object-assign": "^4.1.1"
+ }
+ },
"proxy-addr": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
@@ -6837,16 +6930,25 @@
"integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ=="
},
"public-encrypt": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz",
- "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==",
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
+ "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
"dev": true,
"requires": {
"bn.js": "^4.1.0",
"browserify-rsa": "^4.0.0",
"create-hash": "^1.1.0",
"parse-asn1": "^5.0.0",
- "randombytes": "^2.0.1"
+ "randombytes": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ },
+ "dependencies": {
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ }
}
},
"pump": {
@@ -6979,6 +7081,28 @@
}
}
},
+ "react": {
+ "version": "16.5.2",
+ "resolved": "https://registry.npmjs.org/react/-/react-16.5.2.tgz",
+ "integrity": "sha512-FDCSVd3DjVTmbEAjUNX6FgfAmQ+ypJfHUsqUJOYNCBUp1h8lqmtC+0mXJ+JjsWx4KAVTkk1vKd1hLQPvEviSuw==",
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.6.2",
+ "schedule": "^0.5.0"
+ }
+ },
+ "react-dom": {
+ "version": "16.5.2",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.5.2.tgz",
+ "integrity": "sha512-RC8LDw8feuZOHVgzEf7f+cxBr/DnKdqp56VU0lAs1f4UfKc4cU8wU4fTq/mgnvynLQo8OtlPC19NUFh/zjZPuA==",
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.6.2",
+ "schedule": "^0.5.0"
+ }
+ },
"read-pkg": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
@@ -7448,10 +7572,18 @@
}
}
},
+ "schedule": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/schedule/-/schedule-0.5.0.tgz",
+ "integrity": "sha512-HUcJicG5Ou8xfR//c2rPT0lPIRR09vVvN81T9fqfVgBmhERUbDEQoYKjpBxbueJnCPpSu2ujXzOnRQt6x9o/jw==",
+ "requires": {
+ "object-assign": "^4.1.1"
+ }
+ },
"schema-utils": {
- "version": "0.4.5",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz",
- "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==",
+ "version": "0.4.7",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
+ "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
"dev": true,
"requires": {
"ajv": "^6.1.0",
@@ -7459,21 +7591,27 @@
},
"dependencies": {
"ajv": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.4.0.tgz",
- "integrity": "sha1-06/3jpJ3VJdx2vAWTP9ISCt1T8Y=",
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz",
+ "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==",
"dev": true,
"requires": {
- "fast-deep-equal": "^1.0.0",
+ "fast-deep-equal": "^2.0.1",
"fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.3.0",
- "uri-js": "^3.0.2"
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
}
},
- "ajv-keywords": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.1.0.tgz",
- "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74=",
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true
}
}
@@ -7889,6 +8027,24 @@
"urix": "^0.1.0"
}
},
+ "source-map-support": {
+ "version": "0.5.9",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz",
+ "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
"source-map-url": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
@@ -8366,6 +8522,153 @@
"inherits": "2"
}
},
+ "terser": {
+ "version": "3.10.2",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-3.10.2.tgz",
+ "integrity": "sha512-+QrFoqBImmsQGB4c/HvaqgZynmbNvNBwoBxuu7fYXtq5EEtlLUzph+WimDj+xMkuqawXPMl2lgCIz81CdXvt+w==",
+ "dev": true,
+ "requires": {
+ "commander": "~2.17.1",
+ "source-map": "~0.6.1",
+ "source-map-support": "~0.5.6"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "terser-webpack-plugin": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.1.0.tgz",
+ "integrity": "sha512-61lV0DSxMAZ8AyZG7/A4a3UPlrbOBo8NIQ4tJzLPAdGOQ+yoNC7l5ijEow27lBAL2humer01KLS6bGIMYQxKoA==",
+ "dev": true,
+ "requires": {
+ "cacache": "^11.0.2",
+ "find-cache-dir": "^2.0.0",
+ "schema-utils": "^1.0.0",
+ "serialize-javascript": "^1.4.0",
+ "source-map": "^0.6.1",
+ "terser": "^3.8.1",
+ "webpack-sources": "^1.1.0",
+ "worker-farm": "^1.5.2"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz",
+ "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+ "dev": true
+ },
+ "find-cache-dir": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz",
+ "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==",
+ "dev": true,
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^1.0.0",
+ "pkg-dir": "^3.0.0"
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz",
+ "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz",
+ "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ },
+ "pkg-dir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+ "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+ "dev": true,
+ "requires": {
+ "find-up": "^3.0.0"
+ }
+ },
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
"text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@@ -8374,7 +8677,7 @@
},
"through": {
"version": "2.3.8",
- "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
"dev": true
},
@@ -8561,167 +8864,6 @@
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
"dev": true
},
- "uglify-js": {
- "version": "3.4.9",
- "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz",
- "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==",
- "dev": true,
- "requires": {
- "commander": "~2.17.1",
- "source-map": "~0.6.1"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
- }
- }
- },
- "uglifyjs-webpack-plugin": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-2.0.1.tgz",
- "integrity": "sha512-1HhCHkOB6wRCcv7htcz1QRPVbWPEY074RP9vzt/X0LF4xXm9l4YGd0qja7z88abDixQlnVwBjXsTBs+Xsn/eeQ==",
- "dev": true,
- "requires": {
- "cacache": "^11.2.0",
- "find-cache-dir": "^2.0.0",
- "schema-utils": "^1.0.0",
- "serialize-javascript": "^1.4.0",
- "source-map": "^0.6.1",
- "uglify-js": "^3.0.0",
- "webpack-sources": "^1.1.0",
- "worker-farm": "^1.5.2"
- },
- "dependencies": {
- "ajv": {
- "version": "6.5.3",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz",
- "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==",
- "dev": true,
- "requires": {
- "fast-deep-equal": "^2.0.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- }
- },
- "fast-deep-equal": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
- "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
- "dev": true
- },
- "find-cache-dir": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz",
- "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==",
- "dev": true,
- "requires": {
- "commondir": "^1.0.1",
- "make-dir": "^1.0.0",
- "pkg-dir": "^3.0.0"
- }
- },
- "find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
- "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "dev": true,
- "requires": {
- "locate-path": "^3.0.0"
- }
- },
- "json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
- },
- "locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
- "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
- "dev": true,
- "requires": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- }
- },
- "p-limit": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz",
- "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==",
- "dev": true,
- "requires": {
- "p-try": "^2.0.0"
- }
- },
- "p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
- "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
- "dev": true,
- "requires": {
- "p-limit": "^2.0.0"
- }
- },
- "p-try": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz",
- "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==",
- "dev": true
- },
- "path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
- "dev": true
- },
- "pkg-dir": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
- "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
- "dev": true,
- "requires": {
- "find-up": "^3.0.0"
- }
- },
- "punycode": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
- "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
- "dev": true
- },
- "schema-utils": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
- "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
- "dev": true,
- "requires": {
- "ajv": "^6.1.0",
- "ajv-errors": "^1.0.0",
- "ajv-keywords": "^3.1.0"
- }
- },
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
- },
- "uri-js": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
- "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
- "dev": true,
- "requires": {
- "punycode": "^2.1.0"
- }
- }
- }
- },
"unicode-canonical-property-names-ecmascript": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
@@ -8862,18 +9004,18 @@
"dev": true
},
"uri-js": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-3.0.2.tgz",
- "integrity": "sha1-+QuFhQf4HepNz7s8TD2/orVX+qo=",
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
"dev": true,
"requires": {
"punycode": "^2.1.0"
},
"dependencies": {
"punycode": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz",
- "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
"dev": true
}
}
@@ -9185,9 +9327,9 @@
}
},
"webpack": {
- "version": "4.20.2",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.20.2.tgz",
- "integrity": "sha512-75WFUMblcWYcocjSLlXCb71QuGyH7egdBZu50FtBGl2Nso8CK3Ej+J7bTZz2FPFq5l6fzCisD9modB7t30ikuA==",
+ "version": "4.22.0",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.22.0.tgz",
+ "integrity": "sha512-2+3EYFqyhPl12buLQ42QPHEEh8BHn3P9ipRvGRHhdfKJ1u9svhZ3QjhIoEdL5SeIhL5gfOZVbBnartYEabkEsg==",
"dev": true,
"requires": {
"@webassemblyjs/ast": "1.7.8",
@@ -9295,12 +9437,6 @@
"once": "^1.3.1"
}
},
- "punycode": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
- "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
- "dev": true
- },
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -9342,15 +9478,6 @@
"worker-farm": "^1.5.2"
}
},
- "uri-js": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
- "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
- "dev": true,
- "requires": {
- "punycode": "^2.1.0"
- }
- },
"webpack-sources": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz",
diff --git a/package.json b/package.json
index c3f2d6290..4ec9038f9 100644
--- a/package.json
+++ b/package.json
@@ -7,6 +7,7 @@
"build": "cross-env NODE_ENV=development webpack --display-error-details --mode development --progress --hide-modules"
},
"dependencies": {
+ "@brainhubeu/react-carousel": "^1.10.1",
"axios": "^0.18.0",
"buefy": "^0.7.0",
"bulma": "^0.7.2",
@@ -14,6 +15,8 @@
"moment": "^2.22.2",
"node-sass": "^4.9.4",
"qs": "^6.5.2",
+ "react": "^16.5.2",
+ "react-dom": "^16.5.2",
"t": "^0.5.1",
"v-tooltip": "^2.0.0-rc.33",
"vue": "^2.5.17",
@@ -27,6 +30,7 @@
"devDependencies": {
"@babel/core": "^7.1.2",
"@babel/preset-env": "^7.1.0",
+ "@babel/preset-react": "^7.0.0",
"autoprefixer": "^9.2.1",
"babel-loader": "^8.0.4",
"cross-env": "^5.2.0",
@@ -43,7 +47,7 @@
"vue-custom-element": "^3.2.6",
"vue-loader": "^15.4.2",
"vue-template-compiler": "^2.5.17",
- "webpack": "^4.20.2",
+ "webpack": "^4.22.0",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.9"
}
diff --git a/src/admin/admin.vue b/src/admin/admin.vue
index f9d323ad7..95a8aaad0 100644
--- a/src/admin/admin.vue
+++ b/src/admin/admin.vue
@@ -2,24 +2,34 @@
-
-
-
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
@@ -113,7 +123,7 @@
top: 192px;
left: 0px;
max-width: 25px;
- height: 20px;
+ height: 25px;
width: 25px;
border: none;
background-color: $blue5;
diff --git a/src/admin/class-tainacan-admin.php b/src/admin/class-tainacan-admin.php
index e4ac9fda4..5a6955a98 100644
--- a/src/admin/class-tainacan-admin.php
+++ b/src/admin/class-tainacan-admin.php
@@ -67,7 +67,8 @@ class Admin {
function add_theme_files() {
global $TAINACAN_BASE_URL;
- wp_enqueue_style( 'style', $TAINACAN_BASE_URL . '/assets/css/fonts/materialdesignicons.css' );
+ // wp_enqueue_style( 'style', $TAINACAN_BASE_URL . '/assets/css/fonts/materialdesignicons.css' );
+ wp_enqueue_style( 'style', $TAINACAN_BASE_URL . '/assets/css/fonts/tainacanicons.css' );
wp_enqueue_script('underscore', includes_url('js') . '/underscore.min.js' );
}
@@ -170,21 +171,22 @@ class Admin {
}
$settings = [
- 'root' => esc_url_raw( rest_url() ) . 'tainacan/v2',
- 'root_wp_api' => esc_url_raw( rest_url() ) . 'wp/v2/',
- 'wp_ajax_url' => admin_url( 'admin-ajax.php' ),
- 'nonce' => wp_create_nonce( 'wp_rest' ),
- 'components' => $components,
- 'i18n' => $tainacan_admin_i18n,
- 'user_caps' => $user_caps,
- 'user_prefs' => $prefs,
- 'base_url' => $TAINACAN_BASE_URL,
- '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,
- 'repository_name' => get_bloginfo('name')
+ 'root' => esc_url_raw( rest_url() ) . 'tainacan/v2',
+ 'root_wp_api' => esc_url_raw( rest_url() ) . 'wp/v2/',
+ 'wp_ajax_url' => admin_url( 'admin-ajax.php' ),
+ 'nonce' => wp_create_nonce( 'wp_rest' ),
+ 'components' => $components,
+ 'i18n' => $tainacan_admin_i18n,
+ 'user_caps' => $user_caps,
+ 'user_prefs' => $prefs,
+ 'base_url' => $TAINACAN_BASE_URL,
+ 'admin_url' => admin_url(),
+ 'theme_collection_list_url' => get_post_type_archive_link( 'tainacan-collection' ),
+ '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,
+ 'repository_name' => get_bloginfo('name')
];
$maps = [
diff --git a/src/admin/components/advanced-search/advanced-search.vue b/src/admin/components/advanced-search/advanced-search.vue
index 45037053e..0f5946baf 100644
--- a/src/admin/components/advanced-search/advanced-search.vue
+++ b/src/admin/components/advanced-search/advanced-search.vue
@@ -11,9 +11,9 @@
v-if="!metadataIsLoading"
class="content has-text-gray has-text-centered">
-
+
+
+
{{ isRepositoryLevel ?
$i18n.get('info_there_are_no_metadata_in_repository_level' ) :
@@ -128,9 +128,9 @@
-
+
+
+
@@ -143,13 +143,11 @@
:class="{'add-link-advanced-search-header': isHeader, 'add-link-advanced-search': !isHeader }"
class="field column is-12">
-
+ @click="addSearchCriteria"
+ style="font-size: 0.75rem;">
+
+
+
{{ searchCriteria.length <= 0 ?
$i18n.get('add_one_search_criterion') :
$i18n.get('add_another_search_criterion')
diff --git a/src/admin/components/bulk-edition/bulk-edition-modal.vue b/src/admin/components/bulk-edition/bulk-edition-modal.vue
index a9df96169..4e2d2cc5e 100644
--- a/src/admin/components/bulk-edition/bulk-edition-modal.vue
+++ b/src/admin/components/bulk-edition/bulk-edition-modal.vue
@@ -173,9 +173,9 @@
v-if="!bulkEditionProcedures[criterion].isDone && !bulkEditionProcedures[criterion].isExecuting"
@click="removeThis(criterion)"
class="button is-white is-pulled-right">
-
+
+
+
-
+
+
+
@@ -210,9 +210,9 @@
animated
multilined
:label="bulkEditionProcedures[criterion].actionResult.constructor.name !== 'Object' && bulkEditionProcedures[criterion].actionResult === 1 ? `${bulkEditionProcedures[criterion].actionResult} ${$i18n.get('info_item_affected')}` : `${bulkEditionProcedures[criterion].actionResult} ${$i18n.get('info_items_affected')}`">
-
+
+
+
@@ -233,9 +233,9 @@
animated
multilined
:label="bulkEditionProcedures[criterion].actionResult.constructor.name === 'Object' ? (bulkEditionProcedures[criterion].actionResult.error_message ? bulkEditionProcedures[criterion].actionResult.error_message : bulkEditionProcedures[criterion].actionResult.message) : ''">
-
+
+
+
@@ -248,14 +248,14 @@
bulkEditionProcedures[criterion].action"
@click="executeBulkEditionProcedure(criterion)"
class="button is-white is-pulled-right">
-
+
+
+
@@ -711,7 +711,7 @@
cursor: not-allowed !important;
}
- .tainacan-loader {
+ .mdi-loader {
-webkit-animation: spin 2s linear infinite; /* Safari */
animation: spin 2s linear infinite;
}
diff --git a/src/admin/components/edition/collection-edition-form.vue b/src/admin/components/edition/collection-edition-form.vue
index 542a12e22..850a6f92e 100644
--- a/src/admin/components/edition/collection-edition-form.vue
+++ b/src/admin/components/edition/collection-edition-form.vue
@@ -28,6 +28,7 @@
@blur="updateSlug"
@focus="clearErrors('name')"/>
+
-
+
+
+
@@ -122,9 +123,9 @@
-
+
+
+
@@ -134,15 +135,17 @@
-
+
+
+
-
+
+
+
@@ -151,11 +154,10 @@
:class="{'disabled': form.enable_cover_page != 'yes'}"
target="_blank"
:href="newPagePath">
-
- {{ $i18n.get('label_create_new_page') }}
+
+
+
+ {{ $i18n.get('label_create_new_page') }}
@@ -176,7 +178,9 @@
position="is-top-right"
type="button">
{{ $i18n.get('label_enabled_view_modes') }}
-
+
+
+
+ class="tainacan-icon tainacan-icon-18px"
+ :class="'tainacan-icon-' + getStatusIcon(statusOption.value)"/>
{{ statusOption.label }}
@@ -290,18 +294,18 @@
id="button-edit-header-image"
:aria-label="$i18n.get('label_button_edit_header_image')"
@click="headerImageMediaFrame.openFrame($event)">
-
+
+
+
@@ -440,11 +444,28 @@
type="button"
@click="cancelBack">{{ $i18n.get('cancel') }}
+
+
+ {{ $i18n.get('label_save_goto_metadata') }}
+
+
+ {{ $i18n.get('label_save_goto_filter') }}
+
{{ $i18n.get('save') }}
+ @click.prevent="onSubmit('items')"
+ class="button is-success">{{ $i18n.get('finish') }}
{{ formErrorMessage }}
@@ -460,7 +481,6 @@
import { mapActions } from 'vuex';
import wpMediaFrames from '../../js/wp-media-frames';
import FileItem from '../other/file-item.vue';
-import EyeIcon from '../other/eye-icon.vue';
import { wpAjax, formHooks } from '../../js/mixins';
export default {
@@ -529,8 +549,7 @@ export default {
}
},
components: {
- FileItem,
- EyeIcon
+ FileItem
},
methods: {
...mapActions('collection', [
@@ -569,7 +588,7 @@ export default {
this.isUpdatingSlug = false;
});
}, 500),
- onSubmit() {
+ onSubmit(goTo) {
this.isLoading = true;
this.form.moderators_ids = [];
@@ -617,8 +636,14 @@ export default {
if (this.fromImporter)
this.$router.go(-1);
- else
- this.$router.push(this.$routerHelper.getCollectionPath(this.collectionId));
+ else {
+ if (goTo == 'metadata')
+ this.$router.push(this.$routerHelper.getCollectionMetadataPath(this.collectionId));
+ else if (goTo == 'filters')
+ this.$router.push(this.$routerHelper.getCollectionFiltersPath(this.collectionId));
+ else
+ this.$router.push(this.$routerHelper.getCollectionPath(this.collectionId));
+ }
})
.catch((errors) => {
for (let error of errors.errors) {
@@ -802,11 +827,11 @@ export default {
},
getStatusIcon(status) {
switch(status) {
- case 'publish': return 'earth';
- case 'private': return 'lock';
- case 'draft': return 'clipboard-text';
+ case 'publish': return 'public';
+ case 'private': return 'private';
+ case 'draft': return 'draft';
case 'trash': return 'delete';
- default: return 'file';
+ default: return 'item';
}
}
},
@@ -934,7 +959,7 @@ export default {
display: inherit;
padding: 0;
margin: 0;
- margin-top: 1px;
+ margin-top: -2px;
font-size: 18px;
}
}
@@ -1010,20 +1035,12 @@ export default {
}
.selected-cover-page-buttons {
float: right;
- padding: 4px 6px;
- .icon { font-size: 20px; }
- .eye-icon {
- position: relative;
- top: 2px;
- }
+ padding: 4px 6px;
&.disabled {
pointer-events: none;
cursor: not-allowed;
.icon { color: $gray2; }
- .eye-icon {
- fill: $gray2 !important;
- }
}
}
.status-radios {
diff --git a/src/admin/components/edition/filter-edition-form.vue b/src/admin/components/edition/filter-edition-form.vue
index d822b559a..bb41a3b6b 100644
--- a/src/admin/components/edition/filter-edition-form.vue
+++ b/src/admin/components/edition/filter-edition-form.vue
@@ -112,10 +112,9 @@
class="button is-white is-pulled-right"
:aria-label="$i18n.getFrom('items','edit_item')"
@click.prevent="showEditMaxOptions = true">
-
+
+
+
-
+
+
+
diff --git a/src/admin/components/edition/importer-edition-form.vue b/src/admin/components/edition/importer-edition-form.vue
index 2d74ed49c..24c244351 100644
--- a/src/admin/components/edition/importer-edition-form.vue
+++ b/src/admin/components/edition/importer-edition-form.vue
@@ -50,11 +50,11 @@
tag="a"
class="is-inline add-link"
:to="{ path: $routerHelper.getNewCollectionPath(), query: { fromImporter: true }}">
-
- {{ $i18n.get('new_blank_collection') }}
+
+
+
+ {{ $i18n.get('new_blank_collection') }}
+
@@ -74,9 +74,9 @@
-
+
+
+
{{ $i18n.get('instruction_drop_file_or_click_to_upload') }}
@@ -90,7 +90,7 @@
target="_blank"
@click.prevent="importerFile = undefined">
-
+
diff --git a/src/admin/components/edition/importer-mapping-form.vue b/src/admin/components/edition/importer-mapping-form.vue
index 5051fc415..273067e9f 100644
--- a/src/admin/components/edition/importer-mapping-form.vue
+++ b/src/admin/components/edition/importer-mapping-form.vue
@@ -59,6 +59,9 @@
{{ $i18n.get('label_select_metadatum') }}
+
+ {{ $i18n.get('label_create_metadatum') }}
+
-
- {{ $i18n.get('label_add_more_metadata') }}
+
+
+
+ {{ $i18n.get('label_add_more_metadata') }}
+
+
{{ $i18n.get('add_items_bulk') }}
+
+ {{ $i18n.get('back') }}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/admin/components/edition/item-edition-form.vue b/src/admin/components/edition/item-edition-form.vue
index 174a202fa..d36324a44 100644
--- a/src/admin/components/edition/item-edition-form.vue
+++ b/src/admin/components/edition/item-edition-form.vue
@@ -7,21 +7,37 @@
-
+
+
+
-
{{ $i18n.get('title_create_item_collection') + ' ' }}{{ collectionName }}
-
{{ $i18n.get('title_edit_item') + ' ' }}{{ (item != null && item != undefined) ? item.title : '' }}
-
- {{ $i18n.get('back') }}
-
+
+ {{ $i18n.get('title_create_item_collection') + ' ' }}
+ {{ collectionName }}
+ {{ $i18n.get(item.status) }}
+
+
+ {{ $i18n.get('title_edit_item') + ' ' }}
+ {{ (item != null && item != undefined) ? item.title : '' }}
+ {{ $i18n.get(item.status) }}
+
+ {{ $i18n.get('back') }}
+
+
+ :name="(isOnSequenceEdit && sequenceRightDirection != undefined) ? (sequenceRightDirection ? 'page-right' : 'page-left') : ''">
@@ -451,7 +482,7 @@
type="button"
class="button sequence-button">
-
+
{{ $i18n.get('previous') }}
@@ -474,9 +505,19 @@
class="button sequence-button">
{{ $i18n.get('next') }}
-
+
+
+
+
+
+ {{ $i18n.get('finish') }}
+
@@ -587,7 +648,7 @@ export default {
isLoading: false,
isMetadataColumnCompressed: false,
metadatumCollapses: [],
- collapseAll: false,
+ collapseAll: true,
visibility: 'publish',
form: {
collectionId: Number,
@@ -649,9 +710,7 @@ export default {
},
watch: {
'$route.params.itemPosition'(newItemPosition, oldItemPosition) {
- if (oldItemPosition == undefined)
- this.sequenceRightDirection;
- else if (oldItemPosition == newItemPosition)
+ if (oldItemPosition == undefined || oldItemPosition == newItemPosition)
this.sequenceRightDirection = undefined;
this.itemPosition = Number(newItemPosition);
@@ -716,6 +775,7 @@ export default {
onSubmit(status) {
// Puts loading on Item edition
this.isLoading = true;
+ this.sequenceRightDirection = undefined;
let previousStatus = this.form.status;
this.form.status = status;
@@ -799,8 +859,9 @@ export default {
// Obtains Item Metadatum
this.fetchMetadata(this.itemId).then((metadata) => {
this.isLoading = false;
- for (let metadatum of metadata) {
- this.metadatumCollapses.push(metadatum.metadatum.required == 'yes');
+ for (let i = 0; i < metadata.length; i++) {
+ this.metadatumCollapses.push(false);
+ this.metadatumCollapses[i] = true;
}
});
},
@@ -1179,6 +1240,16 @@ export default {
flex-shrink: 1;
flex-grow: 1;
}
+ .status-tag {
+ color: white;
+ background: $turquoise5;
+ padding: 0.15rem 0.5rem;
+ font-size: 0.75rem;
+ margin: 0 1rem;
+ font-weight: 600;
+ position: relative;
+ top: -2px;
+ }
a.back-link{
font-weight: 500;
float: right;
@@ -1193,17 +1264,17 @@ export default {
}
.column.is-5-5 {
- width: 45.833333333%;
+ max-width: 55%;
padding-left: $page-side-padding;
padding-right: $page-side-padding;
transition: width 0.6s;
@media screen and (max-width: 769px) {
- width: 100%;
+ max-width: 100%;
}
}
.column.is-4-5 {
- width: 37.5%;
+ max-width: 45%;
padding-left: $page-side-padding;
padding-right: $page-side-padding;
transition: all 0.6s;
@@ -1213,7 +1284,7 @@ export default {
}
@media screen and (max-width: 769px) {
- width: 100%;
+ max-width: 100%;
}
}
@@ -1317,7 +1388,7 @@ export default {
display: inherit;
padding: 0;
margin: 0;
- margin-top: 1px;
+ margin-top: -2px;
font-size: 18px;
}
}
@@ -1369,9 +1440,6 @@ export default {
margin-left: 16px;
margin-right: 6px;
}
- .is-outlined {
- border: none;
- }
}
@keyframes blink {
@@ -1422,10 +1490,6 @@ export default {
background-color: transparent;
color: $turquoise5;
border: none;
-
- .icon {
- margin-top: 0.3rem;
- }
}
}
diff --git a/src/admin/components/edition/item-metadata-bulk-edition-form.vue b/src/admin/components/edition/item-metadata-bulk-edition-form.vue
new file mode 100644
index 000000000..a25f87485
--- /dev/null
+++ b/src/admin/components/edition/item-metadata-bulk-edition-form.vue
@@ -0,0 +1,655 @@
+
+
+
+
+
+
+
diff --git a/src/admin/components/edition/taxonomy-edition-form.vue b/src/admin/components/edition/taxonomy-edition-form.vue
index 8e558ccd9..98468eec2 100644
--- a/src/admin/components/edition/taxonomy-edition-form.vue
+++ b/src/admin/components/edition/taxonomy-edition-form.vue
@@ -89,7 +89,6 @@
-
-
+
{
+ next();
+ }
+ }
+ });
} else {
next();
}
@@ -358,6 +373,9 @@
},
labelNewTerms(){
return ( this.form.allowInsert === 'yes' ) ? this.$i18n.get('label_yes') : this.$i18n.get('label_no');
+ },
+ isEditingTermUpdate (value) {
+ this.isEditinTerm = value;
}
},
mounted(){
@@ -397,5 +415,6 @@
}
}
+
+
+
diff --git a/src/admin/components/lists/collections-list.vue b/src/admin/components/lists/collections-list.vue
index a89460210..e1d303b43 100644
--- a/src/admin/components/lists/collections-list.vue
+++ b/src/admin/components/lists/collections-list.vue
@@ -20,7 +20,9 @@
class="button is-white"
slot="trigger">
{{ $i18n.get('label_bulk_actions') }}
-
+
+
+
-
+ @click.prevent.stop="goToCollectionEditPage(collection.id)">
+
+
+
-
+
+
+
diff --git a/src/admin/components/lists/events-list.vue b/src/admin/components/lists/events-list.vue
index 8f7ad2cb6..11328a488 100644
--- a/src/admin/components/lists/events-list.vue
+++ b/src/admin/components/lists/events-list.vue
@@ -79,8 +79,9 @@
-
-
+
@@ -103,7 +104,9 @@
-
+
+
+
{{ $i18n.get('info_no_events') }}
@@ -113,8 +116,6 @@
-
-
+
\ No newline at end of file
diff --git a/src/admin/components/lists/filters-list.vue b/src/admin/components/lists/filters-list.vue
index 3f52b86f3..42feb1561 100644
--- a/src/admin/components/lists/filters-list.vue
+++ b/src/admin/components/lists/filters-list.vue
@@ -1,7 +1,20 @@
-
+
-
+
+
+ {{ $i18n.get('title_collection_filters_edition') + ' ' }}
+ {{ collectionName }}
+
+
+ {{ $i18n.get('back') }}
+
+
+
{{ $i18n.get('info_repository_filters_inheritance') }}
@@ -11,9 +24,9 @@
class="field is-grouped-centered section">
-
+
+
+
{{ $i18n.get('info_there_is_no_filter' ) }}
{{ $i18n.get('info_create_filters' ) }}
@@ -43,11 +56,13 @@
v-for="(filter, index) in activeFilterList"
:key="index">
-
+
+
+
+ :class="{ 'tainacan-icon-collections has-text-turquoise5': filter.collection_id == collectionId, 'tainacan-icon-repository has-text-blue5': filter.collection_id != collectionId }"
+ class="tainacan-icon" />
-
+
+
+
-
+
+
+
@@ -159,11 +174,13 @@
v-for="(metadatum, index) in availableMetadatumList"
:key="index"
@click.prevent="addMetadatumViaButton(metadatum, index)">
-
+
+
+
+ :class="{ 'tainacan-icon-collections has-text-turquoise5': metadatum.collection_id == collectionId && !isRepositoryLevel, 'tainacan-icon-repository has-text-blue5': isRepositoryLevel || metadatum.collection_id != collectionId }"
+ class="tainacan-icon" />
{{ metadatum.name }}
@@ -174,9 +191,9 @@
class="field is-grouped-centered section">
-
+
+
+
{{ $i18n.get('info_there_is_no_metadatum' ) }}
import { mapActions, mapGetters } from 'vuex';
-import GripIcon from '../other/grip-icon.vue';
import FilterEditionForm from './../edition/filter-edition-form.vue';
import CustomDialog from '../other/custom-dialog.vue';
@@ -204,6 +220,7 @@ export default {
data(){
return {
collectionId: '',
+ collectionName: '',
isRepositoryLevel: false,
isDraggingFromAvailable: false,
isLoadingMetadatumTypes: true,
@@ -234,8 +251,7 @@ export default {
}
},
components: {
- FilterEditionForm,
- GripIcon
+ FilterEditionForm
},
beforeRouteLeave ( to, from, next ) {
let hasUnsavedForms = false;
@@ -282,6 +298,9 @@ export default {
...mapGetters('metadata', [
'getMetadata',
]),
+ ...mapActions('collection', [
+ 'fetchCollectionName'
+ ]),
handleChange($event) {
if ($event.added) {
this.addNewFilter($event.added.element, $event.added.newIndex);
@@ -492,6 +511,13 @@ export default {
.catch(() => {
this.isLoadingFilters = false;
});
+
+
+ // Obtains collection name
+ this.fetchCollectionName(this.collectionId).then((collectionName) => {
+ this.collectionName = collectionName;
+ });
+
}
}
@@ -500,317 +526,353 @@ export default {
@import "../../scss/_variables.scss";
- .loading-spinner {
- animation: spinAround 500ms infinite linear;
- border: 2px solid #dbdbdb;
- border-radius: 290486px;
- border-right-color: transparent;
- border-top-color: transparent;
- content: "";
- display: inline-block;
- height: 1em;
- width: 1em;
- }
+ .filters-list-page {
- .active-filters-area {
- font-size: 14px;
- margin-right: 0.8em;
- margin-left: -0.8em;
- padding-right: 6em;
- min-height: 330px;
+ .tainacan-page-title {
+ margin-bottom: 40px;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: flex-end;
+ justify-content: space-between;
- @media screen and (max-width: 769px) {
- min-height: 45px;
- margin: 0;
- padding-right: 0em;
- }
- @media screen and (max-width: 1216px) {
- padding-right: 1em;
- }
-
- &.filters-area-receive {
- border: 1px dashed gray;
- }
-
- .collapse {
- display: initial;
- }
-
- .active-filter-item {
- background-color: white;
- padding: 0.7em 0.9em;
- margin: 4px;
- min-height: 40px;
- position: relative;
- display: block;
- transition: top 0.1s ease;
- cursor: grab;
-
- form.tainacan-form {
- padding: 1.0em 2.0em;
- margin-top: 1.0em;
- border-top: 1px solid $gray2;
- border-bottom: 1px solid $gray2;
+ h1, h2 {
+ font-size: 20px;
+ font-weight: 500;
+ color: $gray5;
+ display: inline-block;
+ width: 80%;
+ flex-shrink: 1;
+ flex-grow: 1;
}
-
- &>.field, form {
- background-color: white !important;
+ a.back-link{
+ font-weight: 500;
+ float: right;
+ margin-top: 5px;
+ }
+ hr{
+ margin: 3px 0px 4px 0px;
+ height: 1px;
+ background-color: $secondary;
+ width: 100%;
+ }
+ }
+
+ .column:not(.available-metadata-area){
+ overflow: hidden;
+ flex-grow: 2;
+ }
+
+ .loading-spinner {
+ animation: spinAround 500ms infinite linear;
+ border: 2px solid #dbdbdb;
+ border-radius: 290486px;
+ border-right-color: transparent;
+ border-top-color: transparent;
+ content: "";
+ display: inline-block;
+ height: 1em;
+ width: 1em;
+ }
+
+ .active-filters-area {
+ font-size: 14px;
+ margin-right: 0.8em;
+ margin-left: -0.8em;
+ padding-right: 6em;
+ min-height: 330px;
+
+ @media screen and (max-width: 769px) {
+ min-height: 45px;
+ margin: 0;
+ padding-right: 0em;
+ }
+ @media screen and (max-width: 1216px) {
+ padding-right: 1em;
}
- .handle {
- padding-right: 6em;
+ &.filters-area-receive {
+ border: 1px dashed gray;
}
- .grip-icon {
- fill: $gray3;
- top: 1px;
+
+ .collapse {
+ display: initial;
+ }
+
+ .active-filter-item {
+ background-color: white;
+ padding: 0.7em 0.9em;
+ margin: 4px;
+ min-height: 40px;
position: relative;
- }
- .filter-name {
- text-overflow: ellipsis;
- overflow-x: hidden;
- white-space: nowrap;
- font-weight: bold;
- margin-left: 0.4em;
- margin-right: 0.4em;
+ display: block;
+ transition: top 0.1s ease;
+ cursor: grab;
- &.is-danger {
- color: $danger !important;
+ form.tainacan-form {
+ padding: 1.0em 2.0em;
+ margin-top: 1.0em;
+ border-top: 1px solid $gray2;
+ border-bottom: 1px solid $gray2;
}
- }
- .label-details {
- font-weight: normal;
- color: $gray3;
- }
- .not-saved {
- font-style: italic;
- font-weight: bold;
- color: $danger;
- }
- .controls {
- position: absolute;
- right: 5px;
- top: 10px;
- .switch {
- position: relative;
- bottom: 3px;
- }
- .icon {
- bottom: 1px;
- position: relative;
- i, i:before { font-size: 20px; }
- }
- }
-
- &.not-sortable-item, &.not-sortable-item:hover {
- cursor: default;
- background-color: white !important;
-
- .handle .label-details, .handle .icon {
- color: $gray3 !important;
- }
- }
- &.not-focusable-item, &.not-focusable-item:hover {
- cursor: default;
-
- .metadatum-name {
- color: $secondary;
- }
- .handle .label-details, .handle .icon {
- color: $gray3 !important;
- }
- }
- &.disabled-metadatum {
- color: $gray3;
- }
- }
- .active-filter-item:hover:not(.not-sortable-item) {
- background-color: $secondary;
- border-color: $secondary;
- color: white !important;
-
- &>.field, form {
- background-color: white !important;
- }
-
- .grip-icon {
- fill: $white;
- }
-
- .label-details, .icon, .icon-level-identifier>i {
- color: white !important;
- }
-
- .switch.is-small {
- input[type="checkbox"] + .check {
- background-color: $secondary !important;
- border: 1.5px solid white !important;
- &::before { background-color: white !important; }
- }
- input[type="checkbox"]:checked + .check {
- border: 1.5px solid white !important;
- &::before { background-color: white !important; }
- }
- &:hover input[type="checkbox"] + .check {
- border: 1.5px solid white !important;
- background-color: $secondary !important;
- }
- }
- }
- .sortable-ghost {
- border: 1px dashed $gray2;
- display: block;
- padding: 0.7em 0.9em;
- margin: 4px;
- height: 40px;
- position: relative;
-
- .grip-icon {
- fill: $gray3;
- top: 2px;
- position: relative;
- }
- }
- }
-
- .available-metadata-area {
- padding: 10px 0px 10px 10px;
- margin: 0;
- max-width: 280px;
- font-size: 14px;
-
- @media screen and (max-width: 769px) {
- max-width: 100%;
- padding: 10px;
- h3 {
- margin: 1em 0em 1em 0em !important;
- }
- .available-metadatum-item::before,
- .available-metadatum-item::after {
- display: none !important;
- }
- }
-
- h3 {
- margin: 0.2em 0em 1em -1.2em;
- font-weight: 500;
- }
-
- .available-metadatum-item {
- padding: 0.7em;
- margin: 4px;
- background-color: white;
- cursor: pointer;
- left: 0;
- line-height: 1.3em;
- height: 40px;
- position: relative;
- border: 1px solid $gray2;
- border-radius: 1px;
- transition: left 0.2s ease;
- .grip-icon {
- fill: $gray3;
- top: -3px;
- position: relative;
- display: inline-block;
+ &>.field, form {
+ background-color: white !important;
+ }
+
+ .handle {
+ padding-right: 6em;
+ white-space: nowrap;
+ display: flex;
+ }
+ .grip-icon {
+ color: $gray3;
+ position: relative;
+ }
+ .filter-name {
+ text-overflow: ellipsis;
+ overflow-x: hidden;
+ white-space: nowrap;
+ font-weight: bold;
+ margin-left: 0.4em;
+ margin-right: 0.4em;
+
+ &.is-danger {
+ color: $danger !important;
+ }
+ }
+ .label-details {
+ font-weight: normal;
+ color: $gray3;
+ }
+ .not-saved {
+ font-style: italic;
+ font-weight: bold;
+ color: $danger;
+ margin-left: 0.5rem;
+ }
+ .controls {
+ position: absolute;
+ right: 5px;
+ top: 10px;
+ .switch {
+ position: relative;
+ bottom: 3px;
+ }
+ .icon {
+ bottom: 1px;
+ position: relative;
+ i, i:before { font-size: 20px; }
+ }
+ }
+
+ &.not-sortable-item, &.not-sortable-item:hover {
+ cursor: default;
+ background-color: white !important;
+ }
+ &.not-focusable-item, &.not-focusable-item:hover {
+ cursor: default;
+
+ .metadatum-name {
+ color: $secondary;
+ }
+ .handle .label-details, .handle .icon {
+ color: $gray3 !important;
+ }
+ }
+ &.disabled-metadatum {
+ color: $gray3;
+ }
}
- .icon {
- position: relative;
- bottom: 3px;
- }
- .metadatum-name {
- text-overflow: ellipsis;
- overflow-x: hidden;
- white-space: nowrap;
- font-weight: bold;
- margin-left: 0.4em;
- display: inline-block;
- max-width: 180px;
- }
- &:after,
- &:before {
- content: '';
- display: block;
- position: absolute;
- right: 100%;
- width: 0;
- height: 0;
- border-style: solid;
- }
- &:after {
- top: -1px;
- border-color: transparent white transparent transparent;
- border-right-width: 16px;
- border-top-width: 20px;
- border-bottom-width: 20px;
- left: -19px;
- }
- &:before {
- top: -1px;
- border-color: transparent $gray2 transparent transparent;
- border-right-width: 16px;
- border-top-width: 20px;
- border-bottom-width: 20px;
- left: -20px;
- }
- }
- .sortable-drag {
- opacity: 1 !important;
- }
- .available-metadatum-item:not(.disabled-metadatum) {
- &:hover{
+ .active-filter-item:hover:not(.not-sortable-item) {
background-color: $secondary;
border-color: $secondary;
color: white !important;
- position: relative;
- left: -4px;
- &:after {
- border-color: transparent $secondary transparent transparent;
+ &>.field, form {
+ background-color: white !important;
}
- &:before {
- border-color: transparent $secondary transparent transparent;
+
+ .grip-icon {
+ color: $white;
}
- .icon-level-identifier>i {
+
+ .label-details, .icon, .icon-level-identifier>i {
color: white !important;
}
- .grip-icon {
- fill: white !important;
+
+ .switch.is-small {
+ input[type="checkbox"] + .check {
+ background-color: $secondary !important;
+ border: 1.5px solid white !important;
+ &::before { background-color: white !important; }
+ }
+ input[type="checkbox"]:checked + .check {
+ border: 1.5px solid white !important;
+ &::before { background-color: white !important; }
+ }
+ &:hover input[type="checkbox"] + .check {
+ border: 1.5px solid white !important;
+ background-color: $secondary !important;
+ }
+ }
+ }
+ .sortable-ghost {
+ border: 1px dashed $gray2;
+ display: block;
+ padding: 0.7em 0.9em;
+ margin: 4px;
+ height: 40px;
+ position: relative;
+
+ .grip-icon {
+ color: $gray3;
+ top: 2px;
+ position: relative;
}
}
}
- }
- .inherited-filter {
- &.active-filter-item:hover:not(.not-sortable-item) {
- background-color: $blue5;
- border-color: $blue5;
+ .available-metadata-area {
+ padding: 10px 0px 10px 10px;
+ margin: 0;
+ max-width: 500px;
+ min-width: 20.8333333%;
+ font-size: 0.875rem;
+
+ @media screen and (max-width: 769px) {
+ max-width: 100%;
+ padding: 10px;
+ h3 {
+ margin: 1em 0em 1em 0em !important;
+ }
+ .available-metadatum-item::before,
+ .available-metadatum-item::after {
+ display: none !important;
+ }
+ }
+
+ h3 {
+ margin: 0.2em 0em 1em -1.2em;
+ font-weight: 500;
+ }
+
+ .available-metadatum-item {
+ padding: 0.7em;
+ margin: 4px;
+ background-color: white;
+ cursor: pointer;
+ left: 0;
+ line-height: 1.3em;
+ height: 40px;
+ position: relative;
+ border: 1px solid $gray2;
+ border-radius: 1px;
+ transition: left 0.2s ease;
+
+ .grip-icon {
+ color: $gray3;
+ top: -4px;
+ position: relative;
+ display: inline-block;
+ }
+ .icon {
+ position: relative;
+ bottom: 4px;
+ }
+ .metadatum-name {
+ text-overflow: ellipsis;
+ overflow-x: hidden;
+ white-space: nowrap;
+ font-weight: bold;
+ margin-left: 0.4em;
+ display: inline-block;
+ max-width: 180px;
+ width: 60%;
+ }
+ &:after,
+ &:before {
+ content: '';
+ display: block;
+ position: absolute;
+ right: 100%;
+ width: 0;
+ height: 0;
+ border-style: solid;
+ }
+ &:after {
+ top: -1px;
+ border-color: transparent white transparent transparent;
+ border-right-width: 16px;
+ border-top-width: 20px;
+ border-bottom-width: 20px;
+ left: -19px;
+ }
+ &:before {
+ top: -1px;
+ border-color: transparent $gray2 transparent transparent;
+ border-right-width: 16px;
+ border-top-width: 20px;
+ border-bottom-width: 20px;
+ left: -20px;
+ }
+ }
+ .sortable-drag {
+ opacity: 1 !important;
+ }
+ .available-metadatum-item:not(.disabled-metadatum) {
+ &:hover{
+ background-color: $secondary;
+ border-color: $secondary;
+ color: white !important;
+ position: relative;
+ left: -4px;
+
+ &:after {
+ border-color: transparent $secondary transparent transparent;
+ }
+ &:before {
+ border-color: transparent $secondary transparent transparent;
+ }
+ .icon-level-identifier>i {
+ color: white !important;
+ }
+ .grip-icon {
+ color: 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;
- .switch.is-small {
- input[type="checkbox"] + .check {
- background-color: $blue5 !important;
- }
- &:hover input[type="checkbox"] + .check {
- background-color: $blue5 !important;
+ &:after {
+ border-color: transparent $blue5 transparent transparent !important;
}
+ &:before {
+ border-color: transparent $blue5 transparent transparent !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;
- }
-
- }
- }
-
diff --git a/src/admin/components/lists/items-list.vue b/src/admin/components/lists/items-list.vue
index c67e9469c..c2f7afa83 100644
--- a/src/admin/components/lists/items-list.vue
+++ b/src/admin/components/lists/items-list.vue
@@ -36,7 +36,9 @@
class="button is-white"
slot="trigger">
{{ $i18n.get('label_bulk_actions') }}
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
@@ -213,26 +217,28 @@
id="button-edit"
:aria-label="$i18n.getFrom('items','edit_item')"
@click.prevent.stop="goToItemEditPage(item)">
-
+
+
+
-
+
+
+
-
+
+
+
@@ -284,26 +290,28 @@
id="button-edit"
:aria-label="$i18n.getFrom('items','edit_item')"
@click.prevent.stop="goToItemEditPage(item)">
-
+
+
+
-
+
+
+
-
+
+
+
@@ -423,26 +431,28 @@
id="button-edit"
:aria-label="$i18n.getFrom('items','edit_item')"
@click.prevent.stop="goToItemEditPage(item)">
-
+
+
+
-
+
+
+
-
+
+
+
@@ -620,26 +630,28 @@
id="button-edit"
:aria-label="$i18n.getFrom('items','edit_item')"
@click.prevent.stop="goToItemEditPage(item)">
-
+
+
+
-
+
+
+
-
+
+
+
diff --git a/src/admin/components/lists/metadata-list.vue b/src/admin/components/lists/metadata-list.vue
index 1738212cf..ef8d579e2 100644
--- a/src/admin/components/lists/metadata-list.vue
+++ b/src/admin/components/lists/metadata-list.vue
@@ -1,8 +1,21 @@
-
+
-
+
+
+ {{ $i18n.get('title_collection_metadata_edition') + ' ' }}
+ {{ collectionName }}
+
+
+ {{ $i18n.get('back') }}
+
+
+
{{ $i18n.get('info_repository_metadata_inheritance') }}
@@ -14,9 +27,9 @@
class="field is-grouped-centered section">
-
+
+
+
{{ $i18n.get('info_there_is_no_metadatum' ) }}
{{ $i18n.get('info_create_metadata' ) }}
@@ -47,14 +60,16 @@
v-for="(metadatum, index) in activeMetadatumList"
:key="index">
-
+
+
+
+ class="tainacan-icon" />
-
+
+
+
-
+
+
+
@@ -153,7 +168,9 @@
:class="{ 'hightlighted-metadatum' : hightlightedMetadatum == metadatum.name, 'inherited-metadatum': isRepositoryLevel }"
v-for="(metadatum, index) in availableMetadatumList"
:key="index">
-
+
+
+
{{ metadatum.name }}
-
+
+
+
{{ $i18n.get('info_there_is_no_metadatum') }}
{{ $i18n.get('info_create_metadata') }}
@@ -254,9 +271,9 @@
? 'visible' : 'hidden'
}"
@click.prevent="editMetadatumCustomMapper(props.row)">
-
+
+
+
-
+
+
+
@@ -280,10 +297,9 @@
v-if="collectionId != null && collectionId != undefined"
class="is-inline is-pulled-left add-link"
@click="onNewMetadataMapperMetadata()">
-
+
+
+
{{ $i18n.get('label_add_more_mapper_metadata') }}
@@ -351,7 +367,6 @@
@@ -791,395 +813,433 @@ export default {
@import "../../scss/_variables.scss";
- .page-title {
- border-bottom: 1px solid $secondary;
- h2 {
- color: $blue5;
- font-weight: 500;
+ .metadata-list-page {
+
+ .tainacan-page-title {
+ margin-bottom: 40px;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: flex-end;
+ justify-content: space-between;
+
+ h1, h2 {
+ font-size: 20px;
+ font-weight: 500;
+ color: $gray5;
+ display: inline-block;
+ width: 80%;
+ flex-shrink: 1;
+ flex-grow: 1;
+ }
+ a.back-link{
+ font-weight: 500;
+ float: right;
+ margin-top: 5px;
+ }
+ hr{
+ margin: 3px 0px 4px 0px;
+ height: 1px;
+ background-color: $secondary;
+ width: 100%;
+ }
}
- margin: 1em 0em 2.0em 0em;
- }
-
- .w-100 {
- width: 100%;
- position: relative;
- float: left;
- }
-
- .modal-new-link {
- padding: 0.5em 1em 3em 1em;
- }
-
- .loading-spinner {
- animation: spinAround 500ms infinite linear;
- border: 2px solid #dbdbdb;
- border-radius: 290486px;
- border-right-color: transparent;
- border-top-color: transparent;
- content: "";
- display: inline-block;
- height: 1em;
- width: 1em;
- }
-
- .active-metadata-area {
- font-size: 14px;
- margin-right: 0.8em;
- margin-left: -0.8em;
- padding-right: 6em;
- min-height: 330px;
-
- @media screen and (max-width: 769px) {
- min-height: 45px;
- margin: 0;
- padding-right: 0em;
- }
- @media screen and (max-width: 1216px) {
- padding-right: 1em;
- }
-
- &.metadata-area-receive {
- border: 1px dashed gray;
- }
-
- .collapse {
- display: initial;
- }
-
- .active-metadatum-item {
- background-color: white;
- padding: 0.7em 0.9em;
- margin: 4px;
- min-height: 40px;
- display: block;
- position: relative;
- cursor: grab;
- opacity: 1 !important;
- &>.field, form {
- background-color: white !important;
- }
-
- .handle {
- padding-right: 6em;
- }
- .grip-icon {
- fill: $gray3;
- top: 1px;
- position: relative;
- }
- .metadatum-name {
- text-overflow: ellipsis;
- overflow-x: hidden;
- white-space: nowrap;
- font-weight: bold;
- margin-left: 0.4em;
- margin-right: 0.4em;
+ .column:not(.available-metadata-area){
+ overflow: hidden;
+ flex-grow: 2;
+ }
- &.is-danger {
- color: $danger !important;
+ .page-title {
+ border-bottom: 1px solid $secondary;
+ h2 {
+ color: $blue5;
+ font-weight: 500;
+ }
+ margin: 1em 0em 2.0em 0em;
+ }
+
+ .w-100 {
+ width: 100%;
+ position: relative;
+ float: left;
+ }
+
+ .modal-new-link {
+ padding: 0.5em 1em 3em 1em;
+ }
+
+ .loading-spinner {
+ animation: spinAround 500ms infinite linear;
+ border: 2px solid #dbdbdb;
+ border-radius: 290486px;
+ border-right-color: transparent;
+ border-top-color: transparent;
+ content: "";
+ display: inline-block;
+ height: 1em;
+ width: 1em;
+ }
+
+ .active-metadata-area {
+ font-size: 14px;
+ margin-right: 0.8em;
+ margin-left: -0.8em;
+ padding-right: 6em;
+ min-height: 330px;
+
+ @media screen and (max-width: 769px) {
+ min-height: 45px;
+ margin: 0;
+ padding-right: 0em;
+ }
+ @media screen and (max-width: 1216px) {
+ padding-right: 1em;
+ }
+
+ &.metadata-area-receive {
+ border: 1px dashed gray;
+ }
+
+ .collapse {
+ display: initial;
+ }
+
+ .active-metadatum-item {
+ background-color: white;
+ padding: 0.7em 0.9em;
+ margin: 4px;
+ min-height: 40px;
+ display: block;
+ position: relative;
+ cursor: grab;
+ opacity: 1 !important;
+
+ &>.field, form {
+ background-color: white !important;
+ }
+
+ .handle {
+ padding-right: 6em;
+ white-space: nowrap;
+ display: flex;
+ }
+ .grip-icon {
+ color: $gray3;
+ position: relative;
+ }
+ .metadatum-name {
+ text-overflow: ellipsis;
+ overflow-x: hidden;
+ white-space: nowrap;
+ font-weight: bold;
+ margin-left: 0.4em;
+ margin-right: 0.4em;
+
+ &.is-danger {
+ color: $danger !important;
+ }
+ }
+ .label-details {
+ font-weight: normal;
+ color: $gray3;
+ }
+ .not-saved {
+ font-style: italic;
+ font-weight: bold;
+ color: $danger;
+ margin-left: 0.5rem;
+ }
+ .controls {
+ position: absolute;
+ right: 5px;
+ top: 10px;
+ .switch {
+ position: relative;
+ bottom: 3px;
+ }
+ .icon {
+ bottom: 1px;
+ position: relative;
+ i, i:before { font-size: 20px; }
+ }
+ }
+
+ &.not-sortable-item, &.not-sortable-item:hover {
+ cursor: default;
+ background-color: white !important;
+ }
+ &.not-focusable-item, &.not-focusable-item:hover {
+ cursor: default;
+
+ .metadatum-name {
+ color: $secondary;
+ }
+ .handle .label-details, .handle .icon {
+ color: $gray3 !important;
+ }
+ }
+ &.disabled-metadatum {
+ color: $gray3;
+ }
+ }
+ .active-metadatum-item:hover:not(.not-sortable-item) {
+ background-color: $secondary;
+ border-color: $secondary;
+ color: white !important;
+
+ &>.field, form {
+ background-color: white !important;
+ }
+
+ .label-details, .icon, .not-saved, .icon-level-identifier>i {
+ color: white !important;
+ }
+
+ .grip-icon {
+ color: white;
+ }
+
+ .switch.is-small {
+ input[type="checkbox"] + .check {
+ background-color: $secondary !important;
+ border: 1.5px solid white !important;
+ &::before { background-color: white !important; }
+ }
+ input[type="checkbox"]:checked + .check {
+ border: 1.5px solid white !important;
+ &::before { background-color: white !important; }
+ }
+ &:hover input[type="checkbox"] + .check {
+ border: 1.5px solid white !important;
+ background-color: $secondary !important;
+ }
}
}
- .label-details {
- font-weight: normal;
- color: $gray3;
+ .sortable-ghost {
+ border: 1px dashed $gray2;
+ display: block;
+ padding: 0.7em 0.9em;
+ margin: 4px;
+ height: 40px;
+ position: relative;
+
+ .grip-icon {
+ color: white;
+ }
}
- .not-saved {
- font-style: italic;
- font-weight: bold;
- color: $danger;
+ }
+
+ .available-metadata-area {
+ padding: 10px 0px 10px 10px;
+ margin: 0;
+ max-width: 500px;
+ min-width: 20.8333333%;
+ font-size: 0.875rem;
+
+ @media screen and (max-width: 769px) {
+ max-width: 100%;
+ padding: 10px;
+ h3 {
+ margin: 1em 0em 1em 0em !important;
+ }
+ .available-metadatum-item::before,
+ .available-metadatum-item::after {
+ display: none !important;
+ }
}
- .controls {
- position: absolute;
- right: 5px;
- top: 10px;
- .switch {
+
+ h3 {
+ margin: 0.2em 0em 1em -1.2em;
+ font-weight: 500;
+ }
+
+ .available-metadatum-item {
+ padding: 0.7em;
+ margin: 4px;
+ background-color: white;
+ cursor: pointer;
+ left: 0;
+ line-height: 1.3em;
+ height: 40px;
+ position: relative;
+ border: 1px solid $gray2;
+ border-radius: 1px;
+ transition: left 0.2s ease;
+
+ .grip-icon {
+ color: $gray3;
+ top: -4px;
position: relative;
- bottom: 3px;
+ display: inline-block;
}
.icon {
- bottom: 1px;
position: relative;
- i, i:before { font-size: 20px; }
+ bottom: 1px;
}
- }
-
- &.not-sortable-item, &.not-sortable-item:hover {
- cursor: default;
- background-color: white !important;
-
- // .handle .label-details, .handle .icon, {
- // color: $gray3 !important;
- // }
- }
- &.not-focusable-item, &.not-focusable-item:hover {
- cursor: default;
-
.metadatum-name {
- color: $secondary;
+ text-overflow: ellipsis;
+ overflow-x: hidden;
+ white-space: nowrap;
+ font-weight: bold;
+ margin-left: 0.4em;
+ display: inline-block;
+ max-width: 180px;
+ width: 60%;
}
- .handle .label-details, .handle .icon {
- color: $gray3 !important;
+ &:after,
+ &:before {
+ content: '';
+ display: block;
+ position: absolute;
+ right: 100%;
+ width: 0;
+ height: 0;
+ border-style: solid;
+ }
+ &:after {
+ top: -1px;
+ border-color: transparent white transparent transparent;
+ border-right-width: 16px;
+ border-top-width: 20px;
+ border-bottom-width: 20px;
+ left: -19px;
+ }
+ &:before {
+ top: -1px;
+ border-color: transparent $gray2 transparent transparent;
+ border-right-width: 16px;
+ border-top-width: 20px;
+ border-bottom-width: 20px;
+ left: -20px;
}
}
- &.disabled-metadatum {
- color: $gray3;
- }
- }
- .active-metadatum-item:hover:not(.not-sortable-item) {
- background-color: $secondary;
- border-color: $secondary;
- color: white !important;
-
- &>.field, form {
- background-color: white !important;
+
+ .sortable-drag {
+ opacity: 1 !important;
}
- .label-details, .icon, .not-saved, .icon-level-identifier>i {
- color: white !important;
- }
-
- .grip-icon {
- fill: white;
- }
-
- .switch.is-small {
- input[type="checkbox"] + .check {
- background-color: $secondary !important;
- border: 1.5px solid white !important;
- &::before { background-color: white !important; }
- }
- input[type="checkbox"]:checked + .check {
- border: 1.5px solid white !important;
- &::before { background-color: white !important; }
+ @keyframes hightlighten {
+ 0% {
+ color: #222;
+ background-color: white;
+ border-color: white;
}
- &:hover input[type="checkbox"] + .check {
- border: 1.5px solid white !important;
- background-color: $secondary !important;
+ 25% {
+ color: white;
+ background-color: #2cb4c1;
+ border-color: #2cb4c1;
+ }
+ 75% {
+ color: white;
+ background-color: #2cb4c1;
+ border-color: #2cb4c1;
+ }
+ 100% {
+ color: #222;
+ background-color: white;
+ border-color: white;
}
}
- }
- .sortable-ghost {
- border: 1px dashed $gray2;
- display: block;
- padding: 0.7em 0.9em;
- margin: 4px;
- height: 40px;
- position: relative;
-
- .grip-icon {
- fill: white;
+ @keyframes hightlighten-icon {
+ 0% { color: #b1b1b1; }
+ 25% { color: white; }
+ 75% { color: white; }
+ 100% { color: #b1b1b1; }
}
- }
- }
-
- .available-metadata-area {
- padding: 10px 0px 10px 10px;
- margin: 0;
- max-width: 280px;
- font-size: 14px;
-
- @media screen and (max-width: 769px) {
- max-width: 100%;
- padding: 10px;
- h3 {
- margin: 1em 0em 1em 0em !important;
+ @keyframes hightlighten-arrow {
+ 0% {
+ border-color: transparent white transparent transparent;
+ border-color: transparent white transparent transparent;
+ }
+ 25% {
+ border-color: transparent #2cb4c1 transparent transparent;
+ border-color: transparent #2cb4c1 transparent transparent;
+ }
+ 75% {
+ border-color: transparent #2cb4c1 transparent transparent;
+ border-color: transparent #2cb4c1 transparent transparent;
+ }
+ 100% {
+ border-color: transparent white transparent transparent;
+ border-color: transparent white transparent transparent;
+ }
}
- .available-metadatum-item::before,
- .available-metadatum-item::after {
- display: none !important;
- }
- }
-
- h3 {
- margin: 0.2em 0em 1em -1.2em;
- font-weight: 500;
- }
-
- .available-metadatum-item {
- padding: 0.7em;
- margin: 4px;
- background-color: white;
- cursor: pointer;
- left: 0;
- line-height: 1.3em;
- height: 40px;
- position: relative;
- border: 1px solid $gray2;
- border-radius: 1px;
- transition: left 0.2s ease;
-
- .grip-icon {
- fill: $gray3;
- top: -3px;
- position: relative;
- display: inline-block;
- }
- .icon {
- position: relative;
- bottom: 1px;
- }
- .metadatum-name {
- text-overflow: ellipsis;
- overflow-x: hidden;
- white-space: nowrap;
- font-weight: bold;
- margin-left: 0.4em;
- display: inline-block;
- max-width: 200px;
- }
- &:after,
- &:before {
- content: '';
- display: block;
- position: absolute;
- right: 100%;
- width: 0;
- height: 0;
- border-style: solid;
- }
- &:after {
- top: -1px;
- border-color: transparent white transparent transparent;
- border-right-width: 16px;
- border-top-width: 20px;
- border-bottom-width: 20px;
- left: -19px;
- }
- &:before {
- top: -1px;
- border-color: transparent $gray2 transparent transparent;
- border-right-width: 16px;
- border-top-width: 20px;
- border-bottom-width: 20px;
- left: -20px;
- }
- }
-
- .sortable-drag {
- opacity: 1 !important;
- }
-
- @keyframes hightlighten {
- 0% {
- color: #222;
+ .hightlighted-metadatum {
background-color: white;
- border-color: white;
- }
- 25% {
- color: white;
- background-color: #2cb4c1;
- border-color: #2cb4c1;
- }
- 75% {
- color: white;
- background-color: #2cb4c1;
- border-color: #2cb4c1;
- }
- 100% {
- color: #222;
- background-color: white;
- border-color: white;
- }
- }
- @keyframes hightlighten-icon {
- 0% { fill: #b1b1b1; }
- 25% { fill: white; }
- 75% { fill: white; }
- 100% { fill: #b1b1b1; }
- }
- @keyframes hightlighten-arrow {
- 0% {
- border-color: transparent white transparent transparent;
- border-color: transparent white transparent transparent;
- }
- 25% {
- border-color: transparent #2cb4c1 transparent transparent;
- border-color: transparent #2cb4c1 transparent transparent;
- }
- 75% {
- border-color: transparent #2cb4c1 transparent transparent;
- border-color: transparent #2cb4c1 transparent transparent;
- }
- 100% {
- border-color: transparent white transparent transparent;
- border-color: transparent white transparent transparent;
- }
- }
- .hightlighted-metadatum {
- background-color: white;
- position: relative;
- left: 0px;
- animation-name: hightlighten;
- animation-duration: 1.0s;
- animation-iteration-count: 2;
-
- .grip-icon{
- animation-name: hightlighten-icon;
- animation-duration: 1.0s;
- animation-iteration-count: 2;
- }
-
- &::before,
- &::after {
- animation-name: hightlighten-arrow;
+ position: relative;
+ left: 0px;
+ animation-name: hightlighten;
animation-duration: 1.0s;
animation-iteration-count: 2;
- }
- }
- .available-metadatum-item:hover {
- background-color: $secondary;
- border-color: $secondary;
- color: white;
- position: relative;
- left: -4px;
+
+ .grip-icon{
+ animation-name: hightlighten-icon;
+ animation-duration: 1.0s;
+ animation-iteration-count: 2;
+ }
- &:after {
- border-color: transparent $secondary transparent transparent;
- }
- &:before {
- border-color: transparent $secondary transparent transparent;
- }
- .icon {
- color: white !important;
- }
-
- .grip-icon {
- fill: white;
- }
-
- }
- }
- .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;
+ &::before,
+ &::after {
+ animation-name: hightlighten-arrow;
+ animation-duration: 1.0s;
+ animation-iteration-count: 2;
}
}
- }
- &.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;
- }
+ .available-metadatum-item:hover {
+ background-color: $secondary;
+ border-color: $secondary;
+ color: white;
+ position: relative;
+ left: -4px;
+ &:after {
+ border-color: transparent $secondary transparent transparent;
+ }
+ &:before {
+ border-color: transparent $secondary transparent transparent;
+ }
+ .icon {
+ color: white !important;
+ }
+
+ .grip-icon {
+ color: white;
+ }
+
+ }
}
- }
- #mappers-options-dropdown {
- background-color: transparent;
- color: #fff;
+ .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;
+ }
+
}
diff --git a/src/admin/components/lists/processes-list.vue b/src/admin/components/lists/processes-list.vue
index 05e1f2705..cfa85197b 100644
--- a/src/admin/components/lists/processes-list.vue
+++ b/src/admin/components/lists/processes-list.vue
@@ -20,7 +20,9 @@
class="button is-white"
slot="trigger">
{{ $i18n.get('label_bulk_actions') }}
-
+
+
+
-
+
-
+
-
+
diff --git a/src/admin/components/lists/recursive-term-item.vue b/src/admin/components/lists/recursive-term-item.vue
index 51553cba3..bfba4a854 100644
--- a/src/admin/components/lists/recursive-term-item.vue
+++ b/src/admin/components/lists/recursive-term-item.vue
@@ -12,15 +12,15 @@
-
+
@@ -46,18 +46,18 @@
:class="{'is-disabled': isEditingTerm}">
-
+
-
+
-
+
@@ -233,8 +233,11 @@ export default {
});
},
eventOnChildTermDeleted(parentTermId) {
- if (this.term.id == parentTermId && this.totalTerms > 0)
+ if (this.term.id == parentTermId && this.totalTerms > 0) {
this.totalTerms--;
+ this.loadChildTerms(parentTermId);
+ }
+
},
eventOnEditTerm() {
this.isEditingTerm = true;
@@ -296,6 +299,8 @@ export default {
color: $blue2;
position: absolute;
left: -21px;
+ top: 1px;
+ font-size: 24px;
}
.children-dropdown {
color: $blue4;
diff --git a/src/admin/components/lists/taxonomies-list.vue b/src/admin/components/lists/taxonomies-list.vue
index 202e1a475..0b494ede0 100644
--- a/src/admin/components/lists/taxonomies-list.vue
+++ b/src/admin/components/lists/taxonomies-list.vue
@@ -21,7 +21,9 @@
class="button is-white"
slot="trigger">
{{ $i18n.get('label_bulk_actions') }}
-
+
+
+
-
+
+
+
-
+
+
+
diff --git a/src/admin/components/lists/terms-list.vue b/src/admin/components/lists/terms-list.vue
index 9788af21d..f0a6c3f8d 100644
--- a/src/admin/components/lists/terms-list.vue
+++ b/src/admin/components/lists/terms-list.vue
@@ -15,17 +15,17 @@
:disabled="localTerms.length <= 0 || isLoadingTerms || isEditingTerm || order == 'asc'"
class="button is-white is-small"
@click="onChangeOrder('asc')">
-
+
+
+
-
+
+
+
@@ -41,7 +41,7 @@
-
+
@@ -113,7 +113,9 @@
-
+
+
+
{{ $i18n.get('info_no_terms_created_on_taxonomy') }}
0)
+ if ((parentTermId == 0 || parentTermId == undefined ) && this.totalTerms > 0) {
this.totalTerms--;
+ this.loadTerms(parentTermId);
+ }
},
eventOnEditTerm(term) {
// Position edit form in a visible area
@@ -404,10 +409,6 @@ export default {
diff --git a/src/admin/components/other/alert-icon.vue b/src/admin/components/other/alert-icon.vue
deleted file mode 100644
index df4ac4d3b..000000000
--- a/src/admin/components/other/alert-icon.vue
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/admin/components/other/check-icon.vue b/src/admin/components/other/check-icon.vue
deleted file mode 100644
index 5e1054c8d..000000000
--- a/src/admin/components/other/check-icon.vue
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/admin/components/other/checkbox-radio-modal.vue b/src/admin/components/other/checkbox-radio-modal.vue
index 7d75a0896..1698ed1c1 100644
--- a/src/admin/components/other/checkbox-radio-modal.vue
+++ b/src/admin/components/other/checkbox-radio-modal.vue
@@ -14,8 +14,7 @@
@input="autoComplete"
class="input">
-
+
@@ -35,8 +34,9 @@
role="button"
class="tainacan-checkbox-list-page-changer"
@click="beforePage">
-
+
+
+
@@ -132,6 +156,11 @@
{{ pathItem.option.label }}
+
+ {{ "(" + pathItem.option.total_items + ")" }}
+
@@ -179,17 +208,33 @@
class="tainacan-li-search-results"
v-for="(option, key) in searchResults"
:key="key">
-
- {{ `${ option.name ? limitChars(option.name) : limitChars(option.label) }` }}
-
+ class="b-checkbox checkbox is-small">
+
+
+
+ {{ `${ option.name ? limitChars(option.name) : limitChars(option.label) }` }}
+
+ {{ "(" + option.total_items + ")" }}
+
+
+
{{ `${ option.name ? limitChars(option.name) : limitChars(option.label) }` }}
+
+ {{ "(" + option.total_items + ")" }}
+
{
@@ -404,7 +449,10 @@
this.isSearchingLoading = true;
let query_items = { 'current_query': this.query };
- let query = `?hideempty=0&order=asc&number=${this.maxNumSearchResultsShow}&searchterm=${this.optionName}&` + qs.stringify(query_items);
+ let query = `?order=asc&number=${this.maxNumSearchResultsShow}&searchterm=${this.optionName}&` + qs.stringify(query_items);
+
+ if (!this.isFilter)
+ query += '&hideempty=0';
let route = `/collection/${this.collection_id}/facets/${this.metadatum_id}${query}`;
@@ -522,7 +570,10 @@
parent = option.value;
}
- let query = `?hideempty=0&order=asc&parent=${parent}&number=${this.maxNumOptionsCheckboxFinderColumns}&offset=0&` + qs.stringify(query_items);
+ let query = `?order=asc&parent=${parent}&number=${this.maxNumOptionsCheckboxFinderColumns}&offset=0&` + qs.stringify(query_items);
+
+ if (!this.isFilter)
+ query += '&hideempty=0';
this.isColumnLoading = true;
@@ -552,7 +603,10 @@
let offset = finderColumn.length;
let query_items = { 'current_query': this.query };
- let query = `?hideempty=0&order=asc&parent=${parent}&number=${this.maxNumOptionsCheckboxFinderColumns}&offset=${offset}&` + qs.stringify(query_items);
+ let query = `?order=asc&parent=${parent}&number=${this.maxNumOptionsCheckboxFinderColumns}&offset=${offset}&` + qs.stringify(query_items);
+
+ if (!this.isFilter)
+ query += '&hideempty=0';
this.isColumnLoading = true;
@@ -611,6 +665,10 @@
.breadcrumb {
background-color: white !important;
+
+ li + li::before {
+ content: ">" !important;
+ }
}
@media screen and (max-width: 768px) {
@@ -668,7 +726,7 @@
cursor: pointer;
border: 1px solid $gray1;
margin-top: 10px;
- margin-bottom: 0.2rem;
+ margin-bottom: -0.2rem;
&:hover {
background-color: $blue1;
@@ -681,7 +739,7 @@
max-width: calc(50% - 8.3333333%);
.b-checkbox, .b-radio {
- max-width: 86%;
+ max-width: 81%;
margin-right: 10px;
}
@@ -692,10 +750,11 @@
.tainacan-li-checkbox-modal {
display: flex;
+ justify-content: space-between;
padding: 0;
.b-checkbox, .b-radio {
- max-width: 86%;
+ max-width: 81%;
margin-left: 0.7rem;
height: 24px;
}
@@ -851,6 +910,19 @@
background-color: $turquoise1;
}
+ .b-checkbox .control-label {
+ display: flex;
+ flex-wrap: nowrap;
+ width: 100%;
+
+ .checkbox-label-text {
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
+ }
+
+
diff --git a/src/admin/components/other/custom-dialog.vue b/src/admin/components/other/custom-dialog.vue
index 08048d1bb..8bc5335e0 100644
--- a/src/admin/components/other/custom-dialog.vue
+++ b/src/admin/components/other/custom-dialog.vue
@@ -6,7 +6,12 @@
-
+
+
+
+
\ No newline at end of file
+
+
+
+
diff --git a/src/admin/components/other/eye-icon.vue b/src/admin/components/other/eye-icon.vue
deleted file mode 100644
index 7b324bfbc..000000000
--- a/src/admin/components/other/eye-icon.vue
+++ /dev/null
@@ -1,163 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/admin/components/other/file-item.vue b/src/admin/components/other/file-item.vue
index 44537713f..bfc9a764c 100644
--- a/src/admin/components/other/file-item.vue
+++ b/src/admin/components/other/file-item.vue
@@ -18,10 +18,11 @@
:style="{ 'background-color': '#dbdbdb' }"
v-else
class="file-placeholder">
-
+
+
+
@@ -66,7 +67,7 @@ export default {
if (type[0] == 'application' && type[1] != undefined){
switch (type[1]) {
case 'pdf':
- return 'file-pdf';
+ return 'pdf';
default:
return '';
}
@@ -75,9 +76,9 @@ export default {
case 'video':
return 'video';
case 'audio':
- return 'volume-high';
+ return 'audio';
case 'text':
- return 'format-align-left';
+ return 'text';
default:
return '';
}
diff --git a/src/admin/components/other/grip-icon.vue b/src/admin/components/other/grip-icon.vue
deleted file mode 100644
index 85fce6f6b..000000000
--- a/src/admin/components/other/grip-icon.vue
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
-
-
-
-
diff --git a/src/admin/components/other/help-button.vue b/src/admin/components/other/help-button.vue
index ca8b61f39..9f71f19ce 100644
--- a/src/admin/components/other/help-button.vue
+++ b/src/admin/components/other/help-button.vue
@@ -1,9 +1,10 @@
-
+
+
+
+
@@ -55,23 +55,23 @@
v-if="bgProcess.done <= 0 && bgProcess.status == 'closed'"
class="icon has-text-gray action-icon"
@click="resumeProcess(index)">
-
+
-->
-
+
-
+
-
+
+
-
diff --git a/src/admin/js/router.js b/src/admin/js/router.js
index 0e512d518..a3be1291c 100644
--- a/src/admin/js/router.js
+++ b/src/admin/js/router.js
@@ -3,6 +3,7 @@ import VueRouter from 'vue-router'
import qs from 'qs';
// Main Pages
+import HomePage from '../pages/home-page.vue'
import CollectionsPage from '../pages/lists/collections-page.vue'
import CollectionPage from '../pages/singles/collection-page.vue'
import ItemsPage from '../pages/lists/items-page.vue'
@@ -10,7 +11,6 @@ import ItemPage from '../pages/singles/item-page.vue'
import MetadataPage from '../pages/lists/metadata-page.vue'
import FiltersPage from '../pages/lists/filters-page.vue'
import Page from '../pages/lists/taxonomies-page.vue'
-import TaxonomyPage from '../pages/singles/taxonomy-page.vue'
import EventsPage from '../pages/lists/events-page.vue'
import EventPage from '../pages/singles/event-page.vue'
import ExportPage from '../pages/singles/export-page.vue'
@@ -20,8 +20,10 @@ import CollectionEditionForm from '../components/edition/collection-edition-form
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 ItemBulkEditionForm from '../components/edition/item-bulk-edition-form.vue'
+import ItemMetadataBulkEditionForm from '../components/edition/item-metadata-bulk-edition-form.vue'
import TaxonomyEditionForm from '../components/edition/taxonomy-edition-form.vue'
-import AvailableImportersPage from '../pages/lists/available-importers-page.vue';
+import AvailableImportersPage from '../pages/lists/available-importers-page.vue'
// Listing components
import FiltersList from '../components/lists/filters-list.vue'
@@ -35,7 +37,8 @@ const i18nGet = function (key) {
};
const routes = [
- { path: '/', redirect:'/collections' },
+ { path: '/', redirect:'/home' },
+ { path: '/home', name: 'HomePage', component: HomePage, meta: {title: 'Tainacan'} },
{ path: '/collections', name: 'CollectionsPage', component: CollectionsPage, meta: {title: i18nGet('title_repository_collections_page'), icon: 'folder-multiple'} },
{ path: '/collections/new', name: 'CollectionCreationForm', component: CollectionEditionForm, meta: {title: i18nGet('title_create_collection'), icon: 'folder-multiple'} },
@@ -48,6 +51,8 @@ const routes = [
{ path: 'items/:itemId/edit', name: 'ItemEditionForm', component: ItemEditionForm, meta: {title: i18nGet('title_edit_item'), icon: 'folder-multiple'} },
{ path: 'items/new', name: 'CollectionItemCreatePage', component: ItemEditionForm, meta: {title: i18nGet('title_create_item_collection'), icon: 'folder-multiple'} },
{ path: 'items/:itemId', name: 'ItemPage', component: ItemPage, meta: {title: i18nGet('title_item_page'), icon: 'folder-multiple'} },
+ { path: 'bulk-add', name: 'CollectionItemBulkAddPage', component: ItemBulkEditionForm, meta: {title: i18nGet('title_item_bulk_add'), icon: 'folder-multiple'} },
+ { path: 'bulk-add/:groupId', name: 'CollectionItemBulkAddMetadataPage', component: ItemMetadataBulkEditionForm, meta: {title: i18nGet('title_item_bulk_add'), icon: 'folder-multiple'} },
{ path: 'settings', component: CollectionEditionForm, name: 'CollectionEditionForm', meta: {title: i18nGet('title_collection_settings'), icon: 'folder-multiple'} },
{ path: 'metadata', component: MetadataList, name: 'MetadataList', meta: {title: i18nGet('title_collection_metadata_edition'), icon: 'folder-multiple'} },
{ path: 'filters', component: FiltersList, name: 'FiltersList', meta: {title: i18nGet('title_collection_filters_edition'), icon: 'folder-multiple'} },
diff --git a/src/admin/js/theme-main.js b/src/admin/js/theme-main.js
index 8c8968af6..e9a44db8e 100644
--- a/src/admin/js/theme-main.js
+++ b/src/admin/js/theme-main.js
@@ -106,7 +106,8 @@ export const ThemeItemsListing = new Vue({
taxonomy: '',
collectionId: '',
defaultViewMode: '',
- enabledViewModes: {}
+ enabledViewModes: {},
+ customFilters: []
},
render: h => h(ThemeItemsList),
beforeMount () {
@@ -125,6 +126,7 @@ export const ThemeItemsListing = new Vue({
this.termId = this.$el.attributes['term-id'].value;
if (this.$el.attributes['taxonomy'] != undefined)
this.taxonomy = this.$el.attributes['taxonomy'].value;
+
}
});
\ No newline at end of file
diff --git a/src/admin/js/utilities.js b/src/admin/js/utilities.js
index 5eb7ab072..9bc0307d3 100644
--- a/src/admin/js/utilities.js
+++ b/src/admin/js/utilities.js
@@ -270,6 +270,9 @@ RouterHelperPlugin.install = function (Vue, options = {}) {
getNewEventPath() {
return '/events/new';
},
+ getNewItemBulkAddPath(collectionId) {
+ return '/collections/' + collectionId + '/bulk-add';
+ },
// Edit
getCollectionEditPath(id) {
return '/collections/' + id + '/settings';
@@ -295,6 +298,9 @@ RouterHelperPlugin.install = function (Vue, options = {}) {
getImporterMappingPath(importerType, sessionId, collectionId) {
return '/importers/' + importerType + '/' + sessionId + '/mapping/' + collectionId;
},
+ getItemMetadataBulkAddPath(collectionId, groupId) {
+ return '/collections/' + collectionId + '/bulk-add/' + groupId;
+ },
}
}
diff --git a/src/admin/pages/home-page.vue b/src/admin/pages/home-page.vue
new file mode 100644
index 000000000..ca9967491
--- /dev/null
+++ b/src/admin/pages/home-page.vue
@@ -0,0 +1,328 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/admin/pages/lists/collections-page.vue b/src/admin/pages/lists/collections-page.vue
index e45f9dcdb..4ed2659b5 100644
--- a/src/admin/pages/lists/collections-page.vue
+++ b/src/admin/pages/lists/collections-page.vue
@@ -12,7 +12,9 @@
class="button is-secondary"
slot="trigger">
{{ $i18n.getFrom('collections', 'new_item') }}
-
+
+
+
-
+
+
+
{{ $i18n.get('info_no_collection_created') }}
{{ $i18n.get('info_no_collection_draft') }}
{{ $i18n.get('info_no_collection_trash') }}
-
- {{ $i18n.getFrom('collections', 'new_item') }}
-
+
+
+
+
+ {{ $i18n.getFrom('collections', 'new_item') }}
+
+
+
+
+
+
+ {{ $i18n.get('new_blank_collection') }}
+
+ {{ $i18n.get('info_choose_your_metadata') }}
+
+
+
+
+ {{ $i18n.get(metadatum_mapper.name) }}
+
+
+
+
+ {{ $i18n.get('import') }}
+
+ {{ $i18n.get('info_import_collection') }}
+
+
+
+
+
diff --git a/src/admin/pages/lists/events-page.vue b/src/admin/pages/lists/events-page.vue
index 2114f36b2..26807b939 100644
--- a/src/admin/pages/lists/events-page.vue
+++ b/src/admin/pages/lists/events-page.vue
@@ -46,7 +46,9 @@
-
+
+
+
{{ $i18n.get('info_no_process') }}
@@ -136,7 +138,6 @@
\ No newline at end of file
diff --git a/src/admin/scss/_buttons.scss b/src/admin/scss/_buttons.scss
index bfccf5159..ff9e77b4c 100644
--- a/src/admin/scss/_buttons.scss
+++ b/src/admin/scss/_buttons.scss
@@ -28,10 +28,13 @@
transform: none !important;
}
&.is-outlined {
- color: $turquoise5 !important;
+ color: $turquoise5;
background-color: white !important;
border-color: $gray4 !important;
}
+ &.is-outlined:hover {
+ color: $turquoise5 !important;
+ }
&:focus {
outline: 0px;
}
@@ -52,11 +55,10 @@
}
}
.button.is-small {
- height: 26px !important;
+ height: 1.625rem !important;
line-height: 0.75rem;
}
.button:not(.is-small):not(.is-medium):not(.is-large) {
- height: 30px !important;
- line-height: 1.25rem !important;
+ height: 1.875rem !important;
font-size: 0.875rem !important;
}
\ No newline at end of file
diff --git a/src/admin/scss/_collection-home-cards.scss b/src/admin/scss/_collection-home-cards.scss
new file mode 100644
index 000000000..9c198dc70
--- /dev/null
+++ b/src/admin/scss/_collection-home-cards.scss
@@ -0,0 +1,112 @@
+.tainacan-cards-container {
+ min-height: 50vh;
+ padding: 0;
+ display: flex;
+ flex-wrap: wrap;
+ flex-grow: 1;
+ flex-shrink: 1;
+ justify-content: space-between;
+ align-content: baseline;
+ animation-name: item-appear;
+ animation-duration: 0.5s;
+
+ .tainacan-card {
+ background-color: $gray1;
+ padding: 0px;
+ margin-top: 0.75rem;
+ margin-bottom: 1.6rem;
+ flex-basis: 0;
+ min-height: 135px;
+ cursor: pointer;
+ text-decoration: none !important;
+ display: flex;
+ flex-wrap: wrap;
+
+ @media screen and (max-width: 768px) {
+ max-width: 100%;
+ min-width: 100%;
+ }
+
+ &:hover .menu-list {
+ background-color: $gray2;
+ a { background-color: $gray2; }
+ }
+
+ &.new-card {
+ .list-metadata {
+ text-align: center;
+ color: $turquoise5;
+ max-width: calc(100% - 46px);
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ flex-wrap: wrap;
+ width: 100%;
+ }
+ .menu-list {
+ width: 46px;
+ flex-wrap: nowrap;
+ flex-direction: column;
+ li { height: 100%; }
+ }
+ }
+
+ &.first-card {
+ .list-metadata {
+ text-align: center;
+ color: $turquoise5;
+ max-width:100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ }
+ }
+
+ .menu-list {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ flex-wrap: nowrap;
+
+ li {
+ text-align: center;
+ width: 100%;
+ a {
+ color: $turquoise5;
+ padding: 0.5em 0.5em;
+ border-radius: 0;
+ transition: none;
+ }
+ }
+ }
+
+ .card-body {
+ width: 100%;
+ display: flex;
+
+ img {
+ width: 96px;
+ height: 96px;
+ border-radius: 0px;
+ }
+ .metadata-title {
+ overflow: hidden;
+ padding: 0.75rem 1rem;
+ flex-basis: calc(100% - 96px);
+
+ p {
+ color: black !important;
+ font-size: 0.875rem !important;
+ margin-bottom: 0;
+ }
+ }
+ &:hover .metadata-title {
+ p { text-decoration: none !important; }
+ }
+ }
+ }
+}
+
+
diff --git a/src/admin/scss/_dropdown-and-autocomplete.scss b/src/admin/scss/_dropdown-and-autocomplete.scss
index b0a2e3aa6..ebf6c0045 100644
--- a/src/admin/scss/_dropdown-and-autocomplete.scss
+++ b/src/admin/scss/_dropdown-and-autocomplete.scss
@@ -2,9 +2,10 @@
.dropdown-trigger{
.button {
border: none;
+ align-items: center;
.icon {
color: $secondary;
- align-items: start;
+ align-items: center;
}
}
.button.is-primary, .button.is-secondary, .button.is-success {
@@ -12,6 +13,9 @@
color: $white;
}
}
+ .dropdown.is-disabled {
+ cursor: default;
+ }
}
.dropdown-menu {
padding: 0px;
@@ -33,11 +37,19 @@
.is-small { color: $gray4; }
&.is-active { background-color: $turquoise2; }
+ .media-left {
+ margin-right: 0.5rem;
+ }
.media-content {
- overflow-x: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- max-width: 150px;
+ display: flex;
+ width: 80%;
+
+ .ellipsed-text {
+ overflow-x: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ margin-right: 3px;
+ }
}
}
}
diff --git a/src/admin/scss/_filters-menu-modal.scss b/src/admin/scss/_filters-menu-modal.scss
index 598e5a62a..345c8e356 100644
--- a/src/admin/scss/_filters-menu-modal.scss
+++ b/src/admin/scss/_filters-menu-modal.scss
@@ -11,7 +11,7 @@
.modal-content {
background-color: white;
margin: 0 8.3333333% 0 0;
- padding: 24px $page-side-padding;
+ padding: 24px $page-side-padding 24px 8.3333333%;
border-radius: 0;
height: 100%;
max-height: 100%;
diff --git a/src/admin/scss/_modals.scss b/src/admin/scss/_modals.scss
index 2917c9a3d..05b91dfd6 100644
--- a/src/admin/scss/_modals.scss
+++ b/src/admin/scss/_modals.scss
@@ -3,10 +3,6 @@
width: 100%;
}
-.modal {
- display: inline-block;
-}
-
.tainacan-modal-title {
display: flex;
flex-wrap: wrap;
diff --git a/src/admin/scss/_tables.scss b/src/admin/scss/_tables.scss
index ca0251cc0..f89d79cbb 100644
--- a/src/admin/scss/_tables.scss
+++ b/src/admin/scss/_tables.scss
@@ -188,10 +188,6 @@
a {
margin: auto;
font-size: 1.125rem !important;
-
- .mdi-settings, .mdi-settings::before {
- font-size: 1.4375rem;
- }
}
}
diff --git a/src/admin/scss/_tainacan-form.scss b/src/admin/scss/_tainacan-form.scss
index 03922d30d..18574096a 100644
--- a/src/admin/scss/_tainacan-form.scss
+++ b/src/admin/scss/_tainacan-form.scss
@@ -32,8 +32,14 @@
overflow: hidden;
vertical-align: top;
}
+ .section-label>label {
+ cursor: default;
+ }
.required-metadatum-asterisk {
- color: $gray3;
+ color: $gray5;
+ position: relative;
+ top: -3px;
+
&.is-danger {
color: $danger;
}
@@ -109,5 +115,6 @@
transition: color 0.2s background-color 0.2s;
border-radius: 0 !important;
border-color: $gray2;
+ padding: 1.25rem;
}
}
\ No newline at end of file
diff --git a/src/admin/scss/_variables.scss b/src/admin/scss/_variables.scss
index 063d40e46..fa87ecb84 100644
--- a/src/admin/scss/_variables.scss
+++ b/src/admin/scss/_variables.scss
@@ -26,6 +26,7 @@ $turquoise4-invert: findColorInvert($turquoise4);
$turquoise5: #298596;
$turquoise5-invert: findColorInvert($turquoise5);
// Gray, used mostyl for information
+$gray0: #f6f6f6;
$gray1: #f2f2f2;
$gray1-invert: findColorInvert($gray1);
$gray2: #dbdbdb;
@@ -150,7 +151,7 @@ $table-cell-padding: 1.0em 0.75em;
// Roboto font
$family-sans-serif: 'Roboto', sans-serif;
-// Bulma's modal (needs to be greather than taincan-admin-app)
+// Bulma's modal (needs to be greather than tainacan-admin-app)
$modal-z: 9999999;
// Animations for Slide Menu
diff --git a/src/admin/scss/_view-mode-cards.scss b/src/admin/scss/_view-mode-cards.scss
index bb4a50c4a..98612b66d 100644
--- a/src/admin/scss/_view-mode-cards.scss
+++ b/src/admin/scss/_view-mode-cards.scss
@@ -56,7 +56,7 @@
.actions-area {
position: relative;
float: right;
- top: -5px;
+ top: -7px;
padding-right: 12px;
//width: 80px;
display: flex;
@@ -86,7 +86,7 @@
.metadata-title {
flex-shrink: 0;
padding: 0.6rem 4.75rem 0.5rem 2.75rem;
- margin-bottom: -27px;
+ margin-bottom: -25px;
min-height: 40px;
font-size: 0.875rem !important;
text-overflow: ellipsis;
diff --git a/src/admin/scss/_view-mode-grid.scss b/src/admin/scss/_view-mode-grid.scss
index b83e4bd16..be1384eba 100644
--- a/src/admin/scss/_view-mode-grid.scss
+++ b/src/admin/scss/_view-mode-grid.scss
@@ -53,8 +53,8 @@
}
img {
- min-width: 255px;
max-width: 255px;
+ max-height: 255px;
height: auto;
border-radius: 0px;
margin-bottom: -5px;
diff --git a/src/admin/scss/_view-mode-masonry.scss b/src/admin/scss/_view-mode-masonry.scss
index fcc2af7c5..27e8916f4 100644
--- a/src/admin/scss/_view-mode-masonry.scss
+++ b/src/admin/scss/_view-mode-masonry.scss
@@ -41,7 +41,7 @@
opacity: 0;
padding: 2px 8px;
transition: visibility 0.2s, opacity 0.2s;
- margin-top: -31px;
+ margin-top: -29px;
background-color: $gray2;
a {
diff --git a/src/admin/scss/_view-mode-records.scss b/src/admin/scss/_view-mode-records.scss
index c953c83ae..208d14ac6 100644
--- a/src/admin/scss/_view-mode-records.scss
+++ b/src/admin/scss/_view-mode-records.scss
@@ -43,7 +43,7 @@
.actions-area {
position: relative;
float: right;
- top: -5px;
+ top: -7px;
padding-right: 12px;
//width: 80px;
display: flex;
@@ -51,6 +51,10 @@
visibility: hidden;
opacity: 0;
transition: visibility 0.2s, opacity 0.2s;
+
+ a {
+ margin-left: 12px;
+ }
}
&:hover .actions-area {
visibility: visible;
diff --git a/src/admin/scss/_view-mode-slideshow.scss b/src/admin/scss/_view-mode-slideshow.scss
index 7dc5421b7..ca4472155 100644
--- a/src/admin/scss/_view-mode-slideshow.scss
+++ b/src/admin/scss/_view-mode-slideshow.scss
@@ -108,11 +108,18 @@
margin-bottom: 0.75rem !important;
display: inline-flex;
align-items: center;
+ max-width: 100%;
- span {
+ span:not(.ellipsed-text) {
margin-right: 5px;
margin-left: -5px;
}
+ .ellipsed-text {
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ max-width: 100%;
+ }
}
.content {
font-size: 0.75rem;
@@ -293,6 +300,9 @@
border-radius: 100px;
background: white;
border: 3px solid $turquoise5;
+ i, i:before {
+ font-size: 36px;
+ }
}
&:focus, &:active {
outline: 0;
@@ -300,8 +310,8 @@
}
.circular-counter {
position: absolute;
- right: calc(4.16667% + 1px);
- top: -3px;
+ right: calc(4.16667% + -2px);
+ top: -6px;
}
}
}
@@ -325,7 +335,7 @@
width: 2.5rem;
text-align: center;
- .mdi::before {
+ .tainacan-icon::before {
line-height: 5rem;
font-size: 5rem;
color: $turquoise5;
@@ -349,7 +359,7 @@
height: 2.5rem;
width: 1.5rem;
- .mdi::before {
+ .tainacan-icon::before {
line-height: 3rem;
font-size: 3rem;
color: white;
diff --git a/src/admin/scss/tainacan-admin.scss b/src/admin/scss/tainacan-admin.scss
index 672fd3d8b..25e701ee6 100644
--- a/src/admin/scss/tainacan-admin.scss
+++ b/src/admin/scss/tainacan-admin.scss
@@ -1,3 +1,6 @@
+// TAINACAN ICON FONT
+@import "../../assets/css/fonts/tainacanicons.css";
+
// Tainacan custom colors and bulma's core
@import "./_variables.scss";
diff --git a/src/admin/tainacan-admin-i18n.php b/src/admin/tainacan-admin-i18n.php
index 381678d56..a97bee585 100644
--- a/src/admin/tainacan-admin-i18n.php
+++ b/src/admin/tainacan-admin-i18n.php
@@ -55,7 +55,7 @@ return apply_filters( 'tainacan-admin-i18n', [
'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_bulk' => __( 'Bulk add items', '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' ),
@@ -120,6 +120,7 @@ return apply_filters( 'tainacan-admin-i18n', [
'title_export_item_page' => __( 'Export Item', 'tainacan' ),
'title_export_page' => __( 'Export', 'tainacan' ),
'title_processes_page' => __( 'Processes', 'tainacan' ),
+ 'title_item_bulk_add' => __( 'Bulk Add Items', 'tainacan' ),
// Labels (used mainly on Aria Labels and Inputs)
'label_clean' => __( 'Clear', 'tainacan' ),
@@ -264,6 +265,7 @@ return apply_filters( 'tainacan-admin-i18n', [
'label_url_source_link' => __( 'URL Source link', 'tainacan' ),
'label_metadata_mapping' => __( 'Metadata mapping', 'tainacan' ),
'label_select_metadatum' => __( 'Select metadatum', 'tainacan' ),
+ 'label_create_metadatum' => __( 'Create 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' ),
@@ -309,12 +311,25 @@ return apply_filters( 'tainacan-admin-i18n', [
'label_untrash_selected_items' => __( 'Recover from trash', 'tainacan' ),
'label_value_not_informed' => __( 'Value not informed.', 'tainacan' ),
'label_description_not_informed' => __( 'Description not informed.', 'tainacan' ),
+ 'label_save_goto_metadata' => __( 'Save and Go to Metadata', 'tainacan' ),
+ 'label_save_goto_filter' => __( 'Save and Go to Filters', 'tainacan' ),
+ 'label_view_all_collections' => __( 'View all Collections', 'tainacan' ),
+ 'label_view_on_theme' => __( 'View on Theme', 'tainacan' ),
+ 'label_create_collection' => __( 'Create Collection', 'tainacan' ),
'label_hide_metadata' => __( 'Hide metadata', 'tainacan' ),
'label_show_metadata' => __( 'Show metadata', 'tainacan' ),
'label_all_terms' => __( 'All terms', 'tainacan' ),
'label_selected_terms' => __( 'Selected terms', 'tainacan'),
'label_editing_item_number' => __( 'Editing item n.', 'tainacan'),
'label_sequence_editing_item' => __( 'Sequence editing: Item', 'tainacan'),
+ 'label_files_remaining' => __( 'files remaining.', 'tainacan'),
+ 'label_file_remaining' => __( 'file remaining.', 'tainacan'),
+ 'label_upload_file_prepare_items' => __( 'Uploading files and preparing items', 'tainacan'),
+ 'label_bulk_edit_items' => __( 'Bulk edit items', 'tainacan'),
+ 'label_sequence_edit_items' => __( 'Sequence edit items', 'tainacan'),
+ 'label_documents_upload' => __( 'Documents upload', 'tainacan'),
+ 'label_added_items' => __( 'Added items', 'tainacan'),
+ 'label_filters_from' => __( 'Filters from', 'tainacan'),
// Instructions. More complex sentences to guide user and placeholders
'instruction_delete_selected_collections' => __( 'Delete selected collections', 'tainacan' ),
@@ -409,7 +424,7 @@ return apply_filters( 'tainacan-admin-i18n', [
'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_taxonomy_not_saved' => __( 'Are you sure? The taxonomy 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' ),
@@ -453,6 +468,7 @@ return apply_filters( 'tainacan-admin-i18n', [
'info_there_are_no_metadata_in_repository_level' => __( 'There are no metadata in repository level', 'tainacan' ),
'info_import_collection' => __( 'Import from external sources.', 'tainacan' ),
'info_import_items' => __( 'Import items from external sources.', 'tainacan' ),
+ 'info_bulk_add_items' => __( 'Bulk add documents from your computer as items.', 'tainacan' ),
'info_editing_items_in_bulk' => __( 'Bulk edit items', 'tainacan' ),
'info_by_inner' => __( 'by', 'tainacan' ),
'info_items_selected' => __( 'items selected', 'tainacan' ),
@@ -461,7 +477,19 @@ return apply_filters( 'tainacan-admin-i18n', [
'info_no_parent_term_found' => __( 'No valid parent term was found with this name.', 'tainacan' ),
'info_warning_changing_parent_term' => __( 'Warning! Changing parent term will reload the terms list, thus uncheking any selection.', 'tainacan' ),
'info_warning_selected_items_remove_from_trash' => __( 'Do you really want to remove from trash the selected items?', 'tainacan'),
-
+ 'info_no_options_avialable_filtering' => __( 'No options for this filtering.', 'tainacan'),
+ 'info_no_options_found' => __( 'No options found.', 'tainacan'),
+ 'info_all_files_uploaded' => __( 'All files uploaded.', 'tainacan'),
+ 'info_there_are' => __( 'There are', 'tainacan'),
+ 'info_items_being_edited' => __( 'items being edited', 'tainacan'),
+ 'info_there_is' => __( 'There is', 'tainacan'),
+ 'info_item_being_edited' => __( 'item being edited', 'tainacan'),
+ 'info_no_preview_found' => __( 'No preview was found.', 'tainacan'),
+ 'info_leaving_bulk_edition' => __( 'You are leaving the bulk edition now.', 'tainacan'),
+ 'info_leaving_bulk_edition' => __( 'You are leaving the bulk edition now.', 'tainacan'),
+ 'info_current_view_mode_metadata_not_allowed' => __( 'Current view mode does not allow displayed metadata selection.', 'tainacan'),
+ 'info_cant_select_metadata_without_items' => __( 'Can not select displayed metadata without items on list.', 'tainacan'),
+
// Tainacan Metadatum Types
'tainacan-text' => __( 'Text', 'tainacan' ),
'tainacan-textarea' => __( 'Text area', 'tainacan' ),
diff --git a/src/admin/theme-items-list.vue b/src/admin/theme-items-list.vue
index 87e22ae91..75d7ca2fb 100644
--- a/src/admin/theme-items-list.vue
+++ b/src/admin/theme-items-list.vue
@@ -10,6 +10,8 @@
v-if="$root.termId != undefined && $root.termId != ''"
class="theme-items-list"
:taxonomy="$root.taxonomy"
+ :custom-filters="$root.customFilters"
+ :collection-id="$root.collectionId"
:enabled-view-modes="$root.enabledViewModes"
:default-view-mode="$root.defaultViewMode"
:term-id="$root.termId" />
@@ -25,9 +27,10 @@ export default {
}
-
\ No newline at end of file
diff --git a/src/classes/filter-types/filter-types-mixin.js b/src/classes/filter-types/filter-types-mixin.js
index 694655398..5fe6fa89f 100644
--- a/src/classes/filter-types/filter-types-mixin.js
+++ b/src/classes/filter-types/filter-types-mixin.js
@@ -16,7 +16,16 @@ export const filter_type_mixin = {
collection_id: [Number], // not required, but overrides the filter metadatum id if is set
filter_type: [String], // not required, but overrides the filter metadatum type if is set
id: '',
- query: {}
+ query: {},
+ isLoadingOptions: false
+ },
+ mounted() {
+ // We listen to event, but reload event if hasFiltered is negative, as
+ // an empty query also demands filters reloading.
+ this.$eventBusSearch.$on('hasFiltered', () => {
+ if (typeof this.loadOptions == "function")
+ this.loadOptions(true);
+ });
},
methods: {
getValuesPlainText(metadatumId, search, isRepositoryLevel, valuesToIgnore, offset, number, isInCheckboxModal, getSelected = '0') {
@@ -32,16 +41,16 @@ export const filter_type_mixin = {
}
let query_items = { 'current_query': currentQuery };
- let url = `/collection/${this.collection}/facets/${metadatumId}?getSelected=${getSelected}&`;
-
+ let url = '';
+ if (isRepositoryLevel)
+ url = `/facets/${metadatumId}?getSelected=${getSelected}&`;
+ else
+ url = `/collection/${this.collection}/facets/${metadatumId}?getSelected=${getSelected}&`;
+
if(offset != undefined && number != undefined){
url += `offset=${offset}&number=${number}&`;
}
- if(isRepositoryLevel){
- url = `/facets/${metadatumId}`;
- }
-
if(search && offset != undefined && number != undefined){
url += `search=${search}&` + qs.stringify(query_items);
} else if(search){
@@ -49,11 +58,15 @@ export const filter_type_mixin = {
} else {
url += qs.stringify(query_items);
}
-
+
+ this.isLoadingOptions = true;
+
return new Object ({
request:
axios.tainacan.get(url, { cancelToken: source.token })
.then(res => {
+ this.isLoadingOptions = false;
+
let sResults = [];
let opts = [];
@@ -64,24 +77,28 @@ export const filter_type_mixin = {
if (search && isInCheckboxModal) {
sResults.push({
label: metadata.label,
- value: metadata.value
+ value: metadata.value,
+ total_items: metadata.total_items
});
} else if (indexToIgnore < 0) {
opts.push({
label: metadata.label,
- value: metadata.value
+ value: metadata.value,
+ total_items: metadata.total_items
});
}
} else {
if (search && isInCheckboxModal) {
sResults.push({
label: metadata.label,
- value: metadata.value
+ value: metadata.value,
+ total_items: metadata.total_items
});
} else {
opts.push({
label: metadata.label,
- value: metadata.value
+ value: metadata.value,
+ total_items: metadata.total_items
});
}
}
@@ -115,13 +132,14 @@ export const filter_type_mixin = {
if (axios.isCancel(thrown)) {
console.log('Request canceled: ', thrown.message);
} else {
+ this.isLoadingOptions = false;
reject(thrown);
}
}),
source: source
});
},
- getValuesRelationship(collectionTarget, search, valuesToIgnore, offset, number, isInCheckboxModal, getSelected = '0') {
+ getValuesRelationship(collectionTarget, search, isRepositoryLevel, valuesToIgnore, offset, number, isInCheckboxModal, getSelected = '0') {
const source = axios.CancelToken.source();
@@ -133,8 +151,13 @@ export const filter_type_mixin = {
}
}
let query_items = { 'current_query': currentQuery };
- let url = '/collection/' + this.filter.collection_id + '/facets/' + this.filter.metadatum.metadatum_id + `?getSelected=${getSelected}&`;
+ let url = '';
+ if (isRepositoryLevel)
+ url = '/facets/' + this.filter.metadatum.metadatum_id + `?getSelected=${getSelected}&`;
+ else
+ url = '/collection/' + this.filter.collection_id + '/facets/' + this.filter.metadatum.metadatum_id + `?getSelected=${getSelected}&`;
+
if(offset != undefined && number != undefined){
url += `offset=${offset}&number=${number}`;
} else {
@@ -145,10 +168,14 @@ export const filter_type_mixin = {
url += `&search=${search}`;
}
+ this.isLoadingOptions = true;
+
return new Object ({
request:
- axios.tainacan.get(url + '&fetch_only[0]=thumbnail&fetch_only[1]=title&fetch_only[2]=id&' + qs.stringify(query_items))
+ axios.tainacan.get(url + '&fetch_only[0]=thumbnail&fetch_only[1]=title&fetch_only[2]=id&' + qs.stringify(query_items))
.then(res => {
+ this.isLoadingOptions = false;
+
let sResults = [];
let opts = [];
@@ -160,13 +187,15 @@ export const filter_type_mixin = {
if (search && isInCheckboxModal) {
sResults.push({
label: item.label,
- value: item.value
+ value: item.value,
+ total_items: item.total_items
});
} else if (indexToIgnore < 0) {
opts.push({
label: item.label,
value: item.value,
- img: (item.img ? item.img : this.thumbPlaceholderPath)
+ img: (item.img ? item.img : this.thumbPlaceholderPath),
+ total_items: item.total_items
});
}
} else {
@@ -174,13 +203,15 @@ export const filter_type_mixin = {
sResults.push({
label: item.label,
value: item.value,
- img: (item.img ? item.img : this.thumbPlaceholderPath)
+ img: (item.img ? item.img : this.thumbPlaceholderPath),
+ total_items: item.total_items
});
} else {
opts.push({
label: item.label,
value: item.value,
- img: (item.img ? item.img : this.thumbPlaceholderPath)
+ img: (item.img ? item.img : this.thumbPlaceholderPath),
+ total_items: item.total_items
});
}
}
@@ -210,8 +241,13 @@ export const filter_type_mixin = {
}
})
- .catch(error => {
- this.$console.error(error);
+ .catch((thrown) => {
+ if (axios.isCancel(thrown)) {
+ console.log('Request canceled: ', thrown.message);
+ } else {
+ this.isLoadingOptions = false;
+ reject(thrown);
+ }
}),
source: source
});
diff --git a/src/classes/filter-types/selectbox/Selectbox.vue b/src/classes/filter-types/selectbox/Selectbox.vue
index 7ac0e8e5b..bdd78ff99 100644
--- a/src/classes/filter-types/selectbox/Selectbox.vue
+++ b/src/classes/filter-types/selectbox/Selectbox.vue
@@ -2,7 +2,7 @@
{{ option.label }}
+ :value="option.value">
+ {{ option.label }}
+ {{ "(" + option.total_items + ")" }}
+
@@ -53,7 +58,6 @@
},
data(){
return {
- isLoading: false,
options: [],
type: '',
collection: '',
@@ -76,7 +80,6 @@
},
methods: {
loadOptions(){
- this.isLoading = true;
// Cancels previous Request
if (this.getOptionsValuesCancel != undefined)
@@ -84,14 +87,11 @@
let promise = null;
promise = this.getValuesPlainText( this.metadatum, null, this.isRepositoryLevel );
-
promise.request
.then(() => {
- this.isLoading = false;
})
.catch( error => {
this.$console.error('error select', error );
- this.isLoading = false;
});
// Search Request Token for cancelling
diff --git a/src/classes/filter-types/taginput/Taginput.vue b/src/classes/filter-types/taginput/Taginput.vue
index 231c12020..47c17280f 100644
--- a/src/classes/filter-types/taginput/Taginput.vue
+++ b/src/classes/filter-types/taginput/Taginput.vue
@@ -7,11 +7,12 @@
:data="options"
autocomplete
expanded
+ :loading="isLoadingOptions"
:remove-on-keys="[]"
field="label"
attached
@typing="search"
- :placeholder="(type == 'Tainacan\\Metadata_Types\\Relationship') ? $i18n.get('info_type_to_add_items') : $i18n.get('info_type_to_add_metadata')">
+ :placeholder="(type == 'Tainacan\\Metadata_Types\\Relationship') ? $i18n.get('info_type_to_search_items') : $i18n.get('info_type_to_add_metadata')">
+ {{ $i18n.get('info_no_options_found' ) }}
@@ -119,7 +124,7 @@
if ( this.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, query, valuesToIgnore );
+ promise = this.getValuesRelationship( collectionTarget, query, this.isRepositoryLevel, valuesToIgnore );
} else {
promise = this.getValuesPlainText( this.metadatum, query, this.isRepositoryLevel, valuesToIgnore );
diff --git a/src/classes/filter-types/tainacan-filter-item.vue b/src/classes/filter-types/tainacan-filter-item.vue
index f10066e7b..ac6ad61aa 100644
--- a/src/classes/filter-types/tainacan-filter-item.vue
+++ b/src/classes/filter-types/tainacan-filter-item.vue
@@ -17,9 +17,11 @@
class="label"
slot="trigger"
slot-scope="props">
-
+
+
+
{{ filter.name }}
diff --git a/src/classes/filter-types/taxonomy/Checkbox.vue b/src/classes/filter-types/taxonomy/Checkbox.vue
index 1bcd02d8e..2d4ad463d 100644
--- a/src/classes/filter-types/taxonomy/Checkbox.vue
+++ b/src/classes/filter-types/taxonomy/Checkbox.vue
@@ -8,20 +8,36 @@
-
{{ option.label }}
+ class="b-checkbox checkbox is-small">
+
+
+
+ {{ option.label }}
+ {{ "(" + option.total_items + ")" }}
+
+
+
+ {{ $i18n.get('info_no_options_avialable_filtering') }}
+
@@ -38,7 +54,15 @@
this.loadOptions();
this.$eventBusSearch.$on('removeFromFilterTag', this.cleanSearchFromTag);
- },
+ },
+ mounted(){
+ // We listen to event, but reload event if hasFiltered is negative, as
+ // an empty query also demands filters reloading.
+ this.$eventBusSearch.$on('hasFiltered', () => {
+ if (typeof this.loadOptions == "function")
+ this.loadOptions(true);
+ });
+ },
data(){
return {
isLoading: false,
@@ -70,15 +94,16 @@
}
},
methods: {
- loadOptions(){
+ loadOptions(skipSelected){
this.isLoading = true;
let query_items = { 'current_query': this.query };
- let route = `/collection/${this.collection}/facets/${this.metadatum}?getSelected=1&hideempty=0&order=asc&parent=0&number=${this.filter.max_options}&` + qs.stringify(query_items);
-
- if(this.collection == 'filter_in_repository'){
- route = `/facets/${this.metadatum}?getSelected=1&hideempty=0&order=asc&parent=0&number=${this.filter.max_options}&` + qs.stringify(query_items);
- }
+ let route = '';
+
+ if(this.collection == 'filter_in_repository')
+ route = `/facets/${this.metadatum}?getSelected=1&order=asc&parent=0&number=${this.filter.max_options}&` + qs.stringify(query_items);
+ else
+ route = `/collection/${this.collection}/facets/${this.metadatum}?getSelected=1&order=asc&parent=0&number=${this.filter.max_options}&` + qs.stringify(query_items);
this.options = [];
@@ -88,10 +113,15 @@
for (let item of res.data) {
this.taxonomy = item.taxonomy;
this.taxonomy_id = item.taxonomy_id;
- this.options.push(item);
+
+ let existingOptionIndex = this.options.findIndex(anOption => anOption.value == item.value)
+ if (existingOptionIndex < 0)
+ this.options.push(item);
+ else
+ this.$set(this.options, item, existingOptionIndex);
}
- if ( this.options ){
+ if (this.options) {
let hasChildren = false;
for( let term of this.options ){
@@ -117,7 +147,9 @@
}
this.isLoading = false;
- this.selectedValues();
+ if (skipSelected == undefined || skipSelected == false) {
+ this.selectedValues();
+ }
})
.catch(error => {
this.$console.log(error);
@@ -153,28 +185,45 @@
let valueIndex = this.options.findIndex(option => option.value == selected );
if (valueIndex >= 0) {
- onlyLabels.push(this.options[valueIndex].label)
+
+ let existingLabelIndex = onlyLabels.findIndex(aLabel => aLabel == this.options[valueIndex].label)
+ if (existingLabelIndex < 0)
+ onlyLabels.push(this.options[valueIndex].label);
+ else
+ this.$set(onlyLabels, onlyLabels.push(this.options[valueIndex].label), existingLabelIndex);
+
} else {
- let route = '/collection/'+ this.collection +'/facets/' + this.metadatum +`?term_id=${selected}&fetch_only[0]=name&fetch_only[1]=id`;
-
- if(this.collection == 'filter_in_repository'){
- route = '/facets/' + this.metadatum +`?term_id=${selected}&fetch_only[0]=name&fetch_only[1]=id`
- }
-
+ let route = '';
+
+ if(this.collection == 'filter_in_repository')
+ route = '/facets/' + this.metadatum +`?term_id=${selected}&fetch_only[0]=name&fetch_only[1]=id`;
+ else
+ route = '/collection/'+ this.collection +'/facets/' + this.metadatum +`?term_id=${selected}&fetch_only[0]=name&fetch_only[1]=id`;
+
axios.get(route)
.then( res => {
-
if(!res || !res.data){
return false;
}
- onlyLabels.push(res.data[0].label);
- this.options.push({
- isChild: true,
- label: res.data[0].label,
- value: res.data[0].value
- })
+ let existingLabelIndex = onlyLabels.findIndex(aLabel => aLabel == res.data[0].label)
+ if (existingLabelIndex < 0) {
+ onlyLabels.push(res.data[0].label);
+ this.options.push({
+ isChild: true,
+ label: res.data[0].label,
+ value: res.data[0].value
+ });
+ } else {
+ this.$set(onlyLabels, onlyLabels.push(res.data[0].label), existingLabelIndex);
+ this.$set(this.options, {
+ isChild: true,
+ label: res.data[0].label,
+ value: res.data[0].value
+ }
+ , existingLabelIndex);
+ }
})
.catch(error => {
this.$console.log(error);
@@ -257,4 +306,21 @@
border-top-color: #dbdbdb !important;
border-right-color: #dbdbdb !important;
}
+
+ .no-options-placeholder {
+ margin-left: 0.5rem;
+ font-size: 0.75rem;
+ color: #898d8f;
+ }
+
+ .b-checkbox .control-label {
+ display: flex;
+ flex-wrap: nowrap;
+ width: 100%;
+ }
+ .checkbox-label-text {
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
diff --git a/src/classes/filter-types/taxonomy/Taginput.vue b/src/classes/filter-types/taxonomy/Taginput.vue
index 9da74cecc..57f03e996 100644
--- a/src/classes/filter-types/taxonomy/Taginput.vue
+++ b/src/classes/filter-types/taxonomy/Taginput.vue
@@ -6,13 +6,26 @@
v-model="selected"
:data="options"
autocomplete
+ :loading="isLoading"
expanded
:remove-on-keys="[]"
field="label"
attached
:class="{'has-selected': selected != undefined && selected != []}"
@typing="search"
- :placeholder="$i18n.get('info_type_to_add_terms')" />
+ :placeholder="$i18n.get('info_type_to_add_terms')">
+
+
+
+ {{ $i18n.get('info_no_options_found' ) }}
+
@@ -101,7 +114,7 @@
let endpoint = this.isRepositoryLevel ? '/facets/' + this.metadatum : '/collection/'+ this.collection +'/facets/' + this.metadatum;
- endpoint += '?hideempty=0&order=asc&' + qs.stringify(query_items);
+ endpoint += '?order=asc&' + qs.stringify(query_items);
let valuesToIgnore = [];
for(let val of this.selected){
valuesToIgnore.push( val.value );
@@ -147,7 +160,7 @@
},
getTerm( taxonomy, id ){
//getting a specific value from api, does not need be in fecat api
- return axios.get('/taxonomy/' + taxonomy + '/terms/' + id + '?order=asc&hideempty=0' )
+ return axios.get('/taxonomy/' + taxonomy + '/terms/' + id + '?order=asc' )
.then( res => {
this.selected.push({ label: res.data.name, value: res.data.id })
})
diff --git a/src/classes/metadata-types/core-description/class-tainacan-core-description.php b/src/classes/metadata-types/core-description/class-tainacan-core-description.php
index 425b09f65..3590e0ef3 100644
--- a/src/classes/metadata-types/core-description/class-tainacan-core-description.php
+++ b/src/classes/metadata-types/core-description/class-tainacan-core-description.php
@@ -19,6 +19,8 @@ class Core_Description extends Metadata_Type {
$this->set_core(true);
$this->set_related_mapped_prop('description');
$this->set_component('tainacan-textarea');
+ $this->set_name( __('Core Description', 'tainacan') );
+ $this->set_description( __('The fixed "Description" metadatum automatically created to all collection. This is the default description displayed in items lists and where basic search features will look', 'tainacan') );
}
/**
@@ -94,7 +96,7 @@ class Core_Description extends Metadata_Type {
foreach ( $value as $el ) {
$return .= nl2br($this->make_clickable_links($el));
$count ++;
- if ($count <= $total)
+ if ($count < $total)
$return .= ', ';
}
} else {
diff --git a/src/classes/metadata-types/core-title/class-tainacan-core-title.php b/src/classes/metadata-types/core-title/class-tainacan-core-title.php
index e0910ea72..50d911722 100644
--- a/src/classes/metadata-types/core-title/class-tainacan-core-title.php
+++ b/src/classes/metadata-types/core-title/class-tainacan-core-title.php
@@ -19,6 +19,8 @@ class Core_Title extends Metadata_Type {
$this->set_core(true);
$this->set_related_mapped_prop('title');
$this->set_component('tainacan-text');
+ $this->set_name( __('Core Description', 'tainacan') );
+ $this->set_description( __('The fixed "Title" metadatum automatically created to all collection. This is the default title displayed in items lists and where basic search features will look', 'tainacan') );
}
/**
diff --git a/src/classes/metadata-types/date/Date.vue b/src/classes/metadata-types/date/Date.vue
index cadd1441e..5f67b6bea 100644
--- a/src/classes/metadata-types/date/Date.vue
+++ b/src/classes/metadata-types/date/Date.vue
@@ -18,7 +18,7 @@
class="has-text-danger is-italic is-size-7">{{ $i18n.get('info_error_invalid_date') }}
-
+
diff --git a/src/classes/metadata-types/date/class-tainacan-date.php b/src/classes/metadata-types/date/class-tainacan-date.php
index 9bbd54035..7d0e5c339 100644
--- a/src/classes/metadata-types/date/class-tainacan-date.php
+++ b/src/classes/metadata-types/date/class-tainacan-date.php
@@ -17,6 +17,8 @@ class Date extends Metadata_Type {
parent::__construct();
$this->set_primitive_type('date');
$this->set_component('tainacan-date');
+ $this->set_name( __('Date', 'tainacan') );
+ $this->set_description( __('Exact date type, with day, month and year.', 'tainacan') );
}
/**
@@ -33,15 +35,21 @@ class Date extends Metadata_Type {
public function validate( Item_Metadata_Entity $item_metadata) {
-
$value = $item_metadata->get_value();
-
$format = 'Y-m-d';
- $d = \DateTime::createFromFormat($format, $value);
+ if (is_array($value)) {
+ foreach ($value as $date_value) {
+ $d = \DateTime::createFromFormat($format, $date_value);
+ if ( !($d && $d->format($format) === $date_value) ) {
+ return false;
+ }
+ }
+ return True;
+ }
+ $d = \DateTime::createFromFormat($format, $value);
return $d && $d->format($format) === $value;
-
}
diff --git a/src/classes/metadata-types/metadata-type/class-tainacan-metadata-type.php b/src/classes/metadata-types/metadata-type/class-tainacan-metadata-type.php
index 957f2e85a..f7a7d8b08 100644
--- a/src/classes/metadata-types/metadata-type/class-tainacan-metadata-type.php
+++ b/src/classes/metadata-types/metadata-type/class-tainacan-metadata-type.php
@@ -63,6 +63,16 @@ abstract class Metadata_Type {
* @var bool | string
*/
private $form_component = false;
+
+ /**
+ * The Metadata type name. Metadata type classes must set an internationalized string for this property
+ */
+ private $name;
+
+ /**
+ * The Metadata type description. Metadata type classes must set an internationalized string for this property
+ */
+ private $description;
abstract function render( $itemMetadata );
@@ -114,6 +124,22 @@ abstract class Metadata_Type {
$this->form_component = $form_component;
}
+ public function get_name(){
+ return $this->name;
+ }
+
+ public function set_name($name){
+ $this->name = $name;
+ }
+
+ public function get_description(){
+ return $this->description;
+ }
+
+ public function set_description($description){
+ $this->description = $description;
+ }
+
/**
* @param $options
*/
@@ -163,7 +189,9 @@ abstract class Metadata_Type {
public function _toArray(){
$attributes = [];
- $attributes['errors'] = $this->get_errors();
+ $attributes['name'] = $this->get_name();
+ $attributes['description'] = $this->get_description();
+ $attributes['errors'] = $this->get_errors();
$attributes['related_mapped_prop'] = $this->get_related_mapped_prop();
$attributes['options'] = $this->get_options();
$attributes['className'] = get_class($this);
diff --git a/src/classes/metadata-types/numeric/class-tainacan-numeric.php b/src/classes/metadata-types/numeric/class-tainacan-numeric.php
index 6c507510a..e91ccff61 100644
--- a/src/classes/metadata-types/numeric/class-tainacan-numeric.php
+++ b/src/classes/metadata-types/numeric/class-tainacan-numeric.php
@@ -14,6 +14,8 @@ class Numeric extends Metadata_Type {
parent::__construct();
$this->set_primitive_type('float');
$this->set_component('tainacan-numeric');
+ $this->set_name( __('Numeric', 'tainacan') );
+ $this->set_description( __('A numeric value, integer or float', 'tainacan') );
}
/**
diff --git a/src/classes/metadata-types/relationship/Relationship.vue b/src/classes/metadata-types/relationship/Relationship.vue
index 1b5532bd7..ce2ab340f 100644
--- a/src/classes/metadata-types/relationship/Relationship.vue
+++ b/src/classes/metadata-types/relationship/Relationship.vue
@@ -1,6 +1,7 @@
set_primitive_type('item');
$this->set_component('tainacan-relationship');
$this->set_form_component('tainacan-form-relationship');
+ $this->set_name( __('Relationship', 'tainacan') );
+ $this->set_description( __('A relationship with another item', 'tainacan') );
}
/**
diff --git a/src/classes/metadata-types/selectbox/FormSelectbox.vue b/src/classes/metadata-types/selectbox/FormSelectbox.vue
index 5387c36ad..4ce580089 100644
--- a/src/classes/metadata-types/selectbox/FormSelectbox.vue
+++ b/src/classes/metadata-types/selectbox/FormSelectbox.vue
@@ -15,10 +15,9 @@
v-model="options"
@input="emitValues()"
@focus="clear()"
- icon="label"
attached
:class="{'has-selected': options != undefined && options != []}"
- :placeholder="$i18n.get('new')"/>
+ :placeholder="$i18n.get('new') + ', ...'"/>
diff --git a/src/classes/metadata-types/selectbox/Selectbox.vue b/src/classes/metadata-types/selectbox/Selectbox.vue
index 2f0d940b7..532a63b64 100644
--- a/src/classes/metadata-types/selectbox/Selectbox.vue
+++ b/src/classes/metadata-types/selectbox/Selectbox.vue
@@ -1,6 +1,7 @@
set_primitive_type('string');
$this->set_component('tainacan-selectbox');
$this->set_form_component('tainacan-form-selectbox');
+ $this->set_name( __('Selectbox', 'tainacan') );
+ $this->set_description( __('A selectbox with a fixed list of value to choose one from', 'tainacan') );
}
/**
diff --git a/src/classes/metadata-types/tainacan-form-item.vue b/src/classes/metadata-types/tainacan-form-item.vue
index a25bdf361..2177d2caa 100644
--- a/src/classes/metadata-types/tainacan-form-item.vue
+++ b/src/classes/metadata-types/tainacan-form-item.vue
@@ -6,10 +6,20 @@
-
- {{ metadatum.metadatum.name }}
+
+
+
+
+ {{ metadatum.metadatum.name }}
+
- {{ $i18n.get('label_remove_value') }}
+ {{ $i18n.get('label_remove_value') }}
-
- {{ $i18n.get('label_add_value') }}
+
+
+
+ {{ $i18n.get('label_add_value') }}
@@ -230,12 +239,13 @@
font-weight: 500;
margin-left: 15px;
margin-bottom: 0.5em;
+ max-width: 50%;
}
.metadata-type {
font-size: 0.8125rem;
font-weight: 400;
color: $gray3;
- top: -0.2em;
+ top: -0.4em;
position: relative;
}
.help-wrapper {
@@ -245,6 +255,7 @@
cursor: pointer;
position: relative;
margin-left: -42px;
+ white-space: nowrap;
}
}
diff --git a/src/classes/metadata-types/taxonomy/AddNewTerm.vue b/src/classes/metadata-types/taxonomy/AddNewTerm.vue
index 649a1bdee..3af20f1e7 100644
--- a/src/classes/metadata-types/taxonomy/AddNewTerm.vue
+++ b/src/classes/metadata-types/taxonomy/AddNewTerm.vue
@@ -4,11 +4,10 @@
-
- {{ $i18n.get('label_new_term') }}
+
+
+
+ {{ $i18n.get('label_new_term') }}
diff --git a/src/classes/metadata-types/taxonomy/class-tainacan-taxonomy.php b/src/classes/metadata-types/taxonomy/class-tainacan-taxonomy.php
index 61406e10c..e1b463490 100644
--- a/src/classes/metadata-types/taxonomy/class-tainacan-taxonomy.php
+++ b/src/classes/metadata-types/taxonomy/class-tainacan-taxonomy.php
@@ -23,7 +23,9 @@ class Taxonomy extends Metadata_Type {
]);
$this->set_form_component('tainacan-form-taxonomy');
- $this->set_component('tainacan-taxonomy');
+ $this->set_component('tainacan-taxonomy');
+ $this->set_name( __('Taxonomy', 'tainacan') );
+ $this->set_description( __('A metadatum to use a taxonomy in this collection', 'tainacan') );
}
/**
@@ -124,6 +126,7 @@ class Taxonomy extends Metadata_Type {
$term = $term->get_id();
}
+ // TODO term_exists is not fully reliable. Use $terms_repository->term_exists. see issue #159
if (!term_exists($term)) {
$valid = false;
break;
@@ -177,4 +180,16 @@ class Taxonomy extends Metadata_Type {
}
+ public function _toArray() {
+
+ $array = parent::_toArray();
+
+ if ( isset($array['options']['taxonomy_id']) ) {
+ $array['options']['taxonomy'] = \Tainacan\Repositories\Taxonomies::get_instance()->get_db_identifier_by_id( $array['options']['taxonomy_id'] );
+ }
+
+ return $array;
+
+ }
+
}
\ No newline at end of file
diff --git a/src/classes/metadata-types/text/class-tainacan-text.php b/src/classes/metadata-types/text/class-tainacan-text.php
index da4540584..2d75b5e30 100644
--- a/src/classes/metadata-types/text/class-tainacan-text.php
+++ b/src/classes/metadata-types/text/class-tainacan-text.php
@@ -14,7 +14,9 @@ class Text extends Metadata_Type {
// call metadatum type constructor
parent::__construct();
parent::set_primitive_type('string');
- parent::set_component('tainacan-text');
+ parent::set_component('tainacan-text');
+ $this->set_name( __('Text', 'tainacan') );
+ $this->set_description( __('A simple, one line, text input', 'tainacan') );
}
/**
@@ -42,7 +44,7 @@ class Text extends Metadata_Type {
foreach ( $value as $el ) {
$return .= $this->make_clickable_links($el);
$count ++;
- if ($count <= $total)
+ if ($count < $total)
$return .= ', ';
}
} else {
diff --git a/src/classes/metadata-types/textarea/class-tainacan-textarea.php b/src/classes/metadata-types/textarea/class-tainacan-textarea.php
index f1dfc4780..207467591 100644
--- a/src/classes/metadata-types/textarea/class-tainacan-textarea.php
+++ b/src/classes/metadata-types/textarea/class-tainacan-textarea.php
@@ -14,7 +14,9 @@ class Textarea extends Metadata_Type {
// call metadatum type constructor
parent::__construct();
$this->set_primitive_type('long_string');
- $this->set_component('tainacan-textarea');
+ $this->set_component('tainacan-textarea');
+ $this->set_name( __('Textarea', 'tainacan') );
+ $this->set_description( __('A textarea with multiple lines', 'tainacan') );
}
/**
@@ -43,7 +45,7 @@ class Textarea extends Metadata_Type {
foreach ( $value as $el ) {
$return .= nl2br($this->make_clickable_links($el));
$count ++;
- if ($count <= $total)
+ if ($count < $total)
$return .= ', ';
}
} else {
diff --git a/src/classes/repositories/class-tainacan-filters.php b/src/classes/repositories/class-tainacan-filters.php
index 0d50a33b2..c77a87957 100644
--- a/src/classes/repositories/class-tainacan-filters.php
+++ b/src/classes/repositories/class-tainacan-filters.php
@@ -351,6 +351,25 @@ class Filters extends Repository {
return $supported_filter_types;
}
+
+ /**
+ * fetch filters IDs based on WP_Query args
+ *
+ * to learn all args accepted in the $args parameter (@see https://developer.wordpress.org/reference/classes/wp_query/)
+ * You can also use a mapped property, such as name and description, as an argument and it will be mapped to the
+ * appropriate WP_Query argument
+ *
+ * @param array $args WP_Query args || int $args the item id
+ *
+ * @return Array array of IDs;
+ * @throws \Exception
+ */
+ public function fetch_ids( $args = [] ) {
+
+ $args['fields'] = 'ids';
+
+ return $this->fetch( $args )->get_posts();
+ }
/**
* fetch filters by collection, searches all filters available
@@ -372,13 +391,17 @@ class Filters extends Repository {
$parents[] = $collection_id;
//search for default metadatum
- //$parents[] = $this->get_default_metadata_attribute();
+ $parents[] = 'filter_in_repository';
$meta_query = array(
'key' => 'collection_id',
'value' => $parents,
'compare' => 'IN',
);
+
+ $args = array_merge( [
+ 'parent' => 0
+ ], $args );
if ( isset( $args['meta_query'] ) ) {
$args['meta_query'][] = $meta_query;
@@ -392,6 +415,53 @@ class Filters extends Repository {
isset( $args['include_disabled'] ) ? $args['include_disabled'] : false
);
}
+
+ /**
+ * fetch filters IDs by collection, considering inheritance
+ *
+ * @param Entities\Collection|int $collection object or ID
+ * @param array $args WP_Query args plus disabled_metadata
+ *
+ * @return array List of metadata IDs
+ * @throws \Exception
+ */
+ public function fetch_ids_by_collection( $collection, $args = [] ) {
+
+ if ( $collection instanceof Entities\Collection ) {
+ $collection_id = $collection->get_id();
+ } elseif ( is_integer( $collection ) ) {
+ $collection_id = $collection;
+ } else {
+ throw new \InvalidArgumentException( 'fetch_ids_by_collection expects paramater 1 to be a integer or a \Tainacan\Entities\Collection object. ' . gettype( $collection ) . ' given' );
+ }
+
+ //get parent collections
+ $parents = get_post_ancestors( $collection_id );
+
+ //insert the actual collection
+ $parents[] = $collection_id;
+
+ //search for default metadatum
+ $parents[] = 'filter_in_repository';
+
+ $meta_query = array(
+ 'key' => 'collection_id',
+ 'value' => $parents,
+ 'compare' => 'IN',
+ );
+
+ $args = array_merge( [
+ 'parent' => 0
+ ], $args );
+
+ if ( isset( $args['meta_query'] ) ) {
+ $args['meta_query'][] = $meta_query;
+ } elseif ( is_array( $args ) ) {
+ $args['meta_query'] = array( $meta_query );
+ }
+
+ return $this->fetch_ids( $args );
+ }
/**
* Ordinate the result from fetch response if $collection has an ordination,
diff --git a/src/classes/repositories/class-tainacan-logs.php b/src/classes/repositories/class-tainacan-logs.php
index 95b03661a..0164fdf11 100644
--- a/src/classes/repositories/class-tainacan-logs.php
+++ b/src/classes/repositories/class-tainacan-logs.php
@@ -361,18 +361,23 @@ class Logs extends Repository {
* @return string
*/
private function prepare_event_message( $object, $name, $class_name, $action_message ) {
+
+ // translators: 1=Object name, 2=Object type, 3=Action. e.g. The "Subject" taxonomy has been created
+ $msg_format = __( 'The "%1$s" %2$s has been %3$s', 'tainacan' );
+
if ( $object instanceof Entities\Metadatum || $object instanceof Entities\Item || $object instanceof Entities\Filter ) {
$collection = $object->get_collection();
if ( $collection ) {
- $parent = '(parent: ' . $collection->get_name() . ')';
+ $parent = sprintf( __('(collection: %s)', 'tainacan'), $collection->get_name() );
} else {
- $parent = '(on repository level)';
+ $parent = __('(on repository level)', 'tainacan');
}
-
- $description = sprintf( __( "The \"%s\" %s has been %s %s.", 'tainacan' ), $name, strtolower( $class_name ), $action_message, $parent );
+
+ $description = sprintf( $msg_format, $name, strtolower( $class_name ), $action_message );
+ $description .= ' ' . $parent . '.';
} else {
- $description = sprintf( __( "The \"%s\" %s has been %s.", 'tainacan' ), $name, strtolower( $class_name ), $action_message );
+ $description = sprintf( $msg_format, $name, strtolower( $class_name ), $action_message ) . '.';
}
return $description;
diff --git a/src/classes/repositories/class-tainacan-metadata.php b/src/classes/repositories/class-tainacan-metadata.php
index 542e47115..bc06a9c6c 100644
--- a/src/classes/repositories/class-tainacan-metadata.php
+++ b/src/classes/repositories/class-tainacan-metadata.php
@@ -101,17 +101,17 @@ class Metadata extends Repository {
'map' => 'meta',
'title' => __( 'Required', 'tainacan' ),
'type' => 'string',
- 'description' => __( 'The metadata is required', 'tainacan' ),
+ 'description' => __( 'The metadata is required. All items in this collection must fill this field', 'tainacan' ),
'on_error' => __( 'The metadata content is invalid', 'tainacan' ),
'validation' => v::stringType()->in( [ 'yes', 'no' ] ), // yes or no
'default' => 'no'
],
'collection_key' => [
'map' => 'meta',
- 'title' => __( 'Collection key', 'tainacan' ),
+ 'title' => __( 'Unique value', 'tainacan' ),
'type' => 'string',
- 'description' => __( 'Metadata value should not be repeated', 'tainacan' ),
- 'on_error' => __( 'Collection key is invalid', 'tainacan' ),
+ 'description' => __( 'Metadata value should be unique accross all items in this collection', 'tainacan' ),
+ 'on_error' => __( 'You can not have two items with the same value for this metadatum', 'tainacan' ),
'validation' => v::stringType()->in( [ 'yes', 'no' ] ), // yes or no
'default' => 'no'
],
@@ -119,7 +119,7 @@ class Metadata extends Repository {
'map' => 'meta',
'title' => __( 'Multiple', 'tainacan' ),
'type' => 'string',
- 'description' => __( 'Allow multiple values for the metadata', 'tainacan' ),
+ 'description' => __( 'Allow items to have more than one value for this metadatum', 'tainacan' ),
'on_error' => __( 'Invalid multiple metadata', 'tainacan' ),
'validation' => v::stringType()->in( [ 'yes', 'no' ] ),
// yes or no. It cant be multiple if its collection_key
@@ -687,6 +687,7 @@ class Metadata extends Repository {
'collection_id' => $collection->get_id(),
'metadata_type' => 'Tainacan\Metadata_Types\Core_Title',
'status' => 'publish',
+ 'display' => 'yes',
'exposer_mapping' => [
'dublin-core' => 'title'
]
@@ -869,199 +870,307 @@ class Metadata extends Repository {
}
- # TODO: Fetch all metadatum value for repository level
-
/**
- * Fetch all values of a metadatum from a collection or repository
- *
- * @param $collection_id
- * @param $metadatum_id
- *
- * @param string $search
- *
- * @param int $offset
- * @param string $number
- *
- * @return array|null|object
- * @throws \Exception
- */
- public function fetch_all_metadatum_values( $collection_id, $metadatum_id, $search = '', $offset = 0, $number = '' ) {
+ * Return all possible values for a metadatum
+ *
+ * Each metadata is a label with the metadatum name and the value.
+ *
+ * If an ID, a slug or a Tainacan\Entities\Metadatum object is passed in the 'metadata' argument, it returns only one metadata, otherwise
+ * it returns all metadata
+ *
+ * @param int $metadatum_id The ID of the metadata to fetch values from
+ * @param array|string $args {
+ * Optional. Array or string of arguments.
+ *
+ * @type mixed $collection_id The collection ID you want to consider or null for all collections. If a collectoin is set
+ * then only values applied to items in this collection will be returned
+ *
+ * @type int $number The number of values to return (for pagination). Default 0 (unlimited)
+ *
+ * @type int $offset The offset (for pagination). Default 0
+ *
+ * @type array|bool $items_filter Array in the same format used in @see \Tainacan\Repositories\Items::fetch(). It will filter the results to only return values used in the items inside this criteria. If false, it will return all values, even unused ones. Defatul [] (all items)
+ *
+ * @type array $include Array if ids to be included in the result. Default [] (nothing)
+ *
+ * @type array $search String to search. It will only return values that has this string. Default '' (nothing)
+ *
+ * @type array $parent_id Used by taxonomy metadata. The ID of the parent term to retrieve terms from. Default 0
+ *
+ * @type bool $count_items Include the count of items that can be found in each value (uses $items_filter as well). Default false
+ *
+ * }
+ *
+ * @return array Array with the total number of values found. The total number of pages with the current number and the results with id and label for each value. Terms also include parent, taxonomy and number of children.
+ */
+ public function fetch_all_metadatum_values( $metadatum_id, $args = [] ) {
+
+ $defaults = array(
+ 'collection_id' => null,
+ 'search' => '',
+ 'offset' => 0,
+ 'number' => '',
+ 'include' => [],
+ 'items_filter' => [],
+ 'parent_id' => 0,
+ 'count_items' => false
+ );
+ $args = wp_parse_args($args, $defaults);
+
global $wpdb;
- // Clear the result cache
- $wpdb->flush();
-
- $metadatum = new Entities\Metadatum( $metadatum_id );
-
- // handle core titles
- if ( strpos( $metadatum->get_metadata_type(), 'Core' ) !== false && $search ) {
- $collection = new Entities\Collection( $collection_id );
- $Tainacan_Items = \Tainacan\Repositories\Items::get_instance();
-
- if ( $number >= 1 && $offset >= 0 ) {
- $items = $Tainacan_Items->fetch( [
- 's' => $search,
- 'offset' => $offset,
- 'posts_per_page' => $number
- ], $collection, 'OBJECT' );
- } else {
- $items = $Tainacan_Items->fetch( [ 's' => $search ], $collection, 'OBJECT' );
- }
-
- $return = [];
-
- foreach ( $items as $item ) {
- if ( strpos( $metadatum->get_metadata_type(), 'Core_Title' ) !== false ) {
- $title = $item->get_title();
-
- if ( ! empty( $search ) && stristr( $title, $search ) !== false ) {
- $return[] = [ 'metadatum_id' => $metadatum_id, 'mvalue' => $title ];
- } elseif ( empty( $search ) ) {
- $return[] = [ 'metadatum_id' => $metadatum_id, 'mvalue' => $title ];
- }
- } else {
- $description = $item->get_description();
-
- if ( ! empty( $search ) && stristr( $description, $search ) !== false ) {
- $return[] = [ 'metadatum_id' => $metadatum_id, 'mvalue' => $description ];
- } elseif ( empty( $search ) ) {
- $return[] = [ 'metadatum_id' => $metadatum_id, 'mvalue' => $description ];
- }
- }
- }
-
- return $return;
+ $itemsRepo = Items::get_instance();
+ $metadataRepo = Metadata::get_instance();
+
+ $metadatum = $metadataRepo->fetch($metadatum_id);
+ $metadatum_type = $metadatum->get_metadata_type();
+ $metadatum_options = $metadatum->get_metadata_type_options();
+
+ if ( $metadatum_type === 'Tainacan\Metadata_Types\Taxonomy' ) {
+ $taxonomy_id = $metadatum_options['taxonomy_id'];
+ $taxonomy_slug = Taxonomies::get_instance()->get_db_identifier_by_id($taxonomy_id);
}
-
- $item_post_type = "%%{$collection_id}_item";
-
- $collection = new Entities\Collection( $collection_id );
- $capabilities = $collection->get_capabilities();
-
- $results = [];
-
- $search_query = '';
- if ( $search ) {
- $search_param = '%' . $search . '%';
- $search_query = $wpdb->prepare( "WHERE meta_value LIKE %s", $search_param );
+
+
+ //////////////////////////////////////////
+ // Get the query for current items
+ // this avoids wp_query to run the query. We just want to build the query
+ $items_query = false;
+ if ( false !== $args['items_filter'] && is_array($args['items_filter']) ) {
+ add_filter('posts_pre_query', '__return_empty_array');
+
+ $args['items_filter']['fields'] = 'ids';
+ unset($args['items_filter']['paged']);
+ unset($args['items_filter']['offset']);
+ unset($args['items_filter']['perpage']);
+ $args['items_filter']['nopaging'] = 1;
+
+ // When filtering the items, we should consider only other metadata, and ignore current metadatum
+ // This is because the relation between values from the same metadatum when filtering item is OR,
+ // so when you filter items by one value of a metadatum you dont want to exclude all the other possibilities for that meta.
+ // Only values of all other filters (facets) are reduced.
+ if ( $metadatum_type == 'Tainacan\Metadata_Types\Taxonomy' && isset($args['items_filter']['tax_query']) && is_array($args['items_filter']['tax_query']) ) {
+ // remove current taxonomy from tax_query
+ $args['items_filter']['tax_query'] = array_filter($args['items_filter']['tax_query'], function($t) use ($taxonomy_slug) { return $t['taxonomy'] != $taxonomy_slug; });
+ } elseif ( $metadatum_type != 'Tainacan\Metadata_Types\Taxonomy' && isset($args['items_filter']['meta_query']) && is_array($args['items_filter']['meta_query']) ) {
+ // remove current metadata from meta_query
+ //var_dump($args['items_filter']['meta_query']);
+ $args['items_filter']['meta_query'] = array_filter($args['items_filter']['meta_query'], function($t) use ($metadatum_id) { return $t['key'] != $metadatum_id; });
+ //var_dump($args['items_filter']['meta_query']);
+ }
+
+ $items_query = $itemsRepo->fetch($args['items_filter'], $args['collection_id']);
+ $items_query = $items_query->request;
+
+ remove_filter('posts_pre_query', '__return_empty_array');
}
-
+ //// end filtering query ////////
+ ////////////////////////////////////////////
+ ////////////////////////////////////////////
+
$pagination = '';
- if ( $offset >= 0 && $number >= 1 ) {
- $pagination = $wpdb->prepare( "LIMIT %d,%d", (int) $offset, (int) $number );
+ if ( $args['offset'] >= 0 && $args['number'] >= 1 ) {
+ $pagination = $wpdb->prepare( "LIMIT %d,%d", (int) $args['offset'], (int) $args['number'] );
+ }
+
+ $search_q = '';
+ $search = trim($args['search']);
+ if (!empty($search)) {
+ if( $metadatum_type === 'Tainacan\Metadata_Types\Relationship' ) {
+ $search_q = $wpdb->prepare("AND meta_value IN ( SELECT ID FROM $wpdb->posts WHERE post_title LIKE %s )", '%' . $search . '%');
+ } elseif ( $metadatum_type === 'Tainacan\Metadata_Types\Taxonomy' ) {
+ $search_q = $wpdb->prepare("AND t.name LIKE %s", '%' . $search . '%');
+ } else {
+ $search_q = $wpdb->prepare("AND meta_value LIKE %s", '%' . $search . '%');
+ }
+
+
}
- // If no has logged user or actual user can not read private posts
- if ( get_current_user_id() === 0 || ! current_user_can( $capabilities->read_private_posts ) ) {
- $args = [
- 'exclude_from_search' => false,
- 'public' => true,
- 'private' => false,
- 'internal' => false,
- ];
-
- $post_statuses = get_post_stati( $args, 'names', 'and' );
-
- foreach ( $post_statuses as $post_status ) {
-
- if ( $collection_id ) {
- $sql_string = $wpdb->prepare(
- "SELECT DISTINCT metadatum_id, mvalue
- FROM (
- SELECT ID as item_id
- FROM $wpdb->posts
- WHERE post_type LIKE %s AND post_status = %s
- ) items
- JOIN (
- SELECT meta_key as metadatum_id, meta_value as mvalue, post_id
- FROM $wpdb->postmeta $search_query
- ) metas
- ON items.item_id = metas.post_id AND metas.metadatum_id = %d ORDER BY mvalue $pagination",
- $item_post_type, $post_status, $metadatum_id
- );
- } else {
- $sql_string = $wpdb->prepare(
- "SELECT DISTINCT metadatum_id, mvalue
- FROM (
- SELECT ID as item_id
- FROM $wpdb->posts
- WHERE post_status = %s
- ) items
- JOIN (
- SELECT meta_key as metadatum_id, meta_value as mvalue, post_id
- FROM $wpdb->postmeta $search_query
- ) metas
- ON items.item_id = metas.post_id AND metas.metadatum_id = %d ORDER BY mvalue $pagination",
- $post_status, $metadatum_id
- );
- }
-
- $pre_result = $wpdb->get_results( $sql_string, OBJECT );
-
- if ( ! empty( $pre_result ) ) {
- foreach ( $pre_result as $pre ) {
- $results[] = $pre;
- }
+ if ( $metadatum_type === 'Tainacan\Metadata_Types\Taxonomy' ) {
+
+ if ($items_query) {
+ $base_query = $wpdb->prepare("FROM $wpdb->term_relationships tr
+ INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
+ INNER JOIN $wpdb->terms t ON tt.term_id = t.term_id
+ WHERE
+ tt.parent = %d AND
+ tr.object_id IN ($items_query) AND
+ tt.taxonomy = %s
+ $search_q
+ ORDER BY t.name ASC
+ ",
+ $args['parent_id'],
+ $taxonomy_slug
+ );
+ } else {
+ $base_query = $wpdb->prepare("FROM $wpdb->term_taxonomy tt
+ INNER JOIN $wpdb->terms t ON tt.term_id = t.term_id
+ WHERE
+ tt.parent = %d AND
+ tt.taxonomy = %s
+ $search_q
+ ORDER BY t.name ASC
+ ",
+ $args['parent_id'],
+ $taxonomy_slug
+ );
+ }
+
+
+ $query = "SELECT DISTINCT t.name, tt.term_taxonomy_id, tt.parent $base_query $pagination";
+
+ $total_query = "SELECT COUNT(DISTINCT tt.term_taxonomy_id) $base_query";
+
+ $results = $wpdb->get_results($query);
+
+ // add selected to the result
+ if ( !empty($args['include']) ) {
+ if ( is_array($args['include']) && !empty($args['include']) ) {
+
+ // protect sql
+ $args['include'] = array_map(function($t) { return (int) $t; }, $args['include']);
+
+ $include_ids = implode(',', $args['include']);
+ $query_to_include = "SELECT DISTINCT t.name, tt.term_taxonomy_id, tt.parent FROM $wpdb->term_taxonomy tt
+ INNER JOIN $wpdb->terms t ON tt.term_id = t.term_id
+ WHERE
+ tt.term_taxonomy_id IN ($include_ids)";
+
+ $to_include = $wpdb->get_results($query_to_include);
+
+ // remove terms that will be included at the begining
+ $results = array_filter($results, function($t) use($args) { return !in_array($t->term_taxonomy_id, $args['include']); });
+
+ $results = array_merge($to_include, $results);
+
}
}
- } elseif ( current_user_can( $capabilities->read_private_posts ) ) {
- $args = [
- 'exclude_from_search' => false,
- ];
-
- $post_statuses = get_post_stati( $args, 'names', 'and' );
-
- foreach ( $post_statuses as $post_status ) {
-
- if ( $collection_id ) {
- $sql_string = $wpdb->prepare(
- "SELECT DISTINCT metadatum_id, mvalue
- FROM (
- SELECT ID as item_id
- FROM $wpdb->posts
- WHERE post_type LIKE %s AND post_status = %s
- ) items
- JOIN (
- SELECT meta_key as metadatum_id, meta_value as mvalue, post_id
- FROM $wpdb->postmeta $search_query
- ) metas
- ON items.item_id = metas.post_id AND metas.metadatum_id = %d ORDER BY mvalue $pagination",
- $item_post_type, $post_status, $metadatum_id
- );
- } else {
- $sql_string = $wpdb->prepare(
- "SELECT DISTINCT metadatum_id, mvalue
- FROM (
- SELECT ID as item_id
- FROM $wpdb->posts
- WHERE post_status = %s
- ) items
- JOIN (
- SELECT meta_key as metadatum_id, meta_value as mvalue, post_id
- FROM $wpdb->postmeta $search_query
- ) metas
- ON items.item_id = metas.post_id AND metas.metadatum_id = %d ORDER BY mvalue $pagination",
- $post_status, $metadatum_id
- );
- }
-
- $pre_result = $wpdb->get_results( $sql_string, OBJECT );
-
- if ( ! empty( $pre_result ) ) {
- foreach ( $pre_result as $pre ) {
- $results[] = $pre;
+
+ $total = $wpdb->get_var($total_query);
+ $number = is_integer($args['number']) && $args['number'] >=1 ? $args['number'] : $total;
+ if( $number < 1){
+ $pages = 1;
+ } else {
+ $pages = ceil( $total / $number );
+ }
+
+ $values = [];
+ foreach ($results as $r) {
+
+ $count_query = $wpdb->prepare("SELECT COUNT(term_id) FROM $wpdb->term_taxonomy WHERE parent = %d", $r->term_taxonomy_id);
+ $total_children = $wpdb->get_var($count_query);
+
+ $label = $r->name;
+ $total_items = null;
+
+ if ( $args['count_items'] ) {
+ $count_items_query = $args['items_filter'];
+ $count_items_query['posts_per_page'] = 1;
+ if ( !isset($count_items_query['tax_query']) ) {
+ $count_items_query['tax_query'] = [];
}
+ $count_items_query['tax_query'][] = [
+ 'taxonomy' => $taxonomy_slug,
+ 'terms' => $r->term_taxonomy_id
+ ];
+ $count_items_results = $itemsRepo->fetch($count_items_query, $args['collection_id']);
+ $total_items = $count_items_results->found_posts;
+
+ //$label .= " ($total_items)";
+
+ }
+
+ $values[] = [
+ 'value' => $r->term_taxonomy_id,
+ 'label' => $label,
+ 'total_children' => $total_children,
+ 'taxonomy' => $taxonomy_slug,
+ 'taxonomy_id' => $taxonomy_id,
+ 'parent' => $r->parent,
+ 'total_items' => $total_items,
+ 'type' => 'Taxonomy'
+ ];
+
+ }
+
+
+
+ } else {
+
+ $items_query_clause = '';
+ if ($items_query) {
+ $items_query_clause = "AND post_id IN($items_query)";
+ }
+ $base_query = $wpdb->prepare( "FROM $wpdb->postmeta WHERE meta_key = %s $search_q $items_query_clause ORDER BY meta_value", $metadatum_id );
+
+ $total_query = "SELECT COUNT(DISTINCT meta_value) $base_query";
+ $query = "SELECT DISTINCT meta_value $base_query $pagination";
+
+ $results = $wpdb->get_col($query);
+ $total = $wpdb->get_var($total_query);
+ $number = is_integer($args['number']) && $args['number'] >=1 ? $args['number'] : $total;
+ if( $number < 1){
+ $pages = 1;
+ } else {
+ $pages = ceil( $total / $number );
+ }
+
+ // add selected to the result
+ if ( !empty($args['include']) ) {
+ if ( is_array($args['include']) ) {
+ $results = array_unique( array_merge($args['include'], $results) );
}
}
+
+ $values = [];
+ foreach ($results as $r) {
+
+ $label = $r;
+
+ if ( $metadatum_type === 'Tainacan\Metadata_Types\Relationship' ) {
+ $_post = get_post($r);
+ if ( ! $_post instanceof \WP_Post) {
+ continue;
+ }
+ $label = $_post->post_title;
+ }
+
+ $total_items = null;
+
+ if ( $args['count_items'] ) {
+ $count_items_query = $args['items_filter'];
+ $count_items_query['posts_per_page'] = 1;
+ if ( !isset($count_items_query['meta_query']) ) {
+ $count_items_query['meta_query'] = [];
+ }
+ $count_items_query['meta_query'][] = [
+ 'key' => $metadatum_id,
+ 'value' => $r
+ ];
+ $count_items_results = $itemsRepo->fetch($count_items_query, $args['collection_id']);
+ $total_items = $count_items_results->found_posts;
+
+ //$label .= " ($total_items)";
+
+ }
+
+ $values[] = [
+ 'label' => $label,
+ 'value' => $r,
+ 'total_items' => $total_items,
+ 'type' => 'Text'
+ ];
+
+ }
}
-
- $spliced = $this->unique_multidimensional_array( $results, 'mvalue' );
-
- if($number > 0 && count($spliced) > $number){
- array_splice($spliced, (int) $number);
- }
-
- return $spliced;
+
+ return [
+ 'total' => $total,
+ 'pages' => $pages,
+ 'values' => $values
+ ];
+
}
/**
diff --git a/src/classes/repositories/class-tainacan-taxonomies.php b/src/classes/repositories/class-tainacan-taxonomies.php
index 96acb22e2..3e83e0973 100644
--- a/src/classes/repositories/class-tainacan-taxonomies.php
+++ b/src/classes/repositories/class-tainacan-taxonomies.php
@@ -338,6 +338,26 @@ class Taxonomies extends Repository {
}
}
}
+
+ public function get_db_identifier_by_id($id) {
+ $prefix = Entities\Taxonomy::$db_identifier_prefix;
+ return $prefix . $id;
+ }
+
+ /**
+ * Check if a term already exists
+ *
+ * @param Entities\Taxonomy $taxonomy The taxonomy object where to look for terms
+ * @param string $term_name The term name
+ * @param int|null $parent The ID of the parent term to look for children or null to look for terms in any hierarchical position. Default is null
+ * @param bool $return_term wether to return the term object if it exists. default is to false
+ *
+ * @return bool|WP_Term return boolean indicating if term exists. If $return_term is true and term exists, return WP_Term object
+ */
+ public function term_exists(Entities\Taxonomy $taxonomy, $term_name, $parent = null, $return_term = false) {
+ $TermsRepo = Terms::get_instance();
+ return $TermsRepo->term_exists($term_name, $taxonomy, $parent, $return_term);
+ }
}
\ No newline at end of file
diff --git a/src/classes/repositories/class-tainacan-terms.php b/src/classes/repositories/class-tainacan-terms.php
index 56ef2c672..70bbbc946 100644
--- a/src/classes/repositories/class-tainacan-terms.php
+++ b/src/classes/repositories/class-tainacan-terms.php
@@ -113,6 +113,10 @@ class Terms extends Repository {
*/
public function insert( $term ) {
+ if ( ! $term->get_validated() ) {
+ throw new \Exception( 'Entities must be validated before you can save them' );
+ }
+
$is_update = false;
$diffs = [];
if ( $term->get_id() ) {
@@ -154,6 +158,10 @@ class Terms extends Repository {
'description' => $term->get_description(),
] );
}
+
+ if ( is_wp_error($term_saved) ) {
+ throw new \Exception( 'Error adding term ' . $term->get_name() . ' - ' . $term_saved->get_error_message() );
+ }
// Now run through properties stored as postmeta
foreach ( $map as $prop => $mapped ) {
@@ -257,6 +265,54 @@ class Terms extends Repository {
return $deleted;
}
+
+ /**
+ * Check if a term already exists
+ *
+ * @param string $term_name The term name
+ * @param mixed $taxonomy The taxonomy ID, slug or Entity.
+ * @param int $parent The ID of the parent term to look for children or null to look for terms in any hierarchical position. Default is null
+ * @param bool $return_term wether to return the term object if it exists. default is to false
+ *
+ * @return bool|WP_Term return boolean indicating if term exists. If $return_term is true and term exists, return WP_Term object
+ */
+ public function term_exists($name, $taxonomy, $parent = null, $return_term = false) {
+
+ $Tainacan_Taxonomies = \Tainacan\Repositories\Taxonomies::get_instance();
+
+ if ( is_numeric( $taxonomy ) ) {
+ $taxonomy_slug = $Tainacan_Taxonomies->get_db_identifier_by_id( $taxonomy );
+ } elseif (is_string($taxonomy)) {
+ $taxonomy_slug = $taxonomy;
+ } elseif ( $taxonomy instanceof Entities\Taxonomy ) {
+ $taxonomy_slug = $taxonomy->get_db_identifier();
+ }
+
+ $args = [
+ 'name' => $name,
+ 'taxonomy' => $taxonomy_slug,
+ 'parent' => $parent,
+ 'hide_empty' => 0,
+ 'suppress_filter' => true
+ ];
+
+ if (is_null($parent)) {
+ unset($args['parent']);
+ }
+
+ $terms = get_terms($args);
+
+ if (empty($terms)) {
+ return false;
+ }
+
+ if ($return_term) {
+ return $terms[0];
+ }
+
+ return true;
+
+ }
/**
* @param $term_id
diff --git a/src/classes/tainacan-creator.php b/src/classes/tainacan-creator.php
index 41f94db74..fe9e4211a 100644
--- a/src/classes/tainacan-creator.php
+++ b/src/classes/tainacan-creator.php
@@ -148,6 +148,9 @@ require_once(__DIR__ . '/../theme-helper/class-tainacan-theme-helper.php');
require_once(__DIR__ . '/../theme-helper/template-tags.php');
$Tainacan_Theme_Helper = \Tainacan\Theme_Helper::get_instance();
+require_once(__DIR__ . '/../gutenberg-blocks/class-tainacan-gutenberg-block.php');
+$Tainacan_Gutenberg_Block = \Tainacan\GutenbergBlock::get_instance();
+
$Tainacan_Search_Engine = new \Tainacan\Search_Engine();
$Tainacan_Elastic_press = new \Tainacan\Elastic_Press();
diff --git a/src/exporter/class-tainacan-csv.php b/src/exporter/class-tainacan-csv.php
index e3f267736..3719e502c 100644
--- a/src/exporter/class-tainacan-csv.php
+++ b/src/exporter/class-tainacan-csv.php
@@ -10,101 +10,48 @@ class CSV extends Exporter {
parent::__construct($attributes);
$this->set_mapping_method('any'); // set all method to mapping
//$this->set_mapping_method('list', [ "dublin-core" => "Tainacan\\Exposers\\Mappers\\Dublin_Core" ]); // set specific list of methods to mapping
+ //todo create list only slug
}
- public function process_item( $index, $collection_definition ) {
- $collection_id = $collection_definition['id'];
- $tainacan_items = \Tainacan\Repositories\Items::get_instance();
-
- $filters = [
- 'posts_per_page' => 1,
- 'paged' => $index+1,
- 'order' => 'DESC'
- ];
-
- $this->add_log('Proccessing item index ' . $index . ' in collection ' . $collection_definition['id'] );
- $items = $tainacan_items->fetch($filters, $collection_id, 'WP_Query');
- $export_items = "";
- while ($items->have_posts()) {
- $items->the_post();
- $item = new Entities\Item($items->post);
- $printCol = $index == 0;
- $export_items .= $this->get_item_csv($item, $printCol);
- $this->add_log('export_items ' . $export_items );
- }
- wp_reset_postdata();
- return $export_items;
- }
-
- private function get_item_csv($item, $printCol) {
- $items_metadata = $item->get_metadata();
- $prepared_item = [];
- foreach ($items_metadata as $item_metadata) {
- array_push($prepared_item, $item_metadata->_toArray());
- }
- $mapper = $this->mapping_list[$this->mapping_selected];
- $instance_mapper = new $mapper();
- $data = $this->map($prepared_item, $instance_mapper);
- return $this->str_putcsv($data, ',', '"', $printCol);
- }
-
- protected function map($item_arr, $mapper) {
- $ret = $item_arr;
- if(array_key_exists('metadatum', $item_arr)) { // getting a unique metadatum
- $ret = $this->map_metadatum($item_arr, $mapper);
- } else { // array of elements
- $ret = [];
- foreach ($item_arr as $item) {
- if(array_key_exists('metadatum', $item)) {
- $ret = array_merge($ret, $this->map($item, $mapper) );
- } else {
- $ret[] = $this->map($item, $mapper);
- }
+ public function process_item( $processed_item, $mapping ) {
+ if( $processed_item ) {
+ $csv_line = '';
+ foreach ($processed_item as $key => $value) {
+ $csv_line .= $this->str_putcsv($value, $mapping, ',', '"');
}
- }
- return $ret;
- }
-
- protected function map_metadatum($item_arr, $mapper) {
- $ret = $item_arr;
- $metadatum_mapping = $item_arr['metadatum']['exposer_mapping'];
- if(array_key_exists($mapper->slug, $metadatum_mapping)) {
- if(
- is_string($metadatum_mapping[$mapper->slug]) && is_array($mapper->metadata) && !array_key_exists( $metadatum_mapping[$mapper->slug], $mapper->metadata) ||
- is_array($metadatum_mapping[$mapper->slug]) && $mapper->allow_extra_metadata != true
- ) {
- throw new \Exception('Invalid Mapper Option');
- }
- $slug = '';
- if(is_string($metadatum_mapping[$mapper->slug])) {
- $slug = $metadatum_mapping[$mapper->slug];
- } else {
- $slug = $metadatum_mapping[$mapper->slug]['slug'];
- }
- $ret = [$mapper->prefix.$slug.$mapper->sufix => $item_arr['value']];
- } elseif($mapper->slug == 'value') {
- $ret = [$item_arr['metadatum']['name'] => $item_arr['value']];
+ $this->append_to_file('exporter', $csv_line."\n");
} else {
- $ret = [];
+ $this->add_error_log('failed on item '. $this->get_current_collection() );
}
- return $ret;
}
- function str_putcsv($item, $delimiter = ',', $enclosure = '"', $printCol = false) {
+ public function output_header($collection_definition) {
+ $columns = [];
+ foreach ($collection_definition['mapping'] as $key => $value) {
+ $columns[] = $value;
+ }
+ $this->append_to_file('exporter', \implode(",", $columns) . "\n");
+ return false;
+ }
+
+ function str_putcsv($item, $mapping, $delimiter = ',', $enclosure = '"') {
// Open a memory "file" for read/write...
$fp = fopen('php://temp', 'r+');
$out=[];
- $col=[];
foreach ($item as $key => $value) {
- $col[] = $key;
- $out[] = $value;
- }
- if ($printCol) {
- fputcsv($fp, $col, $delimiter, $enclosure);
+ if (array_key_exists($key, $mapping)) {
+ if (is_array($value)) {
+ $out[] = implode("||", $value);
+ } else {
+ $out[] = $value;
+ }
+ }
}
fputcsv($fp, $out, $delimiter, $enclosure);
rewind($fp);
- $data = fread($fp, 1048576);
+ //Getting detailed stats to check filesize:
+ $fstats = fstat($fp);
+ $data = fread($fp, $fstats['size']);
fclose($fp);
return rtrim($data, "\n");
}
diff --git a/src/exporter/class-tainacan-exporter.php b/src/exporter/class-tainacan-exporter.php
index 46cbd9a63..f4db8257e 100644
--- a/src/exporter/class-tainacan-exporter.php
+++ b/src/exporter/class-tainacan-exporter.php
@@ -471,9 +471,26 @@ class Exporter extends CommunImportExport {
'any' => true,
'list' => false
];
+ private $send_email = null;
protected $mapping_list = [];
public $mapping_selected = "";
+ protected $steps = [
+ [
+ 'name' => 'Begin Exporter',
+ 'progress_label' => 'Begin Exporter Process',
+ 'callback' => 'begin_exporter'
+ ],[
+ 'name' => 'Process Items',
+ 'progress_label' => 'Process Items',
+ 'callback' => 'process_collections'
+ ],[
+ 'name' => 'End Exporter',
+ 'progress_label' => 'End Exporter Process',
+ 'callback' => 'end_exporter'
+ ]
+ ];
+
public function __construct($attributess = array()) {
$this->array_attributes = array_merge($this->array_attributes, ['current_collection_item', 'current_collection']);
parent::__construct();
@@ -488,7 +505,6 @@ class Exporter extends CommunImportExport {
}
}
- //"Tainacan\\Exposers\\Mappers\\Value"
public function _to_Array($short = false) {
$return = ['id' => $this->get_id()];
foreach ($this->array_attributes as $attr) {
@@ -500,36 +516,43 @@ class Exporter extends CommunImportExport {
global $Tainacan_Exporter_Handler;
$exporter_definition = $Tainacan_Exporter_Handler->get_exporter_by_object($this);
+ $return['mapping_selected'] = $this->mapping_selected;
+ $return['output_files'] = $this->output_files;
+ $return['send_email'] = $this->send_email;
+
if ($short === false) {
- $return['manual_collection'] = $exporter_definition['manual_collection'];
- $return['mapping_selected'] = $this->mapping_selected;
- $return['mapping_accept'] = $this->mapping_accept;
- $return['mapping_list'] = $this->mapping_list;
- $return['output_files'] = $this->output_files;
- $return['options_form'] = $this->options_form();
+ $return['manual_collection'] = $exporter_definition['manual_collection'];
+ $return['mapping_accept'] = $this->mapping_accept;
+ $return['mapping_list'] = $this->mapping_list;
+ $return['options_form'] = $this->options_form();
}
return $return;
}
- /**
- * get the metadata of file/url to allow mapping
- * should return an array
- *
- * Used when $manual_mapping is set to true, to build the mapping interface
- *
- * @return array $metadata_source the metadata from the source
- */
- public function get_source_metadata() {}
+ public function add_collection(array $collection) {
+ parent::add_collection($collection);
+ $this->update_collection_mapping($collection['id']);
+ }
- /**
- * Method implemented by the child importer/exporter class to return the total number of items that will be imported
- *
- * Used to build the progress bar
- *
- * @return int
- */
- public function get_source_number_of_items() {}
+ private function update_collection_mapping($collection_id) {
+ $collection_repo = Tainacan\Repositories\Collections::get_instance();
+ $collection = $collection_repo->fetch((int)$collection_id);
+ $metas = $collection->get_metadata();
+
+ $mapping = [];
+ foreach ($metas as $key => $value) {
+ $mapper = $this->mapping_list[$this->mapping_selected];
+ $instance_mapper = new $mapper();
+ $metadatum_mapping = $value->get_exposer_mapping();
+ if(array_key_exists($instance_mapper->slug, $metadatum_mapping)) {
+ $mapping[$value->get_name()] = $metadatum_mapping[$instance_mapper->slug];
+ } else if ($instance_mapper->slug == 'value'){
+ $mapping[$value->get_name()] = $value->get_name();
+ }
+ }
+ $this->collections[$collection_id]['mapping'] = $mapping;
+ }
/**
* Method implemented by child importer/exporter to return the HTML of the Options Form to be rendered in the Importer page
@@ -545,32 +568,139 @@ class Exporter extends CommunImportExport {
$collections = $this->get_collections();
$collection_definition = isset($collections[$current_collection]) ? $collections[$current_collection] : false;
$current_collection_item = $this->get_current_collection_item();
-
+
if ( !$collection_definition || !is_array($collection_definition) || !isset($collection_definition['id']) || !isset($collection_definition['mapping']) ) {
$this->add_error_log('Collection misconfigured');
- return false;
+ return false;
}
$this->add_log('Processing item ' . $current_collection_item);
- $processed_item = $this->process_item( $current_collection_item, $collection_definition );
- if( $processed_item ) {
- $this->append_to_file('exporter', $processed_item."\n");
- } else {
- $this->add_error_log('failed on item '. $current_collection_item );
- }
+
+ $this->process_header($current_collection_item, $collection_definition);
+
+ $processed_item = $this->get_item($current_collection_item, $collection_definition);
+ $this->process_item( $processed_item, $collection_definition['mapping'] );
+
+ $this->process_footer($current_collection_item, $collection_definition);
return $this->next_item();
}
-
- /**
- * get values for a single item
- *
- * @param $index
- * @return array with metadatum_source's as the index and values for the
- * item
- *
- * Ex: [ 'Metadatum1' => 'value1', 'Metadatum2' => [ 'value2','value3' ]
- */
- public function process_item( $index, $collection_id ) { }
-
+
+ public function process_item( $processed_item, $mapping ) {
+ $this->append_to_file('exporter', "[--process item--]\n");
+ }
+
+ private function process_header($current_collection_item, $collection_definition) {
+ if ($current_collection_item == 0) {
+ $this->output_header($collection_definition);
+ }
+ }
+
+ public function output_header($collection_definition) {
+ $this->append_to_file('exporter', "[header] \n");
+ return false;
+ }
+
+ private function process_footer($current_collection_item, $collection_definition) {
+ if ($current_collection_item == $collection_definition['total_items']-1) {
+ $this->output_footer();
+ }
+ }
+
+ public function output_footer() {
+ $this->append_to_file('exporter', "[footer] \n");
+ return false;
+ }
+
+ private function get_item($index, $collection_definition) {
+ $collection_id = $collection_definition['id'];
+ $tainacan_items = \Tainacan\Repositories\Items::get_instance();
+
+ $filters = [
+ 'posts_per_page' => 1,
+ 'paged' => $index+1,
+ 'order' => 'DESC'
+ ];
+
+ $this->add_log('Proccessing item index ' . $index . ' in collection ' . $collection_definition['id'] );
+ $items = $tainacan_items->fetch($filters, $collection_id, 'WP_Query');
+ $data = [];
+ while ($items->have_posts()) {
+ $items->the_post();
+ $item = new Entities\Item($items->post);
+ $prepared_item = [];
+ foreach ($item->get_metadata() as $item_metadata) {
+ array_push($prepared_item, $item_metadata->_toArray());
+ }
+ $mapper = $this->mapping_list[$this->mapping_selected];
+ $instance_mapper = new $mapper();
+ $data[] = $this->map($prepared_item, $instance_mapper);
+ }
+ wp_reset_postdata();
+ return $data;
+ }
+
+ protected function map($item_arr, $mapper) {
+ $ret = $item_arr;
+ if(array_key_exists('metadatum', $item_arr)) { // getting a unique metadatum
+ $ret = $this->map_metadatum($item_arr, $mapper);
+ } else { // array of elements
+ $ret = [];
+ foreach ($item_arr as $item) {
+ if(array_key_exists('metadatum', $item)) {
+ $ret = array_merge($ret, $this->map($item, $mapper) );
+ } else {
+ $ret[] = $this->map($item, $mapper);
+ }
+ }
+ }
+ return $ret;
+ }
+
+ protected function map_metadatum($item_arr, $mapper) {
+ $ret = $item_arr;
+ $metadatum_mapping = $item_arr['metadatum']['exposer_mapping'];
+ if(array_key_exists($mapper->slug, $metadatum_mapping)) {
+ if(
+ is_string($metadatum_mapping[$mapper->slug]) && is_array($mapper->metadata) && !array_key_exists( $metadatum_mapping[$mapper->slug], $mapper->metadata) ||
+ is_array($metadatum_mapping[$mapper->slug]) && $mapper->allow_extra_metadata != true
+ ) {
+ throw new \Exception('Invalid Mapper Option');
+ }
+ $slug = '';
+ if(is_string($metadatum_mapping[$mapper->slug])) {
+ $slug = $metadatum_mapping[$mapper->slug];
+ } else {
+ $slug = $metadatum_mapping[$mapper->slug]['slug'];
+ }
+ $data = $this->metadatum_to_array($item_arr);
+ $ret = [$mapper->prefix.$slug.$mapper->sufix => $data];
+
+ } elseif($mapper->slug == 'value') {
+ $data = $this->metadatum_to_array($item_arr);
+ $ret = [$item_arr['metadatum']['name'] => $data];
+ } else {
+ $ret = [];
+ }
+ return $ret;
+ }
+
+ private function metadatum_to_array ($item_arr) {
+ $array_metadatum = [];
+ if ($item_arr['metadatum']['multiple'] == 'yes') {
+ $array_metadatum = $item_arr['value'];
+ } else {
+ $array_metadatum[] = $item_arr['value'];
+ }
+
+ $temp = [];
+ if ($item_arr['metadatum']['metadata_type'] == 'Tainacan\\Metadata_Types\\Taxonomy') {
+ foreach ($array_metadatum as $key => $value) {
+ $temp[] = $value["name"];
+ }
+ $array_metadatum = $temp;
+ }
+ return $array_metadatum;
+ }
+
public function add_new_file($key) {
$upload_dir = wp_upload_dir();
$upload_dir = trailingslashit( $upload_dir['basedir'] );
@@ -618,11 +748,29 @@ class Exporter extends CommunImportExport {
public function set_mapping_selected($mapping_selected) {
$this->mapping_selected = $mapping_selected;
}
-
- public function finished() {
-
+
+ public function set_send_email($email) {
+ $this->send_email = $email;
}
+ public function finished() {
+ if($this->send_email != null) {
+ $msg = 'export completed successfully';
+ wp_mail($this->send_email, __('Finished export.', 'tainacan'), __($msg, 'tainacan'));
+ }
+ }
+
+ public function begin_exporter() {
+ return false;
+ }
+
+ public function end_exporter() {
+ return false;
+ }
+
+ private function set_output_files($output_files) {
+ $this->output_files = $output_files;
+ }
/**
* runs one iteration
*/
diff --git a/src/gutenberg-blocks/api-client/axios.js b/src/gutenberg-blocks/api-client/axios.js
new file mode 100644
index 000000000..715cc9ef2
--- /dev/null
+++ b/src/gutenberg-blocks/api-client/axios.js
@@ -0,0 +1,9 @@
+import axios from 'axios';
+
+const tainacan = axios.create({
+ baseURL: tainacan_plugin.root
+});
+
+tainacan.defaults.headers.common['X-WP-Nonce'] = tainacan_plugin.nonce;
+
+export default tainacan;
\ No newline at end of file
diff --git a/src/gutenberg-blocks/class-tainacan-gutenberg-block.php b/src/gutenberg-blocks/class-tainacan-gutenberg-block.php
new file mode 100644
index 000000000..795e42b1a
--- /dev/null
+++ b/src/gutenberg-blocks/class-tainacan-gutenberg-block.php
@@ -0,0 +1,122 @@
+= '5') {
+ $this->add_gutenberg_blocks_actions();
+ }
+ }
+
+ public static function get_instance() {
+ if ( ! isset( self::$instance ) ) {
+ self::$instance = new self();
+ }
+
+ return self::$instance;
+ }
+
+ private function add_gutenberg_blocks_actions() {
+ //add_action('init', array($this, 'register_tainacan_collections_carousel'));
+ add_action('init', array($this, 'register_tainacan_items_grid'));
+
+ add_action('init', array($this, 'add_plugin_settings'));
+
+ //add_action('wp_enqueue_scripts', array($this, 'enqueue_on_theme'));
+ add_filter('block_categories', array($this, 'register_tainacan_block_categories'), 10, 2);
+ }
+
+ public function register_tainacan_block_categories($categories, $post){
+ if ( $post->post_type !== 'post' ) {
+ return $categories;
+ }
+
+ return array_merge(
+ $categories,
+ array(
+ array(
+ 'slug' => 'tainacan-blocks',
+ 'title' => __( 'Tainacan', 'tainacan' ),
+ ),
+ )
+ );
+ }
+
+ public function enqueue_on_theme(){
+ global $TAINACAN_BASE_URL;
+
+ wp_enqueue_script(
+ 'collections-carousel',
+ $TAINACAN_BASE_URL . '/assets/gutenberg_collections_carousel-components.js'
+ );
+ }
+
+ public function register_tainacan_items_grid(){
+ global $TAINACAN_BASE_URL;
+
+ wp_register_script(
+ 'items-grid',
+ $TAINACAN_BASE_URL . '/assets/gutenberg_items_grid-components.js',
+ array('wp-blocks', 'wp-element', 'wp-components', 'wp-editor', 'underscore')
+ );
+
+ wp_register_style(
+ 'items-grid',
+ $TAINACAN_BASE_URL . '/assets/css/tainacan-gutenberg-blocks-style.css',
+ array('wp-edit-blocks')
+ );
+
+ register_block_type('tainacan/items-grid', array(
+ 'editor_script' => 'items-grid',
+ 'style' => 'items-grid'
+ ));
+ }
+
+ public function register_tainacan_collections_carousel(){
+ global $TAINACAN_BASE_URL;
+
+ wp_register_script(
+ 'collections-carousel',
+ $TAINACAN_BASE_URL . '/assets/gutenberg_collections_carousel-components.js',
+ array('wp-blocks', 'wp-element', 'wp-components', 'wp-editor')
+ );
+
+ wp_register_style(
+ 'collections-carousel',
+ $TAINACAN_BASE_URL . '/assets/css/tainacan-gutenberg-blocks-style.css',
+ array('wp-edit-blocks')
+ );
+
+ register_block_type('tainacan/collections-carousel', array(
+ 'editor_script' => 'collections-carousel',
+ 'style' => 'collections-carousel'
+ ));
+ }
+
+ public function get_plugin_js_settings(){
+ global $TAINACAN_BASE_URL;
+
+ $settings = [
+ 'root' => esc_url_raw( rest_url() ) . 'tainacan/v2',
+ 'nonce' => wp_create_nonce( 'wp_rest' ),
+ 'base_url' => $TAINACAN_BASE_URL
+ ];
+
+ return $settings;
+ }
+
+ function add_plugin_settings() {
+
+ $settings = $this->get_plugin_js_settings();
+
+ //wp_localize_script( 'collections-carousel', 'tainacan_plugin', $settings );
+ wp_localize_script( 'items-grid', 'tainacan_plugin', $settings );
+ }
+}
\ No newline at end of file
diff --git a/src/gutenberg-blocks/gutenberg-blocks-style.scss b/src/gutenberg-blocks/gutenberg-blocks-style.scss
new file mode 100644
index 000000000..c265d31c3
--- /dev/null
+++ b/src/gutenberg-blocks/gutenberg-blocks-style.scss
@@ -0,0 +1,2 @@
+//@import 'tainacan-collections/collections-carousel/collections-carousel';
+@import 'tainacan-items/items-grid/items-grid';
\ No newline at end of file
diff --git a/src/gutenberg-blocks/tainacan-collections/collections-carousel/collections-carousel.scss b/src/gutenberg-blocks/tainacan-collections/collections-carousel/collections-carousel.scss
new file mode 100644
index 000000000..f578529d9
--- /dev/null
+++ b/src/gutenberg-blocks/tainacan-collections/collections-carousel/collections-carousel.scss
@@ -0,0 +1,221 @@
+.wp-block-tainacan-collections-carousel {
+ min-height: 200px;
+
+ .wp-block-tainacan-collections-carousel__carousel-item {
+ display: flex;
+
+ .wp-block-tainacan-collections-carousel__carousel-item-first {
+ display: flex;
+ align-items: flex-start;
+ align-content: start;
+
+ img {
+ padding: 0 !important;
+ max-width: 100% !important;
+ }
+ }
+
+ .wp-block-tainacan-collections-carousel__carousel-item-others {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+
+ img {
+ padding: 0 !important;
+ max-width: 100% !important;
+ }
+ }
+ }
+}
+
+.components-modal__frame {
+ width: 100%;
+}
+
+.BrainhubCarousel {
+ overflow: hidden;
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+}
+
+.BrainhubCarousel .BrainhubCarousel__trackContainer {
+ overflow: hidden;
+}
+
+.BrainhubCarousel .BrainhubCarousel__trackContainer .BrainhubCarousel__track {
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ overflow: hidden;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+.BrainhubCarousel .BrainhubCarousel__trackContainer .BrainhubCarousel__track .BrainhubCarousel__track--transition {
+ -webkit-transition: -webkit-transform;
+ transition: -webkit-transform;
+ transition: transform;
+ transition: transform, -webkit-transform;
+}
+
+/* arrows */
+.BrainhubCarousel__arrows {
+ cursor: pointer;
+}
+
+/* variables */
+.BrainhubCarousel__dots {
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-pack: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ font-size: 0;
+ line-height: 0;
+}
+
+.BrainhubCarousel__dots .BrainhubCarousel__dot {
+ outline: 0;
+ padding: 10px;
+ border: none;
+ opacity: 0.5;
+ cursor: pointer;
+ -webkit-appearance: none;
+}
+
+.BrainhubCarousel__dots .BrainhubCarousel__dot .BrainhubCarousel__dot--selected {
+ opacity: 1 !important;
+}
+
+.BrainhubCarousel__dots .BrainhubCarousel__dot:hover {
+ opacity: 1;
+}
+
+.BrainhubCarousel__dots .BrainhubCarousel__dot:before {
+ content: '';
+ display: block;
+ width: 5px;
+ height: 5px;
+ border-radius: 50%;
+ padding: 0;
+ border: none;
+ background: black;
+}
+
+.BrainhubCarousel__dots .BrainhubCarousel__thumbnail {
+ outline: 0;
+ padding: 10px;
+ border: none;
+ opacity: 0.5;
+ cursor: pointer;
+}
+
+.BrainhubCarousel__dots .BrainhubCarousel__thumbnail .BrainhubCarousel__thumbnail--selected {
+ opacity: 1 !important;
+}
+
+.BrainhubCarousel__dots .BrainhubCarousel__thumbnail:hover {
+ opacity: 1;
+}
+
+.BrainhubCarousel__thumbnail[type=button] {
+ -webkit-appearance: none;
+}
+
+.BrainhubCarousel__arrows {
+ position: relative;
+ padding: 21px;
+ border: none;
+ overflow: hidden;
+ outline: 0;
+ font-size: 0;
+ line-height: 0;
+ background-color: white;
+}
+
+.BrainhubCarousel__arrows span {
+ display: block;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ border-style: solid;
+ border-color: #298596;
+ border-width: 3px 3px 0 0;
+ padding: 5px;
+ -webkit-transition: 0.3s;
+ transition: 0.3s;
+ font-size: 0;
+}
+
+.BrainhubCarousel__arrows:hover {
+ background-color: #298596;
+}
+
+.BrainhubCarousel__arrows:hover span {
+ border-color: #fff;
+ margin: 0;
+}
+
+.BrainhubCarousel__arrowLeft span {
+ -webkit-transform: translate(-50%, -50%) rotate(-135deg);
+ transform: translate(-50%, -50%) rotate(-135deg);
+ margin-left: 2.45px;
+}
+
+.BrainhubCarousel__arrowRight span {
+ -webkit-transform: translate(-50%, -50%) rotate(45deg);
+ transform: translate(-50%, -50%) rotate(45deg);
+ margin-left: -2.45px;
+}
+
+.BrainhubCarousel__track {
+ width: 100% !important;
+ max-width: 100% !important;
+ max-height: 100% !important;
+}
+
+.BrainhubCarouselItem {
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-pack: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ position: relative;
+
+ width: 100% !important;
+ max-width: 100% !important;
+ max-height: 100% !important;
+}
+
+.BrainhubCarouselItem.BrainhubCarouselItem--clickable {
+ cursor: pointer;
+}
+
+.BrainhubCarouselItem .debug-number {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-pack: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ font-size: 2em;
+ text-shadow: 0px 0px 9px white;
+}
\ No newline at end of file
diff --git a/src/gutenberg-blocks/tainacan-collections/collections-carousel/index.js b/src/gutenberg-blocks/tainacan-collections/collections-carousel/index.js
new file mode 100644
index 000000000..8b63e88d9
--- /dev/null
+++ b/src/gutenberg-blocks/tainacan-collections/collections-carousel/index.js
@@ -0,0 +1,400 @@
+const { registerBlockType } = wp.blocks;
+
+const { Modal, Button, IconButton } = wp.components;
+
+const { RichText } = wp.editor;
+
+const { __ } = wp.i18n;
+
+import tainacan from '../../api-client/axios.js';
+
+import Carousel from '@brainhubeu/react-carousel';
+
+global.window.userSettings = { uid: 1 };
+
+registerBlockType('tainacan/collections-carousel', {
+ title: __('Tainacan Collections Carousel', 'tainacan'),
+ icon: 'images-alt',
+ category: 'tainacan-blocks',
+ attributes: {
+ isOpen: {
+ type: Boolean,
+ default: false
+ },
+ collectionsMatched: {
+ type: Array,
+ default: []
+ },
+ selectedCollections: {
+ type: Array,
+ default: []
+ },
+ items: {
+ type: 'array',
+ source: 'query',
+ selector: 'a',
+ query: {
+ style: {
+ source: 'attribute',
+ attribute: 'style'
+ },
+ collection_id: {
+ source: 'attribute',
+ attribute: 'class'
+ },
+ url: {
+ source: 'attribute',
+ attribute: 'href'
+ },
+ img: {
+ source: 'query',
+ selector: 'img',
+ query: {
+ src: {
+ source: 'attribute',
+ attribute: 'src'
+ },
+ alt: {
+ source: 'attribute',
+ attribute: 'alt'
+ },
+ }
+ }
+ },
+ default: [],
+ },
+ contentTemp: {
+ type: Array,
+ default: [],
+ },
+ content: {
+ type: 'array',
+ source: 'children',
+ selector: 'div'
+ },
+ },
+ supports: {
+ align: ['full', 'left', 'right', 'wide'],
+ html: false
+ },
+ keywords: [__('tainacan', 'tainacan'), __('carousel', 'tainacan'), __('collections', 'tainacan')],
+ edit({ attributes, setAttributes, className }) {
+ console.log('edit', attributes);
+
+ let { contentTemp, collectionsMatched, selectedCollections, items, isOpen, content } = attributes;
+ let isInEdit = true;
+
+ const arrowRight = (
+
+
+
+
+
+ );
+
+ const arrowLeft = (
+
+
+
+
+
+ );
+
+ function prepareItem(item, style, collectionName) {
+ return (
+
+
+
+ );
+ }
+
+ function getTop3ItemsOf(collection) {
+ let collectionID = collection.id;
+
+ return tainacan.get(`/collection/${collectionID}/items?perpage=3&paged=1&orderby=date`)
+ .then(response => {
+ return response.data;
+ })
+ .catch(error => {
+ console.error(error);
+ });
+ }
+
+ function updateContent(contentTemp){
+ setAttributes({
+ content: contentTemp.length ?
+ (
+ = 3 ? 3 : contentTemp.length}
+ arrows
+ slides={contentTemp}
+ breakpoints={{
+ 1000: { // these props will be applied when screen width is less than 1000px
+ slidesPerPage: 2,
+ clickToChange: false,
+ centered: false,
+ arrows: true,
+ infinite: false,
+ },
+ 500: {
+ slidesPerPage: 1,
+ slidesPerScroll: 1,
+ clickToChange: false,
+ centered: false,
+ infinite: false,
+ },
+ }}
+ />
+
) : []
+ });
+ }
+
+ function removeCollection(collectionID) {
+ let index = contentTemp.findIndex((coll) => {
+ return coll.key == collectionID;
+ });
+
+ if(index >= 0){
+ contentTemp.splice(index, 1);
+ selectedCollections.splice(index, 1);
+
+ setAttributes({contentTemp: contentTemp});
+ updateContent(contentTemp);
+ }
+ }
+
+ function prepareContent(newContent, items, collection){
+ newContent.push(
+
+
+
+ { isInEdit ? (
+
{
+ console.log('clicked', collection.id);
+ removeCollection(collection.id);
+ }}
+ icon="trash"/>
+ ) : null }
+
+
+
+ {items[0] ? prepareItem(items[0], {display: 'flex', height: '87px'}, collection.name) : null}
+
+
+
+ {items[1] ? prepareItem(items[1], {width: '42px', height: '42px', marginBottom: '3px'}, collection.name) : null}
+ {items[2] ? prepareItem(items[2], {width: '42px', height: '42px'}, collection.name) : null}
+
+
+
+
+ {collection.name}
+
+
+
+ );
+
+ console.info(newContent);
+
+ setAttributes({ contentTemp: newContent });
+ }
+
+ if(content && content.length && content[0].type && !contentTemp.length){
+ let groupedItems = items.reduce((r, a) => {
+ r[a.collection_id] = r[a.collection_id] || [];
+ r[a.collection_id].push(a);
+ return r;
+ }, Object.create(null));
+
+ console.log('Grouped', groupedItems);
+
+ for(let group in groupedItems){
+ let itemsTemp = groupedItems[group];
+
+ prepareContent(contentTemp, itemsTemp, {
+ name: itemsTemp[0].collection_id.split('{}')[1],
+ id: itemsTemp[0].collection_id.split('{}')[0]
+ });
+
+ selectedCollections.push(itemsTemp[0].collection_id.split('{}')[0]);
+ }
+ }
+
+ const autocompleters = [{
+ name: __('Collections', 'tainacan'),
+ triggerPrefix: '/',
+ options(keyword) {
+ if (!keyword) {
+ return [];
+ }
+
+ return tainacan.get(`/collections?search=${keyword}`)
+ .then(response => {
+ return response.data;
+ })
+ .catch(error => {
+ console.error(error);
+ });
+ },
+ getOptionLabel(option) {
+ return ({option.name} );
+ },
+ getOptionKeywords(option) {
+ let found = selectedCollections.find((id) => {
+ return id == option.id;
+ });
+
+ if(found == undefined) {
+ collectionsMatched.push(option.name);
+
+ return collectionsMatched;
+ }
+ },
+ getOptionCompletion(option) {
+
+ let found = selectedCollections.find((id) => {
+ return id == option.id;
+ });
+
+ if(found == undefined) {
+ selectedCollections.push(option.id);
+
+ getTop3ItemsOf(option).then((res) => {
+ res.map((item) => {
+ items.push(prepareItem(item))
+ });
+
+ prepareContent(contentTemp, res, option);
+
+ setAttributes({items: items});
+ });
+
+ setAttributes({selectedCollections: selectedCollections});
+
+ return ({` | ${option.name} `} );
+ }
+ },
+ isDebounced: true,
+ debounceSpeak: true,
+ }];
+
+ return (
+
+
+ setAttributes( { isOpen: true } ) }>{ __('Add collection', 'tainacan') }
+
+
+ { isOpen ?
+
{
+ setAttributes( { isOpen: false } );
+ updateContent(contentTemp);
+ }}>
+
+
+
true}
+ tagName="p"
+ autocompleters={autocompleters}
+ />
+ { __('Type '+ autocompleters[0].triggerPrefix +' for triggering the autocomplete.', 'tainacan') }
+
+
+
+ {
+ setAttributes( { isOpen: false } );
+ updateContent(contentTemp);
+ } }>
+ { __('Close', 'tainacan') }
+
+
+
+ : null
+ }
+
+
+ { contentTemp.length ?
+ = 3 ? 3 : contentTemp.length}
+ arrows
+ slides={contentTemp}
+ breakpoints={{
+ 1000: { // these props will be applied when screen width is less than 1000px
+ slidesPerPage: 2,
+ clickToChange: false,
+ centered: false,
+ arrows: true,
+ infinite: false,
+ },
+ 500: {
+ slidesPerPage: 1,
+ slidesPerScroll: 1,
+ clickToChange: false,
+ centered: false,
+ infinite: false,
+ },
+ }}
+ /> : null
+ }
+
+
+ );
+ },
+ save({ attributes }) {
+ console.log('save', attributes);
+
+ const { content } = attributes;
+
+ return {content}
+ },
+});
\ No newline at end of file
diff --git a/src/gutenberg-blocks/tainacan-items/items-grid/index.js b/src/gutenberg-blocks/tainacan-items/items-grid/index.js
new file mode 100644
index 000000000..ef3853d3e
--- /dev/null
+++ b/src/gutenberg-blocks/tainacan-items/items-grid/index.js
@@ -0,0 +1,343 @@
+const { registerBlockType } = wp.blocks;
+
+const { __ } = wp.i18n;
+
+const { Button, Modal, TextareaControl, QueryControls, Placeholder, CheckboxControl } = wp.components;
+
+const { InspectorControls } = wp.editor;
+
+import tainacan from '../../api-client/axios.js';
+import qs from 'qs';
+
+registerBlockType('tainacan/items-grid', {
+ title: __('Tainacan Items Grid', 'tainacan'),
+ icon: (
+
+
+
+ ),
+ category: 'tainacan-blocks',
+ attributes: {
+ items2: {
+ type: Array,
+ default: []
+ },
+ items: {
+ type: 'array',
+ source: 'query',
+ selector: 'a',
+ query: {
+ url: {
+ source: 'attribute',
+ attribute: 'href'
+ },
+ img: {
+ source: 'query',
+ selector: 'img',
+ query: {
+ src: {
+ source: 'attribute',
+ attribute: 'src'
+ },
+ alt: {
+ source: 'attribute',
+ attribute: 'alt'
+ },
+ }
+ },
+ },
+ default: []
+ },
+ isOpen: {
+ type: Boolean,
+ default: false
+ },
+ content: {
+ type: 'array',
+ source: 'children',
+ selector: 'div'
+ },
+ itemsPerPage: {
+ type: Number,
+ default: 12
+ },
+ query: {
+ type: Object,
+ default: {}
+ },
+ URLCollectionID: {
+ type: String
+ },
+ tainacanURL: {
+ type: String,
+ },
+ showTitle: {
+ type: Boolean,
+ default: false
+ },
+ },
+ supports: {
+ html: false
+ },
+ edit({ attributes, setAttributes, className, isSelected }){
+ let { items, items2, isOpen, content, itemsPerPage, query, URLCollectionID, tainacanURL, showTitle } = attributes;
+
+ function prepareItem(item) {
+ return (
+
+
+ { showTitle ? (
+
+ {item.title ? item.title : item.img[0].alt}
+
+ ) : null }
+
+ );
+ }
+
+ function getItems(collectionID, query) {
+ if(collectionID) {
+ return tainacan.get(`/collection/${collectionID}/items?${query}`)
+ .then(response => {
+ return response.data;
+ })
+ .catch(error => {
+ console.error(error);
+ });
+ } else {
+ return tainacan.get(`/items?${query}`)
+ .then(response => {
+ return response.data;
+ })
+ .catch(error => {
+ console.error(error);
+ });
+ }
+ }
+
+ function setContent(items){
+ setAttributes({
+ content: (
+
+ { items }
+
+ )
+ });
+ }
+
+ function updateQuery(query) {
+ let queryString = qs.stringify(query);
+
+ getItems(URLCollectionID, queryString).then(data => {
+ items = [];
+
+ data.map((item) => {
+ items.push(prepareItem(item));
+ });
+
+ setAttributes({items: items});
+ setAttributes({items2: data});
+ setContent(items);
+ });
+ }
+
+ function parseURL(tainacanURLP) {
+ tainacanURL = tainacanURLP;
+ setAttributes({tainacanURL: tainacanURLP});
+
+ if (!tainacanURLP || !tainacanURLP.includes('tainacan_admin')){
+ return true;
+ }
+
+ let tainacanURLSplited = tainacanURL.split('?');
+
+ let rawQuery = tainacanURLSplited[2];
+ let rawURL = tainacanURLSplited[1];
+
+ let parsedQuery = qs.parse(rawQuery);
+
+ if(parsedQuery.fetch_only && !Object.values(parsedQuery.fetch_only).some(value => value == 'title')){
+ parsedQuery.fetch_only[Object.keys(parsedQuery.fetch_only).length] = 'title';
+ }
+
+ let URLCollID = rawURL.match(/\/(\d+)\/?/);
+ URLCollectionID = URLCollID != undefined ? URLCollID[1]: URLCollID;
+
+ setAttributes({query: parsedQuery});
+ setAttributes({URLCollectionID: URLCollectionID});
+ setAttributes({itemsPerPage: Number(parsedQuery.perpage)});
+
+ getItems(URLCollectionID, qs.stringify(query)).then(data => {
+ items = [];
+
+ data.map((item) => {
+ items.push(prepareItem(item));
+ });
+
+ setAttributes({items: items});
+ setAttributes({items2: data});
+ setContent(items);
+ });
+ }
+
+ function mountBlock(itemsA) {
+ let itemsP = [];
+
+ for (const item of itemsA){
+ itemsP.push(prepareItem(item));
+ }
+
+ items = itemsP;
+ setAttributes({items: itemsP});
+ setContent(itemsP);
+ }
+
+ if(content && content.length && content[0].type){
+ mountBlock(items);
+ }
+
+ return (
+
+
+
+
+
+ {
+ showTitle = isChecked;
+
+ mountBlock(items2);
+
+ setAttributes({showTitle: isChecked});
+ } }
+ />
+
+
+
+
+ { isSelected ? (
+
+ setAttributes({isOpen: true})}>{ items.length ? __('Update items grid', 'tainacan') : __('Add items', 'tainacan')}
+
+ ) : null
+ }
+
+ { !items.length ? (
+
+ )}
+ />) : null
+ }
+
+ { isOpen ?
+
setAttributes({isOpen: false}) }>
+
+
+ parseURL( tainacanURL ) }
+ />
+
+
+ { Object.keys(query).length && query.perpage && tainacanURL ? (
+
+ {
+ query.perpage = !numberOfItems ? 1 : numberOfItems;
+ itemsPerPage = query.perpage;
+
+ setAttributes({itemsPerPage: itemsPerPage});
+
+ _.debounce(updateQuery(query), 300);
+ }
+ }
+ />
+
+ ) : null
+ }
+
+
+ setAttributes({isOpen: false}) }>
+ { __('Close', 'tainacan') }
+
+
+ : null }
+
+
+ { items }
+
+
+ );
+ },
+ save({ attributes }){
+ const { content } = attributes;
+
+ return { content }
+ }
+});
\ No newline at end of file
diff --git a/src/gutenberg-blocks/tainacan-items/items-grid/items-grid.scss b/src/gutenberg-blocks/tainacan-items/items-grid/items-grid.scss
new file mode 100644
index 000000000..67e14b734
--- /dev/null
+++ b/src/gutenberg-blocks/tainacan-items/items-grid/items-grid.scss
@@ -0,0 +1,3 @@
+.wp-block-tainacan-items-grid {
+
+}
\ No newline at end of file
diff --git a/src/importer/class-tainacan-csv.php b/src/importer/class-tainacan-csv.php
index 46d11bebf..d3cb6bb39 100644
--- a/src/importer/class-tainacan-csv.php
+++ b/src/importer/class-tainacan-csv.php
@@ -5,66 +5,56 @@ use Tainacan;
use Tainacan\Entities;
class CSV extends Importer {
-
- public function __construct($attributes = array()) {
+ public function __construct($attributes = array()) {
parent::__construct($attributes);
$this->items_repo = \Tainacan\Repositories\Items::get_instance();
-
- $this->set_default_options([
+ $this->set_default_options([
'delimiter' => ',',
'multivalued_delimiter' => '||',
'encode' => 'utf8',
'enclosure' => ''
- ]);
-
+ ]);
}
/**
* alter the default options
*/
- public function set_option($key,$value){
+ public function set_option($key,$value) {
$this->default_options[$key] = $value;
}
/**
* @inheritdoc
*/
- public function get_source_metadata(){
+ public function get_source_metadata() {
if (($handle = fopen($this->tmp_file, "r")) !== false) {
-
- if( $this->get_option('enclosure') && strlen($this->get_option('enclosure')) > 0 ){
+ if( $this->get_option('enclosure') && strlen($this->get_option('enclosure')) > 0 ) {
$rawColumns = $this->handle_enclosure( $handle );
-
} else {
$rawColumns = fgetcsv($handle, 0, $this->get_option('delimiter'));
}
$columns = [];
- if( $rawColumns ){
- foreach( $rawColumns as $index => $rawColumn ){
-
- if( strpos($rawColumn,'special_') === 0 ){
-
- if( $rawColumn === 'special_document' ){
+ if( $rawColumns ) {
+ foreach( $rawColumns as $index => $rawColumn ) {
+ if( strpos($rawColumn,'special_') === 0 ) {
+ if( $rawColumn === 'special_document' ) {
$this->set_option('document_index', $index);
- } else if( $rawColumn === 'special_attachments' ){
- $this->set_option('attachment_index', $index);
- } else if( $rawColumn === 'special_item_status' ){
- $this->set_option('item_status_index', $index);
- } else if( $rawColumn === 'special_item_id' ){
- $this->set_option('item_id_index', $index);
+ } else if( $rawColumn === 'special_attachments' ) {
+ $this->set_option('attachment_index', $index);
+ } else if( $rawColumn === 'special_item_status' ) {
+ $this->set_option('item_status_index', $index);
+ } else if( $rawColumn === 'special_item_id' ) {
+ $this->set_option('item_id_index', $index);
}
-
} else {
$columns[] = $rawColumn;
}
}
-
return $columns;
}
}
-
return [];
}
@@ -72,25 +62,21 @@ class CSV extends Importer {
*
* returns all header including special
*/
- public function raw_source_metadata(){
-
+ public function raw_source_metadata() {
if (($handle = fopen($this->tmp_file, "r")) !== false) {
-
if( $this->get_option('enclosure') && strlen($this->get_option('enclosure')) > 0 ){
return $this->handle_enclosure( $handle );
-
} else {
return fgetcsv($handle, 0, $this->get_option('delimiter'));
}
}
-
return false;
}
/**
* @inheritdoc
*/
- public function process_item( $index, $collection_definition ){
+ public function process_item( $index, $collection_definition ) {
$processedItem = [];
$headers = $this->raw_source_metadata();
@@ -98,39 +84,33 @@ class CSV extends Importer {
if (($handle = fopen($this->tmp_file, "r")) !== false) {
$file = $handle;
-
} else {
$this->add_error_log(' Error reading the file ');
return false;
-
}
- if( $index === 0 ){
-
+ if( $index === 0 ) {
// moves the pointer forward
fgetcsv($file, 0, $this->get_option('delimiter'));
-
} else {
//get the pointer
$csv_pointer= $this->get_transient('csv_pointer');
-
- if( $csv_pointer ){
+ if( $csv_pointer ) {
fseek($file, $csv_pointer);
}
}
$this->add_transient('csv_last_pointer', ftell($file)); // add reference to post_process item in after_inserted_item()
- if( $this->get_option('enclosure') && strlen($this->get_option('enclosure')) > 0 ){
+ if( $this->get_option('enclosure') && strlen($this->get_option('enclosure')) > 0 ) {
$values = $this->handle_enclosure( $file );
-
} else {
$values = fgetcsv($file, 0, $this->get_option('delimiter'));
}
-
+
$this->add_transient('csv_pointer', ftell($file)); // add reference for insert
- if( count( $headers ) !== count( $values ) ){
+ if( count( $headers ) !== count( $values ) ) {
$string = (is_array($values)) ? implode('::', $values ) : $values;
$this->add_error_log(' Mismatch count headers and row columns ');
@@ -140,35 +120,27 @@ class CSV extends Importer {
$this->add_error_log(' Values string: ' . $string );
return false;
}
-
- if( $this->get_option('item_id_index') ){
+
+ if( $this->get_option('item_id_index') ) {
$this->handle_item_id( $values );
}
-
+
foreach ( $collection_definition['mapping'] as $metadatum_id => $header) {
-
-
foreach ( $headers as $indexRaw => $headerRaw ) {
- if( $headerRaw === $header ){
+ if( $headerRaw === $header ) {
$column = $indexRaw;
}
}
-
+
if(!isset($column))
continue;
$valueToInsert = $this->handle_encoding( $values[ $column ] );
- if( !is_numeric($metadatum_id) ){
- $metadatum = $this->create_metadata( $headers[ $column ], $collection_definition['id']);
- } else {
- $metadatum = new \Tainacan\Entities\Metadatum($metadatum_id);
- }
-
+ $metadatum = new \Tainacan\Entities\Metadatum($metadatum_id);
$processedItem[ $header ] = ( $metadatum->is_multiple() ) ?
explode( $this->get_option('multivalued_delimiter'), $valueToInsert) : $valueToInsert;
}
-
$this->add_log('Success to proccess index: ' . $index );
return $processedItem;
}
@@ -183,49 +155,45 @@ class CSV extends Importer {
if( !empty($column_document) || !empty( $column_attachment ) || !empty( $column_item_status ) ){
- if (($handle = fopen($this->tmp_file, "r")) !== false) {
- $file = $handle;
- } else {
- $this->add_error_log(' Error reading the file ');
- return false;
- }
-
- $csv_pointer= $this->get_transient('csv_last_pointer');
- fseek($file, $csv_pointer);
-
+ if (($handle = fopen($this->tmp_file, "r")) !== false) {
+ $file = $handle;
+ } else {
+ $this->add_error_log(' Error reading the file ');
+ return false;
+ }
+
+ $csv_pointer= $this->get_transient('csv_last_pointer');
+ fseek($file, $csv_pointer);
+
if( $this->get_option('enclosure') && strlen($this->get_option('enclosure')) > 0 ){
$values = $this->handle_enclosure( $file );
-
} else {
$values = fgetcsv($file, 0, $this->get_option('delimiter'));
}
-
- if( is_array($values) && !empty($column_document) ){
+
+ if( is_array($values) && !empty($column_document) ) {
$this->handle_document( $values[$column_document], $inserted_item);
}
- if( is_array($values) && !empty($column_attachment) ){
+ if( is_array($values) && !empty($column_attachment) ) {
$this->handle_attachment( $values[$column_attachment], $inserted_item);
}
- if( is_array($values) && !empty($column_item_status) ){
+ if( is_array($values) && !empty($column_item_status) ) {
$this->handle_item_status( $values[$column_item_status], $inserted_item);
}
-
}
}
/**
* @inheritdoc
*/
- public function get_source_number_of_items(){
+ public function get_source_number_of_items() {
if ( isset($this->tmp_file) && file_exists($this->tmp_file) && ($handle = fopen($this->tmp_file, "r")) !== false) {
$cont = 0;
-
while ( ($data = fgetcsv($handle, 0, $this->get_option('delimiter')) ) !== false ) {
- $cont++;
+ $cont++;
}
-
// does not count the header
return $cont - 1;
}
@@ -234,10 +202,8 @@ class CSV extends Importer {
public function options_form() {
-
ob_start();
?>
-
@@ -322,12 +288,12 @@ class CSV extends Importer {
-
-
- get_option('encode'), 'utf8'); ?> >UTF-8
- get_option('encode'), 'iso88591'); ?> >ISO-88591
-
-
+
+
+ get_option('encode'), 'utf8'); ?> >UTF-8
+ get_option('encode'), 'iso88591'); ?> >ISO-88591
+
+
@@ -349,12 +315,12 @@ class CSV extends Importer {
-
-
- get_option('repeated_item'), 'update'); ?> >Update
- get_option('repeated_item'), 'ignore'); ?> >Ignore
-
-
+
+
+ get_option('repeated_item'), 'update'); ?> >Update
+ get_option('repeated_item'), 'ignore'); ?> >Ignore
+
+
@@ -365,8 +331,8 @@ class CSV extends Importer {
There are two special columns you can use: special_document , which will set the Document of your item, and special_attachments to add one or many attachments.\n
The values for the special_document must be prepended with 'url:'', 'file:'' or 'text:'. This will indicate the Document Type.\n
The values for the special_attachments is just a list of files. If you want to add many attachments, use the separator you set in the Multivalued Delimiter option.\n
- In either case, you can point to a file using a full URL, or just a file name. In this last case, you should set the option below to tell Tainacan where to find the files in your server. You can then upload them directly (via FTP for example) and Taincan will add them to your items.\n
- ", 'taincan')); ?>
+ In either case, you can point to a file using a full URL, or just a file name. In this last case, you should set the option below to tell Tainacan where to find the files in your server. You can then upload them directly (via FTP for example) and tainacan will add them to your items.\n
+ ", 'tainacan')); ?>
@@ -399,16 +365,12 @@ class CSV extends Importer {
/**
* get the encode option and return as expected
*/
- private function handle_encoding($string){
-
- switch( $this->get_option('encode') ){
-
+ private function handle_encoding($string) {
+ switch( $this->get_option('encode') ) {
case 'utf8':
return $string;
-
case 'iso88591':
return utf8_encode($string);
-
default:
return $string;
}
@@ -417,11 +379,11 @@ class CSV extends Importer {
/**
* method responsible to insert the item document
*/
- private function handle_document($column_value, $item_inserted){
+ private function handle_document($column_value, $item_inserted) {
$TainacanMedia = \Tainacan\Media::get_instance();
- $this->items_repo->disable_logs();
+ $this->items_repo->disable_logs();
- if( strpos($column_value,'url:') === 0 ){
+ if( strpos($column_value,'url:') === 0 ) {
$correct_value = trim(substr($column_value, 4));
$item_inserted->set_document( $correct_value );
$item_inserted->set_document_type( 'url' );
@@ -429,8 +391,7 @@ class CSV extends Importer {
if( $item_inserted->validate() ) {
$item_inserted = $this->items_repo->update($item_inserted);
}
-
- } else if( strpos($column_value,'text:') === 0 ){
+ } else if( strpos($column_value,'text:') === 0 ) {
$correct_value = trim(substr($column_value, 5));
$item_inserted->set_document( $correct_value );
$item_inserted->set_document_type( 'text' );
@@ -438,11 +399,9 @@ class CSV extends Importer {
if( $item_inserted->validate() ) {
$item_inserted = $this->items_repo->update($item_inserted);
}
-
- } else if( strpos($column_value,'file:') === 0 ){
+ } else if( strpos($column_value,'file:') === 0 ) {
$correct_value = trim(substr($column_value, 5));
-
- if( filter_var($correct_value, FILTER_VALIDATE_URL) ){
+ if( filter_var($correct_value, FILTER_VALIDATE_URL) ) {
$id = $TainacanMedia->insert_attachment_from_url($correct_value);
if(!$id){
@@ -461,7 +420,7 @@ class CSV extends Importer {
$server_path_files = trailingslashit($this->get_option('server_path'));
$id = $TainacanMedia->insert_attachment_from_file($server_path_files . $correct_value);
- if(!$id){
+ if(!$id) {
$this->add_error_log('Error in Document file imported from server ' . $correct_value);
return false;
}
@@ -473,84 +432,70 @@ class CSV extends Importer {
if( $item_inserted->validate() ) {
$item_inserted = $this->items_repo->update($item_inserted);
}
-
}
-
}
$thumb_id = $this->items_repo->get_thumbnail_id_from_document($item_inserted);
-
if (!is_null($thumb_id)) {
$this->add_log('Setting item thumbnail: ' . $thumb_id);
set_post_thumbnail( $item_inserted->get_id(), (int) $thumb_id );
}
-
- $this->items_repo->enable_logs();
+ $this->items_repo->enable_logs();
return true;
-
}
/**
* method responsible to insert the item document
*/
- private function handle_attachment( $column_value, $item_inserted){
+ private function handle_attachment( $column_value, $item_inserted) {
$TainacanMedia = \Tainacan\Media::get_instance();
-
- $this->items_repo->disable_logs();
-
+ $this->items_repo->disable_logs();
$attachments = explode( $this->get_option('multivalued_delimiter'), $column_value);
+ if( $attachments ) {
+ foreach( $attachments as $attachment ) {
- if( $attachments ){
- foreach( $attachments as $attachment ){
-
- if( filter_var($attachment, FILTER_VALIDATE_URL) ){
+ if( filter_var($attachment, FILTER_VALIDATE_URL) ) {
$id = $TainacanMedia->insert_attachment_from_url($attachment, $item_inserted->get_id());
-
- if(!$id){
+ if(!$id) {
$this->add_error_log('Error in Attachment file imported from URL ' . $attachment);
return false;
}
-
$this->add_log('Attachment file URL imported from ' . $attachment);
-
continue;
- }
+ }
$server_path_files = trailingslashit($this->get_option('server_path'));
$id = $TainacanMedia->insert_attachment_from_file($server_path_files . $attachment, $item_inserted->get_id());
- if(!$id){
+ if(!$id) {
$this->add_log('Error in Attachment file imported from server ' . $attachment);
continue;
}
$this->add_log('Attachment file in Server imported from ' . $attachment);
}
- }
-
- $this->items_repo->enable_logs();
-
+ }
+ $this->items_repo->enable_logs();
}
/**
* @param $file resource the csv file uploaded
*/
- private function handle_enclosure( &$file ){
+ private function handle_enclosure( &$file ) {
$line = trim(fgets($file));
$start = substr($line, 0, strlen($this->get_option('enclosure')));
- if( $this->get_option('enclosure') === $start ){
-
+ if( $this->get_option('enclosure') === $start ) {
$cut_start = strlen($this->get_option('enclosure'));
- $line = substr($line, $cut_start);
+ $line = substr($line, $cut_start);
}
$end = substr($line, ( strlen($line) - strlen($this->get_option('enclosure')) ) , strlen($this->get_option('enclosure')));
- if( $this->get_option('enclosure') === $end ){
- $line = substr($line, 0, ( strlen($line) - strlen($this->get_option('enclosure')) ) );
+ if( $this->get_option('enclosure') === $end ) {
+ $line = substr($line, 0, ( strlen($line) - strlen($this->get_option('enclosure')) ) );
}
$delimiter = $this->get_option('enclosure').$this->get_option('delimiter').$this->get_option('enclosure');
@@ -561,24 +506,22 @@ class CSV extends Importer {
/**
* @param $status string the item status
*/
- private function handle_item_status( $status, $item_inserted ){
+ private function handle_item_status( $status, $item_inserted ) {
+ //if ( in_array( $status, array( 'auto-draft', 'draft', 'pending', 'future', 'publish', 'trash', 'inherit' ) ) ) {
- if ( in_array( $status, array( 'auto-draft', 'draft', 'pending', 'future', 'publish', 'trash', 'inherit' ) ) ) {
+ $status = ( $status == 'public' ) ? 'publish' : $status;
$item_inserted->set_status($status);
-
- if( $item_inserted->validate() ) {
+ if( $item_inserted->validate() ) {
$item_inserted = $this->items_repo->update($item_inserted);
}
- }
-
+ //}
}
/**
* @param $status string the item ID
*/
- private function handle_item_id( $values ){
- $item_id_index = $this->set_option('item_id_index');
-
+ private function handle_item_id( $values ) {
+ $item_id_index = $this->get_option('item_id_index');
if( $item_id_index && isset($values[$item_id_index]) ){
$this->add_transient( 'item_id',$values[$item_id_index] );
$this->add_transient( 'item_action',$this->get_option('repeated_item') );
@@ -595,68 +538,78 @@ class CSV extends Importer {
* @return Tainacan\Entities\Item Item inserted
*/
public function insert( $processed_item, $collection_index ) {
-
- remove_action( 'post_updated', 'wp_save_post_revision' );
- $collections = $this->get_collections();
- $collection_definition = isset($collections[$collection_index]) ? $collections[$collection_index] : false;
- if ( !$collection_definition || !is_array($collection_definition) || !isset($collection_definition['id']) || !isset($collection_definition['mapping']) ) {
- $this->add_error_log('Collection misconfigured');
+ remove_action( 'post_updated', 'wp_save_post_revision' );
+ $collections = $this->get_collections();
+ $collection_definition = isset($collections[$collection_index]) ? $collections[$collection_index] : false;
+ if ( !$collection_definition || !is_array($collection_definition) || !isset($collection_definition['id']) || !isset($collection_definition['mapping']) ) {
+ $this->add_error_log('Collection misconfigured');
return false;
- }
-
- $collection = \Tainacan\Repositories\Collections::get_instance()->fetch($collection_definition['id']);
-
- $Tainacan_Metadata = \Tainacan\Repositories\Metadata::get_instance();
+ }
+
+ $collection = \Tainacan\Repositories\Collections::get_instance()->fetch($collection_definition['id']);
+
+ $Tainacan_Metadata = \Tainacan\Repositories\Metadata::get_instance();
$Tainacan_Item_Metadata = \Tainacan\Repositories\Item_Metadata::get_instance();
$Tainacan_Items = \Tainacan\Repositories\Items::get_instance();
-
- $Tainacan_Items->disable_logs();
- $Tainacan_Metadata->disable_logs();
- $Tainacan_Item_Metadata->disable_logs();
+
+ $Tainacan_Items->disable_logs();
+ $Tainacan_Metadata->disable_logs();
+ $Tainacan_Item_Metadata->disable_logs();
$item = new Entities\Item( ( $this->get_transient('item_id') ) ? $this->get_transient('item_id') : 0 );
- $itemMetadataArray = [];
-
- if( is_array( $processed_item ) ){
- foreach ( $processed_item as $metadatum_source => $values ){
+ $itemMetadataArray = [];
+
+ if( $this->get_transient('item_id') && $item && is_numeric($item->get_id()) && $item->get_id() > 0 && $this->get_transient('item_action') == 'ignore' ){
+ $this->add_log('Repeated Item');
+ return $item;
+ }
+
+ if( is_array( $processed_item ) ) {
+ foreach ( $processed_item as $metadatum_source => $values ) {
$tainacan_metadatum_id = array_search( $metadatum_source, $collection_definition['mapping'] );
$metadatum = $Tainacan_Metadata->fetch( $tainacan_metadatum_id );
- if( $metadatum instanceof Entities\Metadatum ){
+ if( $metadatum instanceof Entities\Metadatum ) {
$singleItemMetadata = new Entities\Item_Metadata_Entity( $item, $metadatum); // *empty item will be replaced by inserted in the next foreach
-
- if( $metadatum->get_metadata_type() == 'Tainacan\Metadata_Types\Taxonomy' ){
-
- $ids = $this->insert_hierarchy( $metadatum, $values );
- $singleItemMetadata->set_value( $ids );
+ if( $metadatum->get_metadata_type() == 'Tainacan\Metadata_Types\Taxonomy' ) {
+ if( !is_array( $values ) ) {
+ $tmp = $this->insert_hierarchy( $metadatum, $values);
+ if ($tmp !== false) {
+ $singleItemMetadata->set_value( $tmp );
+ }
+ } else {
+ $terms = [];
+ foreach($values as $k => $v) {
+ $tmp = $this->insert_hierarchy( $metadatum, $v);
+ if ($tmp !== false) {
+ $terms[] = $tmp;
+ }
+ }
+ $singleItemMetadata->set_value( $terms );
+ }
} else {
- $singleItemMetadata->set_value( $values );
+ $singleItemMetadata->set_value( $values );
}
-
$itemMetadataArray[] = $singleItemMetadata;
} else {
- $this->add_error_log('Metadata ' . $metadatum_source . ' not found');
- }
-
+ $this->add_error_log('Metadata ' . $metadatum_source . ' not found');
+ }
}
}
-
- if( !empty( $itemMetadataArray ) && $collection instanceof Entities\Collection ){
- $item->set_collection( $collection );
- if( $item->validate() ){
- $insertedItem = $Tainacan_Items->insert( $item );
+ if( !empty( $itemMetadataArray ) && $collection instanceof Entities\Collection ) {
+ $item->set_collection( $collection );
+ if( $item->validate() ) {
+ $insertedItem = $Tainacan_Items->insert( $item );
} else {
$this->add_error_log( 'Error inserting item' );
$this->add_error_log( $item->get_errors() );
return false;
}
-
foreach ( $itemMetadataArray as $itemMetadata ) {
$itemMetadata->set_item( $insertedItem ); // *I told you
-
- if( $itemMetadata->validate() ){
- $result = $Tainacan_Item_Metadata->insert( $itemMetadata );
+ if( $itemMetadata->validate() ) {
+ $result = $Tainacan_Item_Metadata->insert( $itemMetadata );
} else {
$this->add_error_log('Error saving value for ' . $itemMetadata->get_metadatum()->get_name());
$this->add_error_log($itemMetadata->get_errors());
@@ -670,27 +623,21 @@ class CSV extends Importer {
//} else {
// $this->add_error_log( 'Item ' . $insertedItem->get_id() . ' has an error' );
//}
- }
-
- $insertedItem->set_status('publish' );
-
+ }
+ $insertedItem->set_status('publish' );
if($insertedItem->validate()) {
- $insertedItem = $Tainacan_Items->update( $insertedItem );
-
- $this->after_inserted_item( $insertedItem, $collection_index );
+ $insertedItem = $Tainacan_Items->update( $insertedItem );
+ $this->after_inserted_item( $insertedItem, $collection_index );
} else {
- $this->add_error_log( 'Error publishing Item' );
- $this->add_error_log( $insertedItem->get_errors() );
- return false;
- }
-
+ $this->add_error_log( 'Error publishing Item' );
+ $this->add_error_log( $insertedItem->get_errors() );
+ return false;
+ }
return $insertedItem;
-
} else {
$this->add_error_log( 'Collection not set');
return false;
}
-
}
/**
@@ -701,34 +648,100 @@ class CSV extends Importer {
*/
private function insert_hierarchy( $metadatum, $values ){
- $Tainacan_Terms = \Tainacan\Repositories\Terms::get_instance();
+ if (empty($values)) {
+ return false;
+ }
+
+ $Tainacan_Terms = \Tainacan\Repositories\Terms::get_instance();
$taxonomy = new Entities\Taxonomy( $metadatum->get_metadata_type_options()['taxonomy_id']);
- $exploded_values = explode(">>",$values);
-
- if( is_array($exploded_values) ){
- $parent = 0;
+ $exploded_values = explode(">>",$values);
+
+ if (empty($exploded_values)) {
+ return false;
+ }
+ if( is_array($exploded_values) ) {
+ $parent = 0;
foreach ( $exploded_values as $key => $value) {
- $value = trim($value);
-
- $exists = term_exists( $value ,$taxonomy->get_db_identifier(), $parent );
- if( 0 !== $exists && null !== $exists && isset($exists['term_id']) ){
- $exists = new Entities\Term($exists['term_id']);
- $parent = $term->get_id();
+ $value = trim($value);
+ if ($value=='') {
+ $this->add_error_log('Malformed term hierarchy for Item ' . $this->get_current_collection_item() . '. Term skipped. Value: ' . $values);
+ return false;
+ }
+ $exists = $Tainacan_Terms->term_exists( $value ,$taxonomy->get_db_identifier(), $parent, true );
+ if (false !== $exists && isset($exists->term_taxonomy_id)) {
+ $parent = $exists->term_taxonomy_id;
} else {
+ $this->add_log('New term created: ' . $value . ' in tax_id: ' . $taxonomy->get_db_identifier() . '; parent: ' . $parent);
$term = new Entities\Term();
$term->set_name( $value );
$term->set_parent( $parent );
- $term->set_taxonomy( $taxonomy->get_db_identifier() );
- $term = $Tainacan_Terms->insert( $term );
-
- $parent = $term->get_id();
+ $term->set_taxonomy( $taxonomy->get_db_identifier() );
+ if ( $term->validate() ) {
+ $term = $Tainacan_Terms->insert( $term );
+ $parent = $term->get_id();
+ } else {
+ $this->add_error_log('Invalid Term for Item ' . $this->get_current_collection_item() . ' on Metadatum ' . $metadatum->get_name() . '. Term skipped. Value: ' . $values);
+ $this->add_error_log( implode(',', $term->get_errors()) );
+ return false;
+ }
+
}
}
-
- return $parent !== 0 ? $parent : false;
+ return $parent !== 0 ? (int)$parent : false;
} else {
return false;
}
}
-}
\ No newline at end of file
+
+ /**
+ * @param $collection_id int the collection id
+ * @param $mapping array the headers-metadata mapping
+ */
+ public function save_mapping( $collection_id, $mapping ){
+ update_post_meta( $collection_id, 'metadata_mapping', $mapping );
+ }
+
+ /**
+ * @param $collection_id
+ *
+ * @return array/bool false if has no mapping or associated array with metadata id and header
+ */
+ public function get_mapping( $collection_id ){
+ $mapping = get_post_meta( $collection_id, 'metadata_mapping', true );
+ return ( $mapping ) ? $mapping : false;
+ }
+
+
+ /**
+ * @inheritdoc
+ *
+ * allow save mapping
+ */
+ public function add_collection(array $collection) {
+ if (isset($collection['id'])) {
+
+ if( isset($collection['mapping']) && is_array($collection['mapping']) ){
+
+ foreach( $collection['mapping'] as $metadatum_id => $header ){
+
+ if( !is_numeric($metadatum_id) ) {
+ $metadatum = $this->create_new_metadata( $header, $collection['id']);
+
+ if( is_object($metadatum) ){
+ unset($collection['mapping'][$metadatum_id]);
+ $collection['mapping'][$metadatum->get_id()] = $header;
+ }
+
+ }
+ }
+
+ $this->save_mapping( $collection['id'], $collection['mapping'] );
+ }
+
+ $this->remove_collection($collection['id']);
+ $this->collections[] = $collection;
+ }
+ }
+
+}
diff --git a/src/importer/class-tainacan-importer.php b/src/importer/class-tainacan-importer.php
index 9da62bb26..b00abd202 100644
--- a/src/importer/class-tainacan-importer.php
+++ b/src/importer/class-tainacan-importer.php
@@ -907,13 +907,15 @@ abstract class Importer {
* @return bool
* @throws \Exception
*/
- protected function create_metadata( $metadata_description, $collection_id){
+ public function create_new_metadata( $metadata_description, $collection_id){
$taxonomy_repo = \Tainacan\Repositories\Taxonomies::get_instance();
$metadata_repo = \Tainacan\Repositories\Metadata::get_instance();
$properties = array_filter( explode('|', $metadata_description) );
- if( !$properties || count($properties) < 2 ){
+ if( is_array($properties) && count($properties) < 2 ){
+ $properties[1] = 'text';
+ } else if( !$properties ){
return false;
}
@@ -931,24 +933,48 @@ abstract class Importer {
if( strcmp($type, "Taxonomy") === 0 ){
$taxonomy = new Entities\Taxonomy();
$taxonomy->set_name($name);
+ $taxonomy->set_status('publish');
$taxonomy->set_allow_insert('yes');
if($taxonomy->validate()){
$inserted_tax = $taxonomy_repo->insert( $taxonomy );
- $newMetadatum->set_metadata_type_options(['taxonomy_id' => $inserted_tax->get_id()]);
+ $newMetadatum->set_metadata_type_options([
+ 'taxonomy_id' => $inserted_tax->get_id(),
+ 'allow_new_terms' => true,
+ 'input_type' => 'tainacan-taxonomy-checkbox'
+ ]);
}
}
/*Properties of metadatum*/
- if( isset($properties[2]) && $properties[2] === 'required'){
- $newMetadatum->set_required(true);
+ if( is_array($properties) && in_array( 'required', $properties)){
+ $newMetadatum->set_required('yes');
}
- if( isset($properties[3]) && $properties[3] === 'multiple' ){
+ if(is_array($properties) && in_array( 'multiple', $properties) ){
$newMetadatum->set_multiple('yes');
}
+ if( is_array($properties) && in_array( 'display_yes', $properties) ){
+ $newMetadatum->set_display('yes');
+ } else if(is_array($properties) && in_array( 'display_no', $properties) ){
+ $newMetadatum->set_display('no');
+ } else if(is_array($properties) && in_array( 'display_never', $properties) ){
+ $newMetadatum->set_display('never');
+ }
+
+ if( is_array($properties) && in_array( 'status_public', $properties) ){
+ $newMetadatum->set_status('publish');
+ } else if( is_array($properties) && in_array( 'status_private', $properties) ){
+ $newMetadatum->set_status('private');
+ }
+
+ if( is_array($properties) && in_array( 'collection_key_yes', $properties) ){
+ $newMetadatum->set_collection_key('yes');
+ } else if( is_array($properties) && in_array( 'collection_key_no', $properties) ){
+ $newMetadatum->set_collection_key('no');
+ }
if($newMetadatum->validate()){
$inserted_metadata = $metadata_repo->insert( $newMetadatum );
@@ -958,6 +984,7 @@ abstract class Importer {
} else{
$this->add_log('Error creating metadata ' . $name . ' in collection ' . $collection_id);
$this->add_log($newMetadatum->get_errors());
+
return false;
}
}
diff --git a/src/importer/class-tainacan-old-tainacan.php b/src/importer/class-tainacan-old-tainacan.php
index 032b9dcfa..80c82c1c6 100644
--- a/src/importer/class-tainacan-old-tainacan.php
+++ b/src/importer/class-tainacan-old-tainacan.php
@@ -685,8 +685,15 @@ class Old_Tainacan extends Importer{
if( get_term_by( 'name', $term->name, $taxonomy_father->get_db_identifier()) ){
continue;
}
-
- $inserted_term = $this->term_repo->insert($new_term);
+
+ if ($new_term->validate()) {
+ $inserted_term = $this->term_repo->insert($new_term);
+ } else {
+ $this->add_error_log( implode(',', $new_term->get_errors()) );
+ $this->abort();
+ return false;
+ }
+
if (is_wp_error($inserted_term)) {
diff --git a/src/importer/class-tainacan-test-importer.php b/src/importer/class-tainacan-test-importer.php
index f954e8820..3175c5fb9 100644
--- a/src/importer/class-tainacan-test-importer.php
+++ b/src/importer/class-tainacan-test-importer.php
@@ -379,7 +379,7 @@ class Test_Importer extends Importer {
'name' => 'Selectbox type',
'type' => 'Tainacan\Metadata_Types\Selectbox',
'options' => [
- 'options' => implode('\\n', $this->selectbox_values)
+ 'options' => implode("\n", $this->selectbox_values)
]
], $col1 );
diff --git a/src/js/event-bus-search.js b/src/js/event-bus-search.js
index 8558cb7e5..e220d8b0f 100644
--- a/src/js/event-bus-search.js
+++ b/src/js/event-bus-search.js
@@ -23,7 +23,7 @@ export default {
} else {
this.add_metaquery(data);
}
-
+
this.updateURLQueries();
});
@@ -47,7 +47,7 @@ export default {
},
watch: {
'$route' (to, from) {
-
+
// Should set Collection ID from URL only when in admin.
if (this.$route.name == 'CollectionItemsPage' || this.$route.name == 'ItemsPage')
this.collectionId = !this.$route.params.collectionId ? this.$route.params.collectionId : parseInt(this.$route.params.collectionId);
@@ -232,14 +232,14 @@ export default {
this.updateURLQueries();
let prefsPerPage = this.collectionId != undefined ? 'items_per_page_' + this.collectionId : 'items_per_page';
- if(this.$userPrefs.get(prefsPerPage) != itemsPerPage) {
+ if (this.$userPrefs.get(prefsPerPage) != itemsPerPage) {
this.$userPrefs.set(prefsPerPage, itemsPerPage)
.catch(() => {});
}
},
setOrderBy(orderBy) {
let prefsOrderBy = this.collectionId != undefined ? 'order_by_' + this.collectionId : 'order_by';
- if(this.$userPrefs.get(prefsOrderBy) != orderBy) {
+ if (this.$userPrefs.get(prefsOrderBy) != orderBy) {
this.$userPrefs.set(prefsOrderBy, orderBy)
.catch(() => {});
}
@@ -248,7 +248,7 @@ export default {
},
setOrder(order) {
let prefsOrder = this.collectionId != undefined ? 'order_' + this.collectionId : 'order';
- if(this.$userPrefs.get(prefsOrder) != order) {
+ if (this.$userPrefs.get(prefsOrder) != order) {
this.$userPrefs.set(prefsOrder, order)
.catch(() => {});
}
@@ -279,7 +279,7 @@ export default {
this.updateURLQueries();
let prefsAdminViewMode = this.collectionId != undefined ? 'admin_view_mode_' + this.collectionId : 'admin_view_mode';
- if(this.$userPrefs.get(prefsAdminViewMode) != adminViewMode) {
+ if (this.$userPrefs.get(prefsAdminViewMode) != adminViewMode) {
this.$userPrefs.set(prefsAdminViewMode, adminViewMode)
.catch(() => { });
}
@@ -293,8 +293,8 @@ export default {
this.updateURLQueries();
},
updateURLQueries() {
- this.$router.replace({query: {}});
- this.$router.replace({query: this.$store.getters['search/getPostQuery']});
+ this.$router.replace({ query: {} });
+ this.$router.replace({ query: this.$store.getters['search/getPostQuery'] });
},
updateStoreFromURL() {
this.$store.dispatch('search/set_postquery', this.$route.query);
@@ -321,7 +321,7 @@ export default {
resp.request.then((res) => {
this.$emit( 'isLoadingItems', false);
this.$emit( 'hasFiltered', res.hasFiltered);
-
+
if(res.advancedSearchResults){
this.$emit('advancedSearchResults', res.advancedSearchResults);
}
diff --git a/src/js/store/modules/bulk-edition/actions.js b/src/js/store/modules/bulk-edition/actions.js
index f210be364..7a8904b01 100644
--- a/src/js/store/modules/bulk-edition/actions.js
+++ b/src/js/store/modules/bulk-edition/actions.js
@@ -22,12 +22,16 @@ export const createEditGroup = ({commit}, parameters) => {
};
}
- return axios.tainacan.post(`/collection/${collectionID}/bulk-edit`, bulkEditParams)
- .then(response => {
- commit('setGroup', response.data);
- })
- .catch(error => {
- console.error(error);
+ return new Promise ((resolve, reject) => {
+ axios.tainacan.post(`/collection/${collectionID}/bulk-edit`, bulkEditParams)
+ .then(response => {
+ commit('setGroup', response.data);
+ resolve(response.data);
+ })
+ .catch(error => {
+ console.error(error);
+ reject(error);
+ });
});
};
@@ -58,6 +62,7 @@ export const setValueInBulk = ({commit}, parameters) => {
return axios.tainacan.post(`/collection/${collectionID}/bulk-edit/${groupID}/set`, bodyParams)
.then(response => {
commit('setActionResult', response.data);
+ commit('setLastUpdated');
return response;
})
.catch(error => {
@@ -138,6 +143,7 @@ export const setStatusInBulk = ({commit}, parameters) => {
return axios.tainacan.post(`/collection/${collectionID}/bulk-edit/${groupID}/set_status`, bodyParams)
.then(response => {
commit('setActionResult', response.data);
+ commit('setLastUpdated');
return response;
})
.catch(error => {
@@ -153,6 +159,7 @@ export const trashItemsInBulk = ({commit}, parameters) => {
return axios.tainacan.post(`/collection/${collectionID}/bulk-edit/${groupID}/trash`)
.then(response => {
commit('setActionResult', response.data);
+ commit('setLastUpdated');
return response;
})
.catch(error => {
@@ -183,6 +190,7 @@ export const deleteItemsInBulk = ({commit}, parameters) => {
return axios.tainacan.post(`/collection/${collectionID}/bulk-edit/${groupID}/delete_items`)
.then(response => {
commit('setActionResult', response.data);
+ commit('setLastUpdated');
return response;
})
.catch(error => {
@@ -205,4 +213,9 @@ export const fetchItemIdInSequence = ({commit}, { collectionId, sequenceId, item
reject(error);
});
});
+};
+
+// BULK ADD SPECIFIC
+export const setBulkAddItems = ({commit}, items) => {
+ commit('setBulkAddItems', items);
};
\ No newline at end of file
diff --git a/src/js/store/modules/bulk-edition/getters.js b/src/js/store/modules/bulk-edition/getters.js
index d7b245096..a3cf8c1f5 100644
--- a/src/js/store/modules/bulk-edition/getters.js
+++ b/src/js/store/modules/bulk-edition/getters.js
@@ -12,4 +12,12 @@ export const getActionResult = state => {
export const getItemIdInSequence = state => {
return state.itemIdInSequence;
-};
\ No newline at end of file
+};
+
+export const getLastUpdated = state => {
+ return state.lastUpdated;
+}
+
+export const getBulkAddItems = state => {
+ return state.bulkAddItems;
+}
\ No newline at end of file
diff --git a/src/js/store/modules/bulk-edition/index.js b/src/js/store/modules/bulk-edition/index.js
index 1f5baddb7..56984b879 100644
--- a/src/js/store/modules/bulk-edition/index.js
+++ b/src/js/store/modules/bulk-edition/index.js
@@ -5,7 +5,9 @@ import * as getters from './getters.js'
const state = {
group: null,
actionResult: null,
- itemIdInSequence: null
+ itemIdInSequence: null,
+ lastUpdated: '',
+ bulkAddItems: []
};
export default {
diff --git a/src/js/store/modules/bulk-edition/mutations.js b/src/js/store/modules/bulk-edition/mutations.js
index dc1b7f51d..191217424 100644
--- a/src/js/store/modules/bulk-edition/mutations.js
+++ b/src/js/store/modules/bulk-edition/mutations.js
@@ -8,4 +8,17 @@ export const setActionResult = (state, actionResult) => {
export const setItemIdInSequence = (state, itemIdInSequence) => {
state.itemIdInSequence = itemIdInSequence;
-};
\ No newline at end of file
+};
+
+export const setLastUpdated = (state, value) => {
+ if (value != undefined)
+ state.lastUpdated = value;
+ else {
+ let now = new Date();
+ state.lastUpdated = now.toLocaleString();
+ }
+}
+
+export const setBulkAddItems = (state, items) => {
+ return state.bulkAddItems = items;
+}
\ No newline at end of file
diff --git a/src/js/store/modules/collection/actions.js b/src/js/store/modules/collection/actions.js
index fe1e4720c..593106b6f 100644
--- a/src/js/store/modules/collection/actions.js
+++ b/src/js/store/modules/collection/actions.js
@@ -9,6 +9,16 @@ export const fetchItems = ({ rootGetters, dispatch, commit }, { collectionId, is
return new Object({
request: new Promise ((resolve, reject) => {
+
+ // Sets term query in case it's on a term items page
+ if (termId != undefined && taxonomy != undefined) {
+
+ dispatch('search/add_taxquery', {
+ taxonomy: taxonomy,
+ terms:[ termId ],
+ compare: 'IN'
+ }, { root: true });
+ }
// Adds queries for filtering
let postQueries = JSON.parse(JSON.stringify(rootGetters['search/getPostQuery']));
@@ -24,23 +34,11 @@ export const fetchItems = ({ rootGetters, dispatch, commit }, { collectionId, is
postQueries.taxquery.length > 0)) ) {
hasFiltered = true;
-
+
if(postQueries.advancedSearch){
advancedSearchResults = postQueries.advancedSearch;
}
- }
-
- // Sets term query in case it's on a term items page
- if (termId != undefined && taxonomy != undefined) {
-
- if (postQueries.taxquery == undefined)
- postQueries.taxquery = [];
-
- postQueries.taxquery.push({
- taxonomy: taxonomy,
- terms:[ termId ],
- compare: 'IN'
- });
+
}
let query = qs.stringify(postQueries);
@@ -70,7 +68,6 @@ export const fetchItems = ({ rootGetters, dispatch, commit }, { collectionId, is
if (postQueries.admin_view_mode != undefined)
postQueries.admin_view_mode = null;
}
-
axios.tainacan.get(endpoint+query, {
cancelToken: source.token
})
@@ -78,10 +75,14 @@ export const fetchItems = ({ rootGetters, dispatch, commit }, { collectionId, is
let items = res.data;
let viewModeObject = tainacan_plugin.registered_view_modes[postQueries.view_mode];
-
+
if (isOnTheme && viewModeObject != undefined && viewModeObject.type == 'template') {
commit('setItemsListTemplate', items);
- resolve({'itemsListTemplate': items, 'total': res.headers['x-wp-total'], hasFiltered: hasFiltered, advancedSearchResults: advancedSearchResults});
+ resolve({
+ 'itemsListTemplate': items,
+ 'total': res.headers['x-wp-total'],
+ hasFiltered: hasFiltered,
+ advancedSearchResults: advancedSearchResults});
} else {
commit('setItems', items);
resolve({
@@ -89,7 +90,7 @@ export const fetchItems = ({ rootGetters, dispatch, commit }, { collectionId, is
'total': res.headers['x-wp-total'],
totalPages: res.headers['x-wp-totalpages'],
hasFiltered: hasFiltered,
- advancedSearchResults: advancedSearchResults });
+ advancedSearchResults: advancedSearchResults });
}
dispatch('search/setTotalItems', res.headers['x-wp-total'], { root: true } );
dispatch('search/setTotalPages', res.headers['x-wp-totalpages'], { root: true } );
@@ -155,6 +156,10 @@ export const cleanCollections = ({ commit }) => {
commit('cleanCollections');
};
+export const cleanItems = ({ commit }) => {
+ commit('cleanItems');
+};
+
export const fetchCollection = ({ commit }, id) => {
commit('cleanCollection');
return new Promise((resolve, reject) =>{
@@ -423,4 +428,25 @@ export const fetchCollectionsForParent = ({ commit }) => {
reject(error);
})
});
+};
+
+// Send Files to Item Bulk Addition
+export const sendFile = ( { commit }, file ) => {
+ return new Promise(( resolve, reject ) => {
+ axios.wp.post('/media/', file, {
+ headers: { 'Content-Type': 'multipart/form-data;', 'Content-Disposition': 'attachment; filename=' + file.name },
+ })
+ .then( res => {
+ let file = res.data;
+ commit('setSingleFile', file);
+ resolve( file );
+ })
+ .catch(error => {
+ reject( error.response );
+ });
+ });
+};
+
+export const cleanFiles = ({ commit }) => {
+ commit('cleanFiles');
};
\ No newline at end of file
diff --git a/src/js/store/modules/collection/getters.js b/src/js/store/modules/collection/getters.js
index 3abd562ae..34ddc8548 100644
--- a/src/js/store/modules/collection/getters.js
+++ b/src/js/store/modules/collection/getters.js
@@ -26,6 +26,10 @@ export const getAttachments = state => {
return state.attachments;
}
+export const getFiles = state => {
+ return state.files;
+}
+
export const getCollectionCommentStatus = state => {
return state.collectionCommentStatus;
}
diff --git a/src/js/store/modules/collection/index.js b/src/js/store/modules/collection/index.js
index 6f67b9c12..2240729bb 100644
--- a/src/js/store/modules/collection/index.js
+++ b/src/js/store/modules/collection/index.js
@@ -12,7 +12,8 @@ const state = {
collectionURL: '',
attachments: [],
collectionCommentStatus: '',
- collectionAllowComments: ''
+ collectionAllowComments: '',
+ files: []
};
export default {
diff --git a/src/js/store/modules/collection/mutations.js b/src/js/store/modules/collection/mutations.js
index 4ac1e814c..e9b8f7c3b 100644
--- a/src/js/store/modules/collection/mutations.js
+++ b/src/js/store/modules/collection/mutations.js
@@ -63,6 +63,20 @@ export const setSingleAttachment = ( state, attachment ) => {
}
}
+export const setSingleFile = ( state, file ) => {
+ let index = state.files.findIndex(newfile => newfile.id === file.id);
+ if ( index >= 0){
+ //state.metadatum[index] = metadatum;
+ Vue.set( state.files, index, file );
+ } else {
+ state.files.push( file );
+ }
+}
+
+export const cleanFiles = (state) => {
+ state.files = [];
+}
+
export const setAttachments = ( state, attachments ) => {
state.attachments = attachments;
}
diff --git a/src/js/store/modules/filter/actions.js b/src/js/store/modules/filter/actions.js
index 2d394947c..3147d83f2 100644
--- a/src/js/store/modules/filter/actions.js
+++ b/src/js/store/modules/filter/actions.js
@@ -1,8 +1,10 @@
import axios from '../../../axios/axios';
+import qs from 'qs';
// FILTERS --------------------------------------------------------
-export const fetchFilters = ({ commit }, {collectionId, isRepositoryLevel, isContextEdit, includeDisabled}) => {
+export const fetchFilters = ({ commit }, { collectionId, isRepositoryLevel, isContextEdit, includeDisabled, customFilters }) => {
return new Promise((resolve, reject) => {
+
let endpoint = '';
if (!isRepositoryLevel)
endpoint = '/collection/' + collectionId + '/filters/';
@@ -19,6 +21,11 @@ export const fetchFilters = ({ commit }, {collectionId, isRepositoryLevel, isCon
endpoint += '&include_disabled=' + includeDisabled;
}
+ if (customFilters != undefined && customFilters.length > 0) {
+ let postin = { 'postin': customFilters };
+ endpoint += '&' + qs.stringify(postin);
+ }
+
axios.tainacan.get(endpoint)
.then((res) => {
let filters= res.data;
@@ -136,4 +143,51 @@ export const fetchFilterTypes = ({ commit} ) => {
export const updateFilteTypes = ( { commit }, filterTypes) => {
commit('setFilterTypes', filterTypes);
+};
+
+// TAXONOMY FILTERS - MULTIPLE COLLECTIONS ------------------------
+export const fetchTaxonomyFilters = ({ dispatch, commit }, taxonomyId ) => {
+
+ commit('clearTaxonomyFilters');
+
+ return new Promise((resolve, reject) => {
+ dispatch('taxonomy/fetchTaxonomy', taxonomyId, { root: true })
+ .then((res) => {
+ let taxonomy = res.taxonomy;
+ if (taxonomy.collections_ids != undefined && taxonomy.collections_ids.length != undefined) {
+
+ let amountOfCollectionsLoaded = 0;
+
+ for (let collectionId of taxonomy.collections_ids ) {
+
+ let endpoint = '';
+ endpoint = '/collection/' + collectionId + '/filters/?nopaging=1&include_disabled=no';
+
+ axios.tainacan.get(endpoint)
+ .then((resp) => {
+ let repositoryFilters = resp.data.filter((filter) => {
+ return (filter.collection_id == 'default' || filter.collection_id == 'filter_in_repository') && filter.metadatum.metadata_type_object.options.taxonomy_id != taxonomyId
+ });
+ let collectionFilters = resp.data.filter((filter) => {
+ return (filter.collection_id != 'default' && filter.collection_id != 'filter_in_repository') && filter.metadatum.metadata_type_object.options.taxonomy_id != taxonomyId
+ });
+ commit('setTaxonomyFiltersForCollection', { collectionName: collectionId, taxonomyFilters: collectionFilters });
+ commit('setTaxonomyFiltersForCollection', { collectionName: undefined, taxonomyFilters: repositoryFilters });
+ amountOfCollectionsLoaded++;
+
+ if (amountOfCollectionsLoaded == taxonomy.collections_ids.length) {
+ resolve();
+ }
+ })
+ .catch((error) => {
+ console.log(error);
+ reject(error);
+ });
+ }
+ }
+ })
+ .error(() => {
+ reject();
+ });
+ });
};
\ No newline at end of file
diff --git a/src/js/store/modules/filter/getters.js b/src/js/store/modules/filter/getters.js
index fb6231a2e..dad1b62c9 100644
--- a/src/js/store/modules/filter/getters.js
+++ b/src/js/store/modules/filter/getters.js
@@ -17,4 +17,8 @@ export const getFilters = state => {
export const getFilterTypes = state => {
return state.filterTypes;
+}
+
+export const getTaxonomyFilters = state => {
+ return state.taxonomyFilters;
}
\ No newline at end of file
diff --git a/src/js/store/modules/filter/index.js b/src/js/store/modules/filter/index.js
index baa48176f..c04db4b8f 100644
--- a/src/js/store/modules/filter/index.js
+++ b/src/js/store/modules/filter/index.js
@@ -9,7 +9,8 @@ const state = {
taxquery: []
},
filters: [],
- filterTypes: []
+ filterTypes: [],
+ taxonomyFilters: {}
};
export default {
diff --git a/src/js/store/modules/filter/mutations.js b/src/js/store/modules/filter/mutations.js
index 99a96a543..45b941896 100644
--- a/src/js/store/modules/filter/mutations.js
+++ b/src/js/store/modules/filter/mutations.js
@@ -34,4 +34,19 @@ export const updateFiltersOrderFromCollection = (state, filtersOrder) => {
export const setFilterTypes = (state, filterTypes) => {
state.filterTypes = filterTypes;
+}
+
+export const setTaxonomyFilters = (state, taxonomyFilters) => {
+ state.taxonomyFilters = taxonomyFilters;
+}
+
+export const setTaxonomyFiltersForCollection = (state, { collectionName, taxonomyFilters }) => {
+ if (collectionName != undefined)
+ Vue.set(state.taxonomyFilters, collectionName, taxonomyFilters);
+ else
+ Vue.set(state.taxonomyFilters, 'repository-filters', taxonomyFilters);
+}
+
+export const clearTaxonomyFilters = (state) => {
+ state.taxonomyFilters = {};
}
\ No newline at end of file
diff --git a/src/js/store/modules/importer/actions.js b/src/js/store/modules/importer/actions.js
index c82ad5b88..2b402043a 100644
--- a/src/js/store/modules/importer/actions.js
+++ b/src/js/store/modules/importer/actions.js
@@ -162,3 +162,18 @@ export const runImporter = ( { dispatch } , importerId ) => {
});
});
};
+
+export const fetchMappingImporter = ( { commit }, { sessionId, collection } ) => {
+ return new Promise(( resolve, reject ) => {
+
+ axios.tainacan.get('importers/session/' + sessionId + '/get_mapping/' + collection)
+ .then( res => {
+ let mapping = res.data;
+ commit('setMappingImporter', mapping);
+ resolve( mapping );
+ })
+ .catch(error => {
+ reject( error.response.data );
+ });
+ });
+};
diff --git a/src/js/store/modules/importer/getters.js b/src/js/store/modules/importer/getters.js
index fd6a37e10..b2f4afb7b 100644
--- a/src/js/store/modules/importer/getters.js
+++ b/src/js/store/modules/importer/getters.js
@@ -12,4 +12,8 @@ export const getImporterSourceInfo = state => {
export const getImporterFile = state => {
return state.importer_file;
+}
+
+export const getImporterMapping = state => {
+ return state.importer_mapping
}
\ No newline at end of file
diff --git a/src/js/store/modules/importer/index.js b/src/js/store/modules/importer/index.js
index 280edc71c..b8b9214d9 100644
--- a/src/js/store/modules/importer/index.js
+++ b/src/js/store/modules/importer/index.js
@@ -6,7 +6,8 @@ const state = {
importer: {},
available_importers: [],
importer_file: {},
- importer_source_info: {}
+ importer_source_info: {},
+ importer_mapping: []
};
export default {
diff --git a/src/js/store/modules/importer/mutations.js b/src/js/store/modules/importer/mutations.js
index 3514aaca7..46ebc112f 100644
--- a/src/js/store/modules/importer/mutations.js
+++ b/src/js/store/modules/importer/mutations.js
@@ -14,4 +14,8 @@ export const setImporterFile = (state, importerFile) => {
export const setImporterSourceInfo= (state, importerSourceInfo) => {
state.importer_source_info = importerSourceInfo;
+}
+
+export const setMappingImporter = (state, importerMapping) => {
+ state.importer_mapping = importerMapping;
}
\ No newline at end of file
diff --git a/src/js/store/modules/taxonomy/actions.js b/src/js/store/modules/taxonomy/actions.js
index 65e97b290..caea9b84b 100644
--- a/src/js/store/modules/taxonomy/actions.js
+++ b/src/js/store/modules/taxonomy/actions.js
@@ -94,7 +94,6 @@ export const fetchTaxonomyName = ({ commit }, taxonomyId) => {
let name = res.data;
commit('setTaxonomyName');
-
resolve(name.name)
})
.catch(error => {
diff --git a/src/readme.txt b/src/readme.txt
index e6fedc76d..ce3bb5ec9 100644
--- a/src/readme.txt
+++ b/src/readme.txt
@@ -2,9 +2,9 @@
Contributors: andrebenedito, daltonmartins, fabianobn, jacsonp, leogermani, weryques, wetah
Tags: museums, libraries, archives, GLAM, collections, repository
Requires at least: 4.8
-Tested up to: 4.9.8
+Tested up to: 5.0 beta-5
Requires PHP: 5.6
-Stable tag: 0.5
+Stable tag: 0.6
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-3.0.html
@@ -14,8 +14,6 @@ Tainacan is a powerful and flexible repository platform for WordPress. Manage an
Tainacan is a powerful and flexible repository platform for WordPress. Manage and publish you digital collections as easily as publishing a post to your blog, while having all the tools of a professional repository platform.
-Please note: This is an early release of this plugin, and we are working hard to release 1.0 soon, please refer to the [project's website](http://tainacan.org/) for more information and road map.
-
= Features =
* "Metadata and Filters": Use a metadata standard or choose whatever set of metadata you want to describe the items in your collections. Also, choose which metadata will be used as a filter when browsing the collection
@@ -77,7 +75,7 @@ If you have Imagick installed in your server, Tainacan will be able to automatic
== Screenshots ==
-1. Manage collections
+1. Manage your repository
2. Set up your collection
3. Choose the metadata and filters for your collection
4. Add items described by your metadata
diff --git a/src/tainacan.php b/src/tainacan.php
index 1797bf923..9b31b35cd 100644
--- a/src/tainacan.php
+++ b/src/tainacan.php
@@ -4,7 +4,7 @@ Plugin Name: Tainacan
Plugin URI: https://tainacan.org/
Description: powerfull and flexible repository platform for WordPress. Manage and publish you digital collections as easily as publishing a post to your blog, while having all the tools of a professional respository platform.
Author: Media Lab / UFG
-Version: 0.5
+Version: 0.6
Text Domain: tainacan
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-3.0.html
diff --git a/src/theme-helper/class-tainacan-theme-helper.php b/src/theme-helper/class-tainacan-theme-helper.php
index 59b008e0c..35b96d4ad 100644
--- a/src/theme-helper/class-tainacan-theme-helper.php
+++ b/src/theme-helper/class-tainacan-theme-helper.php
@@ -60,35 +60,35 @@ class Theme_Helper {
$this->register_view_mode('table', [
'label' => __('Table', 'tainacan'),
'dynamic_metadata' => true,
- 'icon' => ' ',
+ 'icon' => ' ',
'type' => 'component',
]);
$this->register_view_mode('cards', [
'label' => __('Cards', 'tainacan'),
'dynamic_metadata' => false,
'description' => 'A cards view, displaying title, description, author name and creation date.',
- 'icon' => ' ',
+ 'icon' => ' ',
'type' => 'component'
]);
$this->register_view_mode('records', [
'label' => __('Records', 'tainacan'),
'dynamic_metadata' => true,
'description' => 'A records view, similiar to cards, but flexible for metadata',
- 'icon' => ' ',
+ 'icon' => ' ',
'type' => 'component'
]);
$this->register_view_mode('masonry', [
'label' => __('Masonry', 'tainacan'),
'dynamic_metadata' => false,
'description' => 'A masonry view, similar to pinterest, which will display images without cropping.',
- 'icon' => ' ',
+ 'icon' => ' ',
'type' => 'component'
]);
$this->register_view_mode('slideshow', [
'label' => __('Slideshow', 'tainacan'),
'dynamic_metadata' => false,
'description' => 'A fullscreen slideshow view.',
- 'icon' => ' ',
+ 'icon' => ' ',
'type' => 'component',
'show_pagination' => false,
'full_screen' => true
diff --git a/src/theme-helper/template-tags.php b/src/theme-helper/template-tags.php
index 4e599f81d..a5e8aadea 100644
--- a/src/theme-helper/template-tags.php
+++ b/src/theme-helper/template-tags.php
@@ -196,13 +196,15 @@ function tainacan_the_faceted_search() {
if ($term) {
$props .= 'term-id="' . $term->term_id . '" ';
$props .= 'taxonomy="' . $term->taxonomy . '" ';
+ // $props .= 'custom-filters="[72432,84385]" '; // Only to be used when dealing with custom filters
+ // $props .= 'collection-id="43385" '; // Only to be used when dealing with custom filters
}
$props .= 'default-view-mode="' . $default_view_mode . '" ';
$props .= 'enabled-view-modes="' . implode(',', $enabled_view_modes) . '" ';
echo "
";
-
+
}
/**
diff --git a/src/theme-helper/view-mode-cards.vue b/src/theme-helper/view-mode-cards.vue
index 2f0cda8ac..fd714f331 100644
--- a/src/theme-helper/view-mode-cards.vue
+++ b/src/theme-helper/view-mode-cards.vue
@@ -7,9 +7,9 @@
class="section">
-
+
+
+
{{ $i18n.get('info_no_item_found') }}
diff --git a/src/theme-helper/view-mode-masonry.vue b/src/theme-helper/view-mode-masonry.vue
index cd85be182..1b4300cf1 100644
--- a/src/theme-helper/view-mode-masonry.vue
+++ b/src/theme-helper/view-mode-masonry.vue
@@ -7,9 +7,9 @@
class="section">
-
+
+
+
{{ $i18n.get('info_no_item_found') }}
diff --git a/src/theme-helper/view-mode-records.vue b/src/theme-helper/view-mode-records.vue
index 5b8cea968..c19249337 100644
--- a/src/theme-helper/view-mode-records.vue
+++ b/src/theme-helper/view-mode-records.vue
@@ -7,9 +7,9 @@
class="section">
-
+
+
+
{{ $i18n.get('info_no_item_found') }}
diff --git a/src/theme-helper/view-mode-slideshow.vue b/src/theme-helper/view-mode-slideshow.vue
index fcf11abef..7fa5d0d77 100644
--- a/src/theme-helper/view-mode-slideshow.vue
+++ b/src/theme-helper/view-mode-slideshow.vue
@@ -11,7 +11,9 @@
id="close-fullscren-button"
:class="{ 'is-hidden-mobile': !isMetadataCompressed }"
@click="closeSlideViewMode()">
-
+
+
+
@@ -23,7 +25,11 @@
}"
id="metadata-compress-button"
@click="isMetadataCompressed = !isMetadataCompressed">
-
+
+
+