Skip to content

Instantly share code, notes, and snippets.

@DmytroVasin
Last active April 4, 2016 16:13
Show Gist options
  • Save DmytroVasin/2ab7addcb686839802727c0b4f52f803 to your computer and use it in GitHub Desktop.
Save DmytroVasin/2ab7addcb686839802727c0b4f52f803 to your computer and use it in GitHub Desktop.
parts of code
angular.module("Meek").controller "RadioStationsController", (
$sce
$rootScope
$scope
$stateParams
Category
RadioStation
ApplicationService
RankService
) ->
$scope.category = Category.get({ id: $stateParams.categoryId })
$scope.radioStation = RadioStation.get({ id: $stateParams.id }, (radioStation) ->
$rootScope.head.setMetaTag({ name: 'robots', content: 'noindex' }) if radioStation.noindex
$rootScope.head.setAllMetaInformation({ title: radioStation.meta_title, description: radioStation.meta_description, imagePath: radioStation.image, googlebotImage: radioStation.googlebot })
RankService.initRankFor({ id: radioStation.id, type: 'RadioStation' })
$scope.htmlSafeDescription = $sce.trustAsHtml(radioStation.description)
)
angular.module("Meek").service 'AuthenticationService', (
$stateParams
$location
$state
$cookies
RadioStation
Auth
AlertService
FormService
ModalService
PlayerService
Layout
) ->
class Authentication
_newPasswordForm: $('#user-new-password-form')
constructor: ->
@setCurrentUser()
if $stateParams.reset_password_token
ModalService.newPassword($stateParams.reset_password_token)
return this
submitUserRegistration: (event) =>
event.preventDefault()
_registrationForm = $(event.currentTarget)
FormService.clearErrors(_registrationForm)
credentials = {
email: _registrationForm.find('input[name=email]').val(),
password: _registrationForm.find('input[name=password]').val(),
password_confirmation: _registrationForm.find('input[name=password_confirmation]').val()
}
Auth.register(credentials).then ((user) =>
# Auth#register automaticaly set _currentUser on save.
Auth._currentUser = undefined
ModalService.closeAll()
AlertService.display('You need confirm your email', 'warning')
return
), (errors) =>
FormService.displayErrors(_registrationForm, errors.data)
return
return
submitLogin: (event) =>
event.preventDefault()
_signInForm = $(event.currentTarget)
FormService.clearErrors(_signInForm)
credentials = {
email: _signInForm.find('input[name=email]').val(),
password: _signInForm.find('input[name=password]').val(),
}
Auth.login(credentials).then ((user) =>
AlertService.display('Welcome back!', 'success')
@setCurrentUser()
ModalService.closeAll()
@redirectAfterLogin( user.slug ) if Layout.isMobile()
return
), (errors) =>
FormService.displayErrors(_signInForm, errors.data)
return
return
isAuthenticated: ->
Auth.isAuthenticated()
setCurrentUser: =>
Auth.currentUser().then ((user) =>
@currentUser = user
@startDefaultRadio()
return
), (error) =>
@currentUser = null
return
return
logout: =>
Auth.logout().then ( =>
@currentUser = undefined
AlertService.display('You have been logged out', 'success')
if PlayerService.isPlaying() && Layout.isMobile()
PlayerService.destroyPlayer()
$state.go('home')
), (error) ->
AlertService.display('There was a problem logging out. Please try again.', 'warning')
return
displayName: =>
name = ''
if @currentUser?
name = @currentUser.full_name || @currentUser.email
return name
reloadCurrentUser: =>
Auth.reset()
@setCurrentUser()
submitPasswordReset: (event) =>
event.preventDefault()
_passwordResetForm = $(event.currentTarget)
FormService.clearErrors(_passwordResetForm)
result = FormService.submit(_passwordResetForm)
result.success (data) =>
ModalService.closeAll()
AlertService.display('An email with password reset instructions has been sent to you.', 'success')
return
result.error (data) =>
FormService.displayErrors(_passwordResetForm, data)
return
return
submitEmailReconfirm: (event) =>
event.preventDefault()
_resendConfirmationForm = $(event.currentTarget)
FormService.clearErrors(_resendConfirmationForm)
result = FormService.submit(_resendConfirmationForm)
result.success (data) =>
ModalService.closeAll()
AlertService.display('An email with confirmation link has been sent to you.', 'success')
return
result.error (data) =>
FormService.displayErrors(_resendConfirmationForm, data)
return
return
submitNewPassword: (event) =>
event.preventDefault()
_newPasswordForm = $(event.currentTarget)
FormService.clearErrors(_newPasswordForm)
result = FormService.submit(_newPasswordForm)
result.success (data) =>
@reloadCurrentUser()
ModalService.closeAll()
AlertService.display('Your password has been reset.', 'success')
# $state.go('home')
$location.url('/')
return
result.error (data) =>
FormService.displayErrors(_newPasswordForm, data)
return
return
changePassword: (event) =>
event.preventDefault()
$form = $(event.target)
FormService.clearErrors($form)
$result = FormService.submit($form)
$result.success (data, status, headers, config) =>
@reloadCurrentUser()
FormService.clearFields($form)
ModalService.closeAll()
AlertService.display('Your password was changed.', 'success')
$result.error (data, status, headers, config) =>
FormService.displayErrors($form, data)
startDefaultRadio: =>
return if !@currentUser.radio_station_id || !@currentUser.is_auto_play || PlayerService.isPlaying()
RadioStation.get({ id: @currentUser.radio_station_id }, (stationStation) ->
PlayerService.startRadio(stationStation)
)
return
redirectAfterLogin: (slug) =>
url = $cookies.get('previouseState')
$location.url( url )
return new Authentication()
angular.module("Meek").service 'PlayerService', (
$rootScope
$timeout
Metadata
AlertService
ModalService
Layout
Play
) ->
class Player
_meekPlayer: $('#meek-player')
_playerCardImg: $('.player-song-card img')
_playerCardDescriptionRow: $('.player-song-card .song-card-user-description-row')
_playerCardDescription: $('.player-song-card .song-card-user-description')
_playerCardTitle: $('.player-song-card .song-card-title')
constructor: ->
@_player = $("#player").jPlayer
swfPath: "../dist/jplayer"
solution: "html, flash"
supplied: "mp3"
preload: "auto"
volume: 0.8
muted: false
backgroundColor: "#000000"
cssSelectorAncestor: "#meek-player"
cssSelector:
videoPlay: ".jp-video-play"
play: ".new-jp-play"
pause: ".new-jp-pause"
stop: ".new-jp-stop"
seekBar: ".new-jp-seek-bar"
playBar: ".new-jp-play-bar"
mute: ".new-jp-mute"
unmute: ".new-jp-unmute"
volumeBar: ".new-jp-volume-bar"
volumeBarValue: ".new-jp-volume-bar-value"
volumeMax: ".new-jp-volume-max"
playbackRateBar: ".jp-playback-rate-bar"
playbackRateBarValue: ".jp-playback-rate-bar-value"
currentTime: ".new-jp-current-time"
duration: ".new-jp-duration"
title: ".jp-title"
fullScreen: ".jp-full-screen"
restoreScreen: ".jp-restore-screen"
repeat: ".jp-repeat"
repeatOff: ".jp-repeat-off"
gui: ".jp-gui"
noSolution: ".jp-no-solution"
errorAlerts: false
warningAlerts: false
error: (e) ->
AlertService.display('The episode is not available at the moment.', 'warning')
return
return
startRadio: (radioStation) =>
return if @_unAuthorized()
@_currentPodcast = undefined
@_currentEpisode = undefined
@_currentRadioStation = radioStation
@setStream(radioStation.name, radioStation.stream_url)
@showRadioStationPlayer()
@showRadioStationInfo()
@play()
return
showRadioStationInfo: =>
$rootScope.playerInfo.setInfo(
type: 'radio'
image: @_currentRadioStation.image
title: @_currentRadioStation.name
favoriteId: @_currentRadioStation.id
favoriteType: 'RadioStation'
defaultRadioId: @_currentRadioStation.id
radioStationId: @_currentRadioStation.id
categoryId: @_currentRadioStation.category_id
currentPath: @_currentRadioStation.path
)
@_playerCardImg.attr('src', @_currentRadioStation.image)
@_playerCardTitle.html(@_currentRadioStation.name)
@_playerCardDescriptionRow.hide()
@loadRadioStationMetaData()
return
loadRadioStationMetaData: =>
Metadata.get({ id: @_currentRadioStation.id }, (metadata) =>
if metadata.artist? || metadata.song?
@_playerCardDescription.html("<span>Artist:</span>#{metadata.artist} | <span>Song:</span>#{metadata.song}")
@_playerCardDescriptionRow.show()
# since metadata was found, keep polling for changes.
@_radioMetadataTimeout = $timeout( @loadRadioStationMetaData, 5000 )
else
@_playerCardDescriptionRow.hide()
)
return
startPodcast: (podcast, episode, stopped_at) =>
return if @_unAuthorized()
@_currentPodcast = podcast
@_currentEpisode = episode
@_currentRadioStation = undefined
@setStream(@_currentEpisode.name, @_currentEpisode.stream_url)
@showPodcastPlayer()
@showPodcastInfo()
@play(stopped_at)
return
showPodcastInfo: =>
$rootScope.playerInfo.setInfo(
type: 'podcast'
image: @_currentPodcast.image
title: @_currentPodcast.name
favoriteId: @_currentEpisode.id
favoriteType: 'Episode'
episodeId: @_currentEpisode.id
podcastId: @_currentPodcast.id
categoryId: @_currentPodcast.category_id
currentPath: @_currentEpisode.path
)
@_playerCardImg.attr('src', @_currentPodcast.image)
@_playerCardTitle.html(@_currentPodcast.name)
@_playerCardDescription.html(@_currentEpisode.name)
@_playerCardDescriptionRow.show()
return
setStream: (title, streamUrl) =>
# cancel the metadata polling if active
$timeout.cancel(@_radioMetadataTimeout) if @_radioMetadataTimeout?
$timeout.cancel(@_playTrackingTimeout) if @_playTrackingTimeout?
if streamUrl
@_player.jPlayer('setMedia', { mp3: streamUrl })
else
@_player.jPlayer('clearMedia')
return
play: (stopped_at) =>
if stopped_at?
@_player.jPlayer('play', stopped_at)
else
@_player.jPlayer('play')
@showPlayer()
@startPlayTracking()
pause: =>
@_player.jPlayer('pause') if @isPlaying()
showPlayer: =>
$('body').addClass('player-enable')
@_meekPlayer.show()
showPodcastPlayer: =>
@_meekPlayer.addClass('podcastIsPlaying')
@_meekPlayer.removeClass('radioStationIsPlaying')
showRadioStationPlayer: =>
@_meekPlayer.addClass('radioStationIsPlaying')
@_meekPlayer.removeClass('podcastIsPlaying')
isPlaying: =>
return @_currentPodcast || @_currentRadioStation
startPlayTracking: =>
@playTrack = new Play()
if @_currentEpisode?
@playTrack.media_type = 'Episode'
@playTrack.media_id = @_currentEpisode.id
else
@playTrack.media_type = 'RadioStation'
@playTrack.media_id = @_currentRadioStation.id
@playTrack.$save()
@_playTrackingTimeout = $timeout( @playTracking, 3000 )
return
playTracking: =>
id = @playTrack.id
user_id = $rootScope.auth.currentUser.id if $rootScope.auth.isAuthenticated()
stopped_at = @_player.data("jPlayer").status.currentTime if @playTrack.media_type == 'Episode'
Play.update({ id: id, user_id: user_id, stopped_at: stopped_at }) unless @_player.data('jPlayer').status.paused
@_playTrackingTimeout = $timeout( @playTracking, 3000 )
destroyPlayer: =>
$timeout.cancel( @_playTrackingTimeout )
$timeout.cancel( @_radioMetadataTimeout )
@_currentPodcast = undefined
@_currentEpisode = undefined
@_currentRadioStation = undefined
$('body').removeClass('player-enable')
@_meekPlayer.hide()
@_player.jPlayer('stop')
_unAuthorized: =>
if !$rootScope.auth.isAuthenticated() && Layout.isMobile()
ModalService.signInDialog()
return true
return false
return new Player()
module Admins
class NetworkCompaniesController < ApplicationController
def index
self.resources = NetworkCompany.order('created_at DESC').page(params[:page]).per(10)
end
def show
find_resource
end
def new
self.resource = NetworkCompany.new
end
def create
self.resource = NetworkCompany.new(resource_params)
if resource.save
flash[:notice] = t('application.company_created')
redirect_to admins_network_companies_url
else
render :new
end
end
def edit
find_resource
end
def update
find_resource
if resource.update(resource_params)
flash[:notice] = t('application.company_updated')
redirect_to admins_network_company_url(id: params[:id])
else
render :edit
end
end
def destroy
find_resource.destroy
flash[:notice] = t('application.company_destroy')
redirect_to admins_network_companies_url
end
private
def find_resource
self.resource = NetworkCompany.find(params[:id])
end
def resource_params
params.require(:network_company).permit(:name, {company_ids: []})
end
end
end
class AccountsController < ::ApplicationController
skip_before_action :prepare_resource_controller
before_action :authenticate_user!
def edit
@account = current_user.account || current_user.build_account_with_default_params
end
def update
if current_user.update_attributes(get_params)
redirect_to root_path, notice: t('realtors.account.message_updated')
current_user.update(email: get_params[:account_attributes][:personal_email])
else
@account = current_user.account
render :edit
end
end
def destroy
if current_user.provider || current_user.valid_password?(params[:user][:password])
current_user.destroy
redirect_to root_url, notice: t('application.message_after_destroy')
else
redirect_to edit_account_path, alert: t('application.message_after_destroy_error')
end
end
# Not REST!
def inactive
current_user.account.update_attributes(active: false)
redirect_to root_path
end
private
def get_params
send("#{current_user.role}_params")
end
def tenant_params
params.require(:user).permit(:profile_image,
account_attributes: [:first_name, :last_name, :phone,
:personal_email ])
end
def realtor_params
params.require(:user).permit(:profile_image,
account_attributes: [:first_name, :last_name, :phone,
:personal_email, :company_id,
:professional_email, :creci_number])
end
def guest_params
params.require(:user).permit(:profile_image,
account_attributes: [:first_name, :last_name, :phone,
:personal_email, :company_id, :role,
:professional_email, :creci_number])
end
end
class User < ActiveRecord::Base
attr_accessor :month, :day, :year
extend FriendlyId
include CustomerioCallbacks
friendly_id :username, use: :slugged
# Include default devise modules. Others available are:
# :validatable, :lockable, and :timeoutable
devise :database_authenticatable, :registerable, :recoverable,
:rememberable, :trackable, :omniauthable, :confirmable
belongs_to :church_type, class_name: 'ChurchType'
belongs_to :radio_station, class_name: 'RadioStation'
belongs_to :invitation
has_one :address, dependent: :destroy
has_one :identity, dependent: :destroy
has_many :sent_invitations, class_name: 'Invitation', foreign_key: 'sender_id', dependent: :destroy
has_many :audits, class_name: 'Audit', dependent: :destroy
has_many :favorites, class_name: 'Favorite', dependent: :destroy
has_many :plays, class_name: 'Play', dependent: :destroy
has_many :votes, dependent: :destroy
has_many :favorite_podcasts, through: :favorites, source: :favoritable, source_type: 'Podcast'
has_many :favorite_episodes, through: :favorites, source: :favoritable, source_type: 'Episode'
has_many :favorite_stations, through: :favorites, source: :favoritable, source_type: 'RadioStation'
accepts_nested_attributes_for :address
accepts_nested_attributes_for :audits
has_attached_file :background_pic
has_attached_file :profile_pic, default_url: ':default_user', styles: { normal: '200x200#' }
before_create :create_address
# Default Devise Validation ( devise module :validatable )
# ------------------------
validates_presence_of :email, if: :email_changed?
validates_uniqueness_of :email, allow_blank: true, if: :email_changed?
validates_format_of :email, with: Devise::email_regexp, allow_blank: true, if: :email_changed?
validates_presence_of :password, if: :password_required?
validates_confirmation_of :password, if: :password_required?
validates_length_of :password, within: Devise::password_length, allow_blank: true
def password_required?
!password.nil? || !password_confirmation.nil?
end
# ------------------------
validates_length_of :language, maximum: 255, too_long: 'Pick a shorter name'
validates_length_of :church_name, maximum: 255, too_long: 'Pick a shorter name'
validates :username, uniqueness: true, allow_blank: true
validates :gender, inclusion: { in: ['Male', 'Female'] }, allow_blank: true
validates :christian_for, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 100 }, allow_blank: true
validate :format_username
validate :format_birth_date
validates_attachment_content_type :background_pic, content_type: /\Aimage\/.*\Z/
validates_attachment_content_type :profile_pic, content_type: /\Aimage\/.*\Z/
def full_name
"#{first_name} #{last_name}".strip.presence
end
def full_name_with_email
full_name || email
end
def update_tracked_fields(request)
super
audits.build(action: 'login', ip: last_sign_in_ip) if last_sign_in_at_changed?
end
# NOTE: This method is return additional values when we call
#
# respond_to current_user
def as_json(options = {})
result = super
result['address'] = self.address
result['profile_pic'] = self.profile_pic.url(:normal)
result['background_pic'] = self.background_pic.url if self.background_pic.present?
result['full_name'] = self.full_name
result['church_type'] = self.church_type.try(:name)
result['year'] = self.birth_date.try(:year)
result['month'] = self.birth_date.try(:month)
result['day'] = self.birth_date.try(:day)
result['unconfirmed_email'] = self.unconfirmed_email
return result
end
def format_username
if self.username_changed?
precompiled_slug = self.username.downcase.parameterize
if User.where(slug: precompiled_slug).where.not(username: self.username).any?
errors.add( :username, 'Already has such slug')
end
end
end
def format_birth_date
if self.year && self.month && self.day
self.errors.add( :day, 'Date is invalid') unless convert_birth_date
end
end
def convert_birth_date
begin
civil_date = Date.civil( self.year.to_i, self.month.to_i, self.day.to_i )
raise ArgumentError if civil_date > Date.today
self.birth_date = civil_date
rescue ArgumentError
false
end
end
def should_generate_new_friendly_id?
slug.blank? || username_changed?
end
# Note: We should remember user by default.
def remember_me
true
end
# Note: We should create address for new users
def create_address
build_address
end
def christian_for=(num)
num.gsub!(',', '.') if num.is_a?(String)
self[:christian_for] = num
end
end
#main-header {
.right-side {
@include user-avatar(50) {
vertical-align: middle;
}
.header-search-link { display: none; }
.icon-wrapper {
line-height: initial;
display: inline-block;
vertical-align: middle;
}
.icon-search-header {
@include btn-search;
font-size: 25px;
line-height: $navbar-height;
z-index: 10;
}
.header-search {
position: relative;
input {
width: 100%;
padding: 0 60px 0 35px;
border: 0;
color: $header_grey;
line-height: $navbar-height;
background-color: transparent;
box-sizing: border-box;
vertical-align: top;
&:focus { box-shadow: none; }
}
.search-block {
width: 380px;
position: relative;
border-left: 1px solid #3b3b3b;
border-right: 1px solid #3b3b3b;
display: inline-block;
&> * { margin: 0px; }
}
}
.icon-login, .icon-invite {
padding-left: 7px;
font-size: 24px;
}
.icon-text {
font-family: $helvetica-neue, $open-bold;
font-size: 10px;
font-weight: bold;
}
}
}
@include tablet-landscape {
#main-header {
.right-side {
.header-search {
.search-block { width: 160px; }
}
}
}
}
@include tablet-portrait {
#main-header {
.right-side {
.header-search {
display: none;
input {
@include border-radius(5px);
line-height: 50px;
}
}
.header-search-link {
display: inline-block;
position: relative;
&.open {
&:after {
width: 0;
height: 0;
content: '';
border-style: solid;
border-width: 0 7px 7px 7px;
border-color: transparent transparent rgba(0, 0, 0, 0.9) transparent;
position: absolute;
bottom: 0;
left: 40%;
}
.icon-search-header { display: none; }
.icon-close-bold { display: block; }
}
&.open + .header-search {
width: 100%;
display: block;
position: fixed;
left: 0;
background-color: rgba(0, 0, 0, 0.7);
line-height: 50px;
.search-block {
@include border-radius(5px);
width: 90%;
margin: 40px 0;
background-color: #fff;
.icon-search-header { line-height: 50px; }
}
}
.icon-search-header {
padding: 0;
display: block;
position: static;
}
.icon-close-bold { display: none; }
}
}
}
}
@include mobile-landscape {
#main-header {
.right-side {
.header-search {
input { padding: 0 50px 0 15px; }
}
.header-search-link {
&.open {
&:after {
bottom: 0;
left: 8px;
}
&+ .header-search {
.search-block {
.icon-search-header { padding: 0 14px 0 12px; }
}
}
}
.icon-search-header {
line-height: $header-mobile-height;
}
}
.icon-text { display: none; }
.user-avatar {
width: 30px;
height: 30px;
}
}
}
}
class Shop::Cart < ActiveRecord::Base
belongs_to :buyer
belongs_to :order
has_many :cart_items
has_many :products, through: :cart_items
delegate :carrier, to: :buyer
def has_items?
cart_items.present?
end
def include_product? product
@ids ||= products.map &:id
@ids.include? product.id
end
def add_or_update_item item
cart_items << item
end
def remove_item_by_id id
item = cart_items.find id
item.destroy
end
def currency
# TODO: maybe to calculate currency by buyer.country even if the cart is empty? On client side we have done this.
return '' if cart_items.empty?
cart_items.first.product.pricing.currency
end
def total_quantity
cart_items.sum(:quantity)
end
def total_cost
cart_items.to_a.sum(&:total_price)
end
def duplicate_cart_items_into new_cart
new_cart.cart_items = self.cart_items.map do |ci|
new_ci = ci.dup
new_ci.ordered_product_id = nil
new_ci
end
end
end
class User < ActiveRecord::Base
attr_accessor :month, :day, :year
extend FriendlyId
include CustomerioCallbacks
friendly_id :username, use: :slugged
# Include default devise modules. Others available are:
# :validatable, :lockable, and :timeoutable
devise :database_authenticatable, :registerable, :recoverable,
:rememberable, :trackable, :omniauthable, :confirmable
belongs_to :church_type, class_name: 'ChurchType'
belongs_to :radio_station, class_name: 'RadioStation'
belongs_to :invitation
has_one :address, dependent: :destroy
has_one :identity, dependent: :destroy
has_many :sent_invitations, class_name: 'Invitation', foreign_key: 'sender_id', dependent: :destroy
has_many :audits, class_name: 'Audit', dependent: :destroy
has_many :favorites, class_name: 'Favorite', dependent: :destroy
has_many :plays, class_name: 'Play', dependent: :destroy
has_many :votes, dependent: :destroy
has_many :favorite_podcasts, through: :favorites, source: :favoritable, source_type: 'Podcast'
has_many :favorite_episodes, through: :favorites, source: :favoritable, source_type: 'Episode'
has_many :favorite_stations, through: :favorites, source: :favoritable, source_type: 'RadioStation'
accepts_nested_attributes_for :address
accepts_nested_attributes_for :audits
has_attached_file :background_pic
has_attached_file :profile_pic, default_url: ':default_user', styles: { normal: '200x200#' }
before_create :create_address
# Default Devise Validation ( devise module :validatable )
# ------------------------
validates_presence_of :email, if: :email_changed?
validates_uniqueness_of :email, allow_blank: true, if: :email_changed?
validates_format_of :email, with: Devise::email_regexp, allow_blank: true, if: :email_changed?
validates_presence_of :password, if: :password_required?
validates_confirmation_of :password, if: :password_required?
validates_length_of :password, within: Devise::password_length, allow_blank: true
def password_required?
!password.nil? || !password_confirmation.nil?
end
# ------------------------
validates_length_of :language, maximum: 255, too_long: 'Pick a shorter name'
validates_length_of :church_name, maximum: 255, too_long: 'Pick a shorter name'
validates :username, uniqueness: true, allow_blank: true
validates :gender, inclusion: { in: ['Male', 'Female'] }, allow_blank: true
validates :christian_for, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 100 }, allow_blank: true
validate :format_username
validate :format_birth_date
validates_attachment_content_type :background_pic, content_type: /\Aimage\/.*\Z/
validates_attachment_content_type :profile_pic, content_type: /\Aimage\/.*\Z/
def full_name
"#{first_name} #{last_name}".strip.presence
end
def full_name_with_email
full_name || email
end
def update_tracked_fields(request)
super
audits.build(action: 'login', ip: last_sign_in_ip) if last_sign_in_at_changed?
end
# NOTE: This method is return additional values when we call
#
# respond_to current_user
def as_json(options = {})
result = super
result['address'] = self.address
result['profile_pic'] = self.profile_pic.url(:normal)
result['background_pic'] = self.background_pic.url if self.background_pic.present?
result['full_name'] = self.full_name
result['church_type'] = self.church_type.try(:name)
result['year'] = self.birth_date.try(:year)
result['month'] = self.birth_date.try(:month)
result['day'] = self.birth_date.try(:day)
result['unconfirmed_email'] = self.unconfirmed_email
return result
end
def format_username
if self.username_changed?
precompiled_slug = self.username.downcase.parameterize
if User.where(slug: precompiled_slug).where.not(username: self.username).any?
errors.add( :username, 'Already has such slug')
end
end
end
def format_birth_date
if self.year && self.month && self.day
self.errors.add( :day, 'Date is invalid') unless convert_birth_date
end
end
def convert_birth_date
begin
civil_date = Date.civil( self.year.to_i, self.month.to_i, self.day.to_i )
raise ArgumentError if civil_date > Date.today
self.birth_date = civil_date
rescue ArgumentError
false
end
end
def should_generate_new_friendly_id?
slug.blank? || username_changed?
end
# Note: We should remember user by default.
def remember_me
true
end
# Note: We should create address for new users
def create_address
build_address
end
def christian_for=(num)
num.gsub!(',', '.') if num.is_a?(String)
self[:christian_for] = num
end
end
angular.module("Meek").service 'ShareService', (
$location
) ->
class Share
rootUrls: ->
# Remvoe to UTILS
# window.location.origin
$location.$$protocol + '://' + $location.$$host
shareLink: ( type, opts ) =>
url = @rootUrls() + opts.linkPath
image = @rootUrls() + opts.imagePath
text = opts.title
if type == 'google'
@_shareGoogle(url)
if type == 'facebook'
@_shareFacebook(url)
if type == 'twitter'
@_shareTwitter(url, text)
if type == 'pinterest'
@_sharePinterest(url, text, image)
return
_shareGoogle: (url) =>
@_open("https://plus.google.com/share?url=#{ url }")
_shareFacebook: (url) =>
@_open("https://www.facebook.com/sharer/sharer.php?u=#{ url }")
_shareTwitter: (url, text) =>
@_open("https://twitter.com/share?url=#{ url }&text=#{ text }")
_sharePinterest: (url, text, image)=>
@_open("http://pinterest.com/pin/create/button/?url=#{ url }&description=#{ text }&media=#{ image }")
_open: (url) ->
window.open(url, '', 'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=300,width=600')
return
return new Share()
class SearchService
# Current service returns hash of Episodes/Podcasts/RadioStations that contains arrays of appropriate ids
# Appropriate ids depends from ts_rank
def initialize(search_phrase, page)
@options = base_options({ page: page })
@phrase = sanitize_request( search_phrase )
end
def call
return if @phrase.blank?
query = get_sql_raw_string(@phrase)
data = ActiveRecord::Base.connection.select_all(query)
prettify_datas(data)
end
private
def base_options(options)
options[:page] ||= 1
options[:per_page] ||= 10
options[:offset] = (options[:page].to_i - 1) * options[:per_page].to_i
options
end
def sanitize_request(search_phrase)
return nil if search_phrase.blank?
search_phrase.squish.gsub(/[^A-Za-z \-]/, '').split
end
# Method returns hash
# With Keys: "Episode", "Podcast", "RadioStation" values
# With Values: Array of proper Ids
def prettify_datas(data)
resulting_hash = {'Episode' => [], 'Podcast' => [], 'RadioStation' => []}
data.map{ |row|
{
id: row['searchable_id'],
type: row['searchable_type']
}
}.each { |subhash| resulting_hash[subhash[:type]] << subhash[:id] }
resulting_hash
end
def get_sql_raw_string(phrase)
query = prepare_phrase(phrase)
# http://www.postgresql.org/docs/9.1/static/textsearch-controls.html
<<-SQL
SELECT searchable_id,
searchable_type,
ts_rank(p_search.document, to_tsquery('english', '#{query}')) As rank
FROM (
SELECT p.id AS searchable_id,
'Podcast' AS searchable_type,
setweight(to_tsvector('english', p.name), 'A') ||
setweight(to_tsvector('english', p.h1), 'B') ||
setweight(to_tsvector('english', p.short_description), 'C') AS document
FROM podcasts p
UNION
SELECT rs.id AS searchable_id,
'RadioStation' AS searchable_type,
setweight(to_tsvector('english', rs.name), 'A') ||
setweight(to_tsvector('english', rs.h1), 'B') ||
setweight(to_tsvector('english', rs.short_description), 'C') AS document
FROM radio_stations rs
UNION
SELECT ep.id AS searchable_id,
'Episode' AS searchable_type,
setweight(to_tsvector('english', ep.h1), 'A') AS document
FROM episodes ep
) p_search
WHERE p_search.document @@ to_tsquery('english', '#{query}')
ORDER BY ts_rank(p_search.document, to_tsquery('english', '#{query}')) DESC
LIMIT '#{ @options[:per_page] }' OFFSET '#{ @options[:offset] }';
SQL
end
def prepare_phrase(phrase)
# http://www.postgresql.org/docs/9.1/static/datatype-textsearch.html
# This query will match any word in a tsvector that begins with "super". Note that prefixes are first processed by text search configurations, which means this comparison returns true:
#
# SELECT to_tsvector( 'postgraduate' ) @@ to_tsquery( 'postgres:*' );
# ?column?
# ----------
# t
# (1 row)
#
# because postgres gets stemmed to postgr:
phrase.map{|x| "#{x}:*"}.join(' & ')
end
end
class LocationsService
attr_reader :row_types, :relation
def initialize
@row_types = %i[state city neighborhood].map{ |key| I18n.t(key, scope: self.class.name.underscore) }
@relation = City.unscoped.eager_load(:neighborhoods).order(:state_id, population: :desc)
end
# List for JS search element
# [['NameA <i>City</i>', '001'], ['NameB <i>City</i>', '002']]
def list_for_search
prev_state_id = nil
[].tap do |list|
relation.each do |city|
unless city.state_id == prev_state_id
prev_state_id = city.state_id
list << serch_list_row(city.state)
end
list << serch_list_row(city.state, city)
city.neighborhoods.each do |neighborhood|
list << serch_list_row(city.state, city, neighborhood)
end
end
end
end
# List of the cities per state_id for new|edit Property page City select
# {1=>[[2, "Rio Branco"], [1, "Cruzeiro do Sul"], [3, "Sena Madureira"], [4, "Tarauacá"]],
def cities_list
{}.tap do |list|
relation.each do |city|
(list[city.state_id] ||= []) << [city.id, city.name]
end
end
end
# List of the neighborhoods per city_id for new|edit Property page Neighborhood select
# {104=>["Tabapiry", "Arraial Dajuda", "Centro"]
def neighborhoods_list
{}.tap do |list|
relation.each do |city|
if city.neighborhoods.any?
list[city.id] = city.neighborhoods.map(&:name)
end
end
end
end
private
def serch_list_row(state, city = nil, neighborhood = nil)
ids = [state, city, neighborhood].compact.map(&:id)
names = [neighborhood.try(:name), city.try(:name), state.code].compact
["#{names.join(', ')} <i>#{self.row_types[ids.size - 1]}</i>", ids.join(',')]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment