diff --git a/web/package-lock.json b/web/package-lock.json
index 7f5048e..02bc19f 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -1744,6 +1744,21 @@
}
}
},
+ "apexcharts": {
+ "version": "3.6.5",
+ "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.6.5.tgz",
+ "integrity": "sha512-HSDNjTPMEpQaM0MadPj9f6gNvBKSmQXuC100h4Ev2mQFjC1rJId6b1KgF2yKh0In+iXuTXxszI58ozWhKNkbYQ==",
+ "requires": {
+ "promise-polyfill": "8.1.0",
+ "svg.draggable.js": "^2.2.1",
+ "svg.easing.js": "^2.0.0",
+ "svg.filter.js": "^2.0.2",
+ "svg.js": "^2.6.6",
+ "svg.pathmorphing.js": "^0.1.3",
+ "svg.resize.js": "^1.4.1",
+ "svg.select.js": "^2.1.2"
+ }
+ },
"append-transform": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz",
@@ -6865,7 +6880,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"aproba": {
"version": "1.2.0",
@@ -6893,6 +6909,7 @@
"version": "1.1.11",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -6907,7 +6924,8 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"concat-map": {
"version": "0.0.1",
@@ -6918,7 +6936,8 @@
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -7035,7 +7054,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"ini": {
"version": "1.3.5",
@@ -7047,6 +7067,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -7061,6 +7082,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -7068,12 +7090,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -7092,6 +7116,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -7172,7 +7197,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -7184,6 +7210,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"wrappy": "1"
}
@@ -7269,7 +7296,8 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -7305,6 +7333,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -7324,6 +7353,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -7367,12 +7397,14 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
}
}
},
@@ -11900,6 +11932,11 @@
"integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
"dev": true
},
+ "promise-polyfill": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.0.tgz",
+ "integrity": "sha512-OzSf6gcCUQ01byV4BgwyUCswlaQQ6gzXc23aLQWhicvfX9kfsUiUhgt3CCQej8jDnl8/PhGF31JdHX2/MzF3WA=="
+ },
"prompts": {
"version": "0.1.14",
"resolved": "https://registry.npmjs.org/prompts/-/prompts-0.1.14.tgz",
@@ -13687,6 +13724,60 @@
"integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=",
"dev": true
},
+ "svg.draggable.js": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz",
+ "integrity": "sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==",
+ "requires": {
+ "svg.js": "^2.0.1"
+ }
+ },
+ "svg.easing.js": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/svg.easing.js/-/svg.easing.js-2.0.0.tgz",
+ "integrity": "sha1-iqmUawqOJ4V6XEChDrpAkeVpHxI=",
+ "requires": {
+ "svg.js": ">=2.3.x"
+ }
+ },
+ "svg.filter.js": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/svg.filter.js/-/svg.filter.js-2.0.2.tgz",
+ "integrity": "sha1-kQCOFROJ3ZIwd5/L5uLJo2LRwgM=",
+ "requires": {
+ "svg.js": "^2.2.5"
+ }
+ },
+ "svg.js": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz",
+ "integrity": "sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA=="
+ },
+ "svg.pathmorphing.js": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz",
+ "integrity": "sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==",
+ "requires": {
+ "svg.js": "^2.4.0"
+ }
+ },
+ "svg.resize.js": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/svg.resize.js/-/svg.resize.js-1.4.3.tgz",
+ "integrity": "sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==",
+ "requires": {
+ "svg.js": "^2.6.5",
+ "svg.select.js": "^2.1.2"
+ }
+ },
+ "svg.select.js": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-2.1.2.tgz",
+ "integrity": "sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==",
+ "requires": {
+ "svg.js": "^2.2.5"
+ }
+ },
"svgo": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/svgo/-/svgo-1.1.1.tgz",
@@ -14594,6 +14685,11 @@
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.7.tgz",
"integrity": "sha512-g7ADfQ82QU+j6F/bVDioVQf2ccIMYLuR4E8ev+RsDBlmwRkhGO3HhgF4PF9vpwjdPpxyb1zzLur2nQ2oIMAMEg=="
},
+ "vue-apexcharts": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/vue-apexcharts/-/vue-apexcharts-1.3.2.tgz",
+ "integrity": "sha512-3a3v6FKUlpD3BHWiDhuN/7Jcho9pE3+r6PEUccdzfpRFj0jn9W+zAHtaiKrdbBsTqXPKDfbd4dkT25SvBo/cxw=="
+ },
"vue-class-component": {
"version": "6.3.2",
"resolved": "https://registry.npmjs.org/vue-class-component/-/vue-class-component-6.3.2.tgz",
diff --git a/web/package.json b/web/package.json
index e04caf3..46926c8 100644
--- a/web/package.json
+++ b/web/package.json
@@ -14,12 +14,14 @@
"@fortawesome/vue-fontawesome": "^0.1.5",
"@types/js-cookie": "^2.2.1",
"@types/lodash.merge": "^4.6.5",
+ "apexcharts": "^3.6.5",
"axios": "^0.18.0",
"js-cookie": "^2.2.0",
"keen-ui": "^1.1.2",
"lodash.merge": "^4.6.1",
"register-service-worker": "^1.5.2",
"vue": "^2.6.6",
+ "vue-apexcharts": "^1.3.2",
"vue-class-component": "^6.0.0",
"vue-property-decorator": "^7.0.0",
"vue-router": "^3.0.1",
diff --git a/web/src/components/MeasureSummary.vue b/web/src/components/MeasureSummary.vue
new file mode 100644
index 0000000..d21d044
--- /dev/null
+++ b/web/src/components/MeasureSummary.vue
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/web/src/components/measure-summary.scss b/web/src/components/measure-summary.scss
new file mode 100644
index 0000000..6bb0562
--- /dev/null
+++ b/web/src/components/measure-summary.scss
@@ -0,0 +1,9 @@
+@import '~@/styles/vars';
+
+.measure-summary {
+ display: inline-block;
+
+ h2 {
+ border-bottom: solid thin $fg-primary;
+ }
+}
diff --git a/web/src/components/measure-summary.ts b/web/src/components/measure-summary.ts
new file mode 100644
index 0000000..1b7f5ba
--- /dev/null
+++ b/web/src/components/measure-summary.ts
@@ -0,0 +1,27 @@
+import { Component, Prop, Vue } from 'vue-property-decorator';
+import { Measure, MeasureConfig, Measurement, MeasurementMeta } from '@/models';
+import { measurementStore } from '@/store';
+
+@Component
+export class MeasureSummary extends Vue {
+ @Prop() private measure!: Measure;
+
+ private chartOptions = {
+ chart: { sparkline: { enabled: true } },
+ grid: { padding: { top: 20 }},
+ stroke: { curve: 'smooth' }
+ };
+
+ private chartData = [
+ { name: 'Test', data: [1, 10, 4, 6, 2] }
+ ];
+
+ private measurements: Array> = [];
+
+ private mounted() {
+ this.measurements =
+ }
+
+}
+
+export default MeasureSummary;
diff --git a/web/src/main.ts b/web/src/main.ts
index dbe10c7..b2d1cb6 100644
--- a/web/src/main.ts
+++ b/web/src/main.ts
@@ -7,10 +7,12 @@ import router from './router';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import SmartTable from 'vuejs-smart-table';
+import ApexChart from 'vue-apexcharts';
import './registerServiceWorker';
Vue.component('fa-icon', FontAwesomeIcon);
+Vue.component('apex-chart', ApexChart);
Vue.use(SmartTable);
new Vue({
diff --git a/web/src/services/pm-api-client.ts b/web/src/services/pm-api-client.ts
index c0bb4de..9f0abec 100644
--- a/web/src/services/pm-api-client.ts
+++ b/web/src/services/pm-api-client.ts
@@ -1,5 +1,5 @@
import { default as Axios, AxiosInstance } from 'axios';
-import { ApiToken, LoginSubmit, Measure, Measurement, User } from '@/models';
+import { ApiToken, LoginSubmit, Measure, MeasureConfig, Measurement, MeasurementMeta, User } from '@/models';
import { Logger, logService } from '@/services/logging';
import merge from 'lodash.merge';
@@ -108,17 +108,17 @@ export class PmApiClient {
return true;
}
- public async getAllMeasures(): Promise {
+ public async getAllMeasures(): Promise>> {
const resp = await this.http.get(`/measures`);
return resp.data;
}
- public async createMeasure(measure: Measure): Promise {
+ public async createMeasure(measure: Measure): Promise> {
const resp = await this.http.post(`/measures`);
return resp.data;
}
- public async getMeasure(slug: string): Promise {
+ public async getMeasure(slug: string): Promise> {
const resp = await this.http.get(`/measures/${slug}`);
return resp.data;
}
@@ -129,16 +129,16 @@ export class PmApiClient {
}
public async getMeasurements(measureSlug: string)
- : Promise {
+ : Promise>> {
const resp = await this.http.get(`/measure/${measureSlug}`);
return resp.data;
}
- public async createMeasurement(
+ public async createMeasurement(
measureSlug: string,
- measurement: Measurement)
- : Promise {
+ measurement: Measurement)
+ : Promise> {
const resp = await this.http.post(`/measure/${measureSlug}`, measurement);
return resp.data;
@@ -147,7 +147,7 @@ export class PmApiClient {
public async getMeasurement(
measureSlug: string,
measurementId: string)
- : Promise {
+ : Promise> {
const resp = await this.http
.get(`/measure/${measureSlug}/${measurementId}`);
@@ -156,8 +156,8 @@ export class PmApiClient {
public async updateMeasurement(
measureSlug: string,
- measurement: Measurement)
- : Promise {
+ measurement: Measurement)
+ : Promise> {
const resp = await this.http
.put(`/measure/${measureSlug}/${measurement.id}`, measurement);
diff --git a/web/src/store-modules/measure.ts b/web/src/store-modules/measure.ts
index 8391ace..a8a8caa 100644
--- a/web/src/store-modules/measure.ts
+++ b/web/src/store-modules/measure.ts
@@ -7,13 +7,13 @@ import {
VuexModule
} from 'vuex-module-decorators';
import { keyBy } from 'lodash';
-import { User, Measure } from '@/models';
+import { User, Measure, MeasureConfig } from '@/models';
import api from '@/services/pm-api-client';
import { logService } from '@/services/logging';
@Module({ namespaced: true, name: 'measure' })
export class MeasureStoreModule extends VuexModule {
- public measures: { [key: string]: Measure } = {};
+ public measures: { [key: string]: Measure } = {};
private log = logService.getLogger('/store-modules/measure');
@@ -28,7 +28,7 @@ export class MeasureStoreModule extends VuexModule {
return await api.getMeasure(slug);
}
- @Mutation private SET_MEASURE(measure: Measure) {
+ @Mutation private SET_MEASURE(measure: Measure) {
this.measures[measure.slug] = measure;
}
}
diff --git a/web/src/store-modules/measurement.ts b/web/src/store-modules/measurement.ts
new file mode 100644
index 0000000..5531e58
--- /dev/null
+++ b/web/src/store-modules/measurement.ts
@@ -0,0 +1,21 @@
+import {
+ Action,
+ getModule,
+ Module,
+ Mutation,
+ VuexModule
+} from 'vuex-module-decorators';
+import { Measurement, MeasurementMeta } from '@/models';
+import api from '@/services/pm-api-client';
+
+@Module({ namespaced: true, name: 'measurement' })
+export class MeasurementStoreModule extends VuexModule {
+ public measurements: { [key: string]: Array> } = {};
+
+ @Action({ commit: 'SET_MEASUREMENTS', rawError: true })
+ public async getchMeasurements(measureSlug: string) {
+ return await api.getMeasurements(measureSlug);
+ }
+
+ // @Mutation private SET_MEASUREMENTS(
+}
diff --git a/web/src/store.ts b/web/src/store.ts
index 9567e58..27993f6 100644
--- a/web/src/store.ts
+++ b/web/src/store.ts
@@ -4,6 +4,7 @@ import { getModule } from 'vuex-module-decorators';
import { ApiTokenStoreModule } from './store-modules/api-token';
import { AuthStoreModule } from './store-modules/auth';
import { MeasureStoreModule } from './store-modules/measure';
+import { MeasurementStoreModule } from './store-modules/measurement';
import { UserStoreModule } from './store-modules/user';
Vue.use(Vuex);
@@ -16,6 +17,7 @@ export const store = new Vuex.Store({
apiToken: ApiTokenStoreModule,
auth: AuthStoreModule,
measure: MeasureStoreModule,
+ measurements: MeasurementStoreModule,
user: UserStoreModule
}
});
@@ -23,4 +25,5 @@ export const store = new Vuex.Store({
export const apiTokenStore = getModule(ApiTokenStoreModule, store);
export const authStore = getModule(AuthStoreModule, store);
export const measureStore = getModule(MeasureStoreModule, store);
+export const measurementStore = getModule(MeasurementStoreModule, store);
export const userStore = getModule(UserStoreModule, store);
diff --git a/web/src/types/global.d.ts b/web/src/types/global.d.ts
new file mode 100644
index 0000000..afa75c4
--- /dev/null
+++ b/web/src/types/global.d.ts
@@ -0,0 +1 @@
+declare const global: any;
diff --git a/web/src/views/Measures.vue b/web/src/views/Measures.vue
index 64a9918..6e1248b 100644
--- a/web/src/views/Measures.vue
+++ b/web/src/views/Measures.vue
@@ -4,9 +4,13 @@
Things You Are Measuring
-
-
{{measure.name}}
-
+
+
diff --git a/web/src/views/measures.ts b/web/src/views/measures.ts
index d8337cd..747476b 100644
--- a/web/src/views/measures.ts
+++ b/web/src/views/measures.ts
@@ -1,9 +1,13 @@
import { Component, Vue } from 'vue-property-decorator';
+import MeasureSummary from '@/components/MeasureSummary.vue';
+import Test from '@/components/Test.vue';
import { measureStore } from '@/store';
@Component({
- components: { }
+ components: { MeasureSummary }
})
-export default class Measures extends Vue {
+export class Measures extends Vue {
private get measures() { return measureStore.measures; }
}
+
+export default Measures;