Commit 1c421ee1786ef44c55efda50f118003acd9c37ef

Authored by Victor Costa
2 parents ea7661fa 11166297

Merge branch 'stable' into hotfixes

Showing 80 changed files with 1272 additions and 403 deletions   Show diff stats
Gemfile
1 1 source "https://rubygems.org"
2   -gem 'rails'
3   -gem 'fast_gettext'
4   -gem 'acts-as-taggable-on'
5   -gem 'prototype-rails'
6   -gem 'prototype_legacy_helper', '0.0.0', :path => 'vendor/prototype_legacy_helper'
7   -gem 'rails_autolink'
8   -gem 'pg'
9   -gem 'rmagick'
10   -gem 'RedCloth'
11   -gem 'will_paginate'
12   -gem 'ruby-feedparser'
13   -gem 'daemons'
14   -gem 'thin'
15   -gem 'hpricot'
16   -gem 'nokogiri'
  2 +gem 'rails', '~> 3.2.19'
  3 +gem 'fast_gettext', '~> 0.6.8'
  4 +gem 'acts-as-taggable-on', '~> 3.0.2'
  5 +gem 'prototype-rails', '~> 3.2.1'
  6 +gem 'prototype_legacy_helper', '0.0.0', :path => 'vendor/prototype_legacy_helper'
  7 +gem 'rails_autolink', '~> 1.1.5'
  8 +gem 'pg', '~> 0.13.2'
  9 +gem 'rmagick', '~> 2.13.1'
  10 +gem 'RedCloth', '~> 4.2.9'
  11 +gem 'will_paginate', '~> 3.0.3'
  12 +gem 'ruby-feedparser', '~> 0.7'
  13 +gem 'daemons', '~> 1.1.5'
  14 +gem 'thin', '~> 1.3.1'
  15 +gem 'hpricot', '~> 0.8.6'
  16 +gem 'nokogiri', '~> 1.5.5'
17 17 gem 'rake', :require => false
18   -gem 'grape', '0.2.1'
19   -gem 'rest-client'
20   -gem 'exception_notification'
21   -gem 'gettext', :require => false, :group => :development
  18 +gem 'grape', '~> 0.2.1'
  19 +gem 'rest-client', '~> 1.6.7'
  20 +gem 'exception_notification', '~> 4.0.1'
  21 +gem 'gettext', '~> 2.2.1', :require => false, :group => :development
22 22  
23 23 # FIXME list here all actual dependencies (i.e. the ones in debian/control),
24 24 # with their GEM names (not the Debian package names)
25 25  
26 26 group :production do
27   - gem 'dalli'
  27 + gem 'dalli', '~> 2.7.0'
28 28 end
29 29  
30 30 group :test do
31   - gem 'rspec'
32   - gem 'rspec-rails'
33   - gem 'mocha', :require => false
  31 + gem 'rspec', '~> 2.10.0'
  32 + gem 'rspec-rails', '~> 2.10.1'
  33 + gem 'mocha', '~> 1.1.0', :require => false
34 34 end
35 35  
36 36 group :cucumber do
37   - gem 'cucumber-rails', :require => false
38   - gem 'capybara'
39   - gem 'cucumber'
40   - gem 'database_cleaner'
41   - gem 'selenium-webdriver'
  37 + gem 'cucumber-rails', '~> 1.0.6', :require => false
  38 + gem 'capybara', '~> 2.1.0'
  39 + gem 'cucumber', '~> 1.0.6'
  40 + gem 'database_cleaner', '~> 1.2.0'
  41 + gem 'selenium-webdriver', '~> 2.39.0'
42 42 end
43 43  
44 44 # include plugin gemfiles
... ...
Gemfile.lock
... ... @@ -1,206 +0,0 @@
1   -PATH
2   - remote: vendor/prototype_legacy_helper
3   - specs:
4   - prototype_legacy_helper (0.0.0)
5   -
6   -GEM
7   - remote: https://rubygems.org/
8   - specs:
9   - RedCloth (4.2.9)
10   - actionmailer (3.2.6)
11   - actionpack (= 3.2.6)
12   - mail (~> 2.4.4)
13   - actionpack (3.2.6)
14   - activemodel (= 3.2.6)
15   - activesupport (= 3.2.6)
16   - builder (~> 3.0.0)
17   - erubis (~> 2.7.0)
18   - journey (~> 1.0.1)
19   - rack (~> 1.4.0)
20   - rack-cache (~> 1.2)
21   - rack-test (~> 0.6.1)
22   - sprockets (~> 2.1.3)
23   - activemodel (3.2.6)
24   - activesupport (= 3.2.6)
25   - builder (~> 3.0.0)
26   - activerecord (3.2.6)
27   - activemodel (= 3.2.6)
28   - activesupport (= 3.2.6)
29   - arel (~> 3.0.2)
30   - tzinfo (~> 0.3.29)
31   - activeresource (3.2.6)
32   - activemodel (= 3.2.6)
33   - activesupport (= 3.2.6)
34   - activesupport (3.2.6)
35   - i18n (~> 0.6)
36   - multi_json (~> 1.0)
37   - acts-as-taggable-on (3.0.2)
38   - rails (>= 3, < 5)
39   - arel (3.0.2)
40   - builder (3.0.0)
41   - capybara (2.1.0)
42   - mime-types (>= 1.16)
43   - nokogiri (>= 1.3.3)
44   - rack (>= 1.0.0)
45   - rack-test (>= 0.5.4)
46   - xpath (~> 2.0)
47   - childprocess (0.3.3)
48   - ffi (~> 1.0.6)
49   - cucumber (1.0.6)
50   - builder (>= 2.1.2)
51   - diff-lcs (>= 1.1.2)
52   - gherkin (~> 2.4.18)
53   - json (>= 1.4.6)
54   - term-ansicolor (>= 1.0.6)
55   - cucumber-rails (1.0.6)
56   - capybara (>= 1.1.1)
57   - cucumber (>= 1.0.6)
58   - nokogiri (>= 1.5.0)
59   - daemons (1.1.5)
60   - dalli (2.7.0)
61   - database_cleaner (1.2.0)
62   - diff-lcs (1.1.3)
63   - erubis (2.7.0)
64   - eventmachine (0.12.10)
65   - exception_notification (4.0.1)
66   - actionmailer (>= 3.0.4)
67   - activesupport (>= 3.0.4)
68   - fast_gettext (0.6.8)
69   - ffi (1.0.11)
70   - gettext (2.2.1)
71   - locale
72   - gherkin (2.4.21)
73   - json (>= 1.4.6)
74   - grape (0.2.1)
75   - hashie (~> 1.2)
76   - multi_json
77   - multi_xml
78   - rack
79   - rack-mount
80   - hashie (1.2.0)
81   - hike (1.2.1)
82   - hpricot (0.8.6)
83   - i18n (0.6.0)
84   - journey (1.0.3)
85   - json (1.7.3)
86   - locale (2.0.5)
87   - mail (2.4.4)
88   - i18n (>= 0.4.0)
89   - mime-types (~> 1.16)
90   - treetop (~> 1.4.8)
91   - metaclass (0.0.1)
92   - mime-types (1.19)
93   - mocha (0.11.3)
94   - metaclass (~> 0.0.1)
95   - multi_json (1.3.6)
96   - multi_xml (0.5.5)
97   - nokogiri (1.5.5)
98   - pg (0.13.2)
99   - polyglot (0.3.3)
100   - prototype-rails (3.2.1)
101   - rails (~> 3.2)
102   - rack (1.4.1)
103   - rack-cache (1.2)
104   - rack (>= 0.4)
105   - rack-mount (0.8.3)
106   - rack (>= 1.0.0)
107   - rack-ssl (1.3.2)
108   - rack
109   - rack-test (0.6.1)
110   - rack (>= 1.0)
111   - rails (3.2.6)
112   - actionmailer (= 3.2.6)
113   - actionpack (= 3.2.6)
114   - activerecord (= 3.2.6)
115   - activeresource (= 3.2.6)
116   - activesupport (= 3.2.6)
117   - bundler (~> 1.0)
118   - railties (= 3.2.6)
119   - rails_autolink (1.1.5)
120   - rails (> 3.1)
121   - railties (3.2.6)
122   - actionpack (= 3.2.6)
123   - activesupport (= 3.2.6)
124   - rack-ssl (~> 1.3.2)
125   - rake (>= 0.8.7)
126   - rdoc (~> 3.4)
127   - thor (>= 0.14.6, < 2.0)
128   - rake (0.9.2.2)
129   - rdoc (3.9.4)
130   - rest-client (1.6.7)
131   - mime-types (>= 1.16)
132   - rmagick (2.13.1)
133   - rspec (2.10.0)
134   - rspec-core (~> 2.10.0)
135   - rspec-expectations (~> 2.10.0)
136   - rspec-mocks (~> 2.10.0)
137   - rspec-core (2.10.1)
138   - rspec-expectations (2.10.0)
139   - diff-lcs (~> 1.1.3)
140   - rspec-mocks (2.10.1)
141   - rspec-rails (2.10.1)
142   - actionpack (>= 3.0)
143   - activesupport (>= 3.0)
144   - railties (>= 3.0)
145   - rspec (~> 2.10.0)
146   - ruby-feedparser (0.7)
147   - rubyzip (1.1.2)
148   - selenium-webdriver (2.39.0)
149   - childprocess (>= 0.2.5)
150   - multi_json (~> 1.0)
151   - rubyzip (~> 1.0)
152   - websocket (~> 1.0.4)
153   - sprockets (2.1.3)
154   - hike (~> 1.2)
155   - multi_json (~> 1.0)
156   - rack (~> 1.0)
157   - tilt (~> 1.1, != 1.3.0)
158   - term-ansicolor (1.0.7)
159   - thin (1.3.1)
160   - daemons (>= 1.0.9)
161   - eventmachine (>= 0.12.6)
162   - rack (>= 1.0.0)
163   - thor (0.15.3)
164   - tilt (1.3.3)
165   - treetop (1.4.10)
166   - polyglot
167   - polyglot (>= 0.3.1)
168   - tzinfo (0.3.33)
169   - websocket (1.0.7)
170   - will_paginate (3.0.3)
171   - xpath (2.0.0)
172   - nokogiri (~> 1.3)
173   -
174   -PLATFORMS
175   - ruby
176   -
177   -DEPENDENCIES
178   - RedCloth
179   - acts-as-taggable-on
180   - capybara
181   - cucumber
182   - cucumber-rails
183   - daemons
184   - dalli
185   - database_cleaner
186   - exception_notification
187   - fast_gettext
188   - gettext
189   - grape (= 0.2.1)
190   - hpricot
191   - mocha
192   - nokogiri
193   - pg
194   - prototype-rails
195   - prototype_legacy_helper (= 0.0.0)!
196   - rails
197   - rails_autolink
198   - rake
199   - rest-client
200   - rmagick
201   - rspec
202   - rspec-rails
203   - ruby-feedparser
204   - selenium-webdriver
205   - thin
206   - will_paginate
Vagrantfile
... ... @@ -3,7 +3,7 @@
3 3  
4 4 VAGRANTFILE_API_VERSION = "2"
5 5 Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
6   - config.vm.box = "debian-wheezy"
  6 + config.vm.box = ENV.fetch('VAGRANT_BOX', "debian-wheezy")
7 7 config.vm.network :forwarded_port, host: 3000, guest: 3000
8 8 config.vm.provision :shell do |shell|
9 9 shell.inline = 'su vagrant -c /vagrant/script/vagrant'
... ...
app/models/environment.rb
... ... @@ -829,7 +829,7 @@ class Environment &lt; ActiveRecord::Base
829 829 end
830 830  
831 831 def notification_emails
832   - [noreply_email.blank? ? nil : noreply_email].compact + admins.map(&:email)
  832 + [contact_email].select(&:present?) + admins.map(&:email)
833 833 end
834 834  
835 835 after_create :create_templates
... ...
app/models/organization.rb
... ... @@ -135,7 +135,11 @@ class Organization &lt; Profile
135 135 end
136 136  
137 137 def notification_emails
138   - [contact_email.blank? ? nil : contact_email].compact + admins.map(&:email)
  138 + emails = [contact_email].select(&:present?) + admins.map(&:email)
  139 + if emails.empty?
  140 + emails << environment.contact_email
  141 + end
  142 + emails
