Commit 2157d022b5dd108a5568c70485d635df9f2891fb

Authored by Joenio Costa
2 parents a3e6850a e0543b02

Merge branch 'rails235' into AI2983-pg_search_escape_chars_fix

Showing 306 changed files with 6622 additions and 1457 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 306 files displayed.

AUTHORS 0 → 100644
... ... @@ -0,0 +1,239 @@
  1 +If you are not listed here, but should be, please write to the noosfero mailing
  2 +list: http://listas.softwarelivre.org/cgi-bin/mailman/listinfo/noosfero-dev
  3 +(this list requires subscription to post, but since you are an author of
  4 +noosfero, that's not a problem).
  5 +
  6 +Developers
  7 +==========
  8 +
  9 +Alan Freihof Tygel <alantygel@gmail.com>
  10 +alcampelo <alcampelo@alcampelo.(none)>
  11 +Alessandro Palmeira <alessandro.palmeira@gmail.com>
  12 +Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com>
  13 +Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com>
  14 +Alessandro Palmeira + Caio Salgado <caio.csalgado@gmail.com>
  15 +Alessandro Palmeira + Caio Salgado + Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>
  16 +Alessandro Palmeira + Carlos Morais <alessandro.palmeira@gmail.com>
  17 +Alessandro Palmeira + Daniel Alves <alessandro.palmeira@gmail.com>
  18 +Alessandro Palmeira + Daniel Alves + Diego Araújo <diegoamc90@gmail.com>
  19 +Alessandro Palmeira + Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com>
  20 +Alessandro Palmeira + Diego Araujo <alessandro.palmeira@gmail.com>
  21 +Alessandro Palmeira + Diego Araújo <alessandro.palmeira@gmail.com>
  22 +Alessandro Palmeira + Diego Araujo + Daniela Feitosa <alessandro.palmeira@gmail.com>
  23 +Alessandro Palmeira + Diego Araujo <diegoamc90@gmail.com>
  24 +Alessandro Palmeira + Diego Araújo <diegoamc90@gmail.com>
  25 +Alessandro Palmeira + Diego Araujo + Eduardo Morais <alessandro.palmeira@gmail.com>
  26 +Alessandro Palmeira + Diego Araújo + João M. M. da Silva <alessandro.palmeira@gmail.com>
  27 +Alessandro Palmeira + Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>
  28 +Alessandro Palmeira + Diego Araujo + João M. M. da Silva + Paulo Meirelles <alessandro.palmeira@gmail.com>
  29 +Alessandro Palmeira + Diego Araújo + Pedro Leal <diegoamc90@gmail.com>
  30 +Alessandro Palmeira + Diego Araújo + Pedro Leal + João M. M. da Silva <diegoamc90@gmail.com>
  31 +Alessandro Palmeira + Diego Araujo + Rafael Manzo <alessandro.palmeira@gmail.com>
  32 +Alessandro Palmeira + Eduardo Morais <alessandro.palmeira@gmail.com>
  33 +Alessandro Palmeira + Guilherme Rojas <alessandro.palmeira@gmail.com>
  34 +Alessandro Palmeira + Jefferson Fernandes <alessandro.palmeira@gmail.com>
  35 +Alessandro Palmeira + João M. M. da Silva <alessandro.palmeira@gmail.com>
  36 +Alessandro Palmeira + Joao M. M. da Silva + Diego Araujo <alessandro.palmeira@gmail.com>
  37 +Alessandro Palmeira + João M. M. da Silva + Renan Teruo <alessandro.palmeira@gmail.com>
  38 +Alessandro Palmeira + João M. M. Silva <alessandro.palmeira@gmail.com>
  39 +Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com>
  40 +Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com>
  41 +Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com>
  42 +Ana Losnak <analosnak@gmail.com>
  43 +Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br>
  44 +Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br>
  45 +Antonio Terceiro <terceiro@colivre.coop.br>
  46 +Arthur Del Esposte <arthurmde@yahoo.com.br>
  47 +Aurelio A. Heckert <aurelio@colivre.coop.br>
  48 +Braulio Bhavamitra <brauliobo@gmail.com>
  49 +Bráulio Bhavamitra <brauliobo@gmail.com>
  50 +Braulio Bhavamitra <braulio@eita.org.br>
  51 +Caio <caio.csalgado@gmail.com>
  52 +Caio + Diego + Pedro + João <caio.csalgado@gmail.com>
  53 +Caio Formiga <caio.formiga@gmail.com>
  54 +Caio, Pedro <caio.csalgado@gmail.com>
  55 +Caio Salgado + Alessandro Palmeira <caio.csalgado@gmail.com>
  56 +Caio Salgado <caio.csalgado@gmail.com>
  57 +Caio Salgado + Carlos Morais + Diego Araújo + Pedro Leal <diegoamc90@gmail.com>
  58 +Caio Salgado + Diego Araujo <caio.csalgado@gmail.com>
  59 +Caio Salgado + Diego Araújo <caio.csalgado@gmail.com>
  60 +Caio Salgado + Diego Araújo <diegoamc90@gmail.com>
  61 +Caio Salgado + Diego Araújo + Jefferson Fernandes <caio.csalgado@gmail.com>
  62 +Caio Salgado + Diego Araújo + João M. M. da Silva <caio.csalgado@gmail.com>
  63 +Caio Salgado + Diego Araújo + Pedro Leal <caio.csalgado@gmail.com>
  64 +Caio Salgado + Diego Araújo + Pedro Leal <diegoamc90@gmail.com>
  65 +Caio Salgado + Diego Araújo + Rafael Manzo <diegoamc90@gmail.com>
  66 +Caio Salgado + Jefferson Fernandes <caio.csalgado@gmail.com>
  67 +Caio Salgado + Jefferson Fernandes <jeffs.fernandes@gmail.com>
  68 +Caio Salgado + Rafael Manzo <caio.csalgado@gmail.com>
  69 +Caio Salgado + Renan Teruo <caio.csalgado@gmail.com>
  70 +Caio Salgado + Renan Teruo <caio.salgado@gmail.com>
  71 +Caio Salgado + Renan Teruo + Jefferson Fernandes <jeffs.fernandes@gmail.com>
  72 +Caio Salgado + Renan Teruo <renanteruoc@gmail.com>
  73 +Caio SBA <caio@colivre.coop.br>
  74 +Carlos Andre de Souza <carlos.andre.souza@msn.com>
  75 +Carlos Morais <carlos88morais@gmail.com>
  76 +Carlos Morais + Diego Araújo <diegoamc90@gmail.com>
  77 +Carlos Morais + Eduardo Morais <carlos88morais@gmail.com>
  78 +Carlos Morais + Paulo Meirelles <carlos88morais@gmail.com>
  79 +Carlos Morais + Pedro Leal <carlos88morais@gmail.com>
  80 +Daniel Alves + Diego Araújo <danpaulalves@gmail.com>
  81 +Daniel Alves + Diego Araújo <diegoamc90@gmail.com>
  82 +Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com>
  83 +Daniel Alves + Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com>
  84 +Daniel Alves + Diego Araújo + Guilherme Rojas <guilhermehrojas@gmail.com>
  85 +Daniel Alves + Guilherme Rojas <danpaulalves@gmail.com>
  86 +Daniel Alves + Rafael Manzo <rr.manzo@gmail.com>
  87 +Daniela Soares Feitosa <danielafeitosa@colivre.coop.br>
  88 +Daniel Bucher <daniel.bucher88@gmail.com>
  89 +Daniel Cunha <daniel@colivre.coop.br>
  90 +David Carlos <ddavidcarlos1392@gmail.com>
  91 +diegoamc <diegoamc90@gmail.com>
  92 +Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com>
  93 +Diego Araújo + Alessandro Palmeira + João M. M. da Silva <diegoamc90@gmail.com>
  94 +Diego Araújo + Alessandro Palmeira + Rafael Manzo <rr.manzo@gmail.com>
  95 +Diego Araujo + Caio Salgado <diegoamc90@gmail.com>
  96 +Diego Araújo + Daniel Alves + Rafael Manzo <rr.manzo@gmail.com>
  97 +Diego Araújo <diegoamc90@gmail.com>
  98 +Diego Araújo + Eduardo Morais + Paulo Meirelles <diegoamc90@gmail.com>
  99 +Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com>
  100 +Diego Araújo + Jefferson Fernandes <diegoamc90@gmail.com>
  101 +Diego Araujo + Jefferson Fernandes <jeffs.fernandes@gmail.com>
  102 +Diego Araújo + João Machini <diegoamc90@gmail.com>
  103 +Diego Araújo + João Machini <digoamc90@gmail.com>
  104 +Diego Araújo + João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>
  105 +Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>
  106 +Diego Araújo + João M. M. da Silva + João Machini <diegoamc90@gmail.com>
  107 +Diego Araújo + João M. M. da Silva + Pedro Leal <diegoamc90@gmail.com>
  108 +Diego Araújo + Paulo Meirelles <diegoamc90@gmail.com>
  109 +Diego Araújo + Pedro Leal <diegoamc90@gmail.com>
  110 +Diego Araujo + Rafael Manzo <diegoamc90@gmail.com>
  111 +Diego Araújo + Rafael Manzo <diegoamc90@gmail.com>
  112 +Diego Araújo + Renan Teruo + Alessandro Palmeira <diegoamc90@gmail.com>
  113 +Diego Araújo + Renan Teruo <diegoamc90@gmail.com>
  114 +Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com>
  115 +Diego + Jefferson <diegoamc90@gmail.com>
  116 +Diego Martinez <diegoamc90@gmail.com>
  117 +Diego Martinez <diego@diego-K55A.(none)>
  118 +Diego + Renan <renanteruoc@gmail.com>
  119 +Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br>
  120 +Fabio Teixeira <fabio1079@gmail.com>
  121 +Fernanda Lopes <nanda.listas+psl@gmail.com>
  122 +Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br>
  123 +Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)>
  124 +Francisco Marcelo de Araújo Lima Júnior <francisco.lima-junior@serpro.gov.br>
  125 +Francisco Marcelo de Araújo Lima Júnior <maljunior@gmail.com>
  126 +Gabriela Navarro <navarro1703@gmail.com>
  127 +Grazieno Pellegrino <grazieno@gmail.com>
  128 +Gust <darksshades@hotmail.com>
  129 +Hugo Melo <hugo@riseup.net>
  130 +Isaac Canan <isaac@intelletto.com.br>
  131 +Italo Valcy <italo@dcc.ufba.br>
  132 +Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com>
  133 +Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com>
  134 +Jefferson Fernandes + Joao M. M. Silva <jeffs.fernandes@gmail.com>
  135 +João da Silva <jaodsilv@linux.ime.usp.br>
  136 +João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br>
  137 +João M. M. da Silva + Alessandro Palmeira + Diego Araújo + Caio Salgado <jaodsilv@linux.ime.usp.br>
  138 +João M. M. da Silva + Alessandro Palmeira + Diego Araújo <jaodsilv@linux.ime.usp.br>
  139 +Joao M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>
  140 +João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>
  141 +João M. M. da Silva + Alessandro Palmeira + João Machini <jaodsilv@linux.ime.usp.br>
  142 +João M. M. da Silva + Caio Salgado + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>
  143 +João M. M. da Silva + Caio Salgado <jaodsilv@linux.ime.usp.br>
  144 +João M. M. da Silva + Carlos Morais <jaodsilv@linux.ime.usp.br>
  145 +João M. M. da Silva + Diego Araújo <diegoamc90@gmail.com>
  146 +João M. M. da Silva + Diego Araújo <jaodsilv@linux.ime.usp.br>
  147 +João M. M. da Silva + Diego Araújo + Pedro Leal <jaodsilv@linux.ime.usp.br>
  148 +João M. M. da Silva <jaodsilv@linux.ime.usp.br>
  149 +Joao M. M. da Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br>
  150 +João M. M. da Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br>
  151 +João M. M. da Silva + João M. Miranda <jaodsilv@linux.ime.usp.br>
  152 +João M. M. da Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br>
  153 +João M. M. da Silva + Pedro Leal <jaodsilv@linux.ime.usp.br>
  154 +João M. M. da Silva + Rafael Manzo + Diego Araújo <jaodsilv@linux.ime.usp.br>
  155 +João M. M. da Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br>
  156 +João M. M. da Silva + Renan Teruo <jaodsilv@linux.ime.usp.br>
  157 +João M. M. Silva + Caio Salgado <jaodsilv@linux.ime.usp.br>
  158 +João M. M. Silva + Diego Araújo <jaodsilv@linux.ime.usp.br>
  159 +Joao M. M. Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br>
  160 +João M. M. Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br>
  161 +João M. M. Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br>
  162 +João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br>
  163 +Joenio Costa <joenio@colivre.coop.br>
  164 +Josef Spillner <josef.spillner@tu-dresden.de>
  165 +Junior Silva <juniorsilva1001@gmail.com>
  166 +Junior Silva <juniorsilva7@juniorsilva-Aspire-5750Z.(none)>
  167 +Junior Silva <juniorsilva@colivre.coop.br>
  168 +Keilla Menezes <keilla@colivre.coop.br>
  169 +Larissa Reis <larissa@colivre.coop.br>
  170 +Larissa Reis <reiss.larissa@gmail.com>
  171 +Leandro Nunes dos Santos <81665687568@serpro-1541727.Home>
  172 +Leandro Nunes dos Santos <81665687568@serpro-1541727.(none)>
  173 +Leandro Nunes dos Santos <leandronunes@gmail.com>
  174 +Leandro Nunes dos Santos <leandro.santos@serpro.gov.br>
  175 +LinguÁgil 2010 <linguagil.bahia@gmail.com>
  176 +Lucas Melo <lucas@colivre.coop.br>
  177 +Lucas Melo <lucaspradomelo@gmail.com>
  178 +Luis David Aguilar Carlos <ludwig9003@gmail.com>
  179 +Marcos Ramos <ms.ramos@outlook.com>
  180 +Martín Olivera <molivera@solar.org.ar>
  181 +Moises Machado <moises@colivre.coop.br>
  182 +Naíla Alves <naila@colivre.coop.br>
  183 +Nanda Lopes <nanda.listas+psl@gmail.com>
  184 +Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org>
  185 +Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org>
  186 +Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org>
  187 +Paulo Meirelles + Diego Araújo <paulo@softwarelivre.org>
  188 +Paulo Meirelles + João M. M. da Silva <paulo@softwarelivre.org>
  189 +Paulo Meirelles <paulo@softwarelivre.org>
  190 +Paulo Meirelles + Rafael Manzo <paulo@softwarelivre.org>
  191 +Rafael Gomes <rafaelgomes@techfree.com.br>
  192 +Rafael Manzo + Alessandro Palmeira <rr.manzo@gmail.com>
  193 +Rafael Manzo + Daniel Alves <danpaulalves@gmail.com>
  194 +Rafael Manzo + Diego Araújo <rr.manzo@gmail.com>
  195 +Rafael Manzo + João M. M. Silva <rr.manzo@gmail.com>
  196 +Rafael Manzo + Paulo Meirelles <rr.manzo@gmail.com>
  197 +Rafael Martins <rmmartins@gmail.com>
  198 +Rafael Reggiani Manzo + Caio Salgado + Jefferson Fernandes <rr.manzo@gmail.com>
  199 +Rafael Reggiani Manzo + Diego Araujo <diegoamc90@gmail.com>
  200 +Rafael Reggiani Manzo + Diego Araujo <rr.manzo@gmail.com>
  201 +Rafael Reggiani Manzo + Diego Araújo <rr.manzo@gmail.com>
  202 +Rafael Reggiani Manzo + João M. M. da Silva <rr.manzo@gmail.com>
  203 +Rafael Reggiani Manzo <rr.manzo@gmail.com>
  204 +Raphaël Rousseau <raph@r4f.org>
  205 +Raquel Lira <raquel.lira@gmail.com>
  206 +Renan Teruo + Caio Salgado <renanteruoc@gmail.com>
  207 +Renan Teruoc + Diego Araujo <renanteruoc@gmail.com>
  208 +Renan Teruo + Diego Araujo <renanteruoc@gmail.com>
  209 +Renan Teruo + Diego Araújo <renanteruoc@gmail.com>
  210 +Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com>
  211 +Renan Teruo + Rafael Manzo <renanteruoc@gmail.com>
  212 +Rodrigo Souto + Ana Losnak + Daniel Bucher + Caio Almeida + Leandro Nunes + Daniela Feitosa + Mariel Zasso <noosfero-br@listas.softwarelivre.org>
  213 +Rodrigo Souto <diguliu@gmail.com>
  214 +Rodrigo Souto <rodrigo@colivre.coop.br>
  215 +Ronny Kursawe <kursawe.ronny@googlemail.com>
  216 +root <root@debian.sdr.serpro>
  217 +Samuel R. C. Vale <srcvale@holoscopio.com>
  218 +Valessio Brito <contato@valessiobrito.com.br>
  219 +Valessio Brito <contato@valessiobrito.info>
  220 +Valessio Brito <valessio@gmail.com>
  221 +vfcosta <vfcosta@gmail.com>
  222 +Victor Carvalho <victorhugodf.ac@gmail.com>
  223 +Victor Costa <vfcosta@gmail.com>
  224 +Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com>
  225 +Vinicius Cubas Brand <viniciuscb@gmail.com>
  226 +Visita <visita@debian.(none)>
  227 +Yann Lugrin <yann.lugrin@liquid-concept.ch>
  228 +
  229 +Ideas, specifications and incentive
  230 +===================================
  231 +Daniel Tygel <dtygel@fbes.org.br>
  232 +Guilherme Rocha <guilherme@gf7.com.br>
  233 +Raphael Rousseau <raph@r4f.org>
  234 +Théo Bondolfi <move@cooperation.net>
  235 +Vicente Aguiar <vicenteaguiar@colivre.coop.br>
  236 +
  237 +Arts
  238 +===================================
  239 +Nara Oliveira <narananet@gmail.com>
