Update a lots of things.

This commit is contained in:
BoHung Chiu 2021-09-07 00:45:14 +08:00
parent 24f93f7630
commit 9c85d50c5b
53 changed files with 4681 additions and 152 deletions

View File

@ -0,0 +1,496 @@
// Retrieve the initial data
function temporary() {
attributesArray.length = 0;
$('.attributes').each(function() {
var attributesData = {},
$selectType = $('.dataType').data().type;
// Capture "attributes-body" within the input[type = "text"] val
$(this).find('.attributes-body').find('input[type="text"]').each(function(i) {
var $type = $(this).data().type;
attributesData[$type] = $(this).val();
});
// Capture "attributes-body" within the input[type = "radio"] checked
$(this).find('.attributes-body').find('input[type="radio"]').each(function(i) {
var $type = $(this).data().type;
attributesData[$type] = $(this).prop("checked");
});
// Capture "attributes-body" within the dataType selected
$(this).find('.attributes-body').find('.dataType').children("option:selected").each(function () {
attributesData[$selectType] = {};
attributesData[$selectType].index = $(this).index();
attributesData[$selectType].name = $(this).attr('ref');
if($(this).attr('ref') == 'typeB' || $(this).attr('ref') == 'typeE' || $(this).attr('ref') == 'typeF') {
attributesData[$selectType].option = [];
}
});
// Capture "field-type" within the input[type = "text"] val
$(this).find('.field-type').find('input[type="text"]').each(function(i) {
var $type = $(this).data().type;
if(!$type.match('option_lang')) {
attributesData[$selectType][$type] = $(this).val();
}
});
$(this).find('.field-type .add-target').find('.input-append').each(function() {
var append = []
$(this).children('input[type="text"]').each(function() {
var val = $(this).val();
append.push(val);
});
attributesData[$selectType].option.push(append);
})
// Capture "field-type" within the input[type = "checkbox"] checked
$(this).find('.field-type').find('input[type="checkbox"]').each(function() {
var $type = $(this).data().type;
attributesData[$selectType][$type] = $(this).prop("checked");
});
// Capture "field-type" within the input[type = "radio"] checked
$(this).find('.field-type').find('input[type="radio"]').each(function() {
var $type = $(this).data().type;
attributesData[$selectType][$type] = $(this).prop("checked");
});
// Capture "field-type" within the dataType selected
$(this).find('.field-type').find('select').children("option:selected").each(function () {
attributesData[$selectType].dateFormat = $(this).index();
});
attributesArray.push(attributesData);
});
};
// Determine the Append input length
function inputAppendLength() {
$('.add-target').each(function(i) {
if($(this).children('.input-append:not(:hidden)').length == 1 || $(this).children('.input-append').length == 1) {
$(this).children('.input-append').each(function() {
if($(this).children('div').hasClass('tab-content')) {
var btnLength = $(this).children('.btn').length;
$(this).find('.btn').eq(btnLength-2).addClass('last');
$(this).find('.remove-input').addClass('hide');
} else {
var mediumLength = $(this).children('.input-medium').length;
$(this).children('.input-medium').eq(mediumLength-1).addClass('last');
$(this).children('.remove-input').addClass('hide');
}
});
} else {
$(this).children('.input-append').each(function() {
if($(this).children('div').hasClass('tab-content')) {
$(this).find('.btn').removeClass('last');
$(this).find('.remove-input').removeClass('hide');
} else {
$(this).children('.input-medium').removeClass('last');
$(this).children('.remove-input').removeClass('hide');
}
});
}
});
};
// Role Attribute Template Data
function setData(l, type, ol) {
var fields = $('#info').length ? "info[p_hire_fields]" : $('#sub_property').length ? "sub_property[p_hire_fields]" : "property[p_hire_fields]",
data = {
_add_more: ["add_more_" +l, fields+"["+l+"]["+type+"][add_more]"],
_calendar: ["calendar_" +l, fields+"["+l+"]["+type+"][calendar]"],
_cross_lang: ["cross_lang_" +l, fields+"["+l+"]["+type+"][cross_lang]"],
_disabled: ["disabled_" +l, fields+"["+l+"][disabled]"],
_format: ["format_" +l, fields+"["+l+"]["+type+"][format]"],
_initial: ["initial_" +l, fields+"["+l+"]["+type+"][initial]"],
_is_range: ["is_range_" +l, fields+"["+l+"]["+type+"][is_range]"],
_key: ["key_" +l, fields+"["+l+"][key]"],
_markup: fields+"["+l+"][markup]",
_option_list: ["option_list_"+l+"_"+ol, fields+"["+l+"]["+type+"][option_list]["+ol+"]", "option_list_"+ol],
_placeholder: ["placeholder_" +l, fields+"["+l+"]["+type+"][placeholder]"],
_title_translations: ["title_translations_" +l, fields+"["+l+"][title_translations]"],
_to_delete: ["to_delete_" +l, fields+"["+l+"][to_delete]"],
_to_require: ["to_require_" +l, fields+"["+l+"][to_require]"],
};
return data;
}
// Get Default Address Form
function getAddressForm(trigger, element, decide) {
if(decide) {
addressVal.length = addressArray.length = 0;
var addressAllVal = [];
var inputNameArray = [];
trigger.closest('.input-append').find('.tab-pane').each(function() {
var adderssText = $(this).children('input[type="text"]').val(),
addersshidden = '',
addressData = {},
inputName = [];
$(this).children('input:not(:first)').each(function(j) {
var name = $(this).attr('name'),
val = $(this).val();
addersshidden += val;
addressData[name] = val;
inputName.push(name);
});
addressArray.push(addressData);
addressAllVal.push(adderssText);
inputNameArray.push(inputName);
if(adderssText != addersshidden) {
addressVal.push(false);
} else {
addressVal.push(true);
}
});
element.find('.tab-pane').each(function(i) {
$(this).find('textarea, input[type="text"]').each(function(j) {
$(this).attr('name',inputNameArray[i][j]);
});
if(addressVal[i]) {
$(this).find('textarea, input[type="text"]').each(function(j) {
$(this).val(addressArray[i][$(this).attr('name')]);
});
} else {
$(this).find('textarea').val(addressAllVal[i]);
$(this).find('input[type="text"]').each(function(j) {
$(this).val('');
});
}
});
};
element.off('show');
};
// Return Address Form
function returnAddressForm(element, decide) {
if(decide) {
addressArray.length = 0;
element.find('.tab-pane').each(function(i) {
var addressData = {};
$(this).find('textarea, input[type="text"]').each(function(j) {
var name = $(this).attr('name'),
val = $(this).val();
addressData[name] = val;
});
addressArray.push(addressData);
});
$.map(addressInputId, function(n, i) {
var v = '';
$('#'+n).find('input[type="hidden"]').each(function() {
$(this).val(addressArray[i][$(this).attr('name')]);
v += addressArray[i][$(this).attr('name')]
});
$('#'+n).find('input[type="text"]').each(function() {
$(this).val(v);
});
});
};
returnDecide = false;
};
$(function() {
appendIndex = null;
if($('#user-forms').length) {
addressVal = [];
addressArray = [];
addressInputId = [];
propertyType = null;
returnDecide = false;
$('.attributes').each(function() {
if($(this).find('.toggle-check').attr('value') == "true") {
$(this).addClass('disabled').children('.attributes-body').hide();
}
});
$('.returnDecide').on(clickEvent, function() {
returnDecide = true;
})
$('#address-field').on('hidden', function () {
$('.btn[data-toggle="modal"]').removeClass('active').blur();
$(this).find('.nav-tabs > li').removeClass('active').eq(0).addClass('active');
$(this).find('.tab-content > .tab-pane').removeClass('active in').eq(0).addClass('active in');
$(this).on('show', getAddressForm(null, $(this), false));
returnAddressForm($(this), returnDecide)
});
$('.control-group').delegate('.btn[data-toggle="modal"]', 'click', function() {
var $trigger = $(this);
addressInputId.length = 0;
$(this).closest('.input-append').find('.tab-pane').each(function() {
addressInputId.push($(this).attr('id'));
});
$('#address-field').on('show', getAddressForm($trigger, $('#address-field'), true));
});
$('#user-forms').delegate('.togglebox, .delete, .trigger, .remove-input', clickEvent, function(event) {
if($(this).hasClass('togglebox')) {
var property_staus = [];
if($(this).hasClass('disable')) {
$(this).find('.toggle-check')
.attr('value', 'false')
.closest('.attributes')
.removeClass('disabled')
.children('.attributes-body')
.fadeIn(300);
} else {
$(this).find('.toggle-check')
.attr('value', 'true')
.closest('.attributes')
.addClass('disabled')
.children('.attributes-body')
.fadeOut(300)
.find('.check')
.attr("checked",false)
.attr("value",property_staus);
}
$(this).toggleClass('disable');
};
if($(this).hasClass('remove-input')) {
$(this).closest('.input-append').fadeOut(300, function() {
$(this).remove();
inputAppendLength();
});
};
if($(this).hasClass('trigger')) {
appendIndex = $(this).closest('.controls').find('.input-append').length;
nameNumber = $(this).closest('.controls').find('.input-append:eq(0)').find('input').eq(0).attr('name');
nameNumber = nameNumber.match(/[^[\D\]]+(?=])/g)[0];
propertyType = $(this).data('properties')
if($(this).hasClass('textInput')) {
$("#template-text").tmpl().appendTo($(this).closest('.controls').find('.add-target'));
} else if ($(this).hasClass('textLengInput')) {
$("#template-text-language").tmpl().appendTo($(this).closest('.controls').find('.add-target'));
} else if ($(this).hasClass('address')) {
$("#template-address").tmpl().appendTo($(this).closest('.controls').find('.add-target'));
}
inputAppendLength();
};
event.preventDefault();
});
inputAppendLength();
} else {
attributesArray = [];
attributesHeaderLength = null;
templateType = null;
attributeIndex = null;
if($('.add-target').length) {
inputAppendLength();
}
if(!$('.attributes').length) {
$('#attributes-area').addClass('clickHere');
} else {
temporary();
};
$('.add-attributes').on(clickEvent, function() {
if($('#attributes-area').hasClass('clickHere')) {
$('#attributes-area').removeClass('clickHere');
};
attributesHeaderLength = $('.attributes:not(:hidden)').length+1;
attributesLength = $('#attributes-area .attributes').length;
if(templateType == null){
templateType = "typeA";
}
$("#template-attributes").tmpl(setData(attributesLength, templateType, appendIndex)).appendTo( "#attributes-area" );
$('.toggle-check').togglebox();
});
$('.attributes.default').each(function(i) {
$(this).children('.field-type').not('.default').hide();
$(this).find('input[type="text"]').on('keyup', function() {
$(this).trigger("checking");
});
$(this).find('input[type="radio"], input[type="checkbox"], select').change(function() {
$(this).trigger("checking");
});
$(this).delegate('input[type="text"], input[type="radio"], input[type="checkbox"], select', 'checking', function(e) {
var e = e.target.type,
$data = $(this).data().type;
switch(e) {
case 'text':
var val = $(this).val();
if(!$(this).closest('.field-type').length) {
$data = attributesArray[i][$data];
} else if(!$(this).closest('.add-target').length) {
$data = attributesArray[i].select[$data];
} else {
appendIndex = $(this).parent('.input-append').index()
optionIndex = $(this).index()
$data = attributesArray[i].select.option[appendIndex][optionIndex];
}
if(val != $data) {
$(this).closest('.attributes').find('.reply').removeClass('hide');
}
break;
case 'radio':
var checked = $(this).prop("checked");
$data = attributesArray[i][$data];
if(checked != $data) {
$(this).closest('.attributes').find('.reply').removeClass('hide');
}
break;
case 'checkbox':
var checked = $(this).prop("checked");
$data = attributesArray[i].select[$data];
if(checked != $data) {
$(this).closest('.attributes').find('.reply').removeClass('hide');
}
break;
case 'select-one':
var ref,
$data = attributesArray[i].select.name;
$(this).children("option:selected").each(function() {
ref = $(this).attr('ref');
});
if(ref != $data) {
$(this).closest('.attributes').find('.reply').removeClass('hide');
}
break;
};
});
$(this).delegate('.reply', clickEvent, function() {
var $bodyText = $(this).parent('.attributes-header').siblings('.attributes-body').find('input[type="text"]'),
$bodyRadio = $(this).parent('.attributes-header').siblings('.attributes-body').find('input[type="radio"]'),
$bodySelected = $(this).parent('.attributes-header').siblings('.attributes-body').find('.dataType').children("option"),
$fieldTypeO = $(this).parent('.attributes-header').siblings('.field-type.default'),
$fieldTypeN = $(this).parent('.attributes-header').siblings('.field-type').not('.default');
$bodyText.each(function() {
var $type = $(this).data().type;
$(this).val(attributesArray[i][$type]);
});
$bodyRadio.each(function() {
var $type = $(this).data().type;
$(this).prop("checked", attributesArray[i][$type])
});
$fieldTypeO.find('input[type="text"]').each(function() {
var $type = $(this).data().type;
if(!$type.match('option_lang')) {
$(this).val(attributesArray[i].select[$type]);
}
});
$fieldTypeO.find('.add-target').find('.input-append').each(function(k) {
$(this).children('input[type="text"]').each(function(j) {
$(this).val(attributesArray[i].select.option[k][j]);
// var val = $(this).val();
// append.push(val);
});
})
$fieldTypeO.find('input[type="checkbox"], input[type="radio"]').each(function() {
var $type = $(this).data().type;
$(this).prop("checked", attributesArray[i].select[$type]);
});
$fieldTypeO.find('select').children("option").eq(attributesArray[i].select.dateFormat).prop('selected',true);
$bodySelected.eq(attributesArray[i].select.index).prop('selected',true);
$fieldTypeO.show();
$fieldTypeN.empty().hide();
$(this).addClass('hide')
return false
})
});
$('#attributes-area').delegate('.togglebox, .delete, .trigger, .remove-input', clickEvent, function(event) {
if($(this).hasClass('togglebox')) {
if($(this).hasClass('disable')) {
$(this).find('.toggle-check')
.attr('value', 'false')
.closest('.attributes')
.removeClass('disabled')
.find('input, select')
.removeAttr('disabled')
.end('.attributes')
.find('.btn-group .btn')
.removeClass('disabled')
.end().find('.attribute_field_disabled').attr('value', 'false');
if($(this).closest('.attributes').find('.dataType').children("option:selected").attr('ref')) {
$(this).closest('.attributes').find('.field-type').addClass('in').find('.control-group').delay(150).fadeIn(300);
}
} else {
$(this).find('.toggle-check')
.attr('value', 'true')
.closest('.attributes')
.addClass('disabled')
.find('.attributes-body input, .attributes-body select')
.attr({'disabled': 'disabled'})
.end('.attributes')
.find('.btn-group .btn')
.addClass('disabled')
.end().find('.attribute_field_disabled').attr('value', 'true')
.end().find('.field-type .control-group').fadeOut(300, function() {
$(this).parent('.field-type').removeClass('in');
});
}
$(this).toggleClass('disable');
};
if($(this).hasClass('delete')) {
$(this).closest('.attributes').fadeOut(300, function() {
$('.attributes:not(:hidden)').each(function(i) {
$(this).find('.attributes-header h4 span').text(i+1);
});
attributesHeaderLength = $('.attributes:not(:hidden)').length+1;
if(!$('.attributes:not(:hidden)').length) {
$('#attributes-area').addClass('clickHere');
};
}).find('.attribute_field_to_delete').attr('value', 'true');;
};
if($(this).hasClass('trigger')) {
// appendIndex = $(this).closest('.controls').find('.input-append').length;
appendIndex = $(this).closest('.controls').find('.input-append:last-child').children('input:first-child').attr('name');
// appendIndex = appendIndex.split("][");
// appendIndex = parseInt(appendIndex[appendIndex.length-2])+1;
appendIndex = parseInt(appendIndex.match(/[^[\D\]]+(?=])/g)[1])+1;
attributeIndex = $(this).closest('.attributes').index();
templateType = $(this).closest('.attributes').find('.dataType').children("option:selected").attr('ref');
$("#template-input-append").tmpl(setData(attributeIndex, templateType, appendIndex)).appendTo($(this).closest('.controls').find('.add-target'));
inputAppendLength();
};
if($(this).hasClass('remove-input')) {
$(this).parent('.input-append').fadeOut(300, function() {
$(this).remove()
inputAppendLength();
});
}
event.preventDefault();
});
$('#attributes-area').delegate('.dataType', 'change', function() {
$(this).children("option:selected").each(function () {
var target = $(this).closest('.attributes').find('.field-type').not('.default');
attributeIndex = $(this).closest('.attributes').index();
appendIndex = 0
// $(this).closest('.attributes').find('.add-target').find('.input-append').length;
if($(this).closest('.attributes').hasClass('default')){
var i = $(this).closest('.attributes').index()
if($(this).attr('ref') == attributesArray[i].select.name) {
$(this).closest('.attributes').find('.field-type.default').show()
target.empty().hide();
} else {
$(this).closest('.attributes').find('.field-type.default').hide()
if($(this).attr('ref')) {
templateType = $(this).attr('ref');
target.removeAttr('class').addClass('field-type fade in ' + templateType).empty();
$("#template-type").tmpl(setData(attributeIndex, templateType, appendIndex)).appendTo(target);
if(templateType == 'typeB' || templateType == 'typeE' || templateType == 'typeF') {
inputAppendLength();
}
} else {
target.removeAttr('class').addClass('field-type fade')
target.empty();
};
target.show();
}
} else {
if($(this).attr('ref')) {
templateType = $(this).attr('ref');
target.removeAttr('class').addClass('field-type fade in ' + templateType).empty();
$("#template-type").tmpl(setData(attributeIndex, templateType, appendIndex)).appendTo(target);
if(templateType == 'typeB' || templateType == 'typeE' || templateType == 'typeF') {
inputAppendLength();
}
} else {
target.removeAttr('class').addClass('field-type fade')
target.empty();
};
}
});
});
}
});

View File