139 143 end
140 144  
141 145 def already_request_membership?(person)
... ...
debian/control
... ... @@ -9,7 +9,7 @@ Build-Depends:
9 9 ruby-gettext,
10 10 ruby-sqlite3,
11 11 rake,
12   - rails3 (>= 3.2.6-1~),
  12 + rails3 (>= 3.2.19-1~),
13 13 ruby-rspec,
14 14 ruby-rspec-rails,
15 15 ruby-will-paginate,
... ...
debian/noosfero.install
... ... @@ -8,7 +8,6 @@ Rakefile usr/share/noosfero
8 8 vendor usr/share/noosfero
9 9  
10 10 Gemfile usr/share/noosfero
11   -Gemfile.lock usr/share/noosfero
12 11 debian/bundle/config usr/share/noosfero/.bundle
13 12  
14 13 config/application.rb usr/share/noosfero/config
... ...
debian/noosfero.links
... ... @@ -15,3 +15,4 @@ var/lib/noosfero-data/public/thumbnails usr/share/noosfero/public/th
15 15 usr/share/noosfero/public/designs/themes/noosfero usr/share/noosfero/public/designs/themes/default
16 16 usr/share/noosfero/public/designs/icons/tango usr/share/noosfero/public/designs/icons/default
17 17 usr/share/noosfero/script/noosfero-plugins usr/sbin/noosfero-plugins
  18 +usr/share/noosfero/Gemfile.lock /dev/null
