feat: rename list to project everywhere
fix: project table view fix: e2e tests fix: typo in readme fix: list view route fix: don't wait until background is loaded for list to show fix: rename component imports fix: lint fix: parse task text fix: use list card grid fix: use correct class names fix: i18n keys fix: load project fix: task overview fix: list view spacing fix: find project fix: setLoading when updating a project fix: loading saved filter fix: project store loading fix: color picker import fix: cypress tests feat: migrate old list settings chore: add const for project settings fix: wrong projecten rename from lists chore: rename unused variable fix: editor list fix: shortcut list class name fix: pagination list class name fix: notifications list class name fix: list view variable name chore: clarify comment fix: i18n keys fix: router imports fix: comment chore: remove debugging leftover fix: remove duplicate variables fix: change comment fix: list view variable name fix: list view css class name fix: list item property name fix: name update tasks function correctly fix: update comment fix: project create route fix: list view class names fix: list view component name fix: result list class name fix: animation class list name fix: change debug log fix: revert a few navigation changes fix: use @ for imports of all views fix: rename link share list class fix: remove unused css class fix: dynamically import project components again
This commit is contained in:
@ -3,21 +3,21 @@ import {defineStore, acceptHMRUpdate} from 'pinia'
|
||||
|
||||
import {getBlobFromBlurHash} from '@/helpers/getBlobFromBlurHash'
|
||||
|
||||
import ListModel from '@/models/list'
|
||||
import ListService from '../services/list'
|
||||
import ProjectModel from '@/models/project'
|
||||
import ProjectService from '../services/project'
|
||||
import {checkAndSetApiUrl} from '@/helpers/checkAndSetApiUrl'
|
||||
|
||||
import {useMenuActive} from '@/composables/useMenuActive'
|
||||
|
||||
import {useAuthStore} from '@/stores/auth'
|
||||
import type {IList} from '@/modelTypes/IList'
|
||||
import type {IProject} from '@/modelTypes/IProject'
|
||||
|
||||
export const useBaseStore = defineStore('base', () => {
|
||||
const loading = ref(false)
|
||||
const ready = ref(false)
|
||||
|
||||
// This is used to highlight the current list in menu for all list related views
|
||||
const currentList = ref<IList | null>(new ListModel({
|
||||
// This is used to highlight the current project in menu for all project related views
|
||||
const currentProject = ref<IProject | null>(new ProjectModel({
|
||||
id: 0,
|
||||
isArchived: false,
|
||||
}))
|
||||
@ -33,21 +33,21 @@ export const useBaseStore = defineStore('base', () => {
|
||||
loading.value = newLoading
|
||||
}
|
||||
|
||||
function setCurrentList(newCurrentList: IList | null) {
|
||||
// Server updates don't return the right. Therefore, the right is reset after updating the list which is
|
||||
function setCurrentProject(newCurrentProject: IProject | null) {
|
||||
// Server updates don't return the right. Therefore, the right is reset after updating the project which is
|
||||
// confusing because all the buttons will disappear in that case. To prevent this, we're keeping the right
|
||||
// when updating the list in global state.
|
||||
// when updating the project in global state.
|
||||
if (
|
||||
typeof currentList.value?.maxRight !== 'undefined' &&
|
||||
newCurrentList !== null &&
|
||||
typeof currentProject.value?.maxRight !== 'undefined' &&
|
||||
newCurrentProject !== null &&
|
||||
(
|
||||
typeof newCurrentList.maxRight === 'undefined' ||
|
||||
newCurrentList.maxRight === null
|
||||
typeof newCurrentProject.maxRight === 'undefined' ||
|
||||
newCurrentProject.maxRight === null
|
||||
)
|
||||
) {
|
||||
newCurrentList.maxRight = currentList.value.maxRight
|
||||
newCurrentProject.maxRight = currentProject.value.maxRight
|
||||
}
|
||||
currentList.value = newCurrentList
|
||||
currentProject.value = newCurrentProject
|
||||
}
|
||||
|
||||
function setHasTasks(newHasTasks: boolean) {
|
||||
@ -78,44 +78,44 @@ export const useBaseStore = defineStore('base', () => {
|
||||
ready.value = value
|
||||
}
|
||||
|
||||
async function handleSetCurrentList(
|
||||
{list, forceUpdate = false}: {list: IList | null, forceUpdate?: boolean},
|
||||
async function handleSetCurrentProject(
|
||||
{project, forceUpdate = false}: {project: IProject | null, forceUpdate?: boolean},
|
||||
) {
|
||||
if (list === null) {
|
||||
setCurrentList({})
|
||||
if (project === null) {
|
||||
setCurrentProject({})
|
||||
setBackground('')
|
||||
setBlurHash('')
|
||||
return
|
||||
}
|
||||
|
||||
// The forceUpdate parameter is used only when updating a list background directly because in that case
|
||||
// the current list stays the same, but we want to show the new background right away.
|
||||
if (list.id !== currentList.value?.id || forceUpdate) {
|
||||
if (list.backgroundInformation) {
|
||||
// The forceUpdate parameter is used only when updating a project background directly because in that case
|
||||
// the current project stays the same, but we want to show the new background right away.
|
||||
if (project.id !== currentProject.value?.id || forceUpdate) {
|
||||
if (project.backgroundInformation) {
|
||||
try {
|
||||
const blurHash = await getBlobFromBlurHash(list.backgroundBlurHash)
|
||||
const blurHash = await getBlobFromBlurHash(project.backgroundBlurHash)
|
||||
if (blurHash) {
|
||||
setBlurHash(window.URL.createObjectURL(blurHash))
|
||||
}
|
||||
|
||||
const listService = new ListService()
|
||||
const background = await listService.background(list)
|
||||
const projectService = new ProjectService()
|
||||
const background = await projectService.background(project)
|
||||
setBackground(background)
|
||||
} catch (e) {
|
||||
console.error('Error getting background image for list', list.id, e)
|
||||
console.error('Error getting background image for project', project.id, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
typeof list.backgroundInformation === 'undefined' ||
|
||||
list.backgroundInformation === null
|
||||
typeof project.backgroundInformation === 'undefined' ||
|
||||
project.backgroundInformation === null
|
||||
) {
|
||||
setBackground('')
|
||||
setBlurHash('')
|
||||
}
|
||||
|
||||
setCurrentList(list)
|
||||
setCurrentProject(project)
|
||||
}
|
||||
|
||||
const authStore = useAuthStore()
|
||||
@ -128,7 +128,7 @@ export const useBaseStore = defineStore('base', () => {
|
||||
return {
|
||||
loading: readonly(loading),
|
||||
ready: readonly(ready),
|
||||
currentList: readonly(currentList),
|
||||
currentProject: readonly(currentProject),
|
||||
background: readonly(background),
|
||||
blurHash: readonly(blurHash),
|
||||
hasTasks: readonly(hasTasks),
|
||||
@ -138,7 +138,7 @@ export const useBaseStore = defineStore('base', () => {
|
||||
|
||||
setLoading,
|
||||
setReady,
|
||||
setCurrentList,
|
||||
setCurrentProject,
|
||||
setHasTasks,
|
||||
setKeyboardShortcutsActive,
|
||||
setQuickActionsActive,
|
||||
@ -146,7 +146,7 @@ export const useBaseStore = defineStore('base', () => {
|
||||
setBlurHash,
|
||||
setLogoVisible,
|
||||
|
||||
handleSetCurrentList,
|
||||
handleSetCurrentProject,
|
||||
loadApp,
|
||||
|
||||
...useMenuActive(),
|
||||
|
@ -12,7 +12,7 @@ import TaskCollectionService from '@/services/taskCollection'
|
||||
import {setModuleLoading} from '@/stores/helper'
|
||||
|
||||
import type {ITask} from '@/modelTypes/ITask'
|
||||
import type {IList} from '@/modelTypes/IList'
|
||||
import type {IProject} from '@/modelTypes/IProject'
|
||||
import type {IBucket} from '@/modelTypes/IBucket'
|
||||
|
||||
const TASKS_PER_BUCKET = 25
|
||||
@ -45,7 +45,7 @@ const addTaskToBucketAndSort = (buckets: IBucket[], task: ITask) => {
|
||||
*/
|
||||
export const useKanbanStore = defineStore('kanban', () => {
|
||||
const buckets = ref<IBucket[]>([])
|
||||
const listId = ref<IList['id']>(0)
|
||||
const projectId = ref<IProject['id']>(0)
|
||||
const bucketLoading = ref<{[id: IBucket['id']]: boolean}>({})
|
||||
const taskPagesPerBucket = ref<{[id: IBucket['id']]: number}>({})
|
||||
const allTasksLoadedForBucket = ref<{[id: IBucket['id']]: boolean}>({})
|
||||
@ -68,8 +68,8 @@ export const useKanbanStore = defineStore('kanban', () => {
|
||||
isLoading.value = newIsLoading
|
||||
}
|
||||
|
||||
function setListId(newListId: IList['id']) {
|
||||
listId.value = Number(newListId)
|
||||
function setProjectId(newProjectId: IProject['id']) {
|
||||
projectId.value = Number(newProjectId)
|
||||
}
|
||||
|
||||
function setBuckets(newBuckets: IBucket[]) {
|
||||
@ -223,20 +223,20 @@ export const useKanbanStore = defineStore('kanban', () => {
|
||||
allTasksLoadedForBucket.value[bucketId] = true
|
||||
}
|
||||
|
||||
async function loadBucketsForList({listId, params}: {listId: IList['id'], params}) {
|
||||
async function loadBucketsForProject({projectId, params}: {projectId: IProject['id'], params}) {
|
||||
const cancel = setModuleLoading(setIsLoading)
|
||||
|
||||
// Clear everything to prevent having old buckets in the list if loading the buckets from this list takes a few moments
|
||||
// Clear everything to prevent having old buckets in the project if loading the buckets from this project takes a few moments
|
||||
setBuckets([])
|
||||
|
||||
const bucketService = new BucketService()
|
||||
try {
|
||||
const newBuckets = await bucketService.getAll({listId}, {
|
||||
const newBuckets = await bucketService.getAll({projectId}, {
|
||||
...params,
|
||||
per_page: TASKS_PER_BUCKET,
|
||||
})
|
||||
setBuckets(newBuckets)
|
||||
setListId(listId)
|
||||
setProjectId(projectId)
|
||||
return newBuckets
|
||||
} finally {
|
||||
cancel()
|
||||
@ -244,8 +244,8 @@ export const useKanbanStore = defineStore('kanban', () => {
|
||||
}
|
||||
|
||||
async function loadNextTasksForBucket(
|
||||
{listId, ps = {}, bucketId} :
|
||||
{listId: IList['id'], ps, bucketId: IBucket['id']},
|
||||
{projectId, ps = {}, bucketId} :
|
||||
{projectId: IProject['id'], ps, bucketId: IBucket['id']},
|
||||
) {
|
||||
const isLoading = bucketLoading.value[bucketId] ?? false
|
||||
if (isLoading) {
|
||||
@ -288,7 +288,7 @@ export const useKanbanStore = defineStore('kanban', () => {
|
||||
|
||||
const taskService = new TaskCollectionService()
|
||||
try {
|
||||
const tasks = await taskService.getAll({listId}, params, page)
|
||||
const tasks = await taskService.getAll({projectId}, params, page)
|
||||
addTasksToBucket({tasks, bucketId: bucketId})
|
||||
setTasksLoadedForBucketPage({bucketId, page})
|
||||
if (taskService.totalPages <= page) {
|
||||
@ -322,7 +322,7 @@ export const useKanbanStore = defineStore('kanban', () => {
|
||||
const response = await bucketService.delete(bucket)
|
||||
removeBucket(bucket)
|
||||
// We reload all buckets because tasks are being moved from the deleted bucket
|
||||
loadBucketsForList({listId: bucket.listId, params})
|
||||
loadBucketsForProject({projectId: bucket.projectId, params})
|
||||
return response
|
||||
} finally {
|
||||
cancel()
|
||||
@ -366,7 +366,7 @@ export const useKanbanStore = defineStore('kanban', () => {
|
||||
}
|
||||
|
||||
await updateBucket({ id, title })
|
||||
success({message: i18n.global.t('list.kanban.bucketTitleSavedSuccess')})
|
||||
success({message: i18n.global.t('project.kanban.bucketTitleSavedSuccess')})
|
||||
}
|
||||
|
||||
return {
|
||||
@ -382,7 +382,7 @@ export const useKanbanStore = defineStore('kanban', () => {
|
||||
setTaskInBucket,
|
||||
addTaskToBucket,
|
||||
removeTaskInBucket,
|
||||
loadBucketsForList,
|
||||
loadBucketsForProject,
|
||||
loadNextTasksForBucket,
|
||||
createBucket,
|
||||
deleteBucket,
|
||||
|
@ -35,7 +35,7 @@ export const useLabelStore = defineStore('label', () => {
|
||||
})
|
||||
|
||||
// **
|
||||
// * Checks if a list of labels is available in the store and filters them then query
|
||||
// * Checks if a project of labels is available in the store and filters them then query
|
||||
// **
|
||||
const filterLabelsByQuery = computed(() => {
|
||||
return (labelsToHide: ILabel[], query: string) => {
|
||||
|
@ -5,29 +5,29 @@ import NamespaceService from '../services/namespace'
|
||||
import {setModuleLoading} from '@/stores/helper'
|
||||
import {createNewIndexer} from '@/indexes'
|
||||
import type {INamespace} from '@/modelTypes/INamespace'
|
||||
import type {IList} from '@/modelTypes/IList'
|
||||
import {useListStore} from '@/stores/lists'
|
||||
import type {IProject} from '@/modelTypes/IProject'
|
||||
import {useProjectStore} from '@/stores/projects'
|
||||
|
||||
const {add, remove, search, update} = createNewIndexer('namespaces', ['title', 'description'])
|
||||
|
||||
export const useNamespaceStore = defineStore('namespace', () => {
|
||||
const listStore = useListStore()
|
||||
const projectStore = useProjectStore()
|
||||
|
||||
const isLoading = ref(false)
|
||||
// FIXME: should be object with id as key
|
||||
const namespaces = ref<INamespace[]>([])
|
||||
|
||||
const getListAndNamespaceById = computed(() => (listId: IList['id'], ignorePseudoNamespaces = false) => {
|
||||
const getProjectAndNamespaceById = computed(() => (projectId: IProject['id'], ignorePseudoNamespaces = false) => {
|
||||
for (const n in namespaces.value) {
|
||||
|
||||
if (ignorePseudoNamespaces && namespaces.value[n].id < 0) {
|
||||
continue
|
||||
}
|
||||
|
||||
for (const l in namespaces.value[n].lists) {
|
||||
if (namespaces.value[n].lists[l].id === listId) {
|
||||
for (const l in namespaces.value[n].projects) {
|
||||
if (namespaces.value[n].projects[l].id === projectId) {
|
||||
return {
|
||||
list: namespaces.value[n].lists[l],
|
||||
project: namespaces.value[n].projects[l],
|
||||
namespace: namespaces.value[n],
|
||||
}
|
||||
}
|
||||
@ -60,9 +60,9 @@ export const useNamespaceStore = defineStore('namespace', () => {
|
||||
newNamespaces.forEach(n => {
|
||||
add(n)
|
||||
|
||||
// Check for each list in that namespace if it has a subscription and set it if not
|
||||
n.lists.forEach(l => {
|
||||
if (l.subscription === null || l.subscription.entity !== 'list') {
|
||||
// Check for each project in that namespace if it has a subscription and set it if not
|
||||
n.projects.forEach(l => {
|
||||
if (l.subscription === null || l.subscription.entity !== 'project') {
|
||||
l.subscription = n.subscription
|
||||
}
|
||||
})
|
||||
@ -76,13 +76,13 @@ export const useNamespaceStore = defineStore('namespace', () => {
|
||||
return
|
||||
}
|
||||
|
||||
if (!namespace.lists || namespace.lists.length === 0) {
|
||||
namespace.lists = namespaces.value[namespaceIndex].lists
|
||||
if (!namespace.projects || namespace.projects.length === 0) {
|
||||
namespace.projects = namespaces.value[namespaceIndex].projects
|
||||
}
|
||||
|
||||
// Check for each list in that namespace if it has a subscription and set it if not
|
||||
namespace.lists.forEach(l => {
|
||||
if (l.subscription === null || l.subscription.entity !== 'list') {
|
||||
// Check for each project in that namespace if it has a subscription and set it if not
|
||||
namespace.projects.forEach(l => {
|
||||
if (l.subscription === null || l.subscription.entity !== 'project') {
|
||||
l.subscription = namespace.subscription
|
||||
}
|
||||
})
|
||||
@ -91,15 +91,15 @@ export const useNamespaceStore = defineStore('namespace', () => {
|
||||
update(namespace)
|
||||
}
|
||||
|
||||
function setListInNamespaceById(list: IList) {
|
||||
function setProjectInNamespaceById(project: IProject) {
|
||||
for (const n in namespaces.value) {
|
||||
// We don't have the namespace id on the list which means we need to loop over all lists until we find it.
|
||||
// We don't have the namespace id on the project which means we need to loop over all projects until we find it.
|
||||
// FIXME: Not ideal at all - we should fix that at the api level.
|
||||
if (namespaces.value[n].id === list.namespaceId) {
|
||||
for (const l in namespaces.value[n].lists) {
|
||||
if (namespaces.value[n].lists[l].id === list.id) {
|
||||
if (namespaces.value[n].id === project.namespaceId) {
|
||||
for (const l in namespaces.value[n].projects) {
|
||||
if (namespaces.value[n].projects[l].id === project.id) {
|
||||
const namespace = namespaces.value[n]
|
||||
namespace.lists[l] = list
|
||||
namespace.projects[l] = project
|
||||
namespaces.value[n] = namespace
|
||||
return
|
||||
}
|
||||
@ -123,23 +123,23 @@ export const useNamespaceStore = defineStore('namespace', () => {
|
||||
}
|
||||
}
|
||||
|
||||
function addListToNamespace(list: IList) {
|
||||
function addProjectToNamespace(project: IProject) {
|
||||
for (const n in namespaces.value) {
|
||||
if (namespaces.value[n].id === list.namespaceId) {
|
||||
namespaces.value[n].lists.push(list)
|
||||
if (namespaces.value[n].id === project.namespaceId) {
|
||||
namespaces.value[n].projects.push(project)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeListFromNamespaceById(list: IList) {
|
||||
function removeProjectFromNamespaceById(project: IProject) {
|
||||
for (const n in namespaces.value) {
|
||||
// We don't have the namespace id on the list which means we need to loop over all lists until we find it.
|
||||
// We don't have the namespace id on the project which means we need to loop over all projects until we find it.
|
||||
// FIXME: Not ideal at all - we should fix that at the api level.
|
||||
if (namespaces.value[n].id === list.namespaceId) {
|
||||
for (const l in namespaces.value[n].lists) {
|
||||
if (namespaces.value[n].lists[l].id === list.id) {
|
||||
namespaces.value[n].lists.splice(l, 1)
|
||||
if (namespaces.value[n].id === project.namespaceId) {
|
||||
for (const l in namespaces.value[n].projects) {
|
||||
if (namespaces.value[n].projects[l].id === project.id) {
|
||||
namespaces.value[n].projects.splice(l, 1)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -156,10 +156,10 @@ export const useNamespaceStore = defineStore('namespace', () => {
|
||||
const namespaces = await namespaceService.getAll({}, {is_archived: true}) as INamespace[]
|
||||
setNamespaces(namespaces)
|
||||
|
||||
// Put all lists in the list state
|
||||
const lists = namespaces.flatMap(({lists}) => lists)
|
||||
// Put all projects in the project state
|
||||
const projects = namespaces.flatMap(({projects}) => projects)
|
||||
|
||||
listStore.setLists(lists)
|
||||
projectStore.setProjects(projects)
|
||||
|
||||
return namespaces
|
||||
} finally {
|
||||
@ -176,7 +176,7 @@ export const useNamespaceStore = defineStore('namespace', () => {
|
||||
}
|
||||
|
||||
function removeFavoritesNamespaceIfEmpty() {
|
||||
if (namespaces.value[0].id === -2 && namespaces.value[0].lists.length === 0) {
|
||||
if (namespaces.value[0].id === -2 && namespaces.value[0].projects.length === 0) {
|
||||
namespaces.value.splice(0, 1)
|
||||
}
|
||||
}
|
||||
@ -211,17 +211,17 @@ export const useNamespaceStore = defineStore('namespace', () => {
|
||||
isLoading: readonly(isLoading),
|
||||
namespaces: readonly(namespaces),
|
||||
|
||||
getListAndNamespaceById,
|
||||
getProjectAndNamespaceById,
|
||||
getNamespaceById,
|
||||
searchNamespace,
|
||||
|
||||
setNamespaces,
|
||||
setNamespaceById,
|
||||
setListInNamespaceById,
|
||||
setProjectInNamespaceById,
|
||||
addNamespace,
|
||||
removeNamespaceById,
|
||||
addListToNamespace,
|
||||
removeListFromNamespaceById,
|
||||
addProjectToNamespace,
|
||||
removeProjectFromNamespaceById,
|
||||
loadNamespaces,
|
||||
loadNamespacesIfFavoritesDontExist,
|
||||
removeFavoritesNamespaceIfEmpty,
|
||||
|
@ -2,57 +2,57 @@ import {watch, reactive, shallowReactive, unref, toRefs, readonly, ref, computed
|
||||
import {acceptHMRUpdate, defineStore} from 'pinia'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
|
||||
import ListService from '@/services/list'
|
||||
import ProjectService from '@/services/project'
|
||||
import {setModuleLoading} from '@/stores/helper'
|
||||
import {removeListFromHistory} from '@/modules/listHistory'
|
||||
import {removeProjectFromHistory} from '@/modules/projectHistory'
|
||||
import {createNewIndexer} from '@/indexes'
|
||||
import {useNamespaceStore} from './namespaces'
|
||||
|
||||
import type {IList} from '@/modelTypes/IList'
|
||||
import type {IProject} from '@/modelTypes/IProject'
|
||||
|
||||
import type {MaybeRef} from '@vueuse/core'
|
||||
|
||||
import ListModel from '@/models/list'
|
||||
import ProjectModel from '@/models/project'
|
||||
import {success} from '@/message'
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
|
||||
const {add, remove, search, update} = createNewIndexer('lists', ['title', 'description'])
|
||||
const {add, remove, search, update} = createNewIndexer('projects', ['title', 'description'])
|
||||
|
||||
const FavoriteListsNamespace = -2
|
||||
const FavoriteProjectsNamespace = -2
|
||||
|
||||
export interface ListState {
|
||||
[id: IList['id']]: IList
|
||||
export interface ProjectState {
|
||||
[id: IProject['id']]: IProject
|
||||
}
|
||||
|
||||
export const useListStore = defineStore('list', () => {
|
||||
export const useProjectStore = defineStore('project', () => {
|
||||
const baseStore = useBaseStore()
|
||||
const namespaceStore = useNamespaceStore()
|
||||
|
||||
const isLoading = ref(false)
|
||||
|
||||
// The lists are stored as an object which has the list ids as keys.
|
||||
const lists = ref<ListState>({})
|
||||
// The projects are stored as an object which has the project ids as keys.
|
||||
const projects = ref<ProjectState>({})
|
||||
|
||||
|
||||
const getListById = computed(() => {
|
||||
return (id: IList['id']) => typeof lists.value[id] !== 'undefined' ? lists.value[id] : null
|
||||
const getProjectById = computed(() => {
|
||||
return (id: IProject['id']) => typeof projects.value[id] !== 'undefined' ? projects.value[id] : null
|
||||
})
|
||||
|
||||
const findListByExactname = computed(() => {
|
||||
const findProjectByExactname = computed(() => {
|
||||
return (name: string) => {
|
||||
const list = Object.values(lists.value).find(l => {
|
||||
const project = Object.values(projects.value).find(l => {
|
||||
return l.title.toLowerCase() === name.toLowerCase()
|
||||
})
|
||||
return typeof list === 'undefined' ? null : list
|
||||
return typeof project === 'undefined' ? null : project
|
||||
}
|
||||
})
|
||||
|
||||
const searchList = computed(() => {
|
||||
const searchProject = computed(() => {
|
||||
return (query: string, includeArchived = false) => {
|
||||
return search(query)
|
||||
?.filter(value => value > 0)
|
||||
.map(id => lists.value[id])
|
||||
.filter(list => list.isArchived === includeArchived)
|
||||
.map(id => projects.value[id])
|
||||
.filter(project => project.isArchived === includeArchived)
|
||||
|| []
|
||||
}
|
||||
})
|
||||
@ -61,82 +61,82 @@ export const useListStore = defineStore('list', () => {
|
||||
isLoading.value = newIsLoading
|
||||
}
|
||||
|
||||
function setList(list: IList) {
|
||||
lists.value[list.id] = list
|
||||
update(list)
|
||||
function setProject(project: IProject) {
|
||||
projects.value[project.id] = project
|
||||
update(project)
|
||||
|
||||
if (baseStore.currentList?.id === list.id) {
|
||||
baseStore.setCurrentList(list)
|
||||
if (baseStore.currentProject?.id === project.id) {
|
||||
baseStore.setCurrentProject(project)
|
||||
}
|
||||
}
|
||||
|
||||
function setLists(newLists: IList[]) {
|
||||
newLists.forEach(l => {
|
||||
lists.value[l.id] = l
|
||||
function setProjects(newProjects: IProject[]) {
|
||||
newProjects.forEach(l => {
|
||||
projects.value[l.id] = l
|
||||
add(l)
|
||||
})
|
||||
}
|
||||
|
||||
function removeListById(list: IList) {
|
||||
remove(list)
|
||||
delete lists.value[list.id]
|
||||
function removeProjectById(project: IProject) {
|
||||
remove(project)
|
||||
delete projects.value[project.id]
|
||||
}
|
||||
|
||||
function toggleListFavorite(list: IList) {
|
||||
// The favorites pseudo list is always favorite
|
||||
// Archived lists cannot be marked favorite
|
||||
if (list.id === -1 || list.isArchived) {
|
||||
function toggleProjectFavorite(project: IProject) {
|
||||
// The favorites pseudo project is always favorite
|
||||
// Archived projects cannot be marked favorite
|
||||
if (project.id === -1 || project.isArchived) {
|
||||
return
|
||||
}
|
||||
return updateList({
|
||||
...list,
|
||||
isFavorite: !list.isFavorite,
|
||||
return updateProject({
|
||||
...project,
|
||||
isFavorite: !project.isFavorite,
|
||||
})
|
||||
}
|
||||
|
||||
async function createList(list: IList) {
|
||||
async function createProject(project: IProject) {
|
||||
const cancel = setModuleLoading(setIsLoading)
|
||||
const listService = new ListService()
|
||||
const projectService = new ProjectService()
|
||||
|
||||
try {
|
||||
const createdList = await listService.create(list)
|
||||
createdList.namespaceId = list.namespaceId
|
||||
namespaceStore.addListToNamespace(createdList)
|
||||
setList(createdList)
|
||||
return createdList
|
||||
const createdProject = await projectService.create(project)
|
||||
createdProject.namespaceId = project.namespaceId
|
||||
namespaceStore.addProjectToNamespace(createdProject)
|
||||
setProject(createdProject)
|
||||
return createdProject
|
||||
} finally {
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
|
||||
async function updateList(list: IList) {
|
||||
async function updateProject(project: IProject) {
|
||||
const cancel = setModuleLoading(setIsLoading)
|
||||
const listService = new ListService()
|
||||
const projectService = new ProjectService()
|
||||
|
||||
try {
|
||||
await listService.update(list)
|
||||
setList(list)
|
||||
namespaceStore.setListInNamespaceById(list)
|
||||
await projectService.update(project)
|
||||
setProject(project)
|
||||
namespaceStore.setProjectInNamespaceById(project)
|
||||
|
||||
// the returned list from listService.update is the same!
|
||||
// the returned project from projectService.update is the same!
|
||||
// in order to not create a manipulation in pinia store we have to create a new copy
|
||||
const newList = {
|
||||
...list,
|
||||
namespaceId: FavoriteListsNamespace,
|
||||
const newProject = {
|
||||
...project,
|
||||
namespaceId: FavoriteProjectsNamespace,
|
||||
}
|
||||
|
||||
namespaceStore.removeListFromNamespaceById(newList)
|
||||
if (list.isFavorite) {
|
||||
namespaceStore.addListToNamespace(newList)
|
||||
namespaceStore.removeProjectFromNamespaceById(newProject)
|
||||
if (project.isFavorite) {
|
||||
namespaceStore.addProjectToNamespace(newProject)
|
||||
}
|
||||
namespaceStore.loadNamespacesIfFavoritesDontExist()
|
||||
namespaceStore.removeFavoritesNamespaceIfEmpty()
|
||||
return newList
|
||||
return newProject
|
||||
} catch (e) {
|
||||
// Reset the list state to the initial one to avoid confusion for the user
|
||||
setList({
|
||||
...list,
|
||||
isFavorite: !list.isFavorite,
|
||||
// Reset the project state to the initial one to avoid confusion for the user
|
||||
setProject({
|
||||
...project,
|
||||
isFavorite: !project.isFavorite,
|
||||
})
|
||||
throw e
|
||||
} finally {
|
||||
@ -144,15 +144,15 @@ export const useListStore = defineStore('list', () => {
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteList(list: IList) {
|
||||
async function deleteProject(project: IProject) {
|
||||
const cancel = setModuleLoading(setIsLoading)
|
||||
const listService = new ListService()
|
||||
const projectService = new ProjectService()
|
||||
|
||||
try {
|
||||
const response = await listService.delete(list)
|
||||
removeListById(list)
|
||||
namespaceStore.removeListFromNamespaceById(list)
|
||||
removeListFromHistory({id: list.id})
|
||||
const response = await projectService.delete(project)
|
||||
removeProjectById(project)
|
||||
namespaceStore.removeProjectFromNamespaceById(project)
|
||||
removeProjectFromHistory({id: project.id})
|
||||
return response
|
||||
} finally {
|
||||
cancel()
|
||||
@ -161,51 +161,51 @@ export const useListStore = defineStore('list', () => {
|
||||
|
||||
return {
|
||||
isLoading: readonly(isLoading),
|
||||
lists: readonly(lists),
|
||||
projects: readonly(projects),
|
||||
|
||||
getListById,
|
||||
findListByExactname,
|
||||
searchList,
|
||||
getProjectById,
|
||||
findProjectByExactname,
|
||||
searchProject,
|
||||
|
||||
setList,
|
||||
setLists,
|
||||
removeListById,
|
||||
toggleListFavorite,
|
||||
createList,
|
||||
updateList,
|
||||
deleteList,
|
||||
setProject,
|
||||
setProjects,
|
||||
removeProjectById,
|
||||
toggleProjectFavorite,
|
||||
createProject,
|
||||
updateProject,
|
||||
deleteProject,
|
||||
}
|
||||
})
|
||||
|
||||
export function useList(listId: MaybeRef<IList['id']>) {
|
||||
const listService = shallowReactive(new ListService())
|
||||
const {loading: isLoading} = toRefs(listService)
|
||||
const list: IList = reactive(new ListModel())
|
||||
export function useProject(projectId: MaybeRef<IProject['id']>) {
|
||||
const projectService = shallowReactive(new ProjectService())
|
||||
const {loading: isLoading} = toRefs(projectService)
|
||||
const project: IProject = reactive(new ProjectModel())
|
||||
const {t} = useI18n({useScope: 'global'})
|
||||
|
||||
watch(
|
||||
() => unref(listId),
|
||||
async (listId) => {
|
||||
const loadedList = await listService.get(new ListModel({id: listId}))
|
||||
Object.assign(list, loadedList)
|
||||
() => unref(projectId),
|
||||
async (projectId) => {
|
||||
const loadedProject = await projectService.get(new ProjectModel({id: projectId}))
|
||||
Object.assign(project, loadedProject)
|
||||
},
|
||||
{immediate: true},
|
||||
)
|
||||
|
||||
const listStore = useListStore()
|
||||
const projectStore = useProjectStore()
|
||||
async function save() {
|
||||
await listStore.updateList(list)
|
||||
success({message: t('list.edit.success')})
|
||||
await projectStore.updateProject(project)
|
||||
success({message: t('project.edit.success')})
|
||||
}
|
||||
|
||||
return {
|
||||
isLoading: readonly(isLoading),
|
||||
list,
|
||||
project,
|
||||
save,
|
||||
}
|
||||
}
|
||||
|
||||
// support hot reloading
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.accept(acceptHMRUpdate(useListStore, import.meta.hot))
|
||||
import.meta.hot.accept(acceptHMRUpdate(useProjectStore, import.meta.hot))
|
||||
}
|
@ -21,11 +21,11 @@ import type {ILabel} from '@/modelTypes/ILabel'
|
||||
import type {ITask} from '@/modelTypes/ITask'
|
||||
import type {IUser} from '@/modelTypes/IUser'
|
||||
import type {IAttachment} from '@/modelTypes/IAttachment'
|
||||
import type {IList} from '@/modelTypes/IList'
|
||||
import type {IProject} from '@/modelTypes/IProject'
|
||||
|
||||
import {setModuleLoading} from '@/stores/helper'
|
||||
import {useLabelStore} from '@/stores/labels'
|
||||
import {useListStore} from '@/stores/lists'
|
||||
import {useProjectStore} from '@/stores/projects'
|
||||
import {useAttachmentStore} from '@/stores/attachments'
|
||||
import {useKanbanStore} from '@/stores/kanban'
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
@ -83,7 +83,7 @@ export const useTaskStore = defineStore('task', () => {
|
||||
const kanbanStore = useKanbanStore()
|
||||
const attachmentStore = useAttachmentStore()
|
||||
const labelStore = useLabelStore()
|
||||
const listStore = useListStore()
|
||||
const projectStore = useProjectStore()
|
||||
|
||||
const tasks = ref<{ [id: ITask['id']]: ITask }>({}) // TODO: or is this ITask[]
|
||||
const isLoading = ref(false)
|
||||
@ -292,7 +292,7 @@ export const useTaskStore = defineStore('task', () => {
|
||||
return response
|
||||
}
|
||||
|
||||
// Remove the label from the list
|
||||
// Remove the label from the project
|
||||
const labels = t.task.labels.filter(({ id }) => id !== label.id)
|
||||
|
||||
kanbanStore.setTaskInBucketByIndex({
|
||||
@ -337,40 +337,40 @@ export const useTaskStore = defineStore('task', () => {
|
||||
return task
|
||||
}
|
||||
|
||||
function findListId(
|
||||
{ list: listName, listId }:
|
||||
{ list: string, listId: IList['id'] }) {
|
||||
let foundListId = null
|
||||
|
||||
// Uses the following ways to get the list id of the new task:
|
||||
function findProjectId(
|
||||
{ project: projectName, projectId }:
|
||||
{ project: string, projectId: IProject['id'] }) {
|
||||
let foundProjectId = null
|
||||
|
||||
// Uses the following ways to get the project id of the new task:
|
||||
// 1. If specified in quick add magic, look in store if it exists and use it if it does
|
||||
if (listName !== null) {
|
||||
const list = listStore.findListByExactname(listName)
|
||||
foundListId = list === null ? null : list.id
|
||||
if (typeof projectName !== 'undefined' && projectName !== null) {
|
||||
const project = projectStore.findProjectByExactname(projectName)
|
||||
foundProjectId = project === null ? null : project.id
|
||||
}
|
||||
|
||||
// 2. Else check if a list was passed as parameter
|
||||
if (foundListId === null && listId !== 0) {
|
||||
foundListId = listId
|
||||
// 2. Else check if a project was passed as parameter
|
||||
if (foundProjectId === null && projectId !== 0) {
|
||||
foundProjectId = projectId
|
||||
}
|
||||
|
||||
// 3. Otherwise use the id from the route parameter
|
||||
if (typeof router.currentRoute.value.params.listId !== 'undefined') {
|
||||
foundListId = Number(router.currentRoute.value.params.listId)
|
||||
if (typeof router.currentRoute.value.params.projectId !== 'undefined') {
|
||||
foundProjectId = Number(router.currentRoute.value.params.projectId)
|
||||
}
|
||||
|
||||
// 4. If none of the above worked, reject the promise with an error.
|
||||
if (typeof foundListId === 'undefined' || listId === null) {
|
||||
throw new Error('NO_LIST')
|
||||
if (typeof foundProjectId === 'undefined' || projectId === null) {
|
||||
throw new Error('NO_PROJECT')
|
||||
}
|
||||
|
||||
return foundListId
|
||||
return foundProjectId
|
||||
}
|
||||
|
||||
async function createNewTask({
|
||||
title,
|
||||
bucketId,
|
||||
listId,
|
||||
projectId,
|
||||
position,
|
||||
} :
|
||||
Partial<ITask>,
|
||||
@ -379,14 +379,14 @@ export const useTaskStore = defineStore('task', () => {
|
||||
const quickAddMagicMode = getQuickAddMagicMode()
|
||||
const parsedTask = parseTaskText(title, quickAddMagicMode)
|
||||
|
||||
const foundListId = await findListId({
|
||||
list: parsedTask.list,
|
||||
listId: listId || 0,
|
||||
const foundProjectId = await findProjectId({
|
||||
project: parsedTask.project,
|
||||
projectId: projectId || 0,
|
||||
})
|
||||
|
||||
if(foundListId === null || foundListId === 0) {
|
||||
if(foundProjectId === null || foundProjectId === 0) {
|
||||
cancel()
|
||||
throw new Error('NO_LIST')
|
||||
throw new Error('NO_PROJECT')
|
||||
}
|
||||
|
||||
const assignees = await findAssignees(parsedTask.assignees)
|
||||
@ -405,7 +405,7 @@ export const useTaskStore = defineStore('task', () => {
|
||||
|
||||
const task = new TaskModel({
|
||||
title: cleanedTitle,
|
||||
listId: foundListId,
|
||||
projectId: foundProjectId,
|
||||
dueDate,
|
||||
priority: parsedTask.priority,
|
||||
assignees,
|
||||
@ -451,7 +451,7 @@ export const useTaskStore = defineStore('task', () => {
|
||||
addLabelsToTask,
|
||||
createNewTask,
|
||||
setCoverImage,
|
||||
findListId,
|
||||
findProjectId,
|
||||
ensureLabelsExist,
|
||||
}
|
||||
})
|
||||
|
Reference in New Issue
Block a user