twb 0.0.31 → 0.0.33

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 (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
data/bg.cmd ADDED
@@ -0,0 +1,5 @@
1
+ cls
2
+ @echo.
3
+ call gem build twb.gemspec
4
+ @echo.
5
+ call gem install %1%
data/lib/twb.rb CHANGED
@@ -3,10 +3,15 @@ require_relative 'twb/dashboard'
3
3
  require_relative 'twb/worksheet'
4
4
  require_relative 'twb/datasource'
5
5
  require_relative 'twb/storyboard'
6
+ require_relative 'twb/window'
7
+ require_relative 'twb/localfield'
8
+ require_relative 'twb/metadatafield'
9
+ require_relative 'twb/docdashboard'
10
+ require_relative 'twb/util/htmllistcollapsible'
6
11
 
7
- # Represents Tableau Workbooks and theis contents.
12
+ # Represents Tableau Workbooks and their contents.
8
13
  #
9
14
  module Twb
10
- VERSION = '0.0.31'
15
+ VERSION = '0.0.33'
11
16
  end
12
17
 
data/lib/twb/dashboard.rb CHANGED
@@ -22,25 +22,25 @@ module Twb
22
22
 
23
23
  @@hasher = Digest::SHA256.new
24
24
 
25
- attr_reader :node, :name, :worksheets, :autosize, :size, :maxheight, :maxwidth, :minheight, :minwidth, :rangesize, :dimensions
25
+ attr_reader :node, :name, :worksheets, :autosize, :size, :maxheight, :maxwidth, :minheight, :minwidth, :rangesize, :dimensions, :zonecount
26
26
 
27
- def initialize dashboardNode
28
- "initialize Dashboard"
27
+ def initialize dashboardNode, twbworksheets
29
28
  @node = dashboardNode
30
29
  @name = @node.attr('name')
31
30
  @size = @node.xpath('./size')
32
31
  @autosize = @size.empty?
33
32
  loadSize @size unless @autosize
34
- loadSheets
33
+ loadSheets twbworksheets
34
+ @zonecount = @node.xpath('.//zone').length
35
35
  return self
36
36
  end
37
37
 
38
- def loadSheets
38
+ def loadSheets twbworksheets
39
39
  @sheets = {}
40
40
  dsheets = @node.xpath('.//zone[@name]').to_a
41
41
  dsheets.each do |sheetNode|
42
- sheet = Twb::Worksheet.new sheetNode
43
- @sheets[sheet.name] = sheet
42
+ sheetname = sheetNode.attr('name')
43
+ @sheets[sheetname] = twbworksheets[sheetname]
44
44
  end
45
45
  end
46
46
 
@@ -22,7 +22,7 @@ module Twb
22
22
 
23
23
  @@hasher = Digest::SHA256.new
24
24
 
25
- attr_reader :node, :name, :caption, :uiname, :connHash, :class, :connection, :tables
25
+ attr_reader :node, :name, :caption, :uiname, :connHash, :class, :connection, :tables, :localfields, :metadatafields
26
26
 
27
27
  def initialize dataSourceNode
28
28
  @node = dataSourceNode
@@ -30,25 +30,33 @@ module Twb
30
30
  @caption = @node.attr('caption')
31
31
  @uiname = if @caption.nil? || @caption == '' then @name else @caption end
32
32
  processConnection
33
+ processFields
33
34
  return self
34
35
  end
35
36
 
36
37
  def processConnection
37
- @connHash = ''
38
38
  @connection = @node.at_xpath('./connection')
39
39
  unless @connection.nil?
40
40
  @class = @connection.attribute('class').text
41
- dsAttributes = @node.xpath('./connection/@*')
42
- dsConnStr = ''
43
- dsAttributes.each do |attr|
44
- dsConnStr += attr.text
45
- # Note: '' attributes with value '' don't contribute to the hash
46
- end
47
- @connHash = Digest::MD5.hexdigest(dsConnStr)
41
+ setConnectionHash
48
42
  loadTables @connection
49
43
  end
50
44
  end
51
45
 
46
+ # Notes:
47
+ # - TODO: need to determine which, if any, of the connection attributes should be
48
+ # included in the hash in order to identify it unambiguously - without
49
+ # local values that obscure the data source's 'real' identity
50
+ # - attributes with value '' don't contribute to the hash
51
+ def setConnectionHash
52
+ dsAttributes = @node.xpath('./connection/@*')
53
+ dsConnStr = ''
54
+ dsAttributes.each do |attr|
55
+ dsConnStr += attr.text
56
+ end
57
+ @connHash = Digest::MD5.hexdigest(dsConnStr)
58
+ end
59
+
52
60
  def loadTables connection
53
61
  @tables = {}
54
62
  nodes = connection.xpath(".//relation[@type='table']")
@@ -61,6 +69,27 @@ module Twb
61
69
  @name == 'Parameters'
62
70
  end
63
71
 
72
+ def processFields
73
+ # --
74
+ @localfields = {}
75
+ nodes = @node.xpath(".//column")
76
+ nodes.each do |node|
77
+ field = Twb::LocalField.new(node)
78
+ @localfields[field.name] = field
79
+ end
80
+ # --
81
+ @metadatafields = {}
82
+ nodes = @node.xpath("./connection/metadata-records/metadata-record")
83
+ nodes.each do |node|
84
+ field = Twb::MetadataField.new(node)
85
+ @metadatafields[field.name] = field
86
+ end
87
+ end
88
+
89
+ def field name
90
+ field = if localfields[name].nil? then metadatafields[name] end
91
+ end
92
+
64
93
  end
65
94
 
66
95
  end
@@ -0,0 +1,123 @@
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 'set'
18
+
19
+ module Twb
20
+
21
+ class DocDashboard
22
+
23
+ @@types = Set.new( ['h', 'horiz', 'horizontal',
24
+ 'v', 'vert', 'vertical' ] )
25
+
26
+ attr_reader :title, :dashnode, :winnode, :type #, :panels, :autosize, :size
27
+
28
+ @@oneColWebPageDash = Nokogiri::XML::Document.parse <<-ONECOlWEBDASH
29
+ <dashdoc>
30
+ <dashboard name='Single Column Web Page Automatic'>
31
+ <style></style>
32
+ <zones>
33
+ <zone h='100000' id='3' param='vert' type='layout-flow' w='100000' x='0' y='0'>
34
+ <zone h='6221' id='1' type='title' w='100000' x='0' y='0'></zone>
35
+ <zone h='93157' id='4' param='horz' type='layout-flow' w='100000' x='0' y='6221'>
36
+ <zone forceUpdate='' h='93157' id='6' param='URL' type='web' w='99655' x='0' y='6221'></zone>
37
+ </zone>
38
+ </zone>
39
+ </zones>
40
+ </dashboard>
41
+ <window auto-hidden='0' class='dashboard' maximized='1' name='Single Column Web Page Automatic'>
42
+ <zones>
43
+ <zone h='6221' id='1' name='' type='title' w='100000' x='0' y='0' />
44
+ <zone forceUpdate='' h='93157' id='5' name='' param='Web Page' type='web' w='50000' x='50000' y='6221' />
45
+ </zones>
46
+ </window>
47
+ </dashdoc>
48
+ ONECOlWEBDASH
49
+ # notes:
50
+ # - adding a size element to the <dashboard element will change it from automatic, e.g.
51
+ #
52
+ # <dashboard name='One Column Web Page Laptop (800w 600h)'>
53
+ # <style>
54
+ # </style>
55
+ # <size maxheight='600' maxwidth='800' minheight='600' minwidth='800' />
56
+ #
57
+ # - the 'name' sttributes for the window and dashboard must match
58
+
59
+ def title=(title)
60
+ @title = title
61
+ @dashnode['name'] = title
62
+ @winnode['name'] = title
63
+ end
64
+
65
+ def size=(size)
66
+ @size = size
67
+ end
68
+
69
+ def initialize type
70
+ dashboard = if @@types.include?(type)
71
+ then if type[0] == 'v'
72
+ then DocDashboardVert.new
73
+ else DocDashboardHoriz.new
74
+ end
75
+ else nil
76
+ end
77
+ return dashboard
78
+ end
79
+
80
+ def to_s
81
+ return title + ' :: ' + type
82
+ end
83
+
84
+ end
85
+
86
+ class DocDashboardWebVert < DocDashboard
87
+
88
+ attr_reader :url
89
+
90
+ def initialize
91
+ @type = 'columnar Web Page'
92
+ @dashnode = @@oneColWebPageDash.at_xpath('//dashboard')
93
+ @winnode = @@oneColWebPageDash.at_xpath('//window')
94
+ end
95
+
96
+ def title=(title)
97
+ @title = title
98
+ @dashnode['name'] = title
99
+ @winnode['name'] = title
100
+ end
101
+
102
+ def url=(url)
103
+ dashwebzone = @dashnode.at_xpath('.//zone[@type="web"]')
104
+ dashwebzone['param'] = url # unless dashwebzone.nil?
105
+ winwebzone = @winnode.at_xpath('.//zone[@type="web"]')
106
+ winwebzone['param'] = url # unless winwebzone.nil?
107
+ end
108
+
109
+ def url
110
+ dashurl = @dashnode.at_xpath('.//zone[@type="web"]').attribute('param').value
111
+ winurl = @winnode.at_xpath( './/zone[@type="web"]').attribute('param').value
112
+ url = if dashurl == winurl then dashurl end
113
+ end
114
+
115
+ end
116
+
117
+ class DocDashboardWebHoriz < DocDashboard
118
+ def initialize
119
+ @type = 'horizontal'
120
+ end
121
+ end
122
+
123
+ end
data/lib/twb/field.rb ADDED
@@ -0,0 +1,39 @@
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 Field
21
+
22
+ attr_reader :node, :name, :datatype, :role, :type, :hidden, :caption, :aggregation, :uiname
23
+
24
+ def initialize fieldNode
25
+ @node = fieldNode
26
+ @name = @node.attr('name')
27
+ @datatype = @node.attr('datatype')
28
+ @role = @node.attr('role')
29
+ @type = @node.attr('type')
30
+ @hidden = @node.attr('hidden')
31
+ @caption = @node.attr('caption')
32
+ @aggregation = @node.attr('aggregation')
33
+ @uiname = if @caption.nil? || @caption == '' then @name else @caption end
34
+ return self
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,39 @@
1
+ class HashToHTMLList
2
+ def initialize(hash)
3
+ @hash = hash
4
+ @indent = " "
5
+ @tag_space = ""
6
+ @level = 0
7
+ @out = []
8
+ end
9
+
10
+ def append(tag,value=nil)
11
+ str = @indent * @level + "#{tag}"
12
+ str += @tag_space + value unless value.nil?
13
+ str += "\n"
14
+ @out << str
15
+ end
16
+
17
+ def ul(hash)
18
+ open_tag('ul') { li(hash) }
19
+ end
20
+
21
+ def li(hash)
22
+ @level += 1
23
+ hash.each do |key,value|
24
+ open_tag('li',key) { ul(value) if value.is_a?(Hash) }
25
+ end
26
+ @level -= 1
27
+ end
28
+
29
+ def list
30
+ ul(@hash)
31
+ @out.join
32
+ end
33
+
34
+ def open_tag(tag,value=nil,&block)
35
+ append("<#{tag}>",value)
36
+ yield if block_given?
37
+ append("</#{tag}>")
38
+ end
39
+ end
@@ -0,0 +1,154 @@
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 HTMLListCollapsible
21
+
22
+ @@doc = Nokogiri::HTML::Document.parse <<-COLLAPSIBLELIST
23
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
24
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
25
+ <head>
26
+ <title>Tableau Documentation</title>
27
+
28
+ <style type="text/css">
29
+ body, a {
30
+ color: #3B4C56;
31
+ font-family: sans-serif;
32
+ font-size: 14px;
33
+ text-decoration: none;
34
+ }
35
+ #pgtitle
36
+ {
37
+ margin: 0px 0px 20px;
38
+ font-size: 14pt;
39
+ text-align: center;
40
+ }
41
+ a{
42
+ cursor:pointer;
43
+ }
44
+ .tree ul {
45
+ list-style: none outside none;
46
+ }
47
+ .tree li a {
48
+ line-height: 25px;
49
+ }
50
+ .tree > ul > li > a {
51
+ color: #3B4C56;
52
+ display: block;
53
+ font-weight: normal;
54
+ position: relative;
55
+ text-decoration: none;
56
+ }
57
+ .tree li.parent > a {
58
+ padding: 0 0 0 28px;
59
+ }
60
+ .tree li.parent > a:before {
61
+ background-image: url("Controls.png");
62
+ background-position: 20px center;
63
+ content: "";
64
+ display: block;
65
+ height: 20px;
66
+ left: 0;
67
+ position: absolute;
68
+ top: 2px;
69
+ vertical-align: middle;
70
+ width: 20px;
71
+ }
72
+ .tree ul li.active > a:before {
73
+ background-position: 0 center;
74
+ }
75
+ .tree ul li ul {
76
+ border-left: 1px solid #D9DADB;
77
+ display: none;
78
+ margin: 0 0 0 12px;
79
+ overflow: hidden;
80
+ padding: 0 0 0 25px;
81
+ }
82
+ .tree ul li ul li {
83
+ position: relative;
84
+ }
85
+ .tree ul li ul li:before {
86
+ border-bottom: 1px dashed #E2E2E3;
87
+ content: "";
88
+ left: -20px;
89
+ position: absolute;
90
+ top: 12px;
91
+ width: 15px;
92
+ }
93
+ #wrapper {
94
+ margin: 0 auto;
95
+ width: 300px;
96
+ }
97
+ </style>
98
+
99
+ <script src="http://code.jquery.com/jquery-1.7.2.min.js" type="text/javascript" > </script>
100
+
101
+ <script type="text/javascript">
102
+ $( document ).ready( function( ) {
103
+ $( '.tree li' ).each( function() {
104
+ if( $( this ).children( 'ul' ).length > 0 ) {
105
+ $( this ).addClass( 'parent' );
106
+ }
107
+ });
108
+
109
+ $( '.tree li.parent > a' ).click( function( ) {
110
+ $( this ).parent().toggleClass( 'active' );
111
+ $( this ).parent().children( 'ul' ).slideToggle( 'fast' );
112
+ });
113
+
114
+ $( '#all' ).click( function() {
115
+
116
+ $( '.tree li' ).each( function() {
117
+ $( this ).toggleClass( 'active' );
118
+ $( this ).children( 'ul' ).slideToggle( 'fast' );
119
+ });
120
+ });
121
+
122
+ $( '.tree li' ).each( function() {
123
+ $( this ).toggleClass( 'active' );
124
+ $( this ).children( 'ul' ).slideToggle( 'fast' );
125
+ });
126
+
127
+ });
128
+
129
+ </script>
130
+
131
+ </head>
132
+ <body>
133
+ <div id="pgtitle">
134
+ Expandable nested list.
135
+ </div>
136
+ <div id="wrapper">
137
+ <div class="tree">
138
+ <button id="all">Toggle all</button>
139
+ <ul>
140
+ </ul>
141
+ </div>
142
+ </div>
143
+
144
+ </body>
145
+ </html>
146
+ COLLAPSIBLELIST
147
+
148
+ def html
149
+ " here's the @@doc"
150
+ end
151
+
152
+ end
153
+
154
+ end