1
|
# ezFAQ plugin for redMine
|
2
|
# Copyright (C) 2008-2009 Zou Chaoqun
|
3
|
#
|
4
|
# This program is free software; you can redistribute it and/or
|
5
|
# modify it under the terms of the GNU General Public License
|
6
|
# as published by the Free Software Foundation; either version 2
|
7
|
# of the License, or (at your option) any later version.
|
8
|
#
|
9
|
# This program is distributed in the hope that it will be useful,
|
10
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
# GNU General Public License for more details.
|
13
|
#
|
14
|
# You should have received a copy of the GNU General Public License
|
15
|
# along with this program; if not, write to the Free Software
|
16
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
17
|
|
18
|
class EzfaqController < ApplicationController
|
19
|
unloadable
|
20
|
|
21
|
layout 'base'
|
22
|
before_filter :find_project, :authorize
|
23
|
before_filter :find_faq, :only => [:show, :edit, :copy, :destroy, :history, :show_history_version]
|
24
|
|
25
|
helper :attachments
|
26
|
include AttachmentsHelper
|
27
|
helper :messages
|
28
|
include MessagesHelper
|
29
|
helper :sort
|
30
|
include SortHelper
|
31
|
include Redmine::Export::PDF
|
32
|
|
33
|
def index
|
34
|
@categorized_faqs = Faq.find(:all, :conditions => "project_id = #{@project.id} and category_id is not null and is_valid = true")
|
35
|
@not_categorized_faqs = Faq.find(:all, :conditions => "project_id = #{@project.id} and category_id is null and is_valid = true", :order => "question")
|
36
|
@faq_setting = FaqSetting.find(:first, :conditions => "project_id = #{@project.id}")
|
37
|
|
38
|
respond_to do |format|
|
39
|
format.html { render :template => 'ezfaq/index.html.erb', :layout => !request.xhr? }
|
40
|
format.pdf { send_data(faqs_to_pdf, :type => 'application/pdf', :filename => "#{@project}-faq.pdf") }
|
41
|
end
|
42
|
end
|
43
|
|
44
|
def list_invalid_faqs
|
45
|
sort_init "updated_on", "desc"
|
46
|
sort_update %w(id question category_id viewed_count author_id updated_on)
|
47
|
@invalid_faqs = Faq.find(:all, :conditions => "project_id = #{@project.id} and is_valid = false", :order => sort_clause)
|
48
|
|
49
|
render(:template => 'ezfaq/list_invalid_faqs.html.erb', :layout => !request.xhr?)
|
50
|
end
|
51
|
|
52
|
def show
|
53
|
@faq.viewed_count += 1
|
54
|
Faq.update_all("viewed_count = #{@faq.viewed_count}", "id = #{@faq.id}")
|
55
|
@faq_categories = FaqCategory.find(:all, :conditions => "project_id = #{@project.id}", :order => "position")
|
56
|
|
57
|
respond_to do |format|
|
58
|
format.html { render :template => 'ezfaq/show.html.erb', :layout => !request.xhr? }
|
59
|
format.pdf { send_data(faq_to_pdf, :type => 'application/pdf', :filename => "#{@project}-faq-#{@faq.id}.pdf") }
|
60
|
end
|
61
|
end
|
62
|
|
63
|
def new
|
64
|
@faq_categories = FaqCategory.find(:all, :conditions => "project_id = #{@project.id}", :order => "position")
|
65
|
@faq = Faq.new(params[:faq])
|
66
|
@faq.project_id = @project.id
|
67
|
|
68
|
if request.get? || request.xhr?
|
69
|
@faq.difficulty = 5
|
70
|
|
71
|
else
|
72
|
@faq.author_id = User.current.id
|
73
|
@faq.updater_id = User.current.id
|
74
|
@faq.is_valid = false
|
75
|
@faq.viewed_count = 0
|
76
|
if @faq.save
|
77
|
attachments = Attachment.attach_files(@faq, params[:attachments])
|
78
|
flash[:notice] = l(:notice_successful_create)
|
79
|
FaqMailer.deliver_faq_add(@project, @faq)
|
80
|
redirect_to :controller => 'ezfaq', :action => 'show', :id => @project, :faq_id => @faq
|
81
|
return
|
82
|
end
|
83
|
end
|
84
|
end
|
85
|
|
86
|
# Action to preview the FAQ answer
|
87
|
def preview
|
88
|
@text = params[:faq][:answer]
|
89
|
render :partial => 'common/preview'
|
90
|
end
|
91
|
|
92
|
def edit
|
93
|
@faq_categories = FaqCategory.find(:all, :conditions => "project_id = #{@project.id}", :order => "position")
|
94
|
|
95
|
if request.post?
|
96
|
@faq.attributes = params[:faq]
|
97
|
@faq.updater_id = User.current.id
|
98
|
if @faq.save
|
99
|
attachments = Attachment.attach_files(@faq, params[:attachments])
|
100
|
flash[:notice] = l(:notice_successful_update)
|
101
|
FaqMailer.deliver_faq_update(@project, @faq)
|
102
|
redirect_to :controller => 'ezfaq', :action => 'show', :id => @project, :faq_id => @faq
|
103
|
return
|
104
|
end
|
105
|
end
|
106
|
rescue ActiveRecord::StaleObjectError
|
107
|
# Optimistic locking exception
|
108
|
flash.now[:error] = l(:notice_locking_conflict)
|
109
|
end
|
110
|
|
111
|
def copy
|
112
|
@allowed_projects = []
|
113
|
# find projects to which the user is allowed to copy the faq
|
114
|
if User.current.admin?
|
115
|
# admin is allowed to copy faqs to any active (visible) project
|
116
|
@allowed_projects = Project.find(:all, :conditions => Project.visible_by(User.current))
|
117
|
else
|
118
|
User.current.memberships.each {|m| @allowed_projects << m.project if m.role.allowed_to?(:edit_faqs)}
|
119
|
end
|
120
|
@target_project = @allowed_projects.detect {|p| p.id.to_s == params[:new_project_id]} if params[:new_project_id]
|
121
|
@target_project ||= @project
|
122
|
if request.post?
|
123
|
@faq.copy(@target_project)
|
124
|
flash[:notice] = l(:notice_successful_update)
|
125
|
redirect_to :controller => 'ezfaq', :action => 'index', :id => @project
|
126
|
return
|
127
|
end
|
128
|
render :layout => false if request.xhr?
|
129
|
end
|
130
|
|
131
|
def destroy
|
132
|
@faq.destroy
|
133
|
redirect_to :action => 'index', :id => @project
|
134
|
end
|
135
|
|
136
|
def history
|
137
|
limit = per_page_option
|
138
|
@version_count = @faq.versions.count
|
139
|
@version_pages = Paginator.new self, @version_count, limit, params['page']
|
140
|
@versions = @faq.versions.find :all, :order => 'version DESC',
|
141
|
:select => 'id, updater_id, updated_on, version',
|
142
|
:limit => limit,
|
143
|
:offset => @version_pages.current.offset
|
144
|
|
145
|
render :layout => false if request.xhr?
|
146
|
end
|
147
|
|
148
|
def show_history_version
|
149
|
@faq_version = @faq.versions.find_by_version(params[:version])
|
150
|
render_404 unless @faq_version
|
151
|
end
|
152
|
|
153
|
def add_faq_category
|
154
|
@category = FaqCategory.new(params[:category])
|
155
|
@category.project_id = @project.id
|
156
|
if request.post? and @category.save
|
157
|
respond_to do |format|
|
158
|
format.html do
|
159
|
flash[:notice] = l(:notice_successful_create)
|
160
|
redirect_to :controller => 'faq_categories', :action => 'index', :id => @project
|
161
|
end
|
162
|
format.js do
|
163
|
faq_categories = FaqCategory.find(:all, :conditions => "project_id = #{@project.id}")
|
164
|
render(:update) {|page| page.replace "faq_category_id",
|
165
|
content_tag('select', '<option></option>' + options_from_collection_for_select(faq_categories, 'id', 'name', @category.id), :id => 'faq_category_id', :name => 'faq[category_id]')
|
166
|
}
|
167
|
end
|
168
|
end
|
169
|
end
|
170
|
end
|
171
|
|
172
|
def faq_setting
|
173
|
@faq_setting = FaqSetting.find(:first, :conditions => "project_id = #{@project.id}")
|
174
|
if !@faq_setting && request.get?
|
175
|
@faq_setting = FaqSetting.new
|
176
|
elsif request.post?
|
177
|
if !@faq_setting
|
178
|
@faq_setting = FaqSetting.new(params[:faq_setting])
|
179
|
else
|
180
|
@faq_setting.attributes = params[:faq_setting]
|
181
|
end
|
182
|
@faq_setting.project_id = @project.id
|
183
|
if @faq_setting.save
|
184
|
redirect_to :action => 'index', :id => @project
|
185
|
return
|
186
|
end
|
187
|
end
|
188
|
end
|
189
|
|
190
|
private
|
191
|
def find_project
|
192
|
@project = Project.find(params[:id])
|
193
|
rescue ActiveRecord::RecordNotFound
|
194
|
render_404
|
195
|
end
|
196
|
|
197
|
def find_faq
|
198
|
@faq = Faq.find(:first, :conditions => "project_id = #{@project.id} and id = #{params[:faq_id]}")
|
199
|
render_404 unless @faq
|
200
|
rescue
|
201
|
render_404
|
202
|
end
|
203
|
|
204
|
def faq_to_pdf
|
205
|
faq_setting = FaqSetting.find(:first, :conditions => "project_id = #{@project.id}")
|
206
|
|
207
|
pdf = IFPDF.new(current_language)
|
208
|
pdf.SetTitle("#{l(:label_faq)}-#{@faq.question}")
|
209
|
pdf.SetAuthor('ezFAQ for Redmine')
|
210
|
pdf.AliasNbPages
|
211
|
pdf.footer_date = format_date(Date.today)
|
212
|
pdf.AddPage
|
213
|
|
214
|
pdf.SetFontStyle('B',16)
|
215
|
pdf.Cell(200,5, faq_setting.pdf_title)
|
216
|
pdf.Ln(15)
|
217
|
|
218
|
pdf.SetFontStyle('B',11)
|
219
|
pdf.Cell(200,5, "#{l(:field_question)}: #{@faq.question}")
|
220
|
pdf.Ln
|
221
|
pdf.Line(pdf.GetX, pdf.GetY, 180, pdf.GetY)
|
222
|
pdf.Ln
|
223
|
pdf.SetFontStyle('',11)
|
224
|
pdf.MultiCell(200,5, @faq.answer)
|
225
|
pdf.Ln
|
226
|
|
227
|
pdf.Line(pdf.GetX, pdf.GetY, 100, pdf.GetY)
|
228
|
pdf.SetFontStyle('I',8)
|
229
|
pdf.Cell(200,5, 'Auto generated faq-document by ezFAQ. Powered by ezWORK & Redmine.')
|
230
|
|
231
|
pdf.Output
|
232
|
end
|
233
|
|
234
|
def faqs_to_pdf
|
235
|
pdf = IFPDF.new(current_language)
|
236
|
pdf.SetTitle(@faq_setting.pdf_title) if (@faq_setting && @faq_setting.pdf_title)
|
237
|
pdf.SetAuthor('ezFAQ for Redmine')
|
238
|
pdf.AliasNbPages
|
239
|
pdf.footer_date = format_date(Date.today)
|
240
|
pdf.AddPage
|
241
|
|
242
|
pdf.SetFontStyle('B',16)
|
243
|
if (@faq_setting && @faq_setting.pdf_title)
|
244
|
pdf.Cell(200,5, @faq_setting.pdf_title)
|
245
|
else
|
246
|
pdf.Cell(200,5, l(:text_faq_pdf_title_not_set))
|
247
|
end
|
248
|
|
249
|
pdf.Ln(10)
|
250
|
pdf.SetFontStyle('',11)
|
251
|
pdf.MultiCell(180,5, @faq_setting.note) if (@faq_setting && @faq_setting.note)
|
252
|
pdf.Ln
|
253
|
pdf.Line(pdf.GetX, pdf.GetY, 180, pdf.GetY)
|
254
|
pdf.Ln
|
255
|
|
256
|
list_number = 1
|
257
|
if @categorized_faqs.any?
|
258
|
@categorized_faqs.group_by(&:category).sort.each do |category, faqs|
|
259
|
pdf.SetFontStyle('BI', 13)
|
260
|
pdf.Cell(200,5, "#{list_number}. #{category.name}")
|
261
|
pdf.Ln
|
262
|
faq_number = 1
|
263
|
for faq in faqs.sort
|
264
|
pdf.SetFontStyle('B',11)
|
265
|
pdf.Cell(200,5, "#{list_number}.#{faq_number} #{faq.question}")
|
266
|
pdf.Ln
|
267
|
pdf.SetFontStyle('',11)
|
268
|
pdf.MultiCell(200,5, faq.answer)
|
269
|
pdf.Ln
|
270
|
faq_number += 1
|
271
|
end
|
272
|
pdf.Ln
|
273
|
list_number += 1
|
274
|
end
|
275
|
end
|
276
|
|
277
|
if @not_categorized_faqs.any?
|
278
|
pdf.SetFontStyle('BI', 13)
|
279
|
pdf.Cell(200,5, "#{list_number}. #{l(:label_not_categorized)}")
|
280
|
pdf.Ln
|
281
|
faq_number = 1
|
282
|
for faq in @not_categorized_faqs.sort
|
283
|
pdf.SetFontStyle('B',11)
|
284
|
pdf.Cell(200,5, "#{list_number}.#{faq_number} #{faq.question}")
|
285
|
pdf.Ln
|
286
|
pdf.SetFontStyle('',11)
|
287
|
pdf.MultiCell(200,5, faq.answer)
|
288
|
pdf.Ln(10)
|
289
|
faq_number += 1
|
290
|
end
|
291
|
end
|
292
|
|
293
|
pdf.Line(pdf.GetX, pdf.GetY, 100, pdf.GetY)
|
294
|
pdf.SetFontStyle('I',8)
|
295
|
pdf.Cell(200,5, 'Auto generated faq-list by ezFAQ. Powered by ezWORK & Redmine.')
|
296
|
|
297
|
pdf.Output
|
298
|
end
|
299
|
end
|