diff --git a/.env b/.env index 98349f42f..821badb22 100644 --- a/.env +++ b/.env @@ -1,7 +1,6 @@ -# this is for Docker Compose only, to resolve ${...} parameters/expressions -# inside a YAML config file; these values won't automatically override replace -# ARG or ENV values in Dockerfile or containers, unless specified to do so. -PC_URL=http://beta.pathwaycommons.org/ +# webapp +APPUI_IMAGE_TAG=production +APPUI_PORT=3000 +PC_URL=https://www.pathwaycommons.org/ NODE_ENV=production -PORT=9090 -FACTOID_URL=http://unstable.factoid.baderlab.org/ +FACTOID_URL=https://biofactoid.org/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 5eb8276e6..d5841d670 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,5 @@ -# Refer to: -# https://nodejs.org/en/docs/guides/nodejs-docker-webapp/ -# https://github.com/nodejs/docker-node - -# Node.js base image (based on Alpine Linux) -FROM node:8 +# Node.js base image +FROM node:10.24.1 # Create an unprivileged user w/ home directory RUN groupadd appuser && useradd --gid appuser --shell /bin/bash --create-home appuser @@ -24,9 +20,6 @@ RUN NODE_ENV=development npm install ARG NODE_ENV=production ENV NODE_ENV=${NODE_ENV} -RUN npm run clean -RUN npm run build - # Expose port EXPOSE 3000 @@ -34,5 +27,6 @@ EXPOSE 3000 RUN chown appuser:appuser -R /home/appuser/app USER appuser -# Start the application -CMD npm start +# Apply start commands +COPY entrypoint.sh / +CMD ["/entrypoint.sh"] diff --git a/dev-compose.yml b/dev-compose.yml deleted file mode 100644 index b9c8ccd5d..000000000 --- a/dev-compose.yml +++ /dev/null @@ -1,15 +0,0 @@ -version: '3' -services: - pc-apps: - build: - context: . - dockerfile: Dockerfile - args: - NODE_ENV: "${NODE_ENV}" - container_name: pc_apps_dev - ports: - - "${PORT}:3000" - environment: - NODE_ENV: "${NODE_ENV}" - PC_URL: "${PC_URL}" - FACTOID_URL: "${FACTOID_URL}" diff --git a/docker-compose.yml b/docker-compose.yml index 15f0700f3..f3e2a8b78 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,11 +1,18 @@ -version: '3' +version: "3.8" services: webapp: - image: pathwaycommons/app-ui:master - container_name: appui_webapp + image: pathwaycommons/app-ui:${APPUI_IMAGE_TAG:-latest} + restart: unless-stopped + container_name: webapp ports: - - "9090:3000" + - "${APPUI_PORT:-3000}:3000" environment: - NODE_ENV: "production" - PC_URL: "http://www.pathwaycommons.org/" - FACTOID_URL: "http://factoid.baderlab.org/" \ No newline at end of file + PC_URL: + NODE_ENV: + FACTOID_URL: + networks: + - app-ui-network + +networks: + app-ui-network: + driver: bridge diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 000000000..61033e127 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,4 @@ +#!/bin/bash +npm run clean +npm run build +cd /home/appuser/app && npm start \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7a591e978..ca66da560 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "app-ui", - "version": "3.7.0", + "version": "3.8.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index aebad680b..e096cf71d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "app-ui", - "version": "3.7.0", + "version": "3.8.0", "description": "App UI", "repository": { "type": "git", diff --git a/src/client/common/components/contribute.js b/src/client/common/components/contribute.js new file mode 100644 index 000000000..cc21ec7b5 --- /dev/null +++ b/src/client/common/components/contribute.js @@ -0,0 +1,44 @@ +const React = require('react'); +const h = require('react-hyperscript'); +const Popover = require('./popover'); + +const { FACTOID_URL } = require('../../../config'); + +class Contribute extends React.Component { + constructor( props ){ + super( props ); + } + + render(){ + const { text, info } = this.props; + + return h('div.contribute', {}, [ + h('a.plain-link.contribute-popover-link', { + href: `${FACTOID_URL}document/new`, + target: '_blank' + }, text), + h(Popover , { + tippy: { + position: 'bottom', + html: h('div.contribute-popover', [info] ) + } + }, [ h('i.material-icons', 'info') ] + ) + ]); + } +} + +// Specifies the default values for props: +Contribute.defaultProps = { + text: 'Add my data', + info: h('div.contribute-popover-info', { + }, [ + `Authors of primary research articles with pathway and interaction information (e.g. binding, transcription) can contribute these findings to Pathway Commons through Biofactoid. Learn more at `, + h('a.plain-link', { + href: `${FACTOID_URL}`, + target: '_blank' + }, 'biofactoid.org'), '.' + ]), +}; + +module.exports = { Contribute }; \ No newline at end of file diff --git a/src/client/common/components/pc-logo-link.js b/src/client/common/components/pc-logo-link.js index b4dc4ceac..7862e9310 100644 --- a/src/client/common/components/pc-logo-link.js +++ b/src/client/common/components/pc-logo-link.js @@ -1,12 +1,11 @@ const React = require('react'); const h = require('react-hyperscript'); const classNames = require('classnames'); -const { PC_URL } = require('../../../config'); class PcLogoLink extends React.Component { render() { let cn = this.props.className; - return h('a', { href: PC_URL }, [ h('div', { className: classNames('pc-logo', cn) }) ]); + return h('a', { href: '/' }, [ h('div', { className: classNames('pc-logo', cn) }) ]); } } diff --git a/src/client/features/enrichment/index.js b/src/client/features/enrichment/index.js index ced49216d..be5aca01f 100644 --- a/src/client/features/enrichment/index.js +++ b/src/client/features/enrichment/index.js @@ -14,6 +14,7 @@ const { ServerAPI } = require('../../services'); const { enrichmentLayout, enrichmentStylesheet, bindEvents } = require('./cy'); const { TimeoutError } = require('../../../util'); const { ErrorMessage } = require('../../common/components/error-message'); +const { Contribute } = require('../../common/components/contribute'); const MAX_ELEMENTS_CUTOFF = 3; const LIST_ELEMENTS_SHOWN = MAX_ELEMENTS_CUTOFF - 1; @@ -112,7 +113,8 @@ class Enrichment extends React.Component { h(PcLogoLink), h('div.app-bar-title', titleContent) ]), - h(EnrichmentToolbar, { cySrv, sources: this.state.sources, controller: this }) + h(EnrichmentToolbar, { cySrv, sources: this.state.sources, controller: this }), + h(Contribute, { text: 'Add my pathway' }) ]); return !errorMessage ? h('div.enrichment', [ diff --git a/src/client/features/interactions/index.js b/src/client/features/interactions/index.js index 6e2ea2adb..ecb89547c 100644 --- a/src/client/features/interactions/index.js +++ b/src/client/features/interactions/index.js @@ -20,6 +20,7 @@ const MAX_ELEMENTS_CUTOFF = 3; const LIST_ELEMENTS_SHOWN = MAX_ELEMENTS_CUTOFF - 1; const InteractionsMenu = require('./interactions-menu'); +const { Contribute } = require('../../common/components/contribute'); class Interactions extends React.Component { constructor(props) { @@ -110,7 +111,8 @@ class Interactions extends React.Component { h(PcLogoLink), h('div.app-bar-title', titleContent) ]), - h(InteractionsToolbar, { cySrv, activeMenu, sources: this.state.sources, controller: this }) + h(InteractionsToolbar, { cySrv, activeMenu, sources: this.state.sources, controller: this }), + h(Contribute, { text: 'Add my interactions' }) ]); let interactionsLegend = h('div.interactions-legend', [ diff --git a/src/client/features/pathways/index.js b/src/client/features/pathways/index.js index b27c9685d..66d8813dd 100644 --- a/src/client/features/pathways/index.js +++ b/src/client/features/pathways/index.js @@ -15,6 +15,7 @@ const { stylesheet, bindCyEvents, PATHWAYS_LAYOUT_OPTS } = require('./cy'); const { TimeoutError } = require('../../../util'); const { ErrorMessage } = require('../../common/components/error-message'); +const { Contribute } = require('../../common/components/contribute'); class Pathways extends React.Component { constructor(props) { @@ -91,7 +92,8 @@ class Pathways extends React.Component { h('a.plain-link', { href: pathway.datasourceUrl(), target: '_blank' }, ' ' + pathway.datasource()) ]) ]), - h(PathwaysToolbar, { cySrv, pathway, downloadOpts }) + h(PathwaysToolbar, { cySrv, pathway, downloadOpts }), + h(Contribute, { text: 'Add my pathway' }) ]); let content = !errorMessage ? [ diff --git a/src/client/features/search/index.js b/src/client/features/search/index.js index 5004515b4..9478e7be4 100644 --- a/src/client/features/search/index.js +++ b/src/client/features/search/index.js @@ -2,7 +2,7 @@ const React = require('react'); const h = require('react-hyperscript'); const Link = require('react-router-dom').Link; const Loader = require('react-loader'); - +const classNames = require('classnames'); const queryString = require('query-string'); const _ = require('lodash'); @@ -15,6 +15,9 @@ const { GeneResultsView } = require('./gene-results-view'); const { TimeoutError } = require('../../../util'); const { ErrorMessage } = require('../../common/components/error-message'); const { FeatureView } = require('./feature-view'); +const { Contribute } = require('../../common/components/contribute'); + +const { PC_URL } = require('../../../config'); class Search extends React.Component { @@ -117,6 +120,11 @@ class Search extends React.Component { const searchListing = h(Loader, { loaded: !loading, options: { left: '50%', color: '#16A085' } }, [ h('div', [ + h('h2', { + className: classNames({ + 'hidden': _.isEmpty(geneResults) && _.isEmpty(searchHits) + }) + }, 'Explore how your query is connected to millions of curated interactions'), h(FeatureView, { feature }), h(GeneResultsView, { geneResults } ), h(PathwayResultsView, { searchHits, query, controller: this, dataSources, hasFeature: feature != null }) @@ -134,6 +142,39 @@ class Search extends React.Component { let searchBody = errorMessage ? errorMessage : searchListing; return h('div.search', [ + h('div.search-nav-links', [ + h('a', { + href: PC_URL, + target: '_blank' + }, 'About'), + + h('a', { + href: PC_URL + '#faq', + target: '_blank' + }, 'FAQ'), + + h('a', { + href: PC_URL + '#training', + target: '_blank' + }, 'Training'), + + h('a', { + href: PC_URL + '#data', + target: '_blank' + }, 'Data'), + + // h('a', { + // href: PC_URL + '#tools', + // target: '_blank' + // }, 'Tools'), + + h('a', { + href: PC_URL + '#contact', + target: '_blank' + }, 'Contact'), + + h(Contribute, {text: 'Contribute to PC'}) + ]), h('div.search-header', [ h('div.search-branding', [ h(PcLogoLink, { className: 'search-logo'} ), diff --git a/src/styles/common/contribute.css b/src/styles/common/contribute.css new file mode 100644 index 000000000..31fb2e6f0 --- /dev/null +++ b/src/styles/common/contribute.css @@ -0,0 +1,26 @@ +.contribute { + position: absolute; + margin: 0.5em 0; + left: 0.25em; + + & i { + margin: 0em 0.25em; + color: var(--widgetDisabledTextColor); + } + + & i:hover { + cursor: pointer; + } +} + +.contribute-popover-info { + max-width: 30em; + padding: 0.5em; +} + +@media( --small-width-viewport ){ + .contribute-popover-info { + font-size: 0.8em; + } +} + diff --git a/src/styles/common/index.css b/src/styles/common/index.css index ea0eda233..47e23e51e 100644 --- a/src/styles/common/index.css +++ b/src/styles/common/index.css @@ -11,3 +11,4 @@ @import "./tooltip.css"; @import "./card.css"; @import "./app-card.css"; +@import "./contribute.css"; diff --git a/src/styles/features/search.css b/src/styles/features/search.css index d9ffcaf80..c1d2a56dd 100644 --- a/src/styles/features/search.css +++ b/src/styles/features/search.css @@ -3,6 +3,31 @@ width: 100vw; } +.search .hidden { + display: none; +} + +.search-nav-links { + display: flex; + justify-content: flex-start; + align-items: flex-start; + padding: 0em 0.5em; +} + +.search-nav-links a { + padding: 1em 1em; + /* background: cyan; */ +} + +.search-nav-links .contribute { + position: relative; + margin: 1em; + + & a { + padding: 0; + } +} + .search-header { display: flex; justify-content: flex-start; @@ -335,6 +360,10 @@ } @media (--small-width-viewport) { + .search-nav-links { + display: none; + } + .search-header { display: block; }