Add track editing support to track view model

This commit is contained in:
Bartek Fabiszewski 2019-12-29 13:54:26 +01:00
parent 069eab1f63
commit cb5405a9d5
3 changed files with 96 additions and 3 deletions

View File

@ -18,6 +18,7 @@
*/ */
import { lang as $, auth, config } from './initializer.js'; import { lang as $, auth, config } from './initializer.js';
import TrackDialogModel from './trackdialogmodel.js';
import ViewModel from './viewmodel.js'; import ViewModel from './viewmodel.js';
import uObserve from './observe.js'; import uObserve from './observe.js';
import uPositionSet from './positionset.js'; import uPositionSet from './positionset.js';
@ -55,12 +56,15 @@ export default class TrackViewModel extends ViewModel {
/** @type {function} */ /** @type {function} */
onExportKml: null, onExportKml: null,
/** @type {function} */ /** @type {function} */
onImportGpx: null onImportGpx: null,
/** @type {function} */
onTrackEdit: null
}); });
this.setClickHandlers(); this.setClickHandlers();
/** @type HTMLSelectElement */ /** @type HTMLSelectElement */
const listEl = document.querySelector('#track'); const listEl = document.querySelector('#track');
this.importEl = document.querySelector('#input-file'); this.importEl = document.querySelector('#input-file');
this.editEl = this.getBoundElement('onTrackEdit');
this.select = new uSelect(listEl); this.select = new uSelect(listEl);
this.state = state; this.state = state;
this.timerId = 0; this.timerId = 0;
@ -93,9 +97,11 @@ export default class TrackViewModel extends ViewModel {
this.state.onChanged('currentUser', (user) => { this.state.onChanged('currentUser', (user) => {
if (user) { if (user) {
this.loadTrackList(); this.loadTrackList();
TrackViewModel.setMenuVisible(this.editEl, true);
} else { } else {
this.model.currentTrackId = ''; this.model.currentTrackId = '';
this.model.trackList = []; this.model.trackList = [];
TrackViewModel.setMenuVisible(this.editEl, false);
} }
}); });
this.state.onChanged('currentTrack', (track) => { this.state.onChanged('currentTrack', (track) => {
@ -129,6 +135,7 @@ export default class TrackViewModel extends ViewModel {
this.model.onExportGpx = exportCb('gpx'); this.model.onExportGpx = exportCb('gpx');
this.model.onExportKml = exportCb('kml'); this.model.onExportKml = exportCb('kml');
this.model.onImportGpx = () => this.importEl.click(); this.model.onImportGpx = () => this.importEl.click();
this.model.onTrackEdit = () => this.showDialog();
} }
/** /**
@ -264,6 +271,24 @@ export default class TrackViewModel extends ViewModel {
.catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); }); .catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); });
} }
showDialog() {
const vm = new TrackDialogModel(this);
vm.init();
}
onTrackDeleted() {
const index = this.model.trackList.indexOf(this.state.currentTrack);
this.state.currentTrack = null;
if (index !== -1) {
this.model.trackList.splice(index, 1);
if (this.model.trackList.length) {
this.model.currentTrackId = this.model.trackList[index].listValue;
} else {
this.model.currentTrackId = '';
}
}
}
/** /**
* @param {boolean} start * @param {boolean} start
*/ */
@ -285,6 +310,14 @@ export default class TrackViewModel extends ViewModel {
this.model.autoReload = false; this.model.autoReload = false;
} }
static setMenuVisible(el, visible) {
if (visible) {
el.classList.remove('menu-hidden');
} else {
el.classList.add('menu-hidden');
}
}
renderSummary() { renderSummary() {
if (!this.state.currentTrack || !this.state.currentTrack.hasPositions) { if (!this.state.currentTrack || !this.state.currentTrack.hasPositions) {
this.model.summary = ''; this.model.summary = '';

View File

@ -51,6 +51,8 @@ describe('TrackViewModel tests', () => {
let autoReloadEl; let autoReloadEl;
/** @type {HTMLInputElement} */ /** @type {HTMLInputElement} */
let inputFileEl; let inputFileEl;
/** @type {HTMLAnchorElement} */
let trackEditEl;
let tracks; let tracks;
let track1; let track1;
let track2; let track2;
@ -78,6 +80,7 @@ describe('TrackViewModel tests', () => {
forceReloadEl = document.querySelector('#force-reload'); forceReloadEl = document.querySelector('#force-reload');
inputFileEl = document.querySelector('#input-file'); inputFileEl = document.querySelector('#input-file');
autoReloadEl = document.querySelector('#auto-reload'); autoReloadEl = document.querySelector('#auto-reload');
trackEditEl = document.querySelector('#edittrack');
const maxEl = document.querySelector('input[name="MAX_FILE_SIZE"]'); const maxEl = document.querySelector('input[name="MAX_FILE_SIZE"]');
maxEl.value = MAX_FILE_SIZE; maxEl.value = MAX_FILE_SIZE;
state = new uState(); state = new uState();
@ -257,7 +260,6 @@ describe('TrackViewModel tests', () => {
}, 100); }, 100);
}); });
it('should load user latest position when "show latest" is checked and select respective track in list', (done) => { it('should load user latest position when "show latest" is checked and select respective track in list', (done) => {
// given // given
positions[0].trackid = track2.id; positions[0].trackid = track2.id;
@ -604,6 +606,64 @@ describe('TrackViewModel tests', () => {
}, 100); }, 100);
}); });
it('should show user edit dialog on button click', (done) => {
// given
spyOn(vm, 'showDialog');
// when
vm.bindAll();
trackEditEl.click();
// then
setTimeout(() => {
expect(vm.showDialog).toHaveBeenCalledTimes(1);
done();
}, 100);
});
it('should remove current track from track list and set new current track id', () => {
// given
vm.model.trackList = [ track1, track2 ];
vm.state.currentTrack = track1;
vm.model.currentTrackId = track1.listValue;
// when
vm.onTrackDeleted();
// then
expect(vm.model.trackList.length).toBe(1);
expect(vm.model.currentTrackId).toBe(track2.listValue);
expect(vm.state.currentTrack).toBe(null);
});
it('should remove last remaining element from track list and set empty track id', () => {
// given
vm.model.trackList = [ track1 ];
vm.state.currentTrack = track1;
vm.model.currentTrackId = track1.listValue;
// when
vm.onTrackDeleted();
// then
expect(vm.model.trackList.length).toBe(0);
expect(vm.model.currentTrackId).toBe('');
expect(vm.state.currentTrack).toBe(null);
});
it('show hide element', () => {
// given
const element = document.createElement('div');
// when
TrackViewModel.setMenuVisible(element, false);
// then
expect(element.classList.contains('menu-hidden')).toBe(true);
});
it('show shown hidden element', () => {
// given
const element = document.createElement('div');
element.classList.add('menu-hidden');
// when
TrackViewModel.setMenuVisible(element, true);
// then
expect(element.classList.contains('menu-hidden')).toBe(false);
});
describe('on reload clicked', () => { describe('on reload clicked', () => {
it('should reload selected track', (done) => { it('should reload selected track', (done) => {

View File

@ -36,7 +36,7 @@
} }
$track = new uTrack($trackId); $track = new uTrack($trackId);
if (!$track->isValid || if (!$track->isValid ||
(!$auth->isAuthenticated() || (!$auth->isAdmin() && $auth->user->id != $track->userId))) { (!$auth->isAuthenticated() || (!$auth->isAdmin() && $auth->user->id !== $track->userId))) {
uUtils::exitWithError($lang["servererror"]); uUtils::exitWithError($lang["servererror"]);
} }