lentil 0.5.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fc8b593e81dc92d835ecb8376fb7d5483c1e8bbe
4
- data.tar.gz: 3695ab310995d17e570cb4ca4335e1f3242f734b
3
+ metadata.gz: d0071e0e9cac7e3e22897146471625cdc522ca8b
4
+ data.tar.gz: d25b8819f50541f248855b0ac6584bad2ce256d7
5
5
  SHA512:
6
- metadata.gz: 50d9a3f4ad056eefbd00e63dc9635a733f0af428345d5282eb06de0177f43d93a35a9134be387e0171ec779fc8272055a12fbc6b86ff3a19b3f11ba9397f4db8
7
- data.tar.gz: ff2ae62d71a0dc740e012166339b3a7be550e290bd881680601f38eace29d8c85c7c1e3e91e753d7cf00ec9b212d0fa6e23f4b1725a3a93fe949db62117fef8d
6
+ metadata.gz: b6fd1f6e993cfa866b1448ba22e0a07a7f5750cc3a527d1a9a2b247c39fcdb324ae97fb177ad4cb4f7a91f0f61cdac0f81a2e12e5ee230920f1adabed2977358
7
+ data.tar.gz: 878f9f2cbadd5fb71b9804c07d2235a90390c13c126086b6cecca2dd6cdbd09992c426e680280bd554485c7b8c62a403b006c757583056a9fb2fdbd1faaa0b89
data/README.md CHANGED
@@ -17,14 +17,18 @@ Although we are using this gem in production, **this gem should be considered an
17
17
 
18
18
  lentil has been tested under Ruby 1.9.3 through 2.2.0.
19
19
 
