Skip to content

Commit

Permalink
Pull store lists from store API
Browse files Browse the repository at this point in the history
* Newest, cancer resources, and clinical relevance sections are pulled
  from store.opencravat.org
* If the store API can't be reached, it will revert back to organizing
  those sections as before
	* newest - 10 most recently updated annotators
	* cancer and clinical relevance - all annotators with those
	  terms as tags
  • Loading branch information
skanderson authored and kmoad committed Dec 16, 2024
1 parent a063652 commit 8b41efa
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 35 deletions.
16 changes: 16 additions & 0 deletions cravat/store_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ def manifest_nover(self):
def download_counts(self):
return self._build_path(self.base(), "download-counts.yml")

def featured_module_list(self):
return self._build_path(self.base(), "store.json")


def blank_stage_handler(*args, **kwargs):
pass
Expand Down Expand Up @@ -200,6 +203,19 @@ def get_file_to_string(url):
raise HTTPError(url, r.status_code, "", None, None)


def get_file_to_json(url):
"""
Sends a GET request to the given url and returns the response body as a dict
Errors during the GET request are unhandled by this method
"""
r = requests.get(url, timeout=(3, None))
if r.status_code == 200:
return r.json()
else:
raise HTTPError(url, r.status_code, "", None, None)


def file_checksum(path):
"""
Get the md5 checksum of a file.
Expand Down
89 changes: 58 additions & 31 deletions cravat/webstore/nocache/webstore.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,33 @@ function getMostDownloadedModuleNames() {
return top10ModuleNames;
}

function fetchCuratedStoreList() {
// fetch('/store/nocache/store.json')
fetch('/store/lists')
.then(response => {
if (!response.ok) {
console.warn('Could not load OpenCRAVAT store featured list.', response);
return null;
}
return response.json();
})
.then(data => {
OC.storeModuleList = data;
})
.catch(function() {
console.warn('Could not load OpenCRAVAT store featured list.');
OC.storeModuleList = null;
});
}

function getNewestModuleNames() {
// if we have a curated list, return the list of module names
if (OC.storeModuleList && OC.storeModuleList?.latest) {
return OC.storeModuleList.latest
.map(m => m.module)
.filter(name => Object.hasOwn(OC.remoteModuleInfo, name));
}
// else fall back to returning the 10 most recently published
var moduleNames = Object.keys(OC.remoteModuleInfo);
for (var i = 0; i < moduleNames.length; i++) {
for (var j = i + 1; j < moduleNames.length - 1; j++) {
Expand Down Expand Up @@ -379,6 +405,30 @@ function getNewestModuleNames() {
return top10ModuleNames;
}

function getModuleListByCategory(category) {
// if we have a curated list, return the list of module names
if (OC.storeModuleList && OC.storeModuleList[category]) {
return OC.storeModuleList[category]
.map(m => m.module)
.filter(name => Object.hasOwn(OC.remoteModuleInfo, name));
}

// fallback to searching for remote modules with 'category' as a tag
var modules = [];
var remoteModuleNames = Object.keys(OC.remoteModuleInfo);
for (var i = 0; i < remoteModuleNames.length; i++) {
var remoteModuleName = remoteModuleNames[i];
var remoteModule = OC.remoteModuleInfo[remoteModuleName];
if (remoteModule['groups'].length > 0) {
continue;
}
if (remoteModule['tags'].includes(category)) {
modules.push(remoteModuleName);
}
}
return modules;
}

function getHomeCarouselContent (modules, type) {
var sdiv = getEl('div');
sdiv.style.width = (Math.ceil(modules.length / OC.numModulesInHomeSectionRow) * OC.storeTileWidthStep) + 'px'
Expand Down Expand Up @@ -417,39 +467,13 @@ function populateStoreHome() {
var div = document.getElementById('store-home-cancerdiv');
$(div).empty();
var sdiv = getEl('div');
var cancerModules = [];
var remoteModuleNames = Object.keys(OC.remoteModuleInfo);
for (var i = 0; i < remoteModuleNames.length; i++) {
var remoteModuleName = remoteModuleNames[i];
var remoteModule = OC.remoteModuleInfo[remoteModuleName];
if (remoteModule['groups'].length > 0) {
continue;
}
if (remoteModule['tags'].includes('cancer')) {
cancerModules.push(remoteModuleName);
}
}
OC.moduleLists['cancer'] = cancerModules;
var sdiv = getHomeCarouselContent(cancerModules, 'cancer')
OC.moduleLists['cancer'] = getModuleListByCategory('cancer');
var sdiv = getHomeCarouselContent(OC.moduleLists['cancer'], 'cancer')
addEl(div, sdiv);
// Clinical Relevance
var div = document.getElementById('store-home-clinicaldiv');
$(div).empty();
var sdiv = getEl('div');
var clinicalModules = [];
var remoteModuleNames = Object.keys(OC.remoteModuleInfo);
for (var i = 0; i < remoteModuleNames.length; i++) {
var remoteModuleName = remoteModuleNames[i];
var remoteModule = OC.remoteModuleInfo[remoteModuleName];
if (remoteModule['groups'].length > 0) {
continue;
}
if (remoteModule['tags'].includes('clinical relevance')) {
clinicalModules.push(remoteModuleName);
}
}
OC.moduleLists['clinical'] = clinicalModules;
var sdiv = getHomeCarouselContent(clinicalModules, 'clinical')
OC.moduleLists['clinical'] = getModuleListByCategory('clinical');
var sdiv = getHomeCarouselContent(OC.moduleLists['clinical'], 'clinical');
addEl(div, sdiv);
}

Expand Down Expand Up @@ -1872,7 +1896,10 @@ function addWebstoreEventHandlers() {

}

$(document).ready(() => addWebstoreEventHandlers());
$(document).ready(() => {
addWebstoreEventHandlers();
fetchCuratedStoreList();
});

export {
addWebstoreEventHandlers,
Expand Down
8 changes: 8 additions & 0 deletions cravat/webstore/webstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,13 @@ async def get_module_dependencies (request):
deps = au.get_install_deps(module)
return web.json_response(deps)

async def get_featured_module_lists(request):
pb = su.PathBuilder(au.get_system_conf()['store_url'], "url")
list_url = pb.featured_module_list()
featured_list = su.get_file_to_json(list_url)
return web.json_response(featured_list)


routes = []
routes.append(['GET', '/store/remote', get_remote_manifest])
routes.append(['GET', '/store/installwidgetsformodule', install_widgets_for_module])
Expand All @@ -421,3 +428,4 @@ async def get_module_dependencies (request):
routes.append(['GET', '/store/localasremote', get_remote_manifest_from_local])
routes.append(['GET', '/store/locallogo', get_local_module_logo])
routes.append(['GET', '/store/moduledependencies', get_module_dependencies])
routes.append(['GET', '/store/lists', get_featured_module_lists])
4 changes: 0 additions & 4 deletions cravat/websubmit/nocache/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -235,28 +235,24 @@
<div id='store-home-div'>
<div class='store-home-sectiondiv'>
<div class='store-home-sectiontitle'>Most Downloaded</div>
<div>The most downloaded modules to date!</div>
<img src='/store/images/left_arrow.png' class='store-carousel-arrow carousel-left' />
<div id='store-home-featureddiv' class='store-home-carouseldiv'></div>
<img src='/store/images/right_arrow.png' class='store-carousel-arrow carousel-right' />
</div>
<div class='store-home-sectiondiv'>
<div class='store-home-sectiontitle'>Newest</div>
<div>The newest and greatest!</div>
<img src='/store/images/left_arrow.png' class='store-carousel-arrow carousel-left' />
<div id='store-home-newestdiv' class='store-home-carouseldiv'></div>
<img src='/store/images/right_arrow.png' class='store-carousel-arrow carousel-right' />
</div>
<div class='store-home-sectiondiv'>
<div class='store-home-sectiontitle'>Cancer Resources</div>
<div>Cutting edge resources for cancer research!</div>
<img src='/store/images/left_arrow.png' class='store-carousel-arrow carousel-left' />
<div id='store-home-cancerdiv' class='store-home-carouseldiv'></div>
<img src='/store/images/right_arrow.png' class='store-carousel-arrow carousel-right' />
</div>
<div class='store-home-sectiondiv'>
<div class='store-home-sectiontitle'>Clinical Relevance</div>
<div>Our curation of clinically-relevant resources!</div>
<img src='/store/images/left_arrow.png' class='store-carousel-arrow carousel-left' />
<div id='store-home-clinicaldiv' class='store-home-carouseldiv'></div>
<img src='/store/images/right_arrow.png' class='store-carousel-arrow carousel-right' />
Expand Down

0 comments on commit 8b41efa

Please sign in to comment.