twb 0.0.31 → 0.0.33

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/bg.cmd +5 -0
  2. data/lib/twb.rb +7 -2
  3. data/lib/twb/dashboard.rb +7 -7
  4. data/lib/twb/datasource.rb +38 -9
  5. data/lib/twb/docdashboard.rb +123 -0
  6. data/lib/twb/field.rb +39 -0
  7. data/lib/twb/hashtohtml.rb +39 -0
  8. data/lib/twb/htmllistcollapsible.rb +154 -0
  9. data/lib/twb/localfield.rb +42 -0
  10. data/lib/twb/metadatafield.rb +55 -0
  11. data/lib/twb/util/UpLeftArrowsNav.png +0 -0
  12. data/lib/twb/util/hashtohtml.rb +45 -0
  13. data/lib/twb/util/htmllistcollapsible.rb +195 -0
  14. data/lib/twb/window.rb +31 -0
  15. data/lib/twb/workbook.rb +77 -12
  16. data/lib/twb/worksheet.rb +29 -1
  17. data/test/No Content.injected.twb +82 -0
  18. data/test/No Content.twb +68 -0
  19. data/test/No Dashboards.injected.twb +618 -0
  20. data/test/No Dashboards.twb +604 -0
  21. data/test/Special Documentation.html +198 -0
  22. data/test/TableauDocInlineCSS.html +165 -0
  23. data/test/UpLeftArrowsNav.png +0 -0
  24. data/test/Web Page Dashboards.injected.twb +1361 -0
  25. data/test/Web Page Dashboards.twb +1347 -0
  26. data/test/collapsibleList.html +198 -0
  27. data/test/testDocDashboard.rb +53 -0
  28. data/test/testDocDashboardCreate.rb +33 -0
  29. data/test/testHTMLList.rb +23 -0
  30. data/test/testTwbGem.rb +67 -0
  31. data/testTwbGem.rb +23 -9
  32. data/testTwbWrite.rb +22 -0
  33. data/twb-0.0.32.gem +0 -0
  34. metadata +29 -12
  35. data/twb-0.0.1.gem +0 -0
  36. data/twb-0.0.2.gem +0 -0
  37. data/twb-0.0.21.gem +0 -0
  38. data/twb-0.0.22.gem +0 -0
  39. data/twb-0.0.23.gem +0 -0
  40. data/twb-0.0.24.gem +0 -0
  41. data/twb-0.0.25.gem +0 -0
  42. data/twb-0.0.26.gem +0 -0
  43. data/twb-0.0.27.gem +0 -0
  44. data/twb-0.0.29.gem +0 -0
  45. data/twb-0.0.30.gem +0 -0
