From 3f7556c4a975f259c18d8176ac4a280f0cc4d985 Mon Sep 17 00:00:00 2001 From: Patrick Gansterer Date: Sat, 20 Feb 2016 10:34:17 +0100 Subject: [PATCH] Add documents #353 --- Gemfile | 1 + Gemfile.lock | 8 +++ ...ate_documents.foodsoft_documents_engine.rb | 16 +++++ db/schema.rb | 11 +++- plugins/documents/README.md | 18 ++++++ plugins/documents/Rakefile | 40 ++++++++++++ .../app/controllers/documents_controller.rb | 61 +++++++++++++++++++ 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 | 21 +++++++ plugins/documents/lib/foodsoft_documents.rb | 9 +++ .../lib/foodsoft_documents/engine.rb | 15 +++++ .../lib/foodsoft_documents/version.rb | 3 + 21 files changed, 327 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20160220000000_create_documents.foodsoft_documents_engine.rb 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 83c0d5345..3c7344c3f 100644 --- a/Gemfile +++ b/Gemfile @@ -53,6 +53,7 @@ gem 'ruby-filemagic' gem 'acts_as_versioned', github: 'technoweenie/acts_as_versioned' gem 'foodsoft_wiki', path: 'plugins/wiki' gem 'foodsoft_messages', path: 'plugins/messages' +gem 'foodsoft_documents', path: 'plugins/documents' # plugins not enabled by default #gem 'foodsoft_current_orders', path: 'plugins/current_orders' diff --git a/Gemfile.lock b/Gemfile.lock index a09fe794f..6b1013883 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -11,6 +11,13 @@ GIT acts_as_versioned (0.6.0) activerecord (>= 3.0.9) +PATH + remote: plugins/documents + specs: + foodsoft_documents (0.0.1) + deface (~> 1.0.0) + rails + PATH remote: plugins/messages specs: @@ -494,6 +501,7 @@ DEPENDENCIES exception_notification factory_girl_rails faker + foodsoft_documents! foodsoft_messages! foodsoft_wiki! gaffe diff --git a/db/migrate/20160220000000_create_documents.foodsoft_documents_engine.rb b/db/migrate/20160220000000_create_documents.foodsoft_documents_engine.rb new file mode 100644 index 000000000..21bc2eb8f --- /dev/null +++ b/db/migrate/20160220000000_create_documents.foodsoft_documents_engine.rb @@ -0,0 +1,16 @@ +# This migration comes from foodsoft_documents_engine (originally 20160220000000) +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/db/schema.rb b/db/schema.rb index cbeecd91b..ba00a7ea1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160219123220) do +ActiveRecord::Schema.define(version: 20160220000000) do create_table "article_categories", force: :cascade do |t| t.string "name", limit: 255, default: "", null: false @@ -76,6 +76,15 @@ add_index "deliveries", ["supplier_id"], name: "index_deliveries_on_supplier_id", using: :btree + create_table "documents", force: :cascade do |t| + t.string "name" + t.string "mime" + t.binary "data" + t.integer "created_by_user_id" + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "financial_transaction_classes", force: :cascade do |t| t.string "name", null: false end diff --git a/plugins/documents/README.md b/plugins/documents/README.md new file mode 100644 index 000000000..f60743146 --- /dev/null +++ b/plugins/documents/README.md @@ -0,0 +1,18 @@ +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 enabled by default in foodsoft, so you don't need to do anything +to install it. If you still want to, for example when it has been disabled, +add the following to foodsoft's Gemfile: + +```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. + +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 000000000..070cb3df0 --- /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 000000000..f0f8b25aa --- /dev/null +++ b/plugins/documents/app/controllers/documents_controller.rb @@ -0,0 +1,61 @@ +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] == '' + @document.name = params[:document][:data].original_filename + 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 000000000..35f7fb16f --- /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 000000000..65b9a0b32 --- /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 000000000..ef2d5bec5 --- /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 000000000..6d3fc096b --- /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 000000000..5004571e9 --- /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 000000000..638a721a5 --- /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 000000000..c9e5ed796 --- /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 000000000..56ab39a04 --- /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 000000000..5cc997769 --- /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 000000000..ac82e3e7e --- /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 000000000..cfc322e04 --- /dev/null +++ b/plugins/documents/foodsoft_documents.gemspec @@ -0,0 +1,21 @@ +$:.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" +end diff --git a/plugins/documents/lib/foodsoft_documents.rb b/plugins/documents/lib/foodsoft_documents.rb new file mode 100644 index 000000000..26eb92ead --- /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 000000000..b3819a0e9 --- /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 000000000..6e57dbb35 --- /dev/null +++ b/plugins/documents/lib/foodsoft_documents/version.rb @@ -0,0 +1,3 @@ +module FoodsoftDocuments + VERSION = "0.0.1" +end