card 1.16.13 → 1.16.14

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/db/migrate_core_cards/20150501010515_responsive_sidebar.rb +11 -0
  4. data/db/schema.rb +1 -1
  5. data/lib/card/auth.rb +3 -2
  6. data/lib/card/env.rb +1 -1
  7. data/lib/card/loader.rb +79 -40
  8. data/lib/card/query.rb +5 -5
  9. data/lib/card/query/sql_statement.rb +10 -4
  10. data/lib/card/query/value.rb +5 -8
  11. data/lib/card/set.rb +0 -1
  12. data/lib/cardio.rb +18 -22
  13. data/mod/01_core/chunk/link.rb +37 -34
  14. data/mod/01_core/chunk/query_reference.rb +1 -1
  15. data/mod/01_core/set/all/fetch.rb +66 -58
  16. data/mod/01_core/set/all/permissions.rb +84 -83
  17. data/mod/01_core/set/all/templating.rb +6 -5
  18. data/mod/01_core/set/all/type.rb +16 -14
  19. data/mod/02_basic_types/set/all/base.rb +3 -3
  20. data/mod/02_basic_types/set/type/pointer.rb +4 -4
  21. data/mod/02_basic_types/spec/set/all/base_spec.rb +16 -1
  22. data/mod/03_machines/lib/javascript/wagn_mod.js.coffee +65 -0
  23. data/mod/05_email/set/all/follow.rb +6 -10
  24. data/mod/05_email/set/type/email_template.rb +1 -1
  25. data/mod/05_standard/lib/file_uploader.rb +39 -41
  26. data/mod/05_standard/set/all/account.rb +18 -20
  27. data/mod/05_standard/set/all/rich_html/toolbar.rb +1 -1
  28. data/mod/05_standard/set/right/account.rb +2 -2
  29. data/mod/05_standard/set/right/email.rb +14 -13
  30. data/mod/05_standard/set/right/password.rb +20 -12
  31. data/mod/05_standard/set/right/status.rb +2 -2
  32. data/mod/05_standard/set/self/head.rb +66 -53
  33. data/mod/05_standard/set/type/search_type.rb +3 -2
  34. data/mod/05_standard/set/type/set.rb +3 -3
  35. data/mod/06_bootstrap/lib/stylesheets/bootstrap_cards.scss +50 -0
  36. data/spec/lib/card/query_spec.rb +7 -0
  37. data/spec/spec_helper.rb +1 -1
  38. metadata +3 -2
@@ -9,11 +9,11 @@ def account
9
9
  end
10
10
 
11
11
  def accountable?
12
- Card.toggle( rule :accountable )
12
+ Card.toggle(rule :accountable)
13
13
  end
14
14
 
15
15
  def parties
16
- @parties ||= (all_roles << self.id).flatten.reject(&:blank?)
16
+ @parties ||= (all_roles << id).flatten.reject(&:blank?)
17
17
  end
18
18
 
19
19
  def among? ok_ids
@@ -23,18 +23,18 @@ def among? ok_ids
23
23
  ok_ids.member? Card::AnyoneID
24
24
  end
25
25
 
26
- def is_own_account?
26
+ def own_account?
27
27
  # card is +*account card of signed_in user.
28
- cardname.part_names[0].key == Auth.as_card.key and
29
- cardname.part_names[1].key == Card[:account].key
28
+ cardname.part_names[0].key == Auth.as_card.key &&
29
+ cardname.part_names[1].key == Card[:account].key
30
30
  end
31
31
 
32
32
  def read_rules
33
33
  @read_rules ||= begin
34
34
  rule_ids = []
35
- unless id==Card::WagnBotID # always_ok, so not needed
36
- ( [ Card::AnyoneID ] + parties ).each do |party_id|
37
- if rule_ids_for_party = self.class.read_rule_cache[ party_id ]
35
+ unless id == Card::WagnBotID # always_ok, so not needed
36
+ ([Card::AnyoneID] + parties).each do |party_id|
37
+ if rule_ids_for_party = self.class.read_rule_cache[party_id]
38
38
  rule_ids += rule_ids_for_party
39
39
  end
40
40
  end
@@ -44,24 +44,22 @@ def read_rules
44
44
  end
45
45
 
46
46
  def all_roles
47
- @all_roles ||=
48
- if id == Card::AnonymousID
49
- []
50
- else
51
- Auth.as_bot do
52
- role_trait = fetch trait: :roles
53
- [ Card::AnyoneSignedInID ] + ( role_trait ? role_trait.item_ids : [] )
54
- end
55
- end
47
+ @all_roles ||= (id == Card::AnonymousID ? [] : fetch_roles)
56
48
  end
