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">

- + +

@@ -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')"/> + + + + + 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') : ''">
- + + + - + + + @@ -86,9 +102,9 @@ :aria-label="$i18n.get('label_button_edit_document')" id="button-edit-document" @click.prevent="setTextDocument()"> - + + + - + + + @@ -111,9 +127,9 @@ :aria-label="$i18n.get('label_button_edit_document')" id="button-edit-document" @click.prevent="setURLDocument()"> - + + + - + + + @@ -133,7 +149,9 @@

{{ $i18n.get('label_file') }}

@@ -141,7 +159,9 @@

{{ $i18n.get('label_text') }}

@@ -149,7 +169,9 @@

{{ $i18n.get('label_url') }}

@@ -257,9 +279,9 @@ id="button-edit-thumbnail" :aria-label="$i18n.get('label_button_edit_thumb')" @click.prevent="thumbnailMediaFrame.openFrame($event)"> - + + + - + + + @@ -356,16 +378,18 @@ value="publish" native-value="publish"> - - {{ $i18n.get('publish_visibility') }} + + + {{ $i18n.get('publish_visibility') }} - - {{ $i18n.get('private_visibility') }} + + + {{ $i18n.get('private_visibility') }} @@ -391,7 +415,11 @@ class="collapse-all" @click="toggleCollapseAll()"> {{ collapseAll ? $i18n.get('label_collapse_all') : $i18n.get('label_expand_all') }} - + + + - {{ $i18n.get('info_updating_metadata_values') }} + + + + {{ $i18n.get('info_updating_metadata_values') }} {{ formErrorMessage }}

@@ -451,7 +482,7 @@ type="button" class="button sequence-button"> - + {{ $i18n.get('previous') }} @@ -474,9 +505,19 @@ class="button sequence-button"> {{ $i18n.get('next') }} - + + @@ -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 @@ + \ 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 @@ + - 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.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')"> + @@ -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')"> + + + @@ -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 @@ 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 @@