Skip to content
This repository has been archived by the owner on Feb 13, 2024. It is now read-only.

Commit

Permalink
feat: introduced dumb components
Browse files Browse the repository at this point in the history
  • Loading branch information
xgui3783 committed Feb 23, 2021
1 parent 6787930 commit fc58c7c
Show file tree
Hide file tree
Showing 19 changed files with 1,141 additions and 317 deletions.
13 changes: 7 additions & 6 deletions deploy/common/weave.esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ class BaseSvg{
}

static GenerateLabel(label) {
const { latex } = label

const trueLatex = latex.replace(/^\$*/, '').replace(/\$*$/, '') //.replace(/^\\+/, '\\')
const { latex, label: fallbackLabel } = label
const trueLatex = latex
? latex.replace(/^\$*/, '').replace(/\$*$/, '') //.replace(/^\\+/, '\\')
: fallbackLabel
const _ = mathjax.tex2svg(trueLatex, { display: true })
const { width, height } = _.children[0].attributes
return {
Expand Down Expand Up @@ -284,10 +285,10 @@ class PolarSvg extends BaseSvg{
}

// append radial guide lines
const receptors = this.polarData.map(({ receptor }) => {
const receptors = this.polarData.map(({ receptor, ...rest }) => {
const { label: cLabel } = receptor
const found = this.metadata.find(({ receptor: mReceptor }) => mReceptor.label === cLabel)
return found && found.receptor || null
const found = (this.metadata || []).find(({ receptor: mReceptor }) => mReceptor.label === cLabel)
return found && found.receptor || { label: cLabel }
})

const radialGuideLineContainers = graphContainer.selectAll('g')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ const got = require('got')
const sharp = require('sharp')
const { PassThrough } = require('stream')
const d3 = require('d3')
const tmp = require('tmp')
const fs = require('fs')
const { exec } = require('child_process')

const { DS_SINGLE_PRV_KEY, APP_NAME } = require('../constants')
const { getPreviewsHandler } = require('./getPreviews')
const { getSinglePreview } = require('./getSinglePreview')
const { store } = require('../store')
const { weave } = require('../common/weave')
const { queryToParamMiddleware } = require('./util')
const { DS_SINGLE_PRV_KEY, APP_NAME } = require('../../constants')
const { getPreviewsHandler } = require('../getPreviews')
const { getSinglePreview } = require('../getSinglePreview')
const { store } = require('../../store')
const { weave } = require('../../common/weave')
const { queryToParamMiddleware } = require('../util')
const { getGzipSharpStream, setBufferToStore } = require('./util')

let LinearSvg, PolarSvg, parseFingerprint, parseReceptorMetadata, parseReceptorProfile
const mathjaxInitPr = require('mathjax').init({
Expand Down Expand Up @@ -79,7 +77,8 @@ router.get('/',
passThrough.on('end', () => {
if (buf.length === 0) return
const totalBuffer = Buffer.concat(buf)
store.set(getStoreKey({ datasetId, filename }), totalBuffer.toString('base64'))
const key = getStoreKey({ datasetId, filename })
setBufferToStore(key, totalBuffer)
})

const { mimetype } = singlePrv
Expand All @@ -91,33 +90,19 @@ router.get('/',
_url = _url.replace(`${key}:`, contexts[key])
}

tmp.file({ postfix: '.tif' }, (err, filePath, fd, cleancb) => {
if (err) {
console.error(`[${APP_NAME}] generating temp file error`, err)
res.status(500).send(err)
return
}

exec(`curl -o ${filePath} '${_url}'`, (err, stdout, stderr) => {
if (err) {
console.error(err)
return res.status(500).send(err)
}
res.setHeader('Content-Type', 'image/png')
res.setHeader('Content-Encoding', 'gzip')

res.setHeader('Content-Type', 'image/png')
res.setHeader('Content-Encoding', 'gzip')

sharp(filePath)
.png()
.pipe(gzip)
.pipe(passThrough)
.pipe(res)
.on('finish', () => {
fs.unlink(filePath, () => cleancb())
})
})
const s = await getGzipSharpStream(_url)

s.on('error', err => {
res.status(500).send(err)
})

// getGzipSharpStream already caches
// passthrough remains, for backwards compat reason
s.pipe(res)

/**
* got fetching tiff does not seem to work on OKD. save to file with curl, then read from file instead
*/
Expand Down
21 changes: 21 additions & 0 deletions deploy/router/image/imageProxy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const router = require('express').Router()
const { getGzipSharpStream } = require('./util')

const V1_URL = `https://object.cscs.ch/v1`

router.get('/v1', async (req, res) => {
const { u } = req.query
// deliberately do not do any path.join, to prevent path traversal
const _url = `${V1_URL}${u}`

res.setHeader('Content-Type', 'image/png')
res.setHeader('Content-Encoding', 'gzip')
const s = await getGzipSharpStream(_url)
s.on('error', err => {
res.status(500).send(err)
})
s.pipe(res)
})


module.exports = router
86 changes: 86 additions & 0 deletions deploy/router/image/util.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
const tmp = require('tmp')
const zlib = require('zlib')
const { exec } = require('child_process')
const { PassThrough, Readable } = require('stream')
const sharp = require('sharp')
const { APP_NAME } = require('../../constants')
const fs = require('fs')
const { store } = require('../../store')
const MODULE_NAME = `[image/util]`

const getStoreKey = key => `${APP_NAME}${MODULE_NAME}${key}`

const { createGzip } = zlib

const getBufferFromStore = async key => {
const result = await store.get(key)
if (result) {
return Buffer.from(result, 'base64')
}

return null
}

const setBufferToStore = async (key, val) => {
if (!(val instanceof Buffer)) {
throw new Error(`val needs to be an instance of buffer!`)
} else {
await store.set(key, val.toString('base64'))
}
}

const getGzipSharpStream = url => new Promise((rs, rj) => {
tmp.file({ postfix: '.tif' }, async (err, filePath, fd, cleancb) => {
if (err) {
console.error(`[${APP_NAME}] generating temp file error`, err)
res.status(500).send(err)
return
}
const key = getStoreKey(url)
const content = await getBufferFromStore(key)
if (content) {
const r = new Readable()
rs(r)
r.push(content)
r.push(null)
return
}

exec(`curl -o ${filePath} '${url}'`, (err, stdout, stderr) => {
if (err) {
console.error(err)
return rj(err)
}

const gzip = createGzip()

const passThrough = new PassThrough()
const buf = []
passThrough.on('data', data => {
buf.push(data)
})

passThrough.on('end', () => {
if (buf.length === 0) return
const totalBuffer = Buffer.concat(buf)
setBufferToStore(key, totalBuffer)
})

const s = sharp(filePath)
.png()
.pipe(gzip)
.pipe(passThrough)

s.on('finish', () => {
fs.unlink(filePath, () => cleancb())
})

rs(s)
})
})

})

exports.setBufferToStore = setBufferToStore
exports.getBufferFromStore = getBufferFromStore
exports.getGzipSharpStream = getGzipSharpStream
20 changes: 19 additions & 1 deletion deploy/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,25 @@ const getCacheCtrl = ({ minute=1, hour=0, day=0 } = {}) => (_req, res, next) =>

const oneMinCache = getCacheCtrl()

router.use('/getImagePipe', oneMinCache, require('./getImagePipe'))
// used exclusive for debugging dumb components
router.get('/_bs', async (_req, res) => {
try {

const { body } = await got(`https://brainscapes.apps-dev.hbp.eu/features/ReceptorDistribution?region=hoc1`, {
headers: {
'Authorization': `Bearer ${process.env.HBP_ACCESS_TOKEN}`
}
})

res.setHeader('content-type', 'application/json')
res.status(200).send(body)
} catch(e) {
res.status(500).end()
}
})

router.use('/imageProxy', oneMinCache, require('./image/imageProxy'))
router.use('/getImagePipe', oneMinCache, require('./image/getImagePipe'))

router.use('/proxy',
oneMinCache,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kg-dataset-previewer",
"version": "1.1.5",
"version": "1.2.0",
"description": "Preview a few manually curated datasets.",
"main": "dist/index.js",
"module": "dist/index.mjs",
Expand Down
56 changes: 56 additions & 0 deletions src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,33 @@


import { HTMLStencilElement, JSXBase } from '@stencil/core/internal';
import {
TBSFingerprint,
TOriginalFPDataType,
TOriginalMetadata,
TOriginalProfileDataType,
TProfile,
TReceptorSymbol,
} from './utils/types';
import {
IDatasetFile,
} from './utils/renderUtil';

export namespace Components {
interface KgDatasetDumbLine {
'darkmode': boolean;
'profile': TOriginalProfileDataType;
'profileBs': TProfile;
'profileUnit': string;
'receptorSymbols': TReceptorSymbol;
}
interface KgDatasetDumbRadar {
'darkmode': boolean;
'meta': TOriginalMetadata[];
'metaBs': TReceptorSymbol;
'radar': TOriginalFPDataType[];
'radarBs': TBSFingerprint;
}
interface KgDatasetList {
'backendUrl': string;
'containerClass': string;
Expand Down Expand Up @@ -49,6 +71,18 @@ export namespace Components {
declare global {


interface HTMLKgDatasetDumbLineElement extends Components.KgDatasetDumbLine, HTMLStencilElement {}
var HTMLKgDatasetDumbLineElement: {
prototype: HTMLKgDatasetDumbLineElement;
new (): HTMLKgDatasetDumbLineElement;
};

interface HTMLKgDatasetDumbRadarElement extends Components.KgDatasetDumbRadar, HTMLStencilElement {}
var HTMLKgDatasetDumbRadarElement: {
prototype: HTMLKgDatasetDumbRadarElement;
new (): HTMLKgDatasetDumbRadarElement;
};

interface HTMLKgDatasetListElement extends Components.KgDatasetList, HTMLStencilElement {}
var HTMLKgDatasetListElement: {
prototype: HTMLKgDatasetListElement;
Expand All @@ -73,6 +107,8 @@ declare global {
new (): HTMLKgDsPrvRegionalFeatureViewElement;
};
interface HTMLElementTagNameMap {
'kg-dataset-dumb-line': HTMLKgDatasetDumbLineElement;
'kg-dataset-dumb-radar': HTMLKgDatasetDumbRadarElement;
'kg-dataset-list': HTMLKgDatasetListElement;
'kg-dataset-previewer': HTMLKgDatasetPreviewerElement;
'kg-dataset-previewer-chart': HTMLKgDatasetPreviewerChartElement;
Expand All @@ -81,6 +117,22 @@ declare global {
}

declare namespace LocalJSX {
interface KgDatasetDumbLine {
'darkmode'?: boolean;
'onKg-ds-prv-regional-feature-mouseover'?: (event: CustomEvent<any>) => void;
'profile'?: TOriginalProfileDataType;
'profileBs'?: TProfile;
'profileUnit'?: string;
'receptorSymbols'?: TReceptorSymbol;
}
interface KgDatasetDumbRadar {
'darkmode'?: boolean;
'meta'?: TOriginalMetadata[];
'metaBs'?: TReceptorSymbol;
'onKg-ds-prv-regional-feature-mouseover'?: (event: CustomEvent<any>) => void;
'radar'?: TOriginalFPDataType[];
'radarBs'?: TBSFingerprint;
}
interface KgDatasetList {
'backendUrl'?: string;
'containerClass'?: string;
Expand Down Expand Up @@ -114,6 +166,8 @@ declare namespace LocalJSX {
}

interface IntrinsicElements {
'kg-dataset-dumb-line': KgDatasetDumbLine;
'kg-dataset-dumb-radar': KgDatasetDumbRadar;
'kg-dataset-list': KgDatasetList;
'kg-dataset-previewer': KgDatasetPreviewer;
'kg-dataset-previewer-chart': KgDatasetPreviewerChart;
Expand All @@ -127,6 +181,8 @@ export { LocalJSX as JSX };
declare module "@stencil/core" {
export namespace JSX {
interface IntrinsicElements {
'kg-dataset-dumb-line': LocalJSX.KgDatasetDumbLine & JSXBase.HTMLAttributes<HTMLKgDatasetDumbLineElement>;
'kg-dataset-dumb-radar': LocalJSX.KgDatasetDumbRadar & JSXBase.HTMLAttributes<HTMLKgDatasetDumbRadarElement>;
'kg-dataset-list': LocalJSX.KgDatasetList & JSXBase.HTMLAttributes<HTMLKgDatasetListElement>;
'kg-dataset-previewer': LocalJSX.KgDatasetPreviewer & JSXBase.HTMLAttributes<HTMLKgDatasetPreviewerElement>;
'kg-dataset-previewer-chart': LocalJSX.KgDatasetPreviewerChart & JSXBase.HTMLAttributes<HTMLKgDatasetPreviewerChartElement>;
Expand Down
Loading

0 comments on commit fc58c7c

Please sign in to comment.