20
+ > We are currently warning against using MySQL due to issues when encoding emoji. PostgreSQL is preferred, but if this is not an option, you may want to follow [this guide](http://tech.taskrabbit.com/blog/2014/04/24/active-record-mysql-and-emoji/).
21
+
20
22
  ### Create a new Rails app with Rails 3.2.x
21
23
 
22
24
  ```sh
23
- rails new your_app_name
25
+ gem install rails -v '~> 3.2'
26
+ rails _3.2.22_ new your_app_name
24
27
  cd your_app_name
25
28
  ```
29
+ > In the example above, `3.2.22` should be the version of Rails 3.x that is installed by the `gem` command.
26
30
 
27
- ### Add lentil and therubyracer (or another ExecJS runtime) to your Gemfile and `bundle`
31
+ ### Add lentil and therubyracer (or another ExecJS runtime) to your Gemfile and run `bundle update`
28
32
 
29
33
  ```ruby
30
34
  gem 'lentil'
@@ -18,7 +18,7 @@ function listenforpopstate() {
18
18
  // and this doesn't look like an image url
19
19
  // switch to page that matches the url
20
20
  if (!/images\/[0-9]/.test(window.location.pathname)) {
21
- window.location.href = window.location.pathname;
21
+ window.location.href = window.location.pathname;
22
22
  }
23
23
  } else {
24
24
 
@@ -26,7 +26,7 @@ function listenforpopstate() {
26
26
  // but the url looks like an image url
27
27
  // switch to the image page that matches the url
28
28
  if (/images\/[0-9]/.test(window.location.pathname)) {
29
- window.location.href = window.location.pathname;
29
+ window.location.href = window.location.pathname;
30
30
  }
31
31
  }
32
32
  };
@@ -45,28 +45,28 @@ function pushimageurl() {
45
45
  replacementUrl = replacementUrl.replace("//","/");
46
46
  }
47
47
 
48
- // push the url for the displayed image to the browser
49
- window.history.pushState(null, null, replacementUrl);
50
-
51
- Lentil.ga_track(['_trackPageview', replacementUrl]);
52
-
53
- // listen for popstate (back/forward button)
54
- window.onpopstate = function(){
55
- if (/images\/[0-9]/.test(window.location.pathname)) {
56
- // if this url looks like an image show url then switch
57
- // the browser to the displayed url
58
- window.location.href = window.location.pathname;
59
- } else {
60
- // otherwise switch the popcalled state to true
61
- // and close the fancybox
62
- FancyBoxCloseFunctionState.popcalled = true;
63
- $.fancybox.close();
64
- // switch the popcalled flag to false
65
- // and the fancybox visible flag to false
66
- FancyBoxCloseFunctionState.popcalled = false;
67
- FancyBoxCloseFunctionState.fancyboxvisible = false;
68
- }
69
- };
48
+ // push the url for the displayed image to the browser
49
+ window.history.pushState(null, null, replacementUrl);
50
+
51
+ Lentil.ga_track(['_trackPageview', replacementUrl]);
52
+
53
+ // listen for popstate (back/forward button)
54
+ window.onpopstate = function(){
55
+ if (/images\/[0-9]/.test(window.location.pathname)) {
56
+ // if this url looks like an image show url then switch
57
+ // the browser to the displayed url
58
+ window.location.href = window.location.pathname;
59
+ } else {
60
+ // otherwise switch the popcalled state to true
61
+ // and close the fancybox
62
+ FancyBoxCloseFunctionState.popcalled = true;
63
+ $.fancybox.close();
64
+ // switch the popcalled flag to false
65
+ // and the fancybox visible flag to false
66
+ FancyBoxCloseFunctionState.popcalled = false;
67
+ FancyBoxCloseFunctionState.fancyboxvisible = false;
68
+ }
69
+ };
70
70
  }
71
71
 
72
72
  function addfancybox() {
@@ -78,42 +78,38 @@ function addfancybox() {
78
78
  prevEffect : 'none',
79
79
  live : true,
80
80
  loop : false,
81
- minWidth : '250px',
81
+ autoSize : true,
82
+ fitToView: true,
83
+ minWidth : 250,
84
+ scrolling : 'no',
82
85
  type: 'html',
83
86
  helpers : {
84
87
  title : { type : 'inside' },
85
88
  overlay : { locked : false }
86
89
  },
87
90
  aspectRatio : true,
88
- afterLoad: function(current, previous) {
91
+ beforeLoad: function() {
92
+ var img = $(this.element).children(".instagram-img");
89
93
 
90
- // pushing base url so that back/close returns to image gallery
91
- // instead of image show
92
- window.history.pushState(null,null,FancyBoxCloseFunctionState.pathname);
94
+ if($(img).attr("data-media-type") === "video") {
95
+ this.content = '<video class="fancybox-video" controls="controls" height="100%" width="100%" src="' + this.href + '" oncanplay="$.fancybox.update()"></video>';
96
+ } else {
97
+ this.content = '<img class="fancybox-img" src="' + this.href + '" onload="$.fancybox.update()"/>';
98
+ }
99
+ return true;
100
+ },
101
+ afterLoad: function(current, previous) {
102
+ // pushing base url so that back/close returns to image gallery
103
+ // instead of image show
104
+ window.history.pushState(null,null,FancyBoxCloseFunctionState.pathname);
93
105
  },
94
106
  beforeShow : function() {
95
- var img = $(this.element).children(".instagram-img");
96
- if($(img).attr("data-media-type") === "video") {
97
- var video_url = $(img).attr("src");
98
- //this.content = "<video src='" + video_url + "' height='320' width='320' controls='controls'></video>";
99
- $(".fancybox-inner").html('<video controls="controls" height="100%" width="90%" src="' + video_url + '"></video>');
100
- var vid = $(".fancybox-inner").children("video")[0];
101
- vid.oncanplay = function() {
102
- $.fancybox.reposition();
103
- }
104
- }
105
- else {
106
- var image_url = $(img).attr("src");
107
- $(".fancybox-inner").html('<img class="fancybox-image" src="' + image_url + '" />');
108
- }
109
-
110
107
  this.title = $(this.element).next(".text-overlay").html();
111
108
  imageId = $(this.element).parents("div").attr("id");
112
109
  $(".fancybox-wrap").attr('id', imageId);
113
110
  pushimageurl(imageId);
114
111
  },
115
112
  afterShow : function() {
116
-
117
113
  // checks whether browser understands touch events
118
114
  // if so the next/prev buttons are disabled
119
115
  // and swipe down/right is added to advance slides
@@ -130,9 +126,6 @@ function addfancybox() {
130
126
  });
131
127
  }
132
128
 
133
- // adds button handling script to displayed fancybox buttons
134
- buttonhandler();
135
-
136
129
  // this is to check that the fancybox is really visible
137
130
  // afterClose is fired off on fancybox open -- a bug
138
131
  FancyBoxCloseFunctionState.fancyboxvisible = true;
@@ -155,14 +148,14 @@ function addfancybox() {
155
148
  afterClose : function() {
156
149
  if (FancyBoxCloseFunctionState.popcalled === false && FancyBoxCloseFunctionState.fancyboxvisible === true) {
157
150
 
158
- // if after closing the fancybox there is no pop event
159
- // and the fancybox is visible
160
- // (this afterClose event also fires when fancybox opens
161
- // -- a bug we're getting around with this hack)
162
- // switch the flags and point the url at the previous page
163
- // should be an image tile view (recent, popular, staff picks, etc.)
164
- FancyBoxCloseFunctionState.fancyboxvisible = false;
165
- window.history.back();
151
+ // if after closing the fancybox there is no pop event
152
+ // and the fancybox is visible
153
+ // (this afterClose event also fires when fancybox opens
154
+ // -- a bug we're getting around with this hack)
155
+ // switch the flags and point the url at the previous page
156
+ // should be an image tile view (recent, popular, staff picks, etc.)
157
+ FancyBoxCloseFunctionState.fancyboxvisible = false;
158
+ window.history.back();
166
159
  }
167
160
  }
168
161
  });
@@ -1,6 +1,6 @@
1
1
  function buttonhandler() {
2
2
 
3
- $(".like-btn, .flag-confirm").click(function(e) {
3
+ $("body").on("click", ".like-btn, .flag-confirm", function(e) {
4
4
  button = $(this);
5
5
  imageId = $(".fancybox-wrap, .image-show").attr("id");
6
6
  if (!$(button).is(".already-clicked")) {
@@ -20,4 +20,4 @@ function buttonhandler() {
20
20
  }
21
21
  e.preventDefault();
22
22
  });
23
- }
23
+ }
@@ -1,5 +1,5 @@
1
1
  function addimageerrors() {
2
- $(".instagram-img, .battle-img, .fancybox-img").off("error").on("error", function () {
2
+ $(".instagram-img, .battle-img, .fancybox-img, .fancybox-video").off("error").on("error", function () {
3
3
  $(this).parents("div.image-tile, li.image-animate-tile").remove();
4
4
  /*if ($("body.images_animate") || $("body.images_staff_picks_animate")) {
5
5
  addanimatedimages();
@@ -140,6 +140,14 @@ div.images {
140
140
  border-radius: 3px;
141
141
  }
142
142
 
143
+ .fancybox-inner {
144
+ min-width: 250px;
145
+ }
146
+
147
+ .fancybox-nav {
148
+ height:90%;
149
+ }
150
+
143
151
  .pagination .disabled, .pagination .current {
144
152
  color: #000;
145
153
  }
@@ -312,4 +320,4 @@ body.lt-ie8 {
312
320
 
313
321
  body.lt-ie8 div.image-tile {
314
322
  width: 300px;
315
- }
323
+ }
@@ -29,7 +29,7 @@
29
29
  .side-filler { width: fluid(0); }
30
30
 
31
31
  ul {
32
- margin-top: 30px;
32
+ margin-top: 25px;
33
33
  }
34
34
 
35
35
  .navbar .library-brand {
@@ -219,4 +219,4 @@
219
219
 
220
220
  @include breakpoint(124, $label: 'microtile'){
221
221
  .image-tile { width: fluid(8); }
222
- }
222
+ }
@@ -38,7 +38,7 @@ class Lentil::Image < ActiveRecord::Base
38
38
  :do_not_request_donation, :donor_agreement_rejected, :media_type, :video_url, :suppressed
39
39
 
40
40
  attr_protected :original_metadata
41
-
41
+
42
42
  has_many :won_battles, :class_name => "Battle"
43
43
  has_many :losers, :through => :battles
44
44
  has_many :lost_battles, :class_name => "Battle", :foreign_key => "loser_id"
@@ -97,8 +97,8 @@ class Lentil::Image < ActiveRecord::Base
97
97
 
98
98
  def service_tags
99
99
  begin
100
- tag_ids = self.taggings.where(:staff_tag => false).pluck(:tag_id)
101
- tags = Lentil::Tag.find(tag_ids).sort_by(&:name)
100
+ tag_ids = self.taggings.select { |tagging| tagging.staff_tag == false }.map(&:tag_id)
101
+ tags = self.tags.select { |tag| tag_ids.include? tag.id}.sort_by(&:name)
102
102
  rescue
103
103
  Rails.logger.error "Error retrieving service_tags"
104
104
  tags = []
@@ -107,31 +107,19 @@ class Lentil::Image < ActiveRecord::Base
107
107
 
108
108
  def staff_tags
109
109
  begin
110
- tag_ids = self.taggings.where(:staff_tag => true).pluck(:tag_id)
111
- tags = Lentil::Tag.find(tag_ids).sort_by(&:name)
110
+ tag_ids = self.taggings.select { |tagging| tagging.staff_tag == true }.map(&:tag_id)
111
+ tags = self.tags.select { |tag| tag_ids.include? tag.id}.sort_by(&:name)
112
112
  rescue
113
113
  Rails.logger.error "Error retrieving staff_tags"
114
114
  tags = []
115
115
  end
116
116
  end
117
117
 
118
- def available_staff_tags
119
- begin
120
- system_tag_ids = self.taggings.where(:staff_tag => false).pluck(:tag_id)
121
- rescue
122
- Rails.logger.error "Error retrieving staff_tags"
123
- tags = []
124
- else
125
- tags = []
126
- Lentil::Tag.all.each do |tag|
127
- unless system_tag_ids.include? tag.id
128
- tags.push(tag)
129
- end
130
- end
131
-
132
- if tags.length > 0
133
- tags = tags.sort_by(&:name)
134
- end
118
+ def available_staff_tags(all_tags)
119
+ tags = all_tags - (self.tags - self.staff_tags)
120
+
121
+ if tags.length > 0
122
+ tags = tags.sort_by(&:name)
135
123
  end
136
124
  end
137
125
 
@@ -189,7 +177,6 @@ class Lentil::Image < ActiveRecord::Base
189
177
  }
190
178
 
191
179
  state_machine :state, :initial => :pending do
192
-
193
180
  States.each do |name, value|
194
181
  state name, :value => value
195
182
  end
@@ -201,9 +188,8 @@ class Lentil::Image < ActiveRecord::Base
201
188
  event :reject do
202
189
  transition all => :rejected
203
190
  end
204
-
205
191
  end
206
-
192
+
207
193
  def original_metadata=(meta)
208
194
  write_attribute(:original_metadata, meta.to_hash)
209
195
  end
@@ -20,7 +20,9 @@ class Lentil::Tag < ActiveRecord::Base
20
20
  validates_presence_of :name
21
21
 
22
22
  scope :harvestable, where(:lentil_tagsets => {:harvest => true}).includes(:tagsets)
23
-
23
+ scope :not_harvestable, where(:lentil_tagsets => {:harvest => false}).includes(:tagsets)
24
+ scope :no_tagsets, where(:lentil_tagset_assignments => {:tag_id => nil}).includes(:tagset_assignments)
25
+
24
26
  #Stripping tags on write
25
27
  def name=(new_name)
26
28
  write_attribute(:name, new_name.sub(/^#/, ''))
@@ -6,6 +6,7 @@
6
6
  <th>Description</th>
7
7
  <th>Username</th>
8
8
  <th>Service Tags</th>
9
+ <th>Harvesting Tags</th>
9
10
  <th>Staff Tags</th>
10
11
  <th>Staff Like</th>
11
12
  <th>DNR</th>
@@ -31,8 +32,16 @@
31
32
  <td><%= image.service_tags.map{|tag| tag.name}.join(' | ') %>
32
33
  <%= f.input "service_tags", :as => :hidden, :collection => image.service_tags, :wrapper_html => {:style => "list-style: none"} %>
33
34
  </td>
35
+ <td><%= image.service_tags.select{|tag| @harvestable_tag_ids.include? tag.id}.map{|tag| tag.name}.join(' | ') %></td>
34
36
  <td class="moderation_tag">
35
- <%= f.input :tags, :label => false, :as => :select, :collection => image.available_staff_tags, :input_html => {:multiple => true, :class => "chzn-select", :'data-placeholder' => 'Select Tag', :style => "width:190px" }%>
37
+ <% if defined? @tags %>
38
+ <%= f.input :tags, :label => false, :as => :select, :collection => image.available_staff_tags(@tags), :input_html => {:multiple => true, :class => "chzn-select", :'data-placeholder' => 'Select Tag', :style => "width:190px" }%>
39
+ <% else %>
40
+ <% if image.staff_tags.length > 0 %>
41
+ <p><%= image.staff_tags.map{|tag| tag.name}.join(' | ') %></p>
42
+ <% end %>
43
+ <%= link_to('Edit Staff Tags', update_image_admin_lentil_image_path(image)) %>
44
+ <% end %>
36
45
  </td>
37
46
  <td><%= f.input :staff_like, :label => "Staff Like", :wrapper_html => { :class => "moderation_checkbox" } %></td>
38
47
  <td><%= f.input :do_not_request_donation, :label => "Don't request donation", :wrapper_html => { :class => "moderation_checkbox" } %></td>
@@ -7,6 +7,7 @@
7
7
  <th>Description</th>
8
8
  <th>Username</th>
9
9
  <th>All Tags</th>
10
+ <th>Harvesting Tags</th>
10
11
  <th>Moderator</th>
11
12
  <th>Status</th>
12
13
  </tr>
@@ -19,6 +20,7 @@
19
20
  <td><%= image.description %></td>
20
21
  <td><%= image.user.user_name %></td>
21
22
  <td><%= image.tags.map{|tag| tag.name}.join(' | ') %></td>
23
+ <td><%= image.service_tags.select{|tag| @harvestable_tag_ids.include? tag.id}.map{|tag| tag.name}.join(' | ') %></td>
22
24
  <td><%= image.moderator.email if image.moderator %></td>
23
25
  <td><%= image.state_name %></td>
24
26
  <% end -%>
@@ -30,4 +32,4 @@
30
32
  <div class="blank_slate_container">
31
33
  <span class="blank_slate">No Flagging History Found</span>
32
34
  </div>
33
- <% end -%>
35
+ <% end -%>
@@ -0,0 +1,14 @@
1
+ <table class="index_table">
2
+ <thead>
3
+ <tr>
4
+ <th>Stat Name</th>
5
+ <th>Value</th>
6
+ </tr>
7
+ </thead>
8
+ <% @stats.each do |stat| %>
9
+ <tr class=>
10
+ <td><%= stat[:name] %></td>
11
+ <td><%= stat[:value] %></td>
12
+ </tr>
13
+ <% end -%>
14
+ </table>
@@ -1,18 +1,20 @@
1
- <div class="images">
2
- <% @images.each do |image| %>
1
+ <div class="images">
2
+ <% @images.each do |image| %>
3
3
  <div id="image_<%= image.id %>" class="grid__cell image-tile">
4
- <%= link_to url_for(image), 'data-fancybox-href' => image.video_url, 'data-fancybox-group' => "image-tile-gallery", :class => :fancybox do %>
5
- <% unless image.media_type == "video" %>
6
- <%= image_tag(image.jpeg, :class => "instagram-img " + image.id.to_s, :alt => image.description, :data => {:battles_count => image.battles_count, :win_pct => image.win_pct, :popularity => image.popular_score, :staff_like => image.staff_like, :like_votes_count => image.like_votes_count, :media_type => image.media_type}) %>
4
+ <% unless image.media_type == "video" %>
5
+ <%= link_to url_for(image), 'data-fancybox-href' => image.jpeg, 'data-fancybox-group' => "image-tile-gallery", :class => :fancybox do %>
6
+ <%= image_tag(image.jpeg, :class => "instagram-img " + image.id.to_s, :alt => image.description, :data => {:battles_count => image.battles_count, :win_pct => image.win_pct, :popularity => image.popular_score, :staff_like => image.staff_like, :like_votes_count => image.like_votes_count, :media_type => image.media_type}) %>
7
+ <% end %>
7
8
  <% else %>
8
- <%= video_tag(image.video_url, :autoplay => "true", :muted => "true", :loop => "true", :class => "instagram-img " + image.id.to_s, :height => "100%", :width => "100%", :poster => image.jpeg, :data => {:battles_count => image.battles_count, :win_pct => image.win_pct, :popularity => image.popular_score, :staff_like => image.staff_like, :like_votes_count => image.like_votes_count, :media_type => image.media_type}) %>
9
+ <%= link_to url_for(image), 'data-fancybox-href' => image.video_url, 'data-fancybox-group' => "image-tile-gallery", :class => :fancybox do %>
10
+ <%= video_tag(image.video_url, :autoplay => "true", :muted => "true", :loop => "true", :class => "instagram-img-" + image.id.to_s, :class => "instagram-img " + image.id.to_s, :height => "100%", :width => "100%", :poster => image.jpeg, :data => {:battles_count => image.battles_count, :win_pct => image.win_pct, :popularity => image.popular_score, :staff_like => image.staff_like, :like_votes_count => image.like_votes_count, :media_type => image.media_type}) %>
11
+ <% end %>
9
12
  <% end %>
10
- <% end %>
11
13
 
12
- <%= render "/layouts/lentil/image_popup", :image => image %>
13
- <% if params[:controller] == "lentil/thisorthat" %>
14
- <div class="battle-leader-overlay"><%= number_to_percentage(image.win_pct, :precision => 0) %></div>
15
- <% end -%>
14
+ <%= render "/layouts/lentil/image_popup", :image => image %>
15
+ <% if params[:controller] == "lentil/thisorthat" %>
16
+ <div class="battle-leader-overlay"><%= number_to_percentage(image.win_pct, :precision => 0) %></div>
17
+ <% end -%>
16
18
  </div>
17
- <% end -%>
18
- </div>
19
+ <% end -%>
20
+ </div>
@@ -4,10 +4,11 @@
4
4
  <div class="battle-image-wrap grid__cell">
5
5
  <%= semantic_fields_for "image[#{image.id}]", image do |f| %>
6
6
  <div id="image_<%= image.id %>" class="battle-image-tile">
7
- <a href="<%= url_for(image) %>" data-fancybox-href= "<%= image.jpeg %>" class="fancybox">
8
7
  <% unless image.media_type == "video" %>
8
+ <a href="<%= url_for(image) %>" data-fancybox-href= "<%= image.jpeg %>" class="fancybox">
9
9
  <%= image_tag(image.jpeg, :class => "battle-img instagram-img", :data => {:battles_count => image.battles_count, :win_pct => image.win_pct, :popularity => image.popular_score, :staff_like => image.staff_like, :like_votes_count => image.like_votes_count, :media_type => image.media_type}) %>
10
10
  <% else %>
11
+ <a href="<%= url_for(image) %>" data-fancybox-href= "<%= image.video_url %>" class="fancybox">
11
12
  <%= video_tag(image.video_url, :class => "instagram-img " + image.id.to_s, :height => "100%", :width => "100%", :poster => image.jpeg, :controls => "controls", :data => {:battles_count => image.battles_count, :win_pct => image.win_pct, :popularity => image.popular_score, :staff_like => image.staff_like, :like_votes_count => image.like_votes_count, :media_type => image.media_type}) %>
12
13
  <% end %>
13
14
  <div class="battle-image-desc trunc-small"><div class="battle-image-inner-desc"><%= truncate(image.description, :length => 35) %></div></div>
@@ -28,10 +29,11 @@
28
29
  <% @prev_images.each do |image| %>
29
30
  <div class="battle-image-wrap grid__cell" style="background:#e6e6e6">
30
31
  <div id="image_<%= image.id %>" class="battle-image-tile">
31
- <a href="<%= url_for(image) %>" data-fancybox-href= "<%= image.jpeg %>" class="fancybox">
32
32
  <% unless image.media_type == "video" %>
33
+ <a href="<%= url_for(image) %>" data-fancybox-href= "<%= image.jpeg %>" class="fancybox">
33
34
  <%= image_tag(image.jpeg, :class => "battle-img instagram-img", :data => {:battles_count => image.battles_count, :win_pct => image.win_pct, :popularity => image.popular_score, :staff_like => image.staff_like, :like_votes_count => image.like_votes_count, :media_type => image.media_type}) %>
34
35
  <% else %>
36
+ <a href="<%= url_for(image) %>" data-fancybox-href= "<%= image.video_url %>" class="fancybox">
35
37
  <%= video_tag(image.video_url, :class => "instagram-img " + image.id.to_s, :height => "100%", :width => "100%", :poster => image.jpeg, :controls => "controls", :data => {:battles_count => image.battles_count, :win_pct => image.win_pct, :popularity => image.popular_score, :staff_like => image.staff_like, :like_votes_count => image.like_votes_count, :media_type => image.media_type}) %>
36
38
  <% end %>
37
39
  <div class="battle-image-desc trunc-small"><div class="battle-image-inner-desc"><%= truncate(image.description, :length => 35) %></div></div>
@@ -14,4 +14,4 @@ if defined?(ActiveAdmin)
14
14
  column :updated_at
15
15
  end
16
16
  end
17
- end
17
+ end
@@ -2,10 +2,41 @@ if defined?(ActiveAdmin)
2
2
  ActiveAdmin.register Lentil::Image do
3
3
  actions :index, :show
4
4
 
5
- config.batch_actions = false
5
+ config.batch_actions = true
6
6
  config.per_page = 10
7
7
 
8
- filter :state, :as => :select, :collection => proc { Lentil::Image::States }
8
+ batch_action :destroy, false
9
+
10
+ batch_action :approve_all do |ids|
11
+ images = Lentil::Image.where(id: ids)
12
+ total_images = images.size
13
+ image_counter = 0
14
+ errors = []
15
+
16
+ images.each do |image|
17
+ second_moderation = true
18
+ unless image.moderator_id.nil?
19
+ second_moderation = false
20
+ end
21
+
22
+ begin
23
+ image.update_attributes!(:state => 1, :moderator => current_admin_user, :moderated_at => DateTime.now,
24
+ :second_moderation => second_moderation)
25
+ rescue Exception => e
26
+ errors << "image_id #{image.id}: #{e.message}"
27
+ next
28
+ end
29
+
30
+ image_counter += 1
31
+ end
32
+
33
+ if errors.length > 0
34
+ redirect_to collection_path, notice: "#{image_counter} #{'Image'.pluralize(image_counter)} approved (out of #{total_images})", alert: errors.join('<br>').html_safe
35
+ else
36
+ redirect_to collection_path, notice: "#{image_counter} #{'Image'.pluralize(image_counter)} approved (out of #{total_images})"
37
+ end
38
+ end
39
+
9
40
  filter :suppressed
10
41
  filter :media_type, :as => :select
11
42
  filter :user_user_name, :as => :string, :label => "Username"
@@ -22,16 +53,40 @@ if defined?(ActiveAdmin)
22
53
  filter :url, :label => "Service URL"
23
54
  filter :id
24
55
 
56
+ scope :all
57
+ scope :new, :default => true do |images|
58
+ images.where(:state => Lentil::Image::States[:pending])
59
+ end
60
+ scope :approved do |images|
61
+ images.where(:state => Lentil::Image::States[:approved])
62
+ end
63
+ scope :rejected do |images|
64
+ images.where(:state => Lentil::Image::States[:rejected])
65
+ end
66
+ scope :skipped do |images|
67
+ images.where(:state => Lentil::Image::States[:pending]).where("moderator_id IS NOT NULL")
68
+ end
69
+ # scope :flagged do |images|
70
+ # # images.where(:state => Lentil::Image::States[:pending]).where("moderator_id IS NOT NULL")
71
+ # images.includes(:user, :tags, :taggings, :flags).joins(:flags).where(:second_moderation => false).uniq.all
72
+ # end
73
+
25
74
  action_item :only => :show do
26
75
  link_to('Update Image', update_image_admin_lentil_image_path(lentil_image))
27
76
  end
28
77
  action_item { link_to "Moderate New", moderate_admin_lentil_images_path }
29
78
  action_item { link_to "Moderate Skipped", moderate_skipped_admin_lentil_images_path }
30
79
  action_item { link_to "Moderate Flagged", moderate_flagged_admin_lentil_images_path }
80
+ action_item { link_to "Moderate Approved", moderate_approved_admin_lentil_images_path }
81
+ action_item { link_to "Moderate Rejected", moderate_rejected_admin_lentil_images_path }
31
82
  action_item { link_to "Flagging History", flagging_history_admin_lentil_images_path }
32
83
  action_item { link_to "Add Instagram Image", manual_input_admin_lentil_images_path }
33
84
 
34
85
  index do
86
+ harvestable_tag_ids = Lentil::Tag.harvestable.map(&:id)
87
+ if current_scope.name == 'New'
88
+ selectable_column
89
+ end
35
90
  column "Image" do |image|
36
91
  unless image.media_type == "video"
37
92
  link_to(image_tag(image.image_url, :class => "moderation_thumbnail"), admin_lentil_image_path(image))
@@ -50,6 +105,9 @@ if defined?(ActiveAdmin)
50
105
  column "All Tags" do |image|
51
106
  image.tags.map{|tag| tag.name}.join(' | ')
52
107
  end
108
+ column "Harvesting Tags" do |image|
109
+ image.service_tags.select{|tag| harvestable_tag_ids.include? tag.id}.map{|tag| tag.name}.join(' | ')
110
+ end
53
111
  column "Likes", :like_votes_count
54
112
  column :staff_like
55
113
  column "Battles", :battles_count, :sortable => false
@@ -68,6 +126,7 @@ if defined?(ActiveAdmin)
68
126
  end
69
127
 
70
128
  show :title => :id do |image|
129
+ harvestable_tag_ids = Lentil::Tag.harvestable.map(&:id)
71
130
  attributes_table do
72
131
  row :id
73
132
  row :description
@@ -90,6 +149,13 @@ if defined?(ActiveAdmin)
90
149
  "Image has not been tagged."
91
150
  end
92
151
  end
152
+ row "Harvesting Tags" do |image|
153
+ unless image.service_tags.select{|tag| harvestable_tag_ids.include? tag.id}.empty?
154
+ image.service_tags.select{|tag| harvestable_tag_ids.include? tag.id}.map{|tag| tag.name}.join(' | ')
155
+ else
156
+ "Image has no harvesting tags."
157
+ end
158
+ end
93
159
  row :staff_like
94
160
  row :do_not_request_donation
95
161
  row :donor_agreement_submitted_date
@@ -99,51 +165,88 @@ if defined?(ActiveAdmin)
99
165
  image.state_name
100
166
  end
101
167
  row :image do
102
- unless image.media_type == "video"
103
- link_to(image_tag(image.image_url), admin_lentil_image_path(image))
104
- else
105
- video_tag(image.video_url, controls: true, size: "640x640")
106
- end
168
+ unless image.media_type == "video"
169
+ link_to(image_tag(image.image_url), admin_lentil_image_path(image))
170
+ else
171
+ video_tag(image.video_url, controls: true, size: "640x640")
172
+ end
107
173
  end
108
174
  end
109
175
  active_admin_comments
110
176
  end
111
177
 
112
178
  controller do
179
+ def scoped_collection
180
+ super.includes :user, :taggings, :tags
181
+ end
182
+
183
+ # TODO: This method may need optimization
113
184
  def update_images(images, images_params, second_moderation)
185
+ total_images = images.size
186
+ image_counter = 0
187
+ errors = []
188
+
114
189
  images.each do |image|
115
190
  image_params = images_params[image.id.to_s]
116
191
 
117
- incoming_tag_ids = image_params['tag_ids'].reject(&:empty?)
118
- existing_tag_ids = []
119
- service_tag_ids = []
192
+ if image_params.key?(:tag_ids)
193
+ incoming_tag_ids = image_params['tag_ids'].reject(&:empty?)
194
+ existing_tag_ids = []
195
+ service_tag_ids = []
120
196
 
121
- image.taggings.each do |tagging|
122
- existing_tag_ids << tagging[:tag_id]
123
- if tagging[:staff_tag] == false
124
- service_tag_ids << tagging[:tag_id]
197
+ image.taggings.each do |tagging|
198
+ existing_tag_ids << tagging[:tag_id]
199
+ if tagging[:staff_tag] == false
200
+ service_tag_ids << tagging[:tag_id]
201
+ end
125
202
  end
126
- end
127
203
 
128
- new_tag_ids = incoming_tag_ids - existing_tag_ids
129
- tag_ids_to_keep = incoming_tag_ids - new_tag_ids + service_tag_ids
204
+ new_tag_ids = incoming_tag_ids - existing_tag_ids
205
+ tag_ids_to_keep = incoming_tag_ids - new_tag_ids + service_tag_ids
130
206
 
131
- new_taggings = []
132
- new_tag_ids.each do |id|
133
- new_taggings << image.taggings.build(:tag_id => id, :staff_tag => true)
207
+ new_taggings = []
208
+ new_tag_ids.each do |id|
209
+ new_taggings << image.taggings.build(:tag_id => id, :staff_tag => true)
210
+ end
211
+
212
+ taggings_to_keep = image.taggings.select{ |tagging| tag_ids_to_keep.include? tagging.tag_id}
213
+ taggings = new_taggings + taggings_to_keep
214
+
215
+ # Save Updated Image with new tags
216
+ begin
217
+ image.update_attributes!(:state => image_params['state'], :taggings => taggings, :staff_like => image_params['staff_like'],
218
+ :moderator => current_admin_user, :moderated_at => DateTime.now, :second_moderation => second_moderation,
219
+ :do_not_request_donation => image_params['do_not_request_donation'], :suppressed => image_params['suppressed'])
220
+ rescue Exception => e
221
+ errors << "image_id #{image.id}: #{e.message}"
222
+ next
223
+ end
224
+ else
225
+ # Save Updated Image with same tags
226
+ begin
227
+ image.update_attributes!(:state => image_params['state'], :staff_like => image_params['staff_like'],
228
+ :moderator => current_admin_user, :moderated_at => DateTime.now, :second_moderation => second_moderation,
229
+ :do_not_request_donation => image_params['do_not_request_donation'], :suppressed => image_params['suppressed'])
230
+ rescue Exception => e
231
+ errors << "image_id #{image.id}: #{e.message}"
232
+ next
233
+ end
134
234
  end
135
235
 
136
- taggings_to_keep = image.taggings.where(:tag_id => tag_ids_to_keep)
137
- taggings = new_taggings + taggings_to_keep
236
+ image_counter += 1
237
+ end
138
238
 
139
- image.update_attributes!(:state => image_params['state'], :taggings => taggings, :staff_like => image_params['staff_like'],
140
- :moderator => current_admin_user, :moderated_at => DateTime.now, :second_moderation => second_moderation,
141
- :do_not_request_donation => image_params['do_not_request_donation'], :suppressed => image_params['suppressed'])
239
+ if errors.length > 0
240
+ redirect_to :back, notice: "#{image_counter} #{'Image'.pluralize(image_counter)} moderated (out of #{total_images})", alert: errors.join('<br>').html_safe
241
+ else
242
+ redirect_to :back, notice: "#{image_counter} #{'Image'.pluralize(image_counter)} moderated (out of #{total_images})"
142
243
  end
143
244
  end
144
245
  end
145
246
 
146
247
  member_action :update_image do
248
+ @tags = Lentil::Tag.all
249
+ @harvestable_tag_ids = Lentil::Tag.harvestable.map(&:id)
147
250
  id = params['id']
148
251
  @second_moderation = false
149
252
  @images = Lentil::Image.where(id: id)
@@ -151,42 +254,51 @@ if defined?(ActiveAdmin)
151
254
  end
152
255
 
153
256
  collection_action :moderate do
257
+ @harvestable_tag_ids = Lentil::Tag.harvestable.map(&:id)
154
258
  @second_moderation = false
155
- @images = Lentil::Image.where(state: Lentil::Image::States[:pending], moderator_id: nil).paginate(:page => params[:page], :per_page => 10)
259
+ @images = Lentil::Image.includes(:user, :taggings, :tags).where(state: Lentil::Image::States[:pending], moderator_id: nil).paginate(:page => params[:page], :per_page => 10)
260
+ end
261
+
262
+ collection_action :moderate_approved do
263
+ @harvestable_tag_ids = Lentil::Tag.harvestable.map(&:id)
264
+ @second_moderation = false
265
+ @images = Lentil::Image.includes(:user, :taggings, :tags).where(state: Lentil::Image::States[:approved]).paginate(:page => params[:page], :per_page => 10)
266
+ render "/admin/lentil_images/moderate"
267
+ end
268
+
269
+ collection_action :moderate_rejected do
270
+ @harvestable_tag_ids = Lentil::Tag.harvestable.map(&:id)
271
+ @second_moderation = false
272
+ @images = Lentil::Image.includes(:user, :taggings, :tags).where(state: Lentil::Image::States[:rejected]).paginate(:page => params[:page], :per_page => 10)
273
+ render "/admin/lentil_images/moderate"
156
274
  end
157
275
 
158
276
  collection_action :moderate_skipped do
277
+ @harvestable_tag_ids = Lentil::Tag.harvestable.map(&:id)
159
278
  @second_moderation = false
160
- @images = Lentil::Image.where(state: Lentil::Image::States[:pending]).where("moderator_id IS NOT NULL").paginate(:page => params[:page], :per_page => 10)
279
+ @images = Lentil::Image.includes(:user, :taggings, :tags).where(state: Lentil::Image::States[:pending]).where("moderator_id IS NOT NULL").paginate(:page => params[:page], :per_page => 10)
161
280
  render "/admin/lentil_images/moderate"
162
281
  end
163
282
 
164
283
  collection_action :moderate_flagged do
284
+ @harvestable_tag_ids = Lentil::Tag.harvestable.map(&:id)
165
285
  @second_moderation = true
166
- @images = Lentil::Image.joins(:flags).group("lentil_images.id").having("count(lentil_flags.id) > 0").where(:second_moderation => false).paginate(:page => params[:page], :per_page => 10)
286
+ temp_images = Lentil::Image.includes(:user, :tags, :taggings, :flags).joins(:flags).where(:second_moderation => false).uniq.all
287
+ @images = Kaminari.paginate_array(temp_images).page(params[:page]).per(10)
167
288
  render "/admin/lentil_images/moderate"
168
289
  end
169
290
 
170
291
  collection_action :do_moderation, :method => :post do
171
- images = Lentil::Image.find(params[:image].keys)
292
+ images = Lentil::Image.find(params[:image].keys, :include => [:user, :taggings, :tags])
172
293
  images_params = params[:image]
173
294
  second_moderation = params[:moderation]['second_moderation']
174
-
175
- begin
176
- update_images(images, images_params, second_moderation)
177
- rescue => e
178
- message = "Error moderating images: " + e.to_s
179
- redirect_to :back, :flash => {:error => message}
180
- else
181
- number_of_images = params['image'].size
182
- plural = 'image'.pluralize(number_of_images)
183
- message = number_of_images.to_s + " " + plural + " moderated."
184
- redirect_to :back, notice: message
185
- end
295
+ update_images(images, images_params, second_moderation)
186
296
  end
187
297
 
188
298
  collection_action :flagging_history do
189
- @images = Lentil::Image.joins(:flags).group("lentil_images.id").having("count(lentil_flags.id) > 0").paginate(:page => params[:page], :per_page => 10)
299
+ @harvestable_tag_ids = Lentil::Tag.harvestable.map(&:id)
300
+ temp_images = Lentil::Image.includes(:user, :tags, :flags, :moderator).joins(:flags).uniq.all
301
+ @images = Kaminari.paginate_array(temp_images).page(params[:page]).per(10)
190
302
  end
191
303
 
192
304
  collection_action :manual_input do
@@ -0,0 +1,34 @@
1
+ ActiveAdmin.register_page "Stats" do
2
+ content do
3
+ render partial: 'stats'
4
+ end
5
+
6
+ controller do
7
+ def index
8
+ stats = []
9
+
10
+ images = Lentil::Image.all
11
+ battles = Lentil::Battle.count
12
+ like_votes = Lentil::LikeVote.count
13
+ users = Lentil::User.count
14
+ tags = Lentil::Tag.count
15
+ taggings = Lentil::Tagging.count
16
+
17
+ submitted_agreements = images.map(&:donor_agreement_submitted_date).compact.count
18
+ rejected_agreements = images.map(&:donor_agreement_rejected).compact.count
19
+ accepted_aggrements = submitted_agreements - rejected_agreements
20
+
21
+ stats << {name: 'Number of Images', value: images.count}
22
+ stats << {name: 'Number of Battles', value: battles}
23
+ stats << {name: 'Number of Like Votes', value: like_votes}
24
+ stats << {name: 'Number of Users', value: users}
25
+ stats << {name: 'Number of Submitted Donor Agreements', value: submitted_agreements}
26
+ stats << {name: 'Number of Accepted Donor Agreements (implicit)', value: accepted_aggrements}
27
+ stats << {name: 'Number of Rejected Donor Agreements (explicit)', value: rejected_agreements}
28
+ stats << {name: 'Number of Unique Tags', value: tags}
29
+ stats << {name: 'Number of Taggings', value: taggings}
30
+
31
+ @stats = stats
32
+ end
33
+ end
34
+ end
@@ -6,13 +6,34 @@ if defined?(ActiveAdmin)
6
6
  config.sort_order = "name_asc"
7
7
 
8
8
  filter :name
9
+ filter :tagsets_title, :as => :string, :label => "Tagsets"
10
+
11
+ scope :all, :default => true
12
+ scope "Harvesting", :harvestable
13
+ scope "Not Harvesting", :not_harvestable
14
+ scope "Not in a Tagset", :no_tagsets
9
15
 
10
16
  index :download_links => false do
17
+ harvestable_ids = Lentil::Tag.harvestable.map(&:id)
18
+
11
19
  column :id
12
20
  column :name
21
+ column "Harvestable" do |tag|
22
+ if harvestable_ids.include?(tag.id)
23
+ "True"
24
+ else
25
+ "False"
26
+ end
27
+ end
13
28
  column "Tagsets" do |tag|
14
29
  tag.tagsets.sort_by(&:title).map{ |t| t.title}.join(' | ')
15
30
  end
16
31
  end
32
+
33
+ controller do
34
+ def scoped_collection
35
+ super.includes :taggings, :tagsets
36
+ end
37
+ end
17
38
  end
18
- end
39
+ end
@@ -6,6 +6,7 @@ if defined?(ActiveAdmin)
6
6
 
7
7
  filter :title
8
8
  filter :description
9
+ filter :tags_name, :collection => proc {Lentil::Tag.all.sort_by(&:name)}, :as => :string, :label => "Tags"
9
10
 
10
11
  scope :all
11
12
  scope :harvesting, :default => true do |tagsets|
@@ -43,9 +44,11 @@ if defined?(ActiveAdmin)
43
44
  f.input :title
44
45
  f.input :description
45
46
  f.input :tags, :input_html => {:class => [:"chzn-select"]}, :collection => Lentil::Tag.all.sort_by(&:name)
46
- f.input :harvest
47
+ f.input :harvest do |harvest|
48
+ harvest.capitalize
49
+ end
47
50
  end
48
51
  f.actions
49
52
  end
50
53
  end
51
- end
54
+ end
@@ -1,3 +1,3 @@
1
1
  module Lentil
2
- VERSION = "0.5.2"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -4,7 +4,6 @@ sqlite: &sqlite
4
4
 
5
5
  mysql: &mysql
6
6
  adapter: mysql2
7
- encoding: utf8
8
7
  username: travis
9
8
  password:
10
9
  database: lentil_<%= Rails.env %>
@@ -20,6 +19,7 @@ defaults: &defaults
20
19
  pool: 5
21
20
  timeout: 5000
22
21
  host: 127.0.0.1
22
+ encoding: utf8
23
23
  <<: *<%= ENV['DB'] || "sqlite" %>
24
24
 
25
25
  development:
@@ -29,4 +29,4 @@ test:
29
29
  <<: *defaults
30
30
 
31
31
  production:
32
- <<: *defaults
32
+ <<: *defaults
@@ -11,6 +11,12 @@ Dummy::Application.configure do
11
11
  config.serve_static_assets = true
12
12
  config.static_cache_control = "public, max-age=3600"
13
13
 
14
+ # Don't fallback to assets pipeline if a precompiled asset is missed
15
+ #config.assets.compile = false
16
+
17
+ # Generate digests for assets URLs
18
+ #config.assets.digest = true
19
+
14
20
  # Log error messages when you accidentally call methods on nil
15
21
  config.whiny_nils = true
16
22
 
@@ -12,10 +12,10 @@ class ImageModalTest < ActionDispatch::IntegrationTest
12
12
  test "should see a modal when clicking on an image" do
13
13
  visit lentil.images_path
14
14
  assert page.has_no_content?('six #hunttesting')
15
- assert page.has_no_selector?('.fancybox-image')
15
+ assert page.has_no_selector?('.fancybox-img')
16
16
  # all('.fancybox').first.click
17
17
  find('.fancybox', match: :first).click
18
18
  assert page.has_content?('six #hunttesting')
19
- assert page.has_selector?('.fancybox-image')
19
+ assert page.has_selector?('.fancybox-img')
20
20
  end
21
21
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lentil
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Casden
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2015-06-18 00:00:00.000000000 Z
14
+ date: 2015-08-26 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rails
@@ -271,14 +271,14 @@ dependencies:
271
271
  requirements:
272
272
  - - "~>"
273
273
  - !ruby/object:Gem::Version
274
- version: 5.0.5
274
+ version: 5.1.0
275
275
  type: :runtime
276
276
  prerelease: false
277
277
  version_requirements: !ruby/object:Gem::Requirement
278
278
  requirements:
279
279
  - - "~>"
280
280
  - !ruby/object:Gem::Version
281
- version: 5.0.5
281
+ version: 5.1.0
282
282
  - !ruby/object:Gem::Dependency
283
283
  name: google-analytics-rails
284
284
  requirement: !ruby/object:Gem::Requirement
@@ -609,6 +609,7 @@ files:
609
609
  - app/views/admin/lentil_images/flagging_history.html.erb
610
610
  - app/views/admin/lentil_images/manual_input.html.erb
611
611
  - app/views/admin/lentil_images/moderate.html.erb
612
+ - app/views/admin/stats/_stats.html.erb
612
613
  - app/views/layouts/lentil/_apple_touch_icons.html.erb
613
614
  - app/views/layouts/lentil/_error.html.erb
614
615
  - app/views/layouts/lentil/_flag_button.html.erb
@@ -703,6 +704,7 @@ files:
703
704
  - lib/lentil/admin/dashboard.rb
704
705
  - lib/lentil/admin/flags.rb
705
706
  - lib/lentil/admin/images.rb
707
+ - lib/lentil/admin/stats.rb
706
708
  - lib/lentil/admin/tags.rb
707
709
  - lib/lentil/admin/tagsets.rb
708
710
  - lib/lentil/admin/user.rb