web: WIP edit measure configuration.
This commit is contained in:
parent
c685f55d15
commit
f4f695ce80
@ -8,6 +8,7 @@ import Measures from '@/views/Measures.vue';
|
|||||||
import NewMeasure from '@/views/NewMeasure.vue';
|
import NewMeasure from '@/views/NewMeasure.vue';
|
||||||
import NewMeasurement from '@/views/NewMeasurement.vue';
|
import NewMeasurement from '@/views/NewMeasurement.vue';
|
||||||
import DeleteMeasure from '@/views/DeleteMeasure.vue';
|
import DeleteMeasure from '@/views/DeleteMeasure.vue';
|
||||||
|
import EditMeasure from '@/views/EditMeasure.vue';
|
||||||
import NotFound from '@/views/NotFound.vue';
|
import NotFound from '@/views/NotFound.vue';
|
||||||
import QuickPanels from '@/views/QuickPanels.vue';
|
import QuickPanels from '@/views/QuickPanels.vue';
|
||||||
import UserAccount from '@/views/UserAccount.vue';
|
import UserAccount from '@/views/UserAccount.vue';
|
||||||
@ -74,6 +75,11 @@ const router = new Router({
|
|||||||
name: 'delete-measure',
|
name: 'delete-measure',
|
||||||
component: DeleteMeasure
|
component: DeleteMeasure
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/edit/measure/:slug',
|
||||||
|
name: 'edit-measure',
|
||||||
|
component: EditMeasure
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '*',
|
path: '*',
|
||||||
name: 'not-found',
|
name: 'not-found',
|
||||||
|
@ -123,6 +123,11 @@ export class PmApiClient {
|
|||||||
return resp.data;
|
return resp.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async updateMeasure<T extends MeasureConfig>(measure: Measure<T>): Promise<Measure<T>> {
|
||||||
|
const resp = await this.http.post(`/measures/${measure.slug}`, measure);
|
||||||
|
return resp.data;
|
||||||
|
}
|
||||||
|
|
||||||
public async deleteMeasure(slug: string): Promise<boolean> {
|
public async deleteMeasure(slug: string): Promise<boolean> {
|
||||||
const resp = await this.http.delete(`/measures/${slug}`);
|
const resp = await this.http.delete(`/measures/${slug}`);
|
||||||
return true;
|
return true;
|
||||||
|
@ -30,18 +30,24 @@ export class MeasureStoreModule extends VuexModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Action({ rawError: true })
|
@Action({ rawError: true })
|
||||||
public async createMeasure(m: Measure<MeasureConfig>) {
|
public async createMeasure<T extends MeasureConfig>(m: Measure<T>) {
|
||||||
const newMeasure = await api.createMeasure(m);
|
const newMeasure = await api.createMeasure(m);
|
||||||
this.context.commit('SET_MEASURE', newMeasure);
|
this.context.commit('SET_MEASURE', newMeasure);
|
||||||
return newMeasure;
|
return newMeasure;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Action({ rawError: true })
|
@Action({ rawError: true })
|
||||||
public async deleteMeasure(m: Measure<MeasureConfig>) {
|
public async deleteMeasure<T extends MeasureConfig>(m: Measure<T>) {
|
||||||
const delResponse = await api.deleteMeasure(m.slug);
|
const delResponse = await api.deleteMeasure(m.slug);
|
||||||
this.context.commit('DELETE_MEASURE', m);
|
this.context.commit('DELETE_MEASURE', m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Action({ rawError: true })
|
||||||
|
public async updateMeasure<T extends MeasureConfig>(m: Measure<T>) {
|
||||||
|
const updatedMeasure = await api.updateMeasure(m);
|
||||||
|
return updatedMeasure;
|
||||||
|
}
|
||||||
|
|
||||||
@Mutation private SET_MEASURE<T extends MeasureConfig>(measure: Measure<T>) {
|
@Mutation private SET_MEASURE<T extends MeasureConfig>(measure: Measure<T>) {
|
||||||
this.measures = assign({}, this.measures, {[measure.slug]: measure});
|
this.measures = assign({}, this.measures, {[measure.slug]: measure});
|
||||||
}
|
}
|
||||||
|
52
web/src/views/EditMeasure.vue
Normal file
52
web/src/views/EditMeasure.vue
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<template>
|
||||||
|
<div id=edit-measure>
|
||||||
|
<div class=header>
|
||||||
|
<h1>Edit Measure</h1>
|
||||||
|
<h2>{{measure.name}}</h2>
|
||||||
|
</div>
|
||||||
|
<form @submit.prevent=updateMeasure() class=edit-measure-form>
|
||||||
|
<fieldset>
|
||||||
|
<div>
|
||||||
|
<label for=measureName>Display Name</label>
|
||||||
|
<input
|
||||||
|
:disabled=waiting
|
||||||
|
type=text
|
||||||
|
name=measureName
|
||||||
|
placeholder="what you are measuring"
|
||||||
|
required
|
||||||
|
v-model="measure.name" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for=measureDescription>Description</label>
|
||||||
|
<textarea
|
||||||
|
:disabled=waiting
|
||||||
|
name=measureDescription
|
||||||
|
placeholder="optional description"
|
||||||
|
v-model="measure.description" ></textarea>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for=measureSlug>Short name (slug)</label>
|
||||||
|
<input
|
||||||
|
:disabled=waiting
|
||||||
|
type=text
|
||||||
|
name=measureDescription
|
||||||
|
:placeholder='slugFromName + " (default)"'
|
||||||
|
:value="measure.slug"
|
||||||
|
@input="measure.slug = slugify($event.target.value)"/>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<MeasureConfigForm
|
||||||
|
v-model=measure.config
|
||||||
|
:disabled=waiting
|
||||||
|
measureExists=false />
|
||||||
|
<div v-if='!waiting' class=form-actions>
|
||||||
|
<button class=btn-action>Update</button>
|
||||||
|
<a class=btn @click="$router.go(-1)">Cancel</a>
|
||||||
|
</div>
|
||||||
|
<div v-if='waiting' class=form-waiting>
|
||||||
|
<div class=wait-spinner>working <fa-icon icon=sync spin /></div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang=ts src=./edit-measure.ts></script>
|
@ -5,12 +5,26 @@
|
|||||||
<h1>{{measure.name}}</h1>
|
<h1>{{measure.name}}</h1>
|
||||||
<h2>{{measure.description}}</h2>
|
<h2>{{measure.description}}</h2>
|
||||||
</div>
|
</div>
|
||||||
<router-link title="Delete Measure" :to="'/delete/measure/' + measure.slug" class=btn>
|
<div class=actions>
|
||||||
<fa-icon icon=trash></fa-icon>
|
<router-link
|
||||||
</router-link>
|
title="Delete Measure"
|
||||||
<router-link :to="'/new/measurement/' + measure.slug" class=btn-action>
|
:to="'/delete/measure/' + measure.slug"
|
||||||
Add Measurement
|
class=btn-icon >
|
||||||
</router-link>
|
<fa-icon icon=trash></fa-icon>
|
||||||
|
</router-link>
|
||||||
|
<router-link
|
||||||
|
title="Edit Measure"
|
||||||
|
:to="'/edit/measure/' + measure.slug"
|
||||||
|
class=btn-icon>
|
||||||
|
<fa-icon icon=pencil-alt></fa-icon>
|
||||||
|
</router-link>
|
||||||
|
<router-link
|
||||||
|
title="Add Measurement"
|
||||||
|
:to="'/new/measurement/' + measure.slug"
|
||||||
|
class=btn-action>
|
||||||
|
Add Measurement
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MeasureDetails :measure=measure :measurements=measurements />
|
<MeasureDetails :measure=measure :measurements=measurements />
|
||||||
</div>
|
</div>
|
||||||
|
43
web/src/views/edit-measure.ts
Normal file
43
web/src/views/edit-measure.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
|
||||||
|
import { logService } from '@/services/logging';
|
||||||
|
import { measureStore, userStore } from '@/store';
|
||||||
|
import { Measure, MeasureConfig, MeasureType } from '@/models';
|
||||||
|
import MeasureConfigForm from '@/components/measure-config/MeasureConfigForm.vue';
|
||||||
|
import { slugify } from '@/util';
|
||||||
|
|
||||||
|
const logger = logService.getLogger('/views/edit-measure');
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: { MeasureConfigForm }
|
||||||
|
})
|
||||||
|
export class EditMeasure extends Vue {
|
||||||
|
private waiting = false;
|
||||||
|
|
||||||
|
private get measure(): Measure<MeasureConfig> | null {
|
||||||
|
return measureStore.measures[this.$route.params.slug] || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get slugFromName() {
|
||||||
|
return slugify(this.measure.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async updateMeasure() {
|
||||||
|
if (this.measure) {
|
||||||
|
if (!this.measure.slug) {
|
||||||
|
this.measure.slug = slugify(this.measure.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.waiting = true;
|
||||||
|
try {
|
||||||
|
await measureStore.updateMeasure(this.measure);
|
||||||
|
this.$router.push({name: 'measure', params: { slug: this.measure.slug }});
|
||||||
|
} catch (e) {
|
||||||
|
logger.error('Unable to update measure. \n\t' + JSON.stringify(this.measure), e.stack);
|
||||||
|
} finally {
|
||||||
|
this.waiting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditMeasure;
|
@ -1,10 +1,12 @@
|
|||||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core';
|
import { library } from '@fortawesome/fontawesome-svg-core';
|
||||||
|
import { faPencilAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faTrash } from '@fortawesome/free-solid-svg-icons';
|
import { faTrash } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { Measure as MeasureModel, MeasureConfig } from '@/models';
|
import { Measure as MeasureModel, MeasureConfig } from '@/models';
|
||||||
import { measureStore, measurementStore } from '@/store';
|
import { measureStore, measurementStore } from '@/store';
|
||||||
import MeasureDetails from '@/components/measure-details/MeasureDetails.vue';
|
import MeasureDetails from '@/components/measure-details/MeasureDetails.vue';
|
||||||
|
|
||||||
|
library.add(faPencilAlt);
|
||||||
library.add(faTrash);
|
library.add(faTrash);
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -5,6 +5,7 @@ import { logService } from '@/services/logging';
|
|||||||
import { measureStore, userStore } from '@/store';
|
import { measureStore, userStore } from '@/store';
|
||||||
import { Measure, MeasureConfig, MeasureType } from '@/models';
|
import { Measure, MeasureConfig, MeasureType } from '@/models';
|
||||||
import MeasureConfigForm from '@/components/measure-config/MeasureConfigForm.vue';
|
import MeasureConfigForm from '@/components/measure-config/MeasureConfigForm.vue';
|
||||||
|
import { slugify } from '@/util';
|
||||||
|
|
||||||
library.add(faSync);
|
library.add(faSync);
|
||||||
|
|
||||||
@ -29,19 +30,12 @@ export class NewMeasure extends Vue {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private get slugFromName() {
|
private get slugFromName() {
|
||||||
return this.slugify(this.measure.name);
|
return slugify(this.measure.name);
|
||||||
}
|
|
||||||
|
|
||||||
private slugify(s: string): string {
|
|
||||||
return s
|
|
||||||
.toLowerCase()
|
|
||||||
.replace(/[^\w\s\-]/g, '')
|
|
||||||
.replace(/\s+/g, '-');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createMeasure() {
|
private async createMeasure() {
|
||||||
if (!this.measure.slug) {
|
if (!this.measure.slug) {
|
||||||
this.measure.slug = this.slugify(this.measure.name);
|
this.measure.slug = slugify(this.measure.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.waiting = true;
|
this.waiting = true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user