... ...
gitignore.example
... ... @@ -43,3 +43,4 @@ debian/noosfero-apache/
43 43 features/plugins/*
44 44 plugins/solr/config/solr.yml
45 45 /solr
  46 +/Gemfile.lock
... ...
lib/feed_writer.rb
... ... @@ -19,7 +19,7 @@ class FeedWriter
19 19 for article in articles
20 20 xml.item do
21 21 xml.title(article.name)
22   - xml.description(article.to_html)
  22 + xml.description(article.to_html(:feed => true))
23 23 if article.created_at
24 24 # rfc822
25 25 xml.pubDate(article.created_at.rfc2822)
... ...
plugins/dspace/controllers/dspace_plugin_controller.rb 0 → 100644
... ... @@ -0,0 +1,33 @@
  1 +class DspacePluginController < PublicController
  2 + append_view_path File.join(File.dirname(__FILE__) + '/../views')
  3 +
  4 + def view_item
  5 +
  6 + collection_id = params[:collection_id]
  7 + item_id = params[:id]
  8 +
  9 + begin
  10 + @collection = DspacePlugin::Collection.find(collection_id)
  11 + rescue ActiveRecord::RecordNotFound
  12 + render_not_found
  13 + return
  14 + end
  15 +
  16 + begin
  17 + dspace_server = @collection.parent.parent.dspace_server_url
  18 + @item = Dspace::Item.get_item_by_id dspace_server, item_id
  19 + rescue ActiveResource::UnauthorizedAccess
  20 + render_not_found
  21 + return
  22 + end
  23 +
  24 + begin
  25 + @collection = DspacePlugin::Collection.find(collection_id)
  26 + rescue ActiveRecord::RecordNotFound
  27 + render_not_found
  28 + return
  29 + end
  30 +
  31 + end
  32 +
  33 +end
... ...
plugins/dspace/controllers/dspace_plugin_myprofile_controller.rb 0 → 100644
... ... @@ -0,0 +1,72 @@
  1 +class DspacePluginMyprofileController < CmsController
  2 + append_view_path File.join(File.dirname(__FILE__) + '/../views')
  3 +
  4 + def new
  5 +
  6 + @success_back_to = params[:success_back_to]
  7 +
  8 + @parent = profile.articles.find(params[:parent_id]) if params && params[:parent_id]
  9 + record_coming
  10 + @type = params[:type]
  11 + if @type.blank?
  12 + @article_types = []
  13 + available_article_types.each do |type|
  14 + @article_types.push({
  15 + :class => type,
  16 + :short_description => type.short_description,
  17 + :description => type.description
  18 + })
  19 + end
  20 + @parent_id = params[:parent_id]
  21 + render :action => 'select_article_type', :layout => false, :back_to => @back_to
  22 + return
  23 + else
  24 + refuse_blocks
  25 + end
  26 +
  27 + raise "Invalid article type #{@type}" unless valid_article_type?(@type)
  28 +
  29 + klass = @type.constantize
  30 + article_data = environment.enabled?('articles_dont_accept_comments_by_default') ? { :accept_comments => false } : {}
  31 + article_data.merge!(params[:article]) if params[:article]
  32 +
  33 + if @type == 'DspacePlugin::Collection'
  34 + dspace_objects = article_data['dspace_collections']
  35 + elsif @type == 'DspacePlugin::Communityy'
  36 + dspace_objects = article_data['dspace_communities']
  37 + end
  38 +
  39 + dspace_objects.each do |object|
  40 +
  41 + entity = klass.new
  42 +
  43 + parent = check_parent(params[:parent_id])
  44 +
  45 + if parent
  46 + entity.parent = parent
  47 + parent_id = parent.id
  48 + end
  49 +
  50 + if @type == 'DspacePlugin::Communityy'
  51 + entity.dspace_community_id = object['id']
  52 + elsif @type == 'DspacePlugin::Collection'
  53 + entity.dspace_community_id = article_data['dspace_community_id']
  54 + entity.dspace_collection_id = object['id']
  55 + entity.accept_comments = false
  56 + end
  57 +
  58 + entity.name = object['name']
  59 + entity.profile = profile
  60 + entity.author = user
  61 + entity.last_changed_by = user
  62 + entity.created_by = user
  63 +
  64 + entity.save!
  65 +
  66 + end
  67 +
  68 + redirect_to @parent.view_url
  69 +
  70 + end
  71 +
  72 +end
... ...
plugins/dspace/lib/dspace/collection.rb 0 → 100644
... ... @@ -0,0 +1,24 @@
  1 +class Dspace::Collection < Dspace::Resource
  2 +
  3 + def self.get_all_items_from(dspace_server, collection_id)
  4 + self.site = dspace_server
  5 + result = self.find collection_id, :params => { :expand => 'items' }
  6 +
  7 + item_list = []
  8 +
  9 + if result.items.count > 0
  10 + result.items.each { |element|
  11 + item = Dspace::Item.get_item_by_id dspace_server, element.id
  12 + item_list << item
  13 + }
  14 + end
  15 +
  16 + item_list
  17 + end
  18 +
  19 + def self.get_all_collections_from(dspace_server)
  20 + self.site = dspace_server
  21 + self.find(:all)
  22 + end
  23 +
  24 +end
... ...
plugins/dspace/lib/dspace/community.rb 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +class Dspace::Community < Dspace::Resource
  2 +
  3 + def self.get_all_communities_from(dspace_server)
  4 + self.site = dspace_server
  5 + self.find(:all)
  6 + end
  7 +
  8 + def self.get_all_collections_from(dspace_server, community_id)
  9 + self.site = dspace_server
  10 + result = self.find community_id, :params => { :expand => 'collections' }
  11 + result.collections
  12 + end
  13 +
  14 +end
... ...
plugins/dspace/lib/dspace/item.rb 0 → 100644
... ... @@ -0,0 +1,89 @@
  1 +class Dspace::Item < Dspace::Resource
  2 +
  3 + def self.get_all_item_metadata_from(dspace_server, item_id)
  4 + self.site = dspace_server
  5 + result = self.find item_id, :params => { :expand => 'metadata' }
  6 + result.metadata
  7 + end
  8 +
  9 + def self.get_item_by_id(dspace_server, item_id)
  10 + self.site = dspace_server
  11 + result = self.find item_id, :params => { :expand => 'metadata' }
  12 +
  13 + item_metadata = Dspace::Item.get_all_item_metadata_from self.site, result.id
  14 +
  15 + # author
  16 + metadata = item_metadata[0].attributes
  17 + if metadata != {}
  18 + metadata = Hash[[metadata.map{|k,v| v}]]
  19 + author = metadata.has_key?('dc.contributor.author') ? metadata['dc.contributor.author'] : nil
  20 + end
  21 +
  22 + # issue date
  23 + metadata = item_metadata[3].attributes
  24 + if metadata != {}
  25 + metadata = Hash[[metadata.map{|k,v| v}]]
  26 + issue_date = metadata.has_key?('dc.date.issued') ? metadata['dc.date.issued'] : nil
  27 + end
  28 +
  29 + # uri
  30 + metadata = item_metadata[4].attributes
  31 + if metadata != {}
  32 + metadata = Hash[[metadata.map{|k,v| v}]]
  33 + uri = metadata.has_key?('dc.identifier.uri') ? metadata['dc.identifier.uri'] : nil
  34 + end
  35 +
  36 + # description
  37 + metadata = item_metadata[5].attributes
  38 + if metadata != {}
  39 + metadata = Hash[[metadata.map{|k,v| v}]]
  40 + abstract = metadata.has_key?('dc.description') ? metadata['dc.description'] : nil
  41 + end
  42 +
  43 + # abstract
  44 + metadata = item_metadata[6].attributes
  45 + if metadata != {}
  46 + metadata = Hash[[metadata.map{|k,v| v}]]
  47 + description = metadata.has_key?('dc.description.abstract') ? metadata['dc.description.abstract'] : nil
  48 + end
  49 +
  50 + item = DspacePlugin::Item.new
  51 +
  52 + item.id = result.id
  53 + item.name = result.name
  54 + item.author = author
  55 + item.issue_date = issue_date
  56 + item.abstract = abstract
  57 + item.description = description
  58 + item.uri = uri
  59 +
  60 + ### BITSTREAMS
  61 +
  62 + item_bitstreams = self.find item_id, :params => { :expand => 'bitstreams' }
  63 +
  64 + bitstreams = item_bitstreams.bitstreams
  65 +
  66 + bitstreams.each do |bs|
  67 + bitstream = DspacePlugin::Bitstream.new
  68 + bitstream.id = bs.attributes[:id]
  69 + bitstream.name = bs.attributes[:name]
  70 + bitstream.description = bs.attributes[:description]
  71 + bitstream.mimetype = bs.attributes[:mimeType]
  72 + bitstream.size_bytes = bs.attributes[:sizeBytes]
  73 + bitstream.retrieve_link = bs.attributes[:retrieveLink]
  74 + bitstream.format = bs.attributes[:format]
  75 + bitstream.link = bs.attributes[:link]
  76 +
  77 + item.files << bitstream
  78 +
  79 + end
  80 +
  81 + if item.files.count > 0
  82 + item.mimetype = item.files.first.mimetype
  83 + end
  84 +
  85 + item
  86 +
  87 + end
  88 +
  89 +end
... ...
plugins/dspace/lib/dspace/resource.rb 0 → 100644
... ... @@ -0,0 +1,15 @@
  1 +class Dspace::Resource < ActiveResource::Base
  2 +
  3 + class << self
  4 + def element_path(id, prefix_options = {}, query_options = nil)
  5 + prefix_options, query_options = split_options(prefix_options) if query_options.nil?
  6 + "#{prefix(prefix_options)}#{collection_name}/#{id}#{query_string(query_options)}"
  7 + end
  8 +
  9 + def collection_path(prefix_options = {}, query_options = nil)
  10 + prefix_options, query_options = split_options(prefix_options) if query_options.nil?
  11 + "#{prefix(prefix_options)}#{collection_name}#{query_string(query_options)}"
  12 + end
  13 + end
  14 +
  15 +end
... ...
plugins/dspace/lib/dspace_plugin.rb 0 → 100644
... ... @@ -0,0 +1,36 @@
  1 +class DspacePlugin < Noosfero::Plugin
  2 +
  3 + def self.plugin_name
  4 + "DSpace Plugin"
  5 + end
  6 +
  7 + def self.plugin_description
  8 + _("A plugin that add a DSpace library feature to noosfero.")
  9 + end
  10 +
  11 + def content_types
  12 + if context.respond_to?(:params) && context.params
  13 + types = []
  14 + parent_id = context.params[:parent_id]
  15 + types << DspacePlugin::Library if context.profile.community? && !parent_id
  16 + parent = parent_id ? context.profile.articles.find(parent_id) : nil
  17 + if parent.kind_of?(DspacePlugin::Library)
  18 + types << DspacePlugin::Communityy
  19 + elsif parent.kind_of?(DspacePlugin::Communityy)
  20 + types << DspacePlugin::Collection
  21 + end
  22 + types
  23 + else
  24 + [DspacePlugin::Library, DspacePlugin::Collection, DspacePlugin::Communityy]
  25 + end
  26 + end
  27 +
  28 + def stylesheet?
  29 + true
  30 + end
  31 +
  32 + def self.has_admin_url?
  33 + false
  34 + end
  35 +
  36 +end
... ...
plugins/dspace/lib/dspace_plugin/bitstream.rb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +class DspacePlugin::Bitstream
  2 +
  3 + attr_accessor :id, :name, :description, :mimetype, :size_bytes, :retrieve_link, :format, :link
  4 +
  5 +end
... ...
plugins/dspace/lib/dspace_plugin/collection.rb 0 → 100644
... ... @@ -0,0 +1,31 @@
  1 +class DspacePlugin::Collection < Article
  2 +
  3 + settings_items :dspace_collection_id, :type => :string
  4 + settings_items :dspace_community_id, :type => :integer
  5 +
  6 + attr_accessible :dspace_collection_id, :dspace_community_id
  7 +
  8 + def self.icon_name(article = nil)
  9 + 'dspace-collection'
  10 + end
  11 +
  12 + def self.short_description
  13 + _("DSpace collection")
  14 + end
  15 +
  16 + def self.description
  17 + _("Defines a DSpace collection")
  18 + end
  19 +
  20 + def to_html(options = {})
  21 + dspace_content = self
  22 + proc do
  23 + render :file => 'content_viewer/dspace_content', :locals => { :dspace_content => dspace_content }
  24 + end
  25 + end
  26 +
  27 + def items(dspace_server, collection_id)
  28 + Dspace::Collection.get_all_items_from dspace_server, collection_id
  29 + end
  30 +
  31 +end
... ...
plugins/dspace/lib/dspace_plugin/collection_helper.rb 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +module DspacePlugin::CollectionHelper
  2 +
  3 + include ArticleHelper
  4 +
  5 + def custom_options_for_article(article,tokenized_children)
  6 + @article = article
  7 +
  8 + visibility_options(article,tokenized_children) +
  9 + content_tag('div',
  10 + hidden_field_tag('article[accept_comments]', 0)
  11 + )
  12 + end
  13 +
  14 +end
... ...
plugins/dspace/lib/dspace_plugin/communityy.rb 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +class DspacePlugin::Communityy < Folder
  2 +
  3 + settings_items :dspace_community_id, :type => :string
  4 +
  5 + attr_accessible :dspace_community_id
  6 +
  7 + def self.icon_name(article = nil)
  8 + 'dspace-community'
  9 + end
  10 +
  11 + def self.short_description
  12 + _("DSpace community")
  13 + end
  14 +
  15 + def self.description
  16 + _("Defines a DSpace community")
  17 + end
  18 +
  19 + def to_html(options = {})
  20 + dspace_content = self
  21 + proc do
  22 + render :file => 'content_viewer/dspace_content', :locals => { :dspace_content => dspace_content }
  23 + end
  24 + end
  25 +
  26 + def collections(dspace_server, community_id)
  27 + DspacePlugin::Collection.find(:all)
  28 + end
  29 +
  30 +end
... ...
plugins/dspace/lib/dspace_plugin/communityy_helper.rb 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +module DspacePlugin::CommunityyHelper
  2 +
  3 + include ArticleHelper
  4 +
  5 + def custom_options_for_article(article,tokenized_children)
  6 + @article = article
  7 +
  8 + visibility_options(article,tokenized_children) +
  9 + content_tag('div',
  10 + hidden_field_tag('article[accept_comments]', 0)
  11 + )
  12 + end
  13 +
  14 +end
... ...
plugins/dspace/lib/dspace_plugin/item.rb 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +class DspacePlugin::Item
  2 +
  3 + include DspacePlugin::ItemHelper
  4 +
  5 + attr_accessor :id, :name, :author, :issue_date, :abstract, :description, :uri, :files, :mimetype
  6 +
  7 + def initialize
  8 + self.files = []
  9 + end
  10 +
  11 +end
... ...
plugins/dspace/lib/dspace_plugin/item_helper.rb 0 → 100644
... ... @@ -0,0 +1,90 @@
  1 +module DspacePlugin::ItemHelper
  2 +
  3 + TEXT_MIMETYPES = [ 'text/plain; charset=utf-8',
  4 + 'text/html',
  5 + 'text/xml',
  6 + 'text/plain',
  7 + 'text/html',
  8 + 'text/css',
  9 + 'text/richtext' ]
  10 +
  11 + AUDIO_MIMETYPES = [ 'audio/x-pn-realaudio',
  12 + 'audio/x-mpeg',
  13 + 'audio/x-aiff',
  14 + 'audio/basic',
  15 + 'audio/x-wav' ]
  16 +
  17 + DOCUMENT_MIMETYPES = [ 'application/msword',
  18 + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  19 + 'application/vnd.oasis.opendocument.text',
  20 + 'application/vnd.oasis.opendocument.text-template',
  21 + 'application/vnd.oasis.opendocument.text-web',
  22 + 'application/vnd.oasis.opendocument.text-master',
  23 + 'application/vnd.sun.xml.writer',
  24 + 'application/vnd.sun.xml.writer.template',
  25 + 'application/vnd.sun.xml.writer.global',
  26 + 'application/vnd.stardivision.writer',
  27 + 'application/vnd.stardivision.writer-global' ]
  28 +
  29 + PICTURE_MIMETYPES = [ 'image/x-photo-cd',
  30 + 'image/x-ms-bmp',
  31 + 'image/jpeg',
  32 + 'image/gif',
  33 + 'image/png',
  34 + 'image/tiff',
  35 + 'application/x-photoshop',
  36 + 'application/postscript' ]
  37 +
  38 + SPREADSHEET_MIMETYPES = [ 'application/vnd.ms-excel',
  39 + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  40 + 'application/vnd.oasis.opendocument.spreadsheet',
  41 + 'application/vnd.oasis.opendocument.spreadsheet-template',
  42 + 'application/vnd.sun.xml.calc',
  43 + 'application/vnd.sun.xml.calc.template',
  44 + 'application/vnd.sun.xml.math',
  45 + 'application/vnd.stardivision.calc' ]
  46 +
  47 + VIDEO_MIMETYPES = [ 'video/quicktime',
  48 + 'video/mpeg' ]
  49 +
  50 +
  51 + def remove_slash_at_end_url(url)
  52 + url.gsub!(/\/$/,'') if url =~ /\/$/
  53 + url
  54 + end
  55 +
  56 + def class_for_item_mimetype(mimetype)
  57 +
  58 + case
  59 +
  60 + when mimetype == 'application/pdf'
  61 + mimetype_class = 'pdf'
  62 +
  63 + when TEXT_MIMETYPES.include?(mimetype)
  64 + mimetype_class = 'text'
  65 +
  66 + when AUDIO_MIMETYPES.include?(mimetype)
  67 + mimetype_class = 'audio'
  68 +
  69 + when DOCUMENT_MIMETYPES.include?(mimetype)
  70 + mimetype_class = 'document'
  71 +
  72 + when PICTURE_MIMETYPES.include?(mimetype)
  73 + mimetype_class = 'picture'
  74 +
  75 + when SPREADSHEET_MIMETYPES.include?(mimetype)
  76 + mimetype_class = 'spreadsheet'
  77 +
  78 + when VIDEO_MIMETYPES.include?(mimetype)
  79 + mimetype_class = 'video'
  80 +
  81 + else
  82 + mimetype_class = 'other'
  83 +
  84 + end
  85 +
  86 + "icon-#{mimetype_class}"
  87 +
  88 + end
  89 +
  90 +end
... ...
plugins/dspace/lib/dspace_plugin/library.rb 0 → 100644
... ... @@ -0,0 +1,49 @@
  1 +class DspacePlugin::Library < Folder
  2 +
  3 + settings_items :dspace_server_url, :type => :string
  4 +
  5 + attr_accessible :dspace_server_url
  6 +
  7 + def dspace_server_url_valid
  8 +
  9 + if self.dspace_server_url.blank?
  10 + errors.add(:dspace_server_url, _("can't be blank") )
  11 + return
  12 + end
  13 +
  14 + errors.add(self.dspace_server_url, _("is not a valid URL. Please correct it and resubmit.")) unless url_valid?(self.dspace_server_url)
  15 + end
  16 +
  17 + validate :dspace_server_url_valid
  18 +
  19 + def self.icon_name(article = nil)
  20 + 'dspace-library'
  21 + end
  22 +
  23 + def self.short_description
  24 + _("DSpace library")
  25 + end
  26 +
  27 + def self.description
  28 + _("Defines a DSpace library")
  29 + end
  30 +
  31 + def to_html(options = {})
  32 + dspace_content = self
  33 + proc do
  34 + render :file => 'content_viewer/dspace_content', :locals => { :dspace_content => dspace_content }
  35 + end
  36 + end
  37 +
  38 + def communities
  39 + DspacePlugin::Communityy.find(:all)
  40 + end
  41 +
  42 + protected
  43 +
  44 + def url_valid?(url)
  45 + url = URI.parse(url) rescue false
  46 + url.kind_of?(URI::HTTP) || url.kind_of?(URI::HTTPS)
  47 + end
  48 +
  49 +end
... ...
plugins/dspace/lib/dspace_plugin/library_helper.rb 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +module DspacePlugin::LibraryHelper
  2 +
  3 + include ArticleHelper
  4 +
  5 + def custom_options_for_article(article,tokenized_children)
  6 + @article = article
  7 +
  8 + visibility_options(article,tokenized_children) +
  9 + content_tag('div',
  10 + hidden_field_tag('article[accept_comments]', 0)
  11 + )
  12 + end
  13 +
  14 +end
... ...
plugins/dspace/public/icons/audio.png 0 → 100644

717 Bytes

plugins/dspace/public/icons/document.png 0 → 100644

658 Bytes

plugins/dspace/public/icons/dspace.png 0 → 100644

3.2 KB

plugins/dspace/public/icons/pdf.png 0 → 100644

874 Bytes

plugins/dspace/public/icons/picture.png 0 → 100644

525 Bytes

plugins/dspace/public/icons/spreadsheet.png 0 → 100644

644 Bytes

plugins/dspace/public/icons/text.png 0 → 100644

419 Bytes

plugins/dspace/public/icons/video.png 0 → 100644

711 Bytes

plugins/dspace/public/javascripts/dspace_plugin.js 0 → 100644
... ... @@ -0,0 +1,85 @@
  1 +/**
  2 +
  3 +function selectCommunity(element, community_slug) {
  4 + var hidden_field = jQuery('<input>').attr({
  5 + id: 'article_dspace_community_name_',
  6 + name: 'article[dspace_communities_names][]',
  7 + type: 'hidden',
  8 + name: 'article[dspace_communities_names][]',
  9 + value: community_slug
  10 + });
  11 + jQuery(hidden_field).insertAfter(element);
  12 +}
  13 +
  14 +
  15 +function selectCollection(element, collection_slug) {
  16 + var hidden_field = jQuery('<input>').attr({
  17 + id: 'article_dspace_collection_name_',
  18 + name: 'article[dspace_collections_names][]',
  19 + type: 'hidden',
  20 + name: 'article[dspace_collections_names][]',
  21 + value: collection_slug
  22 + });
  23 + jQuery(hidden_field).insertAfter(element);
  24 +}
  25 +
  26 +function select_action(field_active) {
  27 +}
  28 +**/
  29 +
  30 +jQuery(document).ready(function() {
  31 + url_base = window.location.protocol + '//' + window.location.host;
  32 + forms = jQuery('form');
  33 + forms.each( function(f) {
  34 + url_action = forms[f].action;
  35 + if (url_action.indexOf("/cms/new") > -1) {
  36 + forms[f].action = url_action.replace("/cms/new", "/plugin/dspace/new").replace(url_base,'');
  37 + }
  38 + });
  39 +
  40 + function check_fields(check, table_id) {
  41 + var checkboxes = jQuery("#" + table_id + " tbody tr td input[type='checkbox']")
  42 + for (var i = 0; i < checkboxes.length; i++) {
  43 + if (checkboxes[i].disabled == false) {
  44 + checkboxes[i].checked = check
  45 + }
  46 + }
  47 + }
  48 +
  49 + function verify_checked(field_id){
  50 + var checkboxes = jQuery("#" + field_id + "_fields_conf tbody tr td input[type='checkbox']")
  51 + var allchecked = true;
  52 + for (var j = 1; j < checkboxes.length; j++) {
  53 + if(!checkboxes[j].checked) {
  54 + allchecked = false;
  55 + break;
  56 + }
  57 + }
  58 +
  59 + var checkbox = jQuery("#" + field_id + "_active");
  60 + checkbox.attr("checked", allchecked);
  61 + }
  62 +
  63 +
  64 + function check_all(field_id) {
  65 + jQuery("#" + field_id + "_active").click(function (){
  66 + check_fields(this.checked, field_id + "_fields_conf")
  67 + });
  68 + verify_checked(field_id);
  69 + }
  70 +
  71 + check_all("community");
  72 + check_all("collection");
  73 +
  74 + jQuery("input[type='checkbox']").click(function () {
  75 + var checkbox = jQuery(this).attr("id").split("_");
  76 + verify_checked(checkbox.first());
  77 +
  78 + if(this.checked == false) {
  79 + jQuery("#" + checkbox.first() + "_" + checkbox.last()).attr("checked", false)
  80 + }
  81 +
  82 + jQuery(this).next().attr("disabled", !this.checked);
  83 + })
  84 +
  85 +});