@ -65,6 +65,7 @@ window.datetime_format = is_chinese ? 'y M d h:m b' : 'd M, y h:m b';
window.date_format = is_chinese ? 'y M d' : 'd M, y';
window.time_format = "h:m b";
window.date_time_str_format = 'y/MM/d H:m';
window.std_date_format = 'y-MM-d';
window.short_day = (is_chinese ? "d (w)" : "w d")
window.short_date = (is_chinese ? "M d (w)" : "w d, M")
window.getDateString = function(date, format,is_chinese) {
@ -173,9 +174,19 @@ var Calendar = function(dom,property_id,currentView){
if(calEvent.jsEvent && !e){
e = {"originalEvent": calEvent.jsEvent}
}
c.dialog.dismiss();
c.dialog.inflate(calEvent);
c.dialog.show({"x":e.originalEvent.clientX,"y":e.originalEvent.clientY});
var el = $(calEvent.el);
if(el.hasClass("reserve_btn")){
window.calEvent = calEvent;
var start_time = calEvent.event.start;
var date_str = window.getDateString(start_time,std_date_format);
var allow_times = calEvent.event._def.extendedProps.allow_times;
console.log(date_str)
window.pick_hire_date(date_str,allow_times);
}else{
c.dialog.dismiss();
c.dialog.inflate(calEvent);
c.dialog.show({"x":e.originalEvent.clientX,"y":e.originalEvent.clientY});
}
},
dateClick: function(ev) {
var calendar = this;
@ -335,10 +346,15 @@ var EventDialog = function(calendar,event){
this.show = function(pos){
event_quick_view.css({width: '',height: ''});
event_quick_view.css({display: 'inline-block',width: '',height: '', position: "fixed", "z-index": "10000"});
var offset;
var padding = 20;
if(pos){
offset = {"left":pos.x,"top":pos.y};
var pos = getPosition(pos);
event_quick_view.css({"left":pos.x+"px","top":pos.y+"px"});
event_quick_view.offset(offset);
}else{
offset = {"left": padding, "top": padding};
}
event_quick_view.html(template).appendTo("body").show();
event_quick_view.find(".event-close-btn").one("click",function(){_t.dismiss();});
@ -346,13 +362,12 @@ var EventDialog = function(calendar,event){
event_quick_view.find("a.edit").one("click",function(){calendar.editEvent(_this_event.edit_url,_this_event.allDay);return false;});
var window_width = $(window).width(),
window_height = $(window).height();
var offset = event_quick_view.offset();
var dialog_width = event_quick_view.width(),
dialog_height = event_quick_view.height();
var new_offset = Object.assign({},offset);
var need_redisplay = false;
var new_width = null, new_height = null;
var padding = 20;
var padding_top = padding + 40;
if(offset.left + dialog_width > window_width){
new_offset.left = window_width - dialog_width - padding;
need_redisplay = true;
@ -366,9 +381,9 @@ var EventDialog = function(calendar,event){
new_offset.top = window_height - dialog_height - padding;
need_redisplay = true;
}
if(new_offset.top < padding){
new_height = dialog_height - (padding - new_offset.top);
new_offset.top = padding;
if(new_offset.top < padding_top){
new_height = dialog_height - (padding_top - new_offset.top);
new_offset.top = padding_top;
need_redisplay = true;
}
if(need_redisplay){

View File

@ -0,0 +1,140 @@
.card {
position: relative;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
min-width: 0;
word-wrap: break-word;
background-color: #fff;
background-clip: border-box;
border: 1px solid rgba(0,0,0,.125);
border-radius: .25rem;
}
.card hr {
margin-right: 0;
margin-left: 0;
}
.card-header {
padding: .75rem 1.25rem;
margin-bottom: 0;
background-color: rgba(0,0,0,.03);
border-bottom: 1px solid rgba(0,0,0,.125);
}
.card-header:first-child {
border-radius: calc(.25rem - 1px) calc(.25rem - 1px) 0 0;
}
.card-body {
align-items: normal;
-webkit-box-flex: 1;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
padding: 1.25rem;
}
.card-title {
margin-bottom: .75rem;
}
.card-header + .list-group .list-group-item:first-child {
border-top: 0;
}
.card-text:last-child {
margin-bottom: 0;
}
.card-footer {
padding: .75rem 1.25rem;
background-color: rgba(0,0,0,.03);
border-top: 1px solid rgba(0,0,0,.125);
}
.card-footer:last-child {
border-radius: 0 0 calc(.25rem - 1px) calc(.25rem - 1px);
}
.card-group {
display: flex;
flex-direction: column;
// The child selector allows nested `.card` within `.card-group`
// to display properly.
> .card {
margin-bottom: 0.9375em;
}
@media screen and (min-width: 576px) {
flex-flow: row wrap;
// The child selector allows nested `.card` within `.card-group`
// to display properly.
> .card {
flex: 1 0 0%;
margin-bottom: 0;
+ .card {
margin-left: 0;
border-left: 0;
}
&:first-child {
border-right-radius: 0;
.card-img-top,
.card-header {
border-top-right-radius: 0;
}
.card-img-bottom,
.card-footer {
border-bottom-right-radius: 0;
}
}
&:last-child {
border-left-radius: 0;
.card-img-top,
.card-header {
border-top-left-radius: 0;
}
.card-img-bottom,
.card-footer {
border-bottom-left-radius: 0;
}
}
&:only-child {
border-radius: .25rem;
.card-img-top,
.card-header {
border-top-radius: .25rem;
}
.card-img-bottom,
.card-footer {
border-radius: .25rem;
}
}
&:not(:first-child):not(:last-child):not(:only-child) {
border-radius: 0;
.card-img-top,
.card-img-bottom,
.card-header,
.card-footer {
border-radius: 0;
}
}
}
}
}

View File

@ -0,0 +1,79 @@
/*reset*/
h1, h2, h3, h4, h5, p{
margin: 0;
padding: 0;
}
br{
display: block;
margin: 0 0 5px;
}
ol, ul{
margin: 0;
padding: 0;
}
li{
list-style: none;
}
body > img {
display: none;
}
img{
border: none;
padding: 0;
margin: 0;
}
a {
outline: none;
text-decoration: none !important;
}
table, tr, td{
padding: 0;
border-spacing: 0;
}
/*reset end *//* CSS Document */
#property_order_table{
border-collapse: unset !important;
position: relative;
width: 593px;
margin: 40px auto;
}
#property_order_table th{
background-color: #454545;
color: #fff;
}
.position-text{
position: relative;
width: 85px;
}
#property_order_table .editable-input{
position: relative;
width: 25px;
margin-bottom: 0;
padding: 0px 0px 0px 5px;
}
.position-text-div{
height: 22px;
}
.order-edit-notification{
background-color: #ffffd5;
z-index: 10;
display: none;
height: 25px;
left: 40%;
position: fixed;
text-align: center;
margin-top: 5px;
top: 85px;
width: 400px;
font-size: 13px;
}

View File

@ -6,6 +6,9 @@
background: var(--fc-highlight-color, rgba(188, 232, 241, 0.3));
}
}
a.reserve_btn{
cursor: pointer;
}
/* orbit calendar */
#orbit_calendar {
transition: all 0.3s ease;

View File

@ -12,7 +12,20 @@ class Admin::PropertyHiresController < OrbitAdminController
@properties = search_data(@properties,[:title]).page(params[:page]).per(10)
end
def order
@properties = Property.all.sort_order
end
def updateorder
ids_with_order = params[:order]
ids_with_order.each_with_index do |id,idx|
property = Property.find(id) rescue nil
if !property.nil?
property.order_position = idx
property.save
end
end
render :json => {"success" => true}.to_json
end
def my_bookings
@table_fields = ["property_hire.title","property_hire.hiring_person_name", "property_hire.reason_for_hire", "property_hire.hiring_person_number", "property_hire.period", "property_hire.passed", :actions]
@bookings = PHire.where(:hiring_person_id => current_user.member_profile.id.to_s).desc(:created_at).page(params[:page]).per(10)
@ -61,14 +74,27 @@ class Admin::PropertyHiresController < OrbitAdminController
def update
property = Property.where(:uid => params[:id].split("-").last).first rescue nil
redirect_to admin_property_hires_path and return if property.nil?
property.update_attributes(property_params)
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
Admin::PropertyHiresHelper::HireMethod.send_mail('edit',email,property.id,nil,nil,current_user.id)
if params[:page]
redirect_to admin_property_hires_path(:page => params[:page],:locale => params[:locale])
@property_params = property_params
if @property_params[:p_hire_fields]
@property_params[:p_hire_fields].each do |a|
@field_name = 'property'
field_status = a.last[:id].present?
@attribute_field = PHireField.add_p_hire_field(property, a.last, a.last[:id], field_status)
@attribute = property
end
flash.now[:notice] = "Updated Fields"
property.p_hire_fields.each{|t| t.destroy if t["to_delete"] == true}
redirect_to admin_property_hires_path(:locale => params[:locale]) and return
else
redirect_to admin_property_hires_path(:locale => params[:locale])
property.update_attributes(@property_params)
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
Admin::PropertyHiresHelper::HireMethod.send_mail('edit',email,property.id,nil,nil,current_user.id)
if params[:page]
redirect_to admin_property_hires_path(:page => params[:page],:locale => params[:locale])
else
redirect_to admin_property_hires_path(:locale => params[:locale])
end
end
end
@ -175,7 +201,13 @@ class Admin::PropertyHiresController < OrbitAdminController
end
end
end
def custom_fields
@field_name = 'property'
uid = params[:id].split("-").last
@attribute = Property.find_by(:uid=>uid)
@attribute_type = 'property'
@class = 'properties'
end
private
def settings_params
@ -190,6 +222,9 @@ class Admin::PropertyHiresController < OrbitAdminController
end
def property_params
prop = params.require(:property).permit!
if prop[:weekdays].nil?
prop[:weekdays] = []
end
prop.delete(:property_location) if prop[:property_location] == "other"
notes_selector = prop["notes_selector"]
notes_selector = {} if notes_selector.nil?

View File

@ -1,26 +1,34 @@
class PropertyHiresController < ApplicationController
include Admin::PropertyHiresHelper
def index
properties = Property.filter_by_categories.filter_by_tags.desc(:created_at)
properties = Property.filter_by_categories.filter_by_tags.sort_order
data = properties.collect do |property|
actions = []
url_to_show = OrbitHelper.url_to_show(property.to_param)
if property.can_be_hired
hire_url = url_to_show + "?method=hire"
puts url_to_show
actions << {
"text" => t("property_hire.hire"),
"btn-class" => "btn-primary",
"link" => OrbitHelper.url_to_show(property.to_param) + "?method=hire"
}
actions << {
"text" => t("property_hire.view_calendar"),
"btn-class" => "btn-info",
"link" => OrbitHelper.url_to_show(property.to_param) + "?method=view_calendar"
"link" => hire_url
}
unless property.disable_view_calendar_page
actions << {
"text" => t("property_hire.view_calendar"),
"btn-class" => "btn-info",
"link" => url_to_show + "?method=view_calendar"
}
end
if property.disable_content_page
url_to_show = hire_url
end
end
{
"title" => property.title,
"image" => (property.image.url.blank? ? '" style="display: none;' : property.image.url),
"image-thumb" => (property.image.thumb.url.blank? ? '" style="display: none;' : property.image.thumb.url),
"url_to_show" => OrbitHelper.url_to_show(property.to_param),
"url_to_show" => url_to_show,
"location" => property.get_location_name,
"actions" => actions
}
@ -159,9 +167,25 @@ class PropertyHiresController < ApplicationController
def make_booking
booking_p = booking_params
data = check_for_availability(booking_p[:start_time],booking_p[:end_time],booking_p[:property_id], booking_p[:recurring_interval], booking_p[:recurring_end_date])
time_setting_id = booking_p[:time]
start_time = booking_p[:start_time]
end_time = booking_p[:end_time]
time_setting = nil
if time_setting_id.present?
start_time = booking_p[:date]
end_time = start_time
time_setting = PropertyDaySetting.find(time_setting_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)
end
hire = PHire.new(booking_p)
hire.passed = true if PropertyHireSetting.auto_approve_enabled?
hire.save
@ -197,7 +221,8 @@ class PropertyHiresController < ApplicationController
end
def check_availability
data = check_for_availability params[:stime], params[:etime], params[:property_id], params[:interval], params[:recurring_end_date]
time_setting_id = params[:time_setting_id]
data = check_for_availability params[:stime], params[:etime], params[:property_id], params[:interval], params[:recurring_end_date], time_setting_id
render :json => data.to_json
end
@ -210,7 +235,23 @@ class PropertyHiresController < ApplicationController
edt = Time.at(params[:end].to_i)
events = PHire.monthly_event(sdt,edt,params[:property_id])
re = PHire.recurring_event(sdt,edt,params[:property_id])
events = events.map{|e| e.as_json}
allevents = events.inject(re, :<<)
@need_check_events = allevents.map{|e| [Date.parse(e[:start].split("T")[0]),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 all_day_settings.count != 0
time_now = Time.now
get_start_time = [sdt,time_now].max
get_end_time = edt
if property.set_unavailibility
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)
end
end
end
end
end
respond_to do |format|
@ -218,12 +259,124 @@ class PropertyHiresController < ApplicationController
format.json { render json: allevents.to_json }
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"]}
end
def generate_all_reserve_buttons(startt,endt,all_day_settings)
@display_title = I18n.t("property_hire.reserve")
@allevents = []
start_wday = startt.wday
end_flag = false
start_date = startt.to_date
@start_date = start_date
end_date = endt.to_date
@end_date = end_date
@first_check_time = startt.strftime("%H:%M")
@all_day_settings = all_day_settings
@startt = startt
@endt = endt
print all_day_settings
puts nil
def generate_events(start_wday,end_wday,type=0)
if type == 0
(start_wday..end_wday).each do |wday|
wday_str = wday.to_s
is_start_day = (start_wday == wday)
if @all_day_settings.has_key?(wday_str)
check_time = nil
check_time = @first_check_time if is_start_day
i = @need_check_events.index{|e| e[0] > @start_date}
if i.nil?
i = -1
elsif i != -1
i -= 1
end
check_events = []
if i != -1
check_events = @need_check_events[0..i]
end
@need_check_events = @need_check_events[(i+1)..-1]
settings = @all_day_settings[wday_str]
if check_events.count != 0
settings = settings.select do |s|
flag = true
if check_time
if check_time > s[1]
flag = false
end
end
if flag
if s[3] == 0 #reservation_limit == 0 => no limit
true
else
@need_check_events.select{|e| e[1] == s[2] }.count <= s[3]
end
else
false
end
end
end
if settings.count != 0
@allevents << reserve_calendar_event(@start_date,@display_title,settings)
end
end
@start_date += 1.day
if @start_date > @end_date
end_flag = true
break
end
end
else
@all_day_settings.each do |wday_str,settings|
tmp_date = @start_date + wday_str.to_i.send("day")
check_time = "00:00"
i = @need_check_events.index{|e| e[0] > tmp_date}
if i.nil?
i = -1
elsif i != -1
i -= 1
end
check_events = []
if i != -1
check_events = @need_check_events[0..i]
end
@need_check_events = @need_check_events[(i+1)..-1]
if check_events.count != 0
settings = settings.select do |s|
@need_check_events.select{|e| e[1] == s[2] }.count == 0
end
end
if settings.count != 0
@allevents << reserve_calendar_event(tmp_date,@display_title,settings)
end
end
@start_date += 7.day
end
end
all_days = (end_date-start_date).to_i
end_wday = 6
end_date_wday = end_date.wday
only_first_week = false
if (start_wday + all_days <= 6)
end_wday = end_date_wday
only_first_week = true
end
generate_events(start_wday,end_wday)
unless only_first_week
all_days = all_days - (end_wday - start_wday)
while all_days > 6 do
generate_events(0,6)
all_days -= 7
end
generate_events(0,all_days)
end
@allevents
end
private
def booking_params
p_hire_params = params.require(:p_hire).permit!
property = Property.find(params[:property_id]) rescue Property.last
property = Property.find(params[:p_hire][:property_id]) rescue Property.last
if(property.enable_notes_selector rescue false)
note_texts = ""
property.notes_selector.each do |index,sub_hash|
@ -231,7 +384,7 @@ class PropertyHiresController < ApplicationController
name = sub_hash["name"].values.select{|v| v.present?}.first.to_s if name.blank?
values = sub_hash["value"][I18n.locale.to_s]
values = sub_hash["value"].values.select{|v| v.present?}.first.to_s if values.blank?
value_text = p_hire_params["notes_selector"][index.to_s].to_a.map{|i| values[i.to_i]}.join(",")
value_text = p_hire_params["notes_selector"][index.to_s].to_a.map{|i| values[i.to_i]}.join(",") rescue ""
value_text = I18n.t("property_hire.none") if value_text.blank?
note_texts += (name + ":"+value_text)
note_texts += "<br>".html_safe

View File

@ -0,0 +1,555 @@
module Admin::PHireFieldHelper
include ActionView::Helpers::FormTagHelper
include ActionView::Helpers::FormOptionsHelper
include ActionView::Helpers::DateHelper
include ActionView::Helpers::TagHelper
include ActionView::Helpers::RenderingHelper
include ActionView::Context
include OrbitBasis::RenderAnywhere
include OrbitFormHelper
def block_helper(member,index,disable = false,attribute_type=nil,p_hire=nil, to_require=true, col=2)
unless self.disabled
@col = col
@index = index
@require = to_require
@markup_options = markup_options.merge(:disabled=>disable, :required => to_require)
@member = member
@attribute_value = @member.get_value_from_field_id(id,p_hire)
@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
return instance_eval("render_#{markup}") rescue ""
end
end
def lang_tab(str,lang)
content_tag(:div,str,:class=>"tab-pane fade",:id=>(get_field_name_base+"tab_#{lang}"))
end
def render_hint_text
control_group_wrapper do |key,value|
if !@prefiled_value.nil?
value = can_muti_lang_input? ? @prefiled_value[key] : @prefiled_value
else
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
end
def render_address
control_group_wrapper do |key,value|
value = (can_muti_lang_input? ? @prefiled_value[key] : @prefiled_value) rescue nil
key_field = can_muti_lang_input? ? "[#{key}]" : ""
place_holder= @panel_setting["placeholder"][key] rescue ''
# result = text_area_tag(get_field_name_base + key_field, value,@markup_options.merge({:placeholder=>place_holder,:for=>key}))
result = text_field_tag(get_field_name_base + key_field, value,@markup_options.merge({:placeholder=>place_holder,:for=>key}))
add_ext= @attribute_value.address_key[key] rescue {}
result << hidden_field_tag(get_basic_field_name_base+"[address_key][#{key}][county]",add_ext["county"],:class=>"county_#{key}", :id=>nil)
result << hidden_field_tag(get_basic_field_name_base+"[address_key][#{key}][street_address]",add_ext["street_address"],:class=>"street_address_#{key}", :id=>nil)
result << hidden_field_tag(get_basic_field_name_base+"[address_key][#{key}][city]",add_ext["city"],:class=>"city_#{key}", :id=>nil)
result << hidden_field_tag(get_basic_field_name_base+"[address_key][#{key}][zip]",add_ext["zip"],:class=>"zip_#{key}", :id=>nil)
result << hidden_field_tag(get_basic_field_name_base+"[address_key][#{key}][country]",add_ext["country"],:class=>"country_#{key}", :id=>nil)
result << hidden_field_tag(get_basic_field_name_base+"[address_key][#{key}][indicator]",add_ext["indicator"],:class=>"indicator_#{key}", :id=>nil)
end
end
def render_checkbox
@prefiled_value ||=[]
control_group_wrapper do
a = self.typeE[:option_list].collect do |key,value|
label_tag("#{get_basic_field_name_org}_#{self.id}_#{key}",check_box_tag(get_field_name_base+"[#{key}]", true , (@prefiled_value.include?(key) ? true : false), { :id=>"#{get_basic_field_name_org}_#{self.id}_#{key}"})+value[I18n.locale.to_s],@markup_options.merge(:class=>"checkbox inline"))
end.join.html_safe rescue ""
end
end
def render_date
d = DateTime.now()
if date_is_range?
# fill_from = @attribute_value.get_date(:from) rescue nil
# fill_to = @attribute_value.get_date(:to) rescue nil
control_group_wrapper do
case self.typeC['format']
when 'format1'
fill_from = (@prefiled_value && @prefiled_value["from"] ) ? @prefiled_value["from"] : d.strftime("%Y/%m/%d %H:%M")
fill_to = (@prefiled_value && @prefiled_value["to"] ) ? @prefiled_value["to"] : d.strftime("%Y/%m/%d %H:%M")
buf = datetime_picker(get_field_name_base+'[from]', fill_from, 'yyyy/MM/dd hh:mm', true)
buf << ' ~ '
buf << datetime_picker(get_field_name_base+'[to]', fill_to, 'yyyy/MM/dd hh:mm', true)
when 'format2'
fill_from = (@prefiled_value && @prefiled_value["from"] ) ? @prefiled_value["from"] : d.strftime("%Y/%m/%d")
fill_to = (@prefiled_value && @prefiled_value["to"] ) ? @prefiled_value["to"] : d.strftime("%Y/%m/%d")
buf = datetime_picker(get_field_name_base+'[from]', fill_from, 'yyyy/MM/dd')
buf << ' ~ '
buf << datetime_picker(get_field_name_base+'[to]', fill_to, 'yyyy/MM/dd')
when 'format3'
fill_from = (@prefiled_value && @prefiled_value["from"] ) ? @prefiled_value["from"] : d.strftime("%Y/%m")
fill_to = (@prefiled_value && @prefiled_value["to"] ) ? @prefiled_value["to"] : d.strftime("%Y/%m/")
buf = datetime_picker(get_field_name_base+'[from]', fill_from, 'yyyy/MM')
buf << ' ~ '
buf << datetime_picker(get_field_name_base+'[to]', fill_to, 'yyyy/MM')
when 'format4'
fill_from = (@prefiled_value && @prefiled_value["from"] ) ? @prefiled_value["from"] : d.strftime("%Y")
fill_to = (@prefiled_value && @prefiled_value["to"] ) ? @prefiled_value["to"] : d.strftime("%Y")
buf = datetime_picker(get_field_name_base+'[from]', fill_from, 'yyyy')
buf << ' ~ '
buf << datetime_picker(get_field_name_base+'[to]', fill_to, 'yyyy')
end
# buf = date_select(get_field_name_base+'[from]',nil,@markup_options.merge(:default=>fill_from),:class=>"input-small")
# buf << ' ~ '
# buf << date_select(get_field_name_base+'[to]',nil,@markup_options.merge(:default=>fill_to),:class=>"input-small")
buf
end
else
# @prefiled_value = @attribute_value.get_date
# @prefiled_value = @attribute_value.get_date
case self.typeC['format']
when 'format1'
tmp = datetime_picker(get_field_name_base, (@prefiled_value ? @prefiled_value : d.strftime("%Y/%m/%d %H:%M")), 'yyyy/MM/dd hh:mm', true)
when 'format2'
tmp = datetime_picker(get_field_name_base, (@prefiled_value ? @prefiled_value : d.strftime("%Y/%m/%d")), 'yyyy/MM/dd')
when 'format3'
tmp = datetime_picker(get_field_name_base, (@prefiled_value ? @prefiled_value : d.strftime("%Y/%m")), 'yyyy/MM')
when 'format4'
tmp = datetime_picker(get_field_name_base, (@prefiled_value ? @prefiled_value : d.strftime("%Y")), 'yyyy')
end
control_group_wrapper{tmp}
# control_group_wrapper{date_select(get_field_name_base,nil,@markup_options.merge(:default=>@prefiled_value),:class=>"input-small")}
end
end
def property_datetime_picker(object_name, value, format, time=false)
content_tag :div, :class => "input-append datetimepick", "data-date-format"=>format, "data-picktime"=>"#{time}" do
concat text_field_tag(object_name, value, :placeholder=>format)
concat (content_tag :span, :class => 'add-on clearDate' do
content_tag :i, nil, :class => 'icons-cross-3'
end)
concat (content_tag :span, :class => 'add-on iconbtn' do
content_tag :i, nil, 'data-time-icon' => 'icons-clock', 'data-date-icon' => 'icons-calendar', :class=>"icons-calendar"
end)
end
end
def render_date_durnation #Need re-write low priority
end
def render_radio_button
@prefiled_value ||=[]
control_group_wrapper do
self.typeE[:option_list].collect do |key,value|
label_tag("#{get_basic_field_name_org}_#{self.id}_#{key}",radio_button_tag(get_field_name_base, key , (@prefiled_value.include?(key) ? true : false), {:required=>@require,:id=>"#{get_basic_field_name_org}_#{self.id}_#{key}"})+value[I18n.locale.to_s],@markup_options.merge(:class=>"radio inline"))
end.join.html_safe
end
end
def render_property_preferred_session
@prefiled_value ||=[]
@prefiled_value = Array(@prefiled_value)
control_group_wrapper do
@member.summary_chioices.map.with_index do |value,key|
key = key.to_s
label_tag("#{get_basic_field_name_org}_#{self.id}_#{key}",radio_button_tag(get_field_name_base, key , ((@prefiled_value.include?(key) || @prefiled_value.include?(key.to_i)) ? true : false), {:required=>@require,:id=>"#{get_basic_field_name_org}_#{self.id}_#{key}"})+value,@markup_options.merge(:class=>"radio inline"))
end.join.html_safe
end if @member.enable_summary_choice
end
def render_select
prompt = @panel_setting["initial"][I18n.locale.to_s] rescue nil
@markup_options.merge!(:prompt => prompt) unless prompt.nil?
control_group_wrapper{select_tag( get_field_name_base,options_for_select(self.typeB["option_list"].collect{|p| [p[1][I18n.locale.to_s],p[0]]},@prefiled_value),@markup_options)} rescue ""
end
def render_text_area
control_group_wrapper do |key,value|
if !@prefiled_value.nil?
value = can_muti_lang_input? ? @prefiled_value[key] : @prefiled_value
else
value = nil
end
key = can_muti_lang_input? ? "#{key}" : I18n.locale
place_holder= typeD["placeholder"][key] rescue ''
name1 = can_muti_lang_input? ? (get_field_name_base + "[#{key}]") : get_field_name_base
text_area_tag(name1, value,@markup_options.merge(:placeholder=>place_holder,:class=>'ckeditor input-medium form-control'))
end
end
def render_text_field
a = control_group_wrapper do |key,value|
add_more_blank = can_add_more ? "[]" : ""
key_field = can_muti_lang_input? ? "#{key}" : I18n.locale
place_holder= typeA["placeholder"][key_field] rescue ''
name1 = can_muti_lang_input? ? ([get_field_name_base,add_more_blank,"[#{key_field}]"].join) : ([get_field_name_base,add_more_blank].join)
text_field_tag(name1, value,@markup_options.merge(:placeholder=>place_holder,:class=>'input-medium form-control'))
end
end
def date_is_range?
is_range = "false"
data = get_data
if !data.nil?
is_range = data['is_range'] if data.has_key? "is_range"
end
is_range == "true"
end
protected
def valid_locales
site = Site.first
[I18n.locale]+(site.valid_locales-[I18n.locale])
end
def lang_panel_tabbable_wrapper(add_more_params,&block)
add_more_counter = ''
if self.markup=='text_area' #or self.markup=='address'
tmp1 = valid_locales.collect do |key|
if !@prefiled_value.nil?
value = @prefiled_value[key] || @prefiled_value[key.to_s] rescue nil
else
value = nil
end
# div_class_ary = ["tab-pane" ,"fade","#{get_pairing_tab_class({})}_#{key}"]
div_class_ary = ["tab-pane" ,"fade"]
if @show_set_field && @markup=='text_area'
div_id = "ckeditor_#{get_pairing_tab_class({})}_#{key}"
else
div_id = "#{get_pairing_tab_class({})}_#{key}"
end
if can_add_more
add_more_value = add_more_params[0][:value]
add_more_counter = add_more_params[0][:counter]
value = add_more_value[key] rescue nil
div_class_ary << "add_more_item_#{add_more_counter}"
end
div_class = div_class_ary.join(" ")
div_class << (key == I18n.locale ? " active in" : '')
content_tag(:div,yield(key,value), :id=>div_id,:class=>div_class)
end# of VALID_LOCALES.collect for tabed input
tmp2 = content_tag(:div,:class => 'btn-group', :data=>{:toggle=>"buttons-radio"}) do
buff2 = valid_locales.each.collect do |key|
# link_entry = self.add_more ? "#{add_more_tab(:tab_btn,loop_counter,key)}" : "#tab"+id.to_s+"_#{key}"
if @show_set_field && @markup=='text_area'
link_entry_ary = ["#ckeditor_#{get_pairing_tab_class({})}","_#{key}"]
else
link_entry_ary = ["##{get_pairing_tab_class({})}","_#{key}"]
end
link_entry_ary << ".add_more_item_#{add_more_counter}" if can_add_more
link_entry = link_entry_ary.join
link_to(I18n.t(key),link_entry,:data=>{:toggle=>"tab"},:class=>"btn #{(key == I18n.locale ? "active" : nil)}",:for=>key)
end # of VALID_LOCALES.collect for tabs
buff2 << link_to((content_tag :i,'',:class=>'icon-edit'),"##{get_pairing_tab_class({})}_m_window", :role=>"button",:class=>'btn',:data=>{:toggle=>"modal"}) if self.markup == 'address'
buff2 << link_to((content_tag :i,'',:class=>'icon-trash'),"#",:class=>"btn remove-input") if self.add_more
buff2.join.html_safe
end # of content ul
tmp = content_tag :div,:class=> "tab-content textarea-lang" do
tmp2 << tmp1.join('').html_safe
end
else
# tmp = content_tag :div,:class=> (add_more || self.markup=='address') ? "input-append" : "tab-content" do
tmp1 =
content_tag :div,:class=> "tab-content" do
buff = valid_locales.collect do |key|
value = @prefiled_value[key] || @prefiled_value[key.to_s] rescue nil
# div_class_ary = ["tab-pane" ,"fade","#{get_pairing_tab_class({})}_#{key}"]
div_class_ary = ["tab-pane" ,"fade"]
div_id = "#{get_pairing_tab_class({})}_#{key}"
if can_add_more
add_more_value = add_more_params[0][:value]
add_more_counter = add_more_params[0][:counter]
value = add_more_value[key] rescue nil
div_class_ary << "add_more_item_#{add_more_counter}"
end
div_class = div_class_ary.join(" ")
div_class << (key == I18n.locale ? " active in" : '')
content_tag(:div,yield(key,value), :id=>div_id,:class=>div_class)
end# of VALID_LOCALES.collect for tabed input
buff.join('').html_safe
end
tmp2 = content_tag(:div,:class => 'btn-group', :data=>{:toggle=>"buttons-radio"}) do
buff2 = valid_locales.each.collect do |key|
# link_entry = self.add_more ? "#{add_more_tab(:tab_btn,loop_counter,key)}" : "#tab"+id.to_s+"_#{key}"
link_entry_ary = ["##{get_pairing_tab_class({})}","_#{key}"]
link_entry_ary << ".add_more_item_#{add_more_counter}" if can_add_more
link_entry = link_entry_ary.join
link_to(I18n.t(key),link_entry,:data=>{:toggle=>"tab"},:class=>"btn #{(key == I18n.locale ? "active" : nil)}",:for=>key)
end # of VALID_LOCALES.collect for tabs
buff2 << link_to((content_tag :i,'',:class=>'icon-edit'),"#address-field", :role=>"button",:class=>'btn',:data=>{:toggle=>"modal"}) if self.markup == 'address'
buff2 << link_to((content_tag :i,'',:class=>'icon-trash'),"#",:class=>"btn remove-input") if self.add_more
buff2.join.html_safe
end # of content ul
tmp = content_tag :div,:class=> "input-append" do
tmp1 << tmp2
end
end
end
def controls_wrapper(*add_more_params,&block)
result = Array.new
add_more_counter = ""
if can_add_more
add_more_counter = add_more_params[0][:counter]
add_more_value = add_more_params[0][:value]
end
if can_muti_lang_input?
result << lang_panel_tabbable_wrapper(add_more_params,&block)
result << gen_modal_dialog if self.markup == "address"
# result << add_more_unt if can_add_more
else #cross lang field
case can_add_more
when true
value = add_more_params[0][:value]
result << content_tag(:div,:class=>"input-append"){yield(nil,value) + link_to((content_tag :i,'',:class=>'icon-trash'),"#",:class=>"btn remove-input") }
# result << add_more_unt
else
value = @prefiled_value
result << yield(nil,value)
end
end
if self.markup == "address"
result
else
result[0]
end
end # of def controls_wrapper(&block)
def control_group_wrapper(&block)
div_class = can_muti_lang_input? ? "col-sm-#{12-@col} controls" : "col-sm-#{12-@col} controls"
# div_class = can_muti_lang_input? ? "control-group language-swich" : "control-group"
result = ""
case self.markup
when "text_field"
if can_add_more
multipleInputs =
content_tag(:div,:class=>"add-target") do
@attribute_value.add_more_counter.times.collect do |t|
controls_wrapper(:value=>(@prefiled_value[t] rescue nil),:counter=>t,&block)
end.join('').html_safe # of add_more fields
end
temp = content_tag(:div, multipleInputs + add_more_unt, :class=>'add-input')
result = form_label + content_tag(:div,temp,:class=>div_class)
# result = label + multipleInputs + add_more_unt
# result = label + 一堆的輸入框(要用 multipleInput editMore 包起來) + add_more btn + hidden_fields
else
result = form_label + content_tag(:div,controls_wrapper(&block),:class=>div_class)
end
when "address"
# address = content_tag :div,:class=>"multipleInput editMore" do
address = content_tag :div,:class=>"col-sm-#{12-@col}" do
form_label + content_tag(:div, controls_wrapper(&block), :class=>'add-input')
end # of div multipleInput editMore
result = address
else
result = form_label + content_tag(:div,controls_wrapper(&block),:class=>div_class)
end
result = result + end_block
result.html_safe
end
def add_more_unt
temp_field_name = get_basic_field_name_base + '[temp]'
add_more = content_tag :p,:class=> 'add-btn' do
content = link_to (content_tag :i,I18n.t(:add),:class=>"icon-plus"),"#","data-roles"=>"role_a",:class=>"trigger #{can_muti_lang_input? ? 'textLengInput' : 'textInput' } btn btn-small btn-primary"
content << hidden_field_tag("#{temp_field_name}[count]",@attribute_value.add_more_counter ,:class=>"list_count", :id=>nil)
content << hidden_field_tag("#{temp_field_name}[count]",get_basic_field_name_base,:class=>"field_name", :id=>nil)
content
end # of div
# add_more = content_tag :div,:class=> 'controls' do
# content_tag :span,:class=> 'help-block' do
# content = link_to (content_tag :i,I18n.t(:add),:class=>"icon-plus-sign"),"#",:class=>'addinput'
# content << hidden_field_tag("#{temp_field_name}[count]",@attribute_value.add_more_counter ,:class=>"list_count")
# content << hidden_field_tag("#{temp_field_name}[count]",get_basic_field_name_base,:class=>"field_name")
# content
# end # of span
# end # of div
end
def end_block
if @new_attribute
hidden_field_tag(get_basic_field_name_base+"[#{get_basic_field_name}_id]",id,:for=>"field_#{@index}", :id=>nil)
else
hidden_field_tag(get_basic_field_name_base+"[id]",@attribute_value.id,:for=>"field_#{@index}", :id=>nil)
end
end
def add_more_tab(mode,counter,key)
case mode
when :input_field
get_pairing_tab_class(:suffix=>['','tab'+counter.to_s,key].join('-'))
when :tab_btn
".#{get_pairing_tab_class(:suffix=>['','tab'+counter.to_s,key].join('-'))}"
end
end
def get_pairing_tab_class(opts)
prefix = opts[:prefix]
suffix = opts[:suffix]
str = get_basic_field_name_base.gsub("[","_").gsub("]",'')
str = prefix.nil? ? str : prefix+ str
suffix.nil? ? str : str + suffix
end
def get_basic_field_name_org
"p_hire_field_values"
end
def get_basic_field_name
"p_hire_field"
end
def get_basic_field_name_base
"#{get_basic_field_name_org}[#{@index}]"
end
def get_field_name_base
get_basic_field_name_base + "[value]"
end
def form_label
if self.markup == "text_area"
plc = typeD["placeholder"][I18n.locale].to_s.blank? ? '' : "(#{typeD["placeholder"][I18n.locale]})"
"<span style='margin-right: 0.5em;'>"+
label_tag(key,(!@require.blank? ? '*'+title : title),:class=>"col-sm-#{@col} control-label muted",:style =>'display: contents;')+
tag(:br)+"#{plc}</span>"
else
label_tag(key,(!@require.blank? ? '*'+title : title),:class=>"col-sm-#{@col} control-label muted")
end
end
def can_muti_lang_input?
if self.markup == "address"
return true
else
$property_list[:markups][markup]["muti_lang_input_supprt"] and !(get_data["cross_lang"] == "true")
end
end
def can_add_more
if self.markup == "address"
return false
else
add_more
end
end
def gen_modal_dialog
render_anywhere("shared/attribute_field/address_modal_dialog",{
:field_name=>title,
:html_id=>"address-field",
:btn_class => "#{get_pairing_tab_class({})}",
:field_name_basic => get_basic_field_name_base
}
)
end
def show_set_field(field_sets,key_field,key_index,field,markup='text_field')
@show_set_field = true
def self.can_muti_lang_input?
true
end
def self.can_add_more
false
end
@markup = markup
def self.markup
@markup
end
def self.add_more
false
end
@new_attribute = false
@key_index = key_index
def self.key
@key_index
end
def self.form_label
''
end
def self.end_block
unless @attribute_value.new_record?
hidden_field_tag("property[#{@key_field}][#{@key_index}]"+"[id]",
@attribute_value.id,:for=>"field_#{@key_index}", :id=>nil)
else
""
end
end
@key_field = key_field
@field = field
def self.get_basic_field_name_base
"property[#{@key_field}][#{@key_index}][#{@field}]"
end
def self.get_field_name_base
"property[#{@key_field}][#{@key_index}][#{@field}]"
end
@attribute_value = field_sets
@prefiled_value = field_sets[field]
a = control_group_wrapper do |key,value|
add_more_blank = ""
if markup=='text_field'
if key_field == 'property_email_sets'
inside = text_field_tag([get_field_name_base,"[#{key}]"].join,value,:class=>'input-medium form-control')
else
inside = text_field_tag([get_field_name_base,"[#{key}]"].join,value)
end
else
inside = cktext_area("property[#{@key_field}][#{@key_index}][#{@field}]","#{key}",value:value)
end
inside
end
@key_field = nil
@key_index = nil
@field = nil
@show_set_field = nil
return a.html_safe
end
end

View File

@ -0,0 +1,113 @@
module Admin::PHireFieldValuesHelper
def show_property_type_panel(attribute_field,type)
markup = attribute_field.markup
$property_list[:markups][markup]["panel"] == type ? type : [type,'hide'].join(" ")
end
def show_west_calender(from_to=nil)
case from_to
when :to
date = get_date(:to)
when :from
date = get_date(:from)
when nil
date = get_date
end
# case self.member_profile_field["typeC"]["format"]
# when 'format1' # Y/M/D h:m
# date.strftime("%Y/%m/%d %H:%M")
# when 'format2' # Y/M/D
# date.strftime("%Y/%m/%d")
# when 'format3' # Y/M
# date.strftime("%Y/%m")
# when 'format4' # Y
# date.strftime("%Y")
# end # of case west cal format
end
def show_minguo_calendar(from_to=nil)
get_minguo
case from_to
when :to
date = get_date(:to)
when :from
date = get_date(:from)
when nil
date = get_date
end
@date = date.split('/')
date_year = @date[0].to_i
year_str = ""
unless date_year == 1912
m_year = (date_year - 1912).abs.to_s + I18n.t("date.minguo_calendar.year")
year_str = minguo_format_year(m_year)
end
get_minguo_year(from_to) + minguo_m_y_d_time(from_to)
end
def get_minguo_year(from_to=nil)
case from_to
when :to
date = get_date(:to)
when :from
date = get_date(:from)
when nil
date = get_date
end
@date = date.split('/')
date_year = @date[0].to_i
m_year = (date_year - 1911).abs
year_end = I18n.t("date.minguo_calendar.year")
case
when date_year <1912
I18n.t("date.minguo_calendar.before") + (m_year+1).to_s + year_end
when date_year ==1912
I18n.t("date.minguo_calendar.first_year")
when date_year >1912
I18n.t("date.minguo_calendar.after")+ (m_year).to_s + year_end
end # of case tw_calendar year
end
def minguo_m_y_d_time(from_to=nil)
case from_to
when :to
date = get_date(:to)
when :from
date = get_date(:from)
when nil
date = get_date
end
@date = date.split('/')
case self.p_hire_field["typeC"]["format"]
when 'format1' # Y/M/D h:m
"/#{@date[1]}/#{@date[2]}"
when 'format2' # Y/M/D
"/#{@date[1]}/#{@date[2]}"
when 'format3' # Y/M
"/#{@date[1]}#{I18n.t("date.minguo_calendar.month")}"\
when 'format4' # Y
''
end # of case
end
def get_date_by_format(from_to = nil)
case I18n.locale
when :zh_tw
case
when self.p_hire_field["typeC"]["calendar"] == "west_calendar"
show_west_calender(from_to)
when self.p_hire_field["typeC"]["calendar"] == "tw_calendar"
show_minguo_calendar(from_to)
end #case self.p_hire_field["typeC"]["calendar"]
when :en
show_west_calender(from_to)
end
end
end

View File

@ -1,6 +1,7 @@
module Admin::PropertyHiresHelper
def check_for_availability(stime, etime, pid, interval=nil, recurring_end_date=nil)
data = File.open(File.join(File.dirname(__FILE__), '../../../config', 'list.yml')).read
$property_list = YAML::load(ERB.new(data).result(binding)).symbolize_keys
def check_for_availability(stime, etime, pid, interval=nil, recurring_end_date=nil, time_setting_id=nil)
property = Property.find(pid)
return {"success" => false, "msg" => I18n.t("property_hire.values_are_not_ok",:default=>"Values are not ok.")} if property.nil? || stime.blank? || etime.blank?
timezone = (params[:timezone] rescue nil)
@ -39,9 +40,9 @@ module Admin::PropertyHiresHelper
return {"success" => false, "msg" => I18n.t("property_hire.starting_time_cannot_be_greater_than_ending_time")}
end
end
available_flag = property.is_available_for_hire?(stime, etime, interval, recurring_end_date)
available_flag = property.is_available_for_hire?(stime, etime, interval, recurring_end_date, time_setting_id)
if available_flag
if property.not_yet_hired?(stime, etime, interval, recurring_end_date,params[:phire_id])
if property.not_yet_hired?(stime, etime, interval, recurring_end_date,params[:phire_id], time_setting_id)
data = {"success" => true}
else
I18n.with_locale(params[:locale]) do
@ -62,6 +63,25 @@ module Admin::PropertyHiresHelper
end
return data
end
def render_custom_text_field(f,field_name,type)
text = "<div>
<div class=\"input-append\">
<div class=\"tab-content\">"
@site_in_use_locales.each_with_index do |locale,i|
text += "<div class=\"tab-pane fade #{'active in' if i == 0}\" id=\"property_#{field_name}_#{type}_#{locale}\">
#{f.text_field_tag("#{f.object_name}[#{field_name}][#{type}][#{locale}]", f.object.custom_text(field_name,type,locale))}
</div>"
end
text += "<div class=\"btn-group\" data-toggle=\"buttons-radio\">"
@site_in_use_locales.each_with_index do |locale,i|
text += "<a class=\"btn #{'active' if i == 0}\" data-toggle=\"tab\" href=\"#property_#{field_name}_#{type}_#{locale}\" aria-expanded=\"true\">#{t(locale)}</a>"
end
text += "</div>
</div>
</div>
</div>"
text.html_safe
end
module HireMethod
extend ActionView::Helpers::UrlHelper
extend ActionView::Helpers::TagHelper

View File

@ -12,6 +12,7 @@ class PHire
field :hiring_person_name
field :reason_for_hire
field :note_for_hire
field :property_day_setting_id
field :passed, type: Boolean, default: false
field :recurring, type: Boolean, :default => false
field :recurring_end_date, type: DateTime
@ -26,7 +27,8 @@ class PHire
field :contact_person_Email
field :contact_person_department
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 as_json(options = {})
{
:id => self.id.to_s,
@ -38,7 +40,8 @@ class PHire
:end => self.end_time.to_json.gsub('"',''),
:allDay => (self.end_time - self.start_time >= 1),
:color => (self.passed ? "#3788d8" : "#FC4040"),
:error_message => (self.passed ? nil : "Not approved")
:error_message => (self.passed ? nil : "Not approved"),
:s_id=>self.property_day_setting_id.to_s
}
end
@ -88,7 +91,7 @@ class PHire
next if !((startt..endt) & (@start_date..@end_date)).blank?
end
if @start_date < re.recurring_end_date
@recurring << {:id => re.id.to_s, :hiring_person_name => re.hirer_name ,:title=>re.reason_for_hire, :note=>re.reason_for_hire, :start=>@start_date, :end => @end_date, :allDay => (re.end_time - re.start_time >= 1), :recurring => re.recurring, :color => (re.passed ? "#3788d8" : "#FC4040"), :error_message => (re.passed ? nil : "Not approved")}
@recurring << {:id => re.id.to_s, :hiring_person_name => re.hirer_name ,:title=>re.reason_for_hire, :note=>re.reason_for_hire, :start=>@start_date.to_json.gsub('"',''), :end => @end_date.to_json.gsub('"',''), :allDay => (re.end_time - re.start_time >= 1), :recurring => re.recurring, :color => (re.passed ? "#3788d8" : "#FC4040"), :error_message => (re.passed ? nil : "Not approved"),:s_id=>re.property_day_setting_id.to_s}
end
end
when "month"
@ -106,7 +109,7 @@ class PHire
next if !((startt..endt) & (sd..ed)).blank?
end
if sd < re.recurring_end_date
@recurring << {:id => re.id.to_s, :title=>re.reason_for_hire, :note=>re.reason_for_hire, :start=>sd, :end => ed, :allDay => false, :recurring => re.recurring, :color => "#FC4040"}
@recurring << {:id => re.id.to_s, :title=>re.reason_for_hire, :note=>re.reason_for_hire, :start=>sd.to_json.gsub('"',''), :end => ed.to_json.gsub('"',''), :allDay => false, :recurring => re.recurring, :color => "#FC4040"}
end
# end
end

161
app/models/p_hire_field.rb Normal file
View File

@ -0,0 +1,161 @@
class PHireField
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::Attributes::Dynamic
include ::AttributeFieldsHelper
include ::Admin::PHireFieldHelper
field :key, type: String
field :af_count
field :title, type: String, localize: true
field :markup, default: "text_field"
field :option_list, type: Hash,default: {}
field :markup_options, type: Hash
field :built_in, type: Boolean, default: false
field :disabled, type: Boolean, default: false
field :to_delete, type: Boolean, default: false
field :to_require,type: Boolean, default: true
field :typeA, type: Hash, default: {cross_lang: false}
field :typeB, type: Hash, default: {}
field :typeC, type: Hash, default: {calendar: "west_calendar", format: "format3"}
field :typeD, type: Hash, default: {cross_lang: false}
field :typeE, type: Hash, default: {}
field :typeF, type: Hash, default: {}
belongs_to :property
has_many :p_hire_field_values, autosave: true, dependent: :destroy
accepts_nested_attributes_for :p_hire_field_values, :allow_destroy => true
before_save :check_option_list
def markup_value
get_data["option_list"]
end
def add_more
(get_data["add_more"] == "true" ? true : false) rescue false
end
def locale
get_data["cross_lang"] == "true" ? false : true
end
def self_defined_markup_options?
(self.property.method(self[:key].pluralize.to_sym) && self.property.method(self[:key].pluralize+"_for_"+markup)) rescue false
end
def option_list
if self_defined_markup_options?
#Class need to have corresponding field and value agent
# Ex: For "status" the class must have field called "statuses" for the relation and "statuses_for_select" for the select function
method = self.property.method(self[:key].pluralize+"_for_"+markup)
return (method.call rescue {})
elsif self[:option_list].nil? || (self[:option_list].empty?)
return {}
else
return self[:option_list]
end
end
def markup_options=(var)
self[:markup_options] = (eval(var) rescue {})
end
def markup_options
if self[:markup_options].nil?
return {}
else
Hash[self[:markup_options].map{|key,val|[key.to_sym,val]}] rescue {}
end
end
def panel
panel = $property_list[:markups][self[:markup]]["panel"]
end
def get_data
self[panel]
end
def typeA=(var)
check_add_more_convert(var)
check_cross_lang_convert(var,"typeA")
self["typeA"] = var
end
def typeD=(var)
check_cross_lang_convert(var,"typeD")
self["typeD"] = var
end
def is_built_in?
self.built_in
end
def is_disabled?
self.disabled
end
def self.add_p_hire_field(property,property_param, p_hire_field_id=nil,field_status)
@field_name = 'property'
if field_status.eql?(true)
@p_hire_field_counter = property.p_hire_fields.count rescue nil
@p_hire_field = self.find(p_hire_field_id) rescue nil
old_key = @p_hire_field.key
@p_hire_field.update(property_param)
@p_hire_field.save
attribute_values = @p_hire_field.p_hire_field_values
if attribute_values.count > 0
attribute_values.each do |av|
av.key = property_param["key"]
av.save
end
end
@p_hire_field[:af_count] = @p_hire_field_counter
else
@p_hire_field_counter = property.p_hire_fields.count rescue nil
@p_hire_field = property.p_hire_fields.build(property_param) rescue nil
@p_hire_field.save
@p_hire_field[:af_count] = @p_hire_field_counter
end
return @p_hire_field
end
protected
def check_cross_lang_convert(var,field)
if self[field]["cross_lang"] != var["cross_lang"]
case var["cross_lang"]
when "true" #from no-add_more to add_more
cross_lang_convert(:to_cross_lang)
else #from add_more to no-add_more
cross_lang_convert(:to_no_cross_lang)
end # of case
end # of if
end
def check_add_more_convert(var)
if self["typeA"]["add_more"] != var["add_more"]
case var["add_more"]
when "true" #from no-add_more to add_more
add_more_convert(:to_add_more)
else #from add_more to no-add_more
add_more_convert(:to_no_add_more)
end # of case
end # of if
end
def cross_lang_convert(opt)
end
def check_option_list
self[:option_list] = self[panel]["option_list"] rescue nil
end
def add_more_convert(opt)
end
end

View File

@ -0,0 +1,229 @@
class PHireFieldValue
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::Attributes::Dynamic
include ::AttributeValuesHelper
include ::Admin::PHireFieldValuesHelper
field :key, type: String
belongs_to :p_hire_field
belongs_to :p_hire
before_save :check_key
before_save :data_proc
def add_more_counter
index_max = self["val"].count rescue 0
index_max == 0 ? 1 : index_max
end
def value(index = nil)
site = Site.first
result = case self.p_hire_field.markup
when 'text_field','text_area'
if self.p_hire_field.add_more and (self.p_hire_field.markup == "text_field")
index.nil? ? self["val"] : self["val"][index]
else
self.p_hire_field.get_data["cross_lang"] =="true" ? self["val"] : Hash[site.valid_locales.collect{|lang| [lang,self[lang.to_sym]]}]
end
when 'select','radio_button','address'
self["val"]
when 'date'
if !self["val"].blank? and !self["val"]['(1i)'].blank?
"#{self["val"]['(1i)']}/#{self["val"]['(2i)']}/#{self["val"]['(3i)']}"
else
self["val"]
end
when 'checkbox'
self["val"]
end #end of case self.p_hire_field.markup
end
def value=(value)
#save everything to temp_data waiting for futher process
self[:temp_data] = value
end
def get_field_value
p_hire_field = self.p_hire_field
if (p_hire_field.markup.eql?("text_field") || p_hire_field.markup.eql?("text_area"))
if self.value.class == String
field_value = self.value
else
field_value = self.value[I18n.locale]
end
elsif (p_hire_field.markup.eql?("select") || p_hire_field.markup.eql?("radio_button"))
field_value = p_hire_field.markup_value["#{self.value}"][I18n.locale] rescue nil
elsif p_hire_field.markup.eql?("address")
field_value = rf[:address_key][I18n.locale].map{|k,v| v}.delete_if(&:blank?).join(', ')
elsif p_hire_field.markup.eql?("date")
case p_hire_field.typeC['format']
when 'format1'
field_value = self.value.to_date.strftime("%Y/%m/%d")
when 'format2'
field_value = self.value.to_date.strftime("%Y/%m/%d")
when 'format3'
field_value = self.value.to_date.strftime("%Y/%m")
when 'format4'
field_value = self.value.to_date.strftime("%Y")
end
elsif p_hire_field.markup.eql?("checkbox")
field_value = self.value.map {|v| p_hire_field.markup_value["#{v}"][I18n.locale]}.join(', ') rescue nil
end
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
}
else
{
"key" => p_hire_field.key,
"title" => p_hire_field.title,
"value" => "",
"val" => field_value = self.value
}
end
end
def get_value_by_locale(locale,add_more_index=nil)
p_hire_field = self.p_hire_field
case p_hire_field.markup
when "text_field"
case p_hire_field.add_more
when true
if p_hire_field.locale
add_more_index.nil? ? self.value.collect{|t| t[locale.to_s]}.join(",") : self.value(add_more_index)[locale]
else
add_more_index.nil? ? self.value.join(",") : self.value(add_more_index)
end
when false
p_hire_field.locale ? self[locale.to_s] : self.value
end
when "select"
markup_values = p_hire_field.self_defined_markup_options? ? p_hire_field.markup_value : self.p_hire_field.markup_value
markup_values[self.value][locale.to_s] rescue 'NoData'
when "text_area"
p_hire_field.locale ? self[locale.to_s] : self.value
when "date"
if p_hire_field.date_is_range?
get_date_by_format(:from) + ' ~ ' + get_date_by_format(:to)
# self.value["from"] + ' ~ ' + self.value["to"]
else
get_date_by_format
# self.value
end
when "address"
self.value[locale.to_s]
when "radio_button"
markup_values = p_hire_field.markup_value
markup_values[self.value][locale.to_s]
when "checkbox"
markup_values = p_hire_field.markup_value
self.value.collect{|key| markup_values["#{key}"][I18n.locale]}.join(",")
when "date_durnation"
self.value
else
p_hire_field.locale ? self[locale.to_s] : self.value
end
end
def get_date(item = nil)
case item
when :from
# data = self[:val]["from"]
data = self.value["from"]
when :to
# data = self[:val]["to"]
data = self.value["to"]
when nil
# data = self[:val]
data = self.value
end
# Date.new(data["(1i)"].to_i,data["(2i)"].to_i,data["(3i)"].to_i) rescue nil
end
def self.put_field_values(p_hire, field_value_param, field_value_id=nil,field_value_status)
if field_value_status.eql?(true)
@p_hire_field_value = p_hire.p_hire_field_values.find(field_value_id) rescue nil
if @p_hire_field_value!=nil
@p_hire_field_value.update(field_value_param) rescue nil
@p_hire_field_value.save rescue nil
end
else
@p_hire_field_value = p_hire.p_hire_field_values.build(field_value_param) rescue nil
@p_hire_field_value.save
end
return @p_hire_field_value
end
protected
def unset_all_lang_values
VALID_LOCALES.each{|t| self.unset t}
end
def data_proc
p_hire_field = self.p_hire_field
unless self[:temp_data].nil?
case p_hire_field.markup
when "address"
self["val"] = self["temp_data"]
when 'text_field','text_area'
if p_hire_field.add_more
self["val"] = self["temp_data"]
else # if not add_more
if p_hire_field.can_muti_lang_input?
self[:temp_data].each do |key,val|
self[key] = val
end if(!p_hire_field.get_data[:cross_lang])
else
self["val"] = self[:temp_data]
end
end # of self.p_hire_field.add_more
when 'select','date','radio_button'
self["val"] = self[:temp_data]
when 'checkbox'
self["val"] = self[:temp_data].keys
end #end of case self.p_hire_field.markup
end # of self[:temp_data].nil?
self.unset('temp_data')
self.unset('temp')
end #of data_proc
def check_key
if self.p_hire_field_id.present? && self.p_hire_field.nil?
begin
self.p_hire_field = PHireField.find(self.p_hire_field_id)
rescue
nil
end
end
self.key = self.p_hire_field.key rescue nil
end
def method_missing(*field)
if field.size < 1
self[field[0]]
else
self[(field[0].to_s.delete "=")] = field[1]
end
end
end

View File

@ -4,7 +4,10 @@ class Property
include OrbitTag::Taggable
include OrbitCategory::Categorizable
include Slug
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
field :order_position, type: Integer, default: -1
field :title, as: :slug_title, :localize => true
field :property_usage, :localize => true
field :note, :localize => true
@ -22,6 +25,7 @@ class Property
# unavailibility fields
field :can_hire_before_months, type: Integer, default: 0
field :set_availability, type: Boolean, default: false
field :set_unavailibility, type: Boolean, default: false
field :start_time
field :end_time
@ -45,6 +49,19 @@ class Property
has_many :p_hires
has_many :hire_email_sets, :autosave => true, :dependent => :destroy, :inverse_of => :property
accepts_nested_attributes_for :hire_email_sets, :allow_destroy => true
has_many :p_hire_fields, :autosave => true, :dependent => :destroy
accepts_nested_attributes_for :p_hire_fields, :allow_destroy => true
has_many :property_field_sets, :autosave => true, :dependent => :destroy
accepts_nested_attributes_for :property_field_sets, :allow_destroy => true
has_many :property_day_settings, :autosave => true, :dependent => :destroy
accepts_nested_attributes_for :property_day_settings, :allow_destroy => true
has_many :property_carousel_images, :autosave => true, :dependent => :destroy
accepts_nested_attributes_for :property_carousel_images, :allow_destroy => true
has_many :property_files, :autosave => true, :dependent => :destroy
accepts_nested_attributes_for :property_files, :allow_destroy => true
has_many :property_links, :autosave => true, :dependent => :destroy
accepts_nested_attributes_for :property_links, :allow_destroy => true
scope :sort_order, ->{order_by([:order_position,:asc],[:created_at,:desc])}
WEEKDAYS = [
"Sunday",
"Monday",
@ -54,6 +71,37 @@ class Property
"Friday",
"Saturday"
]
before_create do
max_position = self.class.max(:order_position)
max_position = -1 if max_position.nil?
self.order_position = max_position + 1
end
def self.init_class_variables
setting = PropertyHireSetting.last
if setting
@@disable_content_page = setting.disable_content_page rescue false
@@disable_view_calendar_page = setting.disable_view_calendar_page rescue false
else
@@disable_content_page = false
@@disable_view_calendar_page = false
end
end
init_class_variables
def disable_content_page
@@disable_content_page
end
def disable_view_calendar_page
@@disable_view_calendar_page
end
def custom_text(field_name,type,locale=nil)
locale = locale || I18n.locale
default_text = I18n.with_locale(locale){I18n.t("property_hire.#{field_name}")}
if (self.send(field_name)[type][locale.to_s].present? rescue false)
self.send(field_name)[type][locale.to_s]
else
default_text
end
end
def render_unavailable_message
message = ""
property = self
@ -135,7 +183,7 @@ class Property
MemberProfile.find(self.owners) rescue []
end
def is_available_for_hire?(stime, etime, interval = nil, recurring_end_date = nil)
def is_available_for_hire?(stime, etime, interval = nil, recurring_end_date = nil, time_setting_id = nil)
available = false
return true if self.set_unavailibility == false
return true if self.weekdays.empty? && self.can_hire_before_months == 0
@ -194,18 +242,35 @@ class Property
end
end
def not_yet_hired?(stime, etime, interval, recurring_end_date,phire_id=nil)
def not_yet_hired?(stime, etime, interval, recurring_end_date,phire_id=nil,time_setting_id=nil)
phires = self.p_hires
stime = stime.utc
etime = etime.utc
bookings_count = phires.where(:start_time.lte => stime,:end_time.gte => stime,:recurring => false,:id.ne=>phire_id).count
bookings_count = 0
reservation_limit = 0
if time_setting_id
time_setting = PropertyDaySetting.find(time_setting_id)
etime = stime + 1.day
etime = etime.utc
reservation_limit = time_setting.reservation_limit
if reservation_limit == 0
return true
end
bookings_count = phires.where(:start_time.lte => stime,:end_time.gte => stime,:recurring => false,:id.ne=>phire_id,:property_day_setting_id=>time_setting_id).count
+ phires.where(:start_time.gte => stime,:end_time.lte => etime,:recurring => false,:id.ne=>phire_id,:property_day_setting_id=>time_setting_id).count
+phires.where(:start_time.lte => etime,:end_time.gte => etime,:recurring => false,:id.ne=>phire_id,:property_day_setting_id=>time_setting_id).count
if bookings_count < reservation_limit
bookings_count = 0
end
else
bookings_count = phires.where(:start_time.lte => stime,:end_time.gte => stime,:recurring => false,:id.ne=>phire_id).count
+ phires.where(:start_time.gte => stime,:end_time.lte => etime,:recurring => false,:id.ne=>phire_id).count
+phires.where(:start_time.lte => etime,:end_time.gte => etime,:recurring => false,:id.ne=>phire_id).count
end
available = true
if bookings_count != 0
available = false
end
puts ["phire_id",phire_id]
if available
recurring_bookings = phires.where(:recurring_end_date.gte => stime, :recurring => true,:id.ne=>phire_id)
bookings = phires.where(:recurring => false,:recurring_end_date => nil)
@ -217,9 +282,55 @@ class Property
else
d_step = 0
end
bookings = bookings.any_of({:start_time.gte => etime},{:end_time.gte => etime})
if time_setting_id
recurring_bookings = recurring_bookings.where(:property_day_setting_id=>time_setting_id)
bookings = recurring_bookings.where(:property_day_setting_id=>time_setting_id)
end
if true#d_step != 0
bookings += recurring_bookings
end
if time_setting_id
tmp = {}
stime_date = stime.strftime("%Y-%m-%d")
bookings = bookings.each_with_index do |booking,i|
if booking.wday != stime.wday
next
end
b_interval = booking.recurring_interval
b_recurring_end_date = booking.recurring_end_date ? booking.recurring_end_date.utc : nil
booking_date = booking.start_time.utc.strftime("%Y-%m-%d")
if (b_interval == 'month' || b_interval == 'week') && (booking.recurring_end_date.nil? || !booking.recurring)
b_interval = nil
end
if stime_date == booking_date
if tmp[booking_date].nil?
tmp[booking_date] = 0
end
tmp[booking_date] += 1
available = false if tmp[booking_date] > reservation_limit
end
break if available == false
if b_interval.present?
b_interval = (1).send(b_interval)
b_sdata = booking.start_time.utc
b_datas = (b_sdata..b_recurring_end_date).step(b_interval).to_a
all_stime_datas = (stime..b_recurring_end_date).step(b_interval).to_a.map{|t| t.utc.strftime("%Y-%m-%d")}
b_datas.each do |b_data|
booking_date = b_data.utc.strftime("%Y-%m-%d")
if all_stime_datas.include?(booking_date)
if tmp[booking_date].nil?
tmp[booking_date] = 0
end
tmp[booking_date] += 1
available = false if tmp[booking_date] > reservation_limit
end
break if available == false
end
end
break if available == false
end
else
bookings.each_with_index do |booking,i|
stime_tp = stime.clone
etime_tp = etime.clone
@ -248,8 +359,6 @@ class Property
b_datas = [b_sdata..b_edata]
end
while b_datas.present?
sdata = stime_tp
edata = etime_tp
available = b_datas.find{|b_range| b_range & (stime_tp..etime_tp)}.nil?
stime_tp = stime_tp + d_step
etime_tp = etime_tp + d_step
@ -263,6 +372,7 @@ class Property
end
break if available == false
end
end
end
return available
end
@ -272,5 +382,19 @@ class Property
yield(start_time, end_time)
end while (start_time += step) <= end_time
end
def carousel_image_width
(self.custom_carousel_image_width.blank? ? PropertyHireSetting.last.carousel_image_width : self.custom_carousel_image_width) rescue "75%"
end
def get_attribute_value(attribute_field, signup_id)
SeminarSignupValue.find_by(seminar_signup_field_id: attribute_field.id, seminar_signup_id: signup_id)
end
def get_attribute_values(attribute_type=nil)
@attribute_values = attribute_type.seminar_signup_values rescue nil
end
def get_value_from_field_id(field_id,attribute_type=nil)
values = get_attribute_values(attribute_type)
value = values.detect {|value| value.seminar_signup_field_id == field_id} rescue nil
value ? value : nil
end
end

View File

@ -0,0 +1,15 @@
# encoding: utf-8
class PropertyCarouselImage
include Mongoid::Document
include Mongoid::Timestamps
mount_uploader :file, AssetUploader
field :description, localize: true
belongs_to :property
def description_text
Nokogiri::HTML(self.description.to_s).css("body").text() rescue ""
end
end

View File

@ -0,0 +1,11 @@
class PropertyDaySetting
include Mongoid::Document
include Mongoid::Timestamps
field :key
field :day
field :title
field :start_time
field :end_time
field :reservation_limit, type: Integer, default: 1
belongs_to :property
end

View File

@ -0,0 +1,11 @@
class PropertyFieldSet
include Mongoid::Document
include Mongoid::Timestamps
field :field_name, type: String
field :placeholder
field :name
field :disabled, type: Boolean, default: false
field :hidden, type: Boolean, default: false
belongs_to :property
end

View File

@ -0,0 +1,12 @@
# encoding: utf-8
class PropertyFile
include Mongoid::Document
include Mongoid::Timestamps
mount_uploader :file, AssetUploader
field :description, :type => String, :default=> ""
field :title, :type => String, :default=> ""
belongs_to :property
end

View File

@ -3,7 +3,9 @@ class PropertyHireSetting
include Mongoid::Timestamps
field :auto_approve, type: Boolean, :default => false
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
def self.auto_approve_enabled?
self.first.auto_approve rescue false
end

View File

@ -0,0 +1,25 @@
# encoding: utf-8
require 'uri'
class PropertyLink
include Mongoid::Document
include Mongoid::Timestamps
field :url, :type => String, :default=> ""
field :title, :type => String, :default=> ""
before_validation :add_http
belongs_to :property
def display_title
self.title.blank? ? self.url : self.title
end
protected
def add_http
unless self.url[/^http:\/\//] || self.url[/^https:\/\//]
self.url = 'http://' + self.url
end
end
end

View File

@ -0,0 +1,135 @@
<div class="attributes default <%= attribute_field.disabled ? 'disabled' : ''%>">
<%
attribute_field.af_count ? @af_counter = attribute_field_counter + attribute_field.af_count : @af_counter = attribute_field_counter
%>
<div class="attributes-header clearfix">
<div class="toggle-control" style="float: right;">
<div class="togglebox <%= attribute_field.disabled ? 'disabled' : ''%>">
<%= hidden_field "#{@field_name}[p_hire_fields][#{@af_counter}]","disabled",:value=>attribute_field.disabled,:class=>"toggle-check", :data=>{:deploy=>"right"} %>
<label><b></b></label>
</div>
</div>
<a class="btn btn-mini pull-right btn-danger delete" href="#"><i class="icon-trash"></i> <%= t(:delete_)%></a>
<%= hidden_field "#{@field_name}[p_hire_fields][#{@af_counter}]","to_delete",:value=>false,:class=>"attribute_field_to_delete"%>
<a class="btn btn-mini pull-right btn-inverse reply hide" href="#"><i class="icons-reply"></i> Reset</a>
<h4>Field <span><%= @af_counter + 1 %></span></h4>
</div>
<div class="attributes-body">
<div class="control-group">
<label class="control-label muted" for="key_<%= @af_counter %>"><%= t(:key) %></label>
<div class="controls">
<%= text_field "#{@field_name}[p_hire_fields][#{@af_counter}]","key",:value=>attribute_field.key, :data=>{:type=>"key"} %>
</div>
</div>
<%= render :partial=>"shared/attribute_field/placeholder_block",:locals=>{:values=>attribute_field.title_translations,:class_ext=>"pull-left",:label_ext=>t(:name),:field_name=>"#{@field_name}[p_hire_fields][#{@af_counter}][title_translations]"}%>
<div class="control-group">
<label class="control-label muted" for=""><%= t('property_hire.to_require') %></label>
<div class="controls">
<label class="radio inline">
<%= radio_button("#{@field_name}[p_hire_fields][#{@af_counter}]", "to_require", "true",:checked => (attribute_field.to_require == true ? true : false), :data=>{:type=>"search_true"}) %><%= t(:yes_)%>
</label>
<label class="radio inline">
<%= radio_button("#{@field_name}[p_hire_fields][#{@af_counter}]", "to_require", "false",:checked => (attribute_field.to_require == false ? true : false), :data=>{:type=>"search_false"}) %><%= t(:no_)%>
</label>
</div>
</div>
<div class="control-group">
<label class="control-label muted" for=""><%= t(:type)%></label>
<div class="controls">
<select class="dataType" data-type="select" name=<%= "#{@field_name}[p_hire_fields][#{@af_counter}][markup]"%>>
<%$property_list[:markups].each do |key,val|%>
<% next if val["display_only"] && val["display_only"] != "p_hire_field" %>
<% if key != 'address' %>
<option value="<%= key %>" <%= attribute_field.markup == key ? 'selected="selected"' : '' %> ref="<%=val["panel"]%>"><%=t("lists.markups."+key)%></option >
<% end %>
<% end %>
</select>
</div>
</div>
</div>
<div class="field-type fade"></div>
<%= content_tag :div,:class=>"field-type default fade in #{show_property_type_panel(attribute_field,"typeA")}" do%>
<div class="control-group">
<label class="control-label muted"><%= t(:enabled_for)%></label>
<div class="controls">
<label class="checkbox inline">
<%= check_box_tag("#{@field_name}[p_hire_fields][#{@af_counter}][typeA][cross_lang]","true",attribute_field["typeA"]["cross_lang"],:data=>{:type=>"cross_lang"}) %>
<%= t(:cross_lang) %>
</label>
<label class="checkbox inline">
<%= check_box_tag("#{@field_name}[p_hire_fields][#{@af_counter}][typeA][add_more]","true",attribute_field["typeA"]["add_more"],:data=>{:type=>"add_more"}) %>
<%= t(:add_more)%>
</label>
</div>
</div>
<%= render :partial=>"shared/attribute_field/placeholder_block",:locals=>{:values=>attribute_field["typeA"]["placeholder"],:field_name=>"#{@field_name}[p_hire_fields][#{@af_counter}][typeA][placeholder]"}%>
<% end if show_property_type_panel(attribute_field,"typeA") != 'typeA hide' %>
<%= content_tag :div,:class=>"field-type default fade in #{show_property_type_panel(attribute_field,"typeB")}" do %>
<%= render :partial=>"shared/attribute_field/placeholder_block",:locals=>{:label_ext=>t(:initial),:values=>attribute_field["typeB"]["initial"],:field_name=>"#{@field_name}[p_hire_fields][#{@af_counter}][typeB][initial]"}%>
<% if attribute_field.self_defined_markup_options?%>
<%= render :partial=>"shared/attribute_field/list_block",:locals=>{:values=>attribute_field["option_list"],:field_name=> "#{@field_name}[p_hire_fields][#{@af_counter}][attribute][property][statuses]"} %>
<%else #normal list%>
<%= render :partial=>"shared/attribute_field/list_block",:locals=>{:values=>attribute_field["option_list"],:field_name=> "#{@field_name}[p_hire_fields][#{@af_counter}][typeB][option_list]"} %>
<% end #of self_defined_markup_options?%>
<% end if show_property_type_panel(attribute_field,"typeB") != 'typeB hide' %>
<%= content_tag :div,:class=>"field-type default fade in #{show_property_type_panel(attribute_field,"typeC")}" do %>
<div class="control-group">
<label class="control-label"><%= t("date.format")%></label>
<div class="controls">
<%= select "#{@field_name}[p_hire_fields][#{@af_counter}][typeC]","format",Admin::AttributeValuesViewHelper::OPT,:class=>"dataType",:selected=>attribute_field["typeC"]["format"] %>
</div>
</div>
<div class="control-group">
<label class="control-label"><%= t("date.range")%></label>
<div class="controls">
<label class="radio inline">
<%= radio_button("#{@field_name}[p_hire_fields][#{@af_counter}][typeC]", "is_range", "false",:checked => (!attribute_field.date_is_range? ? true : false)) %><%= t(:yes_)%>
</label>
<label class="radio inline">
<%= radio_button("#{@field_name}[p_hire_fields][#{@af_counter}][typeC]", "is_range", "true",:checked => (attribute_field.date_is_range? ? true : false)) %><%= t(:no_)%>
</label>
</div>
</div>
<div class="control-group">
<label class="control-label"><%= t("date.calendar")%></label>
<div class="controls">
<label class="radio inline">
<%= radio_button("#{@field_name}[p_hire_fields][#{@af_counter}][typeC]", "calendar", "west_calendar",:checked =>(attribute_field["typeC"]["calendar"]== "west_calendar" ? true : false)) %><%= t("date.west_calendar")%>
</label>
<label class="radio inline">
<%= radio_button("#{@field_name}[p_hire_fields][#{@af_counter}][typeC]", "calendar", "tw_calendar",:checked =>(attribute_field["typeC"]["calendar"]== "tw_calendar" ? true : false)) %><%= t("date.tw_calendar")%>
</label>
</div>
</div>
<% end if show_property_type_panel(attribute_field,"typeC") != 'typeC hide' %>
<%= content_tag :div,:class=>"field-type default fade in #{show_property_type_panel(attribute_field,"typeD")}" do%>
<div class="control-group">
<label class="control-label"><%= t(:enabled_for)%></label>
<div class="controls">
<label class="checkbox inline">
<%= check_box_tag("#{@field_name}[p_hire_fields][#{@af_counter}][typeD][cross_lang]","true",attribute_field["typeD"]["cross_lang"]) %>
<%= t(:cross_lang)%>
</label>
</div>
</div>
<%= render :partial=>"shared/attribute_field/placeholder_block",:locals=>{:field_name=>"#{@field_name}[p_hire_fields][#{@af_counter}][typeD][placeholder]",:values=>attribute_field["typeD"]["placeholder"]} %>
<% end if show_property_type_panel(attribute_field,"typeD") != 'typeD hide' %>
<%= content_tag :div,:class=>"field-type default fade in #{show_property_type_panel(attribute_field,"typeE")}" do%>
<%= render :partial=>"shared/attribute_field/list_block",:locals=>{:field_name=>"#{@field_name}[p_hire_fields][#{@af_counter}][typeE][option_list]",:values=>attribute_field["typeE"]["option_list"]}%>
<% end if show_property_type_panel(attribute_field,"typeE") != 'typeE hide' %>
<%= content_tag :div,:class=>"field-type default fade in #{show_property_type_panel(attribute_field,"typeF")}" do%>
<%= render :partial=>"shared/attribute_field/hint_block",:locals=>{:values=>attribute_field["typeF"]["placeholder"],:field_name=>"#{@field_name}[p_hire_fields][#{@af_counter}][typeF][placeholder]"}%>
<% end if show_property_type_panel(attribute_field,"typeF") != 'typeF hide' %>
<%= hidden_field "#{@field_name}[p_hire_fields][#{@af_counter}]","id",:value=>attribute_field.id%>
</div>

View File

@ -27,11 +27,45 @@
.remove_btn{
cursor: pointer;
}
.card-header a{
text-align: center;
display: block;
}
.card-header:hover{
background: aquamarine;
}
.card-header:hover a{
text-decoration: none;
}
.add_weekday_setting{
text-align: center;
align-self: center;
}
.time_setting_form, .image_group{
border: 0.2em solid #333;
padding-top: 0;
}
.add-on.iconbtn{
display: none;
}
.time_setting_form:last-child, .image_group:last-child {
margin-bottom: 1em;
}
.card-header {
padding: 0;
}
.card-header a {
padding: .75rem 1.25rem;
}
.card-header h4 {
margin: 0;
}
</style>
<% content_for :page_specific_css do %>
<%= stylesheet_link_tag "lib/main-forms" %>
<%= stylesheet_link_tag "lib/fileupload" %>
<%= stylesheet_link_tag "lib/main-list" %>
<%= stylesheet_link_tag "admin/card" %>
<% end %>
<% content_for :page_specific_javascript do %>
<%= javascript_include_tag "lib/bootstrap-fileupload" %>
@ -48,11 +82,14 @@
<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="#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>
<li><a href="#unavailability" data-toggle="tab"><%= t('property_hire.unavailability')%></a></li>
<li><a href="#carousel_image_upload" data-toggle="tab" title="<%= t('property_hire.carousel_image_title') %>"><%= t('property_hire.carousel_image') %></a></li>
<li><a href="#unavailability" data-toggle="tab"><%= t('property_hire.unavailable_time')%></a></li>
<li><a href="#available_time" data-toggle="tab"><%= t('property_hire.available_time')%></a></li>
<li><a href="#auto_send_email_set" data-toggle="tab"><%= t('property_hire.auto_send_email_set') %></a></li>
<li><a href="#settings" data-toggle="tab"><%= t('property_hire.settings') %></a></li>
<li><a href="#settings" data-toggle="tab"><%= t('property_hire.reservation_fields') %></a></li>
</ul>
<!-- Module -->
<div class="tab-content module-area">
@ -132,6 +169,10 @@
</div>
</div>
</div>
<!-- files_links -->
<div class="tab-pane fade" id="files_links">
<%= render :partial => "form_file_link", :locals=>{:f=>f} %>
</div>
<!-- tags -->
<div class="tab-pane fade" id="tag">
<div class="control-group">
@ -168,6 +209,53 @@
</div>
</div>
</div>
<!-- display img src -->
<div class="control-group">
<%= f.label :display_img, t("property_hire.display_img"), :class => "control-label muted" %>
<div class="controls">
<%= f.check_box :display_img %>
</div>
</div>
<!-- Image display setting -->
<% image_display_class_relation = {"full_width"=>"full-size-img","up_left_corner"=>"pull-left","up_right_corner"=>"pull-right"} %>
<div class="control-group <%='hide' if !f.object.display_img %>" id="image_display_setting">
<%= f.label :image_display_class, t("property_hire.cover_image_display_setting"), :class => "control-label muted" %>
<div class="controls">
<% image_display_class_relation.each.with_index do |(key,value),i| %>
<label>
<%= radio_button_tag "#{f.object_name}[image_display_class]", value , (f.object.image_display_class == value) %>
<%= t("property_hire.#{key}") %>
</label>
<% end %>
</div>
</div>
</div>
<!-- Images Module -->
<div class="tab-pane fade" id="carousel_image_upload">
<div class="control-group">
<label class="control-label muted" for="carousel_image_width"><%= t("property_hire.carousel_image_width") %></label>
<div class="controls">
<%= f.text_field :custom_carousel_image_width, :placeholder => t("property_hire.custom_carousel_image_width_hint") %>
</div>
</div>
<% if f.object && !f.object.property_carousel_images.blank? %>
<div class="exist">
<% f.object.property_carousel_images.each_with_index do |property_carousel_image, i| %>
<%= f.fields_for :property_carousel_images, property_carousel_image do |f| %>
<%= render :partial => 'form_image', :object => property_carousel_image, :locals => {:f => f, :i => i} %>
<% end %>
<% end %>
<hr>
</div>
<% end %>
<!-- Add -->
<div class="add-target">
</div>
<p class="add-btn controls">
<%= hidden_field_tag 'property_carousel_image_count', f.object.property_carousel_images.count %>
<a id="add_carousel_image" class="trigger btn btn-small btn-primary"><i class="icons-plus"></i> <%= t(:add) %></a>
</p>
</div>
<!-- Email Set Module -->
<div class="tab-pane fade" id="auto_send_email_set" style="padding: 1.2em;">
@ -307,27 +395,85 @@
<% end %>
</div>
</div>
<!-- available_time -->
<div class="tab-pane fade" id="available_time">
<div class="control-group">
<%= f.label :set_availability, t("property_hire.set_availability"), :class => "control-label muted" %>
<div class="controls">
<%= f.check_box :set_availability %>
</div>
</div>
<% if @property.set_availability %>
<div id="set_availability_div">
<% else %>
<div id="set_availability_div" style="display: none;">
<% end %>
<ul>
<% all_day_settings = f.object.property_day_settings.asc(:key).group_by(&:day) %>
<% setting_count = 0 %>
<% Property::WEEKDAYS.each_with_index do |weekday,i| %>
<li class="card">
<div class="card-header">
<h4>
<a data-toggle="collapse" href="#<%=weekday%>_setting" role="button" aria-expanded="false" aria-controls="<%=weekday%>_setting"><% trans = t("property_hire.#{weekday}") %><%= (trans.class == ActiveSupport::SafeBuffer ? weekday : trans) %></a>
</h4>
</div>
<div class="collapse" id="<%=weekday%>_setting">
<div class="card card-body">
<div id="add_target_weekday_<%=i%>">
<% if all_day_settings[i.to_s] %>
<% all_day_settings[i.to_s].each_with_index do |setting,j| %>
<%= f.fields_for :property_day_settings, setting,:child_index => setting_count do |f| %>
<%= render :partial => "time_form", :locals=>{:key=>j,:day=>i,:f=>f} %>
<% setting_count += 1 %>
<% end %>
<% end %>
<% end %>
</div>
<a class="btn btn-primary add_weekday_setting" data-target="#add_target_weekday_<%=i%>" data-count="<%= all_day_settings[i] ? all_day_settings[i].count : 0 %>" data-day="<%=i%>"><%=t(:add)%></a>
</div>
</div>
</li>
<% end %>
</ul>
</div>
</div>
<div class="tab-pane fade" id="settings">
<% 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| %>
<div class="control-group">
<label class="control-label muted"><%= t("property_hire.#{field_name}") %></label>
<div class="controls">
<label for="act_enabled_name" class="checkbox inline">
<%= hidden_field_tag "property[#{field_name}][enable]", "0" %>
<%= f.check_box_tag "property[#{field_name}][enable]", "1" , (@property[field_name]["enable"] == "1" rescue false) %>
Enable
</label>
</div>
<div class="controls required">
<label class="radio inline"><%= t("property_hire.required") %></label>
<%= f.fields_for field_name do |sub_f|%>
<label class="radio inline"><%= sub_f.radio_button "required", "true", checked: ((@property[field_name]["required"] rescue "false") == "true") %><%= t(:yes_) %></label>
<label class="radio inline"><%= sub_f.radio_button "required", "false", checked: ((@property[field_name]["required"] rescue "false") == "false") %><%= t(:no_) %></label>
<div style="padding: 1.2em;">
<table style="margin: 0;">
<thead>
<th><%= t('property_hire.field_name') %></th>
<th><%= t('property_hire.name') %></th>
<th><%= t('property_hire.placeholder') %></th>
<th><%= t('property_hire.disable') %></th>
<th><%= t('property_hire.required') %></th>
</thead>
<tbody>
<% fields_name.each do |field_name| %>
<tr>
<td>
<%= t("property_hire.#{field_name}") %>
</td>
<td>
<%= render_custom_text_field(f,field_name,"name") %>
</td>
<td>
<%= render_custom_text_field(f,field_name,"placeholder") %>
</td>
<td>
<input type="hidden" name='<%= "#{f.object_name}[#{field_name}][enable]" %>' value="1">
<%= check_box_tag("#{f.object_name}[#{field_name}][enable]", "0" , (f.object.send(field_name)["enable"] == "0" rescue false)) %>
</td>
<td>
<input type="hidden" name='<%= "#{f.object_name}[#{field_name}][required]" %>' value="false">
<%= check_box_tag("#{f.object_name}[#{field_name}][required]", "true" , (f.object.send(field_name)["required"] == "true" rescue false)) %>
</td>
</tr>
<% end %>
</div>
</div>
<% end %>
</tbody>
</table>
</div>
<hr style="border-color: black; ">
<div class="control-group">
<% field_name = "enable_notes_selector" %>
@ -431,7 +577,7 @@
<label class="control-label muted"><%= t("property_hire.property_usage") %></label>
<div class="controls">
<%= f.fields_for :property_usage_translations do |f| %>
<%= f.text_area locale, class: "input-block-level", placeholder: t("property_hire.property_usage"), value: (@property.property_usage_translations[locale] rescue nil) %>
<%= f.text_area locale, class: "ckeditor input-block-level", placeholder: t("property_hire.property_usage"), value: (@property.property_usage_translations[locale] rescue nil) %>
<% end %>
</div>
</div>
@ -439,7 +585,7 @@
<label class="control-label muted"><%= t("property_hire.note") %></label>
<div class="controls">
<%= f.fields_for :note_translations do |f| %>
<%= f.text_area locale, class: "input-block-level", placeholder: t("property_hire.note"), value: (@property.note_translations[locale] rescue nil) %>
<%= f.text_area locale, class: "ckeditor input-block-level", placeholder: t("property_hire.note"), value: (@property.note_translations[locale] rescue nil) %>
<% end %>
</div>
</div>
@ -456,6 +602,7 @@
<%= link_to t('cancel'), admin_property_hires_path, :class=>"btn" %>
</div>
<script type="text/javascript">
$("#bulletin_display_img").click(function(){$("#image_display_setting").toggleClass("hide")})
$(document).ready(function(){
if($("[type=checkbox][name='property[enable_notes_selector]']:checked").length == 0){
$("#selector_block").css("display","none");
@ -470,7 +617,13 @@
$("#set_unavailibility_div").hide();
}
})
$("#property_set_availability").on("click",function(){
if($(this).is(":checked")){
$("#set_availability_div").show();
}else{
$("#set_availability_div").hide();
}
})
$("#property_property_location").on("change",function(){
if($(this).val() == "other_location"){
$("#other-location-div").show();
@ -593,7 +746,83 @@
$("#selector_block").css("display","");
}
})
var setting_count = <%=setting_count%>;
$(".add_weekday_setting").click(function(){
var target = $($(this).data("target"));
var key = $(this).data("key");
var day = $(this).data("day");
var new_key = $(this).prev().attr('value');
var old_key = new RegExp("new_key", "g");
var new_day = day;
var old_day = new RegExp("new_day", "g");
var new_key = key;
key += 1;
$(this).data("key",key);
var old_index = new RegExp("new_index", "g");
var new_index = setting_count;
setting_count += 1;
<% property_day_setting = f.object.property_day_settings.new(:id=>nil) %>
<%= f.fields_for :property_day_settings,property_day_setting,:child_index => "new_index" do |f| %>
var template_html = "<%= escape_javascript(render(:partial=>"time_form",:locals=>{:f=>f})) %>";
<%end%>
var tmp = $(template_html.replace(old_index,new_index).replace(old_key,new_key).replace(old_day,new_day));
target.append(tmp);
tmp.find("input[data-format]").each(function(i,input){
var $input = $(input);
var format = $input.data("format"),
timeOnly = !(format.match(/Y|M|d/)), timeFormat, dateFormat = "";
if(timeOnly){
timeFormat = format;
}else{
dateFormat = format.match(/yy(\/|-|)(mm|)(\/|-|)(dd|)/i)[0];
timeFormat = $.trim(format.replace(dateFormat,""));
}
var options = {dateFormat: dateFormat,timeFormat: timeFormat,timeOnly: timeOnly};
var additionalOptions = $input.data();
$.extend(options, additionalOptions);
$input.ui_datetimepicker(options);
$input.siblings('.clearDate').click(function(){
$input.val('');
$input.trigger('change');
});
})
})
$(document).on('click', '.setting-form-remove', function(){
if($(this).find(".remove_existing_record").length != 0){
if(confirm("<%= I18n.t(:sure?)%>")){
$(this).find('.should_destroy').attr('value', 1);
$(this).parents('.time_setting_form').hide();
}
}else{
$(this).parents('.time_setting_form').remove();
}
});
$(document).on('click', '.image-form-remove', function(){
if($(this).find(".remove_existing_record").length != 0){
if(confirm("<%= I18n.t(:sure?)%>")){
$(this).find('.should_destroy').attr('value', 1);
$(this).parents('.image_group').hide();
}
}else{
$(this).parents('.image_group').remove();
}
});
$(document).on('click', '#add_carousel_image', function(){
var new_id = $(this).prev().attr('value');
var old_id = new RegExp("new_property_carousel_images", "g");
var on = $('.language-nav li.active').index();
var le = $(this).parent('.add-btn').prev('.add-target').children('.start-line').length;
$(this).prev().attr('value', parseInt(new_id) + 1);
$(this).parent().siblings('.add-target').append(("<%= escape_javascript(add_attribute 'form_image', f, :property_carousel_images) %>").replace(old_id, new_id));
$(this).parent('.add-btn').prev('.add-target').children('.start-line').eq(le).children('.input-append').find('.tab-content').each(function() {
$(this).children('.tab-pane').eq(on).addClass('in active').siblings().removeClass('in active');
});
});
$(document).on('click', '.fileupload-remove', function(){
if($(this).find(".delete_image").length != 0){
$(this).parents('.image_group').remove();
}
});
</script>

View File

@ -0,0 +1,63 @@
<% if form_file.nil? || form_file.new_record? %>
<div class="fileupload fileupload-new start-line" data-provides="fileupload">
<% else %>
<div class="fileupload fileupload-exists start-line" data-provides="fileupload">
<% if form_file.file.blank? %>
<%= t(:no_file) %>
<% else %>
<%= link_to content_tag(:i) + form_file.file_identifier, form_file.file.url, {:class => 'file-link file-type', :target => '_blank', :title => form_file.file_identifier} %>
<% end %>
<% end %>
<div class="input-prepend input-append">
<label>
<span class="add-on btn btn-file" title='<%= t(:file_) %>'>
<i class="icons-paperclip"></i>
<%= f.file_field :file %>
</span>
<div class="uneditable-input input-medium">
<i class="icon-file fileupload-exists"></i>
<span class="fileupload-preview"><%= (form_file.nil? || form_file.new_record? || form_file.file.blank?) ? t(:select_file) : t(:change_file) %></span>
</div>
</label>
<span class="add-on icons-pencil" title='<%= t(:alternative) %>'></span>
<span class="tab-content">
<% if form_file.fields["title"].options[:localize] %>
<% @site_in_use_locales.each_with_index do |locale, i| %>
<span class="tab-pane fade <%= ( i == 0 ) ? "in active" : '' %> <%= locale %>">
<%= f.fields_for :title_translations do |f| %>
<%= f.text_field locale, :class => "input-medium", placeholder: t(:alternative), :value => (form_file.title_translations[locale] rescue nil) %>
<% end %>
</span>
<% end %>
<% else %>
<%= f.text_field :title, :class => "input-medium", placeholder: t(:alternative) %>
<% end %>
</span>
<span class="add-on icons-pencil" title='<%= t(:description) %>'></span>
<span class="tab-content">
<% if form_file.fields["description"].options[:localize] %>
<% @site_in_use_locales.each_with_index do |locale, i| %>
<span class="tab-pane fade <%= ( i == 0 ) ? "in active" : '' %> <%= locale %>">
<%= f.fields_for :description_translations do |f| %>
<%= f.text_field locale, :class => "input-medium", placeholder: t(:description), :value => (form_file.description_translations[locale] rescue nil) %>
<% end %>
</span>
<% end %>
<% else %>
<%= f.text_field :description, :class => "input-medium", placeholder: t(:description) %>
<% end %>
</span>
</span>
<% if form_file.nil? || form_file.new_record? %>
<span class="delete_file add-on btn" title="<%= t(:delete_) %>">
<a class="icon-trash"></a>
</span>
<% else %>
<span class="remove_existing_record add-on btn" title="<%= t(:remove) %>">
<%= f.hidden_field :id %>
<a class="icon-remove"></a>
<%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %>
</span>
<% end %>
</div>
</div>

View File

@ -0,0 +1,93 @@
<!-- Link -->
<div class="control-group">
<label class="control-label muted"><%= t(:link) %></label>
<div class="controls add-input">
<!-- Exist -->
<% if !f.object.nil? && !f.object.property_links.blank? %>
<div class="exist">
<% f.object.property_links.each_with_index do |property_link, i| %>
<%= f.fields_for :property_links, property_link do |f| %>
<%= render :partial => 'form_link', :object=> property_link, :locals => {:f => f, :i => i } %>
<% end %>
<% end %>
<hr>
</div>
<% end %>
<!-- Add -->
<div class="add-target">
</div>
<p class="add-btn">
<%= hidden_field_tag 'property_link_field_count', f.object.property_links.count %>
<a id="add_link" class="trigger btn btn-small btn-primary"><i class="icons-plus"></i> <%= t(:add) %></a>
</p>
</div>
</div>
<!-- File -->
<div class="control-group">
<label class="control-label muted"><%= t(:file_) %></label>
<div class="controls">
<!-- Exist -->
<% if !f.object.nil? && !f.object.property_files.blank? %>
<div class="exist">
<% f.object.property_files.each_with_index do |property_file, i| %>
<%= f.fields_for :property_files, property_file do |f| %>
<%= render :partial => 'form_file',:object => property_file, :locals => {:f => f, :i => i} %>
<% end %>
<% end %>
<hr>
</div>
<% end %>
<!-- Add -->
<div class="add-target">
</div>
<p class="add-btn">
<%= hidden_field_tag 'property_file_field_count', f.object.property_files.count %>
<a id="add_file" class="trigger btn btn-small btn-primary"><i class="icons-plus"></i> <%= t(:add) %></a>
</p>
</div>
</div>
<script type="text/javascript">
$(function() {
$(document).on('click', '#add_link', function(){
var new_id = $(this).prev().attr('value');
var old_id = new RegExp("new_property_links", "g");
var on = $('.language-nav li.active').index();
var le = $(this).parent('.add-btn').prev('.add-target').children('.start-line').length;
$(this).prev().attr('value', parseInt(new_id) + 1);
$(this).parent().siblings('.add-target').append(("<%= escape_javascript(add_attribute 'form_link', f, :property_links) %>").replace(old_id, new_id));
$(this).parent('.add-btn').prev('.add-target').children('.start-line').eq(le).children('.tab-content').children('.tab-pane').eq(on).addClass('in active').siblings().removeClass('in active');
formTip();
});
$(document).on('click', '#add_file', function(){
var new_id = $(this).prev().attr('value');
var old_id = new RegExp("new_property_files", "g");
var on = $('.language-nav li.active').index();
var le = $(this).parent('.add-btn').prev('.add-target').children('.start-line').length;
$(this).prev().attr('value', parseInt(new_id) + 1);
$(this).parent().siblings('.add-target').append(("<%= escape_javascript(add_attribute 'form_file', f, :property_files) %>").replace(old_id, new_id));
$(this).parent('.add-btn').prev('.add-target').children('.start-line').eq(le).children('.input-append').find('.tab-content').each(function() {
$(this).children('.tab-pane').eq(on).addClass('in active').siblings().removeClass('in active');
});
formTip();
});
$(document).on('click', '.delete_link', function(){
$(this).parents('.input-prepend').remove();
});
$(document).on('click', '.delete_file', function(){
$(this).parents('.input-prepend').remove();
});
$(document).on('click', '.remove_existing_record', function(){
if(confirm("<%= I18n.t(:sure?)%>")){
$(this).children('.should_destroy').attr('value', 1);
$(this).parents('.start-line').hide();
}
});
});
</script>

View File

@ -0,0 +1,47 @@
<!-- Images Upload -->
<div class="image_group">
<label class="checkbox inline btn btn-danger image-form-remove">
<% if f.object.new_record? %>
<span class="delete_form" title="<%= t(:delete_) %>">
X
</span>
<% else %>
<span class="remove_existing_record" title="<%= t(:remove) %>">
<%= f.hidden_field :id %>
<%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %>
X
</span>
<% end %>
</label>
<div class="control-group">
<label class="control-label muted"><%= t(:image) %></label>
<div class="controls">
<div class="fileupload fileupload-new clearfix <%= 'fileupload-edit' if form_image.file.present? %>" data-provides="fileupload">
<div class="fileupload-new thumbnail pull-left">
<% if form_image.file.file %>
<%= image_tag form_image.file %>
<% else %>
<img src="http://www.placehold.it/50x50/EFEFEF/AAAAAA" />
<% end %>
</div>
<div class="fileupload-preview fileupload-exists thumbnail pull-left"></div>
<span class="btn btn-file">
<span class="fileupload-new"><%= t(:select_image) %></span>
<span class="fileupload-exists"><%= t(:change) %></span>
<%= f.file_field :file %>
</span>
<a href="#" class="btn fileupload-exists" data-dismiss="fileupload"><%= t(:cancel) %></a>
</div>
</div>
</div>
<% @site_in_use_locales.each do |locale| %>
<%= f.fields_for :description_translations do |f| %>
<div class="control-group">
<label class="control-label muted" for="image_description_<%= locale.to_s %>"><%= t(:description) + " (#{t(locale.to_s)})" %></label>
<div class="controls">
<%= f.text_field locale, value: (form_image.description_translations[locale.to_s] rescue nil) %>
</div>
</div>
<% end %>
<% end %>
</div>

View File

@ -0,0 +1,30 @@
<div class="input-prepend input-append start-line">
<span class="add-on icons-link" title="<%= t(:url) %>"></span>
<%= f.text_field :url, class: "input-large", placeholder: t(:url) %>
<span class="add-on icons-pencil" title="<%= t(:url_alt) %>"></span>
<span class="tab-content">
<% if form_link.fields["title"].options[:localize] %>
<% @site_in_use_locales.each_with_index do |locale, i| %>
<span class="tab-pane fade <%= ( i == 0 ) ? "in active" : '' %> <%= locale %>">
<%= f.fields_for :title_translations do |f| %>
<%= f.text_field locale, :class => "input-large", placeholder: t(:url_alt), :value => (form_link.title_translations[locale] rescue nil) %>
<% end %>
</span>
<% end %>
<% else %>
<%= f.text_field :title, :class => "input-large", placeholder: t(:url_alt) %>
<% end %>
</span>
<% if form_link.nil? || form_link.new_record? %>
<span class="delete_link add-on btn" title="<%= t(:delete_) %>">
<a class="icon-trash"></a>
</span>
<% else %>
<span class="remove_existing_record add-on btn" title="<%= t(:remove) %>">
<%= f.hidden_field :id %>
<a class="icon-remove"></a>
<%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %>
</span>
<% end %>
</div>

View File

@ -0,0 +1,298 @@
<%#= encoding: utf-8 %>
<script id="template-attributes" type="text/x-tmpl">
<div class="attributes">
<div class="attributes-header clearfix">
<input class="toggle-check" data-deploy="right" id="${_disabled[0]}" name="${_disabled[1]}" type="hidden" value="false">
<a class="btn btn-mini pull-right btn-danger delete" href="#"><i class="icon-trash"></i> Delete</a>
<a class="btn btn-mini pull-right btn-inverse reply hide" href="#"><i class="icons-reply"></i> Reply</a>
<input class="attribute_field_to_delete" id="${_to_delete[0]}" name="${_to_delete[1]}" type="hidden" value="false">
<h4>Field <span>${attributesHeaderLength}</span></h4>
</div>
<div class="attributes-body">
<div class="control-group">
<label class="control-label muted" for="${_key[0]}"><%= t(:key) %></label>
<div class="controls">
<input type="text" data-type="key" id="${_key[0]}" name="${_key[1]}" placeholder="<%= t(:key) %>">
</div>
</div>
<div class="control-group">
<label class="control-label muted" for=""><%= t(:name) %></label>
<div class="controls">
<div class="input-append">
<div class="tab-content">
<% @site_in_use_locales.each do |locale| %>
<% active = (locale == @site_in_use_locales.first ? "active" : "") %>
<div class="tab-pane <%= active %> fade in" id="${_title_translations[0]+'_<%= locale%>'}">
<input type="text" data-type="lang_<%= locale%>" name="${_title_translations[1]+'[<%= locale%>]'}" placeholder="<%= t(locale).to_s %>">
</div>
<% end %>
</div>
<div class="btn-group" data-toggle="buttons-radio">
<% @site_in_use_locales.each do |locale| %>
<% active = (locale == @site_in_use_locales.first ? "active" : "") %>
<a class="btn <%= active %>" href="${'#'+_title_translations[0]+'_<%= locale%>'}" data-toggle="tab"><%= t(locale).to_s %></a>
<% end %>
</div>
</div>
</div>
</div>
<div class="control-group">
<label class="control-label muted" for=""><%= t('property_hire.to_require') %></label>
<div class="controls">
<label class="radio inline">
<input type="radio" data-type="search_true" id="${_to_require[0]+'_true'}" name="${_to_require[1]}" value="true" checked=""> <%= t(:yes_)%>
</label>
<label class="radio inline">
<input type="radio" data-type="search_false" id="${_to_require[0]+'_false'}" name="${_to_require[1]}" value="false"> <%= t(:no_)%>
</label>
</div>
</div>
<div class="control-group">
<label class="control-label muted" for=""><%= t(:type)%></label>
<div class="controls">
<select class="dataType" data-type="select" name="${_markup}">
<%$property_list[:markups].each do |key,val|%>
<% next if val["display_only"] && val["display_only"] != params["action"] %>
<% if key != 'address' %>
<option value="<%= key %>" ref="<%=val["panel"]%>"><%=t("lists.markups."+key)%></option >
<% end %>
<% end %>
</select>
</div>
</div>
</div>
<div class="field-type fade in typeA">
<div class="control-group">
<label class="control-label muted"><%= t(:enabled_for)%></label>
<div class="controls">
<label class="checkbox inline">
<input type="checkbox" data-type="enable_monolingual" id="${_cross_lang[0]}" name="${_cross_lang[1]}" value="true">
<%= t(:cross_lang) %>
</label>
<label class="checkbox inline">
<input type="checkbox" data-type="extendable_field" id="${_add_more[0]}" name="${_add_more[1]}" value="true">
<%= t(:add_more)%>
</label>
</div>
</div>
<div class="control-group">
<label class="control-label muted"><%= t(:placeholder) %></label>
<div class="controls">
<div class="input-append">
<div class="tab-content">
<% @site_in_use_locales.each do |locale| %>
<% active = (locale == @site_in_use_locales.first ? "active" : "") %>
<div class="tab-pane <%= active %> fade in" id="${_placeholder[0]+'_<%= locale %>'}">
<input type="text" data-type="lang_<%= locale %>" placeholder="<%= t(locale).to_s %>" name="${_placeholder[1]+'[<%= locale %>]'}">
</div>
<% end %>
</div>
<div class="btn-group" data-toggle="buttons-radio">
<% @site_in_use_locales.each do |locale| %>
<% active = (locale == @site_in_use_locales.first ? "active" : "") %>
<a class="btn <%= active %>" href="${'#'+_placeholder[0]+'_<%= locale %>'}" data-toggle="tab"><%= t(locale).to_s %></a>
<% end %>
</div>
</div>
</div>
</div>
</div>
</div>
</script>
<script id="template-type" type="text/x-tmpl">
{{if templateType == 'typeA' || templateType == 'typeD' || templateType == 'typeG'}}
<div class="control-group">
<label class="control-label muted"><%= t(:enabled_for)%></label>
<div class="controls">
{{if templateType == 'typeA' || templateType == 'typeD'}}
<label class="checkbox inline">
<input type="checkbox" data-type="enable_monolingual" id="${_cross_lang[0]}" name="${_cross_lang[1]}" value="true">
<%= t(:cross_lang) %>
</label>
{{/if}}
{{if templateType == 'typeA' || templateType == 'typeG'}}
<label class="checkbox inline">
<input type="checkbox" data-type="extendable_field" id="${_add_more[0]}" name="${_add_more[1]}" value="true">
<%= t(:add_more)%>
</label>
{{/if}}
</div>
</div>
{{/if}}
{{if templateType == 'typeA' || templateType == 'typeB' || templateType == 'typeD'}}
<div class="control-group">
<label class="control-label muted">
{{if templateType == 'typeB'}}
<%= t(:initial) %>
{{else}}
<%= t(:placeholder) %>
{{/if}}
</label>
<div class="controls">
<div class="input-append">
<div class="tab-content">
<% @site_in_use_locales.each do |locale| %>
<% active = (locale == @site_in_use_locales.first ? "active" : "") %>
<div class="tab-pane <%= active %> fade in" id=
{{if templateType == 'typeB'}}
"${_initial[0]+'_<%= locale %>'}"
{{else}}
"${_placeholder[0]+'_<%= locale %>'}"
{{/if}}
>
<input type="text" data-type="lang_<%= locale %>" placeholder="<%= t(locale).to_s %>" name=
{{if templateType == 'typeB'}}
"${_initial[1]+'[<%= locale %>]' }"
{{else}}
"${_placeholder[1]+'[<%= locale %>]'}"
{{/if}}
>
</div>
<% end %>
</div>
<div class="btn-group" data-toggle="buttons-radio">
<% @site_in_use_locales.each do |locale| %>
<% active = (locale == @site_in_use_locales.first ? "active" : "") %>
<a class="btn <%= active %>" href=
{{if templateType == 'typeB'}}
"${'#'+_initial[0]+'_<%= locale %>'}"
{{else}}
"${'#'+_placeholder[0]+'_<%= locale %>'}"
{{/if}}
data-toggle="tab"><%= t(locale).to_s %></a>
<% end %>
</div>
</div>
</div>
</div>
{{/if}}
{{if templateType == 'typeB' || templateType == 'typeE'}}
<div class="control-group">
<label class="control-label muted" for=""><%= t(:options)%></label>
<div class="controls add-input">
<div class="add-target single">
<%= content_tag :div,:class=>"input-append" do%>
<% @site_in_use_locales.each do |locale| %>
<% last = (locale == @site_in_use_locales.last ? true : false) %>
<input type="text" data-type="${_option_list[2]+'_<%= locale %>' }" id="${_option_list[0]+'_<%= locale %>'}" name="${_option_list[1]+'[<%= locale %>]'}" class="input-medium" placeholder="<%= t(locale).to_s %>">
<% if last %>
<a href="#" class="btn remove-input"> <i class="icon-trash"></i> </a>
<% end %>
<% end %>
<% end %>
</div>
<p class="add-btn">
<a href="#" class="${templateType+' trigger btn btn-mini btn-primary'}"><i class="icons-plus"></i> Add</a>
</p>
</div>
</div>
{{/if}}
{{if templateType == 'typeC'}}
<div class="control-group">
<label class="control-label muted" for=""><%= t("date.format")%></label>
<div class="controls">
<select data-type="date" id="${_format[0]}" name="${_format[1]}">
<option value="format1">YYYY / MM / DD hh : mm</option>
<option value="format2">YYYY / MM / DD</option>
<option value="format3">YYYY / MM</option>
<option value="format4">YYYY</option>
</select>
</div>
</div>
<div class="control-group">
<label class="control-label muted" for=""><%= t("date.range")%></label>
<div class="controls">
<label class="radio inline">
<input type="radio" data-type="time_period_flase" id="${_is_range[0]+'_false'}" name="${_is_range[1]}" value="false" checked="checked"> <%= t(:yes_)%>
</label>
<label class="radio inline">
<input type="radio" data-type="time_period_true" id="${_is_range[0]+'_true'}" name="${_is_range[1]}" value="true"> <%= t(:no_)%>
</label>
</div>
</div>
<div class="control-group">
<label class="control-label muted" for=""><%= t("date.calendar")%></label>
<div class="controls">
<label class="radio inline">
<input type="radio" data-type="calendar_ac" id="${_calendar[0]+'_west_calendar'}" name="${_calendar[1]}" value="west_calendar" checked="checked"> <%= t("date.west_calendar")%>
</label>
<label class="radio inline">
<input type="radio" data-type="calendar_roc" id="${_calendar[0]+'_tw_calendar'}" name="${_calendar[1]}" value="tw_calendar"> <%= t("date.tw_calendar")%>
</label>
</div>
</div>
{{/if}}
{{if templateType == 'typeF'}}
<div class="control-group">
<label class="control-label muted">
<%= t("lists.markups.hint_text") %>
</label>
<div class="controls">
<div class="input-append">
<div class="tab-content">
<% @site_in_use_locales.each do |locale| %>
<% active = (locale == @site_in_use_locales.first ? "active" : "") %>
<div class="tab-pane <%= active %> fade in" id=
"${_placeholder[0]+'_<%= locale %>'}">
<textarea data-type="lang_<%= locale %>" placeholder="<%= t(locale).to_s %>" name="${_placeholder[1]+'[<%= locale %>]'}"></textarea>
</div>
<% end %>
</div>
<div class="btn-group" data-toggle="buttons-radio">
<% @site_in_use_locales.each do |locale| %>
<% active = (locale == @site_in_use_locales.first ? "active" : "") %>
<a class="btn <%= active %>" href="${'#'+_placeholder[0]+'_<%= locale %>'}"data-toggle="tab">
<%= t(locale).to_s %>
</a>
<% end %>
</div>
</div>
</div>
</div>
{{/if}}
</script>
<script id="template-input-append" type="text/x-tmpl">
<%= content_tag :div,:class=>"input-append" do%>
<% @site_in_use_locales.each do |locale| %>
<% last = (locale == @site_in_use_locales.last ? true : false) %>
<input type="text" data-type="${_option_list[2]+'_<%= locale %>' }" id="${_option_list[0]+'_<%= locale %>'}" name="${_option_list[1]+'[<%= locale %>]'}" class="input-medium" placeholder="<%= t(locale).to_s %>">
<% if last %>
<a href="#" class="btn remove-input"> <i class="icon-trash"></i> </a>
<% end %>
<% end %>
<% end %>
</script>
<script id="template-text" type="text/x-tmpl">
<div class="input-append">
<input type="text" id="${'text'+_text[0]}" name="${_text[1]+'[text]'}" class="input-medium" placeholder="Text">
<a href="#" class="btn remove-input">
<i class="icon-trash"></i>
</a>
</div>
</script>

View File

@ -0,0 +1,44 @@
<div class="time_setting_form">
<% key = (defined?(key) && key) ? key : "new_key"
day = (defined?(day) && day) ? key : "new_day"
%>
<label class="checkbox inline btn btn-danger setting-form-remove">
<% if f.object.new_record? %>
<span class="delete_form" title="<%= t(:delete_) %>">
X
</span>
<% else %>
<span class="remove_existing_record" title="<%= t(:remove) %>">
<%= f.hidden_field :id %>
<%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %>
X
</span>
<% end %>
</label>
<div class="control-group">
<%= f.label "time_title_#{key}_#{day}", t("property_hire.time_title"), :class => "control-label muted" %>
<div class="controls">
<%= f.text_field :title, :id=>"time_title_#{key}_#{day}" %>
</div>
</div>
<div class="control-group">
<%= f.label :start_time, t("property_hire.limit_start_time"), :class => "control-label muted" %>
<div class="controls">
<%= f.datetime_picker :start_time, :picker_type => "time", :no_label => true, :new_record => @property.new_record? %>
</div>
</div>
<div class="control-group">
<%= f.label :end_time, t("property_hire.limit_end_time"), :class => "control-label muted" %>
<div class="controls">
<%= f.datetime_picker :end_time, :picker_type => "time", :no_label => true, :new_record => @property.new_record? %>
</div>
</div>
<%= f.hidden_field :key, :value => key %>
<%= f.hidden_field :day, :value => day %>
<div class="control-group">
<%= f.label "reservation_limit_#{key}_#{day}", t("property_hire.reservation_limit"), :class => "control-label muted" %>
<div class="controls">
<%= f.number_field :reservation_limit, :id=>"reservation_limit_#{key}_#{day}" %>
</div>
</div>
</div>

View File

@ -0,0 +1,41 @@
<% content_for :page_specific_css do -%>
<%= stylesheet_link_tag "lib/wrap-nav.css" %>
<%= stylesheet_link_tag "lib/pageslide.css" %>
<%= stylesheet_link_tag "lib/main-forms.css" %>
<%= stylesheet_link_tag "lib/togglebox.css" %>
<% end -%>
<% content_for :page_specific_javascript do -%>
<%= javascript_include_tag "lib/jquery.tmpl.min.js" %>
<%= javascript_include_tag "property_hire/property-field-forms.js" %>
<% end -%>
<style type="text/css">
.input-append, .input-prepend{
font-size: 1em;
}
</style>
<%= form_for @attribute,:url => admin_property_hire_path(@attribute) , :html => { :class=> "form-horizontal main-forms" } do |f| %>
<% if flash.now[:notice].present? %>
<%= flash.now[:notice]%>
<% end %>
<h3><%= @attribute.title %></h3>
<fieldset>
<div id="attributes-area" class="input-area">
<%= render partial: "attribute_field",collection: @attribute.p_hire_fields.asc(:_id)%>
</div>
<div class="form-actions">
<button type="button" class="btn btn-success add-attributes"><%= t(:add_attribute_field) %></button>
<%= hidden_field_tag 'id', params[:id] if !params[:id].blank? %>
<%= f.submit t(:submit),:class=>"btn btn-primary"%>
<%= link_to t('cancel'), get_go_back, :class=>"btn" %>
</div>
</fieldset>
<% end %>
<% content_for :page_specific_javascript do -%>
<%= render 'support_member_form_js' %>
<% end -%>

View File

@ -15,6 +15,7 @@
<div class="quick-edit">
<ul class="nav nav-pills">
<li><a href="<%= edit_admin_property_hire_path(property, :page => params[:page]) %>"><%= t(:edit) %></a></li>
<li><a href="<%= custom_fields_admin_property_hire_path(property) %>"><%= t("property_hire.custom_fields") %></a></li>
<li><a href="<%= admin_property_hire_path(property.id, :page => params[:page]) %>" data-method="delete" data-confirm="Are you sure?"><%= t(:delete_) %></a></li>
</ul>
</div>

View File

@ -0,0 +1,191 @@
<% content_for :page_specific_css do %>
<%= stylesheet_link_tag "admin/properties" %>
<% end %>
<style>
.icons-list-2 {
cursor: all-scroll;
}
</style>
<div class="order-edit-notification"><%= t("property_hire.please_save") %></div>
<table width="100%" id="property_order_table" class="table table-striped" class="web_soursce_table">
<thead>
<tr>
<th></th>
<th><%= t("property_hire.position") %></th>
<th><%= t("property_hire.title") %></th>
</thead>
<tbody>
<% @properties.each_with_index do |property,i| %>
<tr data-index="<%=i%>">
<td><span class="brand"><i class="icons-list-2"></i></span></td>
<td class="position-text">
<div class="position-text-div" data-value="<%= (i + 1).to_s %>"><%= (i + 1).to_s %></div>
</td>
<td>
<div class="property-text-id" data-property-id="<%= property.id.to_s %>"><%= property.title %></div>
</td>
</tr>
<% end %>
</tbody>
</table>
<div class="bottomnav clearfix" style="left: 81px;">
<div class="action pull-right">
<a class="btn btn-info disabled" id="save-order-button" href="#"><%= t("property.save_order") %></a>
</div>
<div class="pagination pagination-centered"></div>
</div>
<script type="text/javascript">
var makeEditable = function(){
var input_box = $("<input type='text'/>"),
el = $(this);
input_box.addClass("editable-input");
input_box.val(el.data("value"));
input_box.attr("data-old-id",el.data("value"));
input_box.on("blur",function(){
putBackdiv($(this));
});
input_box.on("keypress",function(e){
if(e.keyCode == 13 || e.keyCode == 27){
putBackdiv($(this),e.keyCode);
}
})
el.parent().html(input_box);
input_box.focus();
}
var putBackdiv = function(el,keyCode){
current_value = parseInt((el.val() == "" ? el.data("old-id") : el.val())),
old_value = parseInt(el.data("old-id"));
if(isNaN(current_value) || keyCode == 27){
current_value = old_value;
}
if(old_value != current_value){
var new_index_value = (current_value > old_value ? current_value + 1 : current_value - 1),
div = $("<div class='position-text-div' data-value='" + current_value + "'>" + new_index_value + "</div>");
div.on("click",makeEditable);
el.parent().html(div);
$("#save-order-button").removeClass("disabled");
$(".order-edit-notification").slideDown();
sortTable(el.data("old-id"),current_value);
}else{
var div = $("<div class='position-text-div' data-value='" + current_value + "'>" + current_value + "</div>");
div.on("click",makeEditable);
el.parent().html(div);
}
}
var sortTable = function(changed_index,changed_to){
var table_element = document.getElementById("property_order_table"),
data = [],
allRows = table_element.rows;
for(i = 1; i < allRows.length; i++){
var thisRow = allRows[i],
text = thisRow.cells[0].textContent.trim(),
hash = {};
hash.index = parseInt(text);
text = thisRow.cells[1].innerHTML.trim();
if(text != "&nbsp;"){
hash.property = text;
}
data.push(hash);
}
data = data.sort(function(a,b){return a.index - b.index});
renderSortedTable(data,table_element);
}
var renderSortedTable = function(data,table_element){
var allRows = table_element.rows;
for(i = 0;i < data.length; i++){
var thisRow = allRows[i + 1],
current_value = i + 1;
thisRow.cells[0].innerHTML = "<div class='position-text-div' data-value='" + current_value + "'>" + current_value + "</div>";
thisRow.cells[1].innerHTML = data[i].property;
}
$("#property_order_table div.position-text-div").on("click",makeEditable);
}
$("#save-order-button").on("click",function(){
var el = $(this);
if(!el.hasClass("disabled")){
var data = [];
$("#property_order_table .property-text-id").each(function(){
data.push($(this).data("property-id"));
})
$.ajax({
url : "<%=updateorder_admin_property_hires_path%>",
data : {"order" : data},
dataType : "json",
type : "post"
}).done(function(){
el.addClass("disabled");
$(".order-edit-notification").slideUp();
})
}
})
$("#property_order_table div.position-text-div").on("click",makeEditable);
</script>
<script>
var th_width = {};
$(document).ready(function(){
$( ".table tbody" ).each(function(i,tbody){
var table = $(tbody).parents("table").eq(0);
table.data("index",i);
th_width[i] = [];
table.find("thead th").each(function(j,th){
th_width[i].push($(th).outerWidth(true));
})
})
$( ".table tbody" ).sortable({
revert: true,
axis: "y",
handle: ".brand",
start: function(event, ui){
var item = ui.item;
var target = $(event.target);
var index = target.parents(".table").eq(0).data("index");
item.css("width",target.width());
item.find("td").each(function(i,td){
$(td).width(th_width[index][i]);
})
},
stop: function(event, ui) {
var item = ui.item;
item.css("width","");
item.find("td").css("width","");
},
update: function(event, ui) {
var item = ui.item;
var org_index = item.data("index");
console.log(org_index);
var new_index = item.index();
var indices = [org_index,new_index].sort();
var table = item.parents(".table").eq(0);
table.find("tbody tr").each(function(i,tr){
if(i >= indices[0] && i <= indices[1]){
var position_text_div = $(tr).find(".position-text-div");
position_text_div.text(i+1).data("value",i+1);
$(tr).data("index",i);
}
if(i > indices[1]){
return;
}
})
$("#save-order-button").removeClass("disabled");
$(".order-edit-notification").slideDown();
}
});
})
$(window).resize(function(){
th_width = {};
$( ".table tbody" ).each(function(i,tbody){
var table = $(tbody).parents("table").eq(0);
th_width[i] = [];
table.find("thead th").each(function(j,th){
th_width[i].push($(th).outerWidth(true));
})
})
})
</script>

View File

@ -29,6 +29,24 @@
<%= f.check_box :auto_approve %>
</div>
</div>
<div class="control-group">
<%= f.label :disable_content_page, t("property_hire.disable_content_page"), :class => "control-label muted" %>
<div class="controls">
<%= f.check_box :disable_content_page %>
</div>
</div>
<div class="control-group">
<%= f.label :disable_view_calendar_page, t("property_hire.disable_view_calendar_page"), :class => "control-label muted" %>
<div class="controls">
<%= f.check_box :disable_view_calendar_page %>
</div>
</div>
<div class="control-group">
<%= f.label :carousel_image_width, t("announcement.default_carousel_image_width"), :class => "control-label muted" %>
<div class="controls">
<%= f.text_field :carousel_image_width %>
</div>
</div>
</div>
</div>
</div>

View File

@ -1,15 +1,153 @@
<% OrbitHelper.render_css_in_head(["basic/bootstrap-datetimepicker.css","property_hire_fullcalendar.css","property_hire_calendar.scss"]) %>
<% OrbitHelper.render_css_in_head(["basic/bootstrap-datetimepicker.css","property_hire_fullcalendar.css","property_hire_calendar"]) %>
<%= javascript_include_tag "validator.js" %>
<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>
<%
data = action_data
hire = data["hire"]
property = data["property"]
url = data["page"]
current_user = data["current_user"]
data = action_data
hire = data["hire"]
property = data["property"]
url = data["page"]
current_user = data["current_user"]
%>
<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.");
@ -22,22 +160,87 @@
window.location.href = "<%= "/" + I18n.locale.to_s + url %>";
</script>
<% else %>
<h3><%= property.title %></h3>
<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>
<% session.delete("hire-save-msg") %>
<% end %>
<div id="orbit_calendar">
</article>
<div id="orbit_calendar" class="col-lg-8">
<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>
@ -54,17 +257,72 @@
<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?,: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);
var pick_date_mode = <%=property.set_availability%>;
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() == ""){
@ -74,11 +332,11 @@
}
$("#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("*",""));
$("#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("main-content").scrollIntoView();
goto_calendar();
}
$("#calendar").on("select_time",function(ev,date_str){
$("#hidden_date").text(date_str);
@ -106,8 +364,13 @@
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();
end_date = $("#p_hire_end_time").val();
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;
}
@ -124,7 +387,6 @@
}
}
}
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"));
@ -145,61 +407,59 @@
}
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);
var offset = $('#orbit_calendar').offset();
scrollTo(0,offset.top-40);
}
</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>
<div class="col-lg-4">
<%= 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-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()" %>
</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()" %>
</div>
</div>
<% else %>
<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.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;"} %>
<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>
</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.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;"} %>
<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" %>
<%= f.label :recurring, t("property_hire.recurring"), :class => "col-sm-4 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" %>
<%= f.label :recurring_interval, t("property_hire.recurring_interval"), :class => "col-sm-4 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.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;"} %>
<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>
</div>
@ -207,7 +467,7 @@
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-5">
<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 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">
@ -220,7 +480,7 @@
</div>
</div>
<% if property.set_unavailibility %>
<div class="col-sm-offset-2 col-sm-5">
<div class="col-sm-offset-4 col-sm-5">
<b><%= t("property_hire.Unavailibility_Schedule") %></b>
<div>
<%= property.render_unavailable_message%>
@ -230,33 +490,33 @@
</div>
<div class="form-group">
<label for="" class="col-sm-2 control-label"></label>
<div class="col-sm-10">
<label for="" class="col-sm-4 control-label"></label>
<div class="col-sm-8">
<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" %>
<%= f.label :hiring_person_email, "*"+t("property_hire.hiring_person_email"), :class => "col-sm-4 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;"} %>
</div>
</div>
<div class="form-group">
<%= f.label :hiring_person_number, "*"+t("property_hire.hiring_person_number"), :class => "col-sm-2 control-label" %>
<%= f.label :hiring_person_number, "*"+t("property_hire.hiring_person_number"), :class => "col-sm-4 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;"} %>
</div>
</div>
<div class="form-group">
<%= f.label :hiring_person_name, "*"+t("property_hire.hiring_person_name"), :class => "col-sm-2 control-label" %>
<%= f.label :hiring_person_name, "*"+t("property_hire.hiring_person_name"), :class => "col-sm-4 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.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" %>
<%= f.label :reason_for_hire, "*"+t("property_hire.reason_for_hire"), :class => "col-sm-4 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>
@ -269,7 +529,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-4 control-label" %>
<div class="col-sm-5">
<% values.each_with_index do |v,i| %>
<label class="checkbox-inline">
@ -285,7 +545,7 @@
<% end %>
<% else %>
<div class="form-group">
<%= f.label :note_for_hire, t("property_hire.note_for_hire"), :class => "col-sm-2 control-label" %>
<%= f.label :note_for_hire, t("property_hire.note_for_hire"), :class => "col-sm-4 control-label" %>
<div class="col-sm-5">
<%= f.text_area :note_for_hire, :class => "form-control" %>
</div>
@ -296,19 +556,30 @@
<% 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-4 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,4) %>
</div>
<% @form_index = @form_index +1 %>
<% end %>
<% end %>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="col-sm-offset-4 col-sm-8">
<%= 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 %>" />
@ -316,13 +587,16 @@
</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 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();
stime = stime || etime;
etime = etime || stime;
property_id = property_id || window.property_id;
@ -332,7 +606,8 @@
"etime": etime,
"property_id": property_id,
"locale": "<%=I18n.locale%>",
"timezone": timezone
"timezone": timezone,
"time_setting_id": time_setting_id
}
data["interval"] = interval;
data["recurring_end_date"] = recurring_end_date;
@ -374,8 +649,14 @@
url = $(this).attr("href"),
spinner = $("#spinner");
$(".alert").hide();
var stime = $("#p_hire_start_time").val(),
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")){
is_recurring = true;

