moved to bootstrap-vue, there is a bug in vee-validate and bootstrap-vue >rc15

This commit is contained in:
2019-04-23 16:13:18 +02:00
parent c374ae1796
commit 4a97efce6f
26 changed files with 4310 additions and 743 deletions

View File

@@ -22,29 +22,31 @@
</template>
<script>
import { EventBus } from '@/utils'
import {EventBus} from '@/utils';
export default {
data () {
data() {
return {
email: '',
errorMsg: '',
};
},
methods: {
authenticate () {
this.$store.dispatch('login', { email: this.email, password: this.password })
authenticate() {
this.$store.dispatch('login', {email: this.email, password: this.password})
.then(() => this.$router.push('/'));
},
},
mounted () {
this.$log.debug("Admin: mounting...");
mounted() {
this.$log.debug('Admin: mounting...');
},
beforeDestroy () {
beforeDestroy() {
// todo ...
},
computed: {
// todo ...
},
}
};
</script>
<style lang="scss">

View File

@@ -12,7 +12,8 @@
<thead>
<tr>
<th v-for="col in group_columns" v-on:click="sortTable(col)">{{col}}
<div class="arrow" v-if="col == sortColumn" v-bind:class="[ascending ? 'arrow_up' : 'arrow_down']"></div>
<div class="arrow" v-if="col == sortColumn"
v-bind:class="[ascending ? 'arrow_up' : 'arrow_down']"></div>
</th>
</tr>
</thead>
@@ -26,7 +27,8 @@
<div class="number"
v-for="i in num_group_pages()"
v-bind:class="[i == currentPage ? 'active' : '']"
v-on:click="change_page(i)">{{i}}</div>
v-on:click="change_page(i)">{{i}}
</div>
</div>
</div>
@@ -50,17 +52,18 @@
</template>
<script>
import { EventBus } from '@/utils'
import { RepositoryFactory} from "@/api/RepositoryFactory";
const GroupRepository = RepositoryFactory.get('group');
import {EventBus} from '@/utils';
import getRepository from '@/api/RepositoryFactory';
const GroupRepository = getRepository('group');
export default {
data () {
data() {
return {
isLoading: false,
groups: [],
errorMsg: '',
group: {name:'', description:''},
group: {name: '', description: ''},
sortColumn: '',
currentPage: 1,
elementsPerPage: 5,
@@ -71,7 +74,7 @@
this.isLoading = true;
// const { data } = await GroupRepository.get();
GroupRepository.getGroups()
.then(response => {
.then((response) => {
this.groups = response.data;
this.isLoading = false;
this.$log.debug(response);
@@ -79,8 +82,8 @@
},
get_group_rows() {
var start = (this.currentPage-1) * this.elementsPerPage;
var end = start + this.elementsPerPage;
const start = (this.currentPage - 1) * this.elementsPerPage;
const end = start + this.elementsPerPage;
return this.groups.slice(start, end);
},
num_group_pages() {
@@ -97,19 +100,19 @@
this.sortColumn = col;
}
var ascending = this.ascending;
const ascending = this.ascending;
this.groups.sort(function(a, b) {
this.groups.sort((a, b) => {
if (a[col] > b[col]) {
return ascending ? 1 : -1
return ascending ? 1 : -1;
} else if (a[col] < b[col]) {
return ascending ? -1 : 1
return ascending ? -1 : 1;
}
return 0;
})
});
},
createGroup(){
this.$log.info("Creating new group...");
createGroup() {
this.$log.info('Creating new group...');
GroupRepository.createGroup(this.group);
this.fetch();
},
@@ -118,6 +121,7 @@
this.fetch();
},
beforeDestroy() {
// todo....or not
},
computed: {
group_columns() {
@@ -127,7 +131,7 @@
return Object.keys(this.groups[0]);
},
},
}
};
</script>
<style lang="scss">
@@ -135,6 +139,7 @@
color: red;
font-weight: bold;
}
table {
font-family: 'Open Sans', sans-serif;
width: 750px;
@@ -152,17 +157,21 @@
padding: 8px;
min-width: 30px;
}
table th:hover {
background: #717699;
}
table td {
text-align: left;
padding: 8px;
border-right: 2px solid #7D82A8;
}
table td:last-child {
border-right: none;
}
table tbody tr:nth-child(2n) td {
background: #D4D8F9;
}
@@ -184,17 +193,21 @@
padding: 8px;
min-width: 30px;
}
table th:hover {
background: #717699;
}
table td {
text-align: left;
padding: 8px;
border-right: 2px solid #7D82A8;
}
table td:last-child {
border-right: none;
}
table tbody tr:nth-child(2n) td {
background: #D4D8F9;
}
@@ -209,9 +222,11 @@
.arrow_down {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB8AAAAaCAYAAABPY4eKAAAAAXNSR0IArs4c6QAAAvlJREFUSA29Vk1PGlEUHQaiiewslpUJiyYs2yb9AyRuJGm7c0VJoFXSX9A0sSZN04ULF12YEBQDhMCuSZOm1FhTiLY2Rky0QPlQBLRUsICoIN/0PCsGyox26NC3eTNn3r3n3TvnvvsE1PkwGo3yUqkkEQqFgw2Mz7lWqwng7ztN06mxsTEv8U0Aam5u7r5EInkplUol/f391wAJCc7nEAgE9Uwmkzo4OPiJMa1Wq6cFs7Ozt0H6RqlUDmJXfPIx+qrX69Ti4mIyHA5r6Wq1egND+j+IyW6QAUoul18XiUTDNHaSyGazKcZtdgk8wqhUKh9o/OMvsVgsfHJy0iWqVrcQNRUMBnd6enqc9MjISAmRP3e73T9al3XnbWNjIw2+KY1Gc3imsNHR0YV4PP5+d3e32h3K316TySQFoX2WyWR2glzIO5fLTSD6IElLNwbqnFpbWyO/96lCoai0cZjN5kfYQAYi5H34fL6cxWIZbya9iJyAhULBHAqFVlMpfsV/fHxMeb3er+Vy+VUzeduzwWC45XA4dlD/vEXvdDrj8DvURsYEWK3WF4FA4JQP9mg0WrHZbEYmnpa0NxYgPVObm5teiLABdTQT8a6vrwdRWhOcHMzMzCiXlpb2/yV6qDttMpkeshEzRk4Wo/bfoe4X9vb2amzGl+HoXNT29vZqsVi0sK1jJScG+Xx+HGkL4Tew2TPi5zUdQQt9otPpuBk3e0TaHmMDh1zS7/f780S0zX6Yni+NnBj09fUZUfvudDrNZN+GkQbl8Xi8RLRtHzsB9Hr9nfn5+SjSeWUCXC7XPq5kw53wsNogjZNohYXL2EljstvtrAL70/mVaW8Y4OidRO1/gwgbUMvcqGmcDc9aPvD1gnTeQ+0nmaInokRj0nHh+uvIiVOtVvt2a2vLv7Ky0tL3cRTXIcpPAwMDpq6R4/JXE4vFQ5FI5CN+QTaRSFCYc8vLy1l0rge4ARe5kJ/d27kYkLXoy2Jo4C7K8CZOsEBvb+9rlUp1xNXPL7v3IDwxvPD6AAAAAElFTkSuQmCC')
}
.arrow_up {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAaCAYAAACgoey0AAAAAXNSR0IArs4c6QAAAwpJREFUSA21Vt1PUmEYP4dvkQ8JFMwtBRocWAkDbiqXrUWXzU1rrTt0bdVqXbb1tbW16C9IBUSmm27cODdneoXjputa6069qwuW6IIBIdLvdaF4OAcOiGeDc87zPs/vd57P96WpFq7p6enbGo1mjKZpeTabjU1MTCRagGnOZHFxcXxtbe1XKpUq7+zslJeXl//Mz8+Hy+Uy3RxSE9qTk5M3otFooVQqgef4Wl9f343FYoEmoISrxuNxFX5f9vb2jhn/PxUKhfLS0tIPfFifUESRUMV8Pv/M6XReRm5rTGQyGeXxeGxYe1ezeBpBOBx2rKysbO7v79d4Wy3Y2Nj4GQqFbgnhaugxwiuGJx99Pp9FLBbXxYTXvTqd7v3MzIy6riIWGxJnMpl7AwMD14xGYyMsSq1WUyQdUqn0eSPlusQIsbGrq+vl4OCgvhFQZd1utyv1en0gEolcqsi47nWJlUrlG5fLZVcoFFy2nDKSDpIWlUoVTCQSEk4lCHmJMZ2GTCbTiMVikfIZ88l7enoos9l8dXt7+z6fDicxSJUokqDX6xXcl2wCROoc0vQCWL3sNfLOSdzR0fHY4XC4tVotl40gmVwup9xuN4OQv+UyqCFGH9rg7SOGYVRcBs3IEG4J0nVnamrqOtvuBDGGgQg9+wHFcVEi4a0LNkbdd6TrPKo8ODc311mteIIYjT/a398/jK+s1jnVM0kXoufCFvq0GuiIGEVgQIhfoygM1QrteEa9dAL7ITiYCt4RMabOK5AyKKzKWtvupLcRciu8D5J0EuDDPyT/Snd39yh6VtY2NhYQSR9G79Ds7OxdskRjEyAufvb7/cPoO5Z6e1+xtVKrq6vfcFzyi/A3ZrPZ3GdNSlwgo5ekE4X2RIQGf2C1WlufFE0GBeGWYQ8YERWLxQtnUVB830MKLZfL9RHir8lkssCn2G751tZWEWe03zTKm15YWPiEiXXTYDB0Ig/t7yd8PRws4EicwWHxO4jHD8/C5HiTTqd1BwcHFozKU89origB+y/kmzgYpgOBQP4fGmUiZmJ+WNgAAAAASUVORK5CYII=')
}
.arrow {
float: right;
width: 12px;
@@ -230,6 +245,7 @@
margin: 0px 5px;
cursor: pointer;
}
.number:hover, .number.active {
background: #717699;
}

View File

@@ -9,14 +9,14 @@
</div>
</div>
<ul>
<li v-for="(provider, index) in loginProviders" v-bind:id="index">
<a :href="provider.url">{{ index }} ({{provider.type}})</a>
</li>
<li v-for="(provider, index) in loginProviders" v-bind:id="index">
<a :href="provider.url">{{ index }} ({{provider.type}})</a>
</li>
</ul>
<h3>Users</h3>
<ul>
<li v-for="(user) in users" >
<li v-for="(user) in users">
<a href="#">({{user.id}}) {{user.first_name}}</a>
</li>
</ul>
@@ -50,10 +50,11 @@
</template>
<script>
import { EventBus } from '@/utils'
import {EventBus} from '@/utils';
export default {
data () {
data() {
return {
email: '',
password: '',
@@ -62,19 +63,20 @@
};
},
methods: {
authenticate () {
this.$store.dispatch('login', { email: this.email, password: this.password })
authenticate() {
this.$store.dispatch('login', {email: this.email, password: this.password})
.then(() => this.$router.push('/'));
},
register () {
this.$store.dispatch('register', { email: this.email, password: this.password })
register() {
this.$store.dispatch('register', {email: this.email, password: this.password})
.then(() => this.$router.push('/'));
},
oidc_login () {
this.$store.dispatch('oidc_login', "\\oidc_login_redirection");
oidc_login() {
this.$store.dispatch('oidc_login', '\\oidc_login_redirection');
},
},
mounted () {
mounted() {
// this.$parent.$data.isLoading = true;
EventBus.$on('failedRegistering', (msg) => {
this.errorMsg = msg;
});
@@ -91,22 +93,22 @@
this.$store.dispatch('loadLoginProviders');
// get tokens
if(this.$cookies.isKey("tokens")){
this.$store.dispatch('storeTokens', JSON.parse(atob(this.$cookies.get("tokens"))));
this.$cookies.remove("tokens");
if (this.$cookies.isKey('tokens')) {
this.$store.dispatch('storeTokens', JSON.parse(atob(this.$cookies.get('tokens'))));
this.$cookies.remove('tokens');
}
console.log(this.$cookies.keys());
this.$log.debug(this.$cookies.keys());
},
beforeDestroy () {
beforeDestroy() {
EventBus.$off('failedRegistering');
EventBus.$off('failedAuthentication');
},
computed: {
users () {
users() {
return this.$store.state.users;
},
},
}
};
</script>
<style lang="scss">

View File

@@ -1,75 +0,0 @@
<template>
<div>
<div class="field">
<label class="label is-large">Question</label>
<div class="control">
<input type="text" class="input is-large" v-model="question">
</div>
</div>
<div class="field">
<div class="control">
<a class="button is-large is-info" @click="addChoice">
<span class="icon is-small">
<i class="fa fa-plus-square-o fa-align-left" aria-hidden="true"></i>
</span>
<span>Add choice</span>
</a>
<a class="button is-large is-primary" @click="saveQuestion">
<span class="icon is-small">
<i class="fa fa-check"></i>
</span>
<span>Save</span>
</a>
</div>
</div>
<h2 class="label is-large" v-show="choices.length > 0">Question Choices</h2>
<div class="field has-addons" v-for="(choice, idx) in choices" v-bind:key="idx">
<div class="control choice">
<input type="text" class="input is-large" v-model="choices[idx]">
</div>
<div class="control">
<a class="button is-large">
<span class="icon is-small" @click.stop="removeChoice(choice)">
<i class="fa fa-times" aria-hidden="true"></i>
</span>
</a>
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
question: '',
choices: []
}
},
methods: {
removeChoice (choice) {
const idx = this.choices.findIndex(c => c === choice)
this.choices.splice(idx, 1)
},
saveQuestion () {
this.$emit('questionComplete', {
question: this.question,
choices: this.choices.filter(c => !!c)
})
this.question = ''
this.choices = ['']
},
addChoice () {
this.choices.push('')
}
}
}
</script>
<style>
.choice {
width: 90%;
}
</style>

View File

@@ -1,122 +0,0 @@
<template>
<div>
<section class="hero is-primary">
<div class="hero-body">
<div class="container has-text-centered">
<h2 class="title">{{ name }}</h2>
</div>
</div>
</section>
<section class="section">
<div class="container">
<div class="tabs is-centered is-fullwidth is-large">
<ul>
<li :class="{'is-active': step == 'name'}" @click="step = 'name'">
<a>Name</a>
</li>
<li :class="{'is-active': step == 'questions'}" @click="step = 'questions'">
<a>Questions</a>
</li>
<li :class="{'is-active': step == 'review'}" @click="step = 'review'">
<a>Review</a>
</li>
</ul>
</div>
<div class="columns">
<div class="column is-half is-offset-one-quarter">
<div class="name" v-show="step === 'name'">
<div class="field">
<label class="label is-large" for="name">Survey name:</label>
<div class="control">
<input type="text" class="input is-large" id="name" v-model="name">
</div>
</div>
</div>
<div class="questions" v-show="step === 'questions'">
<new-question v-on:questionComplete="appendQuestion"/>
</div>
<div class="review" v-show="step === 'review'">
<ul>
<li class="question" v-for="(question, qIdx) in questions" :key="`question-${qIdx}`">
<div class="title">
{{ question.question }}
<span class="icon is-medium is-pulled-right delete-question"
@click.stop="removeQuestion(question)">
<i class="fa fa-times" aria-hidden="true"></i>
</span>
</div>
<ul>
<li v-for="(choice , cIdx) in question.choices" :key="`choice-${cIdx}`">
{{ cIdx + 1 }}. {{ choice }}
</li>
</ul>
</li>
</ul>
<div class="control">
<a class="button is-large is-primary" @click="submitSurvey">Submit</a>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
</template>
<script>
import NewQuestion from '@/components/NewQuestion'
export default {
components: { NewQuestion },
data () {
return {
step: 'name',
name: '',
questions: []
}
},
methods: {
appendQuestion (newQuestion) {
this.questions.push(newQuestion)
},
removeQuestion (question) {
const idx = this.questions.findIndex(q => q.question === question.question)
this.questions.splice(idx, 1)
},
submitSurvey () {
this.$store.dispatch('submitNewSurvey', {
name: this.name,
questions: this.questions
})
.then(() => this.$router.push('/'))
.catch((error) => {
console.log('Error creating survey', error)
this.$router.push('/')
})
}
}
}
</script>
<style>
.question {
margin: 10px 20px 25px 10px;
}
.delete-question {
cursor: pointer;
padding: 10px;
}
.delete-question:hover {
background-color: lightgray;
border-radius: 50%;
}
</style>

View File

@@ -17,11 +17,11 @@
</template>
<script>
import { EventBus } from '@/utils'
import {getRemainingJwtValiditySeconds} from "../utils";
import {EventBus} from '@/utils';
import {getRemainingJwtValiditySeconds} from '../utils';
export default {
data () {
data() {
return {
email: '',
errorMsg: '',
@@ -30,19 +30,19 @@
};
},
methods: {
authenticate () {
this.$store.dispatch('login', { email: this.email, password: this.password })
authenticate() {
this.$store.dispatch('login', {email: this.email, password: this.password})
.then(() => this.$router.push('/'));
},
},
mounted () {
this.$log.debug("Profile: mounting...");
mounted() {
this.$log.debug('Profile: mounting...');
EventBus.$on('failedLoadingProfile', (msg) => {
this.errorMsg = msg;
});
this.$store.dispatch('loadProfile');
this.$nextTick(() =>{
this.$nextTick( () => {
window.setInterval(() => {
this.$log.debug(getRemainingJwtValiditySeconds(this.$store.state.access_token));
this.tokenValidity = getRemainingJwtValiditySeconds(this.$store.state.access_token);
@@ -52,15 +52,15 @@
},
beforeDestroy () {
beforeDestroy() {
EventBus.$off('failedLoadingProfile');
},
computed: {
profile () {
profile() {
return this.$store.state.profile;
},
},
}
};
</script>
<style lang="scss">

View File

@@ -0,0 +1,271 @@
<template>
<div>
<section class="section">
<h1 class="title">{{ $t('Manage recorders and recorder models') }}</h1>
<p class="subtitle">
{{ $t('List, create, update and delete') }} <strong>{{ $t('recorders') }}</strong> and <strong>recorder models</strong>!
</p>
<hr>
<h2 class="">{{ $t('Create recorder') }}</h2>
<!-- form starts here -->
<form v-on:submit.prevent="$log.debug(form)">
<section class="form">
<div class="field">
<label class="label">{{ $t('name') }}</label>
<div class="control">
<input name="name"
v-model="form.name"
v-validate="'required|min:3'"
v-bind:class="{'is-danger': errors.has('name')}"
class="input" type="text" placeholder="Full name">
</div>
<p class="help is-danger" v-show="errors.has('name')">
{{ errors.first('name') }}
</p>
</div>
<div class="field">
<label class="label">{{ $t('description') }}</label>
<div class="control">
<textarea class="textarea" placeholder="description of recorder"
v-model="form.description"></textarea>
</div>
</div>
<div class="field">
<label class="label">{{ $t('room') }}</label>
<div class="control">
<div class="select">
<select v-model="form.room">
<option disabled value="">No room selected</option>
<option v-for="option in options.room" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
</div>
</div>
</div>
<div class="field">
<label class="label">{{ $t('model') }}</label>
<div class="control">
<div class="select">
<select v-model="form.model">
<option disabled value="">No model selected</option>
<option v-for="option in options.model" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
</div>
</div>
</div>
<div class="field">
<label class="label">LogRocket Usecases</label>
<div class="control">
<div class="select is-multiple">
<select multiple v-model="form.logrocket_usecases">
<option>Debugging</option>
<option>Fixing Errors</option>
<option>User support</option>
</select>
</div>
</div>
</div>
<div class="field">
<div class="control">
<label class="checkbox">
<input type="checkbox" v-model="form.terms">
I agree to the <a href="#">terms and conditions</a>
</label>
</div>
</div>
<div class="field">
<label>
<strong>What dev concepts are you interested in?</strong>
</label>
<div class="control">
<label class="checkbox">
<input type="checkbox" v-model="form.concepts"
value="promises">
Promises
</label>
<label class="checkbox">
<input type="checkbox" v-model="form.concepts"
value="testing">
Testing
</label>
</div>
</div>
<div class="field">
<label><strong>Is JavaScript awesome?</strong></label>
<div class="control">
<label class="radio">
<input v-model="form.js_awesome" type="radio" value="Yes">
Yes
</label>
<label class="radio">
<input v-model="form.js_awesome" type="radio" value="Yeap!">
Yeap!
</label>
</div>
</div>
<div class="field is-grouped">
<div class="control">
<button
v-bind:disabled="errors.any()"
class="button is-primary">
Submit
</button>
</div>
</div>
</section>
</form>
<hr>
<h2 class="">{{ $t('Create recorder model') }}</h2>
<!-- form starts here -->
<form v-on:submit.prevent="$log.debug(form)">
<section class="form">
<div class="field">
<label class="label">{{ $t('model name') }}</label>
<div class="control">
<input name="name"
v-model="form.name"
v-validate="'required|min:3'"
v-bind:class="{'is-danger': errors.has('name')}"
class="input" type="text" placeholder="Full name">
</div>
<p class="help is-danger" v-show="errors.has('name')">
{{ errors.first('name') }}
</p>
</div>
<div class="field">
<label class="label">{{ $t('notes') }}</label>
<div class="control">
<textarea class="textarea" placeholder="Notes"
v-model="form.notes"></textarea>
</div>
</div>
<div class="field">
<label class="label">Recorder commands</label>
<div class="control">
<div class="select is-multiple">
<select multiple v-model="form.commands">
<option v-for="option in recorderCommands.options">
{{ option }}
</option>
</select>
</div>
</div>
</div>
<div class="field is-grouped">
<div class="control">
<button
v-bind:disabled="errors.any()"
class="button is-primary">
Create
</button>
</div>
</div>
</section>
</form>
</section>
<div class="column">
<section class="section" id="results">
<div class="box">
<ul>
<!-- loop through all the `form` properties and show their values -->
<li v-for="(item, k) in form">
<strong>{{ k }}:</strong> {{ item }}
</li>
</ul>
</div>
</section>
</div>
</div>
</template>
<script>
export default {
data() {
return {
step: 'name',
name: '',
questions: [],
form: {
name: '',
message: '',
inquiry_type: '',
logrocket_usecases: [],
terms: false,
concepts: [],
js_awesome: '',
},
};
},
methods: {
appendQuestion(newQuestion) {
this.questions.push(newQuestion);
},
removeQuestion(question) {
const idx = this.questions.findIndex((q) => q.question === question.question);
this.questions.splice(idx, 1);
},
submitSurvey() {
this.$store.dispatch('submitNewSurvey', {
name: this.name,
questions: this.questions,
})
.then(() => this.$router.push('/'))
.catch((error) => {
this.$log.error('Error creating survey', error);
this.$router.push('/');
});
},
},
computed: {
options() {
return {
room: [
{value: 'audimax', text: 'AudiMax'},
{value: 'hmu', text: 'Unterer Hörsaal'},
{value: 'hmo', text: 'Oberer Hörsaal'},
],
model: [
{value: 'extron', text: 'extron'},
{value: 'smp', text: 'SMP'},
{value: 'smp2', text: 'SMP2'},
],
};
},
recorderCommands() {
return {
options: [
'reboot',
'reset',
'setStreamingProfile',
],
};
},
},
};
</script>
<style>
</style>

353
src/components/Rooms.vue Normal file
View File

@@ -0,0 +1,353 @@
<template>
<div class="container">
<section class="section">
<h1 class="title">{{ $t('Manage rooms') }}</h1>
<p class="lead">
{{ $t('List, create and delete') }} <strong>{{ $t('rooms') }}</strong>
</p>
<br/>
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="room-list-tab" data-toggle="tab" href="#room-list" role="tab"
aria-controls="room-list" aria-selected="true">Room list</a>
</li>
<li class="nav-item">
<a class="nav-link" id="room-create-tab" data-toggle="tab" href="#room-create" role="tab"
aria-controls="room-create" aria-selected="false">Create room</a>
</li>
</ul>
<b-tabs card>
<b-tab title="Room list" active>
<p>{{ $t('There are')}}&nbsp;{{rooms.length}}&nbsp;{{ $t('rooms defined')}}:</p>
<b-card-group deck>
<b-card v-for="(room) in rooms" :title="room.name">
<b-card-text>
<h5 class="card-title">{{ $t('name') }}:&nbsp;{{room.name}}&nbsp;
<a class="float-right badge badge-pill badge-primary">
<font-awesome-icon icon="pencil-alt"/>
</a>
</h5>
<p class="card-text"><strong>{{ $t('alternate_name') }}:</strong>&nbsp;{{room.alternate_name}}&nbsp;
<a class="float-right badge badge-pill badge-info">
<font-awesome-icon icon="pencil-alt"/>
</a>
</p>
<p class="card-text"><strong>{{ $t('room_number') }}:</strong>&nbsp;{{room.number}}&nbsp;
<a class="float-right badge badge-pill badge-info">
<font-awesome-icon icon="pencil-alt"/>
</a></p>
<p class="card-text">
<small><strong>{{ $t('comment') }}:</strong>&nbsp;{{room.comment}}&nbsp;
<a class="float-right badge badge-pill badge-info">
<font-awesome-icon icon="pencil-alt"/>
</a></small>
</p>
<hr/>
<div v-if="room.recorder">
<p class="card-text"><strong>{{ $t('Recorder') }}:</strong>&nbsp;{{room.recorder.name}}&nbsp;
<a class="float-right badge badge-pill badge-info">
<font-awesome-icon icon="pencil-alt"/>
</a></p>
</div>
<div v-else>
<p class="card-text"><strong>{{ $t('Recorder') }}:</strong>&nbsp;{{
$t('no_recorder_defined')}}</p>
<div class="form-group row">
<div class="col-sm-8">
<select class="form-control" v-model="form.recorder">
<option disabled value="">No recorder selected</option>
<option v-for="option in options.recorders" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
</div>
<label class="label col-sm-4 col-form-label">{{ $t('recorder') }}</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox"
v-model="show_assigned_recorders" id="defaultCheck1">
<label class="form-check-label" for="defaultCheck1">
Show already assigned recorders
</label>
</div>
</div>
</b-card-text>
<div slot="footer">
<small class="text-muted">Last updated 3 mins ago</small>
</div>
</b-card>
<b-card title="Title">
<b-card-text>
This card has supporting text below as a natural lead-in to additional content.
</b-card-text>
<div slot="footer">
<small class="text-muted">Last updated 3 mins ago</small>
</div>
</b-card>
<b-card title="Title">
<b-card-text>
This is a wider card with supporting text below as a natural lead-in to additional
content.
This card has even longer content than the first to show that equal height action.
</b-card-text>
<div slot="footer">
<small class="text-muted">Last updated 3 mins ago</small>
</div>
</b-card>
</b-card-group>
</b-tab>
<b-tab title="Create room">
<b-card-text>
<p>{{ $t('Create a new room')}}:</p>
</b-card-text>
</b-tab>
</b-tabs>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="room-list" role="tabpanel" aria-labelledby="home-tab">
<p>{{ $t('There are')}}&nbsp;{{rooms.length}}&nbsp;{{ $t('rooms defined')}}:</p>
<div class="card-deck">
<div class="card" v-for="(room) in rooms">
<h5 class="card-header">{{room.name}} - {{room.number}}</h5>
<div class="card-body">
<h5 class="card-title">{{ $t('name') }}:&nbsp;{{room.name}}&nbsp;
<a class="float-right badge badge-pill badge-primary">
<font-awesome-icon icon="pencil-alt"/>
</a>
</h5>
<p class="card-text"><strong>{{ $t('alternate_name') }}:</strong>&nbsp;{{room.alternate_name}}&nbsp;
<a class="float-right badge badge-pill badge-info">
<font-awesome-icon icon="pencil-alt"/>
</a>
</p>
<p class="card-text"><strong>{{ $t('room_number') }}:</strong>&nbsp;{{room.number}}&nbsp;
<a class="float-right badge badge-pill badge-info">
<font-awesome-icon icon="pencil-alt"/>
</a></p>
<p class="card-text">
<small><strong>{{ $t('comment') }}:</strong>&nbsp;{{room.comment}}&nbsp;
<a class="float-right badge badge-pill badge-info">
<font-awesome-icon icon="pencil-alt"/>
</a></small>
</p>
<hr/>
<div v-if="room.recorder">
<p class="card-text"><strong>{{ $t('Recorder') }}:</strong>&nbsp;{{room.recorder.name}}&nbsp;
<a class="float-right badge badge-pill badge-info">
<font-awesome-icon icon="pencil-alt"/>
</a></p>
</div>
<div v-else>
<p class="card-text"><strong>{{ $t('Recorder') }}:</strong>&nbsp;{{
$t('no_recorder_defined')}}</p>
<div class="form-group row">
<div class="col-sm-8">
<select class="form-control" v-model="form.recorder">
<option disabled value="">No recorder selected</option>
<option v-for="option in options.recorders" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
</div>
<label class="label col-sm-4 col-form-label">{{ $t('recorder') }}</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox"
v-model="show_assigned_recorders" id="defaultCheck1">
<label class="form-check-label" for="defaultCheck1">
Show already assigned recorders
</label>
</div>
</div>
</div>
<div class="card-footer text-muted">
<button type="button" class="btn btn-danger">{{ $t('delete') }}&nbsp;<font-awesome-icon
icon="trash"/>
</button>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="room-create" role="tabpanel" aria-labelledby="profile-tab">
<p>{{ $t('Create a new room')}}:</p>
<!-- form starts here -->
<form v-on:submit.prevent="saveRoom()">
<section class="form">
<div class="form-group row">
<label class="label required col-sm-2 col-form-label">{{ $t('name') }}</label>
<div class="col-sm-6">
<input name="name"
v-model="form.name"
v-validate="'required|min:3'"
v-bind:class="{'is-danger': errors.has('name'), 'is-invalid': errors.has('name')}"
class="form-control" type="text" placeholder="Room name" required>
</div>
<p class="col-sm-4" v-show="errors.has('name')">
{{ errors.first('name') }}
</p>
</div>
<div class="form-group row">
<label class="label col-sm-2 col-form-label">{{ $t('alternate_name') }}</label>
<div class="col-sm-6">
<input name="alternate_name"
v-model="form.alternate_name"
class="form-control" type="text" placeholder="Alternate name">
</div>
</div>
<div class="form-group row">
<label class="label required col-sm-2 col-form-label">{{ $t('number') }}</label>
<div class="col-sm-6">
<input name="number"
v-model="form.number"
v-validate="'required|min:3'"
v-bind:class="{'is-danger': errors.has('number'), 'is-invalid': errors.has('number')}"
class="form-control" type="text" placeholder="Room number" required>
</div>
<p class="col-sm-4" v-show="errors.has('number')">
{{ errors.first('number') }}
</p>
</div>
<div class="form-group row">
<label class="label col-sm-2 col-form-label">{{ $t('comment') }}</label>
<div class="col-sm-6">
<textarea class="textarea form-control" placeholder="Comments, remarks, notes, etc."
v-model="form.comment"></textarea>
</div>
</div>
<div class="form-group row">
<label class="label col-sm-2 col-form-label">{{ $t('recorder') }}</label>
<div class="col-sm-6">
<select class="form-control" v-model="form.recorder">
<option disabled value="">No recorder selected</option>
<option v-for="option in options.recorders" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
</div>
</div>
<div class="field is-grouped">
<div class="control">
<button
v-bind:disabled="errors.any()"
type="submit"
class="btn btn-primary">
Create room
</button>
</div>
</div>
</section>
</form>
</div>
</div>
<hr>
</section>
<div class="column">
<section class="section" id="results">
<div class="box">
<ul>
<!-- loop through all the `form` properties and show their values -->
<li v-for="(item, k) in form">
<strong>{{ k }}:</strong> {{ item }}
</li>
</ul>
</div>
</section>
</div>
</div>
</template>
<script>
import PulseLoader from 'vue-spinner/src/PulseLoader.vue';
import getRepository from '@/api/RepositoryFactory';
const RoomRepository = getRepository('room');
export default {
components: {
PulseLoader,
},
props: [],
data() {
return {
show_assigned_recorders: false,
form: {
name: '',
alternate_name: '',
number: '',
comment: '',
recorder: null,
},
};
},
methods: {
saveRoom() {
this.$parent.$data.isLoading = true;
RoomRepository.createRoom(this.form)
.then(() => {
this.$store.dispatch('loadRooms')
.then(() => {
this.$parent.$data.isLoading = false;
});
});
},
},
mounted() {
this.$parent.$data.isLoading = true;
this.$store.dispatch('loadRooms')
.then(() => {
this.$parent.$data.isLoading = false;
});
},
computed: {
options() {
return {
recorders: [
{value: 8, text: 'SMP 351 AudiMax'},
{value: 13, text: 'SMP 351 HMU'},
],
};
},
rooms() {
return this.$store.state.rooms;
},
},
};
</script>
<style>
.comment {
white-space: pre-wrap;
}
.card:hover {
background-color: whitesmoke;
}
.required:after {
content: " *";
}
</style>

View File

@@ -1,115 +0,0 @@
<template>
<div>
<section class="hero is-primary">
<div class="hero-body">
<div class="container has-text-centered">
<h2 class="title">{{ survey.name }}</h2>
</div>
</div>
</section>
<section class="section">
<div class="container">
<div class="columns">
<div class="column is-10 is-offset-1">
<div
v-for="(question, idx) in survey.questions"
v-bind:key="question.id"
v-show="currentQuestion === idx">
<div class="column is-offset-3 is-6">
<h4 class='title has-text-centered'>{{ question.text }}</h4>
</div>
<div class="column is-offset-4 is-4">
<div class="control">
<div v-for="choice in question.choices" v-bind:key="choice.id">
<label class="radio">
<input type="radio" v-model="question.choice" name="choice" :value="choice.id">
{{ choice.text }}
</label>
</div>
</div>
</div>
</div>
<div class="column is-offset-one-quarter is-half">
<nav class="pagination is-centered" role="navigation" aria-label="pagination">
<a class="pagination-previous" @click.stop="goToPreviousQuestion"><i class="fa fa-chevron-left" aria-hidden="true"></i> &nbsp;&nbsp; Back</a>
<a class="pagination-next" @click.stop="goToNextQuestion">Next &nbsp;&nbsp; <i class="fa fa-chevron-right" aria-hidden="true"></i></a>
</nav>
</div>
<div class="has-text-centered">
<a v-show="surveyComplete" class='button is-large is-focused is-primary' @click="handleSubmit">Submit</a>
</div>
</div>
</div>
</div>
</section>
</div>
</template>
<script>
export default {
data () {
return {
currentQuestion: 0
}
},
beforeMount () {
this.$store.dispatch('loadSurvey', { id: parseInt(this.$route.params.id) })
},
methods: {
goToNextQuestion () {
if (this.currentQuestion === this.survey.questions.length - 1) {
this.currentQuestion = 0
} else {
this.currentQuestion++
}
},
goToPreviousQuestion () {
if (this.currentQuestion === 0) {
this.currentQuestion = this.survey.questions.lenth - 1
} else {
this.currentQuestion--
}
},
handleSubmit () {
this.$store.dispatch('addSurveyResponse')
.then(() => this.$router.push('/'))
}
},
computed: {
surveyComplete () {
if (this.survey.questions) {
const numQuestions = this.survey.questions.length
const numCompleted = this.survey.questions.filter(q => q.choice).length
return numQuestions === numCompleted
}
return false
},
survey () {
return this.$store.state.currentSurvey
},
selectedChoice: {
get () {
const question = this.survey.questions[this.currentQuestion]
return question.choice
},
set (value) {
const question = this.survey.questions[this.currentQuestion]
this.$store.commit('setChoice', { questionId: question.id, choice: value })
}
}
}
}
</script>
<style>
</style>

View File

@@ -5,14 +5,15 @@
<div class="hero-body">
<div class="container has-text-centered">
<h3 class="title">Manage users</h3>
<div>{{users}}</div>
<div>{{users}}</div>
<div id="userTable">
<table>
<thead>
<tr>
<th v-for="col in columns" v-on:click="sortTable(col)">{{col}}
<div class="arrow" v-if="col == sortColumn" v-bind:class="[ascending ? 'arrow_up' : 'arrow_down']"></div>
<div class="arrow" v-if="col == sortColumn"
v-bind:class="[ascending ? 'arrow_up' : 'arrow_down']"></div>
</th>
</tr>
</thead>
@@ -26,7 +27,8 @@
<div class="number"
v-for="i in num_pages()"
v-bind:class="[i === currentPage ? 'active' : '']"
v-on:click="change_page(i)">{{i}}</div>
v-on:click="change_page(i)">{{i}}
</div>
</div>
</div>
@@ -47,14 +49,16 @@
</template>
<script>
import { EventBus } from '@/utils';
import {EventBus} from '@/utils';
import {getRemainingJwtValiditySeconds} from '../utils';
import { RepositoryFactory} from '@/api/RepositoryFactory';
const UserRepository = RepositoryFactory.get('user');
import getRepository from '@/api/RepositoryFactory';
const UserRepository = getRepository('user');
export default {
data() {
return {
isLoading: false,
user: {},
users: [],
errorMsg: '',
@@ -68,7 +72,7 @@
this.isLoading = true;
// const { data } = await GroupRepository.get();
UserRepository.getUsers()
.then( (response) => {
.then((response) => {
this.users = response.data;
this.isLoading = false;
this.$log.debug(response);
@@ -76,8 +80,8 @@
},
get_rows() {
let start = (this.currentPage-1) * this.elementsPerPage;
let end = start + this.elementsPerPage;
const start = (this.currentPage - 1) * this.elementsPerPage;
const end = start + this.elementsPerPage;
return this.users.slice(start, end);
},
num_pages() {
@@ -94,19 +98,19 @@
this.sortColumn = col;
}
let ascending = this.ascending;
const ascending = this.ascending;
this.users.sort(function(a, b) {
this.users.sort((a, b) => {
if (a[col] > b[col]) {
return ascending ? 1 : -1
return ascending ? 1 : -1;
} else if (a[col] < b[col]) {
return ascending ? -1 : 1
return ascending ? -1 : 1;
}
return 0;
})
});
},
createUser(){
this.$log.info("Creating new user...");
createUser() {
this.$log.info('Creating new user...');
UserRepository.createUser(this.user);
this.fetch();
},
@@ -115,6 +119,7 @@
this.fetch();
},
beforeDestroy() {
// todo
},
computed: {
columns() {
@@ -124,7 +129,7 @@
return Object.keys(this.users[0]);
},
},
}
};
</script>
<style lang="scss">