... ...
INSTALL.md
... ... @@ -23,7 +23,7 @@ You need to install some packages Noosfero depends on. On Debian GNU/Linux or De
23 23 # apt-get install ruby rake po4a libgettext-ruby-util libgettext-ruby1.8 \
24 24 libsqlite3-ruby rcov librmagick-ruby libredcloth-ruby libhpricot-ruby \
25 25 libwill-paginate-ruby iso-codes libfeedparser-ruby libdaemons-ruby thin \
26   - tango-icon-theme libnokogiri-ruby
  26 + tango-icon-theme
27 27  
28 28 On other systems, they may or may not be available through your regular package management system. Below are the links to their homepages.
29 29  
... ... @@ -41,7 +41,6 @@ On other systems, they may or may not be available through your regular package
41 41 * Thin: http://code.macournoyer.com/thin
42 42 * tango-icon-theme: http://tango.freedesktop.org/Tango_Icon_Library
43 43 * Hpricot: http://hpricot.com
44   -* Nokogiri: http://nokogiri.org/
45 44  
46 45 If you manage to install Noosfero successfully on other systems than Debian,
47 46 please feel free to contact the Noosfero development mailing with the
... ...
app/controllers/admin/environment_design_controller.rb
... ... @@ -3,6 +3,8 @@ class EnvironmentDesignController &lt; BoxOrganizerController
3 3 protect 'edit_environment_design', :environment
4 4  
5 5 def available_blocks
  6 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  7 + # the Noosfero core soon, see ActionItem3045
6 8 @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ]
7 9 @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment)
8 10 end
... ...
app/controllers/admin/environment_themes_controller.rb 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +class EnvironmentThemesController < ThemesController
  2 +
  3 + protect 'edit_appearance', :environment
  4 +
  5 + no_design_blocks
  6 +
  7 + def target
  8 + @target = environment
  9 + end
  10 +
  11 +end
... ...
app/controllers/admin/users_controller.rb
... ... @@ -7,7 +7,7 @@ class UsersController &lt; AdminController
7 7 include UsersHelper
8 8  
9 9 def index
10   - @filter = params[:filter]
  10 + @filter = params[:filter] || 'all_users'
11 11 scope = environment.people.no_templates
12 12 if @filter == 'admin_users'
13 13 scope = scope.admins
... ... @@ -16,6 +16,7 @@ class UsersController &lt; AdminController
16 16 elsif @filter == 'deactivated_users'
17 17 scope = scope.deactivated
18 18 end
  19 + scope = scope.order('name ASC')
19 20 @q = params[:q]
20 21 @collection = find_by_contents(:people, scope, @q, {:per_page => per_page, :page => params[:npage]})[:results]
21 22 end
... ... @@ -44,6 +45,20 @@ class UsersController &lt; AdminController
44 45 redirect_to :action => :index, :q => params[:q], :filter => params[:filter]
45 46 end
46 47  
  48 +
  49 + def destroy_user
  50 + if request.post?
  51 + person = environment.people.find_by_id(params[:id])
  52 + if person && person.destroy
  53 + session[:notice] = _('The profile was deleted.')
  54 + else
  55 + session[:notice] = _('Could not remove profile')
  56 + end
  57 + end
  58 + redirect_to :action => :index, :q => params[:q], :filter => params[:filter]
  59 + end
  60 +
  61 +
47 62 def download
48 63 respond_to do |format|
49 64 format.html
... ...
app/controllers/application_controller.rb
... ... @@ -21,6 +21,7 @@ class ApplicationController &lt; ActionController::Base
21 21 include ApplicationHelper
22 22 layout :get_layout
23 23 def get_layout
  24 + return nil if request.format == :js
24 25 theme_layout = theme_option(:layout)
25 26 if theme_layout
26 27 theme_view_file('layouts/'+theme_layout) || theme_layout
... ...
app/controllers/box_organizer_controller.rb
... ... @@ -70,7 +70,7 @@ class BoxOrganizerController &lt; ApplicationController
70 70 else
71 71 @center_block_types = (Box.acceptable_center_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => 1)
72 72 @side_block_types = (Box.acceptable_side_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => [2,3])
73   - @boxes = boxes_holder.boxes
  73 + @boxes = boxes_holder.boxes.with_position
74 74 render :action => 'add_block', :layout => false
75 75 end
76 76 end
... ... @@ -80,6 +80,22 @@ class BoxOrganizerController &lt; ApplicationController
80 80 render :action => 'edit', :layout => false
81 81 end
82 82  
  83 + def search_autocomplete
  84 + if request.xhr? and params[:query]
  85 + search = params[:query]
  86 + path_list = if boxes_holder.is_a?(Environment) && boxes_holder.enabled?('use_portal_community') && boxes_holder.portal_community
  87 + boxes_holder.portal_community.articles.find(:all, :conditions=>"name ILIKE '%#{search}%' or path ILIKE '%#{search}%'", :limit=>20).map { |content| "/{portal}/"+content.path }
  88 + elsif boxes_holder.is_a?(Profile)
  89 + boxes_holder.articles.find(:all, :conditions=>"name ILIKE '%#{search}%' or path ILIKE '%#{search}%'", :limit=>20).map { |content| "/{profile}/"+content.path }
  90 + else
  91 + []
  92 + end
  93 + render :json => path_list.to_json
  94 + else
  95 + redirect_to "/"
  96 + end
  97 + end
  98 +
83 99 def save
84 100 @block = boxes_holder.blocks.find(params[:id])
85 101 @block.update_attributes(params[:block])
... ... @@ -99,6 +115,12 @@ class BoxOrganizerController &lt; ApplicationController
99 115 end
100 116 end
101 117  
  118 + def clone_block
  119 + block = Block.find(params[:id])
  120 + block.duplicate
  121 + redirect_to :action => 'index'
  122 + end
  123 +
102 124 protected :boxes_editor?
103 125  
104 126 end
... ...
app/controllers/my_profile/cms_controller.rb
... ... @@ -24,10 +24,16 @@ class CmsController &lt; MyProfileController
24 24 (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile)))
25 25 end
26 26  
27   - protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish, :upload_files] do |c, user, profile|
  27 + protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish, :upload_files, :new] do |c, user, profile|
28 28 user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile))
29 29 end
30 30  
  31 + protect_if :only => :new do |c, user, profile|
  32 + article = profile.articles.find_by_id(c.params[:parent_id])
  33 + (!article.nil? && (article.allow_create?(user) || article.parent.allow_create?(user))) ||
  34 + (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile)))
  35 + end
  36 +
31 37 protect_if :only => [:destroy, :publish] do |c, user, profile|
32 38 profile.articles.find(c.params[:id]).allow_post_content?(user)
33 39 end
... ... @@ -221,11 +227,10 @@ class CmsController &lt; MyProfileController
221 227  
222 228 def update_categories
223 229 @object = params[:id] ? @profile.articles.find(params[:id]) : Article.new
  230 + @categories = @toplevel_categories = environment.top_level_categories
224 231 if params[:category_id]
225 232 @current_category = Category.find(params[:category_id])
226 233 @categories = @current_category.children
227   - else
228   - @categories = environment.top_level_categories.select{|i| !i.children.empty?}
229 234 end
230 235 render :partial => 'shared/select_categories', :locals => {:object_name => 'article', :multiple => true}, :layout => false
231 236 end
... ...
app/controllers/my_profile/profile_design_controller.rb
... ... @@ -55,10 +55,4 @@ class ProfileDesignController &lt; BoxOrganizerController
55 55 blocks
56 56 end
57 57  
58   - def clone
59   - block = Block.find(params[:id])
60   - block.duplicate
61   - redirect_to :action => 'index'
62   - end
63   -
64 58 end
... ...
app/controllers/my_profile/profile_editor_controller.rb
... ... @@ -55,11 +55,10 @@ class ProfileEditorController &lt; MyProfileController
55 55  
56 56 def update_categories
57 57 @object = profile
  58 + @categories = @toplevel_categories = environment.top_level_categories
58 59 if params[:category_id]
59 60 @current_category = Category.find(params[:category_id])
60 61 @categories = @current_category.children
61   - else
62   - @categories = environment.top_level_categories.select{|i| !i.children.empty?}
63 62 end
64 63 render :partial => 'shared/select_categories', :locals => {:object_name => 'profile_data', :multiple => true}, :layout => false
65 64 end
... ...
app/controllers/my_profile/profile_members_controller.rb
... ... @@ -2,7 +2,7 @@ class ProfileMembersController &lt; MyProfileController
2 2 protect 'manage_memberships', :profile
3 3  
4 4 def index
5   - @members = profile.members
  5 + @members = profile.members_by_name
6 6 @member_role = environment.roles.find_by_name('member')
7 7 end
8 8  
... ...
app/controllers/my_profile/profile_themes_controller.rb 0 → 100644
... ... @@ -0,0 +1,75 @@
  1 +class ProfileThemesController < ThemesController
  2 +
  3 + needs_profile
  4 +
  5 + protect 'edit_appearance', :profile
  6 +
  7 + no_design_blocks
  8 +
  9 + def target
  10 + @target = profile
  11 + end
  12 +
  13 + def new
  14 + if !request.xhr?
  15 + id = params[:name] ? params[:name].to_slug : 'my-theme'
  16 + t = Theme.new(id, :name => params[:name], :owner => profile, :public => false)
  17 + t.save
  18 + redirect_to :action => 'index'
  19 + else
  20 + render :action => 'new', :layout => false
  21 + end
  22 + end
  23 +
  24 + def edit
  25 + @theme = profile.find_theme(params[:id])
  26 + @css_files = @theme.css_files
  27 + @image_files = @theme.image_files
  28 + end
  29 +
  30 + def add_css
  31 + @theme = profile.find_theme(params[:id])
  32 + if request.xhr?
  33 + render :action => 'add_css', :layout => false
  34 + else
  35 + @theme.add_css(params[:css])
  36 + redirect_to :action => 'edit', :id => @theme.id
  37 + end
  38 + end
  39 +
  40 + def css_editor
  41 + @theme = profile.find_theme(params[:id])
  42 + @css = params[:css]
  43 +
  44 + @code = @theme.read_css(@css)
  45 + render :action => 'css_editor', :layout => false
  46 + end
  47 +
  48 + post_only :update_css
  49 + def update_css
  50 + @theme = profile.find_theme(params[:id])
  51 + @theme.update_css(params[:css], params[:csscode])
  52 + redirect_to :action => 'edit', :id => @theme.id
  53 + end
  54 +
  55 + def add_image
  56 + @theme = profile.find_theme(params[:id])
  57 + if request.xhr?
  58 + render :action => 'add_image', :layout => false
  59 + else
  60 + @theme.add_image(params[:image].original_filename, params[:image].read)
  61 + redirect_to :action => 'edit', :id => @theme.id
  62 + end
  63 + end
  64 +
  65 + def start_test
  66 + session[:theme] = params[:id]
  67 + redirect_to :controller => 'content_viewer', :profile => profile.identifier, :action => 'view_page'
  68 + end
  69 +
  70 + def stop_test
  71 + session[:theme] = nil
  72 + redirect_to :action => 'index'
  73 + end
  74 +
  75 +end
... ...
app/controllers/my_profile/themes_controller.rb
... ... @@ -1,91 +0,0 @@
1   -class ThemesController < MyProfileController
2   -
3   - protect 'edit_appearance', :profile
4   - no_design_blocks
5   -
6   - def set
7   - profile.update_theme(params[:id])
8   - redirect_to :action => 'index'
9   - end
10   -
11   - def unset
12   - profile.update_theme(nil)
13   - redirect_to :action => 'index'
14   - end
15   -
16   - def index
17   - @themes = profile.environment.themes + Theme.approved_themes(profile)
18   - @current_theme = profile.theme
19   -
20   - @layout_templates = LayoutTemplate.all
21   - @current_template = profile.layout_template
22   - end
23   -
24   - def new
25   - if !request.xhr?
26   - id = params[:name] ? params[:name].to_slug : 'my-theme'
27   - t = Theme.new(id, :name => params[:name], :owner => profile, :public => false)
28   - t.save
29   - redirect_to :action => 'index'
30   - else
31   - render :action => 'new', :layout => false
32   - end
33   - end
34   -
35   - def edit
36   - @theme = profile.find_theme(params[:id])
37   - @css_files = @theme.css_files
38   - @image_files = @theme.image_files
39   - end
40   -
41   - def add_css
42   - @theme = profile.find_theme(params[:id])
43   - if request.xhr?
44   - render :action => 'add_css', :layout => false
45   - else
46   - @theme.add_css(params[:css])
47   - redirect_to :action => 'edit', :id => @theme.id
48   - end
49   - end
50   -
51   - def css_editor
52   - @theme = profile.find_theme(params[:id])
53   - @css = params[:css]
54   -
55   - @code = @theme.read_css(@css)
56   - render :action => 'css_editor', :layout => false
57   - end
58   -
59   - post_only :update_css
60   - def update_css
61   - @theme = profile.find_theme(params[:id])
62   - @theme.update_css(params[:css], params[:csscode])
63   - redirect_to :action => 'edit', :id => @theme.id
64   - end
65   -
66   - def add_image
67   - @theme = profile.find_theme(params[:id])
68   - if request.xhr?
69   - render :action => 'add_image', :layout => false
70   - else
71   - @theme.add_image(params[:image].original_filename, params[:image].read)
72   - redirect_to :action => 'edit', :id => @theme.id
73   - end
74   - end
75   -
76   - def start_test
77   - session[:theme] = params[:id]
78   - redirect_to :controller => 'content_viewer', :profile => profile.identifier, :action => 'view_page'
79   - end
80   -
81   - def stop_test
82   - session[:theme] = nil
83   - redirect_to :action => 'index'
84   - end
85   -
86   - def set_layout_template
87   - profile.update_layout_template(params[:id])
88   - redirect_to :action => 'index'
89   - end
90   -
91   -end
app/controllers/public/account_controller.rb
... ... @@ -69,6 +69,8 @@ class AccountController &lt; ApplicationController
69 69 session[:notice] = _("This environment doesn't allow user registration.")
70 70 end
71 71  
  72 + store_location(request.referer) unless params[:return_to] or session[:return_to]
  73 +
72 74 @block_bot = !!session[:may_be_a_bot]
73 75 @invitation_code = params[:invitation_code]
74 76 begin
... ... @@ -77,6 +79,7 @@ class AccountController &lt; ApplicationController
77 79 @user.environment = environment
78 80 @terms_of_use = environment.terms_of_use
79 81 @user.person_data = params[:profile_data]
  82 + @user.return_to = session[:return_to]
80 83 @person = Person.new(params[:profile_data])
81 84 @person.environment = @user.environment
82 85 if request.post?
... ... @@ -98,7 +101,7 @@ class AccountController &lt; ApplicationController
98 101 end
99 102 if @user.activated?
100 103 self.current_user = @user
101   - redirect_to '/'
  104 + go_to_signup_initial_page
102 105 else
103 106 @register_pending = true
104 107 end
... ... @@ -368,32 +371,29 @@ class AccountController &lt; ApplicationController
368 371 end
369 372  
370 373 def go_to_initial_page
  374 + if params[:redirection]
  375 + session[:return_to] = @user.return_to
  376 + @user.return_to = nil
  377 + @user.save
  378 + end
  379 +
371 380 if params[:return_to]
372 381 redirect_to params[:return_to]
373 382 elsif environment.enabled?('allow_change_of_redirection_after_login')
374   - case user.preferred_login_redirection
375   - when 'keep_on_same_page'
376   - redirect_back_or_default(user.admin_url)
377   - when 'site_homepage'
378   - redirect_to :controller => :home
379   - when 'user_profile_page'
380   - redirect_to user.public_profile_url
381   - when 'user_homepage'
382   - redirect_to user.url
383   - when 'user_control_panel'
384   - redirect_to user.admin_url
385   - else
386   - redirect_back_or_default(user.admin_url)
387   - end
  383 + check_redirection_options(user, user.preferred_login_redirection, user.admin_url)
388 384 else
389 385 if environment == current_user.environment
390   - redirect_back_or_default(user.admin_url)
  386 + check_redirection_options(user, environment.redirection_after_login, user.admin_url)
391 387 else
392 388 redirect_back_or_default(:controller => 'home')
393 389 end
394 390 end
395 391 end
396 392  
  393 + def go_to_signup_initial_page
  394 + check_redirection_options(user, user.environment.redirection_after_signup, user.url)
  395 + end
  396 +
