Merge pull request #330 from foodcoops/feature/plugin-move

Move plugins to separate directory.
This commit is contained in:
wvengen 2014-12-02 23:37:22 +01:00
commit a278004c11
59 changed files with 4 additions and 4 deletions

View file

@ -1,18 +0,0 @@
FoodsoftMessages
================
This plugin adds messages to foodsoft. A new 'Messages' 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_messages', path: 'lib/foodsoft_messages'
```
This plugin introduces the foodcoop config option `use_messages`, which can be
set to `false` to disable messages. 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).

View file

@ -1,40 +0,0 @@
#!/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 = 'FoodsoftMessages'
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

View file

@ -1,36 +0,0 @@
class MessagesController < ApplicationController
before_filter -> { require_plugin_enabled FoodsoftMessages }
# Renders the "inbox" action.
def index
@messages = Message.pub.page(params[:page]).per(@per_page).order('created_at DESC').includes(:sender)
end
# Creates a new message object.
def new
@message = Message.new(params[:message])
if @message.reply_to and not @message.reply_to.is_readable_for?(current_user)
redirect_to new_message_url, alert: 'Nachricht ist privat!'
end
end
# Creates a new message.
def create
@message = @current_user.send_messages.new(params[:message])
if @message.save
Resque.enqueue(MessageNotifier, FoodsoftConfig.scope, 'message_deliver', @message.id)
redirect_to messages_url, :notice => I18n.t('messages.create.notice')
else
render :action => 'new'
end
end
# Shows a single message.
def show
@message = Message.find(params[:id])
unless @message.is_readable_for?(current_user)
redirect_to messages_url, alert: 'Nachricht ist privat!'
end
end
end

View file

@ -1,21 +0,0 @@
module MessagesHelper
def format_subject(message, length)
if message.subject.length > length
subject = truncate(message.subject, :length => length)
body = ""
else
subject = message.subject
body = truncate(message.body, :length => length - subject.length)
end
"<b>#{link_to(h(subject), message)}</b> <span style='color:grey'>#{h(body)}</span>".html_safe
end
def link_to_new_message(options = {})
messages_params = options[:message_params] || nil
link_text = content_tag :id, nil, class: 'icon-envelope'
link_text << " #{options[:text]}" if options[:text].present?
link_to(link_text.html_safe, new_message_path(message: messages_params), class: 'btn',
title: I18n.t('helpers.submit.message.create'))
end
end

View file

@ -1,11 +0,0 @@
class MessagesMailer < Mailer
# Sends an email copy of the given internal foodsoft message.
def foodsoft_message(message, recipient)
set_foodcoop_scope
@message = message
mail subject: "[#{FoodsoftConfig[:name]}] " + message.subject,
to: recipient.email,
from: "#{show_user(message.sender)} <#{message.sender.email}>"
end
end

View file

@ -1,92 +0,0 @@
class Message < ActiveRecord::Base
belongs_to :sender, :class_name => "User", :foreign_key => "sender_id"
serialize :recipients_ids, Array
attr_accessor :sent_to_all, :group_id, :recipient_tokens, :reply_to
scope :pending, -> { where(:email_state => 0) }
scope :sent, -> { where(:email_state => 1) }
scope :pub, -> { where(:private => false) }
# Values for the email_state attribute: :none, :pending, :sent, :failed
EMAIL_STATE = {
:pending => 0,
:sent => 1,
:failed => 2
}
validates_presence_of :recipients_ids, :subject, :body
validates_length_of :subject, :in => 1..255
validates_inclusion_of :email_state, :in => EMAIL_STATE.values
before_validation :clean_up_recipient_ids, :on => :create
def self.deliver(message_id)
find(message_id).deliver
end
def clean_up_recipient_ids
self.recipients_ids = recipients_ids.uniq.reject { |id| id.blank? } unless recipients_ids.nil?
self.recipients_ids = User.all.collect(&:id) if sent_to_all == "1"
end
def add_recipients(users)
self.recipients_ids = [] if recipients_ids.blank?
self.recipients_ids += users.collect(&:id) unless users.blank?
end
def group_id=(group_id)
@group_id = group_id
add_recipients Group.find(group_id).users unless group_id.blank?
end
def recipient_tokens=(ids)
@recipient_tokens = ids
add_recipients ids.split(",").collect { |id| User.find(id) }
end
def reply_to=(message_id)
@reply_to = Message.find(message_id)
add_recipients([@reply_to.sender])
self.subject = I18n.t('messages.model.reply_subject', :subject => @reply_to.subject)
self.body = I18n.t('messages.model.reply_header', :user => @reply_to.sender.display, :when => I18n.l(@reply_to.created_at, :format => :short)) + "\n"
@reply_to.body.each_line{ |l| self.body += I18n.t('messages.model.reply_indent', :line => l) }
end
def mail_to=(user_id)
user = User.find(user_id)
add_recipients([user])
end
# Returns true if this message is a system message, i.e. was sent automatically by Foodsoft itself.
def system_message?
self.sender_id.nil?
end
def sender_name
system_message? ? I18n.t('layouts.foodsoft') : sender.display rescue "?"
end
def recipients
User.find(recipients_ids)
end
def deliver
for user in recipients
if user.receive_email?
begin
MessagesMailer.foodsoft_message(self, user).deliver
rescue
Rails.logger.warn "Deliver failed for user \##{user.id}: #{user.email}"
end
end
end
update_attribute(:email_state, 1)
end
def is_readable_for?(user)
!private || sender == user || recipients_ids.include?(user.id)
end
end

View file

@ -1,4 +0,0 @@
/ insert_bottom ':root:last-child'
= config_use_heading form, :use_messages do
= config_input form, :mailing_list, as: :string, input_html: {class: 'input-xlarge'}
= config_input form, :mailing_list_subscribe, as: :string, input_html: {class: 'input-xlarge'}

View file

@ -1,3 +0,0 @@
/ insert_after 'erb:contains("delete")'
- if FoodsoftMessages.enabled?
= link_to t('.send_message'), new_message_path(:message => {:group_id => @ordergroup.id}), class: 'btn'

View file

@ -1,3 +0,0 @@
/ insert_after 'erb:contains("delete")'
- if FoodsoftMessages.enabled?
= link_to t('.send_message'), new_message_path(:message => {:mail_to => @user.id}), class: 'btn'

View file

@ -1,3 +0,0 @@
/ insert_after 'erb:contains("delete")'
- if FoodsoftMessages.enabled?
= link_to_new_message(message_params: {group_id: @workgroup.id})

View file

@ -1,3 +0,0 @@
/ insert_bottom 'tbody tr'
- if FoodsoftMessages.enabled?
%td= link_to_new_message(message_params: {group_id: ordergroup.id})

View file

@ -1,3 +0,0 @@
/ insert_bottom 'tbody tr'
- if FoodsoftMessages.enabled?
%td= link_to_new_message(message_params: {mail_to: user.id})

View file

@ -1,3 +0,0 @@
/ insert_after 'erb:contains("tasks")'
- if FoodsoftMessages.enabled?
= link_to_new_message message_params: {group_id: workgroup.id}

View file

@ -1,3 +0,0 @@
/ insert_after 'erb:contains("tasks")'
- if FoodsoftMessages.enabled?
%li= link_to t('.write_message'), new_message_path

View file

@ -1,7 +0,0 @@
/ insert_after 'erb[silent]:contains("<dashboard_middle_mark>")'
- if FoodsoftMessages.enabled?
- unless Message.pub.empty?
%section#messages
%h2= t '.messages.title'
= render 'messages/messages', messages: Message.pub.order('created_at DESC').limit(5), pagination: false
%p= link_to t('.messages.view_all'), messages_path

View file

@ -1,4 +0,0 @@
/ insert_before 'erb:contains("simple_fields_for :notify")'
- if FoodsoftMessages.enabled?
= s.simple_fields_for :messages, defaults: { inline_label: true, label: false } do |messages|
= messages.input 'send_as_email', as: :boolean, input_html: { checked: f.object.settings.messages['send_as_email'] }

View file

@ -1,14 +0,0 @@
- if pagination
- if Message.pub.count > 20
= items_per_page
= pagination_links_remote messages
- unless messages.empty?
%table.table.table-striped
%tbody
- for message in messages
%tr
%td= format_subject(message, 130)
%td= h(message.sender_name)
%td= format_time(message.created_at)
%td= link_to t('.reply'), new_message_path(:message => {:reply_to => message.id}), class: 'btn'

View file

@ -1,6 +0,0 @@
- title t('.title')
- content_for :actionbar do
= link_to t('.new'), new_message_path, class: 'btn btn-primary'
#messages
= render 'messages', messages: @messages, pagination: true

View file

@ -1 +0,0 @@
$('#messages').html('#{j(render('messages', messages: @messages, pagination: true))}');

View file

@ -1,46 +0,0 @@
- content_for :javascript do
:javascript
$(function() {
$('#message_recipient_tokens').tokenInput("#{users_path(:format => :json)}", {
crossDomain: false,
prePopulate: $('#message_recipient_tokens').data('pre'),
hintText: '#{t '.search_user'}',
noResultText: '#{t '.no_user_found'}',
searchingText: '#{t '.search'}',
theme: 'facebook'
});
$('#message_sent_to_all').on('touchclick', function() {
if ($(this).is(':checked')) {
$('#recipients').slideUp();
} else {
$('#recipients').slideDown();
}
});
});
- title t('.title')
= simple_form_for @message do |f|
- if FoodsoftConfig[:mailing_list].blank?
= f.input :sent_to_all, :as => :boolean
- else
%b= t('.list.desc', list: mail_to(FoodsoftConfig[:mailing_list])).html_safe
%br/
%small{:style => "color:grey"}
= t '.list.subscribe_msg'
%br/
- if FoodsoftConfig[:mailing_list_subscribe].blank?
= t('.list.subscribe', link: link_to(t('.list.wiki'), wiki_page_path('MailingListe'))).html_safe
- else
= t('.list.mail', email: mail_to(FoodsoftConfig[:mailing_list_subscribe])).html_safe
#recipients
= f.input :recipient_tokens, :input_html => { 'data-pre' => User.where(id: @message.recipients_ids).map(&:token_attributes).to_json }
= f.input :group_id, :as => :select, :collection => Group.undeleted.order('type DESC', 'name ASC').reject { |g| g.memberships.empty? }
= f.input :private
= f.input :subject, input_html: {class: 'input-xxlarge'}
= f.input :body, input_html: {class: 'input-xxlarge', rows: 13}
.form-actions
= f.submit class: 'btn btn-primary'
= link_to t('ui.or_cancel'), :back

View file

@ -1,21 +0,0 @@
- title t('.title')
%div{:style => "width:40em"}
%table{:style => "width:25em"}
%tr
%td= t '.from'
%td=h @message.sender_name
%tr
%td= t '.subject'
%td
%b=h @message.subject
%tr
%td= t '.sent_on'
%td= format_time(@message.created_at)
%hr/
%p= simple_format(h(@message.body))
%hr/
%p
= link_to t('.reply'), new_message_path(:message => {:reply_to => @message.id}), class: 'btn'
|
= link_to t('.all_messages'), messages_path

View file

@ -1,4 +0,0 @@
= raw @message.body
======================================================================
\
= raw t '.footer', reply_url: new_message_url('message[reply_to]' => @message.id), msg_url: message_url(@message), profile_url: my_profile_url

View file

@ -1,8 +0,0 @@
class MessageNotifier < UserNotifier
@queue = :foodsoft_notifier
def self.message_deliver(args)
message_id = args.first
Message.find(message_id).deliver
end
end

View file

@ -1,86 +0,0 @@
en:
activerecord:
attributes:
message:
body: Body
group_id: Group
private: Private
recipient_tokens: Recipients
sent_to_all: Send to all members
subject: Subject
models:
message: Message
admin:
ordergroups:
show:
send_message: Send message
users:
show:
send_message: Send message
config:
hints:
mailing_list: Mailing-list email address to use instead of the messaging system for mail to all members.
mailing_list_subscribe: Email address where members can send an email to for subscribing.
use_messages: Allow members to communicate with each other within Foodsoft.
keys:
use_messages: Messages
mailing_list: Mailing-list
mailing_list_subscribe: Mailing-list subscribe
helpers:
messages:
write_message: Write message
submit:
message:
create: send message
home:
index:
messages:
title: Newest Messages
view_all: See all messages
start_nav:
write_message: Write message
messages:
create:
notice: Message is saved and will be sent.
index:
new: New message
title: Messages
messages:
reply: Reply
model:
reply_header: ! '%{user} wrote on %{when}:'
reply_indent: ! '> %{line}'
reply_subject: ! 'Re: %{subject}'
new:
list:
desc: ! 'Please send messages to all using the mailing-list: %{list}'
mail: for example with an email to %{email}.
subscribe: You can find more about the mailing-list at %{link}.
subscribe_msg: You may have to subscribe to the mailing-list first.
wiki: Wiki (page Mailing-List)
no_user_found: No user found
search: Search ...
search_user: Search user
title: New message
show:
all_messages: All messages
from: ! 'From:'
reply: Reply
sent_on: ! 'Sent:'
subject: ! 'Subject:'
title: Show message
messages_mailer:
foodsoft_message:
footer: ! 'Reply: %{reply_url}
See message online: %{msg_url}
Messaging options: %{profile_url}
'
navigation:
messages: Messages
simple_form:
hints:
message:
private: Message doesnt show in Foodsoft mail inbox

View file

@ -1,5 +0,0 @@
Rails.application.routes.draw do
scope '/:foodcoop' do
resources :messages, :only => [:index, :show, :new, :create]
end
end

View file

@ -1,24 +0,0 @@
# This migration has a ".skip" suffix to prevent it from being recognised as
# a migration. While this migration is relevant for the messages plugin, it
# was already included in stock foodsoft when messages were part of its core.
# `rake db:install:migrations` would install this migration, resulting in an
# attempt to create an already existing messages table.
#
# extracted from 20090120184410_road_to_version_three.rb
class CreateMessages < ActiveRecord::Migration
def self.up
create_table :messages do |t|
t.references :sender
t.text :recipients_ids
t.string :subject, :null => false
t.text :body
t.integer :email_state, :default => 0, :null => false
t.boolean :private, :default => false
t.datetime :created_at
end
end
def self.down
drop_table :messages
end
end

View file

@ -1,23 +0,0 @@
$:.push File.expand_path("../lib", __FILE__)
# Maintain your gem's version:
require "foodsoft_messages/version"
# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
s.name = "foodsoft_messages"
s.version = FoodsoftMessages::VERSION
s.authors = ["robwa"]
s.email = ["foodsoft-messages@ini.tiative.net"]
s.homepage = "https://github.com/foodcoops/foodsoft"
s.summary = "Messaging plugin for foodsoft."
s.description = "Adds the ability to exchange messages 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_development_dependency "sqlite3"
end

View file

@ -1,11 +0,0 @@
require "foodsoft_messages/engine"
require "foodsoft_messages/user_link"
require "deface"
module FoodsoftMessages
# Return whether messages are used or not.
# Enabled by default in {FoodsoftConfig} since it used to be part of the foodsoft core.
def self.enabled?
FoodsoftConfig[:use_messages]
end
end

View file

@ -1,19 +0,0 @@
module FoodsoftMessages
class Engine < ::Rails::Engine
def navigation(primary, context)
return unless FoodsoftMessages.enabled?
return if primary[:foodcoop].nil?
sub_nav = primary[:foodcoop].sub_navigation
sub_nav.items <<
SimpleNavigation::Item.new(primary, :messages, I18n.t('navigation.messages'), context.messages_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
def default_foodsoft_config(cfg)
cfg[:use_messages] = true
end
end
end

View file

@ -1,26 +0,0 @@
module FoodsoftMessages
module UserLink
def self.included(base) # :nodoc:
base.class_eval do
# modify user presentation link to writing a message for the user
def show_user_link(user=@current_user)
if user.nil? or not FoodsoftMessages.enabled?
show_user user
else
link_to show_user(user), new_message_path('message[mail_to]' => user.id),
:title => I18n.t('helpers.messages.write_message')
end
end
end
end
end
end
# modify existing helper
ActiveSupport.on_load(:after_initialize) do
ApplicationHelper.send :include, FoodsoftMessages::UserLink
end

View file

@ -1,3 +0,0 @@
module FoodsoftMessages
VERSION = "0.0.1"
end

View file

@ -1,21 +0,0 @@
FoodsoftWiki
============
This plugin adds wiki pages to foodsoft. A new 'Wiki' menu is added next to
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
# we use the git version of acts_as_versioned, so this needs to be in foodsoft's Gemfile
gem 'acts_as_versioned', git: 'git://github.com/technoweenie/acts_as_versioned.git'
gem 'foodsoft_wiki', path: 'lib/foodsoft_wiki'
```
This plugin introduces the foodcoop config option `use_wiki`, which can be set
to `false` to disable the wiki. 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).

