chore: don't resolve when returning from promise & improve list store module

This commit is contained in:
Dominik Pschenitschni 2021-10-09 16:34:57 +02:00
parent 3b940cb56c
commit a776e1d2f3
No known key found for this signature in database
GPG key ID: B257AC0149F43A77
16 changed files with 130 additions and 150 deletions

View file

@ -106,7 +106,7 @@ export default {
window.API_URL = urlToCheck.toString()
return this.$store.dispatch('config/update')
}
return Promise.reject(e)
throw e
})
.catch((e) => {
// Check if it has a port and if not check if it is reachable at https
@ -115,7 +115,7 @@ export default {
window.API_URL = urlToCheck.toString()
return this.$store.dispatch('config/update')
}
return Promise.reject(e)
throw e
})
.catch((e) => {
// Check if it is reachable at /api/v1 and https
@ -128,7 +128,7 @@ export default {
window.API_URL = urlToCheck.toString()
return this.$store.dispatch('config/update')
}
return Promise.reject(e)
throw e
})
.catch((e) => {
// Check if it is reachable at port API_DEFAULT_PORT and https
@ -138,7 +138,7 @@ export default {
window.API_URL = urlToCheck.toString()
return this.$store.dispatch('config/update')
}
return Promise.reject(e)
throw e
})
.catch((e) => {
// Check if it is reachable at :API_DEFAULT_PORT and /api/v1 and https
@ -151,7 +151,7 @@ export default {
window.API_URL = urlToCheck.toString()
return this.$store.dispatch('config/update')
}
return Promise.reject(e)
throw e
})
.catch((e) => {
// Check if it is reachable at port API_DEFAULT_PORT and http
@ -161,7 +161,7 @@ export default {
window.API_URL = urlToCheck.toString()
return this.$store.dispatch('config/update')
}
return Promise.reject(e)
throw e
})
.catch((e) => {
// Check if it is reachable at :API_DEFAULT_PORT and /api/v1 and http
@ -174,7 +174,7 @@ export default {
window.API_URL = urlToCheck.toString()
return this.$store.dispatch('config/update')
}
return Promise.reject(e)
throw e
})
.catch(() => {
// Still not found, url is still invalid

View file

@ -50,7 +50,7 @@ export const refreshToken = (persist: boolean): Promise<AxiosResponse> => {
})
.then(r => {
saveToken(r.data.token, persist)
return Promise.resolve(r)
return r
})
.catch(e => {
throw new Error('Error renewing token: ', { cause: e })

View file

@ -27,14 +27,13 @@ const setI18nLanguage = lang => {
}
export const loadLanguageAsync = lang => {
// If the same language
if (i18n.locale === lang) {
return Promise.resolve(setI18nLanguage(lang))
}
// If the language was already loaded
if (loadedLanguages.includes(lang)) {
return Promise.resolve(setI18nLanguage(lang))
if (
// If the same language
i18n.locale === lang ||
// If the language was already loaded
loadedLanguages.includes(lang)
) {
return setI18nLanguage(lang)
}
// If the language hasn't been loaded yet

View file

@ -295,7 +295,7 @@ export default class AbstractService {
.then(response => {
const result = this.modelGetFactory(response.data)
result.maxRight = Number(response.headers['x-max-right'])
return Promise.resolve(result)
return result
})
.finally(() => {
cancel()
@ -338,14 +338,12 @@ export default class AbstractService {
this.totalPages = Number(response.headers['x-pagination-total-pages'])
if (Array.isArray(response.data)) {
return Promise.resolve(response.data.map(entry => {
return this.modelGetAllFactory(entry)
}))
return response.data.map(entry => this.modelGetAllFactory(entry))
}
if (response.data === null) {
return Promise.resolve([])
return []
}
return Promise.resolve(this.modelGetAllFactory(response.data))
return this.modelGetAllFactory(response.data)
})
.finally(() => {
cancel()
@ -371,7 +369,7 @@ export default class AbstractService {
if (typeof model.maxRight !== 'undefined') {
result.maxRight = model.maxRight
}
return Promise.resolve(result)
return result
})
.finally(() => {
cancel()
@ -394,7 +392,7 @@ export default class AbstractService {
if (typeof model.maxRight !== 'undefined') {
result.maxRight = model.maxRight
}
return Promise.resolve(result)
return result
})
.finally(() => {
cancel()
@ -420,7 +418,7 @@ export default class AbstractService {
* @param model
* @returns {Q.Promise<any>}
*/
delete(model) {
async delete(model) {
if (this.paths.delete === '') {
throw new Error('This model is not able to delete data.')
}
@ -428,13 +426,12 @@ export default class AbstractService {
const cancel = this.setLoading()
const finalUrl = this.getReplacedRoute(this.paths.delete, model)
return this.http.delete(finalUrl, model)
.then(response => {
return Promise.resolve(response.data)
})
.finally(() => {
cancel()
})
try {
const {data} = await this.http.delete(finalUrl, model)
return data
} finally {
cancel()
}
}
/**
@ -485,9 +482,7 @@ export default class AbstractService {
},
},
)
.then(response => {
return Promise.resolve(this.modelCreateFactory(response.data))
})
.then(response => this.modelCreateFactory(response.data))
.finally(() => {
this.uploadProgress = 0
cancel()

View file

@ -37,9 +37,9 @@ export default class AttachmentService extends AbstractService {
return AbstractService.prototype.getBlobUrl.call(this, '/tasks/' + model.taskId + '/attachments/' + model.id)
}
download(model) {
this.getBlobUrl(model)
.then(url => downloadBlob(url, model.file.name))
async download(model) {
const url = await this.getBlobUrl(model)
return downloadBlob(url, model.file.name)
}
/**

View file

@ -46,7 +46,7 @@ export default class ListService extends AbstractService {
background(list) {
if (list.background === null) {
return Promise.resolve('')
return ''
}
return this.http({

View file

@ -19,7 +19,7 @@ export default class PasswordResetService extends AbstractService {
const cancel = this.setLoading()
return this.http.post(this.paths.reset, model)
.then(response => {
return Promise.resolve(this.modelFactory(response.data))
return this.modelFactory(response.data)
})
.finally(() => {
cancel()
@ -30,7 +30,7 @@ export default class PasswordResetService extends AbstractService {
const cancel = this.setLoading()
return this.http.post(this.paths.requestReset, model)
.then(response => {
return Promise.resolve(this.modelFactory(response.data))
return this.modelFactory(response.data)
})
.finally(() => {
cancel()

View file

@ -26,13 +26,12 @@ export default class TotpService extends AbstractService {
return this.post(`${this.urlPrefix}/disable`, model)
}
qrcode() {
return this.http({
async qrcode() {
const response = await this.http({
url: `${this.urlPrefix}/qrcode`,
method: 'GET',
responseType: 'blob',
}).then(response => {
return Promise.resolve(new Blob([response.data]))
})
return new Blob([response.data])
}
}

View file

@ -101,17 +101,17 @@ export default {
// Tell others the user is autheticated
ctx.dispatch('checkAuth')
return Promise.resolve()
})
.catch(e => {
if (e.response) {
if (e.response.data.code === 1017 && !credentials.totpPasscode) {
ctx.commit('needsTotpPasscode', true)
return Promise.reject(e)
}
if (
e.response &&
e.response.data.code === 1017 &&
!credentials.totpPasscode
) {
ctx.commit('needsTotpPasscode', true)
}
return Promise.reject(e)
throw e
})
.finally(() => {
ctx.commit(LOADING, false, {root: true})
@ -134,7 +134,7 @@ export default {
ctx.commit(ERROR_MESSAGE, e.response.data.message, {root: true})
}
return Promise.reject(e)
throw e
})
.finally(() => {
ctx.commit(LOADING, false, {root: true})
@ -157,7 +157,6 @@ export default {
// Tell others the user is autheticated
ctx.dispatch('checkAuth')
return Promise.resolve()
})
.finally(() => {
ctx.commit(LOADING, false, {root: true})
@ -180,7 +179,7 @@ export default {
// This function can be called from multiple places at the same time and shortly after one another.
// To prevent hitting the api too frequently or race conditions, we check at most once per minute.
if (ctx.state.lastUserInfoRefresh !== null && ctx.state.lastUserInfoRefresh > (new Date()).setMinutes((new Date()).getMinutes() + 1)) {
return Promise.resolve()
return
}
const jwt = getToken()
@ -190,14 +189,13 @@ export default {
.split('.')[1]
.replace('-', '+')
.replace('_', '/')
const info = new UserModel(JSON.parse(window.atob(base64)))
const info = new UserModel(JSON.parse(atob(base64)))
const ts = Math.round((new Date()).getTime() / 1000)
authenticated = info.exp >= ts
ctx.commit('info', info)
if (authenticated) {
ctx.dispatch('refreshUserInfo')
ctx.commit('authenticated', authenticated)
}
}
@ -206,8 +204,6 @@ export default {
ctx.commit('info', null)
ctx.dispatch('config/redirectToProviderIfNothingElseIsEnabled', null, {root: true})
}
return Promise.resolve()
},
refreshUserInfo(ctx) {
const jwt = getToken()

View file

@ -66,7 +66,7 @@ export default {
return HTTP.get('info')
.then(r => {
ctx.commit(CONFIG, r.data)
return Promise.resolve(r)
return r
})
},
redirectToProviderIfNothingElseIsEnabled(ctx) {

View file

@ -227,19 +227,19 @@ export default {
.finally(() => cancel())
},
loadNextTasksForBucket(ctx, {listId, ps = {}, bucketId}) {
async loadNextTasksForBucket(ctx, {listId, ps = {}, bucketId}) {
const bucketIndex = findIndexById(ctx.state.buckets, bucketId)
const isLoading = ctx.state.bucketLoading[bucketIndex] ?? false
if (isLoading) {
return Promise.resolve()
return
}
const page = (ctx.state.taskPagesPerBucket[bucketIndex] ?? 1) + 1
const alreadyLoaded = ctx.state.allTasksLoadedForBucket[bucketIndex] ?? false
if (alreadyLoaded) {
return Promise.resolve()
return
}
const cancel = setLoading(ctx, 'kanban')
@ -334,7 +334,7 @@ export default {
// restore original state
ctx.commit('setBucketByIndex', {bucketIndex, bucket: oldBucket})
return Promise.reject(e)
throw e
})
.finally(() => cancel())
},

View file

@ -1,5 +1,7 @@
import LabelService from '@/services/label'
import {setLoading} from '@/store/helper'
import { success } from '@/message'
import {i18n} from '@/i18n'
/**
* Returns the labels by id if found
@ -28,6 +30,18 @@ function getLabelsByIds(state, ids) {
})
}
const labelService = new LabelService()
const getAllLabels = async (page = 1) => {
const labels = await labelService.getAll({}, {}, page)
if (page < labelService.totalPages) {
const nextLabels = await getAllLabels(page + 1)
return labels.concat(nextLabels)
} else {
return labels
}
}
export default {
namespaced: true,
state: () => ({
@ -60,71 +74,59 @@ export default {
},
},
actions: {
loadAllLabels(ctx, {forceLoad} = {}) {
async loadAllLabels(ctx, {forceLoad} = {}) {
if (ctx.state.loaded && !forceLoad) {
return Promise.resolve()
return
}
const cancel = setLoading(ctx, 'labels')
const labelService = new LabelService()
const getAllLabels = (page = 1) => {
return labelService.getAll({}, {}, page)
.then(labels => {
if (page < labelService.totalPages) {
return getAllLabels(page + 1)
.then(nextLabels => {
return labels.concat(nextLabels)
})
} else {
return labels
}
})
.catch(e => {
return Promise.reject(e)
})
try {
const labels = await getAllLabels()
ctx.commit('setLabels', labels)
ctx.commit('setLoaded', true)
return labels
} finally {
cancel()
}
return getAllLabels()
.then(r => {
ctx.commit('setLabels', r)
ctx.commit('setLoaded', true)
return Promise.resolve(r)
})
.finally(() => cancel())
},
deleteLabel(ctx, label) {
async deleteLabel(ctx, label) {
const cancel = setLoading(ctx, 'labels')
const labelService = new LabelService()
return labelService.delete(label)
.then(r => {
ctx.commit('removeLabelById', label)
return Promise.resolve(r)
})
.finally(() => cancel())
try {
const result = await labelService.delete(label)
ctx.commit('removeLabelById', label)
success({message: i18n.global.t('label.deleteSuccess')})
return result
} finally {
cancel()
}
},
updateLabel(ctx, label) {
async updateLabel(ctx, label) {
const cancel = setLoading(ctx, 'labels')
const labelService = new LabelService()
return labelService.update(label)
.then(r => {
ctx.commit('setLabel', r)
return Promise.resolve(r)
})
.finally(() => cancel())
try {
const newLabel = await labelService.update(label)
ctx.commit('setLabel', newLabel)
success({message: i18n.global.t('label.edit.success')})
return newLabel
} finally {
cancel()
}
},
createLabel(ctx, label) {
async createLabel(ctx, label) {
const cancel = setLoading(ctx, 'labels')
const labelService = new LabelService()
return labelService.create(label)
.then(r => {
ctx.commit('setLabel', r)
return Promise.resolve(r)
})
.finally(() => cancel())
try {
const newLabel = await labelService.create(label)
ctx.commit('setLabel', newLabel)
return newLabel
} finally {
cancel()
}
},
},
}

View file

@ -51,7 +51,7 @@ export default {
r.namespaceId = list.namespaceId
ctx.commit('namespaces/addListToNamespace', r, {root: true})
ctx.commit('setList', r)
return Promise.resolve(r)
return r
})
.finally(() => cancel())
},
@ -77,7 +77,7 @@ export default {
}
ctx.dispatch('namespaces/loadNamespacesIfFavoritesDontExist', null, {root: true})
ctx.dispatch('namespaces/removeFavoritesNamespaceIfEmpty', null, {root: true})
return Promise.resolve(newList)
return newList
})
.catch(e => {
// Reset the list state to the initial one to avoid confusion for the user
@ -85,7 +85,7 @@ export default {
...list,
isFavorite: !list.isFavorite,
})
return Promise.reject(e)
throw e
})
.finally(() => cancel())
},

View file

@ -113,7 +113,7 @@ export default {
ctx.commit('lists/setLists', lists, {root: true})
return Promise.resolve(r)
return r
})
.finally(() => {
cancel()
@ -128,7 +128,6 @@ export default {
removeFavoritesNamespaceIfEmpty(ctx) {
if (ctx.state.namespaces[0].id === -2 && ctx.state.namespaces[0].lists.length === 0) {
ctx.state.namespaces.splice(0, 1)
return Promise.resolve()
}
},
deleteNamespace(ctx, namespace) {
@ -138,7 +137,7 @@ export default {
return namespaceService.delete(namespace)
.then(r => {
ctx.commit('removeNamespaceById', namespace.id)
return Promise.resolve(r)
return r
})
.finally(() => cancel())
},
@ -149,7 +148,7 @@ export default {
return namespaceService.create(namespace)
.then(r => {
ctx.commit('addNamespace', r)
return Promise.resolve(r)
return r
})
.finally(() => cancel())
},

View file

@ -43,23 +43,23 @@ function addLabelToTask(task, label) {
return labelTaskService.create(labelTask)
.then(result => {
task.labels.push(label)
return Promise.resolve(result)
return result
})
}
function findAssignees(parsedTaskAssignees) {
async function findAssignees(parsedTaskAssignees) {
if (parsedTaskAssignees.length <= 0) {
return Promise.resolve([])
return []
}
const userService = new UserService()
const assignees = parsedTaskAssignees.map(a =>
userService.getAll({}, {s: a})
.then(users => validateUsername(users, a)),
)
const assignees = parsedTaskAssignees.map(async a => {
const users = await userService.getAll({}, {s: a})
return validateUsername(users, a)
})
return Promise.all(assignees).filter((item) => Boolean(item))
const validatedUsers = await Promise.all(assignees)
return validatedUsers.filter((item) => Boolean(item))
}
@ -136,7 +136,7 @@ export default {
// Usually this means the kanban board hasn't been accessed until now.
// Vuex seems to have its difficulties with that, so we just log the error and fail silently.
console.debug('Could not add assignee to task in kanban, task not found', t)
return Promise.resolve(r)
return r
}
// FIXME: direct store manipulation (task)
t.task.assignees.push(user)
@ -157,7 +157,7 @@ export default {
// Usually this means the kanban board hasn't been accessed until now.
// Vuex seems to have its difficulties with that, so we just log the error and fail silently.
console.debug('Could not remove assignee from task in kanban, task not found', t)
return Promise.resolve(r)
return r
}
for (const a in t.task.assignees) {
@ -186,7 +186,7 @@ export default {
// Usually this means the kanban board hasn't been accessed until now.
// Vuex seems to have its difficulties with that, so we just log the error and fail silently.
console.debug('Could not add label to task in kanban, task not found', t)
return Promise.resolve(r)
return r
}
// FIXME: direct store manipulation (task)
t.task.labels.push(label)
@ -208,7 +208,7 @@ export default {
// Usually this means the kanban board hasn't been accessed until now.
// Vuex seems to have its difficulties with that, so we just log the error and fail silently.
console.debug('Could not remove label from task in kanban, task not found', t)
return Promise.resolve(r)
return r
}
// Remove the label from the list
@ -234,22 +234,21 @@ export default {
const {labels} = rootState.labels
const labelAddsToWaitFor = parsedLabels.map(labelTitle => new Promise((resolve) => {
const labelAddsToWaitFor = parsedLabels.map(async labelTitle => {
let label = validateLabel(labels, labelTitle)
if (typeof label !== 'undefined') {
return resolve(label)
return label
}
// label not found, create it
const labelModel = new LabelModel({title: labelTitle})
return dispatch('labels/createLabel', labelModel).then(() => resolve(label))
await dispatch('labels/createLabel', labelModel)
addLabelToTask(task, label)
})
.then((label) => addLabelToTask(task, label))
.catch(e => Promise.reject(e)),
)
// This waits until all labels are created and added to the task
return Promise.all(labelAddsToWaitFor).then(() => task)
await Promise.all(labelAddsToWaitFor)
return task
},
findListId({ rootGetters }, { list, listId }) {

View file

@ -119,7 +119,7 @@ export default {
}
},
created() {
this.loadLabels()
this.$store.dispatch('labels/loadAllLabels')
},
mounted() {
this.setTitle(this.$t('label.title'))
@ -131,20 +131,11 @@ export default {
loading: state => state[LOADING] && state[LOADING_MODULE] === 'labels',
}),
methods: {
loadLabels() {
this.$store.dispatch('labels/loadAllLabels')
},
deleteLabel(label) {
this.$store.dispatch('labels/deleteLabel', label)
.then(() => {
this.$message.success({message: this.$t('label.deleteSuccess')})
})
return this.$store.dispatch('labels/deleteLabel', label)
},
editLabelSubmit() {
this.$store.dispatch('labels/updateLabel', this.labelEditLabel)
.then(() => {
this.$message.success({message: this.$t('label.edit.success')})
})
return this.$store.dispatch('labels/updateLabel', this.labelEditLabel)
},
editLabel(label) {
if (label.createdBy.id !== this.userInfo.id) {