@papaemmelab/isabl-web 0.3.14 → 0.3.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,8 +20,7 @@ Contributions are welcome, and they are greatly appreciated, check our [contribu
20
20
 
21
21
  ## Development
22
22
 
23
- # Using node v13.13.0 and npm 6.14.4
24
-
23
+ nvm use v13.13.0 # Using node v13.13.0 and npm 6.14.4
25
24
  yarn install # install node dependencies
26
25
  yarn serve # run development server
27
26
  yarn test:unit # run unit tests
@@ -42,5 +41,3 @@ Isabl was created at [Elli Papaemmanuil's lab].
42
41
  [prettier_badge]: https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square
43
42
  [prettier_base]: https://github.com/prettier/prettier
44
43
  [Elli Papaemmanuil's lab]: https://www.mskcc.org/research-areas/labs/elli-papaemmanuilil
45
-
46
-
@@ -89268,7 +89268,7 @@ exports = module.exports = __webpack_require__("2350")(false);
89268
89268
 
89269
89269
 
89270
89270
  // module
89271
- exports.push([module.i, ".isabl-base-card .v-data-table th.column.sortable.active.desc button.sort-icon{-webkit-transform:rotate(-180deg);transform:rotate(-180deg)}.isabl-base-card .v-data-table th.column.sortable.active button.sort-icon{color:var(--v-primary-base)}.isabl-base-card .v-data-table th.column.sortable button{font-size:13px!important;margin-left:4px}.isabl-base-card .v-data-table .v-data-table__wrapper{max-height:300px;overflow-y:auto}.isabl-base-card .v-data-table .table-cell{height:25px!important;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:300px;padding-left:5px!important}.isabl-base-card .v-data-table .table-cell .v-chip.v-size--small{height:20px}.isabl-base-card .v-data-table tr.table-headers.table-cell{position:sticky;top:0;background:#fff;cursor:pointer;height:32px}.isabl-base-card .v-data-table tr.table-headers.table-cell th{background:rgba(0,0,0,.04)}.isabl-base-card .v-data-table.theme--dark,.isabl-base-card .v-data-table.theme--dark tr.column-filters th,.isabl-base-card .v-data-table.theme--dark tr.table-headers.table-cell th{background:var(--v-surface-base)}.isabl-base-card .v-data-table th.column.sortable{padding:0 5px}.isabl-base-card .v-data-table tr.column-filters th{height:32px}.isabl-base-card .v-data-table .v-data-table__empty-wrapper>td{padding:0}.table-filter-input{min-width:150px}.table-filter-input .v-input__icon--append .v-icon{font-size:14px}.table-filter-input input{font-size:14px;font-weight:400;padding-left:6px!important}.table-filter-input label{font-size:13px;padding-left:6px}.column-filters{position:sticky;top:25px;background:#fff}.column-filters .v-select{margin:0}.column-filters .v-select .v-input__slot,.column-filters .v-select input{height:25px}.column-filters .v-select .v-icon{font-size:16px}.column-filters .v-select__selections{display:contents;max-width:120px;font-size:14px;font-weight:400}.column-filters .v-select__selections span,.column-filters .v-text-field .v-input__append-inner{padding:0}.v-list .v-list-item{min-height:25px}.v-list .v-list-item .v-list-item__title{font-size:14px;font-weight:400}.v-list .v-list-item .v-list-item__content{padding:0 10px}div.v-list--dense .v-list-item{min-height:25px;padding:0}div.v-list--dense .v-list-item .v-list-item__action{margin:0;padding:0 4px}div.v-list--dense .v-list-item .v-list-item__title{font-size:14px;font-weight:400}div.v-list--dense .v-list-item .v-list-item__content{padding:0}.v-select-list{overflow:hidden}.v-menu__content:not(.v-autocomplete__content) .v-list__tile{height:23px}table.v-table tbody tr{border:0!important}table.v-table thead tr{height:30px!important}table.v-table thead tr.v-datatable__progress{height:0!important;border-top:1px solid rgba(0,0,0,.05)}table.v-table thead th{padding-left:5px!important;padding-right:5px!important}div.v-data-table__actions{-ms-flex-wrap:nowrap;flex-wrap:nowrap}div.v-data-table__actions__pagination{width:100%;min-width:170px;margin:0 10px 0 10px}div.v-data-table__actions__select{white-space:normal;overflow:hidden;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;margin-right:5px;max-width:100px}div.v-data-table__actions__select .v-select{margin-left:25px;margin-right:0;margin-top:0;margin-bottom:0}div.v-data-table__actions__range-controls{width:100%}div.v-data-table__actions button{margin:0;margin-right:5px}.section-toggle{cursor:pointer}.isabl-base-card .v-data-footer{font-size:12px;padding:0}.isabl-base-card .v-data-footer div.v-select__selection{font-size:12px}.isabl-base-card .v-data-footer div.v-select{margin:4px 0 4px 16px}.v-data-footer__select .v-menu__content .v-list-item{min-height:25px;font-size:14px}.v-data-footer__select .v-menu__content .v-list-item .v-list-item__content{padding:0}code.markdown-style{padding:.2em .4em;margin:0;font-size:85%;background-color:rgba(175,184,193,.2);border-radius:6px;color:#24292f}.v-data-table .v-data-footer .v-data-footer__select{margin-left:0;margin-right:auto}.v-data-table .v-data-footer .v-data-footer__pagination{margin-left:auto;margin-right:auto}.v-data-table .v-data-footer .v-data-footer__icons-before{margin-left:auto;margin-right:0}.v-data-table .v-data-footer .v-data-footer__icons-after{margin-left:0;margin-right:0}", ""]);
89271
+ exports.push([module.i, ".isabl-base-card .v-data-table th.column.sortable.active.desc button.sort-icon{-webkit-transform:rotate(-180deg);transform:rotate(-180deg)}.isabl-base-card .v-data-table th.column.sortable.active button.sort-icon{color:var(--v-primary-base)}.isabl-base-card .v-data-table th.column.sortable button{font-size:13px!important;margin-left:4px}.isabl-base-card .v-data-table .v-data-table__wrapper{max-height:300px;overflow-y:auto}.isabl-base-card .v-data-table .table-cell{height:25px!important;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:300px;padding-left:5px!important}.isabl-base-card .v-data-table .table-cell .v-chip.v-size--small{height:20px}.isabl-base-card .v-data-table tr.table-headers.table-cell{position:sticky;top:0;background:#fff;cursor:pointer;height:32px;z-index:1}.isabl-base-card .v-data-table tr.table-headers.table-cell th{background:rgba(0,0,0,.04)}.isabl-base-card .v-data-table.theme--dark,.isabl-base-card .v-data-table.theme--dark tr.column-filters th,.isabl-base-card .v-data-table.theme--dark tr.table-headers.table-cell th{background:var(--v-surface-base)}.isabl-base-card .v-data-table th.column.sortable{padding:0 5px}.isabl-base-card .v-data-table tr.column-filters th{height:32px}.isabl-base-card .v-data-table .v-data-table__empty-wrapper>td{padding:0}.table-filter-input{min-width:150px}.table-filter-input .v-input__icon--append .v-icon{font-size:14px}.table-filter-input input{font-size:14px;font-weight:400;padding-left:6px!important}.table-filter-input label{font-size:13px;padding-left:6px}.column-filters{position:sticky;top:25px;background:#fff;z-index:1}.column-filters .v-select{margin:0}.column-filters .v-select .v-input__slot,.column-filters .v-select input{height:25px}.column-filters .v-select .v-icon{font-size:16px}.column-filters .v-select__selections{display:contents;max-width:120px;font-size:14px;font-weight:400}.column-filters .v-select__selections span,.column-filters .v-text-field .v-input__append-inner{padding:0}.v-list .v-list-item{min-height:25px}.v-list .v-list-item .v-list-item__title{font-size:14px;font-weight:400}.v-list .v-list-item .v-list-item__content{padding:0 10px}div.v-list--dense .v-list-item{min-height:25px;padding:0}div.v-list--dense .v-list-item .v-list-item__action{margin:0;padding:0 4px}div.v-list--dense .v-list-item .v-list-item__title{font-size:14px;font-weight:400}div.v-list--dense .v-list-item .v-list-item__content{padding:0}.v-select-list{overflow:hidden}.v-menu__content:not(.v-autocomplete__content) .v-list__tile{height:23px}table.v-table tbody tr{border:0!important}table.v-table thead tr{height:30px!important}table.v-table thead tr.v-datatable__progress{height:0!important;border-top:1px solid rgba(0,0,0,.05)}table.v-table thead th{padding-left:5px!important;padding-right:5px!important}div.v-data-table__actions{-ms-flex-wrap:nowrap;flex-wrap:nowrap}div.v-data-table__actions__pagination{width:100%;min-width:170px;margin:0 10px 0 10px}div.v-data-table__actions__select{white-space:normal;overflow:hidden;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;margin-right:5px;max-width:100px}div.v-data-table__actions__select .v-select{margin-left:25px;margin-right:0;margin-top:0;margin-bottom:0}div.v-data-table__actions__range-controls{width:100%}div.v-data-table__actions button{margin:0;margin-right:5px}.section-toggle{cursor:pointer}.isabl-base-card .v-data-footer{font-size:12px;padding:0}.isabl-base-card .v-data-footer div.v-select__selection{font-size:12px}.isabl-base-card .v-data-footer div.v-select{margin:4px 0 4px 16px}.v-data-footer__select .v-menu__content .v-list-item{min-height:25px;font-size:14px}.v-data-footer__select .v-menu__content .v-list-item .v-list-item__content{padding:0}code.markdown-style{padding:.2em .4em;margin:0;font-size:85%;background-color:rgba(175,184,193,.2);border-radius:6px;color:#24292f}.v-data-table .v-data-footer .v-data-footer__select{margin-left:0;margin-right:auto}.v-data-table .v-data-footer .v-data-footer__pagination{margin-left:auto;margin-right:auto}.v-data-table .v-data-footer .v-data-footer__icons-before{margin-left:auto;margin-right:0}.v-data-table .v-data-footer .v-data-footer__icons-after{margin-left:0;margin-right:0}", ""]);
89272
89272
 
89273
89273
  // exports
89274
89274
 
@@ -91168,7 +91168,7 @@ module.exports = overArg;
91168
91168
  /***/ "9224":
91169
91169
  /***/ (function(module) {
91170
91170
 
91171
- module.exports = JSON.parse("{\"name\":\"@papaemmelab/isabl-web\",\"version\":\"0.3.14\",\"scripts\":{\"serve\":\"vue-cli-service serve\",\"lint\":\"vue-cli-service lint\",\"build-lib\":\"vue-cli-service build --target lib --name isabl-web ./src/main.js\",\"build-wc\":\"vue-cli-service build --target wc --name isabl-web ./src/components/*.vue\",\"build-wc-async\":\"vue-cli-service build --target wc-async --name isabl-web ./src/components/*.vue\",\"publish-app\":\"yarn version --patch && yarn build-lib && yarn publish --access public\",\"dev\":\"yarn build-lib --watch\",\"test:unit\":\"vue-cli-service test:unit\",\"test:e2e\":\"vue-cli-service test:e2e\",\"test:travis\":\"yarn test:e2e --headless\",\"test:submissions\":\"node tests/utils/create_test_submission.js\",\"test:report-coverage\":\"nyc report --reporter=text-lcov > coverage.lcov && codecov -t $CODECOV_TOKEN\",\"demo\":\"nodemon demo/demo-app.js\"},\"dependencies\":{\"@mdi/font\":\"^7.0.96\",\"ansi_up\":\"^5\",\"axios\":\"^0.21.1\",\"crossfilter\":\"^1.3.12\",\"crossfilter2\":\"^1.4.7\",\"d3-tip\":\"^0.9.1\",\"dc\":\"3.1.2\",\"detect-csv\":\"^1.1.0\",\"js-md5\":\"^0.7.3\",\"minify-css-string\":\"^1.0.0\",\"moment\":\"^2.22.2\",\"register-service-worker\":\"^1.5.2\",\"v-hotkey\":\"^0.6.0\",\"vue\":\"^2.5.16\",\"vue-clipboard2\":\"^0.2.1\",\"vue-gallery\":\"^1.4.0\",\"vue-highlightjs\":\"^1.3.3\",\"vue-json-excel\":\"^0.2.5\",\"vue-observe-visibility\":\"^0.4.6\",\"vue-router\":\"^3.0.1\",\"vue-upload-component\":\"^2.8.11\",\"vuetify\":\"2.6.10\",\"vuex\":\"^3.0.1\",\"vuex-router-sync\":\"^5.0.0\"},\"devDependencies\":{\"@cypress/code-coverage\":\"^1.10.1\",\"@vue/cli-plugin-babel\":\"^3.3.0\",\"@vue/cli-plugin-e2e-cypress\":\"^3.3.0\",\"@vue/cli-plugin-eslint\":\"^3.3.0\",\"@vue/cli-plugin-pwa\":\"^3.3.0\",\"@vue/cli-plugin-unit-jest\":\"^3.3.0\",\"@vue/cli-service\":\"^3.3.0\",\"@vue/eslint-config-prettier\":\"^3.0.5\",\"@vue/test-utils\":\"^1.0.0-beta.20\",\"axios-mock-adapter\":\"^1.15.0\",\"babel-core\":\"7.0.0-bridge.0\",\"babel-jest\":\"^23.0.1\",\"babel-plugin-istanbul\":\"^5.2.0\",\"codecov\":\"^3.6.1\",\"eslint-plugin-vuetify\":\"^1.1.0\",\"express\":\"^4.16.3\",\"html-webpack-plugin\":\"^3.2.0\",\"istanbul-lib-coverage\":\"^2.0.5\",\"mini-css-extract-plugin\":\"^0.4.2\",\"nyc\":\"^14.1.1\",\"sass\":\"^1.55.0\",\"sass-loader\":\"^7.0.1\",\"vue-template-compiler\":\"^2.5.16\",\"xlsx-populate\":\"^1.19.1\"},\"browserslist\":[\"> 1%\",\"last 2 versions\",\"not ie <= 8\"],\"main\":\"./dist/isabl-web.umd.min.js\",\"license\":\"MIT\",\"files\":[\"dist/isabl-web*.js\"],\"author\":\"Juan S. Medina - Juan E. Arango\",\"description\":\"Isabl Frontend of the MSK Academic License.\",\"bugs\":{\"url\":\"https://github.com/papaemmelab/isabl_web/issues\"},\"homepage\":\"https://github.com/papaemmelab/isabl_web#readme\"}");
91171
+ module.exports = JSON.parse("{\"name\":\"@papaemmelab/isabl-web\",\"version\":\"0.3.18\",\"scripts\":{\"serve\":\"vue-cli-service serve\",\"lint\":\"vue-cli-service lint\",\"build-lib\":\"vue-cli-service build --target lib --name isabl-web ./src/main.js\",\"build-wc\":\"vue-cli-service build --target wc --name isabl-web ./src/components/*.vue\",\"build-wc-async\":\"vue-cli-service build --target wc-async --name isabl-web ./src/components/*.vue\",\"publish-app\":\"yarn version --patch && yarn build-lib && yarn publish --access public\",\"dev\":\"yarn build-lib --watch\",\"test:unit\":\"vue-cli-service test:unit\",\"test:e2e\":\"vue-cli-service test:e2e\",\"test:travis\":\"yarn test:e2e --headless\",\"test:submissions\":\"node tests/utils/create_test_submission.js\",\"test:report-coverage\":\"nyc report --reporter=text-lcov > coverage.lcov && codecov -t $CODECOV_TOKEN\",\"demo\":\"nodemon demo/demo-app.js\"},\"dependencies\":{\"@mdi/font\":\"^7.0.96\",\"ansi_up\":\"^5\",\"axios\":\"^0.21.1\",\"crossfilter\":\"^1.3.12\",\"crossfilter2\":\"^1.4.7\",\"d3-tip\":\"^0.9.1\",\"dc\":\"3.1.2\",\"detect-csv\":\"^1.1.0\",\"js-md5\":\"^0.7.3\",\"minify-css-string\":\"^1.0.0\",\"moment\":\"^2.22.2\",\"register-service-worker\":\"^1.5.2\",\"v-hotkey\":\"^0.6.0\",\"vue\":\"^2.5.16\",\"vue-clipboard2\":\"^0.2.1\",\"vue-gallery\":\"^1.4.0\",\"vue-highlightjs\":\"^1.3.3\",\"vue-json-excel\":\"^0.2.5\",\"vue-observe-visibility\":\"^0.4.6\",\"vue-router\":\"^3.0.1\",\"vue-upload-component\":\"^2.8.11\",\"vuetify\":\"2.6.10\",\"vuex\":\"^3.0.1\",\"vuex-router-sync\":\"^5.0.0\"},\"devDependencies\":{\"@cypress/code-coverage\":\"^1.10.1\",\"@vue/cli-plugin-babel\":\"^3.3.0\",\"@vue/cli-plugin-e2e-cypress\":\"^3.3.0\",\"@vue/cli-plugin-eslint\":\"^3.3.0\",\"@vue/cli-plugin-pwa\":\"^3.3.0\",\"@vue/cli-plugin-unit-jest\":\"^3.3.0\",\"@vue/cli-service\":\"^3.3.0\",\"@vue/eslint-config-prettier\":\"^3.0.5\",\"@vue/test-utils\":\"^1.0.0-beta.20\",\"axios-mock-adapter\":\"^1.15.0\",\"babel-core\":\"7.0.0-bridge.0\",\"babel-jest\":\"^23.0.1\",\"babel-plugin-istanbul\":\"^5.2.0\",\"codecov\":\"^3.6.1\",\"eslint-plugin-vuetify\":\"^1.1.0\",\"express\":\"^4.16.3\",\"html-webpack-plugin\":\"^3.2.0\",\"istanbul-lib-coverage\":\"^2.0.5\",\"mini-css-extract-plugin\":\"^0.4.2\",\"nyc\":\"^14.1.1\",\"sass\":\"^1.55.0\",\"sass-loader\":\"^7.0.1\",\"vue-template-compiler\":\"^2.5.16\",\"xlsx-populate\":\"^1.19.1\"},\"browserslist\":[\"> 1%\",\"last 2 versions\",\"not ie <= 8\"],\"main\":\"./dist/isabl-web.umd.min.js\",\"license\":\"MIT\",\"files\":[\"dist/isabl-web*.js\"],\"author\":\"Juan S. Medina - Juan E. Arango\",\"description\":\"Isabl Frontend of the MSK Academic License.\",\"bugs\":{\"url\":\"https://github.com/papaemmelab/isabl_web/issues\"},\"homepage\":\"https://github.com/papaemmelab/isabl_web#readme\"}");
91172
91172
 
91173
91173
  /***/ }),
91174
91174
 
@@ -209313,7 +209313,7 @@ var tableColumns = (cov_2ayx42smu.s[23]++, {
209313
209313
  field: 'owner'
209314
209314
  }, {
209315
209315
  verboseName: 'Analyst',
209316
- field: 'analyist'
209316
+ field: 'analyst'
209317
209317
  }, {
209318
209318
  verboseName: 'Coordinator',
209319
209319
  field: 'coordinator'
@@ -243670,8 +243670,8 @@ var BaseTabs_component = normalizeComponent(
243670
243670
  )
243671
243671
 
243672
243672
  /* harmony default export */ var BaseTabs = (BaseTabs_component.exports);
243673
- // CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"d220a428-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/table/DataTable.vue?vue&type=template&id=74a20140&
243674
- var DataTablevue_type_template_id_74a20140_render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('v-card',{class:['isabl-base-card no-shadow', _vm.cardClasses]},[_c('base-section-title',{attrs:{"show-more":_vm.showTable},on:{"toggle-show-more":function($event){_vm.showTable = !_vm.showTable}},scopedSlots:_vm._u([{key:"title",fn:function(){return [_vm._v("\n "+_vm._s(_vm._f("capitalize")(_vm.title || _vm.model))+"\n "),(_vm.infoText)?_c('v-tooltip',{attrs:{"top":""},scopedSlots:_vm._u([{key:"activator",fn:function(ref){
243673
+ // CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"d220a428-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/table/DataTable.vue?vue&type=template&id=57e40a80&
243674
+ var DataTablevue_type_template_id_57e40a80_render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('v-card',{class:['isabl-base-card no-shadow', _vm.cardClasses]},[_c('base-section-title',{attrs:{"show-more":_vm.showTable},on:{"toggle-show-more":function($event){_vm.showTable = !_vm.showTable}},scopedSlots:_vm._u([{key:"title",fn:function(){return [_vm._v("\n "+_vm._s(_vm._f("capitalize")(_vm.title || _vm.model))+"\n "),(_vm.infoText)?_c('v-tooltip',{attrs:{"top":""},scopedSlots:_vm._u([{key:"activator",fn:function(ref){
243675
243675
  var on = ref.on;
243676
243676
  return [_c('v-icon',_vm._g({staticClass:"pl-1",staticStyle:{"cursor":"help"},attrs:{"small":"","color":"grey lighten-2"}},on),[_vm._v("\n info\n ")])]}}],null,false,2192405103)},[_c('span',{attrs:{"text-center":""}},[_vm._v(_vm._s(_vm.infoText))])]):_vm._e()]},proxy:true},{key:"actions",fn:function(){return [(_vm.items)?_c('data-table-actions',{attrs:{"model":_vm.model,"items":_vm.items,"headers":_vm.headers,"global-search":_vm.globalSearch,"query-params":_vm.queryParams},on:{"fetch-data":_vm.updateSearchText}}):_vm._e()]},proxy:true}])}),_c('v-data-table',{directives:[{name:"show",rawName:"v-show",value:(_vm.showTable),expression:"showTable"}],attrs:{"headers":_vm.headers,"items":_vm.items,"server-items-length":_vm.totalItems,"loading":_vm.loading,"items-per-page":_vm.itemsPerPage,"page":_vm.page,"footer-props":{ itemsPerPageOptions: _vm.itemsPerPageItems, itemsPerPageText: '' },"loader-height":"2","calculate-widths":"","hide-default-header":"","dense":""},on:{"update:itemsPerPage":function($event){_vm.itemsPerPage=$event},"update:items-per-page":function($event){_vm.itemsPerPage=$event},"update:page":function($event){_vm.page=$event},"page-count":function($event){_vm.pageCount = $event}},scopedSlots:_vm._u([{key:"header",fn:function(ref){
243677
243677
  var props = ref.props;
@@ -243696,10 +243696,10 @@ return [_c('span',{class:[
243696
243696
  var pageStart = ref.pageStart;
243697
243697
  var pageStop = ref.pageStop;
243698
243698
  return [_c('span',{staticClass:"text-body-1"},[_vm._v("\n "+_vm._s(pageStart)+" - "+_vm._s(pageStop)+" of\n "),_c('span',{staticClass:"primary--text text-h6 mx-1"},[_vm._v(_vm._s(_vm._f("formatNumber")(_vm.totalItems)))])])]}}])})],1)}
243699
- var DataTablevue_type_template_id_74a20140_staticRenderFns = []
243699
+ var DataTablevue_type_template_id_57e40a80_staticRenderFns = []
243700
243700
 
243701
243701
 
243702
- // CONCATENATED MODULE: ./src/components/table/DataTable.vue?vue&type=template&id=74a20140&
243702
+ // CONCATENATED MODULE: ./src/components/table/DataTable.vue?vue&type=template&id=57e40a80&
243703
243703
 
243704
243704
  // CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"d220a428-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/table/DataTableActions.vue?vue&type=template&id=0e1da098&
243705
243705
  var DataTableActionsvue_type_template_id_0e1da098_render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('v-row',{staticClass:"pa-0 ma-0 float-right"},[(_vm.searchText || _vm.showSearch)?_c('transition',{attrs:{"name":"slide"}},[_c('v-form',{on:{"submit":function($event){$event.preventDefault();}}},[_c('v-text-field',{ref:"input",staticClass:"pa-0 my-0 table-filter-input",attrs:{"autofocus":true,"append-icon":_vm.searchText ? 'close' : null,"label":"Search","data-test":"table-search-input","single-line":"","hide-details":"","dense":""},on:{"click:append":function($event){_vm.searchText ? (_vm.searchText = '') : null},"keyup":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"esc",27,$event.key,["Esc","Escape"])){ return null; }_vm.searchText = ''},"blur":_vm.onSearchInputBlur},model:{value:(_vm.searchText),callback:function ($$v) {_vm.searchText=$$v},expression:"searchText"}})],1)],1):_vm._e(),_c('v-speed-dial',{staticClass:"float-right",attrs:{"direction":"bottom","color":"primary","transition":"slide-y-transition","open-on-hover":""},scopedSlots:_vm._u([{key:"activator",fn:function(){return [_c('v-btn',{staticClass:"table-action-btn",attrs:{"fab":"","x-small":"","elevation":"0","color":"transparent"},on:{"click":function($event){_vm.showSearch = !_vm.showSearch}}},[(_vm.loading)?_c('v-progress-circular',{attrs:{"width":2,"size":18,"indeterminate":"","color":"primary"}}):(_vm.showActions || _vm.showSearch)?_c('v-icon',{attrs:{"small":""}},[_vm._v("\n search\n ")]):_c('v-icon',[_vm._v("\n more_vert\n ")])],1)]},proxy:true}]),model:{value:(_vm.showActions),callback:function ($$v) {_vm.showActions=$$v},expression:"showActions"}},[_c('JsonExcel',{attrs:{"fields":_vm.jsonHeaders,"fetch":_vm.fetchAllRecords,"worksheet":_vm.model,"name":_vm.exportedFilename,"before-finish":_vm.showFinishedAlert}},[_c('v-btn',{staticClass:"table-action-btn float-right",attrs:{"fab":"","x-small":""}},[_c('v-tooltip',{attrs:{"left":""},scopedSlots:_vm._u([{key:"activator",fn:function(ref){
@@ -247617,7 +247617,7 @@ var orderBy_default = /*#__PURE__*/__webpack_require__.n(orderBy);
247617
247617
  // CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/thread-loader/dist/cjs.js!./node_modules/@vue/cli-plugin-babel/node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/table/DataTable.vue?vue&type=script&lang=js&
247618
247618
  var cov_2h6d9k0h00 = function () {
247619
247619
  var path = "/Users/juanes/papaemmelab/isabl_web/src/components/table/DataTable.vue";
247620
- var hash = "bc4de628811eceb42295fceb48086fc35aa352e5";
247620
+ var hash = "d785cc7739c0c8a3532fce89055018d808c250a9";
247621
247621
  var global = new Function("return this")();
247622
247622
  var gcv = "__coverage__";
247623
247623
  var coverageData = {
@@ -251035,10 +251035,10 @@ var cov_2h6d9k0h00 = function () {
251035
251035
  mappings: ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA",
251036
251036
  file: "DataTable.vue",
251037
251037
  sourceRoot: "src/components/table",
251038
- sourcesContent: ["<template>\n <v-card :class=\"['isabl-base-card no-shadow', cardClasses]\">\n <base-section-title\n :show-more=\"showTable\"\n @toggle-show-more=\"showTable = !showTable\"\n >\n <template v-slot:title>\n {{ title || model | capitalize }}\n <v-tooltip\n v-if=\"infoText\"\n top\n >\n <template v-slot:activator=\"{ on }\">\n <v-icon\n small\n style=\"cursor: help\"\n color=\"grey lighten-2\"\n class=\"pl-1\"\n v-on=\"on\"\n >\n info\n </v-icon>\n </template>\n <span text-center>{{ infoText }}</span>\n </v-tooltip>\n </template>\n <template v-slot:actions>\n <data-table-actions\n v-if=\"items\"\n :model=\"model\"\n :items=\"items\"\n :headers=\"headers\"\n :global-search=\"globalSearch\"\n :query-params=\"queryParams\"\n @fetch-data=\"updateSearchText\"\n />\n </template>\n </base-section-title>\n\n <v-data-table\n v-show=\"showTable\"\n :headers=\"headers\"\n :items=\"items\"\n :server-items-length=\"totalItems\"\n :loading=\"loading\"\n :items-per-page.sync=\"itemsPerPage\"\n :page.sync=\"page\"\n :footer-props=\"{ itemsPerPageOptions: itemsPerPageItems, itemsPerPageText: '' }\"\n loader-height=\"2\"\n calculate-widths\n hide-default-header\n dense\n @page-count=\"pageCount = $event\"\n >\n <template v-slot:header=\"{ props }\">\n <tr class=\"table-headers text-left table-cell py-0 font-normal\">\n <th\n v-for=\"header in props.headers\"\n :key=\"header.text\"\n :class=\"[\n 'column sortable',\n sortByColumns.includes(header.value)\n ? 'asc active'\n : '',\n sortByColumns.includes(`-${header.value}`)\n ? 'desc active'\n : ''\n ]\"\n >\n <v-hover v-slot=\"{ hover }\">\n <span\n :class=\"[\n 'font-weight-medium',\n 'grey--text',\n ]\"\n >\n {{ header.text }}\n <v-icon\n :color=\"\n hover || sortByColumns.includes(header.value) || sortByColumns.includes(`-${header.value}`)\n ? 'text--darken-2'\n : 'transparent'\n \"\n class=\"sort-icon\"\n style=\"vertical-align: middle\"\n small\n @click=\"changeSort(header.value)\"\n >arrow_downward</v-icon>\n <v-icon\n :color=\"hover ? 'text--darken-2' : 'transparent'\"\n class=\"\"\n style=\"vertical-align: middle\"\n small\n @click=\"toggleColumnFilters\"\n >filter_list</v-icon>\n </span>\n </v-hover>\n </th>\n </tr>\n <tr\n v-if=\"showFilters\"\n class=\"column-filters\"\n >\n <th\n v-for=\"header in props.headers\"\n :key=\"header.text\"\n class=\"pa-0 ma-0\"\n >\n <data-table-date-picker\n v-if=\"header.filterType === 'date'\"\n :header=\"header\"\n @filter-search=\"filterSearch\"\n />\n <data-table-select-filter\n v-else\n :header=\"header\"\n :model=\"title || model\"\n @filter-search=\"filterSearch\"\n />\n </th>\n </tr>\n </template>\n <template v-slot:item=\"attrs\">\n <tr>\n <td\n v-for=\"(header, index) in attrs.headers\"\n :key=\"index + header.verboseName\"\n class=\"text-left table-cell py-0 text-body-1\"\n >\n <!-- if value is a model(s) link -->\n <span v-if=\"header.model\">\n <span v-if=\"Array.isArray(getValue(attrs.item, header))\">\n <span\n v-for=\"(value, index) in getValue(attrs.item, header)\"\n :key=\"index\"\n class=\"active-link\"\n @click=\"onClickRecord(value, header.model)\"\n v-html=\"\n highlightText(value, header) +\n `${index + 1 < getValue(attrs.item, header).length ? ', ' : ''}`\n \"\n />\n </span>\n\n <span v-else>\n <span\n class=\"active-link\"\n @click=\"onClickRecord(getValue(attrs.item, header), header.model)\"\n v-html=\"tableValue(attrs.item, header)\"\n />\n </span>\n </span>\n\n <!-- if value is analysis' result -->\n <span\n v-else-if=\"header.field === 'status'\"\n :class=\"classValue(attrs.item, header.field)\"\n v-html=\"tableValue(attrs.item, header)\"\n />\n\n <div\n v-else-if=\"header.field === 'resultName'\"\n class=\"mr-2\"\n >\n <result-chip\n :result=\"attrs.item\"\n :result-index=\"itemsPerPage * (page - 1) + attrs.index\"\n show-all\n @display-result=\"$emit('display-result', $event)\"\n />\n </div>\n\n <span\n v-else-if=\"header.field === 'resultKey'\"\n class=\"mr-2\"\n >\n <code class=\"markdown-style\" v-html=\"tableValue(attrs.item, header)\"/>\n </span>\n\n <!-- any other case -->\n <span\n v-else\n v-html=\"tableValue(attrs.item, header)\"\n />\n </td>\n </tr>\n </template>\n\n <template v-slot:no-data>\n <td\n :colspan=\"headers.length\"\n class=\"text-left table-cell pa-0 text-body-1\"\n >{{ loading ? 'Querying records...' : errorMessage || 'No records found.' }}</td>\n </template>\n\n <template v-slot:loading>\n <td\n :colspan=\"headers.length\"\n class=\"text-left table-cell pa-0 text-body-1\"\n >Querying records...</td>\n </template>\n\n <template v-slot:no-results>\n <td\n :colspan=\"headers.length\"\n class=\"text-left table-cell pa-0 text-body-1\"\n >{{ loading ? 'Querying records...' : 'No records found.' }}</td>\n </template>\n\n <template v-slot:footer.page-text=\"{ pageStart, pageStop }\">\n <span class=\"text-body-1\">\n {{ pageStart }} - {{ pageStop }} of\n <span\n class=\"primary--text text-h6 mx-1\"\n >{{ totalItems | formatNumber }}</span>\n </span>\n </template>\n\n </v-data-table>\n </v-card>\n</template>\n\n<script>\nimport { fetchListRecords } from '@/utils/api'\nimport { SHOW_ALERT } from '@/store/actions/alert'\nimport { SHOW_PANEL } from '@/store/actions/panels'\nimport { tableColumns } from '@/utils/tableColumns'\nimport BaseSectionTitle from '@/components/base/BaseSectionTitle.vue'\nimport DataTableActions from '@/components/table/DataTableActions.vue'\nimport DataTableSelectFilter from '@/components/table/DataTableSelectFilter.vue'\nimport DataTableDatePicker from '@/components/table/DataTableDatePicker.vue'\nimport ResultChip from '@/components/analyses/ResultChip'\nimport debounce from 'lodash/debounce'\nimport isEqual from 'lodash/isEqual'\nimport orderBy from 'lodash/orderBy'\n\nexport default {\n name: 'DataTable',\n components: {\n BaseSectionTitle,\n DataTableActions,\n DataTableSelectFilter,\n DataTableDatePicker,\n ResultChip,\n },\n props: {\n model: {\n type: String,\n required: false\n },\n title: {\n type: String,\n default: ''\n },\n globalSearch: {\n type: Boolean,\n default: false\n },\n params: {\n type: Object,\n default: () => ({})\n },\n // skip columns using the verbose name\n skipColumns: {\n type: Array,\n default: () => []\n },\n // columns using the verbose name\n headersKey: {\n type: String,\n default: ''\n },\n cardClasses: {\n type: String,\n default: ''\n },\n collapse: {\n type: Boolean,\n default: false\n },\n infoText: {\n type: String,\n default: ''\n },\n openRecordsInNewTab: {\n type: Boolean,\n default: false\n },\n data: {\n type: Array,\n default: () => []\n },\n filterRemotely: {\n type: Boolean,\n default: true,\n },\n initialSort: {\n type: Array,\n default: () => [\"-pk\"]\n },\n initialItemsPerPage: {\n type: Number,\n default: 5,\n }\n },\n data() {\n return {\n items: this.filterRemotely ? [] : this.data,\n totalItems: 0,\n loading: true,\n showTable: !this.collapse,\n showFilters: false,\n\n // table params\n headers: tableColumns[this.headersKey || this.model]\n .map(col => {\n col.text = col.verboseName\n col.value = col.field\n return col\n })\n .filter(col => !this.skipColumns.includes(col.verboseName)),\n page: 1,\n pageCount: 0,\n itemsPerPage: this.initialItemsPerPage,\n itemsPerPageItems: [3, 5, 10, 25, 50, 200, 500, 5000],\n sortByColumns: this.initialSort,\n\n // query params\n limit: null,\n offset: null,\n ordering: null,\n errorMessage: null,\n searchText: '',\n filterParams: {},\n queryParams: {}\n }\n },\n watch: {\n params(newParams, oldParams) {\n if (!isEqual(newParams, oldParams)) {\n this.fetchData()\n }\n },\n page() {\n this.updateTable()\n },\n sortByColumns() {\n this.updateTable()\n },\n itemsPerPage() {\n this.updateTable()\n },\n data() {\n this.updateTable()\n }\n },\n created() {\n this.fetchData = debounce(this._fetchData, 500)\n this.updateTable()\n },\n methods: {\n changeSort(column) {\n let sort = this.sortByColumns\n\n if (sort.includes(column)) {\n // Make ordering column -> None\n sort = sort.filter(columns => columns !== column)\n } else if (sort.includes(`-${column}`)) {\n // Make ordering -column -> column\n sort = sort.filter(columns => columns !== `-${column}`)\n sort.push(column)\n } else {\n // Make ordering None -> -column\n sort.push(`-${column}`)\n }\n\n // Move pk to last if exist\n sort.push(sort.splice(sort.indexOf('pk'), 1)[0])\n sort.push(sort.splice(sort.indexOf('-pk'), 1)[0])\n\n this.sortByColumns = sort\n },\n filterSearch(value, field, filter = 'icontains') {\n field = field.split('.').join('__')\n value = Array.isArray(value) ? value.join(',') : value\n\n // Ensure only one filter per key\n this.filterParams = Object.keys(this.filterParams)\n .filter(param => {\n const filterWithSameKey = `${field}__`\n return !param.includes(filterWithSameKey)\n })\n .reduce((obj, key) => {\n obj[key] = this.filterParams[key]\n return obj\n }, {})\n\n this.filterParams[`${field}__${filter}`] = value\n this.offset = null\n this.page = 1\n this.fetchData()\n\n // Track when user makes any string search\n window.analytics.track('Filter from table column', {\n model: this.model,\n query: this.filterParams\n })\n },\n\n columnValueList(val) {\n return this.items.map(d => d[val])\n },\n\n updateSearchText(text) {\n this.searchText = text\n this.offset = null\n this.page = 1\n this.fetchData()\n\n // Track when user makes any string search\n window.analytics.track('Searched From Table', {\n model: this.model,\n search: this.searchText,\n query: this.queryParams\n })\n },\n\n tableValue(item, header) {\n let value = this.getValue(item, header)\n return this.highlightText(value, header)\n },\n\n formatValue(value) {\n return this.highlightText(value)\n },\n\n getValue(item, header) {\n return this.$get(\n item,\n header.accessor || header.field,\n header.default || '-'\n )\n },\n\n isTableSmall() {\n let tables = document.getElementsByClassName('v-datatable__actions')\n return tables && tables.length > 0 && tables[0].offsetWidth < 400\n },\n\n classValue(item, accessor) {\n let value = this.$get(item, accessor)\n .toString()\n .toLowerCase()\n return `status-${value}`\n },\n\n highlightText(rawText, header) {\n header = header.value.split('.').join('__')\n const filterParams = {\n ...this.filterParams,\n search: this.searchText\n }\n let keywords = Object.entries(filterParams)\n .filter(([key, value]) => {\n return (\n value &&\n typeof value !== 'boolean' &&\n (key === 'search' || key.replace(/(__icontains)/, '') === header)\n )\n })\n .map(([, value]) => value.toString().toLowerCase())\n\n let { text, element } = this.$getInnerHtmlText(rawText)\n let shownText = text ? text.toString().slice(0, 41) : ''\n let highlightText = shownText\n\n // Search for match of full string if not each word\n let wordsToHighlight = []\n keywords.forEach(keyword => {\n keyword = keyword.trim()\n if (keyword && shownText.toLowerCase().includes(keyword)) {\n wordsToHighlight.push(keyword)\n } else {\n keyword.split(' ').forEach(word => {\n if (word && shownText.toLowerCase().includes(word)) {\n wordsToHighlight.push(word)\n }\n })\n }\n })\n\n // Highlight the matches\n if (wordsToHighlight.length) {\n const keywordRegex = new RegExp(`(${wordsToHighlight.join('|')})`, 'gi')\n highlightText = text\n .toString()\n .replace(keywordRegex, '<span class=\"highlight\">$1</span>')\n }\n return this.$setInnerHtmlText(element, highlightText)\n },\n\n updateTable() {\n this.limit = this.itemsPerPage\n this.offset = this.itemsPerPage * (this.page - 1)\n this.ordering = this.sortByColumns.join(',')\n\n if (this.filterRemotely) {\n // Make server-side filtering\n this.fetchData()\n } else {\n // Local Items\n this.loading = true\n let rows = this.data\n\n if (this.searchText) {\n rows = rows.filter((row) =>\n Object.values(row).some((column) =>\n column.toLowerCase().includes(this.searchText.toLowerCase())\n )\n )\n }\n if (this.sortByColumns.length) {\n const columns = []\n const order = []\n this.sortByColumns.forEach(param => {\n const [first, ...rest] = param\n if (first === '-') {\n columns.push(rest.join(''))\n order.push('desc')\n } else {\n columns.push(param)\n order.push('asc')\n }\n })\n rows = orderBy(rows, columns, order)\n }\n rows = rows.slice(this.offset, this.offset + this.limit)\n this.items = rows\n this.totalItems = this.data.length\n this.pages = Math.ceil(this.totalItems / this.items)\n this.loading = false\n }\n },\n\n _fetchData() {\n this.loading = true\n const {\n model,\n limit,\n offset,\n ordering,\n params,\n filterParams,\n searchText\n } = this\n\n this.queryParams = {\n ...params,\n ...filterParams,\n limit,\n offset,\n search: searchText,\n ordering,\n }\n\n this.$emit('fetch-data', this.queryParams)\n\n fetchListRecords(model, this.queryParams)\n .then(response => {\n if (searchText === this.searchText) {\n this.items = response.results\n this.totalItems = response.count\n this.pages = Math.ceil(response.count / limit)\n this.errorMessage = response.error || ''\n }\n })\n .catch(error => {\n let errorMessage = `Search failed: `\n if (error.response) {\n const errorMessages = Object.values(error.response.data).flat()\n errorMessage += errorMessages.length ? errorMessages[0] : '...'\n }\n this.$store.dispatch(SHOW_ALERT, {\n error: errorMessage\n })\n })\n .finally(() => (this.loading = false))\n },\n\n onClickRecord(value, model) {\n if (this.openRecordsInNewTab) {\n const queryParams = {\n individual: 'bioModel',\n sample: 'bioModel',\n experiment: 'bioModel'\n }\n const queryParam = this.$get(queryParams, model, model)\n window.open(`/?${queryParam}=${value}`, '_blank')\n } else {\n this.$store.dispatch(SHOW_PANEL, {\n [model]: value\n })\n }\n },\n\n toggleColumnFilters() {\n this.showFilters = !this.showFilters\n if (!this.showFilters) {\n this.filterParams = {}\n this.fetchData()\n }\n },\n }\n}\n</script>\n\n<style lang=\"scss\">\n\n.isabl-base-card .v-data-table {\n th.column.sortable.active.desc button.sort-icon {\n transform: rotate(-180deg);\n }\n th.column.sortable.active button.sort-icon {\n color: var(--v-primary-base);\n }\n th.column.sortable button {\n font-size: 13px !important;\n margin-left: 4px;\n }\n .v-data-table__wrapper {\n max-height: 300px;\n overflow-y: auto;\n }\n .table-cell {\n height: 25px !important;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 300px;\n padding-left: 5px !important;\n .v-chip.v-size--small {\n height: 20px;\n }\n }\n tr.table-headers.table-cell {\n position: sticky;\n top: 0;\n background: white;\n cursor: pointer;\n height: 32px;\n th {\n // border-bottom: thin solid rgba(0,0,0,.12);\n background: rgba(0,0,0,.04);\n }\n }\n &.theme--dark, &.theme--dark tr.table-headers.table-cell th {\n background: var(--v-surface-base);\n }\n &.theme--dark tr.column-filters th {\n background: var(--v-surface-base);\n }\n th.column.sortable {\n padding: 0px 5px;\n }\n tr.column-filters th {\n height: 32px;\n }\n .v-data-table__empty-wrapper>td {\n padding: 0px;\n }\n}\n\n.table-filter-input {\n min-width: 150px;\n .v-input__icon--append .v-icon {\n font-size: 14px;\n }\n input {\n font-size: 14px;\n font-weight: 400;\n padding-left: 6px !important;\n }\n label {\n font-size: 13px;\n padding-left: 6px;\n }\n}\n.column-filters {\n position: sticky;\n top: 25px;\n background: white;\n .v-select {\n margin: 0px;\n .v-input__slot, input {\n height: 25px;\n }\n .v-icon {\n font-size: 16px;\n }\n }\n .v-select__selections {\n display: contents;\n max-width: 120px;\n font-size: 14px;\n font-weight: 400;\n span {\n padding: 0px;\n }\n }\n .v-text-field .v-input__append-inner {\n padding: 0px;\n }\n}\n\n.v-list .v-list-item {\n min-height: 25px;\n .v-list-item__title {\n font-size: 14px;\n font-weight: 400;\n }\n .v-list-item__content {\n padding: 0px 10px;\n }\n}\n\ndiv.v-list--dense .v-list-item {\n min-height: 25px;\n padding: 0px;\n .v-list-item__action {\n margin: 0px;\n padding: 0px 4px;\n }\n .v-list-item__title {\n font-size: 14px;\n font-weight: 400;\n }\n .v-list-item__content {\n padding: 0px;\n }\n}\n\n.v-select-list {\n overflow: hidden;\n}\n\n.v-menu__content:not(.v-autocomplete__content) {\n .v-list__tile {\n height: 23px;\n }\n}\ntable.v-table tbody tr {\n border: 0px !important;\n}\n\ntable.v-table thead {\n tr {\n height: 30px !important;\n }\n tr.v-datatable__progress {\n height: 0px !important;\n border-top: 1px solid rgba(0, 0, 0, 0.05);\n }\n th {\n padding-left: 5px !important;\n padding-right: 5px !important;\n }\n}\n\ndiv.v-data-table__actions {\n flex-wrap: nowrap;\n &__pagination {\n width: 100%;\n min-width: 170px;\n margin: 0 10px 0 10px;\n }\n &__select {\n white-space: normal;\n overflow: hidden;\n justify-content: flex-start;\n margin-right: 5px;\n max-width: 100px;\n .v-select {\n margin-left: 25px;\n margin-right: 0px;\n margin-top: 0px;\n margin-bottom: 0px;\n }\n }\n &__range-controls {\n width: 100%;\n }\n button {\n margin: 0px;\n margin-right: 5px;\n }\n}\n\n.section-toggle {\n cursor: pointer;\n}\n\n.isabl-base-card .v-data-footer {\n font-size: 12px;\n padding: 0px;\n div.v-select__selection {\n font-size: 12px;\n }\n div.v-select {\n margin: 4px 0px 4px 16px;\n }\n}\n.v-data-footer__select\n.v-menu__content .v-list-item {\n min-height: 25px;\n font-size: 14px;\n .v-list-item__content {\n padding: 0px;\n }\n}\n// Style taken from github\ncode.markdown-style {\n padding: 0.2em 0.4em;\n margin: 0;\n font-size: 85%;\n background-color: rgba(175,184,193,0.2);\n border-radius: 6px;\n color: #24292f;\n}\n\n.v-data-table .v-data-footer {\n .v-data-footer__select {\n margin-left: 0;\n margin-right: auto;\n }\n .v-data-footer__pagination {\n margin-left: auto;\n margin-right: auto;\n }\n .v-data-footer__icons-before {\n margin-left: auto;\n margin-right: 0;\n }\n .v-data-footer__icons-after {\n margin-left: 0;\n margin-right: 0;\n }\n}\n\n</style>\n"]
251038
+ sourcesContent: ["<template>\n <v-card :class=\"['isabl-base-card no-shadow', cardClasses]\">\n <base-section-title\n :show-more=\"showTable\"\n @toggle-show-more=\"showTable = !showTable\"\n >\n <template v-slot:title>\n {{ title || model | capitalize }}\n <v-tooltip\n v-if=\"infoText\"\n top\n >\n <template v-slot:activator=\"{ on }\">\n <v-icon\n small\n style=\"cursor: help\"\n color=\"grey lighten-2\"\n class=\"pl-1\"\n v-on=\"on\"\n >\n info\n </v-icon>\n </template>\n <span text-center>{{ infoText }}</span>\n </v-tooltip>\n </template>\n <template v-slot:actions>\n <data-table-actions\n v-if=\"items\"\n :model=\"model\"\n :items=\"items\"\n :headers=\"headers\"\n :global-search=\"globalSearch\"\n :query-params=\"queryParams\"\n @fetch-data=\"updateSearchText\"\n />\n </template>\n </base-section-title>\n\n <v-data-table\n v-show=\"showTable\"\n :headers=\"headers\"\n :items=\"items\"\n :server-items-length=\"totalItems\"\n :loading=\"loading\"\n :items-per-page.sync=\"itemsPerPage\"\n :page.sync=\"page\"\n :footer-props=\"{ itemsPerPageOptions: itemsPerPageItems, itemsPerPageText: '' }\"\n loader-height=\"2\"\n calculate-widths\n hide-default-header\n dense\n @page-count=\"pageCount = $event\"\n >\n <template v-slot:header=\"{ props }\">\n <tr class=\"table-headers text-left table-cell py-0 font-normal\">\n <th\n v-for=\"header in props.headers\"\n :key=\"header.text\"\n :class=\"[\n 'column sortable',\n sortByColumns.includes(header.value)\n ? 'asc active'\n : '',\n sortByColumns.includes(`-${header.value}`)\n ? 'desc active'\n : ''\n ]\"\n >\n <v-hover v-slot=\"{ hover }\">\n <span\n :class=\"[\n 'font-weight-medium',\n 'grey--text',\n ]\"\n >\n {{ header.text }}\n <v-icon\n :color=\"\n hover || sortByColumns.includes(header.value) || sortByColumns.includes(`-${header.value}`)\n ? 'text--darken-2'\n : 'transparent'\n \"\n class=\"sort-icon\"\n style=\"vertical-align: middle\"\n small\n @click=\"changeSort(header.value)\"\n >arrow_downward</v-icon>\n <v-icon\n :color=\"hover ? 'text--darken-2' : 'transparent'\"\n class=\"\"\n style=\"vertical-align: middle\"\n small\n @click=\"toggleColumnFilters\"\n >filter_list</v-icon>\n </span>\n </v-hover>\n </th>\n </tr>\n <tr\n v-if=\"showFilters\"\n class=\"column-filters\"\n >\n <th\n v-for=\"header in props.headers\"\n :key=\"header.text\"\n class=\"pa-0 ma-0\"\n >\n <data-table-date-picker\n v-if=\"header.filterType === 'date'\"\n :header=\"header\"\n @filter-search=\"filterSearch\"\n />\n <data-table-select-filter\n v-else\n :header=\"header\"\n :model=\"title || model\"\n @filter-search=\"filterSearch\"\n />\n </th>\n </tr>\n </template>\n <template v-slot:item=\"attrs\">\n <tr>\n <td\n v-for=\"(header, index) in attrs.headers\"\n :key=\"index + header.verboseName\"\n class=\"text-left table-cell py-0 text-body-1\"\n >\n <!-- if value is a model(s) link -->\n <span v-if=\"header.model\">\n <span v-if=\"Array.isArray(getValue(attrs.item, header))\">\n <span\n v-for=\"(value, index) in getValue(attrs.item, header)\"\n :key=\"index\"\n class=\"active-link\"\n @click=\"onClickRecord(value, header.model)\"\n v-html=\"\n highlightText(value, header) +\n `${index + 1 < getValue(attrs.item, header).length ? ', ' : ''}`\n \"\n />\n </span>\n\n <span v-else>\n <span\n class=\"active-link\"\n @click=\"onClickRecord(getValue(attrs.item, header), header.model)\"\n v-html=\"tableValue(attrs.item, header)\"\n />\n </span>\n </span>\n\n <!-- if value is analysis' result -->\n <span\n v-else-if=\"header.field === 'status'\"\n :class=\"classValue(attrs.item, header.field)\"\n v-html=\"tableValue(attrs.item, header)\"\n />\n\n <div\n v-else-if=\"header.field === 'resultName'\"\n class=\"mr-2\"\n >\n <result-chip\n :result=\"attrs.item\"\n :result-index=\"itemsPerPage * (page - 1) + attrs.index\"\n show-all\n @display-result=\"$emit('display-result', $event)\"\n />\n </div>\n\n <span\n v-else-if=\"header.field === 'resultKey'\"\n class=\"mr-2\"\n >\n <code class=\"markdown-style\" v-html=\"tableValue(attrs.item, header)\"/>\n </span>\n\n <!-- any other case -->\n <span\n v-else\n v-html=\"tableValue(attrs.item, header)\"\n />\n </td>\n </tr>\n </template>\n\n <template v-slot:no-data>\n <td\n :colspan=\"headers.length\"\n class=\"text-left table-cell pa-0 text-body-1\"\n >{{ loading ? 'Querying records...' : errorMessage || 'No records found.' }}</td>\n </template>\n\n <template v-slot:loading>\n <td\n :colspan=\"headers.length\"\n class=\"text-left table-cell pa-0 text-body-1\"\n >Querying records...</td>\n </template>\n\n <template v-slot:no-results>\n <td\n :colspan=\"headers.length\"\n class=\"text-left table-cell pa-0 text-body-1\"\n >{{ loading ? 'Querying records...' : 'No records found.' }}</td>\n </template>\n\n <template v-slot:footer.page-text=\"{ pageStart, pageStop }\">\n <span class=\"text-body-1\">\n {{ pageStart }} - {{ pageStop }} of\n <span\n class=\"primary--text text-h6 mx-1\"\n >{{ totalItems | formatNumber }}</span>\n </span>\n </template>\n\n </v-data-table>\n </v-card>\n</template>\n\n<script>\nimport { fetchListRecords } from '@/utils/api'\nimport { SHOW_ALERT } from '@/store/actions/alert'\nimport { SHOW_PANEL } from '@/store/actions/panels'\nimport { tableColumns } from '@/utils/tableColumns'\nimport BaseSectionTitle from '@/components/base/BaseSectionTitle.vue'\nimport DataTableActions from '@/components/table/DataTableActions.vue'\nimport DataTableSelectFilter from '@/components/table/DataTableSelectFilter.vue'\nimport DataTableDatePicker from '@/components/table/DataTableDatePicker.vue'\nimport ResultChip from '@/components/analyses/ResultChip'\nimport debounce from 'lodash/debounce'\nimport isEqual from 'lodash/isEqual'\nimport orderBy from 'lodash/orderBy'\n\nexport default {\n name: 'DataTable',\n components: {\n BaseSectionTitle,\n DataTableActions,\n DataTableSelectFilter,\n DataTableDatePicker,\n ResultChip,\n },\n props: {\n model: {\n type: String,\n required: false\n },\n title: {\n type: String,\n default: ''\n },\n globalSearch: {\n type: Boolean,\n default: false\n },\n params: {\n type: Object,\n default: () => ({})\n },\n // skip columns using the verbose name\n skipColumns: {\n type: Array,\n default: () => []\n },\n // columns using the verbose name\n headersKey: {\n type: String,\n default: ''\n },\n cardClasses: {\n type: String,\n default: ''\n },\n collapse: {\n type: Boolean,\n default: false\n },\n infoText: {\n type: String,\n default: ''\n },\n openRecordsInNewTab: {\n type: Boolean,\n default: false\n },\n data: {\n type: Array,\n default: () => []\n },\n filterRemotely: {\n type: Boolean,\n default: true,\n },\n initialSort: {\n type: Array,\n default: () => [\"-pk\"]\n },\n initialItemsPerPage: {\n type: Number,\n default: 5,\n }\n },\n data() {\n return {\n items: this.filterRemotely ? [] : this.data,\n totalItems: 0,\n loading: true,\n showTable: !this.collapse,\n showFilters: false,\n\n // table params\n headers: tableColumns[this.headersKey || this.model]\n .map(col => {\n col.text = col.verboseName\n col.value = col.field\n return col\n })\n .filter(col => !this.skipColumns.includes(col.verboseName)),\n page: 1,\n pageCount: 0,\n itemsPerPage: this.initialItemsPerPage,\n itemsPerPageItems: [3, 5, 10, 25, 50, 200, 500, 5000],\n sortByColumns: this.initialSort,\n\n // query params\n limit: null,\n offset: null,\n ordering: null,\n errorMessage: null,\n searchText: '',\n filterParams: {},\n queryParams: {}\n }\n },\n watch: {\n params(newParams, oldParams) {\n if (!isEqual(newParams, oldParams)) {\n this.fetchData()\n }\n },\n page() {\n this.updateTable()\n },\n sortByColumns() {\n this.updateTable()\n },\n itemsPerPage() {\n this.updateTable()\n },\n data() {\n this.updateTable()\n }\n },\n created() {\n this.fetchData = debounce(this._fetchData, 500)\n this.updateTable()\n },\n methods: {\n changeSort(column) {\n let sort = this.sortByColumns\n\n if (sort.includes(column)) {\n // Make ordering column -> None\n sort = sort.filter(columns => columns !== column)\n } else if (sort.includes(`-${column}`)) {\n // Make ordering -column -> column\n sort = sort.filter(columns => columns !== `-${column}`)\n sort.push(column)\n } else {\n // Make ordering None -> -column\n sort.push(`-${column}`)\n }\n\n // Move pk to last if exist\n sort.push(sort.splice(sort.indexOf('pk'), 1)[0])\n sort.push(sort.splice(sort.indexOf('-pk'), 1)[0])\n\n this.sortByColumns = sort\n },\n filterSearch(value, field, filter = 'icontains') {\n field = field.split('.').join('__')\n value = Array.isArray(value) ? value.join(',') : value\n\n // Ensure only one filter per key\n this.filterParams = Object.keys(this.filterParams)\n .filter(param => {\n const filterWithSameKey = `${field}__`\n return !param.includes(filterWithSameKey)\n })\n .reduce((obj, key) => {\n obj[key] = this.filterParams[key]\n return obj\n }, {})\n\n this.filterParams[`${field}__${filter}`] = value\n this.offset = null\n this.page = 1\n this.fetchData()\n\n // Track when user makes any string search\n window.analytics.track('Filter from table column', {\n model: this.model,\n query: this.filterParams\n })\n },\n\n columnValueList(val) {\n return this.items.map(d => d[val])\n },\n\n updateSearchText(text) {\n this.searchText = text\n this.offset = null\n this.page = 1\n this.fetchData()\n\n // Track when user makes any string search\n window.analytics.track('Searched From Table', {\n model: this.model,\n search: this.searchText,\n query: this.queryParams\n })\n },\n\n tableValue(item, header) {\n let value = this.getValue(item, header)\n return this.highlightText(value, header)\n },\n\n formatValue(value) {\n return this.highlightText(value)\n },\n\n getValue(item, header) {\n return this.$get(\n item,\n header.accessor || header.field,\n header.default || '-'\n )\n },\n\n isTableSmall() {\n let tables = document.getElementsByClassName('v-datatable__actions')\n return tables && tables.length > 0 && tables[0].offsetWidth < 400\n },\n\n classValue(item, accessor) {\n let value = this.$get(item, accessor)\n .toString()\n .toLowerCase()\n return `status-${value}`\n },\n\n highlightText(rawText, header) {\n header = header.value.split('.').join('__')\n const filterParams = {\n ...this.filterParams,\n search: this.searchText\n }\n let keywords = Object.entries(filterParams)\n .filter(([key, value]) => {\n return (\n value &&\n typeof value !== 'boolean' &&\n (key === 'search' || key.replace(/(__icontains)/, '') === header)\n )\n })\n .map(([, value]) => value.toString().toLowerCase())\n\n let { text, element } = this.$getInnerHtmlText(rawText)\n let shownText = text ? text.toString().slice(0, 41) : ''\n let highlightText = shownText\n\n // Search for match of full string if not each word\n let wordsToHighlight = []\n keywords.forEach(keyword => {\n keyword = keyword.trim()\n if (keyword && shownText.toLowerCase().includes(keyword)) {\n wordsToHighlight.push(keyword)\n } else {\n keyword.split(' ').forEach(word => {\n if (word && shownText.toLowerCase().includes(word)) {\n wordsToHighlight.push(word)\n }\n })\n }\n })\n\n // Highlight the matches\n if (wordsToHighlight.length) {\n const keywordRegex = new RegExp(`(${wordsToHighlight.join('|')})`, 'gi')\n highlightText = text\n .toString()\n .replace(keywordRegex, '<span class=\"highlight\">$1</span>')\n }\n return this.$setInnerHtmlText(element, highlightText)\n },\n\n updateTable() {\n this.limit = this.itemsPerPage\n this.offset = this.itemsPerPage * (this.page - 1)\n this.ordering = this.sortByColumns.join(',')\n\n if (this.filterRemotely) {\n // Make server-side filtering\n this.fetchData()\n } else {\n // Local Items\n this.loading = true\n let rows = this.data\n\n if (this.searchText) {\n rows = rows.filter((row) =>\n Object.values(row).some((column) =>\n column.toLowerCase().includes(this.searchText.toLowerCase())\n )\n )\n }\n if (this.sortByColumns.length) {\n const columns = []\n const order = []\n this.sortByColumns.forEach(param => {\n const [first, ...rest] = param\n if (first === '-') {\n columns.push(rest.join(''))\n order.push('desc')\n } else {\n columns.push(param)\n order.push('asc')\n }\n })\n rows = orderBy(rows, columns, order)\n }\n rows = rows.slice(this.offset, this.offset + this.limit)\n this.items = rows\n this.totalItems = this.data.length\n this.pages = Math.ceil(this.totalItems / this.items)\n this.loading = false\n }\n },\n\n _fetchData() {\n this.loading = true\n const {\n model,\n limit,\n offset,\n ordering,\n params,\n filterParams,\n searchText\n } = this\n\n this.queryParams = {\n ...params,\n ...filterParams,\n limit,\n offset,\n search: searchText,\n ordering,\n }\n\n this.$emit('fetch-data', this.queryParams)\n\n fetchListRecords(model, this.queryParams)\n .then(response => {\n if (searchText === this.searchText) {\n this.items = response.results\n this.totalItems = response.count\n this.pages = Math.ceil(response.count / limit)\n this.errorMessage = response.error || ''\n }\n })\n .catch(error => {\n let errorMessage = `Search failed: `\n if (error.response) {\n const errorMessages = Object.values(error.response.data).flat()\n errorMessage += errorMessages.length ? errorMessages[0] : '...'\n }\n this.$store.dispatch(SHOW_ALERT, {\n error: errorMessage\n })\n })\n .finally(() => (this.loading = false))\n },\n\n onClickRecord(value, model) {\n if (this.openRecordsInNewTab) {\n const queryParams = {\n individual: 'bioModel',\n sample: 'bioModel',\n experiment: 'bioModel'\n }\n const queryParam = this.$get(queryParams, model, model)\n window.open(`/?${queryParam}=${value}`, '_blank')\n } else {\n this.$store.dispatch(SHOW_PANEL, {\n [model]: value\n })\n }\n },\n\n toggleColumnFilters() {\n this.showFilters = !this.showFilters\n if (!this.showFilters) {\n this.filterParams = {}\n this.fetchData()\n }\n },\n }\n}\n</script>\n\n<style lang=\"scss\">\n\n.isabl-base-card .v-data-table {\n th.column.sortable.active.desc button.sort-icon {\n transform: rotate(-180deg);\n }\n th.column.sortable.active button.sort-icon {\n color: var(--v-primary-base);\n }\n th.column.sortable button {\n font-size: 13px !important;\n margin-left: 4px;\n }\n .v-data-table__wrapper {\n max-height: 300px;\n overflow-y: auto;\n }\n .table-cell {\n height: 25px !important;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 300px;\n padding-left: 5px !important;\n .v-chip.v-size--small {\n height: 20px;\n }\n }\n tr.table-headers.table-cell {\n position: sticky;\n top: 0;\n background: white;\n cursor: pointer;\n height: 32px;\n z-index: 1;\n th {\n // border-bottom: thin solid rgba(0,0,0,.12);\n background: rgba(0,0,0,.04);\n }\n }\n &.theme--dark, &.theme--dark tr.table-headers.table-cell th {\n background: var(--v-surface-base);\n }\n &.theme--dark tr.column-filters th {\n background: var(--v-surface-base);\n }\n th.column.sortable {\n padding: 0px 5px;\n }\n tr.column-filters th {\n height: 32px;\n }\n .v-data-table__empty-wrapper>td {\n padding: 0px;\n }\n}\n\n.table-filter-input {\n min-width: 150px;\n .v-input__icon--append .v-icon {\n font-size: 14px;\n }\n input {\n font-size: 14px;\n font-weight: 400;\n padding-left: 6px !important;\n }\n label {\n font-size: 13px;\n padding-left: 6px;\n }\n}\n.column-filters {\n position: sticky;\n top: 25px;\n background: white;\n z-index: 1;\n .v-select {\n margin: 0px;\n .v-input__slot, input {\n height: 25px;\n }\n .v-icon {\n font-size: 16px;\n }\n }\n .v-select__selections {\n display: contents;\n max-width: 120px;\n font-size: 14px;\n font-weight: 400;\n span {\n padding: 0px;\n }\n }\n .v-text-field .v-input__append-inner {\n padding: 0px;\n }\n}\n\n.v-list .v-list-item {\n min-height: 25px;\n .v-list-item__title {\n font-size: 14px;\n font-weight: 400;\n }\n .v-list-item__content {\n padding: 0px 10px;\n }\n}\n\ndiv.v-list--dense .v-list-item {\n min-height: 25px;\n padding: 0px;\n .v-list-item__action {\n margin: 0px;\n padding: 0px 4px;\n }\n .v-list-item__title {\n font-size: 14px;\n font-weight: 400;\n }\n .v-list-item__content {\n padding: 0px;\n }\n}\n\n.v-select-list {\n overflow: hidden;\n}\n\n.v-menu__content:not(.v-autocomplete__content) {\n .v-list__tile {\n height: 23px;\n }\n}\ntable.v-table tbody tr {\n border: 0px !important;\n}\n\ntable.v-table thead {\n tr {\n height: 30px !important;\n }\n tr.v-datatable__progress {\n height: 0px !important;\n border-top: 1px solid rgba(0, 0, 0, 0.05);\n }\n th {\n padding-left: 5px !important;\n padding-right: 5px !important;\n }\n}\n\ndiv.v-data-table__actions {\n flex-wrap: nowrap;\n &__pagination {\n width: 100%;\n min-width: 170px;\n margin: 0 10px 0 10px;\n }\n &__select {\n white-space: normal;\n overflow: hidden;\n justify-content: flex-start;\n margin-right: 5px;\n max-width: 100px;\n .v-select {\n margin-left: 25px;\n margin-right: 0px;\n margin-top: 0px;\n margin-bottom: 0px;\n }\n }\n &__range-controls {\n width: 100%;\n }\n button {\n margin: 0px;\n margin-right: 5px;\n }\n}\n\n.section-toggle {\n cursor: pointer;\n}\n\n.isabl-base-card .v-data-footer {\n font-size: 12px;\n padding: 0px;\n div.v-select__selection {\n font-size: 12px;\n }\n div.v-select {\n margin: 4px 0px 4px 16px;\n }\n}\n.v-data-footer__select\n.v-menu__content .v-list-item {\n min-height: 25px;\n font-size: 14px;\n .v-list-item__content {\n padding: 0px;\n }\n}\n// Style taken from github\ncode.markdown-style {\n padding: 0.2em 0.4em;\n margin: 0;\n font-size: 85%;\n background-color: rgba(175,184,193,0.2);\n border-radius: 6px;\n color: #24292f;\n}\n\n.v-data-table .v-data-footer {\n .v-data-footer__select {\n margin-left: 0;\n margin-right: auto;\n }\n .v-data-footer__pagination {\n margin-left: auto;\n margin-right: auto;\n }\n .v-data-footer__icons-before {\n margin-left: auto;\n margin-right: 0;\n }\n .v-data-footer__icons-after {\n margin-left: 0;\n margin-right: 0;\n }\n}\n\n</style>\n"]
251039
251039
  },
251040
251040
  _coverageSchema: "43e27e138ebf9cfc5966b082cf9a028302ed4184",
251041
- hash: "bc4de628811eceb42295fceb48086fc35aa352e5"
251041
+ hash: "d785cc7739c0c8a3532fce89055018d808c250a9"
251042
251042
  };
251043
251043
  var coverage = global[gcv] || (global[gcv] = {});
251044
251044
 
@@ -251897,8 +251897,8 @@ var DataTablevue_type_style_index_0_lang_scss_ = __webpack_require__("7bec");
251897
251897
 
251898
251898
  var DataTable_component = normalizeComponent(
251899
251899
  table_DataTablevue_type_script_lang_js_,
251900
- DataTablevue_type_template_id_74a20140_render,
251901
- DataTablevue_type_template_id_74a20140_staticRenderFns,
251900
+ DataTablevue_type_template_id_57e40a80_render,
251901
+ DataTablevue_type_template_id_57e40a80_staticRenderFns,
251902
251902
  false,
251903
251903
  null,
251904
251904
  null,
@@ -265117,12 +265117,12 @@ var ProjectPanelvue_type_template_id_7c1bc440_staticRenderFns = []
265117
265117
 
265118
265118
  // CONCATENATED MODULE: ./src/components/projects/ProjectPanel.vue?vue&type=template&id=7c1bc440&
265119
265119
 
265120
- // CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"d220a428-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/dashboard/BaseDashboard.vue?vue&type=template&id=2fd2fca6&
265121
- var BaseDashboardvue_type_template_id_2fd2fca6_render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{ref:"dashboard"},[_c('v-card',{staticClass:"isabl-base-card",attrs:{"flat":""}},[_c('dc-graph',{attrs:{"model":_vm.model,"params":_vm.params,"items":_vm.items,"figures":_vm.figures,"loading":_vm.loading,"max-records":_vm.maxRecords,"total-items":_vm.totalItems,"is-embedded":_vm.isEmbedded},on:{"set-max-records":_vm.setMaxRecords,"set-options":_vm.setOptions}})],1)],1)}
265122
- var BaseDashboardvue_type_template_id_2fd2fca6_staticRenderFns = []
265120
+ // CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"d220a428-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/dashboard/BaseDashboard.vue?vue&type=template&id=191c4226&
265121
+ var BaseDashboardvue_type_template_id_191c4226_render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{ref:"dashboard"},[_c('v-card',{staticClass:"isabl-base-card",attrs:{"flat":""}},[_c('dc-graph',{attrs:{"model":_vm.model,"params":_vm.params,"items":_vm.items,"figures":_vm.figures,"loading":_vm.loading,"max-records":_vm.maxRecords,"total-items":_vm.totalItems,"is-embedded":_vm.isEmbedded},on:{"set-max-records":_vm.setMaxRecords,"set-options":_vm.setOptions}})],1)],1)}
265122
+ var BaseDashboardvue_type_template_id_191c4226_staticRenderFns = []
265123
265123
 
265124
265124
 
265125
- // CONCATENATED MODULE: ./src/components/dashboard/BaseDashboard.vue?vue&type=template&id=2fd2fca6&
265125
+ // CONCATENATED MODULE: ./src/components/dashboard/BaseDashboard.vue?vue&type=template&id=191c4226&
265126
265126
 
265127
265127
  // CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"d220a428-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/dashboard/DcGraph.vue?vue&type=template&id=7d68029b&
265128
265128
  var DcGraphvue_type_template_id_7d68029b_render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{ref:"main",class:['main-dc', !_vm.isEmbedded ? 'px-2' : '']},[_c('div',{directives:[{name:"show",rawName:"v-show",value:(_vm.loading),expression:"loading"}],staticClass:"overlay"},[_c('v-progress-circular',{staticClass:"loading",attrs:{"width":4,"size":40,"indeterminate":"","color":"primary"}}),_c('div',{staticClass:"mt-6"},[_vm._v("loading records...")])],1),_c('transition',{attrs:{"name":"slide-fade"}},[_c('data-table',{directives:[{name:"show",rawName:"v-show",value:(_vm.showPrefilterTable),expression:"showPrefilterTable"}],attrs:{"model":_vm.model,"params":_vm.params,"open-records-in-new-tab":!_vm.isEmbedded,"title":"Import Into dashboard","info-text":"Search and filter the records you may want to import into the interactive dashboard.","card-classes":"elevation-0 pa-0 mb-12"},on:{"fetch-data":_vm.setOptions}})],1),_c('div',{directives:[{name:"observe-visibility",rawName:"v-observe-visibility",value:(_vm.onVisible),expression:"onVisible"}],staticClass:"dashboard-graphs dc-data-count",attrs:{"id":("dc-data-count-" + _vm.uuid)}},[_c('v-container',{attrs:{"fluid":""}},[_c('v-row',{staticClass:"pb-6 justify-space-between"},[_c('v-col',{staticClass:"pa-0",attrs:{"cols":"4"}},[_c('h2',{staticClass:"isabl-section-title text-left"},[_vm._v(_vm._s(_vm._f("capitalize")(_vm.title || 'Interactive Dashboard')))])]),_c('v-col',{staticClass:"text-center pa-0",attrs:{"cols":"4"}},[_c('span',{staticClass:"filter-count primary--text"}),_vm._v(" selected out of\n "),_c('span',{staticClass:"total-count primary--text"}),(_vm.totalItems && _vm.totalItems > _vm.maxRecords)?_c('span',{staticClass:"total-items"},[_vm._v("\n /\n "),_c('span',{staticClass:"primary--text"},[_c('b',[_vm._v(_vm._s(_vm._f("formatNumber")(_vm.totalItems)))])])]):_vm._e(),_vm._v("\n records\n\n "),(_vm.totalItems && _vm.totalItems > _vm.maxRecords)?_c('v-tooltip',{attrs:{"top":""},scopedSlots:_vm._u([{key:"activator",fn:function(ref){
@@ -291752,7 +291752,7 @@ var DcGraph_component = normalizeComponent(
291752
291752
  // CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/thread-loader/dist/cjs.js!./node_modules/@vue/cli-plugin-babel/node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/dashboard/BaseDashboard.vue?vue&type=script&lang=js&
291753
291753
  var cov_21s3whnekh = function () {
291754
291754
  var path = "/Users/juanes/papaemmelab/isabl_web/src/components/dashboard/BaseDashboard.vue";
291755
- var hash = "80378eaf505b52746695623a345007e2d0c5f9ea";
291755
+ var hash = "0b4078169eae16bef6c925f7ea045fdcabd12d44";
291756
291756
  var global = new Function("return this")();
291757
291757
  var gcv = "__coverage__";
291758
291758
  var coverageData = {
@@ -292644,10 +292644,10 @@ var cov_21s3whnekh = function () {
292644
292644
  mappings: ";;;;;;;;;;;;;;;;;;;;AAoBA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA",
292645
292645
  file: "BaseDashboard.vue",
292646
292646
  sourceRoot: "src/components/dashboard",
292647
- sourcesContent: ["<template>\n <div ref=\"dashboard\">\n <v-card flat class=\"isabl-base-card\">\n <dc-graph\n :model=\"model\"\n :params=\"params\"\n :items=\"items\"\n :figures=\"figures\"\n :loading=\"loading\"\n :max-records=\"maxRecords\"\n :total-items=\"totalItems\"\n :is-embedded=\"isEmbedded\"\n @set-max-records=\"setMaxRecords\"\n @set-options=\"setOptions\"\n />\n </v-card>\n </div>\n</template>\n\n<script>\n import BasePanel from '@/components/base/BasePanel.vue'\n import BaseSectionTitle from '@/components/base/BaseSectionTitle.vue'\n import DataTable from '@/components/table/DataTable.vue'\n import DcGraph from '@/components/dashboard/DcGraph.vue'\n import { fetchListRecords } from '@/utils/api'\n import { SHOW_ALERT } from '@/store/actions/alert'\n\n export default {\n name: 'BaseDashboard',\n components: {\n BasePanel,\n BaseSectionTitle,\n DataTable,\n DcGraph\n },\n props: {\n params: {\n type: Object,\n default: () => ({})\n },\n isEmbedded: {\n type: Boolean,\n default: true\n },\n model: {\n type: String,\n required: true\n },\n figures: {\n type: Array,\n required: true\n },\n requiredFields: {\n type: Array,\n default: () => []\n }\n },\n data() {\n return {\n items: [],\n loading: false,\n maxRecords: 500,\n options: {},\n totalItems: null\n }\n },\n computed: {\n queryFields() {\n const fields = this.figures.map(figure => figure.queryFields)\n // flat and remove duplicates\n return [...new Set(fields.flat())]\n },\n fields() {\n return [\n ...new Set([\n 'pk',\n 'created',\n 'modified',\n 'analytics',\n ...this.requiredFields,\n ...this.queryFields\n ])\n ]\n .filter(i => !!i)\n .map(i => i.replace(/\\./g, '__'))\n }\n },\n created() {\n this.loading = true\n },\n methods: {\n setOptions(options) {\n delete options.offset\n this.options = options\n this.fetchData()\n },\n setMaxRecords(value) {\n if (value !== this.maxRecords) {\n this.maxRecords = value\n this.fetchData()\n }\n },\n fetchData() {\n this.loading = true\n\n const fields = this.fields.map(i => i.replace(/\\./g, '__'))\n fetchListRecords(this.model, {\n ...this.options,\n ...this.params,\n limit: this.maxRecords,\n distinct: true,\n fields,\n 'fields!': ''\n })\n .then(response => {\n this.items = response.results.map(r => {\n const result = {\n ...r,\n ...r.analytics\n }\n delete result.analytics\n return result\n })\n this.totalItems = response.count\n })\n .catch(error => {\n let errorMessage = `Search failed: `\n if (error.response) {\n const errorMessages = Object.values(error.response.data).flat()\n errorMessage += errorMessages.length ? errorMessages[0] : '...'\n }\n this.$store.dispatch(SHOW_ALERT, {\n error: errorMessage\n })\n })\n .finally(() => (this.loading = false))\n }\n }\n }\n</script>\n<style lang=\"scss\">\n.dashboard .panels {\n max-width: 95%;\n max-width: 1800px;\n padding-bottom: 100px;\n}\n</style>\n"]
292647
+ sourcesContent: ["<template>\n <div ref=\"dashboard\">\n <v-card flat class=\"isabl-base-card\">\n <dc-graph\n :model=\"model\"\n :params=\"params\"\n :items=\"items\"\n :figures=\"figures\"\n :loading=\"loading\"\n :max-records=\"maxRecords\"\n :total-items=\"totalItems\"\n :is-embedded=\"isEmbedded\"\n @set-max-records=\"setMaxRecords\"\n @set-options=\"setOptions\"\n />\n </v-card>\n </div>\n</template>\n\n<script>\nimport BasePanel from '@/components/base/BasePanel.vue'\nimport BaseSectionTitle from '@/components/base/BaseSectionTitle.vue'\nimport DataTable from '@/components/table/DataTable.vue'\nimport DcGraph from '@/components/dashboard/DcGraph.vue'\nimport { fetchListRecords } from '@/utils/api'\nimport { SHOW_ALERT } from '@/store/actions/alert'\n\nexport default {\n name: 'BaseDashboard',\n components: {\n BasePanel,\n BaseSectionTitle,\n DataTable,\n DcGraph\n },\n props: {\n params: {\n type: Object,\n default: () => ({})\n },\n isEmbedded: {\n type: Boolean,\n default: true\n },\n model: {\n type: String,\n required: true\n },\n figures: {\n type: Array,\n required: true\n },\n requiredFields: {\n type: Array,\n default: () => []\n }\n },\n data() {\n return {\n items: [],\n loading: false,\n maxRecords: 500,\n options: {},\n totalItems: null\n }\n },\n computed: {\n queryFields() {\n const fields = this.figures.map(figure => figure.queryFields)\n // flat and remove duplicates\n return [...new Set(fields.flat())]\n },\n fields() {\n return [\n ...new Set([\n 'pk',\n 'created',\n 'modified',\n 'analytics',\n ...this.requiredFields,\n ...this.queryFields\n ])\n ]\n .filter(i => !!i)\n .map(i => i.replace(/\\./g, '__'))\n }\n },\n created() {\n this.loading = true\n },\n methods: {\n setOptions(options) {\n delete options.offset\n this.options = options\n this.fetchData()\n },\n setMaxRecords(value) {\n if (value !== this.maxRecords) {\n this.maxRecords = value\n this.fetchData()\n }\n },\n fetchData() {\n this.loading = true\n\n const fields = this.fields.map(i => i.replace(/\\./g, '__'))\n fetchListRecords(this.model, {\n ...this.options,\n ...this.params,\n limit: this.maxRecords,\n distinct: true,\n fields,\n 'fields!': ''\n })\n .then(response => {\n this.items = response.results.map(r => {\n const result = {\n ...r,\n ...r.analytics\n }\n delete result.analytics\n return result\n })\n this.totalItems = response.count\n })\n .catch(error => {\n let errorMessage = `Search failed: `\n if (error.response) {\n const errorMessages = Object.values(error.response.data).flat()\n errorMessage += errorMessages.length ? errorMessages[0] : '...'\n }\n this.$store.dispatch(SHOW_ALERT, {\n error: errorMessage\n })\n })\n .finally(() => (this.loading = false))\n }\n }\n}\n</script>\n<style lang=\"scss\">\n.dashboard .panels {\n max-width: 95%;\n max-width: 1800px;\n padding-bottom: 100px;\n}\n</style>\n"]
292648
292648
  },
292649
292649
  _coverageSchema: "43e27e138ebf9cfc5966b082cf9a028302ed4184",
292650
- hash: "80378eaf505b52746695623a345007e2d0c5f9ea"
292650
+ hash: "0b4078169eae16bef6c925f7ea045fdcabd12d44"
292651
292651
  };
292652
292652
  var coverage = global[gcv] || (global[gcv] = {});
292653
292653
 
@@ -292878,8 +292878,8 @@ var BaseDashboardvue_type_style_index_0_lang_scss_ = __webpack_require__("f624")
292878
292878
 
292879
292879
  var BaseDashboard_component = normalizeComponent(
292880
292880
  dashboard_BaseDashboardvue_type_script_lang_js_,
292881
- BaseDashboardvue_type_template_id_2fd2fca6_render,
292882
- BaseDashboardvue_type_template_id_2fd2fca6_staticRenderFns,
292881
+ BaseDashboardvue_type_template_id_191c4226_render,
292882
+ BaseDashboardvue_type_template_id_191c4226_staticRenderFns,
292883
292883
  false,
292884
292884
  null,
292885
292885
  null,