datagram 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. data/.env.sample +7 -0
  2. data/.gitignore +20 -0
  3. data/.rbenv-version +1 -0
  4. data/Gemfile +12 -0
  5. data/LICENSE.txt +22 -0
  6. data/Procfile +1 -0
  7. data/README.md +29 -0
  8. data/Rakefile +1 -0
  9. data/config.ru +5 -0
  10. data/datagram.gemspec +23 -0
  11. data/db/migrate/1_create_queries.rb +9 -0
  12. data/db/migrate/2_add_name_to_queries.rb +5 -0
  13. data/lib/datagram/version.rb +3 -0
  14. data/lib/datagram.rb +135 -0
  15. data/lib/views/application.coffee +222 -0
  16. data/lib/views/index.haml +47 -0
  17. data/lib/views/layout.haml +17 -0
  18. data/lib/views/style.sass +179 -0
  19. data/public/ace/ace.js +15209 -0
  20. data/public/ace/ext-elastic_tabstops_lite.js +301 -0
  21. data/public/ace/ext-emmet.js +253 -0
  22. data/public/ace/ext-searchbox.js +441 -0
  23. data/public/ace/ext-spellcheck.js +67 -0
  24. data/public/ace/ext-static_highlight.js +96 -0
  25. data/public/ace/ext-textarea.js +492 -0
  26. data/public/ace/ext-whitespace.js +204 -0
  27. data/public/ace/keybinding-emacs.js +962 -0
  28. data/public/ace/keybinding-vim.js +1704 -0
  29. data/public/ace/mode-abap.js +260 -0
  30. data/public/ace/mode-asciidoc.js +372 -0
  31. data/public/ace/mode-c9search.js +182 -0
  32. data/public/ace/mode-c_cpp.js +737 -0
  33. data/public/ace/mode-clojure.js +299 -0
  34. data/public/ace/mode-coffee.js +426 -0
  35. data/public/ace/mode-coldfusion.js +1753 -0
  36. data/public/ace/mode-csharp.js +612 -0
  37. data/public/ace/mode-css.js +773 -0
  38. data/public/ace/mode-curly.js +1950 -0
  39. data/public/ace/mode-dart.js +945 -0
  40. data/public/ace/mode-diff.js +166 -0
  41. data/public/ace/mode-django.js +1969 -0
  42. data/public/ace/mode-dot.js +320 -0
  43. data/public/ace/mode-ftl.js +907 -0
  44. data/public/ace/mode-glsl.js +810 -0
  45. data/public/ace/mode-golang.js +632 -0
  46. data/public/ace/mode-groovy.js +1037 -0
  47. data/public/ace/mode-haml.js +487 -0
  48. data/public/ace/mode-haxe.js +609 -0
  49. data/public/ace/mode-html.js +1881 -0
  50. data/public/ace/mode-jade.js +1951 -0
  51. data/public/ace/mode-java.js +996 -0
  52. data/public/ace/mode-javascript.js +876 -0
  53. data/public/ace/mode-json.js +578 -0
  54. data/public/ace/mode-jsp.js +1351 -0
  55. data/public/ace/mode-jsx.js +635 -0
  56. data/public/ace/mode-latex.js +189 -0
  57. data/public/ace/mode-less.js +807 -0
  58. data/public/ace/mode-liquid.js +862 -0
  59. data/public/ace/mode-lisp.js +138 -0
  60. data/public/ace/mode-livescript.js +288 -0
  61. data/public/ace/mode-logiql.js +664 -0
  62. data/public/ace/mode-lsl.js +828 -0
  63. data/public/ace/mode-lua.js +455 -0
  64. data/public/ace/mode-luapage.js +2340 -0
  65. data/public/ace/mode-lucene.js +64 -0
  66. data/public/ace/mode-makefile.js +313 -0
  67. data/public/ace/mode-markdown.js +2280 -0
  68. data/public/ace/mode-mushcode.js +704 -0
  69. data/public/ace/mode-mushcode_high_rules.js +569 -0
  70. data/public/ace/mode-objectivec.js +659 -0
  71. data/public/ace/mode-ocaml.js +443 -0
  72. data/public/ace/mode-pascal.js +233 -0
  73. data/public/ace/mode-perl.js +316 -0
  74. data/public/ace/mode-pgsql.js +908 -0
  75. data/public/ace/mode-php.js +2291 -0
  76. data/public/ace/mode-powershell.js +618 -0
  77. data/public/ace/mode-python.js +264 -0
  78. data/public/ace/mode-r.js +404 -0
  79. data/public/ace/mode-rdoc.js +184 -0
  80. data/public/ace/mode-rhtml.js +2168 -0
  81. data/public/ace/mode-ruby.js +431 -0
  82. data/public/ace/mode-sass.js +442 -0
  83. data/public/ace/mode-scad.js +670 -0
  84. data/public/ace/mode-scala.js +1025 -0
  85. data/public/ace/mode-scheme.js +144 -0
  86. data/public/ace/mode-scss.js +832 -0
  87. data/public/ace/mode-sh.js +204 -0
  88. data/public/ace/mode-sql.js +118 -0
  89. data/public/ace/mode-stylus.js +483 -0
  90. data/public/ace/mode-svg.js +1442 -0
  91. data/public/ace/mode-tcl.js +319 -0
  92. data/public/ace/mode-tex.js +166 -0
  93. data/public/ace/mode-text.js +0 -0
  94. data/public/ace/mode-textile.js +170 -0
  95. data/public/ace/mode-tmsnippet.js +200 -0
  96. data/public/ace/mode-toml.js +180 -0
  97. data/public/ace/mode-typescript.js +961 -0
  98. data/public/ace/mode-vbscript.js +281 -0
  99. data/public/ace/mode-velocity.js +962 -0
  100. data/public/ace/mode-xml.js +789 -0
  101. data/public/ace/mode-xquery.js +2750 -0
  102. data/public/ace/mode-yaml.js +289 -0
  103. data/public/ace/theme-ambiance.js +202 -0
  104. data/public/ace/theme-chaos.js +182 -0
  105. data/public/ace/theme-chrome.js +161 -0
  106. data/public/ace/theme-clouds.js +135 -0
  107. data/public/ace/theme-clouds_midnight.js +136 -0
  108. data/public/ace/theme-cobalt.js +150 -0
  109. data/public/ace/theme-crimson_editor.js +154 -0
  110. data/public/ace/theme-dawn.js +146 -0
  111. data/public/ace/theme-dreamweaver.js +173 -0
  112. data/public/ace/theme-eclipse.js +122 -0
  113. data/public/ace/theme-github.js +136 -0
  114. data/public/ace/theme-idle_fingers.js +136 -0
  115. data/public/ace/theme-kr.js +143 -0
  116. data/public/ace/theme-merbivore.js +135 -0
  117. data/public/ace/theme-merbivore_soft.js +136 -0
  118. data/public/ace/theme-mono_industrial.js +148 -0
  119. data/public/ace/theme-monokai.js +140 -0
  120. data/public/ace/theme-pastel_on_dark.js +148 -0
  121. data/public/ace/theme-solarized_dark.js +128 -0
  122. data/public/ace/theme-solarized_light.js +131 -0
  123. data/public/ace/theme-terminal.js +154 -0
  124. data/public/ace/theme-textmate.js +0 -0
  125. data/public/ace/theme-tomorrow.js +147 -0
  126. data/public/ace/theme-tomorrow_night.js +147 -0
  127. data/public/ace/theme-tomorrow_night_blue.js +145 -0
  128. data/public/ace/theme-tomorrow_night_bright.js +147 -0
  129. data/public/ace/theme-tomorrow_night_eighties.js +144 -0
  130. data/public/ace/theme-twilight.js +147 -0
  131. data/public/ace/theme-vibrant_ink.js +131 -0
  132. data/public/ace/theme-xcode.js +125 -0
  133. data/public/ace/worker-coffee.js +7091 -0
  134. data/public/ace/worker-css.js +8289 -0
  135. data/public/ace/worker-javascript.js +6496 -0
  136. data/public/ace/worker-json.js +2305 -0
  137. data/public/ace/worker-lua.js +3313 -0
  138. data/public/ace/worker-php.js +6743 -0
  139. data/public/ace/worker-xquery.js +21897 -0
  140. data/public/font/FontAwesome.otf +0 -0
  141. data/public/font/fontawesome-webfont.eot +0 -0
  142. data/public/font/fontawesome-webfont.svg +284 -0
  143. data/public/font/fontawesome-webfont.ttf +0 -0
  144. data/public/font/fontawesome-webfont.woff +0 -0
  145. data/public/font-awesome.css +540 -0
  146. data/public/jquery.js +9597 -0
  147. data/script/migrate.sh +2 -0
  148. metadata +242 -0
