diff --git a/web/src/components/measure-config/measure-config-form.ts b/web/src/components/measure-config/measure-config-form.ts
index e722693..951ffd4 100644
--- a/web/src/components/measure-config/measure-config-form.ts
+++ b/web/src/components/measure-config/measure-config-form.ts
@@ -1,6 +1,6 @@
import { Component, Emit, Prop, Vue, Watch } from 'vue-property-decorator';
import { logService } from '@/services/logging';
-import { Measure, MeasureConfig, MeasureType } from '@/models';
+import { Measure, MeasureConfig } from '@/models';
@Component({})
export class MeasureConfigForm extends Vue {
diff --git a/web/src/components/measure-details/MeasureDetails.vue b/web/src/components/measure-details/MeasureDetails.vue
new file mode 100644
index 0000000..b3b6df2
--- /dev/null
+++ b/web/src/components/measure-details/MeasureDetails.vue
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/web/src/components/measure-details/SimpleDetails.vue b/web/src/components/measure-details/SimpleDetails.vue
new file mode 100644
index 0000000..7acc111
--- /dev/null
+++ b/web/src/components/measure-details/SimpleDetails.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+ Timestamp
+ {{measure.name}}
+
+
+
+
+ {{row.tsDisplay}} |
+ {{row.value}} |
+
+
+
+
+
+
+
diff --git a/web/src/components/measure-details/measure-details.scss b/web/src/components/measure-details/measure-details.scss
new file mode 100644
index 0000000..e69de29
diff --git a/web/src/components/measure-details/measure-details.ts b/web/src/components/measure-details/measure-details.ts
new file mode 100644
index 0000000..d38fe04
--- /dev/null
+++ b/web/src/components/measure-details/measure-details.ts
@@ -0,0 +1,13 @@
+import { Component, Prop, Vue } from 'vue-property-decorator';
+import { Measure, MeasureConfig, MeasureType, Measurement, MeasurementMeta } from '@/models';
+import SimpleDetails from './SimpleDetails.vue';
+
+@Component({
+ components: { SimpleDetails }
+})
+export class MeasureDetails extends Vue {
+ @Prop() private measure!: Measure;
+ @Prop() private measurements!: Array>;
+}
+
+export default MeasureDetails;
diff --git a/web/src/components/measure-details/simple-details.scss b/web/src/components/measure-details/simple-details.scss
new file mode 100644
index 0000000..abd9cb8
--- /dev/null
+++ b/web/src/components/measure-details/simple-details.scss
@@ -0,0 +1,15 @@
+.simple-details {
+ display: flex;
+
+ table {
+ th {
+ border-bottom: 1px black solid;
+ min-width: 15em;
+ text-align: left;
+ }
+
+ td {
+ padding-left: 1em;
+ }
+ }
+}
diff --git a/web/src/components/measure-details/simple-details.ts b/web/src/components/measure-details/simple-details.ts
new file mode 100644
index 0000000..6199f9c
--- /dev/null
+++ b/web/src/components/measure-details/simple-details.ts
@@ -0,0 +1,44 @@
+import { Component, Prop, Vue } from 'vue-property-decorator';
+import { Measure, MeasureConfig, MeasureType, Measurement, MeasurementMeta } from '@/models';
+import * as moment from 'moment';
+import assign from 'lodash.assign';
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { faPencilAlt } from '@fortawesome/free-solid-svg-icons';
+
+library.add(faPencilAlt);
+
+@Component({})
+export class SimpleDetails extends Vue {
+ @Prop() private measure!: Measure;
+ @Prop() private measurements!: Array>;
+
+ private newMeasurement:
+ private moment = moment;
+ private chartOptions = {
+ noData: { text: 'no data',
+ style: { fontSize: '18px' } },
+ stroke: { curve: 'smooth' },
+ xaxis: { type: 'datetime' }
+ };
+
+ private get measurementChartData(): ApexAxisChartSeries {
+ const measurementData = this.measurements || [];
+
+ return [{
+ name: this.measure.name,
+ data: measurementData.map((m) => ({ x: m.timestamp.toISOString(), y: m.value }))
+ }];
+ }
+
+ private get measurementTableData() {
+ return (this.measurements || []).map((m) => {
+ return assign({}, m, {
+ tsDisplay: moment(m.timestamp).format('MMM Do, HH:mm'),
+ tsSort: m.timestamp.toISOString()
+ });
+ });
+ }
+
+}
+
+export default SimpleDetails;
diff --git a/web/src/components/measurement-entry/MeasurementEntry.vue b/web/src/components/measurement-entry/MeasurementEntry.vue
new file mode 100644
index 0000000..c926bd5
--- /dev/null
+++ b/web/src/components/measurement-entry/MeasurementEntry.vue
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/web/src/components/measurement-entry/SimpleEntry.vue b/web/src/components/measurement-entry/SimpleEntry.vue
new file mode 100644
index 0000000..de48c94
--- /dev/null
+++ b/web/src/components/measurement-entry/SimpleEntry.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
diff --git a/web/src/components/measurement-entry/measurement-entry.scss b/web/src/components/measurement-entry/measurement-entry.scss
new file mode 100644
index 0000000..e69de29
diff --git a/web/src/components/measurement-entry/measurement-entry.ts b/web/src/components/measurement-entry/measurement-entry.ts
new file mode 100644
index 0000000..09221a8
--- /dev/null
+++ b/web/src/components/measurement-entry/measurement-entry.ts
@@ -0,0 +1,21 @@
+import { Component, Emit, Prop, Vue, Watch } from 'vue-property-decorator';
+import { Measure, MeasureConfig, MeasureType, Measurement, MeasurementMeta } from '@/models';
+import SimpleEntry from './SimpleEntry.vue';
+
+@Component({
+ components: { SimpleEntry }
+})
+export class MeasurementEntry extends Vue {
+ @Prop() private measure!: Measure;
+ @Prop() private value!: Measurement;
+
+ @Watch('value', { immediate: true, deep: true })
+ @Emit('input')
+ private onMeasurementChanged(newVal: Measurement, oldVal: Measurement) {
+ newVal.measureId = this.measure.id;
+ return newVal;
+ }
+
+}
+
+export default MeasurementEntry;
diff --git a/web/src/components/measurement-entry/simple-entry.scss b/web/src/components/measurement-entry/simple-entry.scss
new file mode 100644
index 0000000..e69de29
diff --git a/web/src/components/measurement-entry/simple-entry.ts b/web/src/components/measurement-entry/simple-entry.ts
new file mode 100644
index 0000000..05d7fb2
--- /dev/null
+++ b/web/src/components/measurement-entry/simple-entry.ts
@@ -0,0 +1,24 @@
+import { Component, Emit, Prop, Vue, Watch } from 'vue-property-decorator';
+import { Measure, MeasureConfig, MeasureType, Measurement, MeasurementMeta } from '@/models';
+
+@Component({})
+export class SimpleEntry extends Vue {
+ @Prop() public measure!: Measure;
+ @Prop() public value!: Measurement;
+ @Prop() public disabled: boolean = false;
+ private editTimestamp: boolean = false;
+
+ @Watch('value', { immediate: true, deep: true })
+ @Emit('input')
+ private onMeasurementChanged(newVal: Measurement, oldVal: Measurement) {
+ newVal.extData.measureType = 'simple' as MeasureType;
+
+ if (typeof(newVal.value) === 'string' ) {
+ newVal.value = parseInt(newVal.value, 10);
+ }
+ return newVal;
+ }
+
+}
+
+export default SimpleEntry;
diff --git a/web/src/store-modules/measurement.ts b/web/src/store-modules/measurement.ts
index a82892b..6058e4a 100644
--- a/web/src/store-modules/measurement.ts
+++ b/web/src/store-modules/measurement.ts
@@ -18,6 +18,11 @@ export interface SetMeasurementsParameters {
measurements: Array>;
}
+export interface MeasureAndMeasurement {
+ measure: Measure;
+ measurement: Measurement;
+}
+
const logger = logService.getLogger('/store-modules/measurement');
@Module({ namespaced: true, name: 'measurement' })
@@ -31,9 +36,27 @@ export class MeasurementStoreModule extends VuexModule {
this.context.commit('SET_MEASUREMENTS', { measure, measurements });
}
+ @Action({ rawError: true })
+ public async createMeasurement(data: MeasureAndMeasurement) {
+ logger.trace('Creating new measurement for ' + data.measure.slug);
+ const newMeasurement = await api.createMeasurement(data.measure.slug, data.measurement);
+ this.context.commit('SET_MEASUREMENT', { measure: data.measure, measurement: newMeasurement });
+ }
+
@Mutation
public SET_MEASUREMENTS({ measure: measure, measurements: measurements }: SetMeasurementsParameters) {
this.measurements = assign({}, this.measurements, { [measure.id]: measurements });
}
+ @Mutation
+ public SET_MEASUREMENT({ measure: measure, measurement: measurement }: MeasureAndMeasurement) {
+ const existing = this.measurements[measure.id] || [];
+ const newMeasurements = existing.slice();
+
+ const index = findIndex(existing, { id: measurement.id });
+ if (index > 0) { newMeasurements.push(measurement); }
+ else { newMeasurements[index] = measurement; }
+ this.measurements = assign({}, this.measurements, { [measure.id]: newMeasurements });
+ }
+
}
diff --git a/web/src/views/Measure.vue b/web/src/views/Measure.vue
index 6b41d6e..39d1364 100644
--- a/web/src/views/Measure.vue
+++ b/web/src/views/Measure.vue
@@ -1,9 +1,13 @@
+