radiant-reader-extension 3.0.0.rc4 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. data/README.md +105 -38
  2. data/Rakefile +4 -4
  3. data/app/controllers/accounts_controller.rb +24 -11
  4. data/app/controllers/admin/groups_controller.rb +15 -0
  5. data/app/controllers/admin/memberships_controller.rb +13 -7
  6. data/app/controllers/admin/messages_controller.rb +1 -0
  7. data/app/controllers/admin/permissions_controller.rb +15 -8
  8. data/app/controllers/groups_controller.rb +6 -4
  9. data/app/controllers/password_resets_controller.rb +1 -1
  10. data/app/controllers/reader_action_controller.rb +7 -51
  11. data/app/controllers/reader_sessions_controller.rb +9 -11
  12. data/app/helpers/reader_helper.rb +23 -3
  13. data/app/models/group.rb +45 -16
  14. data/app/models/message.rb +4 -11
  15. data/app/models/permission.rb +4 -0
  16. data/app/models/reader.rb +61 -26
  17. data/app/models/reader_notifier.rb +2 -2
  18. data/app/models/reader_page.rb +9 -5
  19. data/app/views/accounts/{_memberships.html.haml → _choose_memberships.html.haml} +0 -0
  20. data/app/views/accounts/_form.html.haml +9 -11
  21. data/app/views/accounts/_preamble.html.haml +14 -0
  22. data/app/views/accounts/_profile_form.html.haml +13 -29
  23. data/app/views/accounts/dashboard.html.haml +0 -1
  24. data/app/views/accounts/edit.html.haml +3 -3
  25. data/app/views/accounts/edit_profile.html.haml +10 -10
  26. data/app/views/admin/groups/_chooser.html.haml +8 -0
  27. data/app/views/admin/groups/_form.html.haml +7 -5
  28. data/app/views/admin/groups/_group.html.haml +29 -0
  29. data/app/views/admin/groups/index.html.haml +2 -28
  30. data/app/views/admin/groups/show.html.haml +3 -2
  31. data/app/views/admin/memberships/_reader.html.haml +2 -6
  32. data/app/views/admin/messages/_form.html.haml +10 -11
  33. data/app/views/admin/messages/_list_function.haml +2 -3
  34. data/app/views/admin/messages/{index.haml → index.html.haml} +21 -11
  35. data/app/views/admin/pages/_page_groups.html.haml +5 -11
  36. data/app/views/admin/permissions/_page.html.haml +6 -12
  37. data/app/views/admin/reader_configuration/edit.html.haml +2 -0
  38. data/app/views/admin/reader_configuration/show.html.haml +2 -0
  39. data/app/views/groups/_group.html.haml +12 -0
  40. data/app/views/groups/show.html.haml +10 -3
  41. data/app/views/readers/_description.html.haml +3 -0
  42. data/app/views/readers/_groups.html.haml +9 -0
  43. data/app/views/{accounts → readers}/_links.html.haml +2 -2
  44. data/app/views/readers/_list.html.haml +23 -0
  45. data/app/views/{accounts/_groups.html.haml → readers/_memberships.html.haml} +0 -1
  46. data/app/views/{accounts/_reader.html.haml → readers/_mugshot.html.haml} +1 -1
  47. data/app/views/readers/_people.html.haml +6 -0
  48. data/app/views/readers/_profile.html.haml +30 -0
  49. data/app/views/readers/_reader.html.haml +28 -0
  50. data/app/views/readers/index.html.haml +20 -0
  51. data/app/views/{accounts → readers}/show.html.haml +1 -2
  52. data/app/views/shared/_standard_reader_parts.html.haml +1 -1
  53. data/app/views/shared/not_allowed.html.haml +16 -0
  54. data/config/initializers/formats.rb +1 -2
  55. data/config/initializers/radiant_config.rb +5 -2
  56. data/config/locales/en.yml +181 -140
  57. data/config/routes.rb +25 -16
  58. data/db/migrate/001_create_readers.rb +0 -1
  59. data/db/migrate/20090921125653_reader_messages.rb +0 -1
  60. data/db/migrate/20090921125654_group_messages.rb +0 -1
  61. data/db/migrate/20110812111934_groups_nested_set.rb +19 -0
  62. data/db/migrate/20110814070858_message_has_many_groups.rb +14 -0
  63. data/db/migrate/20110905194602_group_ancestry.rb +23 -0
  64. data/lib/controller_extensions.rb +49 -0
  65. data/lib/grouped_model.rb +49 -8
  66. data/lib/grouped_page.rb +17 -5
  67. data/lib/message_tags.rb +21 -3
  68. data/lib/radiant-reader-extension.rb +1 -1
  69. data/lib/reader_admin_ui.rb +7 -8
  70. data/lib/reader_tags.rb +1 -1
  71. data/lib/site_controller_extensions.rb +7 -18
  72. data/public/images/furniture/csv.png +0 -0
  73. data/public/images/furniture/csv_tiny.png +0 -0
  74. data/public/images/furniture/vcard.png +0 -0
  75. data/public/images/furniture/vcard_tiny.png +0 -0
  76. data/public/javascripts/admin/reader.js +22 -1
  77. data/public/stylesheets/sass/admin/reader_group.sass +23 -22
  78. data/public/stylesheets/sass/reader.sass +81 -17
  79. data/radiant-reader-extension.gemspec +3 -1
  80. data/reader_extension.rb +7 -9
  81. data/spec/controllers/accounts_controller_spec.rb +8 -22
  82. data/spec/controllers/admin/messages_controller_spec.rb +0 -12
  83. data/spec/datasets/readers_dataset.rb +41 -38
  84. data/spec/lib/reader_tags_spec.rb +1 -1
  85. data/spec/models/group_spec.rb +89 -22
  86. data/spec/models/message_spec.rb +1 -1
  87. data/spec/models/reader_notifier_spec.rb +1 -1
  88. data/spec/models/reader_page_spec.rb +34 -18
  89. data/spec/models/reader_spec.rb +0 -1
  90. data/spec/spec.opts +4 -3
  91. metadata +51 -28
  92. data/app/views/accounts/_contributions.html.haml +0 -2
  93. data/app/views/accounts/_description.html.haml +0 -2
  94. data/app/views/accounts/_list.html.haml +0 -17
  95. data/app/views/accounts/_profile.html.haml +0 -29
  96. data/app/views/accounts/index.html.haml +0 -23
  97. data/app/views/groups/_all.html.haml +0 -10
  98. data/app/views/site/not_allowed.html.haml +0 -4
  99. data/db/migrate/20100922152338_lock_versions.rb +0 -9
  100. data/db/migrate/20101004074945_unlock_version.rb +0 -9
