Skip to content
Snippets Groups Projects
NavigationAccount.vue 7.67 KiB
Newer Older
  • Learn to ignore specific revisions
  • <!--
      - @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
      -
      - @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
      -
      - @license GNU AGPL version 3 or any later version
      -
      - This program is free software: you can redistribute it and/or modify
      - it under the terms of the GNU Affero General Public License as
      - published by the Free Software Foundation, either version 3 of the
      - License, or (at your option) any later version.
      -
      - This program is distributed in the hope that it will be useful,
      - but WITHOUT ANY WARRANTY; without even the implied warranty of
      - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      - GNU Affero General Public License for more details.
      -
      - You should have received a copy of the GNU Affero General Public License
      - along with this program.  If not, see <http://www.gnu.org/licenses/>.
      -->
    
    <template>
    
    	<AppNavigationItem
    		v-if="visible"
    		:id="id"
    		:key="id"
    		:icon="iconError"
    		:menu-open.sync="menuOpen"
    		:title="account.emailAddress"
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    		:to="firstMailboxRoute"
    
    GretaD's avatar
    GretaD committed
    		:exact="true"
    
    		@update:menuOpen="onMenuToggle">
    
    		<!-- Color dot -->
    		<AppNavigationIconBullet v-if="bulletColor" slot="icon" :color="bulletColor" />
    
    		<!-- Actions -->
    		<template #actions>
    
    GretaD's avatar
    GretaD committed
    			<ActionText v-if="!account.isUnified" icon="icon-info" :title="t('mail', 'Quota')">
    				{{ quotaText }}
    			</ActionText>
    
    			<ActionRouter :to="settingsRoute" icon="icon-settings">
    
    GretaD's avatar
    GretaD committed
    				{{ t('mail', 'Account settings') }}
    
    			<ActionCheckbox
    				:checked="account.showSubscribedOnly"
    				:disabled="savingShowOnlySubscribed"
    
    				@update:checked="changeShowSubscribedOnly">
    
    				{{ t('mail', 'Show only subscribed folders') }}
    			</ActionCheckbox>
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    			<ActionButton v-if="!editing" icon="icon-folder" @click="openCreateMailbox">
    
    				{{ t('mail', 'Add folder') }}
    
    GretaD's avatar
    GretaD committed
    			</ActionButton>
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    			<ActionInput v-if="editing" icon="icon-folder" @submit.prevent.stop="createMailbox" />
    
    GretaD's avatar
    GretaD committed
    			<ActionText v-if="showSaving" icon="icon-loading-small">
    				{{ t('mail', 'Saving') }}
    			</ActionText>
    
    			<ActionButton v-if="!isFirst" icon="icon-triangle-n" @click="changeAccountOrderUp">
    
    GretaD's avatar
    GretaD committed
    				{{ t('mail', 'Move up') }}
    
    			</ActionButton>
    			<ActionButton v-if="!isLast" icon="icon-triangle-s" @click="changeAccountOrderDown">
    				{{ t('mail', 'Move down') }}
    			</ActionButton>
    
    			<ActionButton v-if="!account.provisioned" icon="icon-delete" @click="removeAccount">
    				{{ t('mail', 'Remove account') }}
    
    			</ActionButton>
    
    		</template>
    	</AppNavigationItem>
    
    import AppNavigationItem from '@nextcloud/vue/dist/Components/AppNavigationItem'
    import AppNavigationIconBullet from '@nextcloud/vue/dist/Components/AppNavigationIconBullet'
    import ActionRouter from '@nextcloud/vue/dist/Components/ActionRouter'
    import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
    
    import ActionCheckbox from '@nextcloud/vue/dist/Components/ActionCheckbox'
    
    import ActionInput from '@nextcloud/vue/dist/Components/ActionInput'
    
    GretaD's avatar
    GretaD committed
    import ActionText from '@nextcloud/vue/dist/Components/ActionText'
    
    import { formatFileSize } from '@nextcloud/files'
    import { generateUrl } from '@nextcloud/router'
    
    import { calculateAccountColor } from '../util/AccountColor'
    
    import logger from '../logger'
    
    import { fetchQuota } from '../service/AccountService'
    
    
    export default {
    	name: 'NavigationAccount',
    	components: {
    		AppNavigationItem,
    
    		AppNavigationIconBullet,
    		ActionRouter,
    		ActionButton,
    
    GretaD's avatar
    GretaD committed
    		ActionText,
    
    	},
    	props: {
    		account: {
    			type: Object,
    			required: true,
    		},
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    		firstMailbox: {
    
    			type: Object,
    			required: true,
    		},
    
    		isFirst: {
    			type: Boolean,
    			default: false,
    		},
    		isLast: {
    			type: Boolean,
    			default: false,
    		},
    
    	data() {
    		return {
    			menuOpen: false,
    
    			loading: {
    				delete: false,
    			},
    
    			savingShowOnlySubscribed: false,
    
    GretaD's avatar
    GretaD committed
    			quota: undefined,
    
    GretaD's avatar
    GretaD committed
    			editing: false,
    			showSaving: false,
    
    	computed: {
    		visible() {
    			return this.account.isUnified !== true && this.account.visible !== false
    		},
    
    		settingsRoute() {
    			return {
    
    				name: 'accountSettings',
    				params: {
    					accountId: this.account.id,
    				},
    			}
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    		firstMailboxRoute() {
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    				name: 'mailbox',
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    					mailboxId: this.firstMailbox.databaseId,
    
    		id() {
    			return 'account-' + this.account.id
    		},
    		bulletColor() {
    			return this.account.error ? undefined : calculateAccountColor(this.account.emailAddress)
    		},
    		iconError() {
    			return this.account.error ? 'icon-error' : undefined
    
    GretaD's avatar
    GretaD committed
    		quotaText() {
    			if (this.quota === undefined) {
    				return t('mail', 'Loading …')
    			}
    			if (this.quota === false) {
    				return t('mail', 'Not supported by the server')
    			}
    
    			return t('mail', '{usage} of {limit} used', {
    				usage: formatFileSize(this.quota.usage),
    				limit: formatFileSize(this.quota.limit),
    			})
    		},
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    		createMailbox(e) {
    
    GretaD's avatar
    GretaD committed
    			this.editing = true
    
    			const name = e.target.elements[1].value
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    			logger.info('creating mailbox ' + name)
    
    			this.menuOpen = false
    			this.$store
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    				.dispatch('createMailbox', { account: this.account, name })
    				.then(() => logger.info(`mailbox ${name} created`))
    
    				.catch((error) => {
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    					logger.error('could not create mailbox', { error })
    
    GretaD's avatar
    GretaD committed
    			this.editing = false
    			this.showSaving = false
    		},
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    		openCreateMailbox() {
    
    GretaD's avatar
    GretaD committed
    			this.editing = true
    			this.showSaving = false
    
    		removeAccount() {
    
    			const id = this.account.id
    
    			logger.info('delete account', { account: this.account })
    
    			OC.dialogs.confirmDestructive(
    				t(
    					'mail',
    					'The account for {email} and cached email data will be removed from Nextcloud, but not from your email provider.',
    
    					{ email: this.account.emailAddress }
    
    				t('mail', 'Remove account {email}', { email: this.account.emailAddress }),
    
    				{
    					type: OC.dialogs.YES_NO_BUTTONS,
    
    					confirm: t('mail', 'Remove {email}', { email: this.account.emailAddress }),
    
    					confirmClasses: 'error',
    					cancel: t('mail', 'Cancel'),
    				},
    				(result) => {
    					if (result) {
    						return this.$store
    							.dispatch('deleteAccount', this.account)
    							.then(() => {
    								this.loading.delete = true
    							})
    							.then(() => {
    								logger.info(`account ${id} deleted, redirecting …`)
    
    								// TODO: update store and handle this more efficiently
    								location.href = generateUrl('/apps/mail')
    							})
    
    							.catch((error) => logger.error('could not delete account', { error }))
    
    					}
    					this.loading.delete = false
    				}
    			)
    
    		changeAccountOrderUp() {
    			this.$store
    
    				.dispatch('moveAccount', { account: this.account, up: true })
    				.catch((error) => logger.error('could not move account up', { error }))
    
    		},
    		changeAccountOrderDown() {
    			this.$store
    
    				.dispatch('moveAccount', { account: this.account })
    				.catch((error) => logger.error('could not move account down', { error }))
    
    		changeShowSubscribedOnly(onlySubscribed) {
    			this.savingShowOnlySubscribed = true
    			this.$store
    				.dispatch('patchAccount', {
    					account: this.account,
    					data: {
    						showSubscribedOnly: onlySubscribed,
    					},
    				})
    				.then(() => {
    					this.savingShowOnlySubscribed = false
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    					logger.info('show only subscribed mailboxes updated to ' + onlySubscribed)
    
    					logger.error('could not update subscription mode', { error })
    
    					this.savingShowOnlySubscribed = false
    					throw error
    				})
    		},
    
    GretaD's avatar
    GretaD committed
    		onMenuToggle(open) {
    			if (open) {
    				console.debug('accounts menu opened, fetching quota')
    				this.fetchQuota()
    			}
    		},
    		async fetchQuota() {
    			const quota = await fetchQuota(this.account.id)
    			console.debug('quota fetched', {
    				quota,
    			})
    
    			if (quota === undefined) {
    				// Server does not support this
    				this.quota = false
    			} else {
    				this.quota = quota
    			}
    		},