Merge branch 'develop' of https://github.com/tainacan/tainacan into develop
This commit is contained in:
commit
4e14364968
|
@ -30,6 +30,8 @@ report.txt
|
|||
demosaved.csv
|
||||
src/assets/css/tainacan-embeds.css
|
||||
src/assets/css/tainacan-embeds.css.map
|
||||
src/assets/css/tainacan-reports.css
|
||||
src/assets/css/tainacan-reports.css.map
|
||||
.DS_Store
|
||||
src/.DS_Store
|
||||
src/assets/css/tainacan-gutenberg-block-dynamic-items-list.css
|
||||
|
|
|
@ -12,33 +12,36 @@ sass -E 'UTF-8' --cache-location .tmp/sass-cache-1 src/views/admin/scss/tainacan
|
|||
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-2 src/views/roles/tainacan-roles.scss:src/assets/css/tainacan-roles.css
|
||||
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-3 src/views/media-component/media-component.scss:src/assets/css/media-component.css
|
||||
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-4 src/views/gutenberg-blocks/tainacan-collections/collections-list/collections-list.scss:src/assets/css/tainacan-gutenberg-block-collections-list.css
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-3 src/views/reports/tainacan-reports.scss:src/assets/css/tainacan-reports.css
|
||||
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-5 src/views/gutenberg-blocks/tainacan-collections/carousel-collections-list/carousel-collections-list.scss:src/assets/css/tainacan-gutenberg-block-carousel-collections-list.css
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-4 src/views/media-component/media-component.scss:src/assets/css/media-component.css
|
||||
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-6 src/views/gutenberg-blocks/tainacan-items/items-list/items-list.scss:src/assets/css/tainacan-gutenberg-block-items-list.css
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-5 src/views/gutenberg-blocks/tainacan-collections/collections-list/collections-list.scss:src/assets/css/tainacan-gutenberg-block-collections-list.css
|
||||
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-7 src/views/gutenberg-blocks/tainacan-items/dynamic-items-list/dynamic-items-list.scss:src/assets/css/tainacan-gutenberg-block-dynamic-items-list.css
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-6 src/views/gutenberg-blocks/tainacan-collections/carousel-collections-list/carousel-collections-list.scss:src/assets/css/tainacan-gutenberg-block-carousel-collections-list.css
|
||||
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-8 src/views/gutenberg-blocks/tainacan-items/search-bar/search-bar.scss:src/assets/css/tainacan-gutenberg-block-search-bar.css
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-7 src/views/gutenberg-blocks/tainacan-items/items-list/items-list.scss:src/assets/css/tainacan-gutenberg-block-items-list.css
|
||||
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-9 src/views/gutenberg-blocks/tainacan-items/carousel-items-list/carousel-items-list.scss:src/assets/css/tainacan-gutenberg-block-carousel-items-list.css
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-8 src/views/gutenberg-blocks/tainacan-items/dynamic-items-list/dynamic-items-list.scss:src/assets/css/tainacan-gutenberg-block-dynamic-items-list.css
|
||||
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-9 src/views/gutenberg-blocks/tainacan-items/search-bar/search-bar.scss:src/assets/css/tainacan-gutenberg-block-search-bar.css
|
||||
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-10 src/views/gutenberg-blocks/tainacan-items/carousel-items-list/carousel-items-list.scss:src/assets/css/tainacan-gutenberg-block-carousel-items-list.css
|
||||
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-11 src/views/gutenberg-blocks/tainacan-terms/terms-list/terms-list.scss:src/assets/css/tainacan-gutenberg-block-terms-list.css
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-12 src/views/gutenberg-blocks/tainacan-items/carousel-items-list/carousel-items-list.scss:src/assets/css/tainacan-gutenberg-block-carousel-items-list.css
|
||||
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-12 src/views/gutenberg-blocks/tainacan-facets/facets-list/facets-list.scss:src/assets/css/tainacan-gutenberg-block-facets-list.css
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-12 src/views/gutenberg-blocks/tainacan-terms/terms-list/terms-list.scss:src/assets/css/tainacan-gutenberg-block-terms-list.css
|
||||
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-13 src/views/gutenberg-blocks/tainacan-terms/carousel-terms-list/carousel-terms-list.scss:src/assets/css/tainacan-gutenberg-block-carousel-terms-list.css
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-13 src/views/gutenberg-blocks/tainacan-facets/facets-list/facets-list.scss:src/assets/css/tainacan-gutenberg-block-facets-list.css
|
||||
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-14 src/views/gutenberg-blocks/tainacan-facets/faceted-search/faceted-search.scss:src/assets/css/tainacan-gutenberg-block-faceted-search.css
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-14 src/views/gutenberg-blocks/tainacan-terms/carousel-terms-list/carousel-terms-list.scss:src/assets/css/tainacan-gutenberg-block-carousel-terms-list.css
|
||||
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-15 src/views/gutenberg-blocks/tainacan-items/item-submission-form/item-submission-form.scss:src/assets/css/tainacan-gutenberg-block-item-submission-form.css
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-15 src/views/gutenberg-blocks/tainacan-facets/faceted-search/faceted-search.scss:src/assets/css/tainacan-gutenberg-block-faceted-search.css
|
||||
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-16 src/views/gutenberg-blocks/gutenberg-blocks-style.scss:src/assets/css/tainacan-gutenberg-block-common-styles.css
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-16 src/views/gutenberg-blocks/tainacan-items/item-submission-form/item-submission-form.scss:src/assets/css/tainacan-gutenberg-block-item-submission-form.css
|
||||
|
||||
sass -E 'UTF-8' --cache-location .tmp/sass-cache-17 src/views/gutenberg-blocks/gutenberg-blocks-style.scss:src/assets/css/tainacan-gutenberg-block-common-styles.css
|
||||
|
||||
echo "Compilação do Sass Concluído!"
|
||||
exit 0
|
||||
|
|
|
@ -1665,6 +1665,19 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"apexcharts": {
|
||||
"version": "3.24.0",
|
||||
"resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.24.0.tgz",
|
||||
"integrity": "sha512-iT6czJCIVrmAtrcO90MZTQCvC+xi6R6Acf0jNH/d40FVTtCfcqECuKIh5iAMyOTtgUb7+fQ8rbadH2bm1kbL9Q==",
|
||||
"requires": {
|
||||
"svg.draggable.js": "^2.2.2",
|
||||
"svg.easing.js": "^2.0.0",
|
||||
"svg.filter.js": "^2.0.2",
|
||||
"svg.pathmorphing.js": "^0.1.3",
|
||||
"svg.resize.js": "^1.4.3",
|
||||
"svg.select.js": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
|
||||
|
@ -2992,6 +3005,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"countup.js": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/countup.js/-/countup.js-2.0.7.tgz",
|
||||
"integrity": "sha512-FO0nQdvG1iQwHp28wdvkErxnNUSbdkzztqZ6YNHKLHydngD2tdiKEW8dFrqpahF3tj+Ma70h0vyYrCBzxlVWdg=="
|
||||
},
|
||||
"create-ecdh": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
|
||||
|
@ -9489,9 +9507,9 @@
|
|||
"integrity": "sha512-NXzN+/HPObKAx191H3zKlYomE5WrVIkoCB5IaSdvKokxTpjBdWfr0RaP+1Z5KOfDT0ZVz+2tdtiBkhsEQ9p+0A=="
|
||||
},
|
||||
"ssri": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz",
|
||||
"integrity": "sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==",
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
|
||||
"integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minipass": "^3.1.1"
|
||||
|
@ -10002,6 +10020,70 @@
|
|||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
||||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
|
||||
},
|
||||
"svg.draggable.js": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz",
|
||||
"integrity": "sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==",
|
||||
"requires": {
|
||||
"svg.js": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"svg.easing.js": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/svg.easing.js/-/svg.easing.js-2.0.0.tgz",
|
||||
"integrity": "sha1-iqmUawqOJ4V6XEChDrpAkeVpHxI=",
|
||||
"requires": {
|
||||
"svg.js": ">=2.3.x"
|
||||
}
|
||||
},
|
||||
"svg.filter.js": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/svg.filter.js/-/svg.filter.js-2.0.2.tgz",
|
||||
"integrity": "sha1-kQCOFROJ3ZIwd5/L5uLJo2LRwgM=",
|
||||
"requires": {
|
||||
"svg.js": "^2.2.5"
|
||||
}
|
||||
},
|
||||
"svg.js": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz",
|
||||
"integrity": "sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA=="
|
||||
},
|
||||
"svg.pathmorphing.js": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz",
|
||||
"integrity": "sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==",
|
||||
"requires": {
|
||||
"svg.js": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"svg.resize.js": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/svg.resize.js/-/svg.resize.js-1.4.3.tgz",
|
||||
"integrity": "sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==",
|
||||
"requires": {
|
||||
"svg.js": "^2.6.5",
|
||||
"svg.select.js": "^2.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"svg.select.js": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-2.1.2.tgz",
|
||||
"integrity": "sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==",
|
||||
"requires": {
|
||||
"svg.js": "^2.2.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"svg.select.js": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-3.0.1.tgz",
|
||||
"integrity": "sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==",
|
||||
"requires": {
|
||||
"svg.js": "^2.6.5"
|
||||
}
|
||||
},
|
||||
"swiper": {
|
||||
"version": "5.4.5",
|
||||
"resolved": "https://registry.npmjs.org/swiper/-/swiper-5.4.5.tgz",
|
||||
|
@ -10718,6 +10800,11 @@
|
|||
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.11.tgz",
|
||||
"integrity": "sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ=="
|
||||
},
|
||||
"vue-apexcharts": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-apexcharts/-/vue-apexcharts-1.6.0.tgz",
|
||||
"integrity": "sha512-sT6tuVTLBwfH3TA7azecDNS/W70bmz14ZJI7aE7QIqcG9I6OywyH7x3hcOeY1v1DxttI8Svc5RuYj4Dd+A5F4g=="
|
||||
},
|
||||
"vue-awesome-swiper": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/vue-awesome-swiper/-/vue-awesome-swiper-4.1.1.tgz",
|
||||
|
@ -10728,6 +10815,11 @@
|
|||
"resolved": "https://registry.npmjs.org/vue-blurhash/-/vue-blurhash-0.1.4.tgz",
|
||||
"integrity": "sha512-B76GgfHXHkdmYgAfI2rZl3BgCMD9OxAgn4Jw2Ro0a8ZoAKa6gqTWUrTo5EGXOftm/EKuMYi1Cc+UcAvV0jnoRw=="
|
||||
},
|
||||
"vue-countup-v2": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-countup-v2/-/vue-countup-v2-4.0.0.tgz",
|
||||
"integrity": "sha512-XjKeHo1ndRlJtXvHd6B1eWOpbrJDdNU3rdYZwVPv2YlUXbvthsBT4kms5Fc/mn9RdXPrMX2H/ktAAQtKjWFisw=="
|
||||
},
|
||||
"vue-eslint-parser": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-5.0.0.tgz",
|
||||
|
@ -10963,15 +11055,6 @@
|
|||
"stream-each": "^1.1.0",
|
||||
"through2": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"ssri": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
|
||||
"integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"figgy-pudding": "^3.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -11057,6 +11140,15 @@
|
|||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
},
|
||||
"ssri": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz",
|
||||
"integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"figgy-pudding": "^3.5.1"
|
||||
}
|
||||
},
|
||||
"tapable": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
"build-prod": "cross-env NODE_ENV=production webpack --config webpack.prod.js --display-error-details --progress --hide-modules"
|
||||
},
|
||||
"dependencies": {
|
||||
"apexcharts": "^3.24.0",
|
||||
"countup.js": "^2.0.7",
|
||||
"axios": "^0.21.1",
|
||||
"blurhash": "^1.1.3",
|
||||
"buefy": "^0.9.7",
|
||||
|
@ -24,8 +26,10 @@
|
|||
"t": "^0.5.1",
|
||||
"v-tooltip": "^2.0.3",
|
||||
"vue": "^2.6.11",
|
||||
"vue-apexcharts": "^1.6.0",
|
||||
"vue-awesome-swiper": "^4.1.1",
|
||||
"vue-blurhash": "^0.1.4",
|
||||
"vue-countup-v2": "^4.0.0",
|
||||
"vue-masonry-css": "^1.0.3",
|
||||
"vue-router": "^3.1.6",
|
||||
"vue-the-mask": "^0.11.1",
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
#tainacan-reports-app {
|
||||
padding: 10px 2px 10px 2px;
|
||||
margin: 0; }
|
||||
#tainacan-reports-app .tainacan-icon::before {
|
||||
opacity: 0.0; }
|
||||
#tainacan-reports-app a:hover {
|
||||
cursor: pointer; }
|
||||
#tainacan-reports-app .wp-heading-inline {
|
||||
margin-bottom: 2rem; }
|
||||
#tainacan-reports-app .columns {
|
||||
max-width: 100%;
|
||||
align-items: flex-start;
|
||||
justify-content: center; }
|
||||
#tainacan-reports-app .columns .column {
|
||||
max-width: 100%;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
box-sizing: content-box; }
|
||||
#tainacan-reports-app .columns .column .postbox {
|
||||
margin: 0.75rem; }
|
||||
#tainacan-reports-app .columns .column .box-last-cached-on {
|
||||
position: absolute;
|
||||
bottom: calc(1px + 0.75rem);
|
||||
right: calc(1px + 0.75rem);
|
||||
display: inline-block;
|
||||
padding: 0px 10px;
|
||||
background-color: var(--tainacan-block-gray2, #dbdbdb);
|
||||
color: var(--tainacan-block-gray4, #555758);
|
||||
font-size: 0.875em;
|
||||
border-top-left-radius: 3px;
|
||||
opacity: 0.0;
|
||||
transition: opacity 0.3s ease; }
|
||||
#tainacan-reports-app .columns .column .box-last-cached-on button {
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer; }
|
||||
#tainacan-reports-app .columns .column .box-last-cached-on button:hover {
|
||||
color: var(--wp-admin-theme-color, #007cba); }
|
||||
#tainacan-reports-app .columns .column .postbox:hover + .box-last-cached-on,
|
||||
#tainacan-reports-app .columns .column .postbox:hover + .box-last-cached-on + .box-last-cached-on,
|
||||
#tainacan-reports-app .columns .column .box-last-cached-on:hover {
|
||||
opacity: 1.0; }
|
||||
#tainacan-reports-app .postbox {
|
||||
padding: 1.125rem 1.25rem;
|
||||
margin-bottom: 0;
|
||||
height: 100%;
|
||||
min-height: 380px;
|
||||
background-color: var(--tainacan-block-gray0, #f6f6f6); }
|
||||
#tainacan-reports-app .postbox label {
|
||||
font-weight: bold;
|
||||
font-size: 0.875rem; }
|
||||
#tainacan-reports-app .postbox .box-header {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap; }
|
||||
#tainacan-reports-app .postbox .box-header .box-header__item {
|
||||
margin-bottom: 10px;
|
||||
line-height: 2rem; }
|
||||
#tainacan-reports-app .graph-mode-switch {
|
||||
display: inline-block; }
|
||||
#tainacan-reports-app .graph-mode-switch button {
|
||||
border: none !important;
|
||||
background: none !important;
|
||||
box-shadow: none !important;
|
||||
padding: 0;
|
||||
cursor: pointer; }
|
||||
#tainacan-reports-app .graph-mode-switch button.current {
|
||||
color: var(--wp-admin-theme-color, #007cba); }
|
||||
#tainacan-reports-app .tainacan-custom-tooltip {
|
||||
padding: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
flex-direction: column; }
|
||||
#tainacan-reports-app .tainacan-custom-tooltip .tainacan-custom-tooltip__header {
|
||||
background-color: var(--tainacan-block-gray1, #f2f2f2);
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 6px 10px 4px 10px; }
|
||||
#tainacan-reports-app .tainacan-custom-tooltip .tainacan-custom-tooltip__header + .tainacan-custom-tooltip__body {
|
||||
padding: 4px 10px 6px 10px; }
|
||||
#tainacan-reports-app .tainacan-custom-tooltip .tainacan-custom-tooltip__body {
|
||||
width: 100%;
|
||||
padding: 6px 10px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
flex-direction: column; }
|
||||
#tainacan-reports-app .tainacan-custom-tooltip .tainacan-custom-tooltip__body p {
|
||||
margin-bottom: 4px;
|
||||
font-size: 0.85rem; }
|
||||
|
||||
/*# sourceMappingURL=tainacan-reports.css.map */
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"version": 3,
|
||||
"mappings": "AAAA,qBAAsB;EAClB,OAAO,EAAE,iBAAiB;EAC1B,MAAM,EAAE,CAAC;EAGT,4CAAuB;IACnB,OAAO,EAAE,GAAG;EAGhB,6BAAQ;IACJ,MAAM,EAAE,OAAO;EAGnB,wCAAmB;IACf,aAAa,EAAE,IAAI;EAGvB,8BAAS;IACL,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,UAAU;IACvB,eAAe,EAAE,MAAM;IAEvB,sCAAQ;MACJ,SAAS,EAAE,IAAI;MACf,OAAO,EAAE,CAAC;MACV,QAAQ,EAAE,QAAQ;MAClB,UAAU,EAAE,WAAW;MAEvB,+CAAS;QACL,MAAM,EAAE,OAAO;MAEnB,0DAAoB;QAChB,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,mBAAmB;QAC3B,KAAK,EAAE,mBAAmB;QAC1B,OAAO,EAAE,YAAY;QACrB,OAAO,EAAE,QAAQ;QACjB,gBAAgB,EAAE,oCAAoC;QACtD,KAAK,EAAE,oCAAoC;QAC3C,SAAS,EAAE,OAAO;QAClB,sBAAsB,EAAE,GAAG;QAC3B,OAAO,EAAE,GAAG;QACZ,UAAU,EAAE,iBAAiB;QAE7B,iEAAO;UACH,MAAM,EAAE,IAAI;UACZ,UAAU,EAAE,IAAI;UAChB,MAAM,EAAE,OAAO;UAEf,uEAAQ;YACJ,KAAK,EAAE,oCAAoC;MAIvD;;sEAE0B;QACtB,OAAO,EAAE,GAAG;EAKxB,8BAAS;IACL,OAAO,EAAE,gBAAgB;IACzB,aAAa,EAAE,CAAC;IAChB,MAAM,EAAE,IAAI;IACZ,UAAU,EAAE,KAAK;IACjB,gBAAgB,EAAE,oCAAoC;IAEtD,oCAAM;MACF,WAAW,EAAE,IAAI;MACjB,SAAS,EAAE,QAAQ;IAGvB,0CAAY;MACR,OAAO,EAAE,IAAI;MACb,WAAW,EAAE,QAAQ;MACrB,eAAe,EAAE,aAAa;MAC9B,SAAS,EAAE,IAAI;MAEf,4DAAkB;QACd,aAAa,EAAE,IAAI;QACnB,WAAW,EAAE,IAAI;EAI7B,wCAAmB;IACf,OAAO,EAAE,YAAY;IACrB,+CAAO;MACH,MAAM,EAAE,eAAe;MACvB,UAAU,EAAE,eAAe;MAC3B,UAAU,EAAE,eAAe;MAC3B,OAAO,EAAE,CAAC;MACV,MAAM,EAAE,OAAO;MAEf,uDAAU;QACN,KAAK,EAAE,oCAAoC;EAKvD,8CAAyB;IACrB,OAAO,EAAE,CAAC;IACV,OAAO,EAAE,IAAI;IACb,eAAe,EAAE,MAAM;IACvB,WAAW,EAAE,UAAU;IACvB,cAAc,EAAE,MAAM;IAEtB,+EAAiC;MAC7B,gBAAgB,EAAE,oCAAoC;MACtD,OAAO,EAAE,IAAI;MACb,eAAe,EAAE,UAAU;MAC3B,WAAW,EAAE,MAAM;MACnB,KAAK,EAAE,IAAI;MACX,OAAO,EAAE,iBAAiB;IAG9B,gHAAgE;MAC5D,OAAO,EAAE,iBAAiB;IAE9B,6EAA+B;MAC3B,KAAK,EAAE,IAAI;MACX,OAAO,EAAE,QAAQ;MACjB,OAAO,EAAE,IAAI;MACb,eAAe,EAAE,MAAM;MACvB,WAAW,EAAE,UAAU;MACvB,cAAc,EAAE,MAAM;MAEtB,+EAAE;QACE,aAAa,EAAE,GAAG;QAClB,SAAS,EAAE,OAAO",
|
||||
"sources": ["../../views/reports/tainacan-reports.scss"],
|
||||
"names": [],
|
||||
"file": "tainacan-reports.css"
|
||||
}
|
|
@ -0,0 +1,837 @@
|
|||
<?php
|
||||
|
||||
namespace Tainacan\API\EndPoints;
|
||||
|
||||
use \Tainacan\API\REST_Controller;
|
||||
use Tainacan\Entities;
|
||||
use Tainacan\Repositories;
|
||||
|
||||
class REST_Reports_Controller extends REST_Controller {
|
||||
|
||||
public function __construct() {
|
||||
$this->rest_base = 'reports';
|
||||
parent::__construct();
|
||||
add_action('init', array(&$this, 'init_objects'), 11);
|
||||
}
|
||||
|
||||
public function init_objects() {
|
||||
$this->items_repository = Repositories\Items::get_instance();
|
||||
$this->taxonomy_repository = Repositories\Taxonomies::get_instance();
|
||||
$this->metadatum_repository = Repositories\Metadata::get_instance();
|
||||
$this->collections_repository = Repositories\Collections::get_instance();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route($this->namespace, $this->rest_base . '/collection',
|
||||
array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array($this, 'get_collections'),
|
||||
'permission_callback' => array($this, 'reports_permissions_check'),
|
||||
'args' => [
|
||||
'force' => [
|
||||
'title' => __( 'Force regenerete', 'tainacan' ),
|
||||
'type' => 'string',
|
||||
'default' => 'no',
|
||||
'description' => __( 'Force generates the reports graphic.', 'tainacan' ),
|
||||
'enum' => array(
|
||||
'no',
|
||||
'yes'
|
||||
)
|
||||
]
|
||||
]
|
||||
),
|
||||
)
|
||||
);
|
||||
register_rest_route($this->namespace, $this->rest_base . '/collection/(?P<collection_id>[\d]+)/summary',
|
||||
array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array($this, 'get_summary'),
|
||||
'permission_callback' => array($this, 'reports_permissions_check'),
|
||||
'args' => [
|
||||
'force' => [
|
||||
'title' => __( 'Force regenerete', 'tainacan' ),
|
||||
'type' => 'string',
|
||||
'default' => 'no',
|
||||
'description' => __( 'Force generates the reports graphic.', 'tainacan' ),
|
||||
'enum' => array(
|
||||
'no',
|
||||
'yes'
|
||||
)
|
||||
]
|
||||
]
|
||||
),
|
||||
)
|
||||
);
|
||||
register_rest_route($this->namespace, $this->rest_base . '/collection/(?P<collection_id>[\d]+)/metadata',
|
||||
array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array($this, 'get_stats_collection_metadata'),
|
||||
'permission_callback' => array($this, 'reports_permissions_check'),
|
||||
'args' => [
|
||||
'force' => [
|
||||
'title' => __( 'Force regenerete', 'tainacan' ),
|
||||
'type' => 'string',
|
||||
'default' => 'no',
|
||||
'description' => __( 'Force generates the reports graphic.', 'tainacan' ),
|
||||
'enum' => array(
|
||||
'no',
|
||||
'yes'
|
||||
)
|
||||
]
|
||||
]
|
||||
),
|
||||
)
|
||||
);
|
||||
register_rest_route($this->namespace, $this->rest_base . '/metadata',
|
||||
array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array($this, 'get_stats_collection_metadata'),
|
||||
'permission_callback' => array($this, 'reports_permissions_check'),
|
||||
'args' => [
|
||||
'force' => [
|
||||
'title' => __( 'Force regenerete', 'tainacan' ),
|
||||
'type' => 'string',
|
||||
'default' => 'no',
|
||||
'description' => __( 'Force generates the reports graphic.', 'tainacan' ),
|
||||
'enum' => array(
|
||||
'no',
|
||||
'yes'
|
||||
)
|
||||
]
|
||||
]
|
||||
),
|
||||
)
|
||||
);
|
||||
register_rest_route($this->namespace, $this->rest_base . '/repository/summary',
|
||||
array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array($this, 'get_summary'),
|
||||
'permission_callback' => array($this, 'reports_permissions_check'),
|
||||
'args' => [
|
||||
'force' => [
|
||||
'title' => __( 'Force regenerete', 'tainacan' ),
|
||||
'type' => 'string',
|
||||
'default' => 'no',
|
||||
'description' => __( 'Force generates the reports graphic.', 'tainacan' ),
|
||||
'enum' => array(
|
||||
'no',
|
||||
'yes'
|
||||
)
|
||||
]
|
||||
]
|
||||
),
|
||||
)
|
||||
);
|
||||
register_rest_route($this->namespace, $this->rest_base . '/taxonomy',
|
||||
array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array($this, 'get_taxonomies_list'),
|
||||
'permission_callback' => array($this, 'reports_permissions_check'),
|
||||
'args' => [
|
||||
'force' => [
|
||||
'title' => __( 'Force regenerete', 'tainacan' ),
|
||||
'type' => 'string',
|
||||
'default' => 'no',
|
||||
'description' => __( 'Force generates the reports graphic.', 'tainacan' ),
|
||||
'enum' => array(
|
||||
'no',
|
||||
'yes'
|
||||
)
|
||||
]
|
||||
]
|
||||
),
|
||||
)
|
||||
);
|
||||
register_rest_route($this->namespace, $this->rest_base . '/taxonomy/(?P<taxonomy_id>[\d]+)',
|
||||
array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array($this, 'get_taxonomy'),
|
||||
'permission_callback' => array($this, 'reports_permissions_check'),
|
||||
'args' => [
|
||||
'force' => [
|
||||
'title' => __( 'Force regenerete', 'tainacan' ),
|
||||
'type' => 'string',
|
||||
'default' => 'no',
|
||||
'description' => __( 'Force generates the reports graphic.', 'tainacan' ),
|
||||
'enum' => array(
|
||||
'no',
|
||||
'yes'
|
||||
)
|
||||
]
|
||||
]
|
||||
),
|
||||
)
|
||||
);
|
||||
register_rest_route($this->namespace, $this->rest_base . '/activities',
|
||||
array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array($this, 'get_activities'),
|
||||
'permission_callback' => array($this, 'reports_permissions_check'),
|
||||
'args' => [
|
||||
'start' => [
|
||||
'title' => __( 'start Date', 'tainacan' ),
|
||||
'type' => 'string',
|
||||
'format' => 'date-time',
|
||||
],
|
||||
'end' => [
|
||||
'title' => __( 'start Date', 'tainacan' ),
|
||||
'type' => 'string',
|
||||
'format' => 'date-time', // RFC3339. https://tools.ietf.org/html/rfc3339#section-5.8
|
||||
],
|
||||
'force' => [
|
||||
'title' => __( 'Force regenerete', 'tainacan' ),
|
||||
'type' => 'string',
|
||||
'default' => 'no',
|
||||
'description' => __( 'Force generates the reports graphic.', 'tainacan' ),
|
||||
'enum' => array(
|
||||
'no',
|
||||
'yes'
|
||||
)
|
||||
]
|
||||
]
|
||||
),
|
||||
)
|
||||
);
|
||||
register_rest_route($this->namespace, $this->rest_base . '/collection/(?P<collection_id>[\d]+)/activities',
|
||||
array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array($this, 'get_activities'),
|
||||
'permission_callback' => array($this, 'reports_permissions_check'),
|
||||
'args' => [
|
||||
'start' => [
|
||||
'title' => __( 'start Date', 'tainacan' ),
|
||||
'type' => 'string',
|
||||
'format' => 'date-time',
|
||||
],
|
||||
'end' => [
|
||||
'title' => __( 'start Date', 'tainacan' ),
|
||||
'type' => 'string',
|
||||
'format' => 'date-time', // RFC3339. https://tools.ietf.org/html/rfc3339#section-5.8
|
||||
],
|
||||
'force' => [
|
||||
'title' => __( 'Force regenerete', 'tainacan' ),
|
||||
'type' => 'string',
|
||||
'default' => 'no',
|
||||
'description' => __( 'Force generates the reports graphic.', 'tainacan' ),
|
||||
'enum' => array(
|
||||
'no',
|
||||
'yes'
|
||||
)
|
||||
]
|
||||
]
|
||||
),
|
||||
)
|
||||
);
|
||||
register_rest_route($this->namespace, $this->rest_base . '/collection/(?P<collection_id>[\d]+)/metadata/(?P<metadata_id>[\d]+)',
|
||||
array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array($this, 'get_metadata'),
|
||||
'permission_callback' => array($this, 'reports_permissions_check'),
|
||||
'args' => [
|
||||
'parent' => [
|
||||
'title' => __( 'parent', 'tainacan' ),
|
||||
'type' => 'integer',
|
||||
],
|
||||
'force' => [
|
||||
'title' => __( 'Force regenerete', 'tainacan' ),
|
||||
'type' => 'string',
|
||||
'default' => 'no',
|
||||
'description' => __( 'Force generates the reports graphic.', 'tainacan' ),
|
||||
'enum' => array(
|
||||
'no',
|
||||
'yes'
|
||||
)
|
||||
]
|
||||
]
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function reports_permissions_check($request) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_collections($request) {
|
||||
$response = array(
|
||||
'list' => []
|
||||
);
|
||||
$key_cache_object = 'collections';
|
||||
$cached_object = $this->get_cache_object($key_cache_object, $request);
|
||||
if($cached_object !== false ) return new \WP_REST_Response($cached_object, 200);
|
||||
$collections = $this->collections_repository->fetch([]);
|
||||
|
||||
if($collections->have_posts()) {
|
||||
while ($collections->have_posts()) {
|
||||
$collections->the_post();
|
||||
$collection = new Entities\Collection($collections->post);
|
||||
$total_items = wp_count_posts( $collection->get_db_identifier(), 'readable' );
|
||||
|
||||
if (isset($total_items->publish) || isset($total_items->private) ||
|
||||
isset($total_items->trash) || isset($total_items->draft)) {
|
||||
$response['list'][$collection->get_db_identifier()] = array(
|
||||
'id' => $collection->get_id(),
|
||||
'name' => $collection->get_name(),
|
||||
'items' => array(
|
||||
'trash' => intval($total_items->trash),
|
||||
'draft' => intval($total_items->draft),
|
||||
'publish' => intval($total_items->publish),
|
||||
'private' => intval($total_items->private),
|
||||
'total' => $total_items->trash + $total_items->draft + $total_items->publish + $total_items->private
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
wp_reset_postdata();
|
||||
}
|
||||
$this->set_cache_object($key_cache_object, $response);
|
||||
return new \WP_REST_Response($response, 200);
|
||||
}
|
||||
|
||||
public function get_summary($request) {
|
||||
$response = array(
|
||||
'totals'=> array(
|
||||
'items' => array(
|
||||
'total' => 0,
|
||||
'trash' => 0,
|
||||
'draft' => 0,
|
||||
'publish' => 0,
|
||||
'private' => 0
|
||||
)
|
||||
)
|
||||
);
|
||||
if(isset($request['collection_id'])) {
|
||||
$collection_id = $request['collection_id'];
|
||||
|
||||
$key_cache_object = 'summary_' . $collection_id;
|
||||
$cached_object = $this->get_cache_object($key_cache_object, $request);
|
||||
if($cached_object !== false ) return new \WP_REST_Response($cached_object, 200);
|
||||
|
||||
$collection = $this->collections_repository->fetch($collection_id);
|
||||
$total_items = wp_count_posts( $collection->get_db_identifier(), 'readable' );
|
||||
if (isset($total_items->publish) ||
|
||||
isset($total_items->private) ||
|
||||
isset($total_items->trash) ||
|
||||
isset($total_items->draft)) {
|
||||
|
||||
$response['totals']['items']['trash'] = intval($total_items->trash);
|
||||
$response['totals']['items']['draft'] = intval($total_items->draft);
|
||||
$response['totals']['items']['publish'] = intval($total_items->publish);
|
||||
$response['totals']['items']['private'] = intval($total_items->private);
|
||||
}
|
||||
} else {
|
||||
$key_cache_object = 'summary';
|
||||
$cached_object = $this->get_cache_object($key_cache_object, $request);
|
||||
if($cached_object !== false ) return new \WP_REST_Response($cached_object, 200);
|
||||
|
||||
$collections = $this->collections_repository->fetch([]);
|
||||
$response['totals']['collections'] = array(
|
||||
'total' => 0,
|
||||
'trash' => 0,
|
||||
'publish' => 0,
|
||||
'private' => 0
|
||||
);
|
||||
if($collections->have_posts()) {
|
||||
while ($collections->have_posts()) {
|
||||
$collections->the_post();
|
||||
$collection = new Entities\Collection($collections->post);
|
||||
$response['totals']['collections'][$collection->get_status()]++;
|
||||
$response['totals']['collections']['total']++;
|
||||
$total_items = wp_count_posts( $collection->get_db_identifier(), 'readable' );
|
||||
|
||||
if (isset($total_items->publish) || isset($total_items->private) ||
|
||||
isset($total_items->trash) || isset($total_items->draft)) {
|
||||
$response['totals']['items']['trash'] += $total_items->trash;
|
||||
$response['totals']['items']['draft'] += $total_items->draft;
|
||||
$response['totals']['items']['publish'] += $total_items->publish;
|
||||
$response['totals']['items']['private'] += $total_items->private;
|
||||
}
|
||||
}
|
||||
wp_reset_postdata();
|
||||
}
|
||||
|
||||
$response['totals']['taxonomies'] = array(
|
||||
'total' => 0,
|
||||
'trash' => 0,
|
||||
'publish' => 0,
|
||||
'draft' => 0,
|
||||
'private' => 0,
|
||||
'used' => 0,
|
||||
'not_used'=> 0
|
||||
);
|
||||
$total_taxonomies = wp_count_posts( 'tainacan-taxonomy', 'readable' );
|
||||
|
||||
if (isset($total_taxonomies->publish) ||
|
||||
isset($total_taxonomies->private) ||
|
||||
isset($total_taxonomies->trash) ||
|
||||
isset($total_taxonomies->draft)) {
|
||||
|
||||
$response['totals']['taxonomies']['trash'] = intval($total_taxonomies->trash);
|
||||
$response['totals']['taxonomies']['publish'] = intval($total_taxonomies->publish);
|
||||
$response['totals']['taxonomies']['draft'] = intval($total_taxonomies->draft);
|
||||
$response['totals']['taxonomies']['private'] = intval($total_taxonomies->private);
|
||||
$response['totals']['taxonomies']['total'] = $response['totals']['taxonomies']['trash'] + $response['totals']['taxonomies']['publish'] + $response['totals']['taxonomies']['draft'] + $response['totals']['taxonomies']['private'];
|
||||
$response['totals']['taxonomies']['used'] = $this->query_count_used_taxononomies();
|
||||
$response['totals']['taxonomies']['not_used'] = $response['totals']['taxonomies']['total'] - $response['totals']['taxonomies']['used'];
|
||||
}
|
||||
}
|
||||
$response['totals']['items']['total'] = ($response['totals']['items']['trash'] + $response['totals']['items']['draft'] + $response['totals']['items']['publish'] + $response['totals']['items']['private']);
|
||||
$this->set_cache_object($key_cache_object, $response);
|
||||
return new \WP_REST_Response($response, 200);
|
||||
}
|
||||
|
||||
public function get_taxonomies_list($request) {
|
||||
$response = array(
|
||||
'list'=> array(
|
||||
|
||||
)
|
||||
);
|
||||
|
||||
$key_cache_object = 'taxonomies_list';
|
||||
$cached_object = $this->get_cache_object($key_cache_object, $request);
|
||||
if($cached_object !== false ) return new \WP_REST_Response($cached_object, 200);
|
||||
|
||||
$taxonomies = $this->taxonomy_repository->fetch();
|
||||
if($taxonomies->have_posts()){
|
||||
while ($taxonomies->have_posts()){
|
||||
$taxonomies->the_post();
|
||||
|
||||
$taxonomy = new Entities\Taxonomy($taxonomies->post);
|
||||
$total_terms = intval(wp_count_terms( $taxonomy->get_db_identifier(), array('hide_empty'=> false) ));
|
||||
$total_terms_used = intval(wp_count_terms( $taxonomy->get_db_identifier(), array('hide_empty'=> true) ));
|
||||
$total_terms_not_used = $total_terms - $total_terms_used;
|
||||
|
||||
$response['list'][$taxonomy->get_db_identifier()] = array(
|
||||
'id' => $taxonomy->get_id(),
|
||||
'name' => $taxonomy->get_name(),
|
||||
'total_terms' => $total_terms,
|
||||
'total_terms_used' => $total_terms_used,
|
||||
'total_terms_not_used' => $total_terms_not_used
|
||||
);
|
||||
}
|
||||
wp_reset_postdata();
|
||||
}
|
||||
$this->set_cache_object($key_cache_object, $response);
|
||||
return new \WP_REST_Response($response, 200);
|
||||
}
|
||||
|
||||
public function get_taxonomy($request) {
|
||||
$response = array(
|
||||
'terms'=> array()
|
||||
);
|
||||
$taxonomy_id = $request['taxonomy_id'];
|
||||
$taxonomy = $this->taxonomy_repository->fetch($taxonomy_id);
|
||||
$taxonomy_identifier = $taxonomy->get_db_identifier();
|
||||
$taxonomy_total_terms = wp_count_terms($taxonomy_identifier, array('hide_empty' => false) );
|
||||
$limit = 100;
|
||||
$offset = 0;
|
||||
|
||||
if ( !$taxonomy_total_terms) {
|
||||
$taxonomy_total_terms = 0;
|
||||
} else {
|
||||
$key_cache_object = 'taxonomy_' . $taxonomy_identifier;
|
||||
$cached_object = $this->get_cache_object($key_cache_object, $request);
|
||||
if($cached_object !== false ) return new \WP_REST_Response($cached_object, 200);
|
||||
}
|
||||
|
||||
while($offset < $taxonomy_total_terms) {
|
||||
$terms = get_terms( array(
|
||||
'taxonomy' => $taxonomy->get_db_identifier(),
|
||||
'number' => $limit,
|
||||
'offset' => $offset,
|
||||
'hide_empty' => false,
|
||||
) );
|
||||
foreach ($terms as $term) {
|
||||
$response['terms'][$term->term_id] = array(
|
||||
'id' => $term->term_id,
|
||||
'name' => $term->name,
|
||||
'count' => $term->count
|
||||
);
|
||||
}
|
||||
$offset+=$limit;
|
||||
}
|
||||
$this->set_cache_object($key_cache_object, $response);
|
||||
return new \WP_REST_Response($response, 200);
|
||||
}
|
||||
|
||||
public function get_metadata($request) {
|
||||
$response = array(
|
||||
'list' => array()
|
||||
);
|
||||
$collection_id = $request['collection_id'];
|
||||
$taxonomy_metadata_id = $request['metadata_id'];;
|
||||
$parent_id = 0;
|
||||
if ( isset($request['parent']) ) {
|
||||
$parent_id = (int) $request['parent'];
|
||||
}
|
||||
|
||||
$key_cache_object = "facet_taxonomy_$taxonomy_metadata_id-$collection_id-$parent_id";
|
||||
$cached_object = $this->get_cache_object($key_cache_object, $request);
|
||||
if($cached_object !== false ) return new \WP_REST_Response($cached_object, 200);
|
||||
|
||||
$metadatum = $this->metadatum_repository->fetch($taxonomy_metadata_id);
|
||||
$metadatum_type = $metadatum->get_metadata_type();
|
||||
if($metadatum_type != 'Tainacan\Metadata_Types\Taxonomy') {
|
||||
return new \WP_REST_Response([
|
||||
'error_message' => __('Only taxonomy metadata type has allowed.', 'tainacan'),
|
||||
'metadatum_type' => $metadatum_type
|
||||
], 400);
|
||||
}
|
||||
|
||||
$args = [
|
||||
'collection_id' => $collection_id,
|
||||
'parent_id' => $parent_id,
|
||||
'count_items'=> true,
|
||||
];
|
||||
$data = $this->metadatum_repository->fetch_all_metadatum_values($taxonomy_metadata_id, $args);
|
||||
$response['list'] = array_map(function($item) {
|
||||
return [
|
||||
'type' => $item['type'],
|
||||
'value' => $item['value'],
|
||||
'label' => $item['label'],
|
||||
'parent' => $item['parent'] == null ? 0 : $item['parent'],
|
||||
'total_items' => intval($item['total_items']),
|
||||
'total_children' => intval($item['total_children']),
|
||||
];
|
||||
}, $data['values']);
|
||||
|
||||
$this->set_cache_object($key_cache_object, $response);
|
||||
return new \WP_REST_Response($response, 200);
|
||||
}
|
||||
|
||||
public function get_stats_collection_metadata($request) {
|
||||
$response = array(
|
||||
'totals'=> array(
|
||||
'metadata' => array(
|
||||
'total' => 0,
|
||||
'publish' => 0,
|
||||
'private' => 0
|
||||
),
|
||||
'metadata_per_type' => array()
|
||||
),
|
||||
'distribution' => array(
|
||||
|
||||
)
|
||||
);
|
||||
|
||||
if(isset($request['collection_id'])) {
|
||||
$collection_id = $request['collection_id'];
|
||||
|
||||
$key_cache_object = 'stats_collection_metadata_' . $collection_id;
|
||||
$cached_object = $this->get_cache_object($key_cache_object, $request);
|
||||
if($cached_object !== false ) return new \WP_REST_Response($cached_object, 200);
|
||||
|
||||
$collection = new Entities\Collection( $collection_id );
|
||||
$result_metadatum = $this->metadatum_repository->fetch_by_collection( $collection, [] );
|
||||
$response['totals']['metadata']['total'] = count($result_metadatum);
|
||||
$meta_ids=[];
|
||||
foreach($result_metadatum as $metadatum) {
|
||||
$meta_type = explode('\\', $metadatum->get_metadata_type()) ;
|
||||
$meta_type = strtolower($meta_type[sizeof($meta_type)-1]);
|
||||
$meta_type_name = $metadatum->get_metadata_type_object()->get_name();
|
||||
if( in_array($meta_type, ['core_description','core_title']) ) {
|
||||
$meta_type = 'text';
|
||||
$meta_type_name = (new \Tainacan\Metadata_Types\Text())->get_name();
|
||||
}
|
||||
|
||||
$response['totals']['metadata'][$metadatum->get_status()]++;
|
||||
$response['totals']['metadata_per_type'][$meta_type]['name'] = $meta_type_name;
|
||||
$response['totals']['metadata_per_type'][$meta_type]['count']++;
|
||||
|
||||
$meta_ids[] = $metadatum->get_id();
|
||||
}
|
||||
$response['distribution'] = $this->query_item_metadata_distribution($meta_ids, $collection->get_db_identifier());
|
||||
//wp_count_posts()
|
||||
} else {
|
||||
$args = [
|
||||
'meta_query' => [
|
||||
[
|
||||
'key' => 'collection_id',
|
||||
'value' => 'default',
|
||||
'compare' => '='
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$key_cache_object = 'stats_collection_metadata';
|
||||
$cached_object = $this->get_cache_object($key_cache_object, $request);
|
||||
if($cached_object !== false ) return new \WP_REST_Response($cached_object, 200);
|
||||
|
||||
$result_metadatum = $this->metadatum_repository->fetch( $args, 'OBJECT' );
|
||||
$meta_ids=[];
|
||||
foreach($result_metadatum as $metadatum) {
|
||||
$meta_type = explode('\\', $metadatum->get_metadata_type()) ;
|
||||
$meta_type = strtolower($meta_type[sizeof($meta_type)-1]);
|
||||
$meta_type_name = $metadatum->get_metadata_type_object()->get_name();
|
||||
if( in_array($meta_type, ['core_description','core_title']) ) {
|
||||
$meta_type = 'text';
|
||||
$meta_type_name = (new \Tainacan\Metadata_Types\Text())->get_name();
|
||||
}
|
||||
|
||||
$response['totals']['metadata'][$metadatum->get_status()]++;
|
||||
$response['totals']['metadata_per_type'][$meta_type]['name'] = $meta_type_name;
|
||||
$response['totals']['metadata_per_type'][$meta_type]['count']++;
|
||||
|
||||
$meta_ids[] = $metadatum->get_id();
|
||||
}
|
||||
$response['distribution'] = $this->query_item_metadata_distribution($meta_ids, 'default');
|
||||
|
||||
}
|
||||
$this->set_cache_object($key_cache_object, $response);
|
||||
return new \WP_REST_Response($response, 200);
|
||||
}
|
||||
|
||||
private function query_item_metadata_distribution($meta_ids, $collection_post_type) {
|
||||
$count_posts = wp_count_posts( $collection_post_type, 'readable' );
|
||||
$total_items = intval($count_posts->trash) + intval($count_posts->draft) +
|
||||
intval($count_posts->publish) + intval($count_posts->private);
|
||||
|
||||
global $wpdb;
|
||||
$string_meta_ids = "'".implode("','", $meta_ids)."'";
|
||||
$sql_statement = $wpdb->prepare(
|
||||
"SELECT p.post_title AS 'name', p.id AS id, IFNULL(((m.total/$total_items) * 100), 0) as fill_percentage
|
||||
FROM
|
||||
$wpdb->posts p LEFT JOIN
|
||||
(
|
||||
SELECT meta_key, count(DISTINCT post_id) AS total
|
||||
FROM $wpdb->postmeta
|
||||
WHERE $wpdb->postmeta.meta_key IN ($string_meta_ids)
|
||||
AND $wpdb->postmeta.post_id IN (
|
||||
SELECT id
|
||||
FROM $wpdb->posts
|
||||
WHERE $wpdb->posts.post_type = '$collection_post_type'
|
||||
)
|
||||
GROUP BY $wpdb->postmeta.meta_key
|
||||
UNION
|
||||
SELECT mt.meta_key, count(DISTINCT tr.object_id) AS total
|
||||
FROM $wpdb->term_taxonomy tt
|
||||
INNER JOIN $wpdb->term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
|
||||
INNER JOIN (
|
||||
SELECT post_id as 'meta_key', concat('tnc_tax_', meta_value) as 'tax_id'
|
||||
FROM $wpdb->postmeta
|
||||
WHERE meta_key='_option_taxonomy_id'
|
||||
) mt ON tt.taxonomy = mt.tax_id
|
||||
WHERE mt.meta_key IN ($string_meta_ids)
|
||||
AND tr.object_id IN (
|
||||
SELECT id
|
||||
FROM $wpdb->posts
|
||||
WHERE $wpdb->posts.post_type = '$collection_post_type'
|
||||
)
|
||||
GROUP BY mt.meta_key
|
||||
) m
|
||||
ON (p.id = m.meta_key)
|
||||
WHERE p.id IN($string_meta_ids)
|
||||
"
|
||||
);
|
||||
$res = $wpdb->get_results($sql_statement);
|
||||
//return ['t' => $res, 's' => $sql_statement];
|
||||
return $res;
|
||||
}
|
||||
|
||||
private function query_count_used_taxononomies() {
|
||||
global $wpdb;
|
||||
$sql_statement = $wpdb->prepare(
|
||||
"SELECT COUNT(DISTINCT($wpdb->postmeta.meta_value))
|
||||
FROM $wpdb->postmeta
|
||||
WHERE meta_key = '_option_taxonomy_id'
|
||||
"
|
||||
);
|
||||
|
||||
$res = intval($wpdb->get_var( $sql_statement ));
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function get_activities($request) {
|
||||
$response = array(
|
||||
'totals' => []
|
||||
);
|
||||
$collection_id = false;
|
||||
if(isset($request['collection_id'])) {
|
||||
$collection_id = $request['collection_id'];
|
||||
}
|
||||
|
||||
if( isset($request['start']) ) {
|
||||
$start = new \DateTime($request['start']);
|
||||
|
||||
$key_cache_object = 'activities_' . $start->format('Y-m-d') . '_' . $collection_id;
|
||||
$cached_object = $this->get_cache_object($key_cache_object, $request);
|
||||
if($cached_object !== false ) return new \WP_REST_Response($cached_object, 200);
|
||||
|
||||
$end_limit = $start->add(new \DateInterval('P1Y1D'))->setTime(0,0,0);
|
||||
$end = isset($request['end']) ? new \DateTime($request['end']) : $end_limit;
|
||||
if($end > $end_limit)
|
||||
$end = $end_limit;
|
||||
$interval = [
|
||||
'start' => (new \DateTime($request['start']))->format('Y-m-d H:i:s'),
|
||||
'end' => $end->format('Y-m-d H:i:s')
|
||||
];
|
||||
} else {
|
||||
$key_cache_object = 'activities_' . $collection_id;
|
||||
$cached_object = $this->get_cache_object($key_cache_object, $request);
|
||||
if($cached_object !== false ) return new \WP_REST_Response($cached_object, 200);
|
||||
$end = (new \DateTime())->add(new \DateInterval('P1D'))->setTime(0,0,0);
|
||||
$interval = [
|
||||
'end' => $end->format('Y-m-d H:i:s'),
|
||||
'start' => $end->sub(new \DateInterval('P1Y1D'))->format('Y-m-d H:i:s')
|
||||
];
|
||||
}
|
||||
|
||||
$response['totals'] = array(
|
||||
'by_interval' => array(
|
||||
'start' => $interval['start'],
|
||||
'end' => $interval['end'],
|
||||
'general' => $this->get_activities_general($collection_id, $interval),
|
||||
'by_user' => $this->get_activities_general_by_user($collection_id, $interval)
|
||||
),
|
||||
'by_user' => $this->get_activities_users($collection_id)
|
||||
);
|
||||
$this->set_cache_object($key_cache_object, $response);
|
||||
return new \WP_REST_Response($response, 200);
|
||||
}
|
||||
|
||||
private function get_activities_general($collection_id = false, $interval) {
|
||||
global $wpdb;
|
||||
$collection_from = "";
|
||||
$start = $interval['start'];
|
||||
$end = $interval['end'];
|
||||
if($collection_id !== false) {
|
||||
$collection_from = "INNER JOIN $wpdb->postmeta pm ON p.id = pm.post_id AND (pm.meta_key='collection_id' AND pm.meta_value='$collection_id')";
|
||||
}
|
||||
$sql_statement = $wpdb->prepare(
|
||||
"SELECT count(DISTINCT (unix_timestamp(p.post_date) DIV 60)) as total, DATE(p.post_date) as date
|
||||
FROM $wpdb->posts p $collection_from
|
||||
WHERE p.post_type='tainacan-log' AND p.post_date BETWEEN '$start' AND '$end'
|
||||
GROUP BY DATE(p.post_date)
|
||||
ORDER BY DATE(p.post_date)"
|
||||
);
|
||||
return $wpdb->get_results($sql_statement);
|
||||
}
|
||||
|
||||
private function get_activities_general_by_user($collection_id = false, $interval) {
|
||||
global $wpdb;
|
||||
$collection_from = "";
|
||||
$start = $interval['start'];
|
||||
$end = $interval['end'];
|
||||
if($collection_id !== false) {
|
||||
$collection_from = "INNER JOIN $wpdb->postmeta pm ON p.id = pm.post_id AND (pm.meta_key='collection_id' AND pm.meta_value='$collection_id')";
|
||||
}
|
||||
$sql_statement = $wpdb->prepare(
|
||||
"SELECT p.post_author as user_id, count(DISTINCT (unix_timestamp(p.post_date) DIV 60)) as total, DATE(p.post_date) as date
|
||||
FROM $wpdb->posts p $collection_from
|
||||
WHERE p.post_type='tainacan-log' AND p.post_date BETWEEN '$start' AND '$end'
|
||||
GROUP BY p.post_author, DATE(p.post_date)
|
||||
ORDER BY DATE(p.post_date)"
|
||||
);
|
||||
$data =$wpdb->get_results($sql_statement);
|
||||
$arr = array();
|
||||
$avatar_sizes = rest_get_avatar_sizes();
|
||||
foreach ($data as $item) {
|
||||
if(!isset($arr[$item->user_id])) {
|
||||
$user_data = get_userdata($item->user_id);
|
||||
$urls = array();
|
||||
foreach ( $avatar_sizes as $size ) {
|
||||
$urls[ $size ] = get_avatar_url( $user_data, array( 'size' => $size ) );
|
||||
}
|
||||
$arr[$item->user_id] = [
|
||||
'user' => !$user_data ? [] : [
|
||||
'id' => $user_data->ID,
|
||||
'username' => $user_data->user_login,
|
||||
'name' => $user_data->display_name,
|
||||
'first_name' => $user_data->first_name,
|
||||
'last_name' => $user_data->last_name,
|
||||
'email' => $user_data->user_email,
|
||||
'avatar_urls' => $urls,
|
||||
],
|
||||
'user_id' => $item->user_id,
|
||||
'total' => 0,
|
||||
'by_date' => []
|
||||
];
|
||||
}
|
||||
$arr[$item->user_id]['by_date'][] = $item;
|
||||
$arr[$item->user_id]['total'] += $item->total;
|
||||
}
|
||||
return array_values($arr);
|
||||
}
|
||||
|
||||
private function get_activities_users($collection_id = false) {
|
||||
global $wpdb;
|
||||
$collection_from = "";
|
||||
if($collection_id !== false) {
|
||||
$collection_from = "INNER JOIN $wpdb->postmeta pm_col ON p.id = pm_col.post_id AND (pm_col.meta_key='collection_id' AND pm_col.meta_value='$collection_id')";
|
||||
}
|
||||
$sql_statement = $wpdb->prepare(
|
||||
"SELECT count(DISTINCT (unix_timestamp(p.post_date) DIV 60)) as total, p.post_author as user, pm.meta_value as action
|
||||
FROM $wpdb->posts p
|
||||
INNER JOIN $wpdb->postmeta pm ON p.id = pm.post_id AND pm.meta_key = 'action'
|
||||
$collection_from
|
||||
WHERE p.post_type='tainacan-log'
|
||||
GROUP BY p.post_author, pm.meta_value
|
||||
ORDER BY total DESC"
|
||||
);
|
||||
$results = $wpdb->get_results($sql_statement);
|
||||
$response = [];
|
||||
$avatar_sizes = rest_get_avatar_sizes();
|
||||
foreach($results as $key => $result) {
|
||||
$user = $result->user;
|
||||
$total = $result->total;
|
||||
$action = $result->action;
|
||||
if(!isset($response[$user])) {
|
||||
$user_data = get_userdata($user);
|
||||
$urls = array();
|
||||
foreach ( $avatar_sizes as $size ) {
|
||||
$urls[ $size ] = get_avatar_url( $user_data, array( 'size' => $size ) );
|
||||
}
|
||||
$response[$user] = [
|
||||
'user' => !$user_data ? [] : [
|
||||
'id' => $user_data->ID,
|
||||
'username' => $user_data->user_login,
|
||||
'name' => $user_data->display_name,
|
||||
'first_name' => $user_data->first_name,
|
||||
'last_name' => $user_data->last_name,
|
||||
'email' => $user_data->user_email,
|
||||
'avatar_urls' => $urls,
|
||||
],
|
||||
'user_id' => $user,
|
||||
'total' => 0,
|
||||
'by_action' => []
|
||||
];
|
||||
}
|
||||
$response[$user]['by_action'][$action] = intval($total);
|
||||
$response[$user]['total'] += $total;
|
||||
}
|
||||
return array_values($response);
|
||||
}
|
||||
|
||||
private $prefix_transient_cahce = 'reports_tnc_';
|
||||
|
||||
private function get_cache_object($key, $request) {
|
||||
if ( !isset($request['force']) || $request['force'] == 'no' ) {
|
||||
$transient = get_transient($this->prefix_transient_cahce . $key);
|
||||
return $transient;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function set_cache_object($key, $data) {
|
||||
$expiration = 604800; //one week
|
||||
$data['report_cached_on'] = (new \DateTime())->format('Y-m-d H:i:s');
|
||||
return set_transient($this->prefix_transient_cahce . $key, $data, $expiration);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -2,27 +2,28 @@
|
|||
|
||||
const TAINACAN_REST_NAMESPACE = 'tainacan/v2';
|
||||
|
||||
//$rest_controller = new \Tainacan\API\REST_Controller();
|
||||
$rest_collections_controller = new \Tainacan\API\EndPoints\REST_Collections_Controller();
|
||||
$rest_items_controller = new \Tainacan\API\EndPoints\REST_Items_Controller();
|
||||
$rest_metadata_controller = new \Tainacan\API\EndPoints\REST_Metadata_Controller();
|
||||
$rest_taxonomies_controller = new \Tainacan\API\EndPoints\REST_Taxonomies_Controller();
|
||||
$rest_terms_controller = new \Tainacan\API\EndPoints\REST_Terms_Controller();
|
||||
$rest_filters_controller = new \Tainacan\API\EndPoints\REST_Filters_Controller();
|
||||
$rest_item_metadata_controller = new \Tainacan\API\EndPoints\REST_Item_Metadata_Controller();
|
||||
$rest_logs_controller = new \Tainacan\API\EndPoints\REST_Logs_Controller();
|
||||
$rest_metadata_types_controller = new \Tainacan\API\EndPoints\REST_Metadata_Types_Controller();
|
||||
$rest_filter_types_controller = new \Tainacan\API\EndPoints\REST_Filter_Types_Controller();
|
||||
$rest_importers_controller = new \Tainacan\API\EndPoints\REST_Importers_Controller();
|
||||
$rest_exporters_controller = new \Tainacan\API\EndPoints\REST_Exporters_Controller();
|
||||
$rest_background_processes_controller = new \Tainacan\API\EndPoints\REST_Background_Processes_Controller();
|
||||
$rest_bulkedit_controller = new \Tainacan\API\EndPoints\REST_Bulkedit_Controller();
|
||||
$rest_exposers_controller = new \Tainacan\API\EndPoints\REST_Exposers_Controller();
|
||||
$rest_roles_controller = new \Tainacan\API\EndPoints\REST_Roles_Controller();
|
||||
new \Tainacan\API\EndPoints\REST_Metadatum_Mappers_Controller();
|
||||
$rest_facets_controller = new \Tainacan\API\EndPoints\REST_Facets_Controller();
|
||||
$rest_oaipmh_expose_controller = new \Tainacan\API\EndPoints\REST_Oaipmh_Expose_Controller();
|
||||
$rest_sequence_edit_controller = new \Tainacan\API\EndPoints\REST_Sequence_Edit_Controller();
|
||||
//$rest_controller = new \Tainacan\API\REST_Controller();
|
||||
$rest_items_controller = new \Tainacan\API\EndPoints\REST_Items_Controller();
|
||||
$rest_terms_controller = new \Tainacan\API\EndPoints\REST_Terms_Controller();
|
||||
$rest_logs_controller = new \Tainacan\API\EndPoints\REST_Logs_Controller();
|
||||
$rest_roles_controller = new \Tainacan\API\EndPoints\REST_Roles_Controller();
|
||||
$rest_facets_controller = new \Tainacan\API\EndPoints\REST_Facets_Controller();
|
||||
$rest_reports_controller = new \Tainacan\API\EndPoints\REST_Reports_Controller();
|
||||
$rest_filters_controller = new \Tainacan\API\EndPoints\REST_Filters_Controller();
|
||||
$rest_exposers_controller = new \Tainacan\API\EndPoints\REST_Exposers_Controller();
|
||||
$rest_bulkedit_controller = new \Tainacan\API\EndPoints\REST_Bulkedit_Controller();
|
||||
$rest_metadata_controller = new \Tainacan\API\EndPoints\REST_Metadata_Controller();
|
||||
$rest_importers_controller = new \Tainacan\API\EndPoints\REST_Importers_Controller();
|
||||
$rest_exporters_controller = new \Tainacan\API\EndPoints\REST_Exporters_Controller();
|
||||
$rest_taxonomies_controller = new \Tainacan\API\EndPoints\REST_Taxonomies_Controller();
|
||||
$rest_collections_controller = new \Tainacan\API\EndPoints\REST_Collections_Controller();
|
||||
$rest_filter_types_controller = new \Tainacan\API\EndPoints\REST_Filter_Types_Controller();
|
||||
$rest_oaipmh_expose_controller = new \Tainacan\API\EndPoints\REST_Oaipmh_Expose_Controller();
|
||||
$rest_item_metadata_controller = new \Tainacan\API\EndPoints\REST_Item_Metadata_Controller();
|
||||
$rest_sequence_edit_controller = new \Tainacan\API\EndPoints\REST_Sequence_Edit_Controller();
|
||||
$rest_metadata_types_controller = new \Tainacan\API\EndPoints\REST_Metadata_Types_Controller();
|
||||
$rest_metadatum_mappers_controller = new \Tainacan\API\EndPoints\REST_Metadatum_Mappers_Controller();
|
||||
$rest_background_processes_controller = new \Tainacan\API\EndPoints\REST_Background_Processes_Controller();
|
||||
// Add here other endpoints imports
|
||||
|
||||
?>
|
||||
|
|
|
@ -83,10 +83,10 @@ class Elastic_Press {
|
|||
return $formatted_args;
|
||||
} );
|
||||
|
||||
// add_action('ep_add_query_log', function($query) { //using to DEBUG
|
||||
//add_action('ep_add_query_log', function($query) { //using to DEBUG
|
||||
// error_log("DEGUG:");
|
||||
// error_log($query["args"]["body"]);
|
||||
// });
|
||||
//});
|
||||
}
|
||||
|
||||
function elasticpress_config_mapping( $mapping ) {
|
||||
|
@ -517,7 +517,7 @@ class Elastic_Press {
|
|||
if (!empty($filter['include'])) {
|
||||
$custom_filter_include = $custom_filter;
|
||||
$custom_filter_include['bool']['must'][] = ["bool" => [ "must"=> [ [ "terms" => ["$field.term_id" => $filter['include'] ] ] ] ] ];
|
||||
$terms_id_inlcude = \implode( "|", $filter['include']);
|
||||
$terms_id_include = \implode( "|", $filter['include']);
|
||||
$aggs[$id.'.include'] = [
|
||||
"filter" => $custom_filter_include,
|
||||
"aggs" => array(
|
||||
|
@ -525,14 +525,14 @@ class Elastic_Press {
|
|||
"terms"=>array(
|
||||
"order" => ["_key" => "asc" ],
|
||||
"field" => "$field.term_name.id",
|
||||
"include" => "(.)*.($terms_id_inlcude).parent=$parent",
|
||||
"include" => "(.)*.($terms_id_include).parent=$parent",
|
||||
"min_doc_count" => 0
|
||||
)
|
||||
// "terms"=>array(
|
||||
// "script" => [
|
||||
// "lang" => "painless",
|
||||
// "source" => "def c= ['']; for (int i = 0; i < doc['$field.term_id'].length; ++i) { if( [$terms_id_inlcude].contains(doc['$field.term_id'][i]) ) { c.add(doc['$field.term_name.id'][i]); } } return c;"
|
||||
// //"source"=> "def c= ['']; if(!params._source.terms.empty && params._source.$field != null) { for(term in params._source.$field) { if( [$terms_id_inlcude].contains(term.term_id) ) { c.add(term.term_id); }}} return c;"
|
||||
// "source" => "def c= ['']; for (int i = 0; i < doc['$field.term_id'].length; ++i) { if( [$terms_id_include].contains(doc['$field.term_id'][i]) ) { c.add(doc['$field.term_name.id'][i]); } } return c;"
|
||||
// //"source"=> "def c= ['']; if(!params._source.terms.empty && params._source.$field != null) { for(term in params._source.$field) { if( [$terms_id_include].contains(term.term_id) ) { c.add(term.term_id); }}} return c;"
|
||||
// ]
|
||||
// )
|
||||
)
|
||||
|
@ -565,7 +565,7 @@ class Elastic_Press {
|
|||
"terms"=>array(
|
||||
"script" => [
|
||||
"lang" => "painless",
|
||||
"source"=> "def c= ['']; if(!params._source.meta.empty && params._source.$meta_label != null) { for(meta in params._source.$meta_label) { if([$meta_id_inlcude].contains(meta.raw)) { c.add(meta.raw); }}} return c;"
|
||||
"source"=> "def c= []; if(!params._source.meta.empty && params._source.$meta_label != null) { for(meta in params._source.$meta_label) { if([$meta_id_inlcude].contains(meta.raw)) { c.add(meta.raw); }}} return c;"
|
||||
]
|
||||
//"field"=> $filter['field']
|
||||
)
|
||||
|
@ -632,6 +632,9 @@ class Elastic_Press {
|
|||
$field = $filter['field'];
|
||||
if ($filter['metadata_type'] == 'Tainacan\Metadata_Types\Taxonomy') {
|
||||
$parent = $filter['parent'];
|
||||
$source = !empty($search) ?
|
||||
"if ( doc.containsKey('$field.term_name.id') ) {List l = new ArrayList(doc['$field.term_name.id']); return l;} return[];" :
|
||||
"if ( doc.containsKey('$field.term_name.id') ) {List l = new ArrayList(doc['$field.term_name.id']); l.removeIf(item->!item.endsWith('.parent=$parent')); return l;} return[];" ;
|
||||
$aggs[$id] = [
|
||||
"composite" => array(
|
||||
"size" => $filter['pagesize'],
|
||||
|
@ -641,7 +644,8 @@ class Elastic_Press {
|
|||
"order" => "asc",
|
||||
"script" => [
|
||||
"lang" => "painless",
|
||||
"source" => "if ( doc.containsKey('$field.term_name.id') ) {List l = new ArrayList(doc['$field.term_name.id']); l.removeIf(item->!item.endsWith('.parent=$parent')); return l;} return[];"
|
||||
"source" => $source
|
||||
//"source" => "if ( doc.containsKey('$field.term_name.id') ) {List l = new ArrayList(doc['$field.term_name.id']); l.removeIf(item->!item.endsWith('.parent=$parent')); return l;} return[];"
|
||||
//"source" => "for (int i = 0; i < doc['$field.parent'].length; ++i) { if (doc['$field.parent'][i] == $parent) { return doc['$field.term_name.id'][i]; }}",
|
||||
//"source" => "for (int i = 0; i < doc['$field.parent'].length; ++i) { if (doc['$field.parent'][i] == $parent) { return doc['$field.term_id'][i]; }}",
|
||||
//"source" => "def c= ['']; if(!params._source.terms.empty && params._source.$field != null) { for(term in params._source.$field) { if(term.parent==$parent) { c.add(term.term_id); }}} return c;"
|
||||
|
|
|
@ -208,9 +208,7 @@ class Taxonomies extends Repository {
|
|||
* @return array Entities\Taxonomy
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function fetch_by_collection( Entities\Collection $collection, $args = [] ) {
|
||||
$collection_id = $collection->get_id();
|
||||
|
||||
public function fetch_by_collection( Entities\Collection $collection, $args = [], $output = 'OBJECT' ) {
|
||||
$Tainacan_Metadata = Metadata::get_instance();
|
||||
|
||||
// get all taxonomy metadata in this collection
|
||||
|
@ -234,7 +232,7 @@ class Taxonomies extends Repository {
|
|||
];
|
||||
|
||||
$args = array_merge($args, $newargs);
|
||||
return $this->fetch($args, 'OBJECT');
|
||||
return $this->fetch($args, $output);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -92,8 +92,8 @@ function tainacan_autoload($class_name) {
|
|||
$dir = TAINACAN_TAPI_DIR;
|
||||
if(count($class_path) > 3) $dir .= strtolower($class_path[2]).DIRECTORY_SEPARATOR;
|
||||
} else if( isset( $class_path[1] ) && $class_path[1] === 'OAIPMHExpose' ){
|
||||
$dir = TAINACAN_OAIPMH_DIR;
|
||||
if(count($class_path) > 3) $dir .= strtolower($class_path[2]).DIRECTORY_SEPARATOR;
|
||||
$dir = TAINACAN_OAIPMH_DIR;
|
||||
if(count($class_path) > 3) $dir .= strtolower($class_path[2]).DIRECTORY_SEPARATOR;
|
||||
} else if( isset( $class_path[1] ) && substr($class_path[1], 0, 3) === 'Cli' ){
|
||||
$dir = TAINACAN_CLI_DIR;
|
||||
} else if( isset( $class_path[1] ) && $class_path[1] === 'Metadata_Types' ) {
|
||||
|
|
|
@ -110,7 +110,9 @@
|
|||
promise.request
|
||||
.then((res) => {
|
||||
this.updateSelectedValues();
|
||||
this.$emit('updateParentCollapse', res.data.values.length > 0 );
|
||||
|
||||
if (res && res.data && res.data.values)
|
||||
this.$emit('updateParentCollapse', res.data.values.length > 0 );
|
||||
})
|
||||
.catch( (error) => {
|
||||
if (isCancel(error)) {
|
||||
|
@ -133,7 +135,6 @@
|
|||
});
|
||||
},
|
||||
updateSelectedValues() {
|
||||
|
||||
if ( !this.query || !this.query.metaquery || !Array.isArray( this.query.metaquery ) )
|
||||
return false;
|
||||
|
||||
|
|
|
@ -64,8 +64,9 @@
|
|||
promise.request
|
||||
.then((res) => {
|
||||
this.updateSelectedValues();
|
||||
|
||||
this.$emit('updateParentCollapse', res.data.values.length > 0 );
|
||||
|
||||
if (res && res.data && res.data.values)
|
||||
this.$emit('updateParentCollapse', res.data.values.length > 0 );
|
||||
})
|
||||
.catch( error => {
|
||||
if (isCancel(error))
|
||||
|
|
|
@ -180,10 +180,11 @@
|
|||
});
|
||||
promise.request
|
||||
.then((res) => {
|
||||
this.prepareOptionsForTaxonomy(res.data.values ? res.data.values : res.data);
|
||||
this.isLoadingOptions = false;
|
||||
|
||||
this.$emit('updateParentCollapse', res.data.values.length > 0 );
|
||||
this.prepareOptionsForTaxonomy(res.data.values ? res.data.values : res.data);
|
||||
|
||||
if (res && res.data && res.data.values)
|
||||
this.$emit('updateParentCollapse', res.data.values.length > 0 );
|
||||
})
|
||||
.catch( error => {
|
||||
if (isCancel(error)) {
|
||||
|
@ -279,7 +280,6 @@
|
|||
// });
|
||||
}
|
||||
}
|
||||
|
||||
this.$emit('sendValuesToTags', { label: onlyLabels, taxonomy: this.taxonomy, value: this.selected });
|
||||
},
|
||||
onSelect() {
|
||||
|
|
|
@ -39,13 +39,96 @@
|
|||
type="search" />
|
||||
</b-field>
|
||||
|
||||
<!-- Search Results -->
|
||||
<div
|
||||
v-if="isSearching"
|
||||
:style="{ height: isModal ? 'auto' : '0px' }"
|
||||
class="modal-card-body tainacan-checkbox-list-container">
|
||||
<a
|
||||
v-if="isUsingElasticSearch ? previousLastTerms.length && previousLastTerms[0] != checkboxListOffset : checkboxListOffset"
|
||||
role="button"
|
||||
class="tainacan-checkbox-list-page-changer"
|
||||
@click="previousSearchPage">
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-previous"/>
|
||||
</span>
|
||||
</a>
|
||||
<ul
|
||||
:class="{
|
||||
'tainacan-modal-checkbox-list-body-dynamic-m-l': !checkboxListOffset,
|
||||
'tainacan-modal-checkbox-list-body-dynamic-m-r': noMoreSearchPage,
|
||||
}"
|
||||
class="tainacan-modal-checkbox-list-body">
|
||||
<template v-if="searchResults.length">
|
||||
<li
|
||||
class="tainacan-li-checkbox-list"
|
||||
v-for="(option, key) in searchResults"
|
||||
:key="key">
|
||||
<label
|
||||
v-if="isCheckbox"
|
||||
class="b-checkbox checkbox">
|
||||
<input
|
||||
v-model="selected"
|
||||
:value="option.id ? (isNaN(Number(option.id)) ? option.id : Number(option.id)) : (isNaN(Number(option.value)) ? option.value : Number(option.value))"
|
||||
type="checkbox">
|
||||
<span class="check" />
|
||||
<span class="control-label">
|
||||
<span
|
||||
class="checkbox-label-text"
|
||||
v-html="`${ option.name ? option.name : (option.label ? (option.hierarchy_path ? renderHierarchicalPath(option.hierarchy_path, option.label) : option.label) : '') }`" />
|
||||
<span
|
||||
v-if="option.total_items != undefined"
|
||||
class="has-text-gray">
|
||||
{{ "(" + option.total_items + ")" }}
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
<b-radio
|
||||
v-tooltip="{
|
||||
content: (option.name ? option.name : option.label) + (option.total_items != undefined ? ('(' + option.total_items + ' ' + $i18n.get('items') + ')') : ''),
|
||||
autoHide: false,
|
||||
}"
|
||||
v-else
|
||||
v-model="selected"
|
||||
:native-value="option.id ? (isNaN(Number(option.id)) ? option.id : Number(option.value)) : (isNaN(Number(option.value)) ? option.value : Number(option.value))">
|
||||
<span
|
||||
class="checkbox-label-text"
|
||||
v-html="`${ option.name ? option.name : (option.label ? (option.hierarchy_path ? renderHierarchicalPath(option.hierarchy_path, option.label) : option.label) : '') }`" />
|
||||
<span
|
||||
v-if="option.total_items != undefined"
|
||||
class="has-text-gray">
|
||||
{{ "(" + option.total_items + ")" }}
|
||||
</span>
|
||||
</b-radio>
|
||||
</li>
|
||||
</template>
|
||||
<template v-if="!isLoadingSearch && !searchResults.length">
|
||||
<li class="tainacan-li-checkbox-list result-info">
|
||||
{{ $i18n.get('info_no_terms_found') }}
|
||||
</li>
|
||||
</template>
|
||||
<b-loading
|
||||
:is-full-page="false"
|
||||
:active.sync="isLoadingSearch"/>
|
||||
</ul>
|
||||
<a
|
||||
v-if="!noMoreSearchPage"
|
||||
role="button"
|
||||
class="tainacan-checkbox-list-page-changer"
|
||||
@click="nextSearchPage">
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-next"/>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Non-hierarchical lists -->
|
||||
<div
|
||||
v-if="!isSearching && !isTaxonomy"
|
||||
:style="{ height: isModal ? 'auto' : '0px' }"
|
||||
class="modal-card-body tainacan-checkbox-list-container">
|
||||
<a
|
||||
v-if="isUsingElasticSearch ? lastTermOnFisrtPage != checkboxListOffset : checkboxListOffset"
|
||||
v-if="isUsingElasticSearch ? previousLastTerms.length && previousLastTerms[0] != checkboxListOffset : checkboxListOffset"
|
||||
role="button"
|
||||
class="tainacan-checkbox-list-page-changer"
|
||||
@click="previousPage">
|
||||
|
@ -59,29 +142,36 @@
|
|||
'tainacan-modal-checkbox-list-body-dynamic-m-r': noMorePage,
|
||||
}"
|
||||
class="tainacan-modal-checkbox-list-body">
|
||||
<li
|
||||
class="tainacan-li-checkbox-list"
|
||||
v-for="(option, key) in options"
|
||||
:key="key">
|
||||
<label class="b-checkbox checkbox">
|
||||
<input
|
||||
v-model="selected"
|
||||
:value="option.value"
|
||||
type="checkbox">
|
||||
<span class="check" />
|
||||
<span class="control-label">
|
||||
<span
|
||||
v-tooltip="{
|
||||
content: option.label + (option.total_items != undefined ? ('(' + option.total_items + ' ' + $i18n.get('items') + ')') : ''),
|
||||
autoHide: false,
|
||||
}"
|
||||
class="checkbox-label-text">{{ `${ (option.label ? option.label : '') }` }}</span>
|
||||
<span
|
||||
v-if="option.total_items != undefined"
|
||||
class="has-text-gray"> {{ "(" + option.total_items + ")" }}</span>
|
||||
</span>
|
||||
</label>
|
||||
</li>
|
||||
<template v-if="options.length">
|
||||
<li
|
||||
class="tainacan-li-checkbox-list"
|
||||
v-for="(option, key) in options"
|
||||
:key="key">
|
||||
<label class="b-checkbox checkbox">
|
||||
<input
|
||||
v-model="selected"
|
||||
:value="option.value"
|
||||
type="checkbox">
|
||||
<span class="check" />
|
||||
<span class="control-label">
|
||||
<span
|
||||
v-tooltip="{
|
||||
content: option.label + (option.total_items != undefined ? ('(' + option.total_items + ' ' + $i18n.get('items') + ')') : ''),
|
||||
autoHide: false,
|
||||
}"
|
||||
class="checkbox-label-text">{{ `${ (option.label ? option.label : '') }` }}</span>
|
||||
<span
|
||||
v-if="option.total_items != undefined"
|
||||
class="has-text-gray"> {{ "(" + option.total_items + ")" }}</span>
|
||||
</span>
|
||||
</label>
|
||||
</li>
|
||||
</template>
|
||||
<template v-if="!isCheckboxListLoading && !options.length">
|
||||
<li class="tainacan-li-checkbox-list result-info">
|
||||
{{ $i18n.get('info_no_terms_found') }}
|
||||
</li>
|
||||
</template>
|
||||
<b-loading
|
||||
:is-full-page="false"
|
||||
:active.sync="isCheckboxListLoading"/>
|
||||
|
@ -192,67 +282,14 @@
|
|||
</ul>
|
||||
</div>
|
||||
</transition-group>
|
||||
|
||||
<b-loading
|
||||
:is-full-page="false"
|
||||
:active.sync="isColumnLoading"/>
|
||||
|
||||
<!-- Search Results -->
|
||||
<div
|
||||
v-if="isSearching"
|
||||
:style="{ height: isModal ? 'auto' : '0px' }"
|
||||
class="modal-card-body tainacan-search-results-container">
|
||||
<ul class="tainacan-modal-checkbox-search-results-body">
|
||||
<li
|
||||
class="tainacan-li-search-results"
|
||||
v-for="(option, key) in searchResults"
|
||||
:key="key">
|
||||
<label
|
||||
v-if="isCheckbox"
|
||||
class="b-checkbox checkbox">
|
||||
<input
|
||||
v-model="selected"
|
||||
:value="option.id ? (isNaN(Number(option.id)) ? option.id : Number(option.id)) : (isNaN(Number(option.value)) ? option.value : Number(option.value))"
|
||||
type="checkbox">
|
||||
<span class="check" />
|
||||
<span class="control-label">
|
||||
<span
|
||||
class="checkbox-label-text"
|
||||
v-html="`${ option.name ? option.name : (option.label ? (option.hierarchy_path ? renderHierarchicalPath(option.hierarchy_path, option.label) : option.label) : '') }`" />
|
||||
<span
|
||||
v-if="option.total_items != undefined"
|
||||
class="has-text-gray">
|
||||
{{ "(" + option.total_items + ")" }}
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
<b-radio
|
||||
v-tooltip="{
|
||||
content: (option.name ? option.name : option.label) + (option.total_items != undefined ? ('(' + option.total_items + ' ' + $i18n.get('items') + ')') : ''),
|
||||
autoHide: false,
|
||||
}"
|
||||
v-else
|
||||
v-model="selected"
|
||||
:native-value="option.id ? (isNaN(Number(option.id)) ? option.id : Number(option.value)) : (isNaN(Number(option.value)) ? option.value : Number(option.value))">
|
||||
<span
|
||||
class="checkbox-label-text"
|
||||
v-html="`${ option.name ? option.name : (option.label ? (option.hierarchy_path ? renderHierarchicalPath(option.hierarchy_path, option.label) : option.label) : '') }`" />
|
||||
<span
|
||||
v-if="option.total_items != undefined"
|
||||
class="has-text-gray">
|
||||
{{ "(" + option.total_items + ")" }}
|
||||
</span>
|
||||
</b-radio>
|
||||
</li>
|
||||
<b-loading
|
||||
:is-full-page="false"
|
||||
:active.sync="isLoadingSearch"/>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</b-tab-item>
|
||||
|
||||
<b-tab-item :label="isTaxonomy ? $i18n.get('label_selected_terms') : $i18n.get('label_selected_metadatum_values')">
|
||||
|
||||
<div class="modal-card-body tainacan-tags-container">
|
||||
<b-field
|
||||
v-if="(selected instanceof Array ? selected.length > 0 : selected) && !isSelectedTermsLoading"
|
||||
|
@ -299,7 +336,11 @@
|
|||
<!--<pre>{{ options }}</pre>-->
|
||||
<!--<pre>{{ searchResults }}</pre>-->
|
||||
<!--<pre>{{ selectedTagsName }}</pre>-->
|
||||
|
||||
<!-- <pre>{{ checkboxListOffset }}</pre>
|
||||
<pre>{{ previousLastTerms }}</pre> -->
|
||||
<!-- <pre>{{ isLoadingSearch }}</pre>
|
||||
<pre>{{ isCheckboxListLoading }}</pre>
|
||||
<pre>{{ isColumnLoading }}</pre> -->
|
||||
<footer
|
||||
class="field is-grouped"
|
||||
:class="{ 'form-submit': isModal }">
|
||||
|
@ -375,17 +416,26 @@
|
|||
checkboxListOffset: 0,
|
||||
isCheckboxListLoading: false,
|
||||
isLoadingSearch: false,
|
||||
noMorePage: 0,
|
||||
noMorePage: false,
|
||||
noMoreSearchPage: false,
|
||||
activeTab: 0,
|
||||
selectedTagsName: {},
|
||||
isSelectedTermsLoading: false,
|
||||
isUsingElasticSearch: tainacan_plugin.wp_elasticpress == "1" ? true : false,
|
||||
previousLastTerms: [],
|
||||
lastTermOnFisrtPage: null
|
||||
previousLastTerms: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
optionName(newValue, oldValue) {
|
||||
if (newValue != oldValue) {
|
||||
this.noMoreSearchPage = false;
|
||||
this.checkboxListOffset = this.isUsingElasticSearch ? '' : 0;
|
||||
this.previousLastTerms = [];
|
||||
}
|
||||
}
|
||||
},
|
||||
updated(){
|
||||
if (!this.isSearching)
|
||||
if (!this.isSearching && this.isTaxonomy)
|
||||
this.highlightHierarchyPath();
|
||||
},
|
||||
created() {
|
||||
|
@ -399,6 +449,7 @@
|
|||
this.$parent.$on('update-taxonomy-inputs', ($event) => {
|
||||
if ($event.taxonomyId == this.taxonomy_id && $event.metadatumId == this.metadatumId) {
|
||||
this.finderColumns = [];
|
||||
this.optionName = '';
|
||||
this.hierarchicalPath = [];
|
||||
this.isSearching = false;
|
||||
this.searchResults = [];
|
||||
|
@ -408,7 +459,7 @@
|
|||
},
|
||||
mounted() {
|
||||
if (this.isModal && this.$refs.CheckboxRadioFilterInput)
|
||||
this.$refs.CheckboxRadioFilterInput.focus()
|
||||
this.$refs.CheckboxRadioFilterInput.focus();
|
||||
},
|
||||
beforeDestroy() {
|
||||
// Cancels previous Request
|
||||
|
@ -418,7 +469,7 @@
|
|||
methods: {
|
||||
initializeValues() {
|
||||
if (!this.isModal)
|
||||
this.maxNumOptionsCheckboxFinderColumns = 12;
|
||||
this.maxNumOptionsCheckboxFinderColumns = 24;
|
||||
|
||||
if (this.isTaxonomy) {
|
||||
this.getOptionChildren();
|
||||
|
@ -472,18 +523,16 @@
|
|||
},
|
||||
previousPage() {
|
||||
|
||||
this.noMorePage = 0;
|
||||
this.noMorePage = false;
|
||||
this.isCheckboxListLoading = true;
|
||||
|
||||
if (this.isUsingElasticSearch) {
|
||||
this.previousLastTerms.pop();
|
||||
|
||||
if (this.previousLastTerms.length > 0) {
|
||||
this.getOptions(this.previousLastTerms.pop());
|
||||
this.previousLastTerms.push(this.checkboxListOffset);
|
||||
} else {
|
||||
if (this.previousLastTerms.length > 0)
|
||||
this.getOptions(this.previousLastTerms[this.previousLastTerms.length - 1]);
|
||||
else
|
||||
this.getOptions(0);
|
||||
}
|
||||
} else {
|
||||
this.checkboxListOffset -= this.maxNumOptionsCheckboxList;
|
||||
if (this.checkboxListOffset < 0)
|
||||
|
@ -492,9 +541,28 @@
|
|||
this.getOptions(this.checkboxListOffset);
|
||||
}
|
||||
},
|
||||
previousSearchPage() {
|
||||
this.noMoreSearchPage = false;
|
||||
|
||||
if (this.isUsingElasticSearch) {
|
||||
this.previousLastTerms.pop();
|
||||
|
||||
if (this.previousLastTerms.length > 0)
|
||||
this.checkboxListOffset = this.previousLastTerms[this.previousLastTerms.length - 1];
|
||||
else
|
||||
this.checkboxListOffset = '';
|
||||
|
||||
} else {
|
||||
this.checkboxListOffset -= this.maxNumSearchResultsShow;
|
||||
|
||||
if (this.checkboxListOffset < 0)
|
||||
this.checkboxListOffset = 0;
|
||||
}
|
||||
this.autoComplete();
|
||||
},
|
||||
nextPage() {
|
||||
|
||||
if (this.isUsingElasticSearch)
|
||||
if (this.isUsingElasticSearch && this.checkboxListOffset)
|
||||
this.previousLastTerms.push(this.checkboxListOffset);
|
||||
|
||||
if (!this.noMorePage && !this.isUsingElasticSearch) {
|
||||
|
@ -506,9 +574,23 @@
|
|||
}
|
||||
|
||||
this.isCheckboxListLoading = true;
|
||||
|
||||
this.getOptions(this.checkboxListOffset);
|
||||
},
|
||||
nextSearchPage() {
|
||||
|
||||
if (this.isUsingElasticSearch && this.checkboxListOffset)
|
||||
this.previousLastTerms.push(this.checkboxListOffset);
|
||||
|
||||
if (!this.noMoreSearchPage && !this.isUsingElasticSearch) {
|
||||
// LIMIT 0, 20 / LIMIT 19, 20 / LIMIT 39, 20 / LIMIT 59, 20
|
||||
if (this.checkboxListOffset === this.maxNumSearchResultsShow)
|
||||
this.checkboxListOffset += this.maxNumSearchResultsShow - 1;
|
||||
else
|
||||
this.checkboxListOffset += this.maxNumSearchResultsShow;
|
||||
}
|
||||
|
||||
this.autoComplete();
|
||||
},
|
||||
getOptions(offset) {
|
||||
let promise = '';
|
||||
|
||||
|
@ -526,14 +608,14 @@
|
|||
this.isCheckboxListLoading = false;
|
||||
this.isLoadingSearch = false;
|
||||
|
||||
if (this.isUsingElasticSearch) {
|
||||
|
||||
this.checkboxListOffset = res.data.last_term.es_term;
|
||||
if (!this.isUsingElasticSearch && res.headers && res.headers['x-wp-total'])
|
||||
this.noMorePage = res.headers['x-wp-total'] <= this.checkboxListOffset + res.data.values.length;
|
||||
|
||||
if (this.isUsingElasticSearch) {
|
||||
this.checkboxListOffset = res.data.last_term.es_term;
|
||||
|
||||
this.noMorePage = !res.data.last_term || !res.data.last_term.es_term;
|
||||
|
||||
if (!this.lastTermOnFisrtPage || this.lastTermOnFisrtPage == this.checkboxListOffset) {
|
||||
this.lastTermOnFisrtPage = this.checkboxListOffset;
|
||||
this.previousLastTerms.push(0);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
|
@ -549,33 +631,38 @@
|
|||
autoComplete: _.debounce( function () {
|
||||
|
||||
this.isSearching = !!this.optionName.length;
|
||||
|
||||
|
||||
if (!this.isSearching)
|
||||
return;
|
||||
|
||||
if (this.isTaxonomy) {
|
||||
this.isLoadingSearch = true;
|
||||
this.isLoadingSearch = true;
|
||||
|
||||
let query_items = { 'current_query': this.query };
|
||||
let query = `?order=asc&number=${this.maxNumSearchResultsShow}&search=${this.optionName}&${qs.stringify(query_items)}`;
|
||||
let query_items = { 'current_query': this.query };
|
||||
let query = `?order=asc&number=${this.maxNumSearchResultsShow}&search=${this.optionName}&${qs.stringify(query_items)}&${this.isUsingElasticSearch ? 'last_term' : 'offset'}=${this.checkboxListOffset}`;
|
||||
|
||||
let route = `/collection/${this.collectionId}/facets/${this.metadatumId}${query}`;
|
||||
let route = `/collection/${this.collectionId}/facets/${this.metadatumId}${query}`;
|
||||
|
||||
if (this.collectionId == 'default')
|
||||
route = `/facets/${this.metadatumId}${query}`;
|
||||
|
||||
if (this.collectionId == 'default')
|
||||
route = `/facets/${this.metadatumId}${query}`;
|
||||
axios.get(route)
|
||||
.then((res) => {
|
||||
this.searchResults = res.data.values;
|
||||
this.isLoadingSearch = false;
|
||||
|
||||
axios.get(route)
|
||||
.then((res) => {
|
||||
this.searchResults = res.data.values;
|
||||
this.isLoadingSearch = false;
|
||||
}).catch((error) => {
|
||||
this.$console.log(error);
|
||||
});
|
||||
} else {
|
||||
this.isLoadingSearch = true;
|
||||
if (!this.isUsingElasticSearch && res.headers && res.headers['x-wp-total'])
|
||||
this.noMoreSearchPage = res.headers['x-wp-total'] <= this.checkboxListOffset + this.searchResults.length;
|
||||
|
||||
if (this.isUsingElasticSearch) {
|
||||
this.checkboxListOffset = res.data.last_term.es_term;
|
||||
|
||||
this.getOptions(0);
|
||||
}
|
||||
this.noMoreSearchPage = !res.data.last_term || !res.data.last_term.es_term;
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
this.$console.log(error);
|
||||
});
|
||||
|
||||
}, 500),
|
||||
highlightHierarchyPath(){
|
||||
for (let [index, el] of this.hierarchicalPath.entries()) {
|
||||
|
@ -805,7 +892,7 @@
|
|||
margin-bottom: 0 !important;
|
||||
|
||||
ul {
|
||||
padding: none;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
.hidden-tabs-section /deep/ .tabs {
|
||||
|
@ -844,37 +931,13 @@
|
|||
cursor: pointer;
|
||||
border: 1px solid var(--tainacan-gray1);
|
||||
margin-top: 10px;
|
||||
margin-bottom: -0.2em;
|
||||
margin-bottom: 0.1em;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--tainacan-blue1);
|
||||
}
|
||||
}
|
||||
|
||||
.tainacan-li-search-results {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 1;
|
||||
width: 100%;
|
||||
padding: 0 0.5em;
|
||||
|
||||
.b-checkbox, .b-radio {
|
||||
max-width: 100%;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 0;
|
||||
overflow: hidden;
|
||||
align-items: baseline;
|
||||
|
||||
.control-label .checkbox-label-text {
|
||||
white-space: normal;
|
||||
line-height: 1.45em;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--tainacan-gray1);
|
||||
}
|
||||
}
|
||||
|
||||
.tainacan-li-checkbox-modal {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
@ -909,6 +972,13 @@
|
|||
&:hover {
|
||||
background-color: var(--tainacan-gray1);
|
||||
}
|
||||
&.result-info {
|
||||
padding: 0.5rem 0.25rem 0.25rem 0.25rem;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
column-span: all;
|
||||
font-size: 0.75em;
|
||||
}
|
||||
}
|
||||
|
||||
.tainacan-finder-columns-container {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
@input="fetchSelectedLabels()"
|
||||
v-model="activeTab">
|
||||
<b-tab-item
|
||||
style="margin: 0 -1.5rem;"
|
||||
style="margin: 0 -0.75rem;"
|
||||
:label="isTaxonomy ? $i18n.get('label_all_terms') : $i18n.get('label_all_metadatum_values')">
|
||||
|
||||
<!-- Search input -->
|
||||
|
@ -38,13 +38,93 @@
|
|||
type="search" />
|
||||
</b-field>
|
||||
|
||||
<!-- Search Results -->
|
||||
<div
|
||||
v-if="isSearching"
|
||||
:style="{ height: expandResultsSection ? 'auto' : '0px' }"
|
||||
class="modal-card-body tainacan-checkbox-list-container">
|
||||
<a
|
||||
v-if="checkboxListOffset"
|
||||
role="button"
|
||||
class="tainacan-checkbox-list-page-changer"
|
||||
@click="previousSearchPage">
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-previous"/>
|
||||
</span>
|
||||
</a>
|
||||
<ul
|
||||
:class="{
|
||||
'tainacan-modal-checkbox-list-body-dynamic-m-l': !checkboxListOffset,
|
||||
'tainacan-modal-checkbox-list-body-dynamic-m-r': noMoreSearchPage,
|
||||
}"
|
||||
class="tainacan-modal-checkbox-list-body">
|
||||
<template v-if="searchResults.length">
|
||||
<li
|
||||
class="tainacan-li-checkbox-list"
|
||||
v-for="(option, key) in searchResults"
|
||||
:key="key">
|
||||
<label
|
||||
v-if="isCheckbox"
|
||||
class="b-checkbox checkbox">
|
||||
<input
|
||||
v-model="selected"
|
||||
:value="option.id ? (isNaN(Number(option.id)) ? option.id : Number(option.id)) : (isNaN(Number(option.value)) ? option.value : Number(option.value))"
|
||||
type="checkbox">
|
||||
<span class="check" />
|
||||
<span class="control-label">
|
||||
<span
|
||||
class="checkbox-label-text"
|
||||
v-html="`${ option.name ? option.name : (option.label ? (option.hierarchy_path ? renderHierarchicalPath(option.hierarchy_path, option.label) : option.label) : '') }`" />
|
||||
</span>
|
||||
</label>
|
||||
<b-radio
|
||||
v-tooltip="{
|
||||
content: option.name ? option.name : option.label,
|
||||
autoHide: false,
|
||||
}"
|
||||
v-else
|
||||
v-model="selected"
|
||||
:native-value="option.id ? (isNaN(Number(option.id)) ? option.id : Number(option.value)) : (isNaN(Number(option.value)) ? option.value : Number(option.value))">
|
||||
<span
|
||||
class="checkbox-label-text"
|
||||
v-html="`${ option.name ? option.name : (option.label ? (option.hierarchy_path ? renderHierarchicalPath(option.hierarchy_path, option.label) : option.label) : '') }`" />
|
||||
</b-radio>
|
||||
</li>
|
||||
</template>
|
||||
<template v-if="!isLoadingSearch && !searchResults.length">
|
||||
<li class="tainacan-li-checkbox-list result-info">
|
||||
{{ $i18n.get('info_no_terms_found') }}
|
||||
</li>
|
||||
</template>
|
||||
<template v-if="!isLoadingSearch && allowNew && !searchResults.length">
|
||||
<li class="tainacan-li-checkbox-list result-info">
|
||||
<a @click="$emit('showAddNewTerm', { name: optionName })">
|
||||
{{ $i18n.get('label_new_term') + ' "' + optionName + '"' }}
|
||||
</a>
|
||||
</li>
|
||||
</template>
|
||||
<b-loading
|
||||
:is-full-page="false"
|
||||
:active.sync="isLoadingSearch"/>
|
||||
</ul>
|
||||
<a
|
||||
v-if="!noMoreSearchPage"
|
||||
role="button"
|
||||
class="tainacan-checkbox-list-page-changer"
|
||||
@click="nextSearchPage">
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-next"/>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Non-hierarchical lists -->
|
||||
<div
|
||||
v-if="!isSearching && !isTaxonomy"
|
||||
:style="{ height: expandResultsSection ? 'auto' : '0px' }"
|
||||
class="modal-card-body tainacan-checkbox-list-container">
|
||||
<a
|
||||
v-if="isUsingElasticSearch ? lastTermOnFisrtPage != checkboxListOffset : checkboxListOffset"
|
||||
v-if="checkboxListOffset"
|
||||
role="button"
|
||||
class="tainacan-checkbox-list-page-changer"
|
||||
@click="previousPage">
|
||||
|
@ -169,79 +249,20 @@
|
|||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-showmore"/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="warning-no-more-terms"
|
||||
v-else>
|
||||
{{ isUsingElasticSearch ? $i18n.get('info_no_more_terms_found') : '' }}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</transition-group>
|
||||
|
||||
<b-loading
|
||||
:is-full-page="false"
|
||||
:active.sync="isColumnLoading"/>
|
||||
|
||||
<!-- Search Results -->
|
||||
<div
|
||||
v-if="isSearching"
|
||||
:style="{ height: expandResultsSection ? 'auto' : '0px' }"
|
||||
class="modal-card-body tainacan-search-results-container">
|
||||
<ul class="tainacan-modal-checkbox-search-results-body">
|
||||
<template v-if="searchResults.length">
|
||||
<li
|
||||
class="tainacan-li-search-results"
|
||||
v-for="(option, key) in searchResults"
|
||||
:key="key">
|
||||
<label
|
||||
v-if="isCheckbox"
|
||||
class="b-checkbox checkbox">
|
||||
<input
|
||||
v-model="selected"
|
||||
:value="option.id ? (isNaN(Number(option.id)) ? option.id : Number(option.id)) : (isNaN(Number(option.value)) ? option.value : Number(option.value))"
|
||||
type="checkbox">
|
||||
<span class="check" />
|
||||
<span class="control-label">
|
||||
<span
|
||||
class="checkbox-label-text"
|
||||
v-html="`${ option.name ? option.name : (option.label ? (option.hierarchy_path ? renderHierarchicalPath(option.hierarchy_path, option.label) : option.label) : '') }`" />
|
||||
</span>
|
||||
</label>
|
||||
<b-radio
|
||||
v-tooltip="{
|
||||
content: option.name ? option.name : option.label,
|
||||
autoHide: false,
|
||||
}"
|
||||
v-else
|
||||
v-model="selected"
|
||||
:native-value="option.id ? (isNaN(Number(option.id)) ? option.id : Number(option.value)) : (isNaN(Number(option.value)) ? option.value : Number(option.value))">
|
||||
<span
|
||||
class="checkbox-label-text"
|
||||
v-html="`${ option.name ? option.name : (option.label ? (option.hierarchy_path ? renderHierarchicalPath(option.hierarchy_path, option.label) : option.label) : '') }`" />
|
||||
</b-radio>
|
||||
</li>
|
||||
</template>
|
||||
<template v-if="!isLoadingSearch && !searchResults.length">
|
||||
<li class="tainacan-li-search-results result-info">
|
||||
{{ $i18n.get('info_no_terms_found') }}
|
||||
</li>
|
||||
</template>
|
||||
<template v-if="!isLoadingSearch && allowNew && !searchResults.length">
|
||||
<li class="tainacan-li-search-results result-info">
|
||||
<a @click="$emit('showAddNewTerm', { name: optionName })">
|
||||
{{ $i18n.get('label_new_term') + ' "' + optionName + '"' }}
|
||||
</a>
|
||||
</li>
|
||||
</template>
|
||||
<b-loading
|
||||
:is-full-page="false"
|
||||
:active.sync="isLoadingSearch"/>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</b-tab-item>
|
||||
|
||||
<b-tab-item :label="(isTaxonomy ? $i18n.get('label_selected_terms') : $i18n.get('label_selected_metadatum_values')) + (amountSelected !== null && amountSelected !== undefined ? (' (' + amountSelected + ')' ): '') ">
|
||||
<b-tab-item
|
||||
style="min-height: 56px;"
|
||||
:label="(isTaxonomy ? $i18n.get('label_selected_terms') : $i18n.get('label_selected_metadatum_values')) + (amountSelected !== null && amountSelected !== undefined ? (' (' + amountSelected + ')' ): '') ">
|
||||
|
||||
<div class="modal-card-body tainacan-tags-container">
|
||||
<b-field
|
||||
|
@ -339,13 +360,11 @@
|
|||
checkboxListOffset: 0,
|
||||
isCheckboxListLoading: false,
|
||||
isLoadingSearch: false,
|
||||
noMorePage: 0,
|
||||
noMorePage: false,
|
||||
noMoreSearchPage: false,
|
||||
activeTab: 0,
|
||||
selectedTagsName: {},
|
||||
isSelectedTermsLoading: false,
|
||||
isUsingElasticSearch: tainacan_plugin.wp_elasticpress == "1" ? true : false,
|
||||
previousLastTerms: [],
|
||||
lastTermOnFisrtPage: null,
|
||||
expandResultsSection: false
|
||||
}
|
||||
},
|
||||
|
@ -357,14 +376,19 @@
|
|||
watch: {
|
||||
selected() {
|
||||
this.$emit('input', this.selected);
|
||||
},
|
||||
optionName(newValue, oldValue) {
|
||||
if (newValue != oldValue) {
|
||||
this.noMoreSearchPage = false;
|
||||
this.checkboxListOffset = 0;
|
||||
}
|
||||
}
|
||||
},
|
||||
updated(){
|
||||
if (!this.isSearching)
|
||||
if (!this.isSearching && this.isTaxonomy)
|
||||
this.highlightHierarchyPath();
|
||||
},
|
||||
created() {
|
||||
this.isUsingElasticSearch = false;
|
||||
|
||||
if (this.shouldBeginWithListExpanded)
|
||||
this.initializeValues();
|
||||
|
@ -389,7 +413,7 @@
|
|||
},
|
||||
methods: {
|
||||
initializeValues() {
|
||||
this.maxNumOptionsCheckboxFinderColumns = 12;
|
||||
this.maxNumOptionsCheckboxFinderColumns = 50;
|
||||
|
||||
if (this.isTaxonomy) {
|
||||
this.getOptionChildren();
|
||||
|
@ -399,7 +423,7 @@
|
|||
}
|
||||
},
|
||||
shouldShowMoreButton(key) {
|
||||
return this.totalRemaining[key].remaining == true || (this.finderColumns[key].children.length < this.totalRemaining[key].remaining);
|
||||
return this.totalRemaining[key].remaining === true || (this.finderColumns[key].children.length < this.totalRemaining[key].remaining);
|
||||
},
|
||||
fetchSelectedLabels() {
|
||||
|
||||
|
@ -443,32 +467,31 @@
|
|||
},
|
||||
previousPage() {
|
||||
|
||||
this.noMorePage = 0;
|
||||
this.noMorePage = false;
|
||||
this.isCheckboxListLoading = true;
|
||||
|
||||
if (this.isUsingElasticSearch) {
|
||||
this.previousLastTerms.pop();
|
||||
this.checkboxListOffset -= this.maxNumOptionsCheckboxList;
|
||||
if (this.checkboxListOffset < 0)
|
||||
this.checkboxListOffset = 0;
|
||||
|
||||
if (this.previousLastTerms.length > 0) {
|
||||
this.getOptions(this.previousLastTerms.pop());
|
||||
this.previousLastTerms.push(this.checkboxListOffset);
|
||||
} else {
|
||||
this.getOptions(0);
|
||||
}
|
||||
} else {
|
||||
this.checkboxListOffset -= this.maxNumOptionsCheckboxList;
|
||||
if (this.checkboxListOffset < 0)
|
||||
this.checkboxListOffset = 0;
|
||||
this.getOptions(this.checkboxListOffset);
|
||||
|
||||
},
|
||||
previousSearchPage() {
|
||||
|
||||
this.getOptions(this.checkboxListOffset);
|
||||
}
|
||||
this.noMoreSearchPage = false;
|
||||
this.isCheckboxListLoading = true;
|
||||
|
||||
this.checkboxListOffset -= this.maxNumSearchResultsShow;
|
||||
if (this.checkboxListOffset < 0)
|
||||
this.checkboxListOffset = 0;
|
||||
|
||||
this.autoComplete();
|
||||
|
||||
},
|
||||
nextPage() {
|
||||
|
||||
if (this.isUsingElasticSearch)
|
||||
this.previousLastTerms.push(this.checkboxListOffset);
|
||||
|
||||
if (!this.noMorePage && !this.isUsingElasticSearch) {
|
||||
if (!this.noMorePage) {
|
||||
// LIMIT 0, 20 / LIMIT 19, 20 / LIMIT 39, 20 / LIMIT 59, 20
|
||||
if (this.checkboxListOffset === this.maxNumOptionsCheckboxList)
|
||||
this.checkboxListOffset += this.maxNumOptionsCheckboxList - 1;
|
||||
|
@ -480,6 +503,20 @@
|
|||
|
||||
this.getOptions(this.checkboxListOffset);
|
||||
},
|
||||
nextSearchPage() {
|
||||
|
||||
if (!this.noMoreSearchPage) {
|
||||
// LIMIT 0, 20 / LIMIT 19, 20 / LIMIT 39, 20 / LIMIT 59, 20
|
||||
if (this.checkboxListOffset === this.maxNumSearchResultsShow)
|
||||
this.checkboxListOffset += this.maxNumSearchResultsShow - 1;
|
||||
else
|
||||
this.checkboxListOffset += this.maxNumSearchResultsShow;
|
||||
}
|
||||
|
||||
this.isCheckboxListLoading = true;
|
||||
|
||||
this.autoComplete();
|
||||
},
|
||||
getOptions(offset) {
|
||||
let promise = '';
|
||||
|
||||
|
@ -493,19 +530,9 @@
|
|||
promise = this.getValuesPlainText( this.metadatumId, this.optionName, this.isRepositoryLevel, [], offset, this.maxNumOptionsCheckboxList, true);
|
||||
|
||||
promise.request
|
||||
.then((res) => {
|
||||
.then(() => {
|
||||
this.isCheckboxListLoading = false;
|
||||
this.isLoadingSearch = false;
|
||||
|
||||
if (this.isUsingElasticSearch) {
|
||||
|
||||
this.checkboxListOffset = res.data.last_term.es_term;
|
||||
|
||||
if (!this.lastTermOnFisrtPage || this.lastTermOnFisrtPage == this.checkboxListOffset) {
|
||||
this.lastTermOnFisrtPage = this.checkboxListOffset;
|
||||
this.previousLastTerms.push(0);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if (isCancel(error))
|
||||
|
@ -520,14 +547,14 @@
|
|||
autoComplete: _.debounce( function () {
|
||||
|
||||
this.isSearching = !!this.optionName.length;
|
||||
|
||||
|
||||
if (!this.isSearching)
|
||||
return;
|
||||
|
||||
if (this.isTaxonomy) {
|
||||
this.isLoadingSearch = true;
|
||||
|
||||
let query = `?order=asc&number=${this.maxNumSearchResultsShow}&search=${this.optionName}&hideempty=0`;
|
||||
let query = `?order=asc&number=${this.maxNumSearchResultsShow}&search=${this.optionName}&hideempty=0&offset=${this.checkboxListOffset}`;
|
||||
|
||||
let route = `/collection/${this.collectionId}/facets/${this.metadatumId}${query}`;
|
||||
|
||||
|
@ -538,9 +565,14 @@
|
|||
.then((res) => {
|
||||
this.searchResults = res.data.values;
|
||||
this.isLoadingSearch = false;
|
||||
}).catch((error) => {
|
||||
this.$console.log(error);
|
||||
});
|
||||
|
||||
if (res.headers && res.headers['x-wp-total'])
|
||||
this.noMoreSearchPage = res.headers['x-wp-total'] <= this.checkboxListOffset + this.searchResults.length;
|
||||
|
||||
})
|
||||
.catch((error) => {
|
||||
this.$console.log(error);
|
||||
});
|
||||
} else {
|
||||
this.isLoadingSearch = true;
|
||||
|
||||
|
@ -604,7 +636,7 @@
|
|||
|
||||
this.totalRemaining = Object.assign({}, this.totalRemaining, {
|
||||
[`${column == undefined ? 0 : column + 1}`]: {
|
||||
remaining: this.isUsingElasticSearch ? (children.length > 0 ? res.data.last_term.value == children[children.length - 1].value : false) : res.headers['x-wp-total'],
|
||||
remaining: res.headers['x-wp-total'],
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -698,10 +730,9 @@
|
|||
|
||||
this.totalRemaining = Object.assign({}, this.totalRemaining, {
|
||||
[`${key}`]: {
|
||||
remaining: this.isUsingElasticSearch ? (res.data.values.length > 0 ? (res.data.last_term.value == res.data.values[res.data.values.length - 1].value) : false) : res.headers['x-wp-total'],
|
||||
remaining: res.headers['x-wp-total'],
|
||||
}
|
||||
});
|
||||
|
||||
this.isColumnLoading = false;
|
||||
})
|
||||
.catch(error => {
|
||||
|
@ -737,7 +768,7 @@
|
|||
}
|
||||
|
||||
.tainacan-li-checkbox-list {
|
||||
max-width: calc(100% - (2 * var(--tainacan-one-column))) !important;
|
||||
max-width: calc(100% - 20px) !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -759,7 +790,7 @@
|
|||
}
|
||||
.tab-content {
|
||||
transition: height 0.2s ease;
|
||||
padding: 0.5em var(--tainacan-one-column) !important;
|
||||
padding: 0.5em 20px !important;
|
||||
}
|
||||
|
||||
// In theme, the bootstrap removes the style of <a> without href
|
||||
|
@ -790,35 +821,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.tainacan-li-search-results {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 1;
|
||||
width: 100%;
|
||||
padding: 0 0.5em;
|
||||
|
||||
.b-checkbox, .b-radio {
|
||||
max-width: 100%;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 0;
|
||||
overflow: hidden;
|
||||
align-items: baseline;
|
||||
|
||||
.control-label .checkbox-label-text {
|
||||
white-space: normal;
|
||||
line-height: 1.45em;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover:not(.result-info) {
|
||||
background-color: var(--tainacan-gray1);
|
||||
}
|
||||
&.result-info {
|
||||
width: 100%;
|
||||
column-span: all;
|
||||
font-size: 0.75em;
|
||||
}
|
||||
}
|
||||
|
||||
.tainacan-li-checkbox-modal {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
@ -842,7 +844,8 @@
|
|||
.tainacan-li-checkbox-list {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 1;
|
||||
max-width: calc(50% - (2 * var(--tainacan-one-column)));
|
||||
max-width: calc(50% - 20px);
|
||||
width: 100%;
|
||||
padding-left: 0.5em;
|
||||
|
||||
.b-checkbox, .b-radio {
|
||||
|
@ -850,9 +853,16 @@
|
|||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&:hover:not(.result-info) {
|
||||
background-color: var(--tainacan-gray1);
|
||||
}
|
||||
&.result-info {
|
||||
padding: 0.5rem 0.25rem 0.25rem 0.25rem;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
column-span: all;
|
||||
font-size: 0.75em;
|
||||
}
|
||||
}
|
||||
|
||||
.tainacan-finder-columns-container {
|
||||
|
@ -953,7 +963,6 @@
|
|||
-webkit-margin-before: 0;
|
||||
}
|
||||
|
||||
|
||||
.field:not(:last-child) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
@ -983,10 +992,13 @@
|
|||
}
|
||||
|
||||
.tainacan-checkbox-list-container {
|
||||
padding: 0 20px !important;
|
||||
border: 1px solid var(--tainacan-gray1);
|
||||
border-top: 0px;
|
||||
margin-top: -1px;
|
||||
min-height: 232px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 20px !important;
|
||||
padding-right: 0 !important;
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
|
@ -1016,15 +1028,11 @@
|
|||
}
|
||||
|
||||
.tainacan-modal-checkbox-list-body-dynamic-m-l {
|
||||
margin-left: var(--tainacan-one-column) !important;
|
||||
margin-left: 2px !important;
|
||||
}
|
||||
|
||||
.tainacan-modal-checkbox-list-body-dynamic-m-r {
|
||||
margin-right: var(--tainacan-one-column) !important;
|
||||
}
|
||||
|
||||
.tainacan-search-results-container {
|
||||
padding: 0.25em !important;
|
||||
margin-right: 2px !important;
|
||||
}
|
||||
|
||||
.tainacan-tags-container {
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
computed: {
|
||||
filterTags() {
|
||||
let tags = this.getFilterTags();
|
||||
|
||||
let flattenTags = [];
|
||||
for (let tag of tags) {
|
||||
if (Array.isArray(tag.label)) {
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
import axios from '../../../axios';
|
||||
|
||||
export const fetchSummary = ({ commit }, { collectionId, force } ) => {
|
||||
|
||||
let endpoint = '/reports';
|
||||
|
||||
if (collectionId && collectionId != 'default')
|
||||
endpoint += '/collection/' + collectionId + '/summary';
|
||||
else
|
||||
endpoint += '/repository/summary';
|
||||
|
||||
if (force && force === true)
|
||||
endpoint += '?force=yes'
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.tainacan.get(endpoint)
|
||||
.then(res => {
|
||||
let summary = res.data;
|
||||
|
||||
commit('setSummary', summary);
|
||||
commit('setReportLatestCachedOn', { report: 'summary-' + (collectionId ? collectionId : 'default'), reportLatestCachedOn: res.data.report_cached_on });
|
||||
resolve(summary);
|
||||
})
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchMetadata = ({ commit }, { collectionId, force } ) => {
|
||||
|
||||
let endpoint = '/reports';
|
||||
|
||||
if (collectionId && collectionId != 'default')
|
||||
endpoint += '/collection/' + collectionId + '/metadata';
|
||||
else
|
||||
endpoint += '/metadata';
|
||||
|
||||
if (force && force === true)
|
||||
endpoint += '?force=yes';
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.tainacan.get(endpoint)
|
||||
.then(res => {
|
||||
let metadata = res.data;
|
||||
|
||||
commit('setMetadata', metadata);
|
||||
commit('setReportLatestCachedOn', { report: 'metadata-' + (collectionId ? collectionId : 'default'), reportLatestCachedOn: res.data.report_cached_on });
|
||||
resolve(metadata);
|
||||
})
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchMetadataList = ({ commit }, { collectionId, onlyTaxonomies } ) => {
|
||||
|
||||
let endpoint = '';
|
||||
|
||||
if (collectionId && collectionId != 'default')
|
||||
endpoint += '/collection/' + collectionId + '/metadata/';
|
||||
else
|
||||
endpoint += '/metadata/';
|
||||
|
||||
if (onlyTaxonomies)
|
||||
endpoint += '?metaquery[0][key]=metadata_type&metaquery[0][value]=Tainacan\\Metadata_Types\\Taxonomy';
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.tainacan.get(endpoint)
|
||||
.then(res => {
|
||||
let metadataList = res.data;
|
||||
|
||||
commit('setMetadataList', metadataList);
|
||||
resolve(metadataList);
|
||||
})
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchCollectionsList = ({ commit }, force) => {
|
||||
|
||||
let endpoint = '/reports/collection';
|
||||
|
||||
if (force && force === true)
|
||||
endpoint += '?force=yes';
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.tainacan.get(endpoint)
|
||||
.then(res => {
|
||||
let collectionsList = res.data.list ? res.data.list : {};
|
||||
|
||||
commit('setCollectionsList', collectionsList);
|
||||
commit('setReportLatestCachedOn', { report: 'collections', reportLatestCachedOn: res.data.report_cached_on });
|
||||
resolve(collectionsList);
|
||||
})
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchTaxonomiesList = ({ commit }, force) => {
|
||||
|
||||
let endpoint = '/reports/taxonomy';
|
||||
|
||||
if (force && force === true)
|
||||
endpoint += '?force=yes';
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.tainacan.get(endpoint)
|
||||
.then(res => {
|
||||
let taxonomiesList = res.data.list ? res.data.list : {};
|
||||
|
||||
commit('setTaxonomiesList', taxonomiesList);
|
||||
commit('setReportLatestCachedOn', { report: 'taxonomies', reportLatestCachedOn: res.data.report_cached_on });
|
||||
resolve(taxonomiesList);
|
||||
})
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchTaxonomyTerms = ({ commit }, { taxonomyId, collectionId, parentTerm, isChildChart, force }) => {
|
||||
|
||||
let endpoint = '/reports';
|
||||
|
||||
if (collectionId && collectionId != 'default')
|
||||
endpoint += '/collection/' + collectionId + '/metadata/' + taxonomyId + '?';
|
||||
else
|
||||
endpoint += '/taxonomy/' + taxonomyId + '?';
|
||||
|
||||
if (force)
|
||||
endpoint += '&force=yes';
|
||||
|
||||
if (parentTerm)
|
||||
endpoint += '&parent=' + parentTerm;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.tainacan.get(endpoint)
|
||||
.then(res => {
|
||||
let taxonomyTerms = {};
|
||||
if (collectionId && collectionId != 'default')
|
||||
taxonomyTerms = res.data.list ? res.data.list : [];
|
||||
else
|
||||
taxonomyTerms = res.data.terms ? Object.values(res.data.terms) : [];
|
||||
|
||||
if (isChildChart) {
|
||||
commit('setTaxonomyChildTerms', taxonomyTerms);
|
||||
commit('setReportLatestCachedOn', {
|
||||
report: 'taxonomy-terms-' + (collectionId ? collectionId : 'default') + '-' + taxonomyId + (parentTerm ? '-' + parentTerm : '') + '-is-child-chart',
|
||||
reportLatestCachedOn: res.data.report_cached_on
|
||||
});
|
||||
} else {
|
||||
commit('setTaxonomyTerms', taxonomyTerms);
|
||||
commit('setReportLatestCachedOn', {
|
||||
report: 'taxonomy-terms-' + (collectionId ? collectionId : 'default') + '-' + taxonomyId + (parentTerm ? '-' + parentTerm : ''),
|
||||
reportLatestCachedOn: res.data.report_cached_on
|
||||
});
|
||||
}
|
||||
resolve(taxonomyTerms);
|
||||
})
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchActivities = ({ commit }, { collectionId, startDate, force } ) => {
|
||||
|
||||
let endpoint = '/reports';
|
||||
|
||||
if (collectionId && collectionId != 'default')
|
||||
endpoint += '/collection/' + collectionId + '/activities?';
|
||||
else
|
||||
endpoint += '/activities?';
|
||||
|
||||
if (startDate)
|
||||
endpoint += '&start=' + startDate;
|
||||
|
||||
if (force)
|
||||
endpoint += '&force=yes';
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.tainacan.get(endpoint)
|
||||
.then(res => {
|
||||
let activities = res.data;
|
||||
|
||||
commit('setActivities', activities);
|
||||
commit('setReportLatestCachedOn', { report: 'activities-' + (collectionId ? collectionId : 'default') + (startDate ? '-' + startDate : ''), reportLatestCachedOn: res.data.report_cached_on });
|
||||
resolve(activities);
|
||||
})
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
};
|
|
@ -0,0 +1,59 @@
|
|||
export const getSummary = state => {
|
||||
return state.summary;
|
||||
};
|
||||
|
||||
export const getMetadata = state => {
|
||||
return state.metadata;
|
||||
};
|
||||
|
||||
export const getMetadataList = state => {
|
||||
return state.metadataList;
|
||||
};
|
||||
|
||||
export const getCollectionsList = state => {
|
||||
return state.collectionsList;
|
||||
};
|
||||
|
||||
export const getTaxonomiesList = state => {
|
||||
return state.taxonomiesList;
|
||||
};
|
||||
|
||||
export const getTaxonomyTerms = state => {
|
||||
return state.taxonomyTerms;
|
||||
};
|
||||
|
||||
export const getTaxonomyChildTerms = state => {
|
||||
return state.taxonomyChildTerms;
|
||||
};
|
||||
|
||||
export const getActivities = state => {
|
||||
return state.activities;
|
||||
};
|
||||
|
||||
export const getStackedBarChartOptions = state => {
|
||||
return state.stackedBarChartOptions;
|
||||
};
|
||||
|
||||
export const getHorizontalBarChartOptions = state => {
|
||||
return state.horizontalBarChartOptions;
|
||||
};
|
||||
|
||||
export const getDonutChartOptions = state => {
|
||||
return state.donutChartOptions;
|
||||
};
|
||||
|
||||
export const getHeatMapChartOptions = state => {
|
||||
return state.heatMapChartOptions;
|
||||
};
|
||||
|
||||
export const getAreaChartOptions = state => {
|
||||
return state.areaChartOptions;
|
||||
};
|
||||
|
||||
export const getTreeMapChartOptions = state => {
|
||||
return state.treeMapChartOptions;
|
||||
};
|
||||
|
||||
export const getReportsLatestCachedOn = state => {
|
||||
return state.reportsLatestCachedOn;
|
||||
};
|
|
@ -0,0 +1,206 @@
|
|||
import * as actions from './actions';
|
||||
import * as getters from './getters';
|
||||
import * as mutations from './mutations';
|
||||
|
||||
const state = {
|
||||
reportsLatestCachedOn: {},
|
||||
summary: {},
|
||||
taxonomiesList: {},
|
||||
collectionsList: {},
|
||||
taxonomyTerms: [],
|
||||
taxonomyChildTerms: [],
|
||||
metadata: {},
|
||||
metadataList: {},
|
||||
activities: {},
|
||||
stackedBarChartOptions: {
|
||||
chart: {
|
||||
type: 'bar',
|
||||
height: 350,
|
||||
stacked: true,
|
||||
toolbar: {
|
||||
show: true
|
||||
},
|
||||
zoom: {
|
||||
enabled: true,
|
||||
autoScaleYaxis: true,
|
||||
}
|
||||
},
|
||||
title: {
|
||||
text: ''
|
||||
},
|
||||
responsive: [{
|
||||
breakpoint: 480,
|
||||
options: {
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
offsetX: -10,
|
||||
offsetY: 0
|
||||
}
|
||||
}
|
||||
}],
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 0,
|
||||
horizontal: false,
|
||||
},
|
||||
},
|
||||
xaxis: {
|
||||
type: 'category',
|
||||
tickPlacement: 'on',
|
||||
categories: [],
|
||||
tooltip: { enabled: true }
|
||||
},
|
||||
yaxis: {
|
||||
title: {
|
||||
text: ''
|
||||
},
|
||||
tooltip: { enabled: true }
|
||||
},
|
||||
legend: {
|
||||
position: 'right',
|
||||
offsetY: 40
|
||||
},
|
||||
fill: {
|
||||
opacity: 1
|
||||
}
|
||||
},
|
||||
donutChartOptions: {
|
||||
chart: {
|
||||
type: 'donut',
|
||||
toolbar: {
|
||||
show: true
|
||||
},
|
||||
height: 350,
|
||||
},
|
||||
title: {
|
||||
text: ''
|
||||
},
|
||||
stroke: {
|
||||
width: 0
|
||||
},
|
||||
labels: [],
|
||||
responsive: [{
|
||||
breakpoint: 480,
|
||||
options: {
|
||||
chart: {
|
||||
width: 200
|
||||
},
|
||||
legend: {
|
||||
position: 'bottom'
|
||||
}
|
||||
}
|
||||
}]
|
||||
},
|
||||
horizontalBarChartOptions: {
|
||||
chart: {
|
||||
type: 'bar',
|
||||
height: 350,
|
||||
stacked: true,
|
||||
stackType: '100%',
|
||||
toolbar: {
|
||||
show: true
|
||||
},
|
||||
zoom: {
|
||||
type: 'y',
|
||||
enabled: true,
|
||||
autoScaleYaxis: true,
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: true,
|
||||
},
|
||||
},
|
||||
title: {
|
||||
text: ''
|
||||
},
|
||||
xaxis: {
|
||||
type: 'category',
|
||||
tickPlacement: 'on',
|
||||
categories: [],
|
||||
tooltip: { enabled: true }
|
||||
},
|
||||
yaxis: {
|
||||
tickPlacement: 'on',
|
||||
tooltip: { enabled: true }
|
||||
},
|
||||
tooltip: {
|
||||
enabled: true
|
||||
},
|
||||
fill: {
|
||||
opacity: 1
|
||||
|
||||
},
|
||||
legend: {
|
||||
position: 'top',
|
||||
horizontalAlign: 'left',
|
||||
offsetX: 40,
|
||||
}
|
||||
},
|
||||
areaChartOptions: {
|
||||
chart: {
|
||||
height: 200,
|
||||
type: 'area',
|
||||
toolbar: {
|
||||
show: true,
|
||||
tools: {
|
||||
download: true,
|
||||
selection: false,
|
||||
zoom: true,
|
||||
zoomin: true,
|
||||
zoomout: true,
|
||||
pan: true,
|
||||
}
|
||||
},
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
stroke: {
|
||||
width: 1,
|
||||
curve: 'smooth'
|
||||
},
|
||||
fill: {
|
||||
opacity: 1,
|
||||
type: 'gradient',
|
||||
gradient: {
|
||||
shade: 'light',
|
||||
type: "vertical",
|
||||
opacityFrom: 0.65,
|
||||
opacityTo: 0.35,
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
position: 'top',
|
||||
horizontalAlign: 'left'
|
||||
},
|
||||
xaxis: {
|
||||
type: 'datetime'
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
minWidth: 64
|
||||
}
|
||||
}
|
||||
},
|
||||
treeMapOptions: {
|
||||
legend: {
|
||||
show: false
|
||||
},
|
||||
chart: {
|
||||
height: 350,
|
||||
type: 'treemap'
|
||||
},
|
||||
title: {
|
||||
text: ''
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions,
|
||||
getters
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
export const setSummary = (state, summary) => {
|
||||
state.summary = summary;
|
||||
};
|
||||
|
||||
export const setMetadata = (state, metadata) => {
|
||||
state.metadata = metadata;
|
||||
};
|
||||
|
||||
export const setMetadataList = (state, metadataList) => {
|
||||
state.metadataList = metadataList;
|
||||
};
|
||||
|
||||
export const setCollectionsList = (state, collectionsList) => {
|
||||
state.collectionsList = collectionsList;
|
||||
};
|
||||
|
||||
export const setTaxonomiesList = (state, taxonomiesList) => {
|
||||
state.taxonomiesList = taxonomiesList;
|
||||
};
|
||||
|
||||
export const setTaxonomyTerms = (state, taxonomyTerms) => {
|
||||
state.taxonomyTerms = taxonomyTerms;
|
||||
};
|
||||
|
||||
export const setTaxonomyChildTerms = (state, taxonomyTerms) => {
|
||||
state.taxonomyChildTerms = taxonomyTerms;
|
||||
};
|
||||
|
||||
export const setActivities = (state, activities) => {
|
||||
state.activities = activities;
|
||||
};
|
||||
|
||||
export const setStackedBarChartOptions = (state, stackedBarChartOptions) => {
|
||||
state.stackedBarChartOptions = stackedBarChartOptions;
|
||||
};
|
||||
|
||||
export const setHorizontalBarChartOptions = (state, horizontalBarChartOptions) => {
|
||||
state.horizontalBarChartOptions = horizontalBarChartOptions;
|
||||
};
|
||||
|
||||
export const setDonutChartOptions = (state, donutChartOptions) => {
|
||||
state.donutChartOptions = donutChartOptions;
|
||||
};
|
||||
|
||||
export const setHeatMapChartOptions = (state, heatMapChartOptions) => {
|
||||
state.heatMapChartOptions = heatMapChartOptions;
|
||||
};
|
||||
|
||||
export const setAreaChartOptions = (state, areaChartOptions) => {
|
||||
state.areaChartOptions = areaChartOptions;
|
||||
};
|
||||
|
||||
export const setTreeMapChartOptions = (state, areaChartOptions) => {
|
||||
state.threeMapChartOptions = areaChartOptions;
|
||||
};
|
||||
|
||||
export const setReportLatestCachedOn = (state, { report, reportLatestCachedOn }) => {
|
||||
Vue.set(state.reportsLatestCachedOn, report, reportLatestCachedOn);
|
||||
};
|
|
@ -14,6 +14,7 @@ import bulkedition from './modules/bulk-edition';
|
|||
import exporter from './modules/exporter';
|
||||
import exposer from './modules/exposer';
|
||||
import capability from './modules/capability';
|
||||
import report from './modules/report';
|
||||
|
||||
// Vue Dev Tools!
|
||||
Vue.config.devtools = process && process.env && process.env.NODE_ENV === 'development';
|
||||
|
@ -41,6 +42,7 @@ export default new Vuex.Store({
|
|||
bulkedition,
|
||||
exporter,
|
||||
exposer,
|
||||
capability
|
||||
capability,
|
||||
report
|
||||
}
|
||||
})
|
|
@ -3,8 +3,8 @@
|
|||
background: none;
|
||||
width: calc(100% - (2 * var(--tainacan-one-column)));
|
||||
width: 91.6666667vw;
|
||||
max-height: 86%;
|
||||
max-height: 86vh;
|
||||
max-height: 87%;
|
||||
max-height: 87vh;
|
||||
overflow: auto;
|
||||
border-radius: 0;
|
||||
|
||||
|
|
|
@ -58,6 +58,15 @@ class Admin {
|
|||
array( &$this, 'roles_page' )
|
||||
);
|
||||
|
||||
$reports_page_suffix = add_submenu_page(
|
||||
$this->menu_slug,
|
||||
__('Reports', 'tainacan'),
|
||||
__('Reports', 'tainacan'),
|
||||
'read',
|
||||
'tainacan_reports',
|
||||
array( &$this, 'reports_page' )
|
||||
);
|
||||
|
||||
add_submenu_page(
|
||||
$this->menu_slug,
|
||||
__('Item Submission', 'tainacan'),
|
||||
|
@ -69,6 +78,7 @@ class Admin {
|
|||
|
||||
add_action( 'load-' . $page_suffix, array( &$this, 'load_admin_page' ) );
|
||||
add_action( 'load-' . $roles_page_suffix, array( &$this, 'load_roles_page' ) );
|
||||
add_action( 'load-' . $reports_page_suffix, array( &$this, 'load_reports_page' ) );
|
||||
}
|
||||
|
||||
function load_admin_page() {
|
||||
|
@ -82,6 +92,11 @@ class Admin {
|
|||
add_action( 'admin_enqueue_scripts', array( &$this, 'add_roles_js' ), 90 );
|
||||
}
|
||||
|
||||
function load_reports_page() {
|
||||
add_action( 'admin_enqueue_scripts', array( &$this, 'add_reports_css' ), 90 );
|
||||
add_action( 'admin_enqueue_scripts', array( &$this, 'add_reports_js' ), 90 );
|
||||
}
|
||||
|
||||
function login_styles_reset( $style ) {
|
||||
if ( strpos( $style, 'wp-admin-css' ) !== false ) {
|
||||
$style = null;
|
||||
|
@ -130,6 +145,34 @@ class Admin {
|
|||
echo "<div id='tainacan-roles-app'></div>";
|
||||
}
|
||||
|
||||
function add_reports_css() {
|
||||
global $TAINACAN_BASE_URL;
|
||||
|
||||
wp_enqueue_style( 'tainacan-fonts', $TAINACAN_BASE_URL . '/assets/css/tainacanicons.css', [], TAINACAN_VERSION );
|
||||
wp_enqueue_style( 'tainacan-reports-page', $TAINACAN_BASE_URL . '/assets/css/tainacan-reports.css', [], TAINACAN_VERSION );
|
||||
}
|
||||
|
||||
function add_reports_js() {
|
||||
|
||||
global $TAINACAN_BASE_URL;
|
||||
|
||||
wp_enqueue_script( 'tainacan-reports', $TAINACAN_BASE_URL . '/assets/js/reports.js', ['underscore', 'wp-i18n'], TAINACAN_VERSION, true );
|
||||
wp_set_script_translations('tainacan-reports', 'tainacan');
|
||||
|
||||
$settings = $this->get_admin_js_localization_params();
|
||||
wp_localize_script( 'tainacan-reports', 'tainacan_plugin', $settings );
|
||||
wp_enqueue_script('underscore');
|
||||
wp_enqueue_script('wp-i18n');
|
||||
|
||||
do_action('tainacan-enqueue-reports-scripts');
|
||||
}
|
||||
|
||||
function reports_page() {
|
||||
global $TAINACAN_BASE_URL;
|
||||
// TODO move it to a separate file and start the Vue project
|
||||
echo "<div id='tainacan-reports-app'></div>";
|
||||
}
|
||||
|
||||
function add_admin_css() {
|
||||
global $TAINACAN_BASE_URL;
|
||||
|
||||
|
|
|
@ -22,6 +22,9 @@ import tainacan from '../../js/axios.js';
|
|||
import TainacanBlocksCompatToolbar from '../../js/tainacan-blocks-compat-toolbar.js';
|
||||
import CollectionModal from '../../tainacan-facets/faceted-search/collection-modal.js';
|
||||
|
||||
|
||||
import DeprecatedBlocks from './item-submission-deprecated.js';
|
||||
|
||||
registerBlockType('tainacan/item-submission-form', {
|
||||
title: __('Tainacan Item Submission Form', 'tainacan'),
|
||||
icon:
|
||||
|
@ -160,6 +163,14 @@ registerBlockType('tainacan/item-submission-form', {
|
|||
metadataSectionLabel: {
|
||||
type: String,
|
||||
default: __( 'Metadata', 'tainacan' )
|
||||
},
|
||||
showItemLinkButton: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
itemLinkButtonLabel: {
|
||||
type: String,
|
||||
default: __( 'Go to the item page', 'tainacan' )
|
||||
}
|
||||
},
|
||||
supports: {
|
||||
|
@ -197,7 +208,9 @@ registerBlockType('tainacan/item-submission-form', {
|
|||
documentSectionLabel,
|
||||
attachmentsSectionLabel,
|
||||
thumbnailSectionLabel,
|
||||
metadataSectionLabel
|
||||
metadataSectionLabel,
|
||||
showItemLinkButton,
|
||||
itemLinkButtonLabel
|
||||
} = attributes;
|
||||
|
||||
const fontSizes = [
|
||||
|
@ -315,6 +328,26 @@ registerBlockType('tainacan/item-submission-form', {
|
|||
setAttributes({ sentFormMessage: sentFormMessage });
|
||||
} }
|
||||
/>
|
||||
<ToggleControl
|
||||
label={__('Show item link button', 'tainacan') }
|
||||
help={ showItemLinkButton ? __('Do not show a button that links to the item public page.', 'tainacan') : __('Toggle to show a button that links to the item public page.', 'tainacan')}
|
||||
checked={ showItemLinkButton }
|
||||
onChange={ ( isChecked ) => {
|
||||
showItemLinkButton = isChecked;
|
||||
setAttributes({ showItemLinkButton: isChecked });
|
||||
}
|
||||
}
|
||||
/>
|
||||
{ showItemLinkButton ?
|
||||
<TextControl
|
||||
label={ __('Label for the item button', 'tainacan') }
|
||||
value={ itemLinkButtonLabel }
|
||||
onChange={ ( updatedLinkButtonName ) =>{
|
||||
itemLinkButtonLabel = updatedLinkButtonName;
|
||||
setAttributes({ itemLinkButtonLabel: itemLinkButtonLabel });
|
||||
} }
|
||||
/>
|
||||
: null }
|
||||
</PanelBody>
|
||||
</InspectorControls>
|
||||
<InspectorControls>
|
||||
|
@ -809,6 +842,8 @@ registerBlockType('tainacan/item-submission-form', {
|
|||
enabledMetadata,
|
||||
sentFormHeading,
|
||||
sentFormMessage,
|
||||
showItemLinkButton,
|
||||
itemLinkButtonLabel
|
||||
} = attributes;
|
||||
|
||||
return <div
|
||||
|
@ -843,8 +878,11 @@ registerBlockType('tainacan/item-submission-form', {
|
|||
document-section-label={ documentSectionLabel }
|
||||
thumbnail-section-label={ thumbnailSectionLabel }
|
||||
attachments-section-label={ attachmentsSectionLabel }
|
||||
metadata-section-label={ metadataSectionLabel } >
|
||||
metadata-section-label={ metadataSectionLabel }
|
||||
show-item-link-button={ showItemLinkButton ? showItemLinkButton.toString() : 'false' }
|
||||
item-link-button-label={ itemLinkButtonLabel ? itemLinkButtonLabel : __( 'Go to the item page', 'tainacan' ) } >
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
},
|
||||
deprecated: DeprecatedBlocks
|
||||
});
|
|
@ -0,0 +1,196 @@
|
|||
const { __ } = wp.i18n;
|
||||
|
||||
export default [
|
||||
/* Deprecated on Tainacan 0.18, due to the introduction of itemLinkButtonLabel and showItemLinkButton */
|
||||
{
|
||||
attributes: {
|
||||
collectionId: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
isCollectionModalOpen: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hideFileModalButton: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hideTextModalButton: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hideLinkModalButton: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hideThumbnailSection: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hideAttachmentsSection: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hideHelpButtons: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hideMetadataTypes: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showAllowCommentsSection: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hideCollapses: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
backgroundColor: {
|
||||
type: Object,
|
||||
default: { r: 255, g: 255, b: 255, a: 0}
|
||||
},
|
||||
baseFontSize: {
|
||||
type: Number,
|
||||
default: 16
|
||||
},
|
||||
inputColor: {
|
||||
type: String,
|
||||
default: '#1d1d1d'
|
||||
},
|
||||
inputBackgroundColor: {
|
||||
type: String,
|
||||
default: '#ffffff'
|
||||
},
|
||||
inputBorderColor: {
|
||||
type: String,
|
||||
default: '#dbdbdb'
|
||||
},
|
||||
labelColor: {
|
||||
type: String,
|
||||
default: '#454647'
|
||||
},
|
||||
infoColor: {
|
||||
type: String,
|
||||
default: '#555758'
|
||||
},
|
||||
primaryColor: {
|
||||
type: String,
|
||||
default: '#d9eced'
|
||||
},
|
||||
secondaryColor: {
|
||||
type: String,
|
||||
default: '#298596'
|
||||
},
|
||||
enabledMetadata: {
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
collectionMetadata: {
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
isLoadingCollectionMetadata: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
sentFormHeading: {
|
||||
type: String,
|
||||
default: __( 'Form submitted!', 'tainacan' )
|
||||
},
|
||||
sentFormMessage: {
|
||||
type: String,
|
||||
default: __( 'Thank you. Your item was submitted to the collection.', 'tainacan' )
|
||||
},
|
||||
documentSectionLabel: {
|
||||
type: String,
|
||||
default: __( 'Document', 'tainacan' )
|
||||
},
|
||||
attachmentsSectionLabel: {
|
||||
type: String,
|
||||
default: __( 'Attachments', 'tainacan' )
|
||||
},
|
||||
thumbnailSectionLabel: {
|
||||
type: String,
|
||||
default: __( 'Thumbnail', 'tainacan' )
|
||||
},
|
||||
metadataSectionLabel: {
|
||||
type: String,
|
||||
default: __( 'Metadata', 'tainacan' )
|
||||
}
|
||||
},
|
||||
supports: {
|
||||
align: ['full', 'wide'],
|
||||
html: true,
|
||||
multiple: false
|
||||
},
|
||||
save({ attributes, className }){
|
||||
const {
|
||||
collectionId,
|
||||
backgroundColor,
|
||||
hideFileModalButton,
|
||||
hideTextModalButton,
|
||||
hideLinkModalButton,
|
||||
hideThumbnailSection,
|
||||
hideAttachmentsSection,
|
||||
showAllowCommentsSection,
|
||||
hideHelpButtons,
|
||||
hideMetadataTypes,
|
||||
hideCollapses,
|
||||
documentSectionLabel,
|
||||
thumbnailSectionLabel,
|
||||
attachmentsSectionLabel,
|
||||
metadataSectionLabel,
|
||||
baseFontSize,
|
||||
inputColor,
|
||||
inputBackgroundColor,
|
||||
inputBorderColor,
|
||||
labelColor,
|
||||
infoColor,
|
||||
primaryColor,
|
||||
secondaryColor,
|
||||
enabledMetadata,
|
||||
sentFormHeading,
|
||||
sentFormMessage,
|
||||
} = attributes;
|
||||
|
||||
return <div
|
||||
style={{
|
||||
'font-size': baseFontSize + 'px',
|
||||
'--tainacan-base-font-size': baseFontSize + 'px',
|
||||
'--tainacan-background-color': 'rgba(' + backgroundColor.r + ',' + backgroundColor.g + ',' + backgroundColor.b + ',' + backgroundColor.a + ')',
|
||||
'--tainacan-input-color': inputColor,
|
||||
'--tainacan-input-background-color': inputBackgroundColor,
|
||||
'--tainacan-input-border-color': inputBorderColor,
|
||||
'--tainacan-label-color': labelColor,
|
||||
'--tainacan-info-color': infoColor,
|
||||
'--tainacan-primary': primaryColor,
|
||||
'--tainacan-secondary': secondaryColor
|
||||
}}
|
||||
className={ className }>
|
||||
<div
|
||||
id="tainacan-item-submission-form"
|
||||
collection-id={ collectionId }
|
||||
hide-file-modal-button={ hideFileModalButton.toString() }
|
||||
hide-text-modal-button={ hideTextModalButton.toString() }
|
||||
hide-link-modal-button={ hideLinkModalButton.toString() }
|
||||
hide-thumbnail-section={ hideThumbnailSection.toString() }
|
||||
hide-attachments-section={ hideAttachmentsSection.toString() }
|
||||
show-allow-comments-section={ showAllowCommentsSection.toString() }
|
||||
hide-help-buttons={ hideHelpButtons.toString() }
|
||||
hide-metadata-types={ hideMetadataTypes.toString() }
|
||||
hide-collapses={ hideCollapses.toString() }
|
||||
enabled-metadata={ enabledMetadata.toString() }
|
||||
sent-form-heading={ sentFormHeading }
|
||||
sent-form-message={ sentFormMessage }
|
||||
document-section-label={ documentSectionLabel }
|
||||
thumbnail-section-label={ thumbnailSectionLabel }
|
||||
attachments-section-label={ attachmentsSectionLabel }
|
||||
metadata-section-label={ metadataSectionLabel } >
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
]
|
|
@ -8,7 +8,7 @@ const { InspectorControls, BlockControls } = ( tainacan_blocks.wp_version < '5.2
|
|||
|
||||
import TainacanBlocksCompatToolbar from '../../js/tainacan-blocks-compat-toolbar.js';
|
||||
import ItemsModal from './items-modal.js';
|
||||
import DeprecatedBlocks from './items-list-deprecated.js'
|
||||
import DeprecatedBlocks from './items-list-deprecated.js';
|
||||
|
||||
registerBlockType('tainacan/items-list', {
|
||||
title: __('Tainacan Items List', 'tainacan'),
|
||||
|
|
|
@ -17,7 +17,10 @@
|
|||
:document-section-label="$root.documentSectionLabel"
|
||||
:thumbnail-section-label="$root.thumbnailSectionLabel"
|
||||
:attachments-section-label="$root.attachmentsSectionLabel"
|
||||
:metadata-section-label="$root.metadataSectionLabel" />
|
||||
:metadata-section-label="$root.metadataSectionLabel"
|
||||
:show-item-link-button="$root.showItemLinkButton"
|
||||
:item-link-button-label="$root.itemLinkButtonLabel"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
|
@ -117,7 +117,9 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||
documentSectionLabel: '',
|
||||
thumbnailSectionLabel: '',
|
||||
attachmentsSectionLabel: '',
|
||||
metadataSectionLabel: ''
|
||||
metadataSectionLabel: '',
|
||||
showItemLinkButton: false,
|
||||
itemLinkButtonLabel: ''
|
||||
},
|
||||
beforeMount () {
|
||||
// Collection source settings
|
||||
|
@ -159,7 +161,11 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||
this.sentFormHeading = this.$el.attributes['sent-form-heading'].value;
|
||||
if (this.$el.attributes['sent-form-message'] != undefined)
|
||||
this.sentFormMessage = this.$el.attributes['sent-form-message'].value;
|
||||
|
||||
if (this.$el.attributes['item-link-button-label'] != undefined)
|
||||
this.itemLinkButtonLabel = this.$el.attributes['item-link-button-label'].value;
|
||||
if (this.$el.attributes['show-item-link-button'] != undefined)
|
||||
this.showItemLinkButton = this.isParameterTrue('show-item-link-button');
|
||||
|
||||
// List of metadata
|
||||
if (this.$el.attributes['enabled-metadata'] != undefined && this.$el.attributes['enabled-metadata'].value)
|
||||
this.enabledMetadata = this.$el.attributes['enabled-metadata'].value.split(',');
|
||||
|
|
|
@ -403,6 +403,14 @@
|
|||
</p>
|
||||
<h2 v-if="sentFormHeading">{{ sentFormHeading }}</h2>
|
||||
<p v-if="sentFormMessage">{{ sentFormMessage }}</p>
|
||||
<p v-if="showItemLinkButton && linkToCreatedItem">
|
||||
<a
|
||||
style="text-decoration: none"
|
||||
:href="linkToCreatedItem"
|
||||
class="button is-secondary">
|
||||
{{ itemLinkButtonLabel }}
|
||||
</a>
|
||||
</p>
|
||||
<br>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -453,6 +461,8 @@ export default {
|
|||
thumbnailSectionLabel: String,
|
||||
attachmentsSectionLabel: String,
|
||||
metadataSectionLabel: String,
|
||||
showItemLinkButton: Boolean,
|
||||
itemLinkButtonLabel: String
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
|
@ -475,7 +485,8 @@ export default {
|
|||
showThumbnailInput: false,
|
||||
couldLoadCollection: true,
|
||||
useCaptcha: 'no',
|
||||
captchaSiteKey: tainacan_plugin['item_submission_captcha_site_key']
|
||||
captchaSiteKey: tainacan_plugin['item_submission_captcha_site_key'],
|
||||
linkToCreatedItem: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -600,9 +611,11 @@ export default {
|
|||
|
||||
if (fakeItemId) {
|
||||
this.finishItemSubmission({ itemSubmission: this.itemSubmission, fakeItemId: fakeItemId })
|
||||
.then(() => {
|
||||
.then((item) => {
|
||||
this.hasSentForm = true;
|
||||
this.isUploading = false;
|
||||
|
||||
this.linkToCreatedItem = item.url;
|
||||
})
|
||||
.catch((errors) => {
|
||||
if (errors.errors) {
|
||||
|
|
|
@ -0,0 +1,348 @@
|
|||
<template>
|
||||
<div>
|
||||
<div
|
||||
:class="{ 'skeleton': isFetchingData || !chartData || isBuildingChart }"
|
||||
class="postbox">
|
||||
<div
|
||||
v-if="currentStart && currentEnd"
|
||||
class="box-header">
|
||||
<div class="box-header__item tablenav-pages">
|
||||
<label for="start_year">
|
||||
{{ $i18n.get('label_activities_during_year') }}
|
||||
</label>
|
||||
<span class="pagination-links">
|
||||
<span
|
||||
@click="(!isBuildingChart && currentStart.getFullYear() > (minYear + 1)) ? decreaseYear() : null"
|
||||
:class="{'tablenav-pages-navspan disabled' : isBuildingChart || currentStart.getFullYear() <= (minYear + 1) }"
|
||||
class="prev-page button"
|
||||
aria-hidden="true">
|
||||
‹
|
||||
</span>
|
||||
<select
|
||||
name="start_year"
|
||||
id="start_year"
|
||||
:placeholder="$i18n.get('label_select_a_year')"
|
||||
:disabled="isBuildingChart"
|
||||
:value="currentStart.getFullYear()"
|
||||
@input="($event) => setStartYear($event.target.value)">
|
||||
<option
|
||||
v-for="index of (maxYear - minYear)"
|
||||
:key="index"
|
||||
:value="index + minYear">
|
||||
{{ index + minYear }}
|
||||
</option>
|
||||
</select>
|
||||
<span
|
||||
@click="(!isBuildingChart && currentStart.getFullYear() <= (maxYear - 1)) ? increaseYear() : null"
|
||||
:class="{ 'tablenav-pages-navspan disabled': isBuildingChart || currentStart.getFullYear() > (maxYear - 1) }"
|
||||
aria-hidden="true"
|
||||
class="next-page button">
|
||||
›
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="box-header__item">
|
||||
<label>{{ $i18n.get('instruction_filter_activities_date') + ': ' }}</label>
|
||||
<span class="paging-input">
|
||||
{{ currentStart.toDateString() }} - {{ currentEnd.toDateString() }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="!isFetchingData && chartData && !isBuildingChart">
|
||||
<div class="users-charts columns is-multiline">
|
||||
<div
|
||||
class="users-charts__card column is-full"
|
||||
v-for="(chartSeries, index) of chartSeriesByUser"
|
||||
:key="index">
|
||||
<div
|
||||
v-if="chartSeries[0].userId == 0"
|
||||
class="users-charts__card--header">
|
||||
<div class="anonymous-user-avatar" />
|
||||
<div class="users-charts__card--header-text">
|
||||
<p>{{ $i18n.get('label_anonymous_user') }}</p>
|
||||
<span>{{ chartSeries[0].total }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="chartSeries[0].userId != 0 && chartSeries[0].userId"
|
||||
class="users-charts__card--header">
|
||||
<img :src="chartSeries[0].userImg">
|
||||
<div class="users-charts__card--header-text">
|
||||
<p>{{ chartSeries[0].userName }}</p>
|
||||
<span>{{ chartSeries[0].total }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<apexchart
|
||||
type="area"
|
||||
height="140"
|
||||
:series="chartSeries"
|
||||
:options="chartOptionsByUser[index]" />
|
||||
</div>
|
||||
</div>
|
||||
<apexchart
|
||||
type="area"
|
||||
height="200"
|
||||
:series="chartSeries"
|
||||
:options="chartOptions" />
|
||||
|
||||
</template>
|
||||
</div>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { reportsChartMixin } from '../js/reports-mixin';
|
||||
|
||||
export default {
|
||||
mixins: [ reportsChartMixin ],
|
||||
data() {
|
||||
return {
|
||||
chartSeriesByUser: [],
|
||||
chartOptionsByUser: [],
|
||||
maxYear: new Date().getFullYear(),
|
||||
minYear: 2017,
|
||||
currentStart: '',
|
||||
currentEnd: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('report', {
|
||||
areaChartOptions: 'getAreaChartOptions',
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
chartData: {
|
||||
handler() {
|
||||
if (this.chartData && this.chartData.totals)
|
||||
this.buildActivitiesChart();
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
increaseYear() {
|
||||
this.setStartYear(this.currentEnd.getFullYear());
|
||||
},
|
||||
decreaseYear() {
|
||||
let currentStartDate = new Date(this.currentStart.getTime());
|
||||
this.setStartYear(new Date(currentStartDate.setFullYear(currentStartDate.getFullYear() - 1)).getFullYear());
|
||||
},
|
||||
setStartYear(newStartYear) {
|
||||
let currentStartDate = new Date(this.currentStart.getTime());
|
||||
const newStart = new Date(currentStartDate.setFullYear(newStartYear));
|
||||
|
||||
this.$emit('time-range-update', newStart.toISOString());
|
||||
},
|
||||
getDaysArray(start, end) {
|
||||
let everyDay = [];
|
||||
for (let day = new Date(start); day <= end; day.setDate(day.getDate() + 1 ) )
|
||||
everyDay.push(new Date(day));
|
||||
return everyDay;
|
||||
},
|
||||
buildActivitiesChart() {
|
||||
this.isBuildingChart = true;
|
||||
|
||||
const daysWithActivities = (this.chartData.totals.by_interval && this.chartData.totals.by_interval.general) ? this.chartData.totals.by_interval.general : [];
|
||||
this.currentStart = new Date(this.chartData.totals.by_interval.start);
|
||||
this.currentEnd = new Date(this.chartData.totals.by_interval.end);
|
||||
|
||||
if (daysWithActivities.length)
|
||||
this.chartSeries = [{
|
||||
name: this.$i18n.get('activities'),
|
||||
data: []
|
||||
}];
|
||||
else
|
||||
this.chartSeries = [];
|
||||
|
||||
let maximumOfActivitiesInADay = 0;
|
||||
let everyDay = this.getDaysArray(this.currentStart, this.currentEnd);
|
||||
|
||||
everyDay.forEach((aDayInTheLifeTime) => {
|
||||
const aDayWithSomeActivityIndex = daysWithActivities.findIndex(activity => new Date(activity.date).toISOString().slice(0,10) == aDayInTheLifeTime.toISOString().slice(0,10));
|
||||
this.chartSeries[0].data.push({
|
||||
x: aDayInTheLifeTime.getTime(),
|
||||
y: aDayWithSomeActivityIndex >= 0 ? parseInt(daysWithActivities[aDayWithSomeActivityIndex].total) : 0
|
||||
});
|
||||
if (aDayWithSomeActivityIndex >= 0 && maximumOfActivitiesInADay < parseInt(daysWithActivities[aDayWithSomeActivityIndex].total))
|
||||
maximumOfActivitiesInADay = parseInt(daysWithActivities[aDayWithSomeActivityIndex].total);
|
||||
});
|
||||
|
||||
this.chartOptions = {
|
||||
...this.areaChartOptions,
|
||||
title: {
|
||||
text: this.$i18n.get('label_all_users'),
|
||||
style: {
|
||||
fontSize: '13px'
|
||||
}
|
||||
},
|
||||
noData: {
|
||||
text: daysWithActivities.length ? this.$i18n.get('label_loading_report') : this.$i18n.get('info_no_activities')
|
||||
},
|
||||
chart: {
|
||||
id: 'generalchart',
|
||||
height: 200,
|
||||
type: 'area',
|
||||
group: 'activities',
|
||||
toolbar: {
|
||||
show: true,
|
||||
tools: {
|
||||
download: true,
|
||||
selection: false,
|
||||
zoom: true,
|
||||
zoomin: true,
|
||||
zoomout: true,
|
||||
pan: true,
|
||||
}
|
||||
},
|
||||
},
|
||||
xaxis: {
|
||||
type: 'datetime',
|
||||
min: this.currentStart.getTime(),
|
||||
max: this.currentEnd.getTime()
|
||||
},
|
||||
yaxis: {
|
||||
show: daysWithActivities.length,
|
||||
max: maximumOfActivitiesInADay,
|
||||
tickAmount: 4,
|
||||
labels: {
|
||||
minWidth: 48
|
||||
}
|
||||
},
|
||||
colors: ['#01295c'],
|
||||
};
|
||||
const daysWithActivitiesByUser = JSON.parse(JSON.stringify(this.chartData.totals.by_interval.by_user)).sort((a, b) => parseInt(b.total) - parseInt(a.total));
|
||||
|
||||
this.chartSeriesByUser = [];
|
||||
this.chartOptionsByUser = []
|
||||
|
||||
daysWithActivitiesByUser.forEach((daysWithActivityByUser) => {
|
||||
|
||||
let perUserSeries = [];
|
||||
everyDay.forEach((aDayInTheLifeTime) => {
|
||||
const aDayWithSomeActivityIndex = daysWithActivityByUser.by_date.findIndex(activity => new Date(activity.date).toISOString().slice(0,10) == aDayInTheLifeTime.toISOString().slice(0,10));
|
||||
perUserSeries.push({
|
||||
x: aDayInTheLifeTime.getTime(),
|
||||
y: aDayWithSomeActivityIndex >= 0 ? parseInt(daysWithActivityByUser.by_date[aDayWithSomeActivityIndex].total) : 0
|
||||
});
|
||||
});
|
||||
|
||||
this.chartSeriesByUser.push([{
|
||||
total: daysWithActivityByUser.total,
|
||||
userId: daysWithActivityByUser.user_id,
|
||||
userName: daysWithActivityByUser.user.name,
|
||||
userImg: daysWithActivityByUser.user.avatar_urls ? daysWithActivityByUser.user.avatar_urls['48'] : '',
|
||||
name: this.$i18n.get('activities'),
|
||||
data: perUserSeries
|
||||
}]);
|
||||
this.chartOptionsByUser.push({
|
||||
...this.areaChartOptions,
|
||||
title: {
|
||||
text: ''
|
||||
},
|
||||
chart: {
|
||||
id: 'userschart-' + daysWithActivityByUser.user_id,
|
||||
height: 140,
|
||||
type: 'area',
|
||||
group: 'activities',
|
||||
toolbar: {
|
||||
show: true,
|
||||
tools: {
|
||||
download: true,
|
||||
selection: false,
|
||||
zoom: true,
|
||||
zoomin: true,
|
||||
zoomout: true,
|
||||
pan: true,
|
||||
}
|
||||
},
|
||||
},
|
||||
xaxis: {
|
||||
type: 'datetime',
|
||||
min: this.currentStart.getTime(),
|
||||
max: this.currentEnd.getTime()
|
||||
},
|
||||
yaxis: {
|
||||
max: maximumOfActivitiesInADay,
|
||||
tickAmount: 4,
|
||||
labels: {
|
||||
minWidth: 48
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
setTimeout(() => this.isBuildingChart = false, 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.postbox {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
min-height: 280px !important;
|
||||
|
||||
.screen-per-page {
|
||||
width: 6em;
|
||||
}
|
||||
}
|
||||
.users-charts {
|
||||
order: 3;
|
||||
padding: 12px;
|
||||
|
||||
.users-charts__card {
|
||||
padding: 20px !important;
|
||||
|
||||
.users-charts__card--header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 6px 12px 2px 12px;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 26px;
|
||||
|
||||
img,
|
||||
.anonymous-user-avatar {
|
||||
margin-right: 0.75em;
|
||||
border-radius: 2px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background-color: var(--tainacan-gray2, #dbdbdb);
|
||||
}
|
||||
.anonymous-user-avatar:before {
|
||||
content: "?";
|
||||
color: var(--tainacan-gray5, #454647);
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.users-charts__card--header-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
p {
|
||||
font-weight: bold;
|
||||
font-size: 1.0em;
|
||||
margin: 0;
|
||||
max-width: 150px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
span {
|
||||
color: var(--tainacan-secondary, #298596);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,153 @@
|
|||
<template>
|
||||
<div>
|
||||
<div
|
||||
v-if="!isFetchingData && chartData.totals && chartData.totals.by_user && !isBuildingChart"
|
||||
:style="{
|
||||
maxHeight: ((120 + (chartData.totals.by_user.length * 58)) <= 800 ? (120 + (chartData.totals.by_user.length * 58)) : 800) + 'px'
|
||||
}"
|
||||
class="postbox activities-per-user-box">
|
||||
<template v-if="chartData.totals && chartData.totals.by_user">
|
||||
<apexchart
|
||||
:height="120 + (chartData.totals.by_user.length * 58)"
|
||||
:series="chartSeries"
|
||||
:options="chartOptions" />
|
||||
</template>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
style="min-height=800px"
|
||||
class="skeleton postbox activities-per-user-box" />
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { reportsChartMixin } from '../js/reports-mixin';
|
||||
|
||||
export default {
|
||||
mixins: [ reportsChartMixin ],
|
||||
computed: {
|
||||
...mapGetters('report', {
|
||||
horizontalBarChartOptions: 'getHorizontalBarChartOptions',
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
chartData: {
|
||||
handler() {
|
||||
this.buildActivitiesPerUserChart();
|
||||
},
|
||||
immediate: true,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
buildActivitiesPerUserChart() {
|
||||
|
||||
this.isBuildingChart = true;
|
||||
|
||||
if (this.chartData.totals && this.chartData.totals.by_user) {
|
||||
|
||||
// Building Activity Per User Bar chart
|
||||
const orderedActivitiesPerUsers = JSON.parse(JSON.stringify(this.chartData.totals.by_user)).sort((a, b) => b.total - a.total );
|
||||
let activityPerUserValues = [];
|
||||
let activityPerUserLabels = [];
|
||||
const userCount = 100 + (this.chartData.totals.by_user.length * 58);
|
||||
const validActions = [
|
||||
"update-metadata-value",
|
||||
"update",
|
||||
"create",
|
||||
"trash",
|
||||
"new-attachment",
|
||||
"update-document",
|
||||
"delete",
|
||||
"delete-attachment",
|
||||
"update-thumbnail"
|
||||
];
|
||||
|
||||
// Create empty series for each possible action
|
||||
validActions.forEach((action) => {
|
||||
activityPerUserValues.push({
|
||||
id: action,
|
||||
name: this.$i18n.get('action_' + action),
|
||||
data: []
|
||||
})
|
||||
});
|
||||
activityPerUserValues.push({
|
||||
id: 'others',
|
||||
name: this.$i18n.get('action_others'),
|
||||
data: []
|
||||
});
|
||||
|
||||
orderedActivitiesPerUsers.forEach(activityPerUser => {
|
||||
activityPerUserLabels.push(activityPerUser.user_id == 0 ? this.$i18n.get('label_anonymous_user') : activityPerUser.user.name);
|
||||
activityPerUserValues.forEach((activity) => {
|
||||
if (activity.id == 'others') {
|
||||
let otherActionsTotal = 0;
|
||||
Object.keys(activityPerUser.by_action).forEach((action) => {
|
||||
if (validActions.indexOf(action) < 0)
|
||||
otherActionsTotal += (activityPerUser.by_action[action] ? activityPerUser.by_action[action] : 0);
|
||||
});
|
||||
activity.data.push(otherActionsTotal);
|
||||
} else {
|
||||
activity.data.push( activityPerUser.by_action[activity.id] ? activityPerUser.by_action[activity.id] : 0 );
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
this.chartSeries = activityPerUserValues;
|
||||
|
||||
this.chartOptions = {
|
||||
...this.horizontalBarChartOptions,
|
||||
...{
|
||||
chart: {
|
||||
type: 'bar',
|
||||
height: userCount,
|
||||
stacked: true,
|
||||
toolbar: {
|
||||
show: true
|
||||
},
|
||||
zoom: {
|
||||
type: 'y',
|
||||
enabled: true,
|
||||
autoScaleYaxis: true,
|
||||
}
|
||||
},
|
||||
title: {
|
||||
text: this.$i18n.get('label_activitiy_per_user')
|
||||
},
|
||||
labels: activityPerUserLabels,
|
||||
yaxis: {
|
||||
title: {
|
||||
text: ''
|
||||
},
|
||||
labels: {
|
||||
maxWidth: 100
|
||||
},
|
||||
tooltip: { enabled: true }
|
||||
},
|
||||
tooltip: {
|
||||
custom: ({ series, seriesIndex, dataPointIndex, w }) => {
|
||||
return '<div class="tainacan-custom-tooltip"><div class="tainacan-custom-tooltip__header">' +
|
||||
(orderedActivitiesPerUsers[dataPointIndex].user_id != 0 ? ('<img src="' + orderedActivitiesPerUsers[dataPointIndex].user.avatar_urls['24'] + '"> ') : '') +
|
||||
"<span><strong>" + w.globals.labels[dataPointIndex] + '</strong></span></div><div class="tainacan-custom-tooltip__body">' +
|
||||
w.globals.seriesNames[seriesIndex] + ": <strong>" +
|
||||
series[seriesIndex][dataPointIndex] +
|
||||
"</strong></div></div>"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => this.isBuildingChart = false, 300);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.postbox.activities-per-user-box {
|
||||
margin: 0.75rem !important;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,105 @@
|
|||
<template>
|
||||
<div>
|
||||
<apexchart
|
||||
v-if="!isBuildingChart && chartData && Object.values(chartData).length"
|
||||
height="380px"
|
||||
class="postbox"
|
||||
:series="chartSeries"
|
||||
:options="chartOptions" />
|
||||
<div
|
||||
v-else
|
||||
style="min-height=380px"
|
||||
class="skeleton postbox" />
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { reportsChartMixin } from '../js/reports-mixin';
|
||||
|
||||
export default {
|
||||
mixins: [ reportsChartMixin ],
|
||||
computed: {
|
||||
...mapGetters('report', {
|
||||
stackedBarChartOptions: 'getStackedBarChartOptions',
|
||||
}),
|
||||
},
|
||||
watch: {
|
||||
chartData: {
|
||||
handler() {
|
||||
this.buildCollectionsList();
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
buildCollectionsList() {
|
||||
|
||||
this.isBuildingChart = true;
|
||||
|
||||
// Building Collections items chart
|
||||
const orderedCollections = Object.values(this.chartData).sort((a, b) => b.items.total - a.items.total);
|
||||
let privateItems = [];
|
||||
let publicItems = [];
|
||||
let trashItems = [];
|
||||
let draftItems = [];
|
||||
let collectionsLabels = [];
|
||||
|
||||
orderedCollections.forEach(collection => {
|
||||
privateItems.push(collection.items.private);
|
||||
publicItems.push(collection.items.publish);
|
||||
draftItems.push(collection.items.draft);
|
||||
trashItems.push(collection.items.trash);
|
||||
collectionsLabels.push(collection.name);
|
||||
});
|
||||
|
||||
this.chartSeries = [
|
||||
{
|
||||
name: this.$i18n.get('status_publish'),
|
||||
data: publicItems
|
||||
},
|
||||
{
|
||||
name: this.$i18n.get('status_private'),
|
||||
data: privateItems
|
||||
},
|
||||
{
|
||||
name: this.$i18n.get('status_draft'),
|
||||
data: draftItems
|
||||
},
|
||||
{
|
||||
name: this.$i18n.get('status_trash'),
|
||||
data: trashItems
|
||||
}
|
||||
];
|
||||
|
||||
this.chartOptions = {
|
||||
...this.stackedBarChartOptions,
|
||||
...{
|
||||
title: {
|
||||
text: this.$i18n.get('label_items_per_collection')
|
||||
},
|
||||
xaxis: {
|
||||
type: 'category',
|
||||
tickPlacement: 'on',
|
||||
categories: collectionsLabels,
|
||||
labels: {
|
||||
show: true,
|
||||
trim: true,
|
||||
hideOverlappingLabels: false
|
||||
},
|
||||
tooltip: { enabled: true }
|
||||
},
|
||||
yaxis: {
|
||||
title: {
|
||||
text: this.$i18n.get('items')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.isBuildingChart = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,243 @@
|
|||
<template>
|
||||
<div v-if="taxonomiesList != undefined">
|
||||
<div
|
||||
:class="{ 'skeleton': isFetchingData || isBuildingChart || isFetchingTaxonomyTerms || !selectedTaxonomy || !selectedTaxonomy.id }"
|
||||
class="postbox">
|
||||
<div class="box-header">
|
||||
<div class="box-header__item">
|
||||
<label
|
||||
v-if="!isFetchingData"
|
||||
for="select_taxonomies">
|
||||
{{ $i18n.get('label_items_per_term_from_taxonomy') }}
|
||||
</label>
|
||||
<select
|
||||
v-if="!isFetchingData"
|
||||
name="select_taxonomies"
|
||||
id="select_taxonomies"
|
||||
:placeholder="$i18n.get('label_select_a_taxonomy')"
|
||||
v-model="selectedTaxonomy">
|
||||
<option
|
||||
v-for="(taxonomy, index) of taxonomiesListArray"
|
||||
:key="index"
|
||||
:value="taxonomy">
|
||||
{{ taxonomy.name + ' (' + taxonomy.total_terms + ' ' + ( taxonomy.total_terms == 1 ? $i18n.get('term') : $i18n.get('terms') ) + ')' }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div
|
||||
v-if="selectedTaxonomy && selectedTaxonomy.id && currentTotalTerms >= 56"
|
||||
class="box-header__item">
|
||||
<label for="max_terms">{{ $i18n.get('label_terms_per_page') }}</label>
|
||||
<input
|
||||
type="number"
|
||||
step="1"
|
||||
min="1"
|
||||
max="999"
|
||||
class="screen-per-page"
|
||||
name="max_terms"
|
||||
id="max_terms"
|
||||
maxlength="3"
|
||||
:disabled="isBuildingChart"
|
||||
v-model.number="maxTermsToDisplay">
|
||||
</div>
|
||||
<div
|
||||
v-if="selectedTaxonomy && selectedTaxonomy.id && currentTotalTerms >= 56"
|
||||
class="box-header__item tablenav-pages">
|
||||
<span class="displaying-num">{{ currentTotalTerms + ' ' + $i18n.get('terms') }}</span>
|
||||
<span class="pagination-links">
|
||||
<span
|
||||
@click="!isBuildingChart ? termsDisplayedPage = 1 : null"
|
||||
:class="{'tablenav-pages-navspan disabled' : termsDisplayedPage <= 1 || isBuildingChart}"
|
||||
class="first-page button"
|
||||
aria-hidden="true">
|
||||
«
|
||||
</span>
|
||||
<span
|
||||
@click="(termsDisplayedPage > 1 && !isBuildingChart) ? termsDisplayedPage-- : null"
|
||||
:class="{'tablenav-pages-navspan disabled' : termsDisplayedPage <= 1 || isBuildingChart}"
|
||||
class="prev-page button"
|
||||
aria-hidden="true">
|
||||
‹
|
||||
</span>
|
||||
<span class="paging-input">
|
||||
<label
|
||||
for="current-page-selector"
|
||||
class="screen-reader-text">
|
||||
{{ $i18n.get('label_current_page') }}
|
||||
</label>
|
||||
<input
|
||||
class="current-page"
|
||||
id="current-page-selector"
|
||||
type="number"
|
||||
step="1"
|
||||
min="1"
|
||||
:disabled="isBuildingChart || maxTermsToDisplay >= currentTotalTerms"
|
||||
:max="Math.ceil(currentTotalTerms/maxTermsToDisplay)"
|
||||
name="paged"
|
||||
v-model.number="termsDisplayedPage"
|
||||
size="1"
|
||||
aria-describedby="table-paging">
|
||||
<span class="tablenav-paging-text"> de <span class="total-pages">{{ Math.ceil(currentTotalTerms/maxTermsToDisplay) }}</span></span>
|
||||
</span>
|
||||
<span
|
||||
@click="(!isBuildingChart && termsDisplayedPage < Math.ceil(currentTotalTerms/maxTermsToDisplay)) ? termsDisplayedPage++ : null"
|
||||
:class="{'tablenav-pages-navspan disabled' : isBuildingChart || termsDisplayedPage >= Math.ceil(currentTotalTerms/maxTermsToDisplay) }"
|
||||
aria-hidden="true"
|
||||
class="next-page button">
|
||||
›
|
||||
</span>
|
||||
<span
|
||||
@click="!isBuildingChart ? termsDisplayedPage = Math.ceil(currentTotalTerms/maxTermsToDisplay) : null"
|
||||
:class="{'tablenav-pages-navspan disabled': isBuildingChart || termsDisplayedPage >= Math.ceil(currentTotalTerms/maxTermsToDisplay) }"
|
||||
class="last-page button"
|
||||
aria-hidden="true">
|
||||
»
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<apexchart
|
||||
v-if="!isFetchingData && !isBuildingChart && !isFetchingTaxonomyTerms && selectedTaxonomy && selectedTaxonomy.id"
|
||||
height="380px"
|
||||
:series="chartSeries"
|
||||
:options="chartOptions" />
|
||||
</div>
|
||||
<div
|
||||
v-if="taxonomyTermsLatestCachedOn"
|
||||
class="box-last-cached-on">
|
||||
<span>{{ $i18n.get('label_report_generated_on') + ': ' + new Date(taxonomyTermsLatestCachedOn).toLocaleString() }}</span>
|
||||
<button
|
||||
@click="loadTaxonomyTerms(true)">
|
||||
<span class="screen-reader-text">
|
||||
{{ $i18n.get('label_get_latest_report') }}
|
||||
</span>
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-updating tainacan-icon-rotate-270" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters } from 'vuex';
|
||||
import { reportsChartMixin } from '../js/reports-mixin';
|
||||
|
||||
export default {
|
||||
mixins: [ reportsChartMixin ],
|
||||
data() {
|
||||
return {
|
||||
isFetchingTaxonomyTerms: false,
|
||||
selectedTaxonomy: {},
|
||||
maxTermsToDisplay: 56,
|
||||
termsDisplayedPage: 1
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('report', {
|
||||
taxonomiesList: 'getTaxonomiesList',
|
||||
stackedBarChartOptions: 'getStackedBarChartOptions',
|
||||
reportsLatestCachedOn: 'getReportsLatestCachedOn'
|
||||
}),
|
||||
taxonomiesListArray() {
|
||||
return this.taxonomiesList && this.taxonomiesList != undefined ? Object.values(this.taxonomiesList) : [];
|
||||
},
|
||||
taxonomyTermsLatestCachedOn() {
|
||||
return this.reportsLatestCachedOn['taxonomy-terms-' + this.selectedTaxonomy.id];
|
||||
},
|
||||
currentTotalTerms() {
|
||||
return Array.isArray(this.chartData) ? this.chartData.length : 0
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
taxonomiesListArray: {
|
||||
handler() {
|
||||
if (this.taxonomiesListArray && this.taxonomiesListArray.length)
|
||||
this.selectedTaxonomy = this.taxonomiesListArray[0];
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
selectedTaxonomy: {
|
||||
handler() {
|
||||
this.termsDisplayedPage = 1;
|
||||
if (this.selectedTaxonomy && this.selectedTaxonomy.id)
|
||||
this.loadTaxonomyTerms();
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
termsDisplayedPage() {
|
||||
this.buildTaxonomyTermsChart();
|
||||
},
|
||||
maxTermsToDisplay() {
|
||||
this.termsDisplayedPage = 1;
|
||||
this.buildTaxonomyTermsChart();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('report', [
|
||||
'fetchTaxonomyTerms'
|
||||
]),
|
||||
buildTaxonomyTermsChart() {
|
||||
|
||||
this.isBuildingChart = true;
|
||||
|
||||
// Building Taxonomy term usage chart
|
||||
let orderedTerms = JSON.parse(JSON.stringify(this.chartData)).sort((a, b) => b.count - a.count);
|
||||
orderedTerms = orderedTerms.slice((this.termsDisplayedPage - 1) * this.maxTermsToDisplay, ((this.termsDisplayedPage - 1) * this.maxTermsToDisplay) + this.maxTermsToDisplay);
|
||||
|
||||
let termsValues = [];
|
||||
let termsLabels = [];
|
||||
|
||||
orderedTerms.forEach(term => {
|
||||
termsValues.push(term.count);
|
||||
termsLabels.push(term.name);
|
||||
});
|
||||
|
||||
this.chartSeries = [
|
||||
{
|
||||
name: this.$i18n.get('label_items_per_term'),
|
||||
data: termsValues
|
||||
}
|
||||
];
|
||||
this.chartOptions = {
|
||||
...this.stackedBarChartOptions,
|
||||
...{
|
||||
title: {},
|
||||
xaxis: {
|
||||
type: 'category',
|
||||
tickPlacement: 'on',
|
||||
categories: termsLabels,
|
||||
labels: {
|
||||
show: true,
|
||||
trim: true,
|
||||
hideOverlappingLabels: false
|
||||
},
|
||||
tooltip: { enabled: true }
|
||||
},
|
||||
yaxis: {
|
||||
title: {
|
||||
text: this.$i18n.get('label_number_of_items')
|
||||
}
|
||||
},
|
||||
animations: {
|
||||
enabled: orderedTerms.length <= 40
|
||||
},
|
||||
colors: ['#01295c'],
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => this.isBuildingChart = false, 500);
|
||||
},
|
||||
loadTaxonomyTerms(force) {
|
||||
this.isFetchingTaxonomyTerms = true;
|
||||
|
||||
this.fetchTaxonomyTerms({ taxonomyId: this.selectedTaxonomy.id, force: force })
|
||||
.then(() => {
|
||||
this.buildTaxonomyTermsChart();
|
||||
this.isFetchingTaxonomyTerms = false;
|
||||
})
|
||||
.catch(() => this.isFetchingTaxonomyTerms = false);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,776 @@
|
|||
<template>
|
||||
<div v-if="metadataList != undefined">
|
||||
<div
|
||||
:class="{ 'skeleton': isFetchingData || isBuildingChart || isFetchingMetadatumTerms || !selectedMetadatum || !selectedMetadatum.id }"
|
||||
class="postbox">
|
||||
<div
|
||||
:style="!isChildColumnCollapsed ? 'margin-left: 0px;' : ''"
|
||||
:class="!isChildColumnCollapsed ? 'columns is-6' : ''">
|
||||
<div :class="!isChildColumnCollapsed ? 'column is-half is-full-tablet' : ''">
|
||||
<div class="box-header">
|
||||
<div
|
||||
v-if="selectedParentTerm.length <= 1"
|
||||
class="box-header__item">
|
||||
<label
|
||||
v-if="!isFetchingData"
|
||||
for="select_metadata_for_terms">
|
||||
{{ $i18n.get('label_items_per_term_from_taxonomy_metadatum') }}
|
||||
</label>
|
||||
<select
|
||||
v-if="!isFetchingData"
|
||||
name="select_metadata_for_terms"
|
||||
id="select_metadata_for_terms"
|
||||
:placeholder="$i18n.get('label_select_a_taxonomy_metadatum')"
|
||||
v-model="selectedMetadatum">
|
||||
<option
|
||||
v-for="(metadatum, index) of metadataListArray"
|
||||
:key="index"
|
||||
:value="metadatum">
|
||||
{{ metadatum.name }}
|
||||
</option>
|
||||
</select>
|
||||
<div class="graph-mode-switch">
|
||||
<button
|
||||
@click="itemsPerTermChartMode = 'bar'"
|
||||
:class="{ 'current': itemsPerTermChartMode == 'bar' }">
|
||||
<span class="screen-reader-text">
|
||||
{{ $i18n.get('label_bar_chart') }}
|
||||
</span>
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-text tainacan-icon-rotate-270" />
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
@click="itemsPerTermChartMode = 'treemap'"
|
||||
:class="{ 'current': itemsPerTermChartMode == 'treemap' }">
|
||||
<span class="screen-reader-text">
|
||||
{{ $i18n.get('label_tree_map') }}
|
||||
</span>
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-viewmasonry tainacan-icon-rotate-270" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="box-header__item"
|
||||
style="display: flex; align-items: baseline;">
|
||||
|
||||
<button
|
||||
class="button button-secondary"
|
||||
@click="backToParentTerm">
|
||||
{{ $i18n.get('label_parent_term') }}
|
||||
</button>
|
||||
<span
|
||||
v-if="!isFetchingMetadatumChildTerms">
|
||||
{{ $i18n.get('label_items_per_child_terms_of') }} <strong>{{ selectedParentTerm[selectedParentTerm.length - 2].label }}</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="selectedMetadatum && selectedMetadatum.id && currentTotalTerms >= 56"
|
||||
class="box-header__item">
|
||||
<label for="max_terms">{{ $i18n.get('label_terms_per_page') }}</label>
|
||||
<input
|
||||
type="number"
|
||||
step="1"
|
||||
min="1"
|
||||
max="999"
|
||||
class="screen-per-page"
|
||||
name="max_terms"
|
||||
id="max_terms"
|
||||
maxlength="3"
|
||||
:disabled="isBuildingChart"
|
||||
v-model.number="maxTermsToDisplay">
|
||||
</div>
|
||||
<div
|
||||
v-if="selectedMetadatum && selectedMetadatum.id && currentTotalTerms >= 56"
|
||||
class="box-header__item tablenav-pages">
|
||||
<span class="displaying-num">{{ currentTotalTerms + ' ' + $i18n.get('terms') }}</span>
|
||||
<span class="pagination-links">
|
||||
<span
|
||||
@click="!isBuildingChart ? termsDisplayedPage = 1 : null"
|
||||
:class="{'tablenav-pages-navspan disabled' : termsDisplayedPage <= 1 || isBuildingChart}"
|
||||
class="first-page button"
|
||||
aria-hidden="true">
|
||||
«
|
||||
</span>
|
||||
<span
|
||||
@click="(termsDisplayedPage > 1 && !isBuildingChart) ? termsDisplayedPage-- : null"
|
||||
:class="{'tablenav-pages-navspan disabled' : termsDisplayedPage <= 1 || isBuildingChart}"
|
||||
class="prev-page button"
|
||||
aria-hidden="true">
|
||||
‹
|
||||
</span>
|
||||
<span class="paging-input">
|
||||
<label
|
||||
for="current-page-selector"
|
||||
class="screen-reader-text">
|
||||
{{ $i18n.get('label_current_page') }}
|
||||
</label>
|
||||
<input
|
||||
class="current-page"
|
||||
id="current-page-selector"
|
||||
type="number"
|
||||
step="1"
|
||||
min="1"
|
||||
:disabled="isBuildingChart || maxTermsToDisplay >= currentTotalTerms"
|
||||
:max="Math.ceil(currentTotalTerms/maxTermsToDisplay)"
|
||||
name="paged"
|
||||
v-model.number="termsDisplayedPage"
|
||||
size="1"
|
||||
aria-describedby="table-paging">
|
||||
<span class="tablenav-paging-text"> {{ $i18n.get('info_of') }} <span class="total-pages">{{ Math.ceil(currentTotalTerms/maxTermsToDisplay) }}</span></span>
|
||||
</span>
|
||||
<span
|
||||
@click="(!isBuildingChart && termsDisplayedPage < Math.ceil(currentTotalTerms/maxTermsToDisplay)) ? termsDisplayedPage++ : null"
|
||||
:class="{'tablenav-pages-navspan disabled' : isBuildingChart || termsDisplayedPage >= Math.ceil(currentTotalTerms/maxTermsToDisplay) }"
|
||||
aria-hidden="true"
|
||||
class="next-page button">
|
||||
›
|
||||
</span>
|
||||
<span
|
||||
@click="!isBuildingChart ? termsDisplayedPage = Math.ceil(currentTotalTerms/maxTermsToDisplay) : null"
|
||||
:class="{'tablenav-pages-navspan disabled': isBuildingChart || termsDisplayedPage >= Math.ceil(currentTotalTerms/maxTermsToDisplay) }"
|
||||
class="last-page button"
|
||||
aria-hidden="true">
|
||||
»
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<apexchart
|
||||
v-if="!isFetchingData && !isBuildingChart && !isFetchingMetadatumTerms && selectedMetadatum && selectedMetadatum.id"
|
||||
height="380px"
|
||||
:series="chartSeries"
|
||||
:options="chartOptions" />
|
||||
<button
|
||||
v-if=" !isFetchingData && !isFetchingMetadatumTerms && selectedMetadatum"
|
||||
@click="isChildColumnCollapsed = !isChildColumnCollapsed"
|
||||
class="button-secondary hide-column-button">
|
||||
<span class="icon">
|
||||
<i
|
||||
:class="isChildColumnCollapsed ? 'tainacan-icon-arrowleft' : 'tainacan-icon-arrowright'"
|
||||
class="tainacan-icon tainacan-icon-1-25em" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
v-if="!isChildColumnCollapsed && !isFetchingData && !isFetchingMetadatumTerms && selectedMetadatum"
|
||||
class="child-term-column column is-half is-full-tablet">
|
||||
<div v-if="selectedParentTerm[selectedParentTerm.length - 1]">
|
||||
<div class="box-header">
|
||||
<div class="box-header__item">
|
||||
<span
|
||||
v-if="!isFetchingMetadatumChildTerms">
|
||||
{{ $i18n.get('label_items_per_child_terms_of') }} <strong>{{ selectedParentTerm[selectedParentTerm.length - 1].label }}</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="currentTotalChildTerms >= 56"
|
||||
class="box-header__item">
|
||||
<label for="max_terms">{{ $i18n.get('label_terms_per_page') }}</label>
|
||||
<input
|
||||
type="number"
|
||||
step="1"
|
||||
min="1"
|
||||
max="999"
|
||||
class="screen-per-page"
|
||||
name="max_terms"
|
||||
id="max_terms"
|
||||
maxlength="3"
|
||||
:disabled="isBuildingChildrenChart"
|
||||
v-model.number="maxChildTermsToDisplay">
|
||||
</div>
|
||||
<div
|
||||
v-if="currentTotalChildTerms >= 56"
|
||||
class="box-header__item tablenav-pages">
|
||||
<span class="displaying-num">{{ currentTotalChildTerms + ' ' + $i18n.get('terms') }}</span>
|
||||
<span class="pagination-links">
|
||||
<span
|
||||
@click="!isBuildingChildrenChart ? childTermsDisplayedPage = 1 : null"
|
||||
:class="{'tablenav-pages-navspan disabled' : childTermsDisplayedPage <= 1 || isBuildingChildrenChart}"
|
||||
class="first-page button"
|
||||
aria-hidden="true">
|
||||
«
|
||||
</span>
|
||||
<span
|
||||
@click="(childTermsDisplayedPage > 1 && !isBuildingChildrenChart) ? childTermsDisplayedPage-- : null"
|
||||
:class="{'tablenav-pages-navspan disabled' : childTermsDisplayedPage <= 1 || isBuildingChildrenChart}"
|
||||
class="prev-page button"
|
||||
aria-hidden="true">
|
||||
‹
|
||||
</span>
|
||||
<span class="paging-input">
|
||||
<label
|
||||
for="current-page-selector"
|
||||
class="screen-reader-text">
|
||||
{{ $i18n.get('label_current_page') }}
|
||||
</label>
|
||||
<input
|
||||
class="current-page"
|
||||
id="current-page-selector"
|
||||
type="number"
|
||||
step="1"
|
||||
min="1"
|
||||
:disabled="isBuildingChildrenChart || maxChildTermsToDisplay >= currentTotalChildTerms"
|
||||
:max="Math.ceil(currentTotalChildTerms/maxChildTermsToDisplay)"
|
||||
name="paged"
|
||||
v-model.number="childTermsDisplayedPage"
|
||||
size="1"
|
||||
aria-describedby="table-paging">
|
||||
<span class="tablenav-paging-text"> {{ $i18n.get('info_of') }} <span class="total-pages">{{ Math.ceil(currentTotalChildTerms/maxChildTermsToDisplay) }}</span></span>
|
||||
</span>
|
||||
<span
|
||||
@click="(!isBuildingChildrenChart && childTermsDisplayedPage < Math.ceil(currentTotalChildTerms/maxChildTermsToDisplay)) ? childTermsDisplayedPage++ : null"
|
||||
:class="{'tablenav-pages-navspan disabled' : isBuildingChildrenChart || childTermsDisplayedPage >= Math.ceil(currentTotalChildTerms/maxChildTermsToDisplay) }"
|
||||
aria-hidden="true"
|
||||
class="next-page button">
|
||||
›
|
||||
</span>
|
||||
<span
|
||||
@click="!isBuildingChildrenChart ? childTermsDisplayedPage = Math.ceil(currentTotalChildTerms/maxChildTermsToDisplay) : null"
|
||||
:class="{'tablenav-pages-navspan disabled': isBuildingChildrenChart || childTermsDisplayedPage >= Math.ceil(currentTotalChildTerms/maxChildTermsToDisplay) }"
|
||||
class="last-page button"
|
||||
aria-hidden="true">
|
||||
»
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<apexchart
|
||||
v-if="!isBuildingChildrenChart && !isFetchingMetadatumChildTerms"
|
||||
height="380px"
|
||||
:series="childrenChartSeries"
|
||||
:options="childrenChartOptions" />
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="child-term-placeholder">
|
||||
<p class="title is-4">
|
||||
<span class="icon has-text-gray">
|
||||
<i class="tainacan-icon tainacan-icon-taxonomies tainacan-icon-1-125em" />
|
||||
</span>
|
||||
{{ $i18n.get('label_children_terms') }}
|
||||
</p>
|
||||
<br>
|
||||
<p class="subtitle is-6">{{ $i18n.get('info_child_terms_chart') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="metadatumTermsLatestCachedOn"
|
||||
style="left: calc(1px + 0.75rem); right: auto;"
|
||||
class="box-last-cached-on">
|
||||
<span>{{ $i18n.get('label_report_generated_on') + ': ' + new Date(metadatumTermsLatestCachedOn).toLocaleString() }}</span>
|
||||
<button @click="loadMetadatumTerms(true)">
|
||||
<span class="screen-reader-text">
|
||||
{{ $i18n.get('label_get_latest_report') }}
|
||||
</span>
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-updating tainacan-icon-rotate-270" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
v-if="!isChildColumnCollapsed && !isFetchingData && !isFetchingMetadatumTerms && selectedMetadatum && metadatumChildTermsLatestCachedOn"
|
||||
class="box-last-cached-on">
|
||||
<span>{{ $i18n.get('label_report_generated_on') + ': ' + new Date(metadatumChildTermsLatestCachedOn).toLocaleString() }}</span>
|
||||
<button
|
||||
@click="loadMetadatumChildTerms(true)">
|
||||
<span class="screen-reader-text">
|
||||
{{ $i18n.get('label_get_latest_report') }}
|
||||
</span>
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-updating tainacan-icon-rotate-270" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapMutations, mapGetters } from 'vuex';
|
||||
import { reportsChartMixin } from '../js/reports-mixin';
|
||||
|
||||
export default {
|
||||
mixins: [ reportsChartMixin ],
|
||||
props: {
|
||||
collectionId: ''
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isFetchingMetadatumTerms: false,
|
||||
selectedMetadatum: {},
|
||||
maxTermsToDisplay: 56,
|
||||
termsDisplayedPage: 1,
|
||||
selectedParentTerm: [],
|
||||
isFetchingMetadatumChildTerms: false,
|
||||
isBuildingChildrenChart: false,
|
||||
childrenChartSeries: [],
|
||||
childrenChartOptions: {},
|
||||
maxChildTermsToDisplay: 56,
|
||||
childTermsDisplayedPage: 1,
|
||||
isChildColumnCollapsed: false,
|
||||
itemsPerTermChartMode: 'bar'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('report', {
|
||||
metadataList: 'getMetadataList',
|
||||
taxonomyTerms: 'getTaxonomyTerms',
|
||||
taxonomyChildTerms: 'getTaxonomyChildTerms',
|
||||
stackedBarChartOptions: 'getStackedBarChartOptions',
|
||||
treeMapChartOptions: 'getTreeMapChartOptions',
|
||||
reportsLatestCachedOn: 'getReportsLatestCachedOn'
|
||||
}),
|
||||
metadataListArray() {
|
||||
return this.metadataList && Array.isArray(this.metadataList) ? this.metadataList : [];
|
||||
},
|
||||
metadatumTermsLatestCachedOn() {
|
||||
return this.reportsLatestCachedOn['taxonomy-terms-' + (this.collectionId ? this.collectionId : 'default') + '-' + this.selectedMetadatum.id + (this.selectedParentTerm.length > 2 && this.selectedParentTerm[this.selectedParentTerm.length - 2] && this.selectedParentTerm[this.selectedParentTerm.length - 2].id ? '-' + this.selectedParentTerm[this.selectedParentTerm.length - 1].id : '')];
|
||||
},
|
||||
metadatumChildTermsLatestCachedOn() {
|
||||
return this.reportsLatestCachedOn['taxonomy-terms-' + (this.collectionId ? this.collectionId : 'default') + '-' + this.selectedMetadatum.id + (this.selectedParentTerm[this.selectedParentTerm.length - 1] && this.selectedParentTerm[this.selectedParentTerm.length - 1].id ? '-' + this.selectedParentTerm[this.selectedParentTerm.length - 1].id : '') + '-is-child-chart'];
|
||||
},
|
||||
currentTotalTerms() {
|
||||
return Array.isArray(this.taxonomyTerms) ? this.taxonomyTerms.length : 0
|
||||
},
|
||||
currentTotalChildTerms() {
|
||||
return Array.isArray(this.taxonomyChildTerms) ? this.taxonomyChildTerms.length : 0
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
metadataListArray: {
|
||||
handler() {
|
||||
if (this.metadataListArray && this.metadataListArray.length)
|
||||
this.selectedMetadatum = this.metadataListArray[0];
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
selectedMetadatum: {
|
||||
handler() {
|
||||
this.termsDisplayedPage = 1;
|
||||
if (this.selectedMetadatum && this.selectedMetadatum.id) {
|
||||
this.selectedParentTerm = [];
|
||||
this.loadMetadatumTerms();
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
termsDisplayedPage() {
|
||||
this.buildMetadatumTermsChart();
|
||||
},
|
||||
maxTermsToDisplay() {
|
||||
this.termsDisplayedPage = 1;
|
||||
this.buildMetadatumTermsChart();
|
||||
},
|
||||
selectedParentTerm() {
|
||||
if (this.selectedParentTerm[this.selectedParentTerm.length - 1] && this.selectedParentTerm[this.selectedParentTerm.length - 1].id) {
|
||||
this.loadMetadatumChildTerms();
|
||||
}
|
||||
},
|
||||
itemsPerTermChartMode() {
|
||||
this.termsDisplayedPage = 1;
|
||||
this.loadMetadatumTerms();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions('report', [
|
||||
'fetchTaxonomyTerms'
|
||||
]),
|
||||
...mapMutations('report', [
|
||||
'setTaxonomyTerms',
|
||||
'setReportLatestCachedOn'
|
||||
]),
|
||||
...mapActions('metadata', [
|
||||
'fetchMetadata'
|
||||
]),
|
||||
buildMetadatumTermsChart() {
|
||||
this.isBuildingChart = true;
|
||||
|
||||
// Building Taxonomy term usage chart
|
||||
let orderedTerms = JSON.parse(JSON.stringify(this.taxonomyTerms)).sort((a, b) => b.total_items - a.total_items );
|
||||
orderedTerms = orderedTerms.slice((this.termsDisplayedPage - 1) * this.maxTermsToDisplay, ((this.termsDisplayedPage - 1) * this.maxTermsToDisplay) + this.maxTermsToDisplay);
|
||||
|
||||
if (this.itemsPerTermChartMode == 'treemap') {
|
||||
this.chartSeries = [
|
||||
{
|
||||
name: this.$i18n.get('label_items_per_term'),
|
||||
data: orderedTerms.map((aTerm) => { return {
|
||||
x: aTerm.label,
|
||||
y: aTerm.total_items
|
||||
} })
|
||||
}
|
||||
];
|
||||
this.chartOptions = {
|
||||
...this.treeMapChartOptions,
|
||||
...{
|
||||
title: {},
|
||||
chart: {
|
||||
type: 'treemap',
|
||||
height: 350,
|
||||
toolbar: {
|
||||
show: true
|
||||
},
|
||||
zoom: {
|
||||
enabled: false
|
||||
},
|
||||
events: {
|
||||
dataPointSelection: (event, chartContext, config) => {
|
||||
if (config.dataPointIndex >= 0 && orderedTerms[config.dataPointIndex]) {
|
||||
this.selectedParentTerm.push({
|
||||
id: orderedTerms[config.dataPointIndex].value,
|
||||
label: orderedTerms[config.dataPointIndex].label
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
formatter: function(text, op) {
|
||||
return [text, op.value]
|
||||
},
|
||||
offsetY: -4
|
||||
},
|
||||
tooltip: {
|
||||
custom: ({ dataPointIndex }) => {
|
||||
return `<div class="tainacan-custom-tooltip">
|
||||
<div class="tainacan-custom-tooltip__header">` + orderedTerms[dataPointIndex].label + `</div>
|
||||
<div class="tainacan-custom-tooltip__body">
|
||||
<span>` + this.$i18n.get('label_items_per_term') + `: <strong>` + orderedTerms[dataPointIndex].total_items + `</strong></span>
|
||||
`+ (orderedTerms[dataPointIndex].total_children
|
||||
? (`<span>` + this.$i18n.getWithVariables(orderedTerms[dataPointIndex].total_children > 1 ? 'instruction_click_to_see_%s_child_terms' : 'instruction_click_to_see_%s_child_term', [ orderedTerms[dataPointIndex].total_children ]) + `</span>`)
|
||||
: ``
|
||||
) +
|
||||
`</div></div>`;
|
||||
}
|
||||
},
|
||||
noData: {
|
||||
text: '0 ' + this.$i18n.get('label_items_with_this_metadum_value')
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
let termsValues = [];
|
||||
let termsLabels = [];
|
||||
|
||||
orderedTerms.forEach(term => {
|
||||
termsValues.push(term.total_items);
|
||||
termsLabels.push(term.label);
|
||||
});
|
||||
|
||||
this.chartSeries = [
|
||||
{
|
||||
name: this.$i18n.get('label_items_per_term'),
|
||||
data: termsValues
|
||||
}
|
||||
];
|
||||
this.chartOptions = {
|
||||
...this.stackedBarChartOptions,
|
||||
...{
|
||||
title: {},
|
||||
xaxis: {
|
||||
type: 'category',
|
||||
tickPlacement: 'on',
|
||||
categories: termsLabels,
|
||||
labels: {
|
||||
show: true,
|
||||
trim: true,
|
||||
hideOverlappingLabels: false
|
||||
},
|
||||
tooltip: { enabled: true }
|
||||
},
|
||||
chart: {
|
||||
type: 'bar',
|
||||
height: 350,
|
||||
stacked: true,
|
||||
toolbar: {
|
||||
show: true
|
||||
},
|
||||
zoom: {
|
||||
enabled: true,
|
||||
autoScaleYaxis: true,
|
||||
},
|
||||
events: {
|
||||
dataPointSelection: (event, chartContext, config) => {
|
||||
if (config.dataPointIndex >=0 && orderedTerms[config.dataPointIndex]) {
|
||||
this.selectedParentTerm.push({
|
||||
id: orderedTerms[config.dataPointIndex].value,
|
||||
label: orderedTerms[config.dataPointIndex].label
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
custom: ({ dataPointIndex }) => {
|
||||
return `<div class="tainacan-custom-tooltip">
|
||||
<div class="tainacan-custom-tooltip__header">` + orderedTerms[dataPointIndex].label + `</div>
|
||||
<div class="tainacan-custom-tooltip__body">
|
||||
<span>` + this.$i18n.get('label_items_per_term') + `: <strong>` + orderedTerms[dataPointIndex].total_items + `</strong></span>
|
||||
`+ (orderedTerms[dataPointIndex].total_children
|
||||
? (`<span>` + this.$i18n.getWithVariables(orderedTerms[dataPointIndex].total_children > 1 ? 'instruction_click_to_see_%s_child_terms' : 'instruction_click_to_see_%s_child_term', [ orderedTerms[dataPointIndex].total_children ]) + `</span>`)
|
||||
: ``
|
||||
) +
|
||||
`</div></div>`;
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
title: {
|
||||
text: this.$i18n.get('label_number_of_items')
|
||||
}
|
||||
},
|
||||
animations: {
|
||||
enabled: orderedTerms.length <= 40
|
||||
},
|
||||
noData: {
|
||||
text: '0 ' + this.$i18n.get('label_items_with_this_metadum_value')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => this.isBuildingChart = false, 500);
|
||||
},
|
||||
buildMetadatumChildTermsChart() {
|
||||
|
||||
this.isBuildingChildrenChart = true;
|
||||
|
||||
// Building Taxonomy term usage chart
|
||||
let orderedTerms = JSON.parse(JSON.stringify(this.taxonomyChildTerms)).sort((a, b) => b.total_items - a.total_items );
|
||||
orderedTerms = orderedTerms.slice((this.termsDisplayedPage - 1) * this.maxTermsToDisplay, ((this.termsDisplayedPage - 1) * this.maxTermsToDisplay) + this.maxTermsToDisplay);
|
||||
|
||||
if (this.itemsPerTermChartMode == 'treemap') {
|
||||
this.childrenChartSeries = [
|
||||
{
|
||||
name: this.$i18n.get('label_items_per_term'),
|
||||
data: orderedTerms.map((aTerm) => { return {
|
||||
x: aTerm.label,
|
||||
y: aTerm.total_items
|
||||
} })
|
||||
}
|
||||
];
|
||||
this.childrenChartOptions = {
|
||||
...this.treeMapChartOptions,
|
||||
...{
|
||||
title: {},
|
||||
chart: {
|
||||
type: 'treemap',
|
||||
height: 350,
|
||||
toolbar: {
|
||||
show: true
|
||||
},
|
||||
zoom: {
|
||||
enabled: false
|
||||
},
|
||||
events: {
|
||||
dataPointSelection: (event, chartContext, config) => {
|
||||
if (config.dataPointIndex >= 0 && orderedTerms[config.dataPointIndex]) {
|
||||
const previousMetadatumChildTermsLatestCachedOn = this.metadatumChildTermsLatestCachedOn ? this.metadatumChildTermsLatestCachedOn.replace('-is-child-chart', '') : '';
|
||||
this.selectedParentTerm.push({
|
||||
id: orderedTerms[config.dataPointIndex].value,
|
||||
label: orderedTerms[config.dataPointIndex].label
|
||||
});
|
||||
|
||||
this.setTaxonomyTerms(this.taxonomyChildTerms);
|
||||
this.setReportLatestCachedOn({
|
||||
report: 'taxonomy-terms-' + (this.collectionId ? this.collectionId : 'default') + '-' + this.selectedMetadatum.id + (this.selectedParentTerm.length > 2 && this.selectedParentTerm[this.selectedParentTerm.length - 2] && this.selectedParentTerm[this.selectedParentTerm.length - 2].id ? '-' + this.selectedParentTerm[this.selectedParentTerm.length - 1].id : ''),
|
||||
reportLatestCachedOn: previousMetadatumChildTermsLatestCachedOn
|
||||
});
|
||||
this.buildMetadatumTermsChart();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
formatter: function(text, op) {
|
||||
return [text, op.value]
|
||||
},
|
||||
offsetY: -4
|
||||
},
|
||||
tooltip: {
|
||||
custom: ({ dataPointIndex }) => {
|
||||
return `<div class="tainacan-custom-tooltip">
|
||||
<div class="tainacan-custom-tooltip__header">` + orderedTerms[dataPointIndex].label + `</div>
|
||||
<div class="tainacan-custom-tooltip__body">
|
||||
<span>` + this.$i18n.get('label_items_per_term') + `: <strong>` + orderedTerms[dataPointIndex].total_items + `</strong></span>
|
||||
`+ (orderedTerms[dataPointIndex].total_children
|
||||
? (`<span>` + this.$i18n.getWithVariables(orderedTerms[dataPointIndex].total_children > 1 ? 'instruction_click_to_see_%s_child_terms' : 'instruction_click_to_see_%s_child_term', [ orderedTerms[dataPointIndex].total_children ]) + `</span>`)
|
||||
: ``
|
||||
) +
|
||||
`</div></div>`;
|
||||
}
|
||||
},
|
||||
noData: {
|
||||
text: '0 ' + this.$i18n.get('label_items_with_this_metadum_value')
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
let termsValues = [];
|
||||
let termsLabels = [];
|
||||
|
||||
orderedTerms.forEach(term => {
|
||||
termsValues.push(term.total_items);
|
||||
termsLabels.push(term.label);
|
||||
});
|
||||
|
||||
this.childrenChartSeries = [
|
||||
{
|
||||
name: this.$i18n.get('label_items_per_term'),
|
||||
data: termsValues
|
||||
}
|
||||
];
|
||||
this.childrenChartOptions = {
|
||||
...this.stackedBarChartOptions,
|
||||
...{
|
||||
title: {},
|
||||
xaxis: {
|
||||
type: 'category',
|
||||
tickPlacement: 'on',
|
||||
categories: termsLabels,
|
||||
labels: {
|
||||
show: true,
|
||||
trim: true,
|
||||
hideOverlappingLabels: false
|
||||
},
|
||||
tooltip: { enabled: true }
|
||||
},
|
||||
chart: {
|
||||
type: 'bar',
|
||||
height: 350,
|
||||
stacked: true,
|
||||
toolbar: {
|
||||
show: true
|
||||
},
|
||||
zoom: {
|
||||
enabled: true,
|
||||
autoScaleYaxis: true,
|
||||
},
|
||||
events: {
|
||||
dataPointSelection: (event, chartContext, config) => {
|
||||
if (config.dataPointIndex >= 0 && orderedTerms[config.dataPointIndex]) {
|
||||
const previousMetadatumChildTermsLatestCachedOn = this.metadatumChildTermsLatestCachedOn ? this.metadatumChildTermsLatestCachedOn.replace('-is-child-chart', '') : '';
|
||||
this.selectedParentTerm.push({
|
||||
id: orderedTerms[config.dataPointIndex].value,
|
||||
label: orderedTerms[config.dataPointIndex].label
|
||||
});
|
||||
|
||||
this.setTaxonomyTerms(this.taxonomyChildTerms);
|
||||
this.setReportLatestCachedOn({
|
||||
report: 'taxonomy-terms-' + (this.collectionId ? this.collectionId : 'default') + '-' + this.selectedMetadatum.id + (this.selectedParentTerm.length > 2 && this.selectedParentTerm[this.selectedParentTerm.length - 2] && this.selectedParentTerm[this.selectedParentTerm.length - 2].id ? '-' + this.selectedParentTerm[this.selectedParentTerm.length - 1].id : ''),
|
||||
reportLatestCachedOn: previousMetadatumChildTermsLatestCachedOn
|
||||
});
|
||||
this.buildMetadatumTermsChart();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
yaxis: {
|
||||
title: {
|
||||
text: this.$i18n.get('label_number_of_items')
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
custom: ({ dataPointIndex }) => {
|
||||
return `<div class="tainacan-custom-tooltip">
|
||||
<div class="tainacan-custom-tooltip__header">` + orderedTerms[dataPointIndex].label + `</div>
|
||||
<div class="tainacan-custom-tooltip__body">
|
||||
<span>` + this.$i18n.get('label_items_per_term') + `: <strong>` + orderedTerms[dataPointIndex].total_items + `</strong></span>
|
||||
`+ (orderedTerms[dataPointIndex].total_children
|
||||
? (`<span>` + this.$i18n.getWithVariables(orderedTerms[dataPointIndex].total_children > 1 ? 'instruction_click_to_see_%s_child_terms' : 'instruction_click_to_see_%s_child_term', [ orderedTerms[dataPointIndex].total_children ]) + `</span>`)
|
||||
: ``
|
||||
) +
|
||||
`</div></div>`;
|
||||
}
|
||||
},
|
||||
animations: {
|
||||
enabled: orderedTerms.length <= 40
|
||||
},
|
||||
noData: {
|
||||
text: this.$i18n.get('label_items_with_this_metadum_value')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => this.isBuildingChildrenChart = false, 500);
|
||||
},
|
||||
loadMetadatumTerms(force) {
|
||||
this.isFetchingMetadatumTerms = true;
|
||||
|
||||
this.fetchTaxonomyTerms({
|
||||
taxonomyId: this.selectedMetadatum.id,
|
||||
collectionId: this.collectionId,
|
||||
parentTerm: this.selectedParentTerm.length > 1 ? this.selectedParentTerm[this.selectedParentTerm.length - 2].id : null,
|
||||
force: force
|
||||
})
|
||||
.then(() => {
|
||||
this.buildMetadatumTermsChart();
|
||||
this.isFetchingMetadatumTerms = false;
|
||||
})
|
||||
.catch(() => this.isFetchingMetadatumTerms = false);
|
||||
},
|
||||
loadMetadatumChildTerms(force) {
|
||||
this.isFetchingMetadatumChildTerms = true;
|
||||
|
||||
this.fetchTaxonomyTerms({
|
||||
taxonomyId: this.selectedMetadatum.id,
|
||||
collectionId: this.collectionId,
|
||||
parentTerm: this.selectedParentTerm[this.selectedParentTerm.length - 1].id,
|
||||
isChildChart: true,
|
||||
force: force
|
||||
})
|
||||
.then(() => {
|
||||
this.buildMetadatumChildTermsChart();
|
||||
this.isFetchingMetadatumChildTerms = false;
|
||||
})
|
||||
.catch(() => this.isFetchingMetadatumChildTerms = false);
|
||||
},
|
||||
backToParentTerm() {
|
||||
this.selectedParentTerm.pop();
|
||||
this.loadMetadatumTerms();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.child-term-column {
|
||||
border-left: 1px dashed var(--tainacan-block-gray3, #cbcbcb);
|
||||
|
||||
&>* {
|
||||
margin-left: 1.25rem;
|
||||
}
|
||||
}
|
||||
.hide-column-button {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: calc(50% - 1rem);
|
||||
margin: 0;
|
||||
margin-right: -0.875rem;
|
||||
padding: 0px;
|
||||
border: 1px solid;
|
||||
background-color: white;
|
||||
z-index: 9;
|
||||
}
|
||||
.child-term-placeholder {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 1rem;
|
||||
min-height: 380px;
|
||||
flex-direction: column;
|
||||
opacity: 0.75;
|
||||
|
||||
p {
|
||||
color: var(--tainacan-block-gray4, #555758);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,147 @@
|
|||
<template>
|
||||
<div>
|
||||
<div
|
||||
v-if="!isFetchingData && chartData.totals && chartData.totals.metadata && !isBuildingChart"
|
||||
:style="{
|
||||
maxHeight: ((170 + (chartData.totals.metadata.total * 36)) <= 690 ? (170 + (chartData.totals.metadata.total * 36)) : 690) + 'px'
|
||||
}"
|
||||
class="postbox metadata-distribution-box">
|
||||
<apexchart
|
||||
:height="100 + (chartData.totals.metadata.total * 36)"
|
||||
:series="chartSeries"
|
||||
:options="chartOptions" />
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
style="min-height=740px"
|
||||
class="skeleton postbox metadata-distribution-box" />
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { reportsChartMixin } from '../js/reports-mixin';
|
||||
|
||||
export default {
|
||||
mixins: [ reportsChartMixin ],
|
||||
computed: {
|
||||
...mapGetters('report', {
|
||||
horizontalBarChartOptions: 'getHorizontalBarChartOptions',
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
chartData: {
|
||||
handler() {
|
||||
this.buildMetadataDistributionChart();
|
||||
},
|
||||
immediate: true,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
buildMetadataDistributionChart() {
|
||||
this.isBuildingChart = true;
|
||||
|
||||
if (this.chartData.distribution) {
|
||||
// Building Metadata Distribution Bar chart
|
||||
const orderedMetadataDistributions = Object.values(this.chartData.distribution).sort((a, b) => b.fill_percentage - a.fill_percentage );
|
||||
let metadataDistributionValues = [];
|
||||
let metadataDistributionValuesInverted = [];
|
||||
let metadataDistributionLabels = [];
|
||||
const metadataCount = 100 + (this.chartData.totals.metadata.total * 36);
|
||||
|
||||
orderedMetadataDistributions.forEach(metadataDistribution => {
|
||||
metadataDistributionValues.push(parseFloat(metadataDistribution.fill_percentage));
|
||||
metadataDistributionValuesInverted.push(100.0000 - parseFloat(metadataDistribution.fill_percentage).toFixed(4));
|
||||
metadataDistributionLabels.push(metadataDistribution.name);
|
||||
})
|
||||
|
||||
// Sets first metadatum as the selected one
|
||||
if (orderedMetadataDistributions.length)
|
||||
this.selectedMetadatum = orderedMetadataDistributions[0].id;
|
||||
|
||||
this.chartSeries = [
|
||||
{
|
||||
name: this.$i18n.get('label_filled'),
|
||||
data: metadataDistributionValues
|
||||
},
|
||||
{
|
||||
name: this.$i18n.get('label_not_filled'),
|
||||
data: metadataDistributionValuesInverted
|
||||
}
|
||||
];
|
||||
this.chartOptions = {
|
||||
...this.horizontalBarChartOptions,
|
||||
...{
|
||||
chart: {
|
||||
type: 'bar',
|
||||
height: metadataCount,
|
||||
stacked: true,
|
||||
stackType: '100%',
|
||||
toolbar: {
|
||||
show: true
|
||||
},
|
||||
zoom: {
|
||||
type: 'y',
|
||||
enabled: true,
|
||||
autoScaleYaxis: true,
|
||||
}
|
||||
},
|
||||
title: {
|
||||
text: this.$i18n.get('label_metadata_fill_distribution')
|
||||
},
|
||||
labels: metadataDistributionLabels,
|
||||
tooltip: {
|
||||
y: {
|
||||
formatter: (val) => val + "%"
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
title: {
|
||||
text: ''
|
||||
},
|
||||
labels: {
|
||||
maxWidth: 100
|
||||
},
|
||||
tooltip: { enabled: true }
|
||||
},
|
||||
colors: ['#298596', '#dbdbdb'],
|
||||
fill: {
|
||||
colors: ['#298596', '#dbdbdb']
|
||||
},
|
||||
dataLabels: {
|
||||
style: {
|
||||
colors: ['#ffffff', '#454647']
|
||||
}
|
||||
},
|
||||
states: {
|
||||
normal: {
|
||||
filter: {
|
||||
type: 'none',
|
||||
value: 0,
|
||||
}
|
||||
},
|
||||
hover: {
|
||||
filter: {
|
||||
type: 'darken',
|
||||
value: 0.85,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => this.isBuildingChart = false, 300);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.postbox.metadata-distribution-box {
|
||||
margin: 0px 0px 0.75rem 1.5rem !important;
|
||||
padding-bottom: 2rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,132 @@
|
|||
<template>
|
||||
<div>
|
||||
<div
|
||||
v-if="!isFetchingData && chartData && chartData.totals && chartData.totals.metadata_per_type && !isBuildingChart"
|
||||
class="postbox">
|
||||
<label>{{ $i18n.get('metadata_types') }} </label>
|
||||
<div class="graph-mode-switch">
|
||||
<button
|
||||
@click="metadataTypeChartMode = 'bar'"
|
||||
:class="{ 'current': metadataTypeChartMode == 'bar' }">
|
||||
<span class="screen-reader-text">
|
||||
{{ $i18n.get('label_bar_chart') }}
|
||||
</span>
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-text tainacan-icon-rotate-270" />
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
@click="metadataTypeChartMode = 'circle'"
|
||||
:class="{ 'current': metadataTypeChartMode == 'circle' }">
|
||||
<span class="screen-reader-text">
|
||||
{{ $i18n.get('label_pie_chart') }}
|
||||
</span>
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-waiting tainacan-icon-rotate-270" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<apexchart
|
||||
height="380px"
|
||||
:series="chartSeries"
|
||||
:options="chartOptions" />
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
style="min-height=380px"
|
||||
class="skeleton postbox" />
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { reportsChartMixin } from '../js/reports-mixin';
|
||||
|
||||
export default {
|
||||
mixins: [ reportsChartMixin ],
|
||||
data() {
|
||||
return {
|
||||
metadataTypeChartMode: 'bar'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('report', {
|
||||
donutChartOptions: 'getDonutChartOptions',
|
||||
stackedBarChartOptions: 'getStackedBarChartOptions',
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
metadataTypeChartMode() {
|
||||
this.buildMetadataTypeChart();
|
||||
},
|
||||
chartData: {
|
||||
handler() {
|
||||
if (this.chartData && this.chartData.totals)
|
||||
this.buildMetadataTypeChart();
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
buildMetadataTypeChart() {
|
||||
|
||||
this.isBuildingChart = true;
|
||||
|
||||
// Building Metadata Type Donut Chart
|
||||
let metadataTypeValues = [];
|
||||
let metadataTypeLabels = [];
|
||||
|
||||
const orderedMetadataPerType = Object.values(this.chartData.totals.metadata_per_type).sort((a, b) => b.count - a.count);
|
||||
orderedMetadataPerType.forEach((metadataPerType) => {
|
||||
metadataTypeValues.push(metadataPerType.count ? metadataPerType.count : 0);
|
||||
metadataTypeLabels.push(metadataPerType.name ? metadataPerType.name : '');
|
||||
});
|
||||
|
||||
this.chartSeries = this.metadataTypeChartMode == 'circle' ? metadataTypeValues : [ { name: this.$i18n.get('label_amount_of_metadata_of_type'), data: metadataTypeValues } ];
|
||||
|
||||
if (this.metadataTypeChartMode == 'circle') {
|
||||
this.chartOptions = JSON.parse(JSON.stringify({
|
||||
...this.donutChartOptions,
|
||||
...{
|
||||
title: {},
|
||||
labels: metadataTypeLabels,
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
this.chartOptions = JSON.parse(JSON.stringify({
|
||||
...this.stackedBarChartOptions,
|
||||
...{
|
||||
chart: {
|
||||
type: 'bar',
|
||||
height: 350,
|
||||
stacked: false,
|
||||
toolbar: {
|
||||
show: true
|
||||
},
|
||||
zoom: {
|
||||
enabled: true,
|
||||
autoScaleYaxis: true,
|
||||
}
|
||||
},
|
||||
title: {},
|
||||
xaxis: {
|
||||
type: 'category',
|
||||
tickPlacement: 'on',
|
||||
categories: metadataTypeLabels,
|
||||
labels: {
|
||||
show: true,
|
||||
trim: true,
|
||||
hideOverlappingLabels: false
|
||||
},
|
||||
tooltip: { enabled: true }
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
setTimeout(() => { this.isBuildingChart = false; }, 500);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,103 @@
|
|||
<template>
|
||||
<div class="number-block">
|
||||
<p class="title is-2">
|
||||
<i-count-up
|
||||
:delay="750"
|
||||
:end-val="total"
|
||||
:options="{ separator: ' ' }" />
|
||||
</p>
|
||||
<p class="subtitle is-3">
|
||||
<span class="icon has-text-gray">
|
||||
<i
|
||||
class="tainacan-icon tainacan-icon-1-125em"
|
||||
:class="'tainacan-icon-' + entityType" />
|
||||
</span>
|
||||
{{ $i18n.get(entityType) }}
|
||||
</p>
|
||||
<p
|
||||
v-if="summary.totals && summary.totals[entityType] && entityType == 'taxonomies'"
|
||||
class="subtitle is-6">
|
||||
{{ $i18n.get('label_used') + ': ' + summary.totals[entityType].used + ' | ' + $i18n.get('label_not_used') + ': ' + summary.totals[entityType].not_used }}
|
||||
</p>
|
||||
<ul class="has-text-gray status-list">
|
||||
<li
|
||||
v-for="(statusOption, index) of $statusHelper.getStatuses()"
|
||||
:key="index"
|
||||
v-if="(statusOption.slug != 'private' || (statusOption.slug == 'private' && $userCaps.hasCapability('tnc_rep_read_private_collections')) && totalByStatus[statusOption.slug])">
|
||||
<span class="value">
|
||||
<i-count-up
|
||||
:delay="750"
|
||||
:end-val="totalByStatus[statusOption.slug]"
|
||||
:options="{ separator: ' ' }" />
|
||||
|
||||
</span>
|
||||
<span
|
||||
v-if="$statusHelper.hasIcon(statusOption.slug)"
|
||||
class="icon has-text-gray">
|
||||
<i
|
||||
class="tainacan-icon tainacan-icon-1-125em"
|
||||
:class="$statusHelper.getIcon(statusOption.slug)"
|
||||
/>
|
||||
</span>
|
||||
<!-- {{ statusOption.name }} -->
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ICountUp from 'vue-countup-v2';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ICountUp
|
||||
},
|
||||
props: {
|
||||
entityType: String,
|
||||
summary: Object
|
||||
},
|
||||
computed: {
|
||||
total() {
|
||||
return this.summary && this.summary.totals && this.summary.totals[this.entityType] && this.summary.totals[this.entityType].total ? this.summary.totals[this.entityType].total : 0;
|
||||
},
|
||||
totalByStatus() {
|
||||
return {
|
||||
'publish': this.summary && this.summary.totals && this.summary.totals[this.entityType] && this.summary.totals[this.entityType].publish ? this.summary.totals[this.entityType].publish : 0,
|
||||
'private': this.summary && this.summary.totals && this.summary.totals[this.entityType] && this.summary.totals[this.entityType].private ? this.summary.totals[this.entityType].private : 0,
|
||||
'draft': this.summary && this.summary.totals && this.summary.totals[this.entityType] && this.summary.totals[this.entityType].draft ? this.summary.totals[this.entityType].draft : 0,
|
||||
'trash': this.summary && this.summary.totals && this.summary.totals[this.entityType] && this.summary.totals[this.entityType].trash ? this.summary.totals[this.entityType].trash : 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.number-block {
|
||||
min-height: 210px !important;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
|
||||
.title {
|
||||
margin-top: 0.25em;
|
||||
}
|
||||
.subtitle {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
.subtitle.is-6 {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.status-list {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
font-size: 0.875rem;
|
||||
|
||||
li {
|
||||
margin: 0 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,119 @@
|
|||
<template>
|
||||
<div v-if="chartData != undefined">
|
||||
<apexchart
|
||||
v-if="!isFetchingData && taxonomiesListArray && taxonomiesListArray.length && !isBuildingChart"
|
||||
height="380px"
|
||||
class="postbox"
|
||||
:series="chartSeries"
|
||||
:options="chartOptions" />
|
||||
<div
|
||||
v-else
|
||||
style="min-height=380px"
|
||||
class="skeleton postbox" />
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { reportsChartMixin } from '../js/reports-mixin';
|
||||
|
||||
export default {
|
||||
mixins: [ reportsChartMixin ],
|
||||
computed: {
|
||||
...mapGetters('report', {
|
||||
stackedBarChartOptions: 'getStackedBarChartOptions',
|
||||
}),
|
||||
taxonomiesListArray() {
|
||||
return this.chartData && this.chartData != undefined ? Object.values(this.chartData) : [];
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
taxonomiesListArray: {
|
||||
handler() {
|
||||
this.buildTaxonomiesList();
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
buildTaxonomiesList() {
|
||||
// Building Taxonomy term usage chart
|
||||
this.isBuildingChart = true;
|
||||
|
||||
const orderedTaxonomies = this.taxonomiesListArray.sort((a, b) => b.total_terms - a.total_terms);
|
||||
let termsUsed = [];
|
||||
let termsNotUsed = [];
|
||||
let taxonomiesLabels = [];
|
||||
|
||||
orderedTaxonomies.forEach(taxonomy => {
|
||||
termsUsed.push(taxonomy.total_terms_used);
|
||||
termsNotUsed.push(taxonomy.total_terms_not_used);
|
||||
taxonomiesLabels.push(taxonomy.name);
|
||||
});
|
||||
|
||||
this.chartSeries = [
|
||||
{
|
||||
name: this.$i18n.get('label_terms_used'),
|
||||
data: termsUsed
|
||||
},
|
||||
{
|
||||
name: this.$i18n.get('label_terms_not_used'),
|
||||
data: termsNotUsed
|
||||
}
|
||||
];
|
||||
|
||||
this.chartOptions = {
|
||||
...this.stackedBarChartOptions,
|
||||
...{
|
||||
title: {
|
||||
text: this.$i18n.get('label_usage_of_terms_per_taxonomy')
|
||||
},
|
||||
xaxis: {
|
||||
type: 'category',
|
||||
tickPlacement: 'on',
|
||||
categories: taxonomiesLabels,
|
||||
labels: {
|
||||
show: true,
|
||||
trim: true,
|
||||
hideOverlappingLabels: false
|
||||
},
|
||||
tooltip: { enabled: true }
|
||||
},
|
||||
yaxis: {
|
||||
title: {
|
||||
text: this.$i18n.get('label_number_of_terms')
|
||||
}
|
||||
},
|
||||
colors: ['#298596', '#dbdbdb'],
|
||||
fill: {
|
||||
colors: ['#298596', '#dbdbdb']
|
||||
},
|
||||
dataLabels: {
|
||||
style: {
|
||||
colors: ['#ffffff', '#454647']
|
||||
}
|
||||
},
|
||||
states: {
|
||||
normal: {
|
||||
filter: {
|
||||
type: 'none',
|
||||
value: 0,
|
||||
}
|
||||
},
|
||||
hover: {
|
||||
filter: {
|
||||
type: 'darken',
|
||||
value: 0.9,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => this.isBuildingChart = false, 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,104 @@
|
|||
import Vue from 'vue';
|
||||
import store from '../../admin/js/store/store';
|
||||
import router from './reports-router';
|
||||
import VTooltip from 'v-tooltip';
|
||||
import { Snackbar, Modal } from 'buefy';
|
||||
import VueApexCharts from 'vue-apexcharts';
|
||||
import cssVars from 'css-vars-ponyfill';
|
||||
import {
|
||||
I18NPlugin,
|
||||
UserCapabilitiesPlugin,
|
||||
StatusHelperPlugin,
|
||||
} from '../../admin/js/admin-utilities';
|
||||
|
||||
// Vue Dev Tools!
|
||||
Vue.config.devtools = process && process.env && process.env.NODE_ENV === 'development';
|
||||
|
||||
import ReportsPage from '../reports.vue';
|
||||
import NumberBlock from '../components/number-block.vue';
|
||||
import ItemsPerTermBlock from '../components/items-per-term-block.vue';
|
||||
import ItemsPerTermCollectionBlock from '../components/items-per-term-collection-block.vue';
|
||||
import TermsPerTaxonomyBlock from '../components/terms-per-taxonomy-block.vue';
|
||||
import MetadataTypesBlock from '../components/metadata-types-block.vue';
|
||||
import MetadataDistributionBlock from '../components/metadata-distribution-block.vue';
|
||||
import CollectionsListBlock from '../components/collections-list-block.vue';
|
||||
import ActivitiesBlock from '../components/activities-block.vue';
|
||||
import ActivitiesPerUserBlock from '../components/activities-per-user-block.vue';
|
||||
|
||||
Vue.use(VueApexCharts)
|
||||
|
||||
Apex.colors = [
|
||||
'#298596', // Tainacan Turquoise
|
||||
'#01295c', // Tainacan Blue
|
||||
'#25a189', // Tainacan Green
|
||||
'#e69810', // Tainacan Yellow
|
||||
'#a23939', // Tainacan Red
|
||||
'#592570', // Tainacan Purple
|
||||
'#ed4f63', // Tainacan Pink
|
||||
'#b46659', // Tainacan Brown
|
||||
'#e5721c', // Tainacan Orange
|
||||
'#04a5ff', // Tainacan Other Blue
|
||||
'#454647' // Tainacan Dark Gray
|
||||
];
|
||||
|
||||
Vue.use(I18NPlugin);
|
||||
Vue.use(UserCapabilitiesPlugin);
|
||||
Vue.use(StatusHelperPlugin);
|
||||
Vue.use(VTooltip);
|
||||
Vue.use(Snackbar);
|
||||
Vue.use(Modal);
|
||||
|
||||
Vue.component('number-block', NumberBlock);
|
||||
Vue.component('items-per-term-block', ItemsPerTermBlock);
|
||||
Vue.component('items-per-term-collection-block', ItemsPerTermCollectionBlock);
|
||||
Vue.component('terms-per-taxonomy-block', TermsPerTaxonomyBlock);
|
||||
Vue.component('metadata-types-block', MetadataTypesBlock);
|
||||
Vue.component('metadata-distribution-block', MetadataDistributionBlock);
|
||||
Vue.component('collections-list-block', CollectionsListBlock);
|
||||
Vue.component('activities-block', ActivitiesBlock);
|
||||
Vue.component('activities-per-user-block', ActivitiesPerUserBlock);
|
||||
Vue.component('apexchart', VueApexCharts);
|
||||
|
||||
// Changing title of pages
|
||||
router.beforeEach((to, from, next) => {
|
||||
document.title = to.meta.title;
|
||||
if (next() != undefined)
|
||||
next();
|
||||
});
|
||||
|
||||
new Vue({
|
||||
el: '#tainacan-reports-app',
|
||||
store,
|
||||
router,
|
||||
render: h => h(ReportsPage)
|
||||
});
|
||||
|
||||
listen("load", window, function() {
|
||||
var iconsStyle = document.createElement("style");
|
||||
iconsStyle.setAttribute('type', 'text/css');
|
||||
iconsStyle.innerText = '.tainacan-icon::before{ opacity: 1.0 !important; }';
|
||||
document.head.appendChild(iconsStyle);
|
||||
});
|
||||
|
||||
// Initialize Ponyfill for Custom CSS properties
|
||||
cssVars({
|
||||
// Options...
|
||||
});
|
||||
|
||||
// Display Icons only once everything is loaded
|
||||
function listen(evnt, elem, func) {
|
||||
if (elem.addEventListener) // W3C DOM
|
||||
elem.addEventListener(evnt,func,false);
|
||||
else if (elem.attachEvent) { // IE DOM
|
||||
var r = elem.attachEvent("on"+evnt, func);
|
||||
return r;
|
||||
} else if (document.head) {
|
||||
var iconHideStyle = document.createElement("style");
|
||||
iconHideStyle.innerText = '.tainacan-icon::before{ opacity: 0.0 !important; }';
|
||||
document.head.appendChild(iconHideStyle);
|
||||
} else {
|
||||
var iconHideStyle = document.createElement("style");
|
||||
iconHideStyle.innerText = '.tainacan-icon::before{ opacity: 0.0 !important; }';
|
||||
document.getElementsByTagName("head")[0].appendChild(iconHideStyle);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
export const reportsChartMixin = {
|
||||
props: {
|
||||
chartData: {},
|
||||
isFetchingData: false
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
isBuildingChart: false,
|
||||
chartSeries: [],
|
||||
chartOptions: {}
|
||||
}
|
||||
}
|
||||
};
|
|
@ -0,0 +1,29 @@
|
|||
import Vue from 'vue';
|
||||
import VueRouter from 'vue-router'
|
||||
import qs from 'qs';
|
||||
|
||||
import ReportsList from '../pages/reports-list.vue';
|
||||
|
||||
const { __ } = wp.i18n;
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
const routes = [
|
||||
{ path: '/', redirect:'/reports' },
|
||||
{ path: '/reports', name: 'ReportsList', component: ReportsList, meta: { title: __('Tainacan Reports') } },
|
||||
|
||||
{ path: '*', redirect: '/'}
|
||||
];
|
||||
|
||||
export default new VueRouter ({
|
||||
routes,
|
||||
// set custom query resolver
|
||||
parseQuery(query) {
|
||||
return qs.parse(query);
|
||||
},
|
||||
stringifyQuery(query) {
|
||||
let result = qs.stringify(query);
|
||||
|
||||
return result ? ('?' + result) : '';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,389 @@
|
|||
<template>
|
||||
<div>
|
||||
<h1 class="wp-heading-inline">{{ $route.meta.title }}</h1>
|
||||
<select
|
||||
name="select_collections"
|
||||
id="select_collections"
|
||||
@input="(inputEvent) => $router.push({ query: { collection: inputEvent.target.value } })"
|
||||
:value="selectedCollection">
|
||||
<option value="default">
|
||||
{{ $i18n.get('repository') }}
|
||||
</option>
|
||||
<option
|
||||
v-for="(collection, index) of collections"
|
||||
:key="index"
|
||||
:value="collection.id">
|
||||
{{ collection.name }}
|
||||
</option>
|
||||
</select>
|
||||
<div class="columns is-multiline">
|
||||
<div
|
||||
:class="{ 'is-three-fifths-desktop': !isRepositoryLevel }"
|
||||
style="margin-bottom: 0px;"
|
||||
class="column is-full columns is-multiline">
|
||||
<div
|
||||
v-if="isRepositoryLevel"
|
||||
class="column is-full is-one-third-tablet has-text-centered">
|
||||
<number-block
|
||||
:class="{ 'skeleton': isFetchingSummary }"
|
||||
class="postbox"
|
||||
:summary="summary"
|
||||
entity-type="collections" />
|
||||
<div
|
||||
v-if="summaryLatestCachedOn"
|
||||
class="box-last-cached-on">
|
||||
<span>{{ $i18n.get('label_report_generated_on') + ': ' + new Date(summaryLatestCachedOn).toLocaleString() }}</span>
|
||||
<button
|
||||
@click="loadSummary(true)">
|
||||
<span class="screen-reader-text">
|
||||
{{ $i18n.get('label_get_latest_report') }}
|
||||
</span>
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-updating tainacan-icon-rotate-270" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
:class="{ 'is-one-third-tablet': isRepositoryLevel }"
|
||||
class="column is-full is-half-tablet has-text-centered">
|
||||
<number-block
|
||||
:class="{ 'skeleton': isFetchingSummary }"
|
||||
class="postbox"
|
||||
:summary="summary"
|
||||
entity-type="items"/>
|
||||
<div
|
||||
v-if="summaryLatestCachedOn"
|
||||
class="box-last-cached-on">
|
||||
<span>{{ $i18n.get('label_report_generated_on') + ': ' + new Date(summaryLatestCachedOn).toLocaleString() }}</span>
|
||||
<button
|
||||
@click="loadSummary(true)">
|
||||
<span class="screen-reader-text">
|
||||
{{ $i18n.get('label_get_latest_report') }}
|
||||
</span>
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-updating tainacan-icon-rotate-270" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="isRepositoryLevel"
|
||||
class="column is-full is-one-third-tablet has-text-centered">
|
||||
<number-block
|
||||
:class="{ 'skeleton': isFetchingSummary }"
|
||||
class="postbox"
|
||||
:summary="summary"
|
||||
entity-type="taxonomies" />
|
||||
<div
|
||||
v-if="summaryLatestCachedOn"
|
||||
class="box-last-cached-on">
|
||||
<span>{{ $i18n.get('label_report_generated_on') + ': ' + new Date(summaryLatestCachedOn).toLocaleString() }}</span>
|
||||
<button
|
||||
@click="loadSummary(true)">
|
||||
<span class="screen-reader-text">
|
||||
{{ $i18n.get('label_get_latest_report') }}
|
||||
</span>
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-updating tainacan-icon-rotate-270" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="column is-full is-half-tablet has-text-centered">
|
||||
<number-block
|
||||
:class="{ 'skeleton': isFetchingMetadata }"
|
||||
class="postbox"
|
||||
:summary="metadata"
|
||||
entity-type="metadata" />
|
||||
<div
|
||||
v-if="summaryLatestCachedOn"
|
||||
class="box-last-cached-on">
|
||||
<span>{{ $i18n.get('label_report_generated_on') + ': ' + new Date(summaryLatestCachedOn).toLocaleString() }}</span>
|
||||
<button
|
||||
@click="loadSummary(true)">
|
||||
<span class="screen-reader-text">
|
||||
{{ $i18n.get('label_get_latest_report') }}
|
||||
</span>
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-updating tainacan-icon-rotate-270" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<collections-list-block
|
||||
class="column is-full"
|
||||
:chart-data="collectionsList"
|
||||
:is-fetching-data="isFetchingCollectionsList"
|
||||
v-if="isRepositoryLevel">
|
||||
<div
|
||||
v-if="collectionsLatestCachedOn"
|
||||
class="box-last-cached-on">
|
||||
<span>{{ $i18n.get('label_report_generated_on') + ': ' + new Date(collectionsLatestCachedOn).toLocaleString() }}</span>
|
||||
<button
|
||||
@click="loadCollectionsList(true)">
|
||||
<span class="screen-reader-text">
|
||||
{{ $i18n.get('label_get_latest_report') }}
|
||||
</span>
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-updating tainacan-icon-rotate-270" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</collections-list-block>
|
||||
|
||||
<metadata-types-block
|
||||
class="column is-full"
|
||||
:chart-data="metadata"
|
||||
:is-fetching-data="isFetchingMetadata"
|
||||
v-if="!isRepositoryLevel">
|
||||
<div
|
||||
v-if="metadataLatestCachedOn"
|
||||
class="box-last-cached-on">
|
||||
<span>{{ $i18n.get('label_report_generated_on') + ': ' + new Date(metadataLatestCachedOn).toLocaleString() }}</span>
|
||||
<button
|
||||
@click="loadMetadata(true)">
|
||||
<span class="screen-reader-text">
|
||||
{{ $i18n.get('label_get_latest_report') }}
|
||||
</span>
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-updating tainacan-icon-rotate-270" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</metadata-types-block>
|
||||
|
||||
<terms-per-taxonomy-block
|
||||
class="column is-full"
|
||||
:chart-data="taxonomyList"
|
||||
:is-fetching-data="isFetchingTaxonomiesList"
|
||||
v-if="isRepositoryLevel">
|
||||
<div
|
||||
v-if="taxonomiesLatestCachedOn"
|
||||
class="box-last-cached-on">
|
||||
<span>{{ $i18n.get('label_report_generated_on') + ': ' + new Date(taxonomiesLatestCachedOn).toLocaleString() }}</span>
|
||||
<button
|
||||
@click="loadTaxonomiesList(true)">
|
||||
<span class="screen-reader-text">
|
||||
{{ $i18n.get('label_get_latest_report') }}
|
||||
</span>
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-updating tainacan-icon-rotate-270" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</terms-per-taxonomy-block>
|
||||
</div>
|
||||
<metadata-distribution-block
|
||||
class="column is-full is-two-fifths-desktop"
|
||||
:chart-data="metadata"
|
||||
:is-fetching-data="isFetchingMetadata"
|
||||
v-if="!isRepositoryLevel">
|
||||
<div
|
||||
v-if="metadataLatestCachedOn"
|
||||
class="box-last-cached-on">
|
||||
<span>{{ $i18n.get('label_report_generated_on') + ': ' + new Date(metadataLatestCachedOn).toLocaleString() }}</span>
|
||||
<button
|
||||
@click="loadMetadata(true)">
|
||||
<span class="screen-reader-text">
|
||||
{{ $i18n.get('label_get_latest_report') }}
|
||||
</span>
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-updating tainacan-icon-rotate-270" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</metadata-distribution-block>
|
||||
|
||||
<items-per-term-block
|
||||
v-if="isRepositoryLevel"
|
||||
class="column is-full"
|
||||
:chart-data="taxonomyTerms"
|
||||
:is-fetching-data="isFetchingTaxonomiesList" />
|
||||
<items-per-term-collection-block
|
||||
v-else
|
||||
class="column is-full"
|
||||
:chart-data="taxonomyTerms"
|
||||
:is-fetching-data="isFetchingMetadataList"
|
||||
:collection-id="selectedCollection" />
|
||||
|
||||
<activities-per-user-block
|
||||
class="column is-full is-two-fifths-tablet"
|
||||
:chart-data="activities"
|
||||
:is-fetching-data="isFetchingActivities">
|
||||
<div
|
||||
v-if="activitiesLatestCachedOn"
|
||||
class="box-last-cached-on">
|
||||
<span>{{ $i18n.get('label_report_generated_on') + ': ' + new Date(activitiesLatestCachedOn).toLocaleString() }}</span>
|
||||
<button
|
||||
@click="loadActivities(true)">
|
||||
<span class="screen-reader-text">
|
||||
{{ $i18n.get('label_get_latest_report') }}
|
||||
</span>
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-updating tainacan-icon-rotate-270" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</activities-per-user-block>
|
||||
|
||||
<activities-block
|
||||
class="column is-full is-three-fifths-tablet"
|
||||
:chart-data="activities"
|
||||
:is-fetching-data="isFetchingActivities"
|
||||
@time-range-update="loadActivities">
|
||||
<div
|
||||
v-if="activitiesLatestCachedOn"
|
||||
class="box-last-cached-on">
|
||||
<span>{{ $i18n.get('label_report_generated_on') + ': ' + new Date(activitiesLatestCachedOn).toLocaleString() }}</span>
|
||||
<button
|
||||
@click="loadActivities(true)">
|
||||
<span class="screen-reader-text">
|
||||
{{ $i18n.get('label_get_latest_report') }}
|
||||
</span>
|
||||
<span class="icon">
|
||||
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-updating tainacan-icon-rotate-270" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</activities-block>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters } from 'vuex';
|
||||
|
||||
export default {
|
||||
name: "ReportsList",
|
||||
data() {
|
||||
return {
|
||||
selectedCollection: 'default',
|
||||
isFetchingCollections: false,
|
||||
isFetchingSummary: false,
|
||||
isFetchingCollectionsList: false,
|
||||
isFetchingMetadata: false,
|
||||
isFetchingActivities: false,
|
||||
isFetchingTaxonomiesList: false,
|
||||
activitiesStartDate: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('collection', {
|
||||
collections: 'getCollections',
|
||||
}),
|
||||
...mapGetters('report', {
|
||||
summary: 'getSummary',
|
||||
metadata: 'getMetadata',
|
||||
collectionsList: 'getCollectionsList',
|
||||
metadataList: 'getMetadataList',
|
||||
taxonomyTerms: 'getTaxonomyTerms',
|
||||
activities: 'getActivities',
|
||||
taxonomyList: 'getTaxonomiesList',
|
||||
reportsLatestCachedOn: 'getReportsLatestCachedOn'
|
||||
}),
|
||||
isRepositoryLevel() {
|
||||
return !this.selectedCollection || this.selectedCollection == 'default';
|
||||
},
|
||||
summaryLatestCachedOn() {
|
||||
return this.reportsLatestCachedOn['summary-' + (this.collectionId ? this.collectionId : 'default')];
|
||||
},
|
||||
metadataLatestCachedOn() {
|
||||
return this.reportsLatestCachedOn['metadata-' + (this.collectionId ? this.collectionId : 'default')];
|
||||
},
|
||||
collectionsLatestCachedOn() {
|
||||
return this.reportsLatestCachedOn['collections'];
|
||||
},
|
||||
taxonomiesLatestCachedOn() {
|
||||
return this.reportsLatestCachedOn['taxonomies'];
|
||||
},
|
||||
activitiesLatestCachedOn() {
|
||||
return this.reportsLatestCachedOn['activities-' + (this.collectionId ? this.collectionId : 'default') + (this.activitiesStartDate ? '-' + this.activitiesStartDate : '')];
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$route.query': {
|
||||
handler(to) {
|
||||
this.selectedCollection = to['collection'] ? to['collection'] : 'default';
|
||||
this.loadSummary();
|
||||
this.loadMetadata();
|
||||
this.loadActivities();
|
||||
|
||||
if (this.isRepositoryLevel) {
|
||||
this.loadCollectionsList();
|
||||
this.loadTaxonomiesList();
|
||||
} else {
|
||||
this.loadMetadataList();
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// Obtains colleciton id from query, if passed
|
||||
this.selectedCollection = this.$route.query['collection'] ? this.$route.query['collection'] : 'default';
|
||||
|
||||
// Loads collection for the select input
|
||||
this.loadCollections();
|
||||
},
|
||||
methods: {
|
||||
...mapActions('collection', [
|
||||
'fetchAllCollectionNames'
|
||||
]),
|
||||
...mapActions('report', [
|
||||
'fetchSummary',
|
||||
'fetchCollectionsList',
|
||||
'fetchMetadata',
|
||||
'fetchMetadataList',
|
||||
'fetchTaxonomiesList',
|
||||
'fetchActivities'
|
||||
]),
|
||||
loadCollections() {
|
||||
this.isFetchingCollections = true;
|
||||
this.fetchAllCollectionNames()
|
||||
.then(() => this.isFetchingCollections = false)
|
||||
.catch(() => this.isFetchingCollections = false);
|
||||
},
|
||||
loadSummary(force) {
|
||||
this.isFetchingSummary = true;
|
||||
this.fetchSummary({ collectionId: this.selectedCollection, force: force })
|
||||
.then(() => this.isFetchingSummary = false)
|
||||
.catch(() => this.isFetchingSummary = false);
|
||||
},
|
||||
loadMetadata(force) {
|
||||
this.isFetchingMetadata = true;
|
||||
this.fetchMetadata({ collectionId: this.selectedCollection, force: force })
|
||||
.then(() => this.isFetchingMetadata = false)
|
||||
.catch(() => this.isFetchingMetadata = false);
|
||||
},
|
||||
loadCollectionsList(force) {
|
||||
this.isFetchingCollectionsList = true;
|
||||
this.fetchCollectionsList(force)
|
||||
.then(() => this.isFetchingCollectionsList = false)
|
||||
.catch(() => this.isFetchingCollectionsList = false);
|
||||
},
|
||||
loadTaxonomiesList(force) {
|
||||
this.isFetchingTaxonomiesList = true;
|
||||
this.fetchTaxonomiesList(force)
|
||||
.then(() => this.isFetchingTaxonomiesList = false)
|
||||
.catch(() => this.isFetchingTaxonomiesList = false);
|
||||
},
|
||||
loadMetadataList() {
|
||||
this.isFetchingMetadataList = true;
|
||||
this.fetchMetadataList({ collectionId: this.selectedCollection, onlyTaxonomies: true })
|
||||
.then(() => this.isFetchingMetadataList = false)
|
||||
.catch(() => this.isFetchingMetadataList = false);
|
||||
},
|
||||
loadActivities(startDate) {
|
||||
this.isFetchingActivities = true;
|
||||
this.fetchActivities({ collectionId: this.selectedCollection, startDate: startDate })
|
||||
.then(() => this.isFetchingActivities = false)
|
||||
.catch(() => this.isFetchingActivities = false);
|
||||
this.activitiesStartDate = startDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,27 @@
|
|||
<template>
|
||||
<div
|
||||
id="tainacan-reports-app"
|
||||
class="wrap">
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "ReportsPage",
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
// TAINACAN Variables
|
||||
@import "../admin/scss/_animations.scss";
|
||||
@import "../admin/scss/_variables.scss";
|
||||
|
||||
// Bulma imports
|
||||
@import "./scss/reports-basics.sass";
|
||||
|
||||
.tainacan_page_tainacan_reports #wpbody {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,14 @@
|
|||
@import "../../../../node_modules/bulma/sass/utilities/_all.sass"
|
||||
@import "../../../../node_modules/bulma/sass/helpers/_all.sass"
|
||||
@import "../../../../node_modules/bulma/sass/form/_all.sass"
|
||||
@import "../../../../node_modules/bulma/sass/grid/_all.sass"
|
||||
@import "../../../../node_modules/bulma/sass/components/pagination.sass"
|
||||
@import "../../../../node_modules/bulma/sass/components/card.sass"
|
||||
@import "../../../../node_modules/bulma/sass/elements/icon.sass"
|
||||
@import "../../../../node_modules/bulma/sass/elements/tag.sass"
|
||||
@import "../../../../node_modules/bulma/sass/elements/title.sass"
|
||||
@import "../../../../node_modules/bulma/sass/elements/notification.sass"
|
||||
@import "../../../../node_modules/bulma/sass/components/tabs.sass"
|
||||
@import "../../../../node_modules/bulma/sass/elements/button.sass"
|
||||
@import "../../../../node_modules/bulma/sass/components/dropdown.sass"
|
||||
@import "../../../../node_modules/bulma/sass/components/modal.sass"
|
|
@ -0,0 +1,135 @@
|
|||
#tainacan-reports-app {
|
||||
padding: 10px 2px 10px 2px;
|
||||
margin: 0;
|
||||
|
||||
// Tainacan Loading
|
||||
.tainacan-icon::before {
|
||||
opacity: 0.0; // Will make it 1 once window.load is done;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.wp-heading-inline {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.columns {
|
||||
max-width: 100%;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
|
||||
.column {
|
||||
max-width: 100%;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
box-sizing: content-box;
|
||||
|
||||
.postbox {
|
||||
margin: 0.75rem;
|
||||
}
|
||||
.box-last-cached-on {
|
||||
position: absolute;
|
||||
bottom: calc(1px + 0.75rem);
|
||||
right: calc(1px + 0.75rem);
|
||||
display: inline-block;
|
||||
padding: 0px 10px;
|
||||
background-color: var(--tainacan-block-gray2, #dbdbdb);
|
||||
color: var(--tainacan-block-gray4, #555758);
|
||||
font-size: 0.875em;
|
||||
border-top-left-radius: 3px;
|
||||
opacity: 0.0;
|
||||
transition: opacity 0.3s ease;
|
||||
|
||||
button {
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: var(--wp-admin-theme-color, #007cba);
|
||||
}
|
||||
}
|
||||
}
|
||||
.postbox:hover+.box-last-cached-on,
|
||||
.postbox:hover+.box-last-cached-on+.box-last-cached-on,
|
||||
.box-last-cached-on:hover {
|
||||
opacity: 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.postbox {
|
||||
padding: 1.125rem 1.25rem;
|
||||
margin-bottom: 0;
|
||||
height: 100%;
|
||||
min-height: 380px;
|
||||
background-color: var(--tainacan-block-gray0, #f6f6f6);
|
||||
|
||||
label {
|
||||
font-weight: bold;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.box-header {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.box-header__item {
|
||||
margin-bottom: 10px;
|
||||
line-height: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.graph-mode-switch {
|
||||
display: inline-block;
|
||||
button {
|
||||
border: none !important;
|
||||
background: none !important;
|
||||
box-shadow: none !important;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
|
||||
&.current {
|
||||
color: var(--wp-admin-theme-color, #007cba);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tainacan-custom-tooltip {
|
||||
padding: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
|
||||
.tainacan-custom-tooltip__header {
|
||||
background-color: var(--tainacan-block-gray1, #f2f2f2);
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 6px 10px 4px 10px;
|
||||
}
|
||||
|
||||
.tainacan-custom-tooltip__header+.tainacan-custom-tooltip__body {
|
||||
padding: 4px 10px 6px 10px;
|
||||
}
|
||||
.tainacan-custom-tooltip__body {
|
||||
width: 100%;
|
||||
padding: 6px 10px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
|
||||
p {
|
||||
margin-bottom: 4px;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ return apply_filters( 'tainacan-admin-i18n', [
|
|||
'items' => __( 'Items', 'tainacan' ),
|
||||
/* translators: Plural, a list of metadata */
|
||||
'metadata' => __( 'Metadata', 'tainacan' ),
|
||||
'metadata_types' => __( 'Metadata types', 'tainacan' ),
|
||||
'filters' => __( 'Filters', 'tainacan' ),
|
||||
'taxonomies' => __( 'Taxonomies', 'tainacan' ),
|
||||
'activities' => __( 'Activities', 'tainacan' ),
|
||||
|
@ -194,6 +195,7 @@ return apply_filters( 'tainacan-admin-i18n', [
|
|||
'label_button_delete_thumb' => __( 'Button Delete Thumbnail', 'tainacan' ),
|
||||
'label_collections_per_page' => __( 'Collections per Page:', 'tainacan' ),
|
||||
'label_taxonomies_per_page' => __( 'Taxonomies per Page:', 'tainacan' ),
|
||||
'label_terms_per_page' => __( 'Terms per Page:', 'tainacan' ),
|
||||
'label_activities_per_page' => __( 'Activities per Page:', 'tainacan' ),
|
||||
'label_items_per_page' => __( 'Items per Page:', 'tainacan' ),
|
||||
'label_attachments_per_page' => __( 'Attachments per Page:', 'tainacan' ),
|
||||
|
@ -536,10 +538,42 @@ return apply_filters( 'tainacan-admin-i18n', [
|
|||
'label_switch_document_type' => __( 'Switch document type', 'tainacan' ),
|
||||
'label_sending_form' => __( 'Sending form...', 'tainacan' ),
|
||||
'label_form_not_loaded' => __( 'This form could not be loaded', 'tainacan' ),
|
||||
'label_terms_not_used' => __( 'Terms not used', 'tainacan' ),
|
||||
'label_terms_used' => __( 'Terms used', 'tainacan' ),
|
||||
'label_number_of_terms' => __( 'Number of terms', 'tainacan' ),
|
||||
'label_number_of_items' => __( 'Number of items', 'tainacan' ),
|
||||
'label_usage_of_terms_per_taxonomy' => __( 'Usage of terms per taxonomy', 'tainacan' ),
|
||||
'label_items_per_term' => __( 'Items per term', 'tainacan' ),
|
||||
'label_items_per_term_from_taxonomy' => __( 'Items per term from taxonomy:', 'tainacan' ),
|
||||
'label_items_per_term_from_taxonomy_metadatum' => __( 'Items per term from taxonomy metadatum:', 'tainacan' ),
|
||||
'label_items_per_child_terms_of' => __( 'Items per child terms of:', 'tainacan' ),
|
||||
'label_items_per_collection' => __( 'Items per collection', 'tainacan' ),
|
||||
'label_loading_report' => __( 'Loading report...', 'tainacan' ),
|
||||
'label_metadata_fill_distribution' => __( 'Metadata fill distribution', 'tainacan' ),
|
||||
'label_not_filled' => __( 'Not filled yet', 'tainacan' ),
|
||||
'label_filled' => __( 'Already filled', 'tainacan' ),
|
||||
/* translators: To be displayed with the number of Taxonomies not used in the colllection */
|
||||
'label_not_used' => __( 'Not used', 'tainacan' ),
|
||||
/* translators: To be displayed with the number of Taxonomies used in the colllection */
|
||||
'label_select_a_taxonomy' => __( 'Select a taxonomy', 'tainacan' ),
|
||||
'label_used' => __( 'Used', 'tainacan' ),
|
||||
'label_select_a_taxonomy_metadatum' => __( 'Select a taxonomy metadatum', 'tainacan' ),
|
||||
'label_items_with_this_metadum_value' => __( 'Items with this metadatum value', 'tainacan' ),
|
||||
'label_amount_of_items_per_metadatum_value' => __( 'Amount of items per metadatum value', 'tainacan' ),
|
||||
'label_activities_during_year' => __( 'Activities during the year', 'tainacan' ),
|
||||
'label_compact_list' => __( 'Compact list', 'tainacan'),
|
||||
'label_detailed_list' => __( 'Detailed list', 'tainacan'),
|
||||
'label_view_metadata_details' => __( 'View metadata details', 'tainacan'),
|
||||
'label_filter_by_metadata_type' => __( 'Filter by metadatum type', 'tainacan'),
|
||||
'label_pie_chart' => __( 'Pie chart', 'tainacan'),
|
||||
'label_bar_chart' => __( 'Bar chart', 'tainacan'),
|
||||
'label_terms_per_page' => __( 'Terms per page', 'tainacan'),
|
||||
'label_anonymous_user' => __( 'Anonymous User', 'tainacan'),
|
||||
'label_select_a_year' => __( 'Select a year', 'tainacan'),
|
||||
'label_all_users' => __( 'All users', 'tainacan'),
|
||||
'label_activitiy_per_user' => __( 'Activities per user', 'tainacan'),
|
||||
'label_report_generated_on' => __( 'Report generated on', 'tainacan'),
|
||||
'label_get_latest_report' => __( 'Get latest report', 'tainacan'),
|
||||
'label_decrease' => __( 'Decrease', 'tainacan'),
|
||||
'label_increase' => __( 'Increase', 'tainacan'),
|
||||
|
||||
|
@ -602,7 +636,9 @@ return apply_filters( 'tainacan-admin-i18n', [
|
|||
'instruction_click_error_to_go_to_metadata' => __( 'Click on the error to go to the metadata:', 'tainacan'),
|
||||
'instruction_click_to_see_or_search' => __( 'Click to see options or type to search...', 'tainacan'),
|
||||
'instruction_select_one_or_more_collections' => __( 'Select one or more collections', 'tainacan'),
|
||||
'instruction_thumbnail_alt' => __( 'Type here a descriptive text for the image thumbnail...', 'tainacan'),
|
||||
'instruction_thumbnail_alt' => __( 'Type here a descriptive text for the image thumbnail...', 'tainacan'),
|
||||
'instruction_click_to_see_%s_child_terms' => __( 'Click to see %s child terms', 'tainacan'),
|
||||
'instruction_click_to_see_%s_child_term' => __( 'Click to see %s child term', 'tainacan'),
|
||||
|
||||
// Info. Other feedback to user.
|
||||
'info_items_tab_all' => __( 'Every published item, including those visible only to editors.', 'tainacan' ),
|
||||
|
@ -708,7 +744,7 @@ return apply_filters( 'tainacan-admin-i18n', [
|
|||
'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_activities' => __( 'No activities yet.', 'tainacan' ),
|
||||
'info_no_activities' => __( 'No activities found.', 'tainacan' ),
|
||||
'info_logs_before' => __( 'Before', 'tainacan' ),
|
||||
'info_logs_after' => __( 'After', 'tainacan' ),
|
||||
'info_there_is_no_metadatum' => __( 'There is no metadata here yet.', 'tainacan' ),
|
||||
|
@ -821,6 +857,23 @@ return apply_filters( 'tainacan-admin-i18n', [
|
|||
'info_recaptcha_link_%s' => __( 'Remember to configure your website reCAPTCHA keys on <a href="%s" target="_blank">the item submission repository page</a>.', 'tainacan'),
|
||||
'info_form_not_loaded' => __( 'There are probably not enought permissions to display it here.', 'tainacan'),
|
||||
'info_validating_slug' => __( 'Validating slug...', 'tainacan'),
|
||||
|
||||
'label_amount_of_metadata_of_type' => __( 'Amount of metadata of this type', 'tainacan'),
|
||||
'info_child_terms_chart' => __( 'Click on the term bar on the chart aside to see its child terms (if any) in this panel', 'tainacan' ),
|
||||
|
||||
/* Activity actions */
|
||||
'action_update-metadata-value' => __( 'Item Metadata Value Updates', 'tainacan'),
|
||||
'action_update' => __( 'General Updates', 'tainacan'),
|
||||
'action_create' => __( 'General Creations', 'tainacan'),
|
||||
'action_update-metadata-order' => __( 'Metadata Order Updates', 'tainacan'),
|
||||
'action_trash' => __( 'Trashing', 'tainacan'),
|
||||
'action_new-attachment' => __( 'Addition of Attachments', 'tainacan'),
|
||||
'action_update-filters-order' => __( 'Filter Order Updates', 'tainacan'),
|
||||
'action_update-document' => __( 'Document Updates', 'tainacan'),
|
||||
'action_delete' => __( 'General Deletions', 'tainacan'),
|
||||
'action_delete-attachment' => __( 'Deletion of Attachments', 'tainacan'),
|
||||
'action_update-thumbnail' => __( 'Thumbnail Updates', 'tainacan'),
|
||||
'action_others' => __( 'Other Actions', 'tainacan'),
|
||||
'info_applied_filters' => __( 'filters applied', 'tainacan'),
|
||||
'info_items_found' => __( 'items found', 'tainacan'),
|
||||
'info_applied_filter' => __( 'filter applied', 'tainacan'),
|
||||
|
|
|
@ -8,6 +8,7 @@ module.exports = {
|
|||
theme_search: './src/views/theme-search/js/theme-main.js',
|
||||
item_submission: './src/views/item-submission/js/item-submission-main.js',
|
||||
roles: './src/views/roles/js/roles-main.js',
|
||||
reports: './src/views/reports/js/reports-main.js',
|
||||
|
||||
block_terms_list: './src/views/gutenberg-blocks/tainacan-terms/terms-list/index.js',
|
||||
|
||||
|
|
Loading…
Reference in New Issue