3 Commits 270f10d72d ... bdeccc6080

Author SHA1 Message Date
  Ecconia bdeccc6080 Adding application form WIP 7 years ago
  Ecconia eb6d9982f6 Fixing typo in description 7 years ago
  Ecconia 19ffef0261 Saving user-object and restoring it + logout button 7 years ago

+ 1 - 1
public/index.html

@@ -5,7 +5,7 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width,initial-scale=1.0">
     <meta name="viewport" content="width=device-width,initial-scale=1.0">
     <meta name="theme-color" content="#111111">
     <meta name="theme-color" content="#111111">
-    <meta name="Description" content="Website of the RedstoneServer. You can create your applications here to be come member. Chat with other members and see who else plays on this server.">
+    <meta name="Description" content="Website of the RedstoneServer. You can create your applications here to become member. Chat with other members and see who else plays on this server.">
     <link rel="icon" href="<%= BASE_URL %>favicon.ico">
     <link rel="icon" href="<%= BASE_URL %>favicon.ico">
     <title>New RS-Website</title>
     <title>New RS-Website</title>
   </head>
   </head>

+ 9 - 2
src/App.vue

@@ -11,7 +11,8 @@
 
 
 			<div class="user">
 			<div class="user">
 				<div v-if="user">
 				<div v-if="user">
-					<span>Username: {{ user.username }}</span>
+					<span>Username: {{ user.username }} </span>
+					<span class="rl" @click="logout">Logout</span>
 				</div>
 				</div>
 				<router-link class="rl" to="/login" v-else>Login</router-link>
 				<router-link class="rl" to="/login" v-else>Login</router-link>
 			</div>
 			</div>
@@ -45,6 +46,12 @@
 			},
 			},
 		},
 		},
 
 
+		methods: {
+			logout() {
+				this.core.logout()
+			}
+		},
+
 		components: {
 		components: {
 			MenuContainer
 			MenuContainer
 		},
 		},
@@ -86,7 +93,7 @@
 	}
 	}
 
 
 	header .user {
 	header .user {
-		padding: 0.2em 1em;
+		padding: 0.2em 0em;
 	}
 	}
 
 
 	.content {
 	.content {

+ 61 - 0
src/components/SimpleProgressBar.vue

@@ -0,0 +1,61 @@
+<template>
+	<div>
+		<div class="background">
+			<div class="bar" ref="bar"/>
+		</div>
+	</div>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+			}
+		},
+		props: [
+			'count',
+			'max',
+			'steps',
+		],
+		methods: {
+			update: function () {
+				let per = this.count / this.max * 100
+				let bar = this.$refs.bar;
+
+				//Break down into steps.
+				per = Math.floor(per / this.stepsize) * this.stepsize
+
+				bar.style.width = per + '%'
+				bar.style.backgroundColor = per >= 100 ? '#0f0' : '#f00'
+			},
+		},
+		computed: {
+			stepsize() {
+				return 100 / this.steps
+			}
+		},
+		watch: {
+			count: function () {
+				this.update()
+			},
+		}
+	}
+</script>
+
+<style scoped>
+	.bar {
+		height: 3px;
+		min-width: 1%;
+		width: 0%;
+		max-width: 100%;
+		background-color: #f00;
+		transition: width 200ms ease-out;
+	}
+
+	.background {
+		height: 3px;
+		width: 100%;
+		max-width: 60em;
+		background-color: #aaa;
+	}
+</style>

+ 64 - 0
src/components/inputtypes/LimitedTextField.vue

@@ -0,0 +1,64 @@
+<template>
+	<div class="width">
+		<textarea v-bind:class="{ textarea: true, not_enough: highlight && !isEnough, enough: highlight && isEnough }" type="text" v-model="inputText" />
+		<SimpleProgressBar class="progbar" :count="len" max="50" steps="5"/>
+	</div>
+</template>
+
+<script>
+	import SimpleProgressBar from '../SimpleProgressBar.vue'
+
+	export default {
+		data() {
+			return {
+				inputText: '',
+			}
+		},
+
+		props: [
+			'highlight'
+		],
+
+		computed: {
+			isEnough() {
+				return this.inputText.length >= 50
+			},
+			len() {
+				return this.inputText.length
+			}
+		},
+
+		mounted() {
+		},
+
+		components: {
+			SimpleProgressBar,
+		},
+	}
+</script>
+
+<style scoped>
+	.textarea {
+		width: 100%;
+		color: #fff;
+		resize: vertical;
+		min-height: 1.2em;
+		height: 1.2em;
+		border: 1px solid #aaa;
+		margin: auto;
+		background-color: #222;
+	}
+
+	.not_enough {
+		border: 1px solid #f00;
+	}
+
+	.enough {
+		border: 1px solid #0f0;	
+	}
+
+	.width {
+		width: 100%;
+		max-width: 60em;
+	}
+</style>

+ 12 - 0
src/main.js

@@ -9,6 +9,18 @@ Vue.config.productionTip = true
 const core = new Core(store)
 const core = new Core(store)
 Vue.prototype.core = core
 Vue.prototype.core = core
 
 
