card 1.16.13 → 1.16.14

Sign up to get free protection for your applications and to get access to all the features.
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) {