2011-02-01 09:57:29 +08:00
#
2013-10-24 06:29:14 +08:00
# Copyright (C) 2011 - 2013 Instructure, Inc.
2011-02-01 09:57:29 +08:00
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
class Group < ActiveRecord :: Base
include Context
include Workflow
2012-05-30 06:55:40 +08:00
include CustomValidations
2012-06-07 04:16:55 +08:00
include UserFollow :: FollowedItem
2012-05-30 06:55:40 +08:00
2013-03-22 07:03:24 +08:00
attr_accessible :name , :context , :max_membership , :group_category , :join_level , :default_view , :description , :is_public , :avatar_attachment , :storage_quota_mb
2013-08-08 06:19:48 +08:00
validates_presence_of :context_id , :context_type , :account_id , :root_account_id , :workflow_state
2012-06-07 01:51:49 +08:00
validates_allowed_transitions :is_public , false = > true
2011-02-01 09:57:29 +08:00
2011-02-09 01:15:49 +08:00
has_many :group_memberships , :dependent = > :destroy , :conditions = > [ 'group_memberships.workflow_state != ?' , 'deleted' ]
has_many :users , :through = > :group_memberships , :conditions = > [ 'users.workflow_state != ?' , 'deleted' ]
2011-02-01 09:57:29 +08:00
has_many :participating_group_memberships , :class_name = > " GroupMembership " , :conditions = > [ 'group_memberships.workflow_state = ?' , 'accepted' ]
has_many :participating_users , :source = > :user , :through = > :participating_group_memberships
belongs_to :context , :polymorphic = > true
2011-09-22 04:31:36 +08:00
belongs_to :group_category
2011-02-01 09:57:29 +08:00
belongs_to :account
2011-06-03 23:54:00 +08:00
belongs_to :root_account , :class_name = > " Account "
2011-02-01 09:57:29 +08:00
has_many :calendar_events , :as = > :context , :dependent = > :destroy
has_many :discussion_topics , :as = > :context , :conditions = > [ 'discussion_topics.workflow_state != ?' , 'deleted' ] , :include = > :user , :dependent = > :destroy , :order = > 'discussion_topics.position DESC, discussion_topics.created_at DESC'
has_many :active_discussion_topics , :as = > :context , :class_name = > 'DiscussionTopic' , :conditions = > [ 'discussion_topics.workflow_state != ?' , 'deleted' ] , :include = > :user
has_many :all_discussion_topics , :as = > :context , :class_name = > " DiscussionTopic " , :include = > :user , :dependent = > :destroy
has_many :discussion_entries , :through = > :discussion_topics , :include = > [ :discussion_topic , :user ] , :dependent = > :destroy
has_many :announcements , :as = > :context , :class_name = > 'Announcement' , :dependent = > :destroy
has_many :active_announcements , :as = > :context , :class_name = > 'Announcement' , :conditions = > [ 'discussion_topics.workflow_state != ?' , 'deleted' ]
2011-09-29 07:26:18 +08:00
has_many :attachments , :as = > :context , :dependent = > :destroy , :extend = > Attachment :: FindInContextAssociation
2011-07-12 02:25:54 +08:00
has_many :active_images , :as = > :context , :class_name = > 'Attachment' , :conditions = > [ " attachments.file_state != ? AND attachments.content_type LIKE 'image%' " , 'deleted' ] , :order = > 'attachments.display_name' , :include = > :thumbnail
2011-02-01 09:57:29 +08:00
has_many :active_assignments , :as = > :context , :class_name = > 'Assignment' , :conditions = > [ 'assignments.workflow_state != ?' , 'deleted' ]
has_many :all_attachments , :as = > 'context' , :class_name = > 'Attachment'
has_many :folders , :as = > :context , :dependent = > :destroy , :order = > 'folders.name'
has_many :active_folders , :class_name = > 'Folder' , :as = > :context , :conditions = > [ 'folders.workflow_state != ?' , 'deleted' ] , :order = > 'folders.name'
2011-03-02 03:17:42 +08:00
has_many :active_folders_with_sub_folders , :class_name = > 'Folder' , :as = > :context , :include = > [ :active_sub_folders ] , :conditions = > [ 'folders.workflow_state != ?' , 'deleted' ] , :order = > 'folders.name'
2011-02-01 09:57:29 +08:00
has_many :active_folders_detailed , :class_name = > 'Folder' , :as = > :context , :include = > [ :active_sub_folders , :active_file_attachments ] , :conditions = > [ 'folders.workflow_state != ?' , 'deleted' ] , :order = > 'folders.name'
2012-12-19 05:59:09 +08:00
has_many :collaborators
2011-02-01 09:57:29 +08:00
has_many :external_feeds , :as = > :context , :dependent = > :destroy
has_many :messages , :as = > :context , :dependent = > :destroy
belongs_to :wiki
has_many :web_conferences , :as = > :context , :dependent = > :destroy
has_many :collaborations , :as = > :context , :order = > 'title, created_at' , :dependent = > :destroy
has_many :media_objects , :as = > :context
2011-12-10 06:37:12 +08:00
has_many :zip_file_imports , :as = > :context
2012-05-18 05:48:07 +08:00
has_many :collections , :as = > :context
2012-06-02 00:24:41 +08:00
belongs_to :avatar_attachment , :class_name = > " Attachment "
2012-06-07 04:16:55 +08:00
has_many :following_user_follows , :class_name = > 'UserFollow' , :as = > :followed_item
has_many :user_follows , :foreign_key = > 'following_user_id'
2012-01-04 04:30:49 +08:00
2013-08-08 06:19:48 +08:00
before_validation :ensure_defaults
before_save :maintain_category_attribute
2011-02-01 09:57:29 +08:00
after_save :close_memberships_if_deleted
2012-01-04 04:30:49 +08:00
2011-09-22 01:36:45 +08:00
include StickySisFields
are_sis_sticky :name
2011-07-14 00:24:17 +08:00
2013-10-16 04:18:38 +08:00
validates_each :name do | record , attr , value |
if value . blank?
record . errors . add attr , t ( :name_required , " Name is required " )
elsif value . length > maximum_string_length
record . errors . add attr , t ( :name_too_long , " Enter a shorter group name " )
end
end
2013-07-23 23:15:22 +08:00
2012-03-03 08:05:06 +08:00
alias_method :participating_users_association , :participating_users
def participating_users ( user_ids = nil )
user_ids ?
2013-03-19 03:07:47 +08:00
participating_users_association . where ( :id = > user_ids ) :
2012-03-03 08:05:06 +08:00
participating_users_association
end
2012-07-24 05:29:18 +08:00
def wiki_with_create
Wiki . wiki_for_context ( self )
2011-02-01 09:57:29 +08:00
end
2012-07-24 05:29:18 +08:00
alias_method_chain :wiki , :create
2012-01-04 04:30:49 +08:00
2012-08-30 04:57:00 +08:00
def auto_accept?
2012-05-16 05:50:43 +08:00
self . group_category &&
self . group_category . allows_multiple_memberships? &&
self . join_level == 'parent_context_auto_join'
2011-02-01 09:57:29 +08:00
end
2012-01-04 04:30:49 +08:00
2012-08-30 04:57:00 +08:00
def allow_join_request?
2012-05-16 05:50:43 +08:00
self . group_category &&
self . group_category . allows_multiple_memberships? &&
[ 'parent_context_auto_join' , 'parent_context_request' ] . include? ( self . join_level )
2011-02-01 09:57:29 +08:00
end
2012-01-04 04:30:49 +08:00
2011-10-08 07:19:20 +08:00
def allow_self_signup? ( user )
2012-05-16 05:50:43 +08:00
self . group_category &&
( self . group_category . unrestricted_self_signup? ||
( self . group_category . restricted_self_signup? && self . has_common_section_with_user? ( user ) ) )
end
2013-05-02 23:18:22 +08:00
def full?
group_category && group_category . group_limit && participating_users . size > = group_category . group_limit
end
2012-08-30 04:57:00 +08:00
def free_association? ( user )
auto_accept? || allow_join_request? || allow_self_signup? ( user )
2011-10-08 07:19:20 +08:00
end
2012-01-04 04:30:49 +08:00
2012-08-31 05:15:34 +08:00
def allow_student_forum_attachments
context . respond_to? ( :allow_student_forum_attachments ) && context . allow_student_forum_attachments
end
2012-03-09 01:14:57 +08:00
def participants ( include_observers = false )
# argument needed because #participants is polymorphic for contexts
2011-02-01 09:57:29 +08:00
participating_users . uniq
end
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
def context_code
2013-03-08 08:08:47 +08:00
raise " DONT USE THIS, use .short_name instead " unless Rails . env . production?
2011-02-01 09:57:29 +08:00
end
2012-01-04 04:30:49 +08:00
def appointment_context_codes
{ :primary = > [ context_string ] , :secondary = > [ group_category . asset_string ] }
end
2011-02-01 09:57:29 +08:00
def membership_for_user ( user )
2012-06-21 05:05:53 +08:00
return nil unless user . present?
self . shard . activate { self . group_memberships . find_by_user_id ( user . id ) }
2011-02-01 09:57:29 +08:00
end
2012-01-04 04:30:49 +08:00
2012-05-16 05:50:43 +08:00
def has_member? ( user )
2012-06-21 05:05:53 +08:00
return nil unless user . present?
self . shard . activate { self . participating_group_memberships . find_by_user_id ( user . id ) }
2012-05-16 05:50:43 +08:00
end
def has_moderator? ( user )
2012-06-21 05:05:53 +08:00
return nil unless user . present?
self . shard . activate { self . participating_group_memberships . moderators . find_by_user_id ( user . id ) }
2012-05-16 05:50:43 +08:00
end
2012-05-30 06:55:40 +08:00
def should_add_creator?
self . group_category && ( self . group_category . communities? || self . group_category . student_organized? )
end
2011-02-01 09:57:29 +08:00
def short_name
name
end
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
def self . find_all_by_context_code ( codes )
ids = codes . map { | c | c . match ( / \ Agroup_( \ d+) \ z / ) [ 1 ] rescue nil } . compact
Group . find ( ids )
end
2012-01-04 04:30:49 +08:00
2013-09-20 07:53:11 +08:00
def self . not_in_group_sql_fragment ( group_ids , prepend_and = true )
2013-06-07 20:59:27 +08:00
" #{ " AND " if prepend_and } NOT EXISTS (SELECT * FROM group_memberships gm
WHERE gm . user_id = users . id AND
2013-01-09 06:06:48 +08:00
gm . workflow_state != 'deleted' AND
2013-09-20 07:53:11 +08:00
gm . group_id IN ( #{group_ids.map(&:to_i).join ','}))" unless group_ids.empty?
2013-01-09 06:06:48 +08:00
end
2011-02-01 09:57:29 +08:00
workflow do
state :available do
event :complete , :transitions_to = > :completed
event :close , :transitions_to = > :closed
end
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
# Closed to new entrants
state :closed do
event :complete , :transitions_to = > :completed
event :open , :transitions_to = > :available
end
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
state :completed
state :deleted
end
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
def active?
self . available? || self . closed?
end
alias_method :destroy! , :destroy
def destroy
self . workflow_state = 'deleted'
self . deleted_at = Time . now
self . save
end
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
def close_memberships_if_deleted
return unless self . deleted?
2013-03-19 03:07:47 +08:00
User . where ( :id = > group_memberships . pluck ( :user_id ) ) . update_all ( :updated_at = > Time . now . utc )
group_memberships . update_all ( :workflow_state = > 'deleted' )
2011-02-01 09:57:29 +08:00
end
2012-01-04 04:30:49 +08:00
2013-07-11 05:39:38 +08:00
Bookmarker = BookmarkedCollection :: SimpleBookmarker . new ( Group , :name , :id )
2013-03-21 03:38:19 +08:00
scope :active , where ( " groups.workflow_state<>'deleted' " )
2013-07-11 05:39:38 +08:00
scope :by_name , lambda { order ( Bookmarker . order_by ) }
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
def full_name
2011-06-14 05:33:59 +08:00
res = before_label ( self . name ) + " "
res += ( self . context . course_code rescue self . context . name ) if self . context
2011-02-01 09:57:29 +08:00
end
def to_atom
Atom :: Entry . new do | entry |
entry . title = self . name
entry . updated = self . updated_at
entry . published = self . created_at
2012-01-04 04:30:49 +08:00
entry . links << Atom :: Link . new ( :rel = > 'alternate' ,
2011-02-01 09:57:29 +08:00
:href = > " /groups/ #{ self . id } " )
end
end
2012-01-04 04:30:49 +08:00
2012-06-02 03:18:32 +08:00
# this method is idempotent
def add_user ( user , new_record_state = nil , moderator = nil )
2011-02-01 09:57:29 +08:00
return nil if ! user
2012-06-02 03:18:32 +08:00
attrs = { :user = > user , :moderator = > ! ! moderator }
2012-05-16 05:50:43 +08:00
new_record_state || = case self . join_level
when 'invitation_only' then 'invited'
when 'parent_context_request' then 'requested'
when 'parent_context_auto_join' then 'accepted'
end
attrs [ :workflow_state ] = new_record_state if new_record_state
2012-06-02 03:18:32 +08:00
if member = self . group_memberships . find_by_user_id ( user . id )
member . workflow_state = new_record_state unless member . active?
# only update moderator if true/false is explicitly passed in
member . moderator = moderator unless moderator . nil?
member . save if member . changed?
else
member = self . group_memberships . create ( attrs )
end
2012-09-27 03:05:39 +08:00
# permissions for this user in the group are probably different now
Rails . cache . delete ( permission_cache_key_for ( user ) )
2011-02-01 09:57:29 +08:00
return member
end
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
def invite_user ( user )
2012-05-16 05:50:43 +08:00
self . add_user ( user , 'invited' )
2011-02-01 09:57:29 +08:00
end
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
def request_user ( user )
2012-05-16 05:50:43 +08:00
self . add_user ( user , 'requested' )
2011-02-01 09:57:29 +08:00
end
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
def invitees = ( params )
invitees = [ ]
( params || { } ) . each do | key , val |
if self . context
invitees << self . context . users . find_by_id ( key . to_i ) if val != '0'
else
invitees << User . find_by_id ( key . to_i ) if val != '0'
end
end
invitees . compact . map { | i | self . invite_user ( i ) } . compact
end
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
def peer_groups
2012-05-16 05:50:43 +08:00
return [ ] if ! self . context || ! self . group_category || self . group_category . allows_multiple_memberships?
2013-03-19 03:07:47 +08:00
self . group_category . groups . where ( " id<>? " , self ) . all
2011-02-01 09:57:29 +08:00
end
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
def migrate_content_links ( html , from_course )
Course . migrate_content_links ( html , from_course , self )
end
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
attr_accessor :merge_mappings
attr_accessor :merge_results
def merge_mapped_id ( * args )
nil
end
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
def map_merge ( * args )
end
def log_merge_result ( text )
@merge_results || = [ ]
@merge_results << text
end
def warn_merge_result ( text )
record_merge_result ( text )
end
2011-09-21 03:24:18 +08:00
def student_organized?
2011-09-22 04:31:36 +08:00
self . group_category && self . group_category . student_organized?
2011-09-21 03:24:18 +08:00
end
2011-02-01 09:57:29 +08:00
def ensure_defaults
2011-04-15 06:09:37 +08:00
self . name || = AutoHandle . generate_securish_uuid
self . uuid || = AutoHandle . generate_securish_uuid
2011-09-22 04:31:36 +08:00
self . group_category || = GroupCategory . student_organized_for ( self . context )
2011-02-01 09:57:29 +08:00
self . join_level || = 'invitation_only'
2012-05-16 05:50:43 +08:00
self . is_public || = false
2012-05-30 06:55:40 +08:00
self . is_public = false unless self . group_category . try ( :communities? )
2011-02-01 09:57:29 +08:00
if self . context && self . context . is_a? ( Course )
2011-09-22 04:31:36 +08:00
self . account = self . context . account
2011-02-01 09:57:29 +08:00
elsif self . context && self . context . is_a? ( Account )
self . account = self . context
end
end
private :ensure_defaults
2011-03-29 03:38:23 +08:00
2011-06-03 23:54:00 +08:00
# update root account when account changes
def account = ( new_account )
self . account_id = new_account . id
end
def account_id = ( new_account_id )
write_attribute ( :account_id , new_account_id )
if self . account_id_changed?
2011-12-28 05:57:56 +08:00
self . root_account = self . account ( true ) . try ( :root_account )
2011-06-03 23:54:00 +08:00
end
end
2011-03-29 03:38:23 +08:00
# if you modify this set_policy block, note that we've denormalized this
# permission check for efficiency -- see User#cached_contexts
2011-02-01 09:57:29 +08:00
set_policy do
2012-05-16 05:50:43 +08:00
given { | user | user && self . has_member? ( user ) }
can :create_collaborations and
can :create_conferences and
can :manage_calendar and
can :manage_content and
can :manage_files and
can :manage_wiki and
can :post_to_forum and
can :read and
can :read_roster and
can :send_messages and
2013-02-07 08:40:16 +08:00
can :send_messages_all and
2013-04-24 22:50:45 +08:00
can :follow and
can :view_unpublished_items and
can :view_hidden_items
2012-01-04 04:30:49 +08:00
2012-05-03 04:45:40 +08:00
# if I am a member of this group and I can moderate_forum in the group's context
# (makes it so group members cant edit each other's discussion entries)
2012-05-16 05:50:43 +08:00
given { | user , session | user && self . has_member? ( user ) && ( ! self . context || self . context . grants_right? ( user , session , :moderate_forum ) ) }
can :moderate_forum
2012-05-03 04:45:40 +08:00
2012-05-16 05:50:43 +08:00
given { | user | user && self . has_moderator? ( user ) }
2012-05-30 06:55:40 +08:00
can :delete and
2012-06-02 03:18:32 +08:00
can :manage and
can :manage_admin_users and
2012-12-12 21:50:15 +08:00
can :manage_students and
2012-05-30 06:55:40 +08:00
can :moderate_forum and
can :update
given { | user | self . group_category . try ( :communities? ) }
can :create
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
given { | user , session | self . context && self . context . grants_right? ( user , session , :participate_as_student ) && self . context . allow_student_organized_groups }
2011-07-14 00:24:17 +08:00
can :create
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
given { | user , session | self . context && self . context . grants_right? ( user , session , :manage_groups ) }
2012-05-16 05:50:43 +08:00
can :create and
2012-07-20 01:13:21 +08:00
can :create_collaborations and
2012-05-16 05:50:43 +08:00
can :create_conferences and
can :delete and
can :manage and
can :manage_admin_users and
can :manage_content and
can :manage_files and
can :manage_students and
can :manage_wiki and
can :moderate_forum and
can :post_to_forum and
can :read and
can :read_roster and
2013-04-24 22:50:45 +08:00
can :update and
can :view_unpublished_items and
can :view_hidden_items
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
given { | user , session | self . context && self . context . grants_right? ( user , session , :view_group_pages ) }
2011-07-14 00:24:17 +08:00
can :read and can :read_roster
2012-01-04 04:30:49 +08:00
2012-06-06 03:57:22 +08:00
given { | user | user && self . is_public? }
can :follow
2012-08-30 04:57:00 +08:00
# Participate means the user is connected to the group somehow and can be
given { | user | user && can_participate? ( user ) }
can :participate
# Join is participate + the group being in a state that allows joining directly (free_association)
given { | user | user && can_participate? ( user ) && free_association? ( user ) }
can :join and can :read_roster
given { | user | user && ( self . group_category . try ( :allows_multiple_memberships? ) || allow_self_signup? ( user ) ) }
can :leave
end
2013-06-06 09:21:29 +08:00
def users_visible_to ( user )
2013-10-26 05:53:23 +08:00
grants_rights? ( user , :read ) ? users : users . none
2013-06-06 09:21:29 +08:00
end
2012-08-30 04:57:00 +08:00
# Helper needed by several permissions, use grants_right?(user, :participate)
def can_participate? ( user )
return false unless user . present? && self . context . present?
return true if self . group_category . try ( :communities? )
if self . context . is_a? ( Course )
return self . context . enrollments . not_fake . where ( :user_id = > user . id ) . first . present?
elsif self . context . is_a? ( Account )
return self . context . user_account_associations . where ( :user_id = > user . id ) . first . present?
end
return false
2011-02-01 09:57:29 +08:00
end
2012-08-30 04:57:00 +08:00
private :can_participate?
2011-03-02 01:44:41 +08:00
2013-02-08 04:09:05 +08:00
# courses lock this down a bit, but in a group, the fact that you are a
# member is good enough
def user_can_manage_own_discussion_posts? ( user )
true
end
2011-02-01 09:57:29 +08:00
def is_a_context?
true
end
def members_json_cached
Rails . cache . fetch ( [ 'group_members_json' , self ] . cache_key ) do
2011-10-29 07:19:11 +08:00
self . users . map { | u | u . group_member_json ( self . context ) }
2011-02-01 09:57:29 +08:00
end
end
def members_count_cached
Rails . cache . fetch ( [ 'group_members_count' , self ] . cache_key ) do
self . members_json_cached . length
end
end
2012-05-30 06:55:40 +08:00
def members_count
self . participating_group_memberships . count
2012-02-16 05:40:13 +08:00
end
2011-10-21 03:06:55 +08:00
def quota
2013-06-05 02:50:15 +08:00
return self . storage_quota || self . account . default_group_storage_quota || self . class . default_storage_quota
end
def self . default_storage_quota
2013-10-05 04:02:49 +08:00
Setting . get ( 'group_default_quota' , 50 . megabytes . to_s ) . to_i
2011-10-21 03:06:55 +08:00
end
2013-03-22 07:03:24 +08:00
def storage_quota_mb
quota / 1 . megabyte
end
def storage_quota_mb = ( val )
self . storage_quota = val . try ( :to_i ) . try ( :megabytes )
end
2012-06-01 06:47:04 +08:00
TAB_HOME , TAB_PAGES , TAB_PEOPLE , TAB_DISCUSSIONS , TAB_CHAT , TAB_FILES ,
2012-07-20 01:13:21 +08:00
TAB_CONFERENCES , TAB_ANNOUNCEMENTS , TAB_PROFILE , TAB_SETTINGS , TAB_COLLABORATIONS = * 1 .. 20
2011-02-01 09:57:29 +08:00
def tabs_available ( user = nil , opts = { } )
available_tabs = [
2011-09-09 06:11:46 +08:00
{ :id = > TAB_HOME , :label = > t ( " # group.tabs.home " , " Home " ) , :css_class = > 'home' , :href = > :group_path } ,
{ :id = > TAB_ANNOUNCEMENTS , :label = > t ( '#tabs.announcements' , " Announcements " ) , :css_class = > 'announcements' , :href = > :group_announcements_path } ,
{ :id = > TAB_PAGES , :label = > t ( " # group.tabs.pages " , " Pages " ) , :css_class = > 'pages' , :href = > :group_wiki_pages_path } ,
2012-10-19 10:13:51 +08:00
{ :id = > TAB_PEOPLE , :label = > t ( " # group.tabs.people " , " People " ) , :css_class = > 'people' , :href = > :group_users_path } ,
2011-09-09 06:11:46 +08:00
{ :id = > TAB_DISCUSSIONS , :label = > t ( " # group.tabs.discussions " , " Discussions " ) , :css_class = > 'discussions' , :href = > :group_discussion_topics_path } ,
{ :id = > TAB_CHAT , :label = > t ( " # group.tabs.chat " , " Chat " ) , :css_class = > 'chat' , :href = > :group_chat_path } ,
2012-06-06 05:06:36 +08:00
{ :id = > TAB_FILES , :label = > t ( " # group.tabs.files " , " Files " ) , :css_class = > 'files' , :href = > :group_files_path } ,
2011-02-01 09:57:29 +08:00
]
2012-06-01 06:47:04 +08:00
2012-06-28 07:22:41 +08:00
if root_account . try :canvas_network_enabled?
2012-06-14 06:19:23 +08:00
available_tabs << { :id = > TAB_PROFILE , :label = > t ( '#tabs.profile' , 'Profile' ) , :css_class = > 'profile' , :href = > :group_profile_path }
end
2012-01-17 06:44:10 +08:00
available_tabs << { :id = > TAB_CONFERENCES , :label = > t ( '#tabs.conferences' , " Conferences " ) , :css_class = > 'conferences' , :href = > :group_conferences_path } if user && self . grants_right? ( user , nil , :read )
2012-07-20 01:13:21 +08:00
available_tabs << { :id = > TAB_COLLABORATIONS , :label = > t ( '#tabs.collaborations' , " Collaborations " ) , :css_class = > 'collaborations' , :href = > :group_collaborations_path } if user && self . grants_right? ( user , nil , :read )
2012-08-31 05:15:34 +08:00
if root_account . try ( :canvas_network_enabled? ) && user && grants_right? ( user , nil , :manage )
2012-08-06 23:46:18 +08:00
available_tabs << { :id = > TAB_SETTINGS , :label = > t ( '#tabs.settings' , 'Settings' ) , :css_class = > 'settings' , :href = > :edit_group_path }
end
2011-08-05 04:20:21 +08:00
available_tabs
2011-02-01 09:57:29 +08:00
end
def self . serialization_excludes ; [ :uuid ] ; end
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
def self . process_migration ( data , migration )
2012-05-16 05:50:43 +08:00
groups = data [ 'groups' ] || [ ]
2011-02-01 09:57:29 +08:00
groups . each do | group |
2012-04-03 06:38:05 +08:00
if migration . import_object? ( " groups " , group [ 'migration_id' ] )
2011-06-18 00:58:18 +08:00
begin
import_from_migration ( group , migration . context )
rescue
2013-04-24 01:12:19 +08:00
migration . add_import_warning ( t ( '#migration.group_type' , " Group " ) , group [ :title ] , $! )
2011-06-18 00:58:18 +08:00
end
2011-02-01 09:57:29 +08:00
end
end
end
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
def self . import_from_migration ( hash , context , item = nil )
hash = hash . with_indifferent_access
return nil if hash [ :migration_id ] && hash [ :groups_to_import ] && ! hash [ :groups_to_import ] [ hash [ :migration_id ] ]
item || = find_by_context_id_and_context_type_and_id ( context . id , context . class . to_s , hash [ :id ] )
item || = find_by_context_id_and_context_type_and_migration_id ( context . id , context . class . to_s , hash [ :migration_id ] ) if hash [ :migration_id ]
item || = context . groups . new
context . imported_migration_items << item if context . imported_migration_items && item . new_record?
item . migration_id = hash [ :migration_id ]
item . name = hash [ :title ]
2011-09-22 04:31:36 +08:00
item . group_category = hash [ :group_category ] . present? ?
context . group_categories . find_or_initialize_by_name ( hash [ :group_category ] ) :
GroupCategory . imported_for ( context )
2012-01-04 04:30:49 +08:00
2011-02-01 09:57:29 +08:00
item . save!
context . imported_migration_items << item
item
end
2011-09-08 23:06:51 +08:00
def allow_media_comments?
true
end
2011-09-21 00:51:50 +08:00
def group_category_name
self . read_attribute ( :category )
end
2011-09-22 04:31:36 +08:00
def maintain_category_attribute
# keep this field up to date even though it's not used (group_category_name
# exists solely for the migration that introduces the GroupCategory model).
# this way group_category_name is correct if someone mistakenly uses it
# (modulo category renaming in the GroupCategory model).
self . write_attribute ( :category , self . group_category && self . group_category . name )
2011-09-21 00:51:50 +08:00
end
def as_json ( options = nil )
json = super ( options )
2011-09-22 04:31:36 +08:00
if json && json [ 'group' ]
# remove anything coming automatically from deprecated db column
json [ 'group' ] . delete ( 'category' )
if self . group_category
2012-01-04 04:30:49 +08:00
# put back version from association
2011-09-22 04:31:36 +08:00
json [ 'group' ] [ 'group_category' ] = self . group_category . name
end
end
2011-09-21 00:51:50 +08:00
json
end
2011-10-08 07:19:20 +08:00
def has_common_section?
self . context && self . context . is_a? ( Course ) &&
self . context . course_sections . active . any? { | section | section . common_to_users? ( self . users ) }
end
def has_common_section_with_user? ( user )
return false unless self . context && self . context . is_a? ( Course )
users = self . users + [ user ]
self . context . course_sections . active . any? { | section | section . common_to_users? ( users ) }
end
2012-06-01 03:21:22 +08:00
def self . join_levels
[
[ " invitation_only " , " Invite only " ] ,
[ " parent_context_auto_join " , " Auto join " ] ,
[ " parent_context_request " , " Request to join " ]
]
end
2012-06-07 05:14:35 +08:00
2012-05-30 04:56:58 +08:00
def default_collection_name
t " # group.default_collection_name " , " %{group_name}'s Collection " , :group_name = > self . name
end
2012-11-17 06:00:05 +08:00
def associated_shards
[ Shard . default ]
end
2013-07-10 00:14:52 +08:00
# Public: Determine if the current context has draft_state enabled.
#
# Returns a boolean.
def draft_state_enabled?
2013-08-22 06:09:35 +08:00
# shouldn't matter, but most specs create anonymous (contextless) groups :(
return false if context . nil?
2013-07-10 00:14:52 +08:00
context . draft_state_enabled?
end
2013-09-18 06:24:57 +08:00
def serialize_permissions ( permissions_hash , user , session )
permissions_hash . merge (
create_discussion_topic : DiscussionTopic . context_allows_user_to_create? ( self , user , session )
)
end
2011-02-01 09:57:29 +08:00
end