+//Update Vuex if localstorage loginstate changed.
+router.beforeEach((from, to, next) => {
+	let user = localStorage.getItem('user')
+	let originalUser = store.state.user
+
+	if(!(user === null && originalUser === null) && (user === null || originalUser === null || user != JSON.stringify(originalUser))) {
+		core.commit('setUser', JSON.parse(user))
+	}
+
+	next()
+})
+
 new Vue({
 new Vue({
   router,
   router,
   store,
   store,

+ 5 - 1
src/router.js

@@ -19,6 +19,10 @@ export default new Router({
 			path: '/login',
 			path: '/login',
 			component: load('Login'),
 			component: load('Login'),
 		},
 		},
+		{
+			path: '/create',
+			component: load('CreateApplication'),
+		},
 		{
 		{
 			path: '/impressum',
 			path: '/impressum',
 			component: load('Impressum')
 			component: load('Impressum')
@@ -42,5 +46,5 @@ export default new Router({
 			path: '*',
 			path: '*',
 			component: load('NotFound')
 			component: load('NotFound')
 		},
 		},
-	]
+	],
 })
 })

+ 7 - 11
src/scripts/core.js

@@ -33,22 +33,18 @@ export default class {
 				})
 				})
 	}
 	}
 
 
-	lol(username, password) {
-		//TODO: return promise somehow
-		//alert('Login attempt as user \'' + username + '\' with password \'' + password + '\'')
-
-		/*
-		this.get('/soos')
-			.then(function (response) {
-				console.log('Response: ', response.data)
-			})
-		*/
+	logout() {
+		localStorage.removeItem('user');
+			this.commit('setUser', null)
+	}
 
 
+	login(username, password) {
+		//TODO: return promise somehow
 		this.post('/login', {
 		this.post('/login', {
 			username: username,
 			username: username,
 			password: password,
 			password: password,
 		}).then((response) => {
 		}).then((response) => {
-			console.log('Response: ', response.data)
+			localStorage.setItem('user', JSON.stringify(response.data));
 			this.commit('setUser', response.data)
 			this.commit('setUser', response.data)
 		})
 		})
 	}
 	}

+ 1 - 1
src/views/Applications.vue

@@ -4,7 +4,7 @@
 		<p>This area is basically the first big GOAL of the final product. Creating and Judging apps. The path to get here is quite long though, many other issues have to be solved first.</p>
 		<p>This area is basically the first big GOAL of the final product. Creating and Judging apps. The path to get here is quite long though, many other issues have to be solved first.</p>
 
 
 		<div v-if="getUser && getUser.rank === undefined">
 		<div v-if="getUser && getUser.rank === undefined">
-			<router-link to="/myapp" v-if="getUser.appstate === 0">Create application.</router-link>
+			<router-link to="/create" v-if="getUser.appstate === 0">Create application.</router-link>
 			<router-link to="/myapp" v-else-if="getUser.appstate === 1">Edit application.</router-link>
 			<router-link to="/myapp" v-else-if="getUser.appstate === 1">Edit application.</router-link>
 		</div>
 		</div>
 
 

+ 64 - 0
src/views/CreateApplication.vue

@@ -0,0 +1,64 @@
+<template>
+	<div>
+		<h1>Create application</h1>
+		<div v-if="user">
+			<span>{{ instruction }}</span>
+			<div class="question_block" v-for="(element, index) in pattern" :key="index">
+				<span class="question">{{ element.text }}</span>
+				<span v-if="element.optional"> (Optional)</span>
+				<br>
+				<LimitedTextField class="textfield" :highlight="highlight"></LimitedTextField>
+				<span class="hint">{{ element.hint }}</span>
+			</div>
+			<button @click="update">Create/Update</button>
+		</div>
+		<span v-else>You are not logged in.</span>
+	</div>
+</template>
+
+<script>
+	import LimitedTextField from '../components/inputtypes/LimitedTextField.vue'
+
+	export default {
+		data () {
+			return {
+				instruction: '',
+				pattern: null,
+				highlight: false,
+			}
+		},
+		created () {
+			this.core.get('/app-pattern').then((response) => {
+				this.instruction = response.data.instruction;
+				this.pattern = response.data.fields;
+			})
+		},
+		computed: {
+			user() {
+				return this.$store.state.user
+			},
+		},
+		methods: {
+			update() {
+				this.highlight = true
+			},
+		},
+		components: {
+			LimitedTextField,
+		},
+	}
+</script>
+
+<style scoped>
+	.question_block {
+		margin: 1em;
+	}
+
+	.question {
+		font-weight: bold;
+	}
+
+	.hint {
+		font-size: 0.7em;
+	}
+</style>

+ 2 - 1
src/views/Login.vue

@@ -16,6 +16,7 @@
 </template>
 </template>
 
 
 <script>
 <script>
+	//TODO: Check username for allowed chars and length.
 	export default {
 	export default {
 		data() {
 		data() {
 			return {
 			return {
@@ -61,7 +62,7 @@
 				return false
 				return false
 			},
 			},
 			attemptLogin() {
 			attemptLogin() {
-				this.core.lol(this.username, this.password)
+				this.core.login(this.username, this.password)
 			},
 			},
 		}
 		}
 	}
 	}