@@ -3,30 +3,19 @@ module SiteControllerExtensions
3
3
  def self.included(base)
4
4
  base.class_eval {
5
5
  # NB. to control access without disabling the cache we have overridden Page.cache?
6
- # to return false for any page that has a group association.
6
+ # to return false for any page that has a group association.
7
7
 
8
8
  def find_page_with_group_check(url)
9
9
  page = find_page_without_group_check(url)
10
- raise ReaderError::AccessDenied if page && !page.visible_to?(current_reader)
11
- page
12
- end
13
-
14
- def show_page_with_group_check
15
- show_page_without_group_check
16
- rescue ReaderError::AccessDenied
17
- if current_reader
18
- flash[:error] = t("reader_extension.access_denied")
19
- redirect_to reader_permission_denied_url
20
- else
21
- flash[:explanation] = t("reader_extension.page_not_public")
22
- flash[:error] = t("reader_extension.please_log_in")
23
- store_location
24
- redirect_to reader_login_url
10
+ if page
11
+ raise ReaderError::LoginRequired, t("reader_extension.page_is_private_please_log_in") if page.restricted? && !current_reader
12
+ raise ReaderError::ActivationRequired, t("reader_extension.page_is_private_please_log_in") if page.restricted? && !current_reader.activated?
13
+ raise ReaderError::AccessDenied, t("reader_extension.page_access_not_given") unless page.visible_to?(current_reader)
25
14
  end
15
+ page
26
16
  end
27
-
28
17
  alias_method_chain :find_page, :group_check
29
- alias_method_chain :show_page, :group_check
18
+
30
19
  }
31
20
  end
32
21
  end
