Web usage report markup (#1409)
This commit is contained in:
parent
e016105a72
commit
5134766d57
@ -23,17 +23,17 @@
|
||||
margin: 0 !important;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "montserrat_regular";
|
||||
src: url("../../satellite/static/fonts/montserrat_regular.ttf");
|
||||
font-family: "font_regular";
|
||||
src: url("../../satellite/static/fonts/font_regular.ttf");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "montserrat_medium";
|
||||
src: url("../../satellite/static/fonts/montserrat_medium.ttf");
|
||||
font-family: "font_medium";
|
||||
src: url("../../satellite/static/fonts/font_medium.ttf");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "montserrat_bold";
|
||||
src: url("../../satellite/static/fonts/montserrat_bold.ttf");
|
||||
font-family: "font_bold";
|
||||
src: url("../../satellite/static/fonts/font_bold.ttf");
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
@ -97,7 +97,7 @@ export default class Failure extends Vue {}
|
||||
|
||||
&__title {
|
||||
width: 558px;
|
||||
font-family: 'montserrat_bold';
|
||||
font-family: 'font_bold';
|
||||
font-size: 48px;
|
||||
font-style: normal;
|
||||
font-stretch: normal;
|
||||
@ -112,7 +112,7 @@ export default class Failure extends Vue {}
|
||||
&__info {
|
||||
margin-top: 24px;
|
||||
width: 446px;
|
||||
font-family: 'montserrat_regular';
|
||||
font-family: 'font_regular';
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-stretch: normal;
|
||||
|
@ -131,7 +131,7 @@ export default class Loading extends Vue {}
|
||||
margin-top: 46px;
|
||||
|
||||
&__text {
|
||||
font-family: 'montserrat_bold';
|
||||
font-family: 'font_bold';
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-stretch: normal;
|
||||
@ -149,7 +149,7 @@ export default class Loading extends Vue {}
|
||||
|
||||
&__support {
|
||||
margin-top: 128px;
|
||||
font-family: 'montserrat_regular';
|
||||
font-family: 'font_regular';
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-stretch: normal;
|
||||
@ -159,7 +159,7 @@ export default class Loading extends Vue {}
|
||||
color: #696c77;
|
||||
|
||||
a {
|
||||
font-family: 'montserrat_medium';
|
||||
font-family: 'font_medium';
|
||||
font-size: 12px;
|
||||
color: #1494ff;
|
||||
text-decoration: none;
|
||||
|
@ -73,7 +73,7 @@
|
||||
|
||||
<style lang="scss">
|
||||
h1 {
|
||||
font-family: 'montserrat_bold';
|
||||
font-family: 'font_bold';
|
||||
font-size: 48px;
|
||||
font-style: normal;
|
||||
font-stretch: normal;
|
||||
@ -85,7 +85,7 @@
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-family: 'montserrat_regular';
|
||||
font-family: 'font_regular';
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-stretch: normal;
|
||||
@ -123,7 +123,7 @@
|
||||
|
||||
h2 {
|
||||
opacity: 0.4;
|
||||
font-family: 'montserrat_bold';
|
||||
font-family: 'font_bold';
|
||||
font-size: 32px;
|
||||
font-style: normal;
|
||||
font-stretch: normal;
|
||||
@ -147,7 +147,7 @@
|
||||
&__input {
|
||||
width: calc(100% - 32px);
|
||||
background-color: #e4e4e6;
|
||||
font-family: 'montserrat_regular';
|
||||
font-family: 'font_regular';
|
||||
border-radius: 12px;
|
||||
border: solid 1px #e4e4e6;
|
||||
font-size: 16px;
|
||||
@ -167,7 +167,7 @@
|
||||
top: 12px;
|
||||
|
||||
&__text {
|
||||
font-family: 'montserrat_bold';
|
||||
font-family: 'font_bold';
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-stretch: normal;
|
||||
@ -194,7 +194,7 @@
|
||||
margin-top: 300px;
|
||||
|
||||
p {
|
||||
font-family: 'montserrat_regular';
|
||||
font-family: 'font_regular';
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
|
@ -89,7 +89,7 @@
|
||||
|
||||
&__title {
|
||||
width: 278px;
|
||||
font-family: 'montserrat_bold';
|
||||
font-family: 'font_bold';
|
||||
font-size: 48px;
|
||||
font-style: normal;
|
||||
font-stretch: normal;
|
||||
@ -104,7 +104,7 @@
|
||||
&__info {
|
||||
margin-top: 24px;
|
||||
width: 446px;
|
||||
font-family: 'montserrat_regular';
|
||||
font-family: 'font_regular';
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-stretch: normal;
|
||||
|
@ -18,6 +18,7 @@
|
||||
"apollo-link-http": "^1.5.5",
|
||||
"graphql": "^14.0.2",
|
||||
"graphql-tag": "^2.10.0",
|
||||
"moment": "^2.24.0",
|
||||
"vue": "^2.5.17",
|
||||
"vue-apollo": "^3.0.0-beta.25",
|
||||
"vue-class-component": "^6.0.0",
|
||||
@ -33,7 +34,7 @@
|
||||
"@types/sinon": "^5.0.5",
|
||||
"@vue/cli-plugin-babel": "^3.0.5",
|
||||
"@vue/cli-plugin-typescript": "^3.0.5",
|
||||
"@vue/cli-plugin-unit-jest": "^3.0.5",
|
||||
"@vue/cli-plugin-unit-jest": "^3.4.1",
|
||||
"@vue/cli-service": "^3.0.5",
|
||||
"@vue/test-utils": "^1.0.0-beta.25",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
|
844
web/satellite/src/components/project/DatePicker.vue
Normal file
844
web/satellite/src/components/project/DatePicker.vue
Normal file
@ -0,0 +1,844 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
// This component needs to be improved in future
|
||||
<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;
|
||||
type === 'next' ? next = (0, _moment2.default)(this.checked.currentMoment).add(1, 'M') : 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 oldtime = this.checked.oldtime;
|
||||
for (let i = 1; i <= monthDays; ++i) {
|
||||
days.push({
|
||||
value: i,
|
||||
inMonth: true,
|
||||
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);
|
||||
}
|
||||
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 UsageReport extends Vue {}
|
||||
</script>
|
@ -52,6 +52,20 @@
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<div class="project-details-info-container" >
|
||||
<div class="project-details-info-container__usage-report-container">
|
||||
<div class="project-details-info-container__usage-report-container__info">
|
||||
<img src="../../../static/images/projectDetails/UsageReport.svg" alt="">
|
||||
<div class="project-details-info-container__usage-report-container__info__text">
|
||||
<h4>Usage Report</h4>
|
||||
<h2>Storj Satellite Usage reports provide access to detailed data, enabling you to better analyze and understand your Storj Network resources consumption</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="project-details-info-container__usage-report-container__buttons-area">
|
||||
<Button label="More" width="140px" height="48px" :onPress="onMoreClick"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="project-details__button-area" id="deleteProjectPopupButton">
|
||||
<Button class="delete-project" label="Delete project" width="180px" height="48px" :onPress="toggleDeleteDialog" isDeletion/>
|
||||
</div>
|
||||
@ -73,6 +87,7 @@ import Checkbox from '@/components/common/Checkbox.vue';
|
||||
import EmptyState from '@/components/common/EmptyStateArea.vue';
|
||||
import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
|
||||
import { PROJETS_ACTIONS, APP_STATE_ACTIONS, NOTIFICATION_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import ROUTES from '@/utils/constants/routerConstants';
|
||||
import DeleteProjectPopup from '@/components/project/DeleteProjectPopup.vue';
|
||||
|
||||
@Component(
|
||||
@ -113,7 +128,10 @@ import DeleteProjectPopup from '@/components/project/DeleteProjectPopup.vue';
|
||||
},
|
||||
toggleDeleteDialog: function (): void {
|
||||
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_DEL_PROJ);
|
||||
}
|
||||
},
|
||||
onMoreClick: function (): void {
|
||||
this.$router.push(ROUTES.USAGE_REPORT);
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
name: function (): string {
|
||||
@ -304,5 +322,30 @@ export default class ProjectDetailsArea extends Vue {
|
||||
height: 10vh;
|
||||
}
|
||||
}
|
||||
|
||||
&__usage-report-container {
|
||||
@extend .project-details-info-container__description-container;
|
||||
|
||||
&__info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
&__text {
|
||||
margin-left: 2vw;
|
||||
}
|
||||
}
|
||||
|
||||
&__buttons-area {
|
||||
@extend .project-details-info-container__usage-report-container__info;
|
||||
width: 380px;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 6vw;
|
||||
height: 10vh;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
188
web/satellite/src/components/project/ReportTable.vue
Normal file
188
web/satellite/src/components/project/ReportTable.vue
Normal file
@ -0,0 +1,188 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<table class="blueTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Bucket Name</th>
|
||||
<th>Roll Up Period</th>
|
||||
<th>Network Stored Data, GBh</th>
|
||||
<th colspan="3">Egress, GB</th>
|
||||
<th colspan="2">Objects, count*hours</th>
|
||||
<th>Metadata Size, GBh</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th>Repair</th>
|
||||
<th>Get</th>
|
||||
<th>Audit</th>
|
||||
<th>Inline Segments</th>
|
||||
<th>Remote segments</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="tg-0lax">My Data Bucket 1</td>
|
||||
<td class="tg-0lax">01.02.2019-01.28.2019</td>
|
||||
<td class="tg-0lax">800</td>
|
||||
<td class="tg-0lax">10</td>
|
||||
<td class="tg-0lax">400</td>
|
||||
<td class="tg-0lax">20</td>
|
||||
<td class="tg-0lax">1000</td>
|
||||
<td class="tg-0lax">700</td>
|
||||
<td class="tg-0lax">0.1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-0lax">My Data Bucket 2</td>
|
||||
<td class="tg-0lax">01.02.2019-01.28.2019</td>
|
||||
<td class="tg-0lax">700</td>
|
||||
<td class="tg-0lax">10</td>
|
||||
<td class="tg-0lax">400</td>
|
||||
<td class="tg-0lax">20</td>
|
||||
<td class="tg-0lax">1000</td>
|
||||
<td class="tg-0lax">700</td>
|
||||
<td class="tg-0lax">0.2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-0lax">My Data Bucket 3</td>
|
||||
<td class="tg-0lax">01.02.2019-01.28.2019</td>
|
||||
<td class="tg-0lax">600</td>
|
||||
<td class="tg-0lax">10</td>
|
||||
<td class="tg-0lax">400</td>
|
||||
<td class="tg-0lax">20</td>
|
||||
<td class="tg-0lax">1000</td>
|
||||
<td class="tg-0lax">700</td>
|
||||
<td class="tg-0lax">0.3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-0lax">My Data Bucket 4</td>
|
||||
<td class="tg-0lax">01.02.2019-01.28.2019</td>
|
||||
<td class="tg-0lax">550</td>
|
||||
<td class="tg-0lax">10</td>
|
||||
<td class="tg-0lax">400</td>
|
||||
<td class="tg-0lax">20</td>
|
||||
<td class="tg-0lax">1000</td>
|
||||
<td class="tg-0lax">700</td>
|
||||
<td class="tg-0lax">0.15</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-0lax">My Data Bucket 5</td>
|
||||
<td class="tg-0lax">01.02.2019-01.28.2019</td>
|
||||
<td class="tg-0lax">500</td>
|
||||
<td class="tg-0lax">10</td>
|
||||
<td class="tg-0lax">400</td>
|
||||
<td class="tg-0lax">20</td>
|
||||
<td class="tg-0lax">1000</td>
|
||||
<td class="tg-0lax">700</td>
|
||||
<td class="tg-0lax">0.11</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-0lax">My Data Bucket 6</td>
|
||||
<td class="tg-0lax">01.02.2019-01.28.2019</td>
|
||||
<td class="tg-0lax">1000</td>
|
||||
<td class="tg-0lax">10</td>
|
||||
<td class="tg-0lax">400</td>
|
||||
<td class="tg-0lax">20</td>
|
||||
<td class="tg-0lax">1000</td>
|
||||
<td class="tg-0lax">700</td>
|
||||
<td class="tg-0lax">0.13</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-0lax">My Data Bucket 7</td>
|
||||
<td class="tg-0lax">01.02.2019-01.28.2019</td>
|
||||
<td class="tg-0lax">1200</td>
|
||||
<td class="tg-0lax">10</td>
|
||||
<td class="tg-0lax">400</td>
|
||||
<td class="tg-0lax">20</td>
|
||||
<td class="tg-0lax">1000</td>
|
||||
<td class="tg-0lax">700</td>
|
||||
<td class="tg-0lax">0.13</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-0lax">My Data Bucket 8</td>
|
||||
<td class="tg-0lax">01.02.2019-01.28.2019</td>
|
||||
<td class="tg-0lax">1300</td>
|
||||
<td class="tg-0lax">10</td>
|
||||
<td class="tg-0lax">400</td>
|
||||
<td class="tg-0lax">20</td>
|
||||
<td class="tg-0lax">1000</td>
|
||||
<td class="tg-0lax">700</td>
|
||||
<td class="tg-0lax">0.13</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-0lax">My Data Bucket 9</td>
|
||||
<td class="tg-0lax">01.02.2019-01.28.2019</td>
|
||||
<td class="tg-0lax">343</td>
|
||||
<td class="tg-0lax">10</td>
|
||||
<td class="tg-0lax">400</td>
|
||||
<td class="tg-0lax">20</td>
|
||||
<td class="tg-0lax">1000</td>
|
||||
<td class="tg-0lax">700</td>
|
||||
<td class="tg-0lax">0.13</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tg-0lax">My Data Bucket 10</td>
|
||||
<td class="tg-0lax">01.02.2019-01.28.2019</td>
|
||||
<td class="tg-0lax">12345</td>
|
||||
<td class="tg-0lax">10</td>
|
||||
<td class="tg-0lax">400</td>
|
||||
<td class="tg-0lax">20</td>
|
||||
<td class="tg-0lax">1000</td>
|
||||
<td class="tg-0lax">700</td>
|
||||
<td class="tg-0lax">0.13</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
@Component(
|
||||
{}
|
||||
)
|
||||
|
||||
export default class ReportTable extends Vue {}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
table.blueTable {
|
||||
border: 1px solid #1C6EA4;
|
||||
background-color: #EEEEEE;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.blueTable td, table.blueTable th {
|
||||
border: 1px solid #AAAAAA;
|
||||
padding: 3px 2px;
|
||||
}
|
||||
table.blueTable tbody td {
|
||||
font-size: 13px;
|
||||
}
|
||||
table.blueTable tbody tr:nth-child(even) {
|
||||
background: #D0E4F5;
|
||||
}
|
||||
table.blueTable thead {
|
||||
background: #1C6EA4;
|
||||
background: -moz-linear-gradient(top, #5592bb 0%, #327cad 66%, #1C6EA4 100%);
|
||||
background: -webkit-linear-gradient(top, #5592bb 0%, #327cad 66%, #1C6EA4 100%);
|
||||
background: linear-gradient(to bottom, #5592bb 0%, #327cad 66%, #1C6EA4 100%);
|
||||
border-bottom: 2px solid #444444;
|
||||
}
|
||||
table.blueTable thead th {
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
color: #FFFFFF;
|
||||
border-left: 2px solid #D0E4F5;
|
||||
}
|
||||
table.blueTable thead th:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
</style>
|
424
web/satellite/src/components/project/UsageReport.vue
Normal file
424
web/satellite/src/components/project/UsageReport.vue
Normal file
@ -0,0 +1,424 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div class="usage-report-container">
|
||||
<div class="usage-report-container__navigation">
|
||||
<div class="usage-report-container__navigation__button" @click="onBackClick">
|
||||
<svg width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.5607 0.43934C11.1464 1.02513 11.1464 1.97487 10.5607 2.56066L5.12132 8H17.5C18.3284 8 19 8.67157 19 9.5C19 10.3284 18.3284 11 17.5 11H5.12132L10.5607 16.4393C11.1464 17.0251 11.1464 17.9749 10.5607 18.5607C9.97487 19.1464 9.02513 19.1464 8.43934 18.5607L0.43934 10.5607C-0.146447 9.97487 -0.146447 9.02513 0.43934 8.43934L8.43934 0.43934C9.02513 -0.146447 9.97487 -0.146447 10.5607 0.43934Z" fill="#384B65"/>
|
||||
</svg>
|
||||
<p>Back to Project Details</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="usage-report-container__header">
|
||||
<p>Usage Report</p>
|
||||
<div class="usage-report-container__header__options-area">
|
||||
<div class="usage-report-container__header__options-area__option active" @click.prevent="onCurrentRollupClick">
|
||||
<p>Current roll up period</p>
|
||||
</div>
|
||||
<div class="usage-report-container__header__options-area__option" @click.prevent="onPreviousRollupClick">
|
||||
<p>Previous Roll Up Period</p>
|
||||
</div>
|
||||
<div class="usage-report-container__header__options-area__option" @click.prevent.self="onCustomDateClick">
|
||||
<p @click.prevent.self="onCustomDateClick">Custom Date Range</p>
|
||||
<Datepicker ref="datePicker" :date="startTime" @change="getDates"/>
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" @click.prevent.self="onCustomDateClick">
|
||||
<path d="M16.3213 2.28026H14.8009V1.50058C14.8009 1.10058 14.4806 0.760742 14.0611 0.760742C13.6611 0.760742 13.3213 1.08106 13.3213 1.50058V2.28026H6.66106V1.50058C6.66106 1.10058 6.34074 0.760742 5.92122 0.760742C5.5009 0.760742 5.2009 1.10058 5.2009 1.50058V2.28026H3.68058C1.92042 2.28026 0.500977 3.70058 0.500977 5.45986V16.0599C0.500977 17.82 1.9213 19.2395 3.68058 19.2395H16.3204C18.0805 19.2395 19.5 17.8191 19.5 16.0599V5.45986C19.5008 3.70048 18.0804 2.28026 16.321 2.28026H16.3213ZM3.68066 3.74042H5.20098V4.5201C5.20098 4.9201 5.5213 5.25994 5.94082 5.25994C6.36114 5.25994 6.68066 4.93962 6.68066 4.5201V3.74042H13.3603V4.5201C13.3603 4.9201 13.6806 5.25994 14.1001 5.25994C14.5001 5.25994 14.8399 4.93962 14.8399 4.5201V3.74042H16.3603C17.3001 3.74042 18.0806 4.50058 18.0806 5.46074V7.06074H1.96098V5.46074C1.96098 4.5209 2.74066 3.74042 3.68052 3.74042H3.68066ZM9.62126 14.2006H10.4009C11.0213 14.2006 11.5213 14.7006 11.5213 15.3209C11.5213 15.9413 11.0213 16.4413 10.4009 16.4413H9.62126C9.00094 16.4413 8.50094 15.9413 8.50094 15.3209C8.50094 14.7006 9.00094 14.2006 9.62126 14.2006ZM8.50094 10.8404C8.50094 10.2201 9.00094 9.7201 9.62126 9.7201L10.4009 9.72088C11.0213 9.72088 11.5213 10.2209 11.5213 10.8412C11.5213 11.4615 11.0213 11.9615 10.4009 11.9615H9.62126C9.00094 11.9607 8.50094 11.4607 8.50094 10.8404V10.8404ZM14.8407 14.2006H15.6204C16.2407 14.2006 16.7407 14.7006 16.7407 15.3209C16.7407 15.9413 16.2407 16.4413 15.6204 16.4413H14.8407C14.2204 16.4413 13.7204 15.9413 13.7204 15.3209C13.7212 14.7006 14.2212 14.2006 14.8407 14.2006ZM13.7212 10.8404C13.7212 10.2201 14.2212 9.7201 14.8415 9.7201H15.6212C16.2415 9.7201 16.7415 10.2201 16.7415 10.8404C16.7415 11.4607 16.2415 11.9607 15.6212 11.9607H14.8415C14.2212 11.9607 13.7212 11.4607 13.7212 10.8404ZM6.2806 10.8404C6.2806 11.4607 5.7806 11.9607 5.16028 11.9607H4.3806C3.76028 11.9607 3.26028 11.4607 3.26028 10.8404C3.26028 10.2201 3.76028 9.7201 4.3806 9.7201H5.16028C5.7806 9.72088 6.2806 10.2209 6.2806 10.8404ZM4.3806 14.2006H5.16028C5.7806 14.2006 6.2806 14.7006 6.2806 15.3209C6.2806 15.9413 5.7806 16.4413 5.16028 16.4413H4.3806C3.76028 16.4413 3.26028 15.9413 3.26028 15.3209C3.26106 14.7006 3.76106 14.2006 4.3806 14.2006Z" fill="#2683FF"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="usage-report-container__main-area">
|
||||
<div class="usage-report-container__main-area__info-area">
|
||||
<div class="usage-report-container__main-area__info-area__item">
|
||||
<h1>Storage GB/H</h1>
|
||||
<h2>200.23</h2>
|
||||
</div>
|
||||
<div class="usage-report-container__main-area__info-area__item">
|
||||
<h1>Egress GB/H</h1>
|
||||
<h2>944.23</h2>
|
||||
</div>
|
||||
<div class="usage-report-container__main-area__info-area__item">
|
||||
<h1>Objects Count/H</h1>
|
||||
<h2>30 223</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="usage-report-container__main-area__footer">
|
||||
<p>Current Roll Up Period <b>{{dateRange.startDate.toLocaleDateString("en-US")}}</b> to <b>{{dateRange.endDate.toLocaleDateString("en-US")}}</b></p>
|
||||
<div class="usage-report-container__main-area__footer__report-area">
|
||||
<p>Download Advanced Report</p>
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg" @click.prevent="onReportClick">
|
||||
<rect width="40" height="40" rx="4" fill="#E2ECF7"/>
|
||||
<path d="M25.6491 19.2809L21.2192 23.5281C20.891 23.8427 20.3988 24 20.0707 24C19.7425 24 19.2503 23.8427 19.0862 23.5281L14.4922 19.2809C13.8359 18.6517 13.8359 17.8652 14.4922 17.236C14.8204 16.9213 15.1485 16.9213 15.6407 16.9213C15.9689 16.9213 16.4611 17.0787 16.6252 17.3933L18.594 19.1236L18.594 11.4157C18.594 10.6292 19.2503 10 20.0707 10C20.891 10 21.5473 10.6292 21.5473 11.4157L21.5473 19.1236L23.5162 17.236C23.6803 16.9213 24.1725 16.9213 24.5006 16.9213C24.8288 16.9213 25.321 17.0787 25.4851 17.3933C26.1414 17.8652 26.1414 18.809 25.6491 19.2809Z" fill="#2683FF"/>
|
||||
<rect x="11" y="28" width="18" height="2" rx="1" fill="#2683FF"/>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="22" height="22" fill="white" transform="translate(10 10)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import ROUTES from '@/utils/constants/routerConstants';
|
||||
import Datepicker from '@/components/project/DatePicker.vue';
|
||||
|
||||
@Component(
|
||||
{
|
||||
data: function () {
|
||||
const currentDate = new Date();
|
||||
const previousDate = new Date();
|
||||
previousDate.setMonth(currentDate.getMonth() - 1);
|
||||
|
||||
return {
|
||||
startTime: {
|
||||
time: '',
|
||||
},
|
||||
dateRange: {
|
||||
startDate: previousDate,
|
||||
endDate: currentDate,
|
||||
}
|
||||
};
|
||||
},
|
||||
components: {
|
||||
Datepicker,
|
||||
},
|
||||
methods: {
|
||||
getDates: function(datesArray: string[]): void {
|
||||
const firstDate = new Date(datesArray[0]);
|
||||
const secondDate = new Date(datesArray[1]);
|
||||
const isInverted = firstDate > secondDate;
|
||||
this.$data.dateRange.startDate = isInverted ? secondDate : firstDate;
|
||||
this.$data.dateRange.endDate = isInverted ? firstDate : secondDate;
|
||||
},
|
||||
onBackClick: function (): void {
|
||||
this.$router.push(ROUTES.PROJECT_DETAILS);
|
||||
},
|
||||
onCurrentRollupClick: function (event: any) {
|
||||
const currentDate = new Date();
|
||||
const previousDate = new Date();
|
||||
previousDate.setMonth(currentDate.getMonth() - 1);
|
||||
|
||||
this.$data.dateRange.startDate = previousDate;
|
||||
this.$data.dateRange.endDate = currentDate;
|
||||
(this as any).onButtonClickAction(event);
|
||||
},
|
||||
onPreviousRollupClick: function (event: any) {
|
||||
const currentDate = new Date();
|
||||
const previousDate = new Date();
|
||||
currentDate.setMonth(currentDate.getMonth() - 1);
|
||||
previousDate.setMonth(currentDate.getMonth() - 1);
|
||||
|
||||
this.$data.dateRange.startDate = previousDate;
|
||||
this.$data.dateRange.endDate = currentDate;
|
||||
(this as any).onButtonClickAction(event);
|
||||
},
|
||||
onCustomDateClick: function (event: any) {
|
||||
(this as any).$refs.datePicker.showCheck();
|
||||
(this as any).onButtonClickAction(event);
|
||||
},
|
||||
onButtonClickAction: function (event: any) {
|
||||
let eventTarget = event.target;
|
||||
|
||||
if (eventTarget.children.length === 0) {
|
||||
eventTarget = eventTarget.parentNode;
|
||||
}
|
||||
|
||||
if (eventTarget.classList.contains('active')) {
|
||||
return;
|
||||
}
|
||||
|
||||
(this as any).changeActiveClass(eventTarget);
|
||||
},
|
||||
changeActiveClass: function (target: any): void {
|
||||
[...document.querySelectorAll('.usage-report-container__header__options-area__option')].forEach(option => {
|
||||
option.classList.remove('active');
|
||||
});
|
||||
|
||||
target.classList.add('active');
|
||||
},
|
||||
onReportClick: function (): void {
|
||||
let route = this.$router.resolve(ROUTES.REPORT_TABLE);
|
||||
window.open(route.href, '_blank');
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
export default class UsageReport extends Vue {}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.usage-report-container {
|
||||
padding: 55px 60px 55px 60px;
|
||||
position: relative;
|
||||
|
||||
&__navigation {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
|
||||
&__button {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
cursor: pointer;
|
||||
|
||||
p {
|
||||
font-family: 'font_medium';
|
||||
font-size: 18px;
|
||||
line-height: 24px;
|
||||
color: #354049;
|
||||
margin-left: 27px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 56px;
|
||||
margin-top: 17px;
|
||||
|
||||
p {
|
||||
font-family: 'font_bold';
|
||||
font-size: 32px;
|
||||
line-height: 39px;
|
||||
color: #354049;
|
||||
}
|
||||
|
||||
&__options-area {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 100%;
|
||||
|
||||
&__option {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 271px;
|
||||
height: 100%;
|
||||
background-color: #FFFFFF;
|
||||
border: solid 1px #F2F2F2;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
margin-left: 20px;
|
||||
|
||||
p {
|
||||
font-family: 'font_medium';
|
||||
font-size: 16px;
|
||||
line-height: 23px;
|
||||
color: #354049;
|
||||
}
|
||||
|
||||
svg {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: #2683FF;
|
||||
|
||||
p {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
svg {
|
||||
path {
|
||||
fill: #ffffff !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__main-area {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 33px;
|
||||
|
||||
&__info-area {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 40vh;
|
||||
|
||||
&__item {
|
||||
max-width: 454px;
|
||||
max-height: 393px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 6px;
|
||||
margin-right: 20px;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: 'font_regular';
|
||||
font-size: 18px;
|
||||
line-height: 24px;
|
||||
color: #AFB7C1;
|
||||
margin-block-start: 0em;
|
||||
margin-block-end: 0em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 22px;
|
||||
font-family: 'font_medium';
|
||||
font-size: 44px;
|
||||
line-height: 67px;
|
||||
color: #354049;
|
||||
margin-block-start: 0.5em;
|
||||
margin-block-end: 0em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__footer {
|
||||
padding: 0 32px;
|
||||
height: 86px;
|
||||
margin-top: 24px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
p {
|
||||
font-family: 'font_regular';
|
||||
font-size: 20px;
|
||||
line-height: 27px;
|
||||
color: #AFB7C1;
|
||||
|
||||
b {
|
||||
font-family: 'font_medium';
|
||||
color: #354049;
|
||||
}
|
||||
}
|
||||
|
||||
&__report-area {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
p {
|
||||
font-family: 'font_medium';
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
line-height: 29px;
|
||||
color: #354049;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
svg {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1600px) {
|
||||
.usage-report-container {
|
||||
&__navigation {
|
||||
p {
|
||||
font-size: 16px;
|
||||
line-height: 21px;
|
||||
}
|
||||
}
|
||||
|
||||
&__header {
|
||||
p {
|
||||
font-size: 24px;
|
||||
line-height: 29px;
|
||||
}
|
||||
&__options-area {
|
||||
&__option {
|
||||
width: 236px;
|
||||
p {
|
||||
font-size: 16px;
|
||||
line-height: 23px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__main-area {
|
||||
&__info-area {
|
||||
&__item {
|
||||
h1 {
|
||||
font-size: 14px;
|
||||
line-height: 19px;
|
||||
}
|
||||
h2 {
|
||||
font-size: 36px;
|
||||
line-height: 54px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__footer {
|
||||
p {
|
||||
font-size: 16px;
|
||||
line-height: 21px;
|
||||
}
|
||||
&__report-area {
|
||||
|
||||
p {
|
||||
font-size: 16px;
|
||||
line-height: 23px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1350px) {
|
||||
.usage-report-container {
|
||||
&__header {
|
||||
&__options-area {
|
||||
&__option {
|
||||
width: 200px;
|
||||
p {
|
||||
font-size: 14px;
|
||||
line-height: 19px;
|
||||
}
|
||||
&:last-child {
|
||||
width: 60px;
|
||||
p {
|
||||
display: none;
|
||||
}
|
||||
svg {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -13,6 +13,8 @@ import ProjectDetails from '@/components/project/ProjectDetailsArea.vue';
|
||||
import TeamArea from '@/components/team/TeamArea.vue';
|
||||
import Page404 from '@/components/errors/Page404.vue';
|
||||
import ApiKeysArea from '@/components/apiKeys/ApiKeysArea.vue';
|
||||
import UsageReport from '@/components/project/UsageReport.vue';
|
||||
import ReportTable from '@/components/project/ReportTable.vue';
|
||||
import BucketArea from '@/components/buckets/BucketArea.vue';
|
||||
import { getToken } from '@/utils/tokenManager';
|
||||
|
||||
@ -52,7 +54,7 @@ let router = new Router({
|
||||
{
|
||||
path: ROUTES.PROJECT_DETAILS.path,
|
||||
name: ROUTES.PROJECT_DETAILS.name,
|
||||
component: ProjectDetails
|
||||
component: ProjectDetails,
|
||||
},
|
||||
{
|
||||
path: ROUTES.TEAM.path,
|
||||
@ -64,6 +66,11 @@ let router = new Router({
|
||||
name: ROUTES.API_KEYS.name,
|
||||
component: ApiKeysArea
|
||||
},
|
||||
{
|
||||
path: ROUTES.USAGE_REPORT.path,
|
||||
name: ROUTES.USAGE_REPORT.name,
|
||||
component: UsageReport,
|
||||
},
|
||||
{
|
||||
path: ROUTES.BUCKETS.path,
|
||||
name: ROUTES.BUCKETS.name,
|
||||
@ -76,6 +83,11 @@ let router = new Router({
|
||||
// },
|
||||
]
|
||||
},
|
||||
{
|
||||
path: ROUTES.REPORT_TABLE.path,
|
||||
name: ROUTES.REPORT_TABLE.name,
|
||||
component: ReportTable,
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
name: '404',
|
||||
|
@ -34,6 +34,14 @@ const ROUTES = {
|
||||
path: '/api-keys',
|
||||
name: 'ApiKeys'
|
||||
},
|
||||
USAGE_REPORT: {
|
||||
path: '/project-details/usage-report',
|
||||
name: 'UsageReport'
|
||||
},
|
||||
REPORT_TABLE: {
|
||||
path: '/project-details/usage-report/detailed-report',
|
||||
name: 'ReportTable'
|
||||
},
|
||||
BUCKETS: {
|
||||
path: '/buckets',
|
||||
name: 'Buckets'
|
||||
|
15
web/satellite/static/images/projectDetails/UsageReport.svg
Normal file
15
web/satellite/static/images/projectDetails/UsageReport.svg
Normal file
@ -0,0 +1,15 @@
|
||||
<svg width="102" height="72" viewBox="0 0 102 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="12" y="0.5" width="79" height="71" rx="11.5" fill="url(#paint0_linear)" stroke="#C7C7C7"/>
|
||||
<path d="M1.76891 47.3241C0.567212 48.004 0.144216 49.5294 0.824126 50.7311C1.50404 51.9328 3.02938 52.3558 4.23109 51.6759L1.76891 47.3241ZM100.226 23.1789C101.429 22.502 101.856 20.9777 101.179 19.7743C100.502 18.571 98.9777 18.1442 97.7743 18.8211L100.226 23.1789ZM53.6852 38.9234L52.0539 40.8178L53.6852 38.9234ZM65.113 40.0614L63.8874 37.8825L65.113 40.0614ZM4.23109 51.6759L36.1104 33.6389L33.6483 29.2871L1.76891 47.3241L4.23109 51.6759ZM44.6976 34.4832L52.0539 40.8178L55.3165 37.0289L47.9602 30.6944L44.6976 34.4832ZM66.3387 42.2404L100.226 23.1789L97.7743 18.8211L63.8874 37.8825L66.3387 42.2404ZM52.0539 40.8178C56.0414 44.2515 61.7523 44.8202 66.3387 42.2404L63.8874 37.8825C61.1356 39.4304 57.709 39.0891 55.3165 37.0289L52.0539 40.8178ZM36.1104 33.6389C38.8644 32.0807 42.2999 32.4185 44.6976 34.4832L47.9602 30.6944C43.9641 27.2532 38.2381 26.6902 33.6483 29.2871L36.1104 33.6389Z" fill="url(#paint1_linear)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear" x1="51.5" y1="0" x2="51.5" y2="72" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#ECECEC"/>
|
||||
<stop offset="1" stop-color="#F2F2F2" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear" x1="99" y1="18" x2="1.49999" y2="47" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#2683FF"/>
|
||||
<stop offset="0.447514" stop-color="#2E8BD5"/>
|
||||
<stop offset="1" stop-color="#495DE3"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
@ -51,6 +51,11 @@ module.exports = {
|
||||
appendTsSuffixTo: [/\.vue$/],
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules/
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpg|gif|svg)$/,
|
||||
loader: 'file-loader',
|
||||
|
Loading…
Reference in New Issue
Block a user