View File

@ -0,0 +1,440 @@
<% OrbitHelper.render_css_in_head(["basic/bootstrap-datetimepicker.css","property_hire_fullcalendar.css","property_hire_calendar"]) %>
<%= javascript_include_tag "validator.js" %>
<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>
<%
data = action_data
hire = data["hire"]
property = data["property"]
url = data["page"]
current_user = data["current_user"]
%>
<% 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 %>
<% if current_user.nil? %>
<script type="text/javascript">
alert("Please login before you hire.");
window.location.href = "<%= "/" + I18n.locale.to_s + url %>";
</script>
<% else %>
<h3 class="property_title"><%= 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") %>
<% end %>
<div id="orbit_calendar">
<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>
</div>
<div class="form-inline" id="range_selection"></div>
</div>
<div id='sec3' class="btn-toolbar">
<div class="btn-group calendar_mode">
<button class="btn btn-default mode_switch btn-sm" data-mode="timeGridDay" >day</button>
<button class="btn btn-default mode_switch btn-sm" data-mode="timeGridWeek" >week</button>
<button class="btn btn-default active mode_switch btn-sm" data-mode="dayGridMonth" >month</button>
</div>
<button id="refresh_btn" class="btn btn-default btn-sm">
<i class="icons-cycle"></i>
</button>
</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>
<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 calendar = new Calendar("#calendar",property_id);
function change_pick(target){
if( $(target).attr("id") == "pick_recurring_end_date"){
if($('#p_hire_recurring_interval').val() == ""){
alert("<%=t("property_hire.please_select_recurring_interval")%>");
$('#p_hire_recurring_interval').focus();
return;
}
$("#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("main-content").scrollIntoView();
}
$("#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');
})
$("#calendar").on("init_time",function(ev,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 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();
end_date = $("#p_hire_end_time").val();
interval = $("#p_hire_recurring_interval").val();
recurring_end_date = date_time;
}
end_date = (end_date == "" ? null : end_date);
start_date = (start_date == "" ? null : start_date);
if(start_date != null && end_date != null && $("#p_hire_start_time").val() != "" && $("#p_hire_end_time").val() != ""){
if(start_date > end_date){
if(target == "#pick_start_date"){
end_date = start_date.split(" ")[0] + " " + end_date.split(" ")[1];
$("#p_hire_end_time").val(end_date);
}else{
start_date = end_date.split(" ")[0] + " " + start_date.split(" ")[1];
$("#p_hire_start_time").val(start_date);
}
}
}
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(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);
}
</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 => "/xhr/property_hires/make_booking", 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>
</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;"} %>
<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>
<!-- ############# recurring ############# -->
<div class="form-group">
<%= f.label :recurring, t("property_hire.recurring"), :class => "col-sm-2 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 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;"} %>
<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>
</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 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=>"") %>
<% if hint1 == ""%>
<b>Please! </b><span> Select an interval time and recurring event end date.</span>
<% else %>
<span><b><%=hint1%></b></span>
<% end %>
</div>
</div>
<% if property.set_unavailibility %>
<div class="col-sm-offset-2 col-sm-5">
<b><%= t("property_hire.Unavailibility_Schedule") %></b>
<div>
<%= property.render_unavailable_message%>
</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" />
</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;"} %>
</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", :value => current_user.member_profile.mobile_no, :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.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.text_field :reason_for_hire, :class => "form-control", :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
</div>
</div>
<% if(property.enable_notes_selector rescue false) %>
<% property.notes_selector.each do |index,sub_hash| %>
<% name = sub_hash["name"][I18n.locale.to_s] %>
<% name = sub_hash["name"].values.select{|v| v.present?}.first.to_s if name.blank? %>
<% values = sub_hash["value"][I18n.locale.to_s] %>
<% 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" %>
<div class="col-sm-5">
<% values.each_with_index do |v,i| %>
<label class="checkbox-inline">
<input type="<%=type%>" name="p_hire[notes_selector][<%=index.to_s%>][]" value="<%=i%>" <%= (type=="radio" && i == 0) ? "checked=\"checked\"" : "" %>>
<%=v%>
</label>
<% end %>
<% if type == "checkbox" && (values.count > 1) %>
<small class="help-block"><%= t("property_hire.checkbox_hint") %></small>
<% end %>
</div>
</div>
<% 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.text_area :note_for_hire, :class => "form-control" %>
</div>
</div>
<% end %>
<% 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(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-2 control-label" %>
<div class="col-sm-5">
<% placeholder = property.custom_text(field_name,"placeholder") %>
<% if required %>
<%= 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", :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) %>
</div>
<% @form_index = @form_index +1 %>
<% end %>
<% end %>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<%= 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.;">
</div>
</div>
<% end %>
<div style="height: 50px;"></div>
<script type="text/javascript">
var property_id = "<%= property.id.to_s %>";
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");
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
}
data["interval"] = interval;
data["recurring_end_date"] = recurring_end_date;
var flag = false;
window.check_message = "";
$.ajax({
"url" : url,
"type" : "get",
"data" : data,
"dataType" : "json",
"async": false
}).done(function(data){
if(data.success){
$("#dates_validated").val("1");
$("#property-unavaialable-alert").hide();
flag = true;
if(!check_only){
$("#property-avaialable-alert").show();
}
}else{
$("#dates_validated").val("0");
$("#property-avaialable-alert").hide();
window.check_message = data.msg;
window.check_message = window.check_message.replace(/{(.*)}/,function(v){
return getDateString(new Date(RegExp.$1),datetime_format,is_chinese);
})
if(!check_only){
$("#property-unavaialable-alert").find("span").html(window.check_message);
$("#property-unavaialable-alert").show();
}
}
spinner.hide();
el.show();
})
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(),
etime = $("#p_hire_end_time").val();
var interval = null, recurring_end_date = null, is_recurring = false;;
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();
check_available(stime,etime,interval,recurring_end_date);
return false;
})
$("#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;
}
}
$("#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();
}
})
</script>
<% end %>