Binary file
Binary file
@@ -1,3 +1,5 @@
1
+ // This is your 'select all' checkbox: its state is applied to all siblings with 'toggled' class.
2
+ //
1
3
  Toggle.SelectAllBehavior = Behavior.create(Toggle.CheckboxBehavior, {
2
4
  toggle: function() {
3
5
  var state = this.element.checked;
@@ -5,7 +7,26 @@ Toggle.SelectAllBehavior = Behavior.create(Toggle.CheckboxBehavior, {
5
7
  }
6
8
  });
7
9
 
10
+ // This is a normal remote link that replaces itself with the response.
11
+ //
12
+ Remote.UpdatingLink = Behavior.create(Remote.Base, {
13
+ onclick : function() {
14
+ var self = this;
15
+ var options = Object.extend({
16
+ url : this.element.href,
17
+ method : 'get',
18
+ update: this.element.up(),
19
+ onLoading: function () { self.element.addClassName('waiting'); },
20
+ onComplete: function () { self.element.removeClassName('waiting'); },
21
+ onSuccess: function () { Event.addBehavior.reload(); },
22
+ onFailure: function () { self.element.addClassName('failed'); }
23
+ }, self.options);
24
+ return self._makeRequest(options);
25
+ }
26
+ });
27
+
8
28
  Event.addBehavior({
9
29
  'div.radio_group': Toggle.RadioGroupBehavior(),
10
- 'input.select_all': Toggle.SelectAllBehavior()
30
+ 'input.select_all': Toggle.SelectAllBehavior(),
31
+ 'a.fake_checkbox': Remote.UpdatingLink()
11
32
  });
@@ -5,14 +5,25 @@
5
5
  &#groups
6
6
  td.name
7
7
  width: 35%
8
- a
9
- font-size: 160%
10
8
  span.notes
11
9
  font-size: 80%
12
10
  color: #929488
13
11
  font-weight: lighter
14
12
  line-height: 1.2
15
13
  margin-top: 0.25em
14
+ tr.level_0
15
+ td.name
16
+ a
17
+ font-size: 120%
18
+ tr.level_1
19
+ td.name
20
+ a
21
+ font-size: 100%
22
+ tr.level_2
23
+ td.name
24
+ a
25
+ font-size: 85%
26
+
16
27
  &#import
17
28
  th
18
29
  text-align: left
@@ -113,39 +124,29 @@
113
124
  *}
114
125
 
115
126
  .fake_checkbox
127
+ display: block
116
128
  padding-left: 20px
117
129
  cursor: pointer
118
130
  background-repeat: no-repeat
119
131
  background-position: 0 3px
132
+ text-decoration: none
133
+ color: #ccc
134
+ font-weight: normal
135
+ background-image: url(/images/admin/chk_off.png)
120
136
  input
121
137
  position: absolute
122
138
  left: -9999px
123
- a
124
- text-decoration: none
125
139
  &.checked
140
+ color: #5da454
126
141
  background-image: url(/images/admin/chk_on.png)
127
- &.unchecked
128
- background-image: url(/images/admin/chk_off.png)
129
142
  &.inherited
143
+ color: #bfe4b9
130
144
  background-image: url(/images/admin/chk_auto.png)
131
145
  &.waiting
146
+ color: #8c8d8e
132
147
  background-image: url(/images/admin/spinner.gif)
133
-
134
- .checked a, .selected a
135
- color: #5da454
136
-
137
- .unchecked a, .unselected a
138
- color: #ccc
139
- font-weight: normal
140
-
141
- .waiting a
142
- color: #8c8d8e
143
-
144
- .failed a
145
- color: #c00
146
-
147
- .inherited
148
- color: #bfe4b9
148
+ &.failed
149
+ color: #c00
149
150
 
150
151
  span.group_actions
151
152
  img
@@ -88,6 +88,7 @@ form.friendly
88
88
  input.standard
89
89
  width: 95%
90
90
  span.formnote
91
+ clear: left
91
92
  +small
92
93
  color: $mid
93
94
  label
@@ -132,21 +133,44 @@ form.friendly
132
133
  h3:first-child
133
134
  margin-top: 0
134
135
 
135
- address
136
- width: 75%
137
- border: 1px solid $paler
138
- padding: 1em
139
- margin: 1em -1em
140
- +border-radius(5px)
136
+ #marginalia
137
+ div.contact
138
+ border: 1px solid $paler
139
+ +box-shadow
140
+ padding: 1em
141
+ margin: 1em -1em
142
+ h3
143
+ margin-bottom: 1em
144
+ ul
145
+ margin-bottom: 0
146
+ li
147
+ margin-bottom: 0
148
+ span.indent
149
+ float: left
150
+ margin-right: 0.5em
151
+ address
152
+ overflow: hidden
141
153
 
142
- a.vcard
143
- padding-left: 25px
144
- background: transparent url(/images/furniture/vcard_tiny.png) no-repeat 0 3px
145
-
146
- h3.vcard
147
- padding-left: 40px
148
- background: transparent url(/images/furniture/vcard.png) no-repeat 0 3px
154
+ a.vcard, a.csv
155
+ padding-left: 12px
156
+ background: transparent url(/images/furniture/vcard_tiny.png) no-repeat 0 0
157
+ &:hover
158
+ background-position: 0 -19px
159
+
160
+ a.csv
161
+ background-image: url(/images/furniture/csv_tiny.png)
149
162
 
163
+ h2
164
+ span.headernote
165
+ font-size: 70%
166
+ a.vcard, a.csv
167
+ display: inline-block
168
+ height: 14px
169
+ width: 20px
170
+ text-indent: -100px
171
+ padding-left: 0
172
+ margin-right: 4px
173
+
150
174
  a.mailto
151
175
  color: $mid
152
176
 
@@ -159,9 +183,18 @@ a.mailto
159
183
 
160
184
  .column
161
185
  float: left
162
- width: 45%
163
- margin-right: 3%
164
-
186
+ width: 30%
187
+ margin-right: 2%
188
+ .reader
189
+ margin-bottom: 1em
190
+ overflow: hidden
191
+ .speaker
192
+ margin-left: 0
193
+ h2
194
+ font-size: 125%
195
+ a.title
196
+ padding-top: 0.5em
197
+
165
198
  ul.groups
166
199
  padding: 0
167
200
  margin: 0 0 1em 0
@@ -170,4 +203,35 @@ ul.groups
170
203
  display: inline
171
204
 
172
205
  .cleared
173
- clear: left
206
+ clear: left
207
+
208
+ .message_head
209
+
210
+ div#preview
211
+ float: left
212
+ width: 80%
213
+ +box-shadow
214
+ background-color: white
215
+ .message_header
216
+ padding: 10px
217
+ overflow: hidden
218
+ background-color: #eee
219
+ color: #333
220
+ font-size: 80%
221
+ line-height: 1.5
222
+ ul
223
+ margin: 0
224
+ padding: 6px 14px
225
+ list-style-type: none
226
+ li.subject
227
+ font-size: 1.6em
228
+ margin-top: 6px
229
+ li.mime-version, li.content-type
230
+ display: none
231
+ .message_body
232
+ iframe
233
+ width: 99%
234
+ height: 520px
235
+ margin: 0
236
+ border: 0
237
+ overflow: auto
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.add_dependency 'snail', "~> 0.5.5"
20
20
  s.add_dependency 'vcard', "~> 0.1.1"
21
21
  s.add_dependency 'fastercsv', "~> 1.5.4"
22
+ s.add_dependency 'ancestry', "~> 1.2.4"
22
23
 
23
24
  ignores = if File.exist?('.gitignore')
24
25
  File.read('.gitignore').split("\n").inject([]) {|a,p| a + Dir[p] }
@@ -35,7 +36,8 @@ Gem::Specification.new do |s|
35
36
 
36
37
  config.gem 'radiant-reader-extension', :version => '~> #{RadiantReaderExtension::VERSION}'
37
38
 
38
- and please remember to enable ActionMailer in your project's config/environment.rb.
39
+ and if you haven't already, remember to enable ActionMailer in your
40
+ project's config/environment.rb.
39
41
  }