@@ -0,0 +1,42 @@
1
+ # Copyright (C) 2014, 2015 Chris Gerrard
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require 'nokogiri'
17
+
18
+ module Twb
19
+
20
+ # Assumption: A field can only be either a MetadataField or a LocalField, not both in a given Workbook data connection.
21
+
22
+ class LocalField
23
+
24
+ attr_reader :type, :node, :name, :datatype, :role, :type, :hidden, :caption, :aggregation, :uiname
25
+
26
+ def initialize fieldNode
27
+ @node = fieldNode
28
+ @type = 'local'
29
+ @name = @node.attr('name')
30
+ @datatype = @node.attr('datatype')
31
+ @role = @node.attr('role')
32
+ @type = @node.attr('type')
33
+ @hidden = @node.attr('hidden')
34
+ @caption = @node.attr('caption')
35
+ @aggregation = @node.attr('aggregation')
36
+ @uiname = if @caption.nil? || @caption == '' then @name else @caption end
37
+ return self
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,55 @@
1
+ # Copyright (C) 2014, 2015 Chris Gerrard
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require 'nokogiri'
17
+
18
+ module Twb
19
+
20
+ # Assumption: A field can only be either a MetadataField or a LocalField, not both in a given Workbook data connection.
21
+
22
+ class MetadataField
23
+
24
+ attr_reader :node, :aggregation, :containsnull, :localname, :localtype, :ordinal, :parentname, :precision, :remotealias, :remotename, :remotetype, :width, :name
25
+
26
+ def initialize fieldNode
27
+ @node = fieldNode
28
+ @aggregation = load 'aggregation'
29
+ @containsnull = load 'contains-null'
30
+ @localname = load 'local-name'
31
+ @localtype = load 'local-type'
32
+ @ordinal = load 'ordinal'
33
+ @parentname = load 'parent-name'
34
+ @precision = load 'precision'
35
+ @remotealias = load 'remote-alias'
36
+ @remotename = load 'remote-name'
37
+ @name = @remotename
38
+ @remotetype = load 'remote-type'
39
+ @width = load 'width'
40
+ return self
41
+ end
42
+
43
+ def load nodeName
44
+ node = @node.at_xpath(nodeName)
45
+ val = if node.nil? then node else node.text end
46
+ # puts "==== MD node:'#{nodeName}' \t nil?'#{node.nil?}' \t == val:#{val} \t = '#{node}' "
47
+ return val
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+
54
+
55
+
Binary file
@@ -0,0 +1,45 @@
1
+ class HashToHTMLList
2
+
3
+ def initialize(hash)
4
+ @hash = hash
5
+ @indent = " "
6
+ @tag_space = ""
7
+ @level = 0
8
+ @out = []
9
+ end
10
+
11
+ def append(tag,value=nil)
12
+ str = @indent * @level + "#{tag}"
13
+ str += @tag_space + "<a>" + value + "</a>" unless value.nil?
14
+ str += "\n"
15
+ @out << str
16
+ end
17
+
18
+ def ul(hash)
19
+ open_tag('ul') { li(hash) }
20
+ end
21
+
22
+ def li(collection)
23
+ @level += 1
24
+ collection.each do |key,value|
25
+ open_tag('li',key) { ul(value) if value.is_a?(Hash) || value.is_a?(Array) }
26
+ end
27
+ @level -= 1
28
+ end
29
+
30
+ def list
31
+ ul(@hash)
32
+ @out.join
33
+ end
34
+
35
+ def open_tag(tag,value=nil,&block)
36
+ append("<#{tag}>",value)
37
+ yield if block_given?
38
+ append("</#{tag}>")
39
+ end
40
+
41
+ def to_s
42
+ @out
43
+ end
44
+
45
+ end
@@ -0,0 +1,195 @@
1
+ # Copyright (C) 2014, 2015 Chris Gerrard
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require 'nokogiri'
17
+ require 'fileutils'
18
+ require_relative 'hashtohtml'
19
+
20
+ module Twb
21
+
22
+ class HTMLListCollapsible
23
+
24
+ @@doc = Nokogiri::HTML::Document.parse <<-COLLAPSIBLELIST
25
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
26
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
27
+ <head>
28
+ <title>Tableau Documentation</title>
29
+
30
+ <style type="text/css">
31
+ body, a {
32
+ color: #3B4C56;
33
+ font-family: sans-serif;
34
+ font-size: 14px;
35
+ text-decoration: none;
36
+ }
37
+ #pgtitle
38
+ {
39
+ margin: 0px 0px 20px;
40
+ font-size: 14pt;
41
+ text-align: center;
42
+ }
43
+ a{
44
+ cursor:pointer;
45
+ }
46
+ .tree ul {
47
+ list-style: none outside none;
48
+ }
49
+ .tree li a {
50
+ line-height: 25px;
51
+ }
52
+ .tree > ul > li > a {
53
+ color: #3B4C56;
54
+ display: block;
55
+ font-weight: normal;
56
+ position: relative;
57
+ text-decoration: none;
58
+ }
59
+ .tree li.parent > a {
60
+ padding: 0 0 0 28px;
61
+ }
62
+ .tree li.parent > a:before {
63
+ background-image: url("UpLeftArrowsNav.png");
64
+ background-position: 20px center;
65
+ content: "";
66
+ display: block;
67
+ height: 20px;
68
+ left: 0;
69
+ position: absolute;
70
+ top: 2px;
71
+ vertical-align: middle;
72
+ width: 20px;
73
+ }
74
+ .tree ul li.active > a:before {
75
+ background-position: 0 center;
76
+ }
77
+ .tree ul li ul {
78
+ border-left: 1px solid #D9DADB;
79
+ display: none;
80
+ margin: 0 0 0 12px;
81
+ overflow: hidden;
82
+ padding: 0 0 0 25px;
83
+ }
84
+ .tree ul li ul li {
85
+ position: relative;
86
+ }
87
+ .tree ul li ul li:before {
88
+ border-bottom: 1px dashed #E2E2E3;
89
+ content: "";
90
+ left: -20px;
91
+ position: absolute;
92
+ top: 12px;
93
+ width: 15px;
94
+ }
95
+ #wrapper {
96
+ margin: 0 auto;
97
+ width: 300px;
98
+ }
99
+ </style>
100
+
101
+ <script src="http://code.jquery.com/jquery-1.7.2.min.js" type="text/javascript" > </script>
102
+
103
+ <script type="text/javascript">
104
+ $( document ).ready( function( ) {
105
+ $( '.tree li' ).each( function() {
106
+ if( $( this ).children( 'ul' ).length > 0 ) {
107
+ $( this ).addClass( 'parent' );
108
+ }
109
+ });
110
+
111
+ $( '.tree li.parent > a' ).click( function( ) {
112
+ $( this ).parent().toggleClass( 'active' );
113
+ $( this ).parent().children( 'ul' ).slideToggle( 'fast' );
114
+ });
115
+
116
+ $( '#all' ).click( function() {
117
+
118
+ $( '.tree li' ).each( function() {
119
+ $( this ).toggleClass( 'active' );
120
+ $( this ).children( 'ul' ).slideToggle( 'fast' );
121
+ });
122
+ });
123
+
124
+ $( '.tree li' ).each( function() {
125
+ $( this ).toggleClass( 'active' );
126
+ $( this ).children( 'ul' ).slideToggle( 'fast' );
127
+ });
128
+
129
+ });
130
+
131
+ </script>
132
+
133
+ </head>
134
+ <body>
135
+ <div id="pgtitle">
136
+ Expandable nested list.
137
+ </div>
138
+ <div id="wrapper">
139
+ <div class="tree">
140
+ <button id="all">Toggle all</button>
141
+ <ul>
142
+ </ul>
143
+ </div>
144
+ </div>
145
+
146
+ </body>
147
+ </html>
148
+ COLLAPSIBLELIST
149
+
150
+ def initialize(hash)
151
+ @htmldoc = @@doc
152
+ @list = HashToHTMLList.new(hash).list
153
+ ul = @htmldoc.at_xpath('//ul')
154
+ ul.replace(@list)
155
+ end
156
+
157
+ def title=(str)
158
+ title = @htmldoc.at_xpath('//div[@id="pgtitle"]')
159
+ title.content = str if title
160
+ end
161
+
162
+ def html
163
+ @htmldoc
164
+ end
165
+
166
+ # Write the HTML to a file using the provided name.
167
+ def write(name='collapsibleList.html')
168
+ $f = File.open(name,'w')
169
+ if $f
170
+ $f.puts @htmldoc
171
+ $f.close
172
+ end
173
+ installNavImageFile
174
+ end
175
+
176
+ def installNavImageFile
177
+ puts "looking for nav controls image"
178
+ # puts " __FILE__ #{__FILE__}" #File.expand_path(File.dirname(_FILE_))
179
+ puts " Dir.pwd #{Dir.pwd}"
180
+ puts " File.dirname(__FILE__) #{File.dirname(__FILE__)}"
181
+ puts " __FILE__ #{__FILE__}"
182
+ navimage = File.dirname(__FILE__) + "/UpLeftArrowsNav.png"
183
+ puts " filemask: #{navimage}"
184
+ cnt = 0
185
+ Dir.glob(navimage) do |twb|
186
+ puts twb
187
+ cnt += 1
188
+ end
189
+ puts " found #{cnt} files"
190
+ FileUtils.cp(navimage, Dir.pwd)
191
+ end
192
+
193
+ end
194
+
195
+ end
data/lib/twb/window.rb ADDED
@@ -0,0 +1,31 @@
1
+ # Copyright (C) 2014, 2015 Chris Gerrard
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require 'nokogiri'
17
+
18
+ module Twb
19
+
20
+ class Window
21
+
22
+ attr_reader :node, :name
23
+
24
+ def initialize node
25
+ @node = node
26
+ @name = @node.attr('name')
27
+ end
28
+
29
+ end
30
+
31
+ end
data/lib/twb/workbook.rb CHANGED
@@ -24,7 +24,7 @@ module Twb
24
24
 
