openproject-meeting 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/CHANGELOG.md +46 -0
- data/README.md +82 -0
- data/app/assets/images/meeting/agenda.png +0 -0
- data/app/assets/images/meeting/meeting.png +0 -0
- data/app/assets/images/meeting/minutes.png +0 -0
- data/app/assets/stylesheets/meeting/meeting.css.erb +39 -0
- data/app/controllers/meeting_agendas_controller.rb +33 -0
- data/app/controllers/meeting_contents_controller.rb +95 -0
- data/app/controllers/meeting_minutes_controller.rb +22 -0
- data/app/controllers/meetings_controller.rb +150 -0
- data/app/helpers/meeting_contents_helper.rb +68 -0
- data/app/helpers/meetings_helper.rb +16 -0
- data/app/mailers/meeting_mailer.rb +28 -0
- data/app/models/meeting.rb +163 -0
- data/app/models/meeting_agenda.rb +95 -0
- data/app/models/meeting_content.rb +67 -0
- data/app/models/meeting_minutes.rb +81 -0
- data/app/models/meeting_participant.rb +45 -0
- data/app/views/hooks/_activity_index_head.html.erb +13 -0
- data/app/views/meeting_contents/_form.html.erb +33 -0
- data/app/views/meeting_contents/_show.html.erb +40 -0
- data/app/views/meeting_contents/diff.html.erb +33 -0
- data/app/views/meeting_contents/history.html.erb +49 -0
- data/app/views/meeting_contents/show.html.erb +13 -0
- data/app/views/meeting_mailer/content_for_review.html.erb +23 -0
- data/app/views/meeting_mailer/content_for_review.text.erb +9 -0
- data/app/views/meetings/_form.html.erb +61 -0
- data/app/views/meetings/edit.html.erb +17 -0
- data/app/views/meetings/index.html.erb +51 -0
- data/app/views/meetings/new.html.erb +17 -0
- data/app/views/meetings/show.html.erb +48 -0
- data/app/views/shared/_meeting_header.html.erb +3 -0
- data/config/locales/de.yml +47 -0
- data/config/locales/en.yml +47 -0
- data/config/routes.rb +53 -0
- data/db/migrate/20110106210555_create_meetings.rb +29 -0
- data/db/migrate/20110106221214_create_meeting_contents.rb +29 -0
- data/db/migrate/20110106221946_create_meeting_content_versions.rb +20 -0
- data/db/migrate/20110108230721_create_meeting_participants.rb +30 -0
- data/db/migrate/20110224180804_add_lock_to_meeting_content.rb +24 -0
- data/db/migrate/20110819162852_create_initial_meeting_journals.rb +49 -0
- data/db/migrate/20111605171815_merge_meeting_content_versions_with_journals.rb +65 -0
- data/db/migrate/20130731151542_remove_meeting_role_id_from_meeting_participants.rb +20 -0
- data/lib/open_project/meeting.rb +16 -0
- data/lib/open_project/meeting/engine.rb +101 -0
- data/lib/open_project/meeting/hooks.rb +17 -0
- data/lib/open_project/meeting/patches/project_patch.rb +24 -0
- data/lib/open_project/meeting/version.rb +16 -0
- data/lib/openproject-meeting.rb +12 -0
- data/spec/controllers/meetings_controller_spec.rb +90 -0
- data/spec/factories/meeting_agenda_factory.rb +16 -0
- data/spec/factories/meeting_agenda_journal_factory.rb +18 -0
- data/spec/factories/meeting_factory.rb +18 -0
- data/spec/factories/meeting_minutes_factory.rb +16 -0
- data/spec/factories/meeting_minutes_journal_factory.rb +18 -0
- data/spec/factories/meeting_participant_factory.rb +17 -0
- data/spec/mailers/meeting_mailer_spec.rb +101 -0
- data/spec/models/meeting_agenda_journal_spec.rb +21 -0
- data/spec/models/meeting_agenda_spec.rb +52 -0
- data/spec/models/meeting_minutes_journal_spec.rb +21 -0
- data/spec/models/meeting_minutes_spec.rb +44 -0
- data/spec/models/meeting_spec.rb +168 -0
- data/spec/models/user_deletion_spec.rb +186 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/plugin_spec_helper.rb +47 -0
- metadata +158 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
#-- copyright
|
2
|
+
# OpenProject is a project management system.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2012-2013 the OpenProject Team
|
5
|
+
#
|
6
|
+
# This program is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU General Public License version 3.
|
8
|
+
#
|
9
|
+
# See doc/COPYRIGHT.rdoc for more details.
|
10
|
+
#++
|
11
|
+
|
12
|
+
module MeetingContentsHelper
|
13
|
+
def can_edit_meeting_content?(content, content_type)
|
14
|
+
authorize_for(content_type.pluralize, 'update') && content.editable?
|
15
|
+
end
|
16
|
+
|
17
|
+
def saved_meeting_content_text_present?(content)
|
18
|
+
!content.new_record? && content.text.present? && !content.text.empty?
|
19
|
+
end
|
20
|
+
|
21
|
+
def show_meeting_content_editor?(content, content_type)
|
22
|
+
can_edit_meeting_content?(content, content_type) && (!saved_meeting_content_text_present?(content) || content.changed?)
|
23
|
+
end
|
24
|
+
|
25
|
+
def meeting_content_context_menu(content, content_type)
|
26
|
+
menu = []
|
27
|
+
menu << meeting_agenda_toggle_status_link(content, content_type)
|
28
|
+
menu << meeting_content_edit_link(content_type) if can_edit_meeting_content?(content, content_type)
|
29
|
+
menu << meeting_content_history_link(content_type, content.meeting)
|
30
|
+
menu << meeting_content_notify_link(content_type, content.meeting) if saved_meeting_content_text_present?(content)
|
31
|
+
menu.join(" ")
|
32
|
+
end
|
33
|
+
|
34
|
+
def meeting_agenda_toggle_status_link(content, content_type)
|
35
|
+
content.meeting.agenda.present? && content.meeting.agenda.locked? ?
|
36
|
+
open_meeting_agenda_link(content_type, content.meeting) :
|
37
|
+
close_meeting_agenda_link(content_type, content.meeting)
|
38
|
+
end
|
39
|
+
|
40
|
+
def close_meeting_agenda_link(content_type, meeting)
|
41
|
+
case content_type
|
42
|
+
when "meeting_agenda"
|
43
|
+
link_to_if_authorized l(:label_meeting_close), {:controller => '/meeting_agendas', :action => 'close', :meeting_id => meeting}, :method => :put, :class => "icon icon-lock show-meeting_agenda"
|
44
|
+
when "meeting_minutes"
|
45
|
+
link_to_if_authorized l(:label_meeting_agenda_close), {:controller => '/meeting_agendas', :action => 'close', :meeting_id => meeting}, :method => :put, :class => "icon icon-lock show-meeting_minutes"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def open_meeting_agenda_link(content_type, meeting)
|
50
|
+
case content_type
|
51
|
+
when "meeting_agenda"
|
52
|
+
link_to_if_authorized l(:label_meeting_open), {:controller => '/meeting_agendas', :action => 'open', :meeting_id => meeting}, :method => :put, :class => 'icon icon-unlock show-meeting_agenda', :confirm => l(:text_meeting_agenda_open_are_you_sure)
|
53
|
+
when "meeting_minutes"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def meeting_content_edit_link(content_type)
|
58
|
+
link_to l(:button_edit), "#", :class => "icon icon-edit show-#{content_type}", :accesskey => accesskey(:edit), :onclick => "$$('.edit-#{content_type}').invoke('show'); $$('.show-#{content_type}').invoke('hide'); return false;"
|
59
|
+
end
|
60
|
+
|
61
|
+
def meeting_content_history_link(content_type, meeting)
|
62
|
+
link_to_if_authorized l(:label_history), {:controller => '/' + content_type.pluralize, :action => 'history', :meeting_id => meeting}, :class => "icon icon-history show-#{content_type}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def meeting_content_notify_link(content_type, meeting)
|
66
|
+
link_to_if_authorized l(:label_notify), {:controller => '/' + content_type.pluralize, :action => 'notify', :meeting_id => meeting}, :method => :put, :class => "icon icon-notification show-#{content_type}"
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#-- copyright
|
2
|
+
# OpenProject is a project management system.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2012-2013 the OpenProject Team
|
5
|
+
#
|
6
|
+
# This program is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU General Public License version 3.
|
8
|
+
#
|
9
|
+
# See doc/COPYRIGHT.rdoc for more details.
|
10
|
+
#++
|
11
|
+
|
12
|
+
module MeetingsHelper
|
13
|
+
def format_participant_list(participants)
|
14
|
+
participants.sort.collect{|p| link_to_user p.user}.join("; ").html_safe
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#-- copyright
|
2
|
+
# OpenProject is a project management system.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2012-2013 the OpenProject Team
|
5
|
+
#
|
6
|
+
# This program is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU General Public License version 3.
|
8
|
+
#
|
9
|
+
# See doc/COPYRIGHT.rdoc for more details.
|
10
|
+
#++
|
11
|
+
|
12
|
+
class MeetingMailer < UserMailer
|
13
|
+
|
14
|
+
def content_for_review(content, content_type)
|
15
|
+
@meeting = content.meeting
|
16
|
+
@meeting_url = meeting_url @meeting
|
17
|
+
@project_url = project_url @meeting.project
|
18
|
+
@content_type = content_type
|
19
|
+
|
20
|
+
open_project_headers 'Project' => @meeting.project.identifier,
|
21
|
+
'Meeting-Id' => @meeting.id
|
22
|
+
|
23
|
+
recipients = @meeting.watcher_recipients.reject{|r| r == @meeting.author.mail}
|
24
|
+
|
25
|
+
subject = "[#{@meeting.project.name}] #{I18n.t(:"label_#{content_type}")}: #{@meeting.title}"
|
26
|
+
mail :to => @meeting.author.mail, :cc => recipients, :subject => subject
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
#-- copyright
|
2
|
+
# OpenProject is a project management system.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2012-2013 the OpenProject Team
|
5
|
+
#
|
6
|
+
# This program is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU General Public License version 3.
|
8
|
+
#
|
9
|
+
# See doc/COPYRIGHT.rdoc for more details.
|
10
|
+
#++
|
11
|
+
|
12
|
+
class Meeting < ActiveRecord::Base
|
13
|
+
|
14
|
+
self.table_name = 'meetings'
|
15
|
+
|
16
|
+
belongs_to :project
|
17
|
+
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
|
18
|
+
has_one :agenda, :dependent => :destroy, :class_name => 'MeetingAgenda'
|
19
|
+
has_one :minutes, :dependent => :destroy, :class_name => 'MeetingMinutes'
|
20
|
+
has_many :contents, :class_name => 'MeetingContent', :readonly => true
|
21
|
+
has_many :participants, :dependent => :destroy, :class_name => 'MeetingParticipant'
|
22
|
+
|
23
|
+
default_scope order("#{Meeting.table_name}.start_time DESC")
|
24
|
+
scope :from_tomorrow, :conditions => ['start_time >= ?', Date.tomorrow.beginning_of_day]
|
25
|
+
scope :with_users_by_date, order("#{Meeting.table_name}.title ASC")
|
26
|
+
.includes({:participants => :user}, :author)
|
27
|
+
|
28
|
+
attr_accessible :title, :location, :start_time, :duration
|
29
|
+
|
30
|
+
acts_as_watchable
|
31
|
+
|
32
|
+
acts_as_searchable :columns => ["#{table_name}.title", "#{MeetingContent.table_name}.text"],
|
33
|
+
:include => [:contents, :project],
|
34
|
+
:date_column => "#{table_name}.created_at"
|
35
|
+
|
36
|
+
acts_as_journalized :activity_find_options => {:include => [:agenda, :author, :project]},
|
37
|
+
:event_title => Proc.new {|o| "#{l :label_meeting}: #{o.title} (#{format_date o.start_time} #{format_time o.start_time, false}-#{format_time o.end_time, false})"},
|
38
|
+
:event_url => Proc.new {|o| {:controller => '/meetings', :action => 'show', :id => o.journaled}}
|
39
|
+
|
40
|
+
register_on_journal_formatter(:plaintext, 'title')
|
41
|
+
register_on_journal_formatter(:fraction, 'duration')
|
42
|
+
register_on_journal_formatter(:datetime, 'start_time')
|
43
|
+
register_on_journal_formatter(:plaintext, 'location')
|
44
|
+
|
45
|
+
accepts_nested_attributes_for :participants, :allow_destroy => true
|
46
|
+
|
47
|
+
validates_presence_of :title, :start_time, :duration
|
48
|
+
|
49
|
+
before_save :add_new_participants_as_watcher
|
50
|
+
|
51
|
+
after_initialize :set_initial_values
|
52
|
+
|
53
|
+
User.before_destroy do |user|
|
54
|
+
Meeting.update_all ['author_id = ?', DeletedUser.first.id], ['author_id = ?', user.id]
|
55
|
+
end
|
56
|
+
|
57
|
+
def start_date
|
58
|
+
# the text_field + calendar_for form helpers expect a Date
|
59
|
+
start_time.to_date if start_time.present?
|
60
|
+
end
|
61
|
+
|
62
|
+
def start_month
|
63
|
+
start_time.month
|
64
|
+
end
|
65
|
+
|
66
|
+
def start_year
|
67
|
+
start_time.year
|
68
|
+
end
|
69
|
+
|
70
|
+
def end_time
|
71
|
+
start_time + duration.hours
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_s
|
75
|
+
title
|
76
|
+
end
|
77
|
+
|
78
|
+
def text
|
79
|
+
agenda.text if agenda.present?
|
80
|
+
end
|
81
|
+
|
82
|
+
def author=(user)
|
83
|
+
super
|
84
|
+
# Don't add the author as participant if we already have some through nested attributes
|
85
|
+
self.participants.build(:user => user, :invited => true) if (self.new_record? && self.participants.empty? && user)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns true if usr or current user is allowed to view the meeting
|
89
|
+
def visible?(user=nil)
|
90
|
+
(user || User.current).allowed_to?(:view_meetings, self.project)
|
91
|
+
end
|
92
|
+
|
93
|
+
def all_possible_participants
|
94
|
+
self.project.users.all(:include => { :memberships => [:roles, :project] } ).select{ |u| self.visible?(u) }
|
95
|
+
end
|
96
|
+
|
97
|
+
def copy(attrs)
|
98
|
+
copy = self.dup
|
99
|
+
|
100
|
+
copy.author = attrs.delete(:author)
|
101
|
+
copy.attributes = attrs
|
102
|
+
copy.send(:set_initial_values)
|
103
|
+
|
104
|
+
copy.participants.clear
|
105
|
+
copy.participants_attributes = self.participants.collect(&:copy_attributes)
|
106
|
+
|
107
|
+
copy
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.group_by_time(meetings)
|
111
|
+
by_start_year_month_date = ActiveSupport::OrderedHash.new do |hy, year|
|
112
|
+
hy[year] = ActiveSupport::OrderedHash.new do |hm, month|
|
113
|
+
hm[month] = ActiveSupport::OrderedHash.new
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
meetings.group_by(&:start_year).each do |year, objs|
|
118
|
+
|
119
|
+
objs.group_by(&:start_month).each do |month,objs|
|
120
|
+
|
121
|
+
objs.group_by(&:start_date).each do |date,objs|
|
122
|
+
|
123
|
+
by_start_year_month_date[year][month][date] = objs
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
by_start_year_month_date
|
132
|
+
end
|
133
|
+
|
134
|
+
def close_agenda_and_copy_to_minutes!
|
135
|
+
self.agenda.lock!
|
136
|
+
self.create_minutes(:text => agenda.text)
|
137
|
+
end
|
138
|
+
|
139
|
+
alias :original_participants_attributes= :participants_attributes=
|
140
|
+
def participants_attributes=(attrs)
|
141
|
+
attrs.each do |participant|
|
142
|
+
participant['_destroy'] = true if !(participant['attended'] || participant['invited'])
|
143
|
+
end
|
144
|
+
self.original_participants_attributes = attrs
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
protected
|
149
|
+
|
150
|
+
def set_initial_values
|
151
|
+
# set defaults
|
152
|
+
self.start_time ||= Date.tomorrow + 10.hours
|
153
|
+
self.duration ||= 1
|
154
|
+
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
def add_new_participants_as_watcher
|
159
|
+
self.participants.select(&:new_record?).each do |p|
|
160
|
+
add_watcher(p.user)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
#-- copyright
|
2
|
+
# OpenProject is a project management system.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2012-2013 the OpenProject Team
|
5
|
+
#
|
6
|
+
# This program is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU General Public License version 3.
|
8
|
+
#
|
9
|
+
# See doc/COPYRIGHT.rdoc for more details.
|
10
|
+
#++
|
11
|
+
|
12
|
+
class MeetingAgenda < MeetingContent
|
13
|
+
|
14
|
+
acts_as_journalized :activity_type => 'meetings',
|
15
|
+
:activity_permission => :view_meetings,
|
16
|
+
:activity_find_options => {:include => {:meeting => :project}},
|
17
|
+
:event_title => Proc.new {|o| "#{l :label_meeting_agenda}: #{o.meeting.title}"},
|
18
|
+
:event_url => Proc.new {|o| {:controller => '/meetings', :action => 'show', :id => o.meeting}}
|
19
|
+
|
20
|
+
def activity_type
|
21
|
+
'meetings'
|
22
|
+
end
|
23
|
+
|
24
|
+
# TODO: internationalize the comments
|
25
|
+
def lock!(user = User.current)
|
26
|
+
self.comment = "Agenda closed"
|
27
|
+
self.author = user
|
28
|
+
self.locked = true
|
29
|
+
self.save
|
30
|
+
end
|
31
|
+
|
32
|
+
def unlock!(user = User.current)
|
33
|
+
self.comment = "Agenda opened"
|
34
|
+
self.author = user
|
35
|
+
self.locked = false
|
36
|
+
self.save
|
37
|
+
end
|
38
|
+
|
39
|
+
def editable?
|
40
|
+
!locked?
|
41
|
+
end
|
42
|
+
|
43
|
+
MeetingAgendaJournal.class_eval do
|
44
|
+
unloadable
|
45
|
+
|
46
|
+
attr_protected :data
|
47
|
+
after_save :compress_version_text
|
48
|
+
|
49
|
+
# Wiki Content might be large and the data should possibly be compressed
|
50
|
+
def compress_version_text
|
51
|
+
self.text = changed_data["text"].last if changed_data["text"]
|
52
|
+
self.text ||= self.journaled.text if self.journaled.text
|
53
|
+
end
|
54
|
+
|
55
|
+
def text=(plain)
|
56
|
+
case Setting.wiki_compression
|
57
|
+
when "gzip"
|
58
|
+
begin
|
59
|
+
text_hash :text => Zlib::Deflate.deflate(plain, Zlib::BEST_COMPRESSION), :compression => Setting.wiki_compression
|
60
|
+
rescue
|
61
|
+
text_hash :text => plain, :compression => ''
|
62
|
+
end
|
63
|
+
else
|
64
|
+
text_hash :text => plain, :compression => ''
|
65
|
+
end
|
66
|
+
plain
|
67
|
+
end
|
68
|
+
|
69
|
+
def text_hash(hash)
|
70
|
+
changed_data.delete("text")
|
71
|
+
changed_data["data"] = hash[:text]
|
72
|
+
changed_data["compression"] = hash[:compression]
|
73
|
+
update_attribute(:changed_data, changed_data)
|
74
|
+
# changed_data = changed_data
|
75
|
+
end
|
76
|
+
|
77
|
+
def text
|
78
|
+
@text ||= case changed_data[:compression]
|
79
|
+
when 'gzip'
|
80
|
+
Zlib::Inflate.inflate(data)
|
81
|
+
else
|
82
|
+
# uncompressed data
|
83
|
+
changed_data["data"]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def meeting
|
88
|
+
journaled.meeting
|
89
|
+
end
|
90
|
+
|
91
|
+
def editable?
|
92
|
+
false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
#-- copyright
|
2
|
+
# OpenProject is a project management system.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2012-2013 the OpenProject Team
|
5
|
+
#
|
6
|
+
# This program is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU General Public License version 3.
|
8
|
+
#
|
9
|
+
# See doc/COPYRIGHT.rdoc for more details.
|
10
|
+
#++
|
11
|
+
|
12
|
+
class MeetingContent < ActiveRecord::Base
|
13
|
+
|
14
|
+
belongs_to :meeting
|
15
|
+
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
|
16
|
+
|
17
|
+
attr_accessor :comment
|
18
|
+
|
19
|
+
validates_length_of :comment, :maximum => 255, :allow_nil => true
|
20
|
+
|
21
|
+
attr_accessible :text, :lock_version, :comment
|
22
|
+
|
23
|
+
before_save :comment_to_journal_notes
|
24
|
+
|
25
|
+
User.before_destroy do |user|
|
26
|
+
MeetingContent.update_all ['author_id = ?', DeletedUser.first], ['author_id = ?', user.id]
|
27
|
+
end
|
28
|
+
|
29
|
+
def editable?
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
def diff(version_to=nil, version_from=nil)
|
34
|
+
version_to = version_to ? version_to.to_i : self.version
|
35
|
+
version_from = version_from ? version_from.to_i : version_to - 1
|
36
|
+
version_to, version_from = version_from, version_to unless version_from < version_to
|
37
|
+
|
38
|
+
content_to = self.journals.find_by_version(version_to)
|
39
|
+
content_from = self.journals.find_by_version(version_from)
|
40
|
+
|
41
|
+
(content_to && content_from) ? WikiPage::WikiDiff.new(content_to, content_from) : nil
|
42
|
+
end
|
43
|
+
|
44
|
+
# Compatibility for mailer.rb
|
45
|
+
def updated_on
|
46
|
+
updated_at
|
47
|
+
end
|
48
|
+
|
49
|
+
# Show the project on activity and search views
|
50
|
+
def project
|
51
|
+
meeting.project
|
52
|
+
end
|
53
|
+
|
54
|
+
# Provided for compatibility of the old pre-journalized migration
|
55
|
+
def self.create_versioned_table
|
56
|
+
end
|
57
|
+
|
58
|
+
# Provided for compatibility of the old pre-journalized migration
|
59
|
+
def self.drop_versioned_table
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def comment_to_journal_notes
|
65
|
+
init_journal(author, comment) unless changes.empty?
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#-- copyright
|
2
|
+
# OpenProject is a project management system.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2012-2013 the OpenProject Team
|
5
|
+
#
|
6
|
+
# This program is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU General Public License version 3.
|
8
|
+
#
|
9
|
+
# See doc/COPYRIGHT.rdoc for more details.
|
10
|
+
#++
|
11
|
+
|
12
|
+
class MeetingMinutes < MeetingContent
|
13
|
+
|
14
|
+
acts_as_journalized :activity_type => 'meetings',
|
15
|
+
:activity_permission => :view_meetings,
|
16
|
+
:activity_find_options => {:include => {:meeting => :project}},
|
17
|
+
:event_title => Proc.new {|o| "#{l :label_meeting_minutes}: #{o.meeting.title}"},
|
18
|
+
:event_url => Proc.new {|o| {:controller => '/meetings', :action => 'show', :id => o.meeting}}
|
19
|
+
|
20
|
+
def activity_type
|
21
|
+
'meetings'
|
22
|
+
end
|
23
|
+
|
24
|
+
def editable?
|
25
|
+
meeting.agenda.present? && meeting.agenda.locked?
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
MeetingMinutesJournal.class_eval do
|
31
|
+
unloadable
|
32
|
+
|
33
|
+
attr_protected :data
|
34
|
+
after_save :compress_version_text
|
35
|
+
|
36
|
+
# Wiki Content might be large and the data should possibly be compressed
|
37
|
+
def compress_version_text
|
38
|
+
self.text = changed_data["text"].last if changed_data["text"]
|
39
|
+
self.text ||= self.journaled.text if self.journaled.text
|
40
|
+
end
|
41
|
+
|
42
|
+
def text=(plain)
|
43
|
+
case Setting.wiki_compression
|
44
|
+
when "gzip"
|
45
|
+
begin
|
46
|
+
text_hash :text => Zlib::Deflate.deflate(plain, Zlib::BEST_COMPRESSION), :compression => Setting.wiki_compression
|
47
|
+
rescue
|
48
|
+
text_hash :text => plain, :compression => ''
|
49
|
+
end
|
50
|
+
else
|
51
|
+
text_hash :text => plain, :compression => ''
|
52
|
+
end
|
53
|
+
plain
|
54
|
+
end
|
55
|
+
|
56
|
+
def text_hash(hash)
|
57
|
+
changed_data.delete("text")
|
58
|
+
changed_data["data"] = hash[:text]
|
59
|
+
changed_data["compression"] = hash[:compression]
|
60
|
+
update_attribute(:changed_data, changed_data)
|
61
|
+
end
|
62
|
+
|
63
|
+
def text
|
64
|
+
@text ||= case changed_data[:compression]
|
65
|
+
when 'gzip'
|
66
|
+
Zlib::Inflate.inflate(data)
|
67
|
+
else
|
68
|
+
# uncompressed data
|
69
|
+
changed_data["data"]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def meeting
|
74
|
+
journaled.meeting
|
75
|
+
end
|
76
|
+
|
77
|
+
def editable?
|
78
|
+
false
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|