V3-1284 Node bootstrap web frontend (#1405)

* V3-1284 Node bootstrap web frontend
This commit is contained in:
Yehor Butko 2019-03-05 13:19:43 +02:00 committed by GitHub
parent 3e2c101bd8
commit 3e90b9e3b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1238 additions and 0 deletions

26
web/bootstrap/.gitignore vendored Normal file
View File

@ -0,0 +1,26 @@
.DS_Store
node_modules
dist
package-lock.json
coverage
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Allow images
!*.svg
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*

View File

@ -0,0 +1,8 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
module.exports = {
presets: [
'@vue/app'
]
}

11
web/bootstrap/index.html Normal file
View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no">
<title>Storj Node Bootstrap</title>
</head>
<body>
<div id="app"></div>
</body>
</html>

View File

@ -0,0 +1,65 @@
{
"name": "storj-bootstrap",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "rm -rf dist/ && npm run build && vue-cli-service serve -s dist",
"lint": "vue-cli-service lint",
"build": "webpack --config webpack.config.dev.js"
},
"dependencies": {
"@types/graphql": "^14.0.3",
"apollo-cache-inmemory": "^1.3.9",
"apollo-client": "^2.4.5",
"apollo-link": "^1.2.4",
"apollo-link-context": "^1.0.10",
"apollo-link-http": "^1.5.5",
"graphql": "^14.0.2",
"graphql-tag": "^2.10.0",
"vue": "^2.5.17",
"vue-apollo": "^3.0.0-beta.25",
"vue-class-component": "^6.0.0",
"vue-clipboards": "^1.2.4",
"vue-property-decorator": "^7.0.0",
"vue-router": "^3.0.1",
"vuex": "^3.0.1"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
"@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-service": "^3.0.5",
"babel-core": "7.0.0-bridge.0",
"css-loader": "^1.0.0",
"eslint": "^5.9.0",
"eslint-plugin-vue": "^5.0.0",
"node-sass": "^4.9.0",
"sass-loader": "^7.0.1",
"tslint": "^5.11.0",
"tslint-consistent-codestyle": "^1.14.1",
"tslint-loader": "^3.5.4",
"typescript": "^3.0.0",
"vue-html-webpack-plugin": "^3.2.2",
"vue-loader": "^15.4.2",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.5.17",
"vue-tslint": "^0.3.2",
"vue-tslint-loader": "^3.5.6",
"webpack": "^4.21.0",
"webpack-cli": "^3.1.2",
"webpack-node-externals": "^1.7.2"
},
"postcss": {
"plugins": {
"autoprefixer": {}
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}

39
web/bootstrap/src/App.vue Normal file
View File

@ -0,0 +1,39 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div id="app">
<router-view/>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
@Component({
})
export default class App extends Vue {
}
</script>
<style lang="scss">
body {
margin: 0 !important;
}
@font-face {
font-family: "montserrat_regular";
src: url("../../satellite/static/fonts/montserrat_regular.ttf");
}
@font-face {
font-family: "montserrat_medium";
src: url("../../satellite/static/fonts/montserrat_medium.ttf");
}
@font-face {
font-family: "montserrat_bold";
src: url("../../satellite/static/fonts/montserrat_bold.ttf");
}
</style>

View File

@ -0,0 +1,32 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
import apolloManager from '@/utils/apolloManager';
import gql from 'graphql-tag';
import { NodeStatus } from '@/types/nodeStatus';
export async function checkAvailability(nodeId: string): Promise<number> {
try {
let response: any = await apolloManager.query(
{
query: gql(`
query {
isNodeUp (
nodeID: "${nodeId}"
)
}`
),
fetchPolicy: 'no-cache',
}
);
if (response.errors) {
return NodeStatus.Error;
}
return response.data.isNodeUp ? NodeStatus.Active : NodeStatus.Error;
} catch (e) {
return NodeStatus.Error;
}
}

15
web/bootstrap/src/main.ts Normal file
View File

@ -0,0 +1,15 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
Vue.config.productionTip = false;
new Vue({
router,
render: (h) => h(App),
store,
}).$mount('#app');

View File

@ -0,0 +1,21 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
import Vue from 'vue';
import Router from 'vue-router';
import Search from '@/views/Search.vue';
Vue.use(Router);
let router = new Router({
mode: 'history',
routes: [
{
path: '',
name: '',
component: Search
},
]
});
export default router;

View File

@ -0,0 +1,38 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
import Vue from 'vue';
import Vuex from 'vuex';
import { ACTIONS, MUTATIONS } from '@/utils/constants';
import { checkAvailability } from '@/api/bootstrap';
import { NodeStatus } from '@/types/nodeStatus';
Vue.use(Vuex);
// Bootstrap store (vuex)
const store = new Vuex.Store({
state: {
isLoading: false,
nodeStatus: 1,
},
mutations: {
[MUTATIONS.SET_NODE_STATUS](state: any, status: NodeStatus): void {
state.nodeStatus = status;
},
[MUTATIONS.SET_LOADING](state:any): void {
state.isLoading = true;
}
},
actions: {
async [ACTIONS.CHECK_NODE_STATUS]({commit}: any, nodeId: string): Promise<any> {
let nodeStatus = await checkAvailability(nodeId);
commit(MUTATIONS.SET_NODE_STATUS, nodeStatus);
},
[ACTIONS.SET_LOADING]({commit}: any): void {
commit(MUTATIONS.SET_LOADING);
}
},
});
export default store;

View File

@ -0,0 +1,8 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
export enum NodeStatus {
None = 1,
Active,
Error,
}

View File

@ -0,0 +1,19 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
import { HttpLink } from 'apollo-link-http';
import ApolloClient from 'apollo-client/ApolloClient';
import { InMemoryCache } from 'apollo-cache-inmemory';
// Bootstrap server url
const bootstrapUrl = new HttpLink({
uri: '/api/graphql/v0',
});
// Creating apollo client
export default new ApolloClient({
link: bootstrapUrl,
cache: new InMemoryCache(),
connectToDevTools: true,
});

View File

@ -0,0 +1,12 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
export const MUTATIONS = {
SET_NODE_STATUS: 'SET_NODE_STATUS',
SET_LOADING: 'SET_LOADING',
};
export const ACTIONS = {
CHECK_NODE_STATUS: 'CHECK_NODE_STATUS',
SET_LOADING: 'SET_LOADING',
};

View File

@ -0,0 +1,162 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="failure-container">
<svg id="loading-svg" width="122px" height="120px" viewBox="0 0 122 120" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient x1="62.8427859%" y1="49.4456705%" x2="-91.4339241%" y2="51.3777925%" id="linearGradient-1">
<stop stop-color="#FF0000" offset="0%"></stop>
<stop stop-color="#505460" offset="100%"></stop>
</linearGradient>
<filter x="-35.1%" y="-1516.0%" width="170.2%" height="3132.0%" filterUnits="objectBoundingBox" id="filter-2">
<feGaussianBlur stdDeviation="8" in="SourceGraphic"></feGaussianBlur>
</filter>
<linearGradient x1="62.8427859%" y1="32.6019784%" x2="-91.4339241%" y2="93.2429871%" id="linearGradient-3">
<stop stop-color="#FF0000" offset="0%"></stop>
<stop stop-color="#505460" offset="100%"></stop>
</linearGradient>
<filter x="-213.9%" y="-1516.0%" width="527.8%" height="3132.0%" filterUnits="objectBoundingBox" id="filter-4">
<feGaussianBlur stdDeviation="8" in="SourceGraphic"></feGaussianBlur>
</filter>
<linearGradient x1="62.8427859%" y1="-400.886306%" x2="-91.4339241%" y2="1170.68321%" id="linearGradient-5">
<stop stop-color="#FF0000" offset="0%"></stop>
<stop stop-color="#505460" offset="100%"></stop>
</linearGradient>
<filter x="-38.2%" y="-54.9%" width="176.4%" height="209.8%" filterUnits="objectBoundingBox" id="filter-6">
<feGaussianBlur stdDeviation="8" in="SourceGraphic"></feGaussianBlur>
</filter>
<linearGradient x1="62.8427859%" y1="-424.051899%" x2="-91.4339241%" y2="1228.26156%" id="linearGradient-7">
<stop stop-color="#FF0000" offset="0%"></stop>
<stop stop-color="#505460" offset="100%"></stop>
</linearGradient>
<linearGradient x1="62.8427859%" y1="-11.1496077%" x2="-91.4339241%" y2="201.988068%" id="linearGradient-8">
<stop stop-color="#FF0000" offset="0%"></stop>
<stop stop-color="#505460" offset="100%"></stop>
</linearGradient>
</defs>
<g id="Icon/node/2-Copy-2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group-2" transform="translate(23.000000, 20.000000)">
<g id="Group" opacity="0.870117188" transform="translate(3.000000, 13.000000)" stroke-width="4.2">
<path d="M5.68434189e-14,25.0148333 L68.3666667,25.0148333" id="Stroke-3" stroke="url(#linearGradient-1)" opacity="0.605352493" filter="url(#filter-2)"></path>
<path d="M58.553,35.6936111 L46.3496667,35.6936111" id="Stroke-5" stroke="url(#linearGradient-3)" opacity="0.605352493" stroke-linecap="round" filter="url(#filter-4)"></path>
<path d="M68.3666667,25.1483333 L68.3666667,34.2016667 C68.3666667,41.565 62.3983333,47.5333333 55.035,47.5333333 L13.3316667,47.5333333 C5.96833333,47.5333333 5.68434189e-14,41.565 5.68434189e-14,34.2016667 L5.68434189e-14,25.015 C5.68434189e-14,24.4783333 0.128333333,23.9516667 0.376666667,23.4766667 L8.855,7.17833333 C11.1516667,2.76666667 15.7116667,-2.34479103e-13 20.685,-2.34479103e-13 L45.945,-2.34479103e-13 C50.5583333,-2.34479103e-13 54.8466667,2.385 57.2766667,6.30833333 L67.8666667,23.3916667 C68.1933333,23.92 68.3666667,24.5283333 68.3666667,25.1483333 Z" id="Stroke-1" stroke="url(#linearGradient-5)" opacity="0.605352493" filter="url(#filter-6)"></path>
</g>
<g id="Group" fill-rule="nonzero">
<g id="Group-4" transform="translate(0.000000, 13.000000)">
<g id="Group-3">
<g id="Group-7">
<g id="Group-5" transform="translate(0.250333, 0.250833)" fill="url(#linearGradient-7)">
<path d="M6.03606851,25.9148333 L68.1003134,25.9148333 L58.4913685,10.4140957 C56.4451258,7.11035405 52.8329636,5.1 48.945,5.1 L23.685,5.1 C19.4945489,5.1 15.6526847,7.43113725 13.7180055,11.147462 L6.03606851,25.9148333 Z M69.2666667,30.1148333 L5.1,30.1148333 L5.1,37.2016667 C5.1,43.405202 10.1281313,48.4333333 16.3316667,48.4333333 L58.035,48.4333333 C64.2385354,48.4333333 69.2666667,43.405202 69.2666667,37.2016667 L69.2666667,30.1148333 Z M73.4666667,28.1483333 L73.4666667,37.2016667 C73.4666667,45.724798 66.5581313,52.6333333 58.035,52.6333333 L16.3316667,52.6333333 C7.80853536,52.6333333 0.9,45.724798 0.9,37.2016667 L0.9,28.015 C0.9,27.1392671 1.11042376,26.2788214 1.51366113,25.507538 L9.99229426,9.20862857 C12.6504846,4.1025112 17.9284291,0.9 23.685,0.9 L48.945,0.9 C54.2867182,0.9 59.2497936,3.66220673 62.0615403,8.20188581 L72.6528236,25.287292 C73.1845977,26.1473551 73.4666667,27.1380876 73.4666667,28.1483333 Z" id="Combined-Shape"></path>
</g>
<path d="M61.8033333,36.8444444 C62.9631313,36.8444444 63.9033333,37.7846465 63.9033333,38.9444444 C63.9033333,40.1042424 62.9631313,41.0444444 61.8033333,41.0444444 L49.6,41.0444444 C48.440202,41.0444444 47.5,40.1042424 47.5,38.9444444 C47.5,37.7846465 48.440202,36.8444444 49.6,36.8444444 L61.8033333,36.8444444 Z" id="Stroke-5" fill="url(#linearGradient-8)"></path>
</g>
</g>
</g>
<path d="M88.2734342,15.145147 C89.1803944,16.0521073 89.1803944,17.4586211 88.2734342,18.3655813 C87.8199541,18.8190614 87.2300672,19.0458015 86.6862538,19.0458015 C86.1424405,19.0458015 85.50648,18.8190614 85.0990735,18.3655813 L79.4768272,12.743335 L73.8545809,18.3197798 C73.4011008,18.7732599 72.8112138,19 72.2674005,19 C71.7235872,19 71.0876267,18.7732599 70.6802202,18.3197798 C69.7732599,17.4128196 69.7732599,16.0063058 70.6802202,15.0993456 L76.256665,9.52290075 L70.6802202,3.90065444 C69.7732599,2.99369424 69.7732599,1.58718036 70.6802202,0.680220153 C71.5871804,-0.226740051 72.9936942,-0.226740051 73.9006544,0.680220153 L79.4770993,6.30246645 L85.0993456,0.680220153 C86.0063058,-0.226740051 87.4128196,-0.226740051 88.3197798,0.680220153 C89.2267401,1.58718036 89.2267401,2.99369424 88.3197798,3.90065444 L82.6975335,9.52290075 L88.2734342,15.145147 Z" id="Path" fill="#FF0000"></path>
</g>
</g>
</g>
</svg>
<div class="failure-container__animation-container">
<p class="failure-container__title">Your Node Not Found</p>
<p class="failure-container__info">Please check your Node ID or restart your Storj Node and try again later</p>
<div class="overlay__main-container__button" @click="onTryAgainClick">
<p class="overlay__main-container__button__text">Try Again</p>
</div>
<p class="overlay__main-container__support">Or Contact our <a>Support</a></p>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
@Component({
mounted() {
setTimeout(() => {
(document as any).querySelector('.failure-container').classList.add('active');
}, 500);
},
methods: {
onTryAgainClick: function () {
location.reload();
},
},
})
export default class Failure extends Vue {}
</script>
<style lang="scss">
.failure-container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
&__title {
width: 558px;
font-family: 'montserrat_bold';
font-size: 48px;
font-style: normal;
font-stretch: normal;
line-height: 57px;
letter-spacing: normal;
text-align: center;
color: #fefeff;
margin-block-start: 0em;
margin-block-end: 0em;
}
&__info {
margin-top: 24px;
width: 446px;
font-family: 'montserrat_regular';
font-size: 16px;
font-style: normal;
font-stretch: normal;
line-height: 23px;
letter-spacing: normal;
text-align: center;
color: #696c77;
margin-block-start: 1.5em;
margin-block-end: 0em;
}
&__animation-container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
visibility: hidden;
position: relative;
bottom: -200px;
opacity: 0;
-webkit-transition: all 0.5s linear;
-moz-transition: all 0.5s linear;
-o-transition: all 0.5s linear;
transition: all 0.5s linear;
}
svg {
display: block;
position: relative;
top: 192px;
transition: all 0.5s linear;
}
}
.failure-container.active {
svg {
top: 0;
}
.failure-container__animation-container {
margin-bottom: 0;
bottom: 0;
visibility: visible;
opacity: 1;
}
}
</style>

