Commit 964e4389 authored by Jarod Owen's avatar Jarod Owen
Browse files

Merge branch 'bootstrap' into 'master'

Bootstrap

See merge request !71
parents aac9690c 32527ef6
Pipeline #11314 passed with stages
in 4 minutes and 5 seconds
......@@ -27,10 +27,10 @@ class SchedulesController extends ApiController
$this->authorizer->protect(Permissions::MANAGE_DOORS);
$this->validate($this->request, [
'duration' => 'required|integer',
'duration' => 'required|integer', /* miliseconds */
'group_id' => 'required|integer',
'type' => 'required|integer',
'rset' => 'required|string',
'type' => 'required|integer', /* 0 = Open, 1 = UserAccess */
'rset' => 'required|string', /* RFC RSet (NOT FULLY COMPLIANT!) */
'description' => 'required|string|max:1024',
]);
......
This diff is collapsed.
......@@ -17,10 +17,12 @@
"@fortawesome/vue-fontawesome": "^0.1.9",
"axios": "^0.19.2",
"bootstrap": "^4.4.1",
"bootswatch": "^4.4.1",
"core-js": "^3.6.4",
"jquery": "^3.4.1",
"node-sass": "^4.13.1",
"jquery": "^3.5.1",
"node-sass": "^4.14.1",
"popper.js": "^1.16.1",
"rrule": "^2.6.4",
"v-calendar": "^1.0.0-beta.23",
"vue": "^2.6.11",
"vue-multiselect": "^2.1.6",
......
......@@ -3,24 +3,73 @@
<h1>Kretschmar Hall Doorcode System</h1>
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/user">Users</router-link> |
<router-link to="/userG">Groups</router-link> |
<router-link to="/door">Doors</router-link> |
<router-link to="/event">Events</router-link> |
<router-link to="/log">Log</router-link>
<router-link to="/about">About</router-link><br /><br />
<router-link v-if="loggedIn() & logIn" to="/me">My Info</router-link>
<span v-if="perms.includes('manage-users')">
| <router-link to="/user">Users</router-link>
</span>
<span v-if="perms.includes('manage-groups')">
| <router-link to="/userG">Groups</router-link>
</span>
<span v-if="perms.includes('manage-doors')">
| <router-link to="/door">Doors</router-link>
</span>
<span v-if="perms.includes('manage-groups')">
| <router-link to="/event">Events</router-link>
</span>
<span v-if="perms.includes('logs-read')">
| <router-link to="/log">Log</router-link>
</span>
</div>
<router-view/>
</div>
</template>
<script>
import axios from 'axios'
import constants from './constants'
export default {
mounted () {
axios.get(constants.APIHOST + '/me/permissions')
.then(response => {
var per = response.data.permissions
console.log(per)
this.perms = per
})
.catch(error => {
console.log(error.response)
})
},
data () {
return {
perms: [],
logIn: false,
dummy: null
}
},
methods: {
loggedIn () {
axios.get(constants.APIHOST + '/me')
.then(response => {
this.logIn = true
})
.catch(error => {
this.dummy = error
this.logIn = false
})
return true
}
}
}
</script>
<style lang="scss">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
color: #000000;
}
#nav {
......@@ -28,7 +77,7 @@
a {
font-weight: bold;
color: #2c3e50;
color: #000000;
&.router-link-exact-active {
color: #42b983;
......@@ -36,3 +85,68 @@
}
}
</style>
<style lang="sass">
.icon
font-size: 125%
.block
@extend .icon
color: red
.notblock
@extend .icon
color: green
.history
@extend .icon
color: blue
.edit
@extend .icon
color: darken(blue, 10%)
.adjust-0
position: relative
left: 3px
.adjust-1
position: relative
right: 3px
.adjust-2
position: relative
left: 139px
.adjust-3
position: relative
top: 3px
.adjust-4
position: relative
top: 9px
.adjust-5
position: relative
left: 36px
.adjust-6
position: relative
right: 33px
.adjust-7
position: relative
left: 6px
.adjust-8
position: relative
top: 3%
.adjust-9
position: relative
top: 2px
.adjust-10
position: relative
left: 12px
.adjust-11
position: relative
top: 16px
.textRow
margin-bottom: 4px
.narrow-1
width: 75%
.radBoxLab
margin:
left: 3px
right: 9px
.chkRow
margin-bottom: 25px
.ovrdLabel
margin-bottom: 8px
</style>
<template>
<div class="form">
<FormError v-if="err" :errJSON="errJSON"></FormError>
Location: <input type="text" v-model="num" /><br />
Name: <input type="text" v-model="name" /><br />
<!--Door Groups:<div class="thinMe"><multiselect
:options="dgroups"
<div class="container">
<div class="row">
<div class="col"><FormError v-if="err" :errJSON="errJSON"></FormError></div>
</div>
<div class="row textRow">
<div class="col text-right adjust-4"><label for="DALoc">Location:</label></div>
<div class="col-3">
<input id="DALoc" class="form-control" type="text" v-model="loc" />
</div>
<div class="col-4"></div>
</div>
<div class="row textRow">
<div class="col text-right adjust-4"><label for="DANom">Name:</label></div>
<div class="col-3">
<input id="DANom" class="form-control" type="text" v-model="name" />
</div>
<div class="col-4"></div>
</div>
<div class="row">
<div class="col text-right">
<label for="DGroup" class="adjust-1 adjust-4">Groups:</label>
</div>
<div class="col-3">
<multiselect
id="DGroup"
:options="groups"
:closeOnSelect="false"
:multiple="true"
v-model="selDGroup"
></multiselect></div><br />-->
<input type="button" value="Cancel" name="del" @click="$emit('cancel')"><br />
<input type="button" value="Submit" name="up" @click="update()"><br />
v-model="selGroup"
></multiselect>
</div>
<div class="col-4"></div>
</div>
<div class="btn-group adjust-4">
<button class="btn btn-primary rounded-left" @click="$emit('cancel')">Cancel</button>
<button class="btn btn-primary rounded-right" @click="update()">Submit</button>
</div>
</div>
</template>
<style>
.thinMe {
width: 20em;
position: relative;
left: 485px;
}
</style>
<script>
import Multiselect from 'vue-multiselect'
import axios from 'axios'
import constants from '../constants'
import FormError from '@/components/FormError.vue'
export default {
components: { FormError },
/* mounted () {
components: { FormError, Multiselect },
mounted () {
axios.get(constants.APIHOST + '/groups')
.then(response => {
var dgrps = response.data.groups
console.log(dgrps)
for (const i in dgrps) {
this.dgroups.push(dgrps[i].title)
this.dgroupIds.push(dgrps[i].id)
var grps = response.data.data
console.log(grps)
for (const i in grps) {
this.groups.push(grps[i].title)
this.groupIds.push(grps[i].id)
}
})
.catch(error => {
console.log(error)
})
}, */
},
data: function () {
return {
num: '',
loc: '',
name: '',
/* dgroups: [],
selDGroup: [],
dgroupIds: [], */
groups: [],
selGroup: [],
groupIds: [],
err: false,
errJSON: null,
id: ''
......@@ -57,10 +75,10 @@ export default {
},
methods: {
update: function () {
axios.post(constants.APIHOST + '/doors', { location: this.num, name: this.name })
axios.post(constants.APIHOST + '/doors', { location: this.loc, name: this.name })
.then(response => {
console.log(response)
/* this.id = response.data.user.id
this.id = response.data.user.id
var addTo = []
for (const i in this.groups) {
if (this.selGroup.includes(this.groups[i])) {
......@@ -75,7 +93,7 @@ export default {
.catch(error => {
console.log('update: add', error)
})
} */
}
this.$emit('cancel')
})
.catch(error => {
......
<template>
<div class="form">
Location: {{ info.location }}<br />
New Location: <input type="text" name="num" v-model="numb" /><br />
Name: {{ info.name }}<br />
New Name: <input type="text" name="name" v-model="nom" /><br />
Normal
<input type="radio" name="status" value="normal" /><br />
Open
<input type="radio" name="status" value="open" /><br />
Locked
<input type="radio" name="status" value="locked" /><br />
Events: NYI <br />
Groups: NYI <br />
<input type="button" value="Cancel" @click="$emit('cancel')"><br />
<input type="button" value="Update" @click="update()"><br />
<input type="button" value="Delete" @click="del()"><br />
<div class="container">
<div class="row textRow">
<div class="col text-right adjust-4"><label for="DLoc">Location:</label></div>
<div class="col-3">
<input id="DLoc" class="form-control" type="text" name="loc" v-model="loc" />
</div>
<div class="col-4"></div>
</div>
<div class="row textRow">
<div class="col text-right adjust-4"><label for="DNom">Name:</label></div>
<div class="col-3">
<input id="DNom" class="form-control" type="text" name="name" v-model="nom" />
</div>
<div class="col-4"></div>
</div>
<div class="row">
<div class="col text-right">
<label for="DGroups" class="adjust-1 adjust-4">Group(s):</label>
</div>
<div class="col-3">
<multiselect
id="DGroups"
:options="groups"
:closeOnSelect="false"
:multiple="true"
v-model="selGroup"
></multiselect>
</div>
<div class="col-4"></div>
</div>
<div class="adjust-11">
<div class="row ovrdLabel textRow">
<div class="col">
<input id="DEOver" class="adjust-8" type="checkbox" v-model="override" />
<label for="DEOver" class="radBoxLab">Override</label>
</div>
</div>
<div class="row textRow" v-if="override">
<div class="col text-right">Type:</div>
<div class="col-3 text-left">
<input class="adjust-8" id="DERadTL" type="radio" name="type" :value="1" v-model="type">
<label class="radBoxLab" for="DERadTL">Closed Mode</label>
<input class="adjust-8" id="DERadTOM" type="radio" name="type" :value="0" v-model="type">
<label class="radBoxLab" for="DERadTOM">Open Mode</label>
</div>
<div class="col-4"></div>
</div>
<div class="row textRow" v-if="override">
<div class="col text-right">
<label class="adjust-4">Start:</label>
</div>
<div class="col-3 text-left">
<v-date-picker v-model="startDate"></v-date-picker>
<vue-timepicker v-model="startTime" :minute-interval="5"
format="hh:mm A"></vue-timepicker>
</div>
<div class="col-4"></div>
</div>
<div class="row textRow" v-if="override">
<div class="col text-right">
<label class="adjust-4">End:</label>
</div>
<div class="col-3 text-left">
<v-date-picker v-model="endDate"></v-date-picker>
<vue-timepicker v-model="endTime" :minute-interval="5"
format="hh:mm A"></vue-timepicker>
</div>
<div class="col-4"></div>
</div>
<div class="row ovrdLabel textRow" v-if="override">
<div class="col text-right">
<label for="DEReason" class="adjust-4">Reason:</label>
</div>
<div class="col-3 text-left">
<input id="DEReason" class="form-control" type="text" v-model="reason" />
</div>
<div class="col-4"></div>
</div>
<div class="btn-group adjust-4">
<button class="btn btn-primary rounded-left" @click="$emit('cancel')">Cancel</button>
<button class="btn btn-primary" @click="update()">Update</button>
<button class="btn btn-primary rounded-right" @click="del()">Delete</button>
</div>
</div><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
</div>
</template>
<style>
#ms {
width: 20em;
position: relative;
left: 485px;
}
</style>
<script>
import Multiselect from 'vue-multiselect'
import VueTimepicker from 'vue2-timepicker'
import axios from 'axios'
import constants from '../constants'
export default {
components: { Multiselect, VueTimepicker },
mounted () {
axios.get(constants.APIHOST + '/groups')
.then(response => {
console.log('mounted', response.data.data[0])
for (const i in response.data.data) {
this.groups.push(response.data.data[i].title)
this.groupIds.push(response.data.data[i].id)
}
})
.catch(error => {
console.log(error)
})
var resp
var retSel = []
var retBef = []
axios.get(constants.APIHOST + '/doors/' + this.info.id + '/groups')
.then(response => {
console.log('getGroups', response.data.data)
resp = response.data.data
for (const i in resp) {
retSel.push(resp[i].title)
retBef.push(resp[i].id)
}
this.selGroup = retSel
this.groupsBefore = retBef
console.log('selGroup', this.selGroup)
})
.catch(error => {
console.log('getGroups', error)
})
axios.get(constants.APIHOST + '/overrides/', { params: { door_id: this.info.id } })
.then(response => {
console.log('overrides', response)
var over = response.data.data
if (over !== []) {
console.log(over)
this.override = true
this.overrideB4 = true
this.overID = over[0].id
this.reason = over[0].reason
this.type = over[0].type
this.startDate = this.dateParser(over[0].start)
this.startTime = this.timeParser(this.startDate)
this.endDate = this.dateParser(over[0].end)
this.endTime = this.timeParser(this.endDate)
}
})
.catch(error => {
console.log(error)
})
},
props: ['info'],
data () {
return {
numb: '',
nom: ''
loc: this.info.location,
nom: this.info.name,
groups: [],
groupIds: [],
selGroup: [],
groupsBefore: [],
overID: null,
override: false,
overrideB4: false,
startDate: new Date(),
endDate: new Date(),
startTime: {
hh: '',
mm: '',
A: ''
},
endTime: {
hh: '',
mm: '',
A: ''
},
type: 1,
reason: ''
}
},
methods: {
update: function () {
var sub = {}
if (this.numb !== '') {
sub.location = this.numb
if (this.loc !== '') {
sub.location = this.loc
}
if (this.nom !== '') {
sub.name = this.nom
}
axios.put(constants.APIHOST + '/doors/' + this.info.id, sub)
axios.patch(constants.APIHOST + '/doors/' + this.info.id, sub)
.then(response => {
console.log(response)
this.$emit('cancel')
console.log('patch', response)
})
.catch(error => {
console.log(this.info.id, error)
console.log(error)
})
var groupsAfter = []
var removeFrom = []
var addTo = []
for (const i in this.groups) {
if (this.selGroup.includes(this.groups[i])) {
groupsAfter.push(this.groupIds[i])
}
}
for (const i in this.groupsBefore) {
if (!(this.groupsBefore[i] in groupsAfter)) {
removeFrom.push(this.groupsBefore[i])
}
}
for (const i in groupsAfter) {
if (!(groupsAfter[i] in this.groupsBefore)) {
addTo.push(groupsAfter[i])
}
}
for (const i in removeFrom) {
axios.delete(constants.APIHOST + '/doors/' + this.info.id + '/group/' + removeFrom[i])
.then(response => {
console.log('update: remove', response)
})
.catch(error => {
console.log('update: remove', error)
})
}
for (const i in addTo) {
axios.post(constants.APIHOST + '/doors/' + this.info.id + '/group/' + addTo[i])
.then(response => {
console.log('update: add', response)
})
.catch(error => {
console.log('update: add', error)
})
}
if (this.override === this.overrideB4) {
console.log('same')
if (this.override) {
console.log('true')
const sTime = this.revTimeParser(this.startTime)
const eTime = this.revTimeParser(this.endTime)
const sDt = new Date(this.startDate.getTime())
sDt.setHours(sTime[0], sTime[1], 0)
const eDt = new Date(this.endDate.getTime())
eDt.setHours(eTime[0], eTime[1], 0)
axios.patch(constants.APIHOST + '/overrides/' + this.overID,
{ start: sDt, end: eDt, reason: this.reason })
.then(response => {
console.log('overrideUpdate', response)
})
.catch(error => {
console.log('overrideUpdate err', error)
})
}