WIP Adding measurement details and entry for simple measurements.
This commit is contained in:
@ -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 {
|
||||
|
8
web/src/components/measure-details/MeasureDetails.vue
Normal file
8
web/src/components/measure-details/MeasureDetails.vue
Normal file
@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<div>
|
||||
<SimpleDetails v-if="measure.config.type === 'simple'"
|
||||
:measure=measure :measurements=measurements />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" src="./measure-details.ts"></script>
|
||||
<style lang="scss" src="./measure-details.scss"></style>
|
22
web/src/components/measure-details/SimpleDetails.vue
Normal file
22
web/src/components/measure-details/SimpleDetails.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<div class=simple-details>
|
||||
<apex-chart type="line" :options=chartOptions :series=measurementChartData />
|
||||
<v-table :data=measurementTableData>
|
||||
<thead slot=head >
|
||||
<tr>
|
||||
<v-th sortKey=tsSort defaultSort=asc >Timestamp</v-th>
|
||||
<v-th sortKey=value >{{measure.name}}</v-th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody slot=body slot-scope={displayData} >
|
||||
<tr v-for="row in displayData" :key="row.id">
|
||||
<td>{{row.tsDisplay}}</td>
|
||||
<td>{{row.value}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</v-table>
|
||||
<SimpleEntry :measure=measure v-model=
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" src="./simple-details.ts"></script>
|
||||
<style lang="scss" src="./simple-details.scss"></style>
|
13
web/src/components/measure-details/measure-details.ts
Normal file
13
web/src/components/measure-details/measure-details.ts
Normal file
@ -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<MeasureConfig>;
|
||||
@Prop() private measurements!: Array<Measurement<MeasurementMeta>>;
|
||||
}
|
||||
|
||||
export default MeasureDetails;
|
15
web/src/components/measure-details/simple-details.scss
Normal file
15
web/src/components/measure-details/simple-details.scss
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
44
web/src/components/measure-details/simple-details.ts
Normal file
44
web/src/components/measure-details/simple-details.ts
Normal file
@ -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<MeasureConfig>;
|
||||
@Prop() private measurements!: Array<Measurement<MeasurementMeta>>;
|
||||
|
||||
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;
|
@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<div>
|
||||
<SimpleEntry v-if="measure.config.type === 'simple'"
|
||||
:measure=measure v-model=value />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" src="./measurement-entry.ts"></script>
|
||||
<style lang="scss" src="./measurement-entry.scss"></style>
|
20
web/src/components/measurement-entry/SimpleEntry.vue
Normal file
20
web/src/components/measurement-entry/SimpleEntry.vue
Normal file
@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<fieldset>
|
||||
<div>
|
||||
<label for=timestamp>Timestamp</label>
|
||||
<input type=datetime-local
|
||||
v-model=value.timestamp
|
||||
v-show=editTimestamp
|
||||
:disabled=disabled />
|
||||
<span v-show="!editTimestamp">
|
||||
now <a href="#" v-on:click.stop.prevent="editTimestamp = true"> (set a time)</a>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<label for=measurementValue>{{measure.name}}</label>
|
||||
<input required type=number v-model=value.value :disabled=disabled />
|
||||
</div>
|
||||
</fieldset>
|
||||
</template>
|
||||
<script lang="ts" src="./simple-entry.ts"></script>
|
||||
<style lang="scss" src="./simple-entry.scss"></style>
|
21
web/src/components/measurement-entry/measurement-entry.ts
Normal file
21
web/src/components/measurement-entry/measurement-entry.ts
Normal file
@ -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<MeasureConfig>;
|
||||
@Prop() private value!: Measurement<MeasurementMeta>;
|
||||
|
||||
@Watch('value', { immediate: true, deep: true })
|
||||
@Emit('input')
|
||||
private onMeasurementChanged(newVal: Measurement<MeasurementMeta>, oldVal: Measurement<MeasurementMeta>) {
|
||||
newVal.measureId = this.measure.id;
|
||||
return newVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MeasurementEntry;
|
24
web/src/components/measurement-entry/simple-entry.ts
Normal file
24
web/src/components/measurement-entry/simple-entry.ts
Normal file
@ -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<MeasureConfig>;
|
||||
@Prop() public value!: Measurement<MeasurementMeta>;
|
||||
@Prop() public disabled: boolean = false;
|
||||
private editTimestamp: boolean = false;
|
||||
|
||||
@Watch('value', { immediate: true, deep: true })
|
||||
@Emit('input')
|
||||
private onMeasurementChanged(newVal: Measurement<MeasurementMeta>, oldVal: Measurement<MeasurementMeta>) {
|
||||
newVal.extData.measureType = 'simple' as MeasureType;
|
||||
|
||||
if (typeof(newVal.value) === 'string' ) {
|
||||
newVal.value = parseInt(newVal.value, 10);
|
||||
}
|
||||
return newVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default SimpleEntry;
|
Reference in New Issue
Block a user