Refactor the planned lines editing logic.

We move most of the logic from the client (as it was until now) to the
server.

The PATCH command maintains the same format but it should provide only
one of the following keys per request:

* ts0
* ts1
* speed
* fsp
* lsp
* lagAfter
* sequence

   Earlier keys in the list above take priority over latter ones.

The following keys may be provided by themselves or in combination with
each other (but not with any of the above):

* name
* remarks
* meta

As a special case, an empty string as the `name` value causes the name
to be auto-generated.

See comments in the code `patch.js` for details on the update logic.
This commit is contained in:
D. Berge
2021-05-27 20:17:32 +02:00
parent 534a54ef75
commit ea3e31058f
2 changed files with 225 additions and 129 deletions

View File

@@ -264,7 +264,7 @@ import suncalc from 'suncalc';
import { mapActions, mapGetters } from 'vuex';
export default {
name: "LineList",
name: "Plan",
components: {
},
@@ -369,35 +369,37 @@ export default {
if (oldVal.value === null) oldVal.value = "";
if (item) {
if (oldVal.key == "lagAfter") {
// We need to shift the times for every subsequent sequence
const delta = oldVal.value*60*1000 - this.lagAfter(item);
await this.shiftTimesAfter(item, delta);
} else if (oldVal.key == "speed") {
const v = oldVal.value*(1.852/3.6)/1000; // m/s
const ts1 = new Date(item.ts0.valueOf() + item.length / v);
const delta = ts1 - item.ts1;
await this.shiftTimesAfter(item, delta);
await this.saveItem({sequence: item.sequence, key: 'ts1', value: ts1});
} else if (oldVal.key == "sequence") {
if (this.shiftAll) {
await this.shiftSequences(oldVal.value-item.sequence);
} else {
await this.shiftSequence(item, oldVal.value);
if (item[oldVal.key] != oldVal.value) {
if (oldVal.key == "lagAfter") {
// Convert from minutes to seconds
oldVal.value *= 60;
} else if (oldVal.key == "speed") {
// Convert knots to metres per second
oldVal.value = oldVal.value*(1.852/3.6);
}
} else if (item[oldVal.key] != oldVal.value) {
if (await this.saveItem(oldVal)) {
item[oldVal.key] = oldVal.value;
} else {
this.edit = oldVal;
}
}
}
}
},
async serverEvent (event) {
if (event.channel == "planned_lines" && event.payload.pid == this.$route.params.project) {
// Ignore non-ops
/*
if (event.payload.old === null && event.payload.new === null) {
return;
}
*/
if (!this.loading && !this.queuedReload) {
// Do not force a non-cached response if refreshing as a result
// of an event notification. We will assume that the server has
@@ -582,92 +584,7 @@ export default {
await this.api([url, init]);
await this.getPlannedLines();
},
async shiftSequences(delta) {
const lines = delta < 0
? this.items
: [...this.items].reverse(); // We go backwards so as to avoid conflicts.
for (const line of lines) {
const sequence = line.sequence+delta;
const url = `/project/${this.$route.params.project}/plan/${line.sequence}`;
const init = {
method: "PATCH",
headers: {"Content-Type": "application/json"},
body: {sequence, name: null} // Setting name to null causes it to be regenerated
}
await this.api([url, init]);
}
},
async shiftSequence (item, newSequence) {
if (item.sequence == newSequence) {
// Nothing to do
return;
}
const conflict = this.items.find(i => i.sequence == newSequence)
if (conflict) {
this.showSnack([`Sequence ${newSequence} already exists`, "error"]);
} else {
// Cannot do this check at the moment as we would have to load the list of sequences.
// TODO We will do this after refactoring.
/*
if (this.sequences.find(i => i.sequence == newSequence)) {
this.showSnack([`Sequence ${newSequence} conflicts with a line that's already been acquired`, "warning"]);
}
*/
const url = `/project/${this.$route.params.project}/plan/${item.sequence}`;
const init = {
method: "PATCH",
headers: {"Content-Type": "application/json"},
body: {
sequence: newSequence,
name: null
} // Setting name to null causes it to be regenerated
}
await this.api([url, init]);
}
},
async shiftTimesAfter(item, delta) {
const pos = this.items.indexOf(item)+1;
if (pos != 0) {
const modifiedLines = this.items.slice(pos);
if (modifiedLines.length) {
modifiedLines.reverse();
for (const line of modifiedLines) {
const ts0 = new Date(line.ts0.valueOf() + delta);
const ts1 = new Date(line.ts1.valueOf() + delta);
const url = `/project/${this.$route.params.project}/plan/${line.sequence}`;
const init = {
method: "PATCH",
headers: {"Content-Type": "application/json"},
body: {ts1, ts0}
}
await this.api([url, init]);
}
}
} else {
console.warn("Item", item, "not found");
}
},
editLagAfter (item) {
const pos = this.items.indexOf(item)+1;
if (pos != 0) {
if (pos < this.items.length) {
// Not last item
this.editedItems = this.items.slice(pos);
} else {
}
} else {
console.warn("Item", item, "not found");
}
},
editItem (item, key, value) {
this.edit = {
sequence: item.sequence,