397 397 def redirect_if_logged_in
398 398 if logged_in?
399 399 go_to_initial_page
... ... @@ -409,4 +409,22 @@ class AccountController &lt; ApplicationController
409 409 user
410 410 end
411 411  
  412 + protected
  413 +
  414 + def check_redirection_options(user, condition, default)
  415 + case condition
  416 + when 'keep_on_same_page'
  417 + redirect_back_or_default(user.admin_url)
  418 + when 'site_homepage'
  419 + redirect_to :controller => :home
  420 + when 'user_profile_page'
  421 + redirect_to user.public_profile_url
  422 + when 'user_homepage'
  423 + redirect_to user.url
  424 + when 'user_control_panel'
  425 + redirect_to user.admin_url
  426 + else
  427 + redirect_back_or_default(default)
  428 + end
  429 + end
412 430 end
... ...
app/controllers/public/comment_controller.rb
... ... @@ -71,7 +71,9 @@ class CommentController &lt; ApplicationController
71 71 return
72 72 end
73 73  
74   - @comment.save
  74 + if @comment.save
  75 + @plugins.dispatch(:process_extra_comment_params, [@comment,params])
  76 + end
75 77  
76 78 respond_to do |format|
77 79 format.js do
... ... @@ -113,6 +115,8 @@ class CommentController &lt; ApplicationController
113 115  
114 116 def update
115 117 if @comment.update_attributes(params[:comment])
  118 + @plugins.dispatch(:process_extra_comment_params, [@comment,params])
  119 +
116 120 respond_to do |format|
117 121 format.js do
118 122 comment_to_render = @comment.comment_root
... ...
app/controllers/public/content_viewer_controller.rb
... ... @@ -111,6 +111,15 @@ class ContentViewerController &lt; ApplicationController
111 111 @comments = @plugins.filter(:unavailable_comments, @comments)
112 112 @comments_count = @comments.count
113 113 @comments = @comments.without_reply.paginate(:per_page => per_page, :page => params[:comment_page] )
  114 + @comment_order = params[:comment_order].nil? ? 'oldest' : params[:comment_order]
  115 +
  116 + if request.xhr? and params[:comment_order]
  117 + if @comment_order == 'newest'
  118 + @comments = @comments.reverse
  119 + end
  120 +
  121 + return render :partial => 'comment/comment', :collection => @comments
  122 + end
114 123  
115 124 if params[:slideshow]
116 125 render :action => 'slideshow', :layout => 'slideshow'
... ...
app/controllers/public/events_controller.rb
... ... @@ -7,11 +7,11 @@ class EventsController &lt; PublicController
7 7 @date = build_date(params[:year], params[:month], params[:day])
8 8  
9 9 if !params[:year] && !params[:month] && !params[:day]
10   - @events = profile.events.next_events_from_month(@date)
  10 + @events = profile.events.next_events_from_month(@date).paginate(:per_page => per_page, :page => params[:page])
11 11 end
12 12  
13 13 if params[:year] || params[:month]
14   - @events = profile.events.by_month(@date)
  14 + @events = profile.events.by_month(@date).paginate(:per_page => per_page, :page => params[:page])
15 15 end
16 16  
17 17 events_in_range = profile.events.by_range((@date - 1.month).at_beginning_of_month .. (@date + 1.month).at_end_of_month)
... ... @@ -29,4 +29,7 @@ class EventsController &lt; PublicController
29 29  
30 30 include EventsHelper
31 31  
  32 + def per_page
  33 + 20
  34 + end
32 35 end
... ...
app/controllers/public/profile_controller.rb
... ... @@ -67,7 +67,7 @@ class ProfileController &lt; PublicController
67 67  
68 68 def members
69 69 if is_cache_expired?(profile.members_cache_key(params))
70   - @members = profile.members.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage])
  70 + @members = profile.members_by_name.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage])
71 71 end
72 72 end
73 73  
... ... @@ -304,14 +304,6 @@ class ProfileController &lt; PublicController
304 304 end
305 305 end
306 306  
307   - def profile_info
308   - begin
309   - @block = profile.blocks.find(params[:block_id])
310   - rescue
311   - render :text => _('Profile information could not be loaded')
312   - end
313   - end
314   -
315 307 def report_abuse
316 308 @abuse_report = AbuseReport.new
317 309 render :layout => false
... ...
app/controllers/public/search_controller.rb
... ... @@ -99,14 +99,14 @@ class SearchController &lt; PublicController
99 99 @events = []
100 100 if params[:day] || !params[:year] && !params[:month]
101 101 @events = @category ?
102   - environment.events.by_day(@date).in_category(Category.find(@category_id)) :
103   - environment.events.by_day(@date)
  102 + environment.events.by_day(@date).in_category(Category.find(@category_id)).paginate(:per_page => per_page, :page => params[:page]) :
  103 + environment.events.by_day(@date).paginate(:per_page => per_page, :page => params[:page])
104 104 end
105 105  
106 106 if params[:year] || params[:month]
107 107 @events = @category ?
108   - environment.events.by_month(@date).in_category(Category.find(@category_id)) :
109   - environment.events.by_month(@date)
  108 + environment.events.by_month(@date).in_category(Category.find(@category_id)).paginate(:per_page => per_page, :page => params[:page]) :
  109 + environment.events.by_month(@date).paginate(:per_page => per_page, :page => params[:page])
110 110 end
111 111  
112 112 @scope = date_range && params[:action] == 'events' ? environment.events.by_range(date_range) : environment.events
... ... @@ -139,7 +139,7 @@ class SearchController &lt; PublicController
139 139  
140 140 def events_by_day
141 141 @date = build_date(params[:year], params[:month], params[:day])
142   - @events = environment.events.by_day(@date)
  142 + @events = environment.events.by_day(@date).paginate(:per_page => per_page, :page => params[:page])
143 143 render :partial => 'events/events'
144 144 end
145 145  
... ... @@ -224,4 +224,8 @@ class SearchController &lt; PublicController
224 224 @environment.send(klass.name.underscore.pluralize).visible.includes(relations)
225 225 end
226 226  
  227 + def per_page
  228 + 20
  229 + end
  230 +
227 231 end
... ...
app/controllers/themes_controller.rb 0 → 100644
... ... @@ -0,0 +1,42 @@
  1 +class ThemesController < ApplicationController
  2 +
  3 + before_filter :login_required
  4 +
  5 + no_design_blocks
  6 +
  7 + # attr_reader :target
  8 +
  9 + def target
  10 + @target
  11 + end
  12 +
  13 + def index
  14 + @environment = environment
  15 + @themes = (environment.themes + Theme.approved_themes(target)).sort_by { |t| t.name }
  16 +
  17 + @current_theme = target.theme
  18 +
  19 + @layout_templates = LayoutTemplate.all
  20 + @current_template = target.layout_template
  21 + end
  22 +
  23 + def set
  24 + target.update_theme(params[:id])
  25 + redirect_to :action => 'index'
  26 + end
  27 +
  28 + def unset
  29 + if target.kind_of?(Environment)
  30 + target.update_theme('default')
  31 + else
  32 + target.update_theme(nil)
  33 + end
  34 + redirect_to :action => 'index'
  35 + end
  36 +
  37 + def set_layout_template
  38 + target.update_layout_template(params[:id])
  39 + redirect_to :action => 'index'
  40 + end
  41 +
  42 +end
... ...
app/helpers/application_helper.rb
... ... @@ -608,49 +608,18 @@ module ApplicationHelper
608 608 end
609 609  
610 610 attr_reader :environment
  611 +
611 612 def select_categories(object_name, title=nil, title_size=4)
612 613 return nil if environment.enabled?(:disable_categories)
613 614 if title.nil?
614 615 title = _('Categories')
615 616 end
616 617  
617   - object = instance_variable_get("@#{object_name}")
618   -
619   - result = content_tag 'h'+title_size.to_s(), title
620   - result << javascript_tag( 'function open_close_cat( link ) {
621   - var div = link.parentNode.getElementsByTagName("div")[0];
622   - var end = function(){
623   - if ( div.style.display == "none" ) {
624   - this.link.className="button icon-button icon-down"
625   - } else {
626   - this.link.className="button icon-button icon-up-red"
627   - }
628   - }
629   - Effect.toggle( div, "slide", { link:link, div:div, afterFinish:end } )
630   - }')
631   - environment.top_level_categories.select{|i| !i.children.empty?}.each do |toplevel|
632   - next unless object.accept_category?(toplevel)
633   - # FIXME
634   - ([toplevel] + toplevel.children_for_menu).each do |cat|
635   - if cat.top_level?
636   - result << '<div class="categorie_box">'.html_safe
637   - result << icon_button( :down, _('open'), '#', :onclick => 'open_close_cat(this); return false' )
638   - result << content_tag('h5', toplevel.name)
639   - result << '<div style="display:none"><ul class="categories">'.html_safe
640   - else
641   - checkbox_id = "#{object_name}_#{cat.full_name.downcase.gsub(/\s+|\//, '_')}"
642   - result << content_tag('li', labelled_check_box(
643   - cat.full_name_without_leading(1, " &rarr; "),
644   - "#{object_name}[category_ids][]", cat.id,
645   - object.category_ids.include?(cat.id), :id => checkbox_id,
646   - :onchange => 'this.parentNode.className=(this.checked?"cat_checked":"")' ),
647   - :class => ( object.category_ids.include?(cat.id) ? 'cat_checked' : '' ) ) + "\n"
648   - end
649   - end
650   - result << '</ul></div></div>'.html_safe
651   - end
  618 + @object = instance_variable_get("@#{object_name}")
  619 + @categories = environment.top_level_categories
652 620  
653   - content_tag('div', result)
  621 + @current_categories = environment.top_level_categories.select{|i| !i.children.empty?}
  622 + render :partial => 'shared/select_categories_top', :locals => {:object_name => object_name, :title => title, :title_size => title_size, :multiple => true, :categories_selected => @object.categories }, :layout => false
654 623 end
655 624  
656 625 def theme_option(opt = nil)
... ... @@ -920,12 +889,11 @@ module ApplicationHelper
920 889  
921 890 def page_title
922 891 (@page ? @page.title + ' - ' : '') +
923   - (profile ? profile.short_name + ' - ' : '') +
924 892 (@topic ? @topic.title + ' - ' : '') +
925 893 (@section ? @section.title + ' - ' : '') +
926 894 (@toc ? _('Online Manual') + ' - ' : '') +
927 895 (@controller.controller_name == 'chat' ? _('Chat') + ' - ' : '') +
928   - environment.name +
  896 + (profile ? profile.short_name : environment.name) +
929 897 (@category ? " - #{@category.full_name}" : '')
930 898 end
931 899  
... ... @@ -1382,16 +1350,16 @@ module ApplicationHelper
1382 1350 end
1383 1351  
1384 1352 def convert_macro(html, source)
1385   - doc = Nokogiri::HTML(html)
  1353 + doc = Hpricot(html)
1386 1354 #TODO This way is more efficient but do not support macro inside of
1387 1355 # macro. You must parse them from the inside-out in order to enable
1388 1356 # that.
1389   - doc.css('.macro').each do |macro|
  1357 + doc.search('.macro').each do |macro|
1390 1358 macro_name = macro['data-macro']
1391 1359 result = @plugins.parse_macro(macro_name, macro, source)
1392   - macro.content = result.kind_of?(Proc) ? self.instance_eval(&result) : result
  1360 + macro.inner_html = result.kind_of?(Proc) ? self.instance_eval(&result) : result
1393 1361 end
1394   - CGI.unescapeHTML(doc.xpath('//body/*').to_s)
  1362 + doc.html
1395 1363 end
1396 1364  
1397 1365 def default_folder_for_image_upload(profile)
... ...
app/helpers/article_helper.rb
... ... @@ -49,8 +49,14 @@ module ArticleHelper
49 49 'div',
50 50 check_box(:article, :display_versions) +
51 51 content_tag('label', _('I want this article to display a link to older versions'), :for => 'article_display_versions')
52   - ) : '')
  52 + ) : '') +
53 53  
  54 + (article.forum? && article.profile.community? ?
  55 + content_tag(
  56 + 'div',
  57 + check_box(:article, :allows_members_to_create_topics) +
  58 + content_tag('label', _('Allow members to create topics'), :for => 'article_allows_members_to_create_topics')
  59 + ) : '')
54 60 )
55 61 end
56 62  
... ...
app/helpers/boxes_helper.rb
... ... @@ -39,7 +39,7 @@ module BoxesHelper
39 39 end
40 40  
41 41 def display_boxes(holder, main_content)
42   - boxes = holder.boxes.first(holder.boxes_limit)
  42 + boxes = holder.boxes.with_position.first(holder.boxes_limit)
43 43 content = boxes.reverse.map { |item| display_box(item, main_content) }.join("\n")
44 44 content = main_content if (content.blank?)
45 45  
... ... @@ -65,7 +65,7 @@ module BoxesHelper
65 65 end
66 66  
67 67 def display_box_content(box, main_content)
68   - context = { :article => @page, :request_path => request.path, :locale => locale, :params => request.params }
  68 + context = { :article => @page, :request_path => request.path, :locale => locale, :params => request.params, :user => user }
69 69 box_decorator.select_blocks(box.blocks.includes(:box), context).map { |item| display_block(item, main_content) }.join("\n") + box_decorator.block_target(box)
70 70 end
71 71  
... ... @@ -212,7 +212,7 @@ module BoxesHelper
212 212  
213 213 if !block.main?
214 214 buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')})
215   - buttons << icon_button(:clone, _('Clone'), { :action => 'clone', :id => block.id }, { :method => 'post' })
  215 + buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' })
216 216 end
217 217  
218 218 if block.respond_to?(:help)
... ...
app/helpers/cache_counter_helper.rb 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +module CacheCounterHelper
  2 + def update_cache_counter(name, object, value)
  3 + if object.present?
  4 + object.class.update_counters(object.id, name => value)
  5 + end
  6 + end
  7 +end
... ...
app/helpers/categories_helper.rb
... ... @@ -48,4 +48,12 @@ module CategoriesHelper
48 48 labelled_form_field(_('Type of category'), select_tag('type', options_for_select(TYPES, value)))
49 49 end
50 50  
  51 + #FIXME make this test
  52 + def selected_category_link(cat)
  53 + content_tag('div', button_to_function_without_text(:remove, _('Remove'), nil) {|page| page["selected-category-#{cat.id}"].remove} +
  54 + link_to_function(cat.full_name(' &rarr; '), nil, :id => "remove-selected-category-#{cat.id}-button", :class => 'select-subcategory-link') {|page| page["selected-category-#{cat.id}"].remove},
  55 + :class => 'selected-category'
  56 + )
  57 + end
  58 +
51 59 end
... ...
app/helpers/comment_helper.rb
... ... @@ -2,7 +2,6 @@ module CommentHelper
2 2  
3 3 def article_title(article, args = {})
4 4 title = article.title
5   - title = article.display_title if article.kind_of?(UploadedFile) && article.image?
6 5 title = content_tag('h1', h(title), :class => 'title')
7 6 if article.belongs_to_blog?
8 7 unless args[:no_link]
... ... @@ -22,6 +21,12 @@ module CommentHelper
22 21 title
23 22 end
24 23  
  24 + def comment_extra_contents(comment)
  25 + @plugins.dispatch(:comment_extra_contents, comment).collect do |extra_content|
  26 + extra_content.kind_of?(Proc) ? self.instance_eval(&extra_content) : extra_content
  27 + end.join('\n')
  28 + end
  29 +
25 30 def comment_actions(comment)
26 31 url = url_for(:profile => profile.identifier, :controller => :comment, :action => :check_actions, :id => comment.id)
27 32 links = links_for_comment_actions(comment)
... ...
app/helpers/content_viewer_helper.rb
... ... @@ -14,8 +14,7 @@ module ContentViewerHelper
14 14 end
15 15  
16 16 def article_title(article, args = {})
17   - title = article.display_title if article.kind_of?(UploadedFile) && article.image?
18   - title = article.title if title.blank?
  17 + title = article.title
19 18 title = content_tag('h1', h(title), :class => 'title')
20 19 if article.belongs_to_blog? || article.belongs_to_forum?
21 20 unless args[:no_link]
... ... @@ -52,15 +51,6 @@ module ContentViewerHelper
52 51 end
53 52 end
54 53  
55   - def addthis_facebook_url(article)
56   - "http://www.facebook.com/sharer.php?s=100&p[title]=%{title}&p[summary]=%{summary}&p[url]=%{url}&p[images][0]=%{image}" % {
57   - :title => CGI.escape(article.title),
58   - :url => CGI.escape(url_for(article.url)),
59   - :summary => CGI.escape(truncate(strip_tags(article.body.to_s), :length => 300)),
60   - :image => CGI.escape(article.body_images_paths.first.to_s)
61   - }
62   - end
63   -
64 54 def addthis_image_tag
65 55 if File.exists?(File.join(Rails.root, 'public', theme_path, 'images', 'addthis.gif'))
66 56 image_tag(File.join(theme_path, 'images', 'addthis.gif'), :border => 0, :alt => '')
... ...
app/helpers/layout_helper.rb
... ... @@ -90,5 +90,8 @@ module LayoutHelper
90 90 end
91 91 end
92 92  
  93 + def meta_description_tag(article=nil)
  94 + article ? truncate(strip_tags(article.body.to_s), :length => 200) : environment.name
  95 + end