View File

@ -0,0 +1,203 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="overlay">
<div class="overlay__main-container">
<div class="overlay__main-container__svg" v-if="nodeStatus.isNone">
<div class="loading-line"></div>
<svg width="120px" height="120px" viewBox="0 0 120 120" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient x1="65.4452463%" y1="208.17803%" x2="167.766742%" y2="150.69682%" id="linearGradient-1">
<stop stop-color="#4381F7" offset="0%"></stop>
<stop stop-color="#505460" offset="100%"></stop>
</linearGradient>
</defs>
<g id="Icon/node/1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group" transform="translate(23.000000, 33.000000)" fill-rule="nonzero">
<g id="Group-2" transform="translate(0.900000, 0.900000)" fill="#505460">
<path d="M5.24781681,25 L66.7017485,25 L57.2767486,9.5639393 C55.2407064,6.22649392 51.6542832,4.2 47.7985861,4.2 L22.6740614,4.2 C18.517928,4.2 14.702343,6.55052798 12.7764624,10.3064151 L5.24781681,25 Z M68,29.2 L4.2,29.2 L4.2,36.6374474 C4.2,42.9203342 9.20330161,48 15.3601658,48 L56.8398342,48 C62.9966984,48 68,42.9203342 68,36.6374474 L68,29.2 Z M72.2,27.4952314 L72.2,36.6374474 C72.2,45.2258089 65.3306541,52.2 56.8398342,52.2 L15.3601658,52.2 C6.86934588,52.2 -1.70530257e-13,45.2258089 -1.70530257e-13,36.6374474 L-1.70530257e-13,27.3605891 C-1.70530257e-13,26.4842425 0.207498838,25.6228069 0.605692679,24.8495457 L9.03884835,8.39062775 C11.6812091,3.23744801 16.9365211,0 22.6740614,0 L47.7985861,0 C53.1230697,0 58.0658931,2.7929223 60.861791,7.37591038 L71.3962549,24.6290296 C71.9217493,25.4919082 72.2,26.4841461 72.2,27.4952314 Z" id="Combined-Shape"></path>
</g>
<path d="M61,36.9 C62.159798,36.9 63.1,37.840202 63.1,39 C63.1,40.159798 62.159798,41.1 61,41.1 L49,41.1 C47.840202,41.1 46.9,40.159798 46.9,39 C46.9,37.840202 47.840202,36.9 49,36.9 L61,36.9 Z" id="Stroke-5" fill="url(#linearGradient-1)"></path>
</g>
</g>
</svg>
</div>
<Success v-if="nodeStatus.isActive"/>
<Failure v-if="nodeStatus.isError"/>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import Success from './Success.vue';
import Failure from './Failure.vue';
import { NodeStatus } from '../types/nodeStatus';
@Component({
mounted() {
(document as any).querySelector('.overlay').classList.add('active');
},
data: function () {
return {
isSuccessCheck: false,
isFailureCheck: false,
};
},
computed: {
nodeStatus: function () {
const currentNodeStatus = this.$store.state.nodeStatus;
const isNone = currentNodeStatus === NodeStatus.None;
const isActive = currentNodeStatus === NodeStatus.Active;
const isError = currentNodeStatus === NodeStatus.Error;
return {
isNone,
isActive,
isError,
};
},
},
components: {
Success,
Failure,
},
})
export default class Loading extends Vue {}
</script>
<style lang="scss">
.overlay {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 0px;
display: flex;
justify-content: center;
align-items: center;
background-color: transparent;
-webkit-transition: all 0.5s linear;
-moz-transition: all 0.5s linear;
-o-transition: all 0.5s linear;
transition: all 0.5s linear;
&__main-container {
width: auto;
height: auto;
visibility: hidden;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
opacity: 0;
-webkit-transition: all 1s linear;
-moz-transition: all 1s linear;
-o-transition: all 1s linear;
transition: all 1s linear;
transition-delay: 1s;
&__svg {
position: relative;
}
.loading-line {
height: 4px;
position: absolute;
top: 59px;
left: 28px;
width: 64px;
-webkit-transition: all 1s linear;
-moz-transition: all 1s linear;
-o-transition: all 1s linear;
transition: all 1s linear;
animation-delay: 5s;
background-color: #1494ff;
border-radius: 12px;
}
h1 {
margin-top: 33px;
}
&__button {
width: 176px;
height: 52px;
border-radius: 8px;
background-color: #1494ff;
margin-top: 46px;
&__text {
font-family: 'montserrat_bold';
font-size: 16px;
font-style: normal;
font-stretch: normal;
line-height: normal;
letter-spacing: normal;
text-align: center;
color: #f3f4f9;
}
&:hover {
cursor: pointer;
background-color: #2039df;
}
}
&__support {
margin-top: 128px;
font-family: 'montserrat_regular';
font-size: 12px;
font-style: normal;
font-stretch: normal;
line-height: 23px;
letter-spacing: normal;
text-align: center;
color: #696c77;
a {
font-family: 'montserrat_medium';
font-size: 12px;
color: #1494ff;
text-decoration: none;
cursor: pointer;
}
}
.loading {
-webkit-transition: all 1s linear;
-moz-transition: all 1s linear;
-o-transition: all 1s linear;
transition: all 5s linear;
animation-delay: 2s;
animation-duration: 2s;
}
}
}
.overlay.active {
background-color: #191919;
width: 100%;
z-index: 9999;
.overlay__main-container {
opacity: 1;
visibility: visible;
}
.loading-line {
animation: pathWidth 3s linear;
}
}
@keyframes pathWidth {
from {
width: 0px;
}
to {
width: 64px;
}
}
</style>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,154 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="success-container" >
<svg width="122px" height="120px" viewBox="0 0 122 120" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient x1="62.8427859%" y1="49.4456705%" x2="-91.4339241%" y2="51.3777925%" id="linearGradient-1">
<stop stop-color="#0058FF" offset="0%"></stop>
<stop stop-color="#505460" offset="100%"></stop>
</linearGradient>
<filter x="-35.1%" y="-1516.0%" width="170.2%" height="3132.0%" filterUnits="objectBoundingBox" id="filter-2">
<feGaussianBlur stdDeviation="8" in="SourceGraphic"></feGaussianBlur>
</filter>
<linearGradient x1="62.8427859%" y1="32.6019784%" x2="-91.4339241%" y2="93.2429871%" id="linearGradient-3">
<stop stop-color="#0058FF" offset="0%"></stop>
<stop stop-color="#505460" offset="100%"></stop>
</linearGradient>
<filter x="-213.9%" y="-1516.0%" width="527.8%" height="3132.0%" filterUnits="objectBoundingBox" id="filter-4">
<feGaussianBlur stdDeviation="8" in="SourceGraphic"></feGaussianBlur>
</filter>
<linearGradient x1="62.8427859%" y1="-400.886306%" x2="-91.4339241%" y2="1170.68321%" id="linearGradient-5">
<stop stop-color="#0058FF" offset="0%"></stop>
<stop stop-color="#505460" offset="100%"></stop>
</linearGradient>
<filter x="-38.2%" y="-54.9%" width="176.4%" height="209.8%" filterUnits="objectBoundingBox" id="filter-6">
<feGaussianBlur stdDeviation="8" in="SourceGraphic"></feGaussianBlur>
</filter>
<linearGradient x1="62.8427859%" y1="46.4797858%" x2="-91.4339241%" y2="58.7495336%" id="linearGradient-7">
<stop stop-color="#4381F7" offset="0%"></stop>
<stop stop-color="#044CFF" offset="100%"></stop>
</linearGradient>
<linearGradient x1="62.8427859%" y1="-424.051899%" x2="-91.4339241%" y2="1228.26156%" id="linearGradient-8">
<stop stop-color="#4381F7" offset="0%"></stop>
<stop stop-color="#044CFF" offset="100%"></stop>
</linearGradient>
<linearGradient x1="62.8427859%" y1="-11.1496077%" x2="-91.4339241%" y2="201.988068%" id="linearGradient-9">
<stop stop-color="#4381F7" offset="0%"></stop>
<stop stop-color="#505460" offset="100%"></stop>
</linearGradient>
</defs>
<g id="Icon/node/2-Copy" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group-2" transform="translate(23.000000, 21.000000)">
<g id="Group" transform="translate(3.000000, 18.000000)" stroke-width="4.2">
<path d="M5.68434189e-14,25.0148333 L68.3666667,25.0148333" id="Stroke-3" stroke="url(#linearGradient-1)" filter="url(#filter-2)"></path>
<path d="M58.553,35.6936111 L46.3496667,35.6936111" id="Stroke-5" stroke="url(#linearGradient-3)" stroke-linecap="round" filter="url(#filter-4)"></path>
<path d="M68.3666667,25.1483333 L68.3666667,34.2016667 C68.3666667,41.565 62.3983333,47.5333333 55.035,47.5333333 L13.3316667,47.5333333 C5.96833333,47.5333333 5.68434189e-14,41.565 5.68434189e-14,34.2016667 L5.68434189e-14,25.015 C5.68434189e-14,24.4783333 0.128333333,23.9516667 0.376666667,23.4766667 L8.855,7.17833333 C11.1516667,2.76666667 15.7116667,-2.34479103e-13 20.685,-2.34479103e-13 L45.945,-2.34479103e-13 C50.5583333,-2.34479103e-13 54.8466667,2.385 57.2766667,6.30833333 L67.8666667,23.3916667 C68.1933333,23.92 68.3666667,24.5283333 68.3666667,25.1483333 Z" id="Stroke-1" stroke="url(#linearGradient-5)" filter="url(#filter-6)"></path>
</g>
<g id="Group-4" transform="translate(0.250333, 12.250833)" fill-rule="nonzero">
<g id="Group-3">
<g id="Group-5" transform="translate(0.900000, 0.900000)">
<polygon id="Stroke-3" fill="url(#linearGradient-7)" points="2.1 29.2148333 2.1 25.0148333 70.4666667 25.0148333 70.4666667 29.2148333"></polygon>
<path d="M68.3666667,27.2483333 C68.3666667,27.0190576 68.3023215,26.7930533 68.181793,26.5981142 L57.5913685,9.51409574 C55.5451258,6.21035405 51.9329636,4.2 48.045,4.2 L22.785,4.2 C18.5945489,4.2 14.7526847,6.53113725 12.8180055,10.247462 L4.33767917,26.5496171 C4.24711487,26.7228441 4.2,26.9155019 4.2,27.115 L4.2,36.3016667 C4.2,42.505202 9.22813131,47.5333333 15.4316667,47.5333333 L57.135,47.5333333 C63.3385354,47.5333333 68.3666667,42.505202 68.3666667,36.3016667 L68.3666667,27.2483333 Z M72.5666667,27.2483333 L72.5666667,36.3016667 C72.5666667,44.824798 65.6581313,51.7333333 57.135,51.7333333 L15.4316667,51.7333333 C6.90853536,51.7333333 -2.84217094e-14,44.824798 -2.84217094e-14,36.3016667 L-2.84217094e-14,27.115 C-2.84217094e-14,26.2392671 0.210423755,25.3788214 0.613661128,24.607538 L9.09229426,8.30862857 C11.7504846,3.2025112 17.0284291,0 22.785,0 L48.045,0 C53.3867182,0 58.3497936,2.76220673 61.1615403,7.30188581 L71.7528236,24.387292 C72.2845977,25.2473551 72.5666667,26.2380876 72.5666667,27.2483333 Z" id="Stroke-1" fill="url(#linearGradient-8)"></path>
</g>
</g>
<path d="M61.553,36.5936111 C62.712798,36.5936111 63.653,37.5338131 63.653,38.6936111 C63.653,39.8534091 62.712798,40.7936111 61.553,40.7936111 L49.3496667,40.7936111 C48.1898687,40.7936111 47.2496667,39.8534091 47.2496667,38.6936111 C47.2496667,37.5338131 48.1898687,36.5936111 49.3496667,36.5936111 L61.553,36.5936111 Z" id="Stroke-5" fill="url(#linearGradient-9)"></path>
</g>
<path d="M69.44417,8.21779453 L69.44417,8.21779453 C70.2538459,7.26705512 71.6659377,7.11616 72.6582279,7.87434261 L78.4,12.2614787 L88.9509915,1.59935829 C89.8468741,0.694039749 91.2857828,0.622683594 92.26684,1.43492382 L92.26684,1.43492382 C93.1329574,2.1520027 93.2537769,3.43543684 92.536698,4.30155419 C92.4934859,4.35374756 92.4476951,4.40375115 92.3994967,4.45137826 L78.68834,18 L69.7763018,11.2574595 C68.850355,10.5569201 68.6676262,9.23839261 69.3681655,8.31244584 C69.392584,8.28017041 69.4179294,8.24860682 69.44417,8.21779453 Z" id="Path" fill="#5FC000" fill-rule="nonzero"></path>
</g>
</g>
</svg>
<div class="success-container__animation-container">
<h1 class="success-container__title">Connected</h1>
<h3 class="success-container__info">Your Node found and it is connected to the network</h3>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
@Component({
mounted() {
setTimeout(() => {
(document as any).querySelector('.success-container').classList.add('active');
}, 500);
}
})
export default class Success extends Vue {}
</script>
<style scoped lang="scss">
.success-container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
&__title {
width: 278px;
font-family: 'montserrat_bold';
font-size: 48px;
font-style: normal;
font-stretch: normal;
line-height: 57px;
letter-spacing: normal;
text-align: center;
color: #fefeff;
margin-block-start: 0em;
margin-block-end: 0em;
}
&__info {
margin-top: 24px;
width: 446px;
font-family: 'montserrat_regular';
font-size: 16px;
font-style: normal;
font-stretch: normal;
line-height: 23px;
letter-spacing: normal;
text-align: center;
color: #696c77;
margin-block-start: 1.5em;
margin-block-end: 0em;
}
&__animation-container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
visibility: hidden;
position: relative;
bottom: -50px;
opacity: 0;
-webkit-transition: all 0.5s linear;
-moz-transition: all 0.5s linear;
-o-transition: all 0.5s linear;
transition: all 0.5s linear;
}
svg {
display: block;
position: relative;
top: 50px;
transition: all 0.5s linear;
}
}
.success-container.active {
svg {
top: 0;
}
.success-container__animation-container {
margin-bottom: 0;
bottom: 0;
visibility: visible;
opacity: 1;
}
}
</style>

