web/satellite: DatePicker rework (#3157)
This commit is contained in:
parent
d29946d3d7
commit
ef2615fcf4
557
web/satellite/src/components/common/VDatePicker.vue
Normal file
557
web/satellite/src/components/common/VDatePicker.vue
Normal 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>
|
@ -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>
|
|
@ -15,7 +15,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="usage-report-container__options-area__option" @click.prevent.self="onCustomDateClick">
|
<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>
|
<p class="usage-report-container__options-area__option__label" @click.prevent.self="onCustomDateClick">Custom Date Range</p>
|
||||||
<Datepicker
|
<VDatepicker
|
||||||
ref="datePicker"
|
ref="datePicker"
|
||||||
:date="startTime"
|
:date="startTime"
|
||||||
@change="getDates"
|
@change="getDates"
|
||||||
@ -58,7 +58,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue } from 'vue-property-decorator';
|
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 { RouteConfig } from '@/router';
|
||||||
import { PROJECT_USAGE_ACTIONS } from '@/store/modules/usage';
|
import { PROJECT_USAGE_ACTIONS } from '@/store/modules/usage';
|
||||||
@ -68,15 +68,15 @@ import { toUnixTimestamp } from '@/utils/time';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
Datepicker,
|
VDatepicker,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
export default class UsageReport extends Vue {
|
export default class UsageReport extends Vue {
|
||||||
public startTime: any = {
|
public readonly startTime = {
|
||||||
time: '',
|
time: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly dateRange: any;
|
private readonly dateRange;
|
||||||
|
|
||||||
public constructor() {
|
public constructor() {
|
||||||
super();
|
super();
|
||||||
@ -179,7 +179,7 @@ export default class UsageReport extends Vue {
|
|||||||
window.open(url.href, '_blank');
|
window.open(url.href, '_blank');
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getDates(datesArray: string[]): Promise<void> {
|
public async getDates(datesArray: Date[]): Promise<void> {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const firstDate = new Date(datesArray[0]);
|
const firstDate = new Date(datesArray[0]);
|
||||||
const secondDate = new Date(datesArray[1]);
|
const secondDate = new Date(datesArray[1]);
|
||||||
@ -240,7 +240,7 @@ export default class UsageReport extends Vue {
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.usage-report-container {
|
.usage-report-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&__header {
|
&__header {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -424,7 +424,7 @@ export default class UsageReport extends Vue {
|
|||||||
|
|
||||||
@media screen and (max-width: 1600px) {
|
@media screen and (max-width: 1600px) {
|
||||||
.usage-report-container {
|
.usage-report-container {
|
||||||
|
|
||||||
&__header {
|
&__header {
|
||||||
|
|
||||||
&__title {
|
&__title {
|
||||||
|
200
web/satellite/src/utils/datepicker.ts
Normal file
200
web/satellite/src/utils/datepicker.ts
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
196
web/satellite/tests/unit/common/VDatePicker.spec.ts
Normal file
196
web/satellite/tests/unit/common/VDatePicker.spec.ts
Normal 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);
|
||||||
|
});
|
||||||
|
});
|
80
web/satellite/tests/unit/utils/datepicker.spec.ts
Normal file
80
web/satellite/tests/unit/utils/datepicker.spec.ts
Normal 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);
|
||||||
|
});
|
||||||
|
});
|
@ -37,8 +37,6 @@
|
|||||||
"tests/**/*.tsx"
|
"tests/**/*.tsx"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules",
|
"node_modules"
|
||||||
// TODO: temporary file
|
|
||||||
"src/components/project/DatePicker.vue"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,7 @@
|
|||||||
],
|
],
|
||||||
"linterOptions": {
|
"linterOptions": {
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules/**",
|
"node_modules/**"
|
||||||
// TODO: temporary file
|
|
||||||
"src/components/project/DatePicker.vue"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
@ -15,7 +13,6 @@
|
|||||||
"align": [true, "parameters", "statements"],
|
"align": [true, "parameters", "statements"],
|
||||||
"array-type": [true, "array-simple"],
|
"array-type": [true, "array-simple"],
|
||||||
"arrow-return-shorthand": true,
|
"arrow-return-shorthand": true,
|
||||||
"check-format": true,
|
|
||||||
"class-name": true,
|
"class-name": true,
|
||||||
"comment-format": [true, "check-space"],
|
"comment-format": [true, "check-space"],
|
||||||
"comment-type": [true, "doc", "singleline"],
|
"comment-type": [true, "doc", "singleline"],
|
||||||
|
Loading…
Reference in New Issue
Block a user