93 96 end
94 97  
... ...
app/helpers/macros_helper.rb
... ... @@ -20,14 +20,16 @@ module MacrosHelper
20 20 jQuery('<div>'+#{macro_configuration_dialog(macro).to_json}+'</div>').dialog({
21 21 title: #{macro_title(macro).to_json},
22 22 modal: true,
23   - buttons: [
24   - {text: #{_('Ok').to_json}, click: function(){
  23 + buttons: {
  24 + #{_('Ok').to_json}: function(){
25 25 tinyMCE.activeEditor.execCommand('mceInsertContent', false,
26 26 (function(dialog){ #{macro_generator(macro)} })(this));
27 27 jQuery(this).dialog('close');
28   - }},
29   - {text: #{_('Cancel').to_json}, click: function(){jQuery(this).dialog('close');}}
30   - ]
  28 + },
  29 + #{_('Cancel').to_json}: function(){
  30 + jQuery(this).dialog('close');
  31 + }
  32 + }
31 33 });
32 34 }"
33 35 end
... ... @@ -57,7 +59,11 @@ module MacrosHelper
57 59  
58 60 def macro_generator(macro)
59 61 if macro.configuration[:generator]
60   - macro.configuration[:generator]
  62 + if macro.configuration[:generator].respond_to?(:call)
  63 + macro.configuration[:generator].call(macro)
  64 + else
  65 + macro.configuration[:generator]
  66 + end
61 67 else
62 68 macro_default_generator(macro)
63 69 end
... ... @@ -66,8 +72,7 @@ module MacrosHelper
66 72  
67 73 def macro_default_generator(macro)
68 74 code = "var params = {};"
69   - configuration = macro_configuration(macro)
70   - configuration[:params].map do |field|
  75 + macro.configuration[:params].map do |field|
71 76 code += "params.#{field[:name]} = jQuery('*[name=#{field[:name]}]', dialog).val();"
72 77 end
73 78 code + "
... ...
app/helpers/person_notifier_helper.rb 0 → 100644
... ... @@ -0,0 +1,15 @@
  1 +module PersonNotifierHelper
  2 +
  3 + include ApplicationHelper
  4 +
  5 + private
  6 +
  7 + def path_to_image(source)
  8 + top_url + source
  9 + end
  10 +
  11 + def top_url
  12 + top_url = @profile.environment ? @profile.environment.top_url : ''
  13 + end
  14 +
  15 +end
... ...
app/helpers/token_helper.rb
... ... @@ -27,7 +27,7 @@ module TokenHelper
27 27 hintText: #{options[:hint_text].to_json},
28 28 noResultsText: #{options[:no_results_text].to_json},
29 29 searchingText: #{options[:searching_text].to_json},
30   - searchDelay: #{options[:serach_delay].to_json},
  30 + searchDelay: #{options[:search_delay].to_json},
31 31 preventDuplicates: #{options[:prevent_duplicates].to_json},
32 32 backspaceDeleteItem: #{options[:backspace_delete_item].to_json},
33 33 queryParam: #{name.to_json},
... ...
app/models/block.rb
... ... @@ -22,11 +22,13 @@ class Block &lt; ActiveRecord::Base
22 22 #
23 23 # * <tt>:article</tt>: the article being viewed currently
24 24 # * <tt>:language</tt>: in which language the block will be displayed
  25 + # * <tt>:user</tt>: the logged user
25 26 def visible?(context = nil)
26 27 return false if display == 'never'
27 28  
28 29 if context
29 30 return false if language != 'all' && language != context[:locale]
  31 + return false unless display_to_user?(context[:user])
30 32  
31 33 begin
32 34 return self.send("display_#{display}", context)
... ... @@ -38,6 +40,10 @@ class Block &lt; ActiveRecord::Base
38 40 true
39 41 end
40 42  
  43 + def display_to_user?(user)
  44 + display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged')
  45 + end
  46 +
41 47 def display_always(context)
42 48 true
43 49 end
... ... @@ -68,6 +74,14 @@ class Block &lt; ActiveRecord::Base
68 74 # the homepage of its owner.
69 75 settings_items :display, :type => :string, :default => 'always'
70 76  
  77 +
  78 + # The condition for displaying a block to users. It can assume the following values:
  79 + #
  80 + # * <tt>'all'</tt>: the block is always displayed
  81 + # * <tt>'logged'</tt>: the block is displayed to logged users only
  82 + # * <tt>'not_logged'</tt>: the block is displayed only to not logged users
  83 + settings_items :display_user, :type => :string, :default => 'all'
  84 +
71 85 # The block can be configured to be displayed in all languages or in just one language. It can assume any locale of the environment:
72 86 #
73 87 # * <tt>'all'</tt>: the block is always displayed
... ... @@ -141,7 +155,7 @@ class Block &lt; ActiveRecord::Base
141 155 end
142 156  
143 157 alias :active_record_cache_key :cache_key
144   - def cache_key(language='en')
  158 + def cache_key(language='en', user=nil)
145 159 active_record_cache_key+'-'+language
146 160 end
147 161  
... ... @@ -171,12 +185,20 @@ class Block &lt; ActiveRecord::Base
171 185 'never' => __('Don\'t display'),
172 186 }
173 187  
174   - def display_options
  188 + def display_options_available
175 189 DISPLAY_OPTIONS.keys
176 190 end
177 191  
178   - def display_option_label(option)
179   - DISPLAY_OPTIONS[option]
  192 + def display_options
  193 + DISPLAY_OPTIONS.slice(*display_options_available)
  194 + end
  195 +
  196 + def display_user_options
  197 + @display_user_options ||= {
  198 + 'all' => __('All users'),
  199 + 'logged' => __('Logged'),
  200 + 'not_logged' => __('Not logged'),
  201 + }
180 202 end
181 203  
182 204 def duplicate
... ...
app/models/box.rb
... ... @@ -5,12 +5,14 @@ class Box &lt; ActiveRecord::Base
5 5  
6 6 include Noosfero::Plugin::HotSpot
7 7  
  8 + named_scope :with_position, :conditions => ['boxes.position > 0']
  9 +
8 10 def environment
9 11 owner ? (owner.kind_of?(Environment) ? owner : owner.environment) : nil
10 12 end
11 13  
12 14 def acceptable_blocks
13   - blocks_classes = central? ? Box.acceptable_center_blocks + plugins.dispatch(:extra_blocks, :position => 1) : Box.acceptable_side_blocks + plugins.dispatch(:extra_blocks, :position => [2, 3])
  15 + blocks_classes = central? ? Box.acceptable_center_blocks + plugins.dispatch(:extra_blocks, :type => owner.class, :position => 1) : Box.acceptable_side_blocks + plugins.dispatch(:extra_blocks, :type => owner.class, :position => [2, 3])
14 16 to_css_class_name(blocks_classes)
15 17 end
16 18  
... ... @@ -24,6 +26,8 @@ class Box &lt; ActiveRecord::Base
24 26 CategoriesBlock,
25 27 CommunitiesBlock,
26 28 EnterprisesBlock,
  29 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  30 + # the Noosfero core soon, see ActionItem3045
27 31 EnvironmentStatisticsBlock,
28 32 FansBlock,
29 33 FavoriteEnterprisesBlock,
... ... @@ -50,6 +54,8 @@ class Box &lt; ActiveRecord::Base
50 54 CommunitiesBlock,
51 55 DisabledEnterpriseMessageBlock,
52 56 EnterprisesBlock,
  57 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  58 + # the Noosfero core soon, see ActionItem3045
53 59 EnvironmentStatisticsBlock,
54 60 FansBlock,
55 61 FavoriteEnterprisesBlock,
... ...
app/models/comment.rb
... ... @@ -172,7 +172,7 @@ class Comment &lt; ActiveRecord::Base
172 172 def mail(comment)
173 173 profile = comment.article.profile
174 174 recipients comment.notification_emails
175   - from "#{profile.environment.name} <#{profile.environment.contact_email}>"
  175 + from "#{profile.environment.name} <#{profile.environment.noreply_email}>"
176 176 subject _("[%s] you got a new comment!") % [profile.environment.name]
177 177 body :recipient => profile.nickname || profile.name,
178 178 :sender => comment.author_name,
... ... @@ -187,7 +187,7 @@ class Comment &lt; ActiveRecord::Base
187 187 def mail_to_followers(comment, emails)
188 188 profile = comment.article.profile
189 189 bcc emails
190   - from "#{profile.environment.name} <#{profile.environment.contact_email}>"
  190 + from "#{profile.environment.name} <#{profile.environment.noreply_email}>"
191 191 subject _("[%s] %s commented on a content of %s") % [profile.environment.name, comment.author_name, profile.short_name]
192 192 body :recipient => profile.nickname || profile.name,
193 193 :sender => comment.author_name,
... ...
app/models/contact.rb
... ... @@ -26,7 +26,7 @@ class Contact &lt; ActiveRecord::Base #WithoutTable
26 26 content_type 'text/html'
27 27 emails = contact.dest.notification_emails
28 28 recipients emails
29   - from "#{contact.name} <#{contact.dest.environment.contact_email}>"
  29 + from "#{contact.name} <#{contact.dest.environment.noreply_email}>"
30 30 reply_to contact.email
31 31 if contact.sender
32 32 headers 'X-Noosfero-Sender' => contact.sender.identifier
... ...
app/models/environment.rb
... ... @@ -26,7 +26,8 @@ class Environment &lt; ActiveRecord::Base
26 26 'manage_environment_users' => N_('Manage environment users'),
27 27 'manage_environment_templates' => N_('Manage environment templates'),
28 28 'manage_environment_licenses' => N_('Manage environment licenses'),
29   - 'manage_environment_trusted_sites' => N_('Manage environment trusted sites')
  29 + 'manage_environment_trusted_sites' => N_('Manage environment trusted sites'),
  30 + 'edit_appearance' => N_('Edit appearance'),
30 31 }
31 32  
32 33 module Roles
... ... @@ -144,6 +145,18 @@ class Environment &lt; ActiveRecord::Base
144 145 end
145 146 validates_inclusion_of :redirection_after_login, :in => Environment.login_redirection_options.keys, :allow_nil => true
146 147  
  148 + def self.signup_redirection_options
  149 + {
  150 + 'keep_on_same_page' => _('Stays on the same page the user was before signup.'),
  151 + 'site_homepage' => _('Redirects the user to the environment homepage.'),
  152 + 'user_profile_page' => _('Redirects the user to his profile page.'),
  153 + 'user_homepage' => _('Redirects the user to his homepage.'),
  154 + 'user_control_panel' => _('Redirects the user to his control panel.')
  155 + }
  156 + end
  157 + validates_inclusion_of :redirection_after_signup, :in => Environment.signup_redirection_options.keys, :allow_nil => true
  158 +
  159 +
147 160 # #################################################
148 161 # Relationships and applied behaviour
149 162 # #################################################
... ... @@ -160,6 +173,8 @@ class Environment &lt; ActiveRecord::Base
160 173  
161 174 # "left" area
162 175 env.boxes[1].blocks << LoginBlock.new
  176 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  177 + # the Noosfero core soon, see ActionItem3045
163 178 env.boxes[1].blocks << EnvironmentStatisticsBlock.new
164 179 env.boxes[1].blocks << RecentDocumentsBlock.new
165 180  
... ... @@ -185,7 +200,7 @@ class Environment &lt; ActiveRecord::Base
185 200 has_many :product_categories, :conditions => { :type => 'ProductCategory'}
186 201 has_many :regions
187 202  
188   - has_many :roles
  203 + has_many :roles, :dependent => :destroy
189 204  
190 205 has_many :qualifiers
191 206 has_many :certifiers
... ... @@ -591,7 +606,7 @@ class Environment &lt; ActiveRecord::Base
591 606 # only one environment can be the default one
592 607 validates_uniqueness_of :is_default, :if => (lambda do |environment| environment.is_default? end), :message => N_('Only one Virtual Community can be the default one')
593 608  
594   - validates_format_of :contact_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda { |record| ! record.contact_email.blank? })
  609 + validates_format_of :contact_email, :noreply_email, :with => Noosfero::Constants::EMAIL_FORMAT, :allow_blank => true
595 610  
596 611 xss_terminate :only => [ :message_for_disabled_enterprise ], :with => 'white_list', :on => 'validation'
597 612  
... ... @@ -677,6 +692,16 @@ class Environment &lt; ActiveRecord::Base
677 692 end
678 693 end
679 694  
  695 + def update_theme(theme)
  696 + self.theme = theme
  697 + self.save!
  698 + end
  699 +
  700 + def update_layout_template(template)
  701 + self.layout_template = template
  702 + self.save!
  703 + end
  704 +
680 705 before_create do |env|
681 706 env.settings[:themes] ||= %w[
682 707 aluminium
... ... @@ -768,7 +793,7 @@ class Environment &lt; ActiveRecord::Base
768 793 end
769 794  
770 795 def notification_emails
771   - [contact_email.blank? ? nil : contact_email].compact + admins.map(&:email)
  796 + [noreply_email.blank? ? nil : noreply_email].compact + admins.map(&:email)
772 797 end
773 798  
774 799 after_create :create_templates
... ...
app/models/environment_statistics_block.rb
  1 +# TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  2 +# the Noosfero core soon, see ActionItem3045
  3 +
1 4 class EnvironmentStatisticsBlock < Block
2 5  
3 6 def self.description
4   - _('Environment stastistics')
  7 + _('Environment stastistics (DEPRECATED)')
5 8 end
6 9  
7 10 def default_title
... ...
app/models/event.rb
... ... @@ -38,15 +38,12 @@ class Event &lt; Article
38 38 named_scope :next_events_from_month, lambda { |date|
39 39 date_temp = date.strftime("%Y-%m-%d")
40 40 { :conditions => ["start_date >= ?","#{date_temp}"],
41   - :limit => 10,
42 41 :order => 'start_date ASC'
43 42 }
44 43 }
45 44  
46 45 named_scope :by_month, lambda { |date|
47   - date_temp = date.strftime("%Y-%m")
48 46 { :conditions => ["EXTRACT(YEAR FROM start_date) = ? AND EXTRACT(MONTH FROM start_date) = ?",date.year,date.month],
49   - :limit => 10,
50 47 :order => 'start_date ASC'
51 48 }
52 49 }
... ...
app/models/forum.rb
... ... @@ -5,6 +5,7 @@ class Forum &lt; Folder
5 5  
6 6 settings_items :terms_of_use, :type => :string, :default => ""
7 7 settings_items :has_terms_of_use, :type => :boolean, :default => false
  8 + settings_items :allows_members_to_create_topics, :type => :boolean, :default => false
8 9 has_and_belongs_to_many :users_with_agreement, :class_name => 'Person', :join_table => 'terms_forum_people'
9 10  
10 11 before_save do |forum|
... ... @@ -66,4 +67,11 @@ class Forum &lt; Folder
66 67 self.users_with_agreement.exists? user
67 68 end
68 69  
  70 + def can_create_topic?(user, profile)
  71 + return profile.community? && profile.members.include?(user) && self.allows_members_to_create_topics
  72 + end
  73 +
  74 + def allow_create?(user)
  75 + super || can_create_topic?(user, profile)
  76 + end
69 77 end
... ...
app/models/friendship.rb
1 1 class Friendship < ActiveRecord::Base
2 2 track_actions :new_friendship, :after_create, :keep_params => ["friend.name", "friend.url", "friend.profile_custom_icon"], :custom_user => :person
3   -
  3 +
  4 + extend CacheCounterHelper
  5 +
4 6 belongs_to :person, :foreign_key => :person_id
5 7 belongs_to :friend, :class_name => 'Person', :foreign_key => 'friend_id'
  8 +
  9 + after_create do |friendship|
  10 + update_cache_counter(:friends_count, friendship.person, 1)
  11 + update_cache_counter(:friends_count, friendship.friend, 1)
  12 + end
  13 +
  14 + after_destroy do |friendship|
  15 + update_cache_counter(:friends_count, friendship.person, -1)
  16 + update_cache_counter(:friends_count, friendship.friend, -1)
  17 + end
6 18 end
... ...
app/models/layout_template.rb
... ... @@ -16,15 +16,15 @@ class LayoutTemplate
16 16 end
17 17  
18 18 def name
19   - @config['name']
  19 + _ @config['name']
20 20 end
21 21  
22 22 def title
23   - @config['title']
  23 + _ @config['title']
24 24 end
25 25  
26 26 def description
27   - @config['description']
  27 + _ @config['description']
28 28 end
29 29  
30 30 def number_of_boxes
... ...
app/models/link_list_block.rb
... ... @@ -63,13 +63,15 @@ class LinkListBlock &lt; Block
63 63 def link_html(link)
64 64 klass = 'icon-' + link[:icon] if link[:icon]
65 65 sanitize_link(
66   - link_to(link[:name], expand_address(link[:address]), :target => link[:target], :class => klass)
  66 + link_to(link[:name], expand_address(link[:address]), :target => link[:target], :class => klass, :title => link[:title])
67 67 )
68 68 end
69 69  
70 70 def expand_address(address)
71 71 add = if owner.respond_to?(:identifier)
72 72 address.gsub('{profile}', owner.identifier)
  73 + elsif owner.is_a?(Environment) && owner.enabled?('use_portal_community') && owner.portal_community
  74 + address.gsub('{portal}', owner.portal_community.identifier)
73 75 else
74 76 address
75 77 end
... ...
app/models/mailing.rb
... ... @@ -17,7 +17,7 @@ class Mailing &lt; ActiveRecord::Base
17 17 end
18 18  
19 19 def generate_from
20   - "#{source.name} <#{source.contact_email}>"
  20 + "#{source.name} <#{if source.is_a? Environment then source.noreply_email else source.contact_email end}>"
21 21 end
22 22  
23 23 def generate_subject
... ...
app/models/main_block.rb
... ... @@ -24,7 +24,7 @@ class MainBlock &lt; Block
24 24 false
25 25 end
26 26  
27   - def display_options
  27 + def display_options_available
28 28 ['always', 'except_home_page']
29 29 end
30 30  
... ...
app/models/members_block.rb
... ... @@ -36,4 +36,15 @@ class MembersBlock &lt; ProfileListBlock
36 36 }
37 37 end
38 38  
  39 + def cache_key(language='en', user=nil)
  40 + logged = ''
  41 + if user
  42 + logged += '-logged-in'
  43 + if user.is_member_of? self.owner
  44 + logged += '-member'
  45 + end
  46 + end
  47 + super + logged
  48 + end
  49 +