... ...
plugins/dspace/public/style.css 0 → 100644
... ... @@ -0,0 +1,101 @@
  1 +#dspace_library ul {
  2 + margin: 0;
  3 + padding: 0 0 0 5px;
  4 +}
  5 +
  6 +#dspace_library li {
  7 + /**list-style-image: url(/designs/themes/base/imgs/li-recent.gif);*/
  8 + list-style-type: none;
  9 +}
  10 +
  11 +#dspace_library li.item,
  12 +#dspace_library li.collection,
  13 +#dspace_library li.community {
  14 + margin: 0;
  15 + padding: 10px 0;
  16 +}
  17 +
  18 +#dspace_library li.item span.name,
  19 +#dspace_library li.collection span.title,
  20 +#dspace_library li.community span.title {
  21 + font-weight: bold;
  22 +}
  23 +
  24 +#dspace_library div#actions {
  25 + margin: 10px 0;
  26 +}
  27 +
  28 +#dspace_library_item {
  29 + /*8border: 1px solid green;*/
  30 +}
  31 +
  32 +.dspace_item_section {
  33 + margin: 15px;
  34 +}
  35 +
  36 +.dspace_item_section_title {
  37 + margin: 0px;
  38 + font-weight: bold;
  39 + border-bottom: 1px solid #c0c0c0;
  40 +}
  41 +
  42 +#dspace_library_item ul {
  43 + list-style-type: none;
  44 +}
  45 +
  46 +#dspace_library_item ul#item_files_list,
  47 +#dspace_library_item ul.item_file_attributes_list {
  48 + margin: 0;
  49 + padding: 0;
  50 +}
  51 +
  52 +#dspace_library_item ul#item_files_list > li {
  53 + margin: 5px 0;
  54 +}
  55 +
  56 +.icon-newdspace-library,
  57 +.icon-dspace-library,
  58 +.icon-newdspace-community,
  59 +.icon-dspace-community,
  60 +.icon-newdspace-collection,
  61 +.icon-dspace-collection {
  62 + background-image: url(/plugins/dspace/icons/dspace.png)
  63 +}
  64 +
  65 +#dspace_library div.icon-item {
  66 + width: 32px;
  67 + height: 33px;
  68 + display: inline-block;
  69 + vertical-align: top;
  70 + border-right: 1px solid #c0c0c0;
  71 +}
  72 +
  73 +#dspace_library div.icon-audio {
  74 + background-image: url(/plugins/dspace/icons/audio.png)
  75 +}
  76 +
  77 +#dspace_library div.icon-document {
  78 + background-image: url(/plugins/dspace/icons/document.png)
  79 +}
  80 +
  81 +#dspace_library div.icon-pdf {
  82 + background-image: url(/plugins/dspace/icons/pdf.png)
  83 +}
  84 +
  85 +#dspace_library div.icon-picture {
  86 + background-image: url(/plugins/dspace/icons/picture.png)
  87 +}
  88 +
  89 +#dspace_library div.icon-spreadsheet {
  90 + background-image: url(/plugins/dspace/icons/spreadsheet.png)
  91 +}
  92 +
  93 +#dspace_library div.icon-text,
  94 +#dspace_library div.icon-other {
  95 + background-image: url(/plugins/dspace/icons/text.png)
  96 +}
  97 +
  98 +#dspace_library div.icon-video {
  99 + background-image: url(/plugins/dspace/icons/video.png)
  100 +}
  101 +
... ...
plugins/dspace/views/cms/dspace_plugin/_collection.html.erb 0 → 100644
... ... @@ -0,0 +1,50 @@
  1 +<h1><%= _('DSpace Collections') %></h1>
  2 +
  3 +<%= hidden_field_tag 'article[parent_id]', @article.parent_id %>
  4 +
  5 +<%= hidden_field_tag 'article[dspace_community_id]', @article.parent.dspace_community_id %>
  6 +
  7 +<% dspace_server_url = @article.parent.parent.dspace_server_url %>
  8 +
  9 +<% community_id = @article.parent.dspace_community_id %>
  10 +
  11 +<% collections = Dspace::Community.get_all_collections_from( dspace_server_url, community_id ).map { |collection| item = [_(collection.name), collection.id] } %>
  12 +
  13 +<table id="collection_fields_conf" border="0" style="border-bottom: 1px solid #c0c0c0;">
  14 + <tr style="background-color: #f0f0f0; border-top: 1px solid #c0c0c0; border-bottom: 1px solid #c0c0c0;">
  15 + <td style="font-style: italic">
  16 + <%= _("Check/Uncheck All Unlocked")%>
  17 + </td>
  18 + <td align="center">
  19 + <input type="checkbox" id="collection_active" />
  20 + </td>
  21 + </tr>
  22 +
  23 + <% dspace_collections_ids = DspacePlugin::Collection.find(:all, :conditions => { :parent_id => @article.parent_id}).map { |collection| ids = collection.dspace_collection_id.to_i } %>
  24 +
  25 + <% collections.each do |collection| %>
  26 +
  27 + <tr>
  28 + <td>
  29 + <%= collection[0] %>
  30 + </td>
  31 +
  32 + <% if dspace_collections_ids.include? collection[1] %>
  33 + <td align="center">
  34 + <%= check_box_tag "article[dspace_collections][][id]", collection[1], true, :disabled => 'disabled', :id => "collection_id_#{collection[1]}" %>
  35 + <%= hidden_field_tag "article[dspace_collections][][name]", collection[0], :disabled => 'disabled' %>
  36 + </td>
  37 + <% else %>
  38 + <td align="center">
  39 + <%= check_box_tag "article[dspace_collections][][id]", collection[1], false, :id => "collection_id_#{collection[1]}" %>
  40 + <%= hidden_field_tag "article[dspace_collections][][name]", collection[0], :disabled => 'disabled', :id => "collection_name_#{collection[1]}" %>
  41 + </td>
  42 + <% end %>
  43 +
  44 + </tr>
  45 +
  46 + <% end %>
  47 +
  48 +</table>
  49 +
  50 +<%= javascript_include_tag 'plugins/dspace/javascripts/dspace_plugin' %>
... ...
plugins/dspace/views/cms/dspace_plugin/_communityy.html.erb 0 → 100644
... ... @@ -0,0 +1,46 @@
  1 +<h1><%= _('DSpace Communities') %></h1>
  2 +
  3 +<%= hidden_field_tag 'article[parent_id]', @article.parent_id %>
  4 +
  5 +<% dspace_server_url = @article.parent.dspace_server_url %>
  6 +
  7 +<% communities = Dspace::Community.get_all_communities_from(dspace_server_url).map { |community| item = [_(community.name), community.id] } %>
  8 +
  9 +<table id="community_fields_conf" border="0" style="border-bottom: 1px solid #c0c0c0;">
  10 + <tr style="background-color: #f0f0f0; border-top: 1px solid #c0c0c0; border-bottom: 1px solid #c0c0c0;">
  11 + <td style="font-style: italic">
  12 + <%= _("Check/Uncheck All Unlocked")%>
  13 + </td>
  14 + <td align="center">
  15 + <input type="checkbox" id="community_active" />
  16 + </td>
  17 + </tr>
  18 +
  19 + <% dspace_communities_ids = DspacePlugin::Communityy.find(:all, :conditions => { :parent_id => @article.parent_id }).map { |community| ids = community.dspace_community_id.to_i } %>
  20 +
  21 + <% communities.each do |community| %>
  22 +
  23 + <tr>
  24 + <td>
  25 + <%= community[0] %>
  26 + </td>
  27 +
  28 + <% if dspace_communities_ids.include? community[1] %>
  29 + <td align="center">
  30 + <%= check_box_tag "article[dspace_communities][][id]", community[1], true, :disabled => 'disabled', :id => "community_id_#{community[1]}" %>
  31 + <%= hidden_field_tag "article[dspace_communities][][name]", community[0], :disabled => 'disabled' %>
  32 + </td>
  33 + <% else %>
  34 + <td align="center">
  35 + <%= check_box_tag "article[dspace_communities][][id]", community[1], false, :id => "community_id_#{community[1]}" %>
  36 + <%= hidden_field_tag "article[dspace_communities][][name]", community[0], :disabled => 'disabled', :id => "community_name_#{community[1]}" %>
  37 + </td>
  38 + <% end %>
  39 +
  40 + </tr>
  41 +
  42 + <% end %>
  43 +
  44 +</table>
  45 +
  46 +<%= javascript_include_tag 'plugins/dspace/javascripts/dspace_plugin' %>
... ...
plugins/dspace/views/cms/dspace_plugin/_library.html.erb 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +<h1><%= _('My DSpace Library') %></h1>
  2 +
  3 +<%= render :file => 'shared/tiny_mce' %>
  4 +
  5 +<%= required f.text_field(:name, :size => '64', :maxlength => 150, :onchange => "updateUrlField(this, 'article_slug')") %>
  6 +
  7 +<%= required f.text_field(:dspace_server_url, :size => '150', :maxlength => 150) %>
  8 +
  9 +<%= render :partial => 'general_fields' %>
  10 +
  11 +<%= labelled_form_field(_('Description:'), text_area(:article, :body, :cols => 68, :rows => 10)) %>
... ...
plugins/dspace/views/content_viewer/_collection.html.erb 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +<li class="collection">
  2 + <span class="title"><%= link_to collection.name, :controller => 'content_viewer', :action => 'view_page', :page => collection.path %></span>
  3 +</li>
... ...
plugins/dspace/views/content_viewer/_community.html.erb 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +<li class="community">
  2 + <span class="title"><%= link_to community.title, :controller => 'content_viewer', :action => 'view_page', :page => community.path %></span>
  3 +</li>
... ...
plugins/dspace/views/content_viewer/_item.html.erb 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +<li class="item">
  2 + <div style="vertical-align: top;">
  3 + <div class="icon-item <%= item.class_for_item_mimetype(item.mimetype) %>"></div>
  4 + <div style="display: inline-block; width: 92%;">
  5 + <span class="name"><%= link_to item.name, :controller => 'dspace_plugin', :action => 'view_item', :id => item.id, :collection_id => @page.id %></span><br />
  6 + <span class="authors"><%= item.author %></span> <span class="date_issued">(<%= item.issue_date %>)</span>
  7 + </div>
  8 + </div>
  9 +</li>
