diff --git a/.gitignore b/.gitignore index d482edc41c..b0abad8970 100644 --- a/.gitignore +++ b/.gitignore @@ -50,10 +50,11 @@ test.db solr/* test/reports/ !config/application.yml +test.sqlite-journal # Ignore NPM node_modules .byebug_history vendor/bundle spec/TEST-Teaspoon-Result.xml yarn.lock -yarn-error.log \ No newline at end of file +yarn-error.log diff --git a/Gemfile b/Gemfile index bb440516ae..7356c62ebb 100644 --- a/Gemfile +++ b/Gemfile @@ -111,7 +111,7 @@ group :test, :development do gem 'phantomjs' gem 'puma', '~> 4.2' gem 'rails-perftest' - gem 'rake', '~> 12.3.3' + gem 'rake', '~> 13.0.1' gem 'rest-client' gem 'rspec' gem 'selenium-webdriver', '~> 3.142.4' diff --git a/Gemfile.lock b/Gemfile.lock index 4dbccdfd1f..14a3710efb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -78,8 +78,7 @@ GEM rack-test (>= 0.6.3) regexp_parser (~> 1.5) xpath (~> 3.2) - childprocess (2.0.0) - rake (< 13.0) + childprocess (1.0.0) chronic (0.10.2) ci_reporter (2.0.0) builder (>= 2.1.2) @@ -108,7 +107,7 @@ GEM term-ansicolor (~> 1.3) thor (>= 0.19.4, < 2.0) tins (~> 1.6) - crass (1.0.4) + crass (1.0.5) declarative (0.0.10) declarative-option (0.1.0) descendants_tracker (0.0.4) @@ -119,11 +118,11 @@ GEM domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) equalizer (0.0.11) - erubi (1.8.0) + erubi (1.9.0) execjs (2.7.0) faraday (0.15.4) multipart-post (>= 1.2, < 3) - ffi (1.11.1) + ffi (1.11.2) ffi-compiler (1.0.1) ffi (>= 1.0.0) rake @@ -202,7 +201,7 @@ GEM http_accept_language (2.1.1) http_parser.rb (0.6.0) httpclient (2.8.3) - i18n (1.6.0) + i18n (1.7.0) concurrent-ruby (~> 1.0) i18n-js (3.3.0) i18n (>= 0.6.6) @@ -243,7 +242,7 @@ GEM rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) ruby_dep (~> 1.2) - loofah (2.2.3) + loofah (2.3.1) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) @@ -268,7 +267,7 @@ GEM mimemagic (0.3.3) mini_mime (1.0.2) mini_portile2 (2.4.0) - minitest (5.12.0) + minitest (5.13.0) minitest-reporters (1.3.8) ansi builder @@ -287,7 +286,7 @@ GEM netrc (0.11.0) nifty-generators (0.4.6) nio4r (2.5.1) - nokogiri (1.10.4) + nokogiri (1.10.5) mini_portile2 (~> 2.4.0) nokogumbo (2.0.1) nokogiri (~> 1.8, >= 1.8.4) @@ -379,8 +378,8 @@ GEM rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.2.0) - loofah (~> 2.2, >= 2.2.2) + rails-html-sanitizer (1.3.0) + loofah (~> 2.3) rails-i18n (5.1.3) i18n (>= 0.7, < 2) railties (>= 5.0, < 6) @@ -394,7 +393,7 @@ GEM rake (>= 0.8.7) thor (>= 0.19.0, < 2.0) rainbow (3.0.0) - rake (12.3.3) + rake (13.0.1) rb-fsevent (0.10.3) rb-inotify (0.10.0) ffi (~> 1.0) @@ -450,9 +449,8 @@ GEM crass (~> 1.0.2) nokogiri (>= 1.8.0) nokogumbo (~> 2.0) - sassc (2.0.1) + sassc (2.2.1) ffi (~> 1.9) - rake sassc-rails (2.1.2) railties (>= 4.0.0) sassc (>= 2.0) @@ -627,7 +625,7 @@ DEPENDENCIES rails-i18n (~> 5.1.3) rails-perftest rails_autolink - rake (~> 12.3.3) + rake (~> 13.0.1) rb-readline rdiscount (~> 2.2, >= 2.2.0.1) recaptcha diff --git a/README.md b/README.md index e23042424a..678e1cd74e 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,18 @@ We recommend you either work in a virtual environment, or on a dual booted syste 1. [Dual Booting](https://www.tecmint.com/install-ubuntu-alongside-with-windows-dual-boot/amp/), [option2](https://askubuntu.com/questions/1031993/how-to-install-ubuntu-18-04-alongside-windows-10), [video guide](https://www.youtube.com/watch?v=qNeJvujdB-0&fbclid=IwAR0APhs89jlNR_ENKbSwrp6TI6P-wxlx-a0My9XBvPNAfwtADZaAXqcKtP4) 2. [Setting up a linux virtual env](https://itsfoss.com/install-linux-in-virtualbox/) +## Redis Installation + +Public Lab uses Redis and may be required for some functionality when running the application locally. +1. Install Redis if you haven't already: + * Using **MacOS**: `brew install redis` + * Using **Linux**: `sudo yum -y install redis` +2. Run Redis server: + * Using **MacOS**: `brew services start redis` + * Using **Linux**: `redis-server` +3. Run SideKiq: `bundle exec sidekiq` +4. If SideKiq started correctly Redis is now configured and working! + ## SSL in Development We, at Public Lab use [openssl](https://github.com/ruby/openssl) gem to provide SSL (Secure Sockets Layer) for the secure connection in the development mode. You can run the https connection on the localhost by following the following steps: @@ -198,6 +210,7 @@ Help improve Public Lab software! * Try out some supportive tasks https://github.com/publiclab/plots2/wiki/Supportive-Tasks * Get involved with our weekly community check-ins. For guidelines: [https://github.com/publiclab/plots2/tree/master/doc/CHECKINS.md ](https://github.com/publiclab/plots2/tree/master/doc/CHECKINS.md) +* You can help us by opening first timers issues or fto. The template for opening an issue can be found https://docs.google.com/document/d/1dO-CAgModEGM5cOaMmcnBh2pEON0hv_rH3P2ou2r1eE/edit ## First Time? diff --git a/app/api/srch/search.rb b/app/api/srch/search.rb index 7c49e6f9d9..d1525929f5 100644 --- a/app/api/srch/search.rb +++ b/app/api/srch/search.rb @@ -103,7 +103,7 @@ class Search < Grape::API if results.present? docs = results.map do |model| DocResult.new( - doc_type: 'USERS', + doc_type: 'USERS', doc_url: '/profile/' + model.name, doc_title: model.username, latitude: model.lat, @@ -181,7 +181,7 @@ class Search < Grape::API DocList.new('', search_request) end end - + # Request URL should be /api/srch/nodes?query=QRY desc 'Perform a search of nodes', hidden: false, is_array: false, @@ -298,7 +298,6 @@ class Search < Grape::API end # Request URL should be /api/srch/taglocations?nwlat=200.0&selat=0.0&nwlng=0.0&selng=200.0[&tag=awesome] - # Note: Query(QRY as above) must have latitude and longitude as query=lat,lon desc 'Perform a search of documents having nearby latitude and longitude tag values', hidden: false, is_array: false, nickname: 'search_tag_locations' @@ -317,6 +316,8 @@ class Search < Grape::API doc_type: 'PLACES', doc_url: model.path(:items), doc_title: model.title, + doc_author: model.user.username, + doc_image_url: !model.images.empty? ? model.images.first.path : 0, score: model.answers.length, latitude: model.lat, longitude: model.lon, @@ -330,7 +331,6 @@ class Search < Grape::API end # Request URL should be /api/srch/nearbyPeople?nwlat=200.0&selat=0.0&nwlng=0.0&selng=200.0[&tag=awesome&sort_by=recent] - # Note: Query(QRY as above) must have latitude and longitude as query=lat,lon desc 'Perform a search to show people nearby a given location', hidden: false, is_array: false, nickname: 'search_nearby_people' diff --git a/app/assets/javascripts/application/i18n/translations.js b/app/assets/javascripts/application/i18n/translations.js deleted file mode 100644 index 203d59a497..0000000000 --- a/app/assets/javascripts/application/i18n/translations.js +++ /dev/null @@ -1,3 +0,0 @@ -I18n.translations || (I18n.translations = {}); -I18n.translations["en"] = I18n.extend((I18n.translations["en"] || {}), {"js":{"dashboard":{"all_updates":"All updates","none":"None","selected_updates":"Selected updates"}}}); -I18n.translations["de"] = I18n.extend((I18n.translations["de"] || {}), {"js":{"dashboard":{"all_updates":"Alle updates","none":"Keiner","selected_updates":"Ausgewählte Updates"}}}); diff --git a/app/assets/javascripts/async_tag_subscriptions.js b/app/assets/javascripts/async_tag_subscriptions.js index b2634d1c52..55363326b0 100644 --- a/app/assets/javascripts/async_tag_subscriptions.js +++ b/app/assets/javascripts/async_tag_subscriptions.js @@ -25,12 +25,13 @@ $(document).ready(function() window.location = "/tag/" + ($('#taginput').val()).replace(/\s/g, '-'); }); $('.index-follow-buttons').on('ajax:success', function(data, status, xhr){ - console.log("Hello"); - var data_recv = JSON.parse(JSON.stringify(status)); - notyNotification('relax', 3000, 'success', 'top', data_recv.message + 'Click here to manage your subscriptions. '); - var html_new = ' Following'; - $('#follow-unfollow-column-'+data_recv.id).html(html_new); - }); + console.log("Hello"); + var data_recv = JSON.parse(JSON.stringify(status)); + notyNotification('relax', 3000, 'success', 'top', data_recv.message + 'Click here to manage your subscriptions. '); + var html_new = ' Following'; + $('#follow-unfollow-column-'+data_recv.id).html(html_new); + window.history.pushState("", "", data_recv.url); // Preserve state + }); $('.index-follow-buttons').on('ajax:error', function(data, status, xhr){ var data_recv = JSON.parse(JSON.stringify(status)); notyNotification('relax', 3000, 'error', 'top', data_recv.message + 'Click here to manage your subscriptions. '); diff --git a/app/assets/javascripts/leaflet_helper.js b/app/assets/javascripts/leaflet_helper.js index 61e8aa7111..b6267a73ed 100644 --- a/app/assets/javascripts/leaflet_helper.js +++ b/app/assets/javascripts/leaflet_helper.js @@ -8,21 +8,6 @@ return map ; } - - function setupFullScreen(map , lat , lon) { - map.addControl(new L.Control.Fullscreen()); // to go full-screen - map.on('fullscreenchange', function () { - if (map.isFullscreen()) { - map.options.minZoom = 3 ; - } - else { - map.options.minZoom = 1 ; - map.panTo(new L.LatLng(lat,lon)); - } - }); - } - - function PLmarker_default(){ L.Icon.PLmarker = L.Icon.extend({ options: { @@ -65,13 +50,14 @@ }); } - function contentLayerParser(map,markers_hash, map_tagname) { + function contentLayerParser(map, markers_hash, map_tagname) { var NWlat = map.getBounds().getNorthWest().lat ; var NWlng = map.getBounds().getNorthWest().lng ; var SElat = map.getBounds().getSouthEast().lat ; var SElng = map.getBounds().getSouthEast().lng ; map.spin(true) ; - if(map_tagname === null && (typeof map_tagname === "undefined")) { + + if(map_tagname === null || (typeof map_tagname === "undefined")) { taglocation_url = "/api/srch/taglocations?nwlat=" + NWlat + "&selat=" + SElat + "&nwlng=" + NWlng + "&selng=" + SElng ; } else { @@ -82,12 +68,19 @@ for (i = 0; i < data.items.length; i++) { var url = data.items[i].doc_url; var title = data.items[i].doc_title; + var author = data.items[i].doc_author; + var image_url = data.items[i].doc_image_url; var default_url = PLmarker_default(); var mid = data.items[i].doc_id ; - var m = L.marker([data.items[i].latitude, data.items[i].longitude], {icon: default_url}).addTo(map).bindPopup("" + title + "") ; - + var m = L.marker([data.items[i].latitude, data.items[i].longitude], {icon: default_url}).bindPopup("" + title + "") ; + if(markers_hash.has(mid) === false){ - m.addTo(map).bindPopup("" + title + "") ; + + if(image_url) { + m.addTo(map).bindPopup("
" ) ; + } else { + m.addTo(map).bindPopup("Title: " + title + ")?\[map\:layers\:(\w*)\:(\S+)\:(\S+)\:(\w+)((\,\w+)*)]/) do |_tagname| mainLayer = Regexp.last_match(2) @@ -356,7 +356,7 @@ def self.data_string(view, tagname, nodes, type) def self.map_data_string(lat, lon, tagname, template, mainLayer = nil) a = ActionController::Base.new - locals_data = if template == "leaflet" + locals_data = if template == "plainInlineLeaflet" { lat: lat, lon: lon, tagname: tagname.to_s } elsif template == "inlineLeaflet" { lat: lat, lon: lon, layers: tagname.to_s, mainLayer: mainLayer } diff --git a/app/models/doc_result.rb b/app/models/doc_result.rb index df9b87cdf5..93a1dd71df 100644 --- a/app/models/doc_result.rb +++ b/app/models/doc_result.rb @@ -1,6 +1,6 @@ # A DocResult is an individual return item for a document (web page) search class DocResult - attr_accessor :doc_id, :doc_type, :doc_url, :doc_title, :doc_score, :latitude, :longitude, :blurred, :category + attr_accessor :doc_id, :doc_type, :doc_url, :doc_title, :doc_score, :latitude, :longitude, :blurred, :category, :doc_author, :doc_image_url def initialize(args = {}) @doc_id = args[:doc_id] @@ -8,6 +8,8 @@ def initialize(args = {}) @doc_url = args[:doc_url] @doc_title = args[:doc_title] @doc_score = args[:doc_score] + @doc_author = args[:doc_author] + @doc_image_url = args[:doc_image_url] @latitude = args[:latitude] @longitude = args[:longitude] @blurred = args[:blurred] diff --git a/app/models/node.rb b/app/models/node.rb index 69eb399ac0..950978f277 100644 --- a/app/models/node.rb +++ b/app/models/node.rb @@ -1,14 +1,12 @@ class UniqueUrlValidator < ActiveModel::Validator def validate(record) - if record.title == '' || record.title.nil? - # record.errors[:base] << "You must provide a title." + if record.title.blank? + record.errors[:base] << "You must provide a title." # otherwise the below title uniqueness check fails, as title presence validation doesn't run until after elsif record.type == 'page' array = %w(create edit update delete new) - array.each do |x| - if record.title == x - record.errors[:base] << "You may not use the title '" + x + "'" - end + if array.include? record.title.downcase + record.errors[:base] << "You may not use the title '#{record.title}'" end else if !Node.where(path: record.generate_path).first.nil? && record.type == 'note' @@ -96,7 +94,7 @@ def updated_month belongs_to :user, foreign_key: 'uid' - validates :title, presence: true + validates :title, presence: true, length: { minimum: 3 } validates_with UniqueUrlValidator, on: :create scope :published, -> { where(status: 1) } @@ -877,6 +875,30 @@ def self.questions .group('node.nid') end + # finds nodes by tag name, user id, and optional node type + def self.find_by_tag_and_author(tagname, user_id, type = 'notes') + + node_type = 'note' if type == 'notes' || 'questions' + node_type = 'page' if type == 'wiki' + # node_type = 'map' if type == 'maps' # Tag.tagged_nodes_by_author does not seem to work with maps, more testing required + + order = 'node_revisions.timestamp DESC' + order = 'created DESC' if node_type == 'note' + + qids = Node.questions.where(status: 1).collect(&:nid) + + nodes = Tag.tagged_nodes_by_author(tagname, user_id) + .includes(:revision) + .references(:node_revisions) + .where(status: 1, type: node_type) + .order(order) + + nodes = nodes.where('node.nid NOT IN (?)', qids) if type == 'notes' + nodes = nodes.where('node.nid IN (?)', qids) if type == 'questions' + + nodes + end + # so we can quickly fetch activities corresponding to this node # with node.activities def activities diff --git a/app/models/user.rb b/app/models/user.rb index 73bbfdab32..ca486019ca 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -71,7 +71,7 @@ def is_new_contributor? end def new_contributor - return "new contributor".html_safe if is_new_contributor? + return "new contributor".html_safe if is_new_contributor? end def set_token @@ -396,7 +396,7 @@ def find_by_username_case_insensitive(username) User.where('lower(username) = ?', username.downcase).first end - # all uses who've posted a node, comment, or answer in the given period + # all users who've posted a node, comment, or answer in the given period def contributor_count_for(start_time, end_time) notes = Node.where(type: 'note', status: 1, created: start_time.to_i..end_time.to_i).pluck(:uid) answers = Answer.where(created_at: start_time..end_time).pluck(:uid) diff --git a/app/services/search_service.rb b/app/services/search_service.rb index 3ceca6f637..d06a850446 100644 --- a/app/services/search_service.rb +++ b/app/services/search_service.rb @@ -154,7 +154,7 @@ def tagNearbyNodes(coordinates, tag, period = { "from" => nil, "to" => nil }, so else items.order(Arel.sql("created #{order_direction}")) .limit(limit) - end + end end # Search nearby people with respect to given latitude, longitute and tags diff --git a/app/views/admin/_nodes.html.erb b/app/views/admin/_nodes.html.erb index 007eb2f9e2..a3c91e3e33 100644 --- a/app/views/admin/_nodes.html.erb +++ b/app/views/admin/_nodes.html.erb @@ -10,8 +10,8 @@ $('#batch-delete').bind('click',function(e) { vals = [] alert_error('The mass spam button is disabled pending resolution of ticket #184.') - //$('.batch-checkbox').each(function(i,a) { if (a.checked) vals.push(a.value) }) - //window.location = "/spam/batch/"+vals.join(',') + $('.batch-checkbox').each(function(i,a) { if (a.checked) vals.push(a.value) }) + window.location = "/spam/batch/" + vals.join(',') }) })() diff --git a/app/views/comments/_comments.html.erb b/app/views/comments/_comments.html.erb index ac16731b1d..e1f44afc92 100644 --- a/app/views/comments/_comments.html.erb +++ b/app/views/comments/_comments.html.erb @@ -3,13 +3,13 @@
- <%= raw t('comments._edit.drag_and_drop') %>
+ <%= raw translation('comments._edit.drag_and_drop') %>
@@ -126,7 +126,7 @@
- <%= raw t('comments._form.drag_and_drop') %>
+ <%= raw translation('comments._form.drag_and_drop') %>
@@ -91,28 +91,28 @@
<%= javascript_include_tag "comment.js" %>
<% if logged_in_as(['admin','moderator']) %>
- <%= t('dashboard._node_moderate.first_time_post') %>
- <%= t('dashboard.moderate.approve') %>
- <%= t('dashboard.moderate.spam') %>
+ <%= translation('dashboard._node_moderate.first_time_post') %>
+ <%= translation('dashboard.moderate.approve') %>
+ <%= translation('dashboard.moderate.spam') %>
<% else %>
- <%= raw t('dashboard.moderate.pending_approval', :url => '/wiki/moderation') %>
+ <%= raw translation('dashboard.moderate.pending_approval', :url => '/wiki/moderation') %>
<% end %>
<%= raw t('comments._edit.logged_in', :username => current_user.username) %> |
- <%= t('comments._edit.formatting') %> |
- <%= t('comments._edit.notifications') %>
+
<%= raw translation('comments._edit.logged_in', :username => current_user.username) %> |
+ <%= translation('comments._edit.formatting') %> |
+ <%= translation('comments._edit.notifications') %>
<%= raw t('comments._form.logged_in', :username => current_user.username) %>
+
<%= raw translation('comments._form.logged_in', :username => current_user.username) %>
<%= t('dashboard._activity.activity') %>
diff --git a/app/views/dashboard/_node_comment.html.erb b/app/views/dashboard/_node_comment.html.erb
index ccf929d013..5eecc5f09f 100644
--- a/app/views/dashboard/_node_comment.html.erb
+++ b/app/views/dashboard/_node_comment.html.erb
@@ -13,7 +13,7 @@
<%= render partial: 'dashboard/comment_moderate', locals: { comment: node } %>
diff --git a/app/views/dashboard/_node_meta.html.erb b/app/views/dashboard/_node_meta.html.erb
index 125438d3a9..e604c339eb 100644
--- a/app/views/dashboard/_node_meta.html.erb
+++ b/app/views/dashboard/_node_meta.html.erb
@@ -1,5 +1,5 @@
<% unless node.is_a?(Comment) || node.is_a?(Revision) || node.type == 'page' %>
- <%= t('dashboard.dashboard.by') %> <%= node.author.name %> <%= node.author.new_contributor %>
+ <%= translation('dashboard.dashboard.by') %> <%= node.author.name %> <%= node.author.new_contributor %>
<% if node.has_power_tag('with') %>
with
<% node.coauthors.each_with_index do |coauthor,i| %>
diff --git a/app/views/dashboard/_node_moderate.html.erb b/app/views/dashboard/_node_moderate.html.erb
index aa57199235..d06e6b74e8 100644
--- a/app/views/dashboard/_node_moderate.html.erb
+++ b/app/views/dashboard/_node_moderate.html.erb
@@ -1,11 +1,11 @@
<% if node.status == 4 %>
<%= node.title %>
-
+
diff --git a/app/views/dashboard/_node_wiki.html.erb b/app/views/dashboard/_node_wiki.html.erb
index 5bf3c3c0b4..d91913a805 100644
--- a/app/views/dashboard/_node_wiki.html.erb
+++ b/app/views/dashboard/_node_wiki.html.erb
@@ -3,10 +3,10 @@
<% if node.is_a?(Node) %>
-
+
<% else %>
-
+
<% end %>
@@ -27,7 +27,7 @@
<% if node.is_a?(Revision) && node.previous %>
- <%= t('dashboard._node_wiki.changes') %> »
+ <%= translation('dashboard._node_wiki.changes') %> »
<% end %>
diff --git a/app/views/editor/rich.html.erb b/app/views/editor/rich.html.erb
index 3d8b8deab9..b485c039dc 100644
--- a/app/views/editor/rich.html.erb
+++ b/app/views/editor/rich.html.erb
@@ -304,14 +304,8 @@
-
+
<%= comments.length %> <%= t('notes._comments.comments') %>
+<%= comments.length %> <%= translation('notes._comments.comments') %>
- <%= t('layout._header.login.login_title') %> to comment. + <%= translation('layout._header.login.login_title') %> to comment.
<% end %> diff --git a/app/views/notes/_notes.html.erb b/app/views/notes/_notes.html.erb index 4669ec58a4..c8ad3546c2 100644 --- a/app/views/notes/_notes.html.erb +++ b/app/views/notes/_notes.html.erb @@ -15,77 +15,72 @@ <% end %>- <% if logged_in_as(['admin','moderator']) %> - <%= t('notes._notes.moderate_first_time_post') %>
- <% end %> + <% if node.status == 4 %> +- <%= t('notes._notes.approve') %> - <%= t('notes._notes.spam') %> - <% else %> - <%= raw t('notes._notes.pending_approval', :url1 => '/wiki/moderation') %> - <% end %> -
+ <% if @current_user && ['admin','moderator'].include?(@current_user.role) %> + <%= t('notes._notes.moderate_first_time_post') %>
+ <% end %> -+ <%= t('notes._notes.approve') %> + <%= t('notes._notes.spam') %> + <% else %> + <%= raw t('notes._notes.pending_approval', :url1 => '/wiki/moderation') %> + <% end %> +
target="_blank"<% end %> href="<%= node.path %>" style="color: black"><%= (node.type == 'note') ? node.title : node.latest.title %>
+target="_blank"<% end %> href="<%= node.path %>" style="color: black"><%= (node.type == 'note') ? node.title : node.latest.title %>
- - <% if node.type == 'note' %> -- <%= node.comments.size %> | <%= distance_of_time_in_words(node.created_at, Time.current, { include_seconds: false, scope:'datetime.time_ago_in_words' }).gsub('about ','') %> - -
+ + <% if node.type == 'note' %> +Post by target="_blank"<% end %> href="/profile/<%= node.author.name %>" style="color: #303030">@<%= node.author.name %> <%= node.author.new_contributor %>
+ <%= node.comments.size %> | <%= distance_of_time_in_words(node.created_at, Time.current, { include_seconds: false, scope:'datetime.time_ago_in_words' }).gsub('about ','') %> + <% end %> + +
+ <% if node.type == 'note' %>-
Made: <%= distance_of_time_in_words(node.created_at, Time.current, { include_seconds: false, scope:'datetime.time_ago_in_words' }) %>
+ <% else %>
-
- target="_blank"<% end %> href="<%= node.path %>#comments">Comments: <%= node.comments.size %>
+ Last Edited: <%= t('notes._notes.last_edit_by') %> target="_blank"<% end %> href="/profile/<%= node.latest.author.name %>"><%= node.latest.author.name %>
- <% else %>
- -
- Last Edited: <%= t('notes._notes.last_edit_by') %> target="_blank"<% end %> href="/profile/<%= node.latest.author.name %>"><%= node.latest.author.name %>
-
- -
- <%= distance_of_time_in_words(Time.at(node.latest.timestamp), Time.current, { include_seconds: false, scope: 'datetime.time_ago_in_words' }) %>
-
- <% end %>
- -
- Total Views: <%= number_with_delimiter(node.views) %> <%= t('notes._notes.views') %>
-
-
- -
- Total Likes: <%= node.likers.length %>
-
-
-
- <% if @compact.nil? %>
- <% if params[:action].to_s.include?("methods") %>
- - <% if logged_in_as(['admin','moderator']) %> <%= t('notes._notes.spam') %><% end %>
- - <%= t('notes._notes.read_more') %>
- <% end %>
- <% if params[:mod] %>
- <%= t('notes._notes.spam') %>
- <% end %>
-
-
-
- - --- target="_blank"<% end %> href="<%= node.path %>#Activities"> <%= node.activities.count %> activities
-
- - target="_blank"<% end %> href="<%= node.path %>#Questions"> <%= node.questions.count %> questions
-
- <% end %> -+ target="_blank"<% end %> href="<%= node.path %>#Activities"> <%= node.activities.count %> activities + target="_blank"<% end %> href="<%= node.path %>#Questions"> <%= node.questions.count %> questions +
+ <% end %> +