View file

@ -1,40 +0,0 @@
#!/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 = 'FoodsoftWiki'
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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 689 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -1,143 +0,0 @@
# encoding: utf-8
class PagesController < ApplicationController
before_filter -> { require_plugin_enabled FoodsoftWiki }
skip_before_filter :authenticate, :only => :all
before_filter :only => :all do
authenticate_or_token(['wiki', 'all'])
end
before_filter do
content_for :head, view_context.rss_meta_tag
end
def index
@page = Page.find_by_permalink "Home"
if @page
render :action => 'show'
else
redirect_to all_pages_path
end
end
def show
if params[:permalink]
@page = Page.find_by_permalink(params[:permalink])
elsif params[:id]
page = Page.find_by_id(params[:id])
if page.nil?
flash[:error] = I18n.t('pages.cshow.error_noexist')
redirect_to all_pages_path and return
else
redirect_to wiki_page_path(page.permalink) and return
end
end
if @page.nil?
redirect_to new_page_path(:title => params[:permalink])
elsif @page.redirect?
page = Page.find_by_id(@page.redirect)
unless page.nil?
flash[:notice] = I18n.t('pages.cshow.redirect_notice', :page => @page.title)
redirect_to wiki_page_path(page.permalink)
end
end
end
def new
@page = Page.new
@page.title = params[:title].gsub("_", " ") if params[:title]
@page.parent = Page.find_by_permalink(params[:parent]) if params[:parent]
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @page }
end
end
def edit
@page = Page.find(params[:id])
end
def create
@page = Page.new(params[:page].merge({:user => current_user}))
if params[:preview]
render :action => 'new'
else
if @page.save
flash[:notice] = I18n.t('pages.create.notice')
redirect_to(wiki_page_path(@page.permalink))
else
render :action => "new"
end
end
end
def update
@page = Page.find(params[:id])
@page.attributes = params[:page].merge({:user => current_user})
if params[:preview]
@page.attributes = params[:page]
render :action => 'edit'
else
if @page.save
@page.parent_id = parent_id if (!params[:parent_id].blank? \
and params[:parent_id] != @page_id)
flash[:notice] = I18n.t('pages.update.notice')
redirect_to wiki_page_path(@page.permalink)
else
render :action => "edit"
end
end
rescue ActiveRecord::StaleObjectError
flash[:error] = I18n.t('pages.error_stale_object')
redirect_to wiki_page_path(@page.permalink)
end
def destroy
@page = Page.find(params[:id])
@page.destroy
flash[:notice] = I18n.t('pages.destroy.notice', :page => @page.title)
redirect_to wiki_path
end
def all
@pages = Page.non_redirected
@partial = params[:view] || 'recent_changes'
if params[:name]
@pages = @pages.where("title LIKE ?", "%#{params[:name]}%").limit(20).order('updated_at DESC')
@partial = 'title_list'
else
order = case @partial
when 'recent_changes' then
'updated_at DESC'
when 'site_map' then
'created_at DESC'
when 'title_list' then
'title DESC'
end
@pages.order(order)
end
respond_to do |format|
format.html
format.rss { render :layout => false }
end
end
def version
@page = Page.find(params[:id])
@version = Page::Version.find_by_page_id_and_lock_version params[:id], params[:version]
end
def revert
@page = Page.find(params[:id])
@page.revert_to!(params[:version].to_i)
redirect_to wiki_page_path(@page.permalink)
end
end

