Skip to content

Commit

Permalink
Ability to add plugins to JBrowseR, convert code to typescript (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Oct 5, 2023
1 parent 90ebdf0 commit da90b73
Show file tree
Hide file tree
Showing 14 changed files with 2,156 additions and 553 deletions.
55 changes: 55 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-type-checked',
'plugin:@typescript-eslint/stylistic-type-checked',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:unicorn/recommended',
],
settings: {
react: {
version: 'detect',
},
},
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: './tsconfig.json',
},
globals: {
Shiny: true,
},
plugins: ['@typescript-eslint', 'react', 'react-refresh'],
rules: {
'unicorn/prevent-abbreviations': 'off',
'unicorn/no-null': 'off',
'unicorn/filename-case': 'off',
'unicorn/no-useless-undefined': 'off',
'unicorn/no-nested-ternary': 'off',

'react/prop-types': 'off',
'react-refresh/only-export-components': 'warn',

'@typescript-eslint/no-base-to-string': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-argument': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/restrict-template-expressions': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/no-unused-vars': [
'warn',
{ argsIgnorePattern: '^_', ignoreRestSiblings: true },
],
curly: 'error',
'no-extra-semi': 'off',
},
}
2 changes: 1 addition & 1 deletion inst/htmlwidgets/JBrowseR.js

Large diffs are not rendered by default.

14 changes: 12 additions & 2 deletions inst/htmlwidgets/JBrowseR.js.LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */

/*! @license DOMPurify 3.0.5 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.0.5/LICENSE */
/*! @license DOMPurify 3.0.6 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.0.6/LICENSE */

/*! https://mths.be/punycode v1.4.1 by @mathias */

Expand Down Expand Up @@ -120,7 +120,17 @@ PERFORMANCE OF THIS SOFTWARE.
*/

