card-mod-follow 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ def follow follow_name, option="*always"
2
+ return unless (follow_rule = Card.fetch(follow_name)&.follow_rule_card(name, new: {}))
3
+
4
+ follow_rule.drop_item "*never"
5
+ follow_rule.add_item option
6
+ follow_rule.save!
7
+ end
@@ -0,0 +1,77 @@
1
+ FOLLOW_TABS = { "Follow" => "follow_tab", "Ignore" => "ignore_tab" }.freeze
2
+
3
+ # a virtual pointer to the sets that a user is following.
4
+ # (data is stored in preferences: `[Set]+[User]+:follow`)
5
+
6
+ include_set Abstract::Pointer
7
+ def virtual?
8
+ new?
9
+ end
10
+
11
+ # overrides pointer default
12
+ def item_names _args={}
13
+ if (user = left)
14
+ Card::Rule.preference_names user.name, "follow"
15
+ else
16
+ []
17
+ end
18
+ end
19
+
20
+ def suggestions
21
+ Card[:follow_suggestions]&.item_names || []
22
+ end
23
+
24
+ def current_user?
25
+ Auth.signed_in? && Auth.current_id == left.id
26
+ end
27
+
28
+ format :html do
29
+ view :one_line_content do
30
+ ""
31
+ end
32
+
33
+ view :edit do
34
+ render :open
35
+ end
36
+
37
+ # renders follow tab and ignore tab
38
+ view :core do
39
+ tabs FOLLOW_TABS, "follow_tab", load: :lazy do
40
+ render_follow_tab
41
+ end
42
+ end
43
+
44
+ view :follow_tab, cache: :never do
45
+ haml :follow_editor, items_method: :following_rules_and_options
46
+ end
47
+
48
+ view :ignore_tab, cache: :never do
49
+ haml :follow_editor, items_method: :ignoring_rules_and_options
50
+ end
51
+
52
+ def show_button?
53
+ card.current_user? || Auth.always_ok?
54
+ end
55
+
56
+ def pointer_items args
57
+ voo.items[:view] ||= :link
58
+ super(args)
59
+ end
60
+
61
+ # TODO: research and generalize
62
+ # this does not look specific to following!
63
+ view :errors, perms: :none do
64
+ return unless card.errors.any?
65
+
66
+ if card.errors.find { |attrib, _msg| attrib == :permission_denied }
67
+ Env.save_interrupted_action(request.env["REQUEST_URI"])
68
+ voo.title = "Problems with #{card.name}"
69
+ class_up "d0-card-frame", "card card-warning card-inverse"
70
+ frame do
71
+ "Please #{link_to_card :signin, 'sign in'}" # " #{to_task}"
72
+ end
73
+ else
74
+ super()
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,8 @@
1
+ .pointer-list-editor
2
+ %ul.delete-list.list-group
3
+ - send items_method do |rule_card, option|
4
+ %li.list-group-item
5
+ -if rule_card
6
+ = subformat(rule_card).follow_item option, show_button?
7
+ -else
8
+ no entries
@@ -0,0 +1,121 @@
1
+ # all the following methods are used to construct the Follow and Ignore tabs
2
+
3
+ # TODO: these object representations are complex enough for their own class
4
+
5
+ format :html do
6
+ # constructs hash of rules/options for "Follow" tab
7
+ def following_rules_and_options &block
8
+ rule_opt_array = following_rule_options_hash.map do |key, val|
9
+ [(Card.fetch key, new: {}), val]
10
+ end
11
+ rules_and_options_by_set_pattern Hash[rule_opt_array], &block
12
+ end
13
+
14
+ # constructs hash of rules/options for "Ignore" tab
15
+ def ignoring_rules_and_options &block
16
+ rule_opts_hash = ignore_rules.each_with_object({}) do |rule, hash|
17
+ hash[rule] = [:never.cardname]
18
+ end
19
+ rules_and_options_by_set_pattern rule_opts_hash, &block
20
+ end
21
+
22
+ private
23
+
24
+ # all rules with ignore
25
+ def ignore_rules
26
+ never = :never.cardname.key
27
+ card.item_cards.select do |follow_rule|
28
+ follow_rule.item_names.select { |n| n.key == never }.any?
29
+ end
30
+ end
31
+
32
+ # @param rule_opts_hash [Hash] { rule1_card => rule1_follow_options }
33
+ # for each rule/option variant, yields with rule_card and option params
34
+ def rules_and_options_by_set_pattern rule_opts_hash
35
+ pattern_hash = a_set_pattern_hash rule_opts_hash
36
+ empty = true
37
+ Card.set_patterns.reverse.map do |pattern|
38
+ pattern_hash[pattern].each do |rule_card, options|
39
+ options.each do |option|
40
+ yield rule_card, option
41
+ empty = false
42
+ end
43
+ end
44
+ end
45
+ yield nil if empty
46
+ end
47
+
48
+ def a_set_pattern_hash rule_opts_hash
49
+ pattern_hash = Hash.new { |h, k| h[k] = [] }
50
+ rule_opts_hash.each do |rule_card, options|
51
+ pattern_hash[rule_card.rule_set.subclass_for_set] << [rule_card, options]
52
+ end
53
+ pattern_hash
54
+ end
55
+
56
+ # @return Hash # { rule1 => rule1_follow_options }
57
+ def following_rule_options_hash
58
+ merge_option_hashes current_following_rule_options_hash,
59
+ suggested_following_rule_options_hash
60
+ end
61
+
62
+ # adds suggested follow options to existing rules where applicable
63
+ def merge_option_hashes current, suggested
64
+ current.each do |key, current_opt|
65
+ if (suggested_opt = suggested.delete(key))
66
+ current[key] = (current_opt + suggested_opt).uniq
67
+ end
68
+ end
69
+ current.merge suggested
70
+ end
71
+
72
+ # @return Hash # { existing_rule1 => rule1_follow_options } (excluding never)
73
+ # (*never is excluded because this list is for the Follow tab, and *never is
74
+ # handled under the Ignore tab)
75
+ def current_following_rule_options_hash
76
+ never = :never.cardname
77
+ card.item_cards.each_with_object({}) do |follow_rule, hash|
78
+ hash[follow_rule.key] = follow_rule.item_names.reject { |item| item == never }
79
+ end
80
+ end
81
+
82
+ # @return Hash # { suggested_rule1 => rule1_follow_options }
83
+ def suggested_following_rule_options_hash
84
+ return {} unless card.current_user?
85
+
86
+ card.suggestions.each_with_object({}) do |sug, hash|
87
+ set_card, opt = a_set_and_option_suggestion(sug) || a_set_only_suggestion(sug)
88
+ hash[set_card.follow_rule_name(card.trunk).key] = [opt]
89
+ end
90
+ end
91
+
92
+ # @param sug [String] follow suggestion
93
+ # @return [Array] set_card and option
94
+ # suggestion value contains both set and follow option
95
+ def a_set_and_option_suggestion sug
96
+ return unless (set_card = valid_set_card(sug.to_name.left))
97
+
98
+ [set_card, suggested_follow_option(sug.to_name.right)]
99
+ end
100
+
101
+ def suggested_follow_option name
102
+ # FIXME: option should be unambiguously name or codename
103
+ # (if codename use colon or Symbol)
104
+ option_card = Card.fetch(name) || Card[name.to_sym]
105
+ option_card&.follow_option? ? option_card.name : :always.cardname
106
+ end
107
+
108
+ # @param sug [String] follow suggestion
109
+ # @return [Array] set_card and option
110
+ # suggestion value contains only set (implies *always)
111
+ def a_set_only_suggestion sug
112
+ return unless (set_card = valid_set_card(sug))
113
+
114
+ yield set_card, :always.cardname
115
+ end
116
+
117
+ def valid_set_card name
118
+ card = Card.fetch(name)
119
+ card&.type_code == :set ? card : false
120
+ end
121
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: card-mod-follow
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.11.0
5
+ platform: ruby
6
+ authors:
7
+ - Ethan McCutchen
8
+ - Philipp Kühl
9
+ - Gerry Gleason
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2020-12-24 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: card
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - '='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.101.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - '='
27
+ - !ruby/object:Gem::Version
28
+ version: 1.101.0
29
+ - !ruby/object:Gem::Dependency
30
+ name: card-mod-carrierwave
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - '='
34
+ - !ruby/object:Gem::Version
35
+ version: 0.11.0
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - '='
41
+ - !ruby/object:Gem::Version
42
+ version: 0.11.0
43
+ description: ''
44
+ email:
45
+ - info@decko.org
46
+ executables: []
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - README.md
51
+ - lib/card/follow_option.rb
52
+ - lib/card/follower_stash.rb
53
+ - set/abstract/follow_option.rb
54
+ - set/all/follow.rb
55
+ - set/all/follow/follow_link.rb
56
+ - set/all/follow/follow_link_views.rb
57
+ - set/all/follow/followed_by.rb
58
+ - set/all/follow/follower_ids.rb
59
+ - set/all/follow/start_follow_link.rb
60
+ - set/all/follow/stop_follow_link.rb
61
+ - set/all/notify.rb
62
+ - set/all/notify/base_views.rb
63
+ - set/all/notify/html_views.rb
64
+ - set/right/account.rb
65
+ - set/right/follow.rb
66
+ - set/right/follow/follow_status.haml
67
+ - set/right/follow_fields.rb
68
+ - set/right/followers.rb
69
+ - set/right/following.rb
70
+ - set/self/always.rb
71
+ - set/self/created.rb
72
+ - set/self/edited.rb
73
+ - set/self/follow.rb
74
+ - set/self/follow_defaults.rb
75
+ - set/self/follow_fields.rb
76
+ - set/self/never.rb
77
+ - set/type/cardtype.rb
78
+ - set/type/notification_template.rb
79
+ - set/type/set.rb
80
+ - set/type/user.rb
81
+ - set/type_plus_right/user/follow.rb
82
+ - set/type_plus_right/user/follow/follow_editor.haml
83
+ - set/type_plus_right/user/follow/follow_editor_helper.rb
84
+ homepage: http://decko.org
85
+ licenses:
86
+ - GPL-3.0
87
+ metadata:
88
+ card-mod: follow
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '2.5'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubygems_version: 3.0.3
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: follower notifications
108
+ test_files: []