39 50 end
... ...
app/models/organization.rb
... ... @@ -26,18 +26,7 @@ class Organization &lt; Profile
26 26  
27 27 has_many :mailings, :class_name => 'OrganizationMailing', :foreign_key => :source_id, :as => 'source'
28 28  
29   - named_scope :more_popular,
30   - :select => "#{Profile.qualified_column_names}, count(resource_id) as total",
31   - :group => Profile.qualified_column_names,
32   - :joins => "LEFT OUTER JOIN role_assignments ON profiles.id = role_assignments.resource_id",
33   - :order => "total DESC"
34   -
35   - named_scope :more_active,
36   - :select => "#{Profile.qualified_column_names}, count(action_tracker.id) as total",
37   - :joins => "LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.target_id",
38   - :group => Profile.qualified_column_names,
39   - :order => 'total DESC',
40   - :conditions => ['action_tracker.created_at >= ? OR action_tracker.id IS NULL', ActionTracker::Record::RECENT_DELAY.days.ago]
  29 + named_scope :more_popular, :order => 'members_count DESC'
41 30  
42 31 def validation_methodology
43 32 self.validation_info ? self.validation_info.validation_methodology : nil
... ...
app/models/organization_mailing.rb
1 1 class OrganizationMailing < Mailing
2 2  
3 3 def generate_from
4   - "#{person.name} <#{source.environment.contact_email}>"
  4 + "#{person.name} <#{source.environment.noreply_email}>"
5 5 end
6 6  
7 7 def recipients(offset=0, limit=100)
... ...
app/models/pending_task_notifier.rb
... ... @@ -2,7 +2,7 @@ class PendingTaskNotifier &lt; ActionMailer::Base
2 2  
3 3 def notification(person)
4 4 recipients person.email
5   - from "#{person.environment.name} <#{person.environment.contact_email}>"
  5 + from "#{person.environment.name} <#{person.environment.noreply_email}>"
6 6 subject _("[%s] Pending tasks") % person.environment.name
7 7 body :person => person,
8 8 :tasks => person.tasks.pending,
... ...
app/models/person.rb
... ... @@ -71,18 +71,7 @@ class Person &lt; Profile
71 71 has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people'
72 72 has_and_belongs_to_many :articles_with_access, :class_name => 'Article', :join_table => 'article_privacy_exceptions'
73 73  
74   - named_scope :more_popular,
75   - :select => "#{Profile.qualified_column_names}, count(friend_id) as total",
76   - :group => Profile.qualified_column_names,
77   - :joins => "LEFT OUTER JOIN friendships on profiles.id = friendships.person_id",
78   - :order => "total DESC"
79   -
80   - named_scope :more_active,
81   - :select => "#{Profile.qualified_column_names}, count(action_tracker.id) as total",
82   - :joins => "LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.user_id",
83   - :group => Profile.qualified_column_names,
84   - :order => 'total DESC',
85   - :conditions => ['action_tracker.created_at >= ? OR action_tracker.id IS NULL', ActionTracker::Record::RECENT_DELAY.days.ago]
  74 + named_scope :more_popular, :order => 'friends_count DESC'
86 75  
87 76 named_scope :abusers, :joins => :abuse_complaints, :conditions => ['tasks.status = 3'], :select => 'DISTINCT profiles.*'
88 77 named_scope :non_abusers, :joins => "LEFT JOIN tasks ON profiles.id = tasks.requestor_id AND tasks.type='AbuseComplaint'", :conditions => ["tasks.status != 3 OR tasks.id is NULL"], :select => "DISTINCT profiles.*"
... ... @@ -501,6 +490,17 @@ class Person &lt; Profile
501 490 gravatar_profile_image_url(self.email, :size=>20, :d => gravatar_default)
502 491 end
503 492  
  493 + settings_items :last_notification, :type => DateTime
  494 + settings_items :notification_time, :type => :integer, :default => 0
  495 +
  496 + def notifier
  497 + @notifier ||= PersonNotifier.new(self)
  498 + end
  499 +
  500 + after_update do |person|
  501 + person.notifier.reschedule_next_notification_mail
  502 + end
  503 +
504 504 protected
505 505  
506 506 def followed_by?(profile)
... ...
app/models/person_notifier.rb 0 → 100644
... ... @@ -0,0 +1,89 @@
  1 +class PersonNotifier
  2 +
  3 + def initialize(person)
  4 + @person = person
  5 + end
  6 +
  7 + def self.schedule_all_next_notification_mail
  8 + Delayed::Job.enqueue(NotifyAllJob.new) unless NotifyAllJob.exists?
  9 + end
  10 +
  11 + def schedule_next_notification_mail
  12 + dispatch_notification_mail if !NotifyJob.exists?(@person.id)
  13 + end
  14 +
  15 + def dispatch_notification_mail
  16 + Delayed::Job.enqueue(NotifyJob.new(@person.id), nil, @person.notification_time.hours.from_now) if @person.notification_time>0
  17 + end
  18 +
  19 + def reschedule_next_notification_mail
  20 + return nil unless @person.setting_changed?(:notification_time) || @person.setting_changed?(:last_notification)
  21 + NotifyJob.find(@person.id).delete_all
  22 + schedule_next_notification_mail
  23 + end
  24 +
  25 + def notify
  26 + if @person.notification_time && @person.notification_time > 0
  27 + from = @person.last_notification || DateTime.now - @person.notification_time.hours
  28 + notifications = @person.tracked_notifications.find(:all, :conditions => ["created_at > ?", from])
  29 + Noosfero.with_locale @person.environment.default_language do
  30 + Mailer::deliver_content_summary(@person, notifications) unless notifications.empty?
  31 + end
  32 + @person.settings[:last_notification] = DateTime.now
  33 + @person.save!
  34 + end
  35 + end
  36 +
  37 + class NotifyAllJob
  38 + def self.exists?
  39 + Delayed::Job.where(:handler => "--- !ruby/object:PersonNotifier::NotifyAllJob {}\n\n").count > 0
  40 + end
  41 +
  42 + def perform
  43 + Person.find_each {|person| person.notifier.schedule_next_notification_mail }
  44 + end
  45 + end
  46 +
  47 + class NotifyJob < Struct.new(:person_id)
  48 +
  49 + def self.exists?(person_id)
  50 + !find(person_id).empty?
  51 + end
  52 +
  53 + def self.find(person_id)
  54 + Delayed::Job.where(:handler => "--- !ruby/struct:PersonNotifier::NotifyJob \nperson_id: #{person_id}\n")
  55 + end
  56 +
  57 + def perform
  58 + Person.find(person_id).notifier.notify
  59 + end
  60 +
  61 + def on_permanent_failure
  62 + person = Person.find(person_id)
  63 + person.notifier.dispatch_notification_mail
  64 + end
  65 +
  66 + end
  67 +
  68 + class Mailer < ActionMailer::Base
  69 +
  70 + add_template_helper(PersonNotifierHelper)
  71 +
  72 + def session
  73 + {:theme => nil}
  74 + end
  75 +
  76 + def content_summary(person, notifications)
  77 + @current_theme = 'default'
  78 + @profile = person
  79 + recipients person.email
  80 + from "#{@profile.environment.name} <#{@profile.environment.contact_email}>"
  81 + subject _("[%s] Network Activity") % [@profile.environment.name]
  82 + body :recipient => @profile.nickname || @profile.name,
  83 + :environment => @profile.environment.name,
  84 + :url => @profile.environment.top_url,
  85 + :notifications => notifications
  86 + content_type "text/html"
  87 + end
  88 + end
  89 +end
... ...
app/models/profile.rb
... ... @@ -88,8 +88,8 @@ class Profile &lt; ActiveRecord::Base
88 88 ScopeTool.union *scopes
89 89 end
90 90  
91   - def members_count
92   - members.count
  91 + def members_by_name
  92 + members.order(:name)
93 93 end
94 94  
95 95 class << self
... ... @@ -114,10 +114,11 @@ class Profile &lt; ActiveRecord::Base
114 114  
115 115 named_scope :visible, :conditions => { :visible => true }
116 116 named_scope :public, :conditions => { :visible => true, :public_profile => true }
117   - # Subclasses must override these methods
  117 +
  118 + # Subclasses must override this method
118 119 named_scope :more_popular
119   - named_scope :more_active
120 120  
  121 + named_scope :more_active, :order => 'activities_count DESC'
121 122 named_scope :more_recent, :order => "created_at DESC"
122 123  
123 124 acts_as_trackable :dependent => :destroy
... ... @@ -612,10 +613,10 @@ private :generate_url, :url_options
612 613 # Adds a person as member of this Profile.
613 614 def add_member(person)
614 615 if self.has_members?
615   - if self.closed? && members_count > 0
  616 + if self.closed? && members.count > 0
616 617 AddMember.create!(:person => person, :organization => self) unless self.already_request_membership?(person)
617 618 else
618   - self.affiliate(person, Profile::Roles.admin(environment.id)) if members_count == 0
  619 + self.affiliate(person, Profile::Roles.admin(environment.id)) if members.count == 0
619 620 self.affiliate(person, Profile::Roles.member(environment.id))
620 621 end
621 622 else
... ...
app/models/scrap.rb
... ... @@ -14,7 +14,7 @@ class Scrap &lt; ActiveRecord::Base
14 14  
15 15 named_scope :not_replies, :conditions => {:scrap_id => nil}
16 16  
17   - track_actions :leave_scrap, :after_create, :keep_params => ['sender.name', 'content', 'receiver.name', 'receiver.url'], :if => Proc.new{|s| s.sender != s.receiver && s.sender != s.top_root.receiver}, :custom_target => :action_tracker_target
  17 + track_actions :leave_scrap, :after_create, :keep_params => ['sender.name', 'content', 'receiver.name', 'receiver.url'], :if => Proc.new{|s| s.sender != s.receiver && s.sender != s.top_root.receiver}, :custom_target => :action_tracker_target
18 18  
19 19 track_actions :leave_scrap_to_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.sender == s.receiver}
20 20  
... ... @@ -59,7 +59,7 @@ class Scrap &lt; ActiveRecord::Base
59 59 sender, receiver = scrap.sender, scrap.receiver
60 60 recipients receiver.email
61 61  
62   - from "#{sender.environment.name} <#{sender.environment.contact_email}>"
  62 + from "#{sender.environment.name} <#{sender.environment.noreply_email}>"
63 63 subject _("[%s] You received a scrap!") % [sender.environment.name]
64 64 body :recipient => receiver.name,
65 65 :sender => sender.name,
... ...
app/models/task_mailer.rb
... ... @@ -60,7 +60,7 @@ class TaskMailer &lt; ActionMailer::Base
60 60 end
61 61  
62 62 def self.generate_from(task)
63   - "#{task.environment.name} <#{task.environment.contact_email}>"
  63 + "#{task.environment.name} <#{task.environment.noreply_email}>"
64 64 end
65 65  
66 66 def generate_environment_url(task, url = {})
... ...
app/models/theme.rb
... ... @@ -42,17 +42,25 @@ class Theme
42 42 end
43 43  
44 44 def approved_themes(owner)
45   - Dir.glob(File.join(system_themes_dir, '*')).select do |item|
46   - if File.exists?( File.join(item, 'theme.yml') )
47   - config = YAML.load_file(File.join(item, 'theme.yml'))
48   - (config['owner_type'] == owner.class.base_class.name) &&
49   - (config['owner_id'] == owner.id) || config['public']
  45 + Dir.glob(File.join(system_themes_dir, '*')).map do |item|
  46 + next unless File.exists? File.join(item, 'theme.yml')
  47 + id = File.basename item
  48 + config = YAML.load_file File.join(item, 'theme.yml')
  49 +
  50 + approved = config['public']
  51 + unless approved
  52 + begin
  53 + approved = owner.kind_of?(config['owner_type'].constantize)
  54 + rescue
  55 + end
  56 + approved &&= config['owner_id'] == owner.id if config['owner_id'].present?
50 57 end
51   - end.map do |desc|
52   - new(File.basename(desc))
  58 +
  59 + [id, config] if approved
  60 + end.compact.map do |id, config|
  61 + new id, config
53 62 end
54 63 end
55   -
56 64 end
57 65  
58 66 class DuplicatedIdentifier < Exception; end
... ...
app/models/uploaded_file.rb
... ... @@ -12,15 +12,12 @@ class UploadedFile &lt; Article
12 12  
13 13 include ShortFilename
14 14  
15   - settings_items :title, :type => 'string'
16   - xss_terminate :only => [ :title ]
17   -
18   - def title_with_default
19   - title_without_default || short_filename(name, 60)
  15 + def title
  16 + if self.name.present? then self.name else self.filename end
  17 + end
  18 + def title= value
  19 + self.name = value
20 20 end
21   - alias_method_chain :title, :default
22   -
23   - validates_size_of :title, :maximum => 60, :if => (lambda { |file| !file.title.blank? })
24 21  
25 22 sanitize_filename
26 23  
... ... @@ -32,10 +29,6 @@ class UploadedFile &lt; Article
32 29 self.image? ? self.full_filename(:display).gsub(File.join(RAILS_ROOT, 'public'), '') : nil
33 30 end
34 31  
35   - def display_title
36   - title.blank? ? name : title
37   - end
38   -
39 32 def first_paragraph
40 33 ''
41 34 end
... ... @@ -109,7 +102,7 @@ class UploadedFile &lt; Article
109 102 alias :orig_set_filename :filename=
110 103 def filename=(value)
111 104 orig_set_filename(value)
112   - self.name = self.filename
  105 + self.name ||= self.filename
113 106 end
114 107  
115 108 def download_headers
... ...
app/models/user.rb
... ... @@ -54,7 +54,7 @@ class User &lt; ActiveRecord::Base
54 54 def activation_email_notify(user)
55 55 user_email = "#{user.login}@#{user.email_domain}"
56 56 recipients user_email
57   - from "#{user.environment.name} <#{user.environment.contact_email}>"
  57 + from "#{user.environment.name} <#{user.environment.noreply_email}>"
58 58 subject _("[%{environment}] Welcome to %{environment} mail!") % { :environment => user.environment.name }
59 59 body :name => user.name,
60 60 :email => user_email,
... ... @@ -66,12 +66,13 @@ class User &lt; ActiveRecord::Base
66 66 def activation_code(user)
67 67 recipients user.email
68 68  
69   - from "#{user.environment.name} <#{user.environment.contact_email}>"
  69 + from "#{user.environment.name} <#{user.environment.noreply_email}>"
70 70 subject _("[%s] Activate your account") % [user.environment.name]
71 71 body :recipient => user.name,
72 72 :activation_code => user.activation_code,
73 73 :environment => user.environment.name,
74   - :url => user.environment.top_url
  74 + :url => user.environment.top_url,
  75 + :redirection => (true if user.return_to)
75 76 end
76 77  
77 78 def signup_welcome_email(user)
... ... @@ -81,7 +82,7 @@ class User &lt; ActiveRecord::Base
81 82 content_type 'text/html'
82 83 recipients user.email
83 84  
84   - from "#{user.environment.name} <#{user.environment.contact_email}>"
  85 + from "#{user.environment.name} <#{user.environment.noreply_email}>"
85 86 subject email_subject.blank? ? _("Welcome to environment %s") % [user.environment.name] : email_subject
86 87 body email_body
87 88 end
... ... @@ -93,7 +94,7 @@ class User &lt; ActiveRecord::Base
93 94 self.person.save!
94 95 end
95 96 end
96   -
  97 +
97 98 has_one :person, :dependent => :destroy
98 99 belongs_to :environment
99 100  
... ... @@ -183,7 +184,7 @@ class User &lt; ActiveRecord::Base
183 184 encryption_methods[sym] = block
184 185 end
185 186  
186   - # the encryption method used for this instance
  187 + # the encryption method used for this instance
187 188 def encryption_method
188 189 (password_type || User.system_encryption_method).to_sym
189 190 end
... ... @@ -226,7 +227,7 @@ class User &lt; ActiveRecord::Base
226 227 end
227 228  
228 229 def remember_token?
229   - remember_token_expires_at && Time.now.utc < remember_token_expires_at
  230 + remember_token_expires_at && Time.now.utc < remember_token_expires_at
230 231 end
231 232  
232 233 # These create and unset the fields required for remembering users between browser closes
... ... @@ -255,7 +256,7 @@ class User &lt; ActiveRecord::Base
255 256 raise IncorrectPassword unless self.authenticated?(current)
256 257 self.force_change_password!(new, confirmation)
257 258 end
258   -
  259 +
