Move everything to models and services (#17)
This commit is contained in:
21
src/models/abstractModel.js
Normal file
21
src/models/abstractModel.js
Normal file
@ -0,0 +1,21 @@
|
||||
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.
|
||||
* @return {{}}
|
||||
*/
|
||||
defaults() {
|
||||
return {}
|
||||
}
|
||||
}
|
1
src/models/config.js
Normal file
1
src/models/config.js
Normal file
@ -0,0 +1 @@
|
||||
export const URL_PREFIX = '/api/v1' // _without_ slash at the end
|
111
src/models/list.js
Normal file
111
src/models/list.js
Normal file
@ -0,0 +1,111 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import TaskModel from './task'
|
||||
import UserModel from './user'
|
||||
|
||||
export default class ListModel extends AbstractModel {
|
||||
|
||||
constructor(data) {
|
||||
super(data)
|
||||
|
||||
// Make all tasks to task models
|
||||
this.tasks = this.tasks.map(t => {
|
||||
return new TaskModel(t)
|
||||
})
|
||||
|
||||
this.owner = new UserModel(this.owner)
|
||||
this.sortTasks()
|
||||
}
|
||||
|
||||
// Default attributes that define the "empty" state.
|
||||
defaults() {
|
||||
return {
|
||||
id: 0,
|
||||
title: '',
|
||||
description: '',
|
||||
owner: UserModel,
|
||||
tasks: [],
|
||||
namespaceID: 0,
|
||||
|
||||
created: 0,
|
||||
updated: 0,
|
||||
}
|
||||
}
|
||||
|
||||
////////
|
||||
// Helpers
|
||||
//////
|
||||
|
||||
/**
|
||||
* Sorts all tasks according to their due date
|
||||
* @returns {this}
|
||||
*/
|
||||
sortTasks() {
|
||||
if (this.tasks === null || this.tasks === []) {
|
||||
return
|
||||
}
|
||||
return this.tasks.sort(function(a,b) {
|
||||
if (a.done < b.done)
|
||||
return -1
|
||||
if (a.done > b.done)
|
||||
return 1
|
||||
return 0
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a task to the task array of this list. Usually only used when creating a new task
|
||||
* @param task
|
||||
*/
|
||||
addTaskToList(task) {
|
||||
// If it's a subtask, add it to its parent, otherwise append it to the list of tasks
|
||||
if (task.parentTaskID === 0) {
|
||||
this.tasks.push(task)
|
||||
} else {
|
||||
for (const t in this.tasks) {
|
||||
if (this.tasks[t].id === task.parentTaskID) {
|
||||
this.tasks[t].subtasks.push(task)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
this.sortTasks()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a task by its ID by looping through all tasks.
|
||||
* @param id
|
||||
* @returns {TaskModel}
|
||||
*/
|
||||
getTaskByID(id) {
|
||||
// TODO: Binary search?
|
||||
for (const t in this.tasks) {
|
||||
if (this.tasks[t].id === parseInt(id)) {
|
||||
return this.tasks[t]
|
||||
}
|
||||
}
|
||||
return {} // FIXME: This should probably throw something to make it clear to the user noting was found
|
||||
}
|
||||
|
||||
/**
|
||||
* Loops through all tasks and updates the one with the id it has
|
||||
* @param task
|
||||
*/
|
||||
updateTaskByID(task) {
|
||||
for (const t in this.tasks) {
|
||||
if (this.tasks[t].id === task.id) {
|
||||
this.tasks[t] = task
|
||||
break
|
||||
}
|
||||
|
||||
if (this.tasks[t].id === task.parentTaskID) {
|
||||
for (const s in this.tasks[t].subtasks) {
|
||||
if (this.tasks[t].subtasks[s].id === task.id) {
|
||||
this.tasks[t].subtasks[s] = task
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.sortTasks()
|
||||
}
|
||||
}
|
28
src/models/namespace.js
Normal file
28
src/models/namespace.js
Normal file
@ -0,0 +1,28 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import ListModel from './list'
|
||||
import UserModel from './user'
|
||||
|
||||
export default class NamespaceModel extends AbstractModel {
|
||||
constructor(data) {
|
||||
super(data)
|
||||
|
||||
this.lists = this.lists.map(l => {
|
||||
return new ListModel(l)
|
||||
})
|
||||
this.owner = new UserModel(this.owner)
|
||||
}
|
||||
|
||||
// Default attributes that define the 'empty' state.
|
||||
defaults() {
|
||||
return {
|
||||
id: 0,
|
||||
name: '',
|
||||
description: '',
|
||||
owner: UserModel,
|
||||
lists: [],
|
||||
|
||||
created: 0,
|
||||
updated: 0,
|
||||
}
|
||||
}
|
||||
}
|
17
src/models/passwordReset.js
Normal file
17
src/models/passwordReset.js
Normal file
@ -0,0 +1,17 @@
|
||||
import AbstractModel from "./abstractModel";
|
||||
|
||||
export default class PasswordResetModel extends AbstractModel {
|
||||
constructor(data) {
|
||||
super(data)
|
||||
|
||||
this.token = localStorage.getItem('passwordResetToken')
|
||||
}
|
||||
|
||||
defaults() {
|
||||
return {
|
||||
token: '',
|
||||
new_password: '',
|
||||
email: '',
|
||||
}
|
||||
}
|
||||
}
|
99
src/models/task.js
Normal file
99
src/models/task.js
Normal file
@ -0,0 +1,99 @@
|
||||
import AbstractModel from './abstractModel';
|
||||
import UserModel from './user'
|
||||
|
||||
export default class TaskModel extends AbstractModel {
|
||||
|
||||
constructor(data) {
|
||||
super(data)
|
||||
|
||||
// Make date objects from timestamps
|
||||
this.dueDate = this.parseDateIfNessecary(this.dueDate)
|
||||
this.startDate = this.parseDateIfNessecary(this.startDate)
|
||||
this.endDate = this.parseDateIfNessecary(this.endDate)
|
||||
|
||||
this.reminderDates = this.reminderDates.map(d => {
|
||||
return this.parseDateIfNessecary(d)
|
||||
})
|
||||
this.reminderDates.push(null) // To trigger the datepicker
|
||||
|
||||
// Parse the repeat after into something usable
|
||||
this.parseRepeatAfter()
|
||||
|
||||
// Parse the assignees into user models
|
||||
this.assignees = this.assignees.map(a => {
|
||||
return new UserModel(a)
|
||||
})
|
||||
this.createdBy = new UserModel(this.createdBy)
|
||||
}
|
||||
|
||||
defaults() {
|
||||
return {
|
||||
id: 0,
|
||||
text: '',
|
||||
description: '',
|
||||
done: false,
|
||||
priority: 0,
|
||||
labels: [],
|
||||
assignees: [],
|
||||
|
||||
dueDate: 0,
|
||||
startDate: 0,
|
||||
endDate: 0,
|
||||
repeatAfter: 0,
|
||||
reminderDates: [],
|
||||
subtasks: [],
|
||||
parentTaskID: 0,
|
||||
|
||||
createdBy: UserModel,
|
||||
created: 0,
|
||||
updated: 0,
|
||||
|
||||
listID: 0, // Meta, only used when creating a new task
|
||||
sortBy: 'duedate', // Meta, only used when listing all tasks
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Helper functions
|
||||
///////////////
|
||||
|
||||
/**
|
||||
* Makes a js date object from a unix timestamp (in seconds).
|
||||
* @param unixTimestamp
|
||||
* @returns {*}
|
||||
*/
|
||||
parseDateIfNessecary(unixTimestamp) {
|
||||
let dateobj = new Date(unixTimestamp * 1000)
|
||||
if (unixTimestamp === 0) {
|
||||
return null
|
||||
}
|
||||
return dateobj
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the "repeat after x seconds" from the task into a usable js object inside the task.
|
||||
* This function should only be called from the constructor.
|
||||
*/
|
||||
parseRepeatAfter() {
|
||||
let repeatAfterHours = (this.repeatAfter / 60) / 60
|
||||
this.repeatAfter = {type: 'hours', amount: repeatAfterHours}
|
||||
|
||||
// if its dividable by 24, its something with days, otherwise hours
|
||||
if (repeatAfterHours % 24 === 0) {
|
||||
let repeatAfterDays = repeatAfterHours / 24
|
||||
if (repeatAfterDays % 7 === 0) {
|
||||
this.repeatAfter.type = 'weeks'
|
||||
this.repeatAfter.amount = repeatAfterDays / 7
|
||||
} else if (repeatAfterDays % 30 === 0) {
|
||||
this.repeatAfter.type = 'months'
|
||||
this.repeatAfter.amount = repeatAfterDays / 30
|
||||
} else if (repeatAfterDays % 365 === 0) {
|
||||
this.repeatAfter.type = 'years'
|
||||
this.repeatAfter.amount = repeatAfterDays / 365
|
||||
} else {
|
||||
this.repeatAfter.type = 'days'
|
||||
this.repeatAfter.amount = repeatAfterDays
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
29
src/models/team.js
Normal file
29
src/models/team.js
Normal file
@ -0,0 +1,29 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
import UserModel from './user'
|
||||
import TeamMemberModel from './teamMember'
|
||||
|
||||
export default class TeamModel extends AbstractModel {
|
||||
constructor(data) {
|
||||
super(data)
|
||||
|
||||
// Make the members to usermodels
|
||||
this.members = this.members.map(m => {
|
||||
return new TeamMemberModel(m)
|
||||
})
|
||||
this.createdBy = new UserModel(this.createdBy)
|
||||
}
|
||||
|
||||
defaults() {
|
||||
return {
|
||||
id: 0,
|
||||
name: '',
|
||||
description: '',
|
||||
members: [],
|
||||
right: 0,
|
||||
|
||||
createdBy: {},
|
||||
created: 0,
|
||||
updated: 0
|
||||
}
|
||||
}
|
||||
}
|
13
src/models/teamList.js
Normal file
13
src/models/teamList.js
Normal file
@ -0,0 +1,13 @@
|
||||
import TeamShareBaseModel from './teamShareBase'
|
||||
import {merge} from "lodash";
|
||||
|
||||
export default class TeamListModel extends TeamShareBaseModel {
|
||||
defaults() {
|
||||
return merge(
|
||||
super.defaults(),
|
||||
{
|
||||
listID: 0,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
14
src/models/teamMember.js
Normal file
14
src/models/teamMember.js
Normal file
@ -0,0 +1,14 @@
|
||||
import UserModel from './user'
|
||||
import {merge} from 'lodash'
|
||||
|
||||
export default class TeamMemberModel extends UserModel {
|
||||
defaults() {
|
||||
return merge(
|
||||
super.defaults(),
|
||||
{
|
||||
admin: false,
|
||||
teamID: 0,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
13
src/models/teamNamespace.js
Normal file
13
src/models/teamNamespace.js
Normal file
@ -0,0 +1,13 @@
|
||||
import TeamShareBaseModel from './teamShareBase'
|
||||
import {merge} from 'lodash'
|
||||
|
||||
export default class TeamNamespaceModel extends TeamShareBaseModel {
|
||||
defaults() {
|
||||
return merge(
|
||||
super.defaults(),
|
||||
{
|
||||
namespaceID: 0,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
17
src/models/teamShareBase.js
Normal file
17
src/models/teamShareBase.js
Normal file
@ -0,0 +1,17 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
|
||||
/**
|
||||
* This class is a base class for common team sharing model.
|
||||
* It is extended in a way so it can be used for namespaces as well for lists.
|
||||
*/
|
||||
export default class TeamShareBaseModel extends AbstractModel {
|
||||
defaults() {
|
||||
return {
|
||||
teamID: 0,
|
||||
right: 0,
|
||||
|
||||
created: 0,
|
||||
updated: 0
|
||||
}
|
||||
}
|
||||
}
|
13
src/models/user.js
Normal file
13
src/models/user.js
Normal file
@ -0,0 +1,13 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
|
||||
export default class UserModel extends AbstractModel {
|
||||
defaults() {
|
||||
return {
|
||||
id: 0,
|
||||
email: '',
|
||||
username: '',
|
||||
created: 0,
|
||||
updated: 0
|
||||
}
|
||||
}
|
||||
}
|
14
src/models/userList.js
Normal file
14
src/models/userList.js
Normal file
@ -0,0 +1,14 @@
|
||||
import UserShareBaseModel from './userShareBase'
|
||||
import {merge} from 'lodash'
|
||||
|
||||
// This class extends the user share model with a 'rights' parameter which is used in sharing
|
||||
export default class UserListModel extends UserShareBaseModel {
|
||||
defaults() {
|
||||
return merge(
|
||||
super.defaults(),
|
||||
{
|
||||
listID: 0,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
14
src/models/userNamespace.js
Normal file
14
src/models/userNamespace.js
Normal file
@ -0,0 +1,14 @@
|
||||
import UserShareBaseModel from "./userShareBase";
|
||||
import {merge} from 'lodash'
|
||||
|
||||
// This class extends the user share model with a 'rights' parameter which is used in sharing
|
||||
export default class UserNamespaceModel extends UserShareBaseModel {
|
||||
defaults() {
|
||||
return merge(
|
||||
super.defaults(),
|
||||
{
|
||||
namespaceID: 0,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
13
src/models/userShareBase.js
Normal file
13
src/models/userShareBase.js
Normal file
@ -0,0 +1,13 @@
|
||||
import AbstractModel from './abstractModel'
|
||||
|
||||
export default class UserShareBaseModel extends AbstractModel {
|
||||
defaults() {
|
||||
return {
|
||||
userID: 0,
|
||||
right: 0,
|
||||
|
||||
created: 0,
|
||||
updated: 0,
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user