Add documents (merges foodcoops/foodsoft#353)
This commit is contained in:
parent
33c9b23e2f
commit
8bb58c5519
18 changed files with 310 additions and 0 deletions
1
Gemfile
1
Gemfile
|
@ -56,6 +56,7 @@ gem 'foodsoft_messages', path: 'plugins/messages'
|
||||||
# plugins not enabled by default
|
# plugins not enabled by default
|
||||||
#gem 'foodsoft_current_orders', path: 'plugins/current_orders'
|
#gem 'foodsoft_current_orders', path: 'plugins/current_orders'
|
||||||
#gem 'foodsoft_uservoice', path: 'plugins/uservoice'
|
#gem 'foodsoft_uservoice', path: 'plugins/uservoice'
|
||||||
|
#gem 'foodsoft_documents', path: 'plugins/documents'
|
||||||
|
|
||||||
|
|
||||||
group :production do
|
group :production do
|
||||||
|
|
32
plugins/documents/README.md
Normal file
32
plugins/documents/README.md
Normal file
|
@ -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).
|
40
plugins/documents/Rakefile
Normal file
40
plugins/documents/Rakefile
Normal file
|
@ -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
|
63
plugins/documents/app/controllers/documents_controller.rb
Normal file
63
plugins/documents/app/controllers/documents_controller.rb
Normal file
|
@ -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
|
5
plugins/documents/app/models/document.rb
Normal file
5
plugins/documents/app/models/document.rb
Normal file
|
@ -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
|
|
@ -0,0 +1,2 @@
|
||||||
|
/ insert_before ':root:first-child'
|
||||||
|
= config_input form, :use_documents, as: :boolean
|
20
plugins/documents/app/views/documents/_documents.html.haml
Normal file
20
plugins/documents/app/views/documents/_documents.html.haml
Normal file
|
@ -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'
|
7
plugins/documents/app/views/documents/index.html.haml
Normal file
7
plugins/documents/app/views/documents/index.html.haml
Normal file
|
@ -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"
|
1
plugins/documents/app/views/documents/index.js.haml
Normal file
1
plugins/documents/app/views/documents/index.js.haml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
$('#documentsTable').html('#{escape_javascript(render("documents"))}');
|
8
plugins/documents/app/views/documents/new.html.haml
Normal file
8
plugins/documents/app/views/documents/new.html.haml
Normal file
|
@ -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
|
29
plugins/documents/config/locales/de.yml
Normal file
29
plugins/documents/config/locales/de.yml
Normal file
|
@ -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
|
29
plugins/documents/config/locales/en.yml
Normal file
29
plugins/documents/config/locales/en.yml
Normal file
|
@ -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
|
9
plugins/documents/config/routes.rb
Normal file
9
plugins/documents/config/routes.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
Rails.application.routes.draw do
|
||||||
|
|
||||||
|
scope '/:foodcoop' do
|
||||||
|
|
||||||
|
resources :documents
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -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
|
22
plugins/documents/foodsoft_documents.gemspec
Normal file
22
plugins/documents/foodsoft_documents.gemspec
Normal file
|
@ -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
|
9
plugins/documents/lib/foodsoft_documents.rb
Normal file
9
plugins/documents/lib/foodsoft_documents.rb
Normal file
|
@ -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
|
15
plugins/documents/lib/foodsoft_documents/engine.rb
Normal file
15
plugins/documents/lib/foodsoft_documents/engine.rb
Normal file
|
@ -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
|
3
plugins/documents/lib/foodsoft_documents/version.rb
Normal file
3
plugins/documents/lib/foodsoft_documents/version.rb
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module FoodsoftDocuments
|
||||||
|
VERSION = "0.0.1"
|
||||||
|
end
|
Loading…
Reference in a new issue