Skip to content

Commit

Permalink
Recursively hide tree sub categories at deeper levels and update perm…
Browse files Browse the repository at this point in the history
…issions for documents and categories
  • Loading branch information
gbprz committed Aug 22, 2014
1 parent faf6ff2 commit 89181ba
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 66 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Expand Up @@ -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)
Expand Down
27 changes: 26 additions & 1 deletion 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");
Expand All @@ -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;
}
}
1 change: 0 additions & 1 deletion app/assets/stylesheets/categories.css.scss
Expand Up @@ -29,7 +29,6 @@
text-decoration: none;
color: black;
background: #E6E6E6;
border-radius: 5px;
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions app/models/revision.rb
Expand Up @@ -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
Expand Down
17 changes: 12 additions & 5 deletions app/views/categories/_categories_nav.html.erb
Expand Up @@ -4,20 +4,27 @@
<!-- Category list -->
<ul style="list-style-type: none; padding-left: 15px;" class="categories_nav" >
<% categories.each do |root| %>
<% position = 0 %>
<!-- Show root categories -->
<li style="display:block-inline" value="root">
<i class="fa fa-plus-square-o button-id-<%=root.id%>" onclick="toggleDescendants(<%= root.id %>)"></i>
<%= link_to root.name, category_path(root, view_style: "grid") %>
<li style="display:block-inline" value="root" class="order-<%=position%>">
<% if root.descendants.length > 0 %>
<i class="fa fa-minus-square-o button-id-<%=root.id%>" onclick="toggleDescendants(<%= root.id %>, <%= position %>)"></i>
<% else %>
<i class="fa fa-square-o button-id-<%=root.id%>"></i>
<% end %>
<b> <%= link_to root.name, category_path(root, view_style: "grid") %> </b>
</li>
<!-- Subcategories are intially hidden in a tree menu -->
<% root.descendants.each do |cat| %>
<li class="parent-id-<%=cat.parent_id%>" style="padding-left:<%= 20 * cat.depth %>px; display: none" value="hidden">
<li class="parent-id-<%=cat.parent_id%> order-<%=position%>" style="padding-left:<%= 20 * cat.depth %>px; display: block" value="shown">
<!-- only show the subcategories toggle button if this subcategory has descendants -->
<% if cat.descendants.length > 0 %>
<i class="fa fa-plus-square-o button-id-<%=cat.id%>" onclick="toggleDescendants(<%= cat.id %>)"></i>
<i class="fa fa-minus-square-o button-id-<%=cat.id%>" onclick="toggleDescendants(<%= cat.id %>, <%= position %>)"></i>
<% end %>
<%= link_to cat.name, category_path(cat, view_style: "grid") %>
</li>
<% end %>
<br />
<% position += 1 %>
<% end %>
</ul>
56 changes: 27 additions & 29 deletions app/views/categories/_form.html.erb
@@ -1,31 +1,29 @@
<%= form_for @category, url: category_path(@category), method: :patch do |f| %>
<div class="col-md-6">
<div class="row">
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, :class => "form-control"%>
</div>
<br />
<div class="form-group">
<%= f.label :description %>
<%= f.text_field :description, :class => "form-control" %>
</div>
<%= f.label :owning_group %>
<%= f.select :group_id, @groups, {include_blank: true} %>
<br />
<%= f.label :parent_id %>
<%= f.select :parent_id, @categories, {include_blank: true} %>
<br />
<%= f.label :is_private %>
<%= f.check_box :is_private %>
<br />
<%= f.label :is_writable %>
<%= f.check_box :is_writable %>
<br />
<%= f.label :is_featured %>
<%= f.check_box :is_featured %>
<br />
<%= f.submit %>
<div class="col-md-6">
<div class="row">
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, :class => "form-control"%>
</div>
<br />
<div class="form-group">
<%= f.label :description %>
<%= f.text_field :description, :class => "form-control" %>
</div>
<%= f.label :owning_group %>
<%= f.select :group_id, @groups, {include_blank: true} %>
<br />
<%= f.label :parent_id %>
<%= f.select :parent_id, @categories, {include_blank: true} %>
<br />
<%= f.label :is_private %>
<%= f.check_box :is_private %>
<br />
<%= f.label :is_writable %>
<%= f.check_box :is_writable %>
<br />
<%= f.label :is_featured %>
<%= f.check_box :is_featured %>
<br />
<%= f.submit %>
</div>
<% end %>
</div>
4 changes: 3 additions & 1 deletion app/views/categories/edit.html.erb
Expand Up @@ -6,6 +6,8 @@
</ol>