259 260 # Changes the password of a user without asking for the old password. This
260 261 # method is intended to be used by the "I forgot my password", and must be
261 262 # used with care.
... ... @@ -326,7 +327,7 @@ class User &lt; ActiveRecord::Base
326 327 end
327 328  
328 329 protected
329   - # before filter
  330 + # before filter
330 331 def encrypt_password
331 332 return if password.blank?
332 333 self.salt ||= Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record?
... ...
app/sweepers/profile_sweeper.rb
... ... @@ -8,6 +8,8 @@ class ProfileSweeper # &lt; ActiveRecord::Observer
8 8 end
9 9  
10 10 def after_create(profile)
  11 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  12 + # the Noosfero core soon, see ActionItem3045
11 13 expire_statistics_block_cache(profile)
12 14 end
13 15  
... ... @@ -29,6 +31,8 @@ protected
29 31 expire_blogs(profile) if profile.organization?
30 32 end
31 33  
  34 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  35 + # the Noosfero core soon, see ActionItem3045
32 36 def expire_statistics_block_cache(profile)
33 37 blocks = profile.environment.blocks.select { |b| b.kind_of?(EnvironmentStatisticsBlock) }
34 38 BlockSweeper.expire_blocks(blocks)
... ...
app/views/admin_panel/_site_info.rhtml
1 1 <%= required labelled_form_field(_('Site name'), text_field(:environment, :name)) %>
2 2 <%= labelled_form_field(_('Contact email'), text_field(:environment, :contact_email)) %>
  3 +<%= labelled_form_field(_('No reply email'), text_field(:environment, :noreply_email)) %>
3 4 <% themes_options = Theme.system_themes.map {|theme| [theme.name, theme.id] }.sort %>
4 5 <%= labelled_form_field(_('Theme'), select(:environment, :theme, options_for_select(themes_options, environment.theme))) %>
5 6 <%= required f.text_field(:reports_lower_bound, :size => 3) %>
... ...
app/views/admin_panel/index.rhtml
... ... @@ -6,6 +6,7 @@
6 6 <tr><td><%= link_to _('Environment settings'), :action => 'site_info' %></td></tr>
7 7 <tr><td><%= link_to _('Features'), :controller => 'features' %></td></tr>
8 8 <tr><td><%= link_to _('Plugins'), :controller => 'plugins' %></td></tr>
  9 + <tr><td><%= link_to _('Appearance'), :controller =>'environment_themes' %></td></tr>
9 10 <tr><td><%= link_to _('Sideboxes'), :controller => 'environment_design'%></td></tr>
10 11 <tr><td><%= link_to _('Homepage'), :action => 'set_portal_community' %></td></tr>
11 12 <tr><td><%= link_to _('Licenses'), :controller =>'licenses' %></td></tr>
... ...
app/views/blocks/location.html.erb
... ... @@ -3,7 +3,6 @@
3 3 <div class='the-localization-map'>
4 4 <img src="https://maps.google.com/maps/api/staticmap?center=<%=profile.lat%>,<%=profile.lng%>&zoom=<%=block.zoom%>&size=190x250&maptype=<%=block.map_type%>&markers=<%=profile.lat%>,<%=profile.lng%>&sensor=false"/>
5 5 </div>
6   -</div>
7 6 <% else %>
8 7 <i><%= _('This profile has no geographical position registered.') %></i>
9 8 <% end %>
... ...
app/views/blocks/profile_image.rhtml
1 1 <div class="vcard">
2 2  
3   -<p><%= block.title %></p>
  3 +<% if block.title.present? %>
  4 + <p><%= block.title %></p>
  5 +<% end %>
4 6  
5 7 <div class="profile-big-image">
6 8 <div class="profile-big-image-inner1">
... ... @@ -16,7 +18,7 @@
16 18  
17 19 <% if !user.nil? and user.has_permission?('edit_profile', profile) %>
18 20 <div class='admin-link'>
19   - <%= link_to _('Control panel'), :controller => 'profile_editor' %>
  21 + <%= link_to _('Control panel'), block.owner.admin_url %>
20 22 </div>
21 23 <% end %>
22 24  
... ...
app/views/blocks/profile_info.rhtml
... ... @@ -21,7 +21,7 @@
21 21 <li><%= link_to(_('Products/Services'), :controller => 'catalog', :profile => block.owner.identifier) %></li>
22 22 <% end %>
23 23 <% if !user.nil? and user.has_permission?('edit_profile', profile) %>
24   - <li><%= link_to _('Control panel'), :controller => 'profile_editor' %></li>
  24 + <li><%= link_to _('Control panel'), block.owner.admin_url %></li>
25 25 <% end %>
26 26 <% if profile.person? %>
27 27 <li><%= _('Since %{year}/%{month}') % { :year => block.owner.created_at.year, :month => block.owner.created_at.month } %></li>
... ... @@ -40,7 +40,7 @@
40 40 <% end %>
41 41  
42 42 <div class="profile-info-options">
43   - <%= render :file => view_for_profile_actions(@block.owner.class) %>
  43 + <%= render :file => view_for_profile_actions(block.owner.class) %>
44 44 </div>
45 45  
46 46 </div><!-- end class="vcard" -->
... ...
app/views/box_organizer/_link_list_block.rhtml
  1 +<%= javascript_include_tag "edit-link-list.js" %>
  2 +
1 3 <strong><%= _('Links') %></strong>
2   -<div id='edit-link-list-block' style='width:450px'>
3   -<table id='links' class='noborder'>
4   - <tr><th><%= _('Icon') %></th><th><%= _('Name') %></th><th><%= _('Address') %></th><th><%= _('Target') %></th></tr>
5   - <% for link in @block.links do %>
6   - <tr>
7   - <td>
8   - <%= icon_selector(link['icon']) %>
9   - </td>
10   - <td><%= text_field_tag 'block[links][][name]', link[:name], :class => 'link-name', :maxlength => 20 %></td>
11   - <td class='cel-address'><%= text_field_tag 'block[links][][address]', link[:address], :class => 'link-address' %></td>
12   - <td>
13   - <%= select_tag('block[links][][target]', options_for_select(LinkListBlock::TARGET_OPTIONS, link[:target])) %>
14   - </td>
15   - </tr>
16   - <% end %>
17   -</table>
  4 +<div id='edit-link-list-block'>
  5 + <ul class='link-list-header'>
  6 + <li class='link-list-icon'><%= _('Icon') %></li>
  7 + <li class='link-list-name'><%= _('Name') %></li>
  8 + <li class='link-list-address'><%= _('Address') %></li>
  9 + <li class='link-list-target'><%= _('Target') %></li>
  10 + </ul>
  11 + <ul id="dropable-link-list">
  12 + <% for link in @block.links do %>
  13 + <li>
  14 + <ul class="link-list-row">
  15 + <li>
  16 + <%= icon_selector(link['icon']) %>
  17 + </li>
  18 + <li>
  19 + <%= text_field_tag 'block[links][][name]', link[:name], :class => 'link-name', :maxlength => 20 %>
  20 + </li>
  21 + <li>
  22 + <%= text_field_tag 'block[links][][address]', link[:address], :class => 'link-address' %>
  23 + </li>
  24 + <li>
  25 + <%= select_tag('block[links][][target]', options_for_select(LinkListBlock::TARGET_OPTIONS, link[:target])) %>
  26 + </li>
  27 + <li>
  28 + <%= button_without_text(:delete, _('Delete'), "#" , :class=>"delete-link-list-row") %>
  29 + </li>
  30 + </ul>
  31 + </li>
  32 + <% end %>
  33 + </ul>
  34 + <input type="hidden" id="page_url" value="<%=url_for(:action=>'search_autocomplete')%>" />
18 35 </div>
19 36  
20 37 <%= link_to_function(_('New link'), nil, :class => 'button icon-add with-text') do |page|
21   - page.insert_html :bottom, 'links', content_tag('tr',
22   - content_tag('td', icon_selector('ok')) +
23   - content_tag('td', text_field_tag('block[links][][name]', '', :maxlength => 20)) +
24   - content_tag('td', text_field_tag('block[links][][address]', nil, :class => 'link-address'), :class => 'cel-address') +
25   - content_tag('td', select_tag('block[links][][target]',
26   -options_for_select(LinkListBlock::TARGET_OPTIONS, '_self')))
  38 + page.insert_html :bottom, 'dropable-link-list', content_tag('li',
  39 + content_tag('ul',
  40 + content_tag('li', icon_selector('ok')) +
  41 + content_tag('li', text_field_tag('block[links][][name]', '', :maxlength => 20)) +
  42 + content_tag('li', text_field_tag('block[links][][address]', nil, :class => 'link-address')) +
  43 + content_tag('li', select_tag('block[links][][target]',
  44 + options_for_select(LinkListBlock::TARGET_OPTIONS, '_self'))) +
  45 + content_tag('li', button_without_text(:delete, _('Delete'), "#" , :class=>"delete-link-list-row")),
  46 + :class=>"link-list-row new_link_row")
27 47 ) +
28   - javascript_tag("$('edit-link-list-block').scrollTop = $('edit-link-list-block').scrollHeight")
  48 + javascript_tag("new_link_action()")
29 49 end %>
... ...
app/views/box_organizer/edit.rhtml
... ... @@ -7,13 +7,14 @@
7 7  
8 8 <%= render :partial => partial_for_class(@block.class) %>
9 9  
10   - <%= labelled_form_field _('Display this block:'), '' %>
11   - <div style='margin-left: 10px'>
12   - <% @block.display_options.each do |option| %>
13   - <%= radio_button(:block, :display, option) %>
14   - <%= label_tag("block_display_#{option}", _(@block.display_option_label(option))) %>
15   - <br/>
16   - <% end %>
  10 + <div class="display">
  11 + <%= labelled_form_field _('Display this block:'),
  12 + select_tag('block[display]', options_from_collection_for_select(@block.display_options, :first, :last, @block.display))
  13 + %>
  14 + </div>
  15 + <div class="display_user">
  16 + <%= labelled_form_field _('Display to users:'), '' %>
  17 + <%= select_tag('block[display_user]', options_from_collection_for_select(@block.display_user_options, :first, :last, @block.display_user)) %>
17 18 </div>
18 19  
19 20 <%= labelled_form_field(_('Show for:'), select(:block, :language, [ [ _('all languages'), 'all']] + environment.locales.map {|key, value| [value, key]} )) %>
... ...
app/views/cms/edit.rhtml
1 1 <%= error_messages_for 'article' %>
2   -<%= javascript_include_tag "article.js" %>
3 2  
4 3 <div class='<%= (environment.enabled?('media_panel') ? 'with_media_panel' : 'no_media_panel') %>'>
5 4 <% labelled_form_for 'article', @article, :html => { :multipart => true, :class => @type } do |f| %>
... ... @@ -63,3 +62,5 @@
63 62 <% end %>
64 63  
65 64 <br style='clear: both'/>
  65 +
  66 +<%= javascript_include_tag "article.js" %>
... ...
app/views/comment/_comment.rhtml
... ... @@ -43,6 +43,7 @@
43 43 <p/>
44 44 <%= txt2html comment.body %>
45 45 </div>
  46 + <%= @plugins.dispatch(:comment_extra_contents, local_assigns).collect { |content| instance_eval(&content) }.join("") %>
46 47 </div>
47 48  
48 49 <div class="comment_reply post_comment_box closed" id="comment_reply_to_<%= comment.id %>">
... ...
app/views/content_viewer/_addthis.rhtml 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +<div id="addThis">
  2 + <script type="text/javascript">
  3 + addthis_pub = '<%= escape_javascript( NOOSFERO_CONF['addthis_pub'] ) %>';
  4 + addthis_logo = '<%= escape_javascript( NOOSFERO_CONF['addthis_logo'] ) %>';
  5 + addthis_options = '<%= escape_javascript( NOOSFERO_CONF['addthis_options'] ) %>';
  6 + </script>
  7 + <a href="http://www.addthis.com/bookmark.php" id="bt_addThis" target="_blank" onmouseover="return addthis_open(this, '', '[URL]')" onmouseout="addthis_close()" onclick="return addthis_sendto()"><%= addthis_image_tag %></a>
  8 +</div>
... ...
app/views/content_viewer/_article_toolbar.rhtml
... ... @@ -26,7 +26,7 @@
26 26 <%= expirable_button @page, :spread, content, url if url %>
27 27 <% end %>
28 28  
29   - <% if !@page.gallery? && @page.allow_create?(user) %>
  29 + <% if !@page.gallery? && (@page.allow_create?(user) || (@page.parent && @page.parent.allow_create?(user))) %>
30 30 <% if @page.translatable? && !@page.native_translation.language.blank? && !remove_content_button(:locale) %>
31 31 <% content = _('Add translation') %>
32 32 <% parent_id = (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)) %>
... ...
app/views/content_viewer/view_page.rhtml
... ... @@ -40,32 +40,10 @@
40 40 </div>
41 41 <% end %>
42 42  
43   -<% if !@page.tags.empty? %>
44   - <div id="article-tags">
45   - <%= _("This article's tags:") %>
46   - <%= @page.tags.map { |t| link_to(t, :controller => 'profile', :profile => @profile.identifier, :action => 'tags', :id => t.name ) }.join("\n") %>
47   - </div>
48   -<% end %>
49   -
50   -
51 43 <%= render :partial => 'shared/disabled_enterprise' %>
52 44  
53 45 <% if NOOSFERO_CONF['addthis_enabled'] %>
54   -<div id="addThis">
55   -<script type="text/javascript">
56   - addthis_pub = '<%= escape_javascript( NOOSFERO_CONF['addthis_pub'] ) %>';
57   - addthis_logo = '<%= escape_javascript( NOOSFERO_CONF['addthis_logo'] ) %>';
58   - addthis_config = {
59   - services_custom: {
60   - name: 'Facebook',
61   - url: '<%= addthis_facebook_url(@page) %>',
62   - icon: 'http://cache.addthiscdn.com/icons/v1/thumbs/facebook.gif'
63   - }
64   - };
65   - addthis_options = '<%= escape_javascript( NOOSFERO_CONF['addthis_options'] ) %>';
66   -</script>
67   -<a href="http://www.addthis.com/bookmark.php" id="bt_addThis" target="_blank" onmouseover="return addthis_open(this, '', '[URL]')" onmouseout="addthis_close()" onclick="return addthis_sendto()"><%= addthis_image_tag %></a>
68   -</div>
  46 + <%= render :partial => 'addthis' %>
69 47 <% end %>
70 48  
71 49 <% cache(@page.cache_key(params, user, language)) do %>
... ... @@ -83,8 +61,17 @@
83 61 </div>
84 62 <% end %>
85 63  
  64 +<% if !@page.tags.empty? %>
  65 + <div id="article-tags">
  66 + <%= _("This article's tags:") %>
  67 + <%= @page.tags.map { |t| link_to(t, :controller => 'profile', :profile => @profile.identifier, :action => 'tags', :id => t.name ) }.join("\n") %>
  68 + </div>
  69 +<% end %>
  70 +
86 71 <%= display_source_info(@page) %>
87 72  
  73 +<%= @plugins.dispatch(:article_extra_contents, @page).collect { |content| instance_eval(&content) }.join("") %>
  74 +
88 75 <div class="comments" id="comments_list">
89 76  
90 77 <% if @page.accept_comments? || @comments_count > 0 %>
... ... @@ -93,8 +80,26 @@
93 80 </h3>
94 81 <% end %>
95 82  
96   - <% if @page.accept_comments? && @comments.count > 1 %>
  83 + <% if @page.accept_comments? && @comments_count > 1 %>
97 84 <%= link_to(_('Post a comment'), '#', :class => 'display-comment-form', :id => 'top-post-comment-button', :onclick => "jQuery('#page-comment-form .display-comment-form').first().click();") %>
  85 +
  86 + <%= hidden_field_tag("page_url", url_for(:controller=>'content_viewer', :action=>'view_page', :profile=>profile.identifier)) %>
  87 + <%= javascript_include_tag "comment_order.js" %>
  88 + <div class="comment-order">
  89 + <% form_tag({:controller=>'content_viewer' , :action=>'view_page'}, {:method=>'get', :id=>"form_order"}) do %>
  90 + <%= select_tag 'comment_order', options_for_select({_('Oldest first')=>'oldest', _('Newest first')=>'newest'}, @comment_order) %>
  91 + <% end %>
  92 + </div>
  93 + <% end %>
  94 +
  95 + <% if @page.accept_comments? and @comments.count > 1 %>
  96 + <%= hidden_field_tag("page_url", url_for(:controller=>'content_viewer', :action=>'view_page', :profile=>profile.identifier)) %>
  97 + <%= javascript_include_tag "comment_order.js" %>
  98 + <div class="comment-order">
  99 + <% form_tag({:controller=>'content_viewer' , :action=>'view_page'}, {:method=>'get', :id=>"form_order"}) do %>
  100 + <%= select_tag 'comment_order', options_for_select({_('Oldest first')=>'oldest', _('Newest first')=>'newest'}, @comment_order) %>
  101 + <% end %>
  102 + </div>
98 103 <% end %>
99 104  
100 105 <ul class="article-comments-list">
... ...
app/views/environment_themes/index.rhtml 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +<%= render :partial => 'themes/select_template' %>
  2 +<%= render :partial => 'themes/select_theme' %>
  3 +
  4 +<br style="clear:both" />
  5 +
  6 +<% button_bar do %>
  7 + <%= button(:back, _('Back'), :controller => 'admin_panel', :action => 'index') %>
  8 +<% end %>