57
49
 
50
+ def fetch_roles
51
+ Auth.as_bot do
52
+ role_trait = fetch trait: :roles
53
+ next [Card::AnyoneSignedInID] unless role_trait
54
+ [Card::AnyoneSignedInID] + (role_trait.item_ids)
55
+ end
56
+ end
58
57
 
59
58
  event :generate_token do
60
- Digest::SHA1.hexdigest "--#{Time.now.to_f}--#{rand 10}--"
59
+ Digest::SHA1.hexdigest "--#{Time.zone.now.to_f}--#{rand 10}--"
61
60
  end
62
61
 
63
62
  event :set_stamper, before: :approve do
64
63
  self.updater_id = Auth.current_id
65
- self.creator_id = self.updater_id if new_card?
64
+ self.creator_id = updater_id if new_card?
66
65
  end
67
-
@@ -213,9 +213,9 @@ format :html do
213
213
  path_opts = tag_args.delete(:path_opts) || {}
214
214
  path_opts.merge! action: tag_args.delete(:action) if tag_args[:action]
215
215
  link_to link_text, path_opts, tag_args
216
+
216
217
  end
217
218
  end
218
-
219
219
  def autosaved_draft_link
220
220
  view_link('autosaved draft', :edit, path_opts: {edit_draft: true, slot: {show: :toolbar}}, class: 'navbar-link slotter pull-right')
221
221
  end
@@ -71,7 +71,7 @@ event :require_email, on: :create, after: :approve do
71
71
  end
72
72
 
73
73
  event :set_default_salt, on: :create, before: :process_subcards do
74
- salt = Digest::SHA1.hexdigest "--#{Time.now.to_s}--"
74
+ salt = Digest::SHA1.hexdigest "--#{Time.zone.now}--"
75
75
  Env[:salt] = salt # HACK!!! need viable mechanism to get this to password
76
76
  add_subfield :salt, content: salt
77
77
  end
@@ -146,7 +146,7 @@ event :send_reset_password_token do
146
146
  end
147
147
 
148
148
  def ok_to_read
149
- is_own_account? ? true : super
149
+ own_account? ? true : super
150
150
  end
151
151
 
152
152
  def changes_visible? act
@@ -1,10 +1,11 @@
1
- #event :
2
1
  include All::Permissions::Accounts
3
2
 
4
- view :raw do |args|
3
+ view :raw do
5
4
  case
6
- when card.real? ; card.content
7
- when card.left.account ; card.left.account.email #this supports legacy behavior (should be moved to User+*email+*type plus right)
5
+ when card.real? then card.content
6
+ # following supports legacy behavior
7
+ # (should be moved to User+*email+*type plus right)
8
+ when card.left.account then card.left.account.email
8
9
  else ''
9
10
  end
10
11
  end
@@ -22,7 +23,7 @@ event :validate_unique_email, after: :validate_email, on: :save do
22
23
  Auth.as_bot do
23
24
  wql = { right_id: Card::EmailID, eq: content }
24
25
  wql[:not] = { id: id } if id
25
- if Card.search( wql ).first
26
+ if Card.search(wql).first
26
27
  errors.add :content, 'must be unique'
27
28
  end
28
29
  end
@@ -30,9 +31,8 @@ event :validate_unique_email, after: :validate_email, on: :save do
30
31
  end
31
32
 
32
33
  event :downcase_email, before: :approve, on: :save do
33
- if content and content != content.downcase
34
- self.content = content.downcase
35
- end
34
+ return if !content || content == content.downcase
35
+ self.content = content.downcase
36
36
  end
37
37
 
38
38
  def email_required?
@@ -40,13 +40,14 @@ def email_required?
40
40
  end
41
41
 
42
42
  def ok_to_read
43
- if is_own_account? or Auth.always_ok?
43
+ if own_email? || Auth.always_ok?
44
44
  true
45
45
  else
46
- deny_because "viewing email is restricted to administrators and account holders"
46
+ deny_because 'viewing email is restricted to administrators and ' \
47
+ 'account holders'
47
48
  end
48
49
  end
49
50
 
50
- def is_own_account?
51
- cardname.parts[0].to_name.key == Auth.as_card.cardname.key
52
- end
51
+ def own_email?
52
+ cardname.part_names[0].key == Auth.as_card.key
53
+ end
@@ -1,26 +1,34 @@
1
1
 