40
42
 
41
43
  end
data/reader_extension.rb CHANGED
@@ -6,14 +6,6 @@ class ReaderExtension < Radiant::Extension
6
6
  description RadiantReaderExtension::DESCRIPTION
7
7
  url RadiantReaderExtension::URL
8
8
 
9
- extension_config do |config|
10
- config.gem 'authlogic', :version => "~> 2.1.6"
11
- config.gem 'sanitize', :version => "~> 2.0.1"
12
- config.gem 'snail', :version => "~> 0.5.5"
13
- config.gem 'vcard', :version => "~> 0.1.1"
14
- config.gem 'fastercsv', :version => "~> 1.5.4"
15
- end
16
-
17
9
  migrate_from 'Reader Group', 20110214101339
18
10
 
19
11
  def activate
@@ -50,7 +42,13 @@ class ReaderExtension < Radiant::Extension
50
42
  end
51
43
 
52
44
  module ReaderError
45
+ class LoginRequired < StandardError
46
+ def initialize(message = "Login Required"); super end
47
+ end
48
+ class ActivationRequired < StandardError
49
+ def initialize(message = "Activation Required"); super end
50
+ end
53
51
  class AccessDenied < StandardError
54
- def initialize(message = "Sorry: you have to log in to see that"); super end
52
+ def initialize(message = "Access Denied"); super end
55
53
  end