... ...
plugins/dspace/views/content_viewer/dspace_content.html.erb 0 → 100644
... ... @@ -0,0 +1,59 @@
  1 +<div id="dspace_library">
  2 +
  3 + <% if dspace_content.allow_create?(user) %>
  4 +
  5 + <div id="actions">
  6 +
  7 + <% if dspace_content.is_a? DspacePlugin::Library %>
  8 +
  9 + <%= content_tag('a', :href => url_for({:controller => 'cms', :action => 'new', :type => "DspacePlugin::Communityy", :parent_id => dspace_content.id}), :class => 'button with-text icon-add') do %>
  10 + <%= _("Add %s") % DspacePlugin::Communityy.short_description %>
  11 + <% end %>
  12 +
  13 + <% elsif dspace_content.is_a? DspacePlugin::Communityy %>
  14 +
  15 + <%= content_tag('a', :href => url_for({:controller => 'cms', :action => 'new', :type => "DspacePlugin::Collection", :parent_id => dspace_content.id}), :class => 'button with-text icon-add') do %>
  16 + <%= _("Add %s") % DspacePlugin::Collection.short_description %>
  17 + <% end %>
  18 +
  19 + <% end %>
  20 +
  21 + </div>
  22 +
  23 + <% end %>
  24 +
  25 + <% if dspace_content.is_a? DspacePlugin::Library %>
  26 +
  27 + <% communities = dspace_content.communities %>
  28 +
  29 + <ul id="communities_list">
  30 + <%= render :partial => 'community', :collection => communities %>
  31 + </ul>
  32 +
  33 + <% elsif dspace_content.is_a? DspacePlugin::Communityy %>
  34 +
  35 + <% community_id = dspace_content.dspace_community_id %>
  36 + <% dspace_server = dspace_content.parent.dspace_server_url %>
  37 +
  38 + <% collections = dspace_content.collections dspace_server, community_id %>
  39 +
  40 + <ul id="collections_list">
  41 + <%= render :partial => 'collection', :collection => collections %>
  42 + </ul>
  43 +
  44 + <% elsif dspace_content.is_a? DspacePlugin::Collection %>
  45 +
  46 + <% collection_id = dspace_content.dspace_collection_id %>
  47 + <% dspace_server = dspace_content.parent.parent.dspace_server_url %>
  48 +
  49 + <div id="dspace_library">
  50 + <div id="dspace_collection">
  51 + <ul id="items_list">
  52 + <%= render :partial => 'item', :collection => dspace_content.items(dspace_server, collection_id) %>
  53 + </ul>
  54 + </div>
  55 + </div>
  56 +
  57 + <% end %>
  58 +
  59 +</div>
... ...
plugins/dspace/views/dspace_plugin/_item_file.html.erb 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +<li>
  2 + <ul class="item_file_attributes_list">
  3 + <li>
  4 + <span><%= _('File:') %></span> <%= link_to item_file.name, dspace_server_url + item_file.retrieve_link, :target => '_blank' %></li>
  5 + <% unless item_file.description.blank? %>
  6 + <li>
  7 + <span><%= _('Description:') %> </span> <%= item_file.description %></li>
  8 + <% end %>
  9 + <li>
  10 + <span><%= _('Size:') %> </span> <%= number_to_human_size( item_file.size_bytes ) %></li>
  11 + </ul>
  12 +</li>
... ...
plugins/dspace/views/dspace_plugin/_item_section.html.erb 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +<div class="dspace_item_section">
  2 + <div class="dspace_item_section_title">
  3 + <%= item_section[:title] %>
  4 + </div>
  5 + <div class="dspace_item_section_content">
  6 + <%= item_section[:content] %>
  7 + </div>
  8 +</div>
... ...
plugins/dspace/views/dspace_plugin/view_item.html.erb 0 → 100644
... ... @@ -0,0 +1,28 @@
  1 +<% extend DspacePlugin::ItemHelper %>
  2 +
  3 +<div id="article-parent">
  4 + <%= button(:back, _('Go back to %s') % @collection.short_title, @collection.url) %>
  5 +</div>
  6 +
  7 +<div id="dspace_library_item">
  8 +
  9 + <div id="dspace_item_title">
  10 + <h1 class="title"><%= @item.name %></h1>
  11 + </div>
  12 +
  13 + <% item_files = render :partial => 'item_file',
  14 + :locals => { :dspace_server_url => remove_slash_at_end_url(@collection.parent.parent.dspace_server_url) },
  15 + :collection => @item.files %>
  16 +
  17 + <% item_files_content = content_tag('ul', item_files, :id => 'item_files_list') %>
  18 +
  19 +
  20 + <%= render :partial => 'item_section',
  21 + :collection => [ { :title => _('Authors:'), :content => @item.author },
  22 + { :title => _('Issue date:'), :content => @item.issue_date },
  23 + { :title => _('Abstract:'), :content => @item.abstract },
  24 + { :title => _('Description:'), :content => @item.description },
  25 + { :title => _('URI:'), :content => link_to(@item.uri, @item.uri, :target => '_blank') },
  26 + { :title => _('Files in this item'), :content => item_files_content } ] %>
  27 +
  28 +</div>
... ...
plugins/proposals_discussion/controllers/public/proposals_discussion_plugin_public_controller.rb
... ... @@ -20,6 +20,12 @@ class ProposalsDiscussionPluginPublicController &lt; ApplicationController
20 20 case order
21 21 when 'alphabetical'
22 22 proposals.reorder('name')
  23 + when 'recent'
  24 + proposals.reorder('created_at DESC')
  25 + when 'most_commented'
  26 + proposals.reorder('comments_count DESC')
  27 + when 'most_recently_commented'
  28 + proposals.joins("LEFT OUTER JOIN comments ON comments.source_id=articles.id AND comments.created_at >= '#{5.days.ago}'").group('articles.id').reorder('count(comments.id) DESC')
23 29 else
24 30 set_seed
25 31 proposals.reorder('random()')
... ...
plugins/proposals_discussion/lib/proposals_discussion_plugin/discussion.rb
1 1 class ProposalsDiscussionPlugin::Discussion < Folder
2 2  
  3 + acts_as_having_posts
  4 +
3 5 has_many :topics, :class_name => 'ProposalsDiscussionPlugin::Topic', :foreign_key => 'parent_id'
4 6 has_many :proposals, :class_name => 'ProposalsDiscussionPlugin::Proposal', :through => :children, :source => :children
5 7  
... ... @@ -26,4 +28,9 @@ class ProposalsDiscussionPlugin::Discussion &lt; Folder
26 28 end
27 29 alias_method_chain :cache_key, :person
28 30  
  31 + def posts
  32 + #override posts method to list proposals in feed
  33 + ProposalsDiscussionPlugin::Proposal.from_discussion(self)
  34 + end
  35 +
29 36 end
... ...
plugins/proposals_discussion/lib/proposals_discussion_plugin/proposal.rb
1 1 class ProposalsDiscussionPlugin::Proposal < TinyMceArticle
2 2  
3 3 scope :private, lambda {|user| {:conditions => {:last_changed_by_id => user.id, :published => false}}}
  4 + scope :from_discussion, lambda {|discussion| joins(:parent).where(['parents_articles.parent_id = ?', discussion.id])}
4 5  
5 6 alias :topic :parent
6 7  
... ... @@ -16,8 +17,12 @@ class ProposalsDiscussionPlugin::Proposal &lt; TinyMceArticle
16 17  
17 18  
18 19 def to_html(options = {})
19   - proc do
20   - render :file => 'content_viewer/proposal'
  20 + unless options[:feed]
  21 + proc do
  22 + render :file => 'content_viewer/proposal'
  23 + end
  24 + else
  25 + body
21 26 end
22 27 end
23 28  
... ... @@ -38,4 +43,8 @@ class ProposalsDiscussionPlugin::Proposal &lt; TinyMceArticle
38 43 end
39 44 alias_method_chain :cache_key, :person
40 45  
  46 + def can_display_versions?
  47 + false
  48 + end
  49 +
41 50 end
... ...
plugins/proposals_discussion/lib/proposals_discussion_plugin/proposal_helper.rb
... ... @@ -1,8 +0,0 @@
1   -module ProposalsDiscussionPlugin::ProposalHelper
2   -
3   - def visibility_options(article, tokenized_children)
4   - article.published = false if article.new_record?
5   - super
6   - end
7   -
8   -end
plugins/proposals_discussion/lib/proposals_discussion_plugin/proposals_list_helper.rb
1 1 module ProposalsDiscussionPlugin::ProposalsListHelper
2 2  
  3 + def sort_criteria
  4 + [[_('Random'), :random], [_('Alphabetical'), :alphabetical], [_('Recent'), :recent], [_('Most Commented'), :most_commented], [_('Most Recently Commented'), :most_recently_commented]]
  5 + end
  6 +
3 7 def more_proposals(text, holder, order, page=1)
4 8 link_to text, url_for({:controller => 'proposals_discussion_plugin_public', :action => 'load_proposals', :holder_id => holder.id, :profile => profile.identifier, :order => order, :page => page })
5 9 end
... ...
plugins/proposals_discussion/lib/proposals_discussion_plugin/topic.rb
... ... @@ -44,11 +44,21 @@ class ProposalsDiscussionPlugin::Topic &lt; Folder
44 44 end
45 45  
46 46 def proposals_per_day
47   - proposals.group("date(created_at)").count
  47 + result = proposals.group("date(created_at)").count
  48 + fill_empty_days(result)
48 49 end
49 50  
50 51 def comments_per_day
51   - proposals.joins(:comments).group('date(comments.created_at)').count('comments.id')
  52 + result = proposals.joins(:comments).group('date(comments.created_at)').count('comments.id')
  53 + fill_empty_days(result)
  54 + end
  55 +
  56 + def fill_empty_days(result)
  57 + from = created_at.to_date
  58 + (from..Date.today).inject({}) do |h, date|
  59 + h[date.to_s] = result[date.to_s] || 0
  60 + h
  61 + end
52 62 end
53 63  
54 64 def cache_key_with_person(params = {}, user = nil, language = 'en')
... ...
plugins/proposals_discussion/lib/proposals_discussion_plugin/topic_helper.rb 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +module ProposalsDiscussionPlugin::TopicHelper
  2 +
  3 + def topic_title(topic)
  4 + image_icon = topic.image ? image_tag(topic.image.public_filename(:thumb), :class => 'disable-zoom') : ''
  5 +
  6 + content_tag(:div, (
  7 + content_tag(:div, '', :class=>'topic-color', :style => "background-color: #{topic.color};") +
  8 + content_tag(:h2, link_to(image_icon + content_tag(:span, topic.title), topic.view_url))
  9 + ), :class => 'topic-title')
  10 + end
  11 +
  12 +end
... ...
plugins/proposals_discussion/public/proposals_graph.js~
... ... @@ -1,53 +0,0 @@
1   -(function basic_time(container) {
2   -
3   - var
4   - d1 = [],
5   - start = new Date("2009/01/01 01:00").getTime(),
6   - options,
7   - graph,
8   - i, x, o;
9   -
10   - for (i = 0; i < 100; i++) {
11   - x = start+(i*1000*3600*24*36.5);
12   - d1.push([x, i+Math.random()*30+Math.sin(i/20+Math.random()*2)*20+Math.sin(i/10+Math.random())*10]);
13   - }
14   -
15   - options = {
16   - xaxis : {
17   - mode : 'time',
18   - labelsAngle : 45
19   - },
20   - selection : {
21   - mode : 'x'
22   - },
23   - HtmlText : false,
24   - title : 'Time'
25   - };
26   -
27   - // Draw graph with default options, overwriting with passed options
28   - function drawGraph (opts) {
29   -
30   - // Clone the options, so the 'options' variable always keeps intact.
31   - o = Flotr._.extend(Flotr._.clone(options), opts || {});
32   -
33   - // Return a new graph.
34   - return Flotr.draw(
35   - container,
36   - [ d1 ],
37   - o
38   - );
39   - }
40   -
41   - graph = drawGraph();
42   -
43   - Flotr.EventAdapter.observe(container, 'flotr:select', function(area){
44   - // Draw selected area
45   - graph = drawGraph({
46   - xaxis : { min : area.x1, max : area.x2, mode : 'time', labelsAngle : 45 },
47   - yaxis : { min : area.y1, max : area.y2 }
48   - });
49   - });
50   -
51   - // When graph is clicked, draw the graph with default area.
52   - Flotr.EventAdapter.observe(container, 'flotr:click', function () { graph = drawGraph(); });
53   -})(document.getElementById("editor-render-0"));
plugins/proposals_discussion/public/proposals_list.js
... ... @@ -10,9 +10,9 @@ jQuery(document).ready(function($) {
10 10 });
11 11  
12 12 function proposalsScroll() {
13   - var scroll = $('.article-body-proposals-discussion-plugin_topic .topic-content .proposals_list');
  13 + var scroll = $('.article-body-proposals-discussion-plugin_topic .topic-content .proposals_list .proposals');
14 14 var nextSelector = 'div.more a';
15   - if(scroll.data('jscroll')) scroll.jscroll.destroy();
  15 + if(scroll.data('jscroll')) scroll.data('jscroll', null);
16 16  
17 17 if(scroll.find(nextSelector).length > 0) {
18 18 scroll.jscroll({
... ... @@ -31,6 +31,12 @@ jQuery(document).ready(function($) {
31 31 $('.topics').masonry();
32 32 });
33 33 $('.topics').masonry();
  34 + $(window).resize(function() {
  35 + $('.topics').masonry();
  36 + });
  37 + $(window).bind('toggleFullwidth', function() {
  38 + $('.topics').masonry();
  39 + });
34 40 });
35 41  
36 42 function loadSocialButtons() {
... ...
plugins/proposals_discussion/public/style.css
... ... @@ -156,11 +156,14 @@ form .proposals-discussion-plugin .body textarea {
156 156 #content .topic-item h2 a, #article .article-body-proposals-discussion-plugin_topic h2 a,
157 157 #content .topic h2 a {
158 158 text-decoration: none;
159   - padding: 10px;
160 159 display: inline-block;
161 160 width: 94%;
162 161 color: white;
163 162 }
  163 +#content .topic-title h2 span {
  164 + padding: 10px;
  165 + display: inline-block;
  166 +}
164 167 .topic-item .topic-content, #article .article-body-proposals-discussion-plugin_topic .topic-content {
165 168 padding: 5px 7px 5px 2px;
166 169 }
... ... @@ -177,7 +180,7 @@ form .proposals-discussion-plugin .body textarea {
177 180 margin: 1px 0 0 0;
178 181 }
179 182  
180   -#content .tag_cloud a {
  183 +#content .article-body-proposals-discussion-plugin_topic .tag_cloud a {
181 184 text-decoration: none;
182 185 }
183 186  
... ... @@ -199,7 +202,7 @@ form .proposals-discussion-plugin .body textarea {
199 202 #content .statistics h5 {
200 203 color: rgb(95, 95, 95);
201 204 }
202   -#content .tag_cloud {
  205 +#content .article-body-proposals-discussion-plugin_topic .tag_cloud {
