mumuki-domain 7.9.0 → 7.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -0
  3. data/app/models/application_record.rb +10 -0
  4. data/app/models/assignment.rb +18 -2
  5. data/app/models/avatar.rb +2 -0
  6. data/app/models/concerns/awardee.rb +27 -0
  7. data/app/models/concerns/contextualization.rb +6 -2
  8. data/app/models/concerns/with_description.rb +2 -5
  9. data/app/models/concerns/with_medal.rb +7 -0
  10. data/app/models/concerns/with_progress.rb +4 -0
  11. data/app/models/content.rb +3 -2
  12. data/app/models/discussion.rb +8 -1
  13. data/app/models/indicator.rb +14 -1
  14. data/app/models/medal.rb +3 -0
  15. data/app/models/organization.rb +51 -4
  16. data/app/models/usage.rb +5 -0
  17. data/app/models/user.rb +18 -9
  18. data/db/migrate/20200617142217_add_top_submission_status_to_assignments.rb +1 -1
  19. data/db/migrate/20200828152812_create_medals.rb +8 -0
  20. data/db/migrate/20200828162829_add_medal_to_content.rb +7 -0
  21. data/db/migrate/20200915123020_add_polymorphic_avatars_to_users.rb +6 -0
  22. data/db/migrate/20200915131621_add_once_completed_to_indicators.rb +5 -0
  23. data/db/migrate/20201009193949_add_status_updated_fields_to_discussion.rb +6 -0
  24. data/db/migrate/20201019191036_add_misplaced_flag_to_submission.rb +5 -0
  25. data/db/migrate/20201026222942_add_display_name_and_description_to_organizations.rb +6 -0
  26. data/db/migrate/20201026225312_add_organization_wins_page_flag.rb +5 -0
  27. data/db/migrate/20201027134205_add_immersible_to_organization.rb +5 -0
  28. data/lib/mumuki/domain/extensions/array.rb +13 -0
  29. data/lib/mumuki/domain/factories.rb +2 -1
  30. data/lib/mumuki/domain/factories/medal_factory.rb +6 -0
  31. data/lib/mumuki/domain/factories/organization_factory.rb +1 -0
  32. data/lib/mumuki/domain/helpers/organization.rb +4 -0
  33. data/lib/mumuki/domain/helpers/user.rb +17 -1
  34. data/lib/mumuki/domain/incognito.rb +12 -0
  35. data/lib/mumuki/domain/locales/activerecord/en.yml +2 -0
  36. data/lib/mumuki/domain/locales/activerecord/es.yml +2 -0
  37. data/lib/mumuki/domain/locales/defaults/en.yml +4 -0
  38. data/lib/mumuki/domain/locales/defaults/es-CL.yml +4 -0
  39. data/lib/mumuki/domain/locales/defaults/es.yml +4 -0
  40. data/lib/mumuki/domain/locales/defaults/pt.yml +4 -0
  41. data/lib/mumuki/domain/organization/profile.rb +2 -1
  42. data/lib/mumuki/domain/organization/settings.rb +12 -3
  43. data/lib/mumuki/domain/version.rb +1 -1
  44. metadata +19 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e4d324f2eb4b3e06fb42a0aabbbd007c4c828569899c89a789ad681432bb97ba
4
- data.tar.gz: 3f540fc72a7180e247ee11535316d977920872ecc888c77c7c68346eae0c276e
3
+ metadata.gz: 17efbb5ea487285cf39720f0f3bcaab94641669a8f0ba83c78b8931c8ff949b2
4
+ data.tar.gz: a6213b8093643e8112ffc85609fbae72c871c343f9374e17ba024ee1b9eb73c3
5
5
  SHA512:
6
- metadata.gz: ac7828f09dec30a19e4f4b96bfcfb472fe7fcfc5b53aaeb81e4fb4f5b52533d10b462e9e923d2a2857cec7367cda7d40d6222bd8f8a105dfc84e394b35e552c5
7
- data.tar.gz: 40cede7e7ff373b1a3a170fbd6bf55bb40faf5c2a814af0849a698f2205a15bff49bca7ba5737577620c48265bad4e42d68e8b4befcb4bbb5d78f9ec82bf23fe
6
+ metadata.gz: 821da987d9bc224d803554e8f44f54c200f5dcc9fd38ad90a793e5fb640ad946cf059276a534d8004a84386f2ef75fa448b666b4054049b48dbfb8e76bcce32e
7
+ data.tar.gz: 4b92ea6a719cd03dc2b3c9e338cdb470b86a22f9764b0dff4a61f9a5173bee1d389de9d7396cf55b78cf23d63222ecaca6be6ccf14e2cc83d7de0cabc57a090b
data/README.md CHANGED
@@ -1,3 +1,9 @@
1
+ [![Build Status](https://travis-ci.com/mumuki/mumuki-domain.svg?branch=master)](https://travis-ci.com/mumuki/mumuki-domain)
2
+ [![Code Climate](https://codeclimate.com/github/mumuki/mumuki-domain/badges/gpa.svg)](https://codeclimate.com/github/mumuki/mumuki-domain)
3
+ [![Test Coverage](https://codeclimate.com/github/mumuki/mumuki-domain/badges/coverage.svg)](https://codeclimate.com/github/mumuki/mumuki-domain)
4
+ [![Issue Count](https://codeclimate.com/github/mumuki/mumuki-domain/badges/issue_count.svg)](https://codeclimate.com/github/mumuki/mumuki-domain)
5
+
6
+
1
7
  # Resource Hashes
2
8
 
3
9
  ## Runner Hashes
@@ -3,6 +3,16 @@ class ApplicationRecord < ActiveRecord::Base
3
3
 
4
4
  delegate :whitelist_attributes, to: :class
5
5
 
6
+ def self.teaser_on(*args)
7
+ args.each do |selector|
8
+ teaser_selector = "#{selector}_teaser"
9
+ define_method teaser_selector do
10
+ send(selector)&.markdown_paragraphs&.first
11
+ end
12
+ markdown_on teaser_selector, skip_sanitization: true
13
+ end
14
+ end
15
+
6
16
  def self.defaults(&block)
7
17
  after_initialize :defaults, if: :new_record?
8
18
  define_method :defaults, &block
@@ -42,6 +42,7 @@ class Assignment < Progress
42
42
  alias_method :parent_content, :guide
43
43
  alias_method :user, :submitter
44
44
 
45
+ after_initialize :set_default_top_submission_status
45
46
  before_save :award_experience_points!, :update_top_submission!, if: :submission_status_changed?
46
47
  after_save :dirty_parent_by_submission!, if: :completion_changed?
47
48
  before_validation :set_current_organization!, unless: :organization
@@ -51,6 +52,10 @@ class Assignment < Progress
51
52
  self.organization = Organization.current
52
53
  end
53
54
 
55
+ def set_default_top_submission_status
56
+ self.top_submission_status ||= 0
57
+ end
58
+
54
59
  def completion_changed?
55
60
  completed_before_last_save? != completed?
56
61
  end
@@ -86,7 +91,14 @@ class Assignment < Progress
86
91
  end
87
92
 
88
93
  def notify!
89
- Mumukit::Nuntius.notify! 'submissions', to_resource_h unless Organization.silenced?
94
+ unless Organization.silenced?
95
+ update_misplaced!(current_notification_contexts.size > 1)
96
+ Mumukit::Nuntius.notify! 'submissions', to_resource_h
97
+ end
98
+ end
99
+
100
+ def current_notification_contexts
101
+ [Organization.current, submitter.current_immersive_context_at(exercise)].uniq
90
102
  end
91
103
 
92
104
  def notify_to_accessible_organizations!
@@ -164,7 +176,7 @@ class Assignment < Progress
164
176
 
165
177
  def to_resource_h
166
178
  excluded_fields = %i(created_at exercise_id id organization_id parent_id solution submission_id
167
- submission_status submitted_at submitter_id top_submission_status updated_at)
179
+ submission_status submitted_at submitter_id top_submission_status updated_at misplaced)
168
180
 
169
181
  as_json(except: excluded_fields,
170
182
  include: {
@@ -233,6 +245,10 @@ class Assignment < Progress
233
245
  self.top_submission_status = submission_status unless submission_status.improved_by?(top_submission_status)
234
246
  end
235
247
 
248
+ def update_misplaced!(value)
249
+ update! misplaced: value if value != misplaced?
250
+ end
251
+
236
252
  private
237
253
 
238
254
  def update_submissions_count!
@@ -1,4 +1,6 @@
1
1
  class Avatar < ApplicationRecord
2
+ has_many :users, as: :avatar
3
+
2
4
  include WithTargetAudience
3
5
 
4
6
  def self.sample_for(user)
@@ -0,0 +1,27 @@
1
+ module Awardee
2
+ def acquired_medals(organization=Organization.current)
3
+ @acquired_medals ||= medals_for awarded_contents_in(organization)
4
+ end
5
+
6
+ def unacquired_medals(organization=Organization.current)
7
+ @unacquired_medals ||= medals_for unawarded_contents_in(organization)
8
+ end
9
+
10
+ private
11
+
12
+ def medals_for(content)
13
+ content.map(&:medal)
14
+ end
15
+
16
+ def awarded_contents_in(organization)
17
+ awardable_contents_in(organization).first
18
+ end
19
+
20
+ def unawarded_contents_in(organization)
21
+ awardable_contents_in(organization).second
22
+ end
23
+
24
+ def awardable_contents_in(organization)
25
+ @awardable_contents_in ||= organization.awardable_contents.partition { |c| c.once_completed_for? self, organization }
26
+ end
27
+ end
@@ -51,7 +51,7 @@ module Contextualization
51
51
  end
52
52
 
53
53
  def single_visible_test_result?
54
- test_results.size == 1 && visible_success_output?
54
+ test_results.single? && visible_success_output?
55
55
  end
56
56
 
57
57
  def first_test_result
@@ -131,8 +131,12 @@ module Contextualization
131
131
  .compact
132
132
  .merge(
133
133
  title: it[:title].affable,
134
- result: it[:result].sanitized,
134
+ result: it[:result],
135
135
  status: it[:status])
136
136
  end
137
137
  end
138
+
139
+ def sanitized_affable_test_results
140
+ affable_test_results.each { |it| it[:result] = it[:result]&.sanitized }
141
+ end
138
142
  end
@@ -2,11 +2,8 @@ module WithDescription
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  included do
5
- markdown_on :description, :description_teaser, skip_sanitization: true
5
+ markdown_on :description, skip_sanitization: true
6
+ teaser_on :description
6
7
  validates_presence_of :description
7
8
  end
8
-
9
- def description_teaser
10
- description.markdown_paragraphs.first
11
- end
12
9
  end
@@ -0,0 +1,7 @@
1
+ module WithMedal
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ belongs_to :medal, optional: true
6
+ end
7
+ end
@@ -23,6 +23,10 @@ module WithProgress
23
23
  progress_for(user, organization).completed?
24
24
  end
25
25
 
26
+ def once_completed_for?(user, organization)
27
+ progress_for(user, organization).once_completed?
28
+ end
29
+
26
30
  private
27
31
 
28
32
  def structural_children_changed?(old_structural_children)
@@ -4,10 +4,11 @@ class Content < ApplicationRecord
4
4
  include Mumuki::Domain::Syncable
5
5
  include WithDescription
6
6
  include WithLocale
7
- include WithSlug
8
- include WithUsages
7
+ include WithMedal
9
8
  include WithName
10
9
  include WithProgress
10
+ include WithSlug
11
+ include WithUsages
11
12
 
12
13
  def to_resource_h(*args)
13
14
  to_expanded_resource_h(*args).compact
@@ -4,7 +4,10 @@ class Discussion < ApplicationRecord
4
4
  belongs_to :item, polymorphic: true
5
5
  has_many :messages, -> { order(:created_at) }, dependent: :destroy
6
6
  belongs_to :initiator, class_name: 'User'
7
+
7
8
  belongs_to :last_moderator_access_by, class_name: 'User', optional: true
9
+ belongs_to :status_updated_by, class_name: 'User', optional: true
10
+
8
11
  belongs_to :exercise, foreign_type: :exercise, foreign_key: 'item_id'
9
12
  belongs_to :organization
10
13
  has_many :subscriptions
@@ -106,7 +109,11 @@ class Discussion < ApplicationRecord
106
109
  end
107
110
 
108
111
  def update_status!(status, user)
109
- update!(status: status) if reachable_status_for?(user, status)
112
+ if reachable_status_for?(user, status)
113
+ update! status: status,
114
+ status_updated_by: user,
115
+ status_updated_at: Time.now
116
+ end
110
117
  end
111
118
 
112
119
  def has_messages?
@@ -37,6 +37,7 @@ class Indicator < Progress
37
37
  def clean!
38
38
  self.dirty_by_submission = false
39
39
  self.dirty_by_content_change = false
40
+ self.once_completed ||= all_children_passed?
40
41
  end
41
42
 
42
43
  def refresh_children_count!
@@ -54,7 +55,15 @@ class Indicator < Progress
54
55
 
55
56
  def completed?
56
57
  rebuild!
57
- children_passed_count == children_count
58
+ all_children_passed?
59
+ end
60
+
61
+ def once_completed?
62
+ self.once_completed || completed?
63
+ end
64
+
65
+ def self.delete_all_for!(content, organization)
66
+ where(content: content, organization: organization).delete_all
58
67
  end
59
68
 
60
69
  private
@@ -74,4 +83,8 @@ class Indicator < Progress
74
83
  def parent_content
75
84
  content.usage_in_organization(organization).structural_parent
76
85
  end
86
+
87
+ def all_children_passed?
88
+ children_passed_count == children_count
89
+ end
77
90
  end
@@ -0,0 +1,3 @@
1
+ class Medal < ApplicationRecord
2
+ has_many :users, as: :avatar
3
+ end
@@ -11,10 +11,12 @@ class Organization < ApplicationRecord
11
11
  serialize :settings, Mumuki::Domain::Organization::Settings
12
12
  serialize :theme, Mumuki::Domain::Organization::Theme
13
13
 
14
- markdown_on :description
14
+ markdown_on :description, :display_description, :page_description
15
+ teaser_on :display_description
15
16
 
16
17
  validate :ensure_consistent_public_login
17
18
  validate :ensure_valid_activity_range
19
+ validate :ensure_not_immersive_and_immersible
18
20
 
19
21
  belongs_to :book
20
22
  has_many :usages
@@ -97,11 +99,13 @@ class Organization < ApplicationRecord
97
99
  end
98
100
 
99
101
  def title_suffix
100
- central? ? '' : " - #{book.name}"
102
+ warn "Don't use title_suffix. Use page_name instead"
103
+ " - #{page_name}"
101
104
  end
102
105
 
103
106
  def site_name
104
- central? ? 'mumuki' : name
107
+ warn "Don't use site_name. Use display_name instead"
108
+ name
105
109
  end
106
110
 
107
111
  # Tells if the given user can
@@ -130,12 +134,55 @@ class Organization < ApplicationRecord
130
134
  update! progressive_display_lookahead: lookahead
131
135
  end
132
136
 
137
+ def progressive_display_lookahead=(lookahead)
138
+ self[:progressive_display_lookahead] = lookahead.to_i.positive? ? lookahead : nil
139
+ end
140
+
141
+ # ==============
142
+ # Display fields
143
+ # ==============
144
+
133
145
  def display_name
134
- name.gsub(/\W/, ' ').titleize
146
+ self[:display_name].presence || name.try { |it| it.gsub(/\W/, ' ').titleize }
147
+ end
148
+
149
+ def display_description
150
+ self[:display_description].presence || I18n.t('defaults.organization.display_description', name: name)
151
+ end
152
+
153
+ # ===========
154
+ # Page fields
155
+ # ===========
156
+
157
+ # Since an organization has a single book, both concepts may be merged
158
+ # when describing a site. In such contexts, wins_page?
159
+ # control whether the book or the organization header fields are
160
+ # more important
161
+
162
+ def page_name
163
+ wins_page? ? display_name : book.name
164
+ end
165
+
166
+ def page_description
167
+ wins_page? ? display_description : book.description
168
+ end
169
+
170
+ def all_contents
171
+ Usage.where(organization: self)
172
+ .group_by(&:item_type)
173
+ .flat_map { |item_type, item| item_type.constantize.where(id: item.map(&:item_id)) }
174
+ end
175
+
176
+ def awardable_contents
177
+ gamification_enabled? ? all_contents.select(&:medal_id) : []
135
178
  end
136
179
 
137
180
  private
138
181
 
182
+ def ensure_not_immersive_and_immersible
183
+ errors.add(:immersible, :cannot_be_immersive) if immersible? && immersive?
184
+ end
185
+
139
186
  def ensure_consistent_public_login
140
187
  errors.add(:base, :consistent_public_login) if settings.customized_login_methods? && public?
141
188
  end
@@ -8,6 +8,7 @@ class Usage < ApplicationRecord
8
8
 
9
9
  before_save :set_slug
10
10
  before_destroy :destroy_children_usages!
11
+ before_destroy :delete_associated_indicators!
11
12
 
12
13
  def self.destroy_all_where(query)
13
14
  where(query).destroy_all
@@ -27,6 +28,10 @@ class Usage < ApplicationRecord
27
28
 
28
29
  private
29
30
 
31
+ def delete_associated_indicators!
32
+ Indicator.delete_all_for!(item, organization)
33
+ end
34
+
30
35
  def set_slug
31
36
  self.slug = item.slug
32
37
  end
@@ -4,6 +4,7 @@ class User < ApplicationRecord
4
4
  WithUserNavigation,
5
5
  WithReminders,
6
6
  WithDiscussionCreation,
7
+ Awardee,
7
8
  Disabling,
8
9
  Mumuki::Domain::Helpers::User
9
10
 
@@ -31,7 +32,7 @@ class User < ApplicationRecord
31
32
  has_many :exams, through: :exam_authorizations
32
33
 
33
34
  enum gender: %i(female male other unspecified)
34
- belongs_to :avatar, optional: true
35
+ belongs_to :avatar, polymorphic: true, optional: true
35
36
 
36
37
  before_validation :set_uid!
37
38
  validates :uid, presence: true
@@ -190,6 +191,10 @@ class User < ApplicationRecord
190
191
  can_discuss_in? Organization.current
191
192
  end
192
193
 
194
+ def can_access_teacher_info_in?(organization)
195
+ teacher_of?(organization) || organization.teacher_training?
196
+ end
197
+
193
198
  def name_initials
194
199
  name.split.map(&:first).map(&:capitalize).join(' ')
195
200
  end
@@ -232,6 +237,18 @@ class User < ApplicationRecord
232
237
  end
233
238
  end
234
239
 
240
+ def current_organic_context
241
+ Organization.current? ? Organization.current : main_organization
242
+ end
243
+
244
+ def current_immersive_context_at(exercise)
245
+ if Organization.current?
246
+ immersive_organization_at(exercise) || Organization.current
247
+ else
248
+ main_organization
249
+ end
250
+ end
251
+
235
252
  private
236
253
 
237
254
  def welcome_to_new_organizations!
@@ -285,12 +302,4 @@ class User < ApplicationRecord
285
302
  def self.buried_profile
286
303
  (@buried_profile || {}).slice(:first_name, :last_name, :email)
287
304
  end
288
-
289
- def current_organic_context
290
- if Organization.current?
291
- Organization.current
292
- else
293
- main_organization
294
- end
295
- end
296
305
  end
@@ -1,5 +1,5 @@
1
1
  class AddTopSubmissionStatusToAssignments < ActiveRecord::Migration[5.1]
2
2
  def change
3
- add_column :assignments, :top_submission_status, :integer, default: 0
3
+ add_column :assignments, :top_submission_status, :integer
4
4
  end
5
5
  end
@@ -0,0 +1,8 @@
1
+ class CreateMedals < ActiveRecord::Migration[5.1]
2
+ def change
3
+ create_table :medals do |t|
4
+ t.string :image_url
5
+ t.string :description
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ class AddMedalToContent < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_reference :books, :medal, index: false
4
+ add_reference :guides, :medal, index: false
5
+ add_reference :topics, :medal, index: false
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ class AddPolymorphicAvatarsToUsers < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_column :users, :avatar_type, :string, default: 'Avatar'
4
+ add_index :users, [:avatar_type, :avatar_id]
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class AddOnceCompletedToIndicators < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_column :indicators, :once_completed, :boolean
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class AddStatusUpdatedFieldsToDiscussion < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_reference :discussions, :status_updated_by, index: true
4
+ add_column :discussions, :status_updated_at, :datetime
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class AddMisplacedFlagToSubmission < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_column :assignments, :misplaced, :boolean
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class AddDisplayNameAndDescriptionToOrganizations < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_column :organizations, :display_name, :text
4
+ add_column :organizations, :display_description, :text
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class AddOrganizationWinsPageFlag < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_column :organizations, :wins_page, :boolean
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddImmersibleToOrganization < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_column :organizations, :immersible, :boolean
4
+ end
5
+ end
@@ -2,6 +2,19 @@ class Array
2
2
  def insert_last(element)
3
3
  self + [element]
4
4
  end
5
+
6
+ def single
7
+ first if single?
8
+ end
9
+
10
+ def single!
11
+ raise 'There is more than one element' unless single?
12
+ first
13
+ end
14
+
15
+ def single?
16
+ size == 1
17
+ end
5
18
  end
6
19
 
7
20
  class NilClass
@@ -12,8 +12,9 @@ require_relative './factories/guide_factory'
12
12
  require_relative './factories/invitation_factory'
13
13
  require_relative './factories/lesson_factory'
14
14
  require_relative './factories/login_settings_factory'
15
+ require_relative './factories/medal_factory'
15
16
  require_relative './factories/message_factory'
16
17
  require_relative './factories/organization_factory'
17
18
  require_relative './factories/topic_factory'
18
- require_relative './factories/user_factory'
19
19
  require_relative './factories/usage_factory'
20
+ require_relative './factories/user_factory'
@@ -0,0 +1,6 @@
1
+ FactoryBot.define do
2
+ factory :medal do
3
+ image_url { Faker::Internet.url }
4
+ end
5
+ end
6
+
@@ -25,6 +25,7 @@ FactoryBot.define do
25
25
 
26
26
  factory :test_organization, parent: :public_organization do
27
27
  name { 'test' }
28
+ immersible { true }
28
29
  book { create(:book, name: 'test', slug: 'mumuki/mumuki-the-book') }
29
30
  end
30
31
 
@@ -28,6 +28,10 @@ module Mumuki::Domain::Helpers::Organization
28
28
  name == 'base'
29
29
  end
30
30
 
31
+ def immersed_in?(other)
32
+ immersible? && other.immersive? && target_audience == other.target_audience
33
+ end
34
+
31
35
  def switch!
32
36
  Mumukit::Platform::Organization.switch! self
33
37
  end
@@ -87,8 +87,24 @@ module Mumuki::Domain::Helpers::User
87
87
  student_granted_organizations.first || any_granted_organizations.first
88
88
  end
89
89
 
90
+ # Deprecated: use `immersive_organization_at` which
91
+ # properly looks for a single immersive organization taking
92
+ # current organization and path into account
90
93
  def has_immersive_main_organization?
91
- !!main_organization.try(&:immersive?)
94
+ main_organization.try(&:immersive?).present?
95
+ end
96
+
97
+ def immersive_organization_at(path_item, current = Organization.current)
98
+ immersive_organizations_at(path_item, current).single
99
+ end
100
+
101
+ def immersive_organizations_at(path_item, current = Organization.current)
102
+ return [] unless current.immersible?
103
+
104
+ usage_filter = path_item ? lambda { |it| path_item.used_in?(it) } : lambda { |_| true }
105
+ student_granted_organizations
106
+ .select { |it| current.immersed_in?(it) }
107
+ .select(&usage_filter)
92
108
  end
93
109
 
94
110
  ## API Exposure
@@ -44,6 +44,18 @@ module Mumuki::Domain
44
44
  false
45
45
  end
46
46
 
47
+ def can_access_teacher_info_in?(*)
48
+ false
49
+ end
50
+
51
+ def current_immersive_context_at(_)
52
+ nil
53
+ end
54
+
55
+ def immersive_organizations_at(_)
56
+ []
57
+ end
58
+
47
59
  # ========
48
60
  # Visiting
49
61
  # ========
@@ -28,3 +28,5 @@ en:
28
28
  base:
29
29
  consistent_public_login: 'A public organization can not restrict login methods'
30
30
  invalid_activity_range: 'The organization activity range are not valid'
31
+ immersible:
32
+ cannot_be_immersive: 'An organization cannot be immersible and immersive at the same time'
@@ -45,6 +45,8 @@ es:
45
45
  base:
46
46
  consistent_public_login: 'Una organización pública no puede restringir los métodos de login'
47
47
  invalid_activity_range: 'La fecha de deshabilitación no puede ser anterior a la de inicio del recorrido'
48
+ immersible:
49
+ cannot_be_immersive: 'Una organización no puede ser inmersible e inmersiva a la vez'
48
50
  models:
49
51
  exercise:
50
52
  one: Ejercicio
@@ -0,0 +1,4 @@
1
+ en:
2
+ defaults:
3
+ organization:
4
+ display_description: "In this site you will find programming contents about %{name}"
@@ -0,0 +1,4 @@
1
+ es-CL:
2
+ defaults:
3
+ organization:
4
+ display_description: "En este sitio encontrarás el contenido sobre programación de %{name}"
@@ -0,0 +1,4 @@
1
+ es:
2
+ defaults:
3
+ organization:
4
+ display_description: "En este sitio encontrarás el contenido sobre programación de %{name}"
@@ -0,0 +1,4 @@
1
+ pt:
2
+ defaults:
3
+ organization:
4
+ display_description: "Neste site você encontrará conteúdos de programação sobre %{name}"
@@ -12,7 +12,8 @@ class Mumuki::Domain::Organization::Profile < Mumukit::Platform::Model
12
12
  :terms_of_service,
13
13
  :community_link,
14
14
  :errors_explanations,
15
- :welcome_email_template
15
+ :welcome_email_template,
16
+ :welcome_email_sender
16
17
 
17
18
  def locale_json
18
19
  locale_h.to_json
@@ -8,6 +8,7 @@ class Mumuki::Domain::Organization::Settings < Mumukit::Platform::Model
8
8
  :forum_enabled?,
9
9
  :forum_only_for_trusted?,
10
10
  :gamification_enabled?,
11
+ :greet_new_users?,
11
12
  :immersive?,
12
13
  :in_preparation_until,
13
14
  :login_methods,
@@ -16,7 +17,7 @@ class Mumuki::Domain::Organization::Settings < Mumukit::Platform::Model
16
17
  :public?,
17
18
  :raise_hand_enabled?,
18
19
  :report_issue_enabled?,
19
- :greet_new_users?
20
+ :teacher_training?
20
21
 
21
22
  def private?
22
23
  !public?
@@ -30,11 +31,19 @@ class Mumuki::Domain::Organization::Settings < Mumukit::Platform::Model
30
31
  (@forum_discussions_minimal_role || 'student').to_sym
31
32
  end
32
33
 
34
+ def disabled_from=(disabled_from)
35
+ @disabled_from = disabled_from&.to_time
36
+ end
37
+
38
+ def in_preparation_until=(in_preparation_until)
39
+ @in_preparation_until = in_preparation_until&.to_time
40
+ end
41
+
33
42
  def disabled?
34
- disabled_from.present? && disabled_from.to_datetime < DateTime.now
43
+ disabled_from.present? && disabled_from < Time.now
35
44
  end
36
45
 
37
46
  def in_preparation?
38
- in_preparation_until.present? && in_preparation_until.to_datetime > DateTime.now
47
+ in_preparation_until.present? && in_preparation_until > Time.now
39
48
  end
40
49
  end
@@ -1,5 +1,5 @@
1
1
  module Mumuki
2
2
  module Domain
3
- VERSION = '7.9.0'
3
+ VERSION = '7.11.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mumuki-domain
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.9.0
4
+ version: 7.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Franco Leonardo Bulgarelli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-11 00:00:00.000000000 Z
11
+ date: 2020-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -252,6 +252,7 @@ files:
252
252
  - app/models/chapter.rb
253
253
  - app/models/complement.rb
254
254
  - app/models/concerns/assistable.rb
255
+ - app/models/concerns/awardee.rb
255
256
  - app/models/concerns/container.rb
256
257
  - app/models/concerns/contextualization.rb
257
258
  - app/models/concerns/disabling.rb
@@ -281,6 +282,7 @@ files:
281
282
  - app/models/concerns/with_language.rb
282
283
  - app/models/concerns/with_layout.rb
283
284
  - app/models/concerns/with_locale.rb
285
+ - app/models/concerns/with_medal.rb
284
286
  - app/models/concerns/with_messages.rb
285
287
  - app/models/concerns/with_name.rb
286
288
  - app/models/concerns/with_number.rb
@@ -315,6 +317,7 @@ files:
315
317
  - app/models/invitation.rb
316
318
  - app/models/language.rb
317
319
  - app/models/lesson.rb
320
+ - app/models/medal.rb
318
321
  - app/models/message.rb
319
322
  - app/models/organization.rb
320
323
  - app/models/progress.rb
@@ -620,6 +623,15 @@ files:
620
623
  - db/migrate/20200730221001_add_trusted_for_forum_to_user.rb
621
624
  - db/migrate/20200731081757_add_last_moderator_access_fields_to_discussion.rb
622
625
  - db/migrate/20200804191643_add_incognito_mode_enabled_to_organization.rb
626
+ - db/migrate/20200828152812_create_medals.rb
627
+ - db/migrate/20200828162829_add_medal_to_content.rb
628
+ - db/migrate/20200915123020_add_polymorphic_avatars_to_users.rb
629
+ - db/migrate/20200915131621_add_once_completed_to_indicators.rb
630
+ - db/migrate/20201009193949_add_status_updated_fields_to_discussion.rb
631
+ - db/migrate/20201019191036_add_misplaced_flag_to_submission.rb
632
+ - db/migrate/20201026222942_add_display_name_and_description_to_organizations.rb
633
+ - db/migrate/20201026225312_add_organization_wins_page_flag.rb
634
+ - db/migrate/20201027134205_add_immersible_to_organization.rb
623
635
  - lib/mumuki/domain.rb
624
636
  - lib/mumuki/domain/area.rb
625
637
  - lib/mumuki/domain/engine.rb
@@ -656,6 +668,7 @@ files:
656
668
  - lib/mumuki/domain/factories/invitation_factory.rb
657
669
  - lib/mumuki/domain/factories/lesson_factory.rb
658
670
  - lib/mumuki/domain/factories/login_settings_factory.rb
671
+ - lib/mumuki/domain/factories/medal_factory.rb
659
672
  - lib/mumuki/domain/factories/message_factory.rb
660
673
  - lib/mumuki/domain/factories/organization_factory.rb
661
674
  - lib/mumuki/domain/factories/topic_factory.rb
@@ -675,6 +688,10 @@ files:
675
688
  - lib/mumuki/domain/locales/console_submission/es-CL.yml
676
689
  - lib/mumuki/domain/locales/console_submission/es.yml
677
690
  - lib/mumuki/domain/locales/console_submission/pt.yml
691
+ - lib/mumuki/domain/locales/defaults/en.yml
692
+ - lib/mumuki/domain/locales/defaults/es-CL.yml
693
+ - lib/mumuki/domain/locales/defaults/es.yml
694
+ - lib/mumuki/domain/locales/defaults/pt.yml
678
695
  - lib/mumuki/domain/organization.rb
679
696
  - lib/mumuki/domain/organization/profile.rb
680
697
  - lib/mumuki/domain/organization/settings.rb