View file

@ -1,82 +0,0 @@
module PagesHelper
include WikiCloth
def rss_meta_tag
tag('link', :rel => "alternate", :type => "application/rss+xml", :title => "RSS", :href => all_pages_rss_url).html_safe
end
def wikified_body(body, title = nil)
WikiCloth.new(:data => body+"\n",
:link_handler => Wikilink.new,
:params => {:referer => title})
.to_html(wikicloth_render_options)
.html_safe
rescue => e
"<span class='alert alert-error'>#{t('.wikicloth_exception', :msg => e)}</span>".html_safe # try the following with line breaks: === one === == two == = three =
end
def link_to_wikipage(page, text = nil)
if text == nil
link_to page.title, wiki_page_path(:permalink => page.permalink)
else
link_to text, wiki_page_path(:permalink => page.permalink)
end
end
def link_to_wikipage_by_permalink(permalink, text = nil)
unless permalink.blank?
page = Page.find_by_permalink(permalink)
if page.nil?
if text.nil?
link_to permalink, new_page_path(:title => permalink)
else
link_to text, new_page_path(:title => permalink)
end
else
link_to_wikipage(page, text)
end
end
end
def generate_toc(body)
toc = String.new
body.gsub(/^([=]{1,6})\s*(.*?)\s*(\1)/) do
number = $1.length - 1
name = $2
toc << "*" * number + " #{name}\n"
end
unless toc.blank?
WikiCloth.new(:data => toc,
:link_handler => Wikilink.new)
.to_html(wikicloth_render_options)
.gsub(/<li>([^<>\n]*)/) do
name = $1
anchor = name.gsub(/\s/, '_').gsub(/[^a-zA-Z_]/, '')
"<li><a href='##{anchor}'>#{name.truncate(20)}</a>"
end.html_safe
end
end
def parent_pages_to_select(current_page)
unless current_page.homepage? # Homepage is the page trees root!
Page.non_redirected.reject { |p| p == current_page or p.ancestors.include?(current_page) }
else
Array.new
end
end
# return url for all_pages rss feed
def all_pages_rss_url(options={})
token = TokenVerifier.new(['wiki', 'all']).generate
all_pages_url({:format => 'rss', :token => token}.merge(options))
end
private
def wikicloth_render_options
{:locale => I18n.locale} # workaround for wikicloth 0.8.0 https://github.com/nricciar/wikicloth/pull/59
end
end