203 206 float: right;
204 207 width: 300px;
205 208 box-shadow: 5px 5px 5px -2px #ddd;
... ... @@ -219,3 +222,13 @@ form .proposals-discussion-plugin .body textarea {
219 222 clear: both;
220 223 padding-top: 10px;
221 224 }
  225 +
  226 +.proposal .actions .fb-share-button {
  227 + top: -3px;
  228 +}
  229 +
  230 +.topic-title h2 img {
  231 + max-height: 36px;
  232 + vertical-align: middle;
  233 + padding: 4px 0 4px 4px;
  234 +}
... ...
plugins/proposals_discussion/test/functional/proposals_discussion_plugin_public_controller_test.rb
... ... @@ -35,4 +35,48 @@ class ProposalsDiscussionPluginPublicControllerTest &lt; ActionController::TestCase
35 35 assert_equal [proposal2, proposal3, proposal1], assigns(:proposals)
36 36 end
37 37  
  38 + should 'load proposals with most commented order' do
  39 + proposal1 = fast_create(ProposalsDiscussionPlugin::Proposal, :name => 'proposal1', :abstract => 'proposal abstract', :profile_id => profile.id, :parent_id => topic.id)
  40 + proposal2 = fast_create(ProposalsDiscussionPlugin::Proposal, :name => 'proposal2', :abstract => 'proposal abstract', :profile_id => profile.id, :parent_id => topic.id)
  41 + proposal3 = fast_create(ProposalsDiscussionPlugin::Proposal, :name => 'proposal3', :abstract => 'proposal abstract', :profile_id => profile.id, :parent_id => topic.id)
  42 +
  43 + author = fast_create(Person)
  44 + Comment.create!(:source => proposal2, :body => 'text', :author => author)
  45 + Comment.create!(:source => proposal2, :body => 'text', :author => author)
  46 + Comment.create!(:source => proposal3, :body => 'text', :author => author)
  47 +
  48 + get :load_proposals, :profile => profile.identifier, :holder_id => topic.id, :order => 'most_commented'
  49 + assert_equal [proposal2, proposal3, proposal1], assigns(:proposals)
  50 + end
  51 +
  52 + should 'load proposals with most recent order' do
  53 + proposal1 = fast_create(ProposalsDiscussionPlugin::Proposal, :name => 'z', :abstract => 'proposal abstract', :profile_id => profile.id, :parent_id => topic.id)
  54 + proposal2 = fast_create(ProposalsDiscussionPlugin::Proposal, :name => 'b', :abstract => 'proposal abstract', :profile_id => profile.id, :parent_id => topic.id)
  55 + proposal3 = fast_create(ProposalsDiscussionPlugin::Proposal, :name => 'k', :abstract => 'proposal abstract', :profile_id => profile.id, :parent_id => topic.id)
  56 +
  57 + author = fast_create(Person)
  58 + Comment.create!(:source => proposal2, :body => 'text', :author => author)
  59 + Comment.create!(:source => proposal2, :body => 'text', :author => author)
  60 + Comment.create!(:source => proposal3, :body => 'text', :author => author)
  61 +
  62 + get :load_proposals, :profile => profile.identifier, :holder_id => topic.id, :order => 'recent'
  63 + assert_equal [proposal3, proposal2, proposal1], assigns(:proposals)
  64 + end
  65 +
  66 + should 'load proposals with most recently commented order' do
  67 + proposal1 = fast_create(ProposalsDiscussionPlugin::Proposal, :name => 'proposal1', :abstract => 'proposal abstract', :profile_id => profile.id, :parent_id => topic.id)
  68 + proposal2 = fast_create(ProposalsDiscussionPlugin::Proposal, :name => 'proposal2', :abstract => 'proposal abstract', :profile_id => profile.id, :parent_id => topic.id)
  69 + proposal3 = fast_create(ProposalsDiscussionPlugin::Proposal, :name => 'proposal3', :abstract => 'proposal abstract', :profile_id => profile.id, :parent_id => topic.id)
  70 +
  71 + author = fast_create(Person)
  72 + Comment.create!({:source => proposal2, :body => 'text', :author => author, :created_at => 10.days.ago}, :without_protection => true)
  73 + Comment.create!({:source => proposal2, :body => 'text', :author => author, :created_at => 10.days.ago}, :without_protection => true)
  74 + Comment.create!(:source => proposal3, :body => 'text', :author => author)
  75 + Comment.create!(:source => proposal3, :body => 'text', :author => author)
  76 + Comment.create!(:source => proposal1, :body => 'text', :author => author)
  77 +
  78 + get :load_proposals, :profile => profile.identifier, :holder_id => topic.id, :order => 'most_recently_commented'
  79 + assert_equal [proposal3, proposal1, proposal2], assigns(:proposals)
  80 + end
  81 +
38 82 end
... ...
plugins/proposals_discussion/test/unit/proposal_test.rb
... ... @@ -29,4 +29,26 @@ class ProposalTest &lt; ActiveSupport::TestCase
29 29 assert !proposal.allow_edit?(fast_create(Person))
30 30 end
31 31  
  32 + should 'return body when to_html was called with feed=true' do
  33 + assert_equal proposal.body, proposal.to_html(:feed => true)
  34 + end
  35 +
  36 + should 'return a proc when to_html was called with feed=false' do
  37 + assert proposal.to_html(:feed => false).kind_of?(Proc)
  38 + end
  39 +
  40 + should 'return a proc when to_html was called with no feed parameter' do
  41 + assert proposal.to_html.kind_of?(Proc)
  42 + end
  43 +
  44 + should 'return proposals by discussion' do
  45 + discussion = fast_create(ProposalsDiscussionPlugin::Discussion)
  46 + topic = fast_create(ProposalsDiscussionPlugin::Topic, :parent_id => discussion.id)
  47 + proposal1 = fast_create(ProposalsDiscussionPlugin::Proposal, :parent_id => topic.id)
  48 + proposal2 = fast_create(ProposalsDiscussionPlugin::Proposal)
  49 + proposal3 = fast_create(ProposalsDiscussionPlugin::Proposal, :parent_id => topic.id)
  50 +
  51 + assert_equivalent [proposal1, proposal3], ProposalsDiscussionPlugin::Proposal.from_discussion(discussion)
  52 + end
  53 +
32 54 end
... ...
plugins/proposals_discussion/views/cms/proposals_discussion_plugin/_proposal.html.erb
... ... @@ -5,7 +5,14 @@
5 5 <% title_limit = 70 %>
6 6 <% abstract_limit = 140 %>
7 7  
  8 +<% extend ProposalsDiscussionPlugin::TopicHelper %>
  9 +
8 10 <div class="proposals-discussion-plugin">
  11 +
  12 + <div class="topic">
  13 + <%= topic_title @article.topic %>
  14 + </div>
  15 +
9 16 <div class="title">
10 17 <%= required labelled_form_field _('Title'), limited_text_area(:article, :name, title_limit, 'title_textarea', :rows => 1) %>
11 18 </div>
... ...
plugins/proposals_discussion/views/cms/proposals_discussion_plugin/_topic.html.erb
... ... @@ -11,3 +11,8 @@
11 11  
12 12 <%= labelled_colorpicker_field(_('Color:'), :article, :color) %>
13 13 <span id="color_preview" class = "color_marker" style="background-color: <%= @article.color %>" ></span>
  14 +
  15 +<%= f.fields_for :image_builder, @article.image do |i| %>
  16 + <%= file_field_or_thumbnail(_('Image:'), @article.image, i)%>
  17 + <%= _("Max size: %s (.jpg, .gif, .png)")% Image.max_size.to_humanreadable %>
  18 +<% end %>
... ...
plugins/proposals_discussion/views/content_viewer/_proposals_list.html.erb
... ... @@ -12,7 +12,7 @@
12 12 <% order ||= 'random' %>
13 13 <div class="proposals_list">
14 14 <div class="filters">
15   - <% [[_('Random'), :random], [_('Aplhabetical'), :alphabetical]].each_with_index do |order, i| %>
  15 + <% sort_criteria.each_with_index do |order, i| %>
16 16 <%= link_to order.first, url_for({:controller => 'proposals_discussion_plugin_public', :action => 'load_proposals', :holder_id => holder.id, :profile => profile.identifier, :order => order.second}), :remote => true, :class => "order #{order.second} #{i==0 ? 'selected':''}" %>
17 17 <% end %>
18 18 </div>
... ...
plugins/proposals_discussion/views/content_viewer/_social.html.erb
1 1 <a href="https://twitter.com/share" class="twitter-share-button" data-url="<%= url_for proposal.view_url %>" data-text="<%= proposal.title %>" data-count="none"></a>
2 2  
3   -<div class="fb-share-button" data-href="<%= url_for proposal.view_url %>" data-layout="box-count"></div>
  3 +<div class="fb-share-button" data-href="<%= url_for proposal.view_url %>"></div>
... ...
plugins/proposals_discussion/views/content_viewer/discussion.html.erb
1 1 <%= javascript_include_tag 'plugins/proposals_discussion/proposals_list.js' %>
2 2  
  3 +<%= add_rss_feed_to_head(@page.name, @page.feed.url) if @page.feed %>
  4 +
3 5 <div class="description">
4 6 <%= @page.body %>
5 7 </div>
... ...
plugins/proposals_discussion/views/content_viewer/proposal.html.erb
... ... @@ -2,9 +2,10 @@
2 2 <h5><%= @page.topic.discussion.title %> </h5>
3 3 </div>
4 4  
  5 +<% extend ProposalsDiscussionPlugin::TopicHelper %>
  6 +
5 7 <div class="topic">
6   - <div class="topic-color" style="background-color: <%= @page.topic.color %>;"></div>
7   - <h2><%= link_to @page.topic.title, @page.topic.view_url %></h2>
  8 + <%= topic_title @page.topic %>
8 9 </div>
9 10  
10 11 <div class="title">
... ...
plugins/proposals_discussion/views/content_viewer/topic.html.erb
... ... @@ -4,8 +4,8 @@
4 4 <%= javascript_include_tag 'plugins/proposals_discussion/proposals_list.js' %>
5 5 <% end %>
6 6  
7   -<div class="topic-color" style="background-color: <%= topic.color %>;"></div>
8   -<h2><%= link_to topic.title, topic.view_url %></h2>
  7 +<% extend ProposalsDiscussionPlugin::TopicHelper %>
  8 +<%= topic_title topic %>
9 9  
10 10 <div class="topic-content">
11 11  
... ...
plugins/proposals_discussion/views/select_topic.html.erb
... ... @@ -16,7 +16,7 @@
16 16 <h3><%= _('Select topic') %></h3>
17 17 <div id="topics">
18 18  
19   - <% @discussion.children.each do |topic| %>
  19 + <% @discussion.topics.each do |topic| %>