25
25
  attr_reader :name, :dir, :modtime, :version, :build, :ndoc, :datasources, :dashboards, :storyboards, :worksheets
26
26
 
27
- # Creates a Workbook, from it's file name.
27
+ # Creates a Workbook, from its file name.
28
28
  #
29
29
  # == Parameters:
30
30
  # twbWithDir
@@ -35,17 +35,20 @@ module Twb
35
35
  @name = File.basename(twbWithDir)
36
36
  @dir = File.dirname(File.expand_path(twbWithDir))
37
37
  @modtime = File.new(twbWithDir).mtime
38
- @ndoc = Nokogiri::XML(open(twbWithDir))
38
+ @ndoc = Nokogiri::XML(open(twbWithDir))
39
+ @wbnode = @ndoc.at_xpath('//workbook')
39
40
  @version = @ndoc.xpath('/workbook/@version')
40
41
  @build = @ndoc.xpath('/workbook/comment()').text.gsub(/^[^0-9]+/,'').strip
41
42
  loaddatasources
43
+ loadWorksheets
42
44
  loadDashboards
43
45
  loadStoryboards
44
- loadWorksheets
46
+ loadWindows
45
47
  return true
46
48
  end
47
49
 
48
50
  def loaddatasources
51
+ @dataSources = @ndoc.at_xpath('//workbook/datasources')
49
52
  @datasources = {}
50
53
  @datasourceNodes = @ndoc.xpath('//workbook/datasources/datasource').to_a
