Skip to content

Commit

Permalink
Develop 5.1 (#143)
Browse files Browse the repository at this point in the history
* attempt at working with the history driver

* WIP allow a search query to fill in the treatment

to solve: validation & optional 'go'

* Add validation for treatment type when copy/pasting or using search query

When there is new input and is validated by the API, validate the output
auto complete only works when there are more than 1 option

* Add parameter to automatically start search

Still need to fix edge conditions when the search field is changed later
Remove temporary debug outputs

* only trigger autorun once

When the query is changed and then changed back to the original value, autorun should not trigger

* Simplify single autorun logic

* Support a search query string to automatically select specific samples at load

Only perform the action once
We should add a check whether all specified samples were in fact found/selected

* Add filter search query handling

* Fix Filter testbench

filter model has a new input stream, add xs.empty() for each test

* Fix page failure when no filter search query present

Added missing object selector

* combine the page state to create a sharable URL

* Pass strings in the page state instead of arrays so page state is uniform

Moving burden of knowing what format the data is in to the one where it is generated

* temporarily display generated URL on the bottom of the page

Add server name, port, protocol in the URL. Haven't found it in the router though.

* Create placeholder for clipboardDriver and add functionality to genericTreatment page

* Add clipboard driver functionality

* Restyle temporary vdom search query divs

Just making it looking a little bit less bad

* Add POC floating action button

buttons/icons are still from example
somehow materialize css doesn't get applied

* Improve POC

* WIP Work on getting modal to display

Text for modal is hidden and opens when fab is pressed, however often/always? requires two presses initially
Modal is shown but only inline with current position of div instead of floating over rest of the page
Closing modal disables scrolling the page too

* Open & close of modal

somewhere triggers to the modal are getting delayed between the stream in index.js & the driver

* Use span instead of a to prevent errors in history driver

errors caused the modal not opening due delayed streams
Add same styling for fab 'a' for 'span'

* Move modal styling to own sass file, move sass files to separate folder

* Add trigger placeholders for fab

restructure code to pass triggers to the model

* Create first draft of what the export menu could possibly look like

Add some text and buttons with options that are at least a bit topical

* Disable signature export buttons when no signature present

does not yet work for FAB, probably code loses track as the classes change

* add option in ghost scenario runner to wait for a condition that must be matched

This allows the scenario to be more reactive to backend delays instead of having to wait fixed times

* Add option in genericTreatments to use the typer for the treatment search value

add typer as parameter, if empty or "yes" it uses a default speed of 100ms
minimum value 50ms, maximum value 5000ms

* Add search query functionality in the disease WF

validation happens when all genes are found, silently translate substitutions (wanted?)

* Add search query functionality for the correlation WF

Add typers & autorun code in form
changed lenses in SignatureCheck to set correct IDs

* refactor modal to use clipboard and disable not available exports

* add download of url and signature

pass url & signature to modal creation so we can add the required download functionality

* add file exports in modal

* Add placeholders for exporting plots

* Add extra support for exporting to clipboard

* Provide way to paste images in clipboard

copying of plots is with fixed data

* change notEmpty to notEmptyOrUndefined and support arrays

use ramda 'isEmpty' but also catch undefined. isEmpty returns false for undefined
Add plotsPresent$ functionality

* add basic code to get vega image and paste to clipboard

add test button in FAB so it's easier to assign test functionality
add stream return to vega driver builder

* Move creation of plot data to separate stream

remove static encoded image
new plot string already contains "data:image/png;base64," so don't add it in the file download

* Select similarity plot for exports

* Remove temporary test button and diverse stream.debug and console.log statements

* Add exporter modal and FAB to disease and correlation WF

Add optional chaining to input data that is not available in all WFs
Add config object to exporter creation so settings can be passed, ie. currently only the plot name

* Add plot name for exporter and merge with sources instead of separate variable

Adding config into the sources follows our/cycle.js style much better

* Move creation of export modal lines into separate function that is reused

* Add config field in config for the signature button to be disabled or hidden

Intended values are "", ".hide", ".disabled"

* add some basic documentation

* Add file download data types in model instead of in view

* Add wave effect on copy/download buttons

This effect is also used in the table for the download buttons

* Fix downloads messing up the router. Has something to do with clicking a 'a' directly

make the i child the full size of the a parent to capture the direct click

* Add extra explanation of the workaround

remove all padding of the a element instead of only left & right

* use numTableHead and numTableTail parameters in search query to set default entries in table

Sets the start value, the user can still change the value later, so functionally should and does act as an alternative default value from the settings

* Initialize FAB once vdom$ launches vdom

Add extra 1ms delay so vdom$ can propagate to DOM before calling FAB init

* Add unit test for search queries in filters

Simple test with changed values, unchanged values & an invalid option
Check both 'output' and 'filter_output'

* Add autorun to search query by default

However, only add '?' or autorun when a state is available, otherwise just link base link address

* Hide pdf report option for now

it's never available, so don't show the button

* Add option to update FAB when signature becomes available, add waves effect

Added waves effect on FAB to indicate action

* Hide signature FAB shortcut for disease and correlation WF

* WIP rewrite of clipboard to return permissions and results

* Add sender in clipboard object

add undefined type as meaning raw text to be copied

split class identifiers of elements in fab and modal (url and signature)
let modal use clipboard objects with sender

* Display clipboard results in modal

For now just make button green or red for 2 seconds

* Always require objects to be passed to clipboard driver
Rewrite poc driver to not use shameful methods but instead create a nested provider & listener (thanks Toni!)

* Give DOM more time before initializing FAB
1ms delay is not guaranteed to be enough. so far 50ms seems fine.

* rename clipboardDriver -> makeClipboardDriver

* Add clipboard result to FAB

* keep FAB open when updating it

FAB should be destroyed during update instead of closed, fixes most of behavior issues.
Still does some animation but at least the overall state is correct now

* Provide optional stream sink for clipboard driver

Allows clipboard driver to be used without a result listener and instead provides a void sink for the result stream

* if search query, reload page without search query but store search query in router state

This removes the ...?xxx from the browser URL which prevents users making changes to the page
and believing the URL can be copied and to have a valid state

However this introduces an additional issue that page refreshes or clicking on the same WF
still starts the same search query as it stays in the router state
Handle this by only converting the data when the router type is set to 'push'.
When we push to the state, the router state is set to 'push' but when the user refreshes/clicks same WF link
the type is undefined

* Version bump to 5.1.0-alpha1

* Add filter in correlation WF (#126)

* Gskcmp 20 sorting sample selection table (#121)

* Start making SampleSelection sortable

Clicking the header triggers sort selection and direction
Sort selection and direction is displayed in the header

No actual sorting is happening for now

* Use button in header and add sort icon on hover

Use button as it is provides mouse cursor changes
Add sort icon when hovering over the title to indicate functionality

* Sort data when header clicked

match header id to entry field names

* Prevent header updates while loading

Prevents updates on loaded vdom stream which would otherwise replace the loading vdom
move icon name logic to separate const to make code clearer

* Fix header buttons in place

Keep the text centered with the icons next to it
Force text and icons on the same line on small screens

* Gskcmp 86 auto complete doesnt work with single result while still not complete (#114)

* Update the AutoComplete even if there is only 1 result

Prevents an incomplete entry getting no results
However, now requires the user to type out the full or click the suggestion

* Don't feed autofeed when the input matches the single AutoComplete data

This restores the original intended functionality

* Clear AutoComplete when input completely matches single entry

When the user types the full name, close the AutoComplete instead of wanting the user to confirm their only option

* Truncate dose when text is too long

When dose isn't a number or the dose unit is long, truncate the whole string

* Version bump to 5.0.1

* Don't allow 'Use' column to be sorted

* Sort dose & time numerically

These examples are typical issues
2 < 10
0.02 < 0.4

* Fix truncation with long dose unit names

add missing .length

* Gskcmp 89 ghost mode leaves page in dirty state (#119)

* Let ghost mode use router params functionality

Change treatments scenario as proof of concept:
- all selecting is done by setting the router params
- set continue functions
- remove old functionality

* Update disease WF ghost mode

Still a bit WIP. Setting of filters etc needs some attention, currently doesn't use the router params system

* Basic update for ghost mode in correlation WF

* Don't allow search queries when ghost mode is enabled

Don't apply the state to the routerInformation.params
Still clear the search string from the browser url

* Move ghost mode strings & settings to deployments too

Change scenario logic for disease and correlation WFs to same style as genericTreatment as it is now very similar

* Update CHANGELOG.md

* Add documentation for v5.0.1

* Delay loading vdom by 100ms (#128)

State can glitch, especially when using the search queries.
This causes loading vdom to be output and directly being overwritten by init vdom

* Remove debug statements from clipboard driver and scenario logic

* Add TRT_OE as possible treatment to be displayed in the top tables (#129)

Copied from trt_sh

* Allow filter values API call coming in later than the input trigger (#134)

In disease & correlation WFs the input trigger comes instantaneously but the API for filter values is still under its way. This means that a regular samplecombine doesn't output the values

first combine input trigger and filter values and then samplecombine the search values

* Catch error thrown in permission query under Firefox (#136)

Firefox doesn't implement 'clipboard-write' but also doesn't allow querying it
Catch the exception that gets thrown.

Co-authored-by: Toni Verbeiren <[email protected]>
  • Loading branch information
Grifs and tverbeiren authored Mar 28, 2022
1 parent 9212776 commit 04d4dd9
Show file tree
Hide file tree
Showing 31 changed files with 1,733 additions and 215 deletions.
33 changes: 30 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,45 @@
# CHANGELOG

## Version 5.1.0

### Functionality

- URL Queries: ComPass accepts URL queries and runs the complete analysis automatically. For instance, the following URI:

```
http://localhost:3000/disease?autorun&signature=HSPA1A+DNAJB1+DDIT4+-TSEN2&numTableHead=10
```

will run the Disease workflow using the signature `HSPA1A DNAJB1 DDIT4` and will show 10 entries for the top table.

- Export: Add buttons to export data and plots to a file or copy it to the clipboard. A popup window is available with all the possible export features on the right bottom of the screen.

- Correlation workflow has filters.

- Sample tables can be sorted by clicking the columns header

### Other

- Ghost mode has been improved, it no longer requires explicit timings in the scenarios

## Version 5.0.2

- Fix mistake in sample selection column truncation code

## Version 5.0.0-alpha4
## Version 5.0.1

- The head and tail tables use pictures to display the treatment type
- Adapt the behaviour for the autocomplete when there is only one option to choose from and if the entered value matches the single autocomplete value

## Version 5.0.0

## Functionality
### Functionality

- A new 'Genetic' workflow is created useful for searching for genetic perturbations.
- Inverting the filter selection can be done using the `ALT` (Option on Mac) modifier key instead of the `a` key
- Filter values are populated dynamically based on the data available through the API

## Other
### Other

- The dependency stack has been cleaned and (partly) updated
- Cycle dependencies have been updated to the latest versions except for `@cycle/state`.
Expand Down
43 changes: 31 additions & 12 deletions deployments.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,41 @@
},
"ghost": {
"compound": {
"treatment": "BRD-K93645900",
"index": 0,
"sample": ["A375_6H_BRD_K93645900_10"],
"signature": "-CRCP"
"params": {
"typer": 500,
"treatment": "BRD-K93645900",
"samples": "A375_6H_BRD_K93645900_10",
"trtType": "trt_cp"
}
},
"ligand": {
"treatment": "ANGPT1",
"index": 0,
"sample": ["HCC515_4H_CMAP_CYT_SRP3007_50"],
"signature": "FBXO11 SLC35 F5BAG4 RIF1"
"params": {
"typer": 500,
"treatment": "ANGPT1",
"samples": "HCC515_4H_CMAP_CYT_SRP3007_50",
"trtType": "trt_cp"
}
},
"genetic": {
"treatment": "PARP2",
"index": 0,
"sample": ["DER001_HCC515_96H_X1_F1B6_DUO52HI53LO:B03"],
"signature": "-COPS7A -KEAP1 -CCNB1 -HMG20B -ELOVL6 -DERA LPL -PLEKHJ1 -TPI1 ST3GAL5 -HAT1 -MLF2 -FOXG1 -STRAP -MRPL4 -EDN1 -PON2 KMT2A FRMD4A -C16orf58"
"params": {
"typer": 500,
"treatment": "PARP2",
"samples": "DER001_HCC515_96H_X1_F1B6_DUO52HI53LO",
"trtType": "trt_cp"
}
},
"disease": {
"params": {
"typer": 100,
"signature": "HSPA1A DNAJB1 DDIT4 -TSEN2"
}
},
"correlation": {
"params": {
"typer": 100,
"signature1": "HSPA1A DNAJB1 DDIT4 -TSEN2",
"signature2": "DNAJB1 DDIT4 -TSEN2"
}
}
},
"modelTranslations": [
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": "LuciusWeb",
"version": "5.0.2",
"version": "5.1.0",
"description": "Web interface for ComPass aka Lucius",
"repository": {
"type": "git",
Expand Down
50 changes: 45 additions & 5 deletions src/js/components/CorrelationForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ENTER_KEYCODE } from '../utils/keycodes.js'
import { SignatureCheck, checkLens1, checkLens2 } from '../components/SignatureCheck'
import dropRepeats from 'xstream/extra/dropRepeats'
import { loggerFactory } from '../utils/logger'
import { typer } from '../utils/searchUtils'

const stateTemplate = {
form: {
Expand All @@ -21,8 +22,29 @@ const stateTemplate = {

// Granular access to global state and parts of settings
const formLens = {
get: state => ({ core: state.form, settings: { form: state.settings.form, api: state.settings.api } }),
set: (state, childState) => ({ ...state, form: childState.core })
get: state => ({
core: state.form,
settings: {
form: state.settings.form,
api: state.settings.api
},
search1: state.routerInformation.params?.signature1,
search2: state.routerInformation.params?.signature2,
searchAutoRun: state.routerInformation.params?.autorun,
searchTyper: state.routerInformation.params?.typer,
}),
set: (state, childState) => ({
...state,
form: childState.core,
routerInformation: {
...state.routerInformation,
pageState: {
...state.routerInformation.pageState,
signature1: childState.core.query1,
signature2: childState.core.query2,
}
}
})
};

function CorrelationForm(sources) {
Expand Down Expand Up @@ -79,15 +101,20 @@ function CorrelationForm(sources) {
});

// Update in query, or simply ENTER
const typer1$ = typer(state$, 'search1', 'searchTyper')
const newQuery1$ = xs.merge(
sources.DOM.select('.Query1').events('input').map(ev => ev.target.value),
// Ghost
state$.map(state => state.core.query1).compose(dropRepeats())
state$.map(state => state.core.query1).compose(dropRepeats()),
typer1$,
)

const typer2$ = typer(state$, 'search2', 'searchTyper')
const newQuery2$ = xs.merge(
sources.DOM.select('.Query2').events('input').map(ev => ev.target.value),
// Ghost
state$.map(state => state.core.query2).compose(dropRepeats())
state$.map(state => state.core.query2).compose(dropRepeats()),
typer2$,
)

// Updated state is propagated and picked up by the necessary components
Expand Down Expand Up @@ -187,12 +214,25 @@ function CorrelationForm(sources) {
const childReducer1$ = signatureCheck1.onion
const childReducer2$ = signatureCheck2.onion

// Auto start query
// Only run once, even if query is changed and then reverted to original value
const searchAutoRun$ = state$
.filter(
(state) => state.searchAutoRun == "" || state.searchAutoRun == "yes"
)
.filter((state) => state.search1 == state.core.query1 && state.search2 == state.core.query2)
.filter((state) => state.core.validated1 == true && state.core.validated2 == true)
.mapTo(true)
.compose(dropRepeats(equals))


// When GO clicked or enter -> send updated 'value' to sink
// Maybe catch when no valid query?
const query$ = xs.merge(
update$,
// Ghost mode
sources.onion.state$.map(state => state.core.ghost).filter(ghost => ghost).compose(dropRepeats())
sources.onion.state$.map(state => state.core.ghost).filter(ghost => ghost).compose(dropRepeats()),
searchAutoRun$,
)
.compose(sampleCombine(state$))
.map(([update, state]) => ({query1: state.core.query1, query2: state.core.query2}))
Expand Down
Loading

0 comments on commit 04d4dd9

Please sign in to comment.