mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-11-29 10:24:20 +01:00
161 lines
5.1 KiB
Ruby
161 lines
5.1 KiB
Ruby
class Project < ActiveRecord::Base
|
|
include AASM
|
|
include NotifyWith::NotificationAttachedObject
|
|
include OpenlabSync
|
|
|
|
# elastic initialisations
|
|
include Elasticsearch::Model
|
|
index_name 'fablab'
|
|
document_type 'projects'
|
|
|
|
# kaminari
|
|
paginates_per 12 # dependency in projects.coffee
|
|
|
|
# friendlyId
|
|
extend FriendlyId
|
|
friendly_id :name, use: :slugged
|
|
|
|
has_one :project_image, as: :viewable, dependent: :destroy
|
|
accepts_nested_attributes_for :project_image, allow_destroy: true
|
|
has_many :project_caos, as: :viewable, dependent: :destroy
|
|
accepts_nested_attributes_for :project_caos, allow_destroy: true, reject_if: :all_blank
|
|
|
|
has_and_belongs_to_many :machines, join_table: :projects_machines
|
|
has_and_belongs_to_many :spaces, join_table: :projects_spaces
|
|
has_and_belongs_to_many :components, join_table: :projects_components
|
|
has_and_belongs_to_many :themes, join_table: :projects_themes
|
|
|
|
has_many :project_users, dependent: :destroy
|
|
has_many :users, through: :project_users
|
|
|
|
belongs_to :author, foreign_key: :author_id, class_name: 'User'
|
|
belongs_to :licence, foreign_key: :licence_id
|
|
|
|
has_many :project_steps, dependent: :destroy
|
|
accepts_nested_attributes_for :project_steps, allow_destroy: true
|
|
|
|
# validations
|
|
validates :author, :name, presence: true
|
|
|
|
after_save :after_save_and_publish
|
|
|
|
aasm :column => 'state' do
|
|
state :draft, initial: true
|
|
state :published
|
|
|
|
event :publish, :after => :notify_admin_when_project_published do
|
|
transitions from: :draft, :to => :published
|
|
end
|
|
end
|
|
|
|
#scopes
|
|
scope :published, -> { where("state = 'published'") }
|
|
|
|
## elastic
|
|
# callbacks
|
|
after_save { ProjectIndexerWorker.perform_async(:index, self.id) }
|
|
after_destroy { ProjectIndexerWorker.perform_async(:delete, self.id) }
|
|
|
|
# mapping
|
|
settings index: { number_of_replicas: 0 } do
|
|
mappings dynamic: 'true' do
|
|
indexes 'state', analyzer: 'simple'
|
|
indexes 'tags', analyzer: Rails.application.secrets.elasticsearch_language_analyzer
|
|
indexes 'name', analyzer: Rails.application.secrets.elasticsearch_language_analyzer
|
|
indexes 'description', analyzer: Rails.application.secrets.elasticsearch_language_analyzer
|
|
indexes 'project_steps' do
|
|
indexes 'title', analyzer: Rails.application.secrets.elasticsearch_language_analyzer
|
|
indexes 'description', analyzer: Rails.application.secrets.elasticsearch_language_analyzer
|
|
end
|
|
end
|
|
end
|
|
|
|
def as_indexed_json
|
|
Jbuilder.new do |json|
|
|
json.id id
|
|
json.state state
|
|
json.author_id author_id
|
|
json.user_ids user_ids
|
|
json.machine_ids machine_ids
|
|
json.theme_ids theme_ids
|
|
json.component_ids component_ids
|
|
json.tags tags
|
|
json.name name
|
|
json.description description
|
|
json.project_steps project_steps do |project_step|
|
|
json.title project_step.title
|
|
json.description project_step.description
|
|
end
|
|
json.created_at created_at
|
|
json.updated_at updated_at
|
|
end.target!
|
|
end
|
|
|
|
def self.search(params, current_user)
|
|
Project.__elasticsearch__.search(build_search_query_from_context(params, current_user))
|
|
end
|
|
|
|
def self.build_search_query_from_context(params, current_user)
|
|
search = {
|
|
query: {
|
|
bool: {
|
|
must: [],
|
|
should: [],
|
|
filter: [],
|
|
}
|
|
}
|
|
}
|
|
|
|
if params['q'].blank? # we sort by created_at if there isn't a query
|
|
search[:sort] = { created_at: { order: :desc } }
|
|
else # otherwise we search for the word (q) in various fields
|
|
search[:query][:bool][:must] << {
|
|
multi_match: {
|
|
query: params['q'],
|
|
type: 'most_fields',
|
|
fields: %w(tags^4 name^5 description^3 project_steps.title^2 project_steps.description)
|
|
}
|
|
}
|
|
end
|
|
|
|
params.each do |name, value| # we filter by themes, components, machines
|
|
if name =~ /(.+_id$)/
|
|
search[:query][:bool][:filter] << { term: { "#{name}s" => value } } if value
|
|
end
|
|
end
|
|
|
|
if current_user and params.key?('from') # if use select filter 'my project' or 'my collaborations'
|
|
if params['from'] == 'mine'
|
|
search[:query][:bool][:filter] << { term: { author_id: current_user.id } }
|
|
end
|
|
if params['from'] == 'collaboration'
|
|
search[:query][:bool][:filter] << { term: { user_ids: current_user.id } }
|
|
end
|
|
end
|
|
|
|
if current_user # if user is connected, also display his draft projects
|
|
search[:query][:bool][:should] << { term: { state: 'published' } }
|
|
search[:query][:bool][:should] << { term: { author_id: current_user.id } }
|
|
search[:query][:bool][:should] << { term: { user_ids: current_user.id } }
|
|
else # otherwise display only published projects
|
|
search[:query][:bool][:must] << { term: { state: 'published' } }
|
|
end
|
|
|
|
search
|
|
end
|
|
|
|
private
|
|
def notify_admin_when_project_published
|
|
NotificationCenter.call type: 'notify_admin_when_project_published',
|
|
receiver: User.admins,
|
|
attached_object: self
|
|
end
|
|
|
|
def after_save_and_publish
|
|
if state_changed? and published?
|
|
update_columns(published_at: Time.now)
|
|
notify_admin_when_project_published
|
|
end
|
|
end
|
|
end
|