Merge pull request #2730 from nextcloud/feature/add_delete_action_folder

Add delete action for folders
This commit is contained in:
Christoph Wurst 2020-08-10 16:39:37 +02:00 коммит произвёл GitHub
Родитель 72617c4d85 a543bbcd4b
Коммит 1530f48e5a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
10 изменённых файлов: 200 добавлений и 1 удалений

Просмотреть файл

@ -79,6 +79,11 @@ return [
'url' => '/api/accounts/{accountId}/folders/{folderId}/stats',
'verb' => 'GET'
],
[
'name' => 'folders#delete',
'url' => '/api/accounts/{accountId}/folders/{folderId}',
'verb' => 'DELETE'
],
[
'name' => 'messages#downloadAttachment',
'url' => '/api/accounts/{accountId}/folders/{folderId}/messages/{messageId}/attachment/{attachmentId}',

Просмотреть файл

@ -142,4 +142,12 @@ interface IMailManager {
* @return Quota|null
*/
public function getQuota(Account $account): ?Quota;
/**
* @param Account $account
* @param string $folderId
*
* @throws ServiceException
*/
public function deleteMailbox(Account $account, string $folderId): void;
}

Просмотреть файл

@ -234,4 +234,17 @@ class FoldersController extends Controller {
return new JSONResponse($this->mailManager->createFolder($account, $name));
}
/**
* @NoAdminRequired
* @TrapError
* @param int $accountId
* @param string $folderId
* @throws ServiceException
*/
public function delete(int $accountId, string $folderId): JSONResponse {
$account = $this->accountService->find($this->currentUserId, $accountId);
$this->mailManager->deleteMailbox($account, base64_decode($folderId));
return new JSONResponse();
}
}

Просмотреть файл

@ -219,4 +219,17 @@ class FolderMapper {
}
}
}
/**
* @param Horde_Imap_Client_Socket $client
* @param string $folderId
* @throws ServiceException
*/
public function delete(Horde_Imap_Client_Socket $client, string $folderId): void {
try {
$client->deleteMailbox($folderId);
} catch (Horde_Imap_Client_Exception $e) {
throw new ServiceException('Could not delete mailbox: '.$e->getMessage(), 0, $e);
}
}
}

Просмотреть файл

@ -373,4 +373,21 @@ class MailManager implements IMailManager {
1024 * (int)($storage['limit'] ?? 0)
);
}
/**
* @param Account $account
* @param string $folderId
* @throws ServiceException
*/
public function deleteMailbox(Account $account,
string $folderId): void {
try {
$mailbox = $this->mailboxMapper->find($account, $folderId);
} catch (DoesNotExistException $e) {
throw new ServiceException("Source mailbox $folderId does not exist", 0, $e);
}
$client = $this->imapClientFactory->getClient($account);
$this->folderMapper->delete($client, $folderId);
$this->mailboxMapper->delete($mailbox);
}
}

Просмотреть файл

@ -70,6 +70,9 @@
@click="clearCache">
{{ t('mail', 'Clear locally cached data, in case there are issues with synchronization.') }}
</ActionButton>
<ActionButton v-if="!account.isUnified && !folder.specialRole" icon="icon-delete" @click="deleteFolder">
{{ t('mail', 'Delete folder') }}
</ActionButton>
</template>
</template>
<AppNavigationCounter v-if="folder.unread" slot="counter">
@ -294,6 +297,32 @@ export default {
this.clearCache = false
}
},
deleteFolder() {
const id = this.folder.id
logger.info('delete folder', { folder: this.folder })
OC.dialogs.confirmDestructive(
t('mail', 'The folder and all messages in it will be deleted.', {
folderId: this.folderId,
}),
t('mail', 'Delete folder'),
{
type: OC.dialogs.YES_NO_BUTTONS,
confirm: t('mail', 'Delete folder {folderId}', { folderId: this.folderId }),
confirmClasses: 'error',
cancel: t('mail', 'Cancel'),
},
(result) => {
if (result) {
return this.$store
.dispatch('deleteFolder', { account: this.account, folder: this.folder })
.then(() => {
logger.info(`folder ${id} deleted`)
})
.catch((error) => logger.error('could not delete folder', { error }))
}
}
)
},
},
}
</script>

Просмотреть файл

@ -39,3 +39,12 @@ export function markFolderRead(accountId, folderId) {
return Axios.post(url).then((resp) => resp.data)
}
export const deleteFolder = async(accountId, folderId) => {
const url = generateUrl('/apps/mail/api/accounts/{accountId}/folders/{folderId}', {
accountId,
folderId,
})
await Axios.delete(url)
}

Просмотреть файл

@ -50,7 +50,12 @@ import {
update as updateAccount,
updateSignature,
} from '../service/AccountService'
import { create as createFolder, fetchAll as fetchAllFolders, markFolderRead } from '../service/FolderService'
import {
create as createFolder,
fetchAll as fetchAllFolders,
markFolderRead,
deleteFolder,
} from '../service/FolderService'
import {
deleteMessage,
fetchEnvelope,
@ -147,6 +152,10 @@ export default {
throw err
})
},
async deleteFolder({ commit }, { account, folder }) {
await deleteFolder(account.id, folder.id)
commit('removeFolder', { accountId: account.id, folderId: folder.id })
},
createFolder({ commit }, { account, name }) {
return createFolder(account.id, name).then((folder) => {
console.debug(`folder ${name} created for account ${account.id}`, { folder })

Просмотреть файл

@ -110,6 +110,18 @@ export default {
account.folders.push(id)
})
},
removeFolder(state, { accountId, folderId }) {
const account = state.accounts[accountId]
const id = normalizedFolderId(accountId, folderId)
Vue.delete(state.folders, id)
account.folders = account.folders.filter((fId) => fId !== id)
account.folders.forEach((fId) => {
const folder = state.folders[fId]
if (folder.folders) {
folder.folders = folder.folders.filter((fId) => fId !== id)
}
})
},
addEnvelope(state, { accountId, folderId, query, envelope }) {
const folder = state.folders[normalizedFolderId(accountId, folderId)]
Vue.set(state.envelopes, envelope.uuid, envelope)

Просмотреть файл

@ -254,4 +254,88 @@ describe('Vuex store mutations', () => {
},
})
})
it('removes a folder', () => {
const state = {
accounts: {
13: {
accountId: 13,
id: 13,
folders: ['13-INBOX'],
},
},
folders: {
'13-INBOX': {
id: 'INBOX',
specialUse: ['inbox'],
specialRole: 'inbox',
},
},
}
mutations.removeFolder(state, {
accountId: 13,
folderId: 'INBOX',
})
expect(state).to.deep.equal({
accounts: {
13: {
accountId: 13,
id: 13,
folders: [],
},
},
folders: {},
})
})
it('removes a subfolder', () => {
const state = {
accounts: {
13: {
accountId: 13,
id: 13,
folders: ['13-INBOX'],
},
},
folders: {
'13-INBOX': {
id: 'INBOX',
specialUse: ['inbox'],
specialRole: 'inbox',
folders: ['13-INBOX.sub'],
},
'13-INBOX.sub': {
id: 'INBOX.sub',
specialUse: ['inbox'],
specialRole: 'inbox',
folders: [],
},
},
}
mutations.removeFolder(state, {
accountId: 13,
folderId: 'INBOX.sub',
})
expect(state).to.deep.equal({
accounts: {
13: {
accountId: 13,
id: 13,
folders: ['13-INBOX'],
},
},
folders: {
'13-INBOX': {
id: 'INBOX',
specialUse: ['inbox'],
specialRole: 'inbox',
folders: [],
},
},
})
})
})