View File

@ -0,0 +1,72 @@
<% site = Site.first%>
<div id="address-field" class="modal hide fade">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3><%= (field_name rescue nil) || t("address_modal.default_title") %></h3>
</div>
<div class="modal-body form-horizontal address-modal">
<div class="tabbable">
<ul class="nav nav-tabs">
<% site.valid_locales.each do |locale|%>
<% active = (locale == I18n.locale.to_s ? ["active"] : [] ) %>
<%= content_tag :li,:class=>active,:for=>locale do%>
<%= link_to t(locale).to_s,".#{btn_class}.address_modal.#{locale}",:data=>{:toggle=>"tab"}%>
<% end %>
<% end %>
</ul>
<div class="tab-content">
<% site.valid_locales.each do |locale|%>
<!-- start of lang tab context -->
<% active = (locale == I18n.locale.to_s ? "active" : "" ) %>
<div class="tab-pane fade <%= active %> in %>" for="<%= locale %>">
<div class="control-group">
<label class="control-label muted" for="street_address"><%= t("address_modal.street_address") %></label>
<div class="controls">
<%= text_area_tag("#{field_name_basic}[temp][address_ext][#{locale}][street_address]",nil,:rows=>3,:func=>'street_address', :class=>"input-xlarge") %>
</div>
</div>
<div class="control-group">
<label class="control-label muted" for="city"><%= t("address_modal.city") %></label>
<div class="controls">
<%= text_field_tag("#{field_name_basic}[temp][address_ext][#{locale}][city]",'',:func=>'city', :class=>"input-xlarge") %>
</div>
</div>
<div class="control-group">
<label class="control-label muted" for="counties"><%= t("address_modal.county") %></label>
<div class="controls">
<%= text_field_tag("#{field_name_basic}[temp][address_ext][#{locale}][county]",'',:func=>'county', :class=>"input-xlarge") %>
</div>
</div>
<div class="control-group">
<label class="control-label muted" for="zip"><%= t("address_modal.zip") %></label>
<div class="controls">
<%= text_field_tag("#{field_name_basic}[temp][address_ext][#{locale}][zip]",nil,:class=>"input-mini",:func=>'zip', :class=>"input-xlarge") %>
</div>
</div>
<div class="control-group">
<label class="control-label muted" for="country"><%= t("address_modal.country") %></label>
<div class="controls">
<%= text_field_tag("#{field_name_basic}[temp][address_ext][#{locale}][country]",'',:func=>'country', :class=>"input-xlarge") %>
</div>
</div>
<div class="control-group hide">
<label class="control-label muted" for="indicator"><%= t("address_modal.Indicator") %></label>
<div class="controls">
<%= text_field_tag("#{field_name_basic}[temp][address_ext][#{locale}][indicator]",'',:func=>'country', :class=>"input-xlarge") %>
</div>
</div>
</div>
<!-- end of tab context -->
<% end %>
</div>
</div>
</div>
<div class="modal-footer">
<a class="btn" data-dismiss="modal" aria-hidden="true"><%=t(:close)%></a>
<a class="btn btn-primary returnDecide" data-dismiss="modal" aria-hidden="true"><%=t(:save_and_close)%></a>
</div>
</div>

