concen 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 (67) hide show
  1. data/app/controllers/concen/application_controller.rb +25 -0
  2. data/app/controllers/concen/grid_files_controller.rb +75 -0
  3. data/app/controllers/concen/pages_controller.rb +95 -0
  4. data/app/controllers/concen/performances_controller.rb +35 -0
  5. data/app/controllers/concen/sessions_controller.rb +30 -0
  6. data/app/controllers/concen/statuses_controller.rb +63 -0
  7. data/app/controllers/concen/traffics_controller.rb +43 -0
  8. data/app/controllers/concen/users_controller.rb +118 -0
  9. data/app/controllers/concen/visits_controller.rb +38 -0
  10. data/app/helpers/concen/application_helper.rb +10 -0
  11. data/app/helpers/concen/pages_helper.rb +5 -0
  12. data/app/helpers/concen/visits_helper.rb +4 -0
  13. data/app/models/concen/grid_file.rb +67 -0
  14. data/app/models/concen/page.rb +342 -0
  15. data/app/models/concen/response.rb +45 -0
  16. data/app/models/concen/user.rb +88 -0
  17. data/app/models/concen/visit/page.rb +100 -0
  18. data/app/models/concen/visit/referral.rb +45 -0
  19. data/app/stylesheets/application.sass +445 -0
  20. data/app/stylesheets/config.rb +9 -0
  21. data/app/stylesheets/ie.sass +4 -0
  22. data/app/stylesheets/non_ios.sass +16 -0
  23. data/app/stylesheets/partials/_base.sass +92 -0
  24. data/app/stylesheets/partials/_fileuploader.sass +75 -0
  25. data/app/stylesheets/partials/_flot.sass +8 -0
  26. data/app/stylesheets/partials/_form.sass +74 -0
  27. data/app/stylesheets/partials/_mixins.sass +8 -0
  28. data/app/stylesheets/partials/_variables.sass +17 -0
  29. data/app/stylesheets/print.sass +4 -0
  30. data/app/views/concen/grid_files/_form.html.haml +15 -0
  31. data/app/views/concen/grid_files/edit.html.haml +9 -0
  32. data/app/views/concen/pages/_file_list.haml +7 -0
  33. data/app/views/concen/pages/_files.haml +24 -0
  34. data/app/views/concen/pages/_form.html.haml +18 -0
  35. data/app/views/concen/pages/_nested_list.html.haml +15 -0
  36. data/app/views/concen/pages/edit.html.haml +15 -0
  37. data/app/views/concen/pages/index.html.haml +9 -0
  38. data/app/views/concen/pages/new.html.haml +9 -0
  39. data/app/views/concen/performances/_runtimes.html.haml +5 -0
  40. data/app/views/concen/performances/show.html.haml +30 -0
  41. data/app/views/concen/sessions/new.html.haml +12 -0
  42. data/app/views/concen/statuses/_server.html.haml +19 -0
  43. data/app/views/concen/statuses/show.html.haml +18 -0
  44. data/app/views/concen/traffics/_pages.html.haml +5 -0
  45. data/app/views/concen/traffics/_referrals.html.haml +9 -0
  46. data/app/views/concen/traffics/show.html.haml +30 -0
  47. data/app/views/concen/users/_form.html.haml +29 -0
  48. data/app/views/concen/users/_password_reset.html.haml +0 -0
  49. data/app/views/concen/users/_settings.html.haml +15 -0
  50. data/app/views/concen/users/edit.html.haml +9 -0
  51. data/app/views/concen/users/index.html.haml +32 -0
  52. data/app/views/concen/users/new.html.haml +4 -0
  53. data/app/views/concen/users/new_invite.html.haml +15 -0
  54. data/app/views/concen/users/new_reset_password.html.haml +15 -0
  55. data/app/views/concen/visits/visit_recorder_js.erb +13 -0
  56. data/app/views/layouts/concen/_additional_header_links.haml +0 -0
  57. data/app/views/layouts/concen/_header.html.haml +18 -0
  58. data/app/views/layouts/concen/_iphone.html.haml +6 -0
  59. data/app/views/layouts/concen/application.html.haml +48 -0
  60. data/app/views/layouts/concen/maintenance.html.haml +0 -0
  61. data/config/routes.rb +64 -0
  62. data/lib/concen.rb +11 -0
  63. data/lib/concen/engine.rb +14 -0
  64. data/lib/concen/railties/page.rake +12 -0
  65. data/lib/concen/railties/setup.rake +23 -0
  66. data/lib/concen/version.rb +3 -0
  67. metadata +246 -0