51
54
  @datasourceNodes.each do |node|
@@ -55,12 +58,22 @@ module Twb
55
58
  return true
56
59
  end
57
60
 
61
+ def loadWorksheets
62
+ @worksheets = {}
63
+ sheets = @ndoc.xpath('//workbook/worksheets/worksheet' ).to_a
64
+ sheets.each do |node|
65
+ sheet = Twb::Worksheet.new(node)
66
+ @worksheets[sheet.name] = sheet
67
+ end
68
+ end
69
+
58
70
  def loadDashboards
71
+ @dashesNode = @ndoc.at_xpath('//workbook/dashboards')
59
72
  @dashboards = {}
60
73
  dashes = @ndoc.xpath('//workbook/dashboards/dashboard' ).to_a
61
74
  dashes.each do |node|
62
75
  unless node.attr('type') == 'storyboard' then
63
- dashboard = Twb::Dashboard.new(node)
76
+ dashboard = Twb::Dashboard.new(node, @worksheets)
64
77
  @dashboards[dashboard.name] = dashboard
65
78
  end
66
79
  end
@@ -75,12 +88,13 @@ module Twb
75
88
  end
76
89
  end
77
90
 
78
- def loadWorksheets
79
- @worksheets = {}
80
- sheets = @ndoc.xpath('//workbook/worksheets/worksheet' ).to_a
81
- sheets.each do |node|
82
- sheet = Twb::Worksheet.new(node)
83
- @worksheets[sheet.name] = sheet
91
+ def loadWindows
92
+ @windowsnode = @ndoc.at_xpath("//workbook/windows")
93
+ @windows = {}
94
+ windows = @ndoc.xpath("//workbook/windows/window[@name]")
95
+ windows.each do |node|
96
+ window = Twb::Window.new(node)
97
+ @windows[window.name] = window
84
98
  end
85
99
  end
86
100
 
@@ -101,7 +115,6 @@ module Twb
101
115
  @worksheets.values
102
116
  end
103
117
 
104
-
105
118
  def datasourceNames
106
119
  @datasources.keys
107
120
  end
@@ -118,7 +131,6 @@ module Twb
118
131
  @worksheets.keys
119
132
  end
120
133
 
121
-
122
134
  def datasource name
123
135
  @datasources[name]
124
136
  end
@@ -134,6 +146,59 @@ module Twb
134
146
  def worksheet name
135
147
  @worksheets[name]
136
148
  end
149
+
150
+ # Make sure that the TWB has a <dashboards> node.
151
+ # It's possible for a TWB to have no dashboards, and therefore no <dashboards> node.
152
+ def ensureDashboardsNodeExists
153
+ if @dashesNode.nil?
154
+ @dashesNode = Nokogiri::XML::Node.new "dashboards", @ndoc
155
+ @dataSources.add_next_sibling(@dashesNode)
156
+ end
157
+ end
158
+
159
+ # Add a new Documentation Dashboard to the TWB.
160
+ # Ensure that the TWB has a <dashboards> node (it may not).
161
+ # Make sure that the new Doc Dashboard's name doesn't conflict with an existing Dashboard - increment the incoming name if necessary.
162
+ # Add Doc Dashboard's <dashboard> and <window> nodes to the TWB; there's always a <windows> node in the TWB.
163
+ def addDocDashboard docDashboard
164
+ ensureDashboardsNodeExists
165
+ title = getNewDashboardTitle(docDashboard.title)
166
+ docDashboard.title=(title) unless title == docDashboard.title
167
+ @dashesNode.add_child(docDashboard.dashnode)
168
+ @windowsnode.add_child(docDashboard.winnode)
169
+ end
170
+
171
+ def getNewDashboardTitle(t)
172
+ title = t
173
+ if @datasources.include?(title)
174
+ inc = 0
175
+ loop do
176
+ inc+=1
177
+ title = t + ' ' + inc.to_s
178
+ if !@datasources.include?(title)
179
+ break
180
+ end
181
+ end
182
+ end
183
+ return title
184
+ end
185
+
186
+ # Write the TWB to a file, with an optional name.
187
+ # Can be used to write over the existing TWB (dangerous), or to a new file (preferred).
188
+ def write(name=@name)
189
+ $f = File.open(name,'w')
190
+ if $f
191
+ $f.puts @ndoc
192
+ $f.close
193
+ end
194
+ end
195
+
196
+ # Write the TWB to a file, appending the base name with the provided string.
197
+ # Intended for use when making adjustments to the TWB without overwriting the original.
198
+ def writeAppend(str)
199
+ newName = @name.sub(/[.]twb$/,'') + str.gsub(/^[.]*/,'.') + '.twb'
200
+ write newName
201
+ end
137
202
 
138
203
  end
139
204