View File

@ -0,0 +1,2 @@
<% @field_name = 'info' %>
<%= render :partial=>'admin/roles/attribute_field.html.erb',:locals => {attribute_field: attribute_field,attribute_field_counter: attribute_field_counter} %>

View File

@ -0,0 +1,25 @@
<% values ||=[]%>
<%= content_tag :div,:class=>"control-group" do%>
<label class="control-label muted" for=""><%= (defined? label_ext) ? label_ext : t("lists.markups.hint_text") %></label>
<div class="controls">
<div class="input-append">
<div class="tab-content">
<% @site_in_use_locales.each do |locale| %>
<% active = (locale == @site_in_use_locales.first ? "active in" : "'") %>
<%= content_tag :div,:class=>"tab-pane fade #{active}",:id=>"#{name_to_id(field_name)}_#{locale}" do%>
<% locale_value = values[locale.to_s] rescue nil%>
<%= text_area(field_name, locale,:value=>locale_value,:placeholder=> "#{t(locale).to_s}",:data=>{:type=>"lang_#{locale}"}) %>
<% end %>
<% end %>
</div>
<div class="btn-group" data-toggle="buttons-radio">
<% @site_in_use_locales.each do |locale| %>
<% active = (locale == @site_in_use_locales.first ? "active" : "") %>
<%= link_to t(locale).to_s,"##{name_to_id(field_name)}_#{locale}",:class=>"btn #{active}",:data=>{:toggle=>"tab"}%>
<% end %>
</div>
</div>
</div>
<% end %>

