Commit 7f062d8f89065ac1d4ab1f8e6de7906e8c99a276
1 parent
3600768c
Exists in
master
and in
29 other branches
Introduce EventPlugin with EventBlock
ActionItem2119 Signed-off-by: Arthur Del Esposte <arthurmde@gmail.com> Signed-off-by: Aurélio A. Heckert <aurelio@colivre.coop.br>
Showing
14 changed files
with
785 additions
and
1 deletions
Show diff stats
app/models/event.rb
@@ -141,6 +141,10 @@ class Event < Article | @@ -141,6 +141,10 @@ class Event < Article | ||
141 | result | 141 | result |
142 | end | 142 | end |
143 | 143 | ||
144 | + def duration | ||
145 | + ((self.end_date || self.start_date) - self.start_date).to_i | ||
146 | + end | ||
147 | + | ||
144 | def lead | 148 | def lead |
145 | content_tag('div', | 149 | content_tag('div', |
146 | show_period(start_date, end_date), | 150 | show_period(start_date, end_date), |
@@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
1 | +class EventPlugin < Noosfero::Plugin | ||
2 | + | ||
3 | + def self.plugin_name | ||
4 | + _("Event Extras") | ||
5 | + end | ||
6 | + | ||
7 | + def self.plugin_description | ||
8 | + _("Include a new block to show the environment's or profiles' events information") | ||
9 | + end | ||
10 | + | ||
11 | + def self.extra_blocks | ||
12 | + { EventPlugin::EventBlock => { :type => [Community, Person, Enterprise, Environment] } } | ||
13 | + end | ||
14 | + | ||
15 | + def stylesheet? | ||
16 | + true | ||
17 | + end | ||
18 | + | ||
19 | + def js_files | ||
20 | + 'event.js' | ||
21 | + end | ||
22 | + | ||
23 | +end |
@@ -0,0 +1,87 @@ | @@ -0,0 +1,87 @@ | ||
1 | +class EventPlugin::EventBlock < Block | ||
2 | + include DatesHelper | ||
3 | + | ||
4 | + attr_accessible :all_env_events, :limit, :future_only, :date_distance_limit | ||
5 | + | ||
6 | + settings_items :all_env_events, :type => :boolean, :default => false | ||
7 | + settings_items :limit, :type => :integer, :default => 4 | ||
8 | + settings_items :future_only, :type => :boolean, :default => false | ||
9 | + settings_items :date_distance_limit, :type => :integer, :default => 0 | ||
10 | + | ||
11 | + def self.description | ||
12 | + _('Events') | ||
13 | + end | ||
14 | + | ||
15 | + def help | ||
16 | + _('Show the profile events or all environment events.') | ||
17 | + end | ||
18 | + | ||
19 | + def events_source | ||
20 | + unless all_env_events | ||
21 | + if self.owner.kind_of? Environment | ||
22 | + return self.owner | ||
23 | + elsif environment.portal_community | ||
24 | + return environment.portal_community | ||
25 | + end | ||
26 | + end | ||
27 | + | ||
28 | + environment | ||
29 | + end | ||
30 | + | ||
31 | + def events(user = nil) | ||
32 | + events = events_source.events | ||
33 | + events = events.published.order('start_date') | ||
34 | + | ||
35 | + if future_only | ||
36 | + events = events.where('start_date >= ?', Date.today) | ||
37 | + end | ||
38 | + | ||
39 | + if date_distance_limit > 0 | ||
40 | + events = events.by_range([ | ||
41 | + Date.today - date_distance_limit, | ||
42 | + Date.today + date_distance_limit | ||
43 | + ]) | ||
44 | + end | ||
45 | + | ||
46 | + event_list = [] | ||
47 | + events.each do |event| | ||
48 | + event_list << event if event.display_to? user | ||
49 | + break if event_list.length >= limit | ||
50 | + end | ||
51 | + | ||
52 | + event_list | ||
53 | + end | ||
54 | + | ||
55 | + def content(args={}) | ||
56 | + block = self | ||
57 | + proc do | ||
58 | + render( | ||
59 | + :file => 'blocks/event', | ||
60 | + :locals => { :block => block } | ||
61 | + ) | ||
62 | + end | ||
63 | + end | ||
64 | + | ||
65 | + def human_time_left(days_left) | ||
66 | + months_left = (days_left/30.0).round | ||
67 | + if days_left <= -60 | ||
68 | + n_('Started one month ago.', 'Started %d months ago.', -months_left) % -months_left | ||
69 | + elsif days_left < 0 | ||
70 | + n_('Started one day ago.', 'Started %d days ago.', -days_left) % -days_left | ||
71 | + elsif days_left == 0 | ||
72 | + _("I happens today.") | ||
73 | + elsif days_left < 60 | ||
74 | + n_('One day left to start.', '%d days left to start.', days_left) % days_left | ||
75 | + else | ||
76 | + n_('One month left to start.', '%d months left to start.', months_left) % months_left | ||
77 | + end | ||
78 | + end | ||
79 | + | ||
80 | + def date_to_html(date) | ||
81 | + content_tag(:span, show_day_of_week(date, true), :class => 'week-day') + | ||
82 | + content_tag(:span, month_name(date.month, true), :class => 'month') + | ||
83 | + content_tag(:span, date.day.to_s, :class => 'day') + | ||
84 | + content_tag(:span, date.year.to_s, :class => 'year') | ||
85 | + end | ||
86 | + | ||
87 | +end |
@@ -0,0 +1,110 @@ | @@ -0,0 +1,110 @@ | ||
1 | +# SOME DESCRIPTIVE TITLE. | ||
2 | +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER | ||
3 | +# This file is distributed under the same license as the PACKAGE package. | ||
4 | +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. | ||
5 | +# | ||
6 | +msgid "" | ||
7 | +msgstr "" | ||
8 | +"Project-Id-Version: 1.0\n" | ||
9 | +"POT-Creation-Date: 2015-01-30 11:52-0000\n" | ||
10 | +"PO-Revision-Date: 2015-01-30 00:18-0000\n" | ||
11 | +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||
12 | +"Language-Team: LANGUAGE <LL@li.org>\n" | ||
13 | +"Language: \n" | ||
14 | +"MIME-Version: 1.0\n" | ||
15 | +"Content-Type: text/plain; charset=UTF-8\n" | ||
16 | +"Content-Transfer-Encoding: 8bit\n" | ||
17 | +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" | ||
18 | + | ||
19 | +#: plugins/event/lib/event_plugin/event_block.rb:12 | ||
20 | +msgid "Events" | ||
21 | +msgstr "Eventos" | ||
22 | + | ||
23 | +#: plugins/event/lib/event_plugin/event_block.rb:16 | ||
24 | +msgid "Show the profile events or all environment events." | ||
25 | +msgstr "Mostrar todos os eventos." | ||
26 | + | ||
27 | +#: plugins/event/lib/event_plugin/event_block.rb:68 | ||
28 | +msgid "Started one month ago." | ||
29 | +msgid_plural "Started %d months ago." | ||
30 | +msgstr[0] "Iniciou a um mês atrás." | ||
31 | +msgstr[1] "Iniciou a %d meses atrás." | ||
32 | + | ||
33 | +#: plugins/event/lib/event_plugin/event_block.rb:70 | ||
34 | +msgid "Started one day ago." | ||
35 | +msgid_plural "Started %d days ago." | ||
36 | +msgstr[0] "Iniciou a Um dia atrás." | ||
37 | +msgstr[1] "Iniciou a %d dias atrás." | ||
38 | + | ||
39 | +#: plugins/event/lib/event_plugin/event_block.rb:72 | ||
40 | +msgid "I happens today." | ||
41 | +msgstr "Acontece hoje." | ||
42 | + | ||
43 | +#: plugins/event/lib/event_plugin/event_block.rb:74 | ||
44 | +msgid "One day left to start." | ||
45 | +msgid_plural "%d days left to start." | ||
46 | +msgstr[0] "Um dia para iniciar." | ||
47 | +msgstr[1] "%d dias para iniciar." | ||
48 | + | ||
49 | +#: plugins/event/lib/event_plugin/event_block.rb:76 | ||
50 | +msgid "One month left to start." | ||
51 | +msgid_plural "%d months left to start." | ||
52 | +msgstr[0] "Um mês para iniciar" | ||
53 | +msgstr[1] "% meses para iniciar" | ||
54 | + | ||
55 | +#: plugins/event/lib/event_plugin.rb:4 | ||
56 | +msgid "Event Extras" | ||
57 | +msgstr "Eventos" | ||
58 | + | ||
59 | +#: plugins/event/lib/event_plugin.rb:8 | ||
60 | +msgid "" | ||
61 | +"Include a new block to show the environment's or profiles' events information" | ||
62 | +msgstr "" | ||
63 | +"Adiciona um novo bloco para apresentar as informações de eventos do ambiente " | ||
64 | +"ou de perfis" | ||
65 | + | ||
66 | +#: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:1 | ||
67 | +msgid "Limit of items" | ||
68 | +msgstr "Limite de itens" | ||
69 | + | ||
70 | +#: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:3 | ||
71 | +msgid "Show all environment events" | ||
72 | +msgstr "Apresentar todos os eventos do ambiente" | ||
73 | + | ||
74 | +#: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:8 | ||
75 | +msgid "(Don't check to show only your events)" | ||
76 | +msgstr "(Não marque para apresentar somente seus eventos)" | ||
77 | + | ||
78 | +#: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:10 | ||
79 | +msgid "(Don't check to show only %s events)" | ||
80 | +msgstr "(Não marque para apresentar somente os eventos de %s)" | ||
81 | + | ||
82 | +#: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:13 | ||
83 | +msgid "(Don't check to show only the environment events)" | ||
84 | +msgstr "(Não marque para apresentar somente os eventos do ambiente)" | ||
85 | + | ||
86 | +#: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:18 | ||
87 | +msgid "Limit of days to display" | ||
88 | +msgstr "Limite de dias de distância para mostrar eventos" | ||
89 | + | ||
90 | +#: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:20 | ||
91 | +msgid "Only show events on this limit of days." | ||
92 | +msgstr "Mostar somente eventos que acontecem dentro do limite de dias" | ||
93 | + | ||
94 | +#: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:23 | ||
95 | +msgid "Only show future events" | ||
96 | +msgstr "Mostrar apenas eventos futuros" | ||
97 | + | ||
98 | +#: plugins/event/views/event_plugin/event_block_item.html.erb:6 | ||
99 | +msgid "Duration: 1 day" | ||
100 | +msgid_plural "Duration: %s days" | ||
101 | +msgstr[0] "" | ||
102 | +msgstr[1] "" | ||
103 | + | ||
104 | +#~ msgid "1 day" | ||
105 | +#~ msgid_plural "%s days" | ||
106 | +#~ msgstr[0] "1 dia" | ||
107 | +#~ msgstr[1] "%s dias" | ||
108 | + | ||
109 | +#~ msgid "Event Block Plugin" | ||
110 | +#~ msgstr "Plugin de Bloco de Eventos" |
@@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
1 | +(function(){ | ||
2 | + function change_title_size(){ | ||
3 | + jQuery(".event-plugin_event-block .event .title").each(function(num, el){ | ||
4 | + var title = jQuery(el); | ||
5 | + console.log(title.height(), title.css("line-height")); | ||
6 | + if (title.height() > parseInt(title.css("line-height")) * 2) { | ||
7 | + title.addClass("toobig") | ||
8 | + } | ||
9 | + }); | ||
10 | + } | ||
11 | + | ||
12 | + | ||
13 | + jQuery(document).ready(function(){ | ||
14 | + change_title_size(); | ||
15 | + }); | ||
16 | +})(); | ||
0 | \ No newline at end of file | 17 | \ No newline at end of file |
@@ -0,0 +1,186 @@ | @@ -0,0 +1,186 @@ | ||
1 | +.event-plugin_event-block { | ||
2 | + font-size: 12px; | ||
3 | +} | ||
4 | + | ||
5 | +.event-plugin_event-block .events { | ||
6 | + margin: 0; | ||
7 | + padding: 0; | ||
8 | + border-bottom: 1px solid #DDD; | ||
9 | +} | ||
10 | + | ||
11 | +.event-plugin_event-block .events li { | ||
12 | + margin: 0; | ||
13 | + padding: 1px 0; | ||
14 | + list-style: none; | ||
15 | + border-top: 1px solid #DDD; | ||
16 | +} | ||
17 | + | ||
18 | +.event-plugin_event-block .event a { | ||
19 | + display: block; | ||
20 | + min-height: 60px; | ||
21 | + overflow: hidden; | ||
22 | + padding: 3px 0; | ||
23 | + text-decoration: none; | ||
24 | + color: inherit; | ||
25 | +} | ||
26 | + | ||
27 | +.event-plugin_event-block .event a:hover { | ||
28 | + background-color: #EEE; | ||
29 | + text-decoration: none; | ||
30 | + color: inherit; | ||
31 | +} | ||
32 | + | ||
33 | +.event-plugin_event-block .event a:visited { | ||
34 | + color: inherit; | ||
35 | +} | ||
36 | + | ||
37 | +.event-plugin_event-block .event .date { | ||
38 | + display: block; | ||
39 | + width: 60px; | ||
40 | + height: auto; | ||
41 | + background-size: cover; | ||
42 | + background-position: 50% 40%; | ||
43 | + font-weight: bold; | ||
44 | + text-align: center; | ||
45 | + float: left; | ||
46 | + margin-right: 10px; | ||
47 | +} | ||
48 | + | ||
49 | +.event-plugin_event-block .event .date.no-img { | ||
50 | + background-color: #AAA; | ||
51 | +} | ||
52 | + | ||
53 | +.event-plugin_event-block .event:hover .date.no-img { | ||
54 | + background-color: #79B; | ||
55 | +} | ||
56 | + | ||
57 | +.event-plugin_event-block .event:hover .date.no-img * { | ||
58 | + opacity: 0.8; | ||
59 | + filter: alpha(opacity=80); | ||
60 | +} | ||
61 | + | ||
62 | +.event-plugin_event-block .event .month { | ||
63 | + display: block; | ||
64 | + background: rgba(90,90,90,0.6); | ||
65 | + color: #FFF; | ||
66 | + text-shadow: 0 0 2px #000; | ||
67 | + font-size: 20px; | ||
68 | + line-height: 22px; | ||
69 | +} | ||
70 | + | ||
71 | +.msie8 .event-plugin_event-block .event .month{ | ||
72 | + background: #797979; | ||
73 | + width: 60px; | ||
74 | + float: left; | ||
75 | + text-align: center; | ||
76 | +} | ||
77 | + | ||
78 | +.event-plugin_event-block .event:hover .has-img .month { | ||
79 | + opacity: 0.9; | ||
80 | + background: rgba(90,90,90,0.4); | ||
81 | +} | ||
82 | + | ||
83 | +.msie8 .event-plugin_event-block .event:hover .has-img .month { | ||
84 | + background: #D8D8D8; | ||
85 | +} | ||
86 | + | ||
87 | +.event-plugin_event-block .event .day { | ||
88 | + display: block; | ||
89 | + background: rgba(255,255,255,0.5); | ||
90 | + border: 2px solid rgba(90,90,90,0.6); | ||
91 | + border-top: none; | ||
92 | + color: #000; | ||
93 | + font-size: 36px; | ||
94 | + line-height: 36px; | ||
95 | +} | ||
96 | + | ||
97 | +.msie8 .event-plugin_event-block .event .day { | ||
98 | + display: block; | ||
99 | + background: #D4D4D4; | ||
100 | + border: 2px solid #797979; | ||
101 | + width: 56px; | ||
102 | + text-align: center; | ||
103 | +} | ||
104 | + | ||
105 | +.event-plugin_event-block .event .has-img .day { | ||
106 | + text-shadow: 0 0 5px #FFF, 0 0 5px #FFF; | ||
107 | +} | ||
108 | + | ||
109 | +.event-plugin_event-block .event:hover .has-img .day { | ||
110 | + opacity: 0.8; | ||
111 | + background: rgba(255,255,255,0.3); | ||
112 | +} | ||
113 | + | ||
114 | +.event-plugin_event-block .event:hover .has-img .day { | ||
115 | + filter: alpha(opacity=80); | ||
116 | +} | ||
117 | + | ||
118 | +.msie8 .event-plugin_event-block .event:hover .has-img .day{ | ||
119 | + background: #D4D4D4; | ||
120 | +} | ||
121 | + | ||
122 | +.event-plugin_event-block .event .duration { | ||
123 | + display: block; | ||
124 | +} | ||
125 | + | ||
126 | +.event-plugin_event-block .event .duration span { | ||
127 | + font-weight: bold; | ||
128 | +} | ||
129 | + | ||
130 | +#content .event-plugin_event-block .event .title { | ||
131 | + position: relative; | ||
132 | + display: block; | ||
133 | + font-size: 14px; | ||
134 | + line-height: 16px; | ||
135 | + margin: 0; | ||
136 | + overflow: hidden; | ||
137 | + max-height: 33px; | ||
138 | +} | ||
139 | + | ||
140 | +.event-plugin_event-block .event .title.toobig:after { | ||
141 | + content: "..."; | ||
142 | + position: absolute; | ||
143 | + bottom: 0; | ||
144 | + right: 0; | ||
145 | + width: 5em; | ||
146 | + padding-right: 4px; | ||
147 | + text-align: right; | ||
148 | + color: rgba(0, 0, 0, 0.5); | ||
149 | + background: -webkit-gradient(linear, left top, right top, | ||
150 | + from(rgba(255, 255, 255, 0)), to(#FFF), color-stop(80%, #FFF)); | ||
151 | + background: -moz-linear-gradient(to right, rgba(255, 255, 255, 0), #FFF 80%, #FFF); | ||
152 | + background: -ms-linear-gradient(to right, rgba(255, 255, 255, 0), #FFF 80%, #FFF); | ||
153 | + background: -o-linear-gradient(to right, rgba(255, 255, 255, 0), #FFF 80%, #FFF); | ||
154 | + background: linear-gradient(to right, rgba(255, 255, 255, 0), #FFF 80%, #FFF); | ||
155 | +} | ||
156 | + | ||
157 | +.event-plugin_event-block .event:hover .title.toobig:after { | ||
158 | + background: -webkit-gradient(linear, left top, right top, | ||
159 | + from(rgba(238, 238, 238, 0)), to(#EEE), color-stop(80%, #EEE)); | ||
160 | + background: -moz-linear-gradient(to right, rgba(238, 238, 238, 0), #EEE 80%, #EEE); | ||
161 | + background: -ms-linear-gradient(to right, rgba(238, 238, 238, 0), #EEE 80%, #EEE); | ||
162 | + background: -o-linear-gradient(to right, rgba(238, 238, 238, 0), #EEE 80%, #EEE); | ||
163 | + background: linear-gradient(to right, rgba(238, 238, 238, 0), #EEE 80%, #EEE); | ||
164 | +} | ||
165 | + | ||
166 | +.event-plugin_event-block .event .address i { | ||
167 | + display: block; | ||
168 | + font-style: normal; | ||
169 | + overflow: hidden; | ||
170 | + white-space: nowrap; | ||
171 | + text-overflow: ellipsis; | ||
172 | +} | ||
173 | + | ||
174 | +.event-plugin_event-block .event .days-left { | ||
175 | + display: block; | ||
176 | +} | ||
177 | + | ||
178 | +.event-plugin_event-block .event .days-left.past { | ||
179 | + filter: alpha(opacity=50); | ||
180 | +} | ||
181 | + | ||
182 | +.msie8 #content .event-plugin_event-block .event .title, | ||
183 | +.msie8 #content .event-plugin_event-block .event .adress i, | ||
184 | +.msie8 #content .event-plugin_event-block .event .days-left { | ||
185 | + float: left; | ||
186 | +} |
@@ -0,0 +1,70 @@ | @@ -0,0 +1,70 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../test/test_helper' | ||
2 | + | ||
3 | +# Re-raise errors caught by the controller. | ||
4 | +class HomeController | ||
5 | + #append_view_path File.join(File.dirname(__FILE__) + '/../../views') | ||
6 | + def rescue_action(e) | ||
7 | + raise e | ||
8 | + end | ||
9 | +end | ||
10 | + | ||
11 | +class HomeControllerTest < ActionController::TestCase | ||
12 | + | ||
13 | + def setup | ||
14 | + @env = Environment.default | ||
15 | + @env.enable_plugin('EventPlugin') | ||
16 | + | ||
17 | + @p1 = fast_create(Person, :environment_id => @env.id) | ||
18 | + @e1a = fast_create(Event, :name=>'Event p1 A', :profile_id=>@p1.id) | ||
19 | + | ||
20 | + box = Box.create!(:owner => @env) | ||
21 | + @block = EventPlugin::EventBlock.create!(:box => box) | ||
22 | + end | ||
23 | + | ||
24 | + # Event item CSS selector | ||
25 | + ev = '.event-plugin_event-block ul.events li.event[itemscope]' + | ||
26 | + '[itemtype="http://data-vocabulary.org/Event"] ' | ||
27 | + | ||
28 | + should 'see events microdata sturcture' do | ||
29 | + get :index | ||
30 | + assert_select '.event-plugin_event-block ul.events' | ||
31 | + assert_select ev | ||
32 | + assert_select ev + 'a[itemprop="url"]' | ||
33 | + assert_select ev + 'time.date[itemprop="startDate"][datetime]' | ||
34 | + assert_select ev + 'time.date .day' | ||
35 | + assert_select ev + 'time.date .month' | ||
36 | + assert_select ev + 'time.date .year' | ||
37 | + assert_select ev + '.title[itemprop="summary"]' | ||
38 | + assert_select ev + '.address[itemprop="location"] *[itemprop="name"]' | ||
39 | + assert_select ev + '.days-left' | ||
40 | + end | ||
41 | + | ||
42 | + should 'see event duration' do | ||
43 | + @e1a.slug = 'event1a' | ||
44 | + @e1a.start_date = Date.today | ||
45 | + @e1a.end_date = Date.tomorrow | ||
46 | + @e1a.save! | ||
47 | + get :index | ||
48 | + assert_select ev + 'time.duration[itemprop="endDate"]', '+1 day' | ||
49 | + | ||
50 | + @e1a.slug = 'event1a' | ||
51 | + @e1a.start_date = Date.today | ||
52 | + @e1a.end_date = Date.tomorrow+1 | ||
53 | + @e1a.save! | ||
54 | + get :index | ||
55 | + assert_select ev + 'time.duration[itemprop="endDate"]', '+2 days' | ||
56 | + end | ||
57 | + | ||
58 | + should 'not see event duration for one day events' do | ||
59 | + get :index | ||
60 | + assert_select ev + 'time.duration[itemprop="endDate"]', false | ||
61 | + | ||
62 | + @e1a.slug = 'event1a' | ||
63 | + @e1a.start_date = Date.today | ||
64 | + @e1a.end_date = Date.today | ||
65 | + @e1a.save! | ||
66 | + get :index | ||
67 | + assert_select ev + 'time.duration[itemprop="endDate"]', false | ||
68 | + end | ||
69 | + | ||
70 | +end |
@@ -0,0 +1,189 @@ | @@ -0,0 +1,189 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../test/test_helper' | ||
2 | + | ||
3 | +class EventPlugin::EventBlockTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @env = Environment.default | ||
7 | + @env.enable_plugin('EventPlugin') | ||
8 | + | ||
9 | + @p1 = fast_create(Person, :environment_id => @env.id) | ||
10 | + @event = fast_create(Event, :name => 'Event p1 A', :profile_id => @p1.id, | ||
11 | + :start_date => Date.today+30) | ||
12 | + fast_create(Event, :name => 'Event p1 B', :profile_id => @p1.id, | ||
13 | + :start_date => Date.today+10) | ||
14 | + | ||
15 | + @p2 = fast_create(Community, :environment_id => @env.id) | ||
16 | + fast_create(Event, :name => 'Event p2 A', :profile_id => @p2.id, | ||
17 | + :start_date => Date.today-10) | ||
18 | + fast_create(Event, :name => 'Event p2 B', :profile_id => @p2.id, | ||
19 | + :start_date => Date.today-30) | ||
20 | + | ||
21 | + box = fast_create(Box, :owner_id => @p1) | ||
22 | + @block = EventPlugin::EventBlock.new(:limit => 99, :box => box) | ||
23 | + end | ||
24 | + | ||
25 | + def set_portal(env, portal) | ||
26 | + env.portal_community = portal | ||
27 | + env.enable('use_portal_community') | ||
28 | + env.save! | ||
29 | + end | ||
30 | + | ||
31 | + should 'select source as env, while visiting the profile' do | ||
32 | + @block.box.owner = @p1 | ||
33 | + @block.all_env_events = true | ||
34 | + | ||
35 | + assert_equal @env, @block.events_source | ||
36 | + assert_equal 4, @block.events.length | ||
37 | + | ||
38 | + set_portal(@env, @p2) | ||
39 | + | ||
40 | + assert_equal @env, @block.events_source | ||
41 | + assert_equal 4, @block.events.length | ||
42 | + end | ||
43 | + | ||
44 | + should 'select source as env, while visiting an env page' do | ||
45 | + @block.box.owner = @env | ||
46 | + @block.all_env_events = true | ||
47 | + | ||
48 | + assert_equal @env, @block.events_source | ||
49 | + assert_equal 4, @block.events.length | ||
50 | + | ||
51 | + set_portal @env, @p2 | ||
52 | + | ||
53 | + assert_equal @env, @block.events_source | ||
54 | + assert_equal 4, @block.events.length | ||
55 | + end | ||
56 | + | ||
57 | + should 'select source as portal_community, while visiting an env page' do | ||
58 | + set_portal @env, @p2 | ||
59 | + | ||
60 | + @block.box.owner = @env.portal_community | ||
61 | + @block.all_env_events = false | ||
62 | + | ||
63 | + assert_equal @p2, @block.events_source | ||
64 | + assert_equal 2, @block.events.length | ||
65 | + end | ||
66 | + | ||
67 | + should 'select source as profile, while visiting its page' do | ||
68 | + @block.stubs(:owner).returns(@p1) | ||
69 | + @block.all_env_events = false | ||
70 | + | ||
71 | + assert_equal @p1, @block.events_source | ||
72 | + assert_equal 2, @block.events.length | ||
73 | + | ||
74 | + set_portal @env, @p2 | ||
75 | + | ||
76 | + assert_equal @p1, @block.events_source | ||
77 | + assert_equal 2, @block.events.length | ||
78 | + end | ||
79 | + | ||
80 | + should 'say human left time for an event' do | ||
81 | + one_day = @block.human_time_left(Date.tomorrow - Date.today) | ||
82 | + | ||
83 | + assert_match /One day left/, one_day | ||
84 | + assert_match /5 days left/, @block.human_time_left(5) | ||
85 | + assert_match /30 days left/, @block.human_time_left(30) | ||
86 | + assert_match /2 months left/, @block.human_time_left(60) | ||
87 | + assert_match /3 months left/, @block.human_time_left(85) | ||
88 | + end | ||
89 | + | ||
90 | + should 'say human past time for an event' do | ||
91 | + one_day = @block.human_time_left(Date.yesterday - Date.today) | ||
92 | + | ||
93 | + assert_match /One day past/, one_day | ||
94 | + assert_match /5 days past/, @block.human_time_left(-5) | ||
95 | + assert_match /30 days past/, @block.human_time_left(-30) | ||
96 | + assert_match /2 months past/, @block.human_time_left(-60) | ||
97 | + assert_match /3 months past/, @block.human_time_left(-85) | ||
98 | + end | ||
99 | + | ||
100 | + should 'write formatable data in html' do | ||
101 | + html = '<span class="week-day">Tue</span>'+ | ||
102 | + '<span class="month">Sep</span>'+ | ||
103 | + '<span class="day">27</span>'+ | ||
104 | + '<span class="year">1983</span>' | ||
105 | + | ||
106 | + assert_equal html, @block.date_to_html(Date.new 1983, 9, 27) | ||
107 | + end | ||
108 | + | ||
109 | + should 'show unlimited time distance events' do | ||
110 | + @block.box.owner = @env | ||
111 | + @block.all_env_events = true | ||
112 | + @block.date_distance_limit = 0 | ||
113 | + | ||
114 | + assert_equal 4, @block.events.length | ||
115 | + end | ||
116 | + | ||
117 | + should 'only show 20 days distant events' do | ||
118 | + @block.box.owner = @env | ||
119 | + @block.all_env_events = true | ||
120 | + @block.date_distance_limit = 20 | ||
121 | + | ||
122 | + assert_equal 2, @block.events.length | ||
123 | + end | ||
124 | + | ||
125 | + should 'show future and past events' do | ||
126 | + @block.box.owner = @env | ||
127 | + @block.all_env_events = true | ||
128 | + @block.future_only = false | ||
129 | + | ||
130 | + assert_equal 4, @block.events.length | ||
131 | + end | ||
132 | + | ||
133 | + should 'show only future events' do | ||
134 | + @block.box.owner = @env | ||
135 | + @block.all_env_events = true | ||
136 | + @block.future_only = true | ||
137 | + | ||
138 | + assert_equal 2, @block.events.length | ||
139 | + end | ||
140 | + | ||
141 | + should 'show only published events' do | ||
142 | + @block.box.owner = @env | ||
143 | + @block.all_env_events = true | ||
144 | + @event.published = false | ||
145 | + @event.save! | ||
146 | + | ||
147 | + assert_equal 3, @block.events.length | ||
148 | + end | ||
149 | + | ||
150 | + should 'filter events from non public profiles' do | ||
151 | + person = create_user('testuser', :environment_id => @env.id).person | ||
152 | + person.public_profile = false | ||
153 | + person.save! | ||
154 | + | ||
155 | + visibility_content_test_from_a_profile person | ||
156 | + end | ||
157 | + | ||
158 | + should 'filter events from non visible profiles' do | ||
159 | + person = create_user('testuser', :environment_id=>@env.id).person | ||
160 | + person.visible = false | ||
161 | + person.save! | ||
162 | + | ||
163 | + visibility_content_test_from_a_profile person | ||
164 | + end | ||
165 | + | ||
166 | + def visibility_content_test_from_a_profile(profile) | ||
167 | + @block.box.owner = @env | ||
168 | + ev = fast_create Event, :name => '2 de Julho', :profile_id => profile.id | ||
169 | + @block.all_env_events = true | ||
170 | + | ||
171 | + # Do not list event from private profile for non logged visitor | ||
172 | + assert ! @block.events.include?(ev) | ||
173 | + assert_equal 4, @block.events.length | ||
174 | + | ||
175 | + # Do not list event from private profile for non unprivileged user | ||
176 | + assert ! @block.events.include?(ev) | ||
177 | + assert_equal 4, @block.events(@p1).length | ||
178 | + | ||
179 | + # Must to list event from private profile for a friend | ||
180 | + AddFriend.create!(:requestor => @p1, :target => profile).finish | ||
181 | + | ||
182 | + assert @block.events(@p1).include?(ev) | ||
183 | + assert_equal 5, @block.events(@p1).length | ||
184 | + | ||
185 | + # Must to list event from private profile for itself | ||
186 | + assert @block.events(profile).include?(ev) | ||
187 | + assert_equal 5, @block.events(profile).length | ||
188 | + end | ||
189 | +end |
@@ -0,0 +1,19 @@ | @@ -0,0 +1,19 @@ | ||
1 | +<%= block_title(block.title) %> | ||
2 | + | ||
3 | +<ul class="events"> | ||
4 | + <% block.events(@user).map do |event| %> | ||
5 | + <% days_left = ( event.start_date - Date.today ).round %> | ||
6 | + <li itemscope="itemscope" itemtype="http://data-vocabulary.org/Event" class="event"> | ||
7 | + <%= render( | ||
8 | + :file => 'event_plugin/event_block_item', | ||
9 | + :locals => { | ||
10 | + :event => event, | ||
11 | + :block => block, | ||
12 | + :time_class => days_left < 0 ? 'future' : 'past', | ||
13 | + :time_left_str => block.human_time_left(days_left) | ||
14 | + } | ||
15 | + ) | ||
16 | + %> | ||
17 | + </li> | ||
18 | + <% end %> | ||
19 | +</ul> |
plugins/event/views/event_plugin/event_block_item.html.erb
0 → 100644
@@ -0,0 +1,41 @@ | @@ -0,0 +1,41 @@ | ||
1 | +<% | ||
2 | + # compute layout values | ||
3 | + ev_days_tag = '' | ||
4 | + if event.duration > 0 | ||
5 | + ev_days_tag = content_tag('time', | ||
6 | + n_('Duration: 1 day', 'Duration: %s days', event.duration) % "<b>#{event.duration}</b>", | ||
7 | + :itemprop => 'endDate', | ||
8 | + :datetime => show_date(event.end_date) + 'T00:00', | ||
9 | + :class => 'duration', | ||
10 | + :title => show_date(event.start_date) + ' — ' + time_left_str | ||
11 | + ) | ||
12 | + end | ||
13 | + | ||
14 | + img = event.image.nil? ? event.first_image : event.image.public_filename | ||
15 | + bg = "background-image: url(#{img})" if not img.blank? | ||
16 | + img_class = img.blank? ? 'no-img' : 'has-img' | ||
17 | +%> | ||
18 | +<%= | ||
19 | + link_to([ | ||
20 | + content_tag('time', | ||
21 | + block.date_to_html(event.start_date), | ||
22 | + :itemprop => 'startDate', | ||
23 | + :datetime => show_date(event.start_date), | ||
24 | + :class => 'date ' + img_class, :style => bg, | ||
25 | + :title => show_date(event.start_date) + ' — ' + time_left_str | ||
26 | + ), | ||
27 | + ev_days_tag, | ||
28 | + content_tag('strong', h(event.name), :class => 'title', | ||
29 | + :title => event.name, :itemprop => 'summary'), | ||
30 | + content_tag('span', content_tag('i', event.address, :itemprop=>:name), | ||
31 | + :title => h(event.address), | ||
32 | + :class => 'address', :itemscope => :itemscope, | ||
33 | + :itemtype => 'http://schema.org/Place', | ||
34 | + :itemprop => :location), | ||
35 | + content_tag('span', time_left_str, :class => 'days-left ' + time_class) | ||
36 | + ].join("\n"), | ||
37 | + (event.link.blank? ? event.url : event.link), | ||
38 | + :class => 'ev-days-' + event.duration.to_s, | ||
39 | + :itemprop => :url | ||
40 | + ) | ||
41 | +%> |
plugins/event/views/profile_design/event_plugin/_event_block.html.erb
0 → 100644
@@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
1 | +<%= labelled_form_field _('Limit of items'), text_field(:block, :limit, :size => 4) %> | ||
2 | + | ||
3 | +<%= labelled_check_box(_('Show all environment events'), "block[all_env_events]", "1", @block.all_env_events) %> | ||
4 | +<br> | ||
5 | +<small><%= | ||
6 | + if @profile | ||
7 | + if @profile.person? | ||
8 | + _("(Don't check to show only your events)") | ||
9 | + else | ||
10 | + _("(Don't check to show only %s events)") % @profile.name | ||
11 | + end | ||
12 | + elsif environment.portal_community | ||
13 | + _("(Don't check to show only the environment events)") | ||
14 | + end | ||
15 | +%></small> | ||
16 | +<br> | ||
17 | + | ||
18 | +<%= labelled_form_field _('Limit of days to display'), | ||
19 | + text_field(:block, :date_distance_limit, :size => 4) %> | ||
20 | +<small>(<%=_('Only show events on this limit of days.')%>)</small> | ||
21 | +<br><br> | ||
22 | + | ||
23 | +<%= labelled_check_box(_('Only show future events'), "block[future_only]", "1", @block.future_only) %> |
test/factories.rb
@@ -247,7 +247,13 @@ module Noosfero::Factory | @@ -247,7 +247,13 @@ module Noosfero::Factory | ||
247 | ############################################### | 247 | ############################################### |
248 | 248 | ||
249 | def defaults_for_event | 249 | def defaults_for_event |
250 | - { :name => 'My event ' + factory_num_seq.to_s, :start_date => Date.today } | 250 | + num = factory_num_seq.to_s |
251 | + { | ||
252 | + :name => 'My event ' + num, | ||
253 | + :slug => 'my-event-' + num, | ||
254 | + :path => '/my-event-' + num, | ||
255 | + :start_date => Date.today | ||
256 | + } | ||
251 | end | 257 | end |
252 | 258 | ||
253 | ############################################### | 259 | ############################################### |