View File

@ -0,0 +1,38 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"noImplicitAny": false,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue"
],
"exclude": [
"node_modules"
]
}

69
web/bootstrap/tslint.json Normal file
View File

@ -0,0 +1,69 @@
{
"defaultSeverity": "warning",
"rulesDirectory": [
"tslint-consistent-codestyle"
],
"linterOptions": {
"exclude": [
"node_modules/**"
]
},
"rules": {
// Enforces vertical alignment.
"align": [true, "parameters", "statements"],
// Enforces use of T[] if T is a simple type.
"array-type": [true, "array-simple"],
// Enforces PascalCased class and interface names.
"class-name": true,
// Enforces formatting rules for single-line comments.
"comment-format": [true, "check-space"],
"quotemark": [true, "single", "avoid-escape"],
// Ensures the file ends with a newline.
"eofline": true,
"indent": [true, "spaces", 4],
// Ensures proper spacing between import statement keywords.
"import-spacing": true,
"interface-name": false,
"ordered-imports": false,
// Enforces consistent semicolon usage at the end of every statement.
"semicolon": [true, "always"],
// Enforces braces for if/for/do/while statements.
"curly": [true, "ignore-same-line"],
// Enforces blank line before return when not the only line in the block.
"newline-before-return": true,
// Disallows multiple variable definitions in the same declaration statement.(Exception for loops)
"one-variable-per-declaration": [true, "ignore-for-loop"],
"object-literal-sort-keys": false,
"whitespace": [
true,
"check-branch", // checks branching statements (if/else/for/while) are followed by whitespace.
"check-decl", // checks that variable declarations have whitespace around the equals token.
"check-operator", // checks for whitespace around operator tokens.
"check-module", // checks for whitespace in import & export statements.
"check-separator", // checks for whitespace after separator tokens (,/;).
"check-type-operator", // checks for whitespace between type operators | and &.
"check-preblock" // checks for whitespace before the opening brace of a block.
],
// Recommends to use an early exit instead of a long if block.
"early-exit": true,
// Bans the use of specified console methods.
"no-console": [true, "log"],
"no-default-export": false,
// Ban the use of this in static methods.
"no-static-this": true,
// Warns if super() appears twice in a constructor.
"no-duplicate-super": true,
// Disallows any type of assignment in conditionals.
"no-conditional-assignment": true,
// Prevents duplicate cases in switch statements.
"no-duplicate-switch-case": true,
// Disallows empty blocks.
"no-empty": true,
// Disallows two or more blank lines in a row.
"no-consecutive-blank-lines": [true, 2],
// Warns on use of ${ in non-template strings.
"no-invalid-template-strings": true,
// Disallows using the this keyword outside of classes.
"no-invalid-this": true
}
}

View File

@ -0,0 +1,13 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
module.exports = {
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
args[0].template = './index.html'
return args
})
}
};

View File

@ -0,0 +1,86 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
var path = require('path');
var webpack = require('webpack');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const clientBundleOutputDir = './dist';
module.exports = {
mode: 'development',
entry: './src/main.ts',
output: {
path: path.resolve(__dirname, clientBundleOutputDir),
publicPath: '/static/dist/',
filename: 'build.js'
},
devServer: {
contentBase: clientBundleOutputDir
},
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
vue: true,
template: './index.html',
filename: path.resolve(__dirname, './dist/public', 'index.html')
}),
],
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
// Since sass-loader (weirdly) has SCSS as its default parse mode, we map
// the "scss" and "sass" values for the lang attribute to the right configs here.
// other preprocessors should work out of the box, no loader config like this necessary.
ts:'ts-loader!tslint-loader',
'scss': 'vue-style-loader!css-loader!sass-loader',
'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax',
}
// other vue-loader options go here
}
},
{
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: /node_modules/,
options: {
appendTsSuffixTo: [/\.vue$/],
}
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: 'images/[name].[ext]'
}
},
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'fonts/[name].[ext]'
}
}
]
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': path.resolve('src')
}
}
}