ngx-mat-shift-selection
Version:
This is a simple date and time selection component design specificly for job shifts etc, with 24-hours available option.
16 lines (14 loc) • 18.8 kB
JavaScript
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@angular/core"),require("moment"),require("lodash"),require("@angular/forms"),require("@angular/common"),require("@angular/flex-layout"),require("@angular/material")):"function"==typeof define&&define.amd?define("ngx-mat-shift-selection",["exports","@angular/core","moment","lodash","@angular/forms","@angular/common","@angular/flex-layout","@angular/material"],t):t((e=e||self)["ngx-mat-shift-selection"]={},e.ng.core,e.moment,e._,e.ng.forms,e.ng.common,e.ng["flex-layout"],e.ng.material)}(this,(function(e,t,n,a,r,i,o,l){"use strict";
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */function s(e,t,n,a){return new(n||(n=Promise))((function(r,i){function o(e){try{s(a.next(e))}catch(e){i(e)}}function l(e){try{s(a.throw(e))}catch(e){i(e)}}function s(e){e.done?r(e.value):new n((function(t){t(e.value)})).then(o,l)}s((a=a.apply(e,t||[])).next())}))}function c(e,t){var n,a,r,i,o={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return i={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function l(i){return function(l){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;o;)try{if(n=1,a&&(r=2&i[0]?a.return:i[0]?a.throw||((r=a.return)&&r.call(a),0):a.next)&&!(r=r.call(a,i[1])).done)return r;switch(a=0,r&&(i=[2&i[0],r.value]),i[0]){case 0:case 1:r=i;break;case 4:return o.label++,{value:i[1],done:!1};case 5:o.label++,a=i[1],i=[0];continue;case 7:i=o.ops.pop(),o.trys.pop();continue;default:if(!(r=(r=o.trys).length>0&&r[r.length-1])&&(6===i[0]||2===i[0])){o=0;continue}if(3===i[0]&&(!r||i[1]>r[0]&&i[1]<r[3])){o.label=i[1];break}if(6===i[0]&&o.label<r[1]){o.label=r[1],r=i;break}if(r&&o.label<r[2]){o.label=r[2],o.ops.push(i);break}r[2]&&o.ops.pop(),o.trys.pop();continue}i=t.call(e,o)}catch(e){i=[6,e],a=0}finally{n=r=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,l])}}}function d(e){var t="function"==typeof Symbol&&e[Symbol.iterator],n=0;return t?t.call(e):{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}}}var u=function(){function e(){}return e.decorators=[{type:t.Injectable,args:[{providedIn:"root"}]}],e.ctorParameters=function(){return[]},e.ngInjectableDef=t.ɵɵdefineInjectable({factory:function(){return new e},token:e,providedIn:"root"}),e}(),m=n,f=function(){function e(){this.currentDate=m(),this.dayNames=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],this.weeks=[],this.sortedDates=[],this.selectAll=!1,this.availableAll=!1,this.time=["00:00","00:30","01:00","01:30","02:00","02:30","03:00","03:30","04:00","04:30","05:00","05:30","06:00","06:30","07:00","07:30","08:00","08:30","09:00","09:30","10:00","10:30","11:00","11:30","12:00","12:30","13:00","13:30","14:00","14:30","15:00","15:30","16:00","16:30","17:00","17:30","18:00","18:30","19:00","19:30","20:00","20:30","21:00","21:30","22:00","22:30","23:00","23:30"],this.selectedDates=[],this.calendarType="month",this.class="",this.onSelectDate=new t.EventEmitter}return e.prototype.ngOnInit=function(){this.generateCalendar()},e.prototype.ngOnChanges=function(e){e.selectedDates&&e.selectedDates.currentValue&&e.selectedDates.currentValue.length>1&&(this.sortedDates=a.sortBy(e.selectedDates.currentValue,(function(e){return e.mDate.valueOf()})),this.generateCalendar())},e.prototype.selectDate=function(e){return s(this,void 0,void 0,(function(){var t;return c(this,(function(n){switch(n.label){case 0:return e.selected=!e.selected,e.isFullTime=!1,e.selected?[3,2]:[4,a.remove(this.selectedDates,(function(t){return t.mDate.format("ll")==e.mDate.format("ll")}))];case 1:return n.sent(),[3,3];case 2:e.startTime="",e.endTime="",e.isTimerVisible=this.weeks[0][1].mDate.week()==e.mDate.week()&&!this.isPast(e.mDate),this.isDuplicate(e.mDate)||this.selectedDates.push(e),n.label=3;case 3:return t=this,[4,a.sortBy(this.selectedDates,(function(e){return e.mDate.valueOf()}))];case 4:return t.sortedDates=n.sent(),this.selectAll=this.areAllSelected(),this.availableAll=this.areAllAvailable(),this.onSelectDate.emit(this.sortedDates),[2]}}))}))},e.prototype.isToday=function(e){return m().isSame(m(e),"day")},e.prototype.isSelected=function(e){return a.findIndex(this.selectedDates,(function(t){return m(e).isSame(t.mDate,"day")}))>-1},e.prototype.isDuplicate=function(e){return a.findIndex(this.selectedDates,(function(t){return m(e).isSame(t.mDate,"day")}))>-1},e.prototype.areAllSelected=function(){var e,t;try{for(var n=d(this.weeks[0]),a=n.next();!a.done;a=n.next()){var r=a.value;if(!r.selected&&!this.isPast(r.mDate))return!1}}catch(t){e={error:t}}finally{try{a&&!a.done&&(t=n.return)&&t.call(n)}finally{if(e)throw e.error}}return!0},e.prototype.areAllAvailable=function(){var e,t,n,a;try{for(var r=d(this.sortedDates),i=r.next();!i.done;i=r.next()){if(!(s=i.value).isFullTime&&s.isTimerVisible)return!1}}catch(t){e={error:t}}finally{try{i&&!i.done&&(t=r.return)&&t.call(r)}finally{if(e)throw e.error}}try{for(var o=d(this.weeks[0]),l=o.next();!l.done;l=o.next()){var s;if(!(s=l.value).selected)return!1}}catch(e){n={error:e}}finally{try{l&&!l.done&&(a=o.return)&&a.call(o)}finally{if(n)throw n.error}}return!0},e.prototype.isFullTime=function(e){return a.findIndex(this.selectedDates,(function(t){return m(e).isSame(t.mDate,"day")&&t.isFullTime}))>-1},e.prototype.isSelectedMonth=function(e){return m(e).isSame(this.currentDate,"month")},e.prototype.isPast=function(e){return m(e).isBefore(m().subtract(1,"day"))},e.prototype.prevMonth=function(){this.currentDate=m(this.currentDate).subtract(1,"months"),this.generateCalendar()},e.prototype.nextMonth=function(){this.currentDate=m(this.currentDate).add(1,"months"),this.generateCalendar()},e.prototype.nextWeek=function(){this.currentDate=m(this.currentDate).add(1,"week"),this.generateCalendar()},e.prototype.prevWeek=function(){this.currentDate=m(this.currentDate).subtract(1,"week"),this.generateCalendar()},e.prototype.firstMonth=function(){this.currentDate=m(this.currentDate).startOf("year"),this.generateCalendar()},e.prototype.lastMonth=function(){this.currentDate=m(this.currentDate).endOf("year"),this.generateCalendar()},e.prototype.prevYear=function(){this.currentDate=m(this.currentDate).subtract(1,"year"),this.generateCalendar()},e.prototype.nextYear=function(){this.currentDate=m(this.currentDate).add(1,"year"),this.generateCalendar()},e.prototype.generateCalendar=function(){for(var e,t,n=this.fillDates(this.currentDate),a=[];n.length>0;)a.push(n.splice(0,7));try{for(var r=d(this.sortedDates),i=r.next();!i.done;i=r.next()){var o=i.value;o.isTimerVisible=a[0][1].mDate.week()==o.mDate.week()&&!this.isPast(o.mDate)}}catch(t){e={error:t}}finally{try{i&&!i.done&&(t=r.return)&&t.call(r)}finally{if(e)throw e.error}}this.weeks=a,this.selectAll=this.areAllSelected(),this.availableAll=this.areAllAvailable()},e.prototype.fillDates=function(e){var t=this;if("week"==this.calendarType){var n=m(e).startOf("week").day(),r=m(e).startOf("week").subtract(n,"days"),i=r.date();return a.range(i,i+7).map((function(e){var n=m(r).date(e);return{today:t.isToday(n),selected:t.isSelected(n),mDate:n,startTime:void 0,endTime:void 0,isTimerVisible:!1,isFullTime:t.isFullTime(n)}}))}var o=m(e).startOf("month").day(),l=m(e).startOf("month").subtract(o,"days"),s=l.date();return a.range(s,s+35).map((function(e){var n=m(l).date(e);return{today:t.isToday(n),selected:t.isSelected(n),mDate:n,startTime:void 0,endTime:void 0,isTimerVisible:!1,isFullTime:t.isFullTime(n)}}))},e.prototype.timeChanged=function(e){e.isFullTime="00:00"==e.startTime&&"23:59"==e.endTime&&this.weeks[0].map((function(t){t.mDate.format("ll")==e.mDate.format("ll")&&(t.isFullTime=e.isFullTime)})),this.availableAll=this.areAllAvailable(),this.onSelectDate.emit(this.sortedDates)},e.prototype.fullTimeChecked=function(e){for(var t in e.startTime=e.isFullTime?"00:00":"",e.endTime=e.isFullTime?"23:59":"",this.sortedDates)this.sortedDates[t].mDate.format("ll")==e.mDate.format("ll")&&(this.sortedDates[t].startTime=e.startTime,this.sortedDates[t].endTime=e.endTime);this.timeChanged(e)},e.prototype.selectAllChecked=function(){var e,t;try{for(var n=d(this.weeks[0]),a=n.next();!a.done;a=n.next()){var r=a.value;r.selected=this.selectAll,this.selectDate(r)}}catch(t){e={error:t}}finally{try{a&&!a.done&&(t=n.return)&&t.call(n)}finally{if(e)throw e.error}}},e.prototype.availableAllChecked=function(){return s(this,void 0,void 0,(function(){var e,t,n,a,r,i,o;return c(this,(function(l){this.availableAll=!this.availableAll,e=function(e){e.isFullTime=e.isTimerVisible?t.availableAll:e.isFullTime,e.startTime=e.isFullTime?"00:00":"",e.endTime=e.isFullTime?"23:59":"",t.weeks[0].map((function(t){t.mDate.format("ll")==e.mDate.format("ll")&&(t.isFullTime=e.isFullTime)}))},t=this;try{for(n=d(this.sortedDates),a=n.next();!a.done;a=n.next())r=a.value,e(r)}catch(e){i={error:e}}finally{try{a&&!a.done&&(o=n.return)&&o.call(n)}finally{if(i)throw i.error}}return this.onSelectDate.emit(this.sortedDates),[2]}))}))},e.prototype.timeSelected=function(){this.onSelectDate.emit(this.sortedDates)},e.decorators=[{type:t.Component,args:[{selector:"ngx-mat-shift-selection",template:'<div fxLayout="column" [ngClass]="class" class="calendar">\n <div fxLayout="column" class="calendar-navs" *ngIf="calendarType != \'week\'">\n <div class="month-nav" fxLayout="row" fxLayoutAlign="space-between center">\n <button mat-icon-button (click)="prevMonth()">\n <mat-icon>arrow_back_ios</mat-icon>\n </button>\n <span class="title p4 mt-1">{{ currentDate.format("MMMM") }}</span>\n <button mat-icon-button (click)="nextMonth()">\n <mat-icon>arrow_forward_ios</mat-icon>\n </button>\n </div>\n <div class="year-nav" fxLayout="row" fxLayoutAlign="space-between center">\n <button mat-icon-button (click)="prevYear()">\n <mat-icon>arrow_back_ios</mat-icon>\n </button>\n <span class="mt-1">{{ currentDate.format("YYYY") }}</span>\n <button mat-icon-button (click)="nextYear()">\n <mat-icon>arrow_forward_ios</mat-icon>\n </button>\n </div>\n </div>\n <div fxLayout="column" class="calendar-navs" *ngIf="calendarType == \'week\'">\n <div class="month-nav" fxLayout="row" fxLayoutAlign="space-between center">\n <button mat-icon-button (click)="prevWeek()">\n <mat-icon>arrow_back_ios</mat-icon>\n </button>\n <span class="title p4 mt-1">{{ currentDate.format("MMMM YYYY") }}</span>\n <button mat-icon-button (click)="nextWeek()">\n <mat-icon>arrow_forward_ios</mat-icon>\n </button>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div fxLayout="column" class="month-grid">\n <div class="day-names" fxLayout="row" fxLayoutAlign="space-between center">\n <div\n fxFlex="14"\n *ngFor="let name of dayNames"\n class="day-name p9"\n style="text-align: center;"\n >\n {{ name }}\n </div>\n </div>\n <div class="weeks" fxLayout="column">\n <div\n *ngFor="let week of weeks"\n class="week"\n style="text-align: center;"\n fxLayout="row"\n fxLayoutAlign="space-between center"\n >\n <ng-container *ngFor="let day of week">\n <div fxFlex="14" class="week-date disabled" *ngIf="isPast(day.mDate)">\n <span class="date-text">{{ day.mDate.date() }}</span>\n </div>\n <div\n fxFlex="14"\n class="week-date enabled"\n *ngIf="!isPast(day.mDate)"\n (click)="selectDate(day)"\n >\n <div\n fxLayout="row"\n fxLayoutAlign="center center"\n [ngClass]="{\n today: day.today,\n fullTimeSelected: day.isFullTime,\n selected: day.selected\n }"\n >\n <span class="date-text">{{ day.mDate.date() }}</span>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class="row justify-content-between p-05">\n <div class="col-12 mb-1">\n Select All Days\n <mat-checkbox\n [checked]="selectAll"\n (change)="selectAllChecked()"\n ></mat-checkbox>\n </div>\n </div>\n <mat-divider></mat-divider>\n <ng-container *ngIf="sortedDates.length > 0">\n <div class="p-05" fxLayout="row" fxLayoutAlign="start center">\n <div fxFlex="50">Select Available Time</div>\n <div fxFlex="50" class="text-right">\n <mat-checkbox\n [checked]="availableAll"\n (change)="availableAllChecked()"\n >\n </mat-checkbox>\n Available 24 Hours\n </div>\n </div>\n <mat-divider></mat-divider>\n </ng-container>\n <div *ngFor="let availableDate of sortedDates">\n <div class="mt-1" *ngIf="availableDate.isTimerVisible">\n <div fxLayout="row" fxLayoutAlign="start center" class="p-05">\n <div fxFlex="50">{{ availableDate.mDate.format("LL") }}</div>\n <div fxFlex="50" class="text-right">\n <mat-checkbox\n [(ngModel)]="availableDate.isFullTime"\n (ngModelChange)="fullTimeChecked(availableDate)"\n aria-label="Checkbox for following text input"\n >\n </mat-checkbox>\n Available 24 Hours\n </div>\n </div>\n <div\n fxLayout="row"\n fxLayoutAlign="start center"\n *ngIf="!availableDate.isFullTime"\n class="p-05"\n >\n <mat-form-field fxFlex="40">\n <input\n type="text"\n placeholder="Start Time"\n aria-label="Number"\n matInput\n [(ngModel)]="availableDate.startTime"\n [matAutocomplete]="auto"\n (ngModelChange)="timeSelected()"\n />\n <mat-autocomplete #auto="matAutocomplete">\n <mat-option *ngFor="let option of time" [value]="option">\n {{ option }}\n </mat-option>\n </mat-autocomplete>\n </mat-form-field>\n <span class="text-center" fxFlex="20">to</span>\n <mat-form-field fxFlex="40">\n <input\n type="text"\n placeholder="End Time"\n aria-label="Number"\n matInput\n [(ngModel)]="availableDate.endTime"\n [matAutocomplete]="auto"\n (ngModelChange)="timeSelected()"\n />\n <mat-autocomplete #auto="matAutocomplete">\n <mat-option *ngFor="let option of time" [value]="option">\n {{ option }}\n </mat-option>\n </mat-autocomplete>\n </mat-form-field>\n </div>\n <mat-divider></mat-divider>\n </div>\n </div>\n</div>\n',styles:['.calendar{display:block;min-width:calc(45px * 7);background-color:transparent}.calendar *{box-sizing:border-box}.calendar .calendar-navs{background-color:transparent}.calendar .month-nav{padding:5px;display:flex;flex-direction:row;justify-content:space-between}.calendar .year-nav{padding:5px;display:flex;flex-direction:row;justify-content:space-between;font-family:Montserrat}.calendar .month-grid .day-names{display:flex;flex-direction:row;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.calendar .month-grid .weeks{display:flex;flex-direction:column}.calendar .month-grid .week{display:flex;flex-direction:row}.calendar .month-grid .day-name,.calendar .month-grid .week-date{text-align:center;padding:5px;display:block;width:45px;display:flex;justify-content:center;align-items:center;font-size:1rem}.calendar .month-grid .day-name{color:#28a1e5}.calendar .month-grid .week-date{height:45px;position:relative;border-radius:50%}.calendar .month-grid .week-date .date-text{z-index:10;font-size:1rem;font-family:Montserrat,sans-serif}.calendar .month-grid .week-date::after{content:"";height:calc(45px * .9);width:calc(45px * .9);position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);border-radius:50%;transition:background-color 150ms linear,color 150ms linear;z-index:1}.calendar .month-grid .week-date.enabled{cursor:pointer}.calendar .month-grid .week-date.enabled:hover{opacity:.6}.calendar .month-grid .week-date .selected,.calendar .month-grid .week-date .selected:after{background-color:#28a1e5;color:#fff;width:34px;height:34px;border-radius:50%}.calendar .month-grid .week-date .selected:hover:after{background-color:transparent;width:34px;height:34px;border-radius:50%}.calendar .month-grid .week-date .fullTimeSelected,.calendar .month-grid .week-date .fullTimeSelected:after{background-color:#757374!important;color:#fff;width:34px;height:34px;border-radius:50%}.calendar .month-grid .week-date .fullTimeSelected:hover:after{background-color:transparent;width:34px;height:34px;border-radius:50%}.calendar .month-grid .week-date.disabled{opacity:.6}.calendar .month-grid .today{font-weight:700}.to-span{padding-top:2.5rem;margin-left:1rem;margin-right:1rem}.p-05{padding:.5rem}.time-selector{display:inline-flex}.title{font-size:1.2rem;font-weight:700}.hr-margin{margin-top:1px;margin-bottom:1px}.text-center{text-align:center}.text-right{text-align:right}*{font-size:.8rem}']}]}],e.ctorParameters=function(){return[]},e.propDecorators={selectedDates:[{type:t.Input}],calendarType:[{type:t.Input}],class:[{type:t.Input}],onSelectDate:[{type:t.Output}]},e}();var h=function(){function e(){}return e.decorators=[{type:t.NgModule,args:[{declarations:[f],imports:[i.CommonModule,r.FormsModule,o.FlexLayoutModule,l.MatFormFieldModule,l.MatInputModule,l.MatAutocompleteModule,l.MatCheckboxModule,l.MatDividerModule,l.MatButtonModule,l.MatIconModule],exports:[f]}]}],e}();e.NgxMatShiftSelectionComponent=f,e.NgxMatShiftSelectionModule=h,e.NgxMatShiftSelectionService=u,Object.defineProperty(e,"__esModule",{value:!0})}));
//# sourceMappingURL=ngx-mat-shift-selection.umd.min.js.map