data/.env.sample ADDED
@@ -0,0 +1,7 @@
1
+ # cat .env.sample > .env
2
+
3
+ # URL to the database that queries will be run against
4
+ REPORTING_DATABASE_URL=mysql2://root@127.0.0.1/my_database
5
+
6
+ # URL to the database where queries are persisted
7
+ QUERY_DATABASE_URL=sqlite://my_query_database.db
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .env
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ .sass-cache
20
+ db/*.db
data/.rbenv-version ADDED
@@ -0,0 +1 @@
1
+ 1.9.3-p125
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'coffee-script'
4
+ gem 'thin'
5
+ gem 'mysql2'
6
+ gem 'json'
7
+ gem 'therubyracer'
8
+ gem 'sass'
9
+ gem 'sqlite3'
10
+
11
+ # Specify your gem's dependencies in datagram.gemspec
12
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Brad Gessler
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Procfile ADDED
@@ -0,0 +1 @@
1
+ web: bundle exec thin start -R config.ru -p $PORT
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Datagram
2
+
3
+ Gist for SQL Queries.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'datagram'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install datagram
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/config.ru ADDED
@@ -0,0 +1,5 @@
1
+ require 'datagram'
2
+
3
+ use Rack::MethodOverride
4
+
5
+ run Datagram::App.new
data/datagram.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'datagram/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "datagram"
8
+ gem.version = Datagram::VERSION
9
+ gem.authors = ["Matt Diebolt", "Brad Gessler"]
10
+ gem.email = ["matt@polleverywhere.com", "brad@polleverywhere.com"]
11
+ gem.description = %q{Gist for MySQL}
12
+ gem.summary = %q{Like Gist, for SQL.}
13
+ gem.homepage = "https://github.com/polleverywhere/datagram"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency "sinatra", ">= 1.4.0"
21
+ gem.add_dependency "haml"
22
+ gem.add_dependency "sequel"
23
+ end
@@ -0,0 +1,9 @@
1
+ Sequel.migration do
2
+ change do
3
+ create_table(:queries) do
4
+ primary_key :id
5
+ String :content, :null => false
6
+ String :filter
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ Sequel.migration do
2
+ change do
3
+ add_column :queries, :name, String
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module Datagram
2
+ VERSION = "0.0.1"
3
+ end
data/lib/datagram.rb ADDED
@@ -0,0 +1,135 @@
1
+ require "datagram/version"
2
+
3
+ require 'coffee-script'
4
+ require 'sinatra'
5
+ require 'sequel'
6
+ require 'haml'
7
+ require 'json'
8
+
9
+ require 'v8'
10
+
11
+ module Datagram
12
+ Sequel::Model.plugin :json_serializer
13
+
14
+ db = Sequel.connect(ENV['QUERY_DATABASE_URL'])
15
+
16
+ class Query < Sequel::Model
17
+ end
18
+
19
+ class App < Sinatra::Base
20
+ set :public_dir, 'public'
21
+
22
+ get '/' do
23
+ if Query.count == 0
24
+ content = """/*
25
+ Enter your SQL query below.
26
+ You can run, save, or delete queries using the buttons above
27
+ */
28
+
29
+ SELECT *
30
+ FROM users
31
+ """
32
+
33
+ filter = """// Enter your JavaScript filter below.
34
+ // Filters modify the returned SQL dataset
35
+ // Query results are available for manipulation
36
+ // via the global variable `results`. Your filtered
37
+ // results will be used to build the report.
38
+ [results[0]]
39
+ """
40
+
41
+ name = 'default query'
42
+
43
+ Query.create :content => content, :filter => filter, :name => name
44
+ end
45
+
46
+ @queries = Query.all
47
+
48
+ haml :index
49
+ end
50
+
51
+ get '/run' do
52
+ @content = params[:content]
53
+ @filter = params[:filter] || ''
54
+
55
+ begin
56
+ @ds = self.class.reporting_db.fetch(@content)
57
+ results = @ds.to_a
58
+
59
+ status 200
60
+ body({:columns => @ds.columns, :items => results}.to_json)
61
+ rescue Sequel::Error => e
62
+ status 500
63
+ body({:message => e.message}.to_json)
64
+ end
65
+ end
66
+
67
+ post '/queries' do
68
+ @content = params[:content]
69
+ @filter = params[:filter] || ''
70
+ @name = params[:name] || ''
71
+
72
+ if query = Query.create(:content => @content, :filter => @filter, :name => @name)
73
+ status 200
74
+ body(query.to_json)
75
+ end
76
+ end
77
+
78
+ get '/queries/:id' do |id|
79
+ if query = Query[id]
80
+ @ds = self.class.reporting_db.fetch(query.content)
81
+ results = @ds.to_a
82
+
83
+ context = V8::Context.new
84
+
85
+ context['results'] = results
86
+ context['filter'] = query.filter
87
+ context['filteredResults'] = context.eval('JSON.stringify(eval(filter))')
88
+
89
+ status 200
90
+
91
+ if context['filteredResults'].nil?
92
+ body(results.to_json)
93
+ else
94
+ body(context['filteredResults'])
95
+ end
96
+ end
97
+ end
98
+
99
+ put '/queries/:id' do |id|
100
+ if query = Query[id]
101
+ name = params[:name] || "Query #{id}"
102
+ content = params[:content] || ''
103
+ filter = params[:filter] || ''
104
+
105
+ query.update_all :name => name, :content => content, :filter => filter
106
+
107
+ status 200
108
+ body(query.to_json)
109
+ end
110
+ end
111
+
112
+ delete '/queries/:id' do |id|
113
+ @query = Query[id]
114
+
115
+ @query.destroy
116
+
117
+ status 204
118
+ end
119
+
120
+ # assets
121
+ get '/style.css' do
122
+ content_type 'text/css', :charset => 'utf-8'
123
+ sass :style
124
+ end
125
+
126
+ get '/application.js' do
127
+ coffee :application
128
+ end
129
+
130
+ private
131
+ def self.reporting_db
132
+ @reporting_db ||= Sequel.connect(ENV['REPORTING_DATABASE_URL'])
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,222 @@
1
+ ## configure editors
2
+ editor = ace.edit('editor')
3
+ editor.setTheme('ace/theme/tomorrow')
4
+ editor.session.setMode('ace/mode/sql')
5
+
6
+ editorSession = editor.getSession()
7
+
8
+ editor.setShowPrintMargin(false)
9
+ editor.renderer.setShowGutter(false)
10
+
11
+ editorSession.setTabSize(2)
12
+ editorSession.setUseSoftTabs(true)
13
+
14
+ filterEditor = ace.edit('filter-editor')
15
+ filterEditor.setTheme('ace/theme/tomorrow')
16
+ filterEditor.session.setMode('ace/mode/javascript')
17
+
18
+ filterSession = filterEditor.getSession()
19
+
20
+ filterEditor.setShowPrintMargin(false)
21
+ filterEditor.clearSelection()
22
+
23
+ filterEditor.renderer.setShowGutter(false)
24
+
25
+ filterSession.setTabSize(2)
26
+ filterSession.setUseSoftTabs(true)
27
+ ##
28
+
29
+ $ ->
30
+ setTimeout ->
31
+ # default to selecting the last query
32
+ if ($last = $('.query:last')).length
33
+ $last.click()
34
+ , 1
35
+
36
+ addQuery = (data) ->
37
+ queryName = if data.name.length then data.name else "Query #{data.id}"
38
+
39
+ $query = "<li class='query' data-content='#{data.content}' data-filter='#{data.filter}' data-name='#{data.name}' data-id='#{data.id}''>#{queryName}</li>"
40
+
41
+ $('.queries').append $query
42
+
43
+ updateQuery = (data) ->
44
+ $query = $('.query.active')
45
+
46
+ $query.attr
47
+ 'data-name': data.name
48
+ 'data-filter': data.filter
49
+ 'data-content': data.content
50
+
51
+ updateQueryName = (newName) ->
52
+ $('header .title .name').removeClass('display-none').text(newName)
53
+ $('header .title .edit-title').addClass('display-none')
54
+
55
+ if ($query = $('.query.active')).length
56
+ $query.text(newName)
57
+ $query.attr('data-name', newName)
58
+
59
+ exportResults = (data, filter) ->
60
+ # export results to the global scope
61
+ # so people can tweak them.
62
+ window.results = data.items
63
+ console.log(results)
64
+
65
+ if filter.length
66
+ window.filteredResults = eval(filter)
67
+
68
+ displayResultsCount = (data) ->
69
+ $('.sql-results, .filter-results').show()
70
+
71
+ $('.sql-results .count').text("#{window.results.length} SQL results returned")
72
+ $('.filter-results .count').text("#{window.filteredResults.length} results after applying JavaScript filter")
73
+
74
+ resultsTable = (data, filter) ->
75
+ $('.results thead, .results tbody').empty()
76
+
77
+ for column in data.columns
78
+ $('table thead').append "<th>#{column}</th>"
79
+
80
+ for item in (if window.filteredResults?.length then window.filteredResults else window.results)
81
+ $tr = $('<tr>')
82
+
83
+ for key, value of item
84
+ $tr.append "<td>#{value}</td>"
85
+
86
+ $('table tbody').append $tr
87
+
88
+ $('.icon-remove').on 'click', ->
89
+ $('.error-message').addClass('display-none')
90
+
91
+ $(document).on 'keydown', (e) ->
92
+ return unless e.keyCode is 27
93
+
94
+ $('.error-message').addClass('display-none')
95
+
96
+ $(document).on 'click', (e) ->
97
+ $target = $(e.target)
98
+
99
+ return if $target.is('.title .edit-title, .title h2')
100
+
101
+ name = $('header .title .edit-title').val()
102
+
103
+ updateQueryName(name)
104
+
105
+ $('header .title .edit-title').on 'keydown', (e) ->
106
+ return unless e.keyCode is 13
107
+
108
+ name = $('header .title .edit-title').val()
109
+
110
+ updateQueryName(name)
111
+
112
+ $('header .title h2').on 'click', (e) ->
113
+ $target = $(e.currentTarget)
114
+
115
+ width = $target.width()
116
+
117
+ $target.addClass 'display-none'
118
+ $target.next().removeClass('display-none').width(width).select()
119
+
120
+ $('.file-tree').on 'click', '.query', (e) ->
121
+ $target = $(e.currentTarget)
122
+
123
+ $('.query').removeClass 'active'
124
+
125
+ $target.addClass 'active'
126
+
127
+ editor.setValue $target.attr('data-content')
128
+ filterEditor.setValue $target.attr('data-filter')
129
+
130
+ $('header .title .name').text($target.text())
131
+ $('header .title .edit-title').val($target.text())
132
+
133
+ $('.btn-show-results').on 'click', (e) ->
134
+ $target = $(e.currentTarget)
135
+
136
+ $editor = $('#editor')
137
+ $results = $('#results')
138
+
139
+ $target.toggleClass 'active'
140
+
141
+ if $target.is('.active')
142
+ $('.query-content').addClass('display-none')
143
+ $('.results-content').removeClass('display-none')
144
+ else
145
+ $('.query-content').removeClass('display-none')
146
+ $('.results-content').addClass('display-none')
147
+
148
+ $('.btn-save').on 'click', ->
149
+ $query = $('.query.active')
150
+
151
+ id = $query.data('id')
152
+ name = $query.data('name')
153
+
154
+ $.ajax
155
+ type: 'PUT'
156
+ url: "/queries/#{id}"
157
+ data:
158
+ content: editor.getValue()
159
+ filter: filterEditor.getValue()
160
+ name: name
161
+ dataType: 'json'
162
+ success: updateQuery
163
+
164
+ $('.btn-copy').on 'click', ->
165
+ queryName = $('header .title .name').text()
166
+
167
+ $.ajax
168
+ type: 'POST'
169
+ url: '/queries'
170
+ data:
171
+ content: editor.getValue()
172
+ filter: filterEditor.getValue()
173
+ name: if queryName.length then queryName else 'new query'
174
+ dataType: 'json'
175
+ success: (data) ->
176
+ addQuery(data)
177
+ $('.query:last').click()
178
+
179
+ $('.btn-run').on 'click', ->
180
+ $.ajax
181
+ type: 'GET'
182
+ url: '/run'
183
+ data:
184
+ content: editor.getValue()
185
+ dataType: 'json'
186
+ success: (data) ->
187
+ exportResults(data, filterEditor.getValue())
188
+ resultsTable(data)
189
+ displayResultsCount(data)
190
+ error: (response) ->
191
+ try
192
+ {message} = JSON.parse(response.responseText)
193
+
194
+ $('.error-message .text').text(message)
195
+
196
+ $('.error-message').removeClass('display-none')
197
+
198
+ $('.sql-results, .filter-results').on 'click', (e) ->
199
+ $target = $(e.currentTarget)
200
+
201
+ $target.hide()
202
+
203
+ $('.btn-delete').on 'click', ->
204
+ $query = $('.query.active')
205
+
206
+ alert "You must select a query to delete" unless $query.length
207
+
208
+ id = $query.data('id')
209
+ queryName = if $query.data('name').length then $query.data('name') else "Query #{id}"
210
+
211
+ if confirm "Are you sure you want to delete '#{queryName}'?"
212
+ $.ajax
213
+ type: 'DELETE'
214
+ url: "queries/#{id}"
215
+ dataType: 'json'
216
+ success: ->
217
+ if ($next = $query.next()).length
218
+ $next.addClass 'active'
219
+ else if ($previous = $query.prev()).length
220
+ $previous.addClass 'active'
221
+
222
+ $query.remove()
@@ -0,0 +1,47 @@
1
+ %header
2
+ .btn-group.actions
3
+ %button.btn.btn-save(title='Save this query')
4
+ %i.icon-save
5
+ %button.btn.btn-copy(title='Copy this query')
6
+ %i.icon-copy
7
+ %button.btn.btn-delete(title='Delete this query')
8
+ %i.icon-trash
9
+
10
+ .btn-group.navigation
11
+ %button.btn.btn-run(title='Run this query')
12
+ %i.icon-play
13
+ /%button.btn.btn-show-results(title='View query results')
14
+ / %i.icon-table
15
+
16
+ .title
17
+ %h2.name
18
+ %input.edit-title.display-none(type='text' value='')
19
+
20
+ .query-content
21
+ .file-tree
22
+ %h4.title Saved Queries
23
+ %ul.queries
24
+ -@queries.each do |query|
25
+ -queryName = query.name.nil? ? "Query #{query.id}" : query.name
26
+
27
+ %li.query(data-content="#{query.content}" data-filter="#{query.filter}" data-name="#{query.name}" data-id="#{query.id}")=queryName
28
+
29
+ #editor
30
+ .sql-results
31
+ .count
32
+ #filter-editor
33
+ .filter-results
34
+ .count
35
+
36
+ .results-content.display-none
37
+ #results
38
+ %h1 Results
39
+
40
+ .query-results
41
+ %table.table.table-striped.results
42
+ %thead
43
+ %tbody
44
+
45
+ .error-message.display-none
46
+ .text
47
+ .icon-remove
@@ -0,0 +1,17 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title Datagram
5
+ %link(href="/style.css" rel="stylesheet" type="text/css")
6
+ %link(href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet" type="text/css")
7
+ %link(href="/font-awesome.css" rel="stylesheet" type="text/css")
8
+
9
+ %script(src="jquery.js" type='text/javascript' charset='utf-8')
10
+ %script(src="ace/ace.js" type="text/javascript" charset="utf-8")
11
+ %script(src="ace/theme-tomorrow.js" type="text/javascript" charset="utf-8")
12
+ %script(src="ace/mode-sql.js" type="text/javascript" charset="utf-8")
13
+ %script(src="ace/mode-javascript.js" type="text/javascript" charset="utf-8")
14
+ %body
15
+ =yield
16
+
17
+ %script(src="/application.js" type="text/javascript" charset="utf-8")