56
54
  end
@@ -117,14 +117,6 @@ describe AccountsController do
117
117
  rsession = ReaderSession.create!(readers(:normal))
118
118
  # controller.stub!(:current_reader_session).and_return(rsession)
119
119
  end
120
-
121
- it "should route '/account' to my account" do
122
- params_from(:get, '/account').should == {:controller => 'accounts', :action => 'edit'}
123
- end
124
-
125
- it "should route '/profile' to my account" do
126
- params_from(:get, '/profile').should == {:controller => 'accounts', :action => 'show'}
127
- end
128
120
 
129
121
  it "should consent to show another reader page" do
130
122
  get :show, :id => reader_id(:visible)
@@ -166,35 +158,29 @@ describe AccountsController do
166
158
  end
167
159
 
168
160
  describe "with an update request" do
169
- before do
170
- login_as_reader(:normal)
171
- end
172
-
173
161
  describe "that is valid" do
174
162
  before do
175
- put :update, {:id => reader_id(:normal), :reader => {:name => "New Name"}}
163
+ login_as_reader(:normal)
164
+ put :update, {:id => reader_id(:normal), :reader => {:name => "Abnormal"}}
176
165
  @reader = readers(:normal)
177
166
  end
178
167
 
179
168
  it "should update the reader" do
180
- @reader.name.should == 'New Name'
169
+ @reader.name.should == 'Abnormal'
170
+ @reader.changed?.should be_false
181
171
  end
182
172
 
183
- it "should redirect to the reader page" do
173
+ it "should redirect to the reader-dashboard page" do
184
174
  response.should be_redirect
185
- response.should redirect_to(dashboard_url)
175
+ response.should redirect_to(reader_dashboard_url)
186
176
  end
187
177
 
188
178
  end
189
179
 
190
180
  describe "that does not validate" do
191
181
  before do
192
- put :update, {:id => reader_id(:normal), :reader => {:login => "visible@spanner.org"}, :current_password => 'password'}
193
- @reader = readers(:normal)
194
- end
195
-
196
- it "should not update the reader" do
197
- @reader.name.should == 'Normal'
182
+ login_as_reader(:normal)
183
+ put :update, {:id => reader_id(:normal), :reader => {:login => readers(:visible).login}}
198
184
  end
199
185
 
200
186
  it "should re-render the edit form" do
@@ -39,17 +39,5 @@ describe Admin::MessagesController do
39
39
  response.should redirect_to(admin_message_url(messages(:taggy)))
40
40
  end
41
41
  end
42
-
43
- describe "on update (and create)" do
44
- before do
45
- login_as :existing
46
- end
47
42
 
48
- it "should redirect to show the updated object" do
49
- put :update, :id => message_id(:normal), :subject => 'testing'
50
- response.should be_redirect
51
- response.should redirect_to(admin_message_path(message_id(:normal)))
52
- end
53
- end
54
-
55
43
  end
@@ -19,6 +19,13 @@ class ReadersDataset < Dataset::Base
19
19
  create_group "Homed", :homepage_id => page_id(:parent)
20
20
  create_group "Elsewhere", :site_id => site_id(:elsewhere) if defined? Site
21
21
 