... ...
app/views/events/_events.rhtml
1   -<%= list_events(@date, @events) %>
2 1 \ No newline at end of file
  2 +<%= list_events(@date, @events) %>
  3 +
  4 +<%= pagination_links @events, :param_name => 'page' %>
... ...
app/views/features/_manage_community_fields.rhtml
1   -<h2><%= __('Manage community fields') %></h2>
2   -
3 1 <% labelled_form_for(:environment, @environment, :url => {:action => 'manage_community_fields'}) do |f| %>
4 2  
5 3 <table id='community_fields_conf'>
... ... @@ -9,21 +7,37 @@
9 7 <th><%= _('Required') %></th>
10 8 <th><%= _('Display on creation?') %></th>
11 9 </tr>
  10 +
  11 + <tr class='manage-fields-batch-actions'>
  12 + <td>
  13 + <%= _("Check/Uncheck All")%>
  14 + </td>
  15 + <td>
  16 + <input type="checkbox" id="community_active" />
  17 + </td>
  18 + <td>
  19 + <input type="checkbox" id="community_required" />
  20 + </td>
  21 + <td>
  22 + <input type="checkbox" id="community_signup" />
  23 + </td>
  24 + </tr>
  25 +
12 26 <% @community_fields.each do |field| %>
13 27 <tr>
14 28 <td><label for="community_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td>
15 29  
16 30 <td>
17 31 <%= hidden_field_tag "community_fields[#{field}][active]", false %>
18   - <%= check_box_tag "community_fields[#{field}][active]", true, environment.custom_community_field(field, 'active'), :onclick => "$('community_fields[#{field}][required]').disabled=$('community_fields[#{field}][signup]').disabled=!this.checked;" %>
  32 + <%= check_box_tag "community_fields[#{field}][active]", true, environment.custom_community_field(field, 'active'), :onclick => "active_action(this, 'community_fields[#{field}][required]', 'community_fields[#{field}][signup]')" %>
19 33 </td>
20 34 <td>
21 35 <%= hidden_field_tag "community_fields[#{field}][required]", false %>
22   - <%= check_box_tag "community_fields[#{field}][required]", true, environment.custom_community_field(field, 'required'), :onclick => "if(this.checked) $('community_fields[#{field}][signup]').checked = true;" %>
  36 + <%= check_box_tag "community_fields[#{field}][required]", true, environment.custom_community_field(field, 'required'), :onclick => "required_action('community_fields[#{field}][active]','community_fields[#{field}][required]', 'community_fields[#{field}][signup]')" %>
23 37 </td>
24 38 <td>
25 39 <%= hidden_field_tag "community_fields[#{field}][signup]", false %>
26   - <%= check_box_tag "community_fields[#{field}][signup]", true, environment.custom_community_field(field, 'signup'), :onclick => "if(!this.checked) $('community_fields[#{field}][required]').checked = false;" %>
  40 + <%= check_box_tag "community_fields[#{field}][signup]", true, environment.custom_community_field(field, 'signup'), :onclick => "signup_action('community_fields[#{field}][active]','community_fields[#{field}][required]', 'community_fields[#{field}][signup]')" %>
27 41 </td>
28 42  
29 43 </tr>
... ... @@ -31,18 +45,18 @@
31 45 </table>
32 46  
33 47 <script type='text/javascript'>
34   - var trs = $$('#community_fields_conf tr');
  48 + var trs = jQuery('#community_fields_conf tr');
