card 1.20.0 → 1.20.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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/card.gemspec +1 -1
  4. data/lib/card.rb +7 -3
  5. data/lib/card/act_manager/stage_director.rb +22 -10
  6. data/lib/card/cache/persistent.rb +15 -9
  7. data/lib/card/format/nest.rb +12 -5
  8. data/lib/card/format/nest/fetch.rb +2 -1
  9. data/lib/card/format/render.rb +5 -2
  10. data/lib/card/set/event.rb +7 -1
  11. data/lib/card/subcards.rb +3 -3
  12. data/lib/card/view/cache.rb +1 -1
  13. data/lib/card/view/fetch.rb +17 -5
  14. data/lib/card/view/options.rb +52 -26
  15. data/lib/cardio.rb +2 -1
  16. data/mod/account/spec/set/right/account_spec.rb +17 -3
  17. data/mod/admin/set/self/admin.rb +0 -2
  18. data/mod/admin/spec/set/self/admin_spec.rb +14 -11
  19. data/mod/bootstrap/set/all/bootstrap/helper.rb +27 -29
  20. data/mod/carrierwave/set/type/file.rb +1 -1
  21. data/mod/carrierwave/set/type/image.rb +18 -6
  22. data/mod/core/set/all/collection.rb +33 -7
  23. data/mod/core/set/all/fetch.rb +16 -3
  24. data/mod/core/set/all/permissions.rb +6 -12
  25. data/mod/core/set/all/trash.rb +3 -1
  26. data/mod/core/spec/set/all/collection_spec.rb +9 -8
  27. data/mod/email/set/all/notify.rb +27 -17
  28. data/mod/email/set/right/follow.rb +49 -36
  29. data/mod/email/set/type/email_template.rb +25 -69
  30. data/mod/email/set/type/email_template/email_config.rb +63 -0
  31. data/mod/email/set/type_plus_right/user/follow.rb +3 -3
  32. data/mod/machines/lib/stylesheets/style_cards.scss +292 -0
  33. data/mod/pointer/set/abstract/01_pointer.rb +8 -8
  34. data/mod/pointer/set/abstract/01_pointer/edit.rb +6 -2
  35. data/mod/prosemirror_editor/lib/javascript/script_prosemirror.js +12283 -11605
  36. data/mod/prosemirror_editor/lib/javascript/script_prosemirror_config.js.coffee +1 -1
  37. data/mod/standard/set/abstract/01_search_params.rb +1 -1
  38. data/mod/standard/set/abstract/search/paging.rb +4 -4
  39. data/mod/standard/set/all/comment.rb +67 -47
  40. data/mod/standard/set/all/links.rb +2 -2
  41. data/mod/standard/set/all/rich_html/content.rb +1 -1
  42. data/mod/standard/set/all/rich_html/editing.rb +3 -2
  43. data/mod/standard/set/all/rich_html/form.rb +21 -12
  44. data/mod/standard/set/all/rich_html/header.rb +9 -0
  45. data/mod/standard/set/all/rich_html/menu.rb +16 -12
  46. data/mod/standard/set/all/rich_html/toolbar.rb +140 -130
  47. data/mod/standard/set/all/rich_html/wrapper.rb +11 -1
  48. data/mod/standard/set/rstar/rules_editor.rb +2 -34
  49. data/mod/standard/set/self/search.rb +1 -1
  50. data/mod/standard/set/type/set.rb +4 -4
  51. data/mod/standard/spec/set/type/email_template/email_config_spec.rb +218 -0
  52. data/mod/standard/spec/set/type/email_template_spec.rb +3 -185
  53. data/spec/lib/card/cache_spec.rb +0 -1
  54. data/spec/lib/card/format/render_spec.rb +19 -0
  55. data/spec/lib/card/stage_director_spec.rb +1 -1
  56. data/tmpsets/set/mod001-core/all/actify.rb +5 -6
  57. data/tmpsets/set/mod001-core/all/fetch.rb +14 -12
  58. data/tmpsets/set/mod001-core/all/name.rb +1 -1
  59. data/tmpsets/set/mod001-core/all/permissions.rb +12 -22
  60. data/tmpsets/set/mod001-core/all/tracked_attributes.rb +76 -0
  61. data/tmpsets/set/mod001-core/all/utils.rb +40 -3
  62. data/tmpsets/set/mod002-history/all/history.rb +1 -2
  63. data/tmpsets/set/mod008-solid_cache/abstract/solid_cache.rb +1 -1
  64. data/tmpsets/set/mod013-carrierwave/abstract/attachment.rb +282 -0
  65. data/tmpsets/set/mod013-carrierwave/type/file.rb +155 -0
  66. data/tmpsets/set/mod013-carrierwave/type/image.rb +96 -0
  67. data/tmpsets/set/mod014-admin/self/admin.rb +113 -0
  68. data/tmpsets/set/mod014-admin/self/admin_info.rb +110 -0
  69. data/tmpsets/set/mod014-admin/self/version.rb +15 -0
  70. data/tmpsets/set/mod015-developer/all/event_viz.rb +59 -0
  71. data/tmpsets/set/mod015-developer/all/view_viz.rb +30 -0
  72. data/tmpsets/set/mod015-developer/right/debug.rb +96 -0
  73. metadata +15 -2