2
2
  include All::Permissions::Accounts
3
3
 
4
- view :editor do |args|
4
+ view :editor do
5
5
  card.content = ''
6
- autocomplete = (@parent && @parent.card.name=='*signin+*account') ? 'on' : 'off' #hack
6
+
7
+ # HACK
8
+ autocomplete = if @parent && @parent.card.name == '*signin+*account'
9
+ 'on'
10
+ else
11
+ 'off'
12
+ end
7
13
  password_field :content, class: 'card-content', autocomplete: autocomplete
8
14
  end
9
15
 
10
- view :raw do |args|
16
+ view :raw do
11
17
  '<em>encrypted</em>'
12
18
  end
13
19
 
14
- event :encrypt_password, on: :save, after: :process_subcards, changed: :content,
15
- when: proc{ |c| !Card::Env[:no_password_encryptions] } do
16
- # no_password_encryptions = hack for import - fix with api for ignoring events
17
-
18
- salt = (left && left.salt)
19
- salt = Card::Env[:salt] unless salt.present? # hack - fix with better ORM handling
20
+ event :encrypt_password, on: :save, after: :process_subcards,
21
+ changed: :content,
22
+ when: proc { !Card::Env[:no_password_encryptions] } do
23
+ # no_password_encryptions = hack for import - fix with api for ignoring events
24
+ salt = left && left.salt
25
+ # HACK: fix with better ORM handling
26
+ salt = Card::Env[:salt] unless salt.present?
20
27
  self.content = Auth.encrypt content, salt
21
28
 
22
- # errors.add :password, 'need a valid salt'
23
- # turns out we have a lot of existing account without a salt. not sure when that broke??
29
+ # errors.add :password, 'need a valid salt'
30
+ # turns out we have a lot of existing account without a salt.
31
+ # not sure when that broke??
24
32
  end
25
33
 
26
34
  event :validate_password, on: :save, before: :approve do
@@ -34,5 +42,5 @@ event :validate_password_present, on: :update, before: :approve do
34
42
  end
35
43
 
36
44
  def ok_to_read
37
- is_own_account? ? true : super
45
+ own_account? ? true : super
38
46
  end
@@ -1,9 +1,9 @@
1
1
  include All::Permissions::Accounts
2
2
 
3
3
  def ok_to_update
4
- if is_own_account? && !Auth.always_ok?
4
+ if own_account? && !Auth.always_ok?
5
5
  deny_because you_cant('change the status of your own account')
6
6
  else
7
7
  super
8
- end
8
+ end
9
9
  end
@@ -1,6 +1,5 @@
1
1
  format :html do
