diff --git a/Gemfile.lock b/Gemfile.lock
index f51a1fd..c923936 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -139,7 +139,7 @@ GEM
treetop (1.4.15)
polyglot
polyglot (>= 0.3.1)
- turbolinks (2.2.2)
+ turbolinks (2.3.0)
coffee-rails
tzinfo (1.2.2)
thread_safe (~> 0.1)
diff --git a/app/assets/javascripts/categories.js b/app/assets/javascripts/categories.js
index cc92544..e0de14e 100644
--- a/app/assets/javascripts/categories.js
+++ b/app/assets/javascripts/categories.js
@@ -1,5 +1,5 @@
// Show all descendant categories of the clicked parent category
-function toggleDescendants(parent_id) {
+function toggleDescendants(parent_id, position) {
// Target class for the subcategories and their states (hidden or shown)
target_class = '.parent-id-' + parent_id.toString();
target_class_state = $(target_class).attr("value");
@@ -19,5 +19,30 @@ function toggleDescendants(parent_id) {
$(target_class).attr("value", "hidden");
// Change the orientation of the collapsible menu button
$("." + button_class).attr("class", "fa fa-plus-square-o " + button_class);
+ // Recursively hide any remaining categories deeper in the tree
+ hideDescendantTree(parent_id + 1, position);
+ }
+}
+
+function hideDescendantTree(parent_id, position) {
+ // Recursively hide any sub categories in the tree
+ target_class = '.parent-id-' + parent_id.toString() + ".order-" + position.toString();
+ target_class_state = $(target_class).attr("value");
+ button_class = "button-id-" + parent_id.toString();
+
+ // Check if the the target class exists
+ if ($(target_class).length) {
+ if ($(target_class_state == "shown")) {
+ // Hide the category
+ $(target_class).css("display", "none");
+ $(target_class).attr("value", "hidden");
+ // Change the toggle button
+ $("." + button_class).attr("class", "fa fa-plus-square-o " + button_class);
+ // Recurse
+ hideDescendantTree(parent_id + 1, position);
+ }
+ } else {
+ // We've reached the end of the tree, return
+ return;
}
}
\ No newline at end of file
diff --git a/app/assets/stylesheets/categories.css.scss b/app/assets/stylesheets/categories.css.scss
index ad95f69..8d7cd3b 100644
--- a/app/assets/stylesheets/categories.css.scss
+++ b/app/assets/stylesheets/categories.css.scss
@@ -29,7 +29,6 @@
text-decoration: none;
color: black;
background: #E6E6E6;
- border-radius: 5px;
}
}
}
diff --git a/app/models/revision.rb b/app/models/revision.rb
index 27ed8ed..2051003 100644
--- a/app/models/revision.rb
+++ b/app/models/revision.rb
@@ -31,6 +31,8 @@ def extract_text
end
tempfile.unlink
+ # Get rid of utf-8 control characters
+ contents.gsub!(/\p{Cc}/, "") if !contents.blank?
# Redundant line breaks are useless to us
self.search_text = contents.gsub(/(\r?\n)+/,"\n") if !contents.blank?
end
diff --git a/app/views/categories/_categories_nav.html.erb b/app/views/categories/_categories_nav.html.erb
index f9e1b5d..6f2a2e9 100644
--- a/app/views/categories/_categories_nav.html.erb
+++ b/app/views/categories/_categories_nav.html.erb
@@ -4,20 +4,27 @@
<% categories.each do |root| %>
+ <% position = 0 %>
- -
-
- <%= link_to root.name, category_path(root, view_style: "grid") %>
+
-
+ <% if root.descendants.length > 0 %>
+
+ <% else %>
+
+ <% end %>
+ <%= link_to root.name, category_path(root, view_style: "grid") %>
<% root.descendants.each do |cat| %>
- -
+
-
<% if cat.descendants.length > 0 %>
-
+
<% end %>
<%= link_to cat.name, category_path(cat, view_style: "grid") %>
<% end %>
+
+ <% position += 1 %>
<% end %>
\ No newline at end of file
diff --git a/app/views/categories/_form.html.erb b/app/views/categories/_form.html.erb
index f14b64e..d61a5e8 100644
--- a/app/views/categories/_form.html.erb
+++ b/app/views/categories/_form.html.erb
@@ -1,31 +1,29 @@
-<%= form_for @category, url: category_path(@category), method: :patch do |f| %>
-
-
-
- <%= f.label :name %>
- <%= f.text_field :name, :class => "form-control"%>
-
-
-
- <%= f.label :description %>
- <%= f.text_field :description, :class => "form-control" %>
-
- <%= f.label :owning_group %>
- <%= f.select :group_id, @groups, {include_blank: true} %>
-
- <%= f.label :parent_id %>
- <%= f.select :parent_id, @categories, {include_blank: true} %>
-
- <%= f.label :is_private %>
- <%= f.check_box :is_private %>
-
- <%= f.label :is_writable %>
- <%= f.check_box :is_writable %>
-
- <%= f.label :is_featured %>
- <%= f.check_box :is_featured %>
-
- <%= f.submit %>
+
+
+
+ <%= f.label :name %>
+ <%= f.text_field :name, :class => "form-control"%>
+
+
+ <%= f.label :description %>
+ <%= f.text_field :description, :class => "form-control" %>
+
+ <%= f.label :owning_group %>
+ <%= f.select :group_id, @groups, {include_blank: true} %>
+
+ <%= f.label :parent_id %>
+ <%= f.select :parent_id, @categories, {include_blank: true} %>
+
+ <%= f.label :is_private %>
+ <%= f.check_box :is_private %>
+
+ <%= f.label :is_writable %>
+ <%= f.check_box :is_writable %>
+
+ <%= f.label :is_featured %>
+ <%= f.check_box :is_featured %>
+
+ <%= f.submit %>
-<% end %>
+
\ No newline at end of file
diff --git a/app/views/categories/edit.html.erb b/app/views/categories/edit.html.erb
index f221966..9469b48 100644
--- a/app/views/categories/edit.html.erb
+++ b/app/views/categories/edit.html.erb
@@ -6,6 +6,8 @@
- <%= render partial: "form" %>
+ <%= form_for @category, url: category_path(@category), method: :patch do |f| %>
+ <%= render partial: "form", locals: {f: f} %>
+ <% end %>
\ No newline at end of file
diff --git a/app/views/categories/new.html.erb b/app/views/categories/new.html.erb
index 49673e7..e685c5a 100644
--- a/app/views/categories/new.html.erb
+++ b/app/views/categories/new.html.erb
@@ -5,6 +5,8 @@
- <%= render partial: "form" %>
+ <%= form_for @category do |f| %>
+ <%= render partial: "form", locals: {f: f} %>
+ <% end %>
\ No newline at end of file
diff --git a/app/views/documents/_document_list_item.html.erb b/app/views/documents/_document_list_item.html.erb
index 96020dd..6a84e9b 100644
--- a/app/views/documents/_document_list_item.html.erb
+++ b/app/views/documents/_document_list_item.html.erb
@@ -1,11 +1,13 @@
-
- <%= link_to doc do %>
-
- <%= image_tag "icons/#{small_document_icon(doc.current_revision.extension_type)}" %>
-
<%= "#{doc.title}" %> <%= " - #{doc.description}" %>
-
- <%= "Date: #{doc.current_revision.updated_at.to_date}" %>
+<% if can_view_document(doc) %>
+
+ <%= link_to doc do %>
+
+ <%= image_tag "icons/#{small_document_icon(doc.current_revision.extension_type)}" %>
+
<%= "#{doc.title}" %> <%= " - #{doc.description}" %>
+
+ <%= "Date: #{doc.current_revision.updated_at.to_date}" %>
+
-
- <% end %>
-
\ No newline at end of file
+ <% end %>
+
+<% end %>
\ No newline at end of file
diff --git a/app/views/documents/_document_tile.html.erb b/app/views/documents/_document_tile.html.erb
index 3cc6d13..9f76ea4 100644
--- a/app/views/documents/_document_tile.html.erb
+++ b/app/views/documents/_document_tile.html.erb
@@ -1,11 +1,13 @@
-
-
- <%= link_to doc do %>
-
- <%= image_tag "icons/#{document_icon(doc.current_revision.extension_type)}" %>
-
- <%= doc.title %>
-
- <% end %>
+<% if can_view_document(doc) %>
+
+
+ <%= link_to doc do %>
+
+ <%= image_tag "icons/#{document_icon(doc.current_revision.extension_type)}" %>
+
+ <%= doc.title %>
+
+ <% end %>
+
-
\ No newline at end of file
+<% end %>
\ No newline at end of file
diff --git a/app/views/documents/_form.html.erb b/app/views/documents/_form.html.erb
index f391b96..18ae0a2 100644
--- a/app/views/documents/_form.html.erb
+++ b/app/views/documents/_form.html.erb
@@ -14,9 +14,9 @@
<%= f.check_box :is_private, :class => "checkbox" %>
- <%= f.label "Visible to Everyone", :style => "display: inline-block" %>
+ <%= f.label "Make Private", :style => "display: inline-block" %>
- Checking this box will make this document visible to everyone.
+ Checking this will hide the document from non-group members.
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index ab25730..984bd75 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -14,7 +14,7 @@
<%= render partial: "layouts/header" %>
-
+
<%= render partial: "categories/categories_nav.html.erb", locals: {categories: Category.roots} %>
diff --git a/lib/permissions.rb b/lib/permissions.rb
index 33faad0..0204e62 100644
--- a/lib/permissions.rb
+++ b/lib/permissions.rb
@@ -4,6 +4,10 @@ def current_user
@current_user = User.find_by_id(session[:user_id])
end
+ # ====================
+ # Category Permissions
+ # ====================
+
# Check if the current user can upload documents to the specified category
def can_upload_documents(category)
if !current_user.nil?
@@ -43,20 +47,54 @@ def upload_permitted_categories
permitted_categories ||= current_user.writable_categories
end
+ # ====================
+ # Document Permissions
+ # ====================
+
+
# Check if the current user can revise a specific document
def can_revise_document(document)
+ # deny user if not logged in
+ return false if current_user.nil?
# current user is an admin
return true if current_user.is_admin?
-
- # current user is a member of the category's
+ # current user is a member of the category's
# group for a document that is write protected
unless document.category.group.nil?
- return true if document.is_writable? and
+ return true if !document.is_writable? and
+ (document.category.group.members.include?(current_user) or
+ document.category.group.leaders.include?(current_user))
+ end
+ return document.is_writable?
+ end
+
+ # Check if the current user can view a specific document
+ def can_view_document(document)
+ # deny access if not logged in
+ return false if current_user.nil?
+ # allow access if user is logged in
+ return true if current_user.is_admin?
+ # current user is a member of the category's
+ # group for a document that is private
+ unless document.category.group.nil?
+ return true if document.is_private? and
(document.category.group.members.include?(current_user) or
document.category.group.leaders.include?(current_user))
end
+ return !document.is_private?
+ end
- # current user does not have permission to revise this document
+ # Check if the current user can edit a specific document
+ def can_edit_document(document)
+ # deny user if not logged in
+ return false if current_user.nil?
+ # current user is an admin
+ return true if current_user.is_admin?
+ # current user is a member of the category's group
+ unless document.category.group.nil?
+ return true if document.category.group.members.include?(current_user) or
+ document.category.group.leaders.include?(current_user)
+ end
return false
end