From 8bb58c551914be790d05413f7d8eaf24a7580947 Mon Sep 17 00:00:00 2001 From: Patrick Gansterer Date: Thu, 28 Apr 2016 13:46:13 +0200 Subject: [PATCH] Add documents (merges foodcoops/foodsoft#353) --- Gemfile | 1 + plugins/documents/README.md | 32 ++++++++++ plugins/documents/Rakefile | 40 ++++++++++++ .../app/controllers/documents_controller.rb | 63 +++++++++++++++++++ plugins/documents/app/models/document.rb | 5 ++ .../add_documents_config.html.haml.deface | 2 + .../app/views/documents/_documents.html.haml | 20 ++++++ .../app/views/documents/index.html.haml | 7 +++ .../app/views/documents/index.js.haml | 1 + .../app/views/documents/new.html.haml | 8 +++ plugins/documents/config/locales/de.yml | 29 +++++++++ plugins/documents/config/locales/en.yml | 29 +++++++++ plugins/documents/config/routes.rb | 9 +++ .../20160220000000_create_documents.rb | 15 +++++ plugins/documents/foodsoft_documents.gemspec | 22 +++++++ plugins/documents/lib/foodsoft_documents.rb | 9 +++ .../lib/foodsoft_documents/engine.rb | 15 +++++ .../lib/foodsoft_documents/version.rb | 3 + 18 files changed, 310 insertions(+) create mode 100644 plugins/documents/README.md create mode 100644 plugins/documents/Rakefile create mode 100644 plugins/documents/app/controllers/documents_controller.rb create mode 100644 plugins/documents/app/models/document.rb create mode 100644 plugins/documents/app/overrides/admin/configs/_tab_others/add_documents_config.html.haml.deface create mode 100644 plugins/documents/app/views/documents/_documents.html.haml create mode 100644 plugins/documents/app/views/documents/index.html.haml create mode 100644 plugins/documents/app/views/documents/index.js.haml create mode 100644 plugins/documents/app/views/documents/new.html.haml create mode 100644 plugins/documents/config/locales/de.yml create mode 100644 plugins/documents/config/locales/en.yml create mode 100644 plugins/documents/config/routes.rb create mode 100644 plugins/documents/db/migrate/20160220000000_create_documents.rb create mode 100644 plugins/documents/foodsoft_documents.gemspec create mode 100644 plugins/documents/lib/foodsoft_documents.rb create mode 100644 plugins/documents/lib/foodsoft_documents/engine.rb create mode 100644 plugins/documents/lib/foodsoft_documents/version.rb diff --git a/Gemfile b/Gemfile index 55a4c32f..e840578a 100644 --- a/Gemfile +++ b/Gemfile @@ -56,6 +56,7 @@ gem 'foodsoft_messages', path: 'plugins/messages' # plugins not enabled by default #gem 'foodsoft_current_orders', path: 'plugins/current_orders' #gem 'foodsoft_uservoice', path: 'plugins/uservoice' +#gem 'foodsoft_documents', path: 'plugins/documents' group :production do diff --git a/plugins/documents/README.md b/plugins/documents/README.md new file mode 100644 index 00000000..50b4d3c9 --- /dev/null +++ b/plugins/documents/README.md @@ -0,0 +1,32 @@ +FoodsoftDocuments +================= + +This plugin adds documents to foodsoft. A new 'Documents' menu entry is added below the 'Foodcoops' menu in the navigation bar. + +This plugin is not enabled by default. To install it, add uncomment the +corresponding line in the `Gemfile`, or add: + +```Gemfile +gem 'foodsoft_documents', path: 'lib/foodsoft_documents' +``` + +This plugin introduces the foodcoop config option `use_documents`, which can be +set to `true` to enable documents. May be useful in multicoop deployments. + + +## Notes + +This plugin may have some issues on certain installations: + +* Files are stored in the database (up to 16MB per file). If your database has + size limitations, you may want to consider how to use them. + +* Members can upload any filetypes and filenames, which means there is no + protection against files with viruses, or executable files. + +Before this plugin would be enabled by default, at least the latter would need +to be solved. + + +This plugin is part of the foodsoft package and uses the GPL-3 license (see +foodsoft's LICENSE for the full license text). diff --git a/plugins/documents/Rakefile b/plugins/documents/Rakefile new file mode 100644 index 00000000..070cb3df --- /dev/null +++ b/plugins/documents/Rakefile @@ -0,0 +1,40 @@ +#!/usr/bin/env rake +begin + require 'bundler/setup' +rescue LoadError + puts 'You must `gem install bundler` and `bundle install` to run rake tasks' +end +begin + require 'rdoc/task' +rescue LoadError + require 'rdoc/rdoc' + require 'rake/rdoctask' + RDoc::Task = Rake::RDocTask +end + +RDoc::Task.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'FoodsoftDocuments' + rdoc.options << '--line-numbers' + rdoc.rdoc_files.include('README.rdoc') + rdoc.rdoc_files.include('lib/**/*.rb') +end + +APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__) +load 'rails/tasks/engine.rake' + + + +Bundler::GemHelper.install_tasks + +require 'rake/testtask' + +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' + t.libs << 'test' + t.pattern = 'test/**/*_test.rb' + t.verbose = false +end + + +task :default => :test diff --git a/plugins/documents/app/controllers/documents_controller.rb b/plugins/documents/app/controllers/documents_controller.rb new file mode 100644 index 00000000..f1a57df6 --- /dev/null +++ b/plugins/documents/app/controllers/documents_controller.rb @@ -0,0 +1,63 @@ +require 'filemagic' + +class DocumentsController < ApplicationController + before_filter -> { require_plugin_enabled FoodsoftDocuments } + + def index + if params["sort"] + sort = case params["sort"] + when "name" then "name" + when "created_at" then "created_at" + when "name_reverse" then "name DESC" + when "created_at_reverse" then "created_at DESC" + end + else + sort = "name" + end + + @documents = Document.page(params[:page]).per(@per_page).order(sort) + end + + def new + @document = Document.new + end + + def create + @document = Document.new + @document.data = params[:document][:data].read + @document.mime = FileMagic.new(FileMagic::MAGIC_MIME).buffer(@document.data) + if params[:document][:name] == '' + name = params[:document][:data].original_filename + name = File.basename(name) + @document.name = name.gsub(/[^\w\.\-]/, '_') + else + @document.name = params[:document][:name] + end + @document.created_by = current_user + @document.save! + redirect_to documents_path, notice: I18n.t('documents.create.notice') + rescue => error + redirect_to documents_path, alert: t('documents.create.error', error: error.message) + end + + def destroy + @document = Document.find(params[:id]) + if @document.created_by == current_user or current_user.role_admin? + @document.destroy + redirect_to documents_path, notice: t('documents.destroy.notice') + else + redirect_to documents_path, alert: t('documents.destroy.no_right') + end + rescue => error + redirect_to documents_path, alert: t('documents.destroy.error', error: error.message) + end + + def show + @document = Document.find(params[:id]) + filename = @document.name + unless filename.include? '.' + filename += '.' + MIME::Types[@document.mime].first.preferred_extension + end + send_data(@document.data, :filename => filename, :type => @document.mime) + end +end diff --git a/plugins/documents/app/models/document.rb b/plugins/documents/app/models/document.rb new file mode 100644 index 00000000..35f7fb16 --- /dev/null +++ b/plugins/documents/app/models/document.rb @@ -0,0 +1,5 @@ +class Document < ActiveRecord::Base + belongs_to :created_by, :class_name => 'User', :foreign_key => 'created_by_user_id' + + validates_presence_of :data +end diff --git a/plugins/documents/app/overrides/admin/configs/_tab_others/add_documents_config.html.haml.deface b/plugins/documents/app/overrides/admin/configs/_tab_others/add_documents_config.html.haml.deface new file mode 100644 index 00000000..65b9a0b3 --- /dev/null +++ b/plugins/documents/app/overrides/admin/configs/_tab_others/add_documents_config.html.haml.deface @@ -0,0 +1,2 @@ +/ insert_before ':root:first-child' += config_input form, :use_documents, as: :boolean diff --git a/plugins/documents/app/views/documents/_documents.html.haml b/plugins/documents/app/views/documents/_documents.html.haml new file mode 100644 index 00000000..ef2d5bec --- /dev/null +++ b/plugins/documents/app/views/documents/_documents.html.haml @@ -0,0 +1,20 @@ +- if Document.count > 20 + = items_per_page += pagination_links_remote @documents +%table.table.table-striped + %thead + %tr + %th= sort_link_helper heading_helper(Document, :name), "name", :per_page => @per_page + %th= sort_link_helper heading_helper(Document, :created_at), "created_at", :per_page => @per_page + %th= heading_helper(Document, :created_by) + %th + %tbody + - for document in @documents + %tr + %td= link_to document.name, document + %td= format_time(document.created_at) + %td= h show_user(document.created_by) + %td + - if document.created_by == current_user or current_user.role_admin? + = link_to t('ui.delete'), document, :method => :delete, :data => {:confirm => t('admin.confirm', name: document.name)}, + class: 'btn btn-mini btn-danger' diff --git a/plugins/documents/app/views/documents/index.html.haml b/plugins/documents/app/views/documents/index.html.haml new file mode 100644 index 00000000..6d3fc096 --- /dev/null +++ b/plugins/documents/app/views/documents/index.html.haml @@ -0,0 +1,7 @@ +- title t('.title') + +- content_for :actionbar do + = link_to t('.new'), new_document_path, class: 'btn btn-primary' + +#documentsTable + = render :partial => "documents" diff --git a/plugins/documents/app/views/documents/index.js.haml b/plugins/documents/app/views/documents/index.js.haml new file mode 100644 index 00000000..5004571e --- /dev/null +++ b/plugins/documents/app/views/documents/index.js.haml @@ -0,0 +1 @@ +$('#documentsTable').html('#{escape_javascript(render("documents"))}'); diff --git a/plugins/documents/app/views/documents/new.html.haml b/plugins/documents/app/views/documents/new.html.haml new file mode 100644 index 00000000..638a721a --- /dev/null +++ b/plugins/documents/app/views/documents/new.html.haml @@ -0,0 +1,8 @@ +- title t('.title') + += simple_form_for(@document) do |f| + = f.input :name, as: :string + = f.input :data, as: :file + .form-actions + = f.submit class: 'btn' + = link_to t('ui.or_cancel'), :back diff --git a/plugins/documents/config/locales/de.yml b/plugins/documents/config/locales/de.yml new file mode 100644 index 00000000..c9e5ed79 --- /dev/null +++ b/plugins/documents/config/locales/de.yml @@ -0,0 +1,29 @@ +de: + activerecord: + attributes: + document: + created_at: Erstellt am + created_by_user_id: Erstellt von + data: Daten + mime: MIME-Typ + name: Name + config: + hints: + use_documents: Einfache Dokumentenverwaltung aktivieren + keys: + use_documents: Dokumente verwenden + navigation: + documents: Dokumente + documents: + create: + error: 'Dokument konnte nicht erstellt werden: %{error}' + notice: Dokument wurde erstellt + destroy: + error: 'Dokument konnt nicht gelöscht werden: %{error}' + no_right: Du hast nicht genügend Rechte um die Datei zu löschen + notice: Dokument wurde gelöscht + index: + new: Neues Dokument anlegen + title: Dokumente + new: + title: Neues Dokument diff --git a/plugins/documents/config/locales/en.yml b/plugins/documents/config/locales/en.yml new file mode 100644 index 00000000..56ab39a0 --- /dev/null +++ b/plugins/documents/config/locales/en.yml @@ -0,0 +1,29 @@ +en: + activerecord: + attributes: + document: + created_at: Created at + created_by_user_id: Created by + data: Data + mime: MIME type + name: Name + config: + hints: + use_documents: Add a basic document sharing page to the foodcoop menu. + keys: + use_documents: Enable documents + navigation: + documents: Documents + documents: + create: + error: 'Document could not be created: %{error}' + notice: Document was created + destroy: + error: 'Document could not be deleted: %{error}' + no_right: You do not have enough rights to delete the document + notice: Document was deleted + index: + new: Upload new document + title: Documents + new: + title: New Document diff --git a/plugins/documents/config/routes.rb b/plugins/documents/config/routes.rb new file mode 100644 index 00000000..5cc99776 --- /dev/null +++ b/plugins/documents/config/routes.rb @@ -0,0 +1,9 @@ +Rails.application.routes.draw do + + scope '/:foodcoop' do + + resources :documents + + end + +end diff --git a/plugins/documents/db/migrate/20160220000000_create_documents.rb b/plugins/documents/db/migrate/20160220000000_create_documents.rb new file mode 100644 index 00000000..ac82e3e7 --- /dev/null +++ b/plugins/documents/db/migrate/20160220000000_create_documents.rb @@ -0,0 +1,15 @@ +class CreateDocuments < ActiveRecord::Migration + def self.up + create_table :documents do |t| + t.string :name + t.string :mime + t.binary :data, limit: 16.megabyte + t.integer :created_by_user_id + t.timestamps + end + end + + def self.down + drop_table :documents + end +end diff --git a/plugins/documents/foodsoft_documents.gemspec b/plugins/documents/foodsoft_documents.gemspec new file mode 100644 index 00000000..1df224ca --- /dev/null +++ b/plugins/documents/foodsoft_documents.gemspec @@ -0,0 +1,22 @@ +$:.push File.expand_path("../lib", __FILE__) + +# Maintain your gem's version: +require "foodsoft_documents/version" + +# Describe your gem and declare its dependencies: +Gem::Specification.new do |s| + s.name = "foodsoft_documents" + s.version = FoodsoftDocuments::VERSION + s.authors = ["paroga"] + s.email = ["paroga@paroga.com"] + s.homepage = "https://github.com/foodcoops/foodsoft" + s.summary = "Documents plugin for foodsoft." + s.description = "Adds simple document management to foodsoft." + + s.files = Dir["{app,config,db,lib}/**/*"] + ["Rakefile", "README.md"] + s.test_files = Dir["test/**/*"] + + s.add_dependency "rails" + s.add_dependency "deface", "~> 1.0.0" + s.add_dependency "ruby-filemagic" +end diff --git a/plugins/documents/lib/foodsoft_documents.rb b/plugins/documents/lib/foodsoft_documents.rb new file mode 100644 index 00000000..26eb92ea --- /dev/null +++ b/plugins/documents/lib/foodsoft_documents.rb @@ -0,0 +1,9 @@ +require 'foodsoft_documents/engine' + +module FoodsoftDocuments + # Return whether the documents are used or not. + # Enabled by default in {FoodsoftConfig} since it used to be part of the foodsoft core. + def self.enabled? + FoodsoftConfig[:use_documents] + end +end diff --git a/plugins/documents/lib/foodsoft_documents/engine.rb b/plugins/documents/lib/foodsoft_documents/engine.rb new file mode 100644 index 00000000..b3819a0e --- /dev/null +++ b/plugins/documents/lib/foodsoft_documents/engine.rb @@ -0,0 +1,15 @@ +module FoodsoftDocuments + class Engine < ::Rails::Engine + def navigation(primary, context) + return unless FoodsoftDocuments.enabled? + return if primary[:foodcoop].nil? + sub_nav = primary[:foodcoop].sub_navigation + sub_nav.items << + SimpleNavigation::Item.new(primary, :documents, I18n.t('navigation.documents'), context.documents_path) + # move to right before tasks item + if i = sub_nav.items.index(sub_nav[:tasks]) + sub_nav.items.insert(i, sub_nav.items.delete_at(-1)) + end + end + end +end diff --git a/plugins/documents/lib/foodsoft_documents/version.rb b/plugins/documents/lib/foodsoft_documents/version.rb new file mode 100644 index 00000000..6e57dbb3 --- /dev/null +++ b/plugins/documents/lib/foodsoft_documents/version.rb @@ -0,0 +1,3 @@ +module FoodsoftDocuments + VERSION = "0.0.1" +end