mirror of
https://github.com/danbulant/Nertivia-Client
synced 2026-06-15 04:21:19 +00:00
home page redesign.
This commit is contained in:
parent
6a29642e56
commit
a84a097f83
30 changed files with 2367 additions and 1059 deletions
10
package-lock.json
generated
10
package-lock.json
generated
|
|
@ -7825,6 +7825,11 @@
|
|||
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
|
||||
"dev": true
|
||||
},
|
||||
"particles.js": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/particles.js/-/particles.js-2.0.0.tgz",
|
||||
"integrity": "sha1-IThsQyjWx/lngKIB6W7t/AnHNvY="
|
||||
},
|
||||
"pascalcase": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
|
||||
|
|
@ -10949,6 +10954,11 @@
|
|||
"resolved": "https://registry.npmjs.org/vue-script2/-/vue-script2-2.0.3.tgz",
|
||||
"integrity": "sha512-sGsFbqCIZDbPq140X1p8T6Y72MoCtkFpQ7CfhknZLqDZxMGWavFqIY/5YsnhqxxatWnYy0us/IoHSDr5l2JZzQ=="
|
||||
},
|
||||
"vue-smooth-reflow": {
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/vue-smooth-reflow/-/vue-smooth-reflow-0.1.12.tgz",
|
||||
"integrity": "sha512-cic+dmqsBzu/lRMXf/mhUPMM0g0vancJGUyNMMGHjis0ilSFd1RjIrZYcU5B7ef+n5oshH33/zbMA8OYyRTu7Q=="
|
||||
},
|
||||
"vue-socket.io": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/vue-socket.io/-/vue-socket.io-3.0.4.tgz",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
"futoji": "^0.5.0",
|
||||
"jquery": "^3.4.0",
|
||||
"match-sorter": "^2.3.0",
|
||||
"particles.js": "^2.0.0",
|
||||
"socket.io": "^2.2.0",
|
||||
"socket.io-client": "^2.2.0",
|
||||
"twemoji": "^11.3.0",
|
||||
|
|
@ -22,6 +23,7 @@
|
|||
"vue-mq": "^1.0.1",
|
||||
"vue-recaptcha": "^1.1.1",
|
||||
"vue-router": "^3.0.2",
|
||||
"vue-smooth-reflow": "^0.1.12",
|
||||
"vue-socket.io": "^3.0.4",
|
||||
"vue-socket.io-extended": "^3.2.0",
|
||||
"vue-twitter": "^0.1.0",
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@
|
|||
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
<!-- Google recaptcha -->
|
||||
<script src="https://www.google.com/recaptcha/api.js?onload=vueRecaptchaApiLoaded&render=explicit" async defer>
|
||||
<!-- Google recaptcha
|
||||
<script src="https://www.google.com/recaptcha/api.js?onload=vueRecaptchaApiLoaded&render=explicit" async defer> -->
|
||||
</script>
|
||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-131765299-1"></script>
|
||||
|
|
|
|||
44
src/Main.vue
44
src/Main.vue
|
|
@ -3,3 +3,47 @@
|
|||
<router-view></router-view>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#app {
|
||||
font-family: "Roboto", sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
color: #383838;
|
||||
height: 100%;
|
||||
}
|
||||
/* ------- SCROLL BAR -------*/
|
||||
/* width */
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
/* Track */
|
||||
::-webkit-scrollbar-track {
|
||||
background: #8080806b;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
/* Handle */
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #f5f5f559;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
/* Handle on hover */
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #f5f5f59e;
|
||||
border-radius: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
BIN
src/assets/graphics/HomeGraphics2.png
Normal file
BIN
src/assets/graphics/HomeGraphics2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 379 KiB |
122
src/components/HeaderLoginTemplate.vue
Normal file
122
src/components/HeaderLoginTemplate.vue
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
<template>
|
||||
<transition name="fade-in" appear >
|
||||
<div class="header">
|
||||
<div :class="{animation: true, night: !isDay }" id="animation">
|
||||
<div :class="{map: true, 'night-map': !isDay }"></div>
|
||||
</div>
|
||||
<div class="title">Nertivia</div>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
isDay: true
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
setInterval(_ => {
|
||||
if (this.isDay) {
|
||||
this.$emit("isDay", false);
|
||||
this.isDay = false;
|
||||
} else {
|
||||
this.$emit("isDay", true);
|
||||
this.isDay = true;
|
||||
}
|
||||
}, 10000);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.fade-in-enter-active {
|
||||
opacity: 0;
|
||||
animation: bounce-in .5s;
|
||||
animation-delay: 0.5s;
|
||||
}
|
||||
|
||||
|
||||
@keyframes bounce-in {
|
||||
0% {
|
||||
transform: translateY(-20px);
|
||||
opacity: 0;
|
||||
}
|
||||
50%{
|
||||
transform: translateY(10px);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* .fade-in-enter-active, .fade-in-leave-active {
|
||||
transition: .5s;
|
||||
transition-delay: 0.5s
|
||||
}
|
||||
.fade-in-enter, .fade-in-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-50px)
|
||||
} */
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: auto;
|
||||
align-items: center;
|
||||
margin-bottom: 0;
|
||||
margin-top: 50px;
|
||||
z-index: 99999;
|
||||
}
|
||||
.animation {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
background-color: #2cb4ff;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0px 0px 96px -4px rgba(69, 212, 255, 1);
|
||||
overflow: hidden;
|
||||
transition: 10s;
|
||||
margin: auto;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.map {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
background-position: -490px center;
|
||||
background-size: 170%;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url(./../assets/LogoAnimation/map.png);
|
||||
animation: rotateGlobe;
|
||||
animation-timing-function: linear;
|
||||
animation-duration: 10s;
|
||||
animation-fill-mode: forwards;
|
||||
animation-iteration-count: infinite;
|
||||
transition: 10s;
|
||||
}
|
||||
.night-map {
|
||||
filter: grayscale(90%);
|
||||
}
|
||||
|
||||
.night {
|
||||
background: rgb(0, 48, 73);
|
||||
box-shadow: 0px 0px 96px -4px rgb(0, 48, 73);
|
||||
}
|
||||
@keyframes rotateGlobe {
|
||||
from {
|
||||
background-position: -400px center;
|
||||
}
|
||||
to {
|
||||
background-position: 190px center;
|
||||
}
|
||||
}
|
||||
.header .title {
|
||||
color: white;
|
||||
font-size: 40px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
136
src/components/ParticlesJS.vue
Normal file
136
src/components/ParticlesJS.vue
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
<template>
|
||||
<div id="particles-js"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "ParticlesJS",
|
||||
|
||||
mounted() {
|
||||
require("particles.js");
|
||||
this.$nextTick(() => {
|
||||
this.initParticlesJS();
|
||||
});
|
||||
},
|
||||
|
||||
methods: {
|
||||
initParticlesJS() {
|
||||
/* eslint-disable */
|
||||
particlesJS("particles-js", {
|
||||
particles: {
|
||||
number: {
|
||||
value: 100,
|
||||
density: {
|
||||
enable: true,
|
||||
value_area: 480
|
||||
}
|
||||
},
|
||||
color: {
|
||||
value: "#ffffff"
|
||||
},
|
||||
shape: {
|
||||
type: "circle",
|
||||
stroke: {
|
||||
width: 0,
|
||||
color: "#000000"
|
||||
},
|
||||
},
|
||||
opacity: {
|
||||
value: 1,
|
||||
random: true,
|
||||
anim: {
|
||||
enable: true,
|
||||
speed: 1,
|
||||
opacity_min: 0,
|
||||
sync: false
|
||||
}
|
||||
},
|
||||
size: {
|
||||
value: 2.5,
|
||||
random: true,
|
||||
anim: {
|
||||
enable: false,
|
||||
speed: 4,
|
||||
size_min: 0.3,
|
||||
sync: false
|
||||
}
|
||||
},
|
||||
line_linked: {
|
||||
enable: false,
|
||||
distance: 150,
|
||||
color: "#ffffff",
|
||||
opacity: 0.4,
|
||||
width: 1
|
||||
},
|
||||
move: {
|
||||
enable: true,
|
||||
speed: 0.1,
|
||||
direction: "none",
|
||||
random: true,
|
||||
straight: false,
|
||||
out_mode: "out",
|
||||
bounce: false,
|
||||
attract: {
|
||||
enable: false,
|
||||
rotateX: 600,
|
||||
rotateY: 600
|
||||
}
|
||||
}
|
||||
},
|
||||
interactivity: {
|
||||
detect_on: "canvas",
|
||||
events: {
|
||||
onhover: {
|
||||
enable: false,
|
||||
mode: "bubble"
|
||||
},
|
||||
onclick: {
|
||||
enable: false,
|
||||
mode: "repulse"
|
||||
},
|
||||
resize: true
|
||||
},
|
||||
modes: {
|
||||
grab: {
|
||||
distance: 400,
|
||||
line_linked: {
|
||||
opacity: 1
|
||||
}
|
||||
},
|
||||
bubble: {
|
||||
distance: 250,
|
||||
size: 0,
|
||||
duration: 2,
|
||||
opacity: 0,
|
||||
speed: 3
|
||||
},
|
||||
repulse: {
|
||||
distance: 400,
|
||||
duration: 0.4
|
||||
},
|
||||
push: {
|
||||
particles_nb: 4
|
||||
},
|
||||
remove: {
|
||||
particles_nb: 2
|
||||
}
|
||||
}
|
||||
},
|
||||
retina_detect: true
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#particles-js {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -13,6 +13,17 @@ export default {
|
|||
|
||||
}
|
||||
},
|
||||
beforeMount(){
|
||||
const existing = document.getElementById('reCaptchaScript');
|
||||
if (existing)
|
||||
existing.remove();
|
||||
|
||||
const $script = document.createElement('script')
|
||||
$script.async = true
|
||||
$script.id = "reCaptchaScript"
|
||||
$script.src = 'https://www.google.com/recaptcha/api.js?onload=vueRecaptchaApiLoaded&render=explicit'
|
||||
document.head.appendChild($script)
|
||||
},
|
||||
methods: {
|
||||
submit(response) {
|
||||
this.$emit('verify', response)
|
||||
|
|
|
|||
|
|
@ -1,15 +1,18 @@
|
|||
<template>
|
||||
<div class="loading-screen">
|
||||
<div class="loading-animation"></div>
|
||||
<div class="title">{{$props.msg}}</div>
|
||||
<div class="loading-animation" :style="`height: ${size}px ; width: ${size}px ;`"></div>
|
||||
<div class="title" v-if="msg">{{$props.msg}}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: [
|
||||
"msg"
|
||||
]
|
||||
props: {
|
||||
msg: String,
|
||||
size: {
|
||||
default: 100
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -19,8 +22,6 @@ export default {
|
|||
margin: auto;
|
||||
}
|
||||
.loading-animation{
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
background-size: 100%;
|
||||
background-image: url(../assets/spinner.svg);
|
||||
display: table;
|
||||
|
|
|
|||
|
|
@ -525,8 +525,8 @@ export default {
|
|||
}
|
||||
|
||||
.heading {
|
||||
border-bottom: solid 2px white;
|
||||
margin: 5px;
|
||||
padding: 5px;
|
||||
background: rgba(0, 0, 0, 0.185);
|
||||
margin-bottom: 0;
|
||||
height: 40px;
|
||||
padding-bottom: 2spx;
|
||||
|
|
|
|||
|
|
@ -278,6 +278,7 @@ export default {
|
|||
}
|
||||
.username:hover{
|
||||
color: rgb(199, 199, 199);
|
||||
text-decoration: underline;
|
||||
}
|
||||
.date {
|
||||
color: rgb(161, 161, 161);
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@ import config from "@/config.js";
|
|||
import MessageTemplate from '@/components/app/MessageTemplate.vue';
|
||||
import SettingsService from '@/services/settingsService.js';
|
||||
|
||||
import { mapState } from "vuex";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MessageTemplate
|
||||
|
|
@ -47,7 +45,9 @@ export default {
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('settingsModule', ['apperance']),
|
||||
apperance() {
|
||||
return this.$store.getters['settingsModule/settings'].apperance;
|
||||
},
|
||||
user() {
|
||||
return this.$store.getters.user
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,34 +1,78 @@
|
|||
<template>
|
||||
<div class="left-panel">
|
||||
<MyMiniInformation />
|
||||
<MyMiniInformation/>
|
||||
|
||||
<div class="list">
|
||||
<online-friends />
|
||||
<server v-for="(data, index) in serverData" :key="index" :server-data="data" @click.native="toggleChannel(index, $event)" :open-channel="openedServer && openedServer === index"/>
|
||||
<server mode="ADD_SERVER"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import MyMiniInformation from '../../components/app/MyMiniInformation.vue'
|
||||
import OnlineFriends from './relationships/OnlineFriends.vue'
|
||||
|
||||
import MyMiniInformation from "@/components/app/MyMiniInformation.vue";
|
||||
import Server from "@/components/app/ServerTemplate/ServerTemplate.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MyMiniInformation,
|
||||
OnlineFriends,
|
||||
|
||||
Server
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
openedServer: null,
|
||||
serverData: {
|
||||
"67574563576897": {
|
||||
name: "DevHelp",
|
||||
channels: [
|
||||
{ name: "General", channelID: 3563567574767467 },
|
||||
{ name: "NodeJS", channelID: 758546746747378 },
|
||||
{ name: "Java", channelID: 57355675747875 },
|
||||
{ name: "C#", channelID: 45656764765676 }
|
||||
]
|
||||
},
|
||||
"24325587980787": {
|
||||
name: "Musica",
|
||||
channels: [
|
||||
{ name: "General", channelID: 3563567574767467 },
|
||||
{ name: "NodeJS", channelID: 758546746747378 },
|
||||
{ name: "Java", channelID: 57355675747875 },
|
||||
{ name: "C#", channelID: 45656764765676 }
|
||||
]
|
||||
},
|
||||
"3468636435": {
|
||||
name: "IDK",
|
||||
channels: [
|
||||
{ name: "General", channelID: 3563567574767467 },
|
||||
{ name: "NodeJS", channelID: 758546746747378 },
|
||||
{ name: "Java", channelID: 57355675747875 },
|
||||
{ name: "C#", channelID: 45656764765676 }
|
||||
]
|
||||
},
|
||||
"63575764574645": {
|
||||
name: "OWO",
|
||||
channels: [
|
||||
{ name: "General", channelID: 3563567574767467 },
|
||||
{ name: "NodeJS", channelID: 758546746747378 },
|
||||
{ name: "Java", channelID: 57355675747875 },
|
||||
{ name: "C#", channelID: 45656764765676 }
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
toggleChannel(index, event) {
|
||||
if (!event.target.closest('.small-view')) return;
|
||||
if (this.openedServer === index)
|
||||
this.openedServer = null;
|
||||
else
|
||||
this.openedServer = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
.left-panel {
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.671);
|
||||
|
|
@ -38,33 +82,33 @@ export default {
|
|||
flex-direction: column;
|
||||
z-index: 1;
|
||||
}
|
||||
.list{
|
||||
margin: 10px;
|
||||
.list {
|
||||
margin: 2px;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------- SCROLL BAR -------*/
|
||||
/* width */
|
||||
.list::-webkit-scrollbar {
|
||||
width: 3px;
|
||||
width: 3px;
|
||||
}
|
||||
|
||||
/* Track */
|
||||
.list::-webkit-scrollbar-track {
|
||||
background: #8080806b;
|
||||
background: #8080806b;
|
||||
}
|
||||
|
||||
/* Handle */
|
||||
.list::-webkit-scrollbar-thumb {
|
||||
background: #f5f5f559;
|
||||
background: #f5f5f559;
|
||||
}
|
||||
|
||||
/* Handle on hover */
|
||||
.list::-webkit-scrollbar-thumb:hover {
|
||||
background: #f5f5f59e;
|
||||
background: #f5f5f59e;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
35
src/components/app/ServerTemplate/ChannelTemplate.vue
Normal file
35
src/components/app/ServerTemplate/ChannelTemplate.vue
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<template>
|
||||
<div class="channel">
|
||||
<i class="material-icons">storage</i>
|
||||
<div class="channel-name">{{ChannelData.name}}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ["ChannelData"]
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.channel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 5px;
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
transition: 0.3s;
|
||||
font-size: 14px;
|
||||
}
|
||||
.channel:hover {
|
||||
background: rgba(139, 139, 139, 0.288);
|
||||
}
|
||||
.channel-name {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-left: 5px;
|
||||
}
|
||||
</style>
|
||||
99
src/components/app/ServerTemplate/ServerTemplate.vue
Normal file
99
src/components/app/ServerTemplate/ServerTemplate.vue
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
<template>
|
||||
<div :class="{server: true, 'add-server': mode === 'ADD_SERVER'}">
|
||||
<div class="small-view" @click="showChannels = !showChannels">
|
||||
<profile-picture size="50px" v-if="!mode" :url="tempImage"/>
|
||||
<div class="add-icon" v-if="mode === 'ADD_SERVER'">
|
||||
<i class="material-icons">add</i>
|
||||
</div>
|
||||
<div class="server-name">{{mode === 'ADD_SERVER'? 'Add Server' : ServerData.name}}</div>
|
||||
</div>
|
||||
<div ref="container">
|
||||
<div class="channel-list" v-if="openChannel">
|
||||
<ChannelTemplate
|
||||
v-for="channel in ServerData.channels"
|
||||
:key="channel.name"
|
||||
:channel-data="channel"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from "@/config.js";
|
||||
import ChannelTemplate from "@/components/app/ServerTemplate/ChannelTemplate.vue";
|
||||
import ProfilePicture from "@/components/ProfilePictureTemplate.vue";
|
||||
import smoothReflow from "vue-smooth-reflow";
|
||||
|
||||
export default {
|
||||
mixins: [smoothReflow],
|
||||
props: ["ServerData", "openChannel", "mode"],
|
||||
components: { ProfilePicture, ChannelTemplate },
|
||||
data() {
|
||||
return {
|
||||
showChannels: false,
|
||||
tempImage: config.domain + "/avatars/noob"
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.$smoothReflow({
|
||||
el: this.$refs.container
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.server {
|
||||
color: white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: rgba(0, 0, 0, 0.137);
|
||||
border-radius: 5px;
|
||||
margin: 5px;
|
||||
transition: 0.3s;
|
||||
}
|
||||
.add-server{
|
||||
background: rgba(0, 255, 21, 0.277);
|
||||
}
|
||||
|
||||
.server:hover {
|
||||
background: rgba(0, 0, 0, 0.288);
|
||||
}
|
||||
.add-server:hover{
|
||||
background: rgba(0, 255, 21, 0.377);
|
||||
}
|
||||
|
||||
.small-view {
|
||||
padding-right: 0;
|
||||
display: flex;
|
||||
transition: 0.3s;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
align-items: center;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.channel-list {
|
||||
background: rgba(0, 0, 0, 0.288);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.server-name {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.add-icon{
|
||||
height: 56px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 10px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.add-icon .material-icons {
|
||||
font-size: 40px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -58,8 +58,6 @@ export default {
|
|||
@media (max-width: 600px) {
|
||||
.left-panel {
|
||||
position: absolute;
|
||||
top: 47px;
|
||||
height: calc(100% - 47px);
|
||||
background-color: rgba(39, 39, 39, 0.97);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,8 +58,6 @@ export default {
|
|||
@media (max-width: 600px) {
|
||||
.left-panel {
|
||||
position: absolute;
|
||||
top: 47px;
|
||||
height: calc(100% - 47px);
|
||||
background-color: rgba(39, 39, 39, 0.97);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,130 +0,0 @@
|
|||
<template>
|
||||
<div class="logged-in">
|
||||
<div class="card">
|
||||
<div class="avatar-outer">
|
||||
<profile-picture :url="avatar" :admin="user.admin" size="90px" emoteSize="27px" />
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="username">{{user.username}}<span class="tag">@{{user.tag}}</span></div>
|
||||
<div class="buttons">
|
||||
<button class="button" @click="openChat">Enter</button>
|
||||
<button class="button logout" @click="logout">Logout</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ProfilePicture from "@/components/ProfilePictureTemplate.vue";
|
||||
import config from '@/config.js'
|
||||
export default {
|
||||
components: {
|
||||
ProfilePicture
|
||||
},
|
||||
methods: {
|
||||
logout() {
|
||||
this.$store.commit('logout')
|
||||
},
|
||||
openChat() {
|
||||
window.location.href = "/app"
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
user() {
|
||||
return this.$store.getters.user;
|
||||
},
|
||||
avatar() {
|
||||
return config.domain + "/avatars/" +this.$store.getters.user.avatar
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.logged-in {
|
||||
color: white;
|
||||
margin-top: 10px;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.card{
|
||||
background-color: rgba(0, 0, 0, 0.041);
|
||||
padding: 20px;
|
||||
margin-bottom: 30px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
align-self: center;
|
||||
justify-content: center;
|
||||
justify-items: center;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
|
||||
.title {
|
||||
display: table;
|
||||
margin: auto;
|
||||
margin-top: 10px;
|
||||
font-size: 25px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.profile-picture {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-left: 10px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.username {
|
||||
font-size: 20px;
|
||||
word-wrap: break-word;
|
||||
word-break: break-word;
|
||||
white-space: pre-wrap;
|
||||
overflow: hidden;
|
||||
user-select: all;
|
||||
max-width: 200px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.tag{
|
||||
font-size: 13px;
|
||||
color: rgb(194, 194, 194);
|
||||
}
|
||||
|
||||
.buttons{
|
||||
display: flex;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.button {
|
||||
color: white;
|
||||
background: rgba(0, 0, 0, 0.308);
|
||||
padding: 10px;
|
||||
border: none;
|
||||
outline: none;
|
||||
margin-right: 10px;
|
||||
margin-left: 10px;
|
||||
margin-top: 30px;
|
||||
transition: 0.3s;
|
||||
font-size: 17px;
|
||||
}
|
||||
.button:hover {
|
||||
background: rgba(0, 0, 0, 0.582);
|
||||
}
|
||||
|
||||
.button.logout{
|
||||
background: rgba(219, 36, 36, 0.438);
|
||||
}
|
||||
.button.logout:hover {
|
||||
background: rgba(255, 18, 18, 0.582);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
<template>
|
||||
<div class="form">
|
||||
<form action="#" @submit.prevent="login">
|
||||
<div class="input">
|
||||
<div class="alert other-alert">{{otherError}}</div>
|
||||
<div class="input-title">Email: <div class="alert">{{email.alert}}</div></div>
|
||||
<input type="email" autocomplete="on" v-model="email.value">
|
||||
</div>
|
||||
<div class="input">
|
||||
<div class="input-title">Password: <div class="alert">{{password.alert}}</div></div>
|
||||
<input type="password" autocomplete="current-password" v-model="password.value">
|
||||
</div>
|
||||
<div class="cap">
|
||||
<recaptcha ref="recaptcha" @verify="captchaSubmit" />
|
||||
</div>
|
||||
<loadingButton :loading="currentMessage == 1" :message="buttonMessages[currentMessage]" />
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Recaptcha from '../Recaptcha.vue'
|
||||
import {bus} from '../../main';
|
||||
import loadingButton from "../../components/Button.vue"
|
||||
import AuthenticationService from '@/services/AuthenticationService';
|
||||
export default {
|
||||
components: {
|
||||
loadingButton,
|
||||
Recaptcha
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
email: {value: "", alert: ""},
|
||||
password: {value: "", alert: ""},
|
||||
otherError: "",
|
||||
buttonMessages: [
|
||||
"Login",
|
||||
"Logging in..."
|
||||
],
|
||||
currentMessage: 0,
|
||||
captcha: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetValues() {
|
||||
// Resets all of the alert values
|
||||
this.email.alert = "";
|
||||
this.password.alert = "";
|
||||
this.otherError = "";
|
||||
},
|
||||
async login() {
|
||||
this.currentMessage = 1
|
||||
this.resetValues();
|
||||
const email = this.email.value.trim();
|
||||
const password = this.password.value.trim();
|
||||
const captcha = this.captcha;
|
||||
|
||||
const {ok, error, result} = await AuthenticationService.login({email, password, token: captcha})
|
||||
this.currentMessage = 0
|
||||
|
||||
if (ok) {
|
||||
this.$store.dispatch('token', result.data.token)
|
||||
this.$store.dispatch('user', result.data.user)
|
||||
} else {
|
||||
this.captcha = null;
|
||||
this.$refs.recaptcha.resetRecaptcha();
|
||||
if (error.response === undefined) {
|
||||
this.otherError = "Can't connect to server."
|
||||
return;
|
||||
}
|
||||
const errors = error.response.data.errors;
|
||||
for (let index in errors) {
|
||||
const message = errors[index].msg;
|
||||
const param = errors[index].param;
|
||||
if(this[param] === undefined) {
|
||||
this.otherError = message;
|
||||
} else {
|
||||
this[param].alert = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
captchaSubmit(token) {
|
||||
this.captcha = token;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.input {
|
||||
display: table;
|
||||
margin: auto;
|
||||
}
|
||||
.cap {
|
||||
margin: 20px;
|
||||
opacity: 0.8;
|
||||
transition: 0.3s;
|
||||
}
|
||||
.cap:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
131
src/components/homePage/Popout.vue
Normal file
131
src/components/homePage/Popout.vue
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
<template>
|
||||
<div class="profile-popout">
|
||||
<div class="triangle"></div>
|
||||
<div class="inner">
|
||||
<div class="outer-profile-picture" v-if="user">
|
||||
<profile-picture
|
||||
:url="avatarDomain + user.avatar"
|
||||
:admin="user.admin"
|
||||
size="40px"
|
||||
emoteSize="17px"
|
||||
/>
|
||||
</div>
|
||||
<div class="information">
|
||||
<div
|
||||
class="username"
|
||||
>{{user.username}}</div>
|
||||
<div class="tag">@{{user.tag}}</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<i class="material-icons warn" @click="logOut">exit_to_app</i>
|
||||
<i class="material-icons" @click="openApp">message</i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ProfilePicture from "@/components/ProfilePictureTemplate.vue";
|
||||
import config from "@/config.js";
|
||||
|
||||
export default {
|
||||
props: ["user"],
|
||||
components: { ProfilePicture },
|
||||
data() {
|
||||
return {
|
||||
avatarDomain: config.domain + "/avatars/"
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
openApp() {
|
||||
window.location.href = "/app";
|
||||
},
|
||||
logOut() {
|
||||
this.$emit('logout');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.profile-popout {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
right: 3px;
|
||||
top: 75px;
|
||||
}
|
||||
.triangle {
|
||||
position: absolute;
|
||||
right: 30px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 10px solid transparent;
|
||||
border-right: 10px solid transparent;
|
||||
border-bottom: 15px solid rgba(0, 0, 0, 0.826);
|
||||
}
|
||||
.inner {
|
||||
right: 0;
|
||||
top: 15px;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
background: rgba(0, 0, 0, 0.826);
|
||||
border-radius: 5px;
|
||||
width: 300px;
|
||||
height: 60px;
|
||||
padding: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
.outer-profile-picture {
|
||||
z-index: 999999;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.information {
|
||||
margin-left: 10px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
.username {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 100%;
|
||||
height: 17px;
|
||||
}
|
||||
.tag {
|
||||
color: rgb(163, 163, 163);
|
||||
}
|
||||
.buttons {
|
||||
display: flex;
|
||||
margin: 5px;
|
||||
}
|
||||
.buttons .material-icons {
|
||||
display: block;
|
||||
margin: 5px;
|
||||
color: rgba(255, 255, 255, 0.651);
|
||||
transition: 0.3s;
|
||||
cursor: default;
|
||||
font-size: 27px;
|
||||
}
|
||||
.buttons .material-icons:hover {
|
||||
color: white;
|
||||
}
|
||||
.buttons .warn {
|
||||
color: rgba(255, 0, 0, 0.651);
|
||||
}
|
||||
.buttons .warn:hover {
|
||||
color: rgba(255, 0, 0, 0.795);
|
||||
}
|
||||
@media (max-width: 342px) {
|
||||
.inner {
|
||||
left: 0;
|
||||
right:0;
|
||||
width: 100%;
|
||||
}
|
||||
.profile-popout{
|
||||
left: 0;
|
||||
right:20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
<template>
|
||||
<div class="form">
|
||||
<form action="#" @submit.prevent="register">
|
||||
<div class="input">
|
||||
<div class="alert">{{otherError}}</div>
|
||||
<div class="input-title">Email: <div class="alert">{{email.alert}}</div></div>
|
||||
<input type="email" autocomplete="on" v-model="email.value">
|
||||
</div>
|
||||
<div class="input">
|
||||
<div class="input-title">Username: <div class="alert">{{username.alert}}</div></div>
|
||||
<input type="username" autocomplete="off" v-model="username.value">
|
||||
</div>
|
||||
<div class="input">
|
||||
<div class="input-title">Password: <div class="alert">{{password.alert}}</div></div>
|
||||
<input type="password" autocomplete="new-password" v-model="password.value">
|
||||
</div>
|
||||
<div class="input">
|
||||
<div class="input-title">Password confirm: <div class="alert">{{passwordConfirm.alert}}</div></div>
|
||||
<input type="password" autocomplete="new-password" v-model="passwordConfirm.value">
|
||||
</div>
|
||||
<div class="cap">
|
||||
<recaptcha ref="recaptcha" @verify="captchaSubmit" />
|
||||
</div>
|
||||
<loading-button :loading="currentMessage == 1" :message="buttonMessages[currentMessage]" />
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Recaptcha from '../Recaptcha.vue'
|
||||
import AuthenticationService from '@/services/AuthenticationService.js'
|
||||
import {bus} from '../../main';
|
||||
import LoadingButton from "../../components/Button.vue"
|
||||
export default {
|
||||
components: {
|
||||
LoadingButton,
|
||||
Recaptcha
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
email: {value: "", alert: ""},
|
||||
username: {value: "", alert: ""},
|
||||
password: {value: "", alert: ""},
|
||||
passwordConfirm: {value: "", alert: ""},
|
||||
otherError: "",
|
||||
buttonMessages: [
|
||||
"Register",
|
||||
"Creating... ( Thank you c: )"
|
||||
],
|
||||
currentMessage: 0,
|
||||
captcha: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetValues() {
|
||||
// Resets all of the alert values
|
||||
this.email.alert = "";
|
||||
this.username.alert = "";
|
||||
this.password.alert = "";
|
||||
this.passwordConfirm.alert = "";
|
||||
this.otherError = ""
|
||||
},
|
||||
async register() {
|
||||
this.currentMessage = 1
|
||||
this.resetValues();
|
||||
const email = this.email.value.trim();
|
||||
const username = this.username.value.trim();
|
||||
const password = this.password.value.trim();
|
||||
const passwordConfirm = this.passwordConfirm.value.trim();
|
||||
|
||||
// check if password + password confirm matches.
|
||||
if ( password != passwordConfirm ) {
|
||||
this.currentMessage = 0;
|
||||
return this.passwordConfirm.alert = "Passwords do not match!"
|
||||
}
|
||||
const {ok, error, result} = await AuthenticationService.register({email, username, password, token: this.captcha})
|
||||
this.currentMessage = 0
|
||||
if ( ok ) {
|
||||
this.$store.dispatch('token', result.data.token)
|
||||
this.$store.dispatch('user', result.data.user)
|
||||
} else {
|
||||
this.captcha = null;
|
||||
this.$refs.recaptcha.resetRecaptcha();
|
||||
if (error.response === undefined) {
|
||||
this.otherError = "Can't connect to server."
|
||||
return;
|
||||
}
|
||||
const errors = error.response.data.errors;
|
||||
for (let index in errors) {
|
||||
const message = errors[index].msg;
|
||||
const param = errors[index].param;
|
||||
if(this[param] === undefined) {
|
||||
this.otherError = message;
|
||||
} else {
|
||||
this[param].alert = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
captchaSubmit(token) {
|
||||
this.captcha = token;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.input {
|
||||
display: table;
|
||||
margin: auto;
|
||||
}
|
||||
.cap {
|
||||
margin: 20px;
|
||||
opacity: 0.8;
|
||||
transition: 0.3s;
|
||||
}
|
||||
.cap:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,184 +0,0 @@
|
|||
<template>
|
||||
<div class="right-panel-home">
|
||||
<div class="right-panel-inner">
|
||||
<img class="logo" src="./../../assets/logo.svg" />
|
||||
<div class="title">Nertivia</div>
|
||||
<spinner :msg="spinnerMessage" v-if="previouslyLoggedIn && user == null && tokenExists" />
|
||||
|
||||
<transition name="component-fade" appear mode="out-in" v-else>
|
||||
|
||||
<logged-in v-if="tokenExists && user != null" />
|
||||
|
||||
<div class="new-member" v-if="!tokenExists">
|
||||
<div class="details">
|
||||
Nertivia chat is the best chat client to be made with 99% uptime, you won't miss a thing! Join now if you’re new!
|
||||
</div>
|
||||
<div class="switch-buttons">
|
||||
<div :class="{button: true, selected: loginSelected}" @click="loginSelected = true">Already a pro</div>
|
||||
<div :class="{button: true, selected: !loginSelected}" @click="loginSelected = false">I'm new!</div>
|
||||
</div>
|
||||
<transition name="switch-selected" mode="out-in">
|
||||
<login-panel v-if="loginSelected" />
|
||||
<register-panel v-if="!loginSelected" />
|
||||
</transition>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {bus} from '../../main';
|
||||
import AuthenticationService from '@/services/AuthenticationService.js'
|
||||
import RegisterPanel from "../../components/homePage/RegisterPanel.vue"
|
||||
import LoginPanel from "../../components/homePage/LoginPanel.vue"
|
||||
import LoggedIn from "../../components/homePage/LoggedIn.vue"
|
||||
import Spinner from "../../components/Spinner.vue"
|
||||
export default {
|
||||
components: {
|
||||
RegisterPanel,
|
||||
LoginPanel,
|
||||
LoggedIn,
|
||||
Spinner
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loginSelected: true,
|
||||
previouslyLoggedIn: false,
|
||||
spinnerMessage: "Logging in...",
|
||||
connectionRetryCount: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async getUser() {
|
||||
// Get details if previously logged in.
|
||||
if (this.previouslyLoggedIn) {
|
||||
const { ok, error, result } = await AuthenticationService.user();
|
||||
if ( ok ) {
|
||||
this.$store.commit( 'user', result.data.user );
|
||||
} else {
|
||||
if ( error.response === undefined ) {
|
||||
this.connectionRetryCount++;
|
||||
this.spinnerMessage = `Connection failed. Trying again (${this.connectionRetryCount})`
|
||||
setTimeout(() => {
|
||||
this.getUser();
|
||||
}, 5000);
|
||||
return;
|
||||
}
|
||||
this.$store.commit( 'logout' );
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
this.previouslyLoggedIn = this.tokenExists;
|
||||
this.getUser()
|
||||
|
||||
},
|
||||
computed: {
|
||||
tokenExists() {
|
||||
return this.$store.getters.tokenExists;
|
||||
},
|
||||
user() {
|
||||
return this.$store.getters.user;
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.component-fade-enter-active, .component-fade-leave-active {
|
||||
transition: .3s ease;
|
||||
}
|
||||
.component-fade-enter, .component-fade-leave-to {
|
||||
transform: translateY(20px);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.switch-selected-enter-active, .switch-selected-leave-active {
|
||||
transition: .3s ease;
|
||||
}
|
||||
.switch-selected-enter, .switch-selected-leave-to {
|
||||
transform: translateY(20px);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
||||
.right-panel-home {
|
||||
width: 400px;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.493);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
user-select: none;
|
||||
}
|
||||
.right-panel-inner{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
}
|
||||
.new-member{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transition: .3s;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 150px;
|
||||
width: 150px;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0px 0px 96px -4px rgba(69,212,255,1);
|
||||
margin: auto;
|
||||
margin-bottom: 0;
|
||||
margin-top: 40px;
|
||||
flex-shrink: 0;
|
||||
|
||||
}
|
||||
|
||||
.title{
|
||||
color: white;
|
||||
font-size: 35px;
|
||||
text-align: center;
|
||||
margin-top: 50px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.right-panel .title {
|
||||
margin: auto;
|
||||
margin-top: 10px;
|
||||
width: 230px;
|
||||
font-size: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
.details{
|
||||
color: rgb(204, 204, 204);
|
||||
margin: 49px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.switch-buttons{
|
||||
display: table;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.button{
|
||||
color: white;
|
||||
font-size: 18px;
|
||||
display: inline-block;
|
||||
padding: 10px;
|
||||
margin: 5px;
|
||||
user-select: none;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.button:hover{
|
||||
border-bottom: solid 2px rgba(255, 255, 255, 0.493);
|
||||
}
|
||||
|
||||
.button.selected{
|
||||
border-bottom: solid 2px white;
|
||||
}
|
||||
|
||||
</style>
|
||||
116
src/router.js
116
src/router.js
|
|
@ -1,58 +1,88 @@
|
|||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
Vue.use(VueRouter)
|
||||
import {store} from './store/index';
|
||||
import VueSocketio from 'vue-socket.io-extended';
|
||||
import io from 'socket.io-client';
|
||||
import config from './config'
|
||||
import VueMq from 'vue-mq'
|
||||
import Vue from "vue";
|
||||
import VueRouter from "vue-router";
|
||||
Vue.use(VueRouter);
|
||||
import { store } from "./store/index";
|
||||
import VueSocketio from "vue-socket.io-extended";
|
||||
import io from "socket.io-client";
|
||||
import config from "./config";
|
||||
import VueMq from "vue-mq";
|
||||
|
||||
import MainApp from '../src/views/App.vue'
|
||||
import HomePage from '../src/views/HomePage.vue'
|
||||
import GDriveCallback from '../src/views/GDriveCallback.vue';
|
||||
// import MainApp from '../src/views/App.vue'
|
||||
//import HomePage from '../src/views/HomePage.vue'
|
||||
//import GDriveCallback from '../src/views/GDriveCallback.vue';
|
||||
//import LoginPage from '../src/views/LoginPage.vue';
|
||||
//import RegisterPage from '../src/views/RegisterPage.vue';
|
||||
|
||||
// const MainApp = () => import('../src/views/App.vue');
|
||||
// const HomePage = () => import('../src/views/HomePage.vue');
|
||||
// const GDriveCallback = () => import( '../src/views/GDriveCallback.vue');
|
||||
const MainApp = () => import(/* webpackChunkName: "MainApp" */ "../src/views/App.vue");
|
||||
const HomePage = () => import(/* webpackChunkName: "HomePage" */ "../src/views/HomePage.vue");
|
||||
const GDriveCallback = () => import(/* webpackChunkName: "GDriveCallback" */ "../src/views/GDriveCallback.vue");
|
||||
const LoginPage = () => import(/* webpackChunkName: "LoginPage" */ "../src/views/LoginPage.vue");
|
||||
const RegisterPage = () => import(/* webpackChunkName: "RegisterPage" */ "../src/views/RegisterPage.vue");
|
||||
|
||||
export const router = new VueRouter({
|
||||
mode: 'history',
|
||||
mode: "history",
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'HomePage',
|
||||
path: "/",
|
||||
name: "HomePage",
|
||||
component: HomePage
|
||||
},
|
||||
{
|
||||
path: '/app',
|
||||
name: 'app',
|
||||
component: MainApp,
|
||||
beforeEnter (to, from, next) {
|
||||
if (!localStorage.getItem('hauthid')){
|
||||
return router.push({ path: '/' })
|
||||
path: "/login",
|
||||
name: "Login",
|
||||
component: LoginPage,
|
||||
beforeEnter(to, from, next) {
|
||||
if (localStorage.getItem("hauthid")) {
|
||||
return router.push({ path: "/app" });
|
||||
}
|
||||
Vue.use(VueSocketio, io(config.socketIP, {
|
||||
transportOptions: {
|
||||
polling: {
|
||||
extraHeaders: {
|
||||
authorization: localStorage.getItem('hauthid')
|
||||
}
|
||||
}
|
||||
}
|
||||
}), {store});
|
||||
Vue.use(VueMq, {
|
||||
breakpoints: {
|
||||
mobile: 600,
|
||||
desktop: Infinity,
|
||||
}
|
||||
})
|
||||
next()
|
||||
next();
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/GDrive_callback',
|
||||
name: 'GDrive callback',
|
||||
component: GDriveCallback
|
||||
path: "/register",
|
||||
name: "Register",
|
||||
component: RegisterPage,
|
||||
beforeEnter(to, from, next) {
|
||||
if (localStorage.getItem("hauthid")) {
|
||||
return router.push({ path: "/app" });
|
||||
}
|
||||
next();
|
||||
}
|
||||
},
|
||||
{
|
||||
path: "/app",
|
||||
name: "app",
|
||||
component: MainApp,
|
||||
beforeEnter(to, from, next) {
|
||||
if (!localStorage.getItem("hauthid")) {
|
||||
return router.push({ path: "/login" });
|
||||
}
|
||||
Vue.use(
|
||||
VueSocketio,
|
||||
io(config.socketIP, {
|
||||
transportOptions: {
|
||||
polling: {
|
||||
extraHeaders: {
|
||||
authorization: localStorage.getItem("hauthid")
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
{ store }
|
||||
);
|
||||
Vue.use(VueMq, {
|
||||
breakpoints: {
|
||||
mobile: 600,
|
||||
desktop: Infinity
|
||||
}
|
||||
});
|
||||
next();
|
||||
}
|
||||
},
|
||||
{
|
||||
path: "/GDrive_callback",
|
||||
name: "GDrive callback",
|
||||
component: GDriveCallback
|
||||
}
|
||||
]
|
||||
})
|
||||
});
|
||||
|
|
|
|||
|
|
@ -78,9 +78,7 @@ const actions = {
|
|||
|
||||
const mutations = {
|
||||
setApperance(state, data) {
|
||||
const apperance = state.apperance || {};
|
||||
apperance[Object.keys(data)[0]] = data[Object.keys(data)[0]]
|
||||
state['apperance'] = apperance
|
||||
Vue.set(state.apperance, Object.keys(data)[0], data[Object.keys(data)[0]])
|
||||
},
|
||||
setSettings(state, settings) {
|
||||
Vue.set(state, Object.assign(state, settings))
|
||||
|
|
|
|||
|
|
@ -1,14 +1,33 @@
|
|||
const config = [
|
||||
{
|
||||
version: 2,
|
||||
|
||||
const prototype = {
|
||||
version: 3,
|
||||
title: "Make your own servers!",
|
||||
shortTitle: "Servers",
|
||||
date: "24/04/2019",
|
||||
headColor: "rgba(155, 244, 66, 0.77)",
|
||||
new: [
|
||||
"",
|
||||
"",
|
||||
],
|
||||
next: [""]
|
||||
}
|
||||
|
||||
const config = [
|
||||
{
|
||||
version: 3,
|
||||
title: "Page Re-designs",
|
||||
shortTitle: "Page Re-designs",
|
||||
date: "28/04/2019",
|
||||
headColor: "rgba(155, 244, 66, 0.77)",
|
||||
new: [
|
||||
"Home page has been re-designed and has some cool animations.",
|
||||
"New login and register pages.",
|
||||
"Padding and margin adjusted and small design changes throughout the app."
|
||||
],
|
||||
fix: [
|
||||
'Fixed bugs with appearance settings not correctly working.'
|
||||
],
|
||||
next: ["Servers (If nothing else distracts me -_-)"]
|
||||
},
|
||||
{
|
||||
version: 1.5,
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ import Spinner from "./../components/Spinner.vue";
|
|||
const ElectronFrameButtons = () =>
|
||||
import("./../components/ElectronJS/FrameButtons.vue");
|
||||
|
||||
const News = () => import("./../components/app/Tabs/News.vue");
|
||||
const News = () => import(/* webpackChunkName: "News" */"./../components/app/Tabs/News.vue");
|
||||
//const DirectMessage = () => import('./../components/app/Tabs/DirectMessage.vue');
|
||||
const DirectMessage = () => ({
|
||||
component: import("./../components/app/Tabs/DirectMessage.vue"),
|
||||
|
|
@ -154,7 +154,7 @@ export default {
|
|||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
height: 35px;
|
||||
max-width: 473px;
|
||||
max-width: 479px;
|
||||
flex-basis: auto; /* default value */
|
||||
flex-grow: 1;
|
||||
-webkit-app-region: no-drag;
|
||||
|
|
@ -168,7 +168,7 @@ export default {
|
|||
flex-shrink: 0;
|
||||
margin: auto;
|
||||
margin-right: 1px;
|
||||
margin-left: 1px;
|
||||
margin-left: 3px;
|
||||
margin-bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.63);
|
||||
color: white;
|
||||
|
|
@ -227,23 +227,7 @@ export default {
|
|||
|
||||
|
||||
<style>
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#app {
|
||||
font-family: "Roboto", sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
color: #383838;
|
||||
height: 100%;
|
||||
}
|
||||
textarea {
|
||||
font-family: "Roboto", sans-serif;
|
||||
}
|
||||
|
|
@ -270,32 +254,30 @@ textarea {
|
|||
display: flex;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
/* ------- SCROLL BAR -------*/
|
||||
/* width */
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
/* Track */
|
||||
::-webkit-scrollbar-track {
|
||||
background: #8080806b;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
/* Handle */
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #f5f5f559;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
/* Handle on hover */
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #f5f5f59e;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
|
||||
input{
|
||||
padding: 10px;
|
||||
background: rgba(0, 0, 0, 0.301);
|
||||
outline: none;
|
||||
border: none;
|
||||
color: white;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 10px;
|
||||
width: 200px;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
input:hover{
|
||||
background: rgba(0, 0, 0, 0.452);
|
||||
}
|
||||
|
||||
input:focus {
|
||||
background: rgba(0, 0, 0, 0.603);
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
|
|
|||
477
src/views/HomePage - Legacy.vue
Normal file
477
src/views/HomePage - Legacy.vue
Normal file
|
|
@ -0,0 +1,477 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<vue-headful title="Nertivia" description="Nertivia Chat Client"/>
|
||||
<div class="background-image"></div>
|
||||
<div class="layout">
|
||||
<div class="small-view-nav-bar">
|
||||
<div class="small-logo"></div>
|
||||
<div class="small-title">Nertivia</div>
|
||||
<div class="show-menu-button" @click="showMobileMenu = !showMobileMenu">
|
||||
<i class="material-icons">
|
||||
menu
|
||||
</i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panels">
|
||||
<div class="left-panel">
|
||||
|
||||
<div class="title">The best chat client that wont restrict you from important and fun features.</div>
|
||||
<img src="../assets/graphics/HomeGraphics.png" class="graphic-app" />
|
||||
<div class="change-log-mini" @click="showChangeLog = true">
|
||||
<div class="change-title">Change log <span style="font-size: 15px; color: rgba(211, 211, 211, 0.774);">Click for details</span></div>
|
||||
<div class="change-list">
|
||||
<div class="change" v-for="change in changelogFiltered" :key="change.title">
|
||||
<div class="notable-changes">{{change.shortTitle}}</div>
|
||||
<div class="change-date">{{change.date}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="twitter-outer">
|
||||
<twitter class="twitter">
|
||||
<div slot="loading">loading .....</div>
|
||||
<a class="twitter-timeline" data-height="500" data-theme="dark" href="https://twitter.com/NertiviaApp?ref_src=twsrc%5Etfw">Tweets by NertiviaApp</a>
|
||||
</twitter>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<RightPanel :class="{'show-menu-content': showMobileMenu }" />
|
||||
</div>
|
||||
</div>
|
||||
<transition name="fade">
|
||||
<ChangeLog v-if="showChangeLog"/>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { twitter } from 'vue-twitter'
|
||||
import {bus} from '../main';
|
||||
import RightPanel from "./../components/homePage/RightPanel.vue"
|
||||
import ChangeLog from "./../components/ChangeLog.vue"
|
||||
import changelog from '@/utils/changelog.js'
|
||||
export default {
|
||||
components: {
|
||||
RightPanel,
|
||||
ChangeLog,
|
||||
twitter
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loginSelected: true,
|
||||
showMobileMenu: false,
|
||||
showChangeLog: false,
|
||||
changelog
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
bus.$on('closeChangeLog', () => {
|
||||
this.showChangeLog = false;
|
||||
})
|
||||
},
|
||||
computed: {
|
||||
changelogFiltered() {
|
||||
return this.changelog.slice(0, 3)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#app {
|
||||
font-family: "Roboto", sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
color: #383838;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.twitter-outer{
|
||||
margin: auto;
|
||||
width: 600px;
|
||||
opacity: 0.8;
|
||||
transition: 0.3s;
|
||||
}
|
||||
.twitter-outer:hover{
|
||||
opacity: 1;
|
||||
}
|
||||
.fade-enter-active, .fade-leave-active {
|
||||
transition: opacity .2s;
|
||||
}
|
||||
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
#app {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
color: #383838;
|
||||
height: 100%;
|
||||
}
|
||||
button {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
.spinner{
|
||||
margin: auto;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.background-image {
|
||||
background: url(./../assets/background.jpg);
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-repeat: no-repeat;
|
||||
background-position: bottom;
|
||||
background-size: cover;
|
||||
|
||||
}
|
||||
|
||||
.layout{
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width:100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
.panels{
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.left-panel {
|
||||
flex: 1;
|
||||
background: rgba(0, 0, 0, 0.253);
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.loader{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
}
|
||||
.title-panel{
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.graphics-panel{
|
||||
flex: 1;
|
||||
|
||||
}
|
||||
|
||||
.graphic-app{
|
||||
display: table;
|
||||
margin: auto;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
width: 900px;
|
||||
height: auto;
|
||||
user-select: none;
|
||||
}
|
||||
.title{
|
||||
color: white;
|
||||
font-size: 35px;
|
||||
text-align: center;
|
||||
margin-top: 120px;
|
||||
}
|
||||
|
||||
.change-log-mini{
|
||||
background: rgba(0, 0, 0, 0.322);
|
||||
height: 150px;
|
||||
width: 640px;
|
||||
margin: auto;
|
||||
margin-top: 20px;
|
||||
color: white;
|
||||
margin-bottom: 50px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.change-title {
|
||||
font-size: 18px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 10px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.change-list{
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.change {
|
||||
background: rgba(0, 0, 0, 0.335);
|
||||
width: 200px;
|
||||
height: 90px;
|
||||
margin-left: 10px;
|
||||
border-radius: 5px;
|
||||
transition: 0.3s;
|
||||
position: relative
|
||||
}
|
||||
.change:hover {
|
||||
background: rgba(0, 0, 0, 0.466);
|
||||
}
|
||||
.notable-changes{
|
||||
margin: 10px;
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.change-date{
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
color: rgba(255, 255, 255, 0.753);
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.small-view-nav-bar{
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
background: rgba(0, 0, 0, 0.411);
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
}
|
||||
|
||||
.small-logo {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
background: url(./../assets/logo.png);
|
||||
background-size: 105%;
|
||||
background-position: center;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0px 0px 96px -4px rgba(69,212,255,1);
|
||||
margin: auto;
|
||||
margin-left: 10px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.small-title{
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
flex: 1;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.show-menu-button{
|
||||
color: rgba(255, 255, 255, 0.698);
|
||||
margin-right: 20px;
|
||||
margin-top: 7px;
|
||||
user-select: none;
|
||||
transition: 0.3s
|
||||
}
|
||||
|
||||
.show-menu-button:hover {
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
.show-menu-content {
|
||||
display: flex !important;
|
||||
width: 400px !important;
|
||||
opacity: 1 !important;
|
||||
transform: scale(1) !important;
|
||||
}
|
||||
|
||||
@media (max-width: 1051px) {
|
||||
.change:nth-child(3){
|
||||
display: none;
|
||||
}
|
||||
.change-log-mini{
|
||||
width: 430px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 906px) {
|
||||
|
||||
.change:nth-child(3){
|
||||
display: block;
|
||||
}
|
||||
.change-log-mini{
|
||||
width: 640px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 649px) {
|
||||
.twitter-outer{
|
||||
margin-top: 20px;
|
||||
margin-bottom: 50px;
|
||||
width: initial;
|
||||
}
|
||||
.change-list{
|
||||
flex-direction: column;
|
||||
}
|
||||
.change-log-mini{
|
||||
height: initial;
|
||||
width: calc(100% - 20px);
|
||||
padding-bottom: 10px;
|
||||
margin: auto;
|
||||
}
|
||||
.change{
|
||||
margin-bottom: 5px;
|
||||
margin-left: 5px;
|
||||
margin-right: 0;
|
||||
width: calc(100% - 10px);
|
||||
}
|
||||
}
|
||||
@media (max-width: 1380px) {
|
||||
.graphic-app{
|
||||
width: calc(100% - 80px);
|
||||
}
|
||||
.title{
|
||||
font-size: 30px;
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
|
||||
}
|
||||
}
|
||||
@media (max-width: 906px) {
|
||||
.right-panel-home {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
top: 50px;
|
||||
display: flex;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
height:calc(100% - 50px);
|
||||
background-color: rgb(34, 34, 34);
|
||||
width: 0;
|
||||
overflow-x: hidden;
|
||||
transition: 0.5s ease;
|
||||
transform: scale(0.97);
|
||||
opacity: 0;
|
||||
|
||||
}
|
||||
.right-panel-inner{
|
||||
width: 400px;
|
||||
}
|
||||
.small-view-nav-bar{
|
||||
display: flex;
|
||||
}
|
||||
|
||||
}
|
||||
@media (max-width: 401px) {
|
||||
.show-menu-content {
|
||||
width: 100% !important;
|
||||
}
|
||||
.right-panel-inner{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<!-- Used for forms !-->
|
||||
<style>
|
||||
@media (max-width: 1380px) {
|
||||
.graphic-app{
|
||||
width: calc(100% - 80px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 906px) {
|
||||
|
||||
|
||||
|
||||
.right-panel-home {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
top: 50px;
|
||||
display: flex;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
height:calc(100% - 50px);
|
||||
background-color: rgba(34, 34, 34, 0.877);
|
||||
width: 0;
|
||||
overflow-x: hidden;
|
||||
transition: 0.5s ease;
|
||||
transform: scale(0.97);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.right-panel-inner{
|
||||
width: 400px;
|
||||
}
|
||||
.small-view-nav-bar{
|
||||
display: flex;
|
||||
}
|
||||
|
||||
}
|
||||
@media (max-width: 401px) {
|
||||
.show-menu-content {
|
||||
width: 100% !important;
|
||||
}
|
||||
.right-panel-inner{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.form {
|
||||
color: white;
|
||||
margin: auto;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
input{
|
||||
padding: 10px;
|
||||
background: rgba(0, 0, 0, 0.301);
|
||||
outline: none;
|
||||
border: none;
|
||||
color: white;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 10px;
|
||||
width: 200px;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
input:hover{
|
||||
background: rgba(0, 0, 0, 0.452);
|
||||
}
|
||||
|
||||
input:focus {
|
||||
background: rgba(0, 0, 0, 0.603);
|
||||
}
|
||||
.input-title{
|
||||
margin-top: 10px;
|
||||
}
|
||||
.form-button{
|
||||
padding: 10px;
|
||||
background: rgba(0, 0, 0, 0.226);
|
||||
display: table;
|
||||
transition: 0.5s;
|
||||
margin: auto;
|
||||
color: white;
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.form-button:hover{
|
||||
background: rgba(0, 0, 0, 0.534)
|
||||
}
|
||||
.alert{
|
||||
color: red;
|
||||
font-size: 15px;
|
||||
width: 220px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,457 +1,409 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<vue-headful title="Nertivia" description="Nertivia Chat Client"/>
|
||||
<div class="background-image"></div>
|
||||
<div class="layout">
|
||||
<div class="small-view-nav-bar">
|
||||
<div class="small-logo"></div>
|
||||
<div class="small-title">Nertivia</div>
|
||||
<div class="show-menu-button" @click="showMobileMenu = !showMobileMenu">
|
||||
<i class="material-icons">
|
||||
menu
|
||||
</i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panels">
|
||||
<div class="left-panel">
|
||||
|
||||
<div class="title">The best chat client that wont restrict you from important and fun features.</div>
|
||||
<img src="../assets/graphics/HomeGraphics.png" class="graphic-app" />
|
||||
<div class="change-log-mini" @click="showChangeLog = true">
|
||||
<div class="change-title">Change log <span style="font-size: 15px; color: rgba(211, 211, 211, 0.774);">Click for details</span></div>
|
||||
<div class="change-list">
|
||||
<div class="change" v-for="change in changelogFiltered" :key="change.title">
|
||||
<div class="notable-changes">{{change.shortTitle}}</div>
|
||||
<div class="change-date">{{change.date}}</div>
|
||||
<div id="app">
|
||||
<vue-headful title="Nertivia" description="Nertivia Chat Client"/>
|
||||
<div class="background-image" ref="backgroundImage"></div>
|
||||
<spinner v-if="!showPage"/>
|
||||
<div class="content" v-if="showPage">
|
||||
<transition name="fall-down" appear>
|
||||
<div class="header">
|
||||
<div class="logo"></div>
|
||||
<div class="name">Nertivia</div>
|
||||
<div class="links">
|
||||
<div class="link" @click="signupPage" v-if="!loggedIn">Sign up</div>
|
||||
<div class="link" @click="loginPage" v-if="!loggedIn">Login</div>
|
||||
<spinner class="spinner-profile" :size="50" v-if="loggedIn && !user" />
|
||||
<div class="outer-profile-picture" v-if="loggedIn && user">
|
||||
<profile-picture @click.native="showPopout = !showPopout" :hover='true' :url="avatarDomain + user.avatar" :admin="user.admin" size="40px" emoteSize="17px"/>
|
||||
</div>
|
||||
<transition name="fall-down-fast">
|
||||
<Popout v-if="user && loggedIn && showPopout" @logout="logOut" :user="user"/>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<transition name="side-in" appear>
|
||||
<div class="inner-content">
|
||||
<div
|
||||
class="title"
|
||||
>The best chat client that won't restrict you from important and fun features.</div>
|
||||
<img class="graphic" src="@/assets/graphics/HomeGraphics2.png">
|
||||
<div class="buttons">
|
||||
<div class="button" @click="openApp">Open In Browser</div>
|
||||
<!-- <div class="button" >Download App</div> -->
|
||||
</div>
|
||||
<div class="features-list">
|
||||
<div class="title">Things you can do in Nertivia</div>
|
||||
<div class="list">
|
||||
<div class="feature">
|
||||
<i class="material-icons">insert_drive_file</i>
|
||||
<div class="description">1GB per file limit, upload huge files!</div>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<i class="material-icons">face</i>
|
||||
<div class="description">Free custom gif emojis and profile picture.</div>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<i class="material-icons">storage</i>
|
||||
<div class="description">Make your own servers with channels.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="twitter-outer">
|
||||
<twitter class="twitter">
|
||||
<div slot="loading">loading .....</div>
|
||||
<a class="twitter-timeline" data-height="500" data-theme="dark" href="https://twitter.com/NertiviaApp?ref_src=twsrc%5Etfw">Tweets by NertiviaApp</a>
|
||||
</twitter>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<RightPanel :class="{'show-menu-content': showMobileMenu }" />
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
<transition name="fade">
|
||||
<ChangeLog v-if="showChangeLog"/>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { twitter } from 'vue-twitter'
|
||||
import {bus} from '../main';
|
||||
import RightPanel from "./../components/homePage/RightPanel.vue"
|
||||
import ChangeLog from "./../components/ChangeLog.vue"
|
||||
import changelog from '@/utils/changelog.js'
|
||||
import Spinner from "@/components/Spinner.vue";
|
||||
import ProfilePicture from "@/components/ProfilePictureTemplate.vue";
|
||||
import Popout from "@/components/homePage/Popout.vue";
|
||||
import AuthenticationService from "@/services/AuthenticationService.js";
|
||||
import config from '@/config.js'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
RightPanel,
|
||||
ChangeLog,
|
||||
twitter
|
||||
},
|
||||
components: { Spinner, ProfilePicture, Popout },
|
||||
data() {
|
||||
return {
|
||||
loginSelected: true,
|
||||
showMobileMenu: false,
|
||||
showChangeLog: false,
|
||||
changelog
|
||||
showPopout: false,
|
||||
showPage: false,
|
||||
loggedIn: localStorage.getItem("hauthid") || null,
|
||||
user: null,
|
||||
avatarDomain: config.domain + '/avatars/'
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
logOut() {
|
||||
localStorage.removeItem("hauthid");
|
||||
this.loggedIn = null;
|
||||
},
|
||||
loginPage() {
|
||||
window.location.href = "/login";
|
||||
},
|
||||
signupPage() {
|
||||
window.location.href = "/register";
|
||||
},
|
||||
openApp() {
|
||||
window.location.href = "/app";
|
||||
},
|
||||
async imagePreloader(srcArray) {
|
||||
srcArray.forEach(async element => {
|
||||
await wrapper(element);
|
||||
});
|
||||
function wrapper(src) {
|
||||
return new Promise(resolve => {
|
||||
const image = new Image();
|
||||
image.src = src;
|
||||
image.onload = () => resolve("done");
|
||||
});
|
||||
}
|
||||
},
|
||||
async preloadImages() {
|
||||
await this.imagePreloader([
|
||||
require("@/assets/logo.png"),
|
||||
require("@/assets/graphics/HomeGraphics2.png")
|
||||
]);
|
||||
const src = require("@/assets/background.jpg");
|
||||
const background = new Image();
|
||||
setTimeout(() => {
|
||||
background.src = src;
|
||||
background.onload = () => {
|
||||
this.$refs.backgroundImage.style.backgroundImage = `url(${
|
||||
background.src
|
||||
})`;
|
||||
this.$refs.backgroundImage.style.opacity = 0.7;
|
||||
setTimeout(() => (this.showPage = true), 500);
|
||||
};
|
||||
}, 500);
|
||||
},
|
||||
async getUser() {
|
||||
const { ok, error, result } = await AuthenticationService.user();
|
||||
if (!ok) {
|
||||
// connection error
|
||||
if (error.response === undefined) {
|
||||
setTimeout(() => {
|
||||
this.getUser();
|
||||
}, 5000);
|
||||
return;
|
||||
} else {
|
||||
localStorage.removeItem('hauthid');
|
||||
this.loggedIn = null
|
||||
}
|
||||
} else {
|
||||
this.user = result.data.user;
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
bus.$on('closeChangeLog', () => {
|
||||
this.showChangeLog = false;
|
||||
})
|
||||
},
|
||||
computed: {
|
||||
changelogFiltered() {
|
||||
return this.changelog.slice(0, 3)
|
||||
}
|
||||
}
|
||||
async mounted() {
|
||||
if (this.loggedIn) this.getUser();
|
||||
this.preloadImages();
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.twitter-outer{
|
||||
margin: auto;
|
||||
width: 600px;
|
||||
opacity: 0.8;
|
||||
transition: 0.3s;
|
||||
}
|
||||
.twitter-outer:hover{
|
||||
opacity: 1;
|
||||
}
|
||||
.fade-enter-active, .fade-leave-active {
|
||||
transition: opacity .2s;
|
||||
}
|
||||
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
|
||||
.fall-down-enter-active {
|
||||
opacity: 0;
|
||||
animation: fall-down 0.5s;
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
|
||||
#app {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
color: #383838;
|
||||
.fall-down-fast-enter-active {
|
||||
opacity: 0;
|
||||
animation: bounce-in 0.2s;
|
||||
}
|
||||
.fall-down-fast-leave-active {
|
||||
opacity: 0;
|
||||
animation: bounce-in 0.2s reverse;
|
||||
}
|
||||
|
||||
@keyframes fall-down {
|
||||
0% {
|
||||
transform: translateY(-20px);
|
||||
opacity: 0;
|
||||
}
|
||||
50% {
|
||||
transform: translateY(10px);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bounce-in {
|
||||
0% {
|
||||
transform: translateY(-20px);
|
||||
opacity: 0;
|
||||
}
|
||||
50% {
|
||||
transform: translateY(10px);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.side-in-enter-active {
|
||||
opacity: 0;
|
||||
animation: side-in 0.5s;
|
||||
animation-delay: 0.5s;
|
||||
}
|
||||
|
||||
@keyframes side-in {
|
||||
0% {
|
||||
transform: translateX(-20px);
|
||||
opacity: 0;
|
||||
}
|
||||
50% {
|
||||
transform: translateX(10px);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
button {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
#app {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
.spinner{
|
||||
margin: auto;
|
||||
padding: 30px;
|
||||
.header {
|
||||
background: rgba(0, 0, 0, 0.52);
|
||||
display: flex;
|
||||
height: 70px;
|
||||
margin: 5px;
|
||||
border-radius: 10px;
|
||||
flex-shrink: 0;
|
||||
border: 10px;
|
||||
position: relative;
|
||||
}
|
||||
.logo {
|
||||
background-image: url("../assets/logo.png");
|
||||
background-size: 100%;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.name {
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
font-size: 20px;
|
||||
margin-left: 10px;
|
||||
color: white;
|
||||
}
|
||||
.outer-profile-picture{
|
||||
user-select: none;
|
||||
z-index: 9999999;
|
||||
}
|
||||
|
||||
.background-image {
|
||||
background: url(./../assets/background.jpg);
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
z-index: -1;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: bottom;
|
||||
background-size: cover;
|
||||
|
||||
opacity: 0;
|
||||
transition: 0.5s;
|
||||
}
|
||||
|
||||
.layout{
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width:100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
.panels{
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.left-panel {
|
||||
flex: 1;
|
||||
background: rgba(0, 0, 0, 0.253);
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.loader{
|
||||
.content {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
}
|
||||
.title-panel{
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.graphics-panel{
|
||||
flex: 1;
|
||||
|
||||
.inner-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.graphic-app{
|
||||
display: table;
|
||||
margin: auto;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
width: 900px;
|
||||
height: auto;
|
||||
user-select: none;
|
||||
}
|
||||
.title{
|
||||
color: white;
|
||||
font-size: 35px;
|
||||
text-align: center;
|
||||
margin-top: 120px;
|
||||
}
|
||||
|
||||
.change-log-mini{
|
||||
background: rgba(0, 0, 0, 0.322);
|
||||
height: 150px;
|
||||
width: 640px;
|
||||
.graphic {
|
||||
width: 700px;
|
||||
height: auto;
|
||||
margin: auto;
|
||||
margin-top: 20px;
|
||||
color: white;
|
||||
margin-bottom: 50px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.change-title {
|
||||
font-size: 18px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 10px;
|
||||
margin-bottom: 0;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.change-list{
|
||||
.title {
|
||||
font-size: 25px;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
}
|
||||
.buttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 30px;
|
||||
}
|
||||
.button {
|
||||
padding: 15px;
|
||||
background: rgba(24, 132, 255, 0.733);
|
||||
border-radius: 5px;
|
||||
color: white;
|
||||
box-shadow: 3px 3px rgb(5, 86, 179);
|
||||
user-select: none;
|
||||
transition: 0.3s;
|
||||
}
|
||||
.button:hover {
|
||||
background: rgb(24, 132, 255);
|
||||
}
|
||||
.button:active {
|
||||
transform: translate(3px, 3px);
|
||||
box-shadow: 0 0 rgb(5, 86, 179);
|
||||
}
|
||||
.features-list {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.features-list .list {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.feature {
|
||||
background: rgba(0, 0, 0, 0.541);
|
||||
color: white;
|
||||
margin: 10px;
|
||||
padding: 2px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
border-radius: 10px;
|
||||
flex-shrink: 0;
|
||||
transition: 0.3s;
|
||||
}
|
||||
.feature .description {
|
||||
width: 150px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
.feature .material-icons {
|
||||
font-size: 60px;
|
||||
}
|
||||
.links {
|
||||
color: white;
|
||||
margin: auto;
|
||||
margin-right: 20px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.change {
|
||||
background: rgba(0, 0, 0, 0.335);
|
||||
width: 200px;
|
||||
height: 90px;
|
||||
margin-left: 10px;
|
||||
.link {
|
||||
padding: 5px;
|
||||
background: rgba(0, 0, 0, 0.219);
|
||||
border-radius: 5px;
|
||||
user-select: none;
|
||||
margin-left: 5px;
|
||||
transition: 0.3s;
|
||||
position: relative
|
||||
}
|
||||
.change:hover {
|
||||
background: rgba(0, 0, 0, 0.466);
|
||||
.link:hover {
|
||||
background: rgba(255, 255, 255, 0.26);
|
||||
}
|
||||
.notable-changes{
|
||||
margin: 10px;
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
.warn {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.change-date{
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
color: rgba(255, 255, 255, 0.753);
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.small-view-nav-bar{
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
background: rgba(0, 0, 0, 0.411);
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
}
|
||||
|
||||
.small-logo {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
background: url(./../assets/logo.png);
|
||||
background-size: 105%;
|
||||
background-position: center;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0px 0px 96px -4px rgba(69,212,255,1);
|
||||
margin: auto;
|
||||
margin-left: 10px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.small-title{
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
flex: 1;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.show-menu-button{
|
||||
color: rgba(255, 255, 255, 0.698);
|
||||
margin-right: 20px;
|
||||
margin-top: 7px;
|
||||
user-select: none;
|
||||
transition: 0.3s
|
||||
}
|
||||
|
||||
.show-menu-button:hover {
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
.show-menu-content {
|
||||
display: flex !important;
|
||||
width: 400px !important;
|
||||
opacity: 1 !important;
|
||||
transform: scale(1) !important;
|
||||
}
|
||||
|
||||
@media (max-width: 1051px) {
|
||||
.change:nth-child(3){
|
||||
display: none;
|
||||
}
|
||||
.change-log-mini{
|
||||
width: 430px;
|
||||
@media (max-width: 1000px) {
|
||||
.graphic {
|
||||
width: calc(100% - 30px);
|
||||
}
|
||||
}
|
||||
@media (max-width: 906px) {
|
||||
|
||||
.change:nth-child(3){
|
||||
display: block;
|
||||
}
|
||||
.change-log-mini{
|
||||
width: 640px;
|
||||
@media (max-width: 662px) {
|
||||
.feature {
|
||||
margin: 5px;
|
||||
padding: 0px;
|
||||
height: 150px;
|
||||
width: 150px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 649px) {
|
||||
.twitter-outer{
|
||||
margin-top: 20px;
|
||||
margin-bottom: 50px;
|
||||
width: initial;
|
||||
}
|
||||
.change-list{
|
||||
|
||||
@media (max-width: 465px) {
|
||||
.features-list .list {
|
||||
flex-direction: column;
|
||||
}
|
||||
.change-log-mini{
|
||||
height: initial;
|
||||
width: calc(100% - 20px);
|
||||
padding-bottom: 10px;
|
||||
margin: auto;
|
||||
.feature {
|
||||
margin: 5px;
|
||||
padding: 0px;
|
||||
height: 150px;
|
||||
width: auto;
|
||||
font-size: 15px;
|
||||
}
|
||||
.change{
|
||||
margin-bottom: 5px;
|
||||
margin-left: 5px;
|
||||
margin-right: 0;
|
||||
width: calc(100% - 10px);
|
||||
}
|
||||
}
|
||||
@media (max-width: 1380px) {
|
||||
.graphic-app{
|
||||
width: calc(100% - 80px);
|
||||
}
|
||||
.title{
|
||||
font-size: 30px;
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
|
||||
}
|
||||
}
|
||||
@media (max-width: 906px) {
|
||||
.right-panel-home {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
top: 50px;
|
||||
display: flex;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
height:calc(100% - 50px);
|
||||
background-color: rgb(34, 34, 34);
|
||||
width: 0;
|
||||
overflow-x: hidden;
|
||||
transition: 0.5s ease;
|
||||
transform: scale(0.97);
|
||||
opacity: 0;
|
||||
|
||||
}
|
||||
.right-panel-inner{
|
||||
width: 400px;
|
||||
}
|
||||
.small-view-nav-bar{
|
||||
display: flex;
|
||||
}
|
||||
|
||||
}
|
||||
@media (max-width: 401px) {
|
||||
.show-menu-content {
|
||||
width: 100% !important;
|
||||
}
|
||||
.right-panel-inner{
|
||||
.feature .description {
|
||||
margin-top: 15px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<!-- Used for forms !-->
|
||||
<style>
|
||||
@media (max-width: 1380px) {
|
||||
.graphic-app{
|
||||
width: calc(100% - 80px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 906px) {
|
||||
|
||||
|
||||
|
||||
.right-panel-home {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
top: 50px;
|
||||
display: flex;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
height:calc(100% - 50px);
|
||||
background-color: rgba(34, 34, 34, 0.877);
|
||||
width: 0;
|
||||
overflow-x: hidden;
|
||||
transition: 0.5s ease;
|
||||
transform: scale(0.97);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.right-panel-inner{
|
||||
width: 400px;
|
||||
}
|
||||
.small-view-nav-bar{
|
||||
display: flex;
|
||||
}
|
||||
|
||||
}
|
||||
@media (max-width: 401px) {
|
||||
.show-menu-content {
|
||||
width: 100% !important;
|
||||
}
|
||||
.right-panel-inner{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.form {
|
||||
color: white;
|
||||
margin: auto;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
input{
|
||||
padding: 10px;
|
||||
background: rgba(0, 0, 0, 0.301);
|
||||
outline: none;
|
||||
border: none;
|
||||
color: white;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 10px;
|
||||
width: 200px;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
input:hover{
|
||||
background: rgba(0, 0, 0, 0.452);
|
||||
}
|
||||
|
||||
input:focus {
|
||||
background: rgba(0, 0, 0, 0.603);
|
||||
}
|
||||
.input-title{
|
||||
margin-top: 10px;
|
||||
}
|
||||
.form-button{
|
||||
padding: 10px;
|
||||
background: rgba(0, 0, 0, 0.226);
|
||||
display: table;
|
||||
transition: 0.5s;
|
||||
margin: auto;
|
||||
color: white;
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.form-button:hover{
|
||||
background: rgba(0, 0, 0, 0.534)
|
||||
}
|
||||
.alert{
|
||||
color: red;
|
||||
font-size: 15px;
|
||||
width: 220px;
|
||||
body {
|
||||
background: rgb(46, 37, 49);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
372
src/views/LoginPage.vue
Normal file
372
src/views/LoginPage.vue
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<div class="app-content">
|
||||
<header-login v-on:isDay="isDayEvent"/>
|
||||
<div class="content">
|
||||
<transition appear name="fade-up">
|
||||
<div class="box" v-if="visible">
|
||||
<div class="title">
|
||||
<i class="material-icons">account_circle</i>
|
||||
Login
|
||||
</div>
|
||||
<div class="info">Login to access Nertivia</div>
|
||||
<form action="#" @submit.prevent="submitForm" v-if="!showCaptcha">
|
||||
<div class="input">
|
||||
<div class="input-text">
|
||||
Email
|
||||
<span class="error" v-if="email.alert">- {{email.alert}}</span>
|
||||
</div>
|
||||
<input type="email" v-model="email.value" placeholder="Email">
|
||||
</div>
|
||||
<div class="input">
|
||||
<div class="input-text">
|
||||
Password
|
||||
<span class="error" v-if="password.alert">- {{password.alert}}</span>
|
||||
</div>
|
||||
<input
|
||||
type="password"
|
||||
v-model="password.value"
|
||||
autocomplete="password"
|
||||
placeholder="Password"
|
||||
>
|
||||
</div>
|
||||
|
||||
<span class="error" style="text-align: center;" v-if="otherError">{{otherError}}</span>
|
||||
<div class="buttons">
|
||||
<button type="submit" :class="{button: true, deactive: deactive}">Login</button>
|
||||
<button class="button register-button" @click.prevent="registerButton">I'm new!</button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="captcha-box" v-if="showCaptcha">
|
||||
<div class="input captcha-input">
|
||||
<div class="input-text">
|
||||
Beep Boop
|
||||
<span class="error" v-if="reCaptcha.alert">- {{reCaptcha.alert}}</span>
|
||||
</div>
|
||||
<div class="captcha">
|
||||
<Recaptcha ref="recaptcha" @verify="captchaSubmit"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
<div class="background">
|
||||
<div :class="{background: true, 'night-background': true, chosen: !isDay}"><particlesJS class="particles"/></div>
|
||||
<div class="background day-background"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Recaptcha from "@/components/Recaptcha.vue";
|
||||
import HeaderLogin from "@/components/HeaderLoginTemplate.vue";
|
||||
import AuthenticationService from "@/services/AuthenticationService";
|
||||
import particlesJS from "@/components/ParticlesJS.vue";
|
||||
export default {
|
||||
components: { HeaderLogin, Recaptcha, particlesJS },
|
||||
data() {
|
||||
return {
|
||||
showCaptcha: false,
|
||||
visible: true,
|
||||
email: { value: "", alert: "" },
|
||||
password: { value: "", alert: "" },
|
||||
reCaptcha: { alert: "" },
|
||||
otherError: "",
|
||||
|
||||
captchaToken: "",
|
||||
isDay: true,
|
||||
deactive: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
resetValues() {
|
||||
// Resets all of the alert values
|
||||
this.email.alert = "";
|
||||
this.password.alert = "";
|
||||
this.reCaptcha.alert = "";
|
||||
this.otherError = "";
|
||||
},
|
||||
isDayEvent(data) {
|
||||
this.isDay = data;
|
||||
},
|
||||
captchaSubmit(token) {
|
||||
this.captchaToken = token;
|
||||
this.login();
|
||||
},
|
||||
submitForm() {
|
||||
this.showCaptcha = true;
|
||||
},
|
||||
async login() {
|
||||
if (this.deactive === true) return;
|
||||
this.resetValues();
|
||||
const email = this.email.value.trim();
|
||||
const password = this.password.value.trim();
|
||||
const captcha = this.captchaToken;
|
||||
|
||||
this.deactive = true;
|
||||
|
||||
const { ok, error, result } = await AuthenticationService.login({
|
||||
email,
|
||||
password,
|
||||
token: captcha
|
||||
});
|
||||
|
||||
if (ok) {
|
||||
this.visible = false;
|
||||
this.$store.dispatch("token", result.data.token);
|
||||
setTimeout(_ => {
|
||||
window.location.href = "/app";
|
||||
}, 1000);
|
||||
} else {
|
||||
this.showCaptcha = false
|
||||
this.deactive = false;
|
||||
this.captchaToken = null;
|
||||
this.$refs.recaptcha.resetRecaptcha();
|
||||
if (error.response === undefined) {
|
||||
this.otherError = "Can't connect to server.";
|
||||
return;
|
||||
}
|
||||
const errors = error.response.data.errors;
|
||||
for (let index in errors) {
|
||||
const message = errors[index].msg;
|
||||
const param = errors[index].param;
|
||||
if (this[param] === undefined) {
|
||||
this.otherError = message;
|
||||
} else {
|
||||
this[param].alert = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
registerButton() {
|
||||
this.$router.push("/register");
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.fade-up-enter-active {
|
||||
opacity: 0;
|
||||
animation: bounce-in 0.5s;
|
||||
animation-delay: 0.7s;
|
||||
}
|
||||
.fade-up-leave-active {
|
||||
animation: bounce-in 0.5s reverse;
|
||||
}
|
||||
|
||||
@keyframes bounce-in {
|
||||
0% {
|
||||
transform: translateX(30px);
|
||||
opacity: 0;
|
||||
}
|
||||
50% {
|
||||
transform: translateX(-10px);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* .fade-up-enter-active, .fade-up-leave-active {
|
||||
transition: .5s;
|
||||
transition-delay: 0.5s
|
||||
}
|
||||
.fade-up-enter, .fade-up-leave-to /* .fade-leave-active {
|
||||
opacity: 0;
|
||||
transform: translateX(20px)
|
||||
} */
|
||||
|
||||
#app {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transition: background 10s;
|
||||
color: white;
|
||||
}
|
||||
.app-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
z-index: 9999;
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
.background {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
transition: background 10s;
|
||||
|
||||
}
|
||||
|
||||
.night-background {
|
||||
opacity: 0;
|
||||
transition: 10s;
|
||||
background: linear-gradient(to bottom, #000000 0%,#606060 100%) !important;
|
||||
}
|
||||
.day-background {
|
||||
opacity: 1;
|
||||
background: linear-gradient(to bottom, #165dc0 0%,#5482bf 100%);
|
||||
z-index: -1
|
||||
}
|
||||
|
||||
.night-background.chosen {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.night-background .particles {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
margin: 10px;
|
||||
}
|
||||
.box {
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
background: rgba(44, 44, 44, 0.774);
|
||||
margin: auto;
|
||||
margin-top: 20px;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
.box .title {
|
||||
text-align: center;
|
||||
font-size: 25px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 5px;
|
||||
color: white;
|
||||
user-select: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 60px;
|
||||
}
|
||||
.box .title .material-icons {
|
||||
margin-right: 5px;
|
||||
font-size: 40px;
|
||||
}
|
||||
.info {
|
||||
text-align: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
.input {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 10px;
|
||||
width: 80%;
|
||||
align-self: center;
|
||||
background: rgb(59, 59, 59);
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.input-text {
|
||||
margin-bottom: 5px;
|
||||
margin-left: 3px;
|
||||
}
|
||||
input {
|
||||
outline: none;
|
||||
padding: 10px;
|
||||
border: solid 1px rgba(0, 0, 0, 0);
|
||||
background: none;
|
||||
border-radius: 5px;
|
||||
background: rgb(36, 36, 36);
|
||||
color: white;
|
||||
}
|
||||
.buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
justify-items: center;
|
||||
}
|
||||
.button {
|
||||
padding: 10px;
|
||||
background: rgba(25, 151, 255, 0.699);
|
||||
border-radius: 5px;
|
||||
margin: 10px;
|
||||
margin-top: 10px;
|
||||
user-select: none;
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 17px;
|
||||
outline: none;
|
||||
transition: 0.2s;
|
||||
box-shadow: 3px 3px rgba(23, 112, 255, 0.479);
|
||||
}
|
||||
.button:hover {
|
||||
background: rgb(25, 151, 255);
|
||||
}
|
||||
.button:focus {
|
||||
background: rgb(25, 151, 255);
|
||||
}
|
||||
.button:active {
|
||||
background: rgb(25, 151, 255);
|
||||
transform: translate(3px, 3px);
|
||||
box-shadow: 0px 0px rgba(0, 97, 207, 0.479);
|
||||
}
|
||||
|
||||
.button.deactive {
|
||||
background: rgba(70, 70, 70, 0.699);
|
||||
box-shadow: 3px 3px rgba(0, 0, 0, 0.479);
|
||||
}
|
||||
|
||||
.button.deactive :hover {
|
||||
background: rgba(70, 70, 70, 0.699);
|
||||
}
|
||||
.button.deactive :focus {
|
||||
background: rgba(70, 70, 70, 0.699);
|
||||
}
|
||||
.button.deactive:active {
|
||||
background: rgba(70, 70, 70, 0.699);
|
||||
transform: translate(3px, 3px);
|
||||
box-shadow: 0px 0px rgba(0, 0, 0, 0.479);
|
||||
}
|
||||
|
||||
.register-button {
|
||||
background: #2ecc70ab;
|
||||
box-shadow: 3px 3px #0f7e3d;
|
||||
}
|
||||
.register-button.button:hover {
|
||||
background: #2ecc71;
|
||||
}
|
||||
.register-button.button:focus {
|
||||
background: #2ecc71;
|
||||
}
|
||||
.register-button.button:active {
|
||||
background: #2ecc71;
|
||||
transform: translate(3px, 3px);
|
||||
box-shadow: 0px 0px #0f7e3d;
|
||||
}
|
||||
|
||||
.captcha-input {
|
||||
width: initial;
|
||||
}
|
||||
.captcha {
|
||||
opacity: 0.7;
|
||||
transition: 0.3s;
|
||||
}
|
||||
.captcha:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
383
src/views/RegisterPage.vue
Normal file
383
src/views/RegisterPage.vue
Normal file
|
|
@ -0,0 +1,383 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<div class="app-content">
|
||||
<header-login v-on:isDay="isDayEvent"/>
|
||||
<div class="content">
|
||||
<transition appear name="fade-up">
|
||||
<div class="box" v-if="visible">
|
||||
<div class="title">
|
||||
<i class="material-icons">account_circle</i>
|
||||
Register
|
||||
</div>
|
||||
<div class="info">Welcome, new user! Hope you enjoy Nertivia!</div>
|
||||
<form action="#" @submit.prevent="formSubmit" v-if="!showCaptcha">
|
||||
<div class="input">
|
||||
<div class="input-text">
|
||||
Email
|
||||
<span class="error" v-if="email.alert">- {{email.alert}}</span>
|
||||
</div>
|
||||
<input type="email" v-model="email.value" placeholder="Email" autocomplete="off">
|
||||
</div>
|
||||
|
||||
<div class="input">
|
||||
<div class="input-text">
|
||||
Username
|
||||
<span class="error" v-if="username.alert">- {{username.alert}}</span>
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
v-model="username.value"
|
||||
placeholder="Username"
|
||||
autocomplete="off"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="input">
|
||||
<div class="input-text">
|
||||
Password
|
||||
<span class="error" v-if="password.alert">- {{password.alert}}</span>
|
||||
</div>
|
||||
<input
|
||||
type="password"
|
||||
v-model="password.value"
|
||||
autocomplete="off"
|
||||
placeholder="Password"
|
||||
>
|
||||
</div>
|
||||
<span class="error" style="text-align: center;" v-if="otherError">{{otherError}}</span>
|
||||
<div class="buttons">
|
||||
<button type="submit" :class="{button: true, deactive: deactive}">Register</button>
|
||||
<button
|
||||
class="button register-button"
|
||||
@click.prevent="loginButton"
|
||||
>I'm already a user!</button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="captcha-box" v-if="showCaptcha">
|
||||
<div class="input captcha-input">
|
||||
<div class="input-text">Beep Boop</div>
|
||||
<div class="captcha">
|
||||
<Recaptcha ref="recaptcha" @verify="captchaSubmit"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
<div class="background">
|
||||
<div :class="{background: true, 'night-background': true, chosen: !isDay}"><particlesJS class="particles"/></div>
|
||||
<div class="background day-background"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Recaptcha from "@/components/Recaptcha.vue";
|
||||
import HeaderLogin from "@/components/HeaderLoginTemplate.vue";
|
||||
import AuthenticationService from "@/services/AuthenticationService";
|
||||
import particlesJS from "@/components/ParticlesJS.vue";
|
||||
export default {
|
||||
components: { HeaderLogin, Recaptcha, particlesJS },
|
||||
data() {
|
||||
return {
|
||||
showCaptcha: false,
|
||||
visible: true,
|
||||
email: { value: "", alert: "" },
|
||||
username: { value: "", alert: "" },
|
||||
password: { value: "", alert: "" },
|
||||
otherError: "",
|
||||
|
||||
captchaToken: "",
|
||||
isDay: true,
|
||||
deactive: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
resetValues() {
|
||||
// Resets all of the alert values
|
||||
this.email.alert = "";
|
||||
this.username.alert = "";
|
||||
this.password.alert = "";
|
||||
this.otherError = "";
|
||||
},
|
||||
isDayEvent(data) {
|
||||
this.isDay = data;
|
||||
},
|
||||
captchaSubmit(token) {
|
||||
this.captchaToken = token;
|
||||
this.register();
|
||||
},
|
||||
formSubmit() {
|
||||
this.showCaptcha = true;
|
||||
},
|
||||
async register() {
|
||||
this.resetValues();
|
||||
const email = this.email.value.trim();
|
||||
const username = this.username.value.trim();
|
||||
const password = this.password.value.trim();
|
||||
|
||||
|
||||
const { ok, error, result } = await AuthenticationService.register({
|
||||
email,
|
||||
username,
|
||||
password,
|
||||
token: this.captchaToken
|
||||
});
|
||||
if (ok) {
|
||||
this.visible = false;
|
||||
this.$store.dispatch("token", result.data.token);
|
||||
setTimeout(_ => {
|
||||
window.location.href = "/app";
|
||||
}, 1000);
|
||||
} else {
|
||||
this.showCaptcha = false
|
||||
this.deactive = false;
|
||||
this.captchaToken = null;
|
||||
this.$refs.recaptcha.resetRecaptcha();
|
||||
if (error.response === undefined) {
|
||||
this.otherError = "Can't connect to server.";
|
||||
return;
|
||||
}
|
||||
const errors = error.response.data.errors;
|
||||
for (let index in errors) {
|
||||
const message = errors[index].msg;
|
||||
const param = errors[index].param;
|
||||
if (this[param] === undefined) {
|
||||
this.otherError = message;
|
||||
} else {
|
||||
this[param].alert = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
loginButton() {
|
||||
this.$router.push("/login");
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.fade-up-enter-active {
|
||||
opacity: 0;
|
||||
animation: bounce-in 0.5s;
|
||||
animation-delay: 0.7s;
|
||||
}
|
||||
.fade-up-leave-active {
|
||||
animation: bounce-in 0.5s reverse;
|
||||
}
|
||||
|
||||
@keyframes bounce-in {
|
||||
0% {
|
||||
transform: translateX(30px);
|
||||
opacity: 0;
|
||||
}
|
||||
50% {
|
||||
transform: translateX(-10px);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* .fade-up-enter-active, .fade-up-leave-active {
|
||||
transition: .5s;
|
||||
transition-delay: 0.5s
|
||||
}
|
||||
.fade-up-enter, .fade-up-leave-to /* .fade-leave-active {
|
||||
opacity: 0;
|
||||
transform: translateX(20px)
|
||||
} */
|
||||
|
||||
#app {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transition: background 10s;
|
||||
color: white;
|
||||
}
|
||||
.app-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
z-index: 9999;
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
.background {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
transition: background 10s;
|
||||
|
||||
}
|
||||
|
||||
.night-background {
|
||||
opacity: 0;
|
||||
transition: 10s;
|
||||
background: linear-gradient(to bottom, #000000 0%,#606060 100%) !important;
|
||||
}
|
||||
.day-background {
|
||||
opacity: 1;
|
||||
background: linear-gradient(to bottom, #165dc0 0%,#5482bf 100%);
|
||||
z-index: -1
|
||||
}
|
||||
|
||||
.night-background.chosen {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.night-background .particles {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
margin: 10px;
|
||||
}
|
||||
.box {
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
background: rgba(44, 44, 44, 0.774);
|
||||
margin: auto;
|
||||
margin-top: 20px;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
.box .title {
|
||||
text-align: center;
|
||||
font-size: 25px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 5px;
|
||||
color: white;
|
||||
user-select: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 60px;
|
||||
}
|
||||
.box .title .material-icons {
|
||||
margin-right: 5px;
|
||||
font-size: 40px;
|
||||
}
|
||||
.info {
|
||||
text-align: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
.input {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 10px;
|
||||
width: 80%;
|
||||
align-self: center;
|
||||
background: rgb(59, 59, 59);
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.input-text {
|
||||
margin-bottom: 5px;
|
||||
margin-left: 3px;
|
||||
}
|
||||
input {
|
||||
outline: none;
|
||||
padding: 10px;
|
||||
border: solid 1px rgba(0, 0, 0, 0);
|
||||
background: none;
|
||||
border-radius: 5px;
|
||||
background: rgb(36, 36, 36);
|
||||
color: white;
|
||||
}
|
||||
.buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
justify-items: center;
|
||||
}
|
||||
.button {
|
||||
padding: 10px;
|
||||
background: rgba(25, 151, 255, 0.699);
|
||||
border-radius: 5px;
|
||||
margin: 10px;
|
||||
margin-top: 10px;
|
||||
user-select: none;
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 17px;
|
||||
outline: none;
|
||||
transition: 0.2s;
|
||||
box-shadow: 3px 3px rgba(23, 112, 255, 0.479);
|
||||
}
|
||||
.button:hover {
|
||||
background: rgb(25, 151, 255);
|
||||
}
|
||||
.button:focus {
|
||||
background: rgb(25, 151, 255);
|
||||
}
|
||||
.button:active {
|
||||
background: rgb(25, 151, 255);
|
||||
transform: translate(3px, 3px);
|
||||
box-shadow: 0px 0px rgba(0, 97, 207, 0.479);
|
||||
}
|
||||
|
||||
.button.deactive {
|
||||
background: rgba(70, 70, 70, 0.699);
|
||||
box-shadow: 3px 3px rgba(0, 0, 0, 0.479);
|
||||
}
|
||||
|
||||
.button.deactive :hover {
|
||||
background: rgba(70, 70, 70, 0.699);
|
||||
}
|
||||
.button.deactive :focus {
|
||||
background: rgba(70, 70, 70, 0.699);
|
||||
}
|
||||
.button.deactive:active {
|
||||
background: rgba(70, 70, 70, 0.699);
|
||||
transform: translate(3px, 3px);
|
||||
box-shadow: 0px 0px rgba(0, 0, 0, 0.479);
|
||||
}
|
||||
|
||||
.register-button {
|
||||
background: #2ecc70ab;
|
||||
box-shadow: 3px 3px #0f7e3d;
|
||||
}
|
||||
.register-button.button:hover {
|
||||
background: #2ecc71;
|
||||
}
|
||||
.register-button.button:focus {
|
||||
background: #2ecc71;
|
||||
}
|
||||
.register-button.button:active {
|
||||
background: #2ecc71;
|
||||
transform: translate(3px, 3px);
|
||||
box-shadow: 0px 0px #0f7e3d;
|
||||
}
|
||||
|
||||
.captcha-input {
|
||||
width: initial;
|
||||
}
|
||||
.captcha {
|
||||
opacity: 0.7;
|
||||
transition: 0.3s;
|
||||
}
|
||||
.captcha:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in a new issue