View File

@ -0,0 +1,62 @@
<% temp_field_name = field_name.gsub /\[\D*\]$/,'[temp]'%>
<% flag = (field_name.split(/\[.*\](?=\[)/)[-1][1...-1] != 'member_relations') %>
<div class="control-group" style="<%= 'display: flex;' if !flag %>">
<% if flag %>
<%= hidden_field_tag "#{temp_field_name}[count]",((values.keys.collect{|t| t.to_i}.max rescue nil) || 0 ),:class=>"list_count"%>
<%= hidden_field_tag "#{temp_field_name}[name]",field_name,:class=>"field_name"%>
<label class="control-label muted" for=""><%= t(:options)%></label>
<% else %>
<div>
<label class="control-label muted"><%= t('list.mode')%></label>
<div class="member_related">
<br>
<label class="control-label muted"><%= t('list.related')%></label>
</div>
</div>
<% end %>
<div class="controls add-input" style="<%= 'margin-left: 1em;' if !flag %>">
<div class="add-target single">
<% if flag %>
<%if values.blank? %>
<%= content_tag :div,:class=>"input-append" do%>
<% @site_in_use_locales.each do |locale| %>
<% last = (locale == @site_in_use_locales.last ? true : false) %>
<% p_value = value[locale.to_s] rescue nil%>
<%= text_field("#{field_name}[0]", locale,:placeholder=>t(locale).to_s,:class=>"input-medium",:data=>{:type=>"option_lang_0_#{locale}"}) %>
<% if last %>
<a href="#" class="btn remove-input"> <i class="icon-trash"></i> </a>
<% end %>
<% end %>
<% end %>
<%else%>
<%values.each do |index,value|%>
<%= content_tag :div,:class=>"input-append" do%>
<% @site_in_use_locales.each do |locale| %>
<% last = (locale == @site_in_use_locales.last ? true : false) %>
<% p_value = value[locale.to_s] rescue nil%>
<%= text_field("#{field_name}[#{index}]", locale,:value=>p_value,:placeholder=>t(locale).to_s,:class=>"input-medium", :data=>{:type=>"option_lang_#{index}_#{locale}"}) %>
<% if last %>
<a href="#" class="btn remove-input"> <i class="icon-trash"></i> </a>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
<% else %>
<%= content_tag :div,:class=>"input-append" do %>
<%= (hidden_field_tag "#{field_name}[0][_id]",values[0].id.to_s) if !values.blank? %>
<%= select_tag "#{field_name}[0][mode]", options_for_select([[t('list.passive'),'passive'],[t('list.active'),'active']],:selected => (values[0]['mode'] rescue nil)),:onChange => 'hidden_option(this)',:class=>'member_relations_opt' %>
<% relates = values.blank? ? [nil] : values[0]['related'] %>
<% relates = [nil] if relates.nil? %>
<div class="member_related">
<% Array(relates).each do |related|%>
<%= select_tag "#{field_name}[0][related][]", options_for_select(Role.all.desc(:created_at).map{|v1| [v1.title,v1.attribute_fields.sort_by{|v| v.key.to_i}.select{|v| v.id.to_s != id}.map{|v| ["&nbsp;&nbsp;#{v.title}".html_safe,v.id]}]}.flatten(2),:disabled=>Role.all.map{|v| v.title},:selected=> related), :class => 'member-relations-related' %>
<% end %>
</div>
<% end %>
<% end %>
</div>
<p class="add-btn"> <a href="#" class="member-relations-add trigger btn btn-mini btn-primary"><i class="icons-plus"></i> <%= t(:add) %></a> </p>
</div>
</div>

View File

@ -0,0 +1,25 @@
<% privacy_settings = ["public","logged_in","locked","only_admin"]%>
<% privacy_settings.each do |privacy_setting|%>
<% case privacy_setting
when "public"
icon = "icons-earth"
when "logged_in"
icon = "icons-users"
when "locked"
icon = "icons-lock"
when "only_admin"
icon = "fa fa-user-secret"
end
%>
<%= radio_button(field_key, "privacy_default", privacy_setting,:checked => (((attribute_field.privacy_default == privacy_setting) rescue false) ? true : false), :data=>{:type=>"radio"}) %><div class="<%=icon%>"></div><%= t("privacy_type.#{privacy_setting}").html_safe %>
<% end %>
<span style="margin-left: 2em;display: inline-flex;">
<label style="margin: 0;font-size: 1em;display: inline-flex;">
<%= hidden_field(field_key, "privacy_default_apply", :value=> "0") %>
<%= check_box_tag("#{field_key}[privacy_default_apply]","1",attribute_field["privacy_default_apply"]) %>
<%= t('apply_to_current_members.content') %>
</label>
<span style="margin-left: 3em;color: #E91E63;">
<%= t('apply_to_current_members.warning') %>
</span>
</span>

36
config/list.yml Normal file
View File

@ -0,0 +1,36 @@
forbidden_item_names:
- admin
- panel
- appfront
#NO_MULTI_TAG = ["select","date","radio_button","checkbox","date_durnation"]
markups:
text_field:
muti_lang_input_supprt: true
ext_support: true
panel: typeA
select:
muti_lang_input_supprt: false
ext_support: false
panel: typeB
date:
muti_lang_input_supprt: false
ext_support: false
panel: typeC
text_area:
muti_lang_input_supprt: true
ext_support: false
panel: typeD
radio_button:
muti_lang_input_supprt: false
ext_support: false
panel: typeE
checkbox:
muti_lang_input_supprt: false
ext_support: false
panel: typeE
hint_text:
muti_lang_input_supprt: false
ext_support: false
panel: typeF

View File

@ -1,5 +1,40 @@
en:
lists:
markups:
hint_text: Hint Text
property_hire:
date: "Date"
time: "Time"
please_choose_date: "Please choose date"
please_select: "Please select"
reserve: Reserve
files_links: "Files, Links"
disable_content_page: Disable content page
disable_view_calendar_page: 'Disable "Calendar" page'
display_img: Display Cover Image in Content Page
carousel_image: Carousel Image
carousel_image_title: Carousel Image(display at the bottom of show page)
custom_carousel_image_width_hint: "If blank, width will be default value."
carousel_image_width: Carousel Image Width
default_carousel_image_width: Default Carousel Image Width
cover_image_display_setting: Cover Image display setting
full_width: Full width
up_left_corner: Up-left corner
up_right_corner: Up-right corner
name: Show Name
placeholder: Placeholder
disable: Disable
time_title: Title
reservation_limit: "Reservation limit(0 present no limit)"
set_availability: Set Availability
reservation_fields: Reservation Fields
to_require: Should Be Filled?
please_save: 'Please click "Save Order" button when you done.'
position: Position
save_order: Save Order
order: Order
custom_fields_setting: Custom fields Setting
custom_fields: Custom fields
please_hire_after_date: "Please hire after %{date}!"
property_is_unavailable_during_this_time: "Property is unavailable during this time."
property_is_already_hired_during_this_time: "Property is already hired during this time."
@ -8,7 +43,7 @@ en:
confirm: Confirm
cancel: Cancel
pick_from_calendar: Pick from calendar
how_many_months_ago_can_be_hired: "How many months ago can be hired?"
how_many_months_ago_can_be_hired: "Unavailable for reservation before how many months?"
month: "%{month} month"
no_limit: No limit
none: None
@ -40,7 +75,7 @@ en:
week: Week
recurring_end_date: Recurring End Date
save: Save
property_hire: Manage of hire
property_hire: Property Reservation
my_bookings: My Bookings
settings: Settings
auto_approve: Auto approve
@ -50,8 +85,10 @@ en:
edit_location: Edit Location
add_location: Add Location
unavailability: Unavailability
unavailable_time: Unavailability
available_time: Time Period
title: Property Title
property_usage: Usage for property
property_usage: Subtitle
note: Note
property_number: Property Number
can_be_hired: Available for hire
@ -66,7 +103,7 @@ en:
limit_end_time: Limit end time
start_time: Start Time
end_time: End Time
weekdays: Unavailability weekdays
weekdays: Unavailable days in a week
start_date: From Date
end_date: To Date
description: Unavailability Description

View File

@ -1,5 +1,40 @@
zh_tw:
lists:
markups:
hint_text: 提示文字
property_hire:
date: "日期"
time: "時段"
please_choose_date: "請選擇日期"
please_select: "請選擇"
reserve: 預約本日
files_links: "檔案與連結"
disable_content_page: 關閉內容頁
disable_view_calendar_page: '關閉"查詢目前借用狀況"頁面'
display_img: 內容頁顯示封面圖片
carousel_image: 輪播圖片
carousel_image_title: 輪播圖片(在show頁面底部顯示)
custom_carousel_image_width_hint: "未填寫,則使用預設寬度"
carousel_image_width: 輪播圖片寬度
default_carousel_image_width: 預設輪播圖片寬度
cover_image_display_setting: 封面圖片顯示設定
full_width: 滿版呈現
up_left_corner: 左上角
up_right_corner: 右上角
name: 顯示名稱
placeholder: 提示文字
disable: 關閉
time_title: 時段名稱
reservation_limit: "預約數限制(0代表無限制)"
set_availability: 設定開放時段
reservation_fields: 預約欄位設定
to_require: 是否必填
please_save: '調整完後, 請點選"儲存順序"'
position: 位置
save_order: 儲存順序
order: 排序
custom_fields_setting: 客製化欄位設定
custom_fields: 客製預約欄位
recurring_end_date_must_exceed_time: "週期結束時間需超過借用結束時間%{time}!"
1_week: "一週"
1_month: "一個月"
@ -31,7 +66,7 @@ zh_tw:
confirm: 確認
cancel: 取消
pick_from_calendar: 從日曆上選擇
how_many_months_ago_can_be_hired: 多少個月內才可被借用
how_many_months_ago_can_be_hired: 多少個月前不開放預約
month: "%{month}月"
no_limit: 無限制
none:
@ -65,7 +100,7 @@ zh_tw:
save: Save
my_bookings: My Bookings
settings: 設定
property_hire: 借用管理
property_hire: 場地設備預約
manage_locations: Manage Locations
location: 位置
auto_approve: Auto approve
@ -73,10 +108,12 @@ zh_tw:
edit_location: Edit Location
add_location: Add Location
unavailability: 不可借用
unavailable_time: 不開放時段
available_time: 開放時段
title: 名稱
select_interval: 選則週期
check_availibility: 檢查是否可借用
property_usage: 用途
property_usage: 副標題
note: 說明
property_number: 編號
can_be_hired: 可供借用
@ -86,10 +123,10 @@ zh_tw:
owner_email: 管理人Email
owner_phone: 管理人聯絡電話
price: Price
set_unavailibility: 設定為不可借用
set_unavailibility: 設定不開放時段
start_time: 可被借用開始時間
end_time: 可被借用結束時間
weekdays: 不可借用工作
weekdays: 每週不開放預約
start_date: 套用限制開始日期
end_date: 套用限制結束日期
description: Unavailability Description

View File

@ -16,6 +16,7 @@ Rails.application.routes.draw do
delete "delete_booking_details"
get "edit_hire"
patch "update_hire"
get "custom_fields"
end
collection do
get "my_bookings"
@ -24,6 +25,8 @@ Rails.application.routes.draw do
get "manage_locations"
get "add_location"
post "create_location"
get "order"
post "updateorder"
end
end
end

View File

@ -15,7 +15,7 @@ module PropertyHire
head_label_i18n 'property_hire.property_hire', icon_class: "icons-map"
available_for "users"
active_for_controllers (['admin/property_hires'])
head_link_path "my_bookings_admin_property_hires_path"
head_link_path "admin_property_hires_path"
context_link 'property_hire.my_bookings',
:link_path=>"my_bookings_admin_property_hires_path" ,
@ -28,7 +28,11 @@ module PropertyHire
:priority=>2,
:active_for_action=>{'admin/property_hires'=>"index"},
:available_for => 'sub_managers'
context_link 'property_hire.order',
:link_path=>"order_admin_property_hires_path" ,
:priority=>2,
:active_for_action=>{'admin/property_hires'=>"order"},
:available_for => 'managers'
context_link 'new_',
:link_path=>"new_admin_property_hire_path" ,
:priority=>3,

View File

@ -0,0 +1,18 @@
<table class="table table-striped">
<thead>
<tr data-list="headers" data-level="0">
<th>{{column}}</th>
</tr>
</thead>
<tbody data-list="properties" data-level="0">
<tr>
<td><a href="{{url_to_show}}">{{title}}</a></td>
<td><img width="150" src="{{image-thumb}}" alt="property image"></td>
<td>{{location}}</td>
<td data-list="actions" data-level="1">
<a href="{{link}}" class="btn {{btn-class}}">{{text}}</a>
</td>
</tr>
</tbody>
</table>
{{pagination_goes_here}}

View File

@ -0,0 +1,14 @@
<div class="property_index_3_col" >
<ul class="property_list" data-level="0" data-list="properties">
<li class="property_item col-md-4 col-xl-3">
<div class="property_img_wrap">
<a href="{{url_to_show}}" title="{{title}}"><img src="{{image-thumb}}" alt="{{title}}"></a>
</div>
<div class="property_content_wrap">
<h4><a href="{{url_to_show}}" title="{{title}}">{{title}}</a></h4>
</div>
</li>
</ul>
</div>
<div class="clearfix"></div>
{{pagination_goes_here}}

View File

@ -0,0 +1,14 @@
<div class="property_index_3_col" >
<ul class="property_list" data-level="0" data-list="properties">
<li class="property_item col-sm-4 col-md-3">
<div class="property_img_wrap">
<a href="{{url_to_show}}" title="{{title}}"><img src="{{image-thumb}}" alt="{{title}}"></a>
</div>
<div class="property_content_wrap">
<h4><a href="{{url_to_show}}" title="{{title}}">{{title}}</a></h4>
</div>
</li>
</ul>
</div>
<div class="clearfix"></div>
{{pagination_goes_here}}

View File

@ -0,0 +1,28 @@
{
"frontend": [
{
"filename" : "index",
"name" : {
"zh_tw" : "1. 列表",
"en" : "1. List"
},
"thumbnail" : "thumb.png"
},
{
"filename" : "index_3_col",
"name" : {
"zh_tw" : "2. 三欄式圖文",
"en" : "2. 3-Column Standard Image + Text Lite"
},
"thumbnail" : "event_news_thumb1.png"
},
{
"filename" : "index_4_col",
"name" : {
"zh_tw" : "3. 四欄式圖文",
"en" : "3. 4-Column Standard Image + Text Lite"
},
"thumbnail" : "event_news_thumb2.png"
}
]
}

View File

@ -0,0 +1,19 @@
<table class="table table-striped">
<thead>
<tr style="text-align: center;">
<td colspan="2"><img width="600" src="{{image}}"></td>
</tr>
</thead>
<tbody data-list="data" data-level="0">
<tr>
<td>{{header}}</td>
<td>{{value}}</td>
</tr>
</tbody>
</table>
<div>
<a href="{{back_url}}" class="btn btn-warning">Back</a>
<span data-list="actions" data-level="0">
<a href="{{link}}" class="btn {{btn-class}}">{{text}}</a>
</span>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -2,7 +2,27 @@ $:.push File.expand_path("../lib", __FILE__)
# Maintain your gem's version:
require "property_hire/version"
begin
require "yaml"
require "erb"
data = File.open(File.join(File.dirname(__FILE__), 'config', 'list.yml')).read
$property_list = YAML.safe_load(ERB.new(data).result(binding)).map{|k,v| [k.to_sym,v]}.to_h
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'
end
end
end
# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
s.name = "property_hire"