View file

@ -1,74 +0,0 @@
class Page < ActiveRecord::Base
include ActsAsTree
belongs_to :user, :foreign_key => 'updated_by'
acts_as_versioned version_column: :lock_version, limit: 20
self.non_versioned_columns += %w(permalink created_at title)
acts_as_tree :order => "title"
attr_accessor :old_title # Save title to create redirect page when editing title
validates_presence_of :title, :body
validates_uniqueness_of :permalink, :title
before_validation :set_permalink, :on => :create
before_validation :update_permalink, :on => :update
after_update :create_redirect
scope :non_redirected, -> { where(:redirect => nil) }
scope :no_parent, -> { where(:parent_id => nil) }
def self.permalink(title)
title.gsub(/[\/\.,;@\s]/, "_").gsub(/[\"\']/, "")
end
def homepage?
permalink == "Home"
end
def set_permalink
unless title.blank?
self.permalink = Page.count == 0 ? "Home" : Page.permalink(title)
end
end
def diff
current = versions.latest
old = versions.where(["page_id = ? and lock_version < ?", current.page_id, current.lock_version]).order('lock_version DESC').first
if old
o = ''
Diffy::Diff.new(old.body, current.body).each do |line|
case line
when /^\+/ then o += "#{line.chomp}<br />" unless line.chomp == "+"
when /^-/ then o += "#{line.chomp}<br />" unless line.chomp == "-"
end
end
o
else
current.body
end
end
protected
def update_permalink
if changed.include?("title")
set_permalink
self.old_title = changes["title"].first # Save title for creating redirect
end
end
def create_redirect
unless old_title.blank?
Page.create :redirect => id,
:title => old_title,
:body => I18n.t('model.page.redirect', :title => title),
:permalink => Page.permalink(old_title),
:updated_by => updated_by
end
end
end

View file

@ -1,9 +0,0 @@
- content = wikified_body @page.body, @page.title
- toc = generate_toc @page.body
- unless toc.blank? or params[:preview]
- content_for :sidebar do
#wikitoc.well.well-small
%h3= t '.title_toc'
= toc
= content

View file

@ -1,85 +0,0 @@
- if params[:preview]
%section#wikiContent
= render 'body'
.row-fluid
.span8
= simple_form_for @page do |f|
= f.hidden_field :lock_version
= f.input :title, input_html: {class: 'input-xxlarge'}
= f.input :body, input_html: {class: 'input-xxlarge', rows: 20}
= f.input :parent_id, as: :select, collection: parent_pages_to_select(@page)
.form-actions
= button_tag :name => 'preview', class: 'btn' do
%i.icon-search= t '.preview'
= button_tag class: 'btn' do
%i.icon-save= t 'ui.save'
= link_to t('ui.or_cancel'), @page
.span4
%h3= t '.help.title'
%table.table
%tbody
%tr
%td(colspan=2)
%b= t '.help.section_character'
%tr
%td
%i= t '.help.italic'
%td
%pre
''#{t '.help.italic'}''<br />
%tr
%td
%b= t '.help.bold'
%td
%pre '''#{t '.help.bold'}'''<br />
%tr
%td= t '.help.noformat'
%td
%pre &lt;nowiki&gt;#{t '.help.text'}&lt;/nowiki&gt;
%tr
%td(colspan=2)
%b= t '.help.section_block'
%tr
%td= t '.help.headings'
%td
%pre
\== #{t '.help.heading', level: 1} ==
%pre
\=== #{t '.help.heading', level: 2} ===
%pre
\==== #{t '.help.heading', level: 3} ====
%tr
%td= t '.help.unordered_list'
%td
%pre
* #{t '.help.list_item_1'}
%pre
** #{t '.help.list_item_2'}
%tr
%td= t '.help.ordered_list'
%td
%pre
\# #{t '.help.list_item_1'}
%pre
\# #{t '.help.list_item_2'}
%tr
%td(colspan=2)
%b= t '.help.section_link'
%tr
%td= t '.help.wiki_links'
%td
%pre
[[#{t '.help.wiki_link_ex'}]]
%tr
%td= t '.help.external_links'
%td
%pre
[http://example.net #{t '.help.external_link_ex'}]
%tr
%td(colspan=2)
%b= t '.help.section_table'
%tr
%td!= t '.help.see_tables', tables_link: link_to(t('.help.tables_link'), "http://www.mediawiki.org/wiki/Help:Tables", :target => '_blank')

View file

@ -1,8 +0,0 @@
-ident = 20 * level
%tr
%td{:style => "padding-left: #{ident}px"}
= link_to page.title, wiki_page_path(page.permalink)
%td #{show_user page.user} (#{format_datetime_timespec(page.updated_at, t('.date_format'))})
-if siteMap == 1
-for child in page.children.all
= render :partial => 'page_list_item', :locals => {:page => child, :level => level+1, :siteMap => 1}

View file

@ -1,8 +0,0 @@
%table.table.table-striped
%thead
%tr
%th= t 'pages.title'
%th= t 'pages.last_updated'
%tbody
- for page in @pages
= render :partial => "page_list_item", :locals => {:page => page, :level => 0, :siteMap => 0}

View file

@ -1,12 +0,0 @@
%table.table.table-striped
%thead
%tr
%th= t 'pages.title'
%th= t 'pages.last_updated'
- homepage = Page.find_by_permalink('Home')
- unless homepage.nil?
= render :partial => 'page_list_item', :locals => {:page => homepage, :level => 0, :siteMap => 1}
%tbody
- for page in @pages
- if page.id != homepage.try(:id)
= render :partial => 'page_list_item', :locals => {:page => page, :level => 0, :siteMap => 1}

View file

@ -1,8 +0,0 @@
%table.table.table-striped
%thead
%tr
%th= t 'pages.title'
%th= t 'pages.last_updated'
%tbody
- for page in @pages
= render :partial => "page_list_item", :locals => {:page => page, :level => 0, :siteMap => 0}

View file

@ -1,18 +0,0 @@
- title t('.title'), false
- content_for :sidebar do
= link_to t('.new_page'), new_page_path, class: 'btn btn-primary'
.navbar
.navbar-inner
%ul.nav
%li= link_to t('.recent_changes'), all_pages_path(:view => 'recent_changes')
%li= link_to t('.title_list'), all_pages_path(:view => 'title_list')
%li= link_to t('.site_map'), all_pages_path(:view => 'site_map')
%li= link_to image_tag('icons/feed-icon-14x14.png', :alt => 'RSS Feed'), all_pages_rss_url
= form_tag all_pages_path, method: :get, class: 'form-search pull-right' do
= text_field_tag :name, params[:name], class: 'input-medium search-query',
placeholder: t('.search.placeholder')
= submit_tag t('.search.action'), class: 'btn'
= render @partial

View file

@ -1,19 +0,0 @@
xml.instruct! :xml, :version => "1.0"
xml.rss :version => "2.0" do
xml.channel do
xml.title FoodsoftConfig[:name] + " Wiki"
xml.description ""
xml.link FoodsoftConfig[:homepage]
for page in @pages
xml.item do
xml.title page.title
xml.description page.diff, :type => "html"
xml.author User.find_by_id(page.updated_by).try(:display)
xml.pubDate page.updated_at.to_s(:rfc822)
xml.link wiki_page_path(page.permalink)
xml.guid page.updated_at.to_i
end
end
end
end

View file

@ -1,3 +0,0 @@
- title t('.title')
= render 'form'

View file

@ -1,3 +0,0 @@
- title t('.title')
= render 'form'

View file

@ -1,51 +0,0 @@
- title @page.title, false
- content_for :sidebar do
%p
= link_to edit_page_path(@page), class: 'btn btn-primary' do
%i.icon-edit= t '.edit'
.well.well-small
%ul.nav.nav-list
%li
%li= link_to t('.versions', count: @page.versions.count), "#versions", 'data-toggle-this' => '#versions'
- unless @page.children.empty?
%li= link_to t('.subpages'), "#subpages", 'data-toggle-this' => '#subpages'
#versions.well.well-small{:style => "display:none"}
%h3= t '.title_versions'
%ul.unstyled
- @page.versions.reverse.each do |version|
%li
= link_to I18n.l(version.updated_at, :format => t('.date_format')), version_page_path(@page, :version => version.lock_version)
= "(#{show_user(User.find_by_id(version.updated_by))})"
- unless @page.children.empty?
#subpages.well.well-small{:style => "display:none"}
%h3= t '.subpages'
%ul.unstyled
- @page.children.each do |page|
%li= link_to_wikipage(page)
%ul.breadcrumb
%li
= link_to_wikipage_by_permalink("Home", "Foodcoop-Wiki")
%span.divider /
- for page in @page.ancestors.reverse
%li
= link_to_wikipage(page)
%span.divider /
%li.active= @page.title
#wikiContent
.page-header
%h1= @page.title
= render :partial => 'body'
%hr.clear/
%p
= link_to edit_page_path(@page), class: 'btn btn-primary' do
%i.icon-edit= t '.edit'
= link_to t('.delete'), @page, class: 'btn btn-danger', :method => :delete,
:data => {:confirm => t('.delete_confirm')}
!= '| ' + t('.last_updated', user: show_user(@page.user), when: format_datetime(@page.updated_at))

View file

@ -1,11 +0,0 @@
- title t('.title', title: @page.title, version: @version.lock_version)
- content_for :sidebar do
%h3= t '.title_version'
%b= "#{format_datetime_timespec(@version.updated_at, t('.date_format'))}"
%ul
%li= t '.author', user: show_user(User.find(@version.updated_by))
%li= link_to t('.view_current'), wiki_page_path(:permalink => @page.permalink)
%li= link_to t('.revert'), revert_page_path(@page, :version => @version.lock_version)
= wikified_body @version.body

View file

@ -1,85 +0,0 @@
en:
activerecord:
attributes:
page:
body: Body
parent_id: Parent page
title: Title
model:
page:
redirect: Redirect to [[%{title}]]...
navigation:
wiki:
all_pages: All Pages
home: Home
title: Wiki
pages:
all:
new_page: Create new page
recent_changes: Recent changes
search:
action: Search
placeholder: Page title ..
site_map: Sitemap
title: All Wiki pages
title_list: List of pages
body:
title_toc: Content
create:
notice: Page was created
cshow:
error_noexist: Page doesnt exist!
redirect_notice: Redirected from %{page} ...
destroy:
notice: The page '%{page}' and all subpages have been deleted successfully.
edit:
title: Edit page
error_stale_object: Warning, the page has just been edited by someone else. Please try again.
form:
help:
bold: bold
external_link_ex: External page
external_links: External links
heading: level %{level}
headings: Heading
italic: italic
list_item_1: First list item
list_item_2: Second list item
noformat: No wiki-formatting
ordered_list: Numbered list
section_block: Block formatting
section_character: Character formatting
section_link: Link formatting
section_table: Table formatting
see_tables: see %{tables_link}
tables_link: Tables
text: text
title: Quick formatting help
unordered_list: Item list
wiki_link_ex: Foodsoft Wiki Page
wiki_links: Wiki-links
preview: Preview
last_updated: Last updated
new:
title: Create new wiki page
page_list_item:
date_format: ! '%a, %d %B %Y %H:%M:%S'
show:
date_format: ! '%d-%m-%y %H:%M'
delete: Delete page
delete_confirm: ! 'Warning: all subpages will be deleted as well. Are you sure?'
edit: Edit page
last_updated: Last updated by <b>%{user}</b> on %{when}
subpages: subpages
title_versions: Versions
versions: Versions (%{count})
title: Title
update:
notice: Page was updated
version:
author: ! 'Author: %{user}'
date_format: ! '%a, %d-%m-%Y, %H:%M'
revert: Revert to this version
title: ! '%{title} - version %{version}'
title_version: Version
view_current: See current version

View file

@ -1,15 +0,0 @@
Rails.application.routes.draw do
scope '/:foodcoop' do
resources :pages do
get :all, :on => :collection
get :version, :on => :member
get :revert, :on => :member
end
get '/wiki/:permalink' => 'pages#show', :as => 'wiki_page' # , :constraints => {:permalink => /[^\s]+/}
get '/wiki' => 'pages#show', :defaults => {:permalink => 'Home'}, :as => 'wiki'
end
end

View file

@ -1,23 +0,0 @@
class CreatePages < ActiveRecord::Migration
def self.up
create_table :pages do |t|
t.string :title
t.text :body
t.string :permalink
t.integer :lock_version, :default => 0
t.integer :updated_by
t.integer :redirect
t.integer :parent_id
t.timestamps
end
add_index :pages, :title
add_index :pages, :permalink
Page.create_versioned_table # Automaticly creates pages_versions table
end
def self.down
drop_table :pages
Page.drop_versioned_table
end
end

View file

@ -1,25 +0,0 @@
$:.push File.expand_path("../lib", __FILE__)
# Maintain your gem's version:
require "foodsoft_wiki/version"
# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
s.name = "foodsoft_wiki"
s.version = FoodsoftWiki::VERSION
s.authors = ["wvengen"]
s.email = ["dev-foodsoft@willem.engen.nl"]
s.homepage = "https://github.com/foodcoops/foodsoft"
s.summary = "Wiki plugin for foodsoft."
s.description = "Adds a wiki to foodsoft."
s.files = Dir["{app,config,db,lib}/**/*"] + ["Rakefile", "README.md"]
s.test_files = Dir["test/**/*"]
s.add_dependency "rails"
s.add_dependency 'wikicloth'
s.add_dependency 'acts_as_versioned' # need git version, make sure that is included in foodsoft's Gemfile
s.add_dependency 'diffy'
s.add_dependency 'content_for_in_controllers'
s.add_development_dependency "sqlite3"
end

View file

@ -1,13 +0,0 @@
require 'wikicloth'
require 'acts_as_versioned'
require 'diffy'
require 'content_for_in_controllers'
require 'foodsoft_wiki/engine'
module FoodsoftWiki
# Return whether the wiki is used or not.
# Enabled by default in {FoodsoftConfig} since it used to be part of the foodsoft core.
def self.enabled?
FoodsoftConfig[:use_wiki]
end
end

View file

@ -1,19 +0,0 @@
module FoodsoftWiki
class Engine < ::Rails::Engine
def navigation(primary, ctx)
return unless FoodsoftWiki.enabled?
primary.item :wiki, I18n.t('navigation.wiki.title'), '#', id: nil do |subnav|
subnav.item :wiki_home, I18n.t('navigation.wiki.home'), ctx.wiki_path, id: nil
subnav.item :all_pages, I18n.t('navigation.wiki.all_pages'), ctx.all_pages_path, id: nil
end
# move this last added item to just after the foodcoop menu
if i = primary.items.index(primary[:foodcoop])
primary.items.insert(i+1, primary.items.delete_at(-1))
end
end
def default_foodsoft_config(cfg)
cfg[:use_wiki] = true
end
end
end

View file

@ -1,3 +0,0 @@
module FoodsoftWiki
VERSION = "0.0.1"
end