diff --git a/frontend/src/api/webmail.js b/frontend/src/api/webmail.js index 067b42a2b..6ee58d7e7 100644 --- a/frontend/src/api/webmail.js +++ b/frontend/src/api/webmail.js @@ -65,23 +65,31 @@ export default { responseType: 'blob', }) }, - deleteSelection(mailbox, selection) { + moveSelection(source, destination, selection) { const body = { - mailbox, + source, + destination, + selection, + } + return repository.post('/webmail/emails/move/', body) + }, + deleteSelection(source, selection) { + const body = { + source, selection, } return repository.post('/webmail/emails/delete/', body) }, - markSelectionAsJunk(mailbox, selection) { + markSelectionAsJunk(source, selection) { const body = { - mailbox, + source, selection, } return repository.post('/webmail/emails/mark_as_junk/', body) }, - markSelectionAsNotJunk(mailbox, selection) { + markSelectionAsNotJunk(source, selection) { const body = { - mailbox, + source, selection, } return repository.post('/webmail/emails/mark_as_not_junk/', body) diff --git a/frontend/src/components/webmail/EmailList.vue b/frontend/src/components/webmail/EmailList.vue index 45da064a2..4c7f2d8e3 100644 --- a/frontend/src/components/webmail/EmailList.vue +++ b/frontend/src/components/webmail/EmailList.vue @@ -5,6 +5,7 @@ v-model="selectAll" class="mr-4" hide-details + color="primary" @update:model-value="toggleAllSelection" /> @@ -119,14 +120,17 @@ :key="email.imapid" density="compact" class="mb-2 mx-1" + draggable="true" + @dragstart="onDragStart(email)" > { const toggleAllSelection = (value) => { if (!value) { - selection.value = [] + webmailStore.selection = [] } else { - selection.value = emails.value.results.map((email) => email.imapid) + webmailStore.selection = emails.value.results.map((email) => email.imapid) } } const deleteSelection = () => { - if (!selection.value.length) { + if (!webmailStore.selection.length) { return } working.value = true - api.deleteSelection(currentMailbox.value, selection.value).then(() => { + api.deleteSelection(currentMailbox.value, webmailStore.selection).then(() => { working.value = false displayNotification({ msg: $gettext('Message(s) deleted') }) fetchEmails() @@ -253,41 +257,47 @@ const deleteSelection = () => { } const markSelectionAsJunk = () => { - if (!selection.value.length) { + if (!webmailStore.selection.length) { return } working.value = true - api.markSelectionAsJunk(currentMailbox.value, selection.value).then(() => { - working.value = false - displayNotification({ msg: $gettext('Message(s) marked as junk') }) - autoRefreshContent() - }) + api + .markSelectionAsJunk(currentMailbox.value, webmailStore.selection) + .then(() => { + working.value = false + displayNotification({ msg: $gettext('Message(s) marked as junk') }) + autoRefreshContent() + }) } const markSelectionAsNotJunk = () => { - if (!selection.value.length) { + if (!webmailStore.selection.length) { return } working.value = true - api.markSelectionAsNotJunk(currentMailbox.value, selection.value).then(() => { - working.value = false - displayNotification({ msg: $gettext('Message(s) marked as not junk') }) - autoRefreshContent() - }) + api + .markSelectionAsNotJunk(currentMailbox.value, webmailStore.selection) + .then(() => { + working.value = false + displayNotification({ msg: $gettext('Message(s) marked as not junk') }) + autoRefreshContent() + }) } const flagSelection = (status) => { - if (!selection.value.length) { + if (!webmailStore.selection.length) { return } working.value = true - api.flagSelection(currentMailbox.value, selection.value, status).then(() => { - working.value = false - selection.value = [] - displayNotification({ msg: $gettext('Message(s) flagged') }) - fetchEmails() - reloadMailboxCounters() - }) + api + .flagSelection(currentMailbox.value, webmailStore.selection, status) + .then(() => { + working.value = false + webmailStore.selection = [] + displayNotification({ msg: $gettext('Message(s) flagged') }) + fetchEmails() + reloadMailboxCounters() + }) } const emptyMailbox = () => { @@ -305,6 +315,25 @@ const toggleFollowState = async (email) => { email.flagged = flag === 'flagged' } +const onDragStart = (email) => { + if (!webmailStore.selection.includes(email.imapid)) { + webmailStore.selection = [email.imapid] + } + const ghost = document.createElement('div') + const count = webmailStore.selection.length || 0 + const msg = $ngettext('%{count} message', '%{count} messages', count, { + count, + }) + ghost.innerHTML = ` +
+
${msg}
+
+ ` + document.body.appendChild(ghost) + event.dataTransfer.setDragImage(ghost, -10, -10) + setTimeout(() => ghost.remove(), 0) +} + onMounted(() => { intervalId = setInterval(autoRefreshContent, 300 * 1000) }) @@ -320,13 +349,22 @@ watch( }, { immediate: true } ) -watch(selection, () => { - if (!selection.value.length) { - selectAll.value = false - } else { - selectAll.value = true +watch( + () => webmailStore.selection, + () => { + if (!webmailStore.selection.length) { + selectAll.value = false + } else { + selectAll.value = true + } } -}) +) +watch( + () => webmailStore.listingKey, + () => { + fetchEmails() + } +) watch(page, () => { fetchEmails() }) diff --git a/frontend/src/components/webmail/MailboxList.vue b/frontend/src/components/webmail/MailboxList.vue index 1e65dc104..9962cda7e 100644 --- a/frontend/src/components/webmail/MailboxList.vue +++ b/frontend/src/components/webmail/MailboxList.vue @@ -12,6 +12,10 @@ @click="updateSelection(mailbox.name)" @mouseover="setHover(mailbox, true)" @mouseleave="setHover(mailbox, false)" + @dragover.prevent + @dragenter="setHover(mailbox, true)" + @dragleave="setHover(mailbox, false)" + @drop="onDrop(mailbox)" >