@@ -0,0 +1,155 @@
1
+ # -*- encoding : utf-8 -*-
2
+ class Card; module Set; class Type; module File; extend Card::Set
3
+ # ~~ above autogenerated; below pulled from /Users/ethan/dev/wagn/gem/card/mod/carrierwave/set/type/file.rb ~~
4
+ attachment :file, uploader: CarrierWave::FileCardUploader
5
+
6
+ module SelectedAction
7
+ def select_action_by_params params
8
+ # skip action table lookups for current revision
9
+ rev_id = params[:rev_id]
10
+ super unless rev_id && rev_id == last_content_action_id
11
+ end
12
+
13
+ def last_content_action_id
14
+ # find action id from content (saves lookups)
15
+ db_content.to_s.split(%r{[/\.]})[1]
16
+ end
17
+ end
18
+ include SelectedAction
19
+
20
+ format do
21
+ view :source do |_args|
22
+ card.attachment.url
23
+ end
24
+
25
+ view :core do |args|
26
+ handle_source args do |source|
27
+ card_url source
28
+ end
29
+ end
30
+
31
+ def handle_source args
32
+ source = _render_source args
33
+ source ? yield(source) : ""
34
+ rescue
35
+ "File Error"
36
+ end
37
+ end
38
+
39
+ format :file do
40
+ # returns send_file args. not in love with this...
41
+ view :core do |_args|
42
+ # this means we only support known formats. dislike.
43
+ if (_format = card.attachment_format(params[:format]))
44
+ if params[:explicit_file] && (r = controller.response)
45
+ r.headers["Expires"] = 1.year.from_now.httpdate
46
+ # currently using default "private", because proxy servers could block
47
+ # needed permission checks
48
+ # r.headers["Cache-Control"] = "public"
49
+ end
50
+
51
+ # formerly supported redirecting to correct file format
52
+ # elsif ![format, 'file'].member? params[:format]
53
+ # path = request.fullpath.sub( /\.#{params[:format]}\b/, '.' + format )
54
+ # return redirect_to(path) #card.attachment.url(style) )
55
+
56
+ file = selected_file_version
57
+ [file.path,
58
+ {
59
+ type: file.content_type,
60
+ filename: "#{card.cardname.safe_key}#{file.extension}",
61
+ x_sendfile: true,
62
+ disposition: (params[:format] == "file" ? "attachment" : "inline")
63
+ }]
64
+ else
65
+ _render_not_found
66
+ end
67
+ end
68
+
69
+ def selected_file_version
70
+ card.attachment
71
+ end
72
+ end
73
+
74
+ format :html do
75
+ view :core do |args|
76
+ handle_source args do |source|
77
+ "<a href=\"#{source}\">Download #{showname args[:title]}</a>"
78
+ end
79
+ end
80
+
81
+ view :editor do |args|
82
+ file_chooser args
83
+ end
84
+
85
+ def preview _args
86
+ ""
87
+ end
88
+
89
+ view :preview_editor, tags: :unknown_ok do |args|
90
+ cached_upload_card_name = Card::Env.params[:attachment_upload]
91
+ cached_upload_card_name.gsub!(/\[\w+\]$/, "[action_id_of_cached_upload]")
92
+ <<-HTML
93
+ <div class="chosen-file">
94
+ <input type="hidden" name="#{cached_upload_card_name}"
95
+ value="#{card.selected_action_id}">
96
+ <table role="presentation" class="table table-striped">
97
+ <tbody class="files">
98
+ <tr class="template-download fade in">
99
+ <td>
100
+ <span class="preview">
101
+ #{preview(args)}
102
+ </span>
103
+ </td>
104
+ <td>
105
+ <p class="name">
106
+ #{card.original_filename}
107
+ </p>
108
+ </td>
109
+ <td>
110
+ <span class="size">
111
+ #{number_to_human_size(card.attachment.size)}
112
+ </span>
113
+ </td>
114
+ <td class="pull-right">
115
+ <button class="btn btn-danger delete cancel-upload"
116
+ data-type="DELETE">
117
+ <i class="glyphicon glyphicon-trash"></i>
118
+ <span>Delete</span>
119
+ </button>
120
+ </td>
121
+ </tr>
122
+ </tbody>
123
+ </table>
124
+ </div>
125
+ HTML
126
+ end
127
+
128
+ def file_chooser args
129
+ <<-HTML
130
+ <div class="choose-file">
131
+ #{preview(args)}
132
+ <span class="btn btn-success fileinput-button">
133
+ <i class="glyphicon glyphicon-cloud-upload"></i>
134
+ <span>
135
+ #{card.new_card? ? 'Add' : 'Replace'} #{card.attachment_name}...
136
+ </span>
137
+ <input class="file-upload slotter form-control" type="file"
138
+ name="card[#{card.type_code}]" id="card_#{card.type_code}">
139
+ #{hidden_field_tag 'attachment_type_id', card.type_id}
140
+ #{hidden_field card.attachment_name, class: 'attachment_card_name',
141
+ value: ''}
142
+ #{hidden_field_tag 'file_card_name', card.cardname.url_key}
143
+ </span>
144
+ </div>
145
+ <div id="progress" class="progress" style="display: none;">
146
+ <div class="progress-bar progress-bar-success" style="width: 0%;"></div>
147
+ </div>
148
+ <div class="chosen-file"></div>
149
+ HTML
150
+ end
151
+ end
152
+
153
+
154
+ # ~~ below autogenerated; above pulled from /Users/ethan/dev/wagn/gem/card/mod/carrierwave/set/type/file.rb ~~
155
+ end;end;end;end;
@@ -0,0 +1,96 @@
1
+ # -*- encoding : utf-8 -*-
2
+ class Card; module Set; class Type; module Image; extend Card::Set
3
+ # ~~ above autogenerated; below pulled from /Users/ethan/dev/wagn/gem/card/mod/carrierwave/set/type/image.rb ~~
4
+ attachment :image, uploader: CarrierWave::ImageCardUploader
5
+
6
+ include File::SelectedAction
7
+
8
+ format do
9
+ include File::Format
10
+
11
+ view :closed_content do |_args|
12
+ _render_core size: :icon
13
+ end
14
+
15
+ view :source do |args|
16
+ style =
17
+ case
18
+ when @mode == :closed then :icon
19
+ when args[:size] then args[:size].to_sym
20
+ when main? then :large
21
+ else :medium
22
+ end
23
+ style = :original if style.to_sym == :full
24
+ if style == :original
25
+ card.image.url
26
+ else
27
+ card.image.versions[style].url
28
+ end
29
+ end
30
+ end
31
+
32
+ format :html do
33
+ include File::HtmlFormat
34
+
35
+ view :core do |args|
36
+ handle_source args do |source|
37
+ if source == "missing"
38
+ "<!-- image missing #{@card.name} -->"
39
+ else
40
+ image_tag(source)
41
+ end
42
+ end
43
+ end
44
+
45
+ def preview args
46
+ if !card.new_card? || card.preliminary_upload?
47
+ content_tag :div, _render_core(args.merge(size: :medium)).html_safe,
48
+ class: "attachment-preview",
49
+ id: "#{card.attachment.filename}-preview"
50
+ end
51
+ end
52
+
53
+ view :content_changes do |args|
54
+ out = ""
55
+ size = args[:diff_type] == :summary ? :icon : :medium
56
+ if !args[:hide_diff] && args[:action] &&
57
+ (last_change = card.last_change_on(:db_content, before: args[:action]))
58
+ card.selected_action_id = last_change.card_action_id
59
+ out << Card::Content::Diff.render_deleted_chunk(_render_core(size: size))
60
+ end
61
+ card.selected_action_id = args[:action].id
62
+ out << Card::Content::Diff.render_added_chunk(_render_core(size: size))
63
+ out
64
+ end
65
+ end
66
+
67
+ format :css do
68
+ view :core do |_args|
69
+ render_source
70
+ end
71
+
72
+ view :content do |_args| # why is this necessary?
73
+ render_core
74
+ end
75
+ end
76
+
77
+ format :file do
78
+ include File::FileFormat
79
+
80
+ view :style do |args| # should this be in model?
81
+ ["", "full"].member?(args[:style].to_s) ? :original : args[:style]
82
+ end
83
+
84
+ def selected_file_version
85
+ style = _render_style(style: params[:size]).to_sym
86
+ if style && style != :original
87
+ card.attachment.versions[style]
88
+ else
89
+ card.attachment
90
+ end
91
+ end
92
+ end
93
+
94
+
95
+ # ~~ below autogenerated; above pulled from /Users/ethan/dev/wagn/gem/card/mod/carrierwave/set/type/image.rb ~~
96
+ end;end;end;end;
@@ -0,0 +1,113 @@
1
+ # -*- encoding : utf-8 -*-
2
+ class Card; module Set; class Self; module Admin; extend Card::Set
3
+ # ~~ above autogenerated; below pulled from /Users/ethan/dev/wagn/gem/card/mod/admin/set/self/admin.rb ~~
4
+ event :admin_tasks, :initialize, on: :update do
5
+ return unless (task = Env.params[:task])
6
+ raise Card::Error::PermissionDenied.new(self) unless Auth.always_ok?
7
+
8
+ case task.to_sym
9
+ when :clear_cache then Card::Cache.reset_all
10
+ when :repair_references then Card::Reference.repair_all
11
+ when :empty_trash then Card.empty_trash
12
+ when :clear_view_cache then Card::Cache::ViewCache.reset
13
+ when :delete_old_revisions then Card::Action.delete_old
14
+ when :repair_permissions then Card.repair_all_permissions
15
+ when :clear_solid_cache then Card.clear_solid_cache
16
+ when :clear_machine_cache then Card.reset_all_machines
17
+ end
18
+ abort :success
19
+ end
20
+
21
+ format :html do
22
+ view :core do |_args|
23
+ stats = card_stats
24
+ stats += cache_stats
25
+ stats += memory_stats
26
+ table_content = stats.map { |args| stat_row(*args) }
27
+ table table_content, header: %w(Stat Value Action)
28
+ end
29
+
30
+ def card_stats
31
+ [
32
+ ["cards", { count: Card.where(trash: false) }],
33
+ ["trashed cards", { count: Card.where(trash: true),
34
+ link_text: "delete all", task: "empty_trash" }],
35
+ ["actions", { count: Card::Action,
36
+ link_text: "delete old",
37
+ task: "delete_old_revisions" }],
38
+ ["references", { count: Card::Reference,
39
+ link_text: "repair all", task: "repair_references" }]
40
+ ]
41
+ end
42
+
43
+ def cache_stats
44
+ stats = [
45
+ ["solid cache", { count: solid_cache_count, unit: " cards",
46
+ link_text: "clear cache",
47
+ task: "clear_solid_cache" }],
48
+ ["machine cache", { count: machine_cache_count, unit: " cards",
49
+ link_text: "clear cache",
50
+ task: "clear_machine_cache" }]
51
+ ]
52
+ return stats unless Card.config.view_cache
53
+ stats <<
54
+ ["view cache", { count: Card::Cache::ViewCache,
55
+ link_text: "clear view cache",
56
+ task: "clear_view_cache" }]
57
+ stats
58
+ end
59
+
60
+ def memory_stats
61
+ oldmem = session[:memory]
62
+ session[:memory] = newmem = card.profile_memory
63
+ stats = [
64
+ ["memory now", { count: newmem, unit: "M",
65
+ link_text: "clear cache", task: "clear_cache" }]
66
+ ]
67
+ return stats unless oldmem
68
+ stats << ["memory prev", { count: oldmem, unit: "M" }]
69
+ stats << ["memory diff", { count: newmem - oldmem, unit: "M" }]
70
+ stats
71
+ end
72
+
73
+ def stat_row name, args={}
74
+ res = [name]
75
+ args[:count] = args[:count].count if args[:count].respond_to?(:count)
76
+ res << "#{args[:count]}#{args[:unit]}"
77
+ return res unless args[:task]
78
+ path = card_path("update/:admin?task=#{args[:task]}")
79
+ res << link_to(args[:link_text] || args[:task], path)
80
+ res
81
+ end
82
+
83
+ def solid_cache_count
84
+ Card.search right: { codename: "solid_cache" }, return: "count"
85
+ end
86
+
87
+ def machine_cache_count
88
+ Card.search right: { codename: "machine_cache" }, return: "count"
89
+ end
90
+
91
+ def delete_sessions_link months
92
+ link_to months,
93
+ card_path("update/:admin?task=delete_old_sessions&months=#{months}")
94
+ end
95
+ end
96
+
97
+ def current_memory_usage
98
+ `ps -o rss= -p #{Process.pid}`.to_i
99
+ end
100
+
101
+ def profile_memory &block
102
+ before = current_memory_usage
103
+ if block_given?
104
+ instance_eval(&block)
105
+ else
106
+ before = 0
107
+ end
108
+ (current_memory_usage - before) / 1024.to_i
109
+ end
110
+
111
+
112
+ # ~~ below autogenerated; above pulled from /Users/ethan/dev/wagn/gem/card/mod/admin/set/self/admin.rb ~~
113
+ end;end;end;end;
@@ -0,0 +1,110 @@
1
+ # -*- encoding : utf-8 -*-
2
+ class Card; module Set; class Self; module AdminInfo; extend Card::Set
3
+ # ~~ above autogenerated; below pulled from /Users/ethan/dev/wagn/gem/card/mod/admin/set/self/admin_info.rb ~~
4
+ def clean_html?
5
+ false
6
+ end
7
+
8
+ format :html do
9
+ view :core do
10
+ warnings = []
11
+ if Card.config.action_mailer.perform_deliveries == false
12
+ warnings << email_warning
13
+ end
14
+ if Card.config.recaptcha_public_key ==
15
+ Card::Auth::Permissions::RECAPTCHA_DEFAULTS[:recaptcha_public_key] &&
16
+ card.rule(:captcha) == "1"
17
+ warnings << recaptcha_warning
18
+ end
19
+ return "" if warnings.empty?
20
+ alert :warning, dismissible: true do
21
+ render_warning_list warnings
22
+ end
23
+ end
24
+
25
+ def render_warning_list warnings
26
+ # 'ADMINISTRATOR WARNING'
27
+ admin_warn = I18n.t(:admin_warn,
28
+ scope: "mod.standard.set.self.admin_info")
29
+ "<h6>#{admin_warn}</h6>".html_safe + list_group(
30
+ warnings,
31
+ items: { class: "list-group-item-warning" }
32
+ )
33
+ end
34
+
35
+ def email_warning
36
+ # "Email delivery is turned off."
37
+ # "Change settings in config/application.rb to send sign up notifications."
38
+ I18n.t(:email_off,
39
+ scope: "mod.standard.set.self.admin_info",
40
+ path: "config/application.rb")
41
+ end
42
+
43
+ def recaptcha_warning
44
+ warning =
45
+ if Card::Env.localhost?
46
+ # %(Your captcha is currently working with temporary settings.
47
+ # This is fine for a local installation, but you will need new
48
+ # recaptcha keys if you want to make this site public.)
49
+ I18n.t(:captcha_temp, scope: "mod.standard.set.self.admin_info")
50
+ else
51
+ # %(You are configured to use [[*captcha]], but for that to work
52
+ # you need new recaptcha keys.)
53
+ process_content(I18n.t(:captcha_keys,
54
+ scope: "mod.standard.set.self.admin_info"))
55
+ end
56
+ # 'Instructions'
57
+ instructions = I18n.t(:instructions,
58
+ scope: "mod.standard.set.self.admin_info")
59
+ <<-HTML
60
+ <p>
61
+ #{warning}
62
+ </p>
63
+ <h4>#{instructions}</h4>
64
+ #{howto_add_new_recaptcha_keys}
65
+ #{howto_turn_captcha_off}
66
+ HTML
67
+ end
68
+
69
+ def instructions title, steps
70
+ steps = list_group steps
71
+ "#{title}#{steps}"
72
+ end
73
+
74
+ def howto_add_new_recaptcha_keys
75
+ instructions(
76
+ # 'How to add new recaptcha keys:'
77
+ I18n.t(:howto_add_keys, scope: "mod.standard.set.self.admin_info"),
78
+ [
79
+ # "1. Register your domain at #{web_link 'http://google.com/recaptcha'}"
80
+ I18n.t(:howto_register,
81
+ scope: "mod.standard.set.self.admin_info",
82
+ recaptcha_link: web_link("http://google.com/recaptcha")),
83
+ # "2. Add your keys to #{card_link :recaptcha_settings}"
84
+ I18n.t(:howto_add,
85
+ scope: "mod.standard.set.self.admin_info",
86
+ recaptcha_settings: card_link(:recaptcha_settings))
87
+ ]
88
+ )
89
+ end
90
+
91
+ def howto_turn_captcha_off
92
+ instructions(
93
+ # 'How to turn captcha off:'
94
+ I18n.t(:howto_turn_off, scope: "mod.standard.set.self.admin_info"),
95
+ [
96
+ # "1. Go to #{card_link :captcha}"
97
+ I18n.t(:howto_go,
98
+ scope: "mod.standard.set.self.admin_info",
99
+ captcha_card: card_link(:captcha)),
100
+ # '2. Update all *captcha rules to "no".'
101
+ I18n.t(:howto_update,
102
+ scope: "mod.standard.set.self.admin_info")
103
+ ]
104
+ )
105
+ end
106
+ end
107
+
108
+
109
+ # ~~ below autogenerated; above pulled from /Users/ethan/dev/wagn/gem/card/mod/admin/set/self/admin_info.rb ~~
110
+ end;end;end;end;