35 49 var tr, td2;
36   - for ( var i=0; tr=trs[i]; i++ ) {
  50 + for ( var i=2; tr=trs[i]; i++ ) {
37 51 if ( td2 = tr.getElementsByTagName('td')[1] ) {
38   - td2.getElementsByTagName('input')[0].onclick();
  52 + td2.getElementsByTagName('input')[1].onclick();
39 53 }
40 54 }
41 55 </script>
42 56  
43 57 <div>
44 58 <% button_bar do %>
45   - <%= submit_button('save', _('Save changes')) %>
  59 + <%= submit_button('save', _('Save changes'), :id=>"save_community_fields") %>
46 60 <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %>
47 61 <% end %>
48 62 </div>
... ...
app/views/features/_manage_enterprise_fields.rhtml
1   -<h2><%= __('Manage enterprise fields') %></h2>
2   -
3 1 <% labelled_form_for(:environment, @environment, :url => {:action => 'manage_enterprise_fields'}) do |f| %>
4 2  
5 3 <table id='enterprise_fields_conf'>
... ... @@ -9,21 +7,37 @@
9 7 <th><%= _('Required') %></th>
10 8 <th><%= _('Display on registration?') %></th>
11 9 </tr>
  10 +
  11 + <tr class='manage-fields-batch-actions'>
  12 + <td>
  13 + <%= _("Check/Uncheck All")%>
  14 + </td>
  15 + <td>
  16 + <input type="checkbox" id="enterprise_active" />
  17 + </td>
  18 + <td>
  19 + <input type="checkbox" id="enterprise_required" />
  20 + </td>
  21 + <td>
  22 + <input type="checkbox" id="enterprise_signup" />
  23 + </td>
  24 + </tr>
  25 +
12 26 <% @enterprise_fields.each do |field| %>
13 27 <tr>
14 28  
15 29 <td><label for="enterprise_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td>
16 30 <td>
17 31 <%= hidden_field_tag "enterprise_fields[#{field}][active]", false %>
18   - <%= check_box_tag "enterprise_fields[#{field}][active]", true, environment.custom_enterprise_field(field, 'active'), :onclick => "$('enterprise_fields[#{field}][required]').disabled=$('enterprise_fields[#{field}][signup]').disabled=!this.checked;" %>
  32 + <%= check_box_tag "enterprise_fields[#{field}][active]", true, environment.custom_enterprise_field(field, 'active'), :onclick => "active_action(this, 'enterprise_fields[#{field}][required]', 'enterprise_fields[#{field}][signup]')" %>
19 33 </td>
20 34 <td>
21 35 <%= hidden_field_tag "enterprise_fields[#{field}][required]", false %>
22   - <%= check_box_tag "enterprise_fields[#{field}][required]", true, environment.custom_enterprise_field(field, 'required'), :onclick => "if(this.checked) $('enterprise_fields[#{field}][signup]').checked = true;" %>
  36 + <%= check_box_tag "enterprise_fields[#{field}][required]", true, environment.custom_enterprise_field(field, 'required'), :onclick => "required_action('enterprise_fields[#{field}][active]','enterprise_fields[#{field}][required]', 'enterprise_fields[#{field}][signup]')" %>
23 37 </td>
24 38 <td>
25 39 <%= hidden_field_tag "enterprise_fields[#{field}][signup]", false %>
26   - <%= check_box_tag "enterprise_fields[#{field}][signup]", true, environment.custom_enterprise_field(field, 'signup'), :onclick => "if(!this.checked) $('enterprise_fields[#{field}][required]').checked = false;" %>
  40 + <%= check_box_tag "enterprise_fields[#{field}][signup]", true, environment.custom_enterprise_field(field, 'signup'), :onclick => "signup_action('enterprise_fields[#{field}][active]','enterprise_fields[#{field}][required]', 'enterprise_fields[#{field}][signup]')" %>
27 41 </td>
28 42  
29 43 </tr>
... ... @@ -31,18 +45,18 @@
31 45 </table>
32 46  
33 47 <script type='text/javascript'>
34   - var trs = $$('#enterprise_fields_conf tr');
  48 + var trs = jQuery('#enterprise_fields_conf tr');
35 49 var tr, td2;
36   - for ( var i=0; tr=trs[i]; i++ ) {
  50 + for ( var i=2; tr=trs[i]; i++ ) {
37 51 if ( td2 = tr.getElementsByTagName('td')[1] ) {
38   - td2.getElementsByTagName('input')[0].onclick();
  52 + td2.getElementsByTagName('input')[1].onclick();
39 53 }
40 54 }
41 55 </script>
42 56  
43 57 <div>
44 58 <% button_bar do %>
45   - <%= submit_button('save', _('Save changes')) %>
  59 + <%= submit_button('save', _('Save changes'), :id=>"save_enterprise_fields") %>
46 60 <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %>
47 61 <% end %>
48 62 </div>
... ...
app/views/features/_manage_person_fields.rhtml
1   -<h2><%= _('Manage person fields') %></h2>
2   -
3 1 <% labelled_form_for(:environment, @environment, :url => {:action => 'manage_person_fields'}) do |f| %>
4 2  
5 3 <table id='person_fields_conf'>
... ... @@ -9,31 +7,48 @@
9 7 <th><%= _('Required') %></th>
10 8 <th><%= _('Display on signup?') %></th>
11 9 </tr>
  10 +
  11 + <tr class='manage-fields-batch-actions'>
  12 + <td>
  13 + <%= _("Check/Uncheck All")%>
  14 + </td>
  15 + <td>
  16 + <input type="checkbox" id="person_active" />
  17 + </td>
  18 + <td>
  19 + <input type="checkbox" id="person_required" />
  20 + </td>
  21 + <td>
  22 + <input type="checkbox" id="person_signup" />
  23 + </td>
  24 + </tr>
  25 +
12 26 <% @person_fields.each do |field| %>
13 27 <tr>
14 28 <td><label for="person_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td>
15 29 <td>
16 30 <%= hidden_field_tag "person_fields[#{field}][active]", false %>
17   - <%= check_box_tag "person_fields[#{field}][active]", true, environment.custom_person_field(field, 'active'), :onclick => "$('person_fields[#{field}][required]').disabled=$('person_fields[#{field}][signup]').disabled=!this.checked;" %>
  31 + <%= check_box_tag "person_fields[#{field}][active]", true, environment.custom_person_field(field, 'active'), :onclick => "active_action(this, 'person_fields[#{field}][required]', 'person_fields[#{field}][signup]')" %>
18 32 </td>
19 33 <td>
20 34 <%= hidden_field_tag "person_fields[#{field}][required]", false %>
21   - <%= check_box_tag "person_fields[#{field}][required]", true, environment.custom_person_field(field, 'required'), :onclick => "if(this.checked) $('person_fields[#{field}][signup]').checked = true;" %>
  35 + <%= check_box_tag "person_fields[#{field}][required]", true, environment.custom_person_field(field, 'required'), :onclick => "required_action('person_fields[#{field}][active]','person_fields[#{field}][required]', 'person_fields[#{field}][signup]')" %>
22 36 </td>
23 37 <td>
24 38 <%= hidden_field_tag "person_fields[#{field}][signup]", false %>
25   - <%= check_box_tag "person_fields[#{field}][signup]", true, environment.custom_person_field(field, 'signup'), :onclick => "if(!this.checked) $('person_fields[#{field}][required]').checked = false;" %>
  39 + <%= check_box_tag "person_fields[#{field}][signup]", true, environment.custom_person_field(field, 'signup'), :onclick => "signup_action('person_fields[#{field}][active]','person_fields[#{field}][required]', 'person_fields[#{field}][signup]')" %>
26 40 </td>
27 41 </tr>
28 42 <% end %>
29 43 </table>
30 44  
31 45 <script type='text/javascript'>// <!--
32   - var trs = $$('#person_fields_conf tr');
  46 + var trs = jQuery('#person_fields_conf tr');
  47 +
33 48 var tr, td2;
34   - for ( var i=0; tr=trs[i]; i++ ) {
  49 + for ( var i=2; tr=trs[i]; i++ ) {
35 50 if ( td2 = tr.getElementsByTagName('td')[1] ) {
36   - td2.getElementsByTagName('input')[0].onclick();
  51 + td2.getElementsByTagName('input')[1].onclick();
37 52 }
38 53 }
39 54 // -->
... ... @@ -41,7 +56,7 @@
41 56  
42 57 <div>
43 58 <% button_bar do %>
44   - <%= submit_button('save', _('Save changes')) %>
  59 + <%= submit_button('save', _('Save changes'), :id=>"save_person_fields") %>
45 60 <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %>
46 61 <% end %>
47 62 </div>
... ...
app/views/features/index.rhtml
... ... @@ -26,9 +26,13 @@ Check all the features you want to enable for your environment, uncheck all the
26 26  
27 27 <h2><%= _('Configure features') %></h2>
28 28  
  29 +<h3><%= _('Page to redirect after signup') %></h3>
  30 + <%= select 'environment', 'redirection_after_signup', Environment.signup_redirection_options.map{|key,value|[value,key]} %>
  31 +<hr/>
29 32 <h3><%= _('Page to redirect after login') %></h3>
30 33 <%= select 'environment', 'redirection_after_login', Environment.login_redirection_options.map{|key,value|[value,key]} %>
31 34 <hr/>
  35 +
32 36 <h3><%= _('Organization Approval Method') %></h3>
33 37 <%= select_organization_approval_method('environment', 'organization_approval_method') %>
34 38 <hr/>
... ...
app/views/features/manage_fields.rhtml
1   -<%= render :partial => 'manage_person_fields' %>
  1 +<h1><%= _('Manage fields displayed for profiles') %></h1>
2 2  
3   -<% if !environment.enabled?('disable_asset_enterprises') %>
4   - <%= render :partial => 'manage_enterprise_fields' %>
  3 +<% tabs = [] %>
  4 +<% tabs << {:title => _("Person's fields"), :id => 'person-fields',
  5 + :content => (render :partial => 'manage_person_fields')} %>
  6 +<% tabs << {:title => _("Community's fields"), :id => 'community-fields',
  7 + :content => (render :partial => 'manage_community_fields')} %>
  8 +<% unless environment.enabled?('disable_asset_enterprises') %>
  9 + <% tabs << {:title => _("Enterprise's fields"), :id => 'enterprise-fields',
  10 + :content => (render :partial => 'manage_enterprise_fields')} %>
5 11 <% end %>
6 12  
7   -<%= render :partial => 'manage_community_fields' %>
  13 +<%= render_tabs(tabs) %>
  14 +
  15 +<%= javascript_include_tag "manage-fields.js" %>
... ...
app/views/layouts/application-ng.rhtml
... ... @@ -6,6 +6,27 @@
6 6 <!--<meta http-equiv="refresh" content="1"/>-->
7 7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
8 8 <meta name="description" content="<%= @environment.name %>" />
  9 +
  10 + <!-- Twitter Card -->
  11 + <meta name="twitter:card" value="summary">
  12 + <meta name="twitter:title" content="<%= h page_title %>">
  13 + <meta name="twitter:description" content="<%= meta_description_tag(@page) %>">
  14 +
  15 + <!-- Open Graph -->
  16 + <meta property="og:type" content="<%= @page ? 'article' : 'website' %>">
  17 + <meta property="og:url" content="<%= @page ? url_for(@page.url) : @environment.top_url %>">
  18 + <meta property="og:title" content="<%= h page_title %>">
  19 + <meta property="og:site_name" content="<%= profile ? profile.name : @environment.name %>">
  20 + <meta property="og:description" content="<%= @page ? truncate(strip_tags(@page.body.to_s), :length => 200) : @environment.name %>">
  21 +
  22 + <% if @page %>
  23 + <meta property="article:published_time" content="<%= show_date(@page.published_at) %>">
  24 + <% @page.body_images_paths.each do |img| %>
  25 + <meta name="twitter:image" content="<%= img.to_s %>">
  26 + <meta property="og:image" content="<%= img.to_s %>">
  27 + <% end %>
  28 + <% end %>
  29 +
9 30 <link rel="shortcut icon" href="<%= image_path(theme_favicon) %>" type="image/x-icon" />
10 31 <%= noosfero_javascript %>
11 32 <%= noosfero_stylesheets %>
... ...
app/views/person_notifier/mailer/_add_member_in_community.rhtml 0 → 100644
... ... @@ -0,0 +1 @@
  1 +<%= render :partial => 'default_activity', :locals => { :activity => activity } %>
... ...
app/views/person_notifier/mailer/_comment.rhtml 0 → 100644
... ... @@ -0,0 +1,33 @@
  1 +<% Comment %>
  2 +<% Profile %>
  3 +<% Person %>
  4 +
  5 +<table style="background: #f0f0f1;border-bottom: 1px solid #d2d2d2 !important;border-top: 1px solid #fff;margin-bottom: 0;">
  6 +<tr>
  7 + <td>
  8 + <% if comment.author %>
  9 + <%= link_to profile_image(comment.author, :minor),
  10 + comment.author_url,
  11 + :class => 'comment-picture',
  12 + :title => comment.author_name
  13 + %>
  14 + <% end %>
  15 + </td>
  16 + <td>
  17 + <%= comment.author.present? ? link_to(comment.author_name, comment.author.url, :style => "font-size: 12px; color: #333; font-weight: bold; text-decoration: none;") : content_tag('strong', comment.author_name) %>
  18 + <% unless comment.title.blank? %>
  19 + <span style="font-size: 12px;"><%= comment.title %></span><br/>
  20 + <% end %>
  21 + <span style="font-size: 10px;"><%= txt2html comment.body %></span><br/>
  22 + <span style="font-size: 8px; color: #444444"><%= time_ago_as_sentence(comment.created_at) %></span>
  23 + <br style="clear: both;" />
  24 +
  25 + <% unless comment.replies.blank? %>
  26 + <ul class="comment-replies">
  27 + <% comment.replies.each do |reply| %>
  28 + <%= render :partial => 'comment', :locals => { :comment => reply } %>
  29 + <% end %>
  30 + </ul>
  31 + <% end %>
  32 + </td>
  33 +</table>
... ...
app/views/person_notifier/mailer/_create_article.rhtml 0 → 100644
... ... @@ -0,0 +1,27 @@
  1 +<table>
  2 +<tr>
  3 + <td>
  4 + <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
  5 + </td>
  6 + <td>
  7 + <p style="width:550px">
  8 + <span style="font-size: 14px;"><%= link_to activity.user.short_name(20), activity.user.url %></span>
  9 + <span style="font-size: 14px;"><%= _("has published on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url, :style => "color: #333; font-weight: bold; text-decoration: none;") if activity.target.profile.is_a?(Community) %></span>
  10 + <span style="font-size: 10px; color: #444444; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span>
  11 + </p>
  12 + <p>
  13 + <span style="font-size: 14px;"><%= link_to(activity.params['name'], activity.params['url'], :style => "color: #333; font-weight: bold; text-decoration: none;") %></span>
  14 + <br/>
  15 + <span title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-new<%= activity.target.class.icon_name %>'></span>
  16 + <%= image_tag(activity.params['first_image']) unless activity.params['first_image'].blank? %><%= strip_tags(truncate(activity.params['lead'], :length => 1000, :ommision => '...')).gsub(/(\xC2\xA0|\s)+/, ' ').gsub(/^\s+/, '') %>
  17 + </p>
  18 + <p><%= content_tag(:p, link_to(_('See complete forum'), activity.get_url), :class => 'see-forum') if activity.target.is_a?(Forum) %></p>
  19 + </td>
  20 +</tr>
  21 +<tr>
  22 + <td></td>
  23 + <td>
  24 + <%= render :partial => 'profile_comments', :locals => { :activity => activity } %>
  25 + </td>
  26 +</tr>
  27 +</table>
... ...
app/views/person_notifier/mailer/_default_activity.rhtml 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +<table>
  2 +<tr>
  3 + <td>
  4 + <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
  5 + </td>
  6 + <td>
  7 + <p style="width:550px">
  8 + <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span>
  9 + <span style="font-size: 10px; color: #444444; float: right;"><%= time_ago_as_sentence(activity.created_at) %></span>
  10 + </p>
  11 + </td>
  12 +</tr>
  13 +<tr>
  14 + <td></td>
  15 + <td>
  16 + <%= render :partial => 'profile_comments', :locals => { :activity => activity } %>
  17 + </td>
  18 +</tr>
  19 +</table>
... ...
app/views/person_notifier/mailer/_join_community.rhtml 0 → 100644
... ... @@ -0,0 +1 @@
  1 +<%= render :partial => 'default_activity', :locals => { :activity => activity } %>
... ...
app/views/person_notifier/mailer/_leave_scrap.rhtml 0 → 100644
... ... @@ -0,0 +1 @@
  1 +<%= render :partial => 'default_activity', :locals => { :activity => activity } %>
... ...
app/views/person_notifier/mailer/_leave_scrap_to_self.rhtml 0 → 120000
... ... @@ -0,0 +1 @@
  1 +_leave_scrap.rhtml
0 2 \ No newline at end of file
... ...
app/views/person_notifier/mailer/_new_friendship.rhtml 0 → 100644
... ... @@ -0,0 +1 @@
  1 +<%= render :partial => 'default_activity', :locals => { :activity => activity } %>
... ...
app/views/person_notifier/mailer/_profile_comments.rhtml 0 → 100644
... ... @@ -0,0 +1,13 @@
  1 +<% if activity.comments_count > 2 %>
  2 + <div style="font-size: 10px;">
  3 + <% if activity.params['url'].blank? %>
  4 + <%= _("%s comments") % activity.comments_count %>
  5 + <% else %>
  6 + <%= link_to(_("View all %s comments") % activity.comments_count, activity.params['url']) %>
  7 + <% end %>
  8 + </div>
  9 +<% else %>
  10 + <ul>
  11 + <%= render :partial => 'comment', :collection => activity.comments %>
  12 + </ul>
  13 +<% end %>
... ...
app/views/person_notifier/mailer/_reply_scrap_on_self.rhtml 0 → 120000
... ... @@ -0,0 +1 @@
  1 +_leave_scrap.rhtml
0 2 \ No newline at end of file
... ...
app/views/person_notifier/mailer/_upload_image.rhtml 0 → 100644
... ... @@ -0,0 +1,15 @@
  1 +<table>
  2 + <tr>
  3 + <td>
  4 + <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
  5 + </td>
  6 + <td>
  7 + <p style="width:550px">
  8 + <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span>
  9 + <span style="font-size: 10px; color: #444444; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span>
  10 + </p>
  11 + </td>
  12 +</tr>
  13 +</table>
  14 +<div title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-newgallery'></div>
  15 +<br/>
... ...
app/views/person_notifier/mailer/content_summary.rhtml 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +<h3><%= _("%s's network activity") % @profile.name %></h3>
  2 +<br/>
  3 +<div>
  4 +<% @notifications.each do |activity| %>
  5 + <div style="border-left:none;border-right:none;border-top:1px solid #ccc;border-bottom:none;padding:10px;width:600px">
  6 + <%= render :partial => activity.verb, :locals => { :activity => activity } rescue "cannot render notification for #{activity.verb}" %>
  7 + </div>
  8 +<% end %>
  9 +</div>
  10 +
  11 +<div style="color:#444444;font-size:11px;">
  12 +<p><%= _("Greetings,") %></p>
  13 +<br/>
  14 +<p>--</p>
  15 +<p><%= _('%s team.') % @environment %></p>
  16 +<p><%= url_for @url %></p>
  17 +</div>
  18 +<br/>
... ...
app/views/profile_editor/_person.rhtml
... ... @@ -19,3 +19,8 @@
19 19 <%= @plugins.dispatch(:profile_info_extra_contents).collect { |content| instance_eval(&content) }.join("") %>
20 20  
21 21 <%= render :partial => 'person_form', :locals => {:f => f} %>
  22 +
  23 + <h2><%= _('Notification options') %></h2>
  24 + <div>
  25 + <%= select_tag 'profile_data[notification_time]', options_for_select([[_('Disabled'), 0], [_('Hourly'), 1], [_('Half Day'), 12], [_('Daily'), 24]], @profile.notification_time) %>
  26 + </div>
... ...
app/views/profile_editor/index.rhtml
... ... @@ -22,7 +22,7 @@
22 22  
23 23 <%= control_panel_button(_('Edit sideboxes'), 'blocks', :controller => 'profile_design', :action => 'index') %>
24 24  
25   - <%= control_panel_button(_('Edit Appearance'), 'design-editor', :controller => 'themes', :action => 'index') %>
  25 + <%= control_panel_button(_('Edit Appearance'), 'design-editor', :controller => 'profile_themes', :action => 'index') %>
26 26  
27 27 <%= control_panel_button(_('Edit Header and Footer'), 'header-and-footer', :controller => 'profile_editor', :action => 'header_footer') unless profile.enterprise? && environment.enabled?('disable_header_and_footer') && !user.is_admin?(environment) %>
28 28  
... ...
app/views/profile_members/_members_list.rhtml
1   -<% collection = @collection == :profile_admins ? profile.admins : profile.members %>
  1 +<% collection = @collection == :profile_admins ? profile.admins : profile.members_by_name %>
2 2 <% title = @title ? @title : _('Current members') %>
3 3 <% remove_action = @remove_action ? @remove_action : {:action => 'unassociate'} %>
4 4  
... ...
app/views/profile_themes/add_css.rhtml 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +<h2><%= _('Add a CSS file') %></h2>
  2 +
  3 +<% form_tag do %>
  4 + <%= labelled_form_field(_('File name'), text_field_tag('css')) %>
  5 +
  6 + <% button_bar do %>
  7 + <%= submit_button(:add, _('Add')) %>
  8 + <%= lightbox_close_button(_('Cancel')) %>
  9 + <% end %>
  10 +
  11 +<% end %>
... ...
app/views/profile_themes/add_image.rhtml 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 +<% form_tag({:action => 'add_image', :id => @theme.id}, :multipart => true) do %>
  2 + <%= labelled_form_field(_('Choose the image file'), file_field_tag(:image)) %>
  3 + <% button_bar do %>
  4 + <%= submit_button(:add, _('Add image')) %>
  5 + <% end %>
  6 +<% end %>
... ...
app/views/profile_themes/css_editor.rhtml 0 → 100644
... ... @@ -0,0 +1,13 @@
  1 +<h2><%= _('CSS code: "%s"') % @css %></h2>
  2 +
  3 +<% form_tag({:action => 'update_css', :id => @theme.id }, :name => 'csscode_form') do %>
  4 + <%= hidden_field_tag('css', @css) %>
  5 + <%= text_area_tag('csscode', @code, :id => "codepressWindow", :class => 'codepress css') %>
  6 + <% button_bar do %>
  7 + <%= submit_button(:save, _('Save')) %>
  8 + <% end %>
  9 +<% end %>
  10 +
  11 +<!--<script type='text/javascript'>-->
  12 + <!--CodePress.run();-->
  13 +<!--</script>-->
... ...
app/views/profile_themes/edit.rhtml 0 → 100644
... ... @@ -0,0 +1,41 @@
  1 +<form>
  2 + <%# FIXME %>
  3 + <h1 id='theme-name'>
  4 + <%= _('Editing theme "%s"') % @theme.name %>
  5 + <%= button(:eyes, _('Preview this theme'), :action => 'start_test', :id => @theme.id) %>
  6 + <%= button(:back, _('Back'), :action => 'index') %>
  7 + </h1>
  8 +</form>
  9 +
  10 +
  11 +<div id='css-files-list'>
  12 + <h2><%= _('CSS files') %></h2>
  13 + <ul>
  14 + <% for css in @css_files %>
  15 + <li><%= link_to_remote(css, :url => { :action => 'css_editor', :id => @theme.id, :css => css }, :update => { :success => 'css-code' }) %></li>
  16 + <% end %>
  17 + </ul>
  18 + <% button_bar do %>
  19 + <%= lightbox_button(:add, _('New CSS'), :action => 'add_css', :id => @theme.id) %>
  20 + <% end %>
  21 +</div>
  22 +
  23 +<div id='image-files-list'>
  24 + <h2><%= _('Images') %></h2>
  25 + <ul>
  26 + <% for image in @image_files %>
  27 + <li><%= image_tag("/user_themes/#{@theme.id}/images/#{image}") %></li>
  28 + <% end %>
  29 + </ul>
  30 + <% button_bar do %>
  31 + <%= lightbox_button(:add, _('Add image'), :action => 'add_image', :id => @theme.id) %>
  32 + <% end %>
  33 +</div>
  34 +
  35 +<div id='css-code'>
  36 + <center style='padding-top: 5em;'>
  37 + <em><%= _('Select a CSS file to edit') %></em>
  38 + </center>
  39 +</div>
  40 +
  41 +<%# javascript_include_tag 'codepress/codepress' %>
... ...
app/views/profile_themes/index.rhtml 0 → 100644
... ... @@ -0,0 +1,48 @@
  1 +<%= render :partial => 'themes/select_template' %>
  2 +<%= render :partial => 'themes/select_theme' %>
  3 +
  4 +<% if environment.enabled?('user_themes') %>
  5 + <div id="user-themes" class="list-options">
  6 +
  7 + <h2><%= _('My themes') %></h2>
  8 +
  9 + <% for themes in profile.themes.in_groups_of(3) %>
  10 + <div class="list-group">
  11 + <% for theme in themes %><%=
  12 + if theme
  13 +
  14 + selected = theme.id == @current_theme
  15 + sel_html = selected ?
  16 + content_tag('big', _('(current)') ) :
  17 + link_to(_('Use this theme'), :action => 'set', :id => theme.id)
  18 +
  19 + content_tag( 'div',
  20 + image_tag(
  21 + '/images/icons-app/design-editor.png',
  22 + :alt => (_('The "%s" theme.') % theme.name)) +
  23 + '<div class="opt-info">' +
  24 + content_tag('strong', theme.name, :class => 'name') +
  25 + ' <br/> '+ sel_html +' <br/> ' +
  26 + link_to(_('Edit this theme'), :action => 'edit', :id => theme.id) +
  27 + ' <br/> ' +
  28 + link_to(_('Test this theme'), :action => 'start_test', :id => theme.id) +
  29 + '</div>',
  30 + :class => 'theme-opt list-opt' + (selected ? ' selected' : '')
  31 + )
  32 +
  33 + end
  34 + %><% end %>
  35 + </div>
  36 + <% end %>
  37 +
  38 + </div><!-- end id="user-themes" -->
  39 +<% end %>
  40 +
  41 +<br style="clear:both" />
  42 +
  43 +<% button_bar do %>
  44 + <% if environment.enabled?('user_themes') %>
  45 + <%= lightbox_button(:add, _('New theme ...'), :action => 'new') %>
  46 + <% end %>
  47 + <%= button(:back, _('Back'), :controller => 'profile_editor', :action => 'index') %>
  48 +<% end %>
... ...
app/views/profile_themes/new.rhtml 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +<h2><%= _('Create new theme') %></h2>
  2 +
  3 +<% form_tag(:action => 'new') do %>
  4 +
  5 + <%= labelled_form_field(_('Name of the new theme:'), text_field_tag(:name)) %>
  6 +
  7 + <% button_bar do %>
  8 + <%= submit_button(:save, _('Create')) %>
  9 + <% end %>
  10 +<% end %>
... ...
app/views/shared/_lead_and_body.rhtml
... ... @@ -33,4 +33,4 @@
33 33 <% end %>
34 34 </div>
35 35  
36   -<%= javascript_include_tag 'article'%>
  36 +<%= javascript_include_tag 'article-lead-and-body'%>
... ...
app/views/shared/_select_categories.rhtml
1   -<div id="category-ajax-selector">
  1 +<% extend CategoriesHelper %>
  2 +
2 3 <% if !@current_category.nil? %>
3   - <h3 class="box-title"><%= _('Current category:') %></h3>
4 4 <%= hidden_field_tag "#{object_name}[#{object_name}_category_id]", @current_category.id unless multiple %>
  5 + <%= hidden_field_tag "#{object_name}[category_ids][]", @current_category.id if multiple %>
  6 + <%= button_to_remote_without_text(:back, _('Back'),
  7 + { :update => "select-categories",
  8 + :url => { :action => 'update_categories', :id => @object },
  9 + :loaded => visual_effect(:highlight, "select-categories")
  10 + },
  11 + :id => 'cancel-category-button') %>
5 12 <%
6 13 categories = [@current_category]
7 14 categories.push(@current_category) while @current_category = @current_category.parent
8 15 %>
9 16 <%= categories.compact.reverse.map{|i|
10   - link_to_remote(i.name,
  17 + link_to_remote(i.name,
11 18 :update => "select-categories",
12 19 :url => { :action => 'update_categories', :category_id => i.id, :id => @object },
13 20 :loaded => visual_effect(:highlight, "select-categories"),
14 21 :class => 'select-current-category-link')}.join(' &rarr; ')
15 22 %>
16   - <strong>
17   - <%= button_to_function_without_text(:save, _('Save'), nil, :id => 'save-category-button') do |page|
18   - page.insert_html :bottom, 'selected-categories', content_tag('li', categories.first.full_name +
  23 + <%= button_to_function_without_text(:add, _('Add'), nil, :id => 'save-category-button') do |page|
  24 + page.insert_html :bottom, 'selected-categories', content_tag('div',
19 25 hidden_field_tag("#{object_name}[category_ids][]", categories.first.id) +
20   - button_to_function_without_text(:cancel, _('Remove'), nil, :id => "remove-selected-category-#{categories.first.id}-button") {|page| page["selected-category-#{categories.first.id}"].remove}, :id => "selected-category-#{categories.first.id}")
  26 + selected_category_link(categories.first), :id => "selected-category-#{categories.first.id}")
  27 + page.replace_html 'select-categories', :partial => 'shared/select_subcategories',
  28 + :locals => {:object_name => object_name, :categories => @toplevel_categories}
21 29 end if multiple %>
22   - <%= button_to_remote_without_text(:cancel, _('Cancel'),
23   - { :update => "select-categories",
24   - :url => { :action => 'update_categories', :id => @object },
25   - :loaded => visual_effect(:highlight, "select-categories")
26   - },
27   - :id => 'cancel-category-button') %>
28   - </strong>
29   -<% else %>
30   - <h3 class="box-title"><%= _('Select a category:') %></h3>
31 30 <% end %>
32 31  
33   -<% if !@categories.empty? %>
34   - <h3><%= _('Categories:') %></h3>
35   - <% @categories.select{|i| !@object.respond_to?(:accept_category?) || @object.accept_category?(i)}.each do |category| %>
36   - <%= link_to_remote category.name,
37   - { :update => "select-categories",
38   - :url => { :action => "update_categories", :category_id => category.id, :id => @object},
39   - :loaded => visual_effect(:highlight, "select-categories")
40   - },
41   - :class => 'select-subcategory-link',
42   - :id => "select-category-#{category.id}-link"
43   - %>
44   - <% end %> &nbsp;
45   -<% end %>
  32 +<div class="toplevel-categories">
  33 + <%= render :partial => 'shared/select_subcategories', :locals => {:object_name => object_name, :categories => @categories} %>
46 34 </div>
... ...