/**
* @mui/x-data-grid v6.13.0
* @license React
* use-sync-external-store-shim.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

/**
* @mui/x-data-grid v6.16.0
*
* @license MIT
* This source code is licensed under the MIT license found in the
Expand Down
15 changes: 13 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
{
"private": true,
"scripts": {
"build": "webpack"
"build": "webpack",
"lint": "eslint srcjs"
},
"dependencies": {
"@jbrowse/react-linear-genome-view": "^2.5.0",
"node-polyfill-webpack-plugin": "^2.0.1",
"react": "^17.0.1",
"react-dom": "^17.0.1"
},
"devDependencies": {
"@babel/core": "^7.22.1",
"@babel/preset-env": "^7.22.4",
"@babel/preset-react": "^7.22.3",
"@babel/preset-typescript": "^7.23.0",
"@typescript-eslint/eslint-plugin": "^6.7.0",
"@typescript-eslint/parser": "^6.7.0",
"babel-loader": "^9.1.2",
"eslint": "^8.49.0",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"eslint-plugin-unicorn": "^48.0.1",
"node-polyfill-webpack-plugin": "^2.0.1",
"prettier": "^3.0.3",
"typescript": "^5.2.2",
"webpack": "^5.85.0",
"webpack-cli": "^5.1.1"
}
Expand Down
File renamed without changes.
23 changes: 0 additions & 23 deletions srcjs/components/JsonView.jsx

This file was deleted.

59 changes: 59 additions & 0 deletions srcjs/components/JsonView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React from 'react'
import {
createViewState,
JBrowseLinearGenomeView,
loadPlugins,
} from '@jbrowse/react-linear-genome-view'
import { ErrorMessage } from '@jbrowse/core/ui'

import { messageShiny } from '../utils'

type ViewState = ReturnType<typeof createViewState>
export default function View({
config,
location,
}: {
location: string
config: string
}) {
const [viewState, setViewState] = React.useState<ViewState>()
const [error, setError] = React.useState<unknown>()
React.useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
;(async () => {
try {
const {
assembly,
tracks,
defaultSession,
theme,
text_index,
plugins: pluginInput = [],
} = JSON.parse(config)
const plugins = await loadPlugins(pluginInput)
const state = createViewState({
assembly,
tracks,
defaultSession,
location,
onChange: messageShiny,
configuration: { theme },
aggregateTextSearchAdapters: [text_index],
plugins: plugins.map(p => p.plugin),
})
setViewState(state)
} catch (error) {
console.error(error)
setError(error)
}
})()
}, [config, location])

return error ? (
<ErrorMessage error={error} />
) : viewState ? (
<JBrowseLinearGenomeView viewState={viewState} />
) : (
<h3>Loading...</h3>
)
}
31 changes: 0 additions & 31 deletions srcjs/components/View.jsx

This file was deleted.

34 changes: 34 additions & 0 deletions srcjs/components/View.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react'
import {
createViewState,
JBrowseLinearGenomeView,
} from '@jbrowse/react-linear-genome-view'

import { messageShiny } from '../utils'

export default function View(props: {
tracks: string
assembly: string
location: string
theme: string
text_index: string
}) {
const { theme, text_index, assembly, tracks, location, ...rest } =
Object.fromEntries(
Object.entries(props).map(([key, value]) => [
key,
key === 'location' ? value : JSON.parse(value),
]),
)
const state = createViewState({
...rest,
onChange: messageShiny,
configuration: { theme },
aggregateTextSearchAdapters: text_index,
location,
assembly,
tracks,
})

return <JBrowseLinearGenomeView viewState={state} />
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React from 'react'
import {
createViewState,
JBrowseLinearGenomeView,
Expand Down Expand Up @@ -86,11 +87,11 @@ const defaultSession = {
},
}

export default function Hg19View(props) {
export default function Hg19View({ location }: { location: string }) {
const state = createViewState({
assembly,
tracks,
location: props.location,
location,
defaultSession,
onChange: messageShiny,
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React from 'react'
import {
createViewState,
JBrowseLinearGenomeView,
Expand Down Expand Up @@ -86,12 +87,11 @@ const defaultSession = {
},
}

export default function ViewHg38(props) {
console.log({ props })
export default function ViewHg38({location}:{location:string}) {
const state = createViewState({
assembly,
tracks,
location: props.location,
location,
defaultSession,
onChange: messageShiny,
})
Expand Down
13 changes: 6 additions & 7 deletions srcjs/utils.js → srcjs/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
* @param patch The JSON patch received from
* the LGV ViewState with what was changed.
*/
export function messageShiny(patch) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function messageShiny(patch: any) {
if (typeof Shiny === 'undefined') {
return
}
Expand All @@ -16,12 +17,10 @@ export function messageShiny(patch) {

if (path.endsWith('featureData')) {
Shiny.setInputValue('selectedFeature', value)
} else if (path.endsWith('Feature')) {
if (value) {
const { featureData } = value
if (featureData) {
Shiny.setInputValue('selectedFeature', featureData)
}
} else if (path.endsWith('Feature') && value) {
const { featureData } = value
if (featureData) {
Shiny.setInputValue('selectedFeature', featureData)
}
}
}
12 changes: 8 additions & 4 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,28 @@ const webpack = require('webpack')

module.exports = {
mode: 'production',
entry: [path.join(__dirname, 'srcjs', 'JBrowseR.jsx')],
entry: [path.join(__dirname, 'srcjs', 'JBrowseR.tsx')],
output: {
path: path.join(__dirname, 'inst/htmlwidgets'),
filename: 'JBrowseR.js',
},
module: {
rules: [
{
test: /\.jsx?$/,
test: /\.(t|j)sx?$/,
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-typescript',
],
},
},
],
},
resolve: {
extensions: ['.js', '.jsx'],
extensions: ['.ts', '.tsx', '.js', '.jsx'],
},
externals: {
react: 'window.React',
Expand Down
Loading

0 comments on commit da90b73

Please sign in to comment.