22
+ create_group "Supergroup" do
23
+ create_group "Subgroup" do
24
+ create_group "Subsubgroup"
25
+ create_group "Anothersubsubgroup"
26
+ end
27
+ end
28
+
22
29
  create_message "Normal"
23
30
  create_message "Grouped", :function_id => "group_welcome"
24
31
  create_message "Filtered", :filter_id => 'Textile', :body => 'this is a *filtered* message'
@@ -50,64 +57,60 @@ From <r:sender:name />
50
57
  admit_to_group :homed, [readers(:normal)]
51
58
  admit_to_group :normal, [readers(:normal), readers(:inactive)]
52
59
  admit_to_group :special, [readers(:another)]
60
+ admit_to_group :subgroup, [readers(:normal), readers(:another)]
61
+
53
62
  restrict_to_group :homed, [pages(:parent), pages(:childless)]
54
63
  restrict_to_group :special, [pages(:news)]
55
64
  restrict_to_group :normal, [messages(:grouped)]
65
+ restrict_to_group :subgroup, [pages(:child)]
66
+ restrict_to_group :subsubgroup, [pages(:child_2)]
56
67
  end
57
68
 
58
69
  helpers do
59
70
  def create_reader(name, attributes={})
60
- reader = create_model Reader, name.symbolize, default_reader_attributes(name).merge(attributes)
61
- end
62
-
63
- def create_group(name, attributes={})
64
- group = create_record Group, name.symbolize, default_group_attributes(name).merge(attributes)
65
- end
66
-
67
- def create_message(subject, attributes={})
68
- message = create_model Message, subject.symbolize, default_message_attributes(subject).merge(attributes)
69
- message.update_attribute(:created_by, users(:existing)) # otherwise this is blanked by the absence of a current_user, and we need it for preview rendering
70
- end
71
-
72
- def create_layout(name, attributes={})
73
- attributes[:site] ||= sites(:test) if Layout.reflect_on_association(:site)
74
- create_model :layout, name.symbolize, attributes.update(:name => name)
75
- end
76
-
77
- def default_reader_attributes(name="John Doe")
78
- symbol = name.symbolize
79
- attributes = {
71
+ create_model :reader, name.symbolize, {
80
72
  :name => name,
81
- :email => "#{symbol}@spanner.org",
82
- :login => "#{symbol}@spanner.org",
73
+ :email => "#{name}@spanner.org",
74
+ :login => name.downcase,
83
75
  :activated_at => Time.now - 1.week,
84
76
  :password_salt => "golly",
85
77
  :password => 'passw0rd',
86
78
  :password_confirmation => 'passw0rd'
87
- }
88
- attributes[:site] = sites(:test) if defined? Site
89
- attributes
79
+ }.merge(attributes)
90
80
  end
91
-
92
- def default_group_attributes(name="Group")
93
- attributes = {
81
+
82
+ def create_group(name, attributes={})
83
+ symbol = name.symbolize
84
+ create_model :group, symbol, {
94
85
  :name => name,
95
86
  :slug => name.downcase,
96
- :description => "#{name} group"
97
- }
98
- attributes[:site_id] ||= site_id(:test) if defined? Site
99
- attributes
87
+ :description => "#{name} group",
88
+ :parent_id => @group_id
89
+ }.merge(attributes)
90
+ if block_given?
91
+ @group_id = group_id(symbol)
92
+ yield
93
+ @group_id = nil
94
+ end
100
95
  end
101
96
 
102
- def default_message_attributes(subject="Message")
103
- attributes = {
97
+ def create_message(subject, attributes={})
98
+ create_record :message, subject.symbolize, {
104
99
  :subject => subject,
105
- :body => "This is the #{subject} message"
106
- }
107
- attributes[:site] = sites(:test) if defined? Site
108
- attributes
100
+ :body => "This is the #{subject} message",
101
+ :created_by_id => user_id(:existing)
102
+ }.merge(attributes)
109
103
  end
110
104
 
105
+ def create_layout(name, attributes={})
106
+ create_model :layout, name.symbolize, {
107
+ :name => name
108
+ }.merge(attributes)
109
+ end
110
+
111
+
112
+
113
+
111
114
  def login_as_reader(reader)
112
115
  activate_authlogic
113
116
  login_reader = reader.is_a?(Reader) ? reader : readers(reader)