diff --git a/app/assets/javascripts/property_hire/property-field-forms.js b/app/assets/javascripts/property_hire/property-field-forms.js new file mode 100644 index 0000000..2efd0f0 --- /dev/null +++ b/app/assets/javascripts/property_hire/property-field-forms.js @@ -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(); + }; + } + }); + }); + } +}); \ No newline at end of file diff --git a/app/assets/javascripts/property_hire_calendar_frontend.js b/app/assets/javascripts/property_hire_calendar_frontend.js index 750f25a..a48237e 100644 --- a/app/assets/javascripts/property_hire_calendar_frontend.js +++ b/app/assets/javascripts/property_hire_calendar_frontend.js @@ -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){ diff --git a/app/assets/stylesheets/admin/card.scss b/app/assets/stylesheets/admin/card.scss new file mode 100644 index 0000000..6b7183b --- /dev/null +++ b/app/assets/stylesheets/admin/card.scss @@ -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; + } + } + } + } +} diff --git a/app/assets/stylesheets/admin/properties.css b/app/assets/stylesheets/admin/properties.css new file mode 100644 index 0000000..f08ea35 --- /dev/null +++ b/app/assets/stylesheets/admin/properties.css @@ -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; +} + diff --git a/app/assets/stylesheets/property_hire_calendar.scss b/app/assets/stylesheets/property_hire_calendar.scss index a4c85bf..6beb81c 100644 --- a/app/assets/stylesheets/property_hire_calendar.scss +++ b/app/assets/stylesheets/property_hire_calendar.scss @@ -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; diff --git a/app/controllers/admin/property_hires_controller.rb b/app/controllers/admin/property_hires_controller.rb index f984d5f..02d428d 100644 --- a/app/controllers/admin/property_hires_controller.rb +++ b/app/controllers/admin/property_hires_controller.rb @@ -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? diff --git a/app/controllers/property_hires_controller.rb b/app/controllers/property_hires_controller.rb index 9a31955..994e2ef 100644 --- a/app/controllers/property_hires_controller.rb +++ b/app/controllers/property_hires_controller.rb @@ -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 += "
".html_safe diff --git a/app/helpers/admin/p_hire_field_helper.rb b/app/helpers/admin/p_hire_field_helper.rb new file mode 100644 index 0000000..fbf99f0 --- /dev/null +++ b/app/helpers/admin/p_hire_field_helper.rb @@ -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]})" + ""+ + label_tag(key,(!@require.blank? ? '*'+title : title),:class=>"col-sm-#{@col} control-label muted",:style =>'display: contents;')+ + tag(:br)+"#{plc}" + 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 \ No newline at end of file diff --git a/app/helpers/admin/p_hire_field_values_helper.rb b/app/helpers/admin/p_hire_field_values_helper.rb new file mode 100644 index 0000000..a3fdbdc --- /dev/null +++ b/app/helpers/admin/p_hire_field_values_helper.rb @@ -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 \ No newline at end of file diff --git a/app/helpers/admin/property_hires_helper.rb b/app/helpers/admin/property_hires_helper.rb index 78d05a1..83f5c35 100644 --- a/app/helpers/admin/property_hires_helper.rb +++ b/app/helpers/admin/property_hires_helper.rb @@ -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 = "
+
+
" + @site_in_use_locales.each_with_index do |locale,i| + text += "
+ #{f.text_field_tag("#{f.object_name}[#{field_name}][#{type}][#{locale}]", f.object.custom_text(field_name,type,locale))} +
" + end + text += "
" + @site_in_use_locales.each_with_index do |locale,i| + text += "#{t(locale)}" + end + text += "
+
+
+
" + text.html_safe + end module HireMethod extend ActionView::Helpers::UrlHelper extend ActionView::Helpers::TagHelper diff --git a/app/models/p_hire.rb b/app/models/p_hire.rb index ea66182..f0c708b 100644 --- a/app/models/p_hire.rb +++ b/app/models/p_hire.rb @@ -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 diff --git a/app/models/p_hire_field.rb b/app/models/p_hire_field.rb new file mode 100644 index 0000000..de2be65 --- /dev/null +++ b/app/models/p_hire_field.rb @@ -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 \ No newline at end of file diff --git a/app/models/p_hire_field_value.rb b/app/models/p_hire_field_value.rb new file mode 100644 index 0000000..917cf7c --- /dev/null +++ b/app/models/p_hire_field_value.rb @@ -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/) ? "#{field_value}" : field_value + field_value = (field_value =~ /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/i) ? "#{field_value}" : 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 diff --git a/app/models/property.rb b/app/models/property.rb index ef60f47..ec13589 100644 --- a/app/models/property.rb +++ b/app/models/property.rb @@ -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 \ No newline at end of file diff --git a/app/models/property_carousel_image.rb b/app/models/property_carousel_image.rb new file mode 100644 index 0000000..48efabd --- /dev/null +++ b/app/models/property_carousel_image.rb @@ -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 diff --git a/app/models/property_day_setting.rb b/app/models/property_day_setting.rb new file mode 100644 index 0000000..f405ac4 --- /dev/null +++ b/app/models/property_day_setting.rb @@ -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 \ No newline at end of file diff --git a/app/models/property_field_set.rb b/app/models/property_field_set.rb new file mode 100644 index 0000000..3ca8b59 --- /dev/null +++ b/app/models/property_field_set.rb @@ -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 \ No newline at end of file diff --git a/app/models/property_file.rb b/app/models/property_file.rb new file mode 100644 index 0000000..358ca24 --- /dev/null +++ b/app/models/property_file.rb @@ -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 diff --git a/app/models/property_hire_setting.rb b/app/models/property_hire_setting.rb index c38ba06..fb02388 100644 --- a/app/models/property_hire_setting.rb +++ b/app/models/property_hire_setting.rb @@ -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 diff --git a/app/models/property_link.rb b/app/models/property_link.rb new file mode 100644 index 0000000..684838f --- /dev/null +++ b/app/models/property_link.rb @@ -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 \ No newline at end of file diff --git a/app/views/admin/property_hires/_attribute_field.html.erb b/app/views/admin/property_hires/_attribute_field.html.erb new file mode 100644 index 0000000..663e94f --- /dev/null +++ b/app/views/admin/property_hires/_attribute_field.html.erb @@ -0,0 +1,135 @@ +
+<% + attribute_field.af_count ? @af_counter = attribute_field_counter + attribute_field.af_count : @af_counter = attribute_field_counter +%> +
+
+
+ <%= hidden_field "#{@field_name}[p_hire_fields][#{@af_counter}]","disabled",:value=>attribute_field.disabled,:class=>"toggle-check", :data=>{:deploy=>"right"} %> + +
+
+ <%= t(:delete_)%> + <%= hidden_field "#{@field_name}[p_hire_fields][#{@af_counter}]","to_delete",:value=>false,:class=>"attribute_field_to_delete"%> + Reset +

Field <%= @af_counter + 1 %>

+
+
+
+ +
+ <%= text_field "#{@field_name}[p_hire_fields][#{@af_counter}]","key",:value=>attribute_field.key, :data=>{:type=>"key"} %> +
+
+ + <%= 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]"}%> + +
+ +
+ + +
+
+
+ +
+ +
+
+
+ +
+ + <%= content_tag :div,:class=>"field-type default fade in #{show_property_type_panel(attribute_field,"typeA")}" do%> +
+ +
+ + +
+
+ <%= 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 %> +
+ +
+ <%= select "#{@field_name}[p_hire_fields][#{@af_counter}][typeC]","format",Admin::AttributeValuesViewHelper::OPT,:class=>"dataType",:selected=>attribute_field["typeC"]["format"] %> +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+ <% 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%> +
+ +
+ +
+
+ <%= 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%> + +
\ No newline at end of file diff --git a/app/views/admin/property_hires/_form.html.erb b/app/views/admin/property_hires/_form.html.erb index 392b52e..cd68226 100644 --- a/app/views/admin/property_hires/_form.html.erb +++ b/app/views/admin/property_hires/_form.html.erb @@ -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; + } <% 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 @@
@@ -132,6 +169,10 @@
+ +
@@ -168,6 +209,53 @@
+ +
+ <%= f.label :display_img, t("property_hire.display_img"), :class => "control-label muted" %> +
+ <%= f.check_box :display_img %> +
+
+ + + <% image_display_class_relation = {"full_width"=>"full-size-img","up_left_corner"=>"pull-left","up_right_corner"=>"pull-right"} %> +
+ <%= f.label :image_display_class, t("property_hire.cover_image_display_setting"), :class => "control-label muted" %> +
+ <% image_display_class_relation.each.with_index do |(key,value),i| %> + + <% end %> +
+
+ + +
@@ -307,27 +395,85 @@ <% end %>
+ +
+
+ <%= f.label :set_availability, t("property_hire.set_availability"), :class => "control-label muted" %> +
+ <%= f.check_box :set_availability %> +
+
+ <% if @property.set_availability %> +
+ <% else %> + +
<% 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| %> -
- -
- -
-
- - <%= f.fields_for field_name do |sub_f|%> - - +
+ + + + + + + + + + <% fields_name.each do |field_name| %> + + + + + + + <% end %> - - - <% end %> + +
<%= t('property_hire.field_name') %><%= t('property_hire.name') %><%= t('property_hire.placeholder') %><%= t('property_hire.disable') %><%= t('property_hire.required') %>
+ <%= t("property_hire.#{field_name}") %> + + <%= render_custom_text_field(f,field_name,"name") %> + + <%= render_custom_text_field(f,field_name,"placeholder") %> + + + <%= check_box_tag("#{f.object_name}[#{field_name}][enable]", "0" , (f.object.send(field_name)["enable"] == "0" rescue false)) %> + + + <%= check_box_tag("#{f.object_name}[#{field_name}][required]", "true" , (f.object.send(field_name)["required"] == "true" rescue false)) %> +
+

<% field_name = "enable_notes_selector" %> @@ -431,7 +577,7 @@
<%= 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 %>
@@ -439,7 +585,7 @@
<%= 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 %>
@@ -456,6 +602,7 @@ <%= link_to t('cancel'), admin_property_hires_path, :class=>"btn" %>
diff --git a/app/views/admin/property_hires/_form_file.html.erb b/app/views/admin/property_hires/_form_file.html.erb new file mode 100644 index 0000000..b276b8c --- /dev/null +++ b/app/views/admin/property_hires/_form_file.html.erb @@ -0,0 +1,63 @@ +<% if form_file.nil? || form_file.new_record? %> +
+<% else %> +
+ <% 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 %> +
+ + + + <% if form_file.fields["title"].options[:localize] %> + <% @site_in_use_locales.each_with_index do |locale, i| %> + <%= 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 %> + + <% end %> + <% else %> + <%= f.text_field :title, :class => "input-medium", placeholder: t(:alternative) %> + <% end %> + + + + <% if form_file.fields["description"].options[:localize] %> + <% @site_in_use_locales.each_with_index do |locale, i| %> + <%= 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 %> + + <% end %> + <% else %> + <%= f.text_field :description, :class => "input-medium", placeholder: t(:description) %> + <% end %> + + + <% if form_file.nil? || form_file.new_record? %> + + + + <% else %> + + <%= f.hidden_field :id %> + + <%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %> + + <% end %> +
+
\ No newline at end of file diff --git a/app/views/admin/property_hires/_form_file_link.html.erb b/app/views/admin/property_hires/_form_file_link.html.erb new file mode 100644 index 0000000..8233f36 --- /dev/null +++ b/app/views/admin/property_hires/_form_file_link.html.erb @@ -0,0 +1,93 @@ + +
+ +
+ + + <% if !f.object.nil? && !f.object.property_links.blank? %> +
+ <% 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 %> +
+
+ <% end %> + + +
+
+

+ <%= hidden_field_tag 'property_link_field_count', f.object.property_links.count %> + <%= t(:add) %> +

+
+
+ + +
+ +
+ + + <% if !f.object.nil? && !f.object.property_files.blank? %> +
+ <% 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 %> +
+
+ <% end %> + + +
+
+

+ <%= hidden_field_tag 'property_file_field_count', f.object.property_files.count %> + <%= t(:add) %> +

+ +
+
+ \ No newline at end of file diff --git a/app/views/admin/property_hires/_form_image.html.erb b/app/views/admin/property_hires/_form_image.html.erb new file mode 100644 index 0000000..a5cb635 --- /dev/null +++ b/app/views/admin/property_hires/_form_image.html.erb @@ -0,0 +1,47 @@ + +
+ +
+ +
+
+
+ <% if form_image.file.file %> + <%= image_tag form_image.file %> + <% else %> + + <% end %> +
+
+ + <%= t(:select_image) %> + <%= t(:change) %> + <%= f.file_field :file %> + + <%= t(:cancel) %> +
+
+
+ <% @site_in_use_locales.each do |locale| %> + <%= f.fields_for :description_translations do |f| %> +
+ +
+ <%= f.text_field locale, value: (form_image.description_translations[locale.to_s] rescue nil) %> +
+
+ <% end %> + <% end %> +
\ No newline at end of file diff --git a/app/views/admin/property_hires/_form_link.html.erb b/app/views/admin/property_hires/_form_link.html.erb new file mode 100644 index 0000000..e753f15 --- /dev/null +++ b/app/views/admin/property_hires/_form_link.html.erb @@ -0,0 +1,30 @@ +
+ + <%= f.text_field :url, class: "input-large", placeholder: t(:url) %> + + + <% if form_link.fields["title"].options[:localize] %> + <% @site_in_use_locales.each_with_index do |locale, i| %> + <%= 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 %> + + <% end %> + <% else %> + <%= f.text_field :title, :class => "input-large", placeholder: t(:url_alt) %> + <% end %> + + + <% if form_link.nil? || form_link.new_record? %> + + + + <% else %> + + <%= f.hidden_field :id %> + + <%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %> + + <% end %> +
\ No newline at end of file diff --git a/app/views/admin/property_hires/_support_member_form_js.erb b/app/views/admin/property_hires/_support_member_form_js.erb new file mode 100644 index 0000000..d2f18e8 --- /dev/null +++ b/app/views/admin/property_hires/_support_member_form_js.erb @@ -0,0 +1,298 @@ +<%#= encoding: utf-8 %> + + + + + + + + + + \ No newline at end of file diff --git a/app/views/admin/property_hires/_time_form.html.erb b/app/views/admin/property_hires/_time_form.html.erb new file mode 100644 index 0000000..9aef44f --- /dev/null +++ b/app/views/admin/property_hires/_time_form.html.erb @@ -0,0 +1,44 @@ +
+<% key = (defined?(key) && key) ? key : "new_key" + day = (defined?(day) && day) ? key : "new_day" +%> + +
+ <%= f.label "time_title_#{key}_#{day}", t("property_hire.time_title"), :class => "control-label muted" %> +
+ <%= f.text_field :title, :id=>"time_title_#{key}_#{day}" %> +
+
+
+ <%= f.label :start_time, t("property_hire.limit_start_time"), :class => "control-label muted" %> +
+ <%= f.datetime_picker :start_time, :picker_type => "time", :no_label => true, :new_record => @property.new_record? %> +
+
+
+ <%= f.label :end_time, t("property_hire.limit_end_time"), :class => "control-label muted" %> +
+ <%= f.datetime_picker :end_time, :picker_type => "time", :no_label => true, :new_record => @property.new_record? %> +
+
+<%= f.hidden_field :key, :value => key %> +<%= f.hidden_field :day, :value => day %> +
+ <%= f.label "reservation_limit_#{key}_#{day}", t("property_hire.reservation_limit"), :class => "control-label muted" %> +
+ <%= f.number_field :reservation_limit, :id=>"reservation_limit_#{key}_#{day}" %> +
+
+
\ No newline at end of file diff --git a/app/views/admin/property_hires/custom_fields.erb b/app/views/admin/property_hires/custom_fields.erb new file mode 100644 index 0000000..85177a6 --- /dev/null +++ b/app/views/admin/property_hires/custom_fields.erb @@ -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 -%> + +<%= 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 %> + +

<%= @attribute.title %>

+
+ +
+ <%= render partial: "attribute_field",collection: @attribute.p_hire_fields.asc(:_id)%> +
+ +
+ + <%= 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" %> +
+
+<% end %> + + +<% content_for :page_specific_javascript do -%> + <%= render 'support_member_form_js' %> +<% end -%> \ No newline at end of file diff --git a/app/views/admin/property_hires/index.html.erb b/app/views/admin/property_hires/index.html.erb index 7a8d900..84c04fe 100644 --- a/app/views/admin/property_hires/index.html.erb +++ b/app/views/admin/property_hires/index.html.erb @@ -15,6 +15,7 @@ diff --git a/app/views/admin/property_hires/order.html.erb b/app/views/admin/property_hires/order.html.erb new file mode 100644 index 0000000..e93d807 --- /dev/null +++ b/app/views/admin/property_hires/order.html.erb @@ -0,0 +1,191 @@ +<% content_for :page_specific_css do %> + <%= stylesheet_link_tag "admin/properties" %> +<% end %> + +
<%= t("property_hire.please_save") %>
+ + + + + + + + + <% @properties.each_with_index do |property,i| %> + + + + + + <% end %> + +
<%= t("property_hire.position") %><%= t("property_hire.title") %>
+
<%= (i + 1).to_s %>
+
+
<%= property.title %>
+
+ + + \ No newline at end of file diff --git a/app/views/admin/property_hires/settings.html.erb b/app/views/admin/property_hires/settings.html.erb index 6e81629..99dbf4a 100644 --- a/app/views/admin/property_hires/settings.html.erb +++ b/app/views/admin/property_hires/settings.html.erb @@ -29,6 +29,24 @@ <%= f.check_box :auto_approve %>
+
+ <%= f.label :disable_content_page, t("property_hire.disable_content_page"), :class => "control-label muted" %> +
+ <%= f.check_box :disable_content_page %> +
+
+
+ <%= f.label :disable_view_calendar_page, t("property_hire.disable_view_calendar_page"), :class => "control-label muted" %> +
+ <%= f.check_box :disable_view_calendar_page %> +
+
+
+ <%= f.label :carousel_image_width, t("announcement.default_carousel_image_width"), :class => "control-label muted" %> +
+ <%= f.text_field :carousel_image_width %> +
+
diff --git a/app/views/property_hires/hire.html.erb b/app/views/property_hires/hire.html.erb index 122928d..d257dc9 100644 --- a/app/views/property_hires/hire.html.erb +++ b/app/views/property_hires/hire.html.erb @@ -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" %> <% - 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"] %> + <% if !property.can_be_hired %> <% else %> -

