Improve display of mail advanced search

This commit is contained in:
Francis Lachapelle
2015-09-14 21:35:34 -04:00
parent 92bf494973
commit c464791d92
10 changed files with 198 additions and 135 deletions
@@ -43,6 +43,18 @@
"Copy To" = "Copy To";
"Add to:" = "Add to:";
/* Subheader of empty addressbook */
"No contact" = "No contact";
/* Number of contacts in addressbook; string is prefixed by number */
"contacts" = "contacts";
/* No contact matching search criteria */
"No matching contact" = "No matching contact";
/* Number of contacts matching search criteria; string is prefixed by number */
"matching contacts" = "matching contacts";
/* Number of selected contacts in list */
"selected" = "selected";
@@ -258,7 +258,7 @@
<md-icon>arrow_back</md-icon>
</md-button>
<md-input-container>
<input name="folderSearch" type="search" />
<input name="folderSearch" type="search" ng-minlength="3"/>
</md-input-container>
<md-input-container>
<md-select>
@@ -327,10 +327,22 @@
</md-toolbar>
<md-content id="contactsList" layout="column" class="md-flex">
<md-subheader>
<md-subheader ng-show="addressbook.service.$query.value">
<span ng-switch="addressbook.selectedFolder.cards.length">
<span ng-switch-when="0"><var:string label:value="No contact"/></span>
<span ng-switch-default="true">{{addressbook.selectedFolder.cards.length}} <var:string label:value="contacts"/></span>
<span ng-switch-when="0"><var:string label:value="No matching contact"/></span>
<span ng-switch-default="true">{{addressbook.selectedFolder.cards.length}} <var:string label:value="matching contacts"/></span>
</span>
</md-subheader>
<md-subheader ng-hide="addressbook.service.$query.value"
ng-switch="addressbook.selectedFolder.isRemote">
<span ng-switch-when="1">
<var:string label:value="Start a search to browse this address book"/>
</span>
<span ng-switch-default="true">
<span ng-switch="addressbook.selectedFolder.cards.length">
<span ng-switch-when="0"><var:string label:value="No contact"/></span>
<span ng-switch-default="true">{{addressbook.selectedFolder.cards.length}} <var:string label:value="contacts"/></span>
</span>
</span>
</md-subheader>
<md-virtual-repeat-container class="md-flex">
@@ -7,6 +7,56 @@
<!-- in virtual mailbox mode -->
<md-toolbar ng-hide="!app.showingAdvancedSearch || mailbox.selectedFolder.$selectedCount() > 0">
<div class="md-toolbar-tools">
<md-input-container>
<label><var:string label:value="Search messages in"/></label>
<md-select ng-model="app.search.mailbox">
<md-option ng-value="">
<span>{{app.accounts[0].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.name}}</span>
</md-option>
</md-select>
</md-input-container>
<md-menu>
<md-button class="sg-icon-button" label:aria-label="More search options" ng-click="$mdOpenMenu()">
<md-icon>settings</md-icon>
</md-button>
<md-menu-content>
<md-menu-item>
<md-button ng-href="#">
<md-checkbox ng-model="app.search.subfolders"
ng-true-value="1"
ng-false-value="0">
<var:string label:value="Search subfolders"/>
</md-checkbox>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button ng-click="app.search.match='AND'">
<md-icon ng-class="{ 'icon-check': app.search.match == 'AND'}">
<!-- 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'}">
<!-- any --></md-icon><var:string label:value="Match any of the following"/>
</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
<md-button class="sg-icon-button"
ng-click="app.toggleAdvancedSearch()"
ng-disabled="app.search.params.length == 0">
<md-icon ng-class="{'icon-stop': app.service.selectedFolder.$isLoading,
'icon-search': !app.service.selectedFolder.$isLoading}"><!-- icon --></md-icon>
</md-button>
</div>
</md-toolbar>
<!-- single-selection toolbars -->
<md-toolbar ng-hide="app.showingAdvancedSearch || mailbox.selectedFolder.$selectedCount() > 0">
@@ -72,7 +122,7 @@
<md-icon>arrow_back</md-icon>
</md-button>
<md-input-container>
<input name="folderSearch" type="search" />
<input name="folderSearch" type="search" ng-minlength="3"/>
</md-input-container>
<md-input-container>
<md-select>
@@ -176,7 +226,8 @@
<span class="msg-date"
ng-bind-html="currentMessage.relativedate"><!-- date --></span>
<div class="sg-md-subhead-multi">
<span ng-show="mailbox.service.$virtualMode">({{currentMessage.$mailbox.path}})</span>
<span class="sg-label-outline"
ng-show="mailbox.service.$virtualMode">{{currentMessage.$mailbox.name}}</span>
{{currentMessage.$shortAddress('from')}}
</div>
<div class="sg-md-body-multi">{{currentMessage.subject}}</div>
+45 -89
View File
@@ -351,100 +351,56 @@
</script>
<script type="text/ng-template" id="UIxMailFolderTemplate">
<md-toolbar layout="row" layout-align="space-between center" class="toolbar-main" ng-hide="app.showingAdvancedSearch">
<md-toolbar layout="row" layout-align="space-between center" class="toolbar-main"
ng-hide="app.showingAdvancedSearch">
<var:component className="UIxTopnavToolbarTemplate"/>
</md-toolbar>
<md-toolbar layout="row" layout-align="space-between center" class="toolbar-main" ng-show="app.showingAdvancedSearch">
<div class="sg-padded" layout="column">
<div layout="row" layout-align="space-between center">
<md-input-container>
<label><var:string label:value="Search messages in"/></label>
<md-select ng-model="app.search.mailbox">
<md-option ng-value="">
<span>{{app.accounts[0].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.name}}</span>
</md-option>
</md-select>
</md-input-container>
<md-menu>
<md-button class="sg-icon-button" label:aria-label="More search options" ng-click="$mdOpenMenu()">
<md-icon>settings</md-icon>
</md-button>
<md-menu-content>
<md-menu-item>
<md-button ng-href="#">
<md-checkbox ng-model="app.search.subfolders"
ng-true-value="1"
ng-false-value="0">
<var:string label:value="Search subfolders"/>
</md-checkbox>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button ng-click="app.search.match='AND'">
<md-icon ng-class="{ 'icon-check': app.search.match == 'AND'}">
<!-- 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'}">
<!-- any --></md-icon><var:string label:value="Match any of the following"/>
</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
<md-chips ng-model="app.search.params"
md-on-append="app.newSearchParam($chip)">
<input type="text" ng-disabled="app.currentSearchParam.length == 0" sg-placeholder="app.search.options[app.currentSearchParam]"/>
<md-chip-template>
<span class="md-caption" ng-show="$chip.negative == 0">(match</span>
<span class="md-caption" ng-show="$chip.negative == 1">(does not match</span>
<span class="md-caption">{{$chip.searchBy}})</span>
<span>{{$chip.searchInput}}</span>
</md-chip-template>
</md-chips>
</div>
<div layout="row" layout-align="space-between center">
<md-button type="button" ng-click="app.addSearchParam('subject')">
<var:string label:value="Subject"/>
</md-button>
<md-button type="button" ng-click="app.addSearchParam('from')">
<var:string label:value="From"/>
</md-button>
<md-button type="button" ng-click="app.addSearchParam('to')">
<var:string label:value="To"/>
</md-button>
<md-button type="button" ng-click="app.addSearchParam('cc')">
<var:string label:value="Cc"/>
</md-button>
<md-button type="button" ng-click="app.addSearchParam('body')">
<var:string label:value="Body"/>
</md-button>
<div class="md-flex"><!-- spacer --></div>
<md-button type="button" class="sg-button"
ng-disabled="app.search.params.length == 0"
ng-hide="app.service. selectedFolder.$isLoading"
ng-click="app.startAdvancedSearch()">
<md-icon>search</md-icon>
</md-button>
<md-button type="button" class="sg-button"
ng-show="app.service.selectedFolder.$isLoading"
ng-click="app.stopAdvancedSearch()">
<md-icon>stop</md-icon>
</md-button>
</div>
</div>
<div class="sg-toolbar-group-last">
<md-button type="button" class="sg-button" ng-click="app.hideAdvancedSearch()">
<!-- Advanced search toolbar -->
<md-toolbar layout="column" class="md-tall toolbar-main"
ng-show="app.showingAdvancedSearch">
<div class="md-toolbar-tools">
<md-chips class="md-flex"
ng-model="app.search.params"
md-on-append="app.newSearchParam($chip)">
<input sg-focus-on="advancedSearch" type="text"
ng-disabled="app.currentSearchParam.length == 0"
sg-placeholder="app.search.options[app.currentSearchParam]"/>
<md-chip-template>
<span class="md-caption" ng-show="$chip.negative == 0">(match</span>
<span class="md-caption" ng-show="$chip.negative == 1">(does not match</span>
<span class="md-caption">{{$chip.searchBy}})</span>
<span>{{$chip.searchInput}}</span>
</md-chip-template>
</md-chips>
<md-button type="button" class="sg-icon-button" ng-click="app.hideAdvancedSearch()">
<md-icon>close</md-icon>
</md-button>
</div>
<div class="md-toolbar-tools">
<div layout="column">
<div class="pseudo-input-container--compact">
<label class="pseudo-input-label"><var:string label:value="Add a Criteria"/></label>
</div>
<div layout="row">
<a class="sg-outline-button" href="#" ng-click="app.addSearchParam('subject')">
<var:string label:value="Subject"/>
</a>
<a class="sg-outline-button" href="#" ng-click="app.addSearchParam('from')">
<var:string label:value="From"/>
</a>
<a class="sg-outline-button" href="#" ng-click="app.addSearchParam('to')">
<var:string label:value="To"/>
</a>
<a class="sg-outline-button" href="#" ng-click="app.addSearchParam('cc')">
<var:string label:value="Cc"/>
</a>
<a class="sg-outline-button" href="#" ng-click="app.addSearchParam('body')">
<var:string label:value="Body"/>
</a>
</div>
</div>
</div>
</md-toolbar>
<div layout="row" class="md-flex">
@@ -89,11 +89,11 @@
// First session query
AddressBook.$cards = [];
}
else if (AddressBook.$query == search) {
else if (AddressBook.$query.value == search) {
// Query hasn't changed
return AddressBook.$q.when(AddressBook.$cards);
}
AddressBook.$query = search;
AddressBook.$query.value = search;
angular.extend(params, options);
@@ -125,6 +125,7 @@
AddressBook.$cards.splice(index, 0, card);
}
});
AddressBook.$log.debug(AddressBook.$cards);
return AddressBook.$cards;
});
};
@@ -12,6 +12,7 @@
AddressBook.selectedFolder = stateAddressbook;
vm.service = AddressBook;
vm.selectedFolder = stateAddressbook;
vm.selectCard = selectCard;
vm.toggleCardSelection = toggleCardSelection;
@@ -37,8 +37,7 @@
vm.newSearchParam = newSearchParam;
vm.showAdvancedSearch = showAdvancedSearch;
vm.hideAdvancedSearch = hideAdvancedSearch;
vm.startAdvancedSearch = startAdvancedSearch;
vm.stopAdvancedSearch = stopAdvancedSearch;
vm.toggleAdvancedSearch = toggleAdvancedSearch;
vm.search = {
options: {'': l('Select a criteria'),
subject: l('Enter Subject'),
@@ -67,49 +66,51 @@
$state.go('mail.account.mailbox', { accountId: account.id, mailboxId: encodeUriFilter(mailbox.path) });
}
function startAdvancedSearch() {
var root, mailboxes = [],
_visit = function(folders) {
_.each(folders, function(o) {
mailboxes.push(o);
if (o.children && o.children.length > 0) {
_visit(o.children);
}
});
};
vm.virtualMailbox = new VirtualMailbox(vm.accounts[0]);
// Don't set the previous selected mailbox if we're in virtual mode
// That allows users to do multiple advanced search but return
// correctly to the previously selected mailbox once done.
if (!Mailbox.$virtualMode)
vm.searchPreviousMailbox = Mailbox.selectedFolder;
Mailbox.selectedFolder = vm.virtualMailbox;
Mailbox.$virtualMode = true;
if (angular.isDefined(vm.search.mailbox)) {
root = vm.accounts[0].$getMailboxByPath(vm.search.mailbox);
mailboxes.push(root);
if (vm.search.subfolders && root.children.length)
_visit(root.children);
function toggleAdvancedSearch() {
if (Mailbox.selectedFolder.$isLoading) {
vm.virtualMailbox.stopSearch();
}
else {
mailboxes = vm.accounts[0].$flattenMailboxes();
var root, mailboxes = [],
_visit = function(folders) {
_.each(folders, function(o) {
mailboxes.push(o);
if (o.children && o.children.length > 0) {
_visit(o.children);
}
});
};
vm.virtualMailbox = new VirtualMailbox(vm.accounts[0]);
// Don't set the previous selected mailbox if we're in virtual mode
// That allows users to do multiple advanced search but return
// correctly to the previously selected mailbox once done.
if (!Mailbox.$virtualMode)
vm.searchPreviousMailbox = Mailbox.selectedFolder;
Mailbox.selectedFolder = vm.virtualMailbox;
Mailbox.$virtualMode = true;
if (angular.isDefined(vm.search.mailbox)) {
root = vm.accounts[0].$getMailboxByPath(vm.search.mailbox);
mailboxes.push(root);
if (vm.search.subfolders && root.children.length)
_visit(root.children);
}
else {
mailboxes = vm.accounts[0].$flattenMailboxes();
}
vm.virtualMailbox.setMailboxes(mailboxes);
vm.virtualMailbox.startSearch(vm.search.match, vm.search.params);
$state.go('mail.account.virtualMailbox', { accountId: vm.accounts[0].id });
}
vm.virtualMailbox.setMailboxes(mailboxes);
vm.virtualMailbox.startSearch(vm.search.match, vm.search.params);
$state.go('mail.account.virtualMailbox', { accountId: vm.accounts[0].id });
}
function stopAdvancedSearch() {
vm.virtualMailbox.stopSearch();
}
function addSearchParam(v) {
vm.currentSearchParam = v;
focus('advancedSearch');
}
function newSearchParam(v) {
@@ -129,3 +129,14 @@ md-list md-list-item button.md-button.sg-icon-button {
padding: 0;
font-size: $iconButton-menu-size;
}
.sg-outline-button {
border-width: 1px;
border-style: solid;
border-radius: $button-border-radius;
margin: rem(0.500);
padding: rem(0.500);
font-size: $sg-font-size-1;
font-weight: $sg-font-medium;
text-transform: uppercase;
}
@@ -108,12 +108,18 @@ md-icon {
&.icon-remove-circle:before {
content: "\e15c";
}
&.icon-search:before {
content: "\e8b6";
}
&.icon-star:before {
content: "\e838";
}
&.icon-star-border:before {
content: "\e83a";
}
&.icon-stop:before {
content: "\e047";
}
&.icon-visibility-off:before {
content: "\e8f5";
}
@@ -369,6 +369,18 @@ html p {
white-space: normal;
}
.sg-label-outline {
// See also .sg-outline-button in button.scss
border-width: 1px;
border-style: solid;
border-radius: 3px; // $button-border-radius
margin: 0;
padding: 0 rem(0.500);
font-size: $sg-font-size-1;
font-weight: $sg-font-medium;
text-transform: uppercase;
}
// Date bloc in use on the toolbar
// ----------------------------------------------------------------------------
$today-font-size: 72px; // Visualy adjusted