diff --git a/README.md b/README.md index 99a8617..6fc068b 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,12 @@ Cubist is a Cubism graphing sandbox. Enter Cube or Graphite expressions, get charts. -Chart settings are chucked in local storage for later use. +Charts are chucked in local storage for later use. + +## Features + +- server preferences and past expressions saved to local storage +- comparison charts can be created by dragging one chart onto another ([screenshot](http://faulkner.io/t/screen2012-06-24at2.17.18AM.png)) ## To install @@ -31,6 +36,5 @@ $ export PORT=1234; cubist - live editing for existing charts - accept chart settings from query params - kill data polling when charts are removed -- support for comparison charts - UI for removing old expressions - change typeahead into an autocomplete based on functions and metrics available diff --git a/css/app.css b/css/app.css index 56db9fc..6eba7f4 100644 --- a/css/app.css +++ b/css/app.css @@ -1,8 +1,12 @@ -.horizon { +.horizon, .comparison { display:inline-block; } .chart-actions { vertical-align:top; display:inline-block; +} + +.title { + display:block; } \ No newline at end of file diff --git a/js/app.coffee b/js/app.coffee index 83b8bb0..a0ada12 100644 --- a/js/app.coffee +++ b/js/app.coffee @@ -25,35 +25,59 @@ class @Store graphite: ['carbon.agents.*.avgUpdateTime'] charts: [] +# chart data sources +@chart_data = [] + @context = cubism.context() .serverDelay(0) .clientDelay(0) .step(config.chart.step) .size(config.chart.size) +chart_container = (charts, template, name='#charts') -> + data_id = (chart_data.push charts) - 1 + container_id = _.uniqueId 'el' + container = $($(template).html()) + .attr('id', container_id) + .data('chart', config.charts.length-1) + .data('data', data_id) + $(name).append(container) + container + @add_chart = (chart, name='#charts') -> if chart.type == 'random' data = random 'random source #'+Math.floor(Math.random()*10000) else data = context[chart.type](chart.dsn).metric chart.expression - container_id = _.uniqueId 'el' - container = $($('#chart').html()) - .attr('id', container_id) - .data('chart', config.charts.length-1) - $(name).append(container) - d3.select('#' + container_id).call (div) -> + container = chart_container data, '#chart' + + d3.select('#' + container.attr('id')).call (div) -> div.select('.axis').call(context.axis().orient("top")) - div.datum(data) div.select('.horizon') + div.datum(data) .call(context.horizon() .height(config.chart.height) .extent(config.chart.extent) .colors(config.chart.colors)) - div.select('.rule').call(context.rule()) - # BREAK YOSELF - $('.title', container).prepend('
') + container.draggable revert: true + container.droppable + drop: (event, ui) -> + flash 'Boom! A comparison chart is born.', 'info' + primary = chart_data[$(@).data('data')] + secondary = chart_data[$(ui.draggable).data('data')] + add_comparison_chart primary, secondary + +@add_comparison_chart = (primary, secondary, name='#charts') -> + container = chart_container [primary, secondary], '#comp_chart' + + d3.select('#' + container.attr('id')).call (div) -> + div.select('.axis').call(context.axis().orient("top")) + div.select('.comparison') + .datum([primary, secondary]) + .call(context.comparison() + .height(config.chart.height)) $('.create-chart').on 'click', (e) -> form = $(e.target).parents('form') @@ -95,6 +119,3 @@ init_form = (name) -> init_form form for form in ['cube', 'graphite'] add_chart c for c in config.charts - -context.on "focus", (i, e) -> - d3.selectAll(".value").style "right", (if not i? then null else context.size() - i + "px") diff --git a/js/util.coffee b/js/util.coffee index 08f5d94..d26e712 100644 --- a/js/util.coffee +++ b/js/util.coffee @@ -1,10 +1,16 @@ -@flash = (msg) -> +@flash = (msg, type='error') -> # TODO: jadify! - $('.container-fluid:first').prepend('
+ $('.container-fluid:first').prepend('
- Oh shiii.. '+msg+' + '+msg+'
') + # auto-remove non-errors + if type='info' + window.setTimeout () -> + $('.alert-info').alert('close') + , 4000 + # pulled from Cubism demo. Tweaked to make horrible assumptions about there being a global @context. @random = (name) -> value = 0 diff --git a/package.json b/package.json index 1806c88..781ce44 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "d3": "2.9.4", "cubism": "1.2.0", "jquery": "1.7.2", - "underscore": "1.3.3" + "underscore": "1.3.3", + "jquery-ui": "git://github.com/jquery/jquery-ui.git" }, "bin": {"cubist": "./bin/cubist"}, "engines": { diff --git a/views/index.jade b/views/index.jade index aa6e9a2..17f3aeb 100644 --- a/views/index.jade +++ b/views/index.jade @@ -31,12 +31,20 @@ block content #charts script(type='text/html', id='chart') - .chart + .chart(draggable="true") .axis .horizon .chart-actions a.btn.btn-mini.close-btn i.icon-trash + script(type='text/html', id='comp_chart') + .chart + .axis + .comparison + .chart-actions + a.btn.btn-mini.close-btn + i.icon-trash + block footer != js('app') diff --git a/views/layout.jade b/views/layout.jade index 3411296..dbad260 100644 --- a/views/layout.jade +++ b/views/layout.jade @@ -5,6 +5,7 @@ head meta(name="viewport", content="width=device-width, initial-scale=1.0") link(href='css/bootstrap.css', type='text/css', rel='stylesheet') link(href='css/app.css', type='text/css', rel='stylesheet') + link(href='n/jquery-ui/themes/base/jquery.ui.all.css', type='text/css', rel='stylesheet') block header body @@ -16,6 +17,11 @@ body script(src='n/d3/d3.v2.js') script(src='n/cubism/cubism.v1.js') script(src='js/bootstrap.js') + script(src="n/jquery-ui/ui/jquery.ui.core.js") + script(src="n/jquery-ui/ui/jquery.ui.widget.js") + script(src="n/jquery-ui/ui/jquery.ui.mouse.js") + script(src="n/jquery-ui/ui/jquery.ui.draggable.js") + script(src="n/jquery-ui/ui/jquery.ui.droppable.js") != js('util') block footer