diff --git a/src/App.vue b/src/App.vue
index 906d8b7..7d2824d 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -2,4 +2,5 @@
+
\ No newline at end of file
diff --git a/src/components.d.ts b/src/components.d.ts
index 07643a1..292d2c1 100644
--- a/src/components.d.ts
+++ b/src/components.d.ts
@@ -30,11 +30,6 @@ declare module 'vue' {
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
Select: typeof import('primevue/select')['default']
- Tab: typeof import('primevue/tab')['default']
- TabList: typeof import('primevue/tablist')['default']
- TabPanel: typeof import('primevue/tabpanel')['default']
- TabPanels: typeof import('primevue/tabpanels')['default']
- Tabs: typeof import('primevue/tabs')['default']
Tag: typeof import('primevue/tag')['default']
Textarea: typeof import('primevue/textarea')['default']
Toast: typeof import('primevue/toast')['default']
diff --git a/src/components/LoadingOverlay.vue b/src/components/LoadingOverlay.vue
new file mode 100644
index 0000000..7ecbb90
--- /dev/null
+++ b/src/components/LoadingOverlay.vue
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/composables/useLoading.ts b/src/composables/useLoading.ts
new file mode 100644
index 0000000..234fafa
--- /dev/null
+++ b/src/composables/useLoading.ts
@@ -0,0 +1,22 @@
+import { ref } from 'vue'
+
+const pendingCount = ref(0)
+const loading = ref(false)
+
+export function useLoading() {
+ function start() {
+ pendingCount.value++
+ loading.value = true
+ }
+
+ function stop() {
+ if (pendingCount.value > 0) {
+ pendingCount.value--
+ }
+ if (pendingCount.value === 0) {
+ loading.value = false
+ }
+ }
+
+ return { loading, start, stop }
+}
diff --git a/src/services/api.ts b/src/services/api.ts
index 04b0e89..e692913 100644
--- a/src/services/api.ts
+++ b/src/services/api.ts
@@ -1,4 +1,7 @@
import axios, { type AxiosInstance } from 'axios'
+import { useLoading } from '../composables/useLoading'
+
+const { start: loadingStart, stop: loadingStop } = useLoading()
export const api: AxiosInstance = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:2000',
@@ -8,6 +11,7 @@ export const api: AxiosInstance = axios.create({
})
api.interceptors.request.use((config) => {
+ loadingStart()
const token = localStorage.getItem('mws_token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
@@ -16,8 +20,12 @@ api.interceptors.request.use((config) => {
})
api.interceptors.response.use(
- (response) => response,
+ (response) => {
+ loadingStop()
+ return response
+ },
(error) => {
+ loadingStop()
if (error.response?.status === 401) {
localStorage.removeItem('mws_token')
localStorage.removeItem('mws_user')
diff --git a/src/views/tasks/TasksBoardView.vue b/src/views/tasks/TasksBoardView.vue
index 1168c90..ec1f2b5 100644
--- a/src/views/tasks/TasksBoardView.vue
+++ b/src/views/tasks/TasksBoardView.vue
@@ -29,10 +29,10 @@
draggable="true"
@dragstart="onDragStart(task)"
@dragend="onDragEnd"
- @click.stop="toggleDesc(task.id)"
+ @click.stop="openEdit(task)"
>
{{ task.title }}
- {{ task.description }}
+ {{ task.description }}
{{ task.assigneeName }}
@@ -80,7 +80,7 @@ const route = useRoute()
const toast = useToast()
const auth = useAuthStore()
-const projectId = String(route.params.id)
+const projectId = computed(() => String(route.params.id))
const tasks = ref([])
const members = ref<{ userId: string; displayName: string }[]>([])
@@ -89,13 +89,10 @@ const dragOverStatus = ref(null)
const dialogVisible = ref(false)
const editingTask = ref(null)
-const expandedDescs = ref(new Set())
-function toggleDesc(id: string) {
- const s = new Set(expandedDescs.value)
- if (s.has(id)) s.delete(id)
- else s.add(id)
- expandedDescs.value = s
+function openEdit(task: Task) {
+ editingTask.value = task
+ dialogVisible.value = true
}
const columns = [
@@ -111,7 +108,7 @@ function tasksIn(status: TaskStatus) {
async function load() {
try {
- const res = await getTasks(projectId, undefined, 1, 100)
+ const res = await getTasks(projectId.value, undefined, 1, 100)
tasks.value = res.items
} catch (e) {
toast.add({ severity: 'error', summary: 'Error', detail: errorMessage(e), life: 4000 })
@@ -120,7 +117,7 @@ async function load() {
async function loadMembers() {
try {
- const res = await getMembers(projectId, 1, 100)
+ const res = await getMembers(projectId.value, 1, 100)
members.value = res.items.map((m) => ({
userId: m.userId,
displayName: m.displayName,
@@ -196,10 +193,14 @@ function formatDate(v: string) {
return new Date(v).toLocaleDateString()
}
-onMounted(async () => {
- await loadMembers()
- await load()
-})
+watch(
+ () => route.params.id,
+ async () => {
+ await loadMembers()
+ await load()
+ },
+ { immediate: true },
+)