Update a lots.(include allow not logins user to hire, let admin set calendar display?,fix bugs)

This commit is contained in:
BoHung Chiu 2021-09-08 10:10:44 +08:00
parent 3366262e62
commit e199880f13
21 changed files with 998 additions and 317 deletions

View File

@ -103,9 +103,10 @@ window.getDateString = function(date, format,is_chinese) {
}
return formattedDate;
};
var Calendar = function(dom,property_id,currentView){
var Calendar = function(dom,property_id,currentView,display_hire_event){
c = this;
display_hire_event = (display_hire_event == undefined ? true : display_hire_event);
this.title = $("#current_title");
this.calendar_dom = $(dom);
this.nextBtn = $("#next_month_btn");
@ -144,7 +145,8 @@ var Calendar = function(dom,property_id,currentView){
data: {
start: Math.round(start.getTime() / 1000),
end: Math.round(end.getTime() / 1000),
_: Date.now()
_: Date.now(),
display_hire_event: display_hire_event
},
success: function(json) {
// json = json.map(function(obj){

View File

@ -170,40 +170,66 @@ class PropertyHiresController < ApplicationController
start_time = booking_p[:start_time]
end_time = booking_p[:end_time]
time_setting = nil
is_admin_page = (params[:url] == "admin")
if time_setting_id.present?
start_time = booking_p[:date]
end_time = start_time
time_setting = PropertyDaySetting.find(time_setting_id)
if booking_p[:recurring_end_date].present?
booking_p[:recurring_end_date] = DateTime.parse(booking_p[:recurring_end_date].strftime('%Y-%m-%d') + time_setting.end_time + Time.zone.to_s)
booking_p[:recurring_end_date] = DateTime.parse(booking_p[:recurring_end_date].split(" ")[0] + ' ' + time_setting.end_time + Time.zone.to_s)
end
booking_p[:start_time] = booking_p[:date] + " " + time_setting.start_time
booking_p[:end_time] = booking_p[:date] + " " + time_setting.end_time
booking_p[:property_day_setting_id] = booking_p[:time]
booking_p.delete(:time)
end
property = Property.find(booking_p[:property_id]) rescue nil
begin
index_page = is_admin_page ? "/#{I18n.locale}/admin/property_hires/#{property.to_param}" : "/#{I18n.locale}#{params[:url]}/#{property.to_param}"
rescue
index_page = is_admin_page ? "/#{I18n.locale}/admin/property_hires" : "/#{I18n.locale}#{params[:url]}"
end
hire_page = is_admin_page ? request.referer : "#{index_page}?method=hire"
need_validate = (PropertyHireSetting.last.allow_no_logins_user rescue false) && current_user.nil?
session.delete(:hire_data)
if need_validate
unless gotcha_valid?
session[:hire_data] = booking_p
session["hire-save-msg"] = I18n.t("property_hire.recaptcha.errors.verification_failed")
if property.nil?
redirect_to index_page and return
else
redirect_to hire_page and return
end
end
end
if params[:url] == "admin"
params[:phire_id] = booking_p[:id]
end
data = check_for_availability(start_time,end_time,booking_p[:property_id], booking_p[:recurring_interval], booking_p[:recurring_end_date], time_setting_id)
property = Property.find(booking_p[:property_id]) rescue nil
if data["success"] == true
if time_setting_id.present?
booking_p[:start_time] = booking_p[:date] + " " + time_setting.start_time
booking_p[:end_time] = booking_p[:date] + " " + time_setting.end_time
booking_p[:property_day_setting_id] = booking_p[:time]
booking_p.delete(:time)
booking_p.delete(:date)
hire = nil
if params[:phire_id]
hire = PHire.find(params[:phire_id])
hire.update_attributes(booking_p)
else
hire = PHire.new(booking_p)
end
hire = PHire.new(booking_p)
hire.passed = true if PropertyHireSetting.auto_approve_enabled?
hire.save
if !property.nil?
if !property.nil? && !is_admin_page
email = Array(MemberProfile.find(property.owners)).collect{|v| v.email} rescue []
email = User.all.select{|v| v.is_admin? && v.user_name != 'rulingcom'}.collect{|v| v.member_profile.email} if email.length == 0
email << hire.hiring_person_email
Admin::PropertyHiresHelper::HireMethod.send_mail('p_hire',email,property.id,nil,hire.id)
end
redirect_to params[:url]
redirect_to index_page
else
session["hire-save-msg"] = data["msg"]
if property.nil?
redirect_to "/" + I18n.locale.to_s + params[:url]
redirect_to index_page
else
redirect_to "/" + I18n.locale.to_s + params[:url] + "/#{property.to_param}?method=hire"
redirect_to hire_page
end
end
end
@ -213,12 +239,31 @@ class PropertyHiresController < ApplicationController
property = Property.where(:uid => params[:uid]).first rescue nil
page = Page.where(:page_id => params[:page_id]).first
return {} if property.nil?
hire = PHire.new
hire = nil
session = OrbitHelper.request.session rescue {}
recover = false
if (session[:hire_data] rescue false)
begin
hire = PHire.new({:id=>nil}.merge(session[:hire_data]))
recover = true
rescue => e
puts e.to_s
hire = PHire.new(:id=>nil)
end
else
hire = PHire.new(:id=>nil)
end
allow_no_logins_user = PropertyHireSetting.last.allow_no_logins_user
all_day_settings = property.all_day_settings.map{|d,settings| [d,settings.map{|s| [s.id.to_s,s.title]}]}.to_h
{
"hire" => hire,
"property" => property,
"page" => page.url,
"current_user" => OrbitHelper.current_user
"current_user" => OrbitHelper.current_user,
"allow_no_logins_user" => allow_no_logins_user,
"carousel_display_style" => "width: #{property.carousel_image_width};",
"all_day_settings" => all_day_settings,
"recover" => recover
}
end
@ -241,8 +286,18 @@ class PropertyHiresController < ApplicationController
allevents = events.inject(re, :<<)
allevents = allevents.sort_by{|e| e[:start]}
@need_check_events = allevents.map{|e| [e[:date],e[:s_id]]}
if property.set_availability
all_day_settings = property.property_day_settings.asc(:key).group_by(&:day).map{|d,settings| [d,settings.map{|s| [s.start_time,s.end_time,s.id.to_s,s.title,s.reservation_limit]}]}.to_h
if property.set_availability && params[:display_hire_event]
check_setting = property.set_unavailibility && (property.property_day_settings.where(:enable=>false).count != 0)
@check_start_time = property.start_time.blank? ? "00:00" : property.start_time
@check_end_time = property.end_time.blank? ? "24:00" : property.end_time
@check_start_date = property.start_date
@check_end_date = property.end_date
if check_setting
if (@check_start_date > edt rescue false) || (@check_end_date > sdt rescue false)
check_setting = false
end
end
all_day_settings = property.all_day_settings.map{|d,settings| [d,settings.map{|s| [s.start_time,s.end_time,s.id.to_s,s.title,s.reservation_limit,s.enable]}]}.to_h
if all_day_settings.count != 0
time_now = Time.zone.now
get_start_time = [sdt,time_now].max
@ -251,7 +306,7 @@ class PropertyHiresController < ApplicationController
if property.can_hire_before_months != 0
get_end_time = [time_now + (property.can_hire_before_months).send("month"),edt].min
end
allevents += generate_all_reserve_buttons(get_start_time,get_end_time,all_day_settings)
allevents += generate_all_reserve_buttons(get_start_time,get_end_time,all_day_settings,check_setting)
end
end
end
@ -263,11 +318,32 @@ class PropertyHiresController < ApplicationController
end
end
def reserve_calendar_event(date,title,allow_times)
{:title=>title, :start=>date.to_s, :end => (date + 1.day).to_s, :allDay => true, :color => "#3788d8",:allow_times=>allow_times,:classNames=>["reserve_btn"]}
available = true
if @check_setting && !allow_times[5]
available = date > @check_end_date || date < @check_start_date
unless available
allow_times = allow_times.select do |allow_time|
if allow_time[0] > @check_end_time || allow_time[1] < @check_start_time
true
else
false
end
end
available = (allow_times.count != 0)
end
end
if available
{:title=>title, :start=>date.to_s, :end => (date + 1.day).to_s, :allDay => true, :color => "#3788d8",:allow_times=>allow_times,:classNames=>["reserve_btn"]}
else
{}
end
end
def generate_all_reserve_buttons(startt,endt,all_day_settings)
def generate_all_reserve_buttons(startt,endt,all_day_settings,check_setting=false)
@check_setting = check_setting
@display_title = I18n.t("property_hire.reserve")
@allevents = []
startt = startt.in_time_zone(Time.zone)
endt = endt.in_time_zone(Time.zone)
start_wday = startt.wday
start_date = startt.to_date
@start_date = start_date
@ -285,18 +361,15 @@ class PropertyHiresController < ApplicationController
if @all_day_settings.has_key?(wday_str)
check_time = nil
check_time = @first_check_time if is_start_day
i = -1
if @need_check_events.count == 1
if @need_check_events[0][0] <= @start_date
i = 0
end
else
i = @need_check_events.index{|e| e[0] > @start_date}
if i.nil?
i = @need_check_events.index{|e| e[0] > @start_date}
if i.nil?
if @need_check_events.length != 0 && @need_check_events[-1][0] <= @start_date
i = @need_check_events.length - 1
else
i = -1
elsif i != -1
i -= 1
end
elsif i != -1
i -= 1
end
check_events = []
if i != -1
@ -335,18 +408,15 @@ class PropertyHiresController < ApplicationController
else
@all_day_settings.each do |wday_str,settings|
tmp_date = @start_date + wday_str.to_i.send("day")
i = -1
if @need_check_events.count == 1
if @need_check_events[0][0] <= tmp_date
i = 0
end
else
i = @need_check_events.index{|e| e[0] > tmp_date}
if i.nil?
i = @need_check_events.index{|e| e[0] > tmp_date}
if i.nil?
if @need_check_events.length != 0 && @need_check_events[-1][0] <= tmp_date
i = @need_check_events.length - 1
else
i = -1
elsif i != -1
i -= 1
end
elsif i != -1
i -= 1
end
check_events = []
if i != -1

View File

@ -10,8 +10,9 @@ module Admin::PHireFieldHelper
include OrbitFormHelper
def block_helper(member,index,disable = false,attribute_type=nil,p_hire=nil, to_require=true, col=2)
def block_helper(member,index,disable = false,attribute_type=nil,p_hire=nil, to_require=true, col=2, value=nil)
unless self.disabled
return "" if self.title.blank?
@col = col
@index = index
@require = to_require
@ -21,7 +22,7 @@ module Admin::PHireFieldHelper
@attribute_type = attribute_type
@new_attribute = @attribute_value.nil?
@attribute_value = @attribute_value || p_hire.p_hire_field_values.build(p_hire_field_id: id)
@prefiled_value = @attribute_value.value rescue nil
@prefiled_value = value || @attribute_value.value rescue nil
return instance_eval("render_#{markup}") rescue ""
end
end
@ -30,6 +31,8 @@ module Admin::PHireFieldHelper
content_tag(:div,str,:class=>"tab-pane fade",:id=>(get_field_name_base+"tab_#{lang}"))
end
def render_hint_text
place_holder= self.get_placeholder rescue ''
return "" if place_holder.blank?
control_group_wrapper do |key,value|
if !@prefiled_value.nil?
value = can_muti_lang_input? ? @prefiled_value[key] : @prefiled_value
@ -37,7 +40,6 @@ module Admin::PHireFieldHelper
value = nil
end
key = can_muti_lang_input? ? "#{key}" : I18n.locale
place_holder= typeF["placeholder"][key] rescue ''
name1 = ""
text_area_tag(name1, place_holder,@markup_options.merge(:class=>'input-medium form-control',:readonly=>"",:rows=>"4"))
end
@ -441,7 +443,7 @@ protected
end
def get_basic_field_name_org
"p_hire_field_values"
"p_hire[p_hire_field_values_attributes]"
end
def get_basic_field_name

View File

@ -53,7 +53,11 @@ module Admin::PropertyHiresHelper
I18n.with_locale(params[:locale]) do
msg = I18n.t("property_hire.property_is_unavailable_during_this_time")
if available_flag.nil?
if recurring_end_date.present?
stime = [stime,recurring_end_date].max
end
can_hire_date = stime - (property.can_hire_before_months).month
puts "can_hire_date #{can_hire_date}"
msg += ("<br>" + I18n.t("property_hire.please_hire_after_date",{:date=>"{#{can_hire_date.utc.to_json.gsub('"','')}}"}))
else
msg += ("<br>" + property.render_unavailable_message)

View File

@ -29,6 +29,9 @@ class PHire
belongs_to :property
has_many :p_hire_field_values, :autosave => true, :dependent => :destroy
accepts_nested_attributes_for :p_hire_field_values, allow_destroy: true
def property_day_setting
PropertyDaySetting.find(self.property_day_setting_id) rescue nil
end
def as_json(options = {})
startt = self.start_time
endt = self.end_time
@ -75,15 +78,15 @@ class PHire
return MemberProfile.find(self.hiring_person_id) rescue nil
end
def self.monthly_event(start_date,end_date,property_id,date_ony=false)
def self.monthly_event(start_date,end_date,property_id,date_only=false)
events = self.where(:property_id => property_id, :recurring => false).any_of(:start_time.gte => start_date, :end_time.gte => start_date).and(:start_time.lte => end_date).asc(:start_time)
if date_ony
if date_only
events = events.where(:date.ne=>nil)
end
events
end
def self.recurring_event(start_date,end_date,property_id,date_ony=false)
def self.recurring_event(start_date,end_date,property_id,date_only=false)
@property = Property.find(property_id) rescue nil
@recurring = []
if @property != nil
@ -96,7 +99,7 @@ class PHire
unavailable_end_date = DateTime.parse(unavailable_end_date.strftime("%Y-%m-%d " + unavailable_end_time.to_s + Time.zone.to_s)) rescue nil
unavailable_weekdays = @property.weekdays.collect{|w| w.to_i}
@recurring_events = self.where(:property_id => property_id, :recurring_end_date.gte => start_date)
if date_ony
if date_only
@recurring_events = @recurring_events.where(:date.ne=>nil)
end
@recurring_events.each do |re|
@ -105,21 +108,23 @@ class PHire
if interval != 0
@start_date = re.start_time
recurring_end_date = re.recurring_end_date
end_date = [recurring_end_date,end_date].min
new_end_date = [recurring_end_date,end_date].min
@end_date = re.end_time
while @start_date <= end_date do
while @start_date <= new_end_date do
if unavailable && (unavailable_start_date <= @start_date) && (unavailable_end_date >= @end_date) && !((@start_date.strftime("%w").to_i .. @end_date.strftime("%w").to_i).to_a & unavailable_weekdays).empty?
startt = DateTime.parse(@start_date.strftime("%Y-%m-%d " + unavailable_start_time + Time.zone.to_s))
endt = DateTime.parse(@end_date.strftime("%Y-%m-%d " + unavailable_end_time + Time.zone.to_s))
next if !((startt..endt) & (@start_date..@end_date)).blank?
end
@recurring << re.as_json({:startt=>@start_date,:endt=>@end_date,:datet=>datet})
if @start_date >= start_date
@recurring << re.as_json({:startt=>@start_date,:endt=>@end_date,:datet=>datet})
end
@start_date += interval
@end_date += interval
datet += interval if datet
end
end
end
end
end
@recurring
end

View File

@ -77,7 +77,18 @@ class PHireField
def get_data
self[panel]
end
def get_placeholder(locale=I18n.locale)
placeholder = self.get_data["placeholder"] rescue nil
if placeholder
if placeholder.respond_to?(:keys)
placeholder[locale.to_s]
else
placeholder
end
else
""
end
end
def typeA=(var)
check_add_more_convert(var)
check_cross_lang_convert(var,"typeA")

View File

@ -74,14 +74,22 @@ class PHireFieldValue
field_value = (field_value =~ /\A#{URI::regexp(['http', 'https'])}\z/) ? "<a href='#{field_value}' target='blank'>#{field_value}</a>" : field_value
field_value = (field_value =~ /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/i) ? "<a href='mailto:#{field_value}'>#{field_value}</a>" : field_value
if !field_value.blank?
{
"key" => p_hire_field.key,
"title" => p_hire_field.title,
"value" => field_value,
"val" => field_value = self.value
}
if p_hire_field.markup.eql?("hint_text")
field_value = p_hire_field.get_placeholder rescue ""
{
"key" => p_hire_field.key,
"title" => p_hire_field.title,
"value" => field_value,
"val" => field_value,
"hint" => true
}
elsif !field_value.blank?
{
"key" => p_hire_field.key,
"title" => p_hire_field.title,
"value" => field_value,
"val" => field_value = self.value
}
else
{
"key" => p_hire_field.key,

View File

@ -4,6 +4,7 @@ class Property
include OrbitTag::Taggable
include OrbitCategory::Categorizable
include Slug
field :custom_calendar_type, type: Integer, default: 0 #0=>預設, 1=> 顯示, 2=> 不顯示
field :custom_carousel_image_width, type: String, default: ""
field :display_img, :type => Boolean, :default => false
field :image_display_class, type: String, default: "full-size-img" #3 choices: full-size-img , pull-left , pull-right
@ -71,11 +72,40 @@ class Property
"Friday",
"Saturday"
]
CAlENDARTYPE = ["default","display","not_display"]
before_create do
max_position = self.class.max(:order_position)
max_position = -1 if max_position.nil?
self.order_position = max_position + 1
end
after_save do
self.change_day_setting_status
end
def all_day_settings
self.property_day_settings.asc(:key).group_by(&:day)
end
def change_day_setting_status
if self.property_day_settings.count != 0
if self.set_unavailibility && self.weekdays.count != 0
self.property_day_settings.where(:day.nin=>self.weekdays).update_all(:enable=>true)
tmp_start_time = self.start_time.blank? ? "00:00" : self.start_time
tmp_end_time = self.end_time.blank? ? "24:00" : self.end_time
self.property_day_settings.where(:day.in=>self.weekdays).each do |setting|
if setting.end_time < tmp_start_time || setting.start_time > tmp_end_time
setting.enable = true
else
setting.enable = false
end
setting.save
end
else
self.property_day_settings.update_all(:enable=>true)
end
end
end
def calendar_type
(self.custom_calendar_type == 0 ? (PropertyHireSetting.last.calendar_type rescue 0) : (self.custom_calendar_type - 1))
end
def self.init_class_variables
setting = PropertyHireSetting.last
if setting
@ -189,6 +219,7 @@ class Property
return true if self.weekdays.empty? && self.can_hire_before_months == 0
if self.can_hire_before_months != 0
return nil if (((stime - Time.now.to_datetime) * 1.day) > (self.can_hire_before_months).month)
available = true
end
startt = self.start_date.nil? ? stime : self.start_date
endt = self.end_date.nil? ? etime : self.end_date
@ -198,18 +229,20 @@ class Property
if !startt.nil?
if !available
common_dates = (startt..endt) & (stime..etime)
return true if common_dates.nil?
time_weekdays = []
Property.time_iterate(common_dates.min, common_dates.max, 1.day) do |t|
time_weekdays << t.wday
available = true if common_dates.nil?
if !available
time_weekdays = []
Property.time_iterate(common_dates.min, common_dates.max, 1.day) do |t|
time_weekdays << t.wday
end
time_weekdays.uniq!
weekdays = weekdays & time_weekdays
available = true if weekdays.blank?
startt = DateTime.parse(stime.strftime("%Y-%m-%d " + (self.start_time.blank? ? "00:00" : self.start_time) + Time.zone.to_s))
endt = DateTime.parse(etime.strftime("%Y-%m-%d " + (self.end_time.blank? ? "23:59" : self.end_time) + Time.zone.to_s))
common_dates = (startt..endt) & (stime..etime)
available = common_dates.nil?
end
time_weekdays.uniq!
weekdays = weekdays & time_weekdays
return true if weekdays.blank?
startt = DateTime.parse(stime.strftime("%Y-%m-%d " + (self.start_time.blank? ? "00:00" : self.start_time) + Time.zone.to_s))
endt = DateTime.parse(etime.strftime("%Y-%m-%d " + (self.end_time.blank? ? "23:59" : self.end_time) + Time.zone.to_s))
common_dates = (startt..endt) & (stime..etime)
available = common_dates.nil?
end
if available
if !recurring_end_date.blank?
@ -236,7 +269,7 @@ class Property
end
return available
else
return false
return available
end
end
end

View File

@ -1,6 +1,7 @@
class PropertyDaySetting
include Mongoid::Document
include Mongoid::Timestamps
field :enable, type: Boolean, default: true
field :key
field :day
field :title

View File

@ -6,6 +6,8 @@ class PropertyHireSetting
field :carousel_image_width, type: String, :default => "75%"
field :disable_content_page, type: Boolean, :default => false
field :disable_view_calendar_page, type: Boolean, :default => false
field :allow_no_logins_user, type: Boolean, :default => false
field :calendar_type, type: Integer, default: 0 # 0=> 顯示, 1=> 不顯示
def self.auto_approve_enabled?
self.first.auto_approve rescue false
end

View File

@ -82,6 +82,7 @@
<div class="nav-name"><strong><%= t(:module) %></strong></div>
<ul class="nav nav-pills module-nav">
<li class="active"><a href="#basic" data-toggle="tab"><%= t(:basic) %></a></li>
<li><a href="#page_setting" data-toggle="tab"><%= t("property_hire.page_setting") %></a></li>
<li><a href="#files_links" data-toggle="tab"><%= t("property_hire.files_links") %></a></li>
<li><a href="#tag" data-toggle="tab"><%= t(:tags) %></a></li>
<li><a href="#imageupload" data-toggle="tab"><%= t(:image) %></a></li>
@ -169,6 +170,15 @@
</div>
</div>
</div>
<!-- page_setting -->
<div class="tab-pane fade" id="page_setting">
<div class="control-group">
<%= f.label :custom_calendar_type, t("property_hire.display_calendar"), :class => "control-label muted" %>
<div class="controls">
<%= f.select :custom_calendar_type, options_for_select(Property::CAlENDARTYPE.map.with_index{|type,i| [t("property_hire.custom_calendar_type.#{type}"), i]}, f.object.custom_calendar_type) %>
</div>
</div>
</div>
<!-- files_links -->
<div class="tab-pane fade" id="files_links">
<%= render :partial => "form_file_link", :locals=>{:f=>f} %>
@ -409,7 +419,7 @@
<div id="set_availability_div" style="display: none;">
<% end %>
<ul>
<% all_day_settings = f.object.property_day_settings.asc(:key).group_by(&:day) %>
<% all_day_settings = f.object.all_day_settings %>
<% setting_count = 0 %>
<% Property::WEEKDAYS.each_with_index do |weekday,i| %>
<li class="card">

View File

@ -82,7 +82,7 @@
<%= stylesheet_link_tag css %>
<% end %>
<% end %>
<script src="/assets/javascripts/validator.js"></script>
<script src="/assets/validator.js"></script>
<script src="https://polyfill.io/v3/polyfill.min.js?features=Intl.DateTimeFormat,Intl.DateTimeFormat.~locale.en,Intl.NumberFormat.~locale.en"></script>
<script type="text/javascript" src="/assets/property_hire_fullcalendar.min.js"></script>
<script type="text/javascript" src="/assets/property_hire_calendar_frontend.js"></script>
@ -90,22 +90,277 @@
hire = @phire
property = @phire.property
%>
<h3><%= property.title %></h3>
<% if session["hire-save-msg"].present? %>
<div id="property-unavaialable-alert" class="alert alert-danger" role="alert"><b>Sorry! </b><span> <%= session["hire-save-msg"] %></span></div>
<% session.delete("hire-save-msg") %>
<% data = {"carousel_display_style"=>"width: #{property.carousel_image_width};"}
recover = true
allow_no_logins_user = false
calendar_type = property.calendar_type.to_i rescue 0
right_col = 12
label_col = 2
input_col = 10
if calendar_type == 0
right_col -= 5
label_col += 2
input_col -= 2
end
url = "admin"
all_day_settings = property.all_day_settings
%>
<style type="text/css">
.w-ba-banner{
position: relative;
}
ul.list-unstyled li {
list-style: none;
}
.s-annc__related-link-list, .s-annc__related-file-list{
display: inline-block;
}
#sec1{
float: left;
}
.btn-toolbar {
margin-top: 0;
}
.form-group .controls{
margin-left: 0;
}
</style>
<style type="text/css">
.full-size-img img {
width: 100%;
}
.full-size-img {
width: 100%;
}
.s-annc__sub-img.pull-right {
margin-left: 2em;
}
.s-annc__sub-img.pull-left {
margin-right: 2em;
}
strong.carousel__description {
color: white;
}
.carousel_images{
<%=data["carousel_display_style"]%>
}
@media (max-width: 767px){
.carousel_images{
width: 100%;
}
}
.carousel_img_item{
display: none;
float: left;
}
.controlplay {
position: absolute;
right: 1em;
top: 3%;
z-index: 200;
}
.controlplay a {
display: inline-block;
margin-right: 0.25em;
cursor: pointer;
padding: 5px 10px;
border: 1px solid rgba(255,255,255,0.5);
background: rgba(0,0,0,0.2);
}
.controlplay a i {
font-family: FontAwesome;
position: relative;
font-size: 1rem;
line-height: 1;
color: #FFF;
vertical-align: middle;
font-style: unset;
}
.controlplay .resume-slide i::before {
content: "\f04b";
}
.controlplay .pause-slide i::before {
content: "\f04c";
}
ul.button-mid .prev-button {
transition: 0.4s;
position: relative;
float: left;
left: 0.5rem;
width: 2.5rem;
height: 2.5rem;
font-size: 2.2rem;
color: #ffffff;
background: rgba(0,0,0,0.2);
text-align: center;
line-height: 2.5rem;
top: 50%;
position: absolute;
transform: translateY(-50%);
z-index: 999;
}
ul.button-mid .next-button {
float: right;
transition: 0.4s;
position: relative;
right: 0.5rem;
width: 2.5rem;
height: 2.5rem;
font-size: 2.2rem;
color: #fff;
background: rgba(0,0,0,0.2);
text-align: center;
line-height: 2.5rem;
top: 50%;
position: absolute;
transform: translateY(-50%);
z-index: 999;
}
.carousel_images_slide{
padding: 3em;
}
.carousel_img_item img{
cursor: pointer;
}
@media (max-width: 479px){
.carousel_img_item:nth-child(-n+1){
display: block;
width: 100%;
float: left;
}
.carousel_img_item{
width: 100%;
}
}
@media (min-width: 480px){
.carousel_img_item:nth-child(-n+2){
display: block;
width: 50%;
float: left;
}
.carousel_img_item{
width: 50%;
}
}
@media (min-width: 768px){
.carousel_img_item:nth-child(-n+3){
display: block;
width: 33%;
float: left;
}
.carousel_img_item{
width: 33%;
}
}
@media (min-width: 1280px){
.carousel_img_item:nth-child(-n+4){
display: block;
width: 25%;
float: left;
}
.carousel_img_item{
width: 25%;
}
}
</style>
<% if !property.can_be_hired %>
<script type="text/javascript">
alert("This property is unavailable for hire.");
window.location.href = "<%= "/" + I18n.locale.to_s + url %>";
</script>
<% end %>
<div id="orbit_calendar">
<% if !allow_no_logins_user && current_user.nil? %>
<script type="text/javascript">
alert("Please login before you hire.");
window.location.href = "<%= "/" + I18n.locale.to_s + url %>";
</script>
<% else %>
<script type="text/javascript">
var pick_date_mode = <%=property.set_availability%>;
</script>
<h3 class="property_title"><%= property.title %></h3>
<article class="s-annc s-property">
<section class="s-annc__post-wrap">
<% if property.display_img %>
<div class="s-annc__sub-img full-size-img">
<img src="<%=property.image.url%>" alt="<%=property.title%>">
<span class="s-annc__img_description"><%=property.title%></span>
</div>
<% end %>
<h4 class="property_subtitle"><%= property.property_usage %></h4>
<% property_carousel_images = property.property_carousel_images %>
<% if property_carousel_images.count != 0 %>
<div class="carousel_images">
<div class="w-ba-banner ba-banner-widget-1">
<div class="w-ba-banner__wrap cycle-slideshow"
data-list="property_carousel_images"
data-level="0"
data-cycle-slides=".property_carousel_slide"
data-cycle-log="false"
data-cycle-auto-height="0"
data-cycle-speed="300"
data-cycle-timeout="5000"
data-cycle-fx="fade"
data-pager-active-class="active-slide"
data-cycle-swipe=true
data-cycle-swipe-fx="scrollHorz"
>
<% property_carousel_images.each do |carousel_image| %>
<div class="w-ba-banner__slide property_carousel_slide"
data-cycle-title="{{description_text}}"
>
<img class="w-ba-banner__image banner-responsive" src="<%=carousel_image.file.url %>" alt="<%=carousel_image.description_text %>">
<div class="ad-overlay w-ad-banner__overlay property_carousel__overlay">
<p><strong class="carousel__description"><%=carousel_image.description %></strong></p>
</div>
<div class="transitionfade"></div>
</div>
<% end %>
</div>
<ul class="controlplay"><a class="resume-slide" title="<%=data["resume_btn_title"]%>"><i></i></a><a class="pause-slide" title="<%=data["pause_btn_title"]%>"><i></i></a></ul>
<ul class="button-mid">
<i class="fa fa-angle-left prev-button" aria-hidden="true" title="<%=data["prev_btn_title"]%>"></i>
<i class="fa fa-angle-right next-button" aria-hidden="true" title="<%=data["next_btn_title"]%>"></i>
</ul>
</div>
</div>
<% end %>
<div class="property_note"><%= property.note %></div>
</section>
<ul class="s-property__related-wrap list-unstyled no-print">
<% if property.property_files.count != 0%>
<li class="s-annc__related-file s-property__related-file">
<i class="fa fa-fw fa-paperclip"></i>
<div class="s-annc__related-file-list s-property__related-file-list" data-list="property_files" data-level="0">
<% property.property_files.each do |property_file| %>
<a class="s-annc__flie-title s-property__flie-title btn btn-default btn-sm" href="<%=property_file.file.url %>" title="<%=property_file.title %>"><%=property_file.title %></a>
<% end %>
</div>
</li>
<% end %>
<% if property.property_links.count != 0%>
<li class="s-annc__related-link s-property__related-link">
<i class="fa fa-fw fa-link"></i>
<div class="s-annc__related-link-list s-property__related-link-list" data-list="bulletin_links" data-level="0">
<% property.property_links.each do |property_link| %>
<a class="s-annc__link-title s-property__link-title btn btn-default btn-sm" href="<%=property_link.url %>" target="_blank"><%=property_link.display_title %></a>
<% end %>
</div>
</li>
<% end %>
</ul>
<% if session["hire-save-msg"].present? %>
<div id="property-unavaialable-alert" class="alert alert-danger" role="alert"><b>Sorry! </b><span> <%= session["hire-save-msg"] %></span></div>
<script type="text/javascript">alert("<%= session["hire-save-msg"] %>")</script>
<% session.delete("hire-save-msg") %>
<% end %>
</article>
<% if property.calendar_type == 0 %>
<div id="orbit_calendar" class="col-lg-7">
<div id="sec1">
<div class="btn-toolbar" id="navigation">
<div id="calendar-nav">
<div class="btn-group">
<button class="btn btn-default btn-sm" id="prev_month_btn">
<i class="icon-chevron-left"></i>
</button>
<button class="btn btn-default btn-sm" id="next_month_btn">
<i class="icon-chevron-right"></i>
</button>
<button class="btn btn-default btn-sm" id="today_btn">Today</button>
</div>
</div>
@ -122,17 +377,71 @@
<i class="icons-cycle"></i>
</button>
</div>
<div class="pull-right">
<button class="btn btn-default btn-sm" id="prev_month_btn">
<i class="icon-chevron-left"></i>
</button>
<button class="btn btn-default btn-sm" id="next_month_btn">
<i class="icon-chevron-right"></i>
</button>
</div>
<div class="clearfix"></div>
<div id="view_holder">
<h3 id="current_title" class="current_day_title"></h3>
<div id="calendar"></div>
<div id="calendar_agenda"></div>
</div>
<div id="calendar-loading"></div>
<div id="hidden_timepicker" class="hide">
<span id="hidden_title" class="pull-left" style="margin-right: 1em;font-weight: bold;"></span>
<div style="display: grid;">
<span id="hidden_date" class="pull-left" style="margin-right: 1em;"></span>
<%= fields_for :timepicker do |f|%>
<%= f.time_picker :timepicker, :no_label => true, :new_record => hire.new_record? && !recover,:format=>"HH:mm", :class => "pull-left", :data=>{"picker-type" => "range", "range" => "end", "fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<% end %>
<div class="pull-left btn-group" style="margin-top: 0.5em;">
<button id="confirm_date" class="btn btn-primary btn-sm" style="margin-right: 0.5em;" onclick="set_datetimepicker()"><%=t("property_hire.confirm")%></button>
<button id="cancel_date" class="btn btn-primary btn-sm" onclick="goto_calendar()"><%=t("property_hire.cancel")%></button>
</div>
</div>
<div style="clear: both;"></div>
<hr>
</div>
</div>
<div id="event_quick_view" class="modal" style="width: 300px; display:none; margin:0 0 0 0;"></div>
<div id="calendar-loading"></div>
<script type="text/javascript">
var property_id = "<%= property.id.to_s %>";
var property_id = "<%= property.id.to_s %>";
var calendar = new Calendar("#calendar",property_id);
function pick_hire_date(date,allow_times){
if(window.processing_hire)
return;
window.processing_hire = true;
try{
var date_target = $("#date_target_block").find("input");
var offset = date_target.offset();
if(date_target.val() == date){
scrollTo(0,offset.top - 40);
return;
}
$("#date_target_block").find("input").val(date);
var select_target;
if($("#hire_time_range_block").find("select").length == 0){
select_target = $("<select name=\""+$("#hire_time_range_block").find("input").attr("name")+"\"></select>");
$("#hire_time_range_block").find("input").remove();
}
else{
select_target = $("#hire_time_range_block").find("select").eq(0);
}
select_target = select_target.empty();
select_target.append("<option value=\"\"><%=t("property_hire.please_select")%></option>");
allow_times.forEach(function(allow_time){
select_target.append("<option value=\""+allow_time[2]+"\">"+allow_time[3]+"</option>");
});
select_target.appendTo($("#hire_time_range_block"));
scrollTo(0,offset.top - 40);
}catch(e){};
window.processing_hire = false;
}
function change_pick(target){
if( $(target).attr("id") == "pick_recurring_end_date"){
if($('#p_hire_recurring_interval').val() == ""){
@ -142,40 +451,45 @@
}
$("#calendar").data("recurring_interval", $('#p_hire_recurring_interval').val());
}
$("#hidden_timepicker").addClass("hide");
$("#calendar").data("target","#"+$(target).attr("id"));
$("#calendar").data("title", $(target).parents(".col-sm-10").prev("label").text().replace("*",""));
$("#calendar").addClass("active_picker");
document.getElementById("orbit_calendar").scrollIntoView();
$("#hidden_timepicker").addClass("hide");
$("#calendar").data("target","#"+$(target).attr("id"));
$("#calendar").data("title", $(target).parents(".col-sm-10").prev("label").text().replace("*",""));
$("#calendar").addClass("active_picker");
goto_calendar();
}
$("#calendar").on("select_time",function(ev,date_str){
$("#hidden_date").text(date_str);
$("#hidden_title").text($("#calendar").data("title"));
$('#hidden_timepicker .time_picker').addClass("pull-left");
$("#hidden_timepicker").removeClass("hide");
var target = $('#timepicker');
var window_width = $(window).width();
var window_height = $(window).height();
var target_offset = target.offset();
scrollTo(target_offset.left - window_width / 2, target_offset.top - window_height / 2);
$('#timepicker').trigger('focus');
$("#hidden_date").text(date_str);
$("#hidden_title").text($("#calendar").data("title"));
$('#hidden_timepicker .time_picker').addClass("pull-left");
$("#hidden_timepicker").removeClass("hide");
var target = $('#timepicker');
var window_width = $(window).width();
var window_height = $(window).height();
var target_offset = target.offset();
scrollTo(target_offset.left - window_width / 2, target_offset.top - window_height / 2);
$('#timepicker').trigger('focus');
})
$("#calendar").on("init_time",function(ev,time_str){
$('#timepicker').val(time_str);
$('#timepicker').val(time_str);
})
function set_datetimepicker(){
var date_time = $("#hidden_date").text() + " " + $('#timepicker').val();
var start_date, end_date, interval = null, recurring_end_date = null;
var date_time = $("#hidden_date").text() + " " + $('#timepicker').val();
var start_date, end_date, interval = null, recurring_end_date = null;
var target = $("#calendar").data("target");
if(target == "#pick_start_date"){
start_date = date_time;
end_date = $("#p_hire_end_time").val();
}else if(target == "#pick_end_date"){
end_date = date_time;
start_date = $("#p_hire_start_time").val();
}else if(target == "#pick_recurring_end_date"){
start_date = $("#p_hire_start_time").val();
if(target == "#pick_start_date"){
start_date = date_time;
end_date = $("#p_hire_end_time").val();
}else if(target == "#pick_end_date"){
end_date = date_time;
start_date = $("#p_hire_start_time").val();
}else if(target == "#pick_recurring_end_date"){
if(pick_date_mode){
start_date = $("#p_hire_date").val();
end_date = start_date;
}else{
start_date = $("#p_hire_start_time").val();
end_date = $("#p_hire_end_time").val();
}
interval = $("#p_hire_recurring_interval").val();
recurring_end_date = date_time;
}
@ -192,91 +506,109 @@
}
}
}
console.log(start_date)
var check_only = (start_date == null || end_date == null);
if(check_available(start_date,end_date,interval,recurring_end_date,check_only)){
var target = $($("#calendar").data("target"));
target.prev().find("input").val(date_time);
$("#hidden_timepicker").addClass("hide");
$("#calendar").removeClass("active_picker");
var window_width = $(window).width();
var window_height = $(window).height();
var target_offset = target.offset();
scrollTo(target_offset.left - window_width / 2, target_offset.top - window_height / 2);
}else{
if(check_available(start_date,end_date,interval,recurring_end_date,check_only)){
var target = $($("#calendar").data("target"));
target.prev().find("input").val(date_time);
$("#hidden_timepicker").addClass("hide");
$("#calendar").removeClass("active_picker");
var window_width = $(window).width();
var window_height = $(window).height();
var target_offset = target.offset();
scrollTo(target_offset.left - window_width / 2, target_offset.top - window_height / 2);
}else{
if(window.check_message !== ""){
alert(window.check_message.replace(/<br>/g,"\n"));
}else{
alert('<%=t("property_hire.unavailability")%>');
}
}
}
}
function goto_calendar(){
$("#hidden_timepicker").addClass("hide");
var target = $("#calendar");
var window_width = $(window).width();
var window_height = $(window).height();
var target_offset = target.offset();
scrollTo(target_offset.left - window_width / 2, target_offset.top - window_height / 2);
$("#hidden_timepicker").addClass("hide");
var offset = $('#orbit_calendar').offset();
scrollTo(0,offset.top-40);
window.setTimeout(function(){
scrollTo(0,offset.top-40);
},500);
}
</script>
<div id="hidden_timepicker" class="hide">
<span id="hidden_title" class="pull-left" style="margin-right: 1em;font-weight: bold;"></span>
<div style="display: grid;">
<span id="hidden_date" class="pull-left" style="margin-right: 1em;"></span>
<%= fields_for :timepicker do |f|%>
<%= f.time_picker :timepicker, :no_label => true, :new_record => hire.new_record?,:format=>"HH:mm", :class => "pull-left", :data=>{"picker-type" => "range", "range" => "end", "fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<% end %>
<div class="pull-left btn-group" style="margin-top: 0.5em;">
<button id="confirm_date" class="btn btn-primary btn-sm" style="margin-right: 0.5em;" onclick="set_datetimepicker()"><%=t("property_hire.confirm")%></button>
<button id="cancel_date" class="btn btn-primary btn-sm" onclick="goto_calendar()"><%=t("property_hire.cancel")%></button>
</div>
</div>
<div style="clear: both;"></div>
<hr>
</div>
<%= form_for hire, :url => update_hire_admin_property_hire_path(hire), html: { class: "form-horizontal" } do |f| %>
<div class="form-group">
<%= f.label :start_time, "*"+t("property_hire.start_time"), :class => "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.datetime_picker :start_time, :no_label => true, :new_record => hire.new_record?,:class => "pull-left", :data=>{"picker-type" => "range", "range" => "start", "fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<button type="button" id="pick_start_date" onclick="change_pick(this)" class="btn btn-primary btn-sm pull-left" style="margin-left: 1em;"><%=t("property_hire.pick_from_calendar")%></button>
<% end %>
<div class="col-lg-<%=right_col%>">
<%= form_for hire, :url => "/xhr/property_hires/make_booking", html: { class: "form-horizontal" } do |f| %>
<% if property.set_availability %>
<div class="form-group">
<%= f.label :date, "*"+t("property_hire.date"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-<%=input_col%>" id="date_target_block">
<% if calendar_type == 0 %>
<%= f.text_field :date, :value=>(recover ? f.object.date.to_s : t("property_hire.please_choose_date")),:readonly=>"",:onclick=>"goto_calendar()" %>
<% else %>
<%= f.datetime_picker :date, :no_label => true, :new_record => hire.new_record? && !recover ,:class => "pull-left", :picker_type => "date", :format=>"yyyy/MM/dd", :data=>{ "fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<% end %>
</div>
</div>
<div class="form-group">
<%= f.label :end_time, "*"+t("property_hire.end_time"), :class => "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.datetime_picker :end_time, :no_label => true, :new_record => hire.new_record?,:class => "pull-left", :data=>{"picker-type" => "range", "range" => "end", "fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<div class="form-group">
<%= f.label :time, "*"+t("property_hire.time"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-<%=input_col%>" id="hire_time_range_block">
<% property_day_setting = recover ? hire.property_day_setting : nil %>
<% if property_day_setting %>
<%= select_tag "#{f.object_name}[time]", options_for_select([[t("property_hire.please_select"),""],[property_day_setting.title,property_day_setting.id.to_s]],hire.property_day_setting_id), :required=>"required" %>
<% else %>
<% if property.calendar_type == 0 %>
<%= f.text_field :time, :value=>t("property_hire.please_choose_date"),:readonly=>"",:onclick=>"goto_calendar()" %>
<% else %>
<%= select_tag "#{f.object_name}[time]", options_for_select([[t("property_hire.please_choose_date"),""]]), :required=>"required" %>
<% end %>
<% end %>
</div>
</div>
<% else %>
<div class="form-group">
<%= f.label :start_time, "*"+t("property_hire.start_time"), :class => "col-sm-#{label_col} control-label" %>
<% if property.calendar_type == 0 %>
<div class="col-sm-<%=input_col%>">
<%= f.datetime_picker :start_time, :no_label => true, :new_record => hire.new_record? && !recover,:class => "pull-left", :data=>{"picker-type" => "range", "range" => "start", "fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<button type="button" id="pick_start_date" onclick="change_pick(this)" class="btn btn-primary btn-sm pull-left" style="margin-left: 1em;"><%=t("property_hire.pick_from_calendar")%></button>
</div>
<% end %>
</div>
<div class="form-group">
<%= f.label :end_time, "*"+t("property_hire.end_time"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-<%=input_col%>">
<%= f.datetime_picker :end_time, :no_label => true, :new_record => hire.new_record? && !recover,:class => "pull-left", :data=>{"picker-type" => "range", "range" => "end", "fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<button type="button" id="pick_end_date" onclick="change_pick(this)" class="btn btn-primary btn-sm pull-left" style="margin-left: 1em;"><%=t("property_hire.pick_from_calendar")%></button>
</div>
</div>
<% end %>
<!-- ############# recurring ############# -->
<div class="form-group">
<%= f.label :recurring, t("property_hire.recurring"), :class => "col-sm-2 control-label" %>
<div class="col-sm-1">
<%= f.label :recurring, t("property_hire.recurring"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-1">
<%= f.check_box :recurring %>
</div>
</div>
<div id="recurring-block" <%= hire.recurring ? "" : "style=display:none;" %>>
<div class="form-group">
<%= f.label :recurring_interval, t("property_hire.recurring_interval"), :class => "col-sm-2 control-label" %>
<div class="col-sm-1">
<%= f.select :recurring_interval, PHire::INTERVALS.collect{|int| [t("property_hire.recurring_interval_types.#{int}"), int] }, {:prompt => t('property_hire.select_interval')}, {:data => {"fv-validation" => "requiredifrecurring;" , "fv-messages" => "Cannot be empty;"}} %>
</div>
</div>
<div id="recurring-block" <%= hire.recurring ? "" : "style=display:none;" %>>
<div class="form-group">
<%= f.label :recurring_interval, t("property_hire.recurring_interval"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-1">
<%= f.select :recurring_interval, PHire::INTERVALS.collect{|int| [t("property_hire.recurring_interval_types.#{int}"), int] }, {:prompt => t('property_hire.select_interval')}, {:data => {"fv-validation" => "requiredifrecurring;" , "fv-messages" => "Cannot be empty;"}} %>
</div>
</div>
<div class="form-group">
<%= f.label :recurring_end_date, "*"+t("property_hire.recurring_end_date"), :class => "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.datetime_picker :recurring_end_date, :no_label => true, :new_record => hire.new_record?, :class=>"pull-left", :data=>{"fv-validation" => "requiredifrecurring;", "fv-messages" => "Cannot be empty;"} %>
<div class="form-group">
<%= f.label :recurring_end_date, "*"+t("property_hire.recurring_end_date"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-<%=input_col%>">
<%= f.datetime_picker :recurring_end_date, :no_label => true, :new_record => hire.new_record? && !recover, :class=>"pull-left", :data=>{"fv-validation" => "requiredifrecurring;", "fv-messages" => "Cannot be empty;"} %>
<% if calendar_type == 0 %>
<button type="button" id="pick_recurring_end_date" onclick="change_pick(this)" class="btn btn-primary btn-sm pull-left" style="margin-left: 1em;"><%=t("property_hire.pick_from_calendar")%></button>
<% end %>
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-5">
<div id="property-avaialable-alert" style="margin-bottom: 5px; padding: 10px; display: none;" class="alert alert-success" role="alert"><b>Hooray! </b>This property is available.</div>
<div class="col-sm-offset-<%=label_col%> col-sm-5">
<div id="property-avaialable-alert" style="margin-bottom: 5px; padding: 10px;<%= 'display: none;' unless recover %>" class="alert alert-success" role="alert"><b>Hooray! </b>This property is available.</div>
<div id="property-unavaialable-alert" style="margin-bottom: 5px; padding: 10px; display: none;" class="alert alert-danger" role="alert"><b>Sorry! </b><span> This property is available.</span></div>
<div id="values-alert" style="margin-bottom: 5px; padding: 10px; display: none;" class="alert alert-warning" role="alert">
<% hint1 = t("property_hire.please_select_recurring_interval_and_recurring_end_time",:default=>"") %>
@ -288,44 +620,44 @@
</div>
</div>
<% if property.set_unavailibility %>
<div class="col-sm-offset-2 col-sm-5">
<b><%= t("property_hire.Unavailibility_Schedule") %></b>
<div>
<div class="col-sm-offset-<%=label_col%> col-sm-5">
<b><%= t("property_hire.Unavailibility_Schedule") %></b>
<div>
<%= property.render_unavailable_message%>
</div>
</div>
</div>
<% end %>
</div>
<div class="form-group">
<label for="" class="col-sm-2 control-label"></label>
<div class="col-sm-10">
<a href="/xhr/property_hires/check_availability" id="check-avail-btn" class="btn btn-primary"><%= t('property_hire.check_availibility') %></a>
<img style="display: none;" width="40" src="/assets/spin.gif" id="spinner" />
<label for="" class="col-sm-<%=label_col%> control-label"></label>
<div class="col-sm-<%=input_col%>">
<a href="/xhr/property_hires/check_availability" id="check-avail-btn" class="btn btn-primary"><%= t('property_hire.check_availibility') %></a>
<img style="display: none;" width="40" src="/assets/spin.gif" id="spinner" />
</div>
</div>
<div class="form-group">
<%= f.label :hiring_person_email, "*"+t("property_hire.hiring_person_email"), :class => "col-sm-2 control-label" %>
<div class="col-sm-5">
<%= f.text_field :hiring_person_email, :class => "form-control", :value => current_user.member_profile.email, :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<%= f.label :hiring_person_email, "*"+t("property_hire.hiring_person_email"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-5">
<%= f.text_field :hiring_person_email, :class => "form-control", :value => (recover ? hire.hiring_person_email : ( current_user.member_profile.email rescue "")), :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
</div>
</div>
<div class="form-group">
<%= f.label :hiring_person_number, "*"+t("property_hire.hiring_person_number"), :class => "col-sm-2 control-label" %>
<div class="col-sm-5">
<%= f.text_field :hiring_person_number, :class => "form-control", :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<%= f.label :hiring_person_number, "*"+t("property_hire.hiring_person_number"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-5">
<%= f.text_field :hiring_person_number, :class => "form-control", :value => (recover ? hire.hiring_person_number : ( current_user.member_profile.mobile_no rescue "")), :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
</div>
</div>
<div class="form-group">
<%= f.label :hiring_person_name, "*"+t("property_hire.hiring_person_name"), :class => "col-sm-2 control-label" %>
<div class="col-sm-5">
<%= f.text_field :hiring_person_name, :class => "form-control", :value => (current_user.name rescue ""), :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<%= f.label :hiring_person_name, "*"+t("property_hire.hiring_person_name"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-5">
<%= f.text_field :hiring_person_name, :class => "form-control", :value => (recover ? hire.hiring_person_name : ( current_user.name rescue "")), :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<%= f.hidden_field :hiring_person_id, :value => (current_user.member_profile.id.to_s rescue "") %>
</div>
</div>
<div class="form-group">
<%= f.label :reason_for_hire, "*"+t("property_hire.reason_for_hire"), :class => "col-sm-2 control-label" %>
<div class="col-sm-5">
<%= f.label :reason_for_hire, "*"+t("property_hire.reason_for_hire"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-5">
<%= f.text_field :reason_for_hire, :class => "form-control", :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
</div>
</div>
@ -337,7 +669,7 @@
<% values = sub_hash["value"].values.select{|v| v.present?}.first.to_s if values.blank? %>
<% type = sub_hash["type"] %>
<div class="form-group">
<%= f.label "notes_selector[#{index}]", name, :class => "col-sm-2 control-label" %>
<%= f.label "notes_selector[#{index}]", name, :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-5">
<% values.each_with_index do |v,i| %>
<label class="checkbox-inline">
@ -353,8 +685,8 @@
<% end %>
<% else %>
<div class="form-group">
<%= f.label :note_for_hire, t("property_hire.note_for_hire"), :class => "col-sm-2 control-label" %>
<div class="col-sm-5">
<%= f.label :note_for_hire, t("property_hire.note_for_hire"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-5">
<%= f.text_area :note_for_hire, :class => "form-control" %>
</div>
</div>
@ -364,43 +696,117 @@
<% if(property[field_name]["enable"] == "1" rescue false) %>
<% required = (property[field_name]["required"] == "true" rescue false) %>
<div class="form-group">
<%= f.label field_name, (required ? "*" : "") + t("property_hire.#{field_name}"), :class => "col-sm-2 control-label" %>
<%= f.label field_name, (required ? "*" : "") + property.custom_text(field_name,"name"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-5">
<% placeholder = property.custom_text(field_name,"placeholder") %>
<% if required %>
<%= f.text_field field_name, :class => "form-control", :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<%= f.text_field field_name, :class => "form-control", :placeholder => placeholder, :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<% else %>
<%= f.text_field field_name, :class => "form-control" %>
<%= f.text_field field_name, :class => "form-control", :placeholder => placeholder %>
<% end %>
</div>
</div>
<% end %>
<% end %>
<% if property.p_hire_fields.count != 0 %>
<% p_hire = PHire.new(:id=>nil) %>
<% @form_index = 0 %>
<% property.p_hire_fields.asc(:_id).each do |rf| %>
<div class="form-group">
<%= rf.block_helper(property,@form_index,false,"p_hire",p_hire, rf.to_require,label_col) %>
</div>
<% @form_index = @form_index +1 %>
<% end %>
<% end %>
<% if allow_no_logins_user && current_user.nil? %>
<!-- 驗證碼 -->
<div class="form-group">
<label for="note" class="col-sm-2 control-label"><%= t('property_hire.recaptcha.recaptcha') %></label>
<div class="col-sm-10">
<%= gotcha_error %>
<%= gotcha %>
</div>
</div>
<% end %>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="col-sm-offset-<%=label_col%> col-sm-<%=input_col%>">
<%= f.hidden_field :id %>
<%= f.submit t("property_hire.save"), :class => "btn btn-primary" %>
<%= f.hidden_field :property_id, :value => property.id %>
<input type="hidden" id="dates_validated" name="dates_validated" value="0" data-fv-validation="checkForDates;" data-fv-messages="Please make sure first if dates are available.;">
<input type="hidden" name="url" value="<%= url %>" />
<input type="hidden" id="dates_validated" name="dates_validated" value="<%=recover ? 1 : 0 %>" data-fv-validation="checkForDates;" data-fv-messages="Please make sure first if dates are available.;">
</div>
</div>
<% end %>
</div>
<div class="clearfix"></div>
<div style="height: 50px;"></div>
<script type="text/javascript">
var property_id = "<%= property.id.to_s %>";
var property_id = "<%= property.id.to_s %>";
var timezone = (new Date().getTimezoneOffset() / -60).toString();
var all_day_settings = <%= all_day_settings.to_json.html_safe %>;
if(timezone[0] != "-"){
timezone = "+" + timezone;
}
$("#p_hire_date").on("change",function(){
var _this = $(this);
var date = new Date(_this.val());
if(date.getTime()){
var wday = date.getDay();
var select_target = $("#p_hire_time");
if(select_target.data("wday") == wday){
return;
}
select_target.empty();
select_target.data("wday",wday);
if(all_day_settings[wday]){
select_target.append("<option value=\"\"><%=t("property_hire.please_select")%></option>");
all_day_settings[wday].forEach(function(allow_time){
select_target.append("<option value=\""+allow_time[0]+"\">"+allow_time[1]+"</option>");
});
}else{
select_target.append("<option value=\"\"><%=t("property_hire.no_time_can_select",:default=>"No time can be selected!")%></option>");
}
}
})
var check_available = function(stime,etime,interval,recurring_end_date,check_only,property_id){
var el = $("#check-avail-btn"),
url = $("#check-avail-btn").attr("href"),
spinner = $("#spinner");
spinner = $("#spinner"),
time_setting_id = $("#hire_time_range_block select").val();
if(Number.isNaN(new Date(stime).getDate())){
window.check_message = "<%=t("property_hire.please_choose_date")%>";
if(!check_only){
$("#property-unavaialable-alert").find("span").html(window.check_message);
$("#property-unavaialable-alert").show();
}
spinner.hide();
el.show();
return false;
}
if(time_setting_id == ""){
window.check_message = "<%=t("property_hire.please_select_time")%>";
if(!check_only){
$("#property-unavaialable-alert").find("span").html(window.check_message);
$("#property-unavaialable-alert").show();
}
$("#hire_time_range_block select").focus();
$("#hire_time_range_block select").css("border","2px solid red");
spinner.hide();
el.show();
return false;
}
stime = stime || etime;
etime = etime || stime;
property_id = property_id || window.property_id;
var timezone = new Date().toString().match(/([-\+][0-9]+)\s/)[1];
data = {
"stime": stime,
"etime": etime,
"property_id": property_id,
"locale": "<%=I18n.locale%>",
"timezone": timezone,
"phire_id": "<%=hire.id%>"
"time_setting_id": time_setting_id,
"phire_id": "<%=hire.id.to_s%>"
}
data["interval"] = interval;
data["recurring_end_date"] = recurring_end_date;
@ -437,60 +843,64 @@
})
return flag;
}
$("#check-avail-btn").on("click",function(){
var el = $(this),
url = $(this).attr("href"),
spinner = $("#spinner");
$(".alert").hide();
var stime = $("#p_hire_start_time").val(),
$(document).on("change","#hire_time_range_block select",function(){
$(this).css("border","");
})
$("#check-avail-btn").on("click",function(){
var el = $(this),
url = $(this).attr("href"),
spinner = $("#spinner");
$(".alert").hide();
var stime, etime;
if(pick_date_mode){
stime = $("#p_hire_date").val();
etime = stime;
}else{
stime = $("#p_hire_start_time").val();
etime = $("#p_hire_end_time").val();
}
var interval = null, recurring_end_date = null, is_recurring = false;;
if($("#p_hire_recurring").is(":checked")){
if($("#p_hire_recurring").is(":checked")){
is_recurring = true;
interval = $("#p_hire_recurring_interval").val(),
recurring_end_date = $("#p_hire_recurring_end_date").val();
if(interval == "" || recurring_end_date == ""){
$("#values-alert").show();
return false;
}
}
spinner.show();
el.hide();
interval = $("#p_hire_recurring_interval").val(),
recurring_end_date = $("#p_hire_recurring_end_date").val();
if(interval == "" || recurring_end_date == ""){
$("#values-alert").show();
return false;
}
}
spinner.show();
el.hide();
check_available(stime,etime,interval,recurring_end_date);
return false;
})
return false;
})
$("#unavailable-schedule").on("click",function(){
$("#unavailable-schedule").on("click",function(){
})
})
var hireForm = new FormValidator($("#new_p_hire"));
hireForm.validate_functions.checkForDates = function(value,element){
return value == "1";
}
hireForm.validate_functions.requiredifrecurring = function(value, element){
if($("#p_hire_recurring").is(":checked")){
return value != "";
}else{
return true;
}
}
var hireForm = new FormValidator($("#new_p_hire"));
hireForm.validate_functions.checkForDates = function(value,element){
return value == "1";
}
hireForm.validate_functions.requiredifrecurring = function(value, element){
if($("#p_hire_recurring").is(":checked")){
return value != "";
}else{
return true;
}
}
$("#p_hire_recurring").on("click",function(){
$("#p_hire_recurring").on("click",function(){
$("#dates_validated").val("0");
$("#property-avaialable-alert").hide();
$("#property-unavaialable-alert").hide();
if($(this).is(":checked")){
$("#recurring-block").slideDown();
}else{
$("#recurring-block").slideUp();
}
})
if($(this).is(":checked")){
$("#recurring-block").slideDown();
}else{
$("#recurring-block").slideUp();
}
})
</script>
<% end %>

View File

@ -23,6 +23,18 @@
<div class="tab-content module-area">
<!-- Basic Module -->
<div class="tab-pane fade in active" id="basic">
<div class="control-group">
<%= f.label :allow_no_logins_user, t("property_hire.allow_no_logins_user"), :class => "control-label muted" %>
<div class="controls">
<%= f.check_box :allow_no_logins_user %>
</div>
</div>
<div class="control-group">
<%= f.label :calendar_type, t("property_hire.display_calendar_default"), :class => "control-label muted" %>
<div class="controls">
<%= f.check_box :calendar_type, {}, "0", "1" %>
</div>
</div>
<div class="control-group">
<%= f.label :auto_approve, t("property_hire.auto_approve"), :class => "control-label muted" %>
<div class="controls">

View File

@ -72,7 +72,7 @@
<div id="calendar-loading"></div>
<script type="text/javascript">
var property_id = "<%= @property.id.to_s %>";
var calendar = new Calendar("#calendar",property_id,"agenda");
var calendar = new Calendar("#calendar",property_id,"agenda",false);
</script>
<% else %>
<table class="table main-list">

View File

@ -1,5 +1,6 @@
<%= csrf_meta_tag %>
<h3><%= @booking.property.title %></h3>
<% property = @booking.property %>
<h3><%= property.title %></h3>
<table class="table main-list">
<tbody>
<tr>
@ -38,13 +39,22 @@
</tr>
<% fields_name = ["organization" ,"person_in_charge" , "tel_of_person_in_charge" , "department" , "contact_person" , "tel_of_contact_person" , "mobile_phone_of_contact_person" , "contact_person_Email" , "contact_person_department"] %>
<% fields_name.each do |field_name| %>
<% if(@booking.property[field_name]["enable"] == "1" rescue false) %>
<% if(property[field_name]["enable"] == "1" rescue false) %>
<tr>
<td><%= t("property_hire.#{field_name}") %></td>
<td><%= property.custom_text(field_name,"name") %></td>
<td><%= @booking[field_name].to_s %></td>
</tr>
<% end %>
<% end %>
<% end %>
<% @booking.p_hire_field_values.each do |v| %>
<% field_info = v.get_field_value rescue {} %>
<% if field_info["title"].present? && !field_info["value"].nil? && !field_info["hint"] %>
<tr>
<td><%=field_info["title"]%>:&nbsp;</td>
<td><%=field_info["value"]%></td>
</tr>
<% end%>
<% end%>
<tr>
<td><%= t("property_hire.passed") %></td>
<td>

View File

@ -23,13 +23,15 @@
<% extra_fields_name = ["organization" ,"person_in_charge" , "tel_of_person_in_charge" , "department" , "contact_person" , "tel_of_contact_person" , "mobile_phone_of_contact_person" , "contact_person_Email" , "contact_person_department"] %>
<% keys = ['hiring_person_name','hiring_person_email','start_time','end_time','recurring','recurring_interval','recurring_end_date','passed','reason_for_hire','note_for_hire'] %>
<% used_extra_fields_name = extra_fields_name.select{|field_name| (property[field_name]["enable"] == "1" rescue false) } %>
<% all_trans = keys.map{|k| t("property_hire.#{k}")} %>
<% all_trans += used_extra_fields_name.map{|k| property.custom_text(k,"name")} %>
<% keys.concat( used_extra_fields_name ) %>
<% keys.each do |k| %>
<% keys.each_with_index do |k,i| %>
<% v = hire.send(k) %>
<% if !v.nil? && !(k.include?('recurring') && hire.recurring != true)%>
<tr>
<td>
<%= t("property_hire.#{k}") %>:&nbsp;
<%= all_trans[i] %>:&nbsp;
</td>
<td>
<% if ['start_time','end_time','recurring','recurring_interval','recurring_end_date','passed'].exclude?(k) %>
@ -47,6 +49,15 @@
</tr>
<% end %>
<% end %>
<% hire.p_hire_field_values.each do |v| %>
<% field_info = v.get_field_value rescue {} %>
<% if field_info["title"].present? && !field_info["value"].nil? %>
<tr>
<td><%=field_info["title"]%>:&nbsp;</td>
<td><%=field_info["value"]%></td>
</tr>
<% end%>
<% end%>
</tbody>
</table>
<% end %>

View File

@ -9,6 +9,18 @@
property = data["property"]
url = data["page"]
current_user = data["current_user"]
allow_no_logins_user = data["allow_no_logins_user"]
all_day_settings = data["all_day_settings"]
recover = data["recover"]
calendar_type = property.calendar_type.to_i rescue 0
right_col = 12
label_col = 2
input_col = 10
if calendar_type == 0
right_col -= 5
label_col += 2
input_col -= 2
end
%>
<style type="text/css">
.full-size-img img {
@ -154,12 +166,15 @@
window.location.href = "<%= "/" + I18n.locale.to_s + url %>";
</script>
<% end %>
<% if current_user.nil? %>
<% if !allow_no_logins_user && current_user.nil? %>
<script type="text/javascript">
alert("Please login before you hire.");
window.location.href = "<%= "/" + I18n.locale.to_s + url %>";
</script>
<% else %>
<script type="text/javascript">
var pick_date_mode = <%=property.set_availability%>;
</script>
<h3 class="property_title"><%= property.title %></h3>
<article class="s-annc s-property">
<section class="s-annc__post-wrap">
@ -233,10 +248,12 @@
</ul>
<% if session["hire-save-msg"].present? %>
<div id="property-unavaialable-alert" class="alert alert-danger" role="alert"><b>Sorry! </b><span> <%= session["hire-save-msg"] %></span></div>
<script type="text/javascript">alert("<%= session["hire-save-msg"] %>")</script>
<% session.delete("hire-save-msg") %>
<% end %>
</article>
<div id="orbit_calendar" class="col-lg-8">
<% if property.calendar_type == 0 %>
<div id="orbit_calendar" class="col-lg-7">
<div id="sec1">
<div class="btn-toolbar" id="navigation">
<div id="calendar-nav">
@ -277,7 +294,7 @@
<div style="display: grid;">
<span id="hidden_date" class="pull-left" style="margin-right: 1em;"></span>
<%= fields_for :timepicker do |f|%>
<%= f.time_picker :timepicker, :no_label => true, :new_record => hire.new_record?,:format=>"HH:mm", :class => "pull-left", :data=>{"picker-type" => "range", "range" => "end", "fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<%= f.time_picker :timepicker, :no_label => true, :new_record => hire.new_record? && !recover,:format=>"HH:mm", :class => "pull-left", :data=>{"picker-type" => "range", "range" => "end", "fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<% end %>
<div class="pull-left btn-group" style="margin-top: 0.5em;">
<button id="confirm_date" class="btn btn-primary btn-sm" style="margin-right: 0.5em;" onclick="set_datetimepicker()"><%=t("property_hire.confirm")%></button>
@ -292,7 +309,6 @@
<script type="text/javascript">
var property_id = "<%= property.id.to_s %>";
var calendar = new Calendar("#calendar",property_id);
var pick_date_mode = <%=property.set_availability%>;
function pick_hire_date(date,allow_times){
if(window.processing_hire)
return;
@ -414,65 +430,82 @@
},500);
}
</script>
<div class="col-lg-4">
<% end %>
<div class="col-lg-<%=right_col%>">
<%= form_for hire, :url => "/xhr/property_hires/make_booking", html: { class: "form-horizontal" } do |f| %>
<%= f.hidden_field :timezone, :value=>"+0",:id=>"timezone_form_field" %>
<% if property.set_availability %>
<div class="form-group">
<%= f.label :date, "*"+t("property_hire.date"), :class => "col-sm-4 control-label" %>
<div class="col-sm-8" id="date_target_block">
<%= f.text_field :date, :value=>t("property_hire.please_choose_date"),:readonly=>"",:onclick=>"goto_calendar()" %>
<%= f.label :date, "*"+t("property_hire.date"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-<%=input_col%>" id="date_target_block">
<% if calendar_type == 0 %>
<%= f.text_field :date, :value=>(recover ? f.object.date.to_s : t("property_hire.please_choose_date")),:readonly=>"",:onclick=>"goto_calendar()" %>
<% else %>
<%= f.datetime_picker :date, :no_label => true, :new_record => hire.new_record? && !recover ,:class => "pull-left", :picker_type => "date", :format=>"yyyy/MM/dd", :data=>{ "fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<% end %>
</div>
</div>
<div class="form-group">
<%= f.label :time, "*"+t("property_hire.time"), :class => "col-sm-4 control-label" %>
<div class="col-sm-8" id="hire_time_range_block">
<%= f.text_field :time, :value=>t("property_hire.please_choose_date"),:readonly=>"",:onclick=>"goto_calendar()" %>
<%= f.label :time, "*"+t("property_hire.time"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-<%=input_col%>" id="hire_time_range_block">
<% property_day_setting = recover ? hire.property_day_setting : nil %>
<% if property_day_setting %>
<%= select_tag "#{f.object_name}[time]", options_for_select([[t("property_hire.please_select"),""],[property_day_setting.title,property_day_setting.id.to_s]],hire.property_day_setting_id), :required=>"required" %>
<% else %>
<% if property.calendar_type == 0 %>
<%= f.text_field :time, :value=>t("property_hire.please_choose_date"),:readonly=>"",:onclick=>"goto_calendar()" %>
<% else %>
<%= select_tag "#{f.object_name}[time]", options_for_select([[t("property_hire.please_choose_date"),""]]), :required=>"required" %>
<% end %>
<% end %>
</div>
</div>
<% else %>
<div class="form-group">
<%= f.label :start_time, "*"+t("property_hire.start_time"), :class => "col-sm-4 control-label" %>
<div class="col-sm-8">
<%= f.datetime_picker :start_time, :no_label => true, :new_record => hire.new_record?,:class => "pull-left", :data=>{"picker-type" => "range", "range" => "start", "fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<%= f.label :start_time, "*"+t("property_hire.start_time"), :class => "col-sm-#{label_col} control-label" %>
<% if property.calendar_type == 0 %>
<div class="col-sm-<%=input_col%>">
<%= f.datetime_picker :start_time, :no_label => true, :new_record => hire.new_record? && !recover,:class => "pull-left", :data=>{"picker-type" => "range", "range" => "start", "fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<button type="button" id="pick_start_date" onclick="change_pick(this)" class="btn btn-primary btn-sm pull-left" style="margin-left: 1em;"><%=t("property_hire.pick_from_calendar")%></button>
</div>
<% end %>
</div>
<div class="form-group">
<%= f.label :end_time, "*"+t("property_hire.end_time"), :class => "col-sm-4 control-label" %>
<div class="col-sm-8">
<%= f.datetime_picker :end_time, :no_label => true, :new_record => hire.new_record?,:class => "pull-left", :data=>{"picker-type" => "range", "range" => "end", "fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<%= f.label :end_time, "*"+t("property_hire.end_time"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-<%=input_col%>">
<%= f.datetime_picker :end_time, :no_label => true, :new_record => hire.new_record? && !recover,:class => "pull-left", :data=>{"picker-type" => "range", "range" => "end", "fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<button type="button" id="pick_end_date" onclick="change_pick(this)" class="btn btn-primary btn-sm pull-left" style="margin-left: 1em;"><%=t("property_hire.pick_from_calendar")%></button>
</div>
</div>
<% end %>
<!-- ############# recurring ############# -->
<div class="form-group">
<%= f.label :recurring, t("property_hire.recurring"), :class => "col-sm-4 control-label" %>
<%= f.label :recurring, t("property_hire.recurring"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-1">
<%= f.check_box :recurring %>
</div>
</div>
<div id="recurring-block" <%= hire.recurring ? "" : "style=display:none;" %>>
<div class="form-group">
<%= f.label :recurring_interval, t("property_hire.recurring_interval"), :class => "col-sm-4 control-label" %>
<%= f.label :recurring_interval, t("property_hire.recurring_interval"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-1">
<%= f.select :recurring_interval, PHire::INTERVALS.collect{|int| [t("property_hire.recurring_interval_types.#{int}"), int] }, {:prompt => t('property_hire.select_interval')}, {:data => {"fv-validation" => "requiredifrecurring;" , "fv-messages" => "Cannot be empty;"}} %>
</div>
</div>
<div class="form-group">
<%= f.label :recurring_end_date, "*"+t("property_hire.recurring_end_date"), :class => "col-sm-4 control-label" %>
<div class="col-sm-8">
<%= f.datetime_picker :recurring_end_date, :no_label => true, :new_record => hire.new_record?, :class=>"pull-left", :data=>{"fv-validation" => "requiredifrecurring;", "fv-messages" => "Cannot be empty;"} %>
<%= f.label :recurring_end_date, "*"+t("property_hire.recurring_end_date"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-<%=input_col%>">
<%= f.datetime_picker :recurring_end_date, :no_label => true, :new_record => hire.new_record? && !recover, :class=>"pull-left", :data=>{"fv-validation" => "requiredifrecurring;", "fv-messages" => "Cannot be empty;"} %>
<% if calendar_type == 0 %>
<button type="button" id="pick_recurring_end_date" onclick="change_pick(this)" class="btn btn-primary btn-sm pull-left" style="margin-left: 1em;"><%=t("property_hire.pick_from_calendar")%></button>
<% end %>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-4 col-sm-5">
<div id="property-avaialable-alert" style="margin-bottom: 5px; padding: 10px; display: none;" class="alert alert-success" role="alert"><b>Hooray! </b>This property is available.</div>
<div class="col-sm-offset-<%=label_col%> col-sm-5">
<div id="property-avaialable-alert" style="margin-bottom: 5px; padding: 10px;<%= 'display: none;' unless recover %>" class="alert alert-success" role="alert"><b>Hooray! </b>This property is available.</div>
<div id="property-unavaialable-alert" style="margin-bottom: 5px; padding: 10px; display: none;" class="alert alert-danger" role="alert"><b>Sorry! </b><span> This property is available.</span></div>
<div id="values-alert" style="margin-bottom: 5px; padding: 10px; display: none;" class="alert alert-warning" role="alert">
<% hint1 = t("property_hire.please_select_recurring_interval_and_recurring_end_time",:default=>"") %>
@ -484,7 +517,7 @@
</div>
</div>
<% if property.set_unavailibility %>
<div class="col-sm-offset-4 col-sm-5">
<div class="col-sm-offset-<%=label_col%> col-sm-5">
<b><%= t("property_hire.Unavailibility_Schedule") %></b>
<div>
<%= property.render_unavailable_message%>
@ -494,33 +527,33 @@
</div>
<div class="form-group">
<label for="" class="col-sm-4 control-label"></label>
<div class="col-sm-8">
<label for="" class="col-sm-<%=label_col%> control-label"></label>
<div class="col-sm-<%=input_col%>">
<a href="/xhr/property_hires/check_availability" id="check-avail-btn" class="btn btn-primary"><%= t('property_hire.check_availibility') %></a>
<img style="display: none;" width="40" src="/assets/spin.gif" id="spinner" />
</div>
</div>
<div class="form-group">
<%= f.label :hiring_person_email, "*"+t("property_hire.hiring_person_email"), :class => "col-sm-4 control-label" %>
<%= f.label :hiring_person_email, "*"+t("property_hire.hiring_person_email"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-5">
<%= f.text_field :hiring_person_email, :class => "form-control", :value => current_user.member_profile.email, :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<%= f.text_field :hiring_person_email, :class => "form-control", :value => (recover ? hire.hiring_person_email : ( current_user.member_profile.email rescue "")), :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
</div>
</div>
<div class="form-group">
<%= f.label :hiring_person_number, "*"+t("property_hire.hiring_person_number"), :class => "col-sm-4 control-label" %>
<%= f.label :hiring_person_number, "*"+t("property_hire.hiring_person_number"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-5">
<%= f.text_field :hiring_person_number, :class => "form-control", :value => current_user.member_profile.mobile_no, :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<%= f.text_field :hiring_person_number, :class => "form-control", :value => (recover ? hire.hiring_person_number : ( current_user.member_profile.mobile_no rescue "")), :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
</div>
</div>
<div class="form-group">
<%= f.label :hiring_person_name, "*"+t("property_hire.hiring_person_name"), :class => "col-sm-4 control-label" %>
<%= f.label :hiring_person_name, "*"+t("property_hire.hiring_person_name"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-5">
<%= f.text_field :hiring_person_name, :class => "form-control", :value => (current_user.name rescue ""), :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<%= f.text_field :hiring_person_name, :class => "form-control", :value => (recover ? hire.hiring_person_name : ( current_user.name rescue "")), :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
<%= f.hidden_field :hiring_person_id, :value => (current_user.member_profile.id.to_s rescue "") %>
</div>
</div>
<div class="form-group">
<%= f.label :reason_for_hire, "*"+t("property_hire.reason_for_hire"), :class => "col-sm-4 control-label" %>
<%= f.label :reason_for_hire, "*"+t("property_hire.reason_for_hire"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-5">
<%= f.text_field :reason_for_hire, :class => "form-control", :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
</div>
@ -533,7 +566,7 @@
<% values = sub_hash["value"].values.select{|v| v.present?}.first.to_s if values.blank? %>
<% type = sub_hash["type"] %>
<div class="form-group">
<%= f.label "notes_selector[#{index}]", name, :class => "col-sm-4 control-label" %>
<%= f.label "notes_selector[#{index}]", name, :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-5">
<% values.each_with_index do |v,i| %>
<label class="checkbox-inline">
@ -549,7 +582,7 @@
<% end %>
<% else %>
<div class="form-group">
<%= f.label :note_for_hire, t("property_hire.note_for_hire"), :class => "col-sm-4 control-label" %>
<%= f.label :note_for_hire, t("property_hire.note_for_hire"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-5">
<%= f.text_area :note_for_hire, :class => "form-control" %>
</div>
@ -560,7 +593,7 @@
<% if(property[field_name]["enable"] == "1" rescue false) %>
<% required = (property[field_name]["required"] == "true" rescue false) %>
<div class="form-group">
<%= f.label field_name, (required ? "*" : "") + property.custom_text(field_name,"name"), :class => "col-sm-4 control-label" %>
<%= f.label field_name, (required ? "*" : "") + property.custom_text(field_name,"name"), :class => "col-sm-#{label_col} control-label" %>
<div class="col-sm-5">
<% placeholder = property.custom_text(field_name,"placeholder") %>
<% if required %>
@ -577,17 +610,28 @@
<% @form_index = 0 %>
<% property.p_hire_fields.asc(:_id).each do |rf| %>
<div class="form-group">
<%= rf.block_helper(property,@form_index,false,"p_hire",p_hire, rf.to_require,4) %>
<%= rf.block_helper(property,@form_index,false,"p_hire",p_hire, rf.to_require,label_col) %>
</div>
<% @form_index = @form_index +1 %>
<% end %>
<% end %>
<% if allow_no_logins_user && current_user.nil? %>
<!-- 驗證碼 -->
<div class="form-group">
<label for="note" class="col-sm-2 control-label"><%= t('property_hire.recaptcha.recaptcha') %></label>
<div class="col-sm-10">
<%= gotcha_error %>
<%= gotcha %>
</div>
</div>
<% end %>
<div class="form-group">
<div class="col-sm-offset-4 col-sm-8">
<div class="col-sm-offset-<%=label_col%> col-sm-<%=input_col%>">
<%= f.hidden_field :id %>
<%= f.submit t("property_hire.save"), :class => "btn btn-primary" %>
<%= f.hidden_field :property_id, :value => property.id %>
<input type="hidden" name="url" value="<%= url %>" />
<input type="hidden" id="dates_validated" name="dates_validated" value="0" data-fv-validation="checkForDates;" data-fv-messages="Please make sure first if dates are available.;">
<input type="hidden" id="dates_validated" name="dates_validated" value="<%=recover ? 1 : 0 %>" data-fv-validation="checkForDates;" data-fv-messages="Please make sure first if dates are available.;">
</div>
</div>
<% end %>
@ -597,10 +641,31 @@
<script type="text/javascript">
var property_id = "<%= property.id.to_s %>";
var timezone = (new Date().getTimezoneOffset() / -60).toString();
var all_day_settings = <%= all_day_settings.to_json.html_safe %>;
if(timezone[0] != "-"){
timezone = "+" + timezone;
}
$("#timezone_form_field").val(timezone);
$("#p_hire_date").on("change",function(){
var _this = $(this);
var date = new Date(_this.val());
if(date.getTime()){
var wday = date.getDay();
var select_target = $("#p_hire_time");
if(select_target.data("wday") == wday){
return;
}
select_target.empty();
select_target.data("wday",wday);
if(all_day_settings[wday]){
select_target.append("<option value=\"\"><%=t("property_hire.please_select")%></option>");
all_day_settings[wday].forEach(function(allow_time){
select_target.append("<option value=\""+allow_time[0]+"\">"+allow_time[1]+"</option>");
});
}else{
select_target.append("<option value=\"\"><%=t("property_hire.no_time_can_select",:default=>"No time can be selected!")%></option>");
}
}
})
var check_available = function(stime,etime,interval,recurring_end_date,check_only,property_id){
var el = $("#check-avail-btn"),
url = $("#check-avail-btn").attr("href"),
@ -637,7 +702,8 @@
"property_id": property_id,
"locale": "<%=I18n.locale%>",
"timezone": timezone,
"time_setting_id": time_setting_id
"time_setting_id": time_setting_id,
"phire_id": "<%=hire.id.to_s%>"
}
data["interval"] = interval;
data["recurring_end_date"] = recurring_end_date;
@ -734,10 +800,4 @@
}
})
</script>
<% end %>
<% end %>

View File

@ -3,6 +3,19 @@ en:
markups:
hint_text: Hint Text
property_hire:
recaptcha:
recaptcha: Recaptcha
errors:
verification_failed: Verification Failed
no_time_can_select: "No time can be selected!"
custom_calendar_type:
default: Default
display: Display
not_display: Not display
page_setting: Page Setting
display_calendar_default: "Display calendar in hire page?(default)"
display_calendar: "Display calendar in hire page?"
allow_no_logins_user: "Allow no logins user to hire property."
please_select_time: "Please select Time!"
date: "Date"
time: "Time"

View File

@ -3,6 +3,19 @@ zh_tw:
markups:
hint_text: 提示文字
property_hire:
recaptcha:
recaptcha: 驗證碼
errors:
verification_failed: 驗證碼錯誤
no_time_can_select: "無時段可選擇!"
custom_calendar_type:
default: 預設
display: 顯示
not_display: 不顯示
page_setting: 頁面設定
display_calendar_default: "是否顯示行事曆在租借頁面(預設值)"
display_calendar: "是否顯示行事曆在租借頁面"
allow_no_logins_user: "允許未登入使用者借用"
please_select_time: "請選擇時段!"
date: "日期"
time: "時段"

View File

@ -4,6 +4,7 @@ Rails.application.routes.draw do
scope "(:locale)", locale: Regexp.new(locales.join("|")) do
get "/xhr/property_hires/check_availability" => "property_hires#check_availability"
post "/xhr/property_hires/make_booking" => "property_hires#make_booking"
patch "/xhr/property_hires/make_booking" => "property_hires#make_booking"
get "/xhr/property_hires/get_bookings" => "property_hires#get_bookings"
namespace :admin do
resources :property_hires do

View File

@ -10,16 +10,19 @@ begin
rescue => e
puts [e.to_s,e.backtrace]
end
app_path = File.expand_path(__dir__)
template_path = ENV['PWD'] + '/app/templates'
all_template = Dir.glob(template_path+'/*/')
puts 'copying module'
all_template.each do |folder|
if folder.split('/')[-1] != 'mobile'
begin
system ('cp -r '+ app_path + '/modules/ ' + folder)
rescue
puts 'error copy'
bundle_update_flag = ARGV[0]=='update' || ARGV[0]=='install'
if bundle_update_flag
app_path = File.expand_path(__dir__)
template_path = ENV['PWD'] + '/app/templates'
all_template = Dir.glob(template_path+'/*/')
puts 'copying module'
all_template.each do |folder|
if folder.split('/')[-1] != 'mobile'
begin
system ('cp -r '+ app_path + '/modules/ ' + folder)
rescue
puts 'error copy'
end
end
end
end