<%= property.title %>

+

<%= property.title %>

+
+
+<% if property.display_img %> +
+ <%=property.title%> + <%=property.title%> +
+<% end %> +

<%= property.property_usage %>

+<% property_carousel_images = property.property_carousel_images %> +<% if property_carousel_images.count != 0 %> + +<% end %> +
<%= property.note %>
+
+ <% if session["hire-save-msg"].present? %> <% session.delete("hire-save-msg") %> <% end %> -
+
+
+
+ + +
+

+
+
+ +
+ + <%= 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 %> +
+ + +
+
+
+
+
-
-
- -
- - <%= 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 %> -
- - -
-
-
-
-
+
<%= form_for hire, :url => "/xhr/property_hires/make_booking", html: { class: "form-horizontal" } do |f| %> + <% if property.set_availability %> +
+ <%= f.label :date, "*"+t("property_hire.date"), :class => "col-sm-4 control-label" %> +
+ <%= f.text_field :date, :value=>t("property_hire.please_choose_date"),:readonly=>"",:onclick=>"goto_calendar()" %> +
+
+
+ <%= f.label :time, "*"+t("property_hire.time"), :class => "col-sm-4 control-label" %> +
+ <%= f.text_field :time, :value=>t("property_hire.please_choose_date"),:readonly=>"",:onclick=>"goto_calendar()" %> +
+
+ <% else %>
- <%= f.label :start_time, "*"+t("property_hire.start_time"), :class => "col-sm-2 control-label" %> -
+ <%= f.label :start_time, "*"+t("property_hire.start_time"), :class => "col-sm-4 control-label" %> +
<%= f.datetime_picker :start_time, :no_label => true, :new_record => hire.new_record?,:class => "pull-left", :data=>{"picker-type" => "range", "range" => "start", "fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
- <%= f.label :end_time, "*"+t("property_hire.end_time"), :class => "col-sm-2 control-label" %> -
+ <%= f.label :end_time, "*"+t("property_hire.end_time"), :class => "col-sm-4 control-label" %> +
<%= 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;"} %>
+ <% end %>
- <%= 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" %>
<%= f.check_box :recurring %>
>
- <%= 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" %>
<%= 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;"}} %>
- <%= f.label :recurring_end_date, "*"+t("property_hire.recurring_end_date"), :class => "col-sm-2 control-label" %> -
+ <%= f.label :recurring_end_date, "*"+t("property_hire.recurring_end_date"), :class => "col-sm-4 control-label" %> +
<%= 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;"} %>
@@ -207,7 +467,7 @@
-
+
<% if property.set_unavailibility %> -
+
<%= t("property_hire.Unavailibility_Schedule") %>
<%= property.render_unavailable_message%> @@ -230,33 +490,33 @@
- -
- <%= 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" %>
<%= f.text_field :hiring_person_email, :class => "form-control", :value => current_user.member_profile.email, :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
- <%= f.label :hiring_person_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" %>
<%= f.text_field :hiring_person_number, :class => "form-control", :value => current_user.member_profile.mobile_no, :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
- <%= f.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" %>
<%= 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 "") %>
- <%= 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" %>
<%= f.text_field :reason_for_hire, :class => "form-control", :data => {"fv-validation" => "required;", "fv-messages" => "Cannot be empty;"} %>
@@ -269,7 +529,7 @@ <% values = sub_hash["value"].values.select{|v| v.present?}.first.to_s if values.blank? %> <% type = sub_hash["type"] %>
- <%= f.label "notes_selector[#{index}]", name, :class => "col-sm-2 control-label" %> + <%= f.label "notes_selector[#{index}]", name, :class => "col-sm-4 control-label" %>
<% values.each_with_index do |v,i| %>