2
-
3
- view :raw do |args|
2
+ view :raw do
4
3
  %(
5
4
  <meta charset="UTF-8">
6
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
@@ -13,79 +12,93 @@ format :html do
13
12
 
14
13
  view :core do |args|
15
14
  case
16
- when focal? ; CGI.escapeHTML _render_raw(args)
17
- when @mainline ; "(*head)"
18
- else ; _render_raw(args)
15
+ when focal? then CGI.escapeHTML _render_raw(args)
16
+ when @mainline then "(*head)"
17
+ else _render_raw(args)
19
18
  end
20
19
  end
21
20
 
22
21
  def head_title
23
22
  title = root.card && root.card.name
24
23
  title = nil if title.blank?
25
- title = params[:action] if title=='*placeholder'
24
+ title = params[:action] if title == '*placeholder'
26
25
  %(<title>#{title ? "#{title} - " : ''}#{ Card.setting :title }</title>)
27
26
  end
28
27
 
29
28
  def head_buttons
30
- bits = []
31
- [:favicon, :logo].each do |name|
32
- if c = Card[name] and c.type_id == ImageID and !c.db_content.blank?
33
- bits << %{<link rel="shortcut icon" href="#{ subformat(c)._render_source size: :small }" />}
34
- break
35
- end
36
- end
37
-
38
- #Universal Edit Button
29
+ bits = [favicon]
39
30
  if root.card
40
- if !root.card.new_record? && root.card.ok?(:update)
41
- bits << %{<link rel="alternate" type="application/x-wiki" title="Edit this page!" href="#{ root.path view: :edit }"/>}
42
- end
43
-
31
+ bits << universal_edit_button
44
32
  # RSS # move to mods!
45
33
  if root.card.type_id == SearchTypeID
46
- opts = { format: :rss }
47
- root.search_params[:vars].each { |key, val| opts["_#{key}"] = val }
48
- bits << %{<link rel="alternate" type="application/rss+xml" title="RSS" href=#{page_path root.card.cardname, opts} />}
34
+ bits << rss_link
49
35
  end
50
36
  end
51
- bits.join "\n "
37
+ bits.compact.join "\n "
38
+ end
39
+
40
+ def favicon
41
+ [:favicon, :logo].each do |name|
42
+ if (c = Card[name]) && c.type_id == ImageID && !c.db_content.blank?
43
+ href = subformat(c)._render_source size: :small
44
+ return %{<link rel="shortcut icon" href="#{ href }" />}
45
+ end
46
+ end
47
+ end
48
+
49
+ def universal_edit_button
50
+ return if root.card.new_record? || !root.card.ok?(:update)
51
+ href = root.path view: :edit
52
+ %{<link rel="alternate" type="application/x-wiki" title="Edit this page!" href="#{ href }"/>}
53
+ end
54
+
55
+ def rss_link
56
+ opts = { format: :rss }
57
+ root.search_params[:vars].each { |key, val| opts["_#{key}"] = val }
58
+ href = page_path root.card.cardname, opts
59
+ %{<link rel="alternate" type="application/rss+xml" title="RSS" href="#{href}" />}
52
60
  end
53
61
 
54
62
  def head_stylesheets
55
63
  manual_style = params[:style]
56
- style_card = Card[manual_style] if manual_style
64
+ style_card = Card[manual_style] if manual_style
57
65
  style_card ||= root.card.rule_card :style
58
- @css_path = if params[:debug] == 'style'
59
- page_path( style_card.cardname, item: :import, format: :css)
60
- elsif style_card
61
- card_path style_card.machine_output_url
62
- end
63
-
64
- if @css_path
65
- %{<link href="#{@css_path}" media="all" rel="stylesheet" type="text/css" />}
66
- end
66
+ @css_path =
67
+ if params[:debug] == 'style'
68
+ page_path(style_card.cardname, item: :import, format: :css)
69
+ elsif style_card
70
+ card_path style_card.machine_output_url
71
+ end
72
+ return unless @css_path
73
+ %{<link href="#{@css_path}" media="all" rel="stylesheet" type="text/css" />}
67
74
  end
68
75
 
69
76
  def head_javascript
70
77
  varvals = [
71
78
  "window.wagn={rootPath:'#{ Card.config.relative_url_root }'}",
72
- "window.tinyMCEPreInit={base:\"#{card_path 'assets/tinymce'}\",query:'3.5.9',suffix:''}" # tinyMCE doesn't load on non-root wagns w/o preinit line
79
+ # tinyMCE doesn't load on non-root wagns w/o preinit line
80
+ "window.tinyMCEPreInit={base:\"#{card_path 'assets/tinymce'}\",query:'3.5.9',suffix:''}"
73
81
  ]
74
- card.have_recaptcha_keys? and varvals << "wagn.recaptchaKey='#{Card.config.recaptcha_public_key}'"
75
- c=Card[:double_click] and !Card.toggle c.content and varvals << 'wagn.noDoubleClick=true'
76
- @css_path and varvals << "wagn.cssPath='#{@css_path}'"
82
+ card.have_recaptcha_keys? &&
83
+ varvals << "wagn.recaptchaKey='#{Card.config.recaptcha_public_key}'"
84
+ (c = Card[:double_click]) && !Card.toggle(c.content) &&
85
+ varvals << 'wagn.noDoubleClick=true'
86
+ @css_path &&
87
+ varvals << "wagn.cssPath='#{@css_path}'"
77
88
 
78
89
  manual_script = params[:script]
79
90
  script_card = Card[manual_script] if manual_script
80
91
  script_card ||= root.card.rule_card :script
81
92
 
82
- @js_tag = if params[:debug] == 'script'
83
- script_card.format(:js).render_core item: :include_tag
84
- elsif script_card
85
- javascript_include_tag script_card.machine_output_url
86
- end
87
- ie9_card = Card[:script_html5shiv_printshiv]
88
- %(#{ javascript_tag do varvals * ';' end }
93
+ @js_tag =
94
+ if params[:debug] == 'script'
95
+ script_card.format(:js).render_core item: :include_tag
96
+ elsif script_card
97
+ javascript_include_tag script_card.machine_output_url
98
+ end
99
+ ie9_card = Card[:script_html5shiv_printshiv]
100
+ <<-HTML
101
+ #{ javascript_tag do varvals * ';' end }
89
102
  #{ @js_tag if @js_tag }
90
103
  <!--[if lt IE 9]>#{ javascript_include_tag ie9_card.machine_output_url if ie9_card }<![endif]-->
91
104
  #{ javascript_tag { "wagn.setTinyMCEConfig('#{ escape_javascript Card.setting(:tiny_mce).to_s }')" } }
@@ -94,26 +107,26 @@ format :html do
94
107
  $('document').ready(function() {
95
108
  $('.card-slot').trigger('slotReady');
96
109
  })
97
- </script>)
110
+ </script>
111
+ HTML
98
112
  end
99
113
 
100
-
101
114
  def google_analytics_head_javascript
102
- if ga_key = Card.setting("*google analytics key") #fixme. escape this?
103
- %{
115
+ if (ga_key = Card.setting("*google analytics key")) # FIXME: escape this?
116
+ <<-HTML
104
117
  <script type="text/javascript">
105
118
  var _gaq = _gaq || [];
106
119
  _gaq.push(['_setAccount', '#{ga_key}']);
107
120
  _gaq.push(['_trackPageview']);
108
121
  (function() {
109
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
122
+ var ga = document.createElement('script');
123
+ ga.type = 'text/javascript'; ga.async = true;
110
124
  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
111
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
125
+ var s = document.getElementsByTagName('script')[0];
126
+ s.parentNode.insertBefore(ga, s);
112
127
  })();
113
128
  </script>
114
- }
129
+ HTML
115
130
  end
116
131
  end
117
132
  end
118
-
119
-
@@ -4,11 +4,12 @@ def item_cards params={}
4
4
  raise('OH NO.. no limit') unless s[:limit]
5
5
  # forces explicit limiting
6
6
  # can be 0 or less to force no limit
7
- Card.search(s)
7
+ Query.run(s, name)
8
8
  end
9
9
 
10
10
  def item_names params={}
11
- Card.search(query(params.merge(return: :name)))
11
+ statement = query params.merge(return: :name)
12
+ Query.run(statement, name)
12
13
  end
13
14
 
14
15
  def item_type
@@ -227,13 +227,13 @@ def junction_only?()
227
227
  end
228
228
 
229
229
  def reset_set_patterns
230
- Card.members( key ).each do |mem|
230
+ Card.cached_set_members(key).each do |mem|
231
231
  Card.expire mem
232
232
  end
233
233
  end
234
234
 
235
235
  def label
236
- if klass = subclass_for_set
236
+ if (klass = subclass_for_set)
237
237
  klass.label cardname.left
238
238
  else
239
239
  ''
@@ -241,7 +241,7 @@ def label
241
241
  end
242
242
 
243
243
  def follow_label
244
- if klass = subclass_for_set
244
+ if (klass = subclass_for_set)
245
245
  klass.follow_label cardname.left
246
246
  else
247
247
  ''
@@ -82,6 +82,56 @@ body.mceContentBody {
82
82
  }
83
83
 
84
84
 
85
+ /*----------- Sidebar -------------*/
86
+
87
+ .row.row-offcanvas {
88
+ > aside, article {
89
+ margin: 0;
90
+ }
91
+ }
92
+
93
+ /* collapsed sidebar styles */
94
+ @media screen and (max-width: 767px) {
95
+ .row-offcanvas {
96
+ position: relative;
97
+ -webkit-transition: all 0.25s ease-out;
98
+ -moz-transition: all 0.25s ease-out;
99
+ transition: all 0.25s ease-out;
100
+ }
101
+
102
+ .sidebar-offcanvas-right {
103
+ right: -41.6%;
104
+ }
105
+
106
+ .sidebar-offcanvas-left {
107
+ left: -41.6%;
108
+ }
109
+ .row-offcanvas.right-active {
110
+ right: 41.6%;
111
+ }
112
+ .row-offcanvas.left-active {
113
+ left: 41.6%;
114
+ }
115
+ .sidebar-offcanvas {
116
+ position: absolute !important;
117
+ top: 0 !important;
118
+ width: 41.6% !important;
119
+ }
120
+ }
121
+
122
+ .offcanvas-toggle {
123
+ font-size: 10px !important;
124
+ padding: 5px !important;
125
+ margin-bottom: 15px !important;
126
+ }
127
+ .offcanvas-toggle-right {
128
+ float: right;
129
+ }
130
+ .offcanvas-toggle-left {
131
+ float: left;
132
+ }
133
+
134
+
85
135
  /*---------- Card menu ------------*/
86
136
 
87
137
  @media (min-width: $screen-xs-max) {