@@ -0,0 +1,45 @@
1
+ module Concen
2
+ class Response
3
+ include Mongoid::Document
4
+ include Mongoid::Timestamps
5
+
6
+ store_in self.name.underscore.gsub("/", ".").pluralize
7
+
8
+ def self.aggregate_average_runtime(*args)
9
+ options = args.extract_options!
10
+
11
+ if options[:type]
12
+ runtime_type = "#{options[:type]}_runtime"
13
+ else
14
+ runtime_type = "total_runtime"
15
+ end
16
+
17
+ map = <<-EOF
18
+ function() {
19
+ emit(this.controller + "#" + this.action, this.#{runtime_type});
20
+ }
21
+ EOF
22
+
23
+ reduce = <<-EOF
24
+ function(controller_action, runtimes) {
25
+ var runtime = 0;
26
+ for (index in runtimes) { runtime += runtimes[index]; };
27
+ return runtime/runtimes.length;
28
+ }
29
+ EOF
30
+
31
+ begin
32
+ results = self.collection.map_reduce(map, reduce, :out => {:inline => 1}, :raw => true)["results"]
33
+ results = results.sort {|x,y| y["value"] <=> x["value"]}
34
+ results = results[0..options[:limit]-1] if options[:limit]
35
+ results = results.map do |result|
36
+ [result["_id"], result["value"]]
37
+ end
38
+ rescue
39
+ results = []
40
+ end
41
+
42
+ return results
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,88 @@
1
+ require "bcrypt"
2
+
3
+ module Concen
4
+ class User
5
+ include Mongoid::Document
6
+ include Mongoid::Timestamps
7
+
8
+ store_in self.name.underscore.gsub("/", ".").pluralize
9
+
10
+ field :full_name, :type => String
11
+ field :username, :type => String
12
+ field :email, :type => String
13
+ field :password_digest, :type => String
14
+ field :full_control, :type => Boolean, :default => false
15
+ field :auth_token, :type => String
16
+ field :password_reset_token, :type => String
17
+ field :password_reset_sent_at, :type => Time
18
+ field :invitation_token, :type => String
19
+ field :invitation_sent_at, :type => Time
20
+
21
+ attr_reader :password, :current_password
22
+ attr_accessible :full_name, :username, :email, :password, :password_confirmation, :current_password
23
+
24
+ validates_presence_of :username
25
+ validates_presence_of :email
26
+ validates_presence_of :full_name
27
+ validates_presence_of :password_digest
28
+ validates_uniqueness_of :username, :case_sensitive => false, :allow_blank => true
29
+ validates_uniqueness_of :email, :case_sensitive => false, :allow_blank => true
30
+ validates_length_of :username, :minimum => 3, :maximum => 30, :allow_blank => true
31
+ validates_format_of :username, :with => /^[a-zA-Z0-9_]+$/, :allow_blank => true
32
+ validates_confirmation_of :password
33
+ validates_presence_of :password, :on => :create
34
+
35
+ before_create { generate_token(:auth_token) }
36
+ before_update :nulify_unused_token
37
+
38
+ def authenticate(unencrypted_password)
39
+ if BCrypt::Password.new(self.password_digest) == unencrypted_password
40
+ self
41
+ else
42
+ false
43
+ end
44
+ end
45
+
46
+ def password=(unencrypted_password)
47
+ @password = unencrypted_password
48
+ unless unencrypted_password.blank?
49
+ self.password_digest = BCrypt::Password.create(unencrypted_password)
50
+ end
51
+ end
52
+
53
+ def send_password_reset
54
+ generate_token(:password_reset_token)
55
+ self.password_reset_sent_at = Time.now
56
+ save
57
+ Rails.logger.info "--called"
58
+ # Send email here.
59
+ end
60
+
61
+ def self.send_invitation(email)
62
+ password = ActiveSupport::SecureRandom.hex(4)
63
+ username = "user#{ActiveSupport::SecureRandom.hex(4)}"
64
+ new_user = self.new(
65
+ :full_name => username,
66
+ :username => username,
67
+ :email => email,
68
+ :password => password,
69
+ :password_confirmation => password
70
+ )
71
+ new_user.generate_token(:invitation_token)
72
+ new_user.invitation_sent_at = Time.now
73
+ new_user.save
74
+ # Send email here.
75
+ end
76
+
77
+ def generate_token(field)
78
+ self.write_attribute(field.to_sym, ActiveSupport::SecureRandom.urlsafe_base64)
79
+ end
80
+
81
+ def nulify_unused_token
82
+ self.password_reset_token = nil
83
+ self.password_reset_sent_at = nil
84
+ self.invitation_token = nil
85
+ self.invitation_sent_at = nil
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,100 @@
1
+ module Concen
2
+ module Visit
3
+ class Page
4
+ include Mongoid::Document
5
+
6
+ store_in self.name.underscore.gsub("/", ".").pluralize
7
+
8
+ field :hour, :type => Time
9
+ field :url, :type => String
10
+ field :count, :type => Integer, :default => 1
11
+ field :title, :type => String
12
+
13
+ index :hour, :background => true
14
+ index :url, :background => true
15
+
16
+ def self.aggregate_count_by_url(*args)
17
+ options = args.extract_options!
18
+
19
+ map = <<-EOF
20
+ function() {
21
+ emit(this.url, this.count);
22
+ }
23
+ EOF
24
+
25
+ reduce = <<-EOF
26
+ function(time, counts) {
27
+ var count = 0;
28
+ for (index in counts) { count += counts[index]; };
29
+ return count;
30
+ }
31
+ EOF
32
+
33
+ begin
34
+ results = self.collection.map_reduce(map, reduce, :out => {:inline => 1}, :raw => true)["results"]
35
+ results = results.sort {|x,y| y["value"] <=> x["value"]}
36
+ results = results[0..options[:limit]-1] if options[:limit]
37
+ results = results.map do |result|
38
+ [result["_id"], result["value"].to_i]
39
+ end
40
+ rescue
41
+ results = []
42
+ end
43
+
44
+ return results
45
+ end
46
+
47
+ def self.aggregate_count_by_time(*args)
48
+ options = args.extract_options!
49
+ if hour = options[:hour]
50
+ hour = hour.to_i
51
+ current_time = Time.now.utc
52
+ end_time = options[:start_time] || Time.utc(current_time.year, current_time.month, current_time.day, current_time.hour)
53
+ start_time = end_time - (hour-1).hours
54
+ hours = []
55
+ (0..hour-1).each do |h|
56
+ hours << (end_time - h.hours).to_i
57
+ end
58
+
59
+ map = <<-EOF
60
+ function() {
61
+ var hours = #{hours.to_json};
62
+ for (index in hours) {
63
+ if (this.hour.getTime() == hours[index]*1000) {
64
+ emit(hours[index], this.count);
65
+ } else {
66
+ emit(hours[index], 0);
67
+ };
68
+ };
69
+
70
+ }
71
+ EOF
72
+
73
+ reduce = <<-EOF
74
+ function(time, counts) {
75
+ var count = 0;
76
+ for (index in counts) { count += counts[index]; };
77
+ return count;
78
+ }
79
+ EOF
80
+
81
+ query = {:hour => {"$gte" => start_time, "$lte" => end_time}}
82
+
83
+ begin
84
+ results = self.collection.map_reduce(map, reduce, :out => {:inline => 1}, :raw => true, :query => query)["results"]
85
+ results = results.sort { |x,y| x["id"] <=> y["id"] }
86
+ results = results.map do |result|
87
+ time = result["_id"].to_i
88
+ time *= 1000 if options[:precision] == "millisecond"
89
+ [time, result["value"].to_i]
90
+ end
91
+ rescue
92
+ results = []
93
+ end
94
+
95
+ return results
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,45 @@
1
+ module Concen
2
+ module Visit
3
+ class Referral
4
+ include Mongoid::Document
5
+
6
+ store_in self.name.underscore.gsub("/", ".").pluralize
7
+
8
+ field :hour, :type => Time
9
+ field :url, :type => String
10
+ field :domain, :type => String
11
+ field :count, :type => Integer, :default => 1
12
+
13
+ index :hour, :background => true
14
+ index :url, :background => true
15
+ index :domain, :background => true
16
+
17
+ def self.aggregate_count_by_domain(*args)
18
+ options = args.extract_options!
19
+
20
+ map = <<-EOF
21
+ function() {
22
+ if (this.domain != null) {
23
+ emit(this.domain, this.count);
24
+ };
25
+ }
26
+ EOF
27
+
28
+ reduce = <<-EOF
29
+ function(time, counts) {
30
+ var count = 0;
31
+ for (index in counts) { count += counts[index]; };
32
+ return count;
33
+ }
34
+ EOF
35
+
36
+ results = self.collection.map_reduce(map, reduce, :out => {:inline => 1}, :raw => true)["results"]
37
+ results = results.sort {|x,y| y["value"] <=> x["value"]}
38
+ results = results[0..options[:limit]-1] if options[:limit]
39
+ results = results.map do |result|
40
+ [result["_id"], result["value"].to_i]
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,445 @@
1
+ @import "compass"
2
+ @import "compass/reset"
3
+ @import "compass/typography/text/force-wrap"
4
+ @import "blueprint/print"
5
+ @import "partials/variables"
6
+ @import "partials/mixins"
7
+ @import "partials/base"
8
+ @import "partials/form"
9
+ @import "partials/fileuploader"
10
+ @import "partials/flot"
11
+
12
+ @media print
13
+ +blueprint-print
14
+
15
+ body.concen
16
+ min-width: 960px
17
+ padding: $standard-gap
18
+ header, #content, footer
19
+ width: 100%
20
+
21
+ // Header
22
+
23
+ header
24
+ display: block
25
+ border-bottom: 1px solid $color-2
26
+ margin: 0 auto
27
+ position: relative
28
+ +clearfix
29
+ h1
30
+ height: 25px
31
+ line-height: 25px
32
+ padding-bottom: 15px
33
+ font-size: 24px
34
+ float: left
35
+ a
36
+ border-bottom: 0
37
+ +clearfix
38
+ text-decoration: none
39
+ span
40
+ float: left
41
+ span.engine-name
42
+ font-weight: bold
43
+ .wf-active &
44
+ font-weight: 700
45
+ span.application-name
46
+ margin-left: $standard-gap/2
47
+ .wf-active &
48
+ font-weight: 400
49
+ img
50
+ display: block
51
+ nav
52
+ position: absolute
53
+ right: 0
54
+ top: 0
55
+ ul
56
+ +horizontal-list(10px)
57
+ font-size: 13px
58
+ overflow: visible
59
+ li
60
+ line-height: 25px
61
+ a
62
+ +hover-link
63
+ form
64
+ position: absolute
65
+ top: 0
66
+ right: 0
67
+ input#keyword
68
+ font-size: 12px
69
+ line-height: 15px
70
+ +background-image-with-dimension('magnifying-glass.png')
71
+ background-position: 6px 5px
72
+ border: 1px solid lighten(#000, 70%)
73
+ outline: none
74
+ +border-radius(60px)
75
+ -webkit-appearance: none
76
+ min-width: 120px
77
+ width: 120px
78
+ height: 15px
79
+ padding: 4px 12px 4px 24px
80
+ color: $gray-60
81
+ input#keyword:focus
82
+ color: $gray-20
83
+
84
+ // Content Section
85
+
86
+ #content
87
+ margin: $standard-gap auto 0 auto
88
+ text-align: left
89
+ h1
90
+ margin-bottom: $standard-gap
91
+ .wf-active &
92
+ font-weight: 600
93
+ span
94
+ margin-right: $standard-gap/2
95
+ div.parent-header
96
+ height: 24px
97
+ width: 100%
98
+ position: relative
99
+ h2
100
+ line-height: 24px
101
+ display: inline
102
+ margin-bottom: 0
103
+ p.description
104
+ font-size: 12px
105
+ display: inline
106
+ margin-left: 6px
107
+ color: lighten(#000, 60%)
108
+ p.counter
109
+ font-style: italic
110
+ font-size: 18px
111
+ line-height: 24px
112
+ float: right
113
+
114
+ ul.pages
115
+ margin-left: 0
116
+ font-size: 14px
117
+ span.handle
118
+ background: url("/concen/images/icon-handle.png")
119
+ width: 12px
120
+ height: 12px
121
+ +inline-block
122
+ p, ul p
123
+ margin-bottom: 10px
124
+ vertical-align: middle
125
+ span, a
126
+ vertical-align: middle
127
+ ul
128
+ p
129
+ // background: $gray-90
130
+ a, ul a
131
+ margin-left: 4px
132
+ ul
133
+ margin-left: 20px
134
+
135
+ section#article
136
+ width: 774px
137
+
138
+ .boxshadow ul.search-result
139
+ padding-bottom: 0
140
+ li.child
141
+ margin-top: 0
142
+ margin-bottom: 30px
143
+ div.text
144
+ margin-top: 0
145
+
146
+ // Footer
147
+
148
+ footer
149
+ color: $color-1
150
+ margin: $standard-gap auto 0 auto
151
+ width: 760px
152
+ display: block
153
+ font-size: 12px
154
+ border-top: 1px solid $color-2
155
+ p
156
+ text-align: center
157
+ margin: 15px 0 0 0
158
+ font-size: 12px
159
+
160
+ // Buttons
161
+
162
+ a.prev
163
+ +background-image-with-dimension("button-prev.png")
164
+ text-indent: -9999px
165
+ display: block
166
+
167
+ a.prev.disabled
168
+ +background-image-with-dimension("button-prev-disabled.png")
169
+
170
+ a.next
171
+ +background-image-with-dimension("button-next.png")
172
+ text-indent: -9999px
173
+ display: block
174
+
175
+ a.next.disabled
176
+ +background-image-with-dimension("button-next-disabled.png")
177
+
178
+ a.grid
179
+ +background-image-with-dimension("button-grid.png")
180
+ text-indent: -9999px
181
+ display: block
182
+
183
+ #file-list
184
+ width: 260px
185
+ float: right
186
+ // background: lighten(#000, 94%)
187
+ padding: 0 0 0 20px
188
+ margin-bottom: 20px
189
+ +text-shadow(white, 0px, 1px, 0px)
190
+ position: relative
191
+ h3
192
+ line-height: 1
193
+ font-size: 13px
194
+ margin-bottom: 10px
195
+ position: relative
196
+ background: lighten(#000, 92%)
197
+ padding: 6px 10px
198
+ +text-shadow(white, 0px, 1px, 0px)
199
+ a.organize
200
+ font-size: 12px
201
+ font-weight: 600
202
+ line-height: 25px
203
+ display: block
204
+ position: absolute
205
+ top: 0
206
+ right: 10px
207
+ color: lighten(#000, 60%)
208
+ a.sort-path
209
+ display: none
210
+ ul
211
+ list-style-position: inside
212
+ margin-bottom: 20px
213
+ li
214
+ font-size: 12px
215
+ line-height: 1
216
+ height: 12px
217
+ list-style-type: square
218
+ padding: 8px 10px
219
+ border-bottom: 1px solid lighten(#000, 92%)
220
+ +clearfix
221
+ a
222
+ font-size: 12px
223
+ .right
224
+ float: right
225
+ height: inherit
226
+ +clearfix
227
+ div, a
228
+ width: 12px
229
+ height: 12px
230
+ margin-left: 10px
231
+ display: block
232
+ text-indent: -9999px
233
+ float: left
234
+ .check
235
+ +background-image-with-dimension("glyph-small-check.png")
236
+ .activate
237
+ +background-image-with-dimension("glyph-small-check-alt.png")
238
+ .activate:hover
239
+ +background-image-with-dimension("glyph-small-check.png")
240
+ .handle
241
+ +background-image-with-dimension("glyph-small-handle.png")
242
+ .delete
243
+ +background-image-with-dimension("glyph-small-delete.png")
244
+
245
+ .panels
246
+ margin-bottom: 30px
247
+ .panel
248
+ float: left
249
+ width: 31.25%
250
+ margin-right: 3.125%
251
+ // margin-bottom: 30px
252
+ font-size: 12px
253
+ .graph
254
+ padding: $standard-gap/2
255
+ h3
256
+ line-height: 1
257
+ border-bottom: 1px solid $color-2
258
+ padding: $standard-gap/3
259
+ background: $color-4
260
+ +border-top-radius(4px)
261
+ +text-shadow(white, 0px, 1px, 0px)
262
+ span
263
+ font-size: 12px
264
+ margin-left: 2px
265
+ color: lighten(#000, 60%)
266
+ font-weight: 500
267
+ span.link
268
+ a
269
+ font-size: 10px
270
+ line-height: 10px
271
+ float: right
272
+ display: block
273
+ border: 1px solid lighten(#000, 60%)
274
+ +border-radius(2px)
275
+ padding: 2px 6px
276
+ font-weight: 600
277
+ +box-shadow(white, 0px, 1px, 0px)
278
+ margin-left: 8px
279
+ text-align: center
280
+ color: lighten(#000, 40%)
281
+ background: lighten(#000, 88%)
282
+ +linear-gradient(color-stops(lighten(#000, 95%), lighten(#000, 85%)))
283
+ a.active, a:active
284
+ color: lighten(#000, 40%)
285
+ border-color: lighten(#000, 50%)
286
+ background: lighten(#000, 85%)
287
+ +linear-gradient(color-stops(lighten(#000, 85%), lighten(#000, 95%)))
288
+ a:hover
289
+ text-decoration: none
290
+ span.timezone
291
+ font-size: 10px
292
+ line-height: 10px
293
+ float: right
294
+ display: block
295
+ border: 1px solid lighten(#000, 70%)
296
+ +border-radius(2px)
297
+ padding: 2px 6px
298
+ font-weight: 600
299
+ +box-shadow(white, 0px, 1px, 0px)
300
+ margin-left: 8px
301
+ text-align: center
302
+ color: lighten(#000, 60%)
303
+ p.big-number
304
+ font-size: 72px
305
+ text-align: center
306
+ height: 168px
307
+ line-height: 168px
308
+ ul
309
+ width: 100%
310
+ min-height: $standard-gap/2
311
+ li
312
+ padding: $standard-gap/5 $standard-gap/3
313
+ border-bottom: 1px solid $color-5
314
+ position: relative
315
+ list-style: none
316
+ overflow: hidden
317
+ &:last-child, &.last
318
+ border-bottom: 0
319
+ a, p
320
+ font-size: 12px
321
+ +ellipsis
322
+ display: block
323
+ width: 100%
324
+ p.right
325
+ position: absolute
326
+ top: $standard-gap/5
327
+ right: $standard-gap/3
328
+ padding-left: 10px
329
+ background: white
330
+ width: auto
331
+
332
+ .panel.wide
333
+ width: auto
334
+ margin-right: 0
335
+ float: none
336
+ .edge
337
+ margin-right: 0px
338
+ ul.historical-visits
339
+ list-style-type: none
340
+ border: none
341
+ li
342
+ float: right
343
+ width: 40px
344
+ padding: 0
345
+ margin: 0
346
+ height: 142px
347
+ border: none
348
+ div.count
349
+ height: 120px
350
+ position: relative
351
+ div.total, div.unique
352
+ position: absolute
353
+ bottom: 0
354
+ left: 0
355
+ width: 100%
356
+ div.total
357
+ background: #43d166
358
+ z-index: 10
359
+ div.unique
360
+ background: #9aeeb0
361
+ z-index: 11
362
+ p
363
+ margin-top: 8px
364
+ height: 14px
365
+ font-size: 11px
366
+ line-height: 14px
367
+ text-align: center
368
+
369
+ // Qtip JS Plugin
370
+
371
+ .qtip-content
372
+ font-size: 13px
373
+ color: $gray-20
374
+ background: white
375
+
376
+ .qtip-tip, .qtip-wrapper
377
+
378
+ .qtip-wrapper
379
+ +box-shadow(rgba(0,0,0,0.75), 0, 1px, 3px)
380
+
381
+ // Ace Text Editor
382
+
383
+ #text-editor
384
+ min-height: 400px
385
+ position: relative
386
+
387
+ #file-manager
388
+ float: right
389
+ width: 25%
390
+ div.border
391
+ padding: 20px
392
+ margin-left: $standard-gap
393
+ h3
394
+ margin-top: 20px
395
+ span
396
+ vertical-align: middle
397
+ a
398
+ margin-right: 4px
399
+ vertical-align: middle
400
+ ul
401
+ list-style-type: none
402
+ li
403
+ font-size: 12px
404
+ margin-top: 10px
405
+ a
406
+ +force-wrap
407
+ color: $color-2
408
+ margin-right: 4px
409
+ &.filename
410
+ color: $color-1
411
+
412
+ form.with-text-editor
413
+ float: left
414
+ width: 75%
415
+ &.wide
416
+ width: 100%
417
+ .border
418
+ padding: 10px
419
+ +box-shadow(rgba($color-2, 0.3) 0 2px 2px inset)
420
+
421
+ .tickLabel
422
+ font-size: 12px
423
+
424
+ table
425
+ border-collapse: collapse
426
+ font-size: 14px
427
+ width: 100%
428
+ th
429
+ background: $color-4
430
+ +border-top-radius(4px)
431
+ font-weight: bold
432
+ font-size: 16px
433
+ .wf-active &
434
+ font-weight: 600
435
+ td, th
436
+ border-bottom: 1px solid $color-5
437
+ padding: $standard-gap/3
438
+ vertical-align: top
439
+ &.center
440
+ text-align: center
441
+ &.right
442
+ text-align: right
443
+ tr:last-child
444
+ td
445
+ border-bottom: 0