Commit d35779c07490f70c33e688afa945036e075a90f2
Exists in
master
and in
23 other branches
Merge branch 'master' into rails-2.3.5
Conflicts: app/controllers/admin_controller.rb app/controllers/application.rb app/controllers/public/account_controller.rb app/controllers/public/content_viewer_controller.rb lib/noosfero/i18n.rb test/functional/account_controller_test.rb test/functional/admin_controller_test.rb test/unit/contact_test.rb test/unit/profile_test.rb
Showing
842 changed files
with
113986 additions
and
21393 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 842 files displayed.
.mailmap
| @@ -3,7 +3,8 @@ Antonio Terceiro <terceiro@colivre.coop.br> <terceiro@softwarelivre.org> | @@ -3,7 +3,8 @@ Antonio Terceiro <terceiro@colivre.coop.br> <terceiro@softwarelivre.org> | ||
| 3 | Aurelio A. Heckert <aurelio@colivre.coop.br> <AurelioAHeckert@3f533792-8f58-4932-b0fe-aaf55b0a4547> | 3 | Aurelio A. Heckert <aurelio@colivre.coop.br> <AurelioAHeckert@3f533792-8f58-4932-b0fe-aaf55b0a4547> |
| 4 | Aurelio A. Heckert <aurelio@colivre.coop.br> <aurelio@colivre.coop.br> | 4 | Aurelio A. Heckert <aurelio@colivre.coop.br> <aurelio@colivre.coop.br> |
| 5 | Aurelio A. Heckert <aurelio@colivre.coop.br> <aurium@gmail.com> | 5 | Aurelio A. Heckert <aurelio@colivre.coop.br> <aurium@gmail.com> |
| 6 | -Caio SBA <caiosba@gmail.com> <caiosba@safernet.org.br> | 6 | +Caio SBA <caio@colivre.coop.br> <caiosba@gmail.com> |
| 7 | +Caio SBA <caio@colivre.coop.br> <caiosba@safernet.org.br> | ||
| 7 | Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> <DanielaFeitosa@3f533792-8f58-4932-b0fe-aaf55b0a4547> | 8 | Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> <DanielaFeitosa@3f533792-8f58-4932-b0fe-aaf55b0a4547> |
| 8 | Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> <danielafeitosa@colivre.coop.br> | 9 | Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> <danielafeitosa@colivre.coop.br> |
| 9 | Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> <daniela@sede.colivre.coop.br> | 10 | Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> <daniela@sede.colivre.coop.br> |
AUTHORS
| @@ -8,8 +8,9 @@ Developers | @@ -8,8 +8,9 @@ Developers | ||
| 8 | 8 | ||
| 9 | Antonio Terceiro <terceiro@colivre.coop.br> | 9 | Antonio Terceiro <terceiro@colivre.coop.br> |
| 10 | Aurelio A. Heckert <aurelio@colivre.coop.br> | 10 | Aurelio A. Heckert <aurelio@colivre.coop.br> |
| 11 | +Braulio Bhavamitra <brauliobo@gmail.com> | ||
| 11 | Bráulio Bhavamitra <brauliobo@gmail.com> | 12 | Bráulio Bhavamitra <brauliobo@gmail.com> |
| 12 | -Caio SBA <caiosba@gmail.com> | 13 | +Caio SBA <caio@colivre.coop.br> |
| 13 | Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> | 14 | Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> |
| 14 | Daniel Cunha <daniel@colivre.coop.br> | 15 | Daniel Cunha <daniel@colivre.coop.br> |
| 15 | Fernanda Lopes <nanda.listas+psl@gmail.com> | 16 | Fernanda Lopes <nanda.listas+psl@gmail.com> |
| @@ -23,6 +24,7 @@ LinguÁgil 2010 <linguagil.bahia@gmail.com> | @@ -23,6 +24,7 @@ LinguÁgil 2010 <linguagil.bahia@gmail.com> | ||
| 23 | Martín Olivera <molivera@solar.org.ar> | 24 | Martín Olivera <molivera@solar.org.ar> |
| 24 | Moises Machado <moises@colivre.coop.br> | 25 | Moises Machado <moises@colivre.coop.br> |
| 25 | Nanda Lopes <nanda.listas+psl@gmail.com> | 26 | Nanda Lopes <nanda.listas+psl@gmail.com> |
| 27 | +Rafael Gomes <rafaelgomes@techfree.com.br> | ||
| 26 | Raphaël Rousseau <raph@r4f.org> | 28 | Raphaël Rousseau <raph@r4f.org> |
| 27 | Raquel Lira <raquel.lira@gmail.com> | 29 | Raquel Lira <raquel.lira@gmail.com> |
| 28 | Rodrigo Souto <rodrigo@colivre.coop.br> | 30 | Rodrigo Souto <rodrigo@colivre.coop.br> |
HACKING
| @@ -31,11 +31,13 @@ You can copy and paste the commands below into a terminal (please review the | @@ -31,11 +31,13 @@ You can copy and paste the commands below into a terminal (please review the | ||
| 31 | commands and make sure you understand what you are doing): | 31 | commands and make sure you understand what you are doing): |
| 32 | 32 | ||
| 33 | # checkout the code from repository | 33 | # checkout the code from repository |
| 34 | - git clone git://git.colivre.coop.br/noosfero.git | 34 | + git clone git://gitorious.org/noosfero/noosfero.git |
| 35 | # enter the directory | 35 | # enter the directory |
| 36 | cd noosfero | 36 | cd noosfero |
| 37 | # copy a sample config file | 37 | # copy a sample config file |
| 38 | cp config/database.yml.sqlite3 config/database.yml | 38 | cp config/database.yml.sqlite3 config/database.yml |
| 39 | + # create tmp directory if it doesn't exist | ||
| 40 | + mkdir tmp | ||
| 39 | # create the development database | 41 | # create the development database |
| 40 | rake db:schema:load | 42 | rake db:schema:load |
| 41 | # run pending migrations | 43 | # run pending migrations |
| @@ -59,8 +61,8 @@ another port than 3000, you can use the -p option of ./script/server: | @@ -59,8 +61,8 @@ another port than 3000, you can use the -p option of ./script/server: | ||
| 59 | 61 | ||
| 60 | The above command makes the server available at http://localhost:9999/ | 62 | The above command makes the server available at http://localhost:9999/ |
| 61 | 63 | ||
| 62 | -The sample-data data scripts creates one administrator user with login "ze" and | ||
| 63 | -password "test". | 64 | +The sample-data data scripts creates two administrator users with login "ze" and |
| 65 | +password "test" and login "adminuser" and password "admin". | ||
| 64 | 66 | ||
| 65 | Note that some operations, like generating image thumbnails, sending e-mails, | 67 | Note that some operations, like generating image thumbnails, sending e-mails, |
| 66 | etc, are done in background in the context of a service independent from the | 68 | etc, are done in background in the context of a service independent from the |
| @@ -84,3 +86,7 @@ you want to enable it then you need to change some files: | @@ -84,3 +86,7 @@ you want to enable it then you need to change some files: | ||
| 84 | 86 | ||
| 85 | 3) Add in config/noosfero.yml at development section: | 87 | 3) Add in config/noosfero.yml at development section: |
| 86 | exception_recipients: [admin@example.com] | 88 | exception_recipients: [admin@example.com] |
| 89 | + | ||
| 90 | +== Releasing and building Debian package | ||
| 91 | + | ||
| 92 | +See RELEASING file. |
INSTALL
| @@ -43,6 +43,9 @@ case will need do install hicolor-icon-theme as well bacause tango-icon-theme | @@ -43,6 +43,9 @@ case will need do install hicolor-icon-theme as well bacause tango-icon-theme | ||
| 43 | depends on it. After that you can try the command line above again, but | 43 | depends on it. After that you can try the command line above again, but |
| 44 | without "tango-icon-theme". | 44 | without "tango-icon-theme". |
| 45 | 45 | ||
| 46 | +More Informations to install the tango-icon-theme on Debian Lenny: | ||
| 47 | +* http://packages.debian.org/en/lenny/all/tango-icon-theme/download | ||
| 48 | + | ||
| 46 | If you manage to install Noosfero successfully on other systems than Debian, | 49 | If you manage to install Noosfero successfully on other systems than Debian, |
| 47 | please feel free to contact the Noosfero development mailing with the | 50 | please feel free to contact the Noosfero development mailing with the |
| 48 | instructions for doing so, and we'll include it here. | 51 | instructions for doing so, and we'll include it here. |
| @@ -98,7 +101,7 @@ downloading from git | @@ -98,7 +101,7 @@ downloading from git | ||
| 98 | Here we are cloning the noosfero repository from git. Note: you will need to | 101 | Here we are cloning the noosfero repository from git. Note: you will need to |
| 99 | install git before. | 102 | install git before. |
| 100 | 103 | ||
| 101 | -$ git clone git://git.colivre.coop.br/noosfero.git current | 104 | +$ git clone git://gitorious.org/noosfero/noosfero.git current |
| 102 | $ cd current | 105 | $ cd current |
| 103 | $ git checkout -b stable origin/stable | 106 | $ git checkout -b stable origin/stable |
| 104 | 107 |
INSTALL.chat
| @@ -221,16 +221,19 @@ Note: module proxy_http must be enabled: | @@ -221,16 +221,19 @@ Note: module proxy_http must be enabled: | ||
| 221 | 221 | ||
| 222 | # a2enmod proxy_http | 222 | # a2enmod proxy_http |
| 223 | 223 | ||
| 224 | - | ||
| 225 | 8. DNS configuration | 224 | 8. DNS configuration |
| 226 | 225 | ||
| 227 | - * /etc/bind/db.colivre: | 226 | +For this point, we assume you are using BIND as your DNS server. You need to |
| 227 | +add the following entries to the DNS zone file corresponding to the domain | ||
| 228 | +of your noosfero site: | ||
| 228 | 229 | ||
| 229 | _xmpp-client._tcp SRV 5 100 5222 master | 230 | _xmpp-client._tcp SRV 5 100 5222 master |
| 230 | -(...) | ||
| 231 | conference CNAME master | 231 | conference CNAME master |
| 232 | _xmpp-client._tcp.conference SRV 5 100 5222 master | 232 | _xmpp-client._tcp.conference SRV 5 100 5222 master |
| 233 | 233 | ||
| 234 | +If you are running a DNS server other than BIND, you will have to figure out | ||
| 235 | +how to create equivalente rules for your zone file. Patches to this | ||
| 236 | +documentation are welcome. | ||
| 234 | 237 | ||
| 235 | 9. Testing this Setup | 238 | 9. Testing this Setup |
| 236 | 239 |
| @@ -0,0 +1,163 @@ | @@ -0,0 +1,163 @@ | ||
| 1 | +== Multitenancy support | ||
| 2 | + | ||
| 3 | +Multitenancy refers to a principle in software architecture where a | ||
| 4 | +single instance of the software runs on a server, serving multiple | ||
| 5 | +client organizations (tenants). Multitenancy is contrasted with a | ||
| 6 | +multi-instance architecture where separate software instances (or | ||
| 7 | +hardware systems) are set up for different client organizations. With | ||
| 8 | +a multitenant architecture, a software application is designed to | ||
| 9 | +virtually partition its data and configuration, and each client | ||
| 10 | +organization works with a customized virtual application instance. | ||
| 11 | + | ||
| 12 | +Today this feature is available only for PostgreSQL databases. | ||
| 13 | + | ||
| 14 | +This document assumes that you have a new fully PostgresSQL default Noosfero | ||
| 15 | +installation as explained at the INSTALL file. | ||
| 16 | + | ||
| 17 | +== Separated data | ||
| 18 | + | ||
| 19 | +The items below are separated for each hosted environment: | ||
| 20 | + | ||
| 21 | +* Uploaded files | ||
| 22 | +* Database | ||
| 23 | +* Ferret index | ||
| 24 | +* ActiveRecord#cache_key | ||
| 25 | +* Feed updater | ||
| 26 | +* Delayed Job Workers | ||
| 27 | + | ||
| 28 | +== Database configuration file | ||
| 29 | + | ||
| 30 | +The file config/database.yml must follow a structure in order to | ||
| 31 | +achieve multitenancy support. In this example, we will set 3 | ||
| 32 | +different environments: env1, env2 and env3. | ||
| 33 | + | ||
| 34 | +Each "hosted" environment must have an entry like this: | ||
| 35 | + | ||
| 36 | +env1_production: | ||
| 37 | + adapter: postgresql | ||
| 38 | + encoding: unicode | ||
| 39 | + database: noosfero | ||
| 40 | + schema_search_path: public | ||
| 41 | + username: noosfero | ||
| 42 | + domains: | ||
| 43 | + - env1.com | ||
| 44 | + - env1.org | ||
| 45 | + | ||
| 46 | +env2_production: | ||
| 47 | + adapter: postgresql | ||
| 48 | + encoding: unicode | ||
| 49 | + database: noosfero | ||
| 50 | + schema_search_path: env2 | ||
| 51 | + username: noosfero | ||
| 52 | + domains: | ||
| 53 | + - env2.com | ||
| 54 | + - env2.org | ||
| 55 | + | ||
| 56 | +env3_production: | ||
| 57 | + adapter: postgresql | ||
| 58 | + encoding: unicode | ||
| 59 | + database: noosfero | ||
| 60 | + schema_search_path: env3 | ||
| 61 | + username: noosfero | ||
| 62 | + domains: | ||
| 63 | + - env3.com | ||
| 64 | + - env3.net | ||
| 65 | + | ||
| 66 | +The "hosted" environments define, besides the schema_search_path, a | ||
| 67 | +list of domains that, when accessed, tells which database the | ||
| 68 | +application should use. Also, the environment name must end with | ||
| 69 | +'_hosting', where 'hosting' is the name of the hosting environment. | ||
| 70 | + | ||
| 71 | +You must also tell the application which is the default environment. | ||
| 72 | + | ||
| 73 | +production: | ||
| 74 | + env1_production | ||
| 75 | + | ||
| 76 | +On the example above there are only three hosted environments, but it | ||
| 77 | +can be more than three. The schemas 'env2' and 'env3' must already | ||
| 78 | +exist in the same database of the hosting environment. As postgres | ||
| 79 | +user, you can create them typing: | ||
| 80 | + | ||
| 81 | +$ psql database_name -c "CREATE SCHEMA env2 AUTHORIZATION database_user" | ||
| 82 | +$ psql database_name -c "CREATE SCHEMA env3 AUTHORIZATION database_user" | ||
| 83 | + | ||
| 84 | +Replace database_name and database_user above with your stuff. | ||
| 85 | + | ||
| 86 | +So, yet on this same example, when a user accesses http://env2.com or | ||
| 87 | +http://env2.org, the Noosfero application running on production will | ||
| 88 | +turn the database schema to 'env2'. When the access is from domains | ||
| 89 | +http://env3.com or http://env3.net, the schema to be loaded will be | ||
| 90 | +'env3'. | ||
| 91 | + | ||
| 92 | +There is an example of this file in config/database.yml.multitenancy | ||
| 93 | + | ||
| 94 | +== Preparing the database | ||
| 95 | + | ||
| 96 | +Now create the environments: | ||
| 97 | + | ||
| 98 | +$ RAILS_ENV=production rake multitenancy:create | ||
| 99 | + | ||
| 100 | +This command above will create the hosted environment files equal to | ||
| 101 | +their hosting environment, here called 'production'. | ||
| 102 | + | ||
| 103 | +Run db:schema:load for each other environment: | ||
| 104 | + | ||
| 105 | +$ RAILS_ENV=env2_production rake db:schema:load | ||
| 106 | +$ RAILS_ENV=env3_production rake db:schema:load | ||
| 107 | + | ||
| 108 | +Then run the migrations for the hosting environment, and it will | ||
| 109 | +run for each of its hosted environments: | ||
| 110 | + | ||
| 111 | +RAILS_ENV=production rake db:migrate | ||
| 112 | + | ||
| 113 | +== Start Noosfero | ||
| 114 | + | ||
| 115 | +Run Noosfero init file as root: | ||
| 116 | + | ||
| 117 | +# invoke-rc.d noosfero start | ||
| 118 | + | ||
| 119 | +== Ferret | ||
| 120 | + | ||
| 121 | +It's necessary to run only one instance of ferret_server. Don't worry | ||
| 122 | +about this, Noosfero initializer had already done this for you. | ||
| 123 | + | ||
| 124 | +== Feed updater & Delayed job | ||
| 125 | + | ||
| 126 | +Just for your information, a daemon of feed-updater and delayed_job | ||
| 127 | +must be running for each environment. Noosfero initializer do this, | ||
| 128 | +relax. | ||
| 129 | + | ||
| 130 | +== Uploaded files | ||
| 131 | + | ||
| 132 | +When running with PostgreSQL, Noosfero uploads stuff to a folder named | ||
| 133 | +the same way as the running schema. Inside the upload folder root, for | ||
| 134 | +example, will be public/image_uploads/env2 and public/image_uploads/env3. | ||
| 135 | + | ||
| 136 | +== Adding multitenancy support to an existing Noosfero environment | ||
| 137 | + | ||
| 138 | +If you already have a Noosfero environment, you can turn it multitenant | ||
| 139 | +by following the steps below in addition to the previous steps: | ||
| 140 | + | ||
| 141 | +1. Reindex your database | ||
| 142 | + | ||
| 143 | +Rebuild the Ferret index by running the following task just | ||
| 144 | +for your hosting environment, do this as noosfero user: | ||
| 145 | + | ||
| 146 | +$ RAILS_ENV=production rake multitenancy:reindex | ||
| 147 | + | ||
| 148 | +2. Move the uploaded files to the right place | ||
| 149 | + | ||
| 150 | +Add a directory with the same name as your schema name (by default this | ||
| 151 | +name is 'public') in the root of each upload directory, for example, | ||
| 152 | +public/articles/0000 will be moved to public/articles/public/0000. Do this | ||
| 153 | +with the directories public/image_uploads, public/articles and public/thumbnails. | ||
| 154 | + | ||
| 155 | +3. Fix paths on activities | ||
| 156 | + | ||
| 157 | +The profile activities store static paths to the images, so it's necessary to fix | ||
| 158 | +these paths. You can do this easily by setting an alias on your webserver. | ||
| 159 | +On Apache you can add the three rules below, where 'public' is the schema name: | ||
| 160 | + | ||
| 161 | + RewriteRule ^/articles(.+) /articles/public$1 | ||
| 162 | + RewriteRule ^/image_uploads(.+) /image_uploads/public$1 | ||
| 163 | + RewriteRule ^/thumbnails(.+) /thumbnails/public$1 |
INSTALL.varnish
| @@ -50,14 +50,22 @@ apache-compatible format. You should change your statistics generation software | @@ -50,14 +50,22 @@ apache-compatible format. You should change your statistics generation software | ||
| 50 | 50 | ||
| 51 | # invoke-rc.d varnish restart | 51 | # invoke-rc.d varnish restart |
| 52 | 52 | ||
| 53 | -6) Configure varnish to store separate caches for each language | 53 | +6) Configure varnish to fit noosfero |
| 54 | +(assuming Noosfero is installed in /var/lib/noosfero) | ||
| 54 | 55 | ||
| 55 | -6a) Add the following line to your /etc/varnish/default.vcl file (assuming | ||
| 56 | -Noosfero is installed in /var/lib/noosfero): | 56 | +6a) Configure noosfero to do specific routines to varnish |
| 57 | + | ||
| 58 | +Add the following line to your /etc/varnish/default.vcl file: | ||
| 59 | + | ||
| 60 | + include "/var/lib/noosfero/etc/noosfero/varnish-noosfero.vcl"; | ||
| 61 | + | ||
| 62 | +6b) Configure varnish to store separate caches for each language | ||
| 63 | + | ||
| 64 | +Add the following line to your /etc/varnish/default.vcl file: | ||
| 57 | 65 | ||
| 58 | include "/var/lib/noosfero/etc/noosfero/varnish-accept-language.vcl"; | 66 | include "/var/lib/noosfero/etc/noosfero/varnish-accept-language.vcl"; |
| 59 | 67 | ||
| 60 | -6b) Restart Varnish | 68 | +7) Restart Varnish |
| 61 | 69 | ||
| 62 | # invoke-rc.d varnish restart | 70 | # invoke-rc.d varnish restart |
| 63 | 71 |
RELEASING
| @@ -12,28 +12,28 @@ This file documents release-related activities. | @@ -12,28 +12,28 @@ This file documents release-related activities. | ||
| 12 | 12 | ||
| 13 | == Releasing noosfero | 13 | == Releasing noosfero |
| 14 | 14 | ||
| 15 | +Considering you are on a Debian GNU/Linux or Debian-based system | ||
| 16 | + # apt-get install devscripts debhelper | ||
| 17 | + | ||
| 15 | To prepare a release of noosfero, you must follow the steps below: | 18 | To prepare a release of noosfero, you must follow the steps below: |
| 16 | 19 | ||
| 17 | -* finish all requirements and bugs assigned to the to-be-released version | ||
| 18 | -* make sure all tests pass | ||
| 19 | -* write release notes at the version's wiki topic. | ||
| 20 | -* generate package with <tt>rake package</tt>. Your tarball will be under the pkg/ | ||
| 21 | - directory, named as noosfero-${VERSION}.tar.gz | ||
| 22 | -* test that the package contains everything that is needed: explode the tarball | ||
| 23 | - in a temporary directory, copy config/database.yml.sqlite3 to | ||
| 24 | - config/database.yml, and make <tt>rake db:migrate</tt> and <tt>rake test</tt>. If | ||
| 25 | - everything is ok, you are done. If not, maybe some files are not going into | ||
| 26 | - the tarball. See lib/tasks/package.rake, probably you'll need to change it. | ||
| 27 | -* Go to the version's wiki topic and edit it to reflect the new reality. | ||
| 28 | -* Attach the generated package to that topic. Before attaching calculate the md5 of the package (with mu5sum and paste the MD5 hash as comment in the attachment form) | 20 | +* Finish all requirements and bugs assigned to the to-be-released version |
| 21 | +* Make sure all tests pass | ||
| 22 | +* Change the version in lib/noosfero.rb and debian/changelog to the | ||
| 23 | + to-be-released version (e.g. 0.2.0, 0.3.1) | ||
| 24 | +* Write release notes at the version's wiki topic | ||
| 25 | +* Generate packages with <tt>rake noosfero:release</tt>. Your tarball and deb | ||
| 26 | + pkg will be under the pkg/ directory. This task will create a git tag too. | ||
| 27 | +* Test that the tarball and deb package are ok | ||
| 28 | +* Go to the version's wiki topic and edit it to reflect the new reality | ||
| 29 | +* Edit the topic WebPreferences and update DEBIAN_REPOSITORY_TOPICS setting | ||
| 30 | +* Attach the generated packages to that topic. Before attaching calculate the | ||
| 31 | + sha1 of the package (with sha1sum and paste the SHA1 hash as comment in the | ||
| 32 | + attachment form) | ||
| 29 | * Download the attached and verify the MD5 hash | 33 | * Download the attached and verify the MD5 hash |
| 30 | -* create a git tag for the released version with <tt>git tag</tt>. | ||
| 31 | -* IMMEDIATELY change the version in lib/noosfero.rb to the next version. (e.g. | ||
| 32 | - 0.2.0 -> 0.3.0) | ||
| 33 | -* update an eventual demonstration version that you run. | ||
| 34 | -* write an announcement e-mail to the relevant maimling lists pointing to the release notes, and maybe to the demonstration version. | 34 | +* Update an eventual demonstration version that you run. |
| 35 | +* Write an announcement e-mail to the relevant mailing lists pointing to the | ||
| 36 | + release notes, and maybe to the demonstration version. | ||
| 35 | 37 | ||
| 36 | If you had any problem during these steps, you can do <tt>rake clobber_package</tt> to | 38 | If you had any problem during these steps, you can do <tt>rake clobber_package</tt> to |
| 37 | completely delete the generated packages and start the process again. | 39 | completely delete the generated packages and start the process again. |
| 38 | - | ||
| 39 | - |
app/controllers/admin/admin_panel_controller.rb
| 1 | class AdminPanelController < AdminController | 1 | class AdminPanelController < AdminController |
| 2 | 2 | ||
| 3 | - before_filter :login_required | ||
| 4 | - | ||
| 5 | protect 'view_environment_admin_panel', :environment | 3 | protect 'view_environment_admin_panel', :environment |
| 6 | 4 | ||
| 7 | def boxes_holder | 5 | def boxes_holder |
| @@ -11,6 +9,7 @@ class AdminPanelController < AdminController | @@ -11,6 +9,7 @@ class AdminPanelController < AdminController | ||
| 11 | def site_info | 9 | def site_info |
| 12 | if request.post? | 10 | if request.post? |
| 13 | if @environment.update_attributes(params[:environment]) | 11 | if @environment.update_attributes(params[:environment]) |
| 12 | + session[:notice] = _('Environment settings updated') | ||
| 14 | redirect_to :action => 'index' | 13 | redirect_to :action => 'index' |
| 15 | end | 14 | end |
| 16 | end | 15 | end |
app/controllers/admin/categories_controller.rb
| @@ -10,11 +10,16 @@ class CategoriesController < AdminController | @@ -10,11 +10,16 @@ class CategoriesController < AdminController | ||
| 10 | @product_categories = environment.product_categories.find(:all, :conditions => {:parent_id => nil}) | 10 | @product_categories = environment.product_categories.find(:all, :conditions => {:parent_id => nil}) |
| 11 | end | 11 | end |
| 12 | 12 | ||
| 13 | + def get_children | ||
| 14 | + children = Category.find(params[:id]).children | ||
| 15 | + render :partial => 'category_children', :locals => {:children => children} | ||
| 16 | + end | ||
| 17 | + | ||
| 13 | ALLOWED_TYPES = CategoriesHelper::TYPES.map {|item| item[1] } | 18 | ALLOWED_TYPES = CategoriesHelper::TYPES.map {|item| item[1] } |
| 14 | 19 | ||
| 15 | # posts back | 20 | # posts back |
| 16 | def new | 21 | def new |
| 17 | - type = (params[:type] || 'Category') | 22 | + type = (params[:type] || params[:parent_type] || 'Category') |
| 18 | raise 'Type not allowed' unless ALLOWED_TYPES.include?(type) | 23 | raise 'Type not allowed' unless ALLOWED_TYPES.include?(type) |
| 19 | 24 | ||
| 20 | @category = type.constantize.new(params[:category]) | 25 | @category = type.constantize.new(params[:category]) |
app/controllers/admin/plugins_controller.rb
| 1 | class PluginsController < AdminController | 1 | class PluginsController < AdminController |
| 2 | + protect 'edit_environment_features', :environment | ||
| 2 | 3 | ||
| 3 | def index | 4 | def index |
| 4 | @active_plugins = Noosfero::Plugin.all.map {|plugin_name| plugin_name.constantize }.compact | 5 | @active_plugins = Noosfero::Plugin.all.map {|plugin_name| plugin_name.constantize }.compact |
app/controllers/admin/role_controller.rb
| @@ -9,21 +9,6 @@ class RoleController < AdminController | @@ -9,21 +9,6 @@ class RoleController < AdminController | ||
| 9 | @role = environment.roles.find(params[:id]) | 9 | @role = environment.roles.find(params[:id]) |
| 10 | end | 10 | end |
| 11 | 11 | ||
| 12 | - def new | ||
| 13 | - @role = Role.new | ||
| 14 | - end | ||
| 15 | - | ||
| 16 | - def create | ||
| 17 | - @role = Role.new(params[:role]) | ||
| 18 | - @role.environment = environment | ||
| 19 | - if @role.save | ||
| 20 | - redirect_to :action => 'show', :id => @role | ||
| 21 | - else | ||
| 22 | - session[:notice] = _('Failed to create role') | ||
| 23 | - render :action => 'new' | ||
| 24 | - end | ||
| 25 | - end | ||
| 26 | - | ||
| 27 | def edit | 12 | def edit |
| 28 | @role = environment.roles.find(params[:id]) | 13 | @role = environment.roles.find(params[:id]) |
| 29 | end | 14 | end |
| @@ -38,13 +23,4 @@ class RoleController < AdminController | @@ -38,13 +23,4 @@ class RoleController < AdminController | ||
| 38 | end | 23 | end |
| 39 | end | 24 | end |
| 40 | 25 | ||
| 41 | - def destroy | ||
| 42 | - @role = environment.roles.find(params[:id]) | ||
| 43 | - if @role.destroy | ||
| 44 | - redirect_to :action => 'index' | ||
| 45 | - else | ||
| 46 | - session[:notice] = _('Failed to edit role') | ||
| 47 | - redirect_to :action => 'index' | ||
| 48 | - end | ||
| 49 | - end | ||
| 50 | end | 26 | end |
app/controllers/admin_controller.rb
app/controllers/box_organizer_controller.rb
| @@ -82,7 +82,7 @@ class BoxOrganizerController < ApplicationController | @@ -82,7 +82,7 @@ class BoxOrganizerController < ApplicationController | ||
| 82 | def save | 82 | def save |
| 83 | @block = boxes_holder.blocks.find(params[:id]) | 83 | @block = boxes_holder.blocks.find(params[:id]) |
| 84 | @block.update_attributes(params[:block]) | 84 | @block.update_attributes(params[:block]) |
| 85 | - expire_timeout_fragment(@block.cache_keys) | 85 | + expire_timeout_fragment(@block.cache_key) |
| 86 | redirect_to :action => 'index' | 86 | redirect_to :action => 'index' |
| 87 | end | 87 | end |
| 88 | 88 | ||
| @@ -93,7 +93,7 @@ class BoxOrganizerController < ApplicationController | @@ -93,7 +93,7 @@ class BoxOrganizerController < ApplicationController | ||
| 93 | def remove | 93 | def remove |
| 94 | @block = Block.find(params[:id]) | 94 | @block = Block.find(params[:id]) |
| 95 | if @block.destroy | 95 | if @block.destroy |
| 96 | - expire_timeout_fragment(@block.cache_keys) | 96 | + expire_timeout_fragment(@block.cache_key) |
| 97 | redirect_to :action => 'index' | 97 | redirect_to :action => 'index' |
| 98 | else | 98 | else |
| 99 | session[:notice] = _('Failed to remove block') | 99 | session[:notice] = _('Failed to remove block') |
app/controllers/my_profile/cms_controller.rb
| @@ -43,6 +43,9 @@ class CmsController < MyProfileController | @@ -43,6 +43,9 @@ class CmsController < MyProfileController | ||
| 43 | if @parent && @parent.blog? | 43 | if @parent && @parent.blog? |
| 44 | articles -= Article.folder_types.map(&:constantize) | 44 | articles -= Article.folder_types.map(&:constantize) |
| 45 | end | 45 | end |
| 46 | + if user.is_admin?(profile.environment) | ||
| 47 | + articles << RawHTMLArticle | ||
| 48 | + end | ||
| 46 | articles | 49 | articles |
| 47 | end | 50 | end |
| 48 | 51 | ||
| @@ -168,8 +171,7 @@ class CmsController < MyProfileController | @@ -168,8 +171,7 @@ class CmsController < MyProfileController | ||
| 168 | @article = @parent = check_parent(params[:parent_id]) | 171 | @article = @parent = check_parent(params[:parent_id]) |
| 169 | @target = @parent ? ('/%s/%s' % [profile.identifier, @parent.full_name]) : '/%s' % profile.identifier | 172 | @target = @parent ? ('/%s/%s' % [profile.identifier, @parent.full_name]) : '/%s' % profile.identifier |
| 170 | @folders = Folder.find(:all, :conditions => { :profile_id => profile }) | 173 | @folders = Folder.find(:all, :conditions => { :profile_id => profile }) |
| 171 | - @media_listing = params[:media_listing] | ||
| 172 | - if @article && !@media_listing | 174 | + if @article |
| 173 | record_coming | 175 | record_coming |
| 174 | end | 176 | end |
| 175 | if request.post? && params[:uploaded_files] | 177 | if request.post? && params[:uploaded_files] |
| @@ -178,26 +180,14 @@ class CmsController < MyProfileController | @@ -178,26 +180,14 @@ class CmsController < MyProfileController | ||
| 178 | end | 180 | end |
| 179 | @errors = @uploaded_files.select { |f| f.errors.any? } | 181 | @errors = @uploaded_files.select { |f| f.errors.any? } |
| 180 | if @errors.any? | 182 | if @errors.any? |
| 181 | - if @media_listing | ||
| 182 | - flash[:notice] = _('Could not upload all files') | ||
| 183 | - redirect_to :action => 'media_listing' | ||
| 184 | - else | ||
| 185 | - render :action => 'upload_files', :parent_id => @parent_id | ||
| 186 | - end | 183 | + render :action => 'upload_files', :parent_id => @parent_id |
| 187 | else | 184 | else |
| 188 | - if @media_listing | ||
| 189 | - flash[:notice] = _('All files were uploaded successfully') | ||
| 190 | - redirect_to :action => 'media_listing' | 185 | + if @back_to |
| 186 | + redirect_to @back_to | ||
| 187 | + elsif @parent | ||
| 188 | + redirect_to :action => 'view', :id => @parent.id | ||
| 191 | else | 189 | else |
| 192 | - if @back_to | ||
| 193 | - redirect_to @back_to | ||
| 194 | - else | ||
| 195 | - redirect_to( if @parent | ||
| 196 | - {:action => 'view', :id => @parent.id} | ||
| 197 | - else | ||
| 198 | - {:action => 'index'} | ||
| 199 | - end) | ||
| 200 | - end | 190 | + redirect_to :action => 'index' |
| 201 | end | 191 | end |
| 202 | end | 192 | end |
| 203 | end | 193 | end |
| @@ -286,44 +276,28 @@ class CmsController < MyProfileController | @@ -286,44 +276,28 @@ class CmsController < MyProfileController | ||
| 286 | @task = SuggestArticle.new(params[:task]) | 276 | @task = SuggestArticle.new(params[:task]) |
| 287 | if request.post? | 277 | if request.post? |
| 288 | @task.target = profile | 278 | @task.target = profile |
| 289 | - if @task.save | 279 | + if verify_recaptcha(:model => @task, :message => _('Please type the words correctly')) && @task.save |
| 290 | session[:notice] = _('Thanks for your suggestion. The community administrators were notified.') | 280 | session[:notice] = _('Thanks for your suggestion. The community administrators were notified.') |
| 291 | redirect_to @back_to | 281 | redirect_to @back_to |
| 292 | end | 282 | end |
| 293 | end | 283 | end |
| 294 | end | 284 | end |
| 295 | 285 | ||
| 296 | - def media_listing | ||
| 297 | - if params[:image_folder_id] | ||
| 298 | - folder = profile.articles.find(params[:image_folder_id]) if !params[:image_folder_id].blank? | ||
| 299 | - @images = (folder ? folder.children : profile.top_level_articles).images | ||
| 300 | - elsif params[:document_folder_id] | ||
| 301 | - folder = profile.articles.find(params[:document_folder_id]) if !params[:document_folder_id].blank? | ||
| 302 | - @documents = (folder ? folder.children : profile.top_level_articles) | ||
| 303 | - else | ||
| 304 | - @documents = profile.articles | ||
| 305 | - @images = @documents.images | ||
| 306 | - @documents -= @images | ||
| 307 | - end | ||
| 308 | - | ||
| 309 | - @images = @images.paginate(:per_page => per_page, :page => params[:ipage], :order => "updated_at desc") if @images | ||
| 310 | - @documents = @documents.paginate(:per_page => per_page, :page => params[:dpage], :order => "updated_at desc", :conditions => {:is_image => false}) if @documents | ||
| 311 | - | ||
| 312 | - @folders = profile.folders | ||
| 313 | - @image_folders = @folders.select {|f| f.children.any? {|c| c.image?} } | ||
| 314 | - @document_folders = @folders.select {|f| f.children.any? {|c| !c.image? && c.kind_of?(UploadedFile) } } | ||
| 315 | - | ||
| 316 | - @media_listing = true | ||
| 317 | - | ||
| 318 | - respond_to do |format| | ||
| 319 | - format.html { render :layout => false} | ||
| 320 | - format.js { | ||
| 321 | - render :update do |page| | ||
| 322 | - page.replace_html 'media-listing-folder-images', :partial => 'image_thumb', :locals => {:images => @images } if !@images.blank? | ||
| 323 | - page.replace_html 'media-listing-folder-documents', :partial => 'document_link', :locals => {:documents => @documents } if !@documents.blank? | ||
| 324 | - end | ||
| 325 | - } | 286 | + def search |
| 287 | + query = params[:q] | ||
| 288 | + results = query.blank? ? [] : profile.articles.published.find_by_contents(query) | ||
| 289 | + render :text => article_list_to_json(results), :content_type => 'application/json' | ||
| 290 | + end | ||
| 291 | + def media_upload | ||
| 292 | + files_uploaded = [] | ||
| 293 | + parent = check_parent(params[:parent_id]) | ||
| 294 | + files = [:file1,:file2, :file3].map { |f| params[f] }.compact | ||
| 295 | + if request.post? | ||
| 296 | + files.each do |file| | ||
| 297 | + files_uploaded << UploadedFile.create(:uploaded_data => file, :profile => profile, :parent => parent) unless file == '' | ||
| 298 | + end | ||
| 326 | end | 299 | end |
| 300 | + render :text => article_list_to_json(files_uploaded), :content_type => 'text/plain' | ||
| 327 | end | 301 | end |
| 328 | 302 | ||
| 329 | protected | 303 | protected |
| @@ -353,7 +327,7 @@ class CmsController < MyProfileController | @@ -353,7 +327,7 @@ class CmsController < MyProfileController | ||
| 353 | end | 327 | end |
| 354 | 328 | ||
| 355 | def refuse_blocks | 329 | def refuse_blocks |
| 356 | - if ['TinyMceArticle', 'Event', 'EnterpriseHomepage'].include?(@type) | 330 | + if ['TinyMceArticle', 'TextileArticle', 'Event', 'EnterpriseHomepage'].include?(@type) |
| 357 | @no_design_blocks = true | 331 | @no_design_blocks = true |
| 358 | end | 332 | end |
| 359 | end | 333 | end |
| @@ -367,5 +341,21 @@ class CmsController < MyProfileController | @@ -367,5 +341,21 @@ class CmsController < MyProfileController | ||
| 367 | @selected_locale = @article.language || FastGettext.locale | 341 | @selected_locale = @article.language || FastGettext.locale |
| 368 | end | 342 | end |
| 369 | 343 | ||
| 344 | + def article_list_to_json(list) | ||
| 345 | + list.map do |item| | ||
| 346 | + { | ||
| 347 | + 'title' => item.title, | ||
| 348 | + 'url' => item.image? ? item.public_filename(:uploaded) : url_for(item.url), | ||
| 349 | + :icon => icon_for_article(item), | ||
| 350 | + :content_type => item.mime_type, | ||
| 351 | + :error => item.errors.any? ? _('%s could not be uploaded') % item.title : nil, | ||
| 352 | + } | ||
| 353 | + end.to_json | ||
| 354 | + end | ||
| 355 | + | ||
| 356 | + def content_editor? | ||
| 357 | + true | ||
| 358 | + end | ||
| 359 | + | ||
| 370 | end | 360 | end |
| 371 | 361 |
app/controllers/my_profile/manage_products_controller.rb
| @@ -4,6 +4,7 @@ class ManageProductsController < ApplicationController | @@ -4,6 +4,7 @@ class ManageProductsController < ApplicationController | ||
| 4 | protect 'manage_products', :profile, :except => [:show] | 4 | protect 'manage_products', :profile, :except => [:show] |
| 5 | before_filter :check_environment_feature | 5 | before_filter :check_environment_feature |
| 6 | before_filter :login_required, :except => [:show] | 6 | before_filter :login_required, :except => [:show] |
| 7 | + before_filter :create_product?, :only => [:new] | ||
| 7 | 8 | ||
| 8 | protected | 9 | protected |
| 9 | 10 | ||
| @@ -14,6 +15,13 @@ class ManageProductsController < ApplicationController | @@ -14,6 +15,13 @@ class ManageProductsController < ApplicationController | ||
| 14 | end | 15 | end |
| 15 | end | 16 | end |
| 16 | 17 | ||
| 18 | + def create_product? | ||
| 19 | + if !profile.create_product? | ||
| 20 | + render_access_denied | ||
| 21 | + return | ||
| 22 | + end | ||
| 23 | + end | ||
| 24 | + | ||
| 17 | public | 25 | public |
| 18 | 26 | ||
| 19 | def index | 27 | def index |
| @@ -40,8 +48,8 @@ class ManageProductsController < ApplicationController | @@ -40,8 +48,8 @@ class ManageProductsController < ApplicationController | ||
| 40 | end | 48 | end |
| 41 | 49 | ||
| 42 | def new | 50 | def new |
| 43 | - @product = @profile.products.build(:product_category_id => params[:selected_category_id]) | ||
| 44 | - @category = @product.product_category | 51 | + @category = params[:selected_category_id] ? Category.find(params[:selected_category_id]) : nil |
| 52 | + @product = @profile.products.build(:product_category => @category) | ||
| 45 | @categories = ProductCategory.top_level_for(environment) | 53 | @categories = ProductCategory.top_level_for(environment) |
| 46 | @level = 0 | 54 | @level = 0 |
| 47 | if request.post? | 55 | if request.post? |
| @@ -50,7 +58,7 @@ class ManageProductsController < ApplicationController | @@ -50,7 +58,7 @@ class ManageProductsController < ApplicationController | ||
| 50 | render :partial => 'shared/redirect_via_javascript', | 58 | render :partial => 'shared/redirect_via_javascript', |
| 51 | :locals => { :url => url_for(:controller => 'manage_products', :action => 'show', :id => @product) } | 59 | :locals => { :url => url_for(:controller => 'manage_products', :action => 'show', :id => @product) } |
| 52 | else | 60 | else |
| 53 | - render :partial => 'shared/dialog_error_messages', :locals => { :object_name => 'product' } | 61 | + render_dialog_error_messages 'product' |
| 54 | end | 62 | end |
| 55 | end | 63 | end |
| 56 | end | 64 | end |
| @@ -72,7 +80,7 @@ class ManageProductsController < ApplicationController | @@ -72,7 +80,7 @@ class ManageProductsController < ApplicationController | ||
| 72 | 80 | ||
| 73 | def edit_category | 81 | def edit_category |
| 74 | @product = @profile.products.find(params[:id]) | 82 | @product = @profile.products.find(params[:id]) |
| 75 | - @category = @product.product_category | 83 | + @category = @product.product_category || ProductCategory.first |
| 76 | @categories = ProductCategory.top_level_for(environment) | 84 | @categories = ProductCategory.top_level_for(environment) |
| 77 | @edit = true | 85 | @edit = true |
| 78 | @level = @category.level | 86 | @level = @category.level |
| @@ -81,7 +89,7 @@ class ManageProductsController < ApplicationController | @@ -81,7 +89,7 @@ class ManageProductsController < ApplicationController | ||
| 81 | render :partial => 'shared/redirect_via_javascript', | 89 | render :partial => 'shared/redirect_via_javascript', |
| 82 | :locals => { :url => url_for(:controller => 'manage_products', :action => 'show', :id => @product) } | 90 | :locals => { :url => url_for(:controller => 'manage_products', :action => 'show', :id => @product) } |
| 83 | else | 91 | else |
| 84 | - render :partial => 'shared/dialog_error_messages', :locals => { :object_name => 'product' } | 92 | + render_dialog_error_messages 'product' |
| 85 | end | 93 | end |
| 86 | end | 94 | end |
| 87 | end | 95 | end |
| @@ -96,7 +104,7 @@ class ManageProductsController < ApplicationController | @@ -96,7 +104,7 @@ class ManageProductsController < ApplicationController | ||
| 96 | @inputs = @product.inputs | 104 | @inputs = @product.inputs |
| 97 | render :partial => 'display_inputs' | 105 | render :partial => 'display_inputs' |
| 98 | else | 106 | else |
| 99 | - render :partial => 'shared/dialog_error_messages', :locals => { :object_name => 'product' } | 107 | + render_dialog_error_messages 'product' |
| 100 | end | 108 | end |
| 101 | else | 109 | else |
| 102 | render :partial => 'add_input' | 110 | render :partial => 'add_input' |
| @@ -147,7 +155,7 @@ class ManageProductsController < ApplicationController | @@ -147,7 +155,7 @@ class ManageProductsController < ApplicationController | ||
| 147 | @inputs = @product.inputs | 155 | @inputs = @product.inputs |
| 148 | render :partial => 'display_inputs' | 156 | render :partial => 'display_inputs' |
| 149 | else | 157 | else |
| 150 | - render :partial => 'shared/dialog_error_messages', :locals => { :object_name => 'input' } | 158 | + render_dialog_error_messages 'input' |
| 151 | end | 159 | end |
| 152 | end | 160 | end |
| 153 | end | 161 | end |
app/controllers/my_profile/profile_design_controller.rb
| @@ -25,6 +25,7 @@ class ProfileDesignController < BoxOrganizerController | @@ -25,6 +25,7 @@ class ProfileDesignController < BoxOrganizerController | ||
| 25 | blocks << DisabledEnterpriseMessageBlock | 25 | blocks << DisabledEnterpriseMessageBlock |
| 26 | blocks << HighlightsBlock | 26 | blocks << HighlightsBlock |
| 27 | blocks << FeaturedProductsBlock | 27 | blocks << FeaturedProductsBlock |
| 28 | + blocks << FansBlock | ||
| 28 | end | 29 | end |
| 29 | 30 | ||
| 30 | # product block exclusive for enterprises in environments that permits it | 31 | # product block exclusive for enterprises in environments that permits it |
| @@ -37,6 +38,10 @@ class ProfileDesignController < BoxOrganizerController | @@ -37,6 +38,10 @@ class ProfileDesignController < BoxOrganizerController | ||
| 37 | blocks << BlogArchivesBlock | 38 | blocks << BlogArchivesBlock |
| 38 | end | 39 | end |
| 39 | 40 | ||
| 41 | + if user.is_admin?(profile.environment) | ||
| 42 | + blocks << RawHTMLBlock | ||
| 43 | + end | ||
| 44 | + | ||
| 40 | blocks | 45 | blocks |
| 41 | end | 46 | end |
| 42 | 47 |
app/controllers/my_profile/profile_editor_controller.rb
| @@ -4,7 +4,7 @@ class ProfileEditorController < MyProfileController | @@ -4,7 +4,7 @@ class ProfileEditorController < MyProfileController | ||
| 4 | protect 'destroy_profile', :profile, :only => [:destroy_profile] | 4 | protect 'destroy_profile', :profile, :only => [:destroy_profile] |
| 5 | 5 | ||
| 6 | def index | 6 | def index |
| 7 | - @pending_tasks = profile.all_pending_tasks.select{|i| user.has_permission?(i.permission, profile)} | 7 | + @pending_tasks = Task.to(profile).pending.select{|i| user.has_permission?(i.permission, profile)} |
| 8 | end | 8 | end |
| 9 | 9 | ||
| 10 | helper :profile | 10 | helper :profile |
app/controllers/my_profile/profile_members_controller.rb
| 1 | class ProfileMembersController < MyProfileController | 1 | class ProfileMembersController < MyProfileController |
| 2 | protect 'manage_memberships', :profile | 2 | protect 'manage_memberships', :profile |
| 3 | - no_design_blocks | ||
| 4 | 3 | ||
| 5 | def index | 4 | def index |
| 6 | @members = profile.members | 5 | @members = profile.members |
| @@ -15,29 +14,25 @@ class ProfileMembersController < MyProfileController | @@ -15,29 +14,25 @@ class ProfileMembersController < MyProfileController | ||
| 15 | rescue ActiveRecord::RecordNotFound | 14 | rescue ActiveRecord::RecordNotFound |
| 16 | @person = nil | 15 | @person = nil |
| 17 | end | 16 | end |
| 18 | - if !params[:confirmation] && @person && @person.is_last_admin_leaving?(profile, @roles) | ||
| 19 | - redirect_to :action => :last_admin, :roles => params[:roles], :person => @person | ||
| 20 | - else | ||
| 21 | - if @person && @person.define_roles(@roles, profile) | 17 | + |
| 18 | + if @person | ||
| 19 | + if@person.is_last_admin_leaving?(profile, @roles) | ||
| 20 | + redirect_to :action => :last_admin | ||
| 21 | + elsif @person.define_roles(@roles, profile) | ||
| 22 | session[:notice] = _('Roles successfuly updated') | 22 | session[:notice] = _('Roles successfuly updated') |
| 23 | + redirect_to :controller => 'profile_editor' | ||
| 23 | else | 24 | else |
| 24 | session[:notice] = _('Couldn\'t change the roles') | 25 | session[:notice] = _('Couldn\'t change the roles') |
| 26 | + redirect_to :action => 'index' | ||
| 25 | end | 27 | end |
| 26 | - if params[:confirmation] | ||
| 27 | - redirect_to profile.url | ||
| 28 | - else | ||
| 29 | - redirect_to :action => :index | ||
| 30 | - end | 28 | + else |
| 29 | + redirect_to :action => 'index' | ||
| 31 | end | 30 | end |
| 32 | end | 31 | end |
| 33 | - | 32 | + |
| 34 | def last_admin | 33 | def last_admin |
| 35 | - @person = params[:person] | ||
| 36 | - @roles = params[:roles] || [] | ||
| 37 | - @members = profile.members.select {|member| !profile.admins.include?(member)} | ||
| 38 | - @title = _('Current admins') | ||
| 39 | - @collection = :profile_admins | ||
| 40 | - @remove_action = {:action => 'remove_admin'} | 34 | + @roles = [Profile::Roles.admin(environment.id)] |
| 35 | + @pre_population = [].to_json | ||
| 41 | end | 36 | end |
| 42 | 37 | ||
| 43 | def add_role | 38 | def add_role |
| @@ -90,6 +85,7 @@ class ProfileMembersController < MyProfileController | @@ -90,6 +85,7 @@ class ProfileMembersController < MyProfileController | ||
| 90 | end | 85 | end |
| 91 | 86 | ||
| 92 | def add_members | 87 | def add_members |
| 88 | + @roles = Profile::Roles.organization_member_roles(environment.id) | ||
| 93 | end | 89 | end |
| 94 | 90 | ||
| 95 | def add_member | 91 | def add_member |
| @@ -122,19 +118,42 @@ class ProfileMembersController < MyProfileController | @@ -122,19 +118,42 @@ class ProfileMembersController < MyProfileController | ||
| 122 | render :layout => false | 118 | render :layout => false |
| 123 | end | 119 | end |
| 124 | 120 | ||
| 125 | - def find_users | ||
| 126 | - if !params[:query] || params[:query].length <= 2 | ||
| 127 | - @users_found = [] | ||
| 128 | - elsif params[:scope] == 'all_users' | ||
| 129 | - @users_found = Person.find_by_contents(params[:query] + '*').select {|user| !profile.members.include?(user)} | ||
| 130 | - @button_alt = _('Add member') | ||
| 131 | - @add_action = {:action => 'add_member'} | ||
| 132 | - elsif params[:scope] == 'new_admins' | ||
| 133 | - @users_found = Person.find_by_contents(params[:query] + '*').select {|user| profile.members.include?(user) && !profile.admins.include?(user)} | ||
| 134 | - @button_alt = _('Add member') | ||
| 135 | - @add_action = {:action => 'add_admin'} | 121 | + def search_user |
| 122 | + role = Role.find(params[:role]) | ||
| 123 | + render :text => environment.people.find(:all, :conditions => ['LOWER(name) LIKE ? OR LOWER(identifier) LIKE ?', "%#{params['q_'+role.key]}%", "%#{params['q_'+role.key]}%"]). | ||
| 124 | + select { |person| !profile.members_by_role(role).include?(person) }. | ||
| 125 | + map {|person| {:id => person.id, :name => person.name} }. | ||
| 126 | + to_json | ||
| 127 | + end | ||
| 128 | + | ||
| 129 | + def save_associations | ||
| 130 | + error = false | ||
| 131 | + roles = Profile::Roles.organization_member_roles(environment.id) | ||
| 132 | + roles.select { |role| params['q_'+role.key] }.each do |role| | ||
| 133 | + people = [Person.find(params['q_'+role.key].split(','))].flatten | ||
| 134 | + to_remove = profile.members_by_role(role) - people | ||
| 135 | + to_add = people - profile.members_by_role(role) | ||
| 136 | + | ||
| 137 | + begin | ||
| 138 | + to_remove.each { |person| profile.disaffiliate(person, role) } | ||
| 139 | + to_add.each { |person| profile.affiliate(person, role) } | ||
| 140 | + rescue Exception => ex | ||
| 141 | + logger.info ex | ||
| 142 | + error = true | ||
| 143 | + end | ||
| 144 | + end | ||
| 145 | + | ||
| 146 | + if error | ||
| 147 | + session[:notice] = _('The members list couldn\'t be updated. Please contact the administrator.') | ||
| 148 | + redirect_to :action => 'add_members' | ||
| 149 | + else | ||
| 150 | + if profile.admins.blank? && !params[:last_admin] | ||
| 151 | + redirect_to :action => 'last_admin' | ||
| 152 | + else | ||
| 153 | + session[:notice] = _('The members list was updated.') | ||
| 154 | + redirect_to :controller => 'profile_editor' | ||
| 155 | + end | ||
| 136 | end | 156 | end |
| 137 | - render :layout => false | ||
| 138 | end | 157 | end |
| 139 | 158 | ||
| 140 | def send_mail | 159 | def send_mail |
app/controllers/my_profile/tasks_controller.rb
| @@ -3,12 +3,13 @@ class TasksController < MyProfileController | @@ -3,12 +3,13 @@ class TasksController < MyProfileController | ||
| 3 | protect 'perform_task', :profile | 3 | protect 'perform_task', :profile |
| 4 | 4 | ||
| 5 | def index | 5 | def index |
| 6 | - @tasks = profile.all_pending_tasks.sort_by(&:created_at) | 6 | + @filter = params[:filter_type].blank? ? nil : params[:filter_type] |
| 7 | + @tasks = Task.to(profile).pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) | ||
| 7 | @failed = params ? params[:failed] : {} | 8 | @failed = params ? params[:failed] : {} |
| 8 | end | 9 | end |
| 9 | 10 | ||
| 10 | def processed | 11 | def processed |
| 11 | - @tasks = profile.all_finished_tasks.sort_by(&:created_at) | 12 | + @tasks = Task.to(profile).finished.sort_by(&:created_at) |
| 12 | end | 13 | end |
| 13 | 14 | ||
| 14 | VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ] | 15 | VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ] |
app/controllers/public/account_controller.rb
| @@ -4,7 +4,6 @@ class AccountController < ApplicationController | @@ -4,7 +4,6 @@ class AccountController < ApplicationController | ||
| 4 | 4 | ||
| 5 | inverse_captcha :field => 'e_mail' | 5 | inverse_captcha :field => 'e_mail' |
| 6 | 6 | ||
| 7 | - | ||
| 8 | before_filter :login_required, :only => [:activation_question, :accept_terms, :activate_enterprise] | 7 | before_filter :login_required, :only => [:activation_question, :accept_terms, :activate_enterprise] |
| 9 | before_filter :redirect_if_logged_in, :only => [:login, :signup] | 8 | before_filter :redirect_if_logged_in, :only => [:login, :signup] |
| 10 | 9 | ||
| @@ -15,6 +14,17 @@ class AccountController < ApplicationController | @@ -15,6 +14,17 @@ class AccountController < ApplicationController | ||
| 15 | end | 14 | end |
| 16 | end | 15 | end |
| 17 | 16 | ||
| 17 | + def activate | ||
| 18 | + @user = User.find_by_activation_code(params[:activation_code]) if params[:activation_code] | ||
| 19 | + if @user and @user.activate | ||
| 20 | + @message = _("Your account has been activated, now you can log in!") | ||
| 21 | + render :action => 'login', :userlogin => @user.login | ||
| 22 | + else | ||
| 23 | + session[:notice] = _("It looks like you're trying to activate an account. Perhaps have already activated this account?") | ||
| 24 | + redirect_to :controller => :home | ||
| 25 | + end | ||
| 26 | + end | ||
| 27 | + | ||
| 18 | # action to perform login to the application | 28 | # action to perform login to the application |
| 19 | def login | 29 | def login |
| 20 | @user = User.new | 30 | @user = User.new |
| @@ -57,9 +67,8 @@ class AccountController < ApplicationController | @@ -57,9 +67,8 @@ class AccountController < ApplicationController | ||
| 57 | @user.person_data = params[:profile_data] | 67 | @user.person_data = params[:profile_data] |
| 58 | @person = Person.new(params[:profile_data]) | 68 | @person = Person.new(params[:profile_data]) |
| 59 | @person.environment = @user.environment | 69 | @person.environment = @user.environment |
| 60 | - if request.post? && params[self.icaptcha_field].blank? | 70 | + if request.post? |
| 61 | @user.signup! | 71 | @user.signup! |
| 62 | - self.current_user = @user | ||
| 63 | owner_role = Role.find_by_name('owner') | 72 | owner_role = Role.find_by_name('owner') |
| 64 | @user.person.affiliate(@user.person, [owner_role]) if owner_role | 73 | @user.person.affiliate(@user.person, [owner_role]) if owner_role |
| 65 | invitation = Task.find_by_code(@invitation_code) | 74 | invitation = Task.find_by_code(@invitation_code) |
| @@ -67,8 +76,7 @@ class AccountController < ApplicationController | @@ -67,8 +76,7 @@ class AccountController < ApplicationController | ||
| 67 | invitation.update_attributes!({:friend => @user.person}) | 76 | invitation.update_attributes!({:friend => @user.person}) |
| 68 | invitation.finish | 77 | invitation.finish |
| 69 | end | 78 | end |
| 70 | - session[:notice] = _("Thanks for signing up!") | ||
| 71 | - go_to_initial_page if redirect? | 79 | + @register_pending = true |
| 72 | end | 80 | end |
| 73 | rescue ActiveRecord::RecordInvalid | 81 | rescue ActiveRecord::RecordInvalid |
| 74 | @person.valid? | 82 | @person.valid? |
| @@ -223,6 +231,8 @@ class AccountController < ApplicationController | @@ -223,6 +231,8 @@ class AccountController < ApplicationController | ||
| 223 | session[:notice] = nil # consume the notice | 231 | session[:notice] = nil # consume the notice |
| 224 | end | 232 | end |
| 225 | 233 | ||
| 234 | + @plugins.enabled_plugins.each { |plugin| user_data.merge!(plugin.user_data_extras) } | ||
| 235 | + | ||
| 226 | render :text => user_data.to_json, :layout => false, :content_type => "application/javascript" | 236 | render :text => user_data.to_json, :layout => false, :content_type => "application/javascript" |
| 227 | end | 237 | end |
| 228 | 238 |
app/controllers/public/browse_controller.rb
| @@ -6,6 +6,8 @@ class BrowseController < PublicController | @@ -6,6 +6,8 @@ class BrowseController < PublicController | ||
| 6 | more_recent | 6 | more_recent |
| 7 | more_active | 7 | more_active |
| 8 | more_popular | 8 | more_popular |
| 9 | + more_comments | ||
| 10 | + more_views | ||
| 9 | ) | 11 | ) |
| 10 | 12 | ||
| 11 | def per_page | 13 | def per_page |
| @@ -36,6 +38,18 @@ class BrowseController < PublicController | @@ -36,6 +38,18 @@ class BrowseController < PublicController | ||
| 36 | @results = @results.compact.paginate(:per_page => per_page, :page => params[:page]) | 38 | @results = @results.compact.paginate(:per_page => per_page, :page => params[:page]) |
| 37 | end | 39 | end |
| 38 | 40 | ||
| 41 | + def contents | ||
| 42 | + @filter = filter | ||
| 43 | + @title = self.filter_description(params[:action] + '_' + @filter ) | ||
| 44 | + | ||
| 45 | + @results = @environment.articles.published.text_articles.send(@filter) | ||
| 46 | + | ||
| 47 | + if !params[:query].blank? | ||
| 48 | + @results = @results.find_by_contents(params[:query]) | ||
| 49 | + end | ||
| 50 | + @results = @results.compact.paginate(:per_page => per_page, :page => params[:page]) | ||
| 51 | + end | ||
| 52 | + | ||
| 39 | protected | 53 | protected |
| 40 | 54 | ||
| 41 | def filter | 55 | def filter |
| @@ -54,6 +68,9 @@ class BrowseController < PublicController | @@ -54,6 +68,9 @@ class BrowseController < PublicController | ||
| 54 | 'communities_more_recent' => _('More recent communities'), | 68 | 'communities_more_recent' => _('More recent communities'), |
| 55 | 'communities_more_active' => _('More active communities'), | 69 | 'communities_more_active' => _('More active communities'), |
| 56 | 'communities_more_popular' => _('More popular communities'), | 70 | 'communities_more_popular' => _('More popular communities'), |
| 71 | + 'contents_more_recent' => _('More recent contents'), | ||
| 72 | + 'contents_more_views' => _('Most viewed contents'), | ||
| 73 | + 'contents_more_comments' => _('Most commented contents'), | ||
| 57 | }[str] || str | 74 | }[str] || str |
| 58 | end | 75 | end |
| 59 | 76 |
app/controllers/public/contact_controller.rb
| @@ -4,10 +4,9 @@ class ContactController < PublicController | @@ -4,10 +4,9 @@ class ContactController < PublicController | ||
| 4 | 4 | ||
| 5 | needs_profile | 5 | needs_profile |
| 6 | 6 | ||
| 7 | - inverse_captcha :field => 'e_mail' | ||
| 8 | def new | 7 | def new |
| 9 | @contact | 8 | @contact |
| 10 | - if request.post? && params[self.icaptcha_field].blank? && params[:confirm] == 'true' | 9 | + if request.post? && params[:confirm] == 'true' |
| 11 | @contact = user.build_contact(profile, params[:contact]) | 10 | @contact = user.build_contact(profile, params[:contact]) |
| 12 | @contact.city = (!params[:city].blank? && City.exists?(params[:city])) ? City.find(params[:city]).name : nil | 11 | @contact.city = (!params[:city].blank? && City.exists?(params[:city])) ? City.find(params[:city]).name : nil |
| 13 | @contact.state = (!params[:state].blank? && State.exists?(params[:state])) ? State.find(params[:state]).name : nil | 12 | @contact.state = (!params[:state].blank? && State.exists?(params[:state])) ? State.find(params[:state]).name : nil |
app/controllers/public/content_viewer_controller.rb
| @@ -2,8 +2,6 @@ class ContentViewerController < ApplicationController | @@ -2,8 +2,6 @@ class ContentViewerController < ApplicationController | ||
| 2 | 2 | ||
| 3 | needs_profile | 3 | needs_profile |
| 4 | 4 | ||
| 5 | - inverse_captcha :field => 'e_mail' | ||
| 6 | - | ||
| 7 | helper ProfileHelper | 5 | helper ProfileHelper |
| 8 | helper TagsHelper | 6 | helper TagsHelper |
| 9 | 7 | ||
| @@ -68,8 +66,13 @@ class ContentViewerController < ApplicationController | @@ -68,8 +66,13 @@ class ContentViewerController < ApplicationController | ||
| 68 | 66 | ||
| 69 | @form_div = params[:form] | 67 | @form_div = params[:form] |
| 70 | 68 | ||
| 71 | - if request.post? && params[:comment] && params[self.icaptcha_field].blank? && params[:confirm] == 'true' && @page.accept_comments? | ||
| 72 | - add_comment | 69 | + if params[:comment] && params[:confirm] == 'true' |
| 70 | + @comment = Comment.new(params[:comment]) | ||
| 71 | + if request.post? && @page.accept_comments? | ||
| 72 | + add_comment | ||
| 73 | + end | ||
| 74 | + else | ||
| 75 | + @comment = Comment.new | ||
| 73 | end | 76 | end |
| 74 | 77 | ||
| 75 | if request.post? && params[:remove_comment] | 78 | if request.post? && params[:remove_comment] |
| @@ -106,11 +109,10 @@ class ContentViewerController < ApplicationController | @@ -106,11 +109,10 @@ class ContentViewerController < ApplicationController | ||
| 106 | protected | 109 | protected |
| 107 | 110 | ||
| 108 | def add_comment | 111 | def add_comment |
| 109 | - @comment = Comment.new(params[:comment]) | ||
| 110 | @comment.author = user if logged_in? | 112 | @comment.author = user if logged_in? |
| 111 | @comment.article = @page | 113 | @comment.article = @page |
| 112 | - if @comment.save | ||
| 113 | - @page.update_attribute(:updated_at, Time.now) | 114 | + if (logged_in? || verify_recaptcha(:model => @comment, :message => _('Please type the words correctly'))) && @comment.save |
| 115 | + @page.touch | ||
| 114 | @comment = nil # clear the comment form | 116 | @comment = nil # clear the comment form |
| 115 | redirect_to :action => 'view_page', :profile => params[:profile], :page => @page.explode_path, :view => params[:view] | 117 | redirect_to :action => 'view_page', :profile => params[:profile], :page => @page.explode_path, :view => params[:view] |
| 116 | else | 118 | else |
app/controllers/public/profile_controller.rb
| @@ -2,8 +2,8 @@ class ProfileController < PublicController | @@ -2,8 +2,8 @@ class ProfileController < PublicController | ||
| 2 | 2 | ||
| 3 | needs_profile | 3 | needs_profile |
| 4 | before_filter :check_access_to_profile, :except => [:join, :join_not_logged, :index, :add] | 4 | before_filter :check_access_to_profile, :except => [:join, :join_not_logged, :index, :add] |
| 5 | - before_filter :store_before_join, :only => [:join, :join_not_logged] | ||
| 6 | - before_filter :login_required, :only => [:add, :join, :join_not_logged, :leave, :unblock, :leave_scrap, :remove_scrap, :remove_activity, :view_more_scraps, :view_more_activities, :view_more_network_activities] | 5 | + before_filter :store_location, :only => [:join, :join_not_logged, :report_abuse] |
| 6 | + before_filter :login_required, :only => [:add, :join, :join_not_logged, :leave, :unblock, :leave_scrap, :remove_scrap, :remove_activity, :view_more_scraps, :view_more_activities, :view_more_network_activities, :report_abuse, :register_report] | ||
| 7 | 7 | ||
| 8 | helper TagsHelper | 8 | helper TagsHelper |
| 9 | 9 | ||
| @@ -44,7 +44,7 @@ class ProfileController < PublicController | @@ -44,7 +44,7 @@ class ProfileController < PublicController | ||
| 44 | tagged, | 44 | tagged, |
| 45 | :title => _("%s's contents tagged with \"%s\"") % [profile.name, @tag], | 45 | :title => _("%s's contents tagged with \"%s\"") % [profile.name, @tag], |
| 46 | :description => _("%s's contents tagged with \"%s\"") % [profile.name, @tag], | 46 | :description => _("%s's contents tagged with \"%s\"") % [profile.name, @tag], |
| 47 | - :link => url_for(:action => 'tags') | 47 | + :link => url_for(profile.url) |
| 48 | ) | 48 | ) |
| 49 | render :text => data, :content_type => "text/xml" | 49 | render :text => data, :content_type => "text/xml" |
| 50 | end | 50 | end |
| @@ -71,6 +71,10 @@ class ProfileController < PublicController | @@ -71,6 +71,10 @@ class ProfileController < PublicController | ||
| 71 | end | 71 | end |
| 72 | end | 72 | end |
| 73 | 73 | ||
| 74 | + def fans | ||
| 75 | + @fans = profile.fans | ||
| 76 | + end | ||
| 77 | + | ||
| 74 | def favorite_enterprises | 78 | def favorite_enterprises |
| 75 | @favorite_enterprises = profile.favorite_enterprises | 79 | @favorite_enterprises = profile.favorite_enterprises |
| 76 | end | 80 | end |
| @@ -96,7 +100,7 @@ class ProfileController < PublicController | @@ -96,7 +100,7 @@ class ProfileController < PublicController | ||
| 96 | if request.post? | 100 | if request.post? |
| 97 | profile.add_member(user) | 101 | profile.add_member(user) |
| 98 | session[:notice] = _('%s administrator still needs to accept you as member.') % profile.name if profile.closed? | 102 | session[:notice] = _('%s administrator still needs to accept you as member.') % profile.name if profile.closed? |
| 99 | - redirect_to_before_join | 103 | + redirect_to_previous_location |
| 100 | else | 104 | else |
| 101 | if user.memberships.include?(profile) | 105 | if user.memberships.include?(profile) |
| 102 | session[:notice] = _('You are already a member of %s.') % profile.name | 106 | session[:notice] = _('You are already a member of %s.') % profile.name |
| @@ -223,6 +227,52 @@ class ProfileController < PublicController | @@ -223,6 +227,52 @@ class ProfileController < PublicController | ||
| 223 | end | 227 | end |
| 224 | end | 228 | end |
| 225 | 229 | ||
| 230 | + def report_abuse | ||
| 231 | + @abuse_report = AbuseReport.new | ||
| 232 | + render :layout => false | ||
| 233 | + end | ||
| 234 | + | ||
| 235 | + def register_report | ||
| 236 | + if !verify_recaptcha | ||
| 237 | + render :text => { | ||
| 238 | + :ok => false, | ||
| 239 | + :error => { | ||
| 240 | + :code => 1, | ||
| 241 | + :message => _('You could not answer the captcha.') | ||
| 242 | + } | ||
| 243 | + }.to_json | ||
| 244 | + else | ||
| 245 | + begin | ||
| 246 | + abuse_report = AbuseReport.new(params[:abuse_report]) | ||
| 247 | + if !params[:content_type].blank? | ||
| 248 | + article = params[:content_type].constantize.find(params[:content_id]) | ||
| 249 | + abuse_report.content = instance_eval(&article.reported_version) | ||
| 250 | + end | ||
| 251 | + | ||
| 252 | + user.register_report(abuse_report, profile) | ||
| 253 | + | ||
| 254 | + if !params[:content_type].blank? | ||
| 255 | + abuse_report = AbuseReport.find_by_reporter_id_and_abuse_complaint_id(user.id, profile.opened_abuse_complaint.id) | ||
| 256 | + Delayed::Job.enqueue DownloadReportedImagesJob.new(abuse_report, article) | ||
| 257 | + end | ||
| 258 | + | ||
| 259 | + render :text => { | ||
| 260 | + :ok => true, | ||
| 261 | + :message => _('Your abuse report was registered. The administrators are reviewing your report.'), | ||
| 262 | + }.to_json | ||
| 263 | + rescue Exception => exception | ||
| 264 | + logger.error(exception.to_s) | ||
| 265 | + render :text => { | ||
| 266 | + :ok => false, | ||
| 267 | + :error => { | ||
| 268 | + :code => 2, | ||
| 269 | + :message => _('Your report couldn\'t be saved due to some problem. Please contact the administrator.') | ||
| 270 | + } | ||
| 271 | + }.to_json | ||
| 272 | + end | ||
| 273 | + end | ||
| 274 | + end | ||
| 275 | + | ||
| 226 | protected | 276 | protected |
| 227 | 277 | ||
| 228 | def check_access_to_profile | 278 | def check_access_to_profile |
| @@ -231,16 +281,16 @@ class ProfileController < PublicController | @@ -231,16 +281,16 @@ class ProfileController < PublicController | ||
| 231 | end | 281 | end |
| 232 | end | 282 | end |
| 233 | 283 | ||
| 234 | - def store_before_join | ||
| 235 | - if session[:before_join].nil? | ||
| 236 | - session[:before_join] = request.referer | 284 | + def store_location |
| 285 | + if session[:previous_location].nil? | ||
| 286 | + session[:previous_location] = request.referer | ||
| 237 | end | 287 | end |
| 238 | end | 288 | end |
| 239 | 289 | ||
| 240 | - def redirect_to_before_join | ||
| 241 | - back = session[:before_join] | 290 | + def redirect_to_previous_location |
| 291 | + back = session[:previous_location] | ||
| 242 | if back | 292 | if back |
| 243 | - session[:before_join] = nil | 293 | + session[:previous_location] = nil |
| 244 | redirect_to back | 294 | redirect_to back |
| 245 | else | 295 | else |
| 246 | redirect_to profile.url | 296 | redirect_to profile.url |
| @@ -259,7 +309,7 @@ class ProfileController < PublicController | @@ -259,7 +309,7 @@ class ProfileController < PublicController | ||
| 259 | end | 309 | end |
| 260 | 310 | ||
| 261 | def invisible_profile | 311 | def invisible_profile |
| 262 | - render_access_denied(_("Sorry, this profile was defined as private by its owner. You'll not be able to view content here unless the profile owner adds adds you."), _("Oops ... you cannot go ahead here")) | 312 | + render_access_denied(_("This profile is inaccessible. You don't have the permission to view the content here."), _("Oops ... you cannot go ahead here")) |
| 263 | end | 313 | end |
| 264 | 314 | ||
| 265 | def per_page | 315 | def per_page |
app/helpers/application_helper.rb
| @@ -209,7 +209,11 @@ module ApplicationHelper | @@ -209,7 +209,11 @@ module ApplicationHelper | ||
| 209 | the_class << ' ' << html_options[:class] | 209 | the_class << ' ' << html_options[:class] |
| 210 | end | 210 | end |
| 211 | the_title = html_options[:title] || label | 211 | the_title = html_options[:title] || label |
| 212 | - link_to(' '+content_tag('span', label), url, html_options.merge(:class => the_class, :title => the_title)) | 212 | + if html_options[:disabled] |
| 213 | + content_tag('a', ' '+content_tag('span', label), html_options.merge(:class => the_class, :title => the_title)) | ||
| 214 | + else | ||
| 215 | + link_to(' '+content_tag('span', label), url, html_options.merge(:class => the_class, :title => the_title)) | ||
| 216 | + end | ||
| 213 | end | 217 | end |
| 214 | 218 | ||
| 215 | def button_to_function(type, label, js_code, html_options = {}, &block) | 219 | def button_to_function(type, label, js_code, html_options = {}, &block) |
| @@ -257,30 +261,59 @@ module ApplicationHelper | @@ -257,30 +261,59 @@ module ApplicationHelper | ||
| 257 | concat(content_tag('div', capture(&block) + tag('br', :style => 'clear: left;'), { :class => 'button-bar' }.merge(options))) | 261 | concat(content_tag('div', capture(&block) + tag('br', :style => 'clear: left;'), { :class => 'button-bar' }.merge(options))) |
| 258 | end | 262 | end |
| 259 | 263 | ||
| 260 | - def partial_for_class(klass) | ||
| 261 | - if klass.nil? | ||
| 262 | - raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' | ||
| 263 | - end | 264 | + VIEW_EXTENSIONS = %w[.rhtml .html.erb] |
| 264 | 265 | ||
| 266 | + def partial_for_class_in_view_path(klass, view_path) | ||
| 267 | + return nil if klass.nil? | ||
| 265 | name = klass.name.underscore | 268 | name = klass.name.underscore |
| 266 | - if File.exists?(File.join(RAILS_ROOT, 'app', 'views', params[:controller], "_#{name}.rhtml")) | ||
| 267 | - name | 269 | + |
| 270 | + search_name = String.new(name) | ||
| 271 | + if search_name.include?("/") | ||
| 272 | + search_name.gsub!(/(\/)([^\/]*)$/,'\1_\2') | ||
| 273 | + name = File.join(params[:controller], name) if defined?(params) && params[:controller] | ||
| 268 | else | 274 | else |
| 269 | - partial_for_class(klass.superclass) | 275 | + search_name = "_" + search_name |
| 276 | + end | ||
| 277 | + | ||
| 278 | + VIEW_EXTENSIONS.each do |ext| | ||
| 279 | + path = defined?(params) && params[:controller] ? File.join(view_path, params[:controller], search_name+ext) : File.join(view_path, search_name+ext) | ||
| 280 | + return name if File.exists?(File.join(path)) | ||
| 270 | end | 281 | end |
| 282 | + | ||
| 283 | + partial_for_class_in_view_path(klass.superclass, view_path) | ||
| 271 | end | 284 | end |
| 272 | 285 | ||
| 273 | - def partial_for_task_class(klass, action) | ||
| 274 | - if klass.nil? | ||
| 275 | - raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' | 286 | + def partial_for_class(klass) |
| 287 | + raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil? | ||
| 288 | + name = klass.name.underscore | ||
| 289 | + @controller.view_paths.each do |view_path| | ||
| 290 | + partial = partial_for_class_in_view_path(klass, view_path) | ||
| 291 | + return partial if partial | ||
| 276 | end | 292 | end |
| 277 | 293 | ||
| 294 | + raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' | ||
| 295 | + end | ||
| 296 | + | ||
| 297 | + def partial_for_task_class(klass, action) | ||
| 298 | + raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil? | ||
| 299 | + | ||
| 278 | name = "#{klass.name.underscore}_#{action.to_s}" | 300 | name = "#{klass.name.underscore}_#{action.to_s}" |
| 279 | - if File.exists?(File.join(RAILS_ROOT, 'app', 'views', params[:controller], "_#{name}.rhtml")) | ||
| 280 | - name | ||
| 281 | - else | ||
| 282 | - partial_for_task_class(klass.superclass, action) | 301 | + VIEW_EXTENSIONS.each do |ext| |
| 302 | + return name if File.exists?(File.join(RAILS_ROOT, 'app', 'views', params[:controller], '_'+name+ext)) | ||
| 303 | + end | ||
| 304 | + | ||
| 305 | + partial_for_task_class(klass.superclass, action) | ||
| 306 | + end | ||
| 307 | + | ||
| 308 | + def view_for_profile_actions(klass) | ||
| 309 | + raise ArgumentError, 'No profile actions view for this class.' if klass.nil? | ||
| 310 | + | ||
| 311 | + name = klass.name.underscore | ||
| 312 | + VIEW_EXTENSIONS.each do |ext| | ||
| 313 | + return "blocks/profile_info_actions/"+name+ext if File.exists?(File.join(RAILS_ROOT, 'app', 'views', 'blocks', 'profile_info_actions', name+ext)) | ||
| 283 | end | 314 | end |
| 315 | + | ||
| 316 | + view_for_profile_actions(klass.superclass) | ||
| 284 | end | 317 | end |
| 285 | 318 | ||
| 286 | def user | 319 | def user |
| @@ -556,17 +589,18 @@ module ApplicationHelper | @@ -556,17 +589,18 @@ module ApplicationHelper | ||
| 556 | 589 | ||
| 557 | def gravatar_url_for(email, options = {}) | 590 | def gravatar_url_for(email, options = {}) |
| 558 | # Ta dando erro de roteamento | 591 | # Ta dando erro de roteamento |
| 592 | + default = theme_option['gravatar'] || NOOSFERO_CONF['gravatar'] || nil | ||
| 559 | url_for( { :gravatar_id => Digest::MD5.hexdigest(email), | 593 | url_for( { :gravatar_id => Digest::MD5.hexdigest(email), |
| 560 | :host => 'www.gravatar.com', | 594 | :host => 'www.gravatar.com', |
| 561 | :protocol => 'http://', | 595 | :protocol => 'http://', |
| 562 | :only_path => false, | 596 | :only_path => false, |
| 563 | :controller => 'avatar.php', | 597 | :controller => 'avatar.php', |
| 564 | - :d => NOOSFERO_CONF['gravatar'] ? NOOSFERO_CONF['gravatar'] : nil | 598 | + :d => default |
| 565 | }.merge(options) ) | 599 | }.merge(options) ) |
| 566 | end | 600 | end |
| 567 | 601 | ||
| 568 | def str_gravatar_url_for(email, options = {}) | 602 | def str_gravatar_url_for(email, options = {}) |
| 569 | - default = NOOSFERO_CONF['gravatar'] ? NOOSFERO_CONF['gravatar'] : nil | 603 | + default = theme_option['gravatar'] || NOOSFERO_CONF['gravatar'] || nil |
| 570 | url = 'http://www.gravatar.com/avatar.php?gravatar_id=' + | 604 | url = 'http://www.gravatar.com/avatar.php?gravatar_id=' + |
| 571 | Digest::MD5.hexdigest(email) | 605 | Digest::MD5.hexdigest(email) |
| 572 | { | 606 | { |
| @@ -870,7 +904,7 @@ module ApplicationHelper | @@ -870,7 +904,7 @@ module ApplicationHelper | ||
| 870 | 904 | ||
| 871 | def template_stylesheet_path | 905 | def template_stylesheet_path |
| 872 | if profile.nil? | 906 | if profile.nil? |
| 873 | - '/designs/templates/default/stylesheets/style.css' | 907 | + "/designs/templates/#{environment.layout_template}/stylesheets/style.css" |
| 874 | else | 908 | else |
| 875 | "/designs/templates/#{profile.layout_template}/stylesheets/style.css" | 909 | "/designs/templates/#{profile.layout_template}/stylesheets/style.css" |
| 876 | end | 910 | end |
| @@ -947,8 +981,10 @@ module ApplicationHelper | @@ -947,8 +981,10 @@ module ApplicationHelper | ||
| 947 | 'thickbox', | 981 | 'thickbox', |
| 948 | 'lightbox', | 982 | 'lightbox', |
| 949 | 'colorpicker', | 983 | 'colorpicker', |
| 984 | + colorbox_stylesheet_path, | ||
| 950 | pngfix_stylesheet_path, | 985 | pngfix_stylesheet_path, |
| 951 | - ] | 986 | + ] + |
| 987 | + tokeninput_stylesheets | ||
| 952 | end | 988 | end |
| 953 | 989 | ||
| 954 | # DEPRECATED. Do not use this· | 990 | # DEPRECATED. Do not use this· |
| @@ -960,6 +996,14 @@ module ApplicationHelper | @@ -960,6 +996,14 @@ module ApplicationHelper | ||
| 960 | 'iepngfix/iepngfix.css' | 996 | 'iepngfix/iepngfix.css' |
| 961 | end | 997 | end |
| 962 | 998 | ||
| 999 | + def colorbox_stylesheet_path | ||
| 1000 | + 'colorbox/colorbox.css' | ||
| 1001 | + end | ||
| 1002 | + | ||
| 1003 | + def tokeninput_stylesheets | ||
| 1004 | + ['token-input', 'token-input-facebook', 'token-input-mac'] | ||
| 1005 | + end | ||
| 1006 | + | ||
| 963 | def noosfero_layout_features | 1007 | def noosfero_layout_features |
| 964 | render :file => 'shared/noosfero_layout_features' | 1008 | render :file => 'shared/noosfero_layout_features' |
| 965 | end | 1009 | end |
| @@ -975,7 +1019,10 @@ module ApplicationHelper | @@ -975,7 +1019,10 @@ module ApplicationHelper | ||
| 975 | def article_to_html(article, options = {}) | 1019 | def article_to_html(article, options = {}) |
| 976 | options.merge!(:page => params[:npage]) | 1020 | options.merge!(:page => params[:npage]) |
| 977 | content = article.to_html(options) | 1021 | content = article.to_html(options) |
| 978 | - return self.instance_eval(&content) if content.kind_of?(Proc) | 1022 | + content = content.kind_of?(Proc) ? self.instance_eval(&content) : content |
| 1023 | + @plugins && @plugins.enabled_plugins.each do |plugin| | ||
| 1024 | + content = plugin.parse_content(content) | ||
| 1025 | + end | ||
| 979 | content | 1026 | content |
| 980 | end | 1027 | end |
| 981 | 1028 | ||
| @@ -1083,6 +1130,17 @@ module ApplicationHelper | @@ -1083,6 +1130,17 @@ module ApplicationHelper | ||
| 1083 | link_to(content_tag(:span, _('Communities Menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger up', :id => 'submenu-communities-trigger') | 1130 | link_to(content_tag(:span, _('Communities Menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger up', :id => 'submenu-communities-trigger') |
| 1084 | end | 1131 | end |
| 1085 | 1132 | ||
| 1133 | + def browse_contents_menu | ||
| 1134 | + links = [ | ||
| 1135 | + {s_('contents|More Comments') => {:href => url_for({:controller => 'browse', :action => 'contents', :filter => 'more_comments'})}}, | ||
| 1136 | + {s_('contents|More Views') => {:href => url_for({:controller => 'browse', :action => 'contents', :filter => 'more_views'})}}, | ||
| 1137 | + {s_('contents|More Recent') => {:href => url_for({:controller => 'browse', :action => 'contents', :filter => 'more_recent'})}} | ||
| 1138 | + ] | ||
| 1139 | + | ||
| 1140 | + link_to(content_tag(:span, _('Contents'), :class => 'icon-blog'), {:controller => "browse", :action => 'contents'}, :id => 'submenu-contents') + | ||
| 1141 | + link_to(content_tag(:span, _('Contents Menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger up', :id => 'submenu-contents-trigger') | ||
| 1142 | + end | ||
| 1143 | + | ||
| 1086 | def pagination_links(collection, options={}) | 1144 | def pagination_links(collection, options={}) |
| 1087 | options = {:prev_label => '« ' + _('Previous'), :next_label => _('Next') + ' »'}.merge(options) | 1145 | options = {:prev_label => '« ' + _('Previous'), :next_label => _('Next') + ' »'}.merge(options) |
| 1088 | will_paginate(collection, options) | 1146 | will_paginate(collection, options) |
| @@ -1099,16 +1157,27 @@ module ApplicationHelper | @@ -1099,16 +1157,27 @@ module ApplicationHelper | ||
| 1099 | result | 1157 | result |
| 1100 | end | 1158 | end |
| 1101 | 1159 | ||
| 1160 | + def manage_enterprises | ||
| 1161 | + if user && !user.enterprises.empty? | ||
| 1162 | + enterprises_link = user.enterprises.map do |enterprise| | ||
| 1163 | + link_to(content_tag('strong', [_('<span>Manage</span> %s') % enterprise.short_name(25)]), @environment.top_url + "/myprofile/#{enterprise.identifier}", :class => "icon-menu-"+enterprise.class.identification.underscore, :title => [_('Manage %s') % enterprise.short_name]) | ||
| 1164 | + end | ||
| 1165 | + render :partial => 'shared/manage_enterprises', :locals => {:enterprises_link => enterprises_link} | ||
| 1166 | + end | ||
| 1167 | + end | ||
| 1168 | + | ||
| 1102 | def usermenu_logged_in | 1169 | def usermenu_logged_in |
| 1103 | pending_tasks_count = '' | 1170 | pending_tasks_count = '' |
| 1104 | - if user && user.all_pending_tasks.count > 0 | ||
| 1105 | - pending_tasks_count = link_to(user.all_pending_tasks.count.to_s, '/myprofile/{login}/tasks', :id => 'pending-tasks-count', :title => _("Manage your pending tasks")) | 1171 | + count = user ? Task.to(user).pending.count : -1 |
| 1172 | + if count > 0 | ||
| 1173 | + pending_tasks_count = link_to(count.to_s, @environment.top_url + '/myprofile/{login}/tasks', :id => 'pending-tasks-count', :title => _("Manage your pending tasks")) | ||
| 1106 | end | 1174 | end |
| 1107 | 1175 | ||
| 1108 | - (_('Welcome, %s') % link_to('<i></i><strong>{login}</strong>', '/{login}', :id => "homepage-link", :title => _('Go to your homepage'))) + | 1176 | + (_("<span class='welcome'>Welcome,</span> %s") % link_to('<i></i><strong>{login}</strong>', @environment.top_url + '/{login}', :id => "homepage-link", :title => _('Go to your homepage'))) + |
| 1109 | render_environment_features(:usermenu) + | 1177 | render_environment_features(:usermenu) + |
| 1110 | - link_to('<i class="icon-menu-admin"></i><strong>' + _('Administration') + '</strong>', { :controller => 'admin_panel', :action => 'index' }, :id => "controlpanel", :title => _("Configure the environment"), :class => 'admin-link', :style => 'display: none') + | ||
| 1111 | - link_to('<i class="icon-menu-ctrl-panel"></i><strong>' + _('Control panel') + '</strong>', '/myprofile/{login}', :id => "controlpanel", :title => _("Configure your personal account and content")) + | 1178 | + link_to('<i class="icon-menu-admin"></i><strong>' + _('Administration') + '</strong>', @environment.top_url + '/admin', :id => "controlpanel", :title => _("Configure the environment"), :class => 'admin-link', :style => 'display: none') + |
| 1179 | + manage_enterprises.to_s + | ||
| 1180 | + link_to('<i class="icon-menu-ctrl-panel"></i><strong>' + _('Control panel') + '</strong>', @environment.top_url + '/myprofile/{login}', :id => "controlpanel", :title => _("Configure your personal account and content")) + | ||
| 1112 | pending_tasks_count + | 1181 | pending_tasks_count + |
| 1113 | link_to('<i class="icon-menu-logout"></i><strong>' + _('Logout') + '</strong>', { :controller => 'account', :action => 'logout'} , :id => "logout", :title => _("Leave the system")) | 1182 | link_to('<i class="icon-menu-logout"></i><strong>' + _('Logout') + '</strong>', { :controller => 'account', :action => 'logout'} , :id => "logout", :title => _("Leave the system")) |
| 1114 | end | 1183 | end |
| @@ -1206,4 +1275,39 @@ module ApplicationHelper | @@ -1206,4 +1275,39 @@ module ApplicationHelper | ||
| 1206 | end | 1275 | end |
| 1207 | end | 1276 | end |
| 1208 | 1277 | ||
| 1278 | + def render_dialog_error_messages(instance_name) | ||
| 1279 | + render :partial => 'shared/dialog_error_messages', :locals => { :object_name => instance_name } | ||
| 1280 | + end | ||
| 1281 | + | ||
| 1282 | + def report_abuse(profile, type, content=nil) | ||
| 1283 | + return if !user || user == profile | ||
| 1284 | + | ||
| 1285 | + url = { :controller => 'profile', | ||
| 1286 | + :action => 'report_abuse', | ||
| 1287 | + :profile => profile.identifier } | ||
| 1288 | + url.merge!({:content_type => content.class.name, :content_id => content.id}) if content | ||
| 1289 | + text = content_tag('span', _('Report abuse')) | ||
| 1290 | + klass = 'report-abuse-action' | ||
| 1291 | + already_reported_message = _('You already reported this profile.') | ||
| 1292 | + report_profile_message = _('Report this profile for abusive behaviour') | ||
| 1293 | + | ||
| 1294 | + if type == :button | ||
| 1295 | + if user.already_reported?(profile) | ||
| 1296 | + button(:alert, text, url, :class => klass+' disabled', :disabled => true, :title => already_reported_message) | ||
| 1297 | + else | ||
| 1298 | + button(:alert, text, url, :class => klass, :title => report_profile_message) | ||
| 1299 | + end | ||
| 1300 | + elsif type == :link | ||
| 1301 | + if user.already_reported?(profile) | ||
| 1302 | + content_tag('a', text, :class => klass + ' disabled button with-text icon-alert', :title => already_reported_message) | ||
| 1303 | + else | ||
| 1304 | + link_to(text, url, :class => klass + ' button with-text icon-alert', :title => report_profile_message) | ||
| 1305 | + end | ||
| 1306 | + elsif type == :comment_link | ||
| 1307 | + (user.already_reported?(profile) ? | ||
| 1308 | + content_tag('a', text, :class => klass + ' disabled comment-footer comment-footer-link', :title => already_reported_message) : | ||
| 1309 | + link_to(text, url, :class => klass + ' comment-footer comment-footer-link', :title => report_profile_message) | ||
| 1310 | + ) + content_tag('span', ' | ', :class => 'comment-footer comment-footer-hide') | ||
| 1311 | + end | ||
| 1312 | + end | ||
| 1209 | end | 1313 | end |
app/helpers/boxes_helper.rb
| @@ -99,7 +99,9 @@ module BoxesHelper | @@ -99,7 +99,9 @@ module BoxesHelper | ||
| 99 | unless block.visible? | 99 | unless block.visible? |
| 100 | options[:title] = _("This block is invisible. Your visitors will not see it.") | 100 | options[:title] = _("This block is invisible. Your visitors will not see it.") |
| 101 | end | 101 | end |
| 102 | - | 102 | + @controller.send(:content_editor?) || @plugins.enabled_plugins.each do |plugin| |
| 103 | + result = plugin.parse_content(result) | ||
| 104 | + end | ||
| 103 | box_decorator.block_target(block.box, block) + | 105 | box_decorator.block_target(block.box, block) + |
| 104 | content_tag('div', | 106 | content_tag('div', |
| 105 | content_tag('div', | 107 | content_tag('div', |
app/helpers/catalog_helper.rb
| @@ -5,16 +5,24 @@ include ManageProductsHelper | @@ -5,16 +5,24 @@ include ManageProductsHelper | ||
| 5 | 5 | ||
| 6 | def display_products_list(profile, products) | 6 | def display_products_list(profile, products) |
| 7 | data = '' | 7 | data = '' |
| 8 | + extra_content = [] | ||
| 9 | + extra_content_list = [] | ||
| 8 | products.each { |product| | 10 | products.each { |product| |
| 9 | - | 11 | + extra_content = @plugins.map(:catalog_item_extras, product).collect { |content| instance_eval(&content) } if @plugins |
| 12 | + extra_content_list = @plugins.map(:catalog_list_item_extras, product).collect { |content| instance_eval(&content) } if @plugins | ||
| 10 | data << content_tag('li', | 13 | data << content_tag('li', |
| 11 | - link_to_product(product, :class => 'product-pic', :style => 'background-image:url(%s)' % ( product.image ? product.image.public_filename(:portrait) : '/images/icons-app/product-default-pic-portrait.png' )) + | 14 | + link_to_product(product, :class => 'product-pic', :style => 'background-image:url(%s)' % product.default_image(:portrait) ) + |
| 12 | content_tag('h3', link_to_product(product)) + | 15 | content_tag('h3', link_to_product(product)) + |
| 13 | content_tag('ul', | 16 | content_tag('ul', |
| 14 | (product.price ? content_tag('li', _('Price: %s') % ( "%.2f" % product.price), :class => 'product_price') : '') + | 17 | (product.price ? content_tag('li', _('Price: %s') % ( "%.2f" % product.price), :class => 'product_price') : '') + |
| 15 | - content_tag('li', product_category_name(profile, product.product_category), :class => 'product_category') | 18 | + content_tag('li', product_category_name(profile, product.product_category), :class => 'product_category') + |
| 19 | + extra_content_list.map { |content| content_tag('li', content)}.join("\n") | ||
| 16 | ) + | 20 | ) + |
| 17 | - (product.description ? content_tag('div', txt2html(product.description), :class => 'description') : tag('br', :style => 'clear:both')), | 21 | + (product.description ? content_tag('div', |
| 22 | + txt2html(product.description), | ||
| 23 | + :class => 'description') : tag('br', | ||
| 24 | + :style => 'clear:both')) + | ||
| 25 | + extra_content.join("\n"), | ||
| 18 | :class => 'product') | 26 | :class => 'product') |
| 19 | } | 27 | } |
| 20 | content_tag('h1', _('Products/Services')) + content_tag('ul', data, :id => 'product_list') | 28 | content_tag('h1', _('Products/Services')) + content_tag('ul', data, :id => 'product_list') |
app/helpers/content_viewer_helper.rb
| @@ -22,9 +22,14 @@ module ContentViewerHelper | @@ -22,9 +22,14 @@ module ContentViewerHelper | ||
| 22 | end | 22 | end |
| 23 | comments = '' | 23 | comments = '' |
| 24 | unless args[:no_comments] || !article.accept_comments | 24 | unless args[:no_comments] || !article.accept_comments |
| 25 | - comments = ("- %s") % link_to_comments(article) | 25 | + comments = (" - %s") % link_to_comments(article) |
| 26 | end | 26 | end |
| 27 | - title << content_tag('span', _("%s, by %s %s") % [show_date(article.published_at), link_to(article.author_name, article.author.url), comments], :class => 'created-at') | 27 | + title << content_tag('span', |
| 28 | + content_tag('span', show_date(article.published_at), :class => 'date') + | ||
| 29 | + content_tag('span', [_(", by %s") % link_to(article.author_name, article.author.url)], :class => 'author') + | ||
| 30 | + content_tag('span', comments, :class => 'comments'), | ||
| 31 | + :class => 'created-at' | ||
| 32 | + ) | ||
| 28 | end | 33 | end |
| 29 | title | 34 | title |
| 30 | end | 35 | end |
| @@ -46,4 +51,21 @@ module ContentViewerHelper | @@ -46,4 +51,21 @@ module ContentViewerHelper | ||
| 46 | end | 51 | end |
| 47 | end | 52 | end |
| 48 | 53 | ||
| 54 | + def addthis_facebook_url(article) | ||
| 55 | + "http://www.facebook.com/sharer.php?s=100&p[title]=%{title}&p[summary]=%{summary}&p[url]=%{url}&p[images][0]=%{image}" % { | ||
| 56 | + :title => CGI.escape(article.title), | ||
| 57 | + :url => CGI.escape(url_for(article.url)), | ||
| 58 | + :summary => CGI.escape(truncate(strip_tags(article.body.to_s), 300)), | ||
| 59 | + :image => CGI.escape(article.body_images_paths.first.to_s) | ||
| 60 | + } | ||
| 61 | + end | ||
| 62 | + | ||
| 63 | + def addthis_image_tag | ||
| 64 | + if File.exists?(File.join(Rails.root, 'public', theme_path, 'images', 'addthis.gif')) | ||
| 65 | + image_tag(File.join(theme_path, 'images', 'addthis.gif'), :border => 0, :alt => '') | ||
| 66 | + else | ||
| 67 | + image_tag("/images/bt-bookmark.gif", :width => 53, :height => 16, :border => 0, :alt => '') | ||
| 68 | + end | ||
| 69 | + end | ||
| 70 | + | ||
| 49 | end | 71 | end |
app/helpers/dates_helper.rb
| @@ -42,11 +42,11 @@ module DatesHelper | @@ -42,11 +42,11 @@ module DatesHelper | ||
| 42 | end | 42 | end |
| 43 | end | 43 | end |
| 44 | 44 | ||
| 45 | - def show_period(date1, date2 = nil) | 45 | + def show_period(date1, date2 = nil, use_numbers = false) |
| 46 | if (date1 == date2) || (date2.nil?) | 46 | if (date1 == date2) || (date2.nil?) |
| 47 | - show_date(date1) | 47 | + show_date(date1, use_numbers) |
| 48 | else | 48 | else |
| 49 | - _('from %{date1} to %{date2}') % {:date1 => show_date(date1), :date2 => show_date(date2)} | 49 | + _('from %{date1} to %{date2}') % {:date1 => show_date(date1, use_numbers), :date2 => show_date(date2, use_numbers)} |
| 50 | end | 50 | end |
| 51 | end | 51 | end |
| 52 | 52 |
app/helpers/display_helper.rb
| @@ -27,14 +27,18 @@ module DisplayHelper | @@ -27,14 +27,18 @@ module DisplayHelper | ||
| 27 | end | 27 | end |
| 28 | 28 | ||
| 29 | def txt2html(txt) | 29 | def txt2html(txt) |
| 30 | - txt. | ||
| 31 | - gsub( /\n\s*\n/, ' <p/> ' ). | ||
| 32 | - gsub( /\n/, ' <br/> ' ). | ||
| 33 | - gsub( /(^|\s)(www\.[^\s])/, '\1http://\2' ). | ||
| 34 | - gsub( /(https?:\/\/([^\s]+))/ ) do | ||
| 35 | - href, content = $1, $2.scan(/.{4}/).join('​') | ||
| 36 | - content_tag(:a, content, :href => href, :target => '_blank', :rel => 'nofolow', | ||
| 37 | - :onclick => "return confirm('%s')" % escape_javascript(_('Are you sure you want to visit this web site?'))) | 30 | + txt.strip. |
| 31 | + gsub( /\s*\n\s*\n\s*/, "\r<p/>\r" ). | ||
| 32 | + gsub( /\s*\n\s*/, "\n<br/>\n" ). | ||
| 33 | + gsub( /\r/, "\n" ). | ||
| 34 | + gsub( /(^|\s)(www\.[^\s]+|https?:\/\/[^\s]+)/ ) do | ||
| 35 | + pre_char, href = $1, $2 | ||
| 36 | + href = 'http://'+href if ! href.match /^https?:/ | ||
| 37 | + content = href.gsub(/^https?:\/\//, '').scan(/.{1,4}/).join('​') | ||
| 38 | + pre_char + | ||
| 39 | + content_tag(:a, content, :href => href, :target => '_blank', | ||
| 40 | + :rel => 'nofolow', :onclick => "return confirm('%s')" % | ||
| 41 | + _('Are you sure you want to visit this web site?')) | ||
| 38 | end | 42 | end |
| 39 | end | 43 | end |
| 40 | end | 44 | end |
app/helpers/events_helper.rb
| @@ -21,14 +21,13 @@ module EventsHelper | @@ -21,14 +21,13 @@ module EventsHelper | ||
| 21 | end | 21 | end |
| 22 | 22 | ||
| 23 | def populate_calendar(selected_date, events) | 23 | def populate_calendar(selected_date, events) |
| 24 | + events.reject! {|event| !event.display_to?(user)} | ||
| 24 | calendar = Event.date_range(selected_date.year, selected_date.month).map do |date| | 25 | calendar = Event.date_range(selected_date.year, selected_date.month).map do |date| |
| 25 | [ | 26 | [ |
| 26 | # the day itself | 27 | # the day itself |
| 27 | date, | 28 | date, |
| 28 | # is there any events in this date? | 29 | # is there any events in this date? |
| 29 | - events.select {|event| event.display_to?(user)}.any? do |event| | ||
| 30 | - event.date_range.include?(date) | ||
| 31 | - end, | 30 | + events.any? {|event| event.date_range.include?(date)}, |
| 32 | # is this date in the current month? | 31 | # is this date in the current month? |
| 33 | true | 32 | true |
| 34 | ] | 33 | ] |
app/helpers/profile_editor_helper.rb
| @@ -104,8 +104,8 @@ module ProfileEditorHelper | @@ -104,8 +104,8 @@ module ProfileEditorHelper | ||
| 104 | @country_helper ||= CountriesHelper.instance | 104 | @country_helper ||= CountriesHelper.instance |
| 105 | end | 105 | end |
| 106 | 106 | ||
| 107 | - def select_country(title, object, method, options) | ||
| 108 | - labelled_form_field(title, select(object, method, [[_('[Select ...]'), nil]] + country_helper.countries, {}, options)) | 107 | + def select_country(title, object, method, html_options = {}, options = {}) |
| 108 | + labelled_form_field(title, select(object, method, [[_('[Select ...]'), nil]] + country_helper.countries, options, html_options)) | ||
| 109 | end | 109 | end |
| 110 | 110 | ||
| 111 | def select_schooling(object, method, options) | 111 | def select_schooling(object, method, options) |
app/helpers/sweeper_helper.rb
| @@ -22,7 +22,7 @@ module SweeperHelper | @@ -22,7 +22,7 @@ module SweeperHelper | ||
| 22 | 22 | ||
| 23 | # friends blocks | 23 | # friends blocks |
| 24 | blocks = profile.blocks.select{|b| b.kind_of?(FriendsBlock)} | 24 | blocks = profile.blocks.select{|b| b.kind_of?(FriendsBlock)} |
| 25 | - blocks.map(&:cache_keys).each{|ck|expire_timeout_fragment(ck)} | 25 | + blocks.map(&:cache_key).each{|ck|expire_timeout_fragment(ck)} |
| 26 | end | 26 | end |
| 27 | 27 | ||
| 28 | def expire_communities(profile) | 28 | def expire_communities(profile) |
| @@ -34,13 +34,13 @@ module SweeperHelper | @@ -34,13 +34,13 @@ module SweeperHelper | ||
| 34 | 34 | ||
| 35 | # communities block | 35 | # communities block |
| 36 | blocks = profile.blocks.select{|b| b.kind_of?(CommunitiesBlock)} | 36 | blocks = profile.blocks.select{|b| b.kind_of?(CommunitiesBlock)} |
| 37 | - blocks.map(&:cache_keys).each{|ck|expire_timeout_fragment(ck)} | 37 | + blocks.map(&:cache_key).each{|ck|expire_timeout_fragment(ck)} |
| 38 | end | 38 | end |
| 39 | 39 | ||
| 40 | def expire_enterprises(profile) | 40 | def expire_enterprises(profile) |
| 41 | # enterprises and favorite enterprises blocks | 41 | # enterprises and favorite enterprises blocks |
| 42 | blocks = profile.blocks.select {|b| [EnterprisesBlock, FavoriteEnterprisesBlock].any?{|klass| b.kind_of?(klass)} } | 42 | blocks = profile.blocks.select {|b| [EnterprisesBlock, FavoriteEnterprisesBlock].any?{|klass| b.kind_of?(klass)} } |
| 43 | - blocks.map(&:cache_keys).each{|ck|expire_timeout_fragment(ck)} | 43 | + blocks.map(&:cache_key).each{|ck|expire_timeout_fragment(ck)} |
| 44 | end | 44 | end |
| 45 | 45 | ||
| 46 | def expire_profile_index(profile) | 46 | def expire_profile_index(profile) |
app/helpers/tags_helper.rb
| @@ -28,7 +28,6 @@ module TagsHelper | @@ -28,7 +28,6 @@ module TagsHelper | ||
| 28 | # courtesy of Aurelio: http://www.colivre.coop.br/Aurium/Nuvem | 28 | # courtesy of Aurelio: http://www.colivre.coop.br/Aurium/Nuvem |
| 29 | # (pt_BR only). | 29 | # (pt_BR only). |
| 30 | def tag_cloud(tags, tagname_option, url, options = {}) | 30 | def tag_cloud(tags, tagname_option, url, options = {}) |
| 31 | - | ||
| 32 | 31 | ||
| 33 | return content_tag('em', _('No tags yet.')) + | 32 | return content_tag('em', _('No tags yet.')) + |
| 34 | ' <a href="' + _('http://en.wikipedia.org/wiki/Tag_%28metadata%29') + | 33 | ' <a href="' + _('http://en.wikipedia.org/wiki/Tag_%28metadata%29') + |
| @@ -42,7 +41,7 @@ module TagsHelper | @@ -42,7 +41,7 @@ module TagsHelper | ||
| 42 | max = tags.values.max.to_f | 41 | max = tags.values.max.to_f |
| 43 | min = tags.values.min.to_f | 42 | min = tags.values.min.to_f |
| 44 | 43 | ||
| 45 | - tags.map do |tag,count| | 44 | + tags.sort_by{ |k,v| k.downcase }.map do |tag,count| |
| 46 | if ( max == min ) | 45 | if ( max == min ) |
| 47 | v = 0.5 | 46 | v = 0.5 |
| 48 | else | 47 | else |
| @@ -0,0 +1,75 @@ | @@ -0,0 +1,75 @@ | ||
| 1 | +class AbuseComplaint < Task | ||
| 2 | + has_many :abuse_reports, :dependent => :destroy | ||
| 3 | + belongs_to :reported, :class_name => "Profile", :foreign_key => "requestor_id" | ||
| 4 | + | ||
| 5 | + validates_presence_of :reported | ||
| 6 | + alias :requestor :reported | ||
| 7 | + | ||
| 8 | + def initialize(*args) | ||
| 9 | + super | ||
| 10 | + self.status = (args.first ? args.first[:status] : nil) || Task::Status::HIDDEN | ||
| 11 | + end | ||
| 12 | + | ||
| 13 | + after_update do |abuse_complaint| | ||
| 14 | + if abuse_complaint.reported.environment.reports_lower_bound < abuse_complaint.abuse_reports.count && abuse_complaint.status == Task::Status::HIDDEN | ||
| 15 | + abuse_complaint.activate | ||
| 16 | + end | ||
| 17 | + end | ||
| 18 | + | ||
| 19 | + def target | ||
| 20 | + reported.environment | ||
| 21 | + end | ||
| 22 | + | ||
| 23 | + def environment | ||
| 24 | + target | ||
| 25 | + end | ||
| 26 | + | ||
| 27 | + def title | ||
| 28 | + abuse_reports.count > 1 ? (_('Abuse complaint (%s)') % abuse_reports.count) :_('Abuse complaint') | ||
| 29 | + end | ||
| 30 | + | ||
| 31 | + def linked_subject | ||
| 32 | + {:text => reported.name, :url => reported.url} | ||
| 33 | + end | ||
| 34 | + | ||
| 35 | + def information | ||
| 36 | + {:message => _('%{linked_subject} was reported due to inappropriate behavior.')} | ||
| 37 | + end | ||
| 38 | + | ||
| 39 | + def accept_details | ||
| 40 | + true | ||
| 41 | + end | ||
| 42 | + | ||
| 43 | + def reject_details | ||
| 44 | + true | ||
| 45 | + end | ||
| 46 | + | ||
| 47 | + def icon | ||
| 48 | + {:type => :profile_image, :profile => reported, :url => reported.url} | ||
| 49 | + end | ||
| 50 | + | ||
| 51 | + def default_decision | ||
| 52 | + 'skip' | ||
| 53 | + end | ||
| 54 | + | ||
| 55 | + def perform | ||
| 56 | + reported.disable | ||
| 57 | + end | ||
| 58 | + | ||
| 59 | + def task_activated_message | ||
| 60 | + _('Your profile was reported by the users of %s due to inappropriate behavior. The administrators of the environment are now reviewing the report. To solve this misunderstanding, please contact the administrators.') % environment.name | ||
| 61 | + end | ||
| 62 | + | ||
| 63 | + def task_finished_message | ||
| 64 | + _('Your profile was disabled by the administrators of %s due to inappropriate behavior. To solve this misunderstanding please contact them.') % environment.name | ||
| 65 | + end | ||
| 66 | + | ||
| 67 | + def target_notification_description | ||
| 68 | + _('%s was reported due to inappropriate behavior.') % reported.name | ||
| 69 | + end | ||
| 70 | + | ||
| 71 | + def target_notification_message | ||
| 72 | + _('The users of %{environment} reported %{reported} due to inappropriate behavior. A task was created with all the reports including the reasons and contents reported by these users. Please verify the reports and decide whether this profile must be disabled or not.') % {:environment => environment.name, :reported => reported.name} | ||
| 73 | + end | ||
| 74 | + | ||
| 75 | +end |
| @@ -0,0 +1,15 @@ | @@ -0,0 +1,15 @@ | ||
| 1 | +class AbuseReport < ActiveRecord::Base | ||
| 2 | + | ||
| 3 | + belongs_to :reporter, :class_name => 'Person' | ||
| 4 | + belongs_to :abuse_complaint | ||
| 5 | + has_many :reported_images, :dependent => :destroy | ||
| 6 | + | ||
| 7 | + validates_presence_of :reporter, :abuse_complaint, :reason | ||
| 8 | + validates_uniqueness_of :reporter_id, :scope => :abuse_complaint_id | ||
| 9 | + | ||
| 10 | + xss_terminate :sanitize => [:reason] | ||
| 11 | + | ||
| 12 | + after_create do |abuse_report| | ||
| 13 | + abuse_report.abuse_complaint.save! | ||
| 14 | + end | ||
| 15 | +end |
app/models/approve_article.rb
| @@ -77,6 +77,10 @@ class ApproveArticle < Task | @@ -77,6 +77,10 @@ class ApproveArticle < Task | ||
| 77 | true | 77 | true |
| 78 | end | 78 | end |
| 79 | 79 | ||
| 80 | + def reject_details | ||
| 81 | + true | ||
| 82 | + end | ||
| 83 | + | ||
| 80 | def default_decision | 84 | def default_decision |
| 81 | if article | 85 | if article |
| 82 | 'skip' | 86 | 'skip' |
| @@ -90,7 +94,11 @@ class ApproveArticle < Task | @@ -90,7 +94,11 @@ class ApproveArticle < Task | ||
| 90 | end | 94 | end |
| 91 | 95 | ||
| 92 | def target_notification_description | 96 | def target_notification_description |
| 93 | - _('%{requestor} wants to publish the article: %{article}.') % {:requestor => requestor.name, :article => article.name} | 97 | + if article |
| 98 | + _('%{requestor} wants to publish the article: %{article}.') % {:requestor => requestor.name, :article => article.name} | ||
| 99 | + else | ||
| 100 | + _('%{requestor} wanted to publish an article but it was removed.') % {:requestor => requestor.name} | ||
| 101 | + end | ||
| 94 | end | 102 | end |
| 95 | 103 | ||
| 96 | def target_notification_message | 104 | def target_notification_message |
| @@ -107,4 +115,11 @@ class ApproveArticle < Task | @@ -107,4 +115,11 @@ class ApproveArticle < Task | ||
| 107 | end | 115 | end |
| 108 | end | 116 | end |
| 109 | 117 | ||
| 118 | + def task_cancelled_message | ||
| 119 | + message = _('Your request for publishing the article "{article}" was rejected.') | ||
| 120 | + if !reject_explanation.blank? | ||
| 121 | + message += " " + _("Here is the reject explanation left by the administrator who rejected your article: \n\n%{reject_explanation}") % {:reject_explanation => reject_explanation} | ||
| 122 | + end | ||
| 123 | + end | ||
| 124 | + | ||
| 110 | end | 125 | end |
app/models/article.rb
| @@ -188,6 +188,14 @@ class Article < ActiveRecord::Base | @@ -188,6 +188,14 @@ class Article < ActiveRecord::Base | ||
| 188 | body || '' | 188 | body || '' |
| 189 | end | 189 | end |
| 190 | 190 | ||
| 191 | + include ApplicationHelper | ||
| 192 | + def reported_version(options = {}) | ||
| 193 | + article = self | ||
| 194 | + search_path = File.join(Rails.root, 'app', 'views', 'shared', 'reported_versions') | ||
| 195 | + partial_path = File.join('shared', 'reported_versions', partial_for_class_in_view_path(article.class, search_path)) | ||
| 196 | + lambda { render_to_string(:partial => partial_path, :locals => {:article => article}) } | ||
| 197 | + end | ||
| 198 | + | ||
| 191 | # returns the data of the article. Must be overriden in each subclass to | 199 | # returns the data of the article. Must be overriden in each subclass to |
| 192 | # provide the correct content for the article. | 200 | # provide the correct content for the article. |
| 193 | def data | 201 | def data |
| @@ -265,6 +273,10 @@ class Article < ActiveRecord::Base | @@ -265,6 +273,10 @@ class Article < ActiveRecord::Base | ||
| 265 | false | 273 | false |
| 266 | end | 274 | end |
| 267 | 275 | ||
| 276 | + def uploaded_file? | ||
| 277 | + false | ||
| 278 | + end | ||
| 279 | + | ||
| 268 | def has_posts? | 280 | def has_posts? |
| 269 | false | 281 | false |
| 270 | end | 282 | end |
| @@ -343,11 +355,20 @@ class Article < ActiveRecord::Base | @@ -343,11 +355,20 @@ class Article < ActiveRecord::Base | ||
| 343 | ['Folder', 'Blog', 'Forum', 'Gallery'] | 355 | ['Folder', 'Blog', 'Forum', 'Gallery'] |
| 344 | end | 356 | end |
| 345 | 357 | ||
| 358 | + def self.text_article_types | ||
| 359 | + ['TextArticle', 'TextileArticle', 'TinyMceArticle'] | ||
| 360 | + end | ||
| 361 | + | ||
| 346 | named_scope :published, :conditions => { :published => true } | 362 | named_scope :published, :conditions => { :published => true } |
| 347 | named_scope :folders, :conditions => { :type => folder_types} | 363 | named_scope :folders, :conditions => { :type => folder_types} |
| 348 | named_scope :no_folders, :conditions => ['type NOT IN (?)', folder_types] | 364 | named_scope :no_folders, :conditions => ['type NOT IN (?)', folder_types] |
| 349 | named_scope :galleries, :conditions => { :type => 'Gallery' } | 365 | named_scope :galleries, :conditions => { :type => 'Gallery' } |
| 350 | named_scope :images, :conditions => { :is_image => true } | 366 | named_scope :images, :conditions => { :is_image => true } |
| 367 | + named_scope :text_articles, :conditions => [ 'articles.type IN (?)', text_article_types ] | ||
| 368 | + | ||
| 369 | + named_scope :more_comments, :order => "comments_count DESC" | ||
| 370 | + named_scope :more_views, :order => "hits DESC" | ||
| 371 | + named_scope :more_recent, :order => "created_at DESC" | ||
| 351 | 372 | ||
| 352 | def self.display_filter(user, profile) | 373 | def self.display_filter(user, profile) |
| 353 | return {:conditions => ['published = ?', true]} if !user | 374 | return {:conditions => ['published = ?', true]} if !user |
| @@ -509,6 +530,35 @@ class Article < ActiveRecord::Base | @@ -509,6 +530,35 @@ class Article < ActiveRecord::Base | ||
| 509 | self.parent && self.parent.accept_uploads? | 530 | self.parent && self.parent.accept_uploads? |
| 510 | end | 531 | end |
| 511 | 532 | ||
| 533 | + def body_images_paths | ||
| 534 | + require 'uri' | ||
| 535 | + Hpricot(self.body.to_s).search('img[@src]').collect do |i| | ||
| 536 | + (self.profile && self.profile.environment) ? URI.join(self.profile.environment.top_url, URI.escape(i.attributes['src'])).to_s : i.attributes['src'] | ||
| 537 | + end | ||
| 538 | + end | ||
| 539 | + | ||
| 540 | + def more_comments_label | ||
| 541 | + amount = self.comments_count | ||
| 542 | + { | ||
| 543 | + 0 => _('no comments'), | ||
| 544 | + 1 => _('one comment') | ||
| 545 | + }[amount] || _("%s comments") % amount | ||
| 546 | + | ||
| 547 | + end | ||
| 548 | + | ||
| 549 | + def more_views_label | ||
| 550 | + amount = self.hits | ||
| 551 | + { | ||
| 552 | + 0 => _('no views'), | ||
| 553 | + 1 => _('one view') | ||
| 554 | + }[amount] || _("%s views") % amount | ||
| 555 | + | ||
| 556 | + end | ||
| 557 | + | ||
| 558 | + def more_recent_label | ||
| 559 | + _('Created at: ') | ||
| 560 | + end | ||
| 561 | + | ||
| 512 | private | 562 | private |
| 513 | 563 | ||
| 514 | def sanitize_tag_list | 564 | def sanitize_tag_list |
app/models/block.rb
| @@ -34,6 +34,12 @@ class Block < ActiveRecord::Base | @@ -34,6 +34,12 @@ class Block < ActiveRecord::Base | ||
| 34 | else | 34 | else |
| 35 | return context[:request_path] == '/' | 35 | return context[:request_path] == '/' |
| 36 | end | 36 | end |
| 37 | + elsif display == 'except_home_page' | ||
| 38 | + if context[:article] | ||
| 39 | + return context[:article] != owner.home_page | ||
| 40 | + else | ||
| 41 | + return context[:request_path] != '/' + owner.identifier | ||
| 42 | + end | ||
| 37 | end | 43 | end |
| 38 | end | 44 | end |
| 39 | true | 45 | true |
| @@ -45,6 +51,8 @@ class Block < ActiveRecord::Base | @@ -45,6 +51,8 @@ class Block < ActiveRecord::Base | ||
| 45 | # * <tt>'never'</tt>: the block is hidden (it does not appear for visitors) | 51 | # * <tt>'never'</tt>: the block is hidden (it does not appear for visitors) |
| 46 | # * <tt>'home_page_only'</tt> the block is displayed only when viewing the | 52 | # * <tt>'home_page_only'</tt> the block is displayed only when viewing the |
| 47 | # homepage of its owner. | 53 | # homepage of its owner. |
| 54 | + # * <tt>'except_home_page'</tt> the block is displayed only when viewing | ||
| 55 | + # the homepage of its owner. | ||
| 48 | settings_items :display, :type => :string, :default => 'always' | 56 | settings_items :display, :type => :string, :default => 'always' |
| 49 | 57 | ||
| 50 | # The block can be configured to be displayed in all languages or in just one language. It can assume any locale of the environment: | 58 | # The block can be configured to be displayed in all languages or in just one language. It can assume any locale of the environment: |
| @@ -119,10 +127,6 @@ class Block < ActiveRecord::Base | @@ -119,10 +127,6 @@ class Block < ActiveRecord::Base | ||
| 119 | true | 127 | true |
| 120 | end | 128 | end |
| 121 | 129 | ||
| 122 | - def cache_keys | ||
| 123 | - "block-id-#{id}" | ||
| 124 | - end | ||
| 125 | - | ||
| 126 | def timeout | 130 | def timeout |
| 127 | 4.hours | 131 | 4.hours |
| 128 | end | 132 | end |
app/models/blog.rb
| @@ -72,4 +72,8 @@ class Blog < Folder | @@ -72,4 +72,8 @@ class Blog < Folder | ||
| 72 | 72 | ||
| 73 | alias :display_posts_in_current_language? :display_posts_in_current_language | 73 | alias :display_posts_in_current_language? :display_posts_in_current_language |
| 74 | 74 | ||
| 75 | + def empty? | ||
| 76 | + posts.empty? | ||
| 77 | + end | ||
| 78 | + | ||
| 75 | end | 79 | end |
app/models/comment.rb
| @@ -2,7 +2,7 @@ class Comment < ActiveRecord::Base | @@ -2,7 +2,7 @@ class Comment < ActiveRecord::Base | ||
| 2 | 2 | ||
| 3 | track_actions :leave_comment, :after_create, :keep_params => ["article.title", "article.url", "title", "url", "body"], :custom_target => :action_tracker_target | 3 | track_actions :leave_comment, :after_create, :keep_params => ["article.title", "article.url", "title", "url", "body"], :custom_target => :action_tracker_target |
| 4 | 4 | ||
| 5 | - validates_presence_of :title, :body | 5 | + validates_presence_of :body |
| 6 | belongs_to :article, :counter_cache => true | 6 | belongs_to :article, :counter_cache => true |
| 7 | belongs_to :author, :class_name => 'Person', :foreign_key => 'author_id' | 7 | belongs_to :author, :class_name => 'Person', :foreign_key => 'author_id' |
| 8 | has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy | 8 | has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy |
| @@ -98,6 +98,16 @@ class Comment < ActiveRecord::Base | @@ -98,6 +98,16 @@ class Comment < ActiveRecord::Base | ||
| 98 | root | 98 | root |
| 99 | end | 99 | end |
| 100 | 100 | ||
| 101 | + include ApplicationHelper | ||
| 102 | + def reported_version(options = {}) | ||
| 103 | + comment = self | ||
| 104 | + lambda { render_to_string(:partial => 'shared/reported_versions/comment', :locals => {:comment => comment}) } | ||
| 105 | + end | ||
| 106 | + | ||
| 107 | + def to_html(option={}) | ||
| 108 | + body || '' | ||
| 109 | + end | ||
| 110 | + | ||
| 101 | class Notifier < ActionMailer::Base | 111 | class Notifier < ActionMailer::Base |
| 102 | def mail(comment) | 112 | def mail(comment) |
| 103 | profile = comment.article.profile | 113 | profile = comment.article.profile |
app/models/community.rb
app/models/contact.rb
| @@ -23,23 +23,26 @@ class Contact < ActiveRecord::Base #WithoutTable | @@ -23,23 +23,26 @@ class Contact < ActiveRecord::Base #WithoutTable | ||
| 23 | 23 | ||
| 24 | class Sender < ActionMailer::Base | 24 | class Sender < ActionMailer::Base |
| 25 | def mail(contact) | 25 | def mail(contact) |
| 26 | + content_type 'text/html' | ||
| 26 | emails = contact.dest.notification_emails | 27 | emails = contact.dest.notification_emails |
| 27 | recipients emails | 28 | recipients emails |
| 28 | - from "#{contact.name} <#{contact.email}>" | 29 | + from "#{contact.name} <#{contact.dest.environment.contact_email}>" |
| 30 | + reply_to contact.email | ||
| 29 | if contact.sender | 31 | if contact.sender |
| 30 | headers 'X-Noosfero-Sender' => contact.sender.identifier | 32 | headers 'X-Noosfero-Sender' => contact.sender.identifier |
| 31 | end | 33 | end |
| 32 | if contact.receive_a_copy | 34 | if contact.receive_a_copy |
| 33 | cc "#{contact.name} <#{contact.email}>" | 35 | cc "#{contact.name} <#{contact.email}>" |
| 34 | end | 36 | end |
| 35 | - subject contact.subject | 37 | + subject "[#{contact.dest.short_name(30)}] " + contact.subject |
| 36 | body :name => contact.name, | 38 | body :name => contact.name, |
| 37 | :email => contact.email, | 39 | :email => contact.email, |
| 38 | :city => contact.city, | 40 | :city => contact.city, |
| 39 | :state => contact.state, | 41 | :state => contact.state, |
| 40 | :message => contact.message, | 42 | :message => contact.message, |
| 41 | :environment => contact.dest.environment.name, | 43 | :environment => contact.dest.environment.name, |
| 42 | - :url => url_for(:host => contact.dest.environment.default_hostname, :controller => 'home') | 44 | + :url => url_for(:host => contact.dest.environment.default_hostname, :controller => 'home'), |
| 45 | + :target => contact.dest.name | ||
| 43 | end | 46 | end |
| 44 | end | 47 | end |
| 45 | 48 |
app/models/domain.rb
| @@ -10,7 +10,7 @@ class Domain < ActiveRecord::Base | @@ -10,7 +10,7 @@ class Domain < ActiveRecord::Base | ||
| 10 | 10 | ||
| 11 | # <tt>name</tt> must be a sequence of word characters (a to z, plus 0 to 9, | 11 | # <tt>name</tt> must be a sequence of word characters (a to z, plus 0 to 9, |
| 12 | # plus '_'). Letters must be lowercase | 12 | # plus '_'). Letters must be lowercase |
| 13 | - validates_format_of :name, :with => /^([a-z0-9_]+\.)+[a-z0-9_]+$/, :message => N_('%{fn} must be composed only of lowercase latters (a to z), numbers (0 to 9) and "_"') | 13 | + validates_format_of :name, :with => /^([a-z0-9_-]+\.)+[a-z0-9_-]+$/, :message => N_('%{fn} must be composed only of lowercase latters (a to z), numbers (0 to 9), "_" and "-"') |
| 14 | 14 | ||
| 15 | # checks validations that could not be expressed using Rails' predefined | 15 | # checks validations that could not be expressed using Rails' predefined |
| 16 | # validations. In particular: | 16 | # validations. In particular: |
app/models/enterprise.rb
| @@ -7,6 +7,8 @@ class Enterprise < Organization | @@ -7,6 +7,8 @@ class Enterprise < Organization | ||
| 7 | has_many :products, :dependent => :destroy, :order => 'name ASC' | 7 | has_many :products, :dependent => :destroy, :order => 'name ASC' |
| 8 | has_many :inputs, :through => :products | 8 | has_many :inputs, :through => :products |
| 9 | 9 | ||
| 10 | + has_and_belongs_to_many :fans, :class_name => 'Person', :join_table => 'favorite_enteprises_people' | ||
| 11 | + | ||
| 10 | extra_data_for_index :product_categories | 12 | extra_data_for_index :product_categories |
| 11 | 13 | ||
| 12 | N_('Organization website'); N_('Historic and current context'); N_('Activities short description'); N_('City'); N_('State'); N_('Country'); N_('ZIP code') | 14 | N_('Organization website'); N_('Historic and current context'); N_('Activities short description'); N_('City'); N_('State'); N_('Country'); N_('ZIP code') |
| @@ -145,6 +147,7 @@ class Enterprise < Organization | @@ -145,6 +147,7 @@ class Enterprise < Organization | ||
| 145 | end | 147 | end |
| 146 | 148 | ||
| 147 | before_create do |enterprise| | 149 | before_create do |enterprise| |
| 150 | + enterprise.validated = enterprise.environment.enabled?('enterprises_are_validated_when_created') | ||
| 148 | if enterprise.environment.enabled?('enterprises_are_disabled_when_created') | 151 | if enterprise.environment.enabled?('enterprises_are_disabled_when_created') |
| 149 | enterprise.enabled = false | 152 | enterprise.enabled = false |
| 150 | end | 153 | end |
| @@ -165,4 +168,12 @@ class Enterprise < Organization | @@ -165,4 +168,12 @@ class Enterprise < Organization | ||
| 165 | enable_contact_us | 168 | enable_contact_us |
| 166 | end | 169 | end |
| 167 | 170 | ||
| 171 | + def control_panel_settings_button | ||
| 172 | + {:title => __('Enterprise Info and settings'), :icon => 'edit-profile-enterprise'} | ||
| 173 | + end | ||
| 174 | + | ||
| 175 | + def create_product? | ||
| 176 | + true | ||
| 177 | + end | ||
| 178 | + | ||
| 168 | end | 179 | end |
app/models/environment.rb
| @@ -9,6 +9,13 @@ class Environment < ActiveRecord::Base | @@ -9,6 +9,13 @@ class Environment < ActiveRecord::Base | ||
| 9 | 9 | ||
| 10 | has_many :tasks, :dependent => :destroy, :as => 'target' | 10 | has_many :tasks, :dependent => :destroy, :as => 'target' |
| 11 | 11 | ||
| 12 | + IDENTIFY_SCRIPTS = /(php[0-9s]?|[sp]htm[l]?|pl|py|cgi|rb)/ | ||
| 13 | + | ||
| 14 | + def self.verify_filename(filename) | ||
| 15 | + filename += '.txt' if File.extname(filename) =~ IDENTIFY_SCRIPTS | ||
| 16 | + filename | ||
| 17 | + end | ||
| 18 | + | ||
| 12 | PERMISSIONS['Environment'] = { | 19 | PERMISSIONS['Environment'] = { |
| 13 | 'view_environment_admin_panel' => N_('View environment admin panel'), | 20 | 'view_environment_admin_panel' => N_('View environment admin panel'), |
| 14 | 'edit_environment_features' => N_('Edit environment features'), | 21 | 'edit_environment_features' => N_('Edit environment features'), |
| @@ -67,6 +74,10 @@ class Environment < ActiveRecord::Base | @@ -67,6 +74,10 @@ class Environment < ActiveRecord::Base | ||
| 67 | self.affiliate(user, Environment::Roles.admin(self.id)) | 74 | self.affiliate(user, Environment::Roles.admin(self.id)) |
| 68 | end | 75 | end |
| 69 | 76 | ||
| 77 | + def remove_admin(user) | ||
| 78 | + self.disaffiliate(user, Environment::Roles.admin(self.id)) | ||
| 79 | + end | ||
| 80 | + | ||
| 70 | def admins | 81 | def admins |
| 71 | Person.members_of(self).all(:conditions => ['role_assignments.role_id = ?', Environment::Roles.admin(self).id]) | 82 | Person.members_of(self).all(:conditions => ['role_assignments.role_id = ?', Environment::Roles.admin(self).id]) |
| 72 | end | 83 | end |
| @@ -106,6 +117,7 @@ class Environment < ActiveRecord::Base | @@ -106,6 +117,7 @@ class Environment < ActiveRecord::Base | ||
| 106 | 'enable_organization_url_change' => _("Allow organizations to change their URL"), | 117 | 'enable_organization_url_change' => _("Allow organizations to change their URL"), |
| 107 | 'admin_must_approve_new_communities' => _("Admin must approve creation of communities"), | 118 | 'admin_must_approve_new_communities' => _("Admin must approve creation of communities"), |
| 108 | 'enterprises_are_disabled_when_created' => __('Enterprises are disabled when created'), | 119 | 'enterprises_are_disabled_when_created' => __('Enterprises are disabled when created'), |
| 120 | + 'enterprises_are_validated_when_created' => __('Enterprises are validated when created'), | ||
| 109 | 'show_balloon_with_profile_links_when_clicked' => _('Show a balloon with profile links when a profile image is clicked'), | 121 | 'show_balloon_with_profile_links_when_clicked' => _('Show a balloon with profile links when a profile image is clicked'), |
| 110 | 'xmpp_chat' => _('XMPP/Jabber based chat'), | 122 | 'xmpp_chat' => _('XMPP/Jabber based chat'), |
| 111 | 'show_zoom_button_on_article_images' => _('Show a zoom link on all article images') | 123 | 'show_zoom_button_on_article_images' => _('Show a zoom link on all article images') |
| @@ -218,7 +230,19 @@ class Environment < ActiveRecord::Base | @@ -218,7 +230,19 @@ class Environment < ActiveRecord::Base | ||
| 218 | settings_items :currency_separator, :type => String, :default => '.' | 230 | settings_items :currency_separator, :type => String, :default => '.' |
| 219 | settings_items :currency_delimiter, :type => String, :default => ',' | 231 | settings_items :currency_delimiter, :type => String, :default => ',' |
| 220 | 232 | ||
| 221 | - settings_items :trusted_sites_for_iframe, :type => Array, :default => ['itheora.org', 'tv.softwarelivre.org', 'stream.softwarelivre.org'] | 233 | + settings_items :trusted_sites_for_iframe, :type => Array, :default => %w[ |
| 234 | + developer.myspace.com | ||
| 235 | + itheora.org | ||
| 236 | + maps.google.com | ||
| 237 | + platform.twitter.com | ||
| 238 | + player.vimeo.com | ||
| 239 | + stream.softwarelivre.org | ||
| 240 | + tv.softwarelivre.org | ||
| 241 | + www.facebook.com | ||
| 242 | + www.flickr.com | ||
| 243 | + www.gmodules.com | ||
| 244 | + www.youtube.com | ||
| 245 | + ] + ('a' .. 'z').map{|i| "#{i}.yimg.com"} | ||
| 222 | 246 | ||
| 223 | settings_items :enabled_plugins, :type => Array, :default => [] | 247 | settings_items :enabled_plugins, :type => Array, :default => [] |
| 224 | 248 | ||
| @@ -228,17 +252,28 @@ class Environment < ActiveRecord::Base | @@ -228,17 +252,28 @@ class Environment < ActiveRecord::Base | ||
| 228 | 252 | ||
| 229 | # Enables a feature identified by its name | 253 | # Enables a feature identified by its name |
| 230 | def enable(feature) | 254 | def enable(feature) |
| 231 | - self.settings["#{feature}_enabled"] = true | 255 | + self.settings["#{feature}_enabled".to_sym] = true |
| 256 | + end | ||
| 257 | + | ||
| 258 | + def enable_plugin(plugin) | ||
| 259 | + self.enabled_plugins += [plugin] | ||
| 260 | + self.enabled_plugins.uniq! | ||
| 261 | + self.save! | ||
| 232 | end | 262 | end |
| 233 | 263 | ||
| 234 | # Disables a feature identified by its name | 264 | # Disables a feature identified by its name |
| 235 | def disable(feature) | 265 | def disable(feature) |
| 236 | - self.settings["#{feature}_enabled"] = false | 266 | + self.settings["#{feature}_enabled".to_sym] = false |
| 267 | + end | ||
| 268 | + | ||
| 269 | + def disable_plugin(plugin) | ||
| 270 | + self.enabled_plugins.delete(plugin) | ||
| 271 | + self.save! | ||
| 237 | end | 272 | end |
| 238 | 273 | ||
| 239 | # Tells if a feature, identified by its name, is enabled | 274 | # Tells if a feature, identified by its name, is enabled |
| 240 | def enabled?(feature) | 275 | def enabled?(feature) |
| 241 | - self.settings["#{feature}_enabled"] == true | 276 | + self.settings["#{feature}_enabled".to_sym] == true |
| 242 | end | 277 | end |
| 243 | 278 | ||
| 244 | # enables the features identified by <tt>features</tt>, which is expected to | 279 | # enables the features identified by <tt>features</tt>, which is expected to |
| @@ -494,6 +529,7 @@ class Environment < ActiveRecord::Base | @@ -494,6 +529,7 @@ class Environment < ActiveRecord::Base | ||
| 494 | xss_terminate :only => [ :message_for_disabled_enterprise ], :with => 'white_list', :on => 'validation' | 529 | xss_terminate :only => [ :message_for_disabled_enterprise ], :with => 'white_list', :on => 'validation' |
| 495 | 530 | ||
| 496 | validates_presence_of :theme | 531 | validates_presence_of :theme |
| 532 | + validates_numericality_of :reports_lower_bound, :allow_nil => false, :only_integer => true, :greater_than_or_equal_to => 0 | ||
| 497 | 533 | ||
| 498 | include WhiteListFilter | 534 | include WhiteListFilter |
| 499 | filter_iframes :message_for_disabled_enterprise, :whitelist => lambda { trusted_sites_for_iframe } | 535 | filter_iframes :message_for_disabled_enterprise, :whitelist => lambda { trusted_sites_for_iframe } |
| @@ -517,12 +553,12 @@ class Environment < ActiveRecord::Base | @@ -517,12 +553,12 @@ class Environment < ActiveRecord::Base | ||
| 517 | # If #force_www is true, adds 'www.' at the beginning of the hostname. If the | 553 | # If #force_www is true, adds 'www.' at the beginning of the hostname. If the |
| 518 | # environment has not associated domains, returns 'localhost'. | 554 | # environment has not associated domains, returns 'localhost'. |
| 519 | def default_hostname(email_hostname = false) | 555 | def default_hostname(email_hostname = false) |
| 520 | - if self.domains(true).empty? | ||
| 521 | - 'localhost' | ||
| 522 | - else | 556 | + domain = 'localhost' |
| 557 | + unless self.domains(true).empty? | ||
| 523 | domain = (self.domains.find_by_is_default(true) || self.domains.find(:first, :order => 'id')).name | 558 | domain = (self.domains.find_by_is_default(true) || self.domains.find(:first, :order => 'id')).name |
| 524 | - email_hostname ? domain : (force_www ? ('www.' + domain) : domain) | 559 | + domain = email_hostname ? domain : (force_www ? ('www.' + domain) : domain) |
| 525 | end | 560 | end |
| 561 | + domain | ||
| 526 | end | 562 | end |
| 527 | 563 | ||
| 528 | def top_url | 564 | def top_url |
| @@ -671,13 +707,14 @@ class Environment < ActiveRecord::Base | @@ -671,13 +707,14 @@ class Environment < ActiveRecord::Base | ||
| 671 | def create_templates | 707 | def create_templates |
| 672 | pre = self.name.to_slug + '_' | 708 | pre = self.name.to_slug + '_' |
| 673 | ent_id = Enterprise.create!(:name => 'Enterprise template', :identifier => pre + 'enterprise_template', :environment => self, :visible => false).id | 709 | ent_id = Enterprise.create!(:name => 'Enterprise template', :identifier => pre + 'enterprise_template', :environment => self, :visible => false).id |
| 710 | + inactive_enterprise_tmpl = Enterprise.create!(:name => 'Inactive Enterprise template', :identifier => pre + 'inactive_enterprise_template', :environment => self, :visible => false) | ||
| 674 | com_id = Community.create!(:name => 'Community template', :identifier => pre + 'community_template', :environment => self, :visible => false).id | 711 | com_id = Community.create!(:name => 'Community template', :identifier => pre + 'community_template', :environment => self, :visible => false).id |
| 675 | pass = Digest::MD5.hexdigest rand.to_s | 712 | pass = Digest::MD5.hexdigest rand.to_s |
| 676 | user = User.create!(:login => (pre + 'person_template'), :email => (pre + 'template@template.noo'), :password => pass, :password_confirmation => pass, :environment => self).person | 713 | user = User.create!(:login => (pre + 'person_template'), :email => (pre + 'template@template.noo'), :password => pass, :password_confirmation => pass, :environment => self).person |
| 677 | - user.visible = false | ||
| 678 | - user.save! | 714 | + user.update_attributes(:visible => false, :name => "Person template") |
| 679 | usr_id = user.id | 715 | usr_id = user.id |
| 680 | self.settings[:enterprise_template_id] = ent_id | 716 | self.settings[:enterprise_template_id] = ent_id |
| 717 | + self.inactive_enterprise_template = inactive_enterprise_tmpl | ||
| 681 | self.settings[:community_template_id] = com_id | 718 | self.settings[:community_template_id] = com_id |
| 682 | self.settings[:person_template_id] = usr_id | 719 | self.settings[:person_template_id] = usr_id |
| 683 | self.save! | 720 | self.save! |
| @@ -685,7 +722,7 @@ class Environment < ActiveRecord::Base | @@ -685,7 +722,7 @@ class Environment < ActiveRecord::Base | ||
| 685 | 722 | ||
| 686 | after_destroy :destroy_templates | 723 | after_destroy :destroy_templates |
| 687 | def destroy_templates | 724 | def destroy_templates |
| 688 | - [enterprise_template, community_template, person_template].compact.each do |template| | 725 | + [enterprise_template, inactive_enterprise_template, community_template, person_template].compact.each do |template| |
| 689 | template.destroy | 726 | template.destroy |
| 690 | end | 727 | end |
| 691 | end | 728 | end |
| @@ -701,6 +738,4 @@ class Environment < ActiveRecord::Base | @@ -701,6 +738,4 @@ class Environment < ActiveRecord::Base | ||
| 701 | def image_galleries | 738 | def image_galleries |
| 702 | portal_community ? portal_community.image_galleries : [] | 739 | portal_community ? portal_community.image_galleries : [] |
| 703 | end | 740 | end |
| 704 | - | ||
| 705 | end | 741 | end |
| 706 | - |
| @@ -0,0 +1,31 @@ | @@ -0,0 +1,31 @@ | ||
| 1 | +class FansBlock < ProfileListBlock | ||
| 2 | + | ||
| 3 | + def self.description | ||
| 4 | + _('Displays the people who like the enterprise') | ||
| 5 | + end | ||
| 6 | + | ||
| 7 | + def default_title | ||
| 8 | + n__('{#} fan', '{#} fans', profile_count) | ||
| 9 | + end | ||
| 10 | + | ||
| 11 | + def help | ||
| 12 | + _('This block presents the fans of an enterprise.') | ||
| 13 | + end | ||
| 14 | + | ||
| 15 | + def footer | ||
| 16 | + profile = self.owner | ||
| 17 | + lambda do | ||
| 18 | + link_to _('View all'), :profile => profile.identifier, :controller => | ||
| 19 | + 'profile', :action => 'fans' | ||
| 20 | + end | ||
| 21 | + end | ||
| 22 | + | ||
| 23 | + def profiles | ||
| 24 | + owner.fans | ||
| 25 | + end | ||
| 26 | + | ||
| 27 | + def profile_count | ||
| 28 | + profiles.visible.count | ||
| 29 | + end | ||
| 30 | + | ||
| 31 | +end |
app/models/folder.rb
| @@ -29,7 +29,7 @@ class Folder < Article | @@ -29,7 +29,7 @@ class Folder < Article | ||
| 29 | def to_html(options = {}) | 29 | def to_html(options = {}) |
| 30 | folder = self | 30 | folder = self |
| 31 | lambda do | 31 | lambda do |
| 32 | - render :file => 'content_viewer/folder', :locals => { :folder => folder } | 32 | + render :file => 'content_viewer/folder', :locals => {:folder => folder} |
| 33 | end | 33 | end |
| 34 | end | 34 | end |
| 35 | 35 |
app/models/image.rb
| 1 | class Image < ActiveRecord::Base | 1 | class Image < ActiveRecord::Base |
| 2 | - belongs_to :owner, :polymorphic => true | ||
| 3 | 2 | ||
| 4 | def self.max_size | 3 | def self.max_size |
| 5 | Image.attachment_options[:max_size] | 4 | Image.attachment_options[:max_size] |
| 6 | end | 5 | end |
| 7 | 6 | ||
| 7 | + sanitize_filename | ||
| 8 | + | ||
| 8 | has_attachment :content_type => :image, | 9 | has_attachment :content_type => :image, |
| 9 | :storage => :file_system, | 10 | :storage => :file_system, |
| 10 | :path_prefix => 'public/image_uploads', | 11 | :path_prefix => 'public/image_uploads', |
| @@ -20,4 +21,6 @@ class Image < ActiveRecord::Base | @@ -20,4 +21,6 @@ class Image < ActiveRecord::Base | ||
| 20 | 21 | ||
| 21 | delay_attachment_fu_thumbnails | 22 | delay_attachment_fu_thumbnails |
| 22 | 23 | ||
| 24 | + postgresql_attachment_fu | ||
| 25 | + | ||
| 23 | end | 26 | end |
app/models/invitation.rb
| @@ -27,6 +27,10 @@ class Invitation < Task | @@ -27,6 +27,10 @@ class Invitation < Task | ||
| 27 | TaskMailer.deliver_invitation_notification(task) unless task.friend | 27 | TaskMailer.deliver_invitation_notification(task) unless task.friend |
| 28 | end | 28 | end |
| 29 | 29 | ||
| 30 | + def title | ||
| 31 | + _('Invitation') | ||
| 32 | + end | ||
| 33 | + | ||
| 30 | def validate | 34 | def validate |
| 31 | super | 35 | super |
| 32 | email = friend ? friend.user.email : friend_email | 36 | email = friend ? friend.user.email : friend_email |
app/models/invite_friend.rb
app/models/link_list_block.rb
| @@ -57,7 +57,7 @@ class LinkListBlock < Block | @@ -57,7 +57,7 @@ class LinkListBlock < Block | ||
| 57 | def link_html(link) | 57 | def link_html(link) |
| 58 | klass = 'icon-' + link[:icon] if link[:icon] | 58 | klass = 'icon-' + link[:icon] if link[:icon] |
| 59 | sanitize_link( | 59 | sanitize_link( |
| 60 | - link_to(_(link[:name]), expand_address(link[:address]), :class => klass) | 60 | + link_to(link[:name], expand_address(link[:address]), :class => klass) |
| 61 | ) | 61 | ) |
| 62 | end | 62 | end |
| 63 | 63 |
app/models/organization.rb
| @@ -95,12 +95,12 @@ class Organization < Profile | @@ -95,12 +95,12 @@ class Organization < Profile | ||
| 95 | [] | 95 | [] |
| 96 | end | 96 | end |
| 97 | 97 | ||
| 98 | - N_('Display name'); N_('Description'); N_('Contact person'); N_('Contact email'); N_('Acronym'); N_('Foundation year'); N_('Legal form'); N_('Economic activity'); N_('Management information'); N_('Validated'); N_('Tag list') | ||
| 99 | - settings_items :display_name, :description, :contact_person, :contact_email, :acronym, :foundation_year, :legal_form, :economic_activity, :management_information, :validated, :cnpj | 98 | + N_('Display name'); N_('Description'); N_('Contact person'); N_('Contact email'); N_('Acronym'); N_('Foundation year'); N_('Legal form'); N_('Economic activity'); N_('Management information'); N_('Tag list') |
| 99 | + settings_items :display_name, :description, :contact_person, :contact_email, :acronym, :foundation_year, :legal_form, :economic_activity, :management_information | ||
| 100 | 100 | ||
| 101 | validates_format_of :foundation_year, :with => Noosfero::Constants::INTEGER_FORMAT | 101 | validates_format_of :foundation_year, :with => Noosfero::Constants::INTEGER_FORMAT |
| 102 | - | ||
| 103 | validates_format_of :contact_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda { |org| !org.contact_email.blank? }) | 102 | validates_format_of :contact_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda { |org| !org.contact_email.blank? }) |
| 103 | + validates_as_cnpj :cnpj | ||
| 104 | 104 | ||
| 105 | xss_terminate :only => [ :acronym, :contact_person, :contact_email, :legal_form, :economic_activity, :management_information ], :on => 'validation' | 105 | xss_terminate :only => [ :acronym, :contact_person, :contact_email, :legal_form, :economic_activity, :management_information ], :on => 'validation' |
| 106 | 106 | ||
| @@ -149,4 +149,12 @@ class Organization < Profile | @@ -149,4 +149,12 @@ class Organization < Profile | ||
| 149 | false | 149 | false |
| 150 | end | 150 | end |
| 151 | 151 | ||
| 152 | + def members_to_json | ||
| 153 | + members.map { |member| {:id => member.id, :name => member.name} }.to_json | ||
| 154 | + end | ||
| 155 | + | ||
| 156 | + def members_by_role_to_json(role) | ||
| 157 | + members_by_role(role).map { |member| {:id => member.id, :name => member.name} }.to_json | ||
| 158 | + end | ||
| 159 | + | ||
| 152 | end | 160 | end |
app/models/person.rb
| @@ -17,6 +17,8 @@ class Person < Profile | @@ -17,6 +17,8 @@ class Person < Profile | ||
| 17 | 17 | ||
| 18 | has_many :requested_tasks, :class_name => 'Task', :foreign_key => :requestor_id, :dependent => :destroy | 18 | has_many :requested_tasks, :class_name => 'Task', :foreign_key => :requestor_id, :dependent => :destroy |
| 19 | 19 | ||
| 20 | + has_many :abuse_reports, :foreign_key => 'reporter_id', :dependent => :destroy | ||
| 21 | + | ||
| 20 | has_many :mailings | 22 | has_many :mailings |
| 21 | 23 | ||
| 22 | has_many :scraps_sent, :class_name => 'Scrap', :foreign_key => :sender_id, :dependent => :destroy | 24 | has_many :scraps_sent, :class_name => 'Scrap', :foreign_key => :sender_id, :dependent => :destroy |
| @@ -116,6 +118,8 @@ class Person < Profile | @@ -116,6 +118,8 @@ class Person < Profile | ||
| 116 | description | 118 | description |
| 117 | ] | 119 | ] |
| 118 | 120 | ||
| 121 | + validates_multiparameter_assignments | ||
| 122 | + | ||
| 119 | def self.fields | 123 | def self.fields |
| 120 | FIELDS | 124 | FIELDS |
| 121 | end | 125 | end |
| @@ -387,6 +391,21 @@ class Person < Profile | @@ -387,6 +391,21 @@ class Person < Profile | ||
| 387 | leave_hash.to_json | 391 | leave_hash.to_json |
| 388 | end | 392 | end |
| 389 | 393 | ||
| 394 | + def already_reported?(profile) | ||
| 395 | + abuse_reports.any? { |report| report.abuse_complaint.reported == profile && report.abuse_complaint.opened? } | ||
| 396 | + end | ||
| 397 | + | ||
| 398 | + def register_report(abuse_report, profile) | ||
| 399 | + AbuseComplaint.create!(:reported => profile, :target => profile.environment) if !profile.opened_abuse_complaint | ||
| 400 | + abuse_report.abuse_complaint = profile.opened_abuse_complaint | ||
| 401 | + abuse_report.reporter = self | ||
| 402 | + abuse_report.save! | ||
| 403 | + end | ||
| 404 | + | ||
| 405 | + def control_panel_settings_button | ||
| 406 | + {:title => _('Profile Info and settings'), :icon => 'edit-profile'} | ||
| 407 | + end | ||
| 408 | + | ||
| 390 | protected | 409 | protected |
| 391 | 410 | ||
| 392 | def followed_by?(profile) | 411 | def followed_by?(profile) |
app/models/product.rb
| @@ -66,7 +66,7 @@ class Product < ActiveRecord::Base | @@ -66,7 +66,7 @@ class Product < ActiveRecord::Base | ||
| 66 | end | 66 | end |
| 67 | 67 | ||
| 68 | def default_image(size='thumb') | 68 | def default_image(size='thumb') |
| 69 | - '/images/icons-app/product-default-pic-%s.png' % size | 69 | + image ? image.public_filename(size) : '/images/icons-app/product-default-pic-%s.png' % size |
| 70 | end | 70 | end |
| 71 | 71 | ||
| 72 | def category_full_name | 72 | def category_full_name |
| @@ -149,4 +149,8 @@ class Product < ActiveRecord::Base | @@ -149,4 +149,8 @@ class Product < ActiveRecord::Base | ||
| 149 | unit.blank? ? name : "#{name} - #{unit.name.downcase}" | 149 | unit.blank? ? name : "#{name} - #{unit.name.downcase}" |
| 150 | end | 150 | end |
| 151 | 151 | ||
| 152 | + def display_supplier_on_search? | ||
| 153 | + true | ||
| 154 | + end | ||
| 155 | + | ||
| 152 | end | 156 | end |
app/models/products_block.rb
| @@ -20,7 +20,15 @@ class ProductsBlock < Block | @@ -20,7 +20,15 @@ class ProductsBlock < Block | ||
| 20 | block_title(title) + | 20 | block_title(title) + |
| 21 | content_tag( | 21 | content_tag( |
| 22 | 'ul', | 22 | 'ul', |
| 23 | - products.map {|product| content_tag('li', link_to(product.name, product.url, :style => 'background-image:url(%s)' % ( product.image ? product.image.public_filename(:minor) : product.default_image('minor'))), :class => 'product' )} | 23 | + products.map {|product| |
| 24 | + content_tag('li', | ||
| 25 | + link_to( product.name, | ||
| 26 | + product.url, | ||
| 27 | + :style => 'background-image:url(%s)' % product.default_image('minor') | ||
| 28 | + ), | ||
| 29 | + :class => 'product' | ||
| 30 | + ) | ||
| 31 | + } | ||
| 24 | ) | 32 | ) |
| 25 | end | 33 | end |
| 26 | 34 |
app/models/profile.rb
| @@ -52,8 +52,9 @@ class Profile < ActiveRecord::Base | @@ -52,8 +52,9 @@ class Profile < ActiveRecord::Base | ||
| 52 | acts_as_accessible | 52 | acts_as_accessible |
| 53 | 53 | ||
| 54 | named_scope :memberships_of, lambda { |person| { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.accessor_type = ? AND role_assignments.accessor_id = ?', person.class.base_class.name, person.id ] } } | 54 | named_scope :memberships_of, lambda { |person| { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.accessor_type = ? AND role_assignments.accessor_id = ?', person.class.base_class.name, person.id ] } } |
| 55 | - named_scope :enterprises, :conditions => "profiles.type = 'Enterprise'" | ||
| 56 | - named_scope :communities, :conditions => "profiles.type = 'Community'" | 55 | + #FIXME: these will work only if the subclass is already loaded |
| 56 | + named_scope :enterprises, lambda { {:conditions => (Enterprise.send(:subclasses).map(&:name) << 'Enterprise').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} } | ||
| 57 | + named_scope :communities, lambda { {:conditions => (Community.send(:subclasses).map(&:name) << 'Community').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} } | ||
| 57 | 58 | ||
| 58 | def members | 59 | def members |
| 59 | Person.members_of(self) | 60 | Person.members_of(self) |
| @@ -163,34 +164,19 @@ class Profile < ActiveRecord::Base | @@ -163,34 +164,19 @@ class Profile < ActiveRecord::Base | ||
| 163 | 164 | ||
| 164 | has_many :events, :source => 'articles', :class_name => 'Event', :order => 'name' | 165 | has_many :events, :source => 'articles', :class_name => 'Event', :order => 'name' |
| 165 | 166 | ||
| 166 | - %w[ pending finished ].each do |status| | ||
| 167 | - class_eval <<-CODE | ||
| 168 | - def all_#{status}_tasks | ||
| 169 | - env_tasks = [] | ||
| 170 | - if self.person? | ||
| 171 | - env_tasks = Environment.find(:all).select{ |env| self.is_admin?(env) }.map{ |env| env.tasks.#{status} }.flatten | ||
| 172 | - end | ||
| 173 | - tasks.#{status} + env_tasks | ||
| 174 | - end | ||
| 175 | - CODE | ||
| 176 | - end | ||
| 177 | - | ||
| 178 | def find_in_all_tasks(task_id) | 167 | def find_in_all_tasks(task_id) |
| 179 | - if tasks.exists?(task_id) | ||
| 180 | - return tasks.find(task_id) | ||
| 181 | - else | ||
| 182 | - if self.person? | ||
| 183 | - environments_admin = Environment.find(:all).select{ |env| self.is_admin?(env) } | ||
| 184 | - task = environments_admin.select{ |env| env.tasks.exists?(task_id) }.map{ |i| i.tasks.find(task_id) } | ||
| 185 | - return task.first unless task.empty? | ||
| 186 | - end | 168 | + begin |
| 169 | + Task.to(self).find(task_id) | ||
| 170 | + rescue | ||
| 171 | + nil | ||
| 187 | end | 172 | end |
| 188 | - return nil | ||
| 189 | end | 173 | end |
| 190 | 174 | ||
| 191 | has_many :profile_categorizations, :conditions => [ 'categories_profiles.virtual = ?', false ] | 175 | has_many :profile_categorizations, :conditions => [ 'categories_profiles.virtual = ?', false ] |
| 192 | has_many :categories, :through => :profile_categorizations | 176 | has_many :categories, :through => :profile_categorizations |
| 193 | 177 | ||
| 178 | + has_many :abuse_complaints, :foreign_key => 'requestor_id' | ||
| 179 | + | ||
| 194 | def interests | 180 | def interests |
| 195 | categories.select {|item| !item.is_a?(Region)} | 181 | categories.select {|item| !item.is_a?(Region)} |
| 196 | end | 182 | end |
| @@ -564,9 +550,7 @@ private :generate_url, :url_options | @@ -564,9 +550,7 @@ private :generate_url, :url_options | ||
| 564 | if self.closed? && members_count > 0 | 550 | if self.closed? && members_count > 0 |
| 565 | AddMember.create!(:person => person, :organization => self) unless self.already_request_membership?(person) | 551 | AddMember.create!(:person => person, :organization => self) unless self.already_request_membership?(person) |
| 566 | else | 552 | else |
| 567 | - if members_count == 0 | ||
| 568 | - self.affiliate(person, Profile::Roles.admin(environment.id)) | ||
| 569 | - end | 553 | + self.affiliate(person, Profile::Roles.admin(environment.id)) if members_count == 0 |
| 570 | self.affiliate(person, Profile::Roles.member(environment.id)) | 554 | self.affiliate(person, Profile::Roles.member(environment.id)) |
| 571 | end | 555 | end |
| 572 | else | 556 | else |
| @@ -809,6 +793,34 @@ private :generate_url, :url_options | @@ -809,6 +793,34 @@ private :generate_url, :url_options | ||
| 809 | "#{jid(options)}/#{short_name}" | 793 | "#{jid(options)}/#{short_name}" |
| 810 | end | 794 | end |
| 811 | 795 | ||
| 796 | + def is_on_homepage?(url, page=nil) | ||
| 797 | + if page | ||
| 798 | + page == self.home_page | ||
| 799 | + else | ||
| 800 | + url == '/' + self.identifier | ||
| 801 | + end | ||
| 802 | + end | ||
| 803 | + | ||
| 804 | + def opened_abuse_complaint | ||
| 805 | + abuse_complaints.opened.first | ||
| 806 | + end | ||
| 807 | + | ||
| 808 | + def disable | ||
| 809 | + self.visible = false | ||
| 810 | + user.password = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{identifier}--") | ||
| 811 | + user.password_confirmation = user.password | ||
| 812 | + save! | ||
| 813 | + user.save! | ||
| 814 | + end | ||
| 815 | + | ||
| 816 | + def control_panel_settings_button | ||
| 817 | + {:title => _('Profile Info and settings'), :icon => 'edit-profile'} | ||
| 818 | + end | ||
| 819 | + | ||
| 820 | + def self.identification | ||
| 821 | + name | ||
| 822 | + end | ||
| 823 | + | ||
| 812 | protected | 824 | protected |
| 813 | 825 | ||
| 814 | def followed_by?(person) | 826 | def followed_by?(person) |
app/models/profile_list_block.rb
| 1 | class ProfileListBlock < Block | 1 | class ProfileListBlock < Block |
| 2 | 2 | ||
| 3 | settings_items :limit, :type => :integer, :default => 6 | 3 | settings_items :limit, :type => :integer, :default => 6 |
| 4 | - settings_items :prioritize_profiles_with_image, :type => :boolean, :default => false | 4 | + settings_items :prioritize_profiles_with_image, :type => :boolean, :default => true |
| 5 | 5 | ||
| 6 | def self.description | 6 | def self.description |
| 7 | _('Random profiles') | 7 | _('Random profiles') |
| @@ -13,21 +13,21 @@ class ProfileListBlock < Block | @@ -13,21 +13,21 @@ class ProfileListBlock < Block | ||
| 13 | end | 13 | end |
| 14 | 14 | ||
| 15 | def profile_list | 15 | def profile_list |
| 16 | - profiles.visible.all(:limit => limit, :select => 'DISTINCT profiles.*, ' + image_prioritizer + randomizer, :joins => "LEFT OUTER JOIN images ON images.owner_id = profiles.id", :order => image_prioritizer + randomizer) | 16 | + result = nil |
| 17 | + if !prioritize_profiles_with_image | ||
| 18 | + result = profiles.visible.all(:limit => limit, :order => 'updated_at DESC').sort_by{ rand } | ||
| 19 | + elsif profiles.visible.with_image.count >= limit | ||
| 20 | + result = profiles.visible.with_image.all(:limit => limit * 5, :order => 'updated_at DESC').sort_by{ rand } | ||
| 21 | + else | ||
| 22 | + result = profiles.visible.with_image.sort_by{ rand } + profiles.visible.without_image.all(:limit => limit * 5, :order => 'updated_at DESC').sort_by{ rand } | ||
| 23 | + end | ||
| 24 | + result.slice(0..limit-1) | ||
| 17 | end | 25 | end |
| 18 | 26 | ||
| 19 | def profile_count | 27 | def profile_count |
| 20 | profiles.visible.count('DISTINCT(profiles.id)') | 28 | profiles.visible.count('DISTINCT(profiles.id)') |
| 21 | end | 29 | end |
| 22 | 30 | ||
| 23 | - def randomizer | ||
| 24 | - @randomizer ||= "(profiles.id % #{rand(profile_count) + 1})" | ||
| 25 | - end | ||
| 26 | - | ||
| 27 | - def image_prioritizer | ||
| 28 | - prioritize_profiles_with_image ? '(images.id is null),' : '' | ||
| 29 | - end | ||
| 30 | - | ||
| 31 | # the title of the block. Probably will be overriden in subclasses. | 31 | # the title of the block. Probably will be overriden in subclasses. |
| 32 | def default_title | 32 | def default_title |
| 33 | _('{#} People or Groups') | 33 | _('{#} People or Groups') |
app/models/suggest_article.rb
| 1 | class SuggestArticle < Task | 1 | class SuggestArticle < Task |
| 2 | 2 | ||
| 3 | - has_captcha | ||
| 4 | - | ||
| 5 | validates_presence_of :target_id, :article_name, :email, :name, :article_body | 3 | validates_presence_of :target_id, :article_name, :email, :name, :article_body |
| 6 | 4 | ||
| 7 | settings_items :email, :type => String | 5 | settings_items :email, :type => String |
app/models/task.rb
| @@ -20,11 +20,14 @@ class Task < ActiveRecord::Base | @@ -20,11 +20,14 @@ class Task < ActiveRecord::Base | ||
| 20 | # the status of a task that was cancelled. | 20 | # the status of a task that was cancelled. |
| 21 | CANCELLED = 2 | 21 | CANCELLED = 2 |
| 22 | 22 | ||
| 23 | - # the status os a task that was successfully finished | 23 | + # the status of a task that was successfully finished |
| 24 | FINISHED = 3 | 24 | FINISHED = 3 |
| 25 | 25 | ||
| 26 | + # the status of a task that was created but is not displayed yet | ||
| 27 | + HIDDEN = 4 | ||
| 28 | + | ||
| 26 | def self.names | 29 | def self.names |
| 27 | - [nil, N_('Active'), N_('Cancelled'), N_('Finished')] | 30 | + [nil, N_('Active'), N_('Cancelled'), N_('Finished'), N_('Hidden')] |
| 28 | end | 31 | end |
| 29 | end | 32 | end |
| 30 | 33 | ||
| @@ -38,7 +41,7 @@ class Task < ActiveRecord::Base | @@ -38,7 +41,7 @@ class Task < ActiveRecord::Base | ||
| 38 | 41 | ||
| 39 | def initialize(*args) | 42 | def initialize(*args) |
| 40 | super | 43 | super |
| 41 | - self.status ||= Task::Status::ACTIVE | 44 | + self.status = (args.first ? args.first[:status] : nil) || Task::Status::ACTIVE |
| 42 | end | 45 | end |
| 43 | 46 | ||
| 44 | attr_accessor :code_length | 47 | attr_accessor :code_length |
| @@ -52,20 +55,26 @@ class Task < ActiveRecord::Base | @@ -52,20 +55,26 @@ class Task < ActiveRecord::Base | ||
| 52 | end | 55 | end |
| 53 | 56 | ||
| 54 | after_create do |task| | 57 | after_create do |task| |
| 55 | - begin | ||
| 56 | - task.send(:send_notification, :created) | ||
| 57 | - rescue NotImplementedError => ex | ||
| 58 | - RAILS_DEFAULT_LOGGER.info ex.to_s | ||
| 59 | - end | ||
| 60 | - | ||
| 61 | - begin | ||
| 62 | - target_msg = task.target_notification_message | ||
| 63 | - TaskMailer.deliver_target_notification(task, target_msg) if target_msg | ||
| 64 | - rescue NotImplementedError => ex | ||
| 65 | - RAILS_DEFAULT_LOGGER.info ex.to_s | 58 | + unless task.status == Task::Status::HIDDEN |
| 59 | + begin | ||
| 60 | + task.send(:send_notification, :created) | ||
| 61 | + rescue NotImplementedError => ex | ||
| 62 | + RAILS_DEFAULT_LOGGER.info ex.to_s | ||
| 63 | + end | ||
| 64 | + | ||
| 65 | + begin | ||
| 66 | + target_msg = task.target_notification_message | ||
| 67 | + TaskMailer.deliver_target_notification(task, target_msg) if target_msg | ||
| 68 | + rescue NotImplementedError => ex | ||
| 69 | + RAILS_DEFAULT_LOGGER.info ex.to_s | ||
| 70 | + end | ||
| 66 | end | 71 | end |
| 67 | end | 72 | end |
| 68 | 73 | ||
| 74 | + def self.all_types | ||
| 75 | + %w[Invitation EnterpriseActivation AddMember Ticket SuggestArticle AddFriend CreateCommunity AbuseComplaint ApproveArticle CreateEnterprise ChangePassword EmailActivation InviteFriend InviteMember] | ||
| 76 | + end | ||
| 77 | + | ||
| 69 | # this method finished the task. It calls #perform, which must be overriden | 78 | # this method finished the task. It calls #perform, which must be overriden |
| 70 | # by subclasses. At the end a message (as returned by #finish_message) is | 79 | # by subclasses. At the end a message (as returned by #finish_message) is |
| 71 | # sent to the requestor with #notify_requestor. | 80 | # sent to the requestor with #notify_requestor. |
| @@ -175,6 +184,12 @@ class Task < ActiveRecord::Base | @@ -175,6 +184,12 @@ class Task < ActiveRecord::Base | ||
| 175 | raise NotImplementedError, "#{self} does not implement #task_cancelled_message" | 184 | raise NotImplementedError, "#{self} does not implement #task_cancelled_message" |
| 176 | end | 185 | end |
| 177 | 186 | ||
| 187 | + # The message that will be sent to the requestor of the task when its | ||
| 188 | + # activated. | ||
| 189 | + def task_activated_message | ||
| 190 | + raise NotImplementedError, "#{self} does not implement #task_cancelled_message" | ||
| 191 | + end | ||
| 192 | + | ||
| 178 | # The message that will be sent to the *target* of the task when it is | 193 | # The message that will be sent to the *target* of the task when it is |
| 179 | # created. The indent of this message is to notify the target about the | 194 | # created. The indent of this message is to notify the target about the |
| 180 | # request that was just created for him/her. | 195 | # request that was just created for him/her. |
| @@ -199,6 +214,23 @@ class Task < ActiveRecord::Base | @@ -199,6 +214,23 @@ class Task < ActiveRecord::Base | ||
| 199 | self.target.environment unless self.target.nil? | 214 | self.target.environment unless self.target.nil? |
| 200 | end | 215 | end |
| 201 | 216 | ||
| 217 | + def activate | ||
| 218 | + self.status = Task::Status::ACTIVE | ||
| 219 | + save! | ||
| 220 | + begin | ||
| 221 | + self.send(:send_notification, :activated) | ||
| 222 | + rescue NotImplementedError => ex | ||
| 223 | + RAILS_DEFAULT_LOGGER.info ex.to_s | ||
| 224 | + end | ||
| 225 | + | ||
| 226 | + begin | ||
| 227 | + target_msg = target_notification_message | ||
| 228 | + TaskMailer.deliver_target_notification(self, target_msg) if target_msg | ||
| 229 | + rescue NotImplementedError => ex | ||
| 230 | + RAILS_DEFAULT_LOGGER.info ex.to_s | ||
| 231 | + end | ||
| 232 | + end | ||
| 233 | + | ||
| 202 | protected | 234 | protected |
| 203 | 235 | ||
| 204 | # This method must be overrided in subclasses, and its implementation must do | 236 | # This method must be overrided in subclasses, and its implementation must do |
| @@ -232,6 +264,23 @@ class Task < ActiveRecord::Base | @@ -232,6 +264,23 @@ class Task < ActiveRecord::Base | ||
| 232 | 264 | ||
| 233 | named_scope :pending, :conditions => { :status => Task::Status::ACTIVE } | 265 | named_scope :pending, :conditions => { :status => Task::Status::ACTIVE } |
| 234 | named_scope :finished, :conditions => { :status => [Task::Status::CANCELLED, Task::Status::FINISHED] } | 266 | named_scope :finished, :conditions => { :status => [Task::Status::CANCELLED, Task::Status::FINISHED] } |
| 267 | + named_scope :opened, :conditions => { :status => [Task::Status::ACTIVE, Task::Status::HIDDEN] } | ||
| 268 | + named_scope :of, lambda { |type| conditions = type ? "type LIKE '#{type}'" : "1=1"; {:conditions => [conditions]} } | ||
| 269 | + named_scope :order_by, lambda { |attribute, ord| {:order => "#{attribute} #{ord}"} } | ||
| 270 | + | ||
| 271 | + named_scope :to, lambda { |profile| | ||
| 272 | + environment_condition = nil | ||
| 273 | + if profile.person? | ||
| 274 | + envs_ids = Environment.find(:all).select{ |env| profile.is_admin?(env) }.map { |env| "target_id = #{env.id}"}.join(' OR ') | ||
| 275 | + environment_condition = envs_ids.blank? ? nil : "(target_type = 'Environment' AND (#{envs_ids}))" | ||
| 276 | + end | ||
| 277 | + profile_condition = "(target_type = 'Profile' AND target_id = #{profile.id})" | ||
| 278 | + { :conditions => [environment_condition, profile_condition].compact.join(' OR ') } | ||
| 279 | + } | ||
| 280 | + | ||
| 281 | + def opened? | ||
| 282 | + status == Task::Status::ACTIVE || status == Task::Status::HIDDEN | ||
| 283 | + end | ||
| 235 | 284 | ||
| 236 | class << self | 285 | class << self |
| 237 | 286 | ||
| @@ -254,6 +303,10 @@ class Task < ActiveRecord::Base | @@ -254,6 +303,10 @@ class Task < ActiveRecord::Base | ||
| 254 | self.find(:first, :conditions => { :code => code, :status => Task::Status::ACTIVE }) | 303 | self.find(:first, :conditions => { :code => code, :status => Task::Status::ACTIVE }) |
| 255 | end | 304 | end |
| 256 | 305 | ||
| 306 | + def per_page | ||
| 307 | + 15 | ||
| 308 | + end | ||
| 309 | + | ||
| 257 | end | 310 | end |
| 258 | 311 | ||
| 259 | end | 312 | end |
app/models/text_article.rb
| 1 | # a base class for all text article types. | 1 | # a base class for all text article types. |
| 2 | class TextArticle < Article | 2 | class TextArticle < Article |
| 3 | 3 | ||
| 4 | - xss_terminate :only => [ :name, :abstract, :body ], :on => 'validation' | 4 | + xss_terminate :only => [ :name ], :on => 'validation' |
| 5 | 5 | ||
| 6 | include Noosfero::TranslatableContent | 6 | include Noosfero::TranslatableContent |
| 7 | 7 |
app/models/textile_article.rb
| @@ -9,11 +9,28 @@ class TextileArticle < TextArticle | @@ -9,11 +9,28 @@ class TextileArticle < TextArticle | ||
| 9 | end | 9 | end |
| 10 | 10 | ||
| 11 | def to_html(options ={}) | 11 | def to_html(options ={}) |
| 12 | - RedCloth.new(self.body|| '').to_html | 12 | + convert_to_html(body) |
| 13 | + end | ||
| 14 | + | ||
| 15 | + def lead | ||
| 16 | + if abstract.blank? | ||
| 17 | + super | ||
| 18 | + else | ||
| 19 | + convert_to_html(abstract) | ||
| 20 | + end | ||
| 13 | end | 21 | end |
| 14 | 22 | ||
| 15 | def notifiable? | 23 | def notifiable? |
| 16 | true | 24 | true |
| 17 | end | 25 | end |
| 18 | 26 | ||
| 27 | + protected | ||
| 28 | + | ||
| 29 | + def convert_to_html(textile) | ||
| 30 | + @@sanitizer ||= HTML::WhiteListSanitizer.new | ||
| 31 | + converter = RedCloth.new(textile|| '') | ||
| 32 | + converter.hard_breaks = false | ||
| 33 | + @@sanitizer.sanitize(converter.to_html) | ||
| 34 | + end | ||
| 35 | + | ||
| 19 | end | 36 | end |
app/models/thumbnail.rb
| @@ -2,4 +2,8 @@ class Thumbnail < ActiveRecord::Base | @@ -2,4 +2,8 @@ class Thumbnail < ActiveRecord::Base | ||
| 2 | has_attachment :storage => :file_system, | 2 | has_attachment :storage => :file_system, |
| 3 | :content_type => :image, :max_size => 5.megabytes | 3 | :content_type => :image, :max_size => 5.megabytes |
| 4 | validates_as_attachment | 4 | validates_as_attachment |
| 5 | + | ||
| 6 | + sanitize_filename | ||
| 7 | + | ||
| 8 | + postgresql_attachment_fu | ||
| 5 | end | 9 | end |
app/models/ticket.rb
app/models/uploaded_file.rb
| @@ -18,6 +18,8 @@ class UploadedFile < Article | @@ -18,6 +18,8 @@ class UploadedFile < Article | ||
| 18 | 18 | ||
| 19 | validates_size_of :title, :maximum => 60, :if => (lambda { |file| !file.title.blank? }) | 19 | validates_size_of :title, :maximum => 60, :if => (lambda { |file| !file.title.blank? }) |
| 20 | 20 | ||
| 21 | + sanitize_filename | ||
| 22 | + | ||
| 21 | before_create do |uploaded_file| | 23 | before_create do |uploaded_file| |
| 22 | uploaded_file.is_image = true if uploaded_file.image? | 24 | uploaded_file.is_image = true if uploaded_file.image? |
| 23 | end | 25 | end |
| @@ -52,6 +54,8 @@ class UploadedFile < Article | @@ -52,6 +54,8 @@ class UploadedFile < Article | ||
| 52 | 54 | ||
| 53 | delay_attachment_fu_thumbnails | 55 | delay_attachment_fu_thumbnails |
| 54 | 56 | ||
| 57 | + postgresql_attachment_fu | ||
| 58 | + | ||
| 55 | def self.icon_name(article = nil) | 59 | def self.icon_name(article = nil) |
| 56 | if article | 60 | if article |
| 57 | article.image? ? article.public_filename(:icon) : (article.mime_type ? article.mime_type.gsub(/[\/+.]/, '-') : 'upload-file') | 61 | article.image? ? article.public_filename(:icon) : (article.mime_type ? article.mime_type.gsub(/[\/+.]/, '-') : 'upload-file') |
| @@ -132,4 +136,8 @@ class UploadedFile < Article | @@ -132,4 +136,8 @@ class UploadedFile < Article | ||
| 132 | def gallery? | 136 | def gallery? |
| 133 | self.parent && self.parent.folder? && self.parent.gallery? | 137 | self.parent && self.parent.folder? && self.parent.gallery? |
| 134 | end | 138 | end |
| 139 | + | ||
| 140 | + def uploaded_file? | ||
| 141 | + true | ||
| 142 | + end | ||
| 135 | end | 143 | end |
app/models/user.rb
| @@ -21,6 +21,8 @@ class User < ActiveRecord::Base | @@ -21,6 +21,8 @@ class User < ActiveRecord::Base | ||
| 21 | end | 21 | end |
| 22 | end | 22 | end |
| 23 | 23 | ||
| 24 | + before_create :make_activation_code | ||
| 25 | + | ||
| 24 | before_create do |user| | 26 | before_create do |user| |
| 25 | if user.environment.nil? | 27 | if user.environment.nil? |
| 26 | user.environment = Environment.default | 28 | user.environment = Environment.default |
| @@ -31,8 +33,11 @@ class User < ActiveRecord::Base | @@ -31,8 +33,11 @@ class User < ActiveRecord::Base | ||
| 31 | user.person ||= Person.new | 33 | user.person ||= Person.new |
| 32 | user.person.attributes = user.person_data.merge(:identifier => user.login, :user_id => user.id, :environment_id => user.environment_id) | 34 | user.person.attributes = user.person_data.merge(:identifier => user.login, :user_id => user.id, :environment_id => user.environment_id) |
| 33 | user.person.name ||= user.login | 35 | user.person.name ||= user.login |
| 36 | + user.person.visible = false unless user.activated? | ||
| 34 | user.person.save! | 37 | user.person.save! |
| 35 | end | 38 | end |
| 39 | + after_create :deliver_activation_code | ||
| 40 | + after_create :delay_activation_check | ||
| 36 | 41 | ||
| 37 | attr_writer :person_data | 42 | attr_writer :person_data |
| 38 | def person_data | 43 | def person_data |
| @@ -55,6 +60,17 @@ class User < ActiveRecord::Base | @@ -55,6 +60,17 @@ class User < ActiveRecord::Base | ||
| 55 | :environment => user.environment.name, | 60 | :environment => user.environment.name, |
| 56 | :url => url_for(:host => user.environment.default_hostname, :controller => 'home') | 61 | :url => url_for(:host => user.environment.default_hostname, :controller => 'home') |
| 57 | end | 62 | end |
| 63 | + | ||
| 64 | + def activation_code(user) | ||
| 65 | + recipients user.email | ||
| 66 | + | ||
| 67 | + from "#{user.environment.name} <#{user.environment.contact_email}>" | ||
| 68 | + subject _("[%s] Activate your account") % [user.environment.name] | ||
| 69 | + body :recipient => user.name, | ||
| 70 | + :activation_code => user.activation_code, | ||
| 71 | + :environment => user.environment.name, | ||
| 72 | + :url => user.environment.top_url | ||
| 73 | + end | ||
| 58 | end | 74 | end |
| 59 | 75 | ||
| 60 | def signup! | 76 | def signup! |
| @@ -67,6 +83,8 @@ class User < ActiveRecord::Base | @@ -67,6 +83,8 @@ class User < ActiveRecord::Base | ||
| 67 | has_one :person, :dependent => :destroy | 83 | has_one :person, :dependent => :destroy |
| 68 | belongs_to :environment | 84 | belongs_to :environment |
| 69 | 85 | ||
| 86 | + attr_protected :activated_at | ||
| 87 | + | ||
| 70 | # Virtual attribute for the unencrypted password | 88 | # Virtual attribute for the unencrypted password |
| 71 | attr_accessor :password | 89 | attr_accessor :password |
| 72 | 90 | ||
| @@ -87,10 +105,22 @@ class User < ActiveRecord::Base | @@ -87,10 +105,22 @@ class User < ActiveRecord::Base | ||
| 87 | # Authenticates a user by their login name and unencrypted password. Returns the user or nil. | 105 | # Authenticates a user by their login name and unencrypted password. Returns the user or nil. |
| 88 | def self.authenticate(login, password, environment = nil) | 106 | def self.authenticate(login, password, environment = nil) |
| 89 | environment ||= Environment.default | 107 | environment ||= Environment.default |
| 90 | - u = find_by_login_and_environment_id(login, environment.id) # need to get the salt | 108 | + u = first :conditions => ['login = ? AND environment_id = ? AND activated_at IS NOT NULL', login, environment.id] # need to get the salt |
| 91 | u && u.authenticated?(password) ? u : nil | 109 | u && u.authenticated?(password) ? u : nil |
| 92 | end | 110 | end |
| 93 | 111 | ||
| 112 | + # Activates the user in the database. | ||
| 113 | + def activate | ||
| 114 | + self.activated_at = Time.now.utc | ||
| 115 | + self.activation_code = nil | ||
| 116 | + self.person.visible = true | ||
| 117 | + self.person.save! && self.save | ||
| 118 | + end | ||
| 119 | + | ||
| 120 | + def activated? | ||
| 121 | + self.activation_code.nil? && !self.activated_at.nil? | ||
| 122 | + end | ||
| 123 | + | ||
| 94 | class UnsupportedEncryptionType < Exception; end | 124 | class UnsupportedEncryptionType < Exception; end |
| 95 | 125 | ||
| 96 | def self.system_encryption_method | 126 | def self.system_encryption_method |
| @@ -195,7 +225,7 @@ class User < ActiveRecord::Base | @@ -195,7 +225,7 @@ class User < ActiveRecord::Base | ||
| 195 | end | 225 | end |
| 196 | 226 | ||
| 197 | def name | 227 | def name |
| 198 | - person.name | 228 | + person ? person.name : login |
| 199 | end | 229 | end |
| 200 | 230 | ||
| 201 | def enable_email! | 231 | def enable_email! |
| @@ -253,4 +283,16 @@ class User < ActiveRecord::Base | @@ -253,4 +283,16 @@ class User < ActiveRecord::Base | ||
| 253 | def password_required? | 283 | def password_required? |
| 254 | crypted_password.blank? || !password.blank? | 284 | crypted_password.blank? || !password.blank? |
| 255 | end | 285 | end |
| 286 | + | ||
| 287 | + def make_activation_code | ||
| 288 | + self.activation_code = Digest::SHA1.hexdigest(Time.now.to_s.split(//).sort_by{rand}.join) | ||
| 289 | + end | ||
| 290 | + | ||
| 291 | + def deliver_activation_code | ||
| 292 | + User::Mailer.deliver_activation_code(self) unless self.activation_code.blank? | ||
| 293 | + end | ||
| 294 | + | ||
| 295 | + def delay_activation_check | ||
| 296 | + Delayed::Job.enqueue(UserActivationJob.new(self.id), 0, 72.hours.from_now) | ||
| 297 | + end | ||
| 256 | end | 298 | end |
app/sweepers/article_sweeper.rb
| @@ -21,7 +21,7 @@ protected | @@ -21,7 +21,7 @@ protected | ||
| 21 | blocks = article.profile.blocks | 21 | blocks = article.profile.blocks |
| 22 | blocks += article.profile.environment.blocks if article.profile.environment | 22 | blocks += article.profile.environment.blocks if article.profile.environment |
| 23 | blocks = blocks.select{|b|[RecentDocumentsBlock, BlogArchivesBlock].any?{|c| b.kind_of?(c)}} | 23 | blocks = blocks.select{|b|[RecentDocumentsBlock, BlogArchivesBlock].any?{|c| b.kind_of?(c)}} |
| 24 | - blocks.map(&:cache_keys).each{|ck|expire_timeout_fragment(ck)} | 24 | + blocks.map(&:cache_key).each{|ck|expire_timeout_fragment(ck)} |
| 25 | env = article.profile.environment | 25 | env = article.profile.environment |
| 26 | if env && (env.portal_community == article.profile) | 26 | if env && (env.portal_community == article.profile) |
| 27 | expire_fragment(env.portal_news_cache_key) | 27 | expire_fragment(env.portal_news_cache_key) |
app/sweepers/friendship_sweeper.rb
| @@ -35,7 +35,7 @@ protected | @@ -35,7 +35,7 @@ protected | ||
| 35 | end | 35 | end |
| 36 | 36 | ||
| 37 | blocks = profile.blocks.select{|b| b.kind_of?(FriendsBlock)} | 37 | blocks = profile.blocks.select{|b| b.kind_of?(FriendsBlock)} |
| 38 | - blocks.map(&:cache_keys).each{|ck|expire_timeout_fragment(ck)} | 38 | + blocks.map(&:cache_key).each{|ck|expire_timeout_fragment(ck)} |
| 39 | end | 39 | end |
| 40 | 40 | ||
| 41 | end | 41 | end |
app/sweepers/profile_sweeper.rb
| @@ -23,12 +23,25 @@ protected | @@ -23,12 +23,25 @@ protected | ||
| 23 | expire_profile_index(profile) if profile.person? | 23 | expire_profile_index(profile) if profile.person? |
| 24 | 24 | ||
| 25 | profile.blocks.each do |block| | 25 | profile.blocks.each do |block| |
| 26 | - expire_timeout_fragment(block.cache_keys) | 26 | + expire_timeout_fragment(block.cache_key) |
| 27 | end | 27 | end |
| 28 | + | ||
| 29 | + expire_blogs(profile) if profile.organization? | ||
| 28 | end | 30 | end |
| 29 | 31 | ||
| 30 | def expire_statistics_block_cache(profile) | 32 | def expire_statistics_block_cache(profile) |
| 31 | blocks = profile.environment.blocks.select { |b| b.kind_of?(EnvironmentStatisticsBlock) } | 33 | blocks = profile.environment.blocks.select { |b| b.kind_of?(EnvironmentStatisticsBlock) } |
| 32 | - blocks.map(&:cache_keys).each{|ck|expire_timeout_fragment(ck)} | 34 | + blocks.map(&:cache_key).each{|ck|expire_timeout_fragment(ck)} |
| 33 | end | 35 | end |
| 36 | + | ||
| 37 | + def expire_blogs(profile) | ||
| 38 | + profile.blogs.select{|b| !b.empty?}.each do |blog| | ||
| 39 | + pages = blog.posts.count / blog.posts_per_page + 1 | ||
| 40 | + ([nil] + (1..pages).to_a).each do |i| | ||
| 41 | + expire_timeout_fragment(blog.cache_key({:npage => i})) | ||
| 42 | + expire_timeout_fragment(blog.cache_key({:npage => i}, profile)) | ||
| 43 | + end | ||
| 44 | + end | ||
| 45 | + end | ||
| 46 | + | ||
| 34 | end | 47 | end |
app/sweepers/role_assignment_sweeper.rb
| @@ -25,7 +25,7 @@ protected | @@ -25,7 +25,7 @@ protected | ||
| 25 | 25 | ||
| 26 | profile.blocks_to_expire_cache.each { |block| | 26 | profile.blocks_to_expire_cache.each { |block| |
| 27 | blocks = profile.blocks.select{|b| b.kind_of?(block)} | 27 | blocks = profile.blocks.select{|b| b.kind_of?(block)} |
| 28 | - blocks.map(&:cache_keys).each{|ck|expire_timeout_fragment(ck)} | 28 | + blocks.map(&:cache_key).each{|ck|expire_timeout_fragment(ck)} |
| 29 | } | 29 | } |
| 30 | end | 30 | end |
| 31 | 31 |
app/views/account/_signup_form.rhtml
| @@ -7,8 +7,7 @@ | @@ -7,8 +7,7 @@ | ||
| 7 | </div> | 7 | </div> |
| 8 | <% end %> | 8 | <% end %> |
| 9 | 9 | ||
| 10 | -<% labelled_form_for :user, @user do |f| %> | ||
| 11 | -<%= icaptcha_field() %> | 10 | +<% labelled_form_for :user, @user, :html => { :multipart => true } do |f| %> |
| 12 | 11 | ||
| 13 | <%= hidden_field_tag :invitation_code, @invitation_code %> | 12 | <%= hidden_field_tag :invitation_code, @invitation_code %> |
| 14 | 13 |
app/views/account/login.rhtml
| @@ -5,9 +5,11 @@ | @@ -5,9 +5,11 @@ | ||
| 5 | <% @user ||= User.new %> | 5 | <% @user ||= User.new %> |
| 6 | <% is_thickbox ||= false %> | 6 | <% is_thickbox ||= false %> |
| 7 | 7 | ||
| 8 | +<%= @message %> | ||
| 9 | + | ||
| 8 | <% labelled_form_for :user, @user, :url => login_url do |f| %> | 10 | <% labelled_form_for :user, @user, :url => login_url do |f| %> |
| 9 | 11 | ||
| 10 | - <%= f.text_field :login, :id => 'main_user_login', :onchange => 'this.value = convToValidLogin( this.value )' %> | 12 | + <%= f.text_field :login, :id => 'main_user_login', :onchange => 'this.value = convToValidLogin( this.value )', :value => params[:userlogin] %> |
| 11 | 13 | ||
| 12 | <%= f.password_field :password %> | 14 | <%= f.password_field :password %> |
| 13 | 15 |
app/views/account/signup.rhtml
| 1 | <h1><%= _('Signup') %></h1> | 1 | <h1><%= _('Signup') %></h1> |
| 2 | -<%= render :partial => 'signup_form' %> | 2 | +<% if @register_pending %> |
| 3 | + <%= _('Thanks for signing up! Now check your e-mail to activate your account!') %> | ||
| 4 | + <p style="text-align: center"><%= link_to(_('Go to the homepage'), '/') %></p> | ||
| 5 | +<% else %> | ||
| 6 | + <%= render :partial => 'signup_form' %> | ||
| 7 | +<% end %> |
app/views/admin_panel/edit_templates.rhtml
| 1 | <h1><%= _('Edit Templates') %></h1> | 1 | <h1><%= _('Edit Templates') %></h1> |
| 2 | 2 | ||
| 3 | <ul> | 3 | <ul> |
| 4 | -<li><%= link_to _('Edit Person Template'), :controller => 'profile_editor', :profile => environment.person_template.identifier %></li> | ||
| 5 | -<li><%= link_to _('Edit Community Template'), :controller => 'profile_editor', :profile => environment.community_template.identifier %></li> | ||
| 6 | -<li><%= link_to __('Edit Enterprise Template'), :controller => 'profile_editor', :profile => environment.enterprise_template.identifier %></li> | 4 | +<% [[_('Edit Person Template'), environment.person_template], |
| 5 | + [_('Edit Community Template'), environment.community_template], | ||
| 6 | + [__('Edit Enterprise Template'), environment.enterprise_template], | ||
| 7 | + [__('Edit Inactive Enterprise Template'), environment.inactive_enterprise_template]].select{|i| i[1]}.each do |row| %> | ||
| 8 | +<li><%= link_to row[0], :controller => 'profile_editor', :profile => row[1].identifier %></li> | ||
| 9 | +<% end %> | ||
| 7 | </ul> | 10 | </ul> |
app/views/admin_panel/index.rhtml
| @@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
| 3 | <p><%= _('You, as an environment administrator, has the following options:')%></p> | 3 | <p><%= _('You, as an environment administrator, has the following options:')%></p> |
| 4 | 4 | ||
| 5 | <table> | 5 | <table> |
| 6 | - <tr><td><%= link_to _('Edit site info'), :action => 'site_info' %></td></tr> | 6 | + <tr><td><%= link_to _('Edit environment settings'), :action => 'site_info' %></td></tr> |
| 7 | <tr><td><%= link_to __('Edit message for disabled enterprises'), :action => 'message_for_disabled_enterprise' %></td></tr> | 7 | <tr><td><%= link_to __('Edit message for disabled enterprises'), :action => 'message_for_disabled_enterprise' %></td></tr> |
| 8 | <tr><td><%= link_to _('Enable/disable features'), :controller => 'features' %></td></tr> | 8 | <tr><td><%= link_to _('Enable/disable features'), :controller => 'features' %></td></tr> |
| 9 | <tr><td><%= link_to _('Enable/disable plugins'), :controller => 'plugins' %></td></tr> | 9 | <tr><td><%= link_to _('Enable/disable plugins'), :controller => 'plugins' %></td></tr> |
| @@ -16,4 +16,7 @@ | @@ -16,4 +16,7 @@ | ||
| 16 | <tr><td><%= link_to _('Manage Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr> | 16 | <tr><td><%= link_to _('Manage Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr> |
| 17 | <tr><td><%= link_to _('Set Portal'), :action => 'set_portal_community' %></td></tr> | 17 | <tr><td><%= link_to _('Set Portal'), :action => 'set_portal_community' %></td></tr> |
| 18 | <tr><td><%= link_to _('Terms of use'), :action => 'terms_of_use' %></td></tr> | 18 | <tr><td><%= link_to _('Terms of use'), :action => 'terms_of_use' %></td></tr> |
| 19 | + <% @plugins.map(:admin_panel_links).each do |link| %> | ||
| 20 | + <tr><td><%= link_to link[:title], link[:url] %></td></tr> | ||
| 21 | + <% end %> | ||
| 19 | </table> | 22 | </table> |
app/views/admin_panel/site_info.rhtml
| 1 | -<h2><%= _('Site info') %></h2> | 1 | +<h2><%= _('Environment settings') %></h2> |
| 2 | 2 | ||
| 3 | -<%= render :file => 'shared/tiny_mce' %> | ||
| 4 | - | ||
| 5 | -<% labelled_form_for :environment, @environment do |f| %> | 3 | +<%= error_messages_for :environment %> |
| 6 | 4 | ||
| 7 | - <%= labelled_form_field(_('Site name'), text_field(:environment, :name)) %> | 5 | +<%= render :file => 'shared/tiny_mce' %> |
| 8 | 6 | ||
| 7 | +<% labelled_form_for :environment, @environment, :url => {:host => @environment.default_hostname} do |f| %> | ||
| 8 | + <%= required labelled_form_field(_('Site name'), text_field(:environment, :name)) %> | ||
| 9 | + <%= required f.text_field(:reports_lower_bound, :size => 3) %> | ||
| 9 | <%= labelled_form_field _('Homepage content'), text_area(:environment, :description, :cols => 40, :style => 'width: 90%', :class => 'mceEditor') %> | 10 | <%= labelled_form_field _('Homepage content'), text_area(:environment, :description, :cols => 40, :style => 'width: 90%', :class => 'mceEditor') %> |
| 10 | 11 | ||
| 11 | <% button_bar do %> | 12 | <% button_bar do %> |
| 12 | - <%= submit_button(:save, _('Save')) %> | ||
| 13 | - <%= button(:cancel, _('Cancel'), :action => 'index') %> | 13 | + <%= submit_button(:save, _('Save'), :cancel => {:action => 'index'}) %> |
| 14 | <% end %> | 14 | <% end %> |
| 15 | - | ||
| 16 | <% end %> | 15 | <% end %> |
app/views/blocks/my_network.rhtml
| @@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
| 6 | <li><%= link_to(__('Homepage'), owner.url, :class => 'url') %></li> | 6 | <li><%= link_to(__('Homepage'), owner.url, :class => 'url') %></li> |
| 7 | <li><%= link_to(_('View profile'), owner.public_profile_url) %></li> | 7 | <li><%= link_to(_('View profile'), owner.public_profile_url) %></li> |
| 8 | <% if !user.nil? and owner.organization? and user.has_permission?('edit_profile', profile) %> | 8 | <% if !user.nil? and owner.organization? and user.has_permission?('edit_profile', profile) %> |
| 9 | - <li><%= link_to _('Control panel'), :controller => 'profile_editor' %></li> | 9 | + <li><%= link_to _('Control panel'), :controller => 'profile_editor', :profile => profile.identifier %></li> |
| 10 | <% end %> | 10 | <% end %> |
| 11 | </ul> | 11 | </ul> |
| 12 | 12 |
app/views/blocks/profile_image.rhtml
| @@ -20,5 +20,5 @@ | @@ -20,5 +20,5 @@ | ||
| 20 | 20 | ||
| 21 | </div><!-- end class="vcard" --> | 21 | </div><!-- end class="vcard" --> |
| 22 | <script type="text/javascript"> | 22 | <script type="text/javascript"> |
| 23 | - <%= remote_function :url => { :controller => 'profile', :action => 'profile_info', :block_id => block.id } %> | 23 | + <%= remote_function :url => { :controller => 'profile', :profile => profile.identifier, :action => 'profile_info', :block_id => block.id } %> |
| 24 | </script> | 24 | </script> |
app/views/blocks/profile_info.rhtml
| @@ -41,5 +41,5 @@ | @@ -41,5 +41,5 @@ | ||
| 41 | 41 | ||
| 42 | </div><!-- end class="vcard" --> | 42 | </div><!-- end class="vcard" --> |
| 43 | <script type="text/javascript"> | 43 | <script type="text/javascript"> |
| 44 | - <%= remote_function :url => { :controller => 'profile', :action => 'profile_info', :block_id => block.id } %> | 44 | + <%= remote_function :url => { :controller => 'profile', :profile => profile.identifier, :action => 'profile_info', :block_id => block.id } %> |
| 45 | </script> | 45 | </script> |
app/views/blocks/profile_info_actions/community.rhtml
| 1 | <ul> | 1 | <ul> |
| 2 | <% if logged_in? %> | 2 | <% if logged_in? %> |
| 3 | - | ||
| 4 | <% if profile.members.include?(user) %> | 3 | <% if profile.members.include?(user) %> |
| 5 | <li> | 4 | <li> |
| 6 | - <%= button(:delete, content_tag('span', __('Leave')), profile.leave_url, :class => 'leave-community', :title => _("Leave community"), :style => 'position: relative;') %> | ||
| 7 | - <%= button(:add, content_tag('span', __('Join')), profile.join_url, :class => 'join-community', :title => _("Join community"), :style => 'position: relative; display: none;') %> | 5 | + <%= button(:delete, content_tag('span', __('Leave')), profile.leave_url, |
| 6 | + :class => 'leave-community', | ||
| 7 | + :title => _("Leave community"), | ||
| 8 | + :style => 'position: relative;') %> | ||
| 9 | + <%= button(:add, content_tag('span', __('Join')), profile.join_url, | ||
| 10 | + :class => 'join-community', | ||
| 11 | + :title => _("Join community"), | ||
| 12 | + :style => 'position: relative; display: none;') %> | ||
| 8 | </li> | 13 | </li> |
| 9 | <% else %> | 14 | <% else %> |
| 10 | <% unless profile.already_request_membership?(user) %> | 15 | <% unless profile.already_request_membership?(user) %> |
| 11 | <li> | 16 | <li> |
| 12 | - <%= button(:delete, content_tag('span', __('Leave')), profile.leave_url, :class => 'leave-community', :title => _("Leave community"), :style => 'position: relative; display: none;') %> | ||
| 13 | - <%= button(:add, content_tag('span', __('Join')), profile.join_url, :class => 'join-community', :title => _("Join community"), :style => 'position: relative;') %> | 17 | + <%= button(:delete, content_tag('span', __('Leave')), profile.leave_url, |
| 18 | + :class => 'leave-community', | ||
| 19 | + :title => _("Leave community"), | ||
| 20 | + :style => 'position: relative; display: none;') %> | ||
| 21 | + <%= button(:add, content_tag('span', __('Join')), profile.join_url, | ||
| 22 | + :class => 'join-community', | ||
| 23 | + :title => _("Join community"), | ||
| 24 | + :style => 'position: relative;') %> | ||
| 14 | </li> | 25 | </li> |
| 15 | <% end %> | 26 | <% end %> |
| 16 | <% end %> | 27 | <% end %> |
| 28 | + | ||
| 17 | <% if profile.enable_contact? %> | 29 | <% if profile.enable_contact? %> |
| 18 | <li> | 30 | <li> |
| 19 | - <%= link_to content_tag('span', _('Send an e-mail')), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}, :class => 'button with-text icon-menu-mail' %> | 31 | + <%= link_to content_tag('span', _('Send an e-mail')), |
| 32 | + { :profile => profile.identifier, | ||
| 33 | + :controller => 'contact', | ||
| 34 | + :action => 'new' }, | ||
| 35 | + :class => 'button with-text icon-menu-mail' %> | ||
| 20 | </li> | 36 | </li> |
| 21 | <% end %> | 37 | <% end %> |
| 22 | - <%= render_environment_features(:profile_actions) %> | ||
| 23 | 38 | ||
| 24 | - <% else %> | 39 | + <li><%= report_abuse(profile, :button) %></li> |
| 25 | 40 | ||
| 41 | + <%= render_environment_features(:profile_actions) %> | ||
| 42 | + <% else %> | ||
| 26 | <li> | 43 | <li> |
| 27 | - <%= link_to content_tag('span', _('Join')), profile.join_not_logged_url, :class => 'button with-text icon-add', :title => _('Join this community') %> | 44 | + <%= link_to content_tag('span', _('Join')), profile.join_not_logged_url, |
| 45 | + :class => 'button with-text icon-add', | ||
| 46 | + :title => _('Join this community') %> | ||
| 28 | </li> | 47 | </li> |
| 29 | - | ||
| 30 | <% end %> | 48 | <% end %> |
| 31 | </ul> | 49 | </ul> |
app/views/blocks/profile_info_actions/enterprise.rhtml
| @@ -7,4 +7,6 @@ | @@ -7,4 +7,6 @@ | ||
| 7 | <% if profile.enable_contact? %> | 7 | <% if profile.enable_contact? %> |
| 8 | <li> <%= link_to content_tag('span', _('Send an e-mail')), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}, {:id => 'enterprise-contact-button', :class => 'button with-text icon-menu-mail'} %> </li> | 8 | <li> <%= link_to content_tag('span', _('Send an e-mail')), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}, {:id => 'enterprise-contact-button', :class => 'button with-text icon-menu-mail'} %> </li> |
| 9 | <% end %> | 9 | <% end %> |
| 10 | + | ||
| 11 | + <li><%= report_abuse(profile, :button) %></li> | ||
| 10 | </ul> | 12 | </ul> |
app/views/blocks/profile_info_actions/person.rhtml
| @@ -11,5 +11,6 @@ | @@ -11,5 +11,6 @@ | ||
| 11 | <li> <%= link_to content_tag('span', _('Send an e-mail')), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}, :class => 'button with-text icon-menu-mail' %> </li> | 11 | <li> <%= link_to content_tag('span', _('Send an e-mail')), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}, :class => 'button with-text icon-menu-mail' %> </li> |
| 12 | <% end %> | 12 | <% end %> |
| 13 | 13 | ||
| 14 | + <li><%= report_abuse(profile, :button) %></li> | ||
| 14 | <% end %> | 15 | <% end %> |
| 15 | </ul> | 16 | </ul> |
app/views/box_organizer/_article_block.rhtml
| @@ -5,6 +5,6 @@ | @@ -5,6 +5,6 @@ | ||
| 5 | </p> | 5 | </p> |
| 6 | <% else %> | 6 | <% else %> |
| 7 | <% articles = @block.available_articles.select {|article| !article.folder? } %> | 7 | <% articles = @block.available_articles.select {|article| !article.folder? } %> |
| 8 | - <%= select_tag('block[article_id]', options_for_select_with_title(articles.map {|item| [item.path, item.id]})) %> | 8 | + <%= select_tag('block[article_id]', options_for_select_with_title(articles.map {|item| [item.path, item.id]}, @block.article ? @block.article.id : nil)) %> |
| 9 | <% end %> | 9 | <% end %> |
| 10 | </div> | 10 | </div> |
app/views/box_organizer/edit.rhtml
| @@ -14,6 +14,9 @@ | @@ -14,6 +14,9 @@ | ||
| 14 | <%= radio_button(:block, :display, 'home_page_only') %> | 14 | <%= radio_button(:block, :display, 'home_page_only') %> |
| 15 | <%= label_tag('block_display_home_page_only', _('Only in the homepage')) %> | 15 | <%= label_tag('block_display_home_page_only', _('Only in the homepage')) %> |
| 16 | <br/> | 16 | <br/> |
| 17 | + <%= radio_button(:block, :display, 'except_home_page') %> | ||
| 18 | + <%= label_tag('block_display_except_home_page', _('In all pages, except in the homepage')) %> | ||
| 19 | + <br/> | ||
| 17 | <%= radio_button(:block, :display, 'never') %> | 20 | <%= radio_button(:block, :display, 'never') %> |
| 18 | <%= label_tag('block_display_never', _("Don't display")) %> | 21 | <%= label_tag('block_display_never', _("Don't display")) %> |
| 19 | </div> | 22 | </div> |
| @@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
| 1 | +<li class="<%= 'browse-results-type-content ' + icon_for_article(result) %>"> | ||
| 2 | + <strong><%= link_to(result.title, result.view_url) %></strong> | ||
| 3 | + <div class="item_meta"> | ||
| 4 | + <span class="item_by"> | ||
| 5 | + <%= _('by %s') % link_to(result.author.name, result.author.url) %> | ||
| 6 | + </span> | ||
| 7 | + <span class="extra-info"> | ||
| 8 | + <%= (@filter == 'more_recent' ? result.send(@filter + '_label') + show_date(result.created_at) : result.send(@filter + '_label')) %> | ||
| 9 | + </span> | ||
| 10 | + </div> | ||
| 11 | +</li> |
app/views/browse/_display_results.rhtml
| @@ -8,7 +8,7 @@ | @@ -8,7 +8,7 @@ | ||
| 8 | <% end %> | 8 | <% end %> |
| 9 | <ul class='common-profile-list-block'> | 9 | <ul class='common-profile-list-block'> |
| 10 | <% @results.each do |result| %> | 10 | <% @results.each do |result| %> |
| 11 | - <%= render :partial => partial_for_class(result.class), :locals => {:profile => result} %> | 11 | + <%= render :partial => partial_for_class(result.class), :locals => {:result => result} %> |
| 12 | <% end %> | 12 | <% end %> |
| 13 | </ul> | 13 | </ul> |
| 14 | <br style='clear: both;'> | 14 | <br style='clear: both;'> |
app/views/browse/_person.rhtml
| 1 | -<%= profile_image_link profile, :portrait, 'li', | ||
| 2 | - "<span class='adr'>#{profile.city}</span>" + | ||
| 3 | - (@filter == 'more_recent' ? profile.send(@filter + '_label') + show_date(profile.created_at) : profile.send(@filter + '_label')) %> | 1 | +<%= profile_image_link result, :portrait, 'li', |
| 2 | + "<span class='adr'>#{result.city}</span>" + | ||
| 3 | + (@filter == 'more_recent' ? result.send(@filter + '_label') + show_date(result.created_at) : result.send(@filter + '_label')) %> |
app/views/browse/_profile.rhtml
| 1 | -<%= profile_image_link profile, :portrait, 'li', @filter == 'more_recent' ? profile.send(@filter + '_label') + show_date(profile.created_at) : profile.send(@filter + '_label') %> | 1 | +<%= profile_image_link result, :portrait, 'li', @filter == 'more_recent' ? result.send(@filter + '_label') + show_date(result.created_at) : result.send(@filter + '_label') %> |
app/views/categories/_category.rhtml
| @@ -2,12 +2,12 @@ | @@ -2,12 +2,12 @@ | ||
| 2 | <div class='treeitem'> | 2 | <div class='treeitem'> |
| 3 | <%= display_color_for_category(category) %> | 3 | <%= display_color_for_category(category) %> |
| 4 | <%= category.name %> | 4 | <%= category.name %> |
| 5 | - <div class='button' id="show_button_<%= category.id %>"> | ||
| 6 | - <%= link_to_function(_('Show'), "['category_#{category.id}','hide_button_#{category.id}'].each(Element.show); Element.hide('show_button_#{category.id}');") unless category.children.empty? %> | ||
| 7 | - </div> | ||
| 8 | - <div class='button' id="hide_button_<%= category.id %>" style='display:none;'> | ||
| 9 | - <%= link_to_function(_('Hide'), "['category_#{category.id}','hide_button_#{category.id}'].each(Element.hide); Element.show('show_button_#{category.id}') ") %> | ||
| 10 | - </div> | 5 | + <% if category.children.count > 0 %> |
| 6 | + <div class='button' id="category-loading-<%= category.id %>" style="position: relative;"> | ||
| 7 | + <a href="#" id="show-button-<%= category.id %>" class="show-button" onclick="return false;" data-category="<%= category.id %>"><%= _('Show') %></a> | ||
| 8 | + </div> | ||
| 9 | + <a href="#" id="hide-button-<%= category.id %>" class="hide-button" onclick="return false;" data-category="<%= category.id %>" style="display: none;"><%= _('Hide') %></a> | ||
| 10 | + <% end %> | ||
| 11 | 11 | ||
| 12 | <div> | 12 | <div> |
| 13 | <%= link_to _('Add subcategory'), :action => 'new', :parent_id => category %> | 13 | <%= link_to _('Add subcategory'), :action => 'new', :parent_id => category %> |
| @@ -16,12 +16,6 @@ | @@ -16,12 +16,6 @@ | ||
| 16 | </div> | 16 | </div> |
| 17 | </div> | 17 | </div> |
| 18 | 18 | ||
| 19 | - <div id="category_<%= category.id %>" style='display:none;'> | ||
| 20 | - <% unless category.children.empty? %> | ||
| 21 | - <ul class='tree'> | ||
| 22 | - <%= render :partial => 'category', :collection => category.children %> | ||
| 23 | - </ul> | ||
| 24 | - <% end %> | ||
| 25 | - </div> | 19 | +<ul id="category-sub-items-<%= category.id %>" class="tree" style='display:none;'></ul> |
| 26 | 20 | ||
| 27 | </li> | 21 | </li> |
app/views/categories/index.rhtml
app/views/cms/_blog.rhtml
| @@ -50,7 +50,7 @@ | @@ -50,7 +50,7 @@ | ||
| 50 | %> | 50 | %> |
| 51 | </div> | 51 | </div> |
| 52 | 52 | ||
| 53 | -<%= labelled_form_field(_('Description:'), text_area(:article, :body, :cols => 64, :rows => 10)) %> | 53 | +<%= labelled_form_field(_('Description:'), text_area(:article, :body, :rows => 10)) %> |
| 54 | 54 | ||
| 55 | <%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [ [ _('Full post'), 'full'], [ _('First paragraph'), 'short'] ])) %> | 55 | <%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [ [ _('Full post'), 'full'], [ _('First paragraph'), 'short'] ])) %> |
| 56 | 56 |
app/views/cms/_document_link.rhtml
| @@ -1,10 +0,0 @@ | @@ -1,10 +0,0 @@ | ||
| 1 | -<div id='media-listing-folder-documents' > | ||
| 2 | - <ul> | ||
| 3 | - <% documents.each do |document| %> | ||
| 4 | - <li><%= link_to(document.name, document.view_url, :class => icon_for_article(document)) %></li> | ||
| 5 | - <% end %> | ||
| 6 | - </ul> | ||
| 7 | - <div id='pagination-documents'> | ||
| 8 | - <%= pagination_links documents, :param_name => 'dpage', :params => {:document_folder_id => params[:document_folder_id]} %> | ||
| 9 | - </div> | ||
| 10 | -</div> |
app/views/cms/_image_thumb.rhtml
| @@ -1,10 +0,0 @@ | @@ -1,10 +0,0 @@ | ||
| 1 | -<div id='media-listing-folder-images' > | ||
| 2 | - <ul> | ||
| 3 | - <% images.each do |image| %> | ||
| 4 | - <li><%= image_tag image.public_filename %></li> | ||
| 5 | - <% end %> | ||
| 6 | - </ul> | ||
| 7 | - <div id='pagination-images'> | ||
| 8 | - <%= pagination_links images, :param_name => 'ipage', :params => {:image_folder_id => params[:image_folder_id]} %> | ||
| 9 | - </div> | ||
| 10 | -</div> |
app/views/cms/_media_listing.rhtml