web/satellite: DatePicker rework (#3157)

This commit is contained in:
Nikolay Yurchenko 2019-10-07 17:40:45 +03:00 committed by GitHub
parent d29946d3d7
commit ef2615fcf4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 1044 additions and 871 deletions

View File

@ -0,0 +1,557 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="cov-vue-date">
<div class="datepickbox">
<input type="text" title="input date" class="cov-datepicker" readonly="readonly" :style="option.inputStyle ? option.inputStyle : {}" />
</div>
<div class="datepicker-overlay" v-if="isChecking" @click.self="dismiss" :style="{'background' : option.overlayOpacity? 'rgba(0,0,0,'+option.overlayOpacity+')' : 'rgba(0,0,0,0.5)'}">
<div class="cov-date-body" :style="{'background-color': option.color ? option.color.header : '#3f51b5'}">
<div class="cov-date-monthly">
<div class="cov-date-previous" @click="onPreviousMonthClick">«</div>
<div class="cov-date-caption" :style="{'color': option.color ? option.color.headerText : '#fff'}">
<span class="year-selection" @click="showYear">{{selectedDateState.year}}</span>
<span class="month-selection" @click="showMonth">{{displayedMonth}}</span>
</div>
<div class="cov-date-next" @click="onNextMonthClick">»</div>
</div>
<div class="cov-date-box" v-if="isDaysChoiceShown">
<div class="cov-picker-box">
<div class="week">
<ul>
<li v-for="week in daysInWeek" :key="week">{{week}}</li>
</ul>
</div>
<div class="day" v-for="(day, index) in daysToShow" :key="index" @click="checkDay(day)" :class="{'checked':day.checked,'unavailable':day.unavailable,'passive-day': !(day.inMonth), 'today': day.today}" :style="day.checked ? (option.color && option.color.checkedDay ? { background: option.color.checkedDay } : { background: '#2683FF' }) : {}">{{day.value}}</div>
</div>
</div>
<div class="cov-date-box list-box" v-if="isYearChoiceShown">
<div class="cov-picker-box date-list" id="yearList">
<div class="date-item year" v-for="yearItem in years" :key="yearItem" @click="setYear(yearItem)">{{yearItem}}</div>
</div>
</div>
<div class="cov-date-box list-box" v-if="isMonthChoiceShown">
<div class="cov-picker-box date-list">
<div class="date-item month" v-for="monthItem in monthsNames" :key="monthItem" @click="setMonth(monthItem)">{{monthItem}}</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import {
DateGenerator,
DateStamp,
DayAction,
DayItem,
DisplayedType,
Options,
} from '@/utils/datepicker';
@Component
export default class VDatePicker extends Vue {
@Prop({default: () => new Options()})
private option: Options;
@Prop({default: () => false})
private isSundayFirst: boolean;
private readonly MAX_DAYS_SELECTED: number = 2;
public selectedDays: Date[] = [];
private showType: number = DisplayedType.Day;
private dateGenerator: DateGenerator = new DateGenerator();
// daysInWeek contains days names abbreviations
public readonly daysInWeek: string[] = [];
public readonly monthsNames: string[] = [];
// years contains years numbers available to choose
public readonly years: number[] = [];
// isChecking indicates when calendar is shown
public isChecking: boolean = false;
public displayedMonth: string;
// daysToShow contains days of selected month with a few extra days from adjacent months
public daysToShow: DayItem[] = [];
// Combination of selected year, month and day
public selectedDateState: DateStamp = new DateStamp(0, 0, 0);
public constructor() {
super();
this.daysInWeek = this.isSundayFirst ? this.option.sundayFirstWeek : this.option.mondayFirstWeek;
this.monthsNames = this.option.month;
this.displayedMonth = this.monthsNames[0];
this.years = this.dateGenerator.populateYears();
}
/**
* computed value that indicates should days view be shown
*/
public get isDaysChoiceShown(): boolean {
return this.showType === DisplayedType.Day;
}
/**
* computed value that indicates should month choice view be shown
*/
public get isMonthChoiceShown(): boolean {
return this.showType === DisplayedType.Month;
}
/**
* computed value that indicates should year choice view be shown
*/
public get isYearChoiceShown(): boolean {
return this.showType === DisplayedType.Year;
}
/**
* onPreviousMonthClick set previous month
*/
public onPreviousMonthClick(): void {
this.nextMonth(DayAction.Previous);
}
/**
* onNextMonthClick set next month
*/
public onNextMonthClick(): void {
this.nextMonth(DayAction.Next);
}
/**
* checkDay toggles checked property of day object
*
* @param day represent day object to check/uncheck
*/
public checkDay(day: DayItem): void {
if (day.unavailable || !day.value) {
return;
}
if (!day.inMonth) {
this.nextMonth(day.action);
return;
}
if (day.checked) {
day.checked = false;
this.selectedDays.splice(this.selectedDays.indexOf(day.moment), 1);
return;
}
if (this.selectedDays.length < this.MAX_DAYS_SELECTED) {
this.selectedDays.push(day.moment);
day.checked = true;
}
if (this.selectedDays.length === this.MAX_DAYS_SELECTED) {
this.submitSelectedDays();
}
}
/**
* setYear selects chosen year
*
* @param year
*/
public setYear(year): void {
this.populateDays(new Date(year, this.selectedDateState.month, this.selectedDateState.day));
}
/**
* setYear selects chosen month
*
* @param month
*/
public setMonth(month: string): void {
const monthIndex = this.monthsNames.indexOf(month);
this.populateDays(new Date(this.selectedDateState.year, monthIndex, this.selectedDateState.day));
}
/**
* dismiss closes popup and clears values
*/
public dismiss(): void {
if (!this.option.dismissible) {
return;
}
this.selectedDays = [];
this.isChecking = false;
}
/**
* showCheck used for external popup opening
*/
public showCheck(): void {
this.populateDays();
this.isChecking = true;
}
/**
* showYear used for opening choose year view
*/
public showYear(): void {
this.showType = DisplayedType.Year;
}
/**
* showMonth used for opening choose month view
*/
public showMonth(): void {
this.showType = DisplayedType.Month;
}
/**
* nextMonth set month depends on day action (next or previous)
*
* @param action represents next or previous type of action
*/
private nextMonth(action: DayAction): void {
const currentMoment = new Date(this.selectedDateState.year, this.selectedDateState.month, this.selectedDateState.day);
const currentMonth = currentMoment.getMonth();
const now = new Date();
switch (action) {
case DayAction.Next:
if (currentMonth === now.getMonth() && currentMoment.getFullYear() === now.getFullYear()) {
return;
}
currentMoment.setMonth(currentMonth + 1);
break;
case DayAction.Previous:
currentMoment.setMonth(currentMonth - 1);
break;
}
this.populateDays(currentMoment);
}
/**
* submitSelectedDays emits function to receive selected dates externally and then clears state
*/
private submitSelectedDays(): void {
this.$emit('change', this.selectedDays);
this.isChecking = false;
this.selectedDays = [];
}
/**
* populateDays used for populating date items into calendars depending on selected date
*
* @param date represents Date which is used to create current date items to show
*/
private populateDays(date: Date = new Date()): void {
this.selectedDateState.fromDate(date);
this.showType = DisplayedType.Day;
this.displayedMonth = this.monthsNames[this.selectedDateState.month];
this.daysToShow = this.dateGenerator.populateDays(this.selectedDateState, this.isSundayFirst);
}
}
</script>
<style scoped lang="scss">
.datepicker-overlay {
position: fixed;
width: 100%;
height: 100%;
z-index: 998;
top: 0;
left: 0;
overflow: hidden;
-webkit-animation: fadein 0.5s;
/* Safari, Chrome and Opera > 12.1 */
-moz-animation: fadein 0.5s;
/* Firefox < 16 */
-ms-animation: fadein 0.5s;
/* Internet Explorer */
-o-animation: fadein 0.5s;
/* Opera < 12.1 */
animation: fadein 0.5s;
}
@keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Firefox < 16 */
@-moz-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Safari, Chrome and Opera > 12.1 */
@-webkit-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Internet Explorer */
@-ms-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Opera < 12.1 */
@-o-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.cov-date-body {
background: #3F51B5;
overflow: hidden;
font-size: 16px;
font-weight: 400;
position: fixed;
display: block;
width: 400px;
max-width: 100%;
z-index: 999;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.2);
font-family: 'font_medium';
}
.cov-picker-box {
background: #fff;
display: inline-block;
padding: 25px;
box-sizing: border-box !important;
-moz-box-sizing: border-box !important;
-webkit-box-sizing: border-box !important;
-ms-box-sizing: border-box !important;
width: 400px;
max-width: 100%;
height: 280px;
text-align: start !important;
}
.day {
width: 14.2857143%;
display: inline-block;
text-align: center;
cursor: pointer;
height: 34px;
padding: 0;
line-height: 34px;
color: #000;
background: #fff;
vertical-align: middle;
}
.week ul {
margin: 0 0 8px;
padding: 0;
list-style: none;
}
.week ul li {
width: 14.2%;
display: inline-block;
text-align: center;
background: transparent;
color: #000;
font-weight: bold;
}
.passive-day {
color: #bbb;
}
.checked {
background: #2683FF;
color: #FFF !important;
}
.unavailable {
color: #ccc;
cursor: not-allowed;
}
.cov-date-monthly {
height: 50px;
}
.cov-date-monthly > div {
display: inline-block;
padding: 0;
margin: 0;
vertical-align: middle;
color: #fff;
height: 50px;
float: left;
text-align: center;
}
.cov-date-previous,
.cov-date-next {
position: relative;
width: 20% !important;
text-indent: -300px;
overflow: hidden;
color: #fff;
}
.cov-date-caption {
width: 60%;
padding: 10px 0 !important;
box-sizing: border-box;
font-size: 18px;
font-family: 'font_medium';
line-height: 30px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.month-selection,
.year-selection {
padding: 0 3px;
}
.cov-date-previous:hover,
.cov-date-next:hover {
background: rgba(255, 255, 255, 0.1);
}
.day:hover {
background: #EAEAEA;
}
.unavailable:hover {
background: none;
}
.cov-date-next::before,
.cov-date-previous::before {
width: 20px;
height: 2px;
text-align: center;
position: absolute;
background: #fff;
top: 50%;
margin-top: -7px;
margin-left: -7px;
left: 50%;
line-height: 0;
content: '';
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
transform: rotate(45deg);
}
.cov-date-next::after,
.cov-date-previous::after {
width: 20px;
height: 2px;
text-align: center;
position: absolute;
background: #fff;
margin-top: 6px;
margin-left: -7px;
top: 50%;
left: 50%;
line-height: 0;
content: '';
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
transform: rotate(-45deg);
}
.cov-date-previous::after {
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
transform: rotate(45deg);
}
.cov-date-previous::before {
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
transform: rotate(-45deg);
}
.date-item {
text-align: center;
font-size: 20px;
padding: 10px 0;
cursor: pointer;
}
.date-item:hover {
background: #e0e0e0;
}
.date-list {
overflow: auto;
vertical-align: top;
padding: 0;
}
.cov-vue-date {
display: inline-block;
color: #5D5D5D;
}
.watch-box {
height: 100%;
overflow: hidden;
}
::-webkit-scrollbar {
width: 2px;
}
::-webkit-scrollbar-track {
background: #E3E3E3;
}
::-webkit-scrollbar-thumb {
background: #C1C1C1;
border-radius: 2px;
}
.cov-date-box {
font-family: 'font_medium';
}
.today {
background: lightblue;
color: white;
}
</style>

View File

@ -1,855 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
// TODO: temporary file
<style scoped lang="scss">
.datepicker-overlay {
position: fixed;
width: 100%;
height: 100%;
z-index: 998;
top: 0;
left: 0;
overflow: hidden;
-webkit-animation: fadein 0.5s;
/* Safari, Chrome and Opera > 12.1 */
-moz-animation: fadein 0.5s;
/* Firefox < 16 */
-ms-animation: fadein 0.5s;
/* Internet Explorer */
-o-animation: fadein 0.5s;
/* Opera < 12.1 */
animation: fadein 0.5s;
}
@keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Firefox < 16 */
@-moz-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Safari, Chrome and Opera > 12.1 */
@-webkit-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Internet Explorer */
@-ms-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Opera < 12.1 */
@-o-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.cov-date-body {
display: inline-block;
background: #3F51B5;
overflow: hidden;
position: relative;
font-size: 16px;
font-family: 'Roboto';
font-weight: 400;
position: fixed;
display: block;
width: 400px;
max-width: 100%;
z-index: 999;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.2);
font-family: 'font_medium';
}
.cov-picker-box {
background: #fff;
width: 100%;
display: inline-block;
padding: 25px;
box-sizing: border-box !important;
-moz-box-sizing: border-box !important;
-webkit-box-sizing: border-box !important;
-ms-box-sizing: border-box !important;
width: 400px;
max-width: 100%;
height: 280px;
text-align: start!important;
}
.cov-picker-box td {
height: 34px;
width: 34px;
padding: 0;
line-height: 34px;
color: #000;
background: #fff;
text-align: center;
cursor: pointer;
}
.cov-picker-box td:hover {
background: #E6E6E6;
}
table {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
}
.day {
width: 14.2857143%;
display: inline-block;
text-align: center;
cursor: pointer;
height: 34px;
padding: 0;
line-height: 34px;
color: #000;
background: #fff;
vertical-align: middle;
}
.week ul {
margin: 0 0 8px;
padding: 0;
list-style: none;
}
.week ul li {
width: 14.2%;
display: inline-block;
text-align: center;
background: transparent;
color: #000;
font-weight: bold;
}
.passive-day {
color: #bbb;
}
.checked {
background: #2683FF;
color: #FFF !important;
}
.unavailable {
color: #ccc;
cursor: not-allowed;
}
.cov-date-monthly {
height: 50px;
}
.cov-date-monthly > div {
display: inline-block;
padding: 0;
margin: 0;
vertical-align: middle;
color: #fff;
height: 50px;
float: left;
text-align: center;
}
.cov-date-previous,
.cov-date-next {
position: relative;
width: 20% !important;
text-indent: -300px;
overflow: hidden;
color: #fff;
}
.cov-date-caption {
width: 60%;
padding: 10px 0!important;
box-sizing: border-box;
font-size: 18px;
font-family: 'font_medium';
line-height: 30px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
span {
padding: 0 3px;
}
}
.cov-date-previous:hover,
.cov-date-next:hover {
background: rgba(255, 255, 255, 0.1);
}
.day:hover {
background: #EAEAEA;
}
.unavailable:hover {
background: none;
}
.cov-date-next::before,
.cov-date-previous::before {
width: 20px;
height: 2px;
text-align: center;
position: absolute;
background: #fff;
top: 50%;
margin-top: -7px;
margin-left: -7px;
left: 50%;
line-height: 0;
content: '';
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
transform: rotate(45deg);
}
.cov-date-next::after,
.cov-date-previous::after {
width: 20px;
height: 2px;
text-align: center;
position: absolute;
background: #fff;
margin-top: 6px;
margin-left: -7px;
top: 50%;
left: 50%;
line-height: 0;
content: '';
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
transform: rotate(-45deg);
}
.cov-date-previous::after {
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
transform: rotate(45deg);
}
.cov-date-previous::before {
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
transform: rotate(-45deg);
}
.date-item {
text-align: center;
font-size: 20px;
padding: 10px 0;
cursor: pointer;
}
.date-item:hover {
background: #e0e0e0;
}
.date-list {
overflow: auto;
vertical-align: top;
padding: 0;
}
.cov-vue-date {
display: inline-block;
color: #5D5D5D;
}
.button-box {
background: #fff;
vertical-align: top;
height: 50px;
line-height: 50px;
text-align: right;
padding-right: 20px;
}
.button-box span {
cursor: pointer;
padding: 10px 20px;
}
.watch-box {
height: 100%;
overflow: hidden;
}
.hour-box,
.min-box {
display: inline-block;
width: 50%;
text-align: center;
height: 100%;
overflow: auto;
float: left;
}
.hour-box ul,
.min-box ul {
list-style: none;
margin: 0;
padding: 0;
}
.hour-item,
.min-item {
padding: 10px;
font-size: 36px;
cursor: pointer;
}
.hour-item:hover,
.min-item:hover {
background: #E3E3E3;
}
.hour-box .active,
.min-box .active {
background: #F50057;
color: #FFF !important;
}
::-webkit-scrollbar {
width: 2px;
}
::-webkit-scrollbar-track {
background: #E3E3E3;
}
::-webkit-scrollbar-thumb {
background: #C1C1C1;
border-radius: 2px;
}
.cov-date-box {
font-family: 'font_medium';
}
</style>
<template>
<div class="cov-vue-date">
<div class="datepickbox">
<input type="text" title="input date" class="cov-datepicker" readonly="readonly" :placeholder="option.placeholder" v-model="date.time" :required="required" :style="option.inputStyle ? option.inputStyle : {}" />
</div>
<div class="datepicker-overlay" v-if="showInfo.check" @click="dismiss($event)" v-bind:style="{'background' : option.overlayOpacity? 'rgba(0,0,0,'+option.overlayOpacity+')' : 'rgba(0,0,0,0.5)'}">
<div class="cov-date-body" :style="{'background-color': option.color ? option.color.header : '#3f51b5'}">
<div class="cov-date-monthly">
<div class="cov-date-previous" @click="nextMonth('pre')">«</div>
<div class="cov-date-caption" :style="{'color': option.color ? option.color.headerText : '#fff'}">
<span @click="showYear">{{checked.year}}</span>
<span @click="showMonth">{{displayInfo.month}}</span>
</div>
<div class="cov-date-next" @click="nextMonth('next')">»</div>
</div>
<div class="cov-date-box" v-if="showInfo.day">
<div class="cov-picker-box">
<div class="week">
<ul>
<li v-for="weekie in library.week">{{weekie}}</li>
</ul>
</div>
<div class="day" v-for="day in dayList" track-by="$index" @click="checkDay(day)" :class="{'checked':day.checked,'unavailable':day.unavailable,'passive-day': !(day.inMonth)}" :style="day.checked ? (option.color && option.color.checkedDay ? { background: option.color.checkedDay } : { background: '#2683FF' }) : {}">{{day.value}}</div>
</div>
</div>
<div class="cov-date-box list-box" v-if="showInfo.year">
<div class="cov-picker-box date-list" id="yearList">
<div class="date-item" v-for="yearItem in library.year" track-by="$index" @click="setYear(yearItem)">{{yearItem}}</div>
</div>
</div>
<div class="cov-date-box list-box" v-if="showInfo.month">
<div class="cov-picker-box date-list">
<div class="date-item" v-for="monthItem in library.month" track-by="$index" @click="setMonth(monthItem)">{{monthItem}}</div>
</div>
</div>
<div class="cov-date-box list-box" v-if="showInfo.hour">
<div class="cov-picker-box date-list">
<div class="watch-box">
<div class="hour-box">
<div class="mui-pciker-rule mui-pciker-rule-ft"></div>
<ul>
<li class="hour-item" v-for="hitem in hours" @click="setTime('hour', hitem, hours)" :class="{'active':hitem.checked}">{{hitem.value}}</li>
</ul>
</div>
<div class="min-box">
<div class="mui-pciker-rule mui-pciker-rule-ft"></div>
<div class="min-item" v-for="mitem in mins" @click="setTime('min',mitem, mins)" :class="{'active':mitem.checked}">{{mitem.value}}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="js">
import { Component, Vue } from 'vue-property-decorator';
let _moment = require('moment');
let _moment2 = _interopRequireDefault(_moment);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@Component({
props: {
required: false,
date: {
type: Object,
required: true
},
option: {
type: Object,
default: function _default() {
return {
type: 'multi-day',
SundayFirst: false,
week: ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'],
month: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
format: 'YYYY-DD-MM',
color: {
checked: '#2683FF',
header: '#2683FF',
headerText: '#444C63'
},
inputStyle: {
'visibility': 'hidden',
'width': '0',
},
placeholder: '',
buttons: {
ok: 'OK',
cancel: 'Cancel'
},
overlayOpacity: 0.5,
dismissible: true
};
}
},
limit: {
type: Array,
default: function _default() {
return [];
}
}
},
data: function data() {
function hours() {
let list = [];
let hour = 24;
while (hour > 0) {
hour--;
list.push({
checked: false,
value: hour < 10 ? '0' + hour : hour
});
}
return list;
}
function mins() {
let list = [];
let min = 60;
while (min > 0) {
min--;
list.push({
checked: false,
value: min < 10 ? '0' + min : min
});
}
return list;
}
return {
hours: hours(),
mins: mins(),
showInfo: {
hour: false,
day: false,
month: false,
year: false,
check: false
},
displayInfo: {
month: ''
},
library: {
week: this.option.week,
month: this.option.month,
year: []
},
checked: {
oldtime: '',
currentMoment: null,
year: '',
month: '',
day: '',
hour: '00',
min: '00'
},
dayList: [],
selectedDays: []
};
},
methods: {
pad: function pad(n) {
n = Math.floor(n);
return n < 10 ? '0' + n : n;
},
nextMonth: function nextMonth(type) {
let next = null;
let currentMoment = (0, _moment2.default)(this.checked.currentMoment);
if (type === 'next') {
if (currentMoment.format('MM') === (0, _moment2.default)(new Date()).format('MM')) {
return;
}
next = (0, _moment2.default)(this.checked.currentMoment).add(1, 'M');
} else {
next = (0, _moment2.default)(this.checked.currentMoment).add(-1, 'M');
}
this.showDay(next);
},
showDay: function showDay(time) {
if (time === undefined || !Date.parse(time)) {
this.checked.currentMoment = (0, _moment2.default)();
} else {
this.checked.currentMoment = (0, _moment2.default)(time, this.option.format);
}
this.showOne('day');
this.checked.year = (0, _moment2.default)(this.checked.currentMoment).format('YYYY');
this.checked.month = (0, _moment2.default)(this.checked.currentMoment).format('MM');
this.checked.day = (0, _moment2.default)(this.checked.currentMoment).format('DD');
this.displayInfo.month = this.library.month[(0, _moment2.default)(this.checked.currentMoment).month()];
let days = [];
let currentMoment = this.checked.currentMoment;
let firstDay = (0, _moment2.default)(currentMoment).date(1).day();
// getting previous and next month
// let currentMonth = moment(currentMoment)
let previousMonth = (0, _moment2.default)(currentMoment);
let nextMonth = (0, _moment2.default)(currentMoment);
nextMonth.add(1, 'months');
previousMonth.subtract(1, 'months');
let monthDays = (0, _moment2.default)(currentMoment).daysInMonth();
let now = (0, _moment2.default)(new Date());
let oldtime = this.checked.oldtime;
for (let i = 1; i <= monthDays; ++i) {
days.push({
value: i,
inMonth: this.checked.month !== now.format('MM') || (this.checked.month === now.format('MM') && i<= now.format('DD')),
unavailable: false,
checked: false,
moment: (0, _moment2.default)(currentMoment).date(i)
});
if (i === Math.ceil((0, _moment2.default)(currentMoment).format('D')) && (0, _moment2.default)(oldtime, this.option.format).year() === (0, _moment2.default)(currentMoment).year() && (0, _moment2.default)(oldtime, this.option.format).month() === (0, _moment2.default)(currentMoment).month()) {
days[i - 1].checked = true;
}
this.checkBySelectDays(i, days);
}
if (firstDay === 0) firstDay = 7;
for (let _i = 0; _i < firstDay - (this.option.SundayFirst ? 0 : 1); _i++) {
let passiveDay = {
value: previousMonth.daysInMonth() - _i,
inMonth: false,
action: 'previous',
unavailable: false,
checked: false,
moment: (0, _moment2.default)(currentMoment).date(1).subtract(_i + 1, 'days')
};
days.unshift(passiveDay);
}
if (this.limit.length > 0) {
let _iteratorNormalCompletion = true;
let _didIteratorError = false;
let _iteratorError = undefined;
try {
for (let _iterator = this.limit[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
let li = _step.value;
switch (li.type) {
case 'fromto':
days = this.limitFromTo(li, days);
break;
case 'weekday':
days = this.limitWeekDay(li, days);
break;
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}
let passiveDaysAtFinal = 42 - days.length;
for (let _i2 = 1; _i2 <= passiveDaysAtFinal; _i2++) {
let _passiveDay = {
value: _i2,
inMonth: false,
action: 'next',
unavailable: false,
checked: false,
moment: (0, _moment2.default)(currentMoment).add(1, 'months').date(_i2)
};
days.push(_passiveDay);
}
this.dayList = days;
},
checkBySelectDays: function checkBySelectDays(d, days) {
let _this = this;
this.selectedDays.forEach(function (day) {
if (_this.checked.year === (0, _moment2.default)(day).format('YYYY') && _this.checked.month === (0, _moment2.default)(day).format('MM') && d === Math.ceil((0, _moment2.default)(day).format('D'))) {
days[d - 1].checked = true;
}
});
},
limitWeekDay: function limitWeekDay(limit, days) {
days.map(function (day) {
if (limit.available.indexOf(Math.floor(day.moment.format('d'))) === -1) {
day.unavailable = true;
}
});
return days;
},
limitFromTo: function limitFromTo(limit, days) {
let _this2 = this;
if (limit.from || limit.to) {
days.map(function (day) {
if (_this2.getLimitCondition(limit, day)) {
day.unavailable = true;
}
});
}
return days;
},
getLimitCondition: function getLimitCondition(limit, day) {
let tmpMoment = (0, _moment2.default)(this.checked.year + '-' + this.pad(this.checked.month) + '-' + this.pad(day.value));
if (limit.from && !limit.to) {
return !tmpMoment.isAfter(limit.from);
} else if (!limit.from && limit.to) {
return !tmpMoment.isBefore(limit.to);
} else {
return !tmpMoment.isBetween(limit.from, limit.to);
}
},
checkDay: function checkDay(obj) {
if (obj.unavailable || obj.value === '') {
return false;
}
if (!obj.inMonth) {
// this.nextMonth(obj.action);
return;
}
if (this.option.type === 'day' || this.option.type === 'min') {
this.dayList.forEach(function (x) {
x.checked = false;
});
this.checked.day = this.pad(obj.value);
obj.checked = true;
} else {
let day = this.pad(obj.value);
let ctime = this.checked.year + '-' + this.checked.month + '-' + day;
if (obj.checked === true) {
obj.checked = false;
this.selectedDays.splice(this.selectedDays.indexOf(ctime), 1);
} else {
if (this.selectedDays.length < 2) {
this.selectedDays.push(ctime);
obj.checked = true;
}
if (this.selectedDays.length === 2) {
this.$emit('change', this.selectedDays);
this.showInfo.check = false;
this.selectedDays = [];
}
}
}
switch (this.option.type) {
case 'day':
this.picked();
break;
case 'min':
this.showOne('hour');
// shift activated time items to visible position.
this.shiftActTime();
break;
}
},
showYear: function showYear() {
let _this3 = this;
let year = (0, _moment2.default)(this.checked.currentMoment).year();
this.library.year = [];
let yearTmp = [];
for (let i = year - 100; i < year + 5; ++i) {
yearTmp.push(i);
}
this.library.year = yearTmp;
this.showOne('year');
this.$nextTick(function () {
let listDom = document.getElementById('yearList');
listDom.scrollTop = listDom.scrollHeight - 100;
_this3.addYear();
});
},
showOne: function showOne(type) {
switch (type) {
case 'year':
this.showInfo.hour = false;
this.showInfo.day = false;
this.showInfo.year = true;
this.showInfo.month = false;
break;
case 'month':
this.showInfo.hour = false;
this.showInfo.day = false;
this.showInfo.year = false;
this.showInfo.month = true;
break;
case 'day':
this.showInfo.hour = false;
this.showInfo.day = true;
this.showInfo.year = false;
this.showInfo.month = false;
break;
case 'hour':
this.showInfo.hour = true;
this.showInfo.day = false;
this.showInfo.year = false;
this.showInfo.month = false;
break;
default:
this.showInfo.day = true;
this.showInfo.year = false;
this.showInfo.month = false;
this.showInfo.hour = false;
}
},
showMonth: function showMonth() {
this.showOne('month');
},
addYear: function addYear() {
let _this4 = this;
let listDom = document.getElementById('yearList');
listDom.addEventListener('scroll', function (e) {
if (listDom.scrollTop >= listDom.scrollHeight - 100) {
return;
}
let len = _this4.library.year.length;
let lastYear = _this4.library.year[len - 1];
_this4.library.year.push(lastYear + 1);
}, false);
},
setYear: function setYear(year) {
this.checked.currentMoment = (0, _moment2.default)(year + '-' + this.checked.month + '-' + this.checked.day);
this.showDay(this.checked.currentMoment);
},
setMonth: function setMonth(month) {
let mo = this.library.month.indexOf(month) + 1;
if (mo < 10) {
mo = '0' + '' + mo;
}
this.checked.currentMoment = (0, _moment2.default)(this.checked.year + '-' + mo + '-' + this.checked.day);
this.showDay(this.checked.currentMoment);
},
showCheck: function showCheck() {
if (this.date.time === '') {
this.showDay();
} else {
if (this.option.type === 'day' || this.option.type === 'min') {
this.checked.oldtime = this.date.time;
this.showDay(this.date.time);
} else {
this.selectedDays = JSON.parse(this.date.time);
if (this.selectedDays.length) {
this.checked.oldtime = this.selectedDays[0];
this.showDay(this.selectedDays[0]);
} else {
this.showDay();
}
}
}
this.showInfo.check = true;
},
setTime: function setTime(type, obj, list) {
let _iteratorNormalCompletion2 = true;
let _didIteratorError2 = false;
let _iteratorError2 = undefined;
try {
for (let _iterator2 = list[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
let item = _step2.value;
item.checked = false;
if (item.value === obj.value) {
item.checked = true;
this.checked[type] = item.value;
}
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
},
picked: function picked() {
if (this.option.type === 'day' || this.option.type === 'min') {
let ctime = this.checked.year + '-' + this.checked.month + '-' + this.checked.day + ' ' + this.checked.hour + ':' + this.checked.min;
this.checked.currentMoment = (0, _moment2.default)(ctime, 'YYYY-MM-DD HH:mm');
this.date.time = (0, _moment2.default)(this.checked.currentMoment).format(this.option.format);
} else {
this.date.time = JSON.stringify(this.selectedDays);
}
this.showInfo.check = false;
this.$emit('change', this.date.time);
},
dismiss: function dismiss(evt) {
if (evt.target.className !== 'datepicker-overlay') {
return;
}
if (!this.option.dismissible) {
return;
}
this.showInfo.check = false;
this.$emit('cancel');
},
shiftActTime: function shiftActTime() {
// shift activated time items to visible position.
this.$nextTick(function () {
if (!document.querySelector('.hour-item.active')) {
return false;
}
document.querySelector('.hour-box').scrollTop = (document.querySelector('.hour-item.active').offsetTop || 0) - 250;
document.querySelector('.min-box').scrollTop = (document.querySelector('.min-item.active').offsetTop || 0) - 250;
});
}
}
})
export default class DatePicker extends Vue {}
</script>

View File

@ -15,7 +15,7 @@
</div>
<div class="usage-report-container__options-area__option" @click.prevent.self="onCustomDateClick">
<p class="usage-report-container__options-area__option__label" @click.prevent.self="onCustomDateClick">Custom Date Range</p>
<Datepicker
<VDatepicker
ref="datePicker"
:date="startTime"
@change="getDates"
@ -58,7 +58,7 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import Datepicker from '@/components/project/DatePicker.vue';
import VDatepicker from '@/components/common/VDatePicker.vue';
import { RouteConfig } from '@/router';
import { PROJECT_USAGE_ACTIONS } from '@/store/modules/usage';
@ -68,15 +68,15 @@ import { toUnixTimestamp } from '@/utils/time';
@Component({
components: {
Datepicker,
VDatepicker,
},
})
export default class UsageReport extends Vue {
public startTime: any = {
time: '',
public readonly startTime = {
time: null,
};
private readonly dateRange: any;
private readonly dateRange;
public constructor() {
super();
@ -179,7 +179,7 @@ export default class UsageReport extends Vue {
window.open(url.href, '_blank');
}
public async getDates(datesArray: string[]): Promise<void> {
public async getDates(datesArray: Date[]): Promise<void> {
const now = new Date();
const firstDate = new Date(datesArray[0]);
const secondDate = new Date(datesArray[1]);
@ -240,7 +240,7 @@ export default class UsageReport extends Vue {
<style scoped lang="scss">
.usage-report-container {
position: relative;
&__header {
display: flex;
flex-direction: row;
@ -424,7 +424,7 @@ export default class UsageReport extends Vue {
@media screen and (max-width: 1600px) {
.usage-report-container {
&__header {
&__title {

View File

@ -0,0 +1,200 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
/**
* Options is a set of options used for VDatePicker.vue
*/
export class Options {
public constructor(
public mondayFirstWeek: string[] = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'],
public sundayFirstWeek: string[] = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
public month: string[] = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
public color = {
checked: '#2683FF',
header: '#2683FF',
headerText: '#444C63',
},
public inputStyle = {
'visibility': 'hidden',
'width': '0',
},
public overlayOpacity: number = 0.5,
public dismissible: boolean = true,
) {}
}
/**
* DayItem is used to store information about day cell in calendar
*/
export class DayItem {
public constructor(
public value: number,
public inMonth: boolean,
public unavailable: boolean,
public checked: boolean,
public moment: Date,
public action: DayAction = DayAction.Default,
public today: boolean = false,
) {}
public equals(dateToCompare: Date): boolean {
const isDayEqual = this.moment.getDate() === dateToCompare.getDate();
const isMonthEqual = this.moment.getMonth() === dateToCompare.getMonth();
const isYearEqual = this.moment.getFullYear() === dateToCompare.getFullYear();
return isDayEqual && isMonthEqual && isYearEqual;
}
}
/**
* DayAction is enum represents month change direction on day click
*/
export enum DayAction {
Next,
Previous,
Default,
}
/**
* DateStamp is cozy representation of Date for view
*/
export class DateStamp {
public constructor(
public year: number,
public month: number,
public day: number,
) {}
public fromDate(date: Date): void {
this.year = date.getFullYear();
this.month = date.getMonth();
this.day = date.getDate();
}
}
/**
* DisplayedType is enum represents view type to show in calendar to check
*/
export enum DisplayedType {
Day,
Month,
Year,
}
/**
* DateGenerator is utility class used for generating DayItem and year lists for calendar
*/
export class DateGenerator {
private current: DateStamp;
private isSundayFirst: boolean;
public populateDays(current: DateStamp, isSundayFirst: boolean): DayItem[] {
this.current = current;
this.isSundayFirst = isSundayFirst;
const days: DayItem[] = [];
this.populateSelectedMonthDays(days);
this.populatePreviousMonthDays(days);
this.populateNextMonthDays(days);
this.markToday(days);
return days;
}
public populateYears(): number[] {
const year = new Date().getFullYear();
const years: number[] = [];
for (let i = year - 99; i <= year; i++) {
years.unshift(i);
}
return years;
}
private populateSelectedMonthDays(days: DayItem[]): void {
const daysInSelectedMonth = new Date(this.current.year, this.current.month + 1, 0).getDate();
const now = new Date();
const daysInCurrentMonth = now.getMonth();
for (let i = 1; i <= daysInSelectedMonth; i++) {
const moment = new Date(this.current.year, this.current.month, this.current.day);
moment.setDate(i);
days.push(
new DayItem(
i,
this.current.month !== daysInCurrentMonth || (this.current.month === daysInCurrentMonth && i <= now.getDate()),
false,
false,
moment,
),
);
}
}
private populatePreviousMonthDays(days: DayItem[]): void {
const previousMonth = new Date(this.current.year, this.current.month, this.current.day);
previousMonth.setMonth(previousMonth.getMonth() - 1);
const firstDate = new Date(this.current.year, this.current.month, this.current.day);
firstDate.setDate(1);
let firstDay = firstDate.getDay();
if (firstDay === 0) firstDay = 7;
const daysInPreviousMonth = new Date(previousMonth.getFullYear(), previousMonth.getMonth() + 1, 0).getDate();
for (let i = 0; i < firstDay - (this.isSundayFirst ? 0 : 1); i++) {
const moment = new Date(this.current.year, this.current.month, this.current.day);
moment.setDate(1);
moment.setMonth(moment.getMonth() - 1);
moment.setDate(new Date(moment.getFullYear(), moment.getMonth() + 1, 0).getDate() - i);
days.unshift(
new DayItem(
daysInPreviousMonth - i,
false,
false,
false,
moment,
DayAction.Previous,
),
);
}
}
private populateNextMonthDays(days: DayItem[]): void {
const passiveDaysAtFinal = 42 - days.length;
for (let i = 1; i <= passiveDaysAtFinal; i++) {
const moment = new Date(this.current.year, this.current.month, this.current.day);
moment.setMonth(moment.getMonth() + 1);
moment.setDate(i);
days.push(
new DayItem(
i,
false,
false,
false,
moment,
DayAction.Next,
),
);
}
}
private markToday(days: DayItem[]): void {
const now = new Date();
const daysCount = days.length;
for (let i = 0; i < daysCount; i++) {
const day: DayItem = days[i];
if (day.equals(now)) {
day.today = true;
break;
}
}
}
}

View File

@ -0,0 +1,196 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
import VDatePicker from '@/components/common/VDatePicker.vue';
import { mount } from '@vue/test-utils';
const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
describe('VDatePicker.vue', () => {
it('renders correctly', function () {
const wrapper = mount(VDatePicker, {});
wrapper.vm.showCheck();
expect(wrapper.findAll('li').at(0).text()).toBe('Mo');
expect(wrapper.findAll('.day').length).toBe(42);
wrapper.vm.showYear();
expect(wrapper.findAll('.year').length).toBe(100);
wrapper.vm.showMonth();
expect(wrapper.findAll('.month').length).toBe(12);
});
it('renders correctly with props', function () {
const wrapper = mount(VDatePicker, {
propsData: {
isSundayFirst: true,
},
});
wrapper.vm.showCheck();
expect(wrapper.findAll('li').at(0).text()).toBe('Su');
expect(wrapper.findAll('.day').length).toBe(42);
});
it('triggers correct functionality on normal check', function () {
const wrapper = mount(VDatePicker);
wrapper.vm.showCheck();
wrapper.vm.setYear(2019);
wrapper.vm.setMonth(months[9]);
wrapper.findAll('.day').at(1).trigger('click');
expect(wrapper.vm.selectedDays.length).toBe(1);
const selectedDay = wrapper.vm.selectedDays[0];
expect(selectedDay.getDate()).toBe(1);
expect(selectedDay.getMonth()).toBe(9);
expect(selectedDay.getFullYear()).toBe(2019);
wrapper.findAll('.day').at(2).trigger('click');
expect(wrapper.vm.selectedDays.length).toBe(0);
});
it('triggers correct functionality on toggle checking', function () {
const wrapper = mount(VDatePicker);
wrapper.vm.showCheck();
wrapper.vm.setYear(2019);
wrapper.vm.setMonth(months[9]);
wrapper.findAll('.day').at(1).trigger('click');
expect(wrapper.vm.selectedDays.length).toBe(1);
const selectedDay1 = wrapper.vm.selectedDays[0];
expect(selectedDay1.getDate()).toBe(1);
expect(selectedDay1.getMonth()).toBe(9);
expect(selectedDay1.getFullYear()).toBe(2019);
wrapper.findAll('.day').at(1).trigger('click');
expect(wrapper.vm.selectedDays.length).toBe(0);
wrapper.findAll('.day').at(2).trigger('click');
expect(wrapper.vm.selectedDays.length).toBe(1);
const selectedDay2 = wrapper.vm.selectedDays[0];
expect(selectedDay2.getDate()).toBe(2);
expect(selectedDay2.getMonth()).toBe(9);
expect(selectedDay2.getFullYear()).toBe(2019);
});
it('triggers correct functionality on month selection', function () {
const wrapper = mount(VDatePicker);
wrapper.vm.showCheck();
wrapper.vm.setYear(2019);
wrapper.vm.setMonth(months[9]);
expect(wrapper.findAll('.month').length).toBe(0);
wrapper.find('.month-selection').trigger('click');
expect(wrapper.findAll('.month').length).toBe(12);
wrapper.findAll('.month').at(0).trigger('click');
expect(wrapper.vm.selectedDateState.month).toBe(0);
expect(wrapper.find('.month-selection').text()).toBe(months[0]);
});
it('triggers correct functionality on year selection', function () {
const wrapper = mount(VDatePicker);
wrapper.vm.showCheck();
wrapper.vm.setYear(2019);
wrapper.vm.setMonth(months[9]);
expect(wrapper.findAll('.year').length).toBe(0);
wrapper.find('.year-selection').trigger('click');
expect(wrapper.findAll('.year').length).toBe(100);
expect(wrapper.findAll('.year').at(0).text()).toBe('2019');
wrapper.find('.year-selection').trigger('click');
wrapper.findAll('.year').at(1).trigger('click');
expect(wrapper.vm.selectedDateState.year).toBe(2018);
expect(wrapper.find('.year-selection').text()).toBe('2018');
});
it('triggers correct functionality on month incrementation', function () {
const wrapper = mount(VDatePicker);
const now = new Date();
const nowYear = now.getFullYear();
wrapper.vm.showCheck();
wrapper.vm.setYear(nowYear);
wrapper.vm.setMonth(months[now.getMonth() - 1]);
const actualDates = wrapper.findAll('.day');
actualDates.at(actualDates.length - 1).trigger('click');
expect(wrapper.vm.selectedDateState.year).toBe(nowYear);
expect(wrapper.vm.selectedDateState.month).toBe(now.getMonth());
wrapper.find('.cov-date-next').trigger('click');
expect(wrapper.vm.selectedDateState.year).toBe(nowYear);
expect(wrapper.vm.selectedDateState.month).toBe(now.getMonth());
wrapper.vm.setYear(nowYear - 1);
wrapper.vm.setMonth(months[0]);
const changedDates = wrapper.findAll('.day');
changedDates.at(changedDates.length - 1).trigger('click');
expect(wrapper.vm.selectedDateState.year).toBe(nowYear - 1);
expect(wrapper.vm.selectedDateState.month).toBe(1);
wrapper.find('.cov-date-next').trigger('click');
expect(wrapper.vm.selectedDateState.year).toBe(nowYear - 1);
expect(wrapper.vm.selectedDateState.month).toBe(2);
});
it('triggers correct functionality on month decrementation', function () {
const wrapper = mount(VDatePicker);
wrapper.vm.showCheck();
wrapper.vm.setYear(2019);
wrapper.vm.setMonth(months[9]);
wrapper.findAll('.day').at(0).trigger('click');
expect(wrapper.vm.selectedDateState.month).toBe(8);
wrapper.find('.cov-date-previous').trigger('click');
expect(wrapper.vm.selectedDateState.month).toBe(7);
wrapper.vm.setMonth(months[0]);
wrapper.find('.cov-date-previous').trigger('click');
expect(wrapper.vm.selectedDateState.year).toBe(2018);
expect(wrapper.vm.selectedDateState.month).toBe(11);
wrapper.vm.setYear(2019);
wrapper.vm.setMonth(months[0]);
wrapper.findAll('.day').at(0).trigger('click');
expect(wrapper.vm.selectedDateState.year).toBe(2018);
expect(wrapper.vm.selectedDateState.month).toBe(11);
});
});

View File

@ -0,0 +1,80 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
import {
DateGenerator,
DateStamp,
DayItem,
} from '@/utils/datepicker';
describe('datepicker', () => {
it('DateGenerator populate years correctly', () => {
const dateGenerator = new DateGenerator();
const currentYear = new Date().getFullYear();
const years = dateGenerator.populateYears();
expect(years.length).toBe(100);
expect(years[0]).toBe(currentYear);
});
it('DateGenerator populate days correctly with exact date and isSundayFirst', () => {
const dateGenerator = new DateGenerator();
// 8th month is september
const currentDate = new DateStamp(2019, 8, 30);
const firstExpectedDay = new DayItem(
25,
false,
false,
false,
new Date(2019, 7, 25),
1,
false,
);
const lastExpectedDay = new DayItem(
5,
false,
false,
false,
new Date(2019, 9, 5),
1,
false,
);
const days = dateGenerator.populateDays(currentDate, true);
expect(days.length).toBe(42);
expect(days[0].equals(firstExpectedDay.moment)).toBe(true);
expect(days[days.length - 1].equals(lastExpectedDay.moment)).toBe(true);
});
it('DateGenerator populate days correctly with exact date and no isSundayFirst', () => {
const dateGenerator = new DateGenerator();
// 8th month is september
const currentDate = new DateStamp(2019, 8, 30);
const firstExpectedDay = new DayItem(
26,
false,
false,
false,
new Date(2019, 7, 26),
1,
false,
);
const lastExpectedDay = new DayItem(
6,
false,
false,
false,
new Date(2019, 9, 6),
1,
false,
);
const days = dateGenerator.populateDays(currentDate, false);
expect(days.length).toBe(42);
expect(days[0].equals(firstExpectedDay.moment)).toBe(true);
expect(days[days.length - 1].equals(lastExpectedDay.moment)).toBe(true);
});
});

View File

@ -37,8 +37,6 @@
"tests/**/*.tsx"
],
"exclude": [
"node_modules",
// TODO: temporary file
"src/components/project/DatePicker.vue"
"node_modules"
]
}

View File

@ -5,9 +5,7 @@
],
"linterOptions": {
"exclude": [
"node_modules/**",
// TODO: temporary file
"src/components/project/DatePicker.vue"
"node_modules/**"
]
},
"rules": {
@ -15,7 +13,6 @@
"align": [true, "parameters", "statements"],
"array-type": [true, "array-simple"],
"arrow-return-shorthand": true,
"check-format": true,
"class-name": true,
"comment-format": [true, "check-space"],
"comment-type": [true, "doc", "singleline"],