Skip to content

Commit

Permalink
Merge pull request #149 from intermine/fixes-columns
Browse files Browse the repository at this point in the history
Fixes column manager and removes infinite loop in open-nodes.
  • Loading branch information
joshkh committed Jun 19, 2015
2 parents ae54a83 + 052ee83 commit a55759e
Show file tree
Hide file tree
Showing 49 changed files with 520 additions and 88 deletions.
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "imtables",
"version": "2.0.0-beta-18",
"version": "2.0.0-beta-39",
"description": "ui widgets for displaying query results in interactive tables",
"main": [
"dist/imtables.min.js",
Expand Down
30 changes: 27 additions & 3 deletions less/active-constraints.less
Original file line number Diff line number Diff line change
@@ -1,10 +1,35 @@
.im-path-finder {
overflow: visible;
}
.im-filter-manager {
.im-path-finder {
.im-path-finder.open {
max-height: 400px;
overflow-y: auto;
}
}

.im-new-constraint {
.im-con-overview {
.im-name-part {
display: none;
}
.im-name-part:first-child:after {
content: '...';
}
.im-name-part:nth-last-child(-n+4):after {
content: "\00bb";
margin-left: 0.5em;
}
.im-name-part:last-child:after {
content: '';
}
.im-name-part:first-child,
.im-name-part:nth-last-child(-n+3) {
display: inline-block;
}
}
}

.im-filter-summary {
.label-path {
.im-name-part {
Expand Down Expand Up @@ -43,7 +68,6 @@
position: relative;

.im-slider-marker {
position: absolute;
font-family: @font-family-monospace;
top: 1em;

Expand Down Expand Up @@ -86,7 +110,7 @@
margin-right: 0.2em;
}
.label {
font-size: 1.25em;
font-size: 1.1em;
}
}

Expand Down
9 changes: 9 additions & 0 deletions less/main.less
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,12 @@ ul.dropdown-menu {
margin-left: 0px;
}
}

.im-evenly-spaced {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
justify-content: space-between;
}
3 changes: 3 additions & 0 deletions less/path-chooser.less
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
.im-path-chooser {
ul {
padding-left: 2em;
}
li {
list-style-type: none;
margin-left: 0px;
Expand Down
3 changes: 2 additions & 1 deletion less/preview.less
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.popover.item-preview {
min-width: 300px;
min-width: 385px;
}
.im-cell-preview-inner {

Expand All @@ -18,6 +18,7 @@
.im-relation {
padding: 0.1em 1em;
width: 50%;
margin-left: 0;
.pull-left();
display: inline-block;

Expand Down
6 changes: 6 additions & 0 deletions less/slider.less
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,9 @@
.im-ui-default-widget-state;
}

.im-slider {
display: flex;
flex-direction: row;
justify-content: space-between;
}

7 changes: 7 additions & 0 deletions less/summary.less
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@
}

}
.im-item-col {
.null-value:after {
font-weight: bold;
color: @gray-lightish;
content: 'NOTHING';
}
}
.im-count-col {
font-weight: bold;
text-shadow: -1px -1px #fff;
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": "imtables",
"version": "2.0.0-beta-38",
"version": "2.0.0-beta-39",
"description": "UI widgets for displaying query results in interactive tables",
"config": {
"port": "9000"
Expand Down
4 changes: 4 additions & 0 deletions src/main.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ require './shim'
{Service: {connect}} = require 'imjs'
{Promise} = require 'es6-promise'

version = require './version'
Types = require './core/type-assertions'
Dashboard = require './views/dashboard'
Table = require './views/table'
Expand Down Expand Up @@ -54,6 +55,9 @@ asElement = (e) ->

# Exported top-level API

# The version of this library, see: bin/inject-version.js
exports.version = version

# Allow end users to configure text.
exports.setMessages = Messages.set.bind(Messages)

Expand Down
1 change: 1 addition & 0 deletions src/messages/actions.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ module.exports =
'export.category.JsonFormat': """
As <%= (jsonFormat === 'objects') ? 'Objects' : 'Rows' %>
"""
'export.category.FastaFormat': 'FASTA options'
'export.category.ColumnHeaders': """
<% if (headers) { %>
<%= {friendly: 'Formatted', path: 'Raw'}[headerType] %>
Expand Down
8 changes: 8 additions & 0 deletions src/messages/logic.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Messages = require '../messages'

Messages.setWithPrefix 'logic',
Heading: 'Manage Constraint Logic'
Manage: -> Messages.getText 'logic.Heading' # synonymous by default - can be made distinct.
ManageShort: 'Constraint Logic'
LogicLabel: -> Messages.getText 'logic.ManageShort'
ApplyLogic: 'Change logic'
13 changes: 11 additions & 2 deletions src/mixins/has-typeaheads.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,26 @@ exports.initTypeaheads = -> @_typeaheads ?= []
exports.removeTypeAheads = ->
return unless @_typeaheads?
while (ta = @_typeaheads.shift())
ta.off('typeahead:select')
ta.off('typeahead:selected')
ta.off('typeahead:autocompleted')
ta.off('typeahead:close')
ta.typeahead('destroy')
ta.remove()

exports.lastTypeahead = -> _.last(@_typeaheads ? [])

exports.activateTypeahead = (input, opts, data, placeholder, cb) ->
# @param input [jQuery] A jQuery selection to apply a typeahead to.
# @param opts [Object] The typeahead options (see http://twitter.github.io/typeahead.js/examples/)
# @param data [(String, ([String]) ->) ->] Data source
# @param placeholder [String] The new place-holder
# @param cb [(Event, Object) ->] Suggestion handler
exports.activateTypeahead = (input, opts, data, placeholder, cb, onChange) ->
input.attr(placeholder: placeholder).typeahead opts, data
input.on 'typeahead:selected', cb
input.on 'typeahead:select', cb
input.on 'typeahead:autocompleted', cb
if onChange?
input.on 'typeahead:close', onChange

# Keep a track of it, so it can be removed.
@initTypeaheads().push input
Expand Down
8 changes: 7 additions & 1 deletion src/mixins/runs-query.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ CACHE = {}
exports.runQuery = (overrides = {}) ->
params = @getExportParameters overrides
key = "results:#{ @query.service.root }:#{ JSON.stringify params }"
CACHE[key] ?= @query.service.post 'query/results', params
endpoint = 'query/results'
format = @model.get('format')
# Custom formats have custom endpoints.
endpoint += "/#{ format.id }" if format.needs?.length
CACHE[key] ?= @query.service.post endpoint, params

exports.getEstimatedSize = ->
q = @getExportQuery()
Expand Down Expand Up @@ -40,4 +44,6 @@ exports.getExportParameters = (overrides = {}) ->
# TODO - this is hacky - the model should reflect the request
if (data.format is 'json') and ('rows' isnt @model.get 'jsonFormat')
data.format += @model.get 'jsonFormat'
if (data.format is 'fasta') and (@model.get('fastaExtension'))
data.extension = @model.get('fastaExtension')
_.extend data, overrides
7 changes: 5 additions & 2 deletions src/models/available-columns.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ module.exports = class AvailableColumns extends Collection

model: PathModel

add: (model) ->
returned = super
if returned and !returned.collection? then returned.collection = @

initialize: ->
super
@on 'change:parts change:displayName', => @sort()

comparator: (a, b) -> # sort by path-length, and then lexically by attribute name.
(cmp partsLen, a, b) or (cmp displayName, a, b)

(cmp partsLen, a, b) or (cmp displayName, a, b)
4 changes: 2 additions & 2 deletions src/models/export-formats.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ _ = require 'underscore'

class Format

constructor: ({@id, @group, icon, needs}) ->
constructor: ({@id, @group, icon, needs, @maxColumns}) ->
# Sigh, it's either this or list redundant info.
ext = if @id is 'tab' then 'tsv' else @id
EXT = ext.toUpperCase()
Expand Down Expand Up @@ -30,7 +30,7 @@ formats = [
new Format(id: 'csv', group: 'flat'),
new Format(id: 'xml', group: 'machine'),
new Format(id: 'json', group: 'machine'),
new Format(id: 'fasta', group: 'bio', icon: 'dna', needs: ['Protein', 'SequenceFeature']),
new Format(id: 'fasta', group: 'bio', icon: 'dna', needs: ['Protein', 'SequenceFeature'], maxColumns: 1),
new Format(id: 'gff3', group: 'bio', icon: 'dna', needs: ['SequenceFeature']),
new Format(id: 'bed', group: 'bio', icon: 'dna', needs: ['SequenceFeature']),
new Format(id: 'fake', group: 'fake', icon: 'fake', needs: ['Department'])
Expand Down
15 changes: 10 additions & 5 deletions src/models/history.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,26 @@ module.exports = class History extends Collection
@listenTo q, "change:views", @onChangeViews
@listenTo q, "change:joins", @onChangeJoins
@listenTo q, "change:sortorder", @onChangeSortOrder
@listenTo q, "change:logic", @onChangeLogic
@listenTo q, "undo", @popState

# TODO - get rid of labels - they are pointless. Use the query prop instead

onChangeConstraints: ->
@onChange 'constraints', 'filter', JSON.stringify
@onChange 'constraints', 'filter', (cons) -> _.map cons, JSON.stringify

onChangeViews: ->
@onChange 'views', 'column'

onChangeJoins: ->
@onChange 'joins', 'join', (style, path) -> "#{ path }:#{ style }"
@onChange 'joins', 'join', (joins) -> _.map joins, (style, path) -> "#{ path }:#{ style }"

onChangeSortOrder: ->
@onChange 'sortOrder', 'sort order element', JSON.stringify
@onChange 'sortOrder', 'sort order element', (so) -> _.map so, JSON.stringify

onChangeLogic: ->
@onChange 'constraintLogic', 'constraint logic element', (expr) ->
expr?.match(/([A-Z]+)/) ? []

# Inform clients that the current query is different
triggerChangedCurrent: ->
Expand All @@ -67,8 +72,8 @@ module.exports = class History extends Collection
onChange: ( prop, label, f = (x) -> x ) ->
query = @currentQuery
prev = @last().get 'query'
xs = _.map prev[prop], f
ys = _.map query[prop], f
xs = f prev[prop]
ys = f query[prop]
was = xs.length
now = ys.length
n = Math.abs was - now
Expand Down
2 changes: 1 addition & 1 deletion src/models/open-nodes.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ module.exports = class OpenNodes extends UniqItems

# Also removes sub-nodes.
remove: (path) ->
if !path? then return false
if path instanceof Backbone.Model
super path

delenda = @filter (node) -> descendsFrom path, node.get('item')
for delendum in delenda
super delendum

9 changes: 3 additions & 6 deletions src/utils/calculate-row-template.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,14 @@ getOJCBelow = (query, p, below) ->
oj = query.getOuterJoin p
return null if (not oj) or (oj is below) # not outerjoined, or joined at the target level.
path = query.makePath(oj)
# outer loop variables.
highest = if path.isCollection() then oj else null
path = path.getParent()

while path and (not path.isRoot())
next = query.getOuterJoin path
while path and (not path.isRoot()) then do (next = query.getOuterJoin path) ->
nextPath = query.makePath(next) if next?
highest = next if nextPath?.isCollection() and (next isnt below)
if nextPath
path = nextPath.getParent()
else
path = null
path = nextPath?.getParent()

return highest

Expand Down
4 changes: 3 additions & 1 deletion src/utils/count-executor.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

CACHE = {}

key = (q) -> "#{ q.root }:#{ q.token }:#{ q.toXML() }"
# A unique key composed of the service we are connected to and the
# canonical representation of the query.
key = (q) -> "#{ q.service.root }:#{ q.service.token }:#{ q.toXML() }"

# Simple caching layer that caches counts.
exports.count = (q) -> CACHE[key q] ?= q.count()
Expand Down
16 changes: 16 additions & 0 deletions src/utils/path-suggestions.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
_ = require 'underscore'
{Promise} = require 'es6-promise'

# Suggestions can be very large and expensive.
CACHE = {}

matchPathsToNames = (paths) -> (names) ->
({path, name} for [path, name] in _.zip paths, names)

module.exports = getPathSuggestions = (query, depth) ->
key = "#{ query.service.root }:#{ query.root }:#{ depth }"
return CACHE[key] if key of CACHE
paths = (query.makePath p for p in query.getPossiblePaths depth)
paths = paths.filter (p) -> not (p.end?.name is 'id')
namings = (p.getDisplayName() for p in paths)
CACHE[key] ?= Promise.all(namings).then matchPathsToNames(paths)
2 changes: 2 additions & 0 deletions src/utils/suggestion-source.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ module.exports = class SuggestionSource
@tooMany = template icons: Icons, messages: Messages, extra: total - maxSuggestions

suggest: (term, cb) =>
if not term? or term is ''
return cb(s for s in @suggestions.slice(0, 10))
parts = (term?.toLowerCase()?.split(' ') ? [])
matches = ({item}) ->
item ?= ''
Expand Down
10 changes: 10 additions & 0 deletions src/views/active-constraint.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ $ = require 'jquery'
{Query, Model} = require 'imjs'

# Support
CoreModel = require '../core-model'
Messages = require '../messages'
Templates = require '../templates'
Icons = require '../icons'
Expand Down Expand Up @@ -54,9 +55,18 @@ basicEql = (a, b) ->
same and= (if _.isArray va then aeql va, vb else va is vb)
return same

class ConstraintModel extends CoreModel

defaults: ->
code: null

isTypeConstraint: -> not @get('op')?

# Composite view with a summary, and controls for editing the constraint.
module.exports = class ActiveConstraint extends View

Model: ConstraintModel

tagName: "div"

className: "im-constraint row-fluid"
Expand Down
Loading

0 comments on commit a55759e

Please sign in to comment.