20 20 <h4>
21 21 <%= radio_button_tag('discussion[topic]', topic.id) %>
22 22 <%= topic.title %>
... ...
public/javascripts/application.js
... ... @@ -1037,7 +1037,7 @@ jQuery(document).ready(function(){
1037 1037 function apply_zoom_to_images(zoom_text) {
1038 1038 jQuery(function($) {
1039 1039 $(window).load( function() {
1040   - $('#article .article-body img').each( function(index) {
  1040 + $('#article .article-body img:not(.disable-zoom)').each( function(index) {
1041 1041 var original = original_image_dimensions($(this).attr('src'));
1042 1042 if ($(this).width() < original['width'] || $(this).height() < original['height']) {
1043 1043 $(this).wrap('<div class="zoomable-image" />');
... ... @@ -1083,6 +1083,7 @@ function toggle_fullwidth(itemId){
1083 1083 jQuery("#fullscreen-btn").hide()
1084 1084 fullwidth = true;
1085 1085 }
  1086 + jQuery(window).trigger("toggleFullwidth", fullwidth);
1086 1087 }
1087 1088  
1088 1089 function fullscreenPageLoad(itemId){
... ...
script/install-dependencies/debian-wheezy.sh
... ... @@ -50,6 +50,13 @@ FPQAoNmiMgP6zGF9rgOEWMEiFEryayrz
50 50 EOF
51 51 fi
52 52  
  53 +if test -f tmp/debian/Release.gpg; then
  54 + echo "deb file://$(pwd)/tmp/debian/ ./" | sudo tee /etc/apt/sources.list.d/local.list
  55 + sudo apt-key add tmp/debian/signing-key.asc
  56 +else
  57 + sudo rm -f /etc/apt/sources.list.d/local.list
  58 +fi
  59 +
53 60 run sudo apt-get update
54 61 run sudo apt-get -qy dist-upgrade
55 62  
... ...
script/install-dependencies/ubuntu-precise.sh 0 → 100644
... ... @@ -0,0 +1,23 @@
  1 +#!/bin/sh
  2 +
  3 +export DEBIAN_INTERFACE=noninteractive
  4 +
  5 +#run sudo apt-get update
  6 +#run sudo apt-get dist-upgrade -qy
  7 +
  8 +run sudo apt-get install -qy dctrl-tools
  9 +
  10 +packages=$(grep-dctrl -n -s Build-Depends,Depends,Recommends -S -X noosfero debian/control | sed -e 's/([^)]*)//g; s/,\s*/\n/g' | grep -v 'rake\|ruby\|thin\|debhelper\|cucumber\|rail\|memcached\|debconf\|dbconfig-common\|misc:Depends\|adduser\|mail-transport-agent')
  11 +
  12 +run sudo apt-get install -qy ruby1.9.1-full build-essential libxml2-dev libxslt-dev libpq-dev libmagickcore-dev libmagickwand-dev $packages
  13 +
  14 +
  15 +export GEM_HOME=$(ruby -e 'puts Gem.user_dir')
  16 +export PATH="${GEM_HOME}/bin:${PATH}"
  17 +(gem list | grep bundler) || run gem install --no-rdoc --no-ri bundler
  18 +run bundle install
  19 +
  20 +sudo tee /etc/profile.d/rubygems-path.sh <<EOF
  21 +export GEM_HOME=\$(ruby -e 'puts Gem.user_dir')
  22 +PATH="\${GEM_HOME}/bin:\${PATH}"
  23 +EOF
... ...
test/factories.rb
... ... @@ -174,7 +174,11 @@ module Noosfero::Factory
174 174 ###############################################
175 175  
176 176 def defaults_for_environment
177   - { :name => 'Environment ' + factory_num_seq.to_s }
  177 + seq = factory_num_seq
  178 + {
  179 + :name => "Environment %d" % seq,
  180 + :contact_email => "environment%d@example.com" % seq
  181 + }
178 182 end
179 183  
180 184 ###############################################
... ...
test/functional/profile_controller_test.rb
... ... @@ -78,7 +78,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
78 78  
79 79 should 'actually add friend' do
80 80 login_as(@profile.identifier)
81   - person = fast_create(Person)
  81 + person = create_user.person
82 82 assert_difference 'AddFriend.count' do
83 83 post :add, :profile => person.identifier
84 84 end
... ... @@ -366,10 +366,10 @@ class ProfileControllerTest &lt; ActionController::TestCase
366 366 assert profile.memberships.include?(community), 'profile should be actually added to the community'
367 367 end
368 368  
369   - should 'create task when join to closed organization with members' do
  369 + should 'create a task when joining a closed organization with members' do
370 370 community = fast_create(Community)
371 371 community.update_attribute(:closed, true)
372   - admin = fast_create(Person)
  372 + admin = create_user.person
373 373 community.add_member(admin)
374 374  
375 375 login_as profile.identifier
... ... @@ -587,7 +587,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
587 587 should "leave a scrap on another profile" do
588 588 login_as(profile.identifier)
589 589 count = Scrap.count
590   - another_person = fast_create(Person)
  590 + another_person = create_user.person
591 591 assert another_person.scraps_received.empty?
592 592 post :leave_scrap, :profile => another_person.identifier, :scrap => {:content => 'something'}
593 593 assert_equal count + 1, Scrap.count
... ... @@ -645,7 +645,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
645 645 should "the sender be the logged user by default" do
646 646 login_as(profile.identifier)
647 647 count = Scrap.count
648   - another_person = fast_create(Person)
  648 + another_person = create_user.person
649 649 post :leave_scrap, :profile => another_person.identifier, :scrap => {:content => 'something'}
650 650 last = Scrap.last
651 651 assert_equal profile, last.sender
... ... @@ -654,7 +654,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
654 654 should "the receiver be the current profile by default" do
655 655 login_as(profile.identifier)
656 656 count = Scrap.count
657   - another_person = fast_create(Person)
  657 + another_person = create_user.person
658 658 post :leave_scrap, :profile => another_person.identifier, :scrap => {:content => 'something'}
659 659 last = Scrap.last
660 660 assert_equal another_person, last.receiver
... ... @@ -686,8 +686,8 @@ class ProfileControllerTest &lt; ActionController::TestCase
686 686 end
687 687  
688 688 should 'not display activities of the current profile when he is not followed by the viewer' do
689   - p1= fast_create(Person)
690   - p2= fast_create(Person)
  689 + p1= create_user.person
  690 + p2= create_user.person
691 691  
692 692 UserStampSweeper.any_instance.stubs(:current_user).returns(p1)
693 693 scrap1 = create(Scrap, defaults_for_scrap(:sender => p1, :receiver => p2))
... ... @@ -714,9 +714,9 @@ class ProfileControllerTest &lt; ActionController::TestCase
714 714 end
715 715  
716 716 should 'not see the friends activities in the current profile' do
717   - p2= fast_create(Person)
  717 + p2 = create_user.person
718 718 assert !profile.is_a_friend?(p2)
719   - p3= fast_create(Person)
  719 + p3 = create_user.person
720 720 p3.add_friend(profile)
721 721 assert p3.is_a_friend?(profile)
722 722 ActionTracker::Record.destroy_all
... ... @@ -737,13 +737,13 @@ class ProfileControllerTest &lt; ActionController::TestCase
737 737 end
738 738  
739 739 should 'see all the activities in the current profile network' do
740   - p1= fast_create(Person)
741   - p2= fast_create(Person)
  740 + p1= create_user.person
  741 + p2= create_user.person
742 742 assert !p1.is_a_friend?(p2)
743 743  
744   - p3= fast_create(Person)
  744 + p3= create_user.person
745 745 p3.add_friend(p1)
746   - assert p3.is_a_friend?(p1)
  746 + p1.add_friend(p3)
747 747  
748 748 ActionTracker::Record.delete_all
749 749  
... ... @@ -759,27 +759,21 @@ class ProfileControllerTest &lt; ActionController::TestCase
759 759 create(Scrap, defaults_for_scrap(:sender => p3, :receiver => p1))
760 760 a3 = ActionTracker::Record.last
761 761  
762   - @controller.stubs(:logged_in?).returns(true)
763   - user = mock()
764   - user.stubs(:person).returns(p3)
765   - user.stubs(:login).returns('some')
766   - @controller.stubs(:current_user).returns(user)
767   - Person.any_instance.stubs(:follows?).returns(true)
768   -
769 762 process_delayed_job_queue
770   - get :index, :profile => p1.identifier
771 763  
  764 + login_as p3.user.login
  765 + get :index, :profile => p1.identifier
772 766 assert_equivalent [a1,a3].map(&:id), assigns(:network_activities).map(&:id)
773 767 end
774 768  
775 769 should 'the network activity be visible only to profile followers' do
776   - p1= fast_create(Person)
777   - p2= fast_create(Person)
  770 + p1= create_user.person
  771 + p2= create_user.person
778 772 assert !p1.is_a_friend?(p2)
779 773  
780   - p3= fast_create(Person)
  774 + p3= create_user.person
781 775 p3.add_friend(p1)
782   - assert p3.is_a_friend?(p1)
  776 + p1.add_friend(p3)
783 777  
784 778 ActionTracker::Record.delete_all
785 779  
... ... @@ -795,24 +789,11 @@ class ProfileControllerTest &lt; ActionController::TestCase
795 789 create(Scrap, defaults_for_scrap(:sender => p3, :receiver => p1))
796 790 a3 = ActionTracker::Record.last
797 791  
798   - @controller.stubs(:logged_in?).returns(true)
799   - user = mock()
800   - user.stubs(:person).returns(p2)
801   - user.stubs(:login).returns('some')
802   - @controller.stubs(:current_user).returns(user)
  792 + process_delayed_job_queue
803 793  
  794 + login_as p2.user.login
804 795 get :index, :profile => p1.identifier
805 796 assert assigns(:network_activities).blank?
806   -
807   - user = mock()
808   - user.stubs(:person).returns(p3)
809   - user.stubs(:login).returns('some')
810   - @controller.stubs(:current_user).returns(user)
811   - Person.any_instance.stubs(:follows?).returns(true)
812   - process_delayed_job_queue
813   -
814   - get :index, :profile => p3.identifier
815   - assert_equivalent [a1,a3], assigns(:network_activities)
816 797 end
817 798  
818 799 should 'the network activity be paginated' do
... ... @@ -829,10 +810,10 @@ class ProfileControllerTest &lt; ActionController::TestCase
829 810 end
830 811  
831 812 should 'the network activity be visible only to logged users' do
832   - p1= fast_create(Person)
833   - p2= fast_create(Person)
  813 + p1= create_user.person
  814 + p2= create_user.person
834 815 assert !p1.is_a_friend?(p2)
835   - p3= fast_create(Person)
  816 + p3= create_user.person
836 817 p3.add_friend(p1)
837 818 assert p3.is_a_friend?(p1)
838 819 ActionTracker::Record.destroy_all
... ... @@ -891,10 +872,10 @@ class ProfileControllerTest &lt; ActionController::TestCase
891 872 end
892 873  
893 874 should 'the self activity not crashes with user not logged in' do
894   - p1= fast_create(Person)
895   - p2= fast_create(Person)
  875 + p1= create_user.person
  876 + p2= create_user.person
896 877 assert !p1.is_a_friend?(p2)
897   - p3= fast_create(Person)
  878 + p3= create_user.person
898 879 p3.add_friend(p1)
899 880 assert p3.is_a_friend?(p1)
900 881 ActionTracker::Record.destroy_all
... ...
test/functional/profile_editor_controller_test.rb
... ... @@ -865,7 +865,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase
865 865  
866 866 should 'not be able to destroy enterprise if is a regular member' do
867 867 enterprise = fast_create(Enterprise)
868   - enterprise.add_member(fast_create(Person)) # first member is admin by default
  868 + enterprise.add_member(create_user.person) # first member is admin by default
869 869  
870 870 person = create_user('foo').person
871 871 enterprise.add_member(person)
... ...
test/unit/application_helper_test.rb
... ... @@ -49,6 +49,20 @@ class ApplicationHelperTest &lt; ActionView::TestCase
49 49 end
50 50 end
51 51  
  52 + should 'plugins path take precedence over core path' do
  53 + core_path = 'core/'
  54 + plugin_path = 'path/'
  55 + @controller = mock()
  56 + @controller.stubs(:view_paths).returns([plugin_path, core_path])
  57 + self.stubs(:params).returns({:controller => 'test'})
  58 +
  59 + File.stubs(:exists?).returns(false)
  60 + File.stubs(:exists?).with(core_path+"test/_block.html.erb").returns(true)
  61 + File.stubs(:exists?).with(plugin_path+"test/_raw_html_block.html.erb").returns(true)
  62 +
  63 + assert_equal 'raw_html_block', partial_for_class(RawHTMLBlock)
  64 + end
  65 +
52 66 should 'generate link to stylesheet' do
53 67 File.stubs(:exists?).returns(false)
54 68 File.expects(:exists?).with(Rails.root.join('public', 'stylesheets', 'something.css')).returns(true)
... ...
test/unit/comment_notifier_test.rb
... ... @@ -57,15 +57,6 @@ class CommentNotifierTest &lt; ActiveSupport::TestCase
57 57 assert_match /comment body/, sent.body.to_s
58 58 end
59 59  
60   - should 'not deliver mail if has no notification emails' do
61   - community = fast_create(Community)
62   - assert_equal [], community.notification_emails
63   - article = fast_create(Article, :name => 'Article test', :profile_id => community.id, :notify_comments => true)
64   - assert_no_difference 'ActionMailer::Base.deliveries.size' do
65   - create_comment_and_notify(:author => @author, :title => 'test comment', :body => 'there is no addresses to send notification', :source => article)
66   - end
67   - end
68   -
69 60 should "deliver mail to followers" do
70 61 author = create_user('follower_author').person
71 62 follower = create_user('follower').person
... ...
test/unit/environment_test.rb
... ... @@ -195,6 +195,12 @@ class EnvironmentTest &lt; ActiveSupport::TestCase
195 195 assert !env.errors[:contact_email.to_s].present?
196 196 end
197 197  
  198 + should 'notify contact email' do
  199 + env = Environment.new(:contact_email => 'foo@bar.com')
  200 + env.stubs(:admins).returns([])
  201 + assert_equal ['foo@bar.com'], env.notification_emails
  202 + end
  203 +
198 204 should 'provide a default hostname' do
199 205 env = fast_create(Environment)
200 206 env.domains << create(Domain, :name => 'example.com', :is_default => true)
... ...
test/unit/feed_reader_block_test.rb
... ... @@ -53,7 +53,7 @@ class FeedReaderBlockTest &lt; ActiveSupport::TestCase
53 53 end
54 54  
55 55 should 'display last fetched date' do
56   - now = Time.now
  56 + now = Time.new(2014,1,1)
57 57 feed.feed_items = ['one', 'two']
58 58 feed.fetched_at = now
59 59 assert_equal "Updated: #{show_date(now)}", feed.footer
... ...
test/unit/organization_test.rb
... ... @@ -123,9 +123,9 @@ class OrganizationTest &lt; ActiveSupport::TestCase
123 123 assert_equal ['admin1@email.com', 'admin2@email.com'], o.notification_emails
124 124 end
125 125  
126   - should 'return empty array if contact_email is a blank string and it has no admin' do
  126 + should 'use the environment contact email if no emails are listed here' do
127 127 o = build(Organization, :contact_email => '', :environment => Environment.default)
128   - assert_equal [], o.notification_emails
  128 + assert_equal [o.environment.contact_email], o.notification_emails
129 129 end
130 130  
131 131 should 'list pending enterprise validations' do
... ...
test/unit/person_test.rb
... ... @@ -1198,8 +1198,8 @@ class PersonTest &lt; ActiveSupport::TestCase
1198 1198  
1199 1199 should 'return tracked_actions and scraps as activities' do
1200 1200 ActionTracker::Record.destroy_all
1201   - person = fast_create(Person)
1202   - another_person = fast_create(Person)
  1201 + person = create_user.person
  1202 + another_person = create_user.person
1203 1203  
1204 1204 UserStampSweeper.any_instance.stubs(:current_user).returns(another_person)
1205 1205 scrap = create(Scrap, defaults_for_scrap(:sender => another_person, :receiver => person, :content => 'A scrap'))
... ...
test/unit/scrap_notifier_test.rb
... ... @@ -57,10 +57,10 @@ class ScrapNotifierTest &lt; ActiveSupport::TestCase
57 57  
58 58 should 'not deliver mail if is a reply on a community' do
59 59 community = fast_create(Community)
60   - person = fast_create(Person)
  60 + person = create_user.person
61 61 scrap = fast_create(Scrap, :receiver_id => community.id, :sender_id => @sender.id)
62 62 assert_no_difference 'ActionMailer::Base.deliveries.size' do
63   - Scrap.create!(:sender_id => person, :receiver_id => @sender.id, :scrap_id => scrap.id, :content => 'Hi myself!')
  63 + Scrap.create!(:sender_id => person.id, :receiver_id => @sender.id, :scrap_id => scrap.id, :content => 'Hi myself!')
64 64 end
65 65 end
66 66  
... ...
test/unit/scrap_test.rb
... ... @@ -42,7 +42,7 @@ class ScrapTest &lt; ActiveSupport::TestCase
42 42 end
43 43  
44 44 should "be associated to Person as sender" do
45   - person = fast_create(Person)
  45 + person = create_user.person
46 46 s = Scrap.new
47 47 assert_nothing_raised do
48 48 s.sender = person
... ... @@ -50,7 +50,7 @@ class ScrapTest &lt; ActiveSupport::TestCase
50 50 end
51 51  
52 52 should "be associated to Person as receiver" do
53   - person = fast_create(Person)
  53 + person = create_user.person
54 54 s = Scrap.new
55 55 assert_nothing_raised do
56 56 s.receiver = person
... ... @@ -66,7 +66,7 @@ class ScrapTest &lt; ActiveSupport::TestCase
66 66 end
67 67  
68 68 should "collect all scraps sent and received of a person" do
69   - person = fast_create(Person)
  69 + person = create_user.person
70 70 s1 = fast_create(Scrap, :sender_id => person.id)
71 71 assert_equal [s1], Scrap.all_scraps(person)
72 72 s2 = fast_create(Scrap, :sender_id => person.id)
... ... @@ -77,7 +77,7 @@ class ScrapTest &lt; ActiveSupport::TestCase
77 77  
78 78 should "collect all scraps sent and received of a community" do
79 79 community = fast_create(Community)
80   - person = fast_create(Person)
  80 + person = create_user.person
81 81 s1 = fast_create(Scrap, :sender_id => person.id)
82 82 assert_equal [], Scrap.all_scraps(community)
83 83 s2 = fast_create(Scrap, :receiver_id => community.id, :sender_id => person.id)
... ... @@ -87,8 +87,8 @@ class ScrapTest &lt; ActiveSupport::TestCase
87 87 end
88 88  
89 89 should "create the leave_scrap action tracker verb on scrap creation of one user to another" do
90   - p1 = fast_create(Person)
91   - p2 = fast_create(Person)
  90 + p1 = create_user.person
  91 + p2 = create_user.person
92 92 s = Scrap.new
93 93 s.sender= p1
94 94 s.receiver= p2
... ... @@ -104,7 +104,7 @@ class ScrapTest &lt; ActiveSupport::TestCase
104 104 end
105 105  
106 106 should "create the leave_scrap action tracker verb on scrap creation of one user to community" do
107   - p = fast_create(Person)
  107 + p = create_user.person
108 108 c = fast_create(Community)
109 109 s = Scrap.new
110 110 s.sender= p
... ... @@ -122,8 +122,8 @@ class ScrapTest &lt; ActiveSupport::TestCase
122 122 end
123 123  
124 124 should "notify leave_scrap action tracker verb to friends and itself" do
125   - p1 = fast_create(Person)
126   - p2 = fast_create(Person)
  125 + p1 = create_user.person
  126 + p2 = create_user.person
127 127 p1.add_friend(p2)
128 128 ActionTrackerNotification.delete_all
129 129 Delayed::Job.delete_all
... ... @@ -140,7 +140,7 @@ class ScrapTest &lt; ActiveSupport::TestCase
140 140 end
141 141  
142 142 should "notify leave_scrap action tracker verb to members of the communities and the community itself" do
143   - p = fast_create(Person)
  143 + p = create_user.person
144 144 c = fast_create(Community)
145 145 c.add_member(p)
146 146 ActionTrackerNotification.delete_all
... ... @@ -158,7 +158,7 @@ class ScrapTest &lt; ActiveSupport::TestCase
158 158 end
159 159  
160 160 should "create the leave_scrap_to_self action tracker verb on scrap creation of one user to itself" do
161   - p = fast_create(Person)
  161 + p = create_user.person
162 162 s = Scrap.new
163 163 s.sender= p
164 164 s.receiver= p
... ... @@ -172,8 +172,8 @@ class ScrapTest &lt; ActiveSupport::TestCase
172 172 end
173 173  
174 174 should "notify leave_scrap_to_self action tracker verb to friends and itself" do
175   - p1 = fast_create(Person)
176   - p2 = fast_create(Person)
  175 + p1 = create_user.person
  176 + p2 = create_user.person
177 177 p1.add_friend(p2)
178 178 ActionTrackerNotification.delete_all
179 179 Delayed::Job.delete_all
... ... @@ -216,7 +216,7 @@ class ScrapTest &lt; ActiveSupport::TestCase
216 216 end
217 217  
218 218 should "update the scrap on reply creation" do
219   - person = fast_create(Person)
  219 + person = create_user.person
220 220 s = fast_create(Scrap, :updated_at => DateTime.parse('2010-01-01'))
221 221 assert_equal DateTime.parse('2010-01-01'), s.updated_at.strftime('%Y-%m-%d')
222 222 DateTime.stubs(:now).returns(DateTime.parse('2010-09-07'))
... ... @@ -242,20 +242,20 @@ class ScrapTest &lt; ActiveSupport::TestCase
242 242 end
243 243  
244 244 should 'strip all html tags' do
245   - s, r = fast_create(Person), fast_create(Person)
  245 + s, r = create_user.person, create_user.person
246 246 s = build Scrap, :sender => s, :receiver => r, :content => "<p>Test <b>Rails</b></p>"
247 247 assert_equal "Test Rails", s.strip_all_html_tags
248 248 end
249 249  
250 250 should 'strip html before save' do
251   - s, r = fast_create(Person), fast_create(Person)
  251 + s, r = create_user.person, create_user.person
252 252 s = build Scrap, :sender => s, :receiver => r, :content => "<p>Test <b>Rails</b></p>"
253 253 s.save!
254 254 assert_equal "Test Rails", s.reload.content
255 255 end
256 256  
257 257 should 'strip html before validate' do
258   - s, r = fast_create(Person), fast_create(Person)
  258 + s, r = create_user.person, create_user.person
259 259 s = build Scrap, :sender => s, :receiver => r, :content => "<p><b></b></p>"
260 260 assert !s.valid?
261 261 s.content = "<p>Test</p>"
... ... @@ -272,7 +272,7 @@ class ScrapTest &lt; ActiveSupport::TestCase
272 272 end
273 273  
274 274 should 'scrap wall url be the root scrap receiver url if it is a reply' do
275   - p1, p2 = fast_create(Person), fast_create(Person)
  275 + p1, p2 = create_user.person, create_user.person
276 276 r = create Scrap, :sender => p1, :receiver => p2, :content => "Hello!"
277 277 s = build Scrap, :sender => p2, :receiver => p1, :content => "Hi!"
278 278 r.replies << s; s.reload
... ... @@ -280,13 +280,13 @@ class ScrapTest &lt; ActiveSupport::TestCase
280 280 end
281 281  
282 282 should 'scrap wall url be the scrap receiver url if it is not a reply' do
283   - p1, p2 = fast_create(Person), fast_create(Person)
  283 + p1, p2 = create_user.person, create_user.person
284 284 s = create Scrap, :sender => p1, :receiver => p2, :content => "Hello!"
285 285 assert_equal s.scrap_wall_url, s.receiver.wall_url
286 286 end
287 287  
288 288 should 'create activity with reply_scrap_on_self when top_root scrap receiver is the same as sender' do
289   - s, r = fast_create(Person), fast_create(Person)
  289 + s, r = create_user.person, create_user.person
290 290 root = fast_create(Scrap, :sender_id => s.id, :receiver_id => r.id)
291 291 assert_difference 'ActionTracker::Record.count', 1 do
292 292 reply = create(Scrap, :sender => r, :receiver => s, :scrap_id => root.id, :content => 'sample')
... ...