Skip to content
Snippets Groups Projects
Envelope.vue 8 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	<router-link class="app-content-list-item" :class="{seen: data.flags.seen, draft, selected: selected}" :to="link">
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    			v-if="mailbox.isUnified"
    
    			class="mail-message-account-color"
    
    			:style="{'background-color': accountColor}" />
    
    			class="app-content-list-item-star icon-starred"
    			:data-starred="data.flags.flagged ? 'true' : 'false'"
    
    			@click.prevent="onToggleFlagged" />
    
    		<div
    			v-if="data.flags.important"
    			class="app-content-list-item-star icon-important"
    
    			:data-starred="data.flags.important ? 'true' : 'false'"
    
    			@click.prevent="onToggleImportant"
    
    			v-html="importantSvg" />
    
    GretaD's avatar
    GretaD committed
    		<div
    			v-if="data.flags.junk"
    			class="app-content-list-item-star icon-junk"
    			:data-starred="data.flags.junk ? 'true' : 'false'"
    
    			@click.prevent="onToggleJunk" />
    
    		<div class="app-content-list-item-icon">
    
    			<Avatar :display-name="addresses" :email="avatarEmail" />
    
    			<p v-if="selectMode" class="app-content-list-item-select-checkbox">
    
    				<input :id="`select-checkbox-${data.uid}`"
    					class="checkbox"
    					type="checkbox"
    					:checked="selected">
    
    				<label :for="`select-checkbox-${data.uid}`" @click.prevent="toggleSelected" />
    			</p>
    
    		<div class="app-content-list-item-line-one" :title="addresses">
    			{{ addresses }}
    
    		</div>
    		<div class="app-content-list-item-line-two" :title="data.subject">
    			<span v-if="data.flags.answered" class="icon-reply" />
    
    			<span v-if="data.flags.hasAttachments === true" class="icon-public icon-attachment" />
    
    			<span v-if="draft" class="draft">
    				<em>{{ t('mail', 'Draft: ') }}</em>
    			</span>
    			{{ data.subject }}
    		</div>
    		<div class="app-content-list-item-details date">
    			<Moment :timestamp="data.dateInt" />
    		</div>
    
    		<Actions class="app-content-list-item-menu" menu-align="right">
    
    GretaD's avatar
    GretaD committed
    			<ActionButton icon="icon-important" @click.prevent="onToggleImportant">
    
    GretaD's avatar
    GretaD committed
    					data.flags.important ? t('mail', 'Mark unimportant') : t('mail', 'Mark important')
    
    GretaD's avatar
    GretaD committed
    			<ActionButton icon="icon-starred" @click.prevent="onToggleFlagged">
    
    GretaD's avatar
    GretaD committed
    					data.flags.flagged ? t('mail', 'Mark unfavorite') : t('mail', 'Mark favorite')
    
    				}}
    			</ActionButton>
    			<ActionButton icon="icon-mail" @click.prevent="onToggleSeen">
    				{{
    					data.flags.seen ? t('mail', 'Mark unread') : t('mail', 'Mark read')
    				}}
    			</ActionButton>
    			<ActionButton icon="icon-junk" @click.prevent="onToggleJunk">
    				{{
    					data.flags.junk ? t('mail', 'Mark not spam') : t('mail', 'Mark as spam')
    				}}
    			</ActionButton>
    			<ActionButton icon="icon-checkmark" :close-after-click="true" @click.prevent="onSelect">
    				{{
    					selected ? t('mail', 'Unselect') : t('mail', 'Select')
    				}}
    			</ActionButton>
    			<ActionButton icon="icon-delete" @click.prevent="onDelete">
    				{{ t('mail', 'Delete') }}
    			</ActionButton>
    
    		</Actions>
    
    	</router-link>
    
    </template>
    
    <script>
    
    import Actions from '@nextcloud/vue/dist/Components/Actions'
    import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
    
    import Moment from './Moment'
    
    import importantSvg from '../../img/important.svg'
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    import Avatar from './Avatar'
    
    import { calculateAccountColor } from '../util/AccountColor'
    
    export default {
    	name: 'Envelope',
    	components: {
    
    		Actions,
    		ActionButton,
    
    		Avatar,
    		Moment,
    	},
    
    			required: true,
    		},
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    		mailbox: {
    
    		selectMode: {
    			type: Boolean,
    			default: false,
    		},
    		selected: {
    			type: Boolean,
    			default: false,
    		},
    
    	data() {
    		return {
    			importantSvg,
    		}
    	},
    
    	computed: {
    
    			return calculateAccountColor(this.$store.getters.getAccount(this.data.accountId).emailAddress)
    		},
    		draft() {
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    			return this.data.flags.draft
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    			if (this.draft) {
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    				// TODO: does not work with a unified drafts mailbox
    				//       the query should also contain the account and mailbox
    
    				//       id for that to work
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    				return {
    					name: 'message',
    					params: {
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    						mailboxId: this.$route.params.mailboxId,
    
    						filter: this.$route.params.filter ? this.$route.params.filter : undefined,
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    						threadId: 'new',
    						draftId: this.data.databaseId,
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    					},
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    				}
    			} else {
    				return {
    					name: 'message',
    					params: {
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    						mailboxId: this.$route.params.mailboxId,
    
    						filter: this.$route.params.filter ? this.$route.params.filter : undefined,
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    						threadId: this.data.databaseId,
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    					},
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    			// Show recipients' label/address in a sent mailbox
    			if (this.mailbox.specialRole === 'sent') {
    
    				const recipients = [this.data.to, this.data.cc].flat().map(function(recipient) {
    
    					return recipient.label ? recipient.label : recipient.email
    				})
    
    				return recipients.length > 0 ? recipients.join(', ') : t('mail', 'Blind copy recipients only')
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    			// Show sender label/address in other mailbox types
    
    			return this.data.from.length === 0 ? '?' : this.data.from[0].label || this.data.from[0].email
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    			// Show first recipients' avatar in a sent mailbox (or undefined when sent to Bcc only)
    			if (this.mailbox.specialRole === 'sent') {
    
    				const recipients = [this.data.to, this.data.cc].flat().map(function(recipient) {
    
    					return recipient.email
    				})
    				return recipients.length > 0 ? recipients[0] : undefined
    			}
    
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    			// Show sender avatar in other mailbox types
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    			if (this.data.from.length > 0) {
    				return this.data.from[0].email
    
    			} else {
    				return undefined
    
    	},
    	methods: {
    
    		onSelect() {
    			this.$emit('update:selected', true)
    		},
    		toggleSelected() {
    			this.$emit('update:selected', !this.selected)
    		},
    
    		onToggleFlagged() {
    
    			this.$store.dispatch('toggleEnvelopeFlagged', this.data)
    
    		onToggleImportant() {
    			this.$store.dispatch('toggleEnvelopeImportant', this.data)
    		},
    
    		onToggleSeen() {
    			this.$store.dispatch('toggleEnvelopeSeen', this.data)
    		},
    
    GretaD's avatar
    GretaD committed
    		onToggleJunk() {
    			this.$store.dispatch('toggleEnvelopeJunk', this.data)
    		},
    
    			this.$store.dispatch('deleteMessage', {
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    				id: this.data.databaseId,
    
    .mail-message-account-color {
    	position: absolute;
    	left: 0px;
    	width: 2px;
    	height: 69px;
    	z-index: 1;
    }
    
    
    	::v-deep path {
    		fill: #ffcc00;
    		stroke: var(--color-main-background);
    	}
    
    	.app-content-list-item:hover &,
    	.app-content-list-item:focus &,
    	.app-content-list-item.active & {
    		::v-deep path {
    			stroke: var(--color-background-dark);
    		}
    	}
    
    	// In message list, but not the one in the action menu
    	&.app-content-list-item-star {
    		background-image: none;
    		left: 7px;
    		top: 13px;
    		opacity: 1;
    
    		&:hover,
    		&:focus {
    			opacity: 0.5;
    		}
    	}
    
    .app-content-list-item .app-content-list-item-select-checkbox {
    	display: inline-block;
    	vertical-align: middle;
    	position: absolute;
    	left: 22px;
    	top: 20px;
    	z-index: 50; // same as icon-starred
    }
    
    
    .app-content-list-item:not(.seen) {
    	font-weight: bold;
    }
    
    .app-content-list-item.selected {
    	background-color: var(--color-background-dark);
    
    	font-weight: bold;
    }
    
    GretaD's avatar
    GretaD committed
    .app-content-list-item-star.junk {
    	background-image: var(--icon-junk-000);
    	opacity: 1;
    }
    
    Christoph Wurst's avatar
    Christoph Wurst committed
    .app-content-list-item.draft .app-content-list-item-line-two {
    	font-style: italic;
    }
    
    .app-content-list-item.active {
    	background-color: var(--color-primary-light);
    }
    
    .icon-reply,
    .icon-attachment {
    	display: inline-block;
    	vertical-align: text-top;
    }
    
    .icon-reply {
    	background-image: url('../../img/reply.svg');
    	-ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=50)';
    	opacity: 0.5;
    }
    
    .icon-attachment {
    	-ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=25)';
    	opacity: 0.25;
    }
    
    
    // Fix layout of messages in list until we move to component
    
    
    .app-content-list .app-content-list-item {
    	padding-right: 0;
    
    	.app-content-list-item-line-two {
    		padding-right: 0;
    		margin-top: -8px;
    	}
    
    	.app-content-list-item-menu {
    		margin-right: -2px;
    		margin-top: -8px;
    
    		::v-deep .action-item__menu {
    			right: 7px !important;
    
    			.action-item__menu_arrow {
    				right: 6px !important;
    			}
    		}
    	}
    
    	.app-content-list-item-details {
    		padding-right: 7px;
    	}
    
    </style>