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 @@ + + + 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 @@