From 447639266aeb5e044d9d6bc769227a85d28ec695 Mon Sep 17 00:00:00 2001 From: Jeffrey Wong Date: Mon, 15 Jan 2024 13:40:15 -0500 Subject: [PATCH 1/7] Don't track pathway snapshots --- .gitignore | 1 + public/img/pathways/.gitkeep | 0 2 files changed, 1 insertion(+) create mode 100644 public/img/pathways/.gitkeep diff --git a/.gitignore b/.gitignore index 111dd6b33..2e6258694 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ src/scripts/jsonld/* /nohup.out src/*.gmt downloads/* +public/img/pathways/*.png diff --git a/public/img/pathways/.gitkeep b/public/img/pathways/.gitkeep new file mode 100644 index 000000000..e69de29bb From f3fddeb62bab260b58dd01f0d27e9560aeda8cb4 Mon Sep 17 00:00:00 2001 From: Jeffrey Wong Date: Mon, 15 Jan 2024 16:36:16 -0500 Subject: [PATCH 2/7] Preview the top pathway hit --- .../features/search/pathway-results-view.js | 27 ++++++++++++------- .../external-services/pathway-commons.js | 19 +++++++++++++ src/styles/features/search.css | 16 ++++++++++- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/client/features/search/pathway-results-view.js b/src/client/features/search/pathway-results-view.js index a35d65a68..b6b749b97 100644 --- a/src/client/features/search/pathway-results-view.js +++ b/src/client/features/search/pathway-results-view.js @@ -3,6 +3,7 @@ const h = require('react-hyperscript'); const Link = require('react-router-dom').Link; const queryString = require('query-string'); const _ = require('lodash'); +const classNames = require('classnames'); const { ErrorMessage } = require('../../common/components/error-message'); @@ -19,20 +20,28 @@ class PathwayResultsView extends React.Component { return null; } - const searchList = pathwayResults.map(result => { + const searchList = pathwayResults.map( ( result, index ) => { let dsInfo = _.get( result, 'sourceInfo', '' ); let iconUrl = dsInfo.iconUrl || ''; let name = dsInfo.name || ''; + const topHit = index === 0; + const hasPreview = result.previewUrl; + const showPreview = topHit && hasPreview; - return h('div.search-item', [ - h('div.search-item-icon',[ - h('img', {src: iconUrl}) + return h('div.search-item', { + className: classNames({ 'featured': showPreview }) + }, [ + h('div.search-item-info', [ + h('div.search-item-icon',[ + h('img', {src: iconUrl}) + ]), + h('div.search-item-content', [ + h(Link, { className: 'plain-link', to: { pathname: '/pathways', search: queryString.stringify({ uri: result.uri }) }, target: '_blank' }, [result.name || 'N/A']), + h('p.search-item-content-datasource', ` ${name}`), + h('p.search-item-content-participants', `${result.numParticipants} Participants`) + ]) ]), - h('div.search-item-content', [ - h(Link, { className: 'plain-link', to: { pathname: '/pathways', search: queryString.stringify({ uri: result.uri }) }, target: '_blank' }, [result.name || 'N/A']), - h('p.search-item-content-datasource', ` ${name}`), - h('p.search-item-content-participants', `${result.numParticipants} Participants`) - ]) + showPreview ? h('img.search-item-preview', {src: result.previewUrl}) : null ]); }); diff --git a/src/server/external-services/pathway-commons.js b/src/server/external-services/pathway-commons.js index 129451ac5..43b3bd7e1 100644 --- a/src/server/external-services/pathway-commons.js +++ b/src/server/external-services/pathway-commons.js @@ -1,3 +1,5 @@ +const fs = require('fs'); +const path = require('path'); const qs = require('query-string'); const url = require('url'); const QuickLRU = require('quick-lru'); @@ -105,7 +107,24 @@ const addSourceInfo = async function( searchHit, dataSources ) { return searchHit; }; +// Fill in preview URL +const addPreviewUrl = function( searchHit ) { + // see https://github.com/PathwayCommons/app-ui/pull/1443 for config vars/functions + const SBGN_IMG_PATH = 'public/img/pathways'; + const uri2filename = s => s.replace(/[^a-z0-9]/gi, '_').toLowerCase(); + const { uri } = searchHit; + const fname = uri2filename( uri ); + const fpath = path.resolve( SBGN_IMG_PATH, `${fname}.png` ); + const hasImage = fs.existsSync( fpath ); + if ( hasImage ){ + const previewUrl = fpath.split( path.sep ).slice(-3).join(path.sep); + searchHit.previewUrl = previewUrl; + } + return searchHit; +}; + const augmentSearchHits = async function( searchHits ) { + if( searchHits.length ) addPreviewUrl( searchHits[0] ); const dataSources = await getDataSourcesMap(); return Promise.all( searchHits.map( searchHit => addSourceInfo( searchHit, dataSources ) ) ); }; diff --git a/src/styles/features/search.css b/src/styles/features/search.css index c1d2a56dd..f42eae1cc 100644 --- a/src/styles/features/search.css +++ b/src/styles/features/search.css @@ -201,10 +201,17 @@ } .search-item { + padding: 1em 0; +} + +.search-item.featured { + background-color: var(--cloud); +} + +.search-item-info { display: flex; vertical-align: middle; align-items: center; - padding: 1em 0; } .search-item-icon { @@ -238,6 +245,13 @@ font-size: 0.66em; } +.search-item-preview { + display: block; + margin-left: auto; + margin-right: auto; + width: 70%; +} + .loader { color: var(--accent-1-colour); } From 2a3514248224507102d68c1465d669c87dc1838c Mon Sep 17 00:00:00 2001 From: Jeffrey Wong Date: Mon, 15 Jan 2024 16:59:42 -0500 Subject: [PATCH 3/7] No preview bkg: source icon white bkg --- src/client/features/search/pathway-results-view.js | 2 +- src/styles/features/search.css | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/client/features/search/pathway-results-view.js b/src/client/features/search/pathway-results-view.js index b6b749b97..001fe0fb7 100644 --- a/src/client/features/search/pathway-results-view.js +++ b/src/client/features/search/pathway-results-view.js @@ -29,7 +29,7 @@ class PathwayResultsView extends React.Component { const showPreview = topHit && hasPreview; return h('div.search-item', { - className: classNames({ 'featured': showPreview }) + className: classNames({ 'preview': showPreview }) }, [ h('div.search-item-info', [ h('div.search-item-icon',[ diff --git a/src/styles/features/search.css b/src/styles/features/search.css index f42eae1cc..6db7ef31a 100644 --- a/src/styles/features/search.css +++ b/src/styles/features/search.css @@ -204,8 +204,9 @@ padding: 1em 0; } -.search-item.featured { - background-color: var(--cloud); +.search-item.preview { + /* background-color: var(--cloud); */ + border: 1px solid var(--cloud-darker); } .search-item-info { From a05d6084ff9863f0698450894cf32ec3e176e5b7 Mon Sep 17 00:00:00 2001 From: Jeffrey Wong Date: Tue, 16 Jan 2024 09:54:51 -0500 Subject: [PATCH 4/7] Revert gitignore --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 2e6258694..defbe541f 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,4 @@ src/scripts/jsonld/* /.idea/ /nohup.out src/*.gmt -downloads/* -public/img/pathways/*.png +downloads/* \ No newline at end of file From 73e7cb5963a288219d4a5b9fd0a0f92a6806a762 Mon Sep 17 00:00:00 2001 From: Jeffrey Wong Date: Tue, 16 Jan 2024 13:12:48 -0500 Subject: [PATCH 5/7] Ignore all pathway snapshots. --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index defbe541f..f6aff726f 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,6 @@ src/scripts/jsonld/* /.idea/ /nohup.out src/*.gmt -downloads/* \ No newline at end of file +downloads/* +public/img/pathways/* +!/**/.gitkeep \ No newline at end of file From dfb855b71689c4d8bc583e56d8b61e089ff49d05 Mon Sep 17 00:00:00 2001 From: Jeffrey Wong Date: Mon, 29 Jan 2024 10:17:45 -0500 Subject: [PATCH 6/7] Make uri converter to utilities. --- src/scripts/cli.js | 4 +--- src/server/external-services/pathway-commons.js | 6 ++---- src/util/uri.js | 6 ++++++ 3 files changed, 9 insertions(+), 7 deletions(-) create mode 100644 src/util/uri.js diff --git a/src/scripts/cli.js b/src/scripts/cli.js index 62a214f20..950f4a486 100644 --- a/src/scripts/cli.js +++ b/src/scripts/cli.js @@ -9,6 +9,7 @@ const fsPromises = require('fs').promises; const readline = require( 'readline' ); const retry = require( 'async-retry' ); +const { uri2filename } = require( '../util/uri.js' ); const logger = require( '../server/logger.js' ); const { DOWNLOADS_FOLDER_NAME, @@ -169,9 +170,6 @@ const parsePCGmtLine = line => { return { uri, meta, genes }; }; -// Create file safe names from a uri -const uri2filename = s => s.replace(/[^a-z0-9]/gi, '_').toLowerCase(); - async function getStore( ) { const store = { async save( item ){ diff --git a/src/server/external-services/pathway-commons.js b/src/server/external-services/pathway-commons.js index 43b3bd7e1..13ad190de 100644 --- a/src/server/external-services/pathway-commons.js +++ b/src/server/external-services/pathway-commons.js @@ -10,6 +10,7 @@ const { cachePromise } = require('../cache'); const { fetch } = require('../../util'); const logger = require('../logger'); const config = require('../../config'); +const { uri2filename } = require('../../util/uri.js'); const xrefCache = new QuickLRU({ maxSize: config.PC_CACHE_MAX_SIZE }); const queryCache = new QuickLRU({ maxSize: config.PC_CACHE_MAX_SIZE }); @@ -109,12 +110,9 @@ const addSourceInfo = async function( searchHit, dataSources ) { // Fill in preview URL const addPreviewUrl = function( searchHit ) { - // see https://github.com/PathwayCommons/app-ui/pull/1443 for config vars/functions - const SBGN_IMG_PATH = 'public/img/pathways'; - const uri2filename = s => s.replace(/[^a-z0-9]/gi, '_').toLowerCase(); const { uri } = searchHit; const fname = uri2filename( uri ); - const fpath = path.resolve( SBGN_IMG_PATH, `${fname}.png` ); + const fpath = path.resolve( config.SBGN_IMG_PATH, `${fname}.png` ); const hasImage = fs.existsSync( fpath ); if ( hasImage ){ const previewUrl = fpath.split( path.sep ).slice(-3).join(path.sep); diff --git a/src/util/uri.js b/src/util/uri.js new file mode 100644 index 000000000..2373f1b7e --- /dev/null +++ b/src/util/uri.js @@ -0,0 +1,6 @@ +// Create file safe names from a uri +const uri2filename = s => s.replace(/[^a-z0-9]/gi, '_').toLowerCase(); + +module.exports = { + uri2filename +}; \ No newline at end of file From 343fd046767fa6fa2479842f7a9440ea7e5e460d Mon Sep 17 00:00:00 2001 From: Jeffrey Wong Date: Mon, 29 Jan 2024 11:57:54 -0500 Subject: [PATCH 7/7] Wrap the entire preview as a Link, otherwise Link to pathway title --- .../features/search/pathway-results-view.js | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/client/features/search/pathway-results-view.js b/src/client/features/search/pathway-results-view.js index 001fe0fb7..84670c88a 100644 --- a/src/client/features/search/pathway-results-view.js +++ b/src/client/features/search/pathway-results-view.js @@ -24,25 +24,39 @@ class PathwayResultsView extends React.Component { let dsInfo = _.get( result, 'sourceInfo', '' ); let iconUrl = dsInfo.iconUrl || ''; let name = dsInfo.name || ''; + const pathwayTitle = result.name; const topHit = index === 0; const hasPreview = result.previewUrl; const showPreview = topHit && hasPreview; - - return h('div.search-item', { - className: classNames({ 'preview': showPreview }) - }, [ - h('div.search-item-info', [ - h('div.search-item-icon',[ - h('img', {src: iconUrl}) - ]), - h('div.search-item-content', [ - h(Link, { className: 'plain-link', to: { pathname: '/pathways', search: queryString.stringify({ uri: result.uri }) }, target: '_blank' }, [result.name || 'N/A']), - h('p.search-item-content-datasource', ` ${name}`), - h('p.search-item-content-participants', `${result.numParticipants} Participants`) - ]) + + let item; + const itemLink = children => h(Link, { className: 'plain-link', to: { pathname: '/pathways', search: queryString.stringify({ uri: result.uri }) }, target: '_blank' }, children || 'N/A'); + const itemPreview = h('img.search-item-preview', {src: result.previewUrl}); + const itemInfo = title => h('div.search-item-info', [ + h('div.search-item-icon', [ + h('img', {src: iconUrl}) ]), - showPreview ? h('img.search-item-preview', {src: result.previewUrl}) : null + h('div.search-item-content', [ + title, + h('p.search-item-content-datasource', ` ${name}`), + h('p.search-item-content-participants', `${result.numParticipants} Participants`) + ]) ]); + + if( showPreview ){ + // Wrap the entire item in a link + item = itemLink([ + itemInfo( pathwayTitle ), + itemPreview + ]); + } else { + // Associate the link with the content + item = itemInfo( itemLink( pathwayTitle ) ); + } + + return h('div.search-item', { + className: classNames({ 'preview': showPreview }) + }, item ); }); const searchResultFilter = h('div.search-filters', [