Move everything to models and services #17

Merged
konrad merged 82 commits from refactor/models into master 2019-03-02 10:25:10 +00:00
4 changed files with 118 additions and 73 deletions
Showing only changes of commit 7f636f6c38 - Show all commits

View File

@ -1,5 +1,5 @@
<template>
<div class="loader-container" :class="{ 'is-loading': loading}">
<div class="loader-container" :class="{ 'is-loading': listService.loading}">
<div class="content">
<router-link :to="{ name: 'editList', params: { id: list.id } }" class="icon settings is-medium">
<icon icon="cog" size="2x"/>
@ -213,6 +213,7 @@
data() {
return {
listID: this.$route.params.id,
listService: ListService,
list: {},
newTask: {text: ''},
error: '',
@ -244,6 +245,7 @@
}
},
created() {
this.listService = new ListService()
this.loadList()
},
watch: {
@ -255,13 +257,12 @@
this.isTaskEdit = false
//const cancel = message.setLoading(this)
let listService = new ListService()
listService.get({id: this.$route.params.id}, {})
this.listService.get({id: this.$route.params.id}, {})
.then(r => {
this.$set(this, 'list', r)
})
.catch(e => {
this.handleError(e)
message.error(e, this)
})
/*

View File

@ -1,13 +1,20 @@
import {defaults, omitBy, isNil} from "lodash";
import {defaults, omitBy, isNil} from 'lodash'
export default class AbstractModel {
/**
* The abstract constructor takes an object and merges its data with the default data of this model.
* @param data
*/
constructor(data) {
// Put all data in our model while overriding those with a value of null or undefined with their defaults
defaults(this, omitBy(data, isNil), this.defaults())
}
// Default attributes that define the "empty" state.
/**
* Default attributes that define the "empty" state.
* @return {{}}
*/
defaults() {
return {}
}

View File

@ -1,10 +1,12 @@
import abstractModel from "./abstractModel";
import AbstractModel from './abstractModel'
export default class ListModel extends abstractModel {
export default class ListModel extends AbstractModel {
constructor(data) {
super(data)
this.sortTasks()
// TODO: fixStuffComingFromAPI (see ShowList.vue)
}
// Default attributes that define the "empty" state.
@ -21,7 +23,9 @@ export default class ListModel extends abstractModel {
updated: 0,
}
}
////////
// Helpers
sortTasks() {
if (this.tasks === null || this.tasks === []) {
return

View File

@ -4,17 +4,25 @@ import {reduce, replace} from 'lodash'
let config = require('../../public/config.json')
export default class AbstractService {
/////////////////////////////
// Initial variable definitions
http = null
loading = false
paths = {
create: '',
get: '',
update: '',
delete: '',
}
///////////////////////////////////////
// SERVICE INIT
///////////////////////////////////////
/////////////
// Service init
/**
* The abstract constructor.
* @param paths An object with all paths. Default values are specified above.
*/
constructor(paths) {
this.http = axios.create({
baseURL: config.VIKUNJA_API_BASE_URL,
@ -37,78 +45,103 @@ export default class AbstractService {
}
}
///////////////////////////////////////
// GLOBAL ERROR HANDLER
///////////////////////////////////////
/////////////////////
// Global error handler
/**
* Handles the error and rejects the promise.
* @param url
* @param error
* @returns {Promise<never>}
*/
errorHandler(url, error) {
// eslint-disable-next-line
console.log('[Err][GET][%s] %o', url, error);
if (error.response) {
return Promise.reject({response: error});
} else if (error.request) {
return Promise.reject({request: error});
} else {
return Promise.reject({message: error});
}
return Promise.reject(error)
}
//////////////////////
// Helper functions //
//////////////////////
/////////////////
// Helper functions
/**
* Returns an object with all route parameters and their values.
* @param route
* @returns object
*/
getRouteReplacements(route) {
var parameters = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var replace$$1 = {};
var pattern = this.getRouteParameterPattern();
pattern = new RegExp(pattern instanceof RegExp ? pattern.source : pattern, 'g');
for (var parameter; (parameter = pattern.exec(route)) !== null;) {
let parameters = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}
let replace$$1 = {}
let pattern = this.getRouteParameterPattern()
pattern = new RegExp(pattern instanceof RegExp ? pattern.source : pattern, 'g')
for (let parameter; (parameter = pattern.exec(route)) !== null;) {
replace$$1[parameter[0]] = parameters[parameter[1]];
}
return replace$$1;
}
/**
* Holds the replacement pattern for url paths, can be overwritten by implementations.
* @return {RegExp}
*/
getRouteParameterPattern() {
return /\{([^}]+)\}/
return /{([^}]+)}/
}
///////////////////////////////////////
// GLOBAL ACTIONS
///////////////////////////////////////
getData(pathparams, params) {
// parse the url
let replacements = this.getRouteReplacements(this.paths.get, pathparams); // Replace all route parameters with their replacement values.
let replaced = reduce(replacements, function (result, value, parameter) {
return replace(result, parameter, value);
/**
* Returns a fully-ready-ready-to-make-a-request-to route with replaced parameters.
* @param path
* @param pathparams
* @return string
*/
getReplacedRoute(path, pathparams) {
let replacements = this.getRouteReplacements(path, pathparams)
return reduce(replacements, function (result, value, parameter) {
return replace(result, parameter, value)
}, this.paths.get)
// eslint-disable-next-line
console.log('[Req][GET][%s] %o', this.paths.get, params, pathparams, replaced);
return this.http.get(replaced, {params: params})
}
/**
* setLoading is a method which sets the loading variable to true, after a timeout of 100ms.
* It has the timeout to prevent the loading indicator from showing for only a blink of an eye in the
* case the api returns a response in < 100ms.
* But because the timeout is created using setTimeout, it will still triggerm even if the request is
* already finished, so we return a method to call in that case.
* @returns {Function}
*/
setLoading() {
const timeout = setTimeout(() => {
this.loading = true
}, 100)
return () => {
clearTimeout(timeout)
this.loading = false
}
}
///////////////
// Global actions
/**
* Performs a get request to the url specified before.
* @param pathparams The parameters inside of the url
* @param params Extra query parameters
* @returns {Q.Promise<any>}
*/
getData(pathparams, params) {
// We later will be able to cancel the loading indicator using this.
const cancel = this.setLoading()
// Finally make the request and get our data.
return this.http.get(this.getReplacedRoute(this.paths.get, pathparams), {params: params})
.catch(error => {
return this.errorHandler(this.paths.get, error);
return this.errorHandler(this.paths.get, error)
})
.then(response => {
// eslint-disable-next-line
console.log('[Res][GET][%s] %o', this.paths.get, response);
//if (Array.isArray(response.data)) {
return Promise.resolve(response.data)
/*}
else {
if (Array.isArray(response.data.content)) {
const paginatedResponse = new PaginatedDomain();
paginatedResponse.setDataFromHttpResponse(response);
return Promise.resolve(paginatedResponse);
}
return Promise.resolve({...response.data});
}*/
});
})
.finally(() => {
cancel()
})
}
}