<div class="panel-body">
<%= render partial: "form" %>
<%= form_for @category, url: category_path(@category), method: :patch do |f| %>
<%= render partial: "form", locals: {f: f} %>
<% end %>
</div>
</div>
4 changes: 3 additions & 1 deletion app/views/categories/new.html.erb
Expand Up @@ -5,6 +5,8 @@
</ol>

<div class="panel-body">
<%= render partial: "form" %>
<%= form_for @category do |f| %>
<%= render partial: "form", locals: {f: f} %>
<% end %>
</div>
</div>
22 changes: 12 additions & 10 deletions app/views/documents/_document_list_item.html.erb
@@ -1,11 +1,13 @@
<div class= "unstyled_link">
<%= link_to doc do %>
<div class="document_listitem_hover">
<%= image_tag "icons/#{small_document_icon(doc.current_revision.extension_type)}" %>
<b> <%= "#{doc.title}" %> </b> <%= " - #{doc.description}" %>
<div class="pull-right">
<%= "Date: #{doc.current_revision.updated_at.to_date}" %>
<% if can_view_document(doc) %>
<div class= "unstyled_link">
<%= link_to doc do %>
<div class="document_listitem_hover">
<%= image_tag "icons/#{small_document_icon(doc.current_revision.extension_type)}" %>
<b> <%= "#{doc.title}" %> </b> <%= " - #{doc.description}" %>
<div class="pull-right">
<%= "Date: #{doc.current_revision.updated_at.to_date}" %>
</div>
</div>
</div>
<% end %>
</div>
<% end %>
</div>
<% end %>
22 changes: 12 additions & 10 deletions app/views/documents/_document_tile.html.erb
@@ -1,11 +1,13 @@
<div class= "unstyled_link">
<div class="document_tile">
<%= link_to doc do %>
<div class="doc_tile_hover">
<%= image_tag "icons/#{document_icon(doc.current_revision.extension_type)}" %>
<br />
<%= doc.title %>
</div>
<% end %>
<% if can_view_document(doc) %>
<div class= "unstyled_link">
<div class="document_tile">
<%= link_to doc do %>
<div class="doc_tile_hover">
<%= image_tag "icons/#{document_icon(doc.current_revision.extension_type)}" %>
<br />
<%= doc.title %>
</div>
<% end %>
</div>
</div>
</div>
<% end %>
4 changes: 2 additions & 2 deletions app/views/documents/_form.html.erb
Expand Up @@ -14,9 +14,9 @@

<div class="form-group">
<%= f.check_box :is_private, :class => "checkbox" %>
<%= f.label "Visible to Everyone", :style => "display: inline-block" %>
<%= f.label "Make Private", :style => "display: inline-block" %>
<br />
<span style="font-size: 10px"> Checking this box will make this document visible to everyone.</span>
<span style="font-size: 10px"> Checking this will hide the document from non-group members.</span>
</div>

<div class="form-group">
Expand Down
2 changes: 1 addition & 1 deletion app/views/layouts/application.html.erb
Expand Up @@ -14,7 +14,7 @@
<%= render partial: "layouts/header" %>
</div>
<div class="row">
<div class="col-md-3">
<div class="col-md-2">
<%= render partial: "categories/categories_nav.html.erb", locals: {categories: Category.roots} %>
</div>
<div class="col-md-9">
Expand Down
46 changes: 42 additions & 4 deletions lib/permissions.rb
Expand Up @@ -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?
Expand Down Expand Up @@ -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

Expand Down

0 comments on commit 89181ba

Please sign in to comment.