commit 8d4945b5fa3063cd3c629a2355be9ffa7142ac0b
parent 5ae82004b2571537600fb288d143099d4f737893
Author: Vetle Haflan <vetle.haflan@luxsave.com>
Date: Sat, 23 May 2020 15:53:41 +0200
Implement prettier time picker
Closes #7
Diffstat:
3 files changed, 143 insertions(+), 24 deletions(-)
diff --git a/internal/services/services.go b/internal/services/services.go
@@ -45,8 +45,8 @@ func GetByID(id uint64) *Service {
}
// GetAll returns all services in the database (TODO)
-func GetAll() ([]*Service) {
- services := []*Service{}
+func GetAll() []*Service {
+ services := []*Service{}
db := database.GetDB()
db.View(func(tx *bbolt.Tx) error {
b := tx.Bucket(database.BucketKeyServices)
@@ -58,9 +58,9 @@ func GetAll() ([]*Service) {
log.Panic("The service-tokens bucket does not exist")
}
- // Go through all k-v pairs in the service *tokens* bucket, in order to get service bucket IDs
+ // Go through all k-v pairs in the service *tokens* bucket, in order to get service bucket IDs.
// Use the ID to get the service bucket and create service fromBucket, then set the service token
- // using the key from the stb
+ // using the key from the stb. The returned list of services will be sorted by *token*.
return stb.ForEach(func(token, id []byte) error {
sb := b.Bucket(id)
service := new(Service)
diff --git a/ui/src/Services.vue b/ui/src/Services.vue
@@ -1,22 +1,29 @@
<template>
<div class="services-wrapper">
- <div v-for="service in services">
- {{ service.id }} :
- <input :type="showPasswords ? 'text' : 'password'" :value="service.token">
- <input type="text" :value="service.name">
- <input type="text" :value="service.description">
- <input type="number" :value="service.period">
- <input type="number" :value="service.maxevents">
+ <div class="service" v-for="service in services" :key="service.id">
+ {{ service.id }} : <br/>
+
+ <span>Token</span>
+ <input :type="showPasswords ? 'text' : 'password'" :value="service.token"/> <br/>
+
+ <span>Name</span>
+ <input type="text" :value="service.name"/> <br/>
+
+ <span>Description</span>
+ <input type="text" :value="service.description"/> <br/>
+
+ <span>Max number of events</span>
+ <input type="number" :value="service.maxevents"/> <br/>
+
+ <span>Expectation period</span>
+ <time-picker :value="service.period"/> <br/>
</div>
- <input :type="showPasswords ? 'text' : 'password'" v-model="newService.token" placeholder="Token">
- <input type="text" v-model="newService.name" placeholder="Name">
- <input type="text" v-model="newService.description"
- placeholder="Description">
- <input type="number" v-model.number="newService.period"
- placeholder="Expectation Period">
- <input type="number" v-model.number="newService.maxevents"
- placeholder="Max number of events">
+ <input :type="showPasswords ? 'text' : 'password'" v-model="newService.token" placeholder="Token"> <br/>
+ <input type="text" v-model="newService.name" placeholder="Name"> <br/>
+ <input type="text" v-model="newService.description" placeholder="Description"> <br/>
+ <input type="number" v-model.number="newService.maxevents" placeholder="Max number of events"> <br/>
+ <time-picker v-model="newService.period" placeholder="Expectation Period"/> <br/>
<button @click="addService">Add service</button>
</div>
@@ -24,8 +31,10 @@
<script>
import api from "./requests.js";
+ import TimePicker from "./TimePicker.vue";
export default {
name: "Services",
+ components: {TimePicker},
data() {
return {
services: [],
@@ -33,7 +42,7 @@
token: "",
name: "",
description: "",
- period: 0,
+ period: {"number": 0, "scalar": 0},
maxevents: 0
},
showPasswords: true
@@ -41,24 +50,55 @@
},
methods: {
addService() {
- api.postService(this.newService,
+ // Make unix milli time formatted period before sending
+ const formattedService = {
+ ...this.newService,
+ };
+ formattedService.period = this.newService.period.scalar * this.newService.period.number;
+ console.log(formattedService);
+ api.postService(formattedService,
success => {
this.services.push(this.newService);
this.newService = {
token: "", name: "", description: "",
- period: 0, maxevents: 0
+ period: {"number": 0, "scalar": 0}, maxevents: 0
};
},
error => {
this.$emit("error");
}
);
+ },
+ getExpectations(unixMilliTime) {
+ const units = [
+ { "unit": "weeks", "scalar": 604800000 },
+ { "unit": "days", "scalar": 86400000 },
+ { "unit": "hours", "scalar": 3600000 },
+ { "unit": "minutes", "scalar": 60000 },
+ { "unit": "seconds", "scalar": 1000 },
+ { "unit": "none", "scalar": 0 }
+ ];
+ if (unixMilliTime === 0) {
+ return { "number": 0, "scalar": 0 };
+ }
+ for (let i = 0; i < units.length; i++) {
+ let u = units[i];
+ if (unixMilliTime % u.scalar === 0) {
+ return {
+ "scalar": u.scalar,
+ "number": unixMilliTime / u.scalar
+ };
+ }
+ }
}
},
mounted() {
api.getServices(
services => {
- this.services = services;
+ this.services = services.map(s => {
+ s.period = this.getExpectations(s.period);
+ return s;
+ });
},
error => {
console.log(error);
@@ -69,5 +109,29 @@
}
</script>
-<style scoped>
+<style >
+span {
+ font-weight: bold;
+}
+input {
+ border-width: 0 0 1px;
+ border-color: #bbf;
+ background-color: inherit;
+ outline-width: 0;
+ flex: 1;
+ margin-bottom: 3px;
+ width: 100%;
+}
+input:focus {
+ outline-width: 0;
+}
+input::placeholder {
+ color: #bbf;
+}
+div .service {
+ border: 1px solid blueviolet;
+ border-radius: 3px;
+ margin-bottom: 1em;
+ padding: 1em;
+}
</style>
diff --git a/ui/src/TimePicker.vue b/ui/src/TimePicker.vue
@@ -0,0 +1,54 @@
+<template>
+ <div>
+ <input type="number" @input="update('number', $event)" :value="number"/>
+ <select @input="update('scalar', $event)" :value="scalar">
+ <option v-for="u in units"
+ :key="u.unit"
+ :value="u.scalar"
+ :selected="scalar === u.scalar">
+ {{u.unit}}
+ </option>
+ </select>
+ </div>
+</template>
+
+<script>
+ export default {
+ name: "TimePicker",
+ props: {
+ value: Object
+ },
+ data() {
+ return {
+ number: this.value.number,
+ scalar: this.value.scalar,
+ units: [
+ { "unit": "weeks", "scalar": 604800000 },
+ { "unit": "days", "scalar": 86400000 },
+ { "unit": "hours", "scalar": 3600000 },
+ { "unit": "minutes", "scalar": 60000 },
+ { "unit": "seconds", "scalar": 1000 },
+ { "unit": "none", "scalar": 0 },
+ ]
+ }
+ },
+ watch: {
+ value: {
+ immediate: true,
+ handler(val) {
+ this.number = val.number;
+ this.scalar = val.scalar;
+ }
+ }
+ },
+ methods: {
+ update(prop, e) {
+ console.log(e)
+ const newValue = this.value;
+ newValue[prop] = e.target.value;
+ this.$emit("input", newValue);
+ },
+
+ }
+ }
+</script>+
\ No newline at end of file