diff --git a/app/assets/javascripts/app/lib/app_post/business_hours.js.coffee b/app/assets/javascripts/app/lib/app_post/business_hours.js.coffee index 0bbc9bd18..13486b66c 100644 --- a/app/assets/javascripts/app/lib/app_post/business_hours.js.coffee +++ b/app/assets/javascripts/app/lib/app_post/business_hours.js.coffee @@ -21,12 +21,12 @@ class App.BusinessHours extends Spine.Controller sun: App.i18n.translateInline('Sunday') render: => - maxTimeframeDay = _.max @hours, (day) -> day.timeframes.length + @updateMaxTimeframes() html = App.view('generic/business_hours') days: @days hours: @options.hours - maxTimeframes: maxTimeframeDay.timeframes.length + maxTimeframes: @maxTimeframes @html html @@ -35,13 +35,21 @@ class App.BusinessHours extends Spine.Controller showMeridian: false # meridian = am/pm .on 'changeTime.timepicker', @onTimeChange + @el.toggleClass 'is-invalid', !@validate() + + updateMaxTimeframes: => + maxTimeframeDay = _.max @hours, (day) -> day.timeframes.length + @maxTimeframes = maxTimeframeDay.timeframes.length + onTimeChange: (event) => input = @$(event.currentTarget) day = input.attr('data-day') slot = input.attr('data-slot') i = input.attr('data-i') - console.log "something changed", event.time - @options.hours[day].timeframes[slot][i] = "#{event.time.hours}:#{event.time.minutes}" + @options.hours[day].timeframes[slot][i] = event.time.hoursAndMinutes + console.log event.time.hoursAndMinutes + + @el.toggleClass 'is-invalid', !@validate() addTime: (event) => day = @$(event.currentTarget).attr('data-day') @@ -58,3 +66,54 @@ class App.BusinessHours extends Spine.Controller day = checkbox.attr('data-target') @options.hours[day].active = checkbox.prop('checked') @$("[data-day=#{day}]").toggleClass('is-active', checkbox.prop('checked')) + + @el.toggleClass 'is-invalid', !@validate() + + validate: => + for day, hours of @options.hours + break if not hours.active + + # edge case: full day + if hours.timeframes[0][0] is '00:00' and hours.timeframes[hours.timeframes.length - 1][1] is '00:00' + return true + + # check each timeframe + for slot in [0..hours.timeframes.length - 1] + + # check if start time is earlier than end time + if not @earlier hours.timeframes[slot][0], hours.timeframes[slot][1] + return false + + # check if start time of slot is later than end time of slot before + if slot > 0 && not @later hours.timeframes[slot][0], hours.timeframes[slot-1][1] + return false + + # all passed + return true + + later: (a, b) -> + # a later b + # input 'hh:mm' + [ha, ma] = a.split(':').map (val) -> parseInt val, 10 + [hb, mb] = b.split(':').map (val) -> parseInt val, 10 + + if ha > hb + return true + if ha is hb + if ma > mb + return true + return false + + earlier: (a, b) -> + # a earlier than b + # input 'hh:mm' + + [ha, ma] = a.split(':').map (val) -> parseInt val, 10 + [hb, mb] = b.split(':').map (val) -> parseInt val, 10 + + if ha < hb + return true + if ha is hb + if ma < mb + return true + return false \ No newline at end of file diff --git a/app/assets/javascripts/app/lib/bootstrap/bootstrap-timepicker.js b/app/assets/javascripts/app/lib/bootstrap/bootstrap-timepicker.js index 29719efd6..48fb283ea 100644 --- a/app/assets/javascripts/app/lib/bootstrap/bootstrap-timepicker.js +++ b/app/assets/javascripts/app/lib/bootstrap/bootstrap-timepicker.js @@ -12,7 +12,8 @@ * - automatically jump from hours to minutes when typing in a number * - continue stepping from manually input value * - activate meridian on class 'time--12' - * - normalize output hour to 24-hour clock + * - normalize output to 24-hour clock + * - add hoursAndMinutes * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -142,7 +143,7 @@ } } else { if (this.hour <= 0) { - this.hour = this.maxHours - 1; + this.hour = this.maxHours; } else { this.hour--; } @@ -950,14 +951,20 @@ // normalize hour to 24-hour clock var hour = this.hour; - if (this.showMeridian && this.meridian == 'PM') { - hour += 12; + if (this.showMeridian) { + if (this.meridian == 'PM' && hour < 12) { + hour += 12; + } + if (this.meridian == 'AM' && hour == 12) { + hour = 0; + } } this.$element.trigger({ 'type': 'changeTime.timepicker', 'time': { 'value': this.getTime(), + 'hoursAndMinutes': this.pad(hour) +':'+ this.pad(this.minute), 'hours': hour, 'minutes': this.minute, 'seconds': this.second, @@ -966,6 +973,10 @@ }); }, + pad: function(val) { + return val.toString().length === 1 ? '0'+ val : val; + }, + updateElement: function() { this.$element.val(this.getTime()).change(); }, diff --git a/app/assets/javascripts/app/views/generic/user_search/input.jst.eco b/app/assets/javascripts/app/views/generic/user_search/input.jst.eco index c9ed38590..6cc7b4359 100644 --- a/app/assets/javascripts/app/views/generic/user_search/input.jst.eco +++ b/app/assets/javascripts/app/views/generic/user_search/input.jst.eco @@ -1,6 +1,6 @@
- + <%- @Icon('arrow-down', 'dropdown-arrow') %>
diff --git a/app/assets/stylesheets/zammad.css.scss b/app/assets/stylesheets/zammad.css.scss index 77e46209b..a13395bf8 100644 --- a/app/assets/stylesheets/zammad.css.scss +++ b/app/assets/stylesheets/zammad.css.scss @@ -1043,6 +1043,10 @@ fieldset > *:not(.form-group) .form-control { .form-group.formGroup--halfSize { width: 50%; float: left; + + .form-control { + min-width: auto; + } } .fromGroup--standalone .form-control { @@ -1068,7 +1072,7 @@ textarea, height: 41px; font-size: 14px; font-weight: normal; - line-height: 22px; + line-height: 27px; color: #555; background: white; border: 1px solid hsl(0, 0%, 90%); @@ -1081,6 +1085,7 @@ textarea, &.form-control--small { padding: 0 8px; height: 31px; + line-height: 29px; } &.form-control--inline { @@ -1089,6 +1094,15 @@ textarea, } } +input[type=url] { + min-width: 400px; +} + +.user-select.form-control { + padding-right: 35px; + min-width: 300px; +} + input[type=time] { width: auto; padding-left: 6px; @@ -1196,10 +1210,6 @@ input.time.time--12 { display: none; } - .form-control.ui-autocomplete-input { - padding-right: 35px; - } - .has-error .form-control, .has-error .form-control:focus, .has-error .form-control.focus { @@ -5858,6 +5868,13 @@ output { background: white; table-layout: auto; + &.is-invalid { + border-radius: 3px; + box-shadow: + 0 0 0 2px white, + 0 0 0 4px hsl(0,90%,70%); + } + &.settings-list--stretch { width: 100%; } diff --git a/public/assets/fonts/firasans-bold-webfont.eot b/public/assets/fonts/firasans-bold-webfont.eot index 63a950feb..f4b8287cd 100755 Binary files a/public/assets/fonts/firasans-bold-webfont.eot and b/public/assets/fonts/firasans-bold-webfont.eot differ diff --git a/public/assets/fonts/firasans-bold-webfont.ttf b/public/assets/fonts/firasans-bold-webfont.ttf index 57b49f461..a018e8b5e 100755 Binary files a/public/assets/fonts/firasans-bold-webfont.ttf and b/public/assets/fonts/firasans-bold-webfont.ttf differ diff --git a/public/assets/fonts/firasans-bold-webfont.woff b/public/assets/fonts/firasans-bold-webfont.woff index 9fb367d43..6c72aef2c 100755 Binary files a/public/assets/fonts/firasans-bold-webfont.woff and b/public/assets/fonts/firasans-bold-webfont.woff differ diff --git a/public/assets/fonts/firasans-bold-webfont.woff2 b/public/assets/fonts/firasans-bold-webfont.woff2 index 7300351e3..f22279f15 100755 Binary files a/public/assets/fonts/firasans-bold-webfont.woff2 and b/public/assets/fonts/firasans-bold-webfont.woff2 differ diff --git a/public/assets/fonts/firasans-book-webfont.eot b/public/assets/fonts/firasans-book-webfont.eot index 2193921a9..0337ee54c 100755 Binary files a/public/assets/fonts/firasans-book-webfont.eot and b/public/assets/fonts/firasans-book-webfont.eot differ diff --git a/public/assets/fonts/firasans-book-webfont.ttf b/public/assets/fonts/firasans-book-webfont.ttf index f11f62e54..5383f0d62 100755 Binary files a/public/assets/fonts/firasans-book-webfont.ttf and b/public/assets/fonts/firasans-book-webfont.ttf differ diff --git a/public/assets/fonts/firasans-book-webfont.woff b/public/assets/fonts/firasans-book-webfont.woff index 8a13b50bc..2f29c3864 100755 Binary files a/public/assets/fonts/firasans-book-webfont.woff and b/public/assets/fonts/firasans-book-webfont.woff differ diff --git a/public/assets/fonts/firasans-book-webfont.woff2 b/public/assets/fonts/firasans-book-webfont.woff2 index debbcdcf6..6b9fadf9c 100755 Binary files a/public/assets/fonts/firasans-book-webfont.woff2 and b/public/assets/fonts/firasans-book-webfont.woff2 differ diff --git a/public/assets/fonts/firasans-light-webfont.eot b/public/assets/fonts/firasans-light-webfont.eot index 1d3d44b71..f97fe8bc6 100755 Binary files a/public/assets/fonts/firasans-light-webfont.eot and b/public/assets/fonts/firasans-light-webfont.eot differ diff --git a/public/assets/fonts/firasans-light-webfont.ttf b/public/assets/fonts/firasans-light-webfont.ttf index 255905ffd..99ed48da2 100755 Binary files a/public/assets/fonts/firasans-light-webfont.ttf and b/public/assets/fonts/firasans-light-webfont.ttf differ diff --git a/public/assets/fonts/firasans-light-webfont.woff b/public/assets/fonts/firasans-light-webfont.woff index eb3f0f055..b5c69cf29 100755 Binary files a/public/assets/fonts/firasans-light-webfont.woff and b/public/assets/fonts/firasans-light-webfont.woff differ diff --git a/public/assets/fonts/firasans-light-webfont.woff2 b/public/assets/fonts/firasans-light-webfont.woff2 index 5332897ae..f668bb49c 100755 Binary files a/public/assets/fonts/firasans-light-webfont.woff2 and b/public/assets/fonts/firasans-light-webfont.woff2 differ