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
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