mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-04-04 21:08:51 +00:00
(js) Review Mail module to decrease watchers
This commit is contained in:
@@ -7,19 +7,20 @@
|
||||
|
||||
<!-- in virtual mailbox mode -->
|
||||
<md-toolbar class="md-whiteframe-z1 md-hue-3"
|
||||
ng-hide="!app.showingAdvancedSearch || mailbox.mode.multiple">
|
||||
ng-hide="!mailbox.service.$virtualPath || mailbox.mode.multiple">
|
||||
<div class="md-toolbar-tools">
|
||||
<md-input-container class="md-flex">
|
||||
<label><var:string label:value="Search messages in"/></label>
|
||||
<md-select ng-model="app.search.mailbox">
|
||||
<md-select ng-model="mailbox.service.$virtualPath">
|
||||
<md-option ng-value="">
|
||||
<span>{{app.accounts[0].name}}</span>
|
||||
<span ng-bind="app.accounts[0].name"><!-- main account name --></span>
|
||||
</md-option>
|
||||
<md-option ng-repeat="folder in
|
||||
app.accounts[0].$flattenMailboxes()
|
||||
track by folder.path"
|
||||
ng-value="folder.path">
|
||||
<span ng-class="'sg-child-level-' + folder.level">{{folder.$displayName}}</span>
|
||||
<span ng-class="'sg-child-level-' + folder.level"
|
||||
ng-bind="folder.$displayName"><!-- mailbox name --></span>
|
||||
</md-option>
|
||||
</md-select>
|
||||
</md-input-container>
|
||||
@@ -38,13 +39,15 @@
|
||||
<md-menu-divider> <!-- divider --></md-menu-divider>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="app.search.match='AND'">
|
||||
<md-icon ng-class="{ 'icon-check': app.search.match == 'AND'}">
|
||||
<md-icon ng-class="{ 'icon-check': app.search.match == 'AND'}"
|
||||
label:aria-label="Match all of the following">
|
||||
<!-- all --></md-icon><var:string label:value="Match all of the following"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="app.search.match='OR'">
|
||||
<md-icon ng-class="{ 'icon-check': app.search.match == 'OR'}">
|
||||
<md-icon ng-class="{ 'icon-check': app.search.match == 'OR'}"
|
||||
label:aria-label="Match any of the following">
|
||||
<!-- any --></md-icon><var:string label:value="Match any of the following"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
@@ -61,7 +64,7 @@
|
||||
</md-toolbar>
|
||||
<!-- single-selection toolbars -->
|
||||
<md-toolbar class="md-accent md-hue-1"
|
||||
ng-hide="app.showingAdvancedSearch || mailbox.mode.multiple">
|
||||
ng-hide="mailbox.service.$virtualPath || mailbox.mode.multiple">
|
||||
<!-- sort mode (default) -->
|
||||
<div class="md-toolbar-tools" ng-hide="mailbox.mode.search">
|
||||
<md-button class="sg-icon-button" label:aria-label="Search"
|
||||
@@ -69,7 +72,7 @@
|
||||
<md-icon>search</md-icon>
|
||||
</md-button>
|
||||
<a href="javascript:void(0)" class="sg-folder-name"
|
||||
ng-click="mailbox.searchMode()">{{mailbox.selectedFolder.$displayName}}</a>
|
||||
ng-click="mailbox.searchMode()" ng-bind="mailbox.selectedFolder.$displayName"><!-- mailbox name --></a>
|
||||
<md-menu>
|
||||
<md-button class="sg-icon-button" label:aria-label="Sort"
|
||||
ng-click="$mdMenu.open()">
|
||||
@@ -78,31 +81,36 @@
|
||||
<md-menu-content>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="mailbox.sort('subject')">
|
||||
<md-icon ng-class="{ 'icon-check': mailbox.sortedBy('subject') }">
|
||||
<md-icon ng-class="{ 'icon-check': mailbox.sortedBy('subject') }"
|
||||
label:aria-label="Subject">
|
||||
<!-- subject --></md-icon> <var:string label:value="Subject"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="mailbox.sort('from')">
|
||||
<md-icon ng-class="{ 'icon-check': mailbox.sortedBy('from') }">
|
||||
<md-icon ng-class="{ 'icon-check': mailbox.sortedBy('from') }"
|
||||
label:aria-label="From">
|
||||
<!-- from --></md-icon> <var:string label:value="From"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="mailbox.sort('date')">
|
||||
<md-icon ng-class="{ 'icon-check': mailbox.sortedBy('date') }">
|
||||
<md-icon ng-class="{ 'icon-check': mailbox.sortedBy('date') }"
|
||||
label:aria-label="Date">
|
||||
<!-- date --></md-icon> <var:string label:value="Date"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="mailbox.sort('size')">
|
||||
<md-icon ng-class="{ 'icon-check': mailbox.sortedBy('size') }">
|
||||
<md-icon ng-class="{ 'icon-check': mailbox.sortedBy('size') }"
|
||||
label:aria-label="Size">
|
||||
<!-- size --></md-icon> <var:string label:value="Size"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="mailbox.sort('arrival')">
|
||||
<md-icon ng-class="{ 'icon-check': mailbox.sortedBy('arrival') }">
|
||||
<md-icon ng-class="{ 'icon-check': mailbox.sortedBy('arrival') }"
|
||||
label:aria-label="Order Received">
|
||||
<!-- order received --></md-icon> <var:string label:value="Order Received"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
@@ -158,7 +166,7 @@
|
||||
<md-button class="sg-icon-button" ng-click="mailbox.unselectMessages()">
|
||||
<md-icon>arrow_back</md-icon>
|
||||
</md-button>
|
||||
<label>{{mailbox.service.selectedFolder.$selectedCount()}} <var:string label:value="selected"/></label>
|
||||
<label><span ng-bind="mailbox.service.selectedFolder.$selectedCount()"><!-- count --></span> <var:string label:value="selected"/></label>
|
||||
<div class="md-flex"><!-- spacer --></div>
|
||||
<md-button class="sg-icon-button" ng-click="mailbox.selectAll()">
|
||||
<md-tooltip md-direction="bottom"><var:string label:value="Select All"/></md-tooltip>
|
||||
@@ -168,8 +176,8 @@
|
||||
<md-icon>delete</md-icon>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button" ng-click="mailbox.markOrUnMarkMessagesAsJunk()">
|
||||
<md-icon ng-hide="mailbox.service.selectedFolder.type == 'junk'">thumb_down</md-icon>
|
||||
<md-icon ng-hide="mailbox.service.selectedFolder.type != 'junk'">thumb_up</md-icon>
|
||||
<md-icon ng-hide="::mailbox.service.selectedFolder.type == 'junk'">thumb_down</md-icon>
|
||||
<md-icon ng-hide="::mailbox.service.selectedFolder.type != 'junk'">thumb_up</md-icon>
|
||||
</md-button>
|
||||
<md-menu>
|
||||
<md-button class="sg-icon-button" label:aria-label="More messages options" ng-click="$mdMenu.open()">
|
||||
@@ -202,19 +210,22 @@
|
||||
<var:string label:value="Copy To"/>
|
||||
</md-button>
|
||||
<md-menu-content width="4">
|
||||
<div ng-repeat="account in mailbox.accounts track by account.id">
|
||||
<div ng-repeat="account in ::mailbox.accounts track by account.id">
|
||||
<md-menu-item>
|
||||
<md-menu>
|
||||
<md-button class="md-primary" ng-click="$mdMenu.open($event)">{{account.name}}</md-button>
|
||||
<md-button class="md-primary" ng-click="$mdMenu.open($event)"
|
||||
ng-bind="::account.name"><!-- account name --></md-button>
|
||||
<md-menu-content class="md-dense" width="4">
|
||||
<div ng-repeat="folder in
|
||||
account.$flattenMailboxes({ all: true })
|
||||
track by folder.path">
|
||||
<md-menu-item>
|
||||
<md-button class="sg-no-wrap"
|
||||
ng-disabled="mailbox.service.selectedFolder.id == folder.id"
|
||||
aria-label="{{folder.$displayName}}"
|
||||
ng-disabled="::(mailbox.service.selectedFolder.id == folder.id)"
|
||||
ng-click="mailbox.copySelectedMessages(folder.id)">
|
||||
<span ng-class="'sg-child-level-' + folder.level">{{folder.$displayName}}</span>
|
||||
<span ng-class="::('sg-child-level-' + folder.level)"
|
||||
ng-bind="folder.$displayName"><!-- mailbox name --></span>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
</div>
|
||||
@@ -231,19 +242,22 @@
|
||||
<var:string label:value="Move To"/>
|
||||
</md-button>
|
||||
<md-menu-content width="4">
|
||||
<div ng-repeat="account in mailbox.accounts track by account.id">
|
||||
<div ng-repeat="account in ::mailbox.accounts track by account.id">
|
||||
<md-menu-item>
|
||||
<md-menu>
|
||||
<md-button class="md-primary" ng-click="$mdMenu.open($event)">{{account.name}}</md-button>
|
||||
<md-button class="md-primary" ng-click="$mdMenu.open($event)"
|
||||
ng-bind="::account.name"><!-- account name --></md-button>
|
||||
<md-menu-content class="md-dense" width="4">
|
||||
<div ng-repeat="folder in
|
||||
account.$flattenMailboxes({ all: true })
|
||||
track by folder.path">
|
||||
<md-menu-item>
|
||||
<md-button class="sg-no-wrap"
|
||||
ng-disabled="mailbox.service.selectedFolder.id == folder.id"
|
||||
aria-label="{{folder.$displayName}}"
|
||||
ng-disabled="::(mailbox.service.selectedFolder.id == folder.id)"
|
||||
ng-click="mailbox.moveSelectedMessages(folder.id)">
|
||||
<span ng-class="'sg-child-level-' + folder.level">{{folder.$displayName}}</span>
|
||||
<span ng-class="::('sg-child-level-' + folder.level)"
|
||||
ng-bind="folder.$displayName"><!-- mailbox name --></span>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
</div>
|
||||
@@ -266,7 +280,7 @@
|
||||
<!-- message count -->
|
||||
<span ng-switch="mailbox.service.selectedFolder.getLength()">
|
||||
<span ng-switch-when="0"><var:string label:value="No message"/></span>
|
||||
<span ng-switch-default="true">{{mailbox.service.selectedFolder.getLength()}} <var:string label:value="messages"/></span>
|
||||
<span ng-switch-default="true"><span ng-bind="mailbox.service.selectedFolder.getLength()"><!-- count --></span> <var:string label:value="messages"/></span>
|
||||
</span>
|
||||
</md-subheader>
|
||||
<md-virtual-repeat-container class="md-flex" md-top-index="mailbox.selectedFolder.$topIndex">
|
||||
@@ -277,11 +291,12 @@
|
||||
sg-drag-count="mailbox.selectedFolder.$selectedCount()">
|
||||
<md-list-item
|
||||
aria-label="{{currentMessage.subject}}"
|
||||
ng-class="{'md-default-theme md-accent md-bg md-hue-2': mailbox.selectedFolder.isSelectedMessage(currentMessage.uid, currentMessage.$mailbox.path),
|
||||
unread: !currentMessage.isread}"
|
||||
class="sg-message-list-item"
|
||||
ng-class="{'md-default-theme md-accent md-bg md-hue-2': mailbox.selectedFolder.isSelectedMessage(currentMessage.uid, currentMessage.$mailbox.path)}"
|
||||
md-virtual-repeat="currentMessage in mailbox.service.selectedFolder"
|
||||
md-on-demand="md-on-demand" md-item-size="56"
|
||||
ng-click="mailbox.selectMessage(currentMessage)">
|
||||
ng-click="mailbox.selectMessage(currentMessage)"
|
||||
sg-message="currentMessage">
|
||||
<div class="md-secondary sg-avatar-selectable"
|
||||
label:aria-label="Select Message"
|
||||
ng-class="{ 'sg-avatar-selected': currentMessage.selected }"
|
||||
@@ -290,37 +305,8 @@
|
||||
sg-email="mailbox.service.selectedFolder.type == 'sent' ? currentMessage.to[0].email : currentMessage.from[0].email"
|
||||
size="40">person</sg-avatar-image>
|
||||
</div>
|
||||
<div class="sg-category"
|
||||
ng-repeat="tag in currentMessage.flags | limitTo:5"
|
||||
ng-style="{ 'background-color': currentMessage.constructor.$tags[tag][1], left: ($index * 3) + 'px' }"><!-- calendar color --></div>
|
||||
<div class="sg-tile-content">
|
||||
<div class="sg-md-subhead">
|
||||
<div>
|
||||
<span class="sg-label-outline ng-hide"
|
||||
ng-show="mailbox.service.$virtualMode">{{currentMessage.$mailbox.$displayName}}</span>
|
||||
<md-icon class="ng-hide"
|
||||
ng-show="currentMessage.priority.level == 1 ||
|
||||
currentMessage.priority.level == 2"
|
||||
ng-class="{'md-warn': currentMessage.priority.level == 1}">error</md-icon>
|
||||
{{mailbox.service.selectedFolder.type == 'sent' ? currentMessage.$shortAddress('to' ) : currentMessage.$shortAddress('from' )}}
|
||||
</div>
|
||||
<div class="sg-tile-date" ng-bind="currentMessage.relativedate"><!-- date --></div>
|
||||
</div>
|
||||
<div class="sg-md-body">
|
||||
<div>{{currentMessage.subject}}</div>
|
||||
<div class="sg-tile-size" ng-bind="currentMessage.size"><!-- size --></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sg-tile-icons">
|
||||
<md-icon class="ng-hide" ng-show="currentMessage.isflagged">star</md-icon>
|
||||
<md-icon class="ng-hide" ng-show="currentMessage.isanswered">reply</md-icon>
|
||||
<md-icon class="ng-hide" ng-show="currentMessage.isforwarded">forward</md-icon>
|
||||
<md-icon class="ng-hide" ng-show="currentMessage.hasattachment">attach_file</md-icon>
|
||||
</div>
|
||||
<div class="sg-progress-linear-bottom">
|
||||
<md-progress-linear class="md-accent"
|
||||
md-mode="indeterminate"
|
||||
ng-disabled="!currentMessage.$isLoading()"><!-- message loading progress --></md-progress-linear>
|
||||
<div class="md-list-item-inner sg-message-list-item-main">
|
||||
<!-- sgMessageListItemMain directive -->
|
||||
</div>
|
||||
</md-list-item>
|
||||
</md-list>
|
||||
|
||||
@@ -34,26 +34,28 @@
|
||||
<var:component className="UIxSidenavToolbarTemplate" />
|
||||
<md-content class="md-flex" layout="column" md-scroll-y="md-scroll-y"
|
||||
md-colors="::{ backgroundColor: 'default-background-300' }">
|
||||
<section layout="column"
|
||||
<section class="sg-account-section"
|
||||
layout="column"
|
||||
ng-repeat="account in ::app.accounts track by account.id"
|
||||
ng-class="{ 'md-flex': account.$expanded }">
|
||||
<md-list>
|
||||
<md-list-item aria-label="{{ ::'Toggle visibility' | loc }}"
|
||||
ng-click="app.toggleAccountState(account)">
|
||||
<div class="sg-no-wrap">{{account.name}}</div>
|
||||
<md-list-item ng-click="app.toggleAccountState(account)">
|
||||
<div class="sg-no-wrap"
|
||||
aria-label="{{ ::'Toggle visibility' | loc }}"
|
||||
ng-bind="::account.name"><!-- account name --></div>
|
||||
<md-menu class="md-secondary">
|
||||
<md-icon label:aria-label="Options"
|
||||
ng-click="$mdMenu.open($event)"
|
||||
md-menu-origin="md-menu-origin">more_vert</md-icon>
|
||||
<md-menu-content width="3">
|
||||
<md-menu-item ng-show="account.id == 0">
|
||||
<md-menu-item ng-show="::account.id == 0">
|
||||
<md-button
|
||||
label:aria-label="Delegation..."
|
||||
ng-click="app.delegate(account)">
|
||||
<var:string label:value="Delegation..."/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-show="app.showSubscribedOnly == 1">
|
||||
<md-menu-item ng-show="::app.showSubscribedOnly == 1">
|
||||
<md-button
|
||||
label:aria-label="Subscribe..."
|
||||
ng-click="app.subscribe(account)">
|
||||
@@ -71,7 +73,7 @@
|
||||
</md-menu>
|
||||
</md-list-item>
|
||||
</md-list>
|
||||
<div class="sg-quota ng-hide" ng-show="account.$quota">
|
||||
<div class="sg-quota ng-hide" ng-show="::account.$quota">
|
||||
<md-progress-linear md-mode="determinate"
|
||||
ng-class="{ 'md-warn': account.$quota.percent > 70 }"
|
||||
value="{{account.$quota.percent}}"><!-- quota --></md-progress-linear>
|
||||
@@ -81,115 +83,14 @@
|
||||
</div>
|
||||
<md-virtual-repeat-container ng-class="{ 'md-flex': account.$expanded }">
|
||||
<md-list>
|
||||
<md-list-item md-virtual-repeat="folder in account" md-item-size="48" md-on-demand="md-on-demand"
|
||||
class="md-clickable md-default-theme md-background md-hue-1"
|
||||
ng-class="{'md-bg': folder.id == app.service.selectedFolder.id}"
|
||||
sg-droppable="app.isDroppableFolder(dragFolder, folder)"
|
||||
sg-drop="app.dragSelectedMessages(dragFolder, folder, dragMode)">
|
||||
<div class="sg-child-level-0"
|
||||
ng-class="'sg-child-level-' + folder.level">
|
||||
<md-checkbox class="sg-folder"
|
||||
ng-class="folder.$icon"
|
||||
label:aria-label="Expanded"
|
||||
ng-model="folder.$expanded"
|
||||
ng-disabled="folder.children.length == 0"
|
||||
ng-change="account.$flattenMailboxes({ reload: true, saveState: true })">
|
||||
<md-icon>{{folder.$icon}}</md-icon></md-checkbox>
|
||||
</div>
|
||||
<p class="sg-item-name ng-hide"
|
||||
ng-click="app.selectFolder($event, account, folder)"
|
||||
ng-dblclick="app.editFolder(folder)"
|
||||
ng-show="app.editMode != folder.path">
|
||||
{{folder.$displayName}}
|
||||
<span class="sg-counter-badge ng-hide" ng-show="folder.unseenCount">{{folder.unseenCount}}</span>
|
||||
</p>
|
||||
<md-input-container class="md-flex ng-hide"
|
||||
ng-show="app.editMode == folder.path">
|
||||
<input class="sg-item-name" type="text"
|
||||
label:aria-label="Enter the new name of your folder"
|
||||
ng-model="folder.name"
|
||||
ng-blur="app.saveFolder(folder)"
|
||||
sg-focus-on="mailboxName_{{folder.path}}"
|
||||
sg-enter="app.saveFolder(folder)"
|
||||
sg-escape="app.revertEditing(folder)"/>
|
||||
</md-input-container>
|
||||
<md-menu class="ng-hide"
|
||||
ng-show="app.service.selectedFolder.id == folder.id">
|
||||
<md-icon label:aria-label="Options"
|
||||
ng-click="$mdMenu.open($event)"
|
||||
md-menu-origin="md-menu-origin">more_vert</md-icon>
|
||||
<md-menu-content width="3">
|
||||
<md-menu-item>
|
||||
<md-button type="button" md-menu-align-target="md-menu-align-target"
|
||||
ng-click="app.markFolderRead(folder)">
|
||||
<var:string label:value="Mark Folder Read"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-hide="folder.$isNoInferiors">
|
||||
<md-button type="button" ng-click="app.newFolder(folder)">
|
||||
<var:string label:value="New Subfolder..."/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-show="folder.$isEditable">
|
||||
<md-button type="button" ng-click="app.editFolder(folder)">
|
||||
<var:string label:value="Rename"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button type="button" ng-click="app.compactFolder(folder)">
|
||||
<var:string label:value="Compact"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-show="folder.$isEditable">
|
||||
<md-button type="button" ng-click="app.confirmDelete(folder)">
|
||||
<var:string label:value="Delete"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-show="folder.type == 'trash'">
|
||||
<md-button type="button" ng-click="app.emptyTrashFolder(folder)">
|
||||
<var:string label:value="Empty Trash"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button type="button" ng-click="folder.exportFolder()">
|
||||
<var:string label:value="Export"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button type="button"
|
||||
ng-click="app.showAdvancedSearch(folder.path)">
|
||||
<var:string label:value="Search"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-divider ng-show="folder.$canFolderAs()"><!-- divider --></md-menu-divider>
|
||||
<md-menu-item ng-show="folder.type == 'folder'">
|
||||
<md-button type="button" ng-click="app.setFolderAs(folder, 'Drafts')">
|
||||
<var:string label:value="Set as Drafts"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-show="folder.$canFolderAs()">
|
||||
<md-button type="button" ng-click="app.setFolderAs(folder, 'Sent')">
|
||||
<var:string label:value="Set as Sent"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-show="folder.$canFolderAs()">
|
||||
<md-button type="button" ng-click="app.setFolderAs(folder, 'Trash')">
|
||||
<var:string label:value="Set as Trash"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-show="folder.$canFolderAs()">
|
||||
<md-button type="button" ng-click="app.setFolderAs(folder, 'Junk')">
|
||||
<var:string label:value="Set as Junk"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-divider ng-show="folder.type != 'additional'"><!-- divider --></md-menu-divider>
|
||||
<md-menu-item ng-show="folder.type != 'additional'">
|
||||
<md-button type="button" ng-click="app.share(folder)">
|
||||
<var:string label:value="Sharing..."/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
<md-list-item
|
||||
class="sg-mailbox-list-item md-clickable md-default-theme md-background md-hue-1"
|
||||
ng-class="{'md-bg sg-selected': folder.id == app.service.selectedFolder.id}"
|
||||
md-virtual-repeat="folder in account" md-item-size="48" md-on-demand="md-on-demand"
|
||||
sg-mailbox="folder"
|
||||
sg-droppable="app.isDroppableFolder(dragFolder, folder)"
|
||||
sg-drop="app.dragSelectedMessages(dragFolder, folder, dragMode)">
|
||||
<!-- sgMailboxListItem directive -->
|
||||
</md-list-item>
|
||||
</md-list>
|
||||
</md-virtual-repeat-container>
|
||||
@@ -204,7 +105,7 @@
|
||||
</md-toolbar>
|
||||
<md-content class="md-flex"
|
||||
md-colors="::{backgroundColor: 'default-background-200'}"
|
||||
layout="column" layout-align="center center" layout-fill="layout-fill">
|
||||
layout="column" layout-align="center center">
|
||||
<div class="sg-md-title"
|
||||
md-colors="::{color: 'default-background-500'}">
|
||||
<var:string label:value="No mailbox selected"/>
|
||||
@@ -215,13 +116,13 @@
|
||||
|
||||
<script type="text/ng-template" id="UIxMailFolderTemplate">
|
||||
<md-toolbar layout="row" layout-align="space-between center" class="toolbar-main"
|
||||
ng-hide="app.showingAdvancedSearch">
|
||||
ng-hide="mailbox.service.$virtualPath">
|
||||
<var:component className="UIxTopnavToolbar"/>
|
||||
</md-toolbar>
|
||||
|
||||
<!-- Advanced search toolbar -->
|
||||
<md-toolbar layout="column" class="md-tall toolbar-main md-hue-3"
|
||||
ng-show="app.showingAdvancedSearch">
|
||||
ng-show="mailbox.service.$virtualPath">
|
||||
<div class="md-toolbar-tools">
|
||||
<div layout="column" class="md-flex">
|
||||
<div class="pseudo-input-container--compact">
|
||||
@@ -261,8 +162,8 @@
|
||||
<md-chip-template>
|
||||
<span class="md-caption" ng-show="$chip.negative == 0">(<var:string label:value="match"/></span>
|
||||
<span class="md-caption" ng-show="$chip.negative == 1">(<var:string label:value="does not match"/></span>
|
||||
<span class="md-caption">{{$chip.searchBy}})</span>
|
||||
<span>{{$chip.searchInput}}</span>
|
||||
<span class="md-caption" ng-bind="$chip.searchBy"><!-- search by --></span>
|
||||
<span ng-bind="$chip.searchInput"><!-- search input --></span>
|
||||
</md-chip-template>
|
||||
</md-chips>
|
||||
</div>
|
||||
@@ -273,11 +174,88 @@
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- modal for mailbox sharing options -->
|
||||
<!-- template of contextual menu for a mailbox -->
|
||||
<script type="text/ng-template" id="UIxMailFolderMenu">
|
||||
<div md-whiteframe="3">
|
||||
<md-menu-content width="3">
|
||||
<md-menu-item>
|
||||
<md-button type="button" md-menu-align-target="md-menu-align-target"
|
||||
ng-click="$menuCtrl.markFolderRead()">
|
||||
<var:string label:value="Mark Folder Read"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-hide="::$menuCtrl.folder.$isNoInferiors">
|
||||
<md-button type="button" ng-click="$menuCtrl.newFolder()">
|
||||
<var:string label:value="New Subfolder..."/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-show="::$menuCtrl.folder.$isEditable">
|
||||
<md-button type="button" ng-click="$menuCtrl.editFolder()">
|
||||
<var:string label:value="Rename"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button type="button" ng-click="$menuCtrl.compactFolder()">
|
||||
<var:string label:value="Compact"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-show="::$menuCtrl.folder.$isEditable">
|
||||
<md-button type="button" ng-click="$menuCtrl.confirmDelete()">
|
||||
<var:string label:value="Delete"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-show="::($menuCtrl.folder.type == 'trash')">
|
||||
<md-button type="button" ng-click="$menuCtrl.emptyTrashFolder()">
|
||||
<var:string label:value="Empty Trash"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button type="button" ng-click="$menuCtrl.folder.exportFolder()">
|
||||
<var:string label:value="Export"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button type="button" ng-click="$menuCtrl.showAdvancedSearch()">
|
||||
<var:string label:value="Search"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-divider ng-show="::$menuCtrl.folder.$canFolderAs()"><!-- divider --></md-menu-divider>
|
||||
<md-menu-item ng-show="::$menuCtrl.folder.$canFolderAs()">
|
||||
<md-button type="button" ng-click="$menuCtrl.setFolderAs('Drafts')">
|
||||
<var:string label:value="Set as Drafts"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-show="::$menuCtrl.folder.$canFolderAs()">
|
||||
<md-button type="button" ng-click="$menuCtrl.setFolderAs('Sent')">
|
||||
<var:string label:value="Set as Sent"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-show="::$menuCtrl.folder.$canFolderAs()">
|
||||
<md-button type="button" ng-click="$menuCtrl.setFolderAs('Trash')">
|
||||
<var:string label:value="Set as Trash"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-show="::$menuCtrl.folder.$canFolderAs()">
|
||||
<md-button type="button" ng-click="$menuCtrl.setFolderAs('Junk')">
|
||||
<var:string label:value="Set as Junk"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-divider ng-show="::($menuCtrl.folder.type != 'additional')"><!-- divider --></md-menu-divider>
|
||||
<md-menu-item ng-show="::($menuCtrl.folder.type != 'additional')">
|
||||
<md-button type="button" ng-click="$menuCtrl.share()">
|
||||
<var:string label:value="Sharing..."/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
</md-menu-content>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- template of modal for mailbox sharing options -->
|
||||
<script type="text/ng-template" id="UIxUserRightsEditor">
|
||||
<var:component className="UIxMailUserRightsEditor" />
|
||||
</script>
|
||||
|
||||
<!-- template of mail viewer -->
|
||||
<script type="text/ng-template" id="UIxMailViewTemplate">
|
||||
<var:component className="UIxMailViewTemplate" />
|
||||
</script>
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
<md-button ng-click="toggleCenter()"
|
||||
class="md-icon-button md-primary md-hue-1 hide show-gt-xs"
|
||||
aria-hidden="true"
|
||||
ng-if="!isPopup">
|
||||
ng-if="::!isPopup">
|
||||
<md-icon class="icon-fullscreen"
|
||||
ng-class="{ 'icon-fullscreen-exit': centerIsClose }"><!-- fullscreen --></md-icon>
|
||||
</md-button>
|
||||
<md-button class="md-icon-button"
|
||||
ng-if="isPopup"
|
||||
ng-if="::isPopup"
|
||||
label:aria-label="Close"
|
||||
ng-click="viewer.closePopup()">
|
||||
<md-icon>close</md-icon>
|
||||
@@ -36,7 +36,7 @@
|
||||
'icon-star-border': !viewer.message.isflagged}"><!-- flag --></md-icon>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button"
|
||||
ng-hide="viewer.message.isDraft"
|
||||
ng-hide="::viewer.message.isDraft"
|
||||
ng-click="viewer.reply($event)"
|
||||
label:aria-label="Reply">
|
||||
<md-tooltip md-direction="bottom"><var:string label:value="Reply to Sender Only"/></md-tooltip>
|
||||
@@ -50,13 +50,13 @@
|
||||
<md-icon>reply_all</md-icon>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button" label:aria-label="Forward"
|
||||
ng-hide="viewer.message.isDraft"
|
||||
ng-hide="::viewer.message.isDraft"
|
||||
ng-click="viewer.forward($event)">
|
||||
<md-tooltip md-direction="bottom"><var:string label:value="Forward selected message"/></md-tooltip>
|
||||
<md-icon>forward</md-icon>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button" label:aria-label="Edit"
|
||||
ng-show="viewer.message.isDraft"
|
||||
ng-show="::viewer.message.isDraft"
|
||||
ng-click="viewer.edit($event)">
|
||||
<md-icon>create</md-icon>
|
||||
</md-button>
|
||||
@@ -66,7 +66,7 @@
|
||||
<md-icon>delete</md-icon>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button hide show-gt-md" label:aria-label="Open in New Mail Window"
|
||||
ng-hide="isPopup"
|
||||
ng-hide="::isPopup"
|
||||
ng-click="viewer.openPopup()">
|
||||
<md-tooltip md-direction="bottom"><var:string label:value="Open in New Mail Window"/></md-tooltip>
|
||||
<md-icon>open_in_new</md-icon>
|
||||
@@ -124,20 +124,20 @@
|
||||
</md-card-actions>
|
||||
<md-card-content>
|
||||
<div class="sg-padded">
|
||||
<h5>{{viewer.message.subject}}</h5>
|
||||
<time class="msg-date" datetime="viewer.message.date" ng-bind="viewer.message.date"><!-- date --></time>
|
||||
<h5 ng-bind="::viewer.message.subject"><!-- subject --></h5>
|
||||
<time class="msg-date" datetime="viewer.message.date" ng-bind="::viewer.message.date"><!-- date --></time>
|
||||
</div>
|
||||
<div>
|
||||
<div layout="row" layout-wrap="layout-wrap">
|
||||
<div class="pseudo-input-container--compact" flex="50" flex-xs="100">
|
||||
<div layout="row" layout-align="start center">
|
||||
<sg-avatar-image class="md-tile-left"
|
||||
sg-email="viewer.message.from[0].email"
|
||||
sg-email="::viewer.message.from[0].email"
|
||||
size="40">person</sg-avatar-image>
|
||||
<div class="md-list-item-text">
|
||||
<span>{{ viewer.message.from[0].name }}</span><br/>
|
||||
<span ng-bind="::viewer.message.from[0].name"><!-- from --></span><br/>
|
||||
<a href="#" class="md-caption"
|
||||
ng-bind="viewer.message.from[0].email"
|
||||
ng-bind="::viewer.message.from[0].email"
|
||||
ng-click="viewer.newMessage($event, { to: [viewer.message.from[0].full] })"><!-- from --></a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -149,22 +149,23 @@
|
||||
</label>
|
||||
<div class="pseudo-input-field"
|
||||
ng-hide="viewer.$showDetailedRecipients">
|
||||
<a href="#" ng-click="viewer.toggleDetailedRecipients($event)">{{viewer.message.$shortRecipients(5)}}</a>
|
||||
<a href="#" ng-click="viewer.toggleDetailedRecipients($event)"
|
||||
ng-bind="::viewer.message.$shortRecipients(5)"><!-- to --></a>
|
||||
</div>
|
||||
<div class="pseudo-input-field" ng-show="viewer.$showDetailedRecipients">
|
||||
<span ng-repeat="recipient in viewer.message.to">
|
||||
<a href="#" ng-bind="recipient.full"
|
||||
<a href="#" ng-bind="::recipient.full"
|
||||
ng-click="viewer.newMessage($event, { to: [recipient.full] })"><!-- recipient --></a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pseudo-input-container--compact" ng-show="viewer.$showDetailedRecipients">
|
||||
<label class="pseudo-input-label" ng-show="viewer.message.cc.length > 0">
|
||||
<label class="pseudo-input-label" ng-show="::viewer.message.cc.length > 0">
|
||||
<var:string label:value="Cc"/>
|
||||
</label>
|
||||
<div class="pseudo-input-field">
|
||||
<span ng-repeat="recipient in viewer.message.cc">
|
||||
<a href="#" ng-bind="recipient.full"
|
||||
<span ng-repeat="recipient in ::viewer.message.cc">
|
||||
<a href="#" ng-bind="::recipient.full"
|
||||
ng-click="viewer.newMessage($event, { to: [recipient.full] })"><!-- recipient --></a>
|
||||
</span>
|
||||
<md-button style="float: right"
|
||||
@@ -184,7 +185,7 @@
|
||||
<span class="sg-chip-color">
|
||||
<span ng-style="{ 'background-color': viewer.service.$tags[$chip][1] }"><!-- color --></span>
|
||||
</span>
|
||||
<span>{{viewer.service.$tags[$chip][0] || $chip}}</span>
|
||||
<span ng-bind="viewer.service.$tags[$chip][0] || $chip"><!-- tag --></span>
|
||||
</md-chip-template>
|
||||
<md-autocomplete
|
||||
md-search-text="viewer.tags.searchText"
|
||||
@@ -196,7 +197,8 @@
|
||||
<div class="sg-color-chip"
|
||||
ng-style="{'background-color': tag.color}"><!-- color --></div>
|
||||
<div md-highlight-text="viewer.tags.searchText"
|
||||
md-highlight-flags="^i">{{tag.description}}</div>
|
||||
md-highlight-flags="^i"
|
||||
ng-bind="tag.description"><!-- description --></div>
|
||||
</div>
|
||||
</md-item-template>
|
||||
</md-autocomplete>
|
||||
@@ -256,14 +258,14 @@
|
||||
<div layout="row" layout-wrap="layout-wrap">
|
||||
<div class="mailer_mailcontent" layout="row" layout-wrap="layout-wrap"
|
||||
ng-repeat="part in viewer.message.$content()"
|
||||
ng-class="part.msgclass">
|
||||
<div class="md-flex"
|
||||
ng-class="::part.msgclass">
|
||||
<div class="md-flex sg-mail-part"
|
||||
tabindex="-1"
|
||||
ng-if="part.html"
|
||||
ng-if="::part.html"
|
||||
ng-click="viewer.filterMailtoLinks($event)"
|
||||
ng-bind-html="part.content | ensureTarget"><!-- html msg --></div>
|
||||
<div class="md-flex"
|
||||
ng-if="part.compile"
|
||||
<div class="md-flex sg-mail-part"
|
||||
ng-if="::part.compile"
|
||||
sg-compile="part.content"
|
||||
sg-zoomable-image="sg-zoomable-image"><!-- angular-friendly msg --></div>
|
||||
</div>
|
||||
|
||||
@@ -9,6 +9,27 @@ String.prototype.startsWith = function(pattern, position) {
|
||||
return this.lastIndexOf(pattern, position) === position;
|
||||
};
|
||||
|
||||
// See ngSanitize
|
||||
String.prototype.encodeEntities = function () {
|
||||
// Regular Expressions for parsing tags and attributes
|
||||
var SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
|
||||
// Match everything outside of normal chars and " (quote character)
|
||||
NON_ALPHANUMERIC_REGEXP = /([^#-~ |!])/g;
|
||||
|
||||
return this.
|
||||
replace(/&/g, '&').
|
||||
replace(SURROGATE_PAIR_REGEXP, function(value) {
|
||||
var hi = value.charCodeAt(0);
|
||||
var low = value.charCodeAt(1);
|
||||
return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
|
||||
}).
|
||||
replace(NON_ALPHANUMERIC_REGEXP, function(value) {
|
||||
return '&#' + value.charCodeAt(0) + ';';
|
||||
}).
|
||||
replace(/</g, '<').
|
||||
replace(/>/g, '>');
|
||||
};
|
||||
|
||||
String.prototype._base64_keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
String.prototype.base64encode = function () {
|
||||
var output = "";
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
selectedFolder: null,
|
||||
$refreshTimeout: null,
|
||||
$virtualMode: false,
|
||||
$virtualPath: false,
|
||||
PRELOAD: PRELOAD
|
||||
});
|
||||
// Initialize sort parameters from user's settings
|
||||
@@ -476,6 +477,16 @@
|
||||
return this.flags.indexOf('noselect') >= 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @function getClassName
|
||||
* @memberof Mailbox.prototype
|
||||
* @desc Not used but defined because it is called from UIxAclEditor.wox.
|
||||
* @returns a string representing the foreground CSS class name
|
||||
*/
|
||||
Mailbox.prototype.getClassName = function(base) {
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $rename
|
||||
* @memberof AddressBook.prototype
|
||||
@@ -623,7 +634,14 @@
|
||||
* @returns a promise of the HTTP operation
|
||||
*/
|
||||
Mailbox.prototype.$markAsRead = function() {
|
||||
return Mailbox.$$resource.post(this.id, 'markRead');
|
||||
var _this = this;
|
||||
|
||||
return Mailbox.$$resource.post(this.id, 'markRead').then(function() {
|
||||
_this.unseenCount = 0;
|
||||
_.forEach(_this.$messages, function(message) {
|
||||
message.isread = true;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -931,6 +949,7 @@
|
||||
}, function(data) {
|
||||
angular.extend(_this, data);
|
||||
_this.isError = true;
|
||||
_this.$isLoading = false;
|
||||
deferred.reject();
|
||||
});
|
||||
|
||||
|
||||
@@ -12,85 +12,68 @@
|
||||
defaultWindowTitle = angular.element($window.document).find('title').attr('sg-default') || "SOGo",
|
||||
hotkeys = [];
|
||||
|
||||
// Expose controller for eventual popup windows
|
||||
$window.$mailboxController = vm;
|
||||
this.$onInit = function() {
|
||||
// Expose controller for eventual popup windows
|
||||
$window.$mailboxController = vm;
|
||||
|
||||
vm.service = Mailbox;
|
||||
vm.accounts = stateAccounts;
|
||||
vm.account = stateAccount;
|
||||
vm.selectedFolder = stateMailbox;
|
||||
vm.selectMessage = selectMessage;
|
||||
vm.messageDialog = null; // also access from Message controller
|
||||
vm.toggleMessageSelection = toggleMessageSelection;
|
||||
vm.sort = sort;
|
||||
vm.sortedBy = sortedBy;
|
||||
vm.searchMode = searchMode;
|
||||
vm.cancelSearch = cancelSearch;
|
||||
vm.newMessage = newMessage;
|
||||
vm.mode = { search: false, multiple: 0 };
|
||||
vm.confirmDeleteSelectedMessages = confirmDeleteSelectedMessages;
|
||||
vm.markOrUnMarkMessagesAsJunk = markOrUnMarkMessagesAsJunk;
|
||||
vm.copySelectedMessages = copySelectedMessages;
|
||||
vm.moveSelectedMessages = moveSelectedMessages;
|
||||
vm.markSelectedMessagesAsFlagged = markSelectedMessagesAsFlagged;
|
||||
vm.markSelectedMessagesAsUnread = markSelectedMessagesAsUnread;
|
||||
vm.markSelectedMessagesAsRead = markSelectedMessagesAsRead;
|
||||
vm.selectAll = selectAll;
|
||||
vm.unselectMessages = unselectMessages;
|
||||
this.service = Mailbox;
|
||||
this.accounts = stateAccounts;
|
||||
this.account = stateAccount;
|
||||
this.selectedFolder = stateMailbox;
|
||||
this.messageDialog = null; // also access from Message controller
|
||||
this.mode = { search: false, multiple: 0 };
|
||||
|
||||
_registerHotkeys(hotkeys);
|
||||
|
||||
stateMailbox.selectFolder();
|
||||
|
||||
_registerHotkeys(hotkeys);
|
||||
|
||||
// Expunge mailbox when leaving the Mail module
|
||||
angular.element($window).on('beforeunload', _compactBeforeUnload);
|
||||
$scope.$on('$destroy', function() {
|
||||
angular.element($window).off('beforeunload', _compactBeforeUnload);
|
||||
// Deregister hotkeys
|
||||
_.forEach(hotkeys, function(key) {
|
||||
sgHotkeys.deregisterHotkey(key);
|
||||
// Expunge mailbox when leaving the Mail module
|
||||
angular.element($window).on('beforeunload', _compactBeforeUnload);
|
||||
$scope.$on('$destroy', function() {
|
||||
angular.element($window).off('beforeunload', _compactBeforeUnload);
|
||||
// Deregister hotkeys
|
||||
_.forEach(hotkeys, function(key) {
|
||||
sgHotkeys.deregisterHotkey(key);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Update window's title with unseen messages count of selected mailbox
|
||||
$scope.$watch(function() { return vm.selectedFolder.unseenCount; }, function(unseenCount) {
|
||||
var title = defaultWindowTitle + ' - ';
|
||||
if (unseenCount)
|
||||
title += '(' + unseenCount + ') ';
|
||||
title += vm.selectedFolder.$displayName;
|
||||
$window.document.title = title;
|
||||
});
|
||||
// Update window's title with unseen messages count of selected mailbox
|
||||
$scope.$watch(function() { return vm.selectedFolder.unseenCount; }, function(unseenCount) {
|
||||
var title = defaultWindowTitle + ' - ';
|
||||
if (unseenCount)
|
||||
title += '(' + unseenCount + ') ';
|
||||
title += vm.selectedFolder.$displayName;
|
||||
$window.document.title = title;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
function _registerHotkeys(keys) {
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: l('hotkey_search'),
|
||||
description: l('Search'),
|
||||
callback: searchMode
|
||||
callback: vm.searchMode
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: l('hotkey_compose'),
|
||||
description: l('Write a new message'),
|
||||
callback: function($event) {
|
||||
if (vm.messageDialog === null)
|
||||
newMessage($event);
|
||||
vm.newMessage($event);
|
||||
}
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: l('hotkey_junk'),
|
||||
description: l('Mark the selected messages as junk'),
|
||||
callback: markOrUnMarkMessagesAsJunk
|
||||
callback: vm.markOrUnMarkMessagesAsJunk
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'space',
|
||||
description: l('Toggle item'),
|
||||
callback: toggleMessageSelection
|
||||
callback: vm.toggleMessageSelection
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'shift+space',
|
||||
description: l('Toggle range of items'),
|
||||
callback: toggleMessageSelection
|
||||
callback: vm.toggleMessageSelection
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'up',
|
||||
@@ -119,7 +102,7 @@
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'backspace',
|
||||
description: l('Delete selected message or folder'),
|
||||
callback: confirmDeleteSelectedMessages
|
||||
callback: vm.confirmDeleteSelectedMessages
|
||||
}));
|
||||
|
||||
// Register the hotkeys
|
||||
@@ -132,20 +115,20 @@
|
||||
return vm.selectedFolder.$compact();
|
||||
}
|
||||
|
||||
function sort(field) {
|
||||
this.sort = function(field) {
|
||||
vm.selectedFolder.$filter({ sort: field });
|
||||
}
|
||||
};
|
||||
|
||||
function sortedBy(field) {
|
||||
this.sortedBy = function(field) {
|
||||
return Mailbox.$query.sort == field;
|
||||
}
|
||||
};
|
||||
|
||||
function searchMode() {
|
||||
this.searchMode = function() {
|
||||
vm.mode.search = true;
|
||||
focus('search');
|
||||
}
|
||||
};
|
||||
|
||||
function cancelSearch() {
|
||||
this.cancelSearch = function() {
|
||||
vm.mode.search = false;
|
||||
vm.selectedFolder.$filter().then(function() {
|
||||
if (vm.selectedFolder.selectedMessage) {
|
||||
@@ -154,9 +137,9 @@
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function newMessage($event, inPopup) {
|
||||
this.newMessage = function($event, inPopup) {
|
||||
var message;
|
||||
|
||||
if (vm.messageDialog === null) {
|
||||
@@ -183,7 +166,7 @@
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function _newMessageInPopup() {
|
||||
var url = [sgSettings.baseURL(),
|
||||
@@ -227,7 +210,7 @@
|
||||
}
|
||||
|
||||
if (index > -1)
|
||||
selectMessage(vm.selectedFolder.$messages[index]);
|
||||
vm.selectMessage(vm.selectedFolder.$messages[index]);
|
||||
|
||||
$event.preventDefault();
|
||||
|
||||
@@ -250,7 +233,7 @@
|
||||
index = 0;
|
||||
|
||||
if (index < vm.selectedFolder.getLength())
|
||||
selectMessage(vm.selectedFolder.$messages[index]);
|
||||
vm.selectMessage(vm.selectedFolder.$messages[index]);
|
||||
else
|
||||
index = -1;
|
||||
|
||||
@@ -265,7 +248,7 @@
|
||||
if (vm.selectedFolder.hasSelectedMessage()) {
|
||||
index = _nextMessage($event);
|
||||
if (index >= 0)
|
||||
toggleMessageSelection($event, vm.selectedFolder.$messages[index]);
|
||||
vm.toggleMessageSelection($event, vm.selectedFolder.$messages[index]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,23 +258,25 @@
|
||||
if (vm.selectedFolder.hasSelectedMessage()) {
|
||||
index = _previousMessage($event);
|
||||
if (index >= 0)
|
||||
toggleMessageSelection($event, vm.selectedFolder.$messages[index]);
|
||||
vm.toggleMessageSelection($event, vm.selectedFolder.$messages[index]);
|
||||
}
|
||||
}
|
||||
|
||||
function selectMessage(message) {
|
||||
this.selectMessage = function(message) {
|
||||
if (Mailbox.$virtualMode)
|
||||
$state.go('mail.account.virtualMailbox.message', {mailboxId: encodeUriFilter(message.$mailbox.path), messageId: message.uid});
|
||||
else
|
||||
$state.go('mail.account.mailbox.message', {messageId: message.uid});
|
||||
}
|
||||
};
|
||||
|
||||
function toggleMessageSelection($event, message) {
|
||||
this.toggleMessageSelection = function($event, message) {
|
||||
var folder = vm.selectedFolder,
|
||||
selectedIndex, nextSelectedIndex, i;
|
||||
|
||||
if (!message)
|
||||
message = folder.$selectedMessage();
|
||||
if (!message)
|
||||
return true;
|
||||
message.selected = !message.selected;
|
||||
vm.mode.multiple += message.selected? 1 : -1;
|
||||
|
||||
@@ -320,7 +305,7 @@
|
||||
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Batch operations
|
||||
@@ -372,7 +357,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
function confirmDeleteSelectedMessages($event) {
|
||||
this.confirmDeleteSelectedMessages = function($event) {
|
||||
var selectedMessages = vm.selectedFolder.$selectedMessages();
|
||||
|
||||
if (vm.messageDialog === null && _.size(selectedMessages) > 0)
|
||||
@@ -417,9 +402,9 @@
|
||||
});
|
||||
|
||||
$event.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
function markOrUnMarkMessagesAsJunk() {
|
||||
this.markOrUnMarkMessagesAsJunk = function() {
|
||||
var moveSelectedMessage = vm.selectedFolder.hasSelectedMessage();
|
||||
var selectedMessages = vm.selectedFolder.$selectedMessages();
|
||||
if (_.size(selectedMessages) === 0 && moveSelectedMessage)
|
||||
@@ -443,9 +428,9 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function copySelectedMessages(dstFolder) {
|
||||
this.copySelectedMessages = function(dstFolder) {
|
||||
var selectedMessages = vm.selectedFolder.$selectedMessages();
|
||||
if (_.size(selectedMessages) > 0)
|
||||
vm.selectedFolder.$copyMessages(selectedMessages, '/' + dstFolder).then(function() {
|
||||
@@ -455,9 +440,9 @@
|
||||
.position('top right')
|
||||
.hideDelay(2000));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function moveSelectedMessages(dstFolder) {
|
||||
this.moveSelectedMessages = function(dstFolder) {
|
||||
var moveSelectedMessage = vm.selectedFolder.hasSelectedMessage();
|
||||
var selectedMessages = vm.selectedFolder.$selectedMessages();
|
||||
var count = vm.selectedFolder.$selectedCount();
|
||||
@@ -479,9 +464,9 @@
|
||||
_unselectMessage(moveSelectedMessage, index);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function selectAll() {
|
||||
this.selectAll = function() {
|
||||
var count = 0;
|
||||
_.forEach(_currentMailboxes(), function(folder) {
|
||||
var i = 0, length = folder.$messages.length;
|
||||
@@ -490,18 +475,18 @@
|
||||
count += length;
|
||||
});
|
||||
vm.mode.multiple = count;
|
||||
}
|
||||
};
|
||||
|
||||
function unselectMessages() {
|
||||
this.unselectMessages = function() {
|
||||
_.forEach(_currentMailboxes(), function(folder) {
|
||||
_.forEach(folder.$messages, function(message) {
|
||||
message.selected = false;
|
||||
});
|
||||
});
|
||||
vm.mode.multiple = 0;
|
||||
}
|
||||
};
|
||||
|
||||
function markSelectedMessagesAsFlagged() {
|
||||
this.markSelectedMessagesAsFlagged = function() {
|
||||
var selectedMessages = vm.selectedFolder.$selectedMessages();
|
||||
if (_.size(selectedMessages) > 0)
|
||||
vm.selectedFolder.$flagMessages(selectedMessages, '\\Flagged', 'add').then(function(messages) {
|
||||
@@ -509,9 +494,9 @@
|
||||
message.isflagged = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function markSelectedMessagesAsUnread() {
|
||||
this.markSelectedMessagesAsUnread = function() {
|
||||
var selectedMessages = vm.selectedFolder.$selectedMessages();
|
||||
if (_.size(selectedMessages) > 0) {
|
||||
vm.selectedFolder.$flagMessages(selectedMessages, 'seen', 'remove').then(function(messages) {
|
||||
@@ -522,9 +507,9 @@
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function markSelectedMessagesAsRead() {
|
||||
this.markSelectedMessagesAsRead = function() {
|
||||
var selectedMessages = vm.selectedFolder.$selectedMessages();
|
||||
if (_.size(selectedMessages) > 0) {
|
||||
vm.selectedFolder.$flagMessages(selectedMessages, 'seen', 'add').then(function(messages) {
|
||||
@@ -535,13 +520,13 @@
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
angular
|
||||
.module('material.components.virtualRepeat')
|
||||
.decorator('mdVirtualRepeatContainerDirective', mdVirtualRepeatContainerDirectiveDecorator);
|
||||
.module('SOGo.MailerUI')
|
||||
.controller('MailboxController', MailboxController);
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
@@ -560,7 +545,8 @@
|
||||
}
|
||||
|
||||
angular
|
||||
.module('SOGo.MailerUI')
|
||||
.controller('MailboxController', MailboxController);
|
||||
.module('material.components.virtualRepeat')
|
||||
.decorator('mdVirtualRepeatContainerDirective', mdVirtualRepeatContainerDirectiveDecorator);
|
||||
|
||||
})();
|
||||
|
||||
|
||||
@@ -6,70 +6,47 @@
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
MailboxesController.$inject = ['$scope', '$state', '$timeout', '$window', '$mdDialog', '$mdToast', '$mdMedia', '$mdSidenav', 'sgConstant', 'sgFocus', 'encodeUriFilter', 'Dialog', 'sgSettings', 'sgHotkeys', 'Account', 'Mailbox', 'VirtualMailbox', 'User', 'Preferences', 'stateAccounts'];
|
||||
function MailboxesController($scope, $state, $timeout, $window, $mdDialog, $mdToast, $mdMedia, $mdSidenav, sgConstant, focus, encodeUriFilter, Dialog, Settings, sgHotkeys, Account, Mailbox, VirtualMailbox, User, Preferences, stateAccounts) {
|
||||
MailboxesController.$inject = ['$scope', '$state', '$transitions', '$timeout', '$window', '$mdDialog', '$mdToast', 'sgFocus', 'encodeUriFilter', 'Dialog', 'sgSettings', 'sgHotkeys', 'Account', 'Mailbox', 'VirtualMailbox', 'User', 'Preferences', 'stateAccounts'];
|
||||
function MailboxesController($scope, $state, $transitions, $timeout, $window, $mdDialog, $mdToast, focus, encodeUriFilter, Dialog, Settings, sgHotkeys, Account, Mailbox, VirtualMailbox, User, Preferences, stateAccounts) {
|
||||
var vm = this,
|
||||
account,
|
||||
mailbox,
|
||||
hotkeys = [];
|
||||
|
||||
vm.service = Mailbox;
|
||||
vm.accounts = stateAccounts;
|
||||
vm.toggleAccountState = toggleAccountState;
|
||||
vm.subscribe = subscribe;
|
||||
vm.newFolder = newFolder;
|
||||
vm.delegate = delegate;
|
||||
vm.editFolder = editFolder;
|
||||
vm.revertEditing = revertEditing;
|
||||
vm.selectFolder = selectFolder;
|
||||
vm.saveFolder = saveFolder;
|
||||
vm.compactFolder = compactFolder;
|
||||
vm.emptyTrashFolder = emptyTrashFolder;
|
||||
vm.confirmDelete = confirmDelete;
|
||||
vm.markFolderRead = markFolderRead;
|
||||
vm.share = share;
|
||||
vm.setFolderAs = setFolderAs;
|
||||
vm.refreshUnseenCount = refreshUnseenCount;
|
||||
vm.isDroppableFolder = isDroppableFolder;
|
||||
vm.dragSelectedMessages = dragSelectedMessages;
|
||||
this.$onInit = function () {
|
||||
this.service = Mailbox;
|
||||
this.accounts = stateAccounts;
|
||||
|
||||
// Advanced search options
|
||||
vm.showingAdvancedSearch = false;
|
||||
vm.currentSearchParam = '';
|
||||
vm.addSearchParam = addSearchParam;
|
||||
vm.newSearchParam = newSearchParam;
|
||||
vm.showAdvancedSearch = showAdvancedSearch;
|
||||
vm.hideAdvancedSearch = hideAdvancedSearch;
|
||||
vm.toggleAdvancedSearch = toggleAdvancedSearch;
|
||||
vm.search = {
|
||||
options: {'': '', // no placeholder when no criteria is active
|
||||
subject: l('Enter Subject'),
|
||||
from: l('Enter From'),
|
||||
to: l('Enter To'),
|
||||
cc: l('Enter Cc'),
|
||||
body: l('Enter Body')
|
||||
},
|
||||
mailbox: 'INBOX',
|
||||
subfolders: 1,
|
||||
match: 'AND',
|
||||
params: []
|
||||
};
|
||||
// Advanced search options
|
||||
this.currentSearchParam = '';
|
||||
this.search = {
|
||||
options: {'': '', // no placeholder when no criteria is active
|
||||
subject: l('Enter Subject'),
|
||||
from: l('Enter From'),
|
||||
to: l('Enter To'),
|
||||
cc: l('Enter Cc'),
|
||||
body: l('Enter Body')
|
||||
},
|
||||
subfolders: 1,
|
||||
match: 'AND',
|
||||
params: []
|
||||
};
|
||||
|
||||
|
||||
Preferences.ready().then(function() {
|
||||
vm.showSubscribedOnly = Preferences.defaults.SOGoMailShowSubscribedFoldersOnly;
|
||||
});
|
||||
|
||||
vm.refreshUnseenCount();
|
||||
|
||||
_registerHotkeys(hotkeys);
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
// Deregister hotkeys
|
||||
_.forEach(hotkeys, function(key) {
|
||||
sgHotkeys.deregisterHotkey(key);
|
||||
Preferences.ready().then(function() {
|
||||
vm.showSubscribedOnly = Preferences.defaults.SOGoMailShowSubscribedFoldersOnly;
|
||||
});
|
||||
});
|
||||
|
||||
this.refreshUnseenCount();
|
||||
|
||||
_registerHotkeys(hotkeys);
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
// Deregister hotkeys
|
||||
_.forEach(hotkeys, function(key) {
|
||||
sgHotkeys.deregisterHotkey(key);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
function _registerHotkeys(keys) {
|
||||
@@ -88,24 +65,16 @@
|
||||
});
|
||||
}
|
||||
|
||||
function showAdvancedSearch(path) {
|
||||
vm.showingAdvancedSearch = true;
|
||||
vm.search.mailbox = path;
|
||||
// Close sidenav on small devices
|
||||
if (!$mdMedia(sgConstant['gt-md']))
|
||||
$mdSidenav('left').close();
|
||||
}
|
||||
|
||||
function hideAdvancedSearch() {
|
||||
vm.showingAdvancedSearch = false;
|
||||
this.hideAdvancedSearch = function() {
|
||||
vm.service.$virtualPath = false;
|
||||
vm.service.$virtualMode = false;
|
||||
|
||||
account = vm.accounts[0];
|
||||
mailbox = vm.searchPreviousMailbox;
|
||||
$state.go('mail.account.mailbox', { accountId: account.id, mailboxId: encodeUriFilter(mailbox.path) });
|
||||
}
|
||||
};
|
||||
|
||||
function toggleAdvancedSearch() {
|
||||
this.toggleAdvancedSearch = function() {
|
||||
if (Mailbox.selectedFolder.$isLoading) {
|
||||
// Stop search
|
||||
vm.virtualMailbox.stopSearch();
|
||||
@@ -133,8 +102,8 @@
|
||||
Mailbox.selectedFolder = vm.virtualMailbox;
|
||||
Mailbox.$virtualMode = true;
|
||||
|
||||
if (angular.isDefined(vm.search.mailbox)) {
|
||||
root = vm.accounts[0].$getMailboxByPath(vm.search.mailbox);
|
||||
if (angular.isDefined(Mailbox.$virtualPath)) {
|
||||
root = vm.accounts[0].$getMailboxByPath(Mailbox.$virtualPath);
|
||||
mailboxes.push(root);
|
||||
if (vm.search.subfolders && root.children.length)
|
||||
_visit(root.children);
|
||||
@@ -145,17 +114,18 @@
|
||||
|
||||
vm.virtualMailbox.setMailboxes(mailboxes);
|
||||
vm.virtualMailbox.startSearch(vm.search.match, vm.search.params);
|
||||
$state.go('mail.account.virtualMailbox', { accountId: vm.accounts[0].id });
|
||||
if ($state.$current.name != 'mail.account.virtualMailbox')
|
||||
$state.go('mail.account.virtualMailbox', { accountId: vm.accounts[0].id });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function addSearchParam(v) {
|
||||
this.addSearchParam = function(v) {
|
||||
vm.currentSearchParam = v;
|
||||
focus('advancedSearch');
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
function newSearchParam(pattern) {
|
||||
this.newSearchParam = function(pattern) {
|
||||
if (pattern.length && vm.currentSearchParam.length) {
|
||||
var n = 0, searchParam = vm.currentSearchParam;
|
||||
if (pattern.startsWith("!")) {
|
||||
@@ -165,9 +135,9 @@
|
||||
vm.currentSearchParam = '';
|
||||
return { searchBy: searchParam, searchInput: pattern, negative: n };
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function toggleAccountState(account) {
|
||||
this.toggleAccountState = function (account) {
|
||||
account.$expanded = !account.$expanded;
|
||||
account.$flattenMailboxes({ reload: true, saveState: true });
|
||||
// Fire a window resize to recompute the virtual-repeater.
|
||||
@@ -176,9 +146,9 @@
|
||||
$timeout(function() {
|
||||
angular.element($window).triggerHandler('resize');
|
||||
}, 150);
|
||||
}
|
||||
};
|
||||
|
||||
function subscribe(account) {
|
||||
this.subscribe = function(account) {
|
||||
$mdDialog.show({
|
||||
templateUrl: account.id + '/subscribe',
|
||||
controller: SubscriptionsDialogController,
|
||||
@@ -212,12 +182,12 @@
|
||||
});
|
||||
|
||||
function close() {
|
||||
$mdDialog.cancel();
|
||||
$mdDialog.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function newFolder(parentFolder) {
|
||||
this.newFolder = function(parentFolder) {
|
||||
Dialog.prompt(l('New Folder...'),
|
||||
l('Enter the new name of your folder'))
|
||||
.then(function(name) {
|
||||
@@ -229,9 +199,9 @@
|
||||
l(data.error));
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function delegate(account) {
|
||||
this.delegate = function(account) {
|
||||
$mdDialog.show({
|
||||
templateUrl: account.id + '/delegation', // UI/Templates/MailerUI/UIxMailUserDelegation.wox
|
||||
controller: MailboxDelegationController,
|
||||
@@ -285,114 +255,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
} // delegate
|
||||
}; // delegate
|
||||
|
||||
function editFolder(folder) {
|
||||
vm.editMode = folder.path;
|
||||
focus('mailboxName_' + folder.path);
|
||||
}
|
||||
|
||||
function revertEditing(folder) {
|
||||
folder.$reset();
|
||||
vm.editMode = false;
|
||||
}
|
||||
|
||||
function selectFolder($event, account, folder) {
|
||||
if (vm.editMode == folder.path)
|
||||
return;
|
||||
vm.editMode = false;
|
||||
vm.showingAdvancedSearch = false;
|
||||
vm.service.$virtualMode = false;
|
||||
// Close sidenav on small devices
|
||||
if (!$mdMedia(sgConstant['gt-md']))
|
||||
$mdSidenav('left').close();
|
||||
$state.go('mail.account.mailbox', { accountId: account.id, mailboxId: encodeUriFilter(folder.path) });
|
||||
$event.stopPropagation();
|
||||
$event.preventDefault();
|
||||
}
|
||||
|
||||
function saveFolder(folder) {
|
||||
folder.$rename()
|
||||
.then(function(data) {
|
||||
vm.editMode = false;
|
||||
});
|
||||
}
|
||||
|
||||
function compactFolder(folder) {
|
||||
folder.$compact().then(function() {
|
||||
$mdToast.show(
|
||||
$mdToast.simple()
|
||||
.content(l('Folder compacted'))
|
||||
.position('top right')
|
||||
.hideDelay(3000));
|
||||
});
|
||||
}
|
||||
|
||||
function emptyTrashFolder(folder) {
|
||||
folder.$emptyTrash().then(function() {
|
||||
$mdToast.show(
|
||||
$mdToast.simple()
|
||||
.content(l('Trash emptied'))
|
||||
.position('top right')
|
||||
.hideDelay(3000));
|
||||
});
|
||||
}
|
||||
|
||||
function confirmDelete(folder) {
|
||||
Dialog.confirm(l('Warning'),
|
||||
l('Do you really want to move this folder into the trash ?'),
|
||||
{ ok: l('Delete') })
|
||||
.then(function() {
|
||||
folder.$delete()
|
||||
.then(function() {
|
||||
$state.go('mail.account.inbox');
|
||||
}, function(response) {
|
||||
Dialog.confirm(l('Warning'),
|
||||
l('The mailbox could not be moved to the trash folder. Would you like to delete it immediately?'),
|
||||
{ ok: l('Delete') })
|
||||
.then(function() {
|
||||
folder.$delete({ withoutTrash: true })
|
||||
.then(function() {
|
||||
$state.go('mail.account.inbox');
|
||||
}, function(response) {
|
||||
Dialog.alert(l('An error occured while deleting the mailbox "%{0}".', folder.name),
|
||||
l(response.error));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function markFolderRead(folder) {
|
||||
folder.$markAsRead();
|
||||
}
|
||||
|
||||
function share(folder) {
|
||||
// Fetch list of ACL users
|
||||
folder.$acl.$users().then(function() {
|
||||
// Show ACL editor
|
||||
$mdDialog.show({
|
||||
templateUrl: folder.id + '/UIxAclEditor', // UI/Templates/UIxAclEditor.wox
|
||||
controller: 'AclController', // from the ng module SOGo.Common
|
||||
controllerAs: 'acl',
|
||||
clickOutsideToClose: true,
|
||||
escapeToClose: true,
|
||||
locals: {
|
||||
usersWithACL: folder.$acl.users,
|
||||
User: User,
|
||||
folder: folder
|
||||
}
|
||||
});
|
||||
});
|
||||
} // share
|
||||
|
||||
function setFolderAs(folder, type) {
|
||||
folder.$setFolderAs(type).then(function() {
|
||||
folder.$account.$getMailboxes({reload: true});
|
||||
});
|
||||
}
|
||||
|
||||
function refreshUnseenCount() {
|
||||
this.refreshUnseenCount = function() {
|
||||
var unseenCountFolders = $window.unseenCountFolders;
|
||||
|
||||
_.forEach(vm.accounts, function(account) {
|
||||
@@ -422,13 +287,13 @@
|
||||
if (refreshViewCheck && refreshViewCheck != 'manually')
|
||||
$timeout(vm.refreshUnseenCount, refreshViewCheck.timeInterval()*1000);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function isDroppableFolder(srcFolder, dstFolder) {
|
||||
this.isDroppableFolder = function(srcFolder, dstFolder) {
|
||||
return (dstFolder.id != srcFolder.id) && !dstFolder.isNoSelect();
|
||||
}
|
||||
};
|
||||
|
||||
function dragSelectedMessages(srcFolder, dstFolder, mode) {
|
||||
this.dragSelectedMessages = function(srcFolder, dstFolder, mode) {
|
||||
var dstId, messages, uids, clearMessageView, promise, success;
|
||||
|
||||
dstId = '/' + dstFolder.id;
|
||||
@@ -456,7 +321,7 @@
|
||||
.position('top right')
|
||||
.hideDelay(2000));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -206,35 +206,53 @@
|
||||
|
||||
if (mailbox) {
|
||||
mailbox.$topIndex = 0;
|
||||
mailbox.selectFolder();
|
||||
return mailbox;
|
||||
}
|
||||
else
|
||||
// Mailbox not found
|
||||
return $state.go('mail.account.inbox');
|
||||
return $q.reject("Mailbox doesn't exist");
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
onEnterInbox.$inject = ['$window', '$state', 'encodeUriFilter', 'stateAccount'];
|
||||
function onEnterInbox($window, $state, encodeUriFilter, stateAccount) {
|
||||
if (stateAccount.$mailboxes.length > 0)
|
||||
$window.location.hash = $state.href('mail.account.mailbox',
|
||||
{accountId: stateAccount.id,
|
||||
mailboxId: encodeUriFilter(stateAccount.$mailboxes[0].path)});
|
||||
else
|
||||
$state.go('mail');
|
||||
onEnterInbox.$inject = ['$transition$', 'encodeUriFilter', 'Mailbox'];
|
||||
function onEnterInbox($transition, encodeUriFilter, Mailbox) {
|
||||
var stateAccountPromise = $transition.injector().getAsync('stateAccount');
|
||||
return stateAccountPromise.then(function(stateAccount) {
|
||||
if (stateAccount.$mailboxes.length > 0) {
|
||||
return $transition.router.stateService.target('mail.account.mailbox', {
|
||||
accountId: stateAccount.id,
|
||||
mailboxId: encodeUriFilter(stateAccount.$mailboxes[0].path)
|
||||
});
|
||||
}
|
||||
else {
|
||||
Mailbox.selectedFolder = false;
|
||||
return $transition.router.stateService.target('mail');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
stateMessages.$inject = ['Mailbox', 'stateMailbox'];
|
||||
function stateMessages(Mailbox, stateMailbox) {
|
||||
stateMessages.$inject = ['$q', '$state', 'Mailbox', 'stateMailbox'];
|
||||
function stateMessages($q, $state, Mailbox, stateMailbox) {
|
||||
var promise;
|
||||
|
||||
if (Mailbox.$virtualMode)
|
||||
return [];
|
||||
|
||||
return stateMailbox.$filter();
|
||||
if (stateMailbox)
|
||||
promise = stateMailbox.$filter().catch(function() {
|
||||
// Mailbox not found
|
||||
return $q.reject('Mailbox not found');
|
||||
});
|
||||
else
|
||||
promise = $q.reject("Mailbox doesn't exist");
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,25 +332,21 @@
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
// stateContent.$inject = ['stateMessage'];
|
||||
// function stateContent(stateMessage) {
|
||||
// return stateMessage.$editableContent();
|
||||
// }
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
runBlock.$inject = ['$rootScope', '$log', '$state', 'Mailbox'];
|
||||
function runBlock($rootScope, $log, $state, Mailbox) {
|
||||
$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
|
||||
$log.error(error);
|
||||
event.preventDefault();
|
||||
// Unselect everything
|
||||
Mailbox.selectedFolder = false;
|
||||
$state.go('mail');
|
||||
});
|
||||
$rootScope.$on('$routeChangeError', function(event, current, previous, rejection) {
|
||||
$log.error(event, current, previous, rejection);
|
||||
runBlock.$inject = ['$window', '$transitions', '$log', '$state', 'Mailbox'];
|
||||
function runBlock($window, $transitions, $log, $state, Mailbox) {
|
||||
if (!$window.DebugEnabled)
|
||||
$state.defaultErrorHandler(function() {
|
||||
// Don't report any state error
|
||||
});
|
||||
$transitions.onError({ to: 'mail.**' }, function(transition) {
|
||||
if (transition.to().name != 'mail' &&
|
||||
!transition.ignored() &&
|
||||
transition.error().message.indexOf('superseded') < 0) {
|
||||
$log.error('transition error to ' + transition.to().name);
|
||||
// Unselect everything
|
||||
Mailbox.selectedFolder = false;
|
||||
$state.go('mail');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
|
||||
/**
|
||||
* sgAccountSection - A directive that is only a controller to manage the selection of the mailboxes.
|
||||
* @memberof SOGo.MailerUI
|
||||
*/
|
||||
function sgAccountSection() {
|
||||
return {
|
||||
restrict: 'C',
|
||||
scope: {},
|
||||
controller: 'sgAccountController'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
sgAccountController.$inject = ['$element', '$transitions', '$state', '$mdMedia', '$mdSidenav', 'sgConstant', 'Mailbox', 'encodeUriFilter'];
|
||||
function sgAccountController($element, $transitions, $state, $mdMedia, $mdSidenav, sgConstant, Mailbox, encodeUriFilter) {
|
||||
var $ctrl = this, mailboxes = [];
|
||||
|
||||
|
||||
this.$postLink = function () {
|
||||
this.quotaElement = _.find($element.find('div'), function(div) {
|
||||
return div.classList.contains('sg-quota');
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// Register a sgMailboxListItem controller
|
||||
this.addMailboxController = function (mailboxController) {
|
||||
mailboxes.push(mailboxController);
|
||||
};
|
||||
|
||||
|
||||
// Called from a sgMailboxListItem controller
|
||||
this.selectFolder = function (mailboxController) {
|
||||
if (Mailbox.selectedFolder !== null) {
|
||||
var selectedMailboxCtrl = _.find(mailboxes, function(ctrl) {
|
||||
return ctrl.mailbox.id == Mailbox.selectedFolder.id;
|
||||
});
|
||||
if (selectedMailboxCtrl)
|
||||
selectedMailboxCtrl.unselectFolder();
|
||||
}
|
||||
// Close sidenav on small devices
|
||||
if (!$mdMedia(sgConstant['gt-md']))
|
||||
$mdSidenav('left').close();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
angular
|
||||
.module('SOGo.MailerUI')
|
||||
.controller('sgAccountController', sgAccountController)
|
||||
.directive('sgAccountSection', sgAccountSection);
|
||||
})();
|
||||
302
UI/WebServerResources/js/Mailer/sgMailboxListItem.directive.js
Normal file
302
UI/WebServerResources/js/Mailer/sgMailboxListItem.directive.js
Normal file
@@ -0,0 +1,302 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
|
||||
/**
|
||||
* sgMailboxListItem - A directive that defines the content of a md-list-item for a mailbox.
|
||||
* @memberof SOGo.MailerUI
|
||||
*/
|
||||
function sgMailboxListItem() {
|
||||
return {
|
||||
restrict: 'C',
|
||||
require: {
|
||||
accountController: '^^sgAccountSection'
|
||||
},
|
||||
scope: {},
|
||||
bindToController: {
|
||||
mailbox: '=sgMailbox'
|
||||
},
|
||||
template: [
|
||||
' <div class="sg-child-level-0"',
|
||||
' ng-class="::$ctrl.childLevel()">',
|
||||
' <md-checkbox class="sg-folder"',
|
||||
' ng-class="::$ctrl.mailbox.$icon"',
|
||||
' aria-label="' + l("Expanded") + '"',
|
||||
' ng-model="$ctrl.mailbox.$expanded"',
|
||||
' ng-disabled="$ctrl.mailbox.children.length == 0"',
|
||||
' ng-change="$ctrl.mailbox.$account.$flattenMailboxes({ reload: true, saveState: true })">',
|
||||
' <md-icon>{{::$ctrl.mailbox.$icon}}</md-icon></md-checkbox>',
|
||||
' </div>',
|
||||
' <p class="sg-item-name"',
|
||||
' ng-click="$ctrl.selectFolder($event)"',
|
||||
' ng-dblclick="$ctrl.editFolder($event)">',
|
||||
' <span ng-bind="$ctrl.mailbox.$displayName"></span>',
|
||||
' <span class="sg-counter-badge ng-hide"',
|
||||
' ng-show="$ctrl.mailbox.unseenCount"',
|
||||
' ng-bind="$ctrl.mailbox.unseenCount"></span>',
|
||||
' </p>',
|
||||
' <md-input-container class="md-flex ng-hide">',
|
||||
' <input class="sg-item-name" type="text"',
|
||||
' aria-label="' + l("Enter the new name of your folder") + '"',
|
||||
' ng-blur="$ctrl.saveFolder($event)"',
|
||||
' sg-enter="$ctrl.saveFolder($event)"',
|
||||
' sg-escape="$ctrl.revertEditing()" />',
|
||||
' </md-input-container>',
|
||||
' <md-icon class="md-menu" ng-click="$ctrl.showMenu($event)" aria-label="' + l("Options") + '">more_vert</md-icon>'
|
||||
].join(''),
|
||||
controller: 'sgMailboxListItemController',
|
||||
controllerAs: '$ctrl'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
sgMailboxListItemController.$inject = ['$scope', '$element', '$compile', '$state', '$mdToast', '$mdPanel', '$mdMedia', '$mdSidenav', 'sgConstant', 'Dialog', 'Mailbox', 'encodeUriFilter'];
|
||||
function sgMailboxListItemController($scope, $element, $compile, $state, $mdToast, $mdPanel, $mdMedia, $mdSidenav, sgConstant, Dialog, Mailbox, encodeUriFilter) {
|
||||
var $ctrl = this;
|
||||
|
||||
|
||||
this.$onInit = function() {
|
||||
this.$element = $element;
|
||||
this.service = Mailbox;
|
||||
this.editMode = false;
|
||||
this.accountController.addMailboxController(this);
|
||||
};
|
||||
|
||||
|
||||
this.$postLink = function() {
|
||||
this.selectableElement = $element.find('div')[0];
|
||||
this.clickableElement = $element.find('p')[0];
|
||||
this.inputContainer = $element.find('md-input-container')[0];
|
||||
this.inputElement = $element.find('input')[0];
|
||||
this.moreOptionsButton = _.last($element.find('md-icon'));
|
||||
|
||||
// Check if router's state has selected a mailbox
|
||||
if (Mailbox.selectedFolder !== null && Mailbox.selectedFolder.id == this.mailbox.id) {
|
||||
this.selectFolder();
|
||||
}
|
||||
};
|
||||
|
||||
this.childLevel = function() {
|
||||
return 'sg-child-level-' + this.mailbox.level;
|
||||
};
|
||||
|
||||
|
||||
this.selectFolder = function($event) {
|
||||
if (this.editMode || this.mailbox == Mailbox.selectedFolder)
|
||||
return;
|
||||
Mailbox.$virtualPath = false;
|
||||
Mailbox.$virtualMode = false;
|
||||
this.accountController.selectFolder(this);
|
||||
if ($event) {
|
||||
$state.go('mail.account.mailbox', {
|
||||
accountId: this.mailbox.$account.id,
|
||||
mailboxId: encodeUriFilter(this.mailbox.path)
|
||||
});
|
||||
$event.stopPropagation();
|
||||
$event.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.unselectFolder = function() {
|
||||
$element[0].classList.remove('md-bg');
|
||||
};
|
||||
|
||||
|
||||
this.editFolder = function($event) {
|
||||
this.editMode = true;
|
||||
this.inputElement.value = this.mailbox.name;
|
||||
this.clickableElement.classList.add('ng-hide');
|
||||
this.inputContainer.classList.remove('ng-hide');
|
||||
this.inputElement.focus();
|
||||
this.inputElement.select();
|
||||
if ($event) {
|
||||
$event.stopPropagation();
|
||||
$event.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.saveFolder = function($event) {
|
||||
if (this.inputElement.disabled)
|
||||
return;
|
||||
|
||||
this.mailbox.name = this.inputElement.value;
|
||||
this.inputElement.disabled = true;
|
||||
this.mailbox.$rename()
|
||||
.then(function(data) {
|
||||
$ctrl.editMode = false;
|
||||
$ctrl.inputContainer.classList.add('ng-hide');
|
||||
$ctrl.clickableElement.classList.remove('ng-hide');
|
||||
})
|
||||
.finally(function() {
|
||||
$ctrl.inputElement.disabled = false;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
this.revertEditing = function() {
|
||||
this.editMode = false;
|
||||
this.clickableElement.classList.remove('ng-hide');
|
||||
this.inputContainer.classList.add('ng-hide');
|
||||
this.inputElement.value = this.mailbox.name;
|
||||
};
|
||||
|
||||
|
||||
this.showMenu = function($event) {
|
||||
var panelPosition = $mdPanel.newPanelPosition()
|
||||
.relativeTo(this.moreOptionsButton)
|
||||
.addPanelPosition(
|
||||
$mdPanel.xPosition.ALIGN_START,
|
||||
$mdPanel.yPosition.ALIGN_TOPS
|
||||
);
|
||||
|
||||
var panelAnimation = $mdPanel.newPanelAnimation()
|
||||
.openFrom(this.moreOptionsButton)
|
||||
.duration(100)
|
||||
.withAnimation($mdPanel.animation.FADE);
|
||||
|
||||
var config = {
|
||||
attachTo: angular.element(document.body),
|
||||
locals: {
|
||||
itemCtrl: this,
|
||||
folder: this.mailbox
|
||||
},
|
||||
bindToController: true,
|
||||
controller: MenuController,
|
||||
controllerAs: '$menuCtrl',
|
||||
position: panelPosition,
|
||||
animation: panelAnimation,
|
||||
targetEvent: $event,
|
||||
templateUrl: 'UIxMailFolderMenu',
|
||||
trapFocus: true,
|
||||
clickOutsideToClose: true,
|
||||
escapeToClose: true,
|
||||
focusOnOpen: true
|
||||
};
|
||||
|
||||
$mdPanel.open(config)
|
||||
.then(function(panelRef) {
|
||||
// Automatically close panel when clicking inside of it
|
||||
panelRef.panelEl.one('click', function() {
|
||||
panelRef.close();
|
||||
});
|
||||
});
|
||||
|
||||
MenuController.$inject = ['mdPanelRef', '$state', '$mdDialog', 'User'];
|
||||
function MenuController(mdPanelRef, $state, $mdDialog, User) {
|
||||
var $menuCtrl = this;
|
||||
|
||||
this.markFolderRead = function() {
|
||||
this.folder.$markAsRead();
|
||||
};
|
||||
|
||||
this.newFolder = function() {
|
||||
Dialog.prompt(l('New Folder...'),
|
||||
l('Enter the new name of your folder'))
|
||||
.then(function(name) {
|
||||
$menuCtrl.folder.$newMailbox($menuCtrl.folder.id, name)
|
||||
.then(function() {
|
||||
// success
|
||||
}, function(data, status) {
|
||||
Dialog.alert(l('An error occured while creating the mailbox "%{0}".', name),
|
||||
l(data.error));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
this.editFolder = function() {
|
||||
this.itemCtrl.editFolder();
|
||||
};
|
||||
|
||||
this.compactFolder = function() {
|
||||
this.folder.$compact().then(function() {
|
||||
$mdToast.show(
|
||||
$mdToast.simple()
|
||||
.content(l('Folder compacted'))
|
||||
.position('top right')
|
||||
.hideDelay(3000));
|
||||
});
|
||||
};
|
||||
|
||||
this.emptyTrashFolder = function() {
|
||||
this.folder.$emptyTrash().then(function() {
|
||||
$mdToast.show(
|
||||
$mdToast.simple()
|
||||
.content(l('Trash emptied'))
|
||||
.position('top right')
|
||||
.hideDelay(3000));
|
||||
});
|
||||
};
|
||||
|
||||
this.confirmDelete = function() {
|
||||
Dialog.confirm(l('Warning'),
|
||||
l('Do you really want to move this folder into the trash ?'),
|
||||
{ ok: l('Delete') })
|
||||
.then(function() {
|
||||
$menuCtrl.folder.$delete()
|
||||
.then(function() {
|
||||
$state.go('mail.account.inbox');
|
||||
}, function(response) {
|
||||
Dialog.confirm(l('Warning'),
|
||||
l('The mailbox could not be moved to the trash folder. Would you like to delete it immediately?'),
|
||||
{ ok: l('Delete') })
|
||||
.then(function() {
|
||||
$menuCtrl.folder.$delete({ withoutTrash: true })
|
||||
.then(function() {
|
||||
$state.go('mail.account.inbox');
|
||||
}, function(response) {
|
||||
Dialog.alert(l('An error occured while deleting the mailbox "%{0}".', $menuCtrl.folder.name),
|
||||
l(response.error));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
this.showAdvancedSearch = function() {
|
||||
Mailbox.$virtualPath = this.folder.path;
|
||||
// Close sidenav on small devices
|
||||
if (!$mdMedia(sgConstant['gt-md']))
|
||||
$mdSidenav('left').close();
|
||||
};
|
||||
|
||||
this.share = function() {
|
||||
// Fetch list of ACL users
|
||||
this.folder.$acl.$users().then(function() {
|
||||
// Show ACL editor
|
||||
$mdDialog.show({
|
||||
templateUrl: $menuCtrl.folder.id + '/UIxAclEditor', // UI/Templates/UIxAclEditor.wox
|
||||
controller: 'AclController', // from the ng module SOGo.Common
|
||||
controllerAs: 'acl',
|
||||
clickOutsideToClose: true,
|
||||
escapeToClose: true,
|
||||
locals: {
|
||||
usersWithACL: $menuCtrl.folder.$acl.users,
|
||||
User: User,
|
||||
folder: $menuCtrl.folder
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
this.setFolderAs = function(type) {
|
||||
this.folder.$setFolderAs(type).then(function() {
|
||||
$menuCtrl.folder.$account.$getMailboxes({reload: true});
|
||||
});
|
||||
};
|
||||
|
||||
} // MenuController
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
angular
|
||||
.module('SOGo.MailerUI')
|
||||
.controller('sgMailboxListItemController', sgMailboxListItemController)
|
||||
.directive('sgMailboxListItem', sgMailboxListItem);
|
||||
})();
|
||||
@@ -0,0 +1,77 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
|
||||
/**
|
||||
* sgMessageListItem - A directive that watches some attributes of a message. Any component inside the
|
||||
* list item should depends on this directive and extend the 'onUpdate' method instead of creating new
|
||||
* independent watchers.
|
||||
* @memberof SOGo.MailerUI
|
||||
*/
|
||||
function sgMessageListItem() {
|
||||
return {
|
||||
restrict: 'C',
|
||||
scope: {},
|
||||
bindToController: {
|
||||
message: '=sgMessage'
|
||||
},
|
||||
controller: 'sgMessageListItemController'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
sgMessageListItemController.$inject = ['$scope', '$element', 'Mailbox'];
|
||||
function sgMessageListItemController($scope, $element, Mailbox) {
|
||||
var $ctrl = this;
|
||||
|
||||
|
||||
this.$onInit = function () {
|
||||
// this.service = Message;
|
||||
this.MailboxService = Mailbox;
|
||||
|
||||
$scope.$watch(
|
||||
function() {
|
||||
return $ctrl.message? [ _.pick($ctrl.message, ['uid', 'isread', 'isflagged']) ] : null;
|
||||
},
|
||||
function(newId, oldId) {
|
||||
if ($ctrl.message) {
|
||||
// Message has changed
|
||||
$ctrl.onUpdate();
|
||||
}
|
||||
},
|
||||
true // compare for object equality
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
this.onUpdate = function () {
|
||||
// Is the message unread?
|
||||
if (this.message.isread)
|
||||
$element.removeClass('unread');
|
||||
else
|
||||
$element.addClass('unread');
|
||||
// Is the message selected?
|
||||
if (Mailbox.selectedFolder.isSelectedMessage(this.message.uid, this.message.$mailbox.path))
|
||||
$element.addClass('md-default-theme md-accent md-bg md-hue-2');
|
||||
else
|
||||
$element.removeClass('md-default-theme md-accent md-bg md-hue-2');
|
||||
};
|
||||
|
||||
|
||||
this.setVisibility = function (element, visible) {
|
||||
if (visible)
|
||||
element.classList.remove('ng-hide');
|
||||
else
|
||||
element.classList.add('ng-hide');
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
angular
|
||||
.module('SOGo.MailerUI')
|
||||
.controller('sgMessageListItemController', sgMessageListItemController)
|
||||
.directive('sgMessageListItem', sgMessageListItem);
|
||||
})();
|
||||
@@ -0,0 +1,181 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
|
||||
/**
|
||||
* sgMessageListItemMain - The main section of a list item for a message. It relies on the
|
||||
* 'onUpdate' method of the parent sgMessageListItem controller to update its content.
|
||||
* @memberof SOGo.MailerUI
|
||||
* @example:
|
||||
*/
|
||||
function sgMessageListItemMain() {
|
||||
return {
|
||||
restrict: 'C',
|
||||
require: '^^sgMessageListItem',
|
||||
scope: {},
|
||||
template: [
|
||||
'<div class="sg-category"',
|
||||
' ng-repeat="tag in $ctrl.message.flags | limitTo:5"',
|
||||
' ng-style="{ \'background-color\': $ctrl.service.$tags[tag][1], left: ($index * 3) + \'px\' }"><!-- tags --></div>',
|
||||
'<div class="sg-tile-content">',
|
||||
' <div class="sg-md-subhead">',
|
||||
' <div>',
|
||||
' <span class="sg-label-outline ng-hide"><!-- mailbox --></span>',
|
||||
' <md-icon class="ng-hide">error</md-icon>', // the priority icon
|
||||
' <span><!-- sender or recipient --></span>',
|
||||
' </div>',
|
||||
' <div class="sg-tile-date"><!-- date --></div>',
|
||||
' </div>',
|
||||
' <div class="sg-md-body">',
|
||||
' <div class="sg-tile-subject"><!-- subject --></div>',
|
||||
' <div class="sg-tile-size"><!-- size --></div>',
|
||||
' </div>',
|
||||
'</div>',
|
||||
'<div class="sg-tile-icons">',
|
||||
' <md-icon class="ng-hide">star</md-icon>',
|
||||
' <md-icon class="ng-hide">reply</md-icon>',
|
||||
' <md-icon class="ng-hide">forward</md-icon>',
|
||||
' <md-icon class="ng-hide">attach_file</md-icon>',
|
||||
'</div>',
|
||||
'<div class="sg-progress-linear-bottom">',
|
||||
' <md-progress-linear class="md-accent"',
|
||||
' md-mode="indeterminate"',
|
||||
' ng-disabled="!$ctrl.message.$isLoading()"><!-- message loading progress --></md-progress-linear>',
|
||||
'</div>'
|
||||
].join(''),
|
||||
link: postLink,
|
||||
controller: 'sgMessageListItemMainController',
|
||||
controllerAs: '$ctrl'
|
||||
};
|
||||
|
||||
function postLink(scope, element, attrs, parentController) {
|
||||
scope.parentController = parentController;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
sgMessageListItemMainController.$inject = ['$scope', '$element', '$parse', '$state', '$mdToast', 'Mailbox', 'Message', 'encodeUriFilter'];
|
||||
function sgMessageListItemMainController($scope, $element, $parse, $state, $mdToast, Mailbox, Message, encodeUriFilter) {
|
||||
var $ctrl = this;
|
||||
|
||||
this.$postLink = function () {
|
||||
var contentDivElement, iconsDivElement;
|
||||
var parentControllerOnUpdate, setVisibility;
|
||||
|
||||
this.parentController = $scope.parentController;
|
||||
|
||||
parentControllerOnUpdate = this.parentController.onUpdate;
|
||||
setVisibility = this.parentController.setVisibility;
|
||||
|
||||
_.forEach($element.find('div'), function(div) {
|
||||
if (div.classList.contains('sg-tile-content'))
|
||||
contentDivElement = angular.element(div);
|
||||
else if (div.classList.contains('sg-tile-icons'))
|
||||
iconsDivElement = angular.element(div);
|
||||
});
|
||||
|
||||
this.priorityIconElement = contentDivElement.find('md-icon')[0];
|
||||
|
||||
if (Mailbox.$virtualMode) {
|
||||
// Show mailbox name in front of the subject
|
||||
this.mailboxNameElement = contentDivElement.find('span')[0];
|
||||
this.mailboxNameElement.classList.remove('ng-hide');
|
||||
}
|
||||
|
||||
this.senderElement = contentDivElement.find('span')[1];
|
||||
|
||||
_.forEach(contentDivElement.find('div'), function(div) {
|
||||
if (div.classList.contains('sg-tile-subject'))
|
||||
$ctrl.subjectElement = div;
|
||||
else if (div.classList.contains('sg-tile-size'))
|
||||
$ctrl.sizeElement = div;
|
||||
else if (div.classList.contains('sg-tile-date'))
|
||||
$ctrl.dateElement = div;
|
||||
});
|
||||
|
||||
_.forEach(iconsDivElement.find('md-icon'), function(div) {
|
||||
if (div.textContent == 'star')
|
||||
$ctrl.flagIconElement = div;
|
||||
else if (div.textContent == 'reply')
|
||||
$ctrl.answerIconElement = div;
|
||||
else if (div.textContent == 'forward')
|
||||
$ctrl.forwardIconElement = div;
|
||||
else if (div.textContent == 'attach_file')
|
||||
$ctrl.attachmentIconElement = div;
|
||||
});
|
||||
|
||||
/**
|
||||
* Update the template when the parent controller has detected a change.
|
||||
*/
|
||||
this.parentController.onUpdate = function () {
|
||||
var i;
|
||||
$ctrl.message = $ctrl.parentController.message;
|
||||
console.debug('onUpdate ' + $ctrl.message.uid);
|
||||
|
||||
// Flags
|
||||
for (i = 0; i < $ctrl.message.flags && i < 5; i++) {
|
||||
var tag = $ctrl.message.flags[i];
|
||||
var flagElement = angular.element('<div class="sg-category"></div>');
|
||||
flagElement.css('left', (i*3) + 'px');
|
||||
flagElement.css('background-color', $ctrl.service.$tags[tag][1]);
|
||||
$element.prepend(flagElement);
|
||||
}
|
||||
|
||||
// Mailbox name when in virtual mode
|
||||
if ($ctrl.mailboxNameElement)
|
||||
$ctrl.mailboxNameElement.innerHTML = $ctrl.message.$mailbox.$displayName;
|
||||
|
||||
// Sender or recipient when in
|
||||
if ($ctrl.MailboxService.selectedFolder.type == 'sent')
|
||||
$ctrl.senderElement.innerHTML = $ctrl.message.$shortAddress('to').encodeEntities();
|
||||
else
|
||||
$ctrl.senderElement.innerHTML = $ctrl.message.$shortAddress('from').encodeEntities();
|
||||
|
||||
// Priority icon
|
||||
if ($ctrl.message.priority && $ctrl.message.priority.level < 3) {
|
||||
$ctrl.priorityIconElement.classList.remove('ng-hide');
|
||||
if ($ctrl.message.priority.level < 2)
|
||||
$ctrl.priorityIconElement.classList.add('md-warn');
|
||||
else
|
||||
$ctrl.priorityIconElement.classList.remove('md-warn');
|
||||
}
|
||||
else
|
||||
$ctrl.priorityIconElement.classList.add('ng-hide');
|
||||
|
||||
// Subject
|
||||
$ctrl.subjectElement.innerHTML = $ctrl.message.subject.encodeEntities();
|
||||
|
||||
// Message size
|
||||
$ctrl.sizeElement.innerHTML = $ctrl.message.size;
|
||||
|
||||
// Received Date
|
||||
$ctrl.dateElement.innerHTML = $ctrl.message.relativedate;
|
||||
|
||||
setVisibility($ctrl.flagIconElement,
|
||||
$ctrl.message.isflagged);
|
||||
setVisibility($ctrl.answerIconElement,
|
||||
$ctrl.message.isanswered);
|
||||
setVisibility($ctrl.forwardIconElement,
|
||||
$ctrl.message.isforwarded);
|
||||
setVisibility($ctrl.attachmentIconElement,
|
||||
$ctrl.message.hasattachment);
|
||||
|
||||
// Call original method on parent controller
|
||||
angular.bind($ctrl.parentController, parentControllerOnUpdate)();
|
||||
};
|
||||
|
||||
this.service = Message;
|
||||
this.MailboxService = Mailbox;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
angular
|
||||
.module('SOGo.MailerUI')
|
||||
.controller('sgMessageListItemMainController', sgMessageListItemMainController)
|
||||
.directive('sgMessageListItemMain', sgMessageListItemMain);
|
||||
})();
|
||||
@@ -1,5 +1,9 @@
|
||||
/// MailerUI.scss -*- Mode: scss; indent-tabs-mode: nil; basic-offset: 2 -*-
|
||||
|
||||
.sg-mailbox-list-item:not(.sg-selected) .md-menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.view-list {
|
||||
// Overwrite style from list.scss to make some place for .sg-tile-icons
|
||||
md-list-item._md-button-wrap > div.md-button:first-child {
|
||||
@@ -83,7 +87,7 @@ md-sidenav {
|
||||
color: rgba(0,0,0,0.54);
|
||||
font-family: 'Material Icons';
|
||||
font-size: 24px;
|
||||
content: "\e2c7";
|
||||
content: "\e2c7"; // folder
|
||||
top: -4px;
|
||||
left: 0px;
|
||||
width: 1em;
|
||||
@@ -94,7 +98,7 @@ md-sidenav {
|
||||
}
|
||||
&.md-checked {
|
||||
.md-container:after {
|
||||
content: "\e2c8";
|
||||
content: "\e2c8"; // folder open
|
||||
}
|
||||
.md-icon {
|
||||
background-color: initial !important;
|
||||
|
||||
Reference in New Issue
Block a user