diff --git a/src/App.vue b/src/App.vue
index bb02f794..c87ce2e9 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,15 +1,15 @@
+
Click arrow to open sidebar
-
+
+
diff --git a/src/components/SearchFilters.vue b/src/components/SearchFilters.vue
index 551be07a..4800c76b 100644
--- a/src/components/SearchFilters.vue
+++ b/src/components/SearchFilters.vue
@@ -1,31 +1,32 @@
+
-
+
+ :show-all-levels="false"
+ :append-to-body="false">
-
+
+
+ Apply Filters
+
+
-
-
- Filter
-
-
-
+
+
+ {{entry.numberOfHits }} Datasets for '{{entry.lastSearch}}' | Showing
-
-
-
-
-
+ >{{this.numberOfResultsText}}
@@ -33,96 +34,96 @@
diff --git a/src/components/SideBar.vue b/src/components/SideBar.vue
index dd70863f..22d01e6a 100644
--- a/src/components/SideBar.vue
+++ b/src/components/SideBar.vue
@@ -3,76 +3,58 @@
+
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
- Title
- Image
-
-
-
-
+
+
+
+ No results found - Please change your search / filter criteria.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Title
- Image
-
-
-
-
+
{{sciCrunchError}}
+
+
+
-
-
+
+
+
@@ -81,17 +63,14 @@
/* eslint-disable no-alert, no-console */
import Vue from "vue";
import {
- Link,
- Icon,
- Card,
Button,
- Select,
- Input,
+ Card,
Drawer,
- Pagination,
+ Icon,
+ Input,
Loading,
+ Pagination,
} from "element-ui";
-import "element-ui/lib/theme-chalk/index.css";
import lang from "element-ui/lib/locale/lang/en";
import locale from "element-ui/lib/locale";
import SearchFilters from "./SearchFilters";
@@ -99,17 +78,27 @@ import DatasetCard from "./DatasetCard";
import EventBus from './EventBus';
locale.use(lang);
-Vue.use(Link);
-Vue.use(Icon);
-Vue.use(Card);
Vue.use(Button);
-Vue.use(Select);
-Vue.use(Input);
+Vue.use(Card);
Vue.use(Drawer);
+Vue.use(Icon);
+Vue.use(Input);
+Vue.use(Loading);
Vue.use(Pagination);
-Vue.use(Loading)
-var api_location = process.env.VUE_APP_API_LOCATION + "filter-search/";
+// handleErrors: A custom fetch error handler to recieve messages from the server
+// even when an error is found
+var handleErrors = async function(response) {
+ if (!response.ok) {
+ let parse = await response.json()
+ if (parse){
+ throw new Error(parse.message)
+ } else {
+ throw new Error(response)
+ }
+ }
+ return response;
+}
var initial_state = {
searchInput: "",
@@ -118,10 +107,14 @@ var initial_state = {
drawerOpen: false,
numberOfHits: 0,
filter:{},
+ filterFacet: undefined,
loadingCards: false,
numberPerPage: 10,
page: 1,
- start: 0
+ pageModel: 1,
+ start: 0,
+ hasSearched: false,
+ sciCrunchError: false
}
export default {
@@ -139,56 +132,60 @@ export default {
entry: {
type: Object,
default: () => (initial_state)
- }
+ },
+ apiLocation: {
+ type: String,
+ default: ""
+ },
},
data: function () {
- return {...this.entry}
+ return {
+ ...this.entry,
+ }
},
computed: {
+ // This computed property populates filter data's entry object with $data from this sidebar
filterEntry: function () {
return {
results: this.results,
lastSearch: this.lastSearch,
numberOfHits: this.numberOfHits,
+ filterFacet: this.filterFacet
};
},
},
- watch: {
- search: function (val) {
- this.searchInput = val;
- this.lastSearch = val;
- },
- },
methods: {
close: function () {
this.drawerOpen = !this.drawerOpen;
- if(this.drawerOpen){
+ if(this.drawerOpen && !this.hasSearched){
this.openSearch(this.searchInput);
}
},
- openSearch: function (search) {
+ openSearch: function (search, filter=undefined) {
this.drawerOpen = true;
- if (this.searchInput !== search){
- this.searchInput = search;
- this.searchSciCrunch(search);
+ this.searchInput = search;
+ this.resetPageNavigation()
+ this.searchSciCrunch(search, filter);
+ if (filter){
+ this.filterFacet = filter[0].facet;
+ EventBus.$emit("filterUiUpdate", filter[0].facet);
}
},
- dock: function(){
- EventBus.$emit("PopoverActionClick", {'type': 'Search', 'entry':this.$data});
- this.drawerOpen = false;
+ clearSearchClicked: function(){
+ this.searchInput = ''
+ this.resetPageNavigation()
+ this.searchSciCrunch(this.searchInput)
},
searchEvent: function (event = false) {
if (event.keyCode === 13 || event instanceof MouseEvent) {
+ this.resetPageNavigation()
this.searchSciCrunch(this.searchInput);
}
},
filterUpdate: function(filter){
- if(filter.facet === undefined){
- this.filter = {}
- } else {
- this.filter = filter
- }
- this.searchSciCrunch(this.searchInput)
+ this.resetPageNavigation()
+ this.searchSciCrunch(this.searchInput, filter);
+ this.filter = filter
},
numberPerPageUpdate: function (val) {
this.numberPerPage = val;
@@ -198,15 +195,51 @@ export default {
this.start = (page-1) * this.numberPerPage;
this.searchSciCrunch(this.searchInput);
},
- searchSciCrunch: function (search) {
+ searchSciCrunch: function (search, filter=undefined) {
this.loadingCards = true;
- let params = this.filter;
- params.size = this.numberPerPage;
- params.start = this.start;
- this.callSciCrunch(api_location, search, params).then((result) => {
- this.resultsProcessing(result);
- this.loadingCards = false;
- });
+ this.results = [];
+ this.disableCards();
+ let params = this.createParams(filter, this.start, this.numberPerPage)
+ this.callSciCrunch(this.apiLocation, this.searchEndpoint, search, params).then((result) => {
+ this.sciCrunchError = false
+ this.resultsProcessing(result)
+ this.$refs.content.style['overflow-y'] = 'scroll'
+ }).catch((result) => {
+ this.sciCrunchError = result.message
+ }).finally(() => {
+ this.loadingCards = false
+ })
+ },
+ disableCards: function(){
+ if(this.$refs.content){
+ this.$refs.content.scroll({top:0, behavior:'smooth'})
+ this.$refs.content.style['overflow-y'] = 'hidden'
+ }
+ },
+ resetPageNavigation: function(){
+ this.start = 0
+ this.page = 1
+ },
+ createParams: function(filter, start, size){
+ var params = {}
+ if (filter !== undefined){
+ params = filter
+ } else {
+ params = this.filter;
+ }
+ if(params.length > 0){
+ for(let i in params){
+ if(params[i].start){
+ params[i].start = start
+ params[i].size = size
+ }
+ }
+ } else {
+ params.start = start
+ params.size = size
+ params = [params]
+ }
+ return params
},
resultsProcessing: function (data) {
this.lastSearch = this.searchInput
@@ -220,42 +253,70 @@ export default {
this.results.push({
description: element.name,
contributors: element.contributors,
- numberSamples: Array.isArray(element.sample)
- ? element.sample.length
+ numberSamples: Array.isArray(element.samples)
+ ? element.samples.length
: 1,
- sexes: element.attributes
- ? element.attributes.sex
- ? [...new Set(element.attributes.map((v) => v.sex.value))]
+ sexes: element.samples
+ ? element.samples[0].sex
+ ? [...new Set(element.samples.map((v) => v.sex.value))]
: undefined
: undefined, // This processing only includes each gender once into 'sexes'
- age: element.attributes
- ? "ageCategory" in element.attributes[0]
- ? element.attributes[0].ageCategory.value
+ organs: (element.organs && element.organs.length > 0)
+ ? [...new Set(element.organs.map((v) => v.name))]
+ : undefined,
+ ages: element.samples
+ ? "ageCategory" in element.samples[0]
+ ? [...new Set(element.samples.map((v) => v.ageCategory.value))]
: undefined
: undefined,
updated: element.updated[0].timestamp.split("T")[0],
- url: element.current[0].uri,
+ url: element.uri[0],
datasetId: element.identifier,
+ csvFiles: element.csvFiles,
id: id,
+ doi: element.doi,
+ scaffold: element.scaffolds ? true : false,
+ scaffolds: element.scaffolds ? element.scaffolds : false
});
id++;
});
},
- callSciCrunch: function (api_location, search, params={}) {
- return new Promise((resolve) => {
- var endpoint = api_location;
+ createfilterParams: function(params){
+ var paramsString = ''
+ for(let param in params){
+ paramsString += (new URLSearchParams(params[param])).toString()
+ paramsString += '&'
+ }
+ paramsString = paramsString.slice(0, -1);
+ return paramsString
+ },
+ callSciCrunch: function (apiLocation, searchEndpoint, search, params={}) {
+ return new Promise((resolve, reject) => {
+ var endpoint = apiLocation + searchEndpoint;
// Add parameters if we are sent them
if (search !== '' && Object.entries(params).length !== 0){
- endpoint = api_location + search + '/?' + (new URLSearchParams(params)).toString();
+ endpoint = endpoint + search + '/?' + this.createfilterParams(params)
+ } else {
+ endpoint = endpoint + '?' + this.createfilterParams(params)
}
+
fetch(endpoint)
+ .then(handleErrors)
.then((response) => response.json())
- .then((data) => {
- resolve(data);
- });
+ .then((data) => resolve(data))
+ .catch((data) => reject(data))
});
},
},
+ created: function () {
+ //Create non-reactive local variables
+ this.searchEndpoint = "filter-search/";
+ },
+ mounted: function() {
+ EventBus.$on("PopoverActionClick", (payLoad) => {
+ this.$emit("actionClick", payLoad);
+ });
+ },
};
@@ -264,21 +325,27 @@ export default {
.side-bar{
position: relative;
height: 100%;
+ pointer-events: none;
+}
+
+.side-bar >>> .el-drawer:focus{
+ outline:none;
}
.open-tab{
width: 20px;
height: 40px;
- z-index: 25;
+ z-index: 8;
position: absolute;
top: calc(50vh - 80px);
right: 0px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06);
- border: solid 1px var(--pale-grey);
+ border: solid 1px #e4e7ed;
background-color: #F7FAFF;
text-align: center;
vertical-align: middle;
cursor: pointer;
+ pointer-events: auto;
}
.el-icon-arrow-left{
@@ -287,7 +354,41 @@ export default {
color: #292b66;
}
-.box-card{
+.el-icon-arrow-right{
+ font-size: 20px;
+ padding-top: 8px;
+ color: #292b66;
+ cursor: pointer;
+ pointer-events: auto;
+}
+
+.close-tab{
+ float: left;
+ flex: 1;
+ width: 20px;
+ height: 40px;
+ z-index: 8;
+ margin-top: calc(50vh - 80px);
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06);
+ border: solid 1px #e4e7ed;
+ border-right: 0;
+ background-color: #F7FAFF;
+ text-align: center;
+ vertical-align: middle;
+ cursor: pointer;
+ pointer-events: auto;
+}
+
+.button{
+ background-color: #8300bf;
+ border: #8300bf;
+ color: white;
+}
+
+.box-card {
+ flex: 3;
+ height: 100%;
+ overflow: hidden;
pointer-events: auto;
}
@@ -296,90 +397,41 @@ export default {
margin-bottom: 18px;
text-align: left;
}
+
.search-input {
- width: 298px;
+ width: 298px!important;
height: 40px;
padding-right: 14px;
align-items: left;
}
.header {
- height: 50px;
border: solid 1px #292b66;
background-color: #292b66;
text-align: left;
}
-.filters {
- witdth: 518px;
-}
-
.pagination {
- padding-top: 10px;
- background-color: #F7FAFF;
+ padding-bottom: 16px;
+ background-color: white;
+ text-align:center;
}
.pagination>>>button{
- background-color: #F7FAFF !important;
+ background-color: white !important;
}
.pagination>>>li{
- background-color: #F7FAFF !important;
+ background-color: white !important;
}
.pagination>>>li.active{
- color: var(--vibrant-purple);
+ color: #8300bf;
}
-.dataset-results-feedback {
- width: 215px;
- height: 16px;
+.error-feedback{
font-family: Asap;
font-size: 14px;
- font-weight: 500;
- font-stretch: normal;
- font-style: normal;
- line-height: normal;
- letter-spacing: normal;
- color: #292b66;
-}
-
-.card-container {
- display: flex;
- position: sticky;
- top:0;
- background-color: white;
- z-index: 300;
- padding-top: 10px;
- height: 20px;
- border-bottom: 1px solid var(--pale-grey);
-}
-
-.dataset-table-title {
- flex: 1.3;
- height: 16px;
- font-family: Asap;
- text-align: left !important;
- padding-left: 16px;
- font-size: 14px;
- font-weight: 500;
- font-stretch: normal;
- font-style: normal;
- line-height: normal;
- letter-spacing: normal;
- color: var(--slate-grey);
-}
-
-.image-table-title {
- flex: 1;
- padding-left: 16px;
- font-family: Asap;
- text-align: left !important;
- font-size: 14px;
- font-weight: 500;
- font-stretch: normal;
- font-style: normal;
- line-height: normal;
- letter-spacing: normal;
- color: var(--slate-grey);
+ font-style: italic;
+ padding-top: 15px;
}
>>> .el-card__header {
@@ -389,47 +441,18 @@ export default {
>>> .el-card__body {
background-color: #f7faff;
-}
-
-.wrapper{
- display: flex;
- flex-direction: row;
-}
-
-.el-icon-copy-document{
- cursor: pointer;
- font-size: 32px;
- width: 16px;
- height: 16px;
- color: #f9f9fa;
- padding-right: 32px;
-}
-
-.el-icon-arrow-right{
- cursor: pointer;
- font-size: 20px;
- top: 50%;
- position: absolute;
- left: 0;
+ height: calc(100% - 8rem);
+ overflow-y: hidden;
}
.content {
width: 518px;
- height: 48rem;
+ height: calc(100vh - 20rem);
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06);
- border: solid 1px var(--pale-grey);
+ border: solid 1px #e4e7ed;
background-color: #ffffff;
overflow-y: scroll;
-}
-
-.box-card {
- height: 100%;
- overflow: auto;
-}
-
-.active {
- width: 380px !important;
- height: 380px !important;
+ scrollbar-width: thin;
}
.scrollbar::-webkit-scrollbar-track {
@@ -439,6 +462,7 @@ export default {
.scrollbar::-webkit-scrollbar {
width: 12px;
+ right: -12px;
background-color: #f5f5f5;
}
@@ -452,13 +476,9 @@ export default {
padding-right: 10px;
}
-
-
\ No newline at end of file
+
+
diff --git a/src/components/index.js b/src/components/index.js
index 799d3f5f..ab9e0247 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -1,15 +1,8 @@
-// The Vue build version to load with the `import` command
-// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
-import Vue from "vue";
import SideBar from "./SideBar.vue"
-const Components = {
- SideBar
- };
-
- Object.keys(Components).forEach(name => {
- Vue.component(name, Components[name]);
- });
-
- export default Components;
-
\ No newline at end of file
+export {
+ SideBar
+};
+
+
+
diff --git a/src/components/scaffold-meta-map.js b/src/components/scaffold-meta-map.js
new file mode 100644
index 00000000..7cbe001f
--- /dev/null
+++ b/src/components/scaffold-meta-map.js
@@ -0,0 +1,5 @@
+export default {
+ 77: {version:2,meta_file:'integrated_metadata.json'},
+ 76: {version:2,meta_file:'mouseColon_metadata.json'},
+ 32: {version:3,meta_file:'mouse-heart-071020_metadata.json'},
+}
diff --git a/vue.config.js b/vue.config.js
index fe205894..40ed2703 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -1 +1,11 @@
-const webpack = require('webpack')
+const nodeExternals = require('webpack-node-externals');
+
+module.exports = {
+ configureWebpack: config => {
+ if(process.env.NODE_ENV === 'production') {
+ //By including element-ui and all abi projects, the problem with element-ui
+ //stylesheet can be avoided.
+ config.externals = [ nodeExternals() ];
+ }
+ },
+}