openproject-meeting 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|