card-mod-follow 0.11.0

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.
@@ -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: []