7 Commity bdeccc6080 ... d177e4c87c

Autor SHA1 Wiadomość Data
  Ecconia d177e4c87c Merge branch 'Enhancement|Menubar2' 7 lat temu
  Ecconia efd4e3428f Upgrading Navigation-Bar 7 lat temu
  Ecconia 3d321fd60b App input text field default height 7 lat temu
  Ecconia e5e35b953f FIx: focus was undefined when logged in 7 lat temu
  Ecconia 9f1cfa71ff Moving whole header in its own component 7 lat temu
  Ecconia 9db90afcaa Switching to computed style 7 lat temu
  Ecconia 2a370b0100 Adding more input types for application form 7 lat temu

+ 7 - 53
src/App.vue

@@ -1,33 +1,16 @@
 <template>
 	<div id="app">
-		<header>
-			<div class="logo">
-				<span>RedstoneServer</span>
-			</div>
+		<HeaderBar />
 
-			<MenuContainer class="menu-container">
-				<router-link class="top-link" :to="link" v-for="(link, text) in menu_entries" :key="link">{{ text }}</router-link>
-			</MenuContainer>
-
-			<div class="user">
-				<div v-if="user">
-					<span>Username: {{ user.username }} </span>
-					<span class="rl" @click="logout">Logout</span>
-				</div>
-				<router-link class="rl" to="/login" v-else>Login</router-link>
-			</div>
-		</header>
-
-		<p>Website under development, please excuse ugly style and broken/missing features as well as missing legal things.</p>
 		<div class="content">
+			<p>Website under development, please excuse ugly style and broken/missing features as well as missing legal things.</p>
 			<router-view/>
 		</div>
-		<router-link to="/impressum">Impressum</router-link>
 	</div>
 </template>
 
 <script>
-	import MenuContainer from './components/MenuContainer.vue'
+	import HeaderBar from './components/HeaderBar.vue'
 
 	export default {
 		data () {
@@ -53,7 +36,7 @@
 		},
 
 		components: {
-			MenuContainer
+			HeaderBar
 		},
 	}
 </script>
@@ -64,6 +47,7 @@
 		background-color: #111;
 		color: #aaa;
 		margin: 0;
+		-webkit-tap-highlight-color: #f0ff;
 	}
 
 	body a:link {
@@ -71,44 +55,14 @@
 	}
 
 	body a:visited {
-		color: #666;
+		/color: #666;
+		color: #ddd;
 	}
 </style>
 
 <style scoped>
-	header {
-		font-size: 1.5em;
-		color: #aaa;
-		background-color: #222;
-		display: flex;
-	}
-
-	header .logo {
-		display: inline-block;
-	}
-
-	header .menu-container {
-		flex-grow: 100;
-		box-sizing: border-box;
-	}
-
-	header .user {
-		padding: 0.2em 0em;
-	}
-
 	.content {
 		margin-left: 8px;
 		margin-right: 8px;
 	}
-
-	.rl {
-		text-decoration: none;
-		color: #aaa;
-		padding: 0.2em 1em;
-	}
-
-	.rl:hover {
-		color: #ddd;
-		background-color: #333;
-	}
 </style>

+ 27 - 0
src/components/ApplicationInputSwitch.vue

@@ -0,0 +1,27 @@
+<template>
+	<div>
+		<LimitedTextField v-if="type === 'text-box-limited'" :highlight="highlight"/>
+		<TextField v-else-if="type === 'text-box'" />
+		<LineInput v-else-if="type === 'line'" />
+
+		<span v-else>= OOPS, this input type '{{ type }}' has to be implemented.</span>
+	</div>
+</template>
+
+<script>
+	import LimitedTextField from './inputtypes/LimitedTextField.vue'
+	import TextField from './inputtypes/TextField.vue'
+	import LineInput from './inputtypes/LineInput.vue'
+
+	export default {
+		props: [
+			'type',
+			'highlight',
+		],
+		components: {
+			LimitedTextField,
+			TextField,
+			LineInput,
+		},
+	}
+</script>

+ 197 - 0
src/components/HeaderBar.vue

@@ -0,0 +1,197 @@
+<template>
+	<header>
+		<div class="logo">
+			<span>RedstoneServer</span>
+		</div>
+
+		<nav ref="navigation">
+			<div class="topbar" ref="topbar">
+				<router-link class="t_link link" :to="element.val" v-for="element in primary" :key="element.key">{{ element.key }}</router-link>
+			</div>
+			<div class="wrapper">
+				<span class="t_link_d t_link link" ref="dropdownArrow">VV</span>
+				<div class="dropdown">
+					<router-link class="d_link link" :to="element.val" v-for="element in secondary" :key="element.key">{{ element.key }}</router-link>
+				</div>
+			</div>
+		</nav>
+
+		<div class="user">
+			<div v-if="user">
+				<span>Username: {{ user.username }} </span>
+				<span class="link" @click="logout">Logout</span>
+			</div>
+			<router-link class="link" to="/login" v-else>Login</router-link>
+		</div>
+	</header>
+</template>
+
+<script>
+	export default {
+		data () {
+			return {
+				links: {
+					primary: {
+						'Startpage': '/',
+						'Applications': '/applications',
+						'Development Blog': '/devblog',
+					},
+					secondary: {
+						'Impressum': '/impressum',
+					},
+				},
+				intLinks: {
+					primary: [],
+					secondary: [],
+				},
+				primary: [],
+				secondary: [],
+			}
+		},
+		created() {
+			//Convert the given links to arrays for later processing.
+			this.intLinks.primary = this.convertToArray(this.links.primary)
+			this.intLinks.secondary = this.convertToArray(this.links.secondary)
+		},
+		computed: {
+			user() {
+				return this.$store.state.user
+			},
+		},
+		methods: {
+			updateMenu() {
+				//Empty to measure the whole available space.
+				this.primary = []
+
+				this.$nextTick(() => {
+					let menubar = this.$refs.topbar
+					//Subtract safety pixels, scrollbars come a bit later after resize.
+					let maxWidth = this.$refs.navigation.clientWidth - this.$refs.dropdownArrow.offsetWidth - 30
+
+					//Add all preprocessed links to measure them in current env.
+					this.primary = this.intLinks.primary
+
+					this.$nextTick(() => {
+						let sizes = []
+						for(let el of menubar.childNodes) {
+							sizes.push(el.offsetWidth)
+						}
+
+						this.primary = []
+						this.secondary = []
+
+						let linkSize = this.intLinks.primary.length
+						let tmp = 0;
+						for(let i = 0; i < linkSize; i++) {
+							tmp += sizes[i] //Add the size of the current element
+
+							if(maxWidth > tmp) {
+								this.primary.push(this.intLinks.primary[i])
+							} else {
+								this.secondary.push(this.intLinks.primary[i])
+							}
+						}
+
+						this.secondary = this.secondary.concat(this.intLinks.secondary)
+					})
+				})
+			},
+			convertToArray(obj) {
+				let els = []
+				for(let key in obj) {
+					if(obj.hasOwnProperty(key)) {
+						els.push({
+							key: key,
+							val: obj[key],
+						})
+					}
+				}
+				return els
+			},
+			logout() {
+				this.core.logout()
+			},
+		},
+		watch: {
+			user: function() {
+				this.updateMenu()
+			}
+		},
+		mounted() {
+			window.addEventListener('resize', this.updateMenu)
+			//Initial menu sorting
+			this.updateMenu()			
+		},
+		beforeDestroy() {
+			//TBI never will be closed...!
+			window.removeEventListener('resize', this.updateMenu)
+		},
+	}
+</script>
+
+<style scoped>
+	/*
+	Whole line:
+	*/
+	header {
+		display: flex;
+
+		white-space: nowrap;
+		background-color: #222;
+	}
+	nav {
+		flex-grow: 100;
+	}
+
+	/*
+	Dropdown mechanic:
+	*/
+	.dropdown {
+		position: absolute;
+		display: none;
+
+		background-color: #222;
+		
+		right: 50%;
+		transform: translateX(50%);
+	}
+	.wrapper:hover > .dropdown {
+		display: block;
+	}
+	.wrapper {
+		position: relative;
+		display: inline;
+	}
+	.topbar {
+		display: inline;
+	}
+
+	/*
+	Generic link properties:
+	*/
+	.link {
+		padding: 0em 0.2em;
+
+		color: #aaa;
+		text-decoration: none;
+	}
+	.link:hover {
+		color: #ddd;
+		background-color: #333;
+	}
+
+	/*
+	Specific link properties:
+	*/
+	.t_link {
+		border-right: 1px solid #aaa;
+	}
+	.d_link {
+		display: block;
+		border-top: 1px solid #aaa;
+	}
+	.t_link_d {
+		border-right: none;
+	}
+
+</style>

+ 0 - 137
src/components/MenuContainer.vue

@@ -1,137 +0,0 @@
-<template>
-	<div ref="whole">
-		<div class="topbar" ref="topbar">
-			<slot class="top-link"></slot>
-		</div>
-		<span class="arrow">
-			<span class="top-link" ref="dropdownbutton">vv</span>
-			<div class="dropdown" ref="dropdown" />
-		</span>
-	</div>
-</template>
-
-<script>
-	export default {
-		methods: {
-			onResize() {
-				this.update()
-			},
-
-			update() {
-				let topbar = this.$refs.topbar
-				let dropdown = this.$refs.dropdown
-				
-				let dropDownButton = this.$refs.dropdownbutton
-				dropDownButton.classList.remove('alone', 'full')
-				let dropdownWidth = dropDownButton.offsetWidth
-				
-				let topbarElements = Array.from(topbar.childNodes)
-				let dropboxElements = Array.from(dropdown.childNodes)
-				for(let el of dropboxElements) {
-					dropdown.removeChild(el)
-					topbar.appendChild(el)
-				}
-
-				let childAndSize = []
-				for(let child of topbarElements.concat(dropboxElements)) {
-					childAndSize.push([child.offsetWidth, child])
-				}
-
-				topbar.innerHTML = ''
-				let width = this.$refs.whole.clientWidth - dropdownWidth - 50
-				let tmp = 0
-				for(let child of childAndSize) {
-					tmp += child[0]
-
-					if(width > tmp) {
-						topbar.appendChild(child[1])
-					} else {
-						dropdown.appendChild(child[1])
-					}
-				}
-
-				if(dropdown.childNodes.length === 0) {
-					dropDownButton.classList.add('full')
-				} else if(topbar.childNodes.length === 0) {
-					dropDownButton.classList.add('alone')
-				}
-			}
-		},
-
-		mounted() {
-			window.addEventListener('resize', this.onResize)
-			//Initial menu sorting
-			this.update()			
-		},
-
-		beforeDestroy() {
-			//TBI never will be closed...!
-			window.removeEventListener('resize', this.onResize)
-		}
-	}
-</script>
-
-<style scoped>
-	.whole {
-		box-sizing: border-box;
-	}
-
-	.topbar > .top-link:first-child {
-		border: none;
-	}
-	.top-link {
-		box-sizing: border-box;
-		white-space: nowrap;
-		display: inline-block;
-		padding: 0.2em 0.3em 0.2em 0.3em;
-		border-left: solid 1px #aaa;
-
-		color: #aaa;
-		text-decoration: none;
-	}
-
-	.alone {
-		border-left: none;
-	}
-
-	.full {
-		display: none;
-	}
-
-	.topbar {
-		box-sizing: border-box;
-		display: inline-block;
-	}
-	.arrow {
-		position: relative;
-	}
-
-	.dropdown {
-		display: none;
-		position: absolute;
-		
-		z-index: 1;
-
-		min-width: 100%;
-		top: 1.3em;
-		left: 50%;
-		transform: translateX(-50%);
-	}
-
-	.dropdown .top-link {
-		border: none;
-		border-top: 1px solid #aaa;
-		display: block;
-		position: relative;
-		background-color: #222;
-	}
-
-	.arrow:hover .dropdown {
-		display: inline-block;
-	}
-
-	.top-link:hover {
-		background-color: #333;
-		color: #ddd;
-	}
-</style>

+ 10 - 21
src/components/SimpleProgressBar.vue

@@ -1,44 +1,33 @@
 <template>
 	<div>
 		<div class="background">
-			<div class="bar" ref="bar"/>
+			<div class="bar" :style="progressBar"/>
 		</div>
 	</div>
 </template>
 
 <script>
 	export default {
-		data() {
-			return {
-			}
-		},
 		props: [
 			'count',
 			'max',
 			'steps',
 		],
-		methods: {
-			update: function () {
+		computed: {
+			stepsize() {
+				return 100 / this.steps
+			},
+			progressBar() {
 				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
+				return {
+					'width': per + '%',
+					'backgroundColor': per >= 100 ? '#0f0' : '#f00',
+				}
 			}
 		},
-		watch: {
-			count: function () {
-				this.update()
-			},
-		}
 	}
 </script>
 

+ 8 - 9
src/components/inputtypes/LimitedTextField.vue

@@ -1,7 +1,7 @@
 <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"/>
+		<SimpleProgressBar class="progbar" :count="len" max="270" steps="5"/>
 	</div>
 </template>
 
@@ -21,16 +21,13 @@
 
 		computed: {
 			isEnough() {
-				return this.inputText.length >= 50
+				return this.inputText.length >= 270
 			},
 			len() {
 				return this.inputText.length
 			}
 		},
 
-		mounted() {
-		},
-
 		components: {
 			SimpleProgressBar,
 		},
@@ -40,12 +37,14 @@
 <style scoped>
 	.textarea {
 		width: 100%;
-		color: #fff;
-		resize: vertical;
 		min-height: 1.2em;
-		height: 1.2em;
-		border: 1px solid #aaa;
+		resize: vertical;
 		margin: auto;
+
+		height: 5em;
+		
+		color: #fff;
+		border: 1px solid #aaa;
 		background-color: #222;
 	}
 

+ 21 - 0
src/components/inputtypes/LineInput.vue

@@ -0,0 +1,21 @@
+<template>
+	<div class="width">
+		<input class="textarea" type="text" />
+	</div>
+</template>
+
+<style scoped>
+	.textarea {
+		width: 50%;
+		margin: auto;
+
+		color: #fff;
+		border: 1px solid #aaa;
+		background-color: #222;
+	}
+
+	.width {
+		width: 100%;
+		max-width: 60em;
+	}
+</style>

+ 25 - 0
src/components/inputtypes/TextField.vue

@@ -0,0 +1,25 @@
+<template>
+	<div class="width">
+		<textarea class="textarea" type="text" />
+	</div>
+</template>
+
+<style scoped>
+	.textarea {
+		width: 100%;
+		min-height: 1.2em;
+		resize: vertical;
+		margin: auto;
+		
+		color: #fff;
+		border: 1px solid #aaa;
+		background-color: #222;
+
+		height: 4em;
+	}
+
+	.width {
+		width: 100%;
+		max-width: 60em;
+	}
+</style>

+ 3 - 3
src/views/CreateApplication.vue

@@ -7,7 +7,7 @@
 				<span class="question">{{ element.text }}</span>
 				<span v-if="element.optional"> (Optional)</span>
 				<br>
-				<LimitedTextField class="textfield" :highlight="highlight"></LimitedTextField>
+				<ApplicationInputSwitch class="textfield" :highlight="highlight" :type="element.type"></ApplicationInputSwitch>
 				<span class="hint">{{ element.hint }}</span>
 			</div>
 			<button @click="update">Create/Update</button>
@@ -17,7 +17,7 @@
 </template>
 
 <script>
-	import LimitedTextField from '../components/inputtypes/LimitedTextField.vue'
+	import ApplicationInputSwitch from '../components/ApplicationInputSwitch.vue'
 
 	export default {
 		data () {
@@ -44,7 +44,7 @@
 			},
 		},
 		components: {
-			LimitedTextField,
+			ApplicationInputSwitch,
 		},
 	}
 </script>

+ 6 - 1
src/views/Login.vue

@@ -3,6 +3,7 @@
 		<h1>Login</h1>
 
 		<div v-if="!user">
+			<span>For not just put in random data, they will work :)</span><br><br>
 			<span>Username: </span>
 			<input @keyup.enter="usernameDone()" v-model="username" placeholder="username" ref="username"><br>
 
@@ -26,7 +27,11 @@
 			}
 		},
 		mounted() {
-			this.$refs.username.focus()
+			//TODO: Improve
+			let usernameField = this.$refs.username
+			if(usernameField) {
+				usernameField.focus()
+			}
 		},
 		computed: {
 			user() {