Commit f25d6c05 authored by rbpotter's avatar rbpotter Committed by Commit Bot

Print Preview Componentization: Destinations Dialog additions

Add the recent destinations list and search box, and enable selection
of printers using the dialog.

Bug: 773928
Cq-Include-Trybots: master.tryserver.chromium.linux:closure_compilation
Change-Id: I157461a6a2ec5223e88b97067a4ddc8933f08ea8
Reviewed-on: https://chromium-review.googlesource.com/885502
Commit-Queue: Rebekah Potter <rbpotter@chromium.org>
Reviewed-by: default avatarDemetrios Papadopoulos <dpapad@chromium.org>
Cr-Commit-Position: refs/heads/master@{#532939}
parent 7b49ae6d
...@@ -65,7 +65,9 @@ ...@@ -65,7 +65,9 @@
settings="[[settings]]"></print-preview-header> settings="[[settings]]"></print-preview-header>
<div id="settings-sections"> <div id="settings-sections">
<print-preview-destination-settings destination="[[destination_]]" <print-preview-destination-settings destination="[[destination_]]"
destination-store="[[destinationStore_]]" user-info="[[userInfo_]]"> destination-store="[[destinationStore_]]"
recent-destinations="[[recentDestinations_]]"
user-info="[[userInfo_]]">
</print-preview-destination-settings> </print-preview-destination-settings>
<print-preview-pages-settings settings="{{settings}}" <print-preview-pages-settings settings="{{settings}}"
document-info="[[documentInfo_]]" document-info="[[documentInfo_]]"
......
...@@ -193,6 +193,14 @@ ...@@ -193,6 +193,14 @@
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'../compiled_resources2.gyp:native_layer', '../compiled_resources2.gyp:native_layer',
'../data/compiled_resources2.gyp:destination', '../data/compiled_resources2.gyp:destination',
'print_preview_search_box',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name': 'print_preview_search_box',
'dependencies': [
'<(DEPTH)/ui/webui/resources/cr_elements/cr_search_field/compiled_resources2.gyp:cr_search_field_behavior',
], ],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
}, },
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
<link rel="import" href="../data/destination_store.html"> <link rel="import" href="../data/destination_store.html">
<link rel="import" href="button_css.html"> <link rel="import" href="button_css.html">
<link rel="import" href="destination_list.html"> <link rel="import" href="destination_list.html">
<link rel="import" href="print_preview_search_box.html">
<link rel="import" href="print_preview_shared_css.html"> <link rel="import" href="print_preview_shared_css.html">
<dom-module id="print-preview-destination-dialog"> <dom-module id="print-preview-destination-dialog">
...@@ -32,6 +33,7 @@ ...@@ -32,6 +33,7 @@
box-shadow: 0 4px 23px 5px rgba(0, 0, 0, 0.2), box-shadow: 0 4px 23px 5px rgba(0, 0, 0, 0.2),
0 2px 6px rgba(0, 0, 0, 0.15); 0 2px 6px rgba(0, 0, 0, 0.15);
max-height: calc(100% - 40px);
width: 640px; width: 640px;
} }
...@@ -57,14 +59,26 @@ ...@@ -57,14 +59,26 @@
width: 24px; width: 24px;
} }
</style> </style>
<dialog is="cr-dialog" id="dialog"> <dialog is="cr-dialog" id="dialog" on-cancel="onCloseOrCancel_"
on-close="onCloseOrCancel_">
<div slot="title"> <div slot="title">
<span>$i18n{destinationSearchTitle}</span> <span>$i18n{destinationSearchTitle}</span>
</div> </div>
<div slot="body" scrollable> <div slot="body" scrollable>
<print-preview-search-box id="searchBox"
label="$i18n{searchBoxPlaceholder}" search-query="{{searchQuery_}}">
</print-preview-search-box>
<print-preview-destination-list
destinations="[[recentDestinationList_]]"
search-query="[[searchQuery_]]"
title="$i18n{recentDestinationsTitle}"
on-destination-selected="onDestinationSelected_">
</print-preview-destination-list>
<print-preview-destination-list destinations="[[destinations_]]" <print-preview-destination-list destinations="[[destinations_]]"
has-action-link=true loading-destinations="[[loadingDestinations_]]" has-action-link loading-destinations="[[loadingDestinations_]]"
title="$i18n{printDestinationsTitle}"> search-query="[[searchQuery_]]"
title="$i18n{printDestinationsTitle}"
on-destination-selected="onDestinationSelected_">
</print-preview-destination-list> </print-preview-destination-list>
</div> </div>
<div slot="button-container"> <div slot="button-container">
......
...@@ -15,7 +15,7 @@ Polymer({ ...@@ -15,7 +15,7 @@ Polymer({
/** @type {!print_preview.UserInfo} */ /** @type {!print_preview.UserInfo} */
userInfo: Object, userInfo: Object,
/** @private {Array<!print_preview.Destination>} */ /** @private {!Array<!print_preview.Destination>} */
destinations_: { destinations_: {
type: Array, type: Array,
notify: true, notify: true,
...@@ -27,6 +27,24 @@ Polymer({ ...@@ -27,6 +27,24 @@ Polymer({
type: Boolean, type: Boolean,
value: false, value: false,
}, },
/** @type {!Array<!print_preview.RecentDestination>} */
recentDestinations: Array,
/** @private {!Array<!print_preview.Destination>} */
recentDestinationList_: {
type: Array,
notify: true,
computed: 'computeRecentDestinationList_(' +
'destinationStore, recentDestinations, recentDestinations.*, ' +
'userInfo, destinations_.*)',
},
/** @private {?RegExp} */
searchQuery_: {
type: Object,
value: null,
},
}, },
/** @private {!EventTracker} */ /** @private {!EventTracker} */
...@@ -55,6 +73,25 @@ Polymer({ ...@@ -55,6 +73,25 @@ Polymer({
this.destinationStore.isPrintDestinationSearchInProgress; this.destinationStore.isPrintDestinationSearchInProgress;
}, },
/**
* @return {!Array<!print_preview.Destination>}
* @private
*/
computeRecentDestinationList_: function() {
let recentDestinations = [];
const filterAccount = this.userInfo.activeUser;
this.recentDestinations.forEach((recentDestination) => {
const destination = this.destinationStore.getDestination(
recentDestination.origin, recentDestination.id,
recentDestination.account || '');
if (destination &&
(!destination.account || destination.account == filterAccount)) {
recentDestinations.push(destination);
}
});
return recentDestinations;
},
/** /**
* @return {string} The cloud print promotion HTML. * @return {string} The cloud print promotion HTML.
* @private * @private
...@@ -64,11 +101,29 @@ Polymer({ ...@@ -64,11 +101,29 @@ Polymer({
'cloudPrintPromotion', '<a is="action-link" class="sign-in">', '</a>'); 'cloudPrintPromotion', '<a is="action-link" class="sign-in">', '</a>');
}, },
/** @private */
onCloseOrCancel_: function() {
if (this.searchQuery_)
this.$.searchBox.setValue('');
this.shadowRoot.querySelectorAll('print-preview-destination-list')
.forEach(list => list.reset());
},
/** @private */ /** @private */
onCancelButtonTap_: function() { onCancelButtonTap_: function() {
this.$.dialog.cancel(); this.$.dialog.cancel();
}, },
/**
* @param {!CustomEvent} e Event containing the selected destination.
* @private
*/
onDestinationSelected_: function(e) {
this.destinationStore.selectDestination(
/** @type {!print_preview.Destination} */ (e.detail));
this.$.dialog.close();
},
show: function() { show: function() {
this.loadingDestinations_ = this.loadingDestinations_ =
this.destinationStore.isPrintDestinationSearchInProgress; this.destinationStore.isPrintDestinationSearchInProgress;
......
...@@ -11,6 +11,11 @@ ...@@ -11,6 +11,11 @@
<dom-module id="print-preview-destination-list"> <dom-module id="print-preview-destination-list">
<template> <template>
<style include="print-preview-shared action-link cr-hidden-style throbber"> <style include="print-preview-shared action-link cr-hidden-style throbber">
:host {
padding: 0 14px 18px;
user-select: none;
}
:host > header { :host > header {
-webkit-padding-end: 19px; -webkit-padding-end: 19px;
-webkit-padding-start: 0; -webkit-padding-start: 0;
...@@ -64,7 +69,7 @@ ...@@ -64,7 +69,7 @@
padding: 0; padding: 0;
} }
:host .destination-list-item { :host .list-item {
-webkit-padding-end: 2px; -webkit-padding-end: 2px;
-webkit-padding-start: 18px; -webkit-padding-start: 18px;
cursor: default; cursor: default;
...@@ -73,22 +78,22 @@ ...@@ -73,22 +78,22 @@
padding-top: 3px; padding-top: 3px;
} }
:not(.moving).destination-list-item { :not(.moving).list-item {
transition: background-color 150ms; transition: background-color 150ms;
} }
.destination-list-item:hover, .list-item:hover,
.destination-list-item:focus { .list-item:focus {
background-color: rgb(228, 236, 247); background-color: rgb(228, 236, 247);
} }
.destination-list-item:focus { .list-item:focus {
outline: none; outline: none;
} }
.destination-list-item.stale :-webkit-any(.destination-list-item-icon, .list-item.stale :-webkit-any(.destination-list-item-icon,
.destination-list-item-name, .destination-list-item-name,
.connection-status) { .connection-status) {
opacity: 0.4; opacity: 0.4;
} }
...@@ -102,7 +107,8 @@ ...@@ -102,7 +107,8 @@
width: 24px; width: 24px;
} }
.destination-list-item-name { .destination-list-item-name,
.search-hint {
flex: 0 1 auto; flex: 0 1 auto;
line-height: 24px; line-height: 24px;
overflow: hidden; overflow: hidden;
...@@ -111,8 +117,14 @@ ...@@ -111,8 +117,14 @@
white-space: nowrap; white-space: nowrap;
} }
.destination-list-item .connection-status, .list-item .search-hint {
.destination-list-item .learn-more-link { -webkit-margin-start: 1em;
color: #999;
font-size: 75%;
}
.list-item .connection-status,
.list-item .learn-more-link {
-webkit-margin-start: 1em; -webkit-margin-start: 1em;
flex: 0 0 auto; flex: 0 0 auto;
font-size: 75%; font-size: 75%;
...@@ -120,7 +132,7 @@ ...@@ -120,7 +132,7 @@
vertical-align: middle; vertical-align: middle;
} }
.destination-list-item .learn-more-link { .list-item .learn-more-link {
color: rgb(51, 103, 214); color: rgb(51, 103, 214);
} }
...@@ -179,15 +191,15 @@ ...@@ -179,15 +191,15 @@
</div> </div>
</header> </header>
<ul> <ul>
<template is="dom-repeat" items="[[destinations]]"> <template is="dom-repeat" items="[[displayedDestinations_]]">
<li class$="destination-list-item <li class$="list-item [[getStaleCssClass_(item.isOfflineOrInvalid)]]"
[[getStaleCssClass_(item.isOfflineOrInvalid)]]" title="[[item.displayName]]"
hidden$="[[isDestinationHidden_(index, showAll_)]]"> hidden$="[[isDestinationHidden_(index, showAll_)]]"
<img class="destination-list-item-icon" alt="" on-tap="onDestinationSelected_">
<img class="destination-list-item-icon"
src="[[item.iconUrl]]" srcset="[[item.srcSet]]"> src="[[item.iconUrl]]" srcset="[[item.srcSet]]">
<span class="destination-list-item-name"> <span class="destination-list-item-name">[[item.displayName]]</span>
[[item.displayName]] <span class="search-hint">[[getSearchHint_(item, searchQuery)]]</span>
</span>
<span class="connection-status" <span class="connection-status"
hidden$="[[!item.isOfflineOrInvalid]]"> hidden$="[[!item.isOfflineOrInvalid]]">
[[item.connectionStatusText]] [[item.connectionStatusText]]
...@@ -227,7 +239,9 @@ ...@@ -227,7 +239,9 @@
<button class="show-all-button" on-tap="onShowAllTap_"> <button class="show-all-button" on-tap="onShowAllTap_">
$i18n{showAllButtonText} $i18n{showAllButtonText}
</button> </button>
<span class="total">[[totalDestinations_(destinations)]]</span> <span class="total">
[[i18n('destinationCount', displayedDestinations_.length)]]
</span>
</footer> </footer>
</template> </template>
<script src="destination_list.js"></script> <script src="destination_list.js"></script>
......
...@@ -18,10 +18,19 @@ Polymer({ ...@@ -18,10 +18,19 @@ Polymer({
destinations: Array, destinations: Array,
/** @type {boolean} */ /** @type {boolean} */
hasActionLink: Boolean, hasActionLink: {
type: Boolean,
value: false,
},
/** @type {boolean} */ /** @type {boolean} */
loadingDestinations: Boolean, loadingDestinations: {
type: Boolean,
value: false,
},
/** @type {?RegExp} */
searchQuery: Object,
/** @type {boolean} */ /** @type {boolean} */
title: String, title: String,
...@@ -32,25 +41,60 @@ Polymer({ ...@@ -32,25 +41,60 @@ Polymer({
value: false, value: false,
}, },
/** @private {!Array<!print_preview.Destination>} */
displayedDestinations_: {
type: Array,
computed: 'computeDisplayedDestinations_(destinations, searchQuery)',
},
/** @type {boolean} */ /** @type {boolean} */
footerHidden_: { footerHidden_: {
type: Boolean, type: Boolean,
computed: 'computeFooterHidden_(destinations, showAll_)', computed: 'computeFooterHidden_(displayedDestinations_, showAll_)',
}, },
/** @private {boolean} */ /** @private {boolean} */
hasDestinations_: { hasDestinations_: {
type: Boolean, type: Boolean,
computed: 'computeHasDestinations_(destinations)', computed: 'computeHasDestinations_(displayedDestinations_)',
}, },
}, },
/**
* @return {!Array<!print_preview.Destination>}
* @private
*/
computeDisplayedDestinations_: function() {
if (!this.searchQuery)
return assert(this.destinations);
return this.destinations.filter(destination => {
return destination.matches(assert(this.searchQuery));
});
},
/**
* @param {!print_preview.Destination} destination The destination to get the
* search hint for.
* @return {string} The property or properties matching the search query.
* @private
*/
getSearchHint_: function(destination) {
if (!this.searchQuery)
return '';
let hint = '';
destination.extraPropertiesToMatch.some(property => {
if (property.match(this.searchQuery))
hint += property;
});
return hint;
},
/** /**
* @return {boolean} * @return {boolean}
* @private * @private
*/ */
computeFooterHidden_: function() { computeFooterHidden_: function() {
return this.destinations.length < SHORT_DESTINATION_LIST_SIZE || return this.displayedDestinations_.length < SHORT_DESTINATION_LIST_SIZE ||
this.showAll_; this.showAll_;
}, },
...@@ -59,7 +103,7 @@ Polymer({ ...@@ -59,7 +103,7 @@ Polymer({
* @private * @private
*/ */
computeHasDestinations_: function() { computeHasDestinations_: function() {
return this.destinations.length != 0; return this.displayedDestinations_.length > 0;
}, },
/** /**
...@@ -81,11 +125,6 @@ Polymer({ ...@@ -81,11 +125,6 @@ Polymer({
return offlineOrInvalid ? 'stale' : ''; return offlineOrInvalid ? 'stale' : '';
}, },
/** @private string */
totalDestinations_: function() {
return this.i18n('destinationCount', this.destinations.length.toString());
},
/** @private */ /** @private */
onActionLinkTap_: function() { onActionLinkTap_: function() {
print_preview.NativeLayer.getInstance().managePrinters(); print_preview.NativeLayer.getInstance().managePrinters();
...@@ -95,5 +134,18 @@ Polymer({ ...@@ -95,5 +134,18 @@ Polymer({
onShowAllTap_: function() { onShowAllTap_: function() {
this.showAll_ = true; this.showAll_ = true;
}, },
/**
* @param {!Event} e Event containing the destination that was selected.
* @private
*/
onDestinationSelected_: function(e) {
this.fire(
'destination-selected', /** @type {!{model: Object}} */ (e).model.item);
},
reset: function() {
this.showAll_ = false;
},
}); });
})(); })();
...@@ -88,7 +88,9 @@ ...@@ -88,7 +88,9 @@
</print-preview-settings-section> </print-preview-settings-section>
<template is="cr-lazy-render" id="destinationDialog"> <template is="cr-lazy-render" id="destinationDialog">
<print-preview-destination-dialog <print-preview-destination-dialog
destination-store="[[destinationStore]]" user-info="[[userInfo]]"> destination-store="[[destinationStore]]"
recent-destinations="[[recentDestinations]]"
user-info="[[userInfo]]">
</print-preview-destination-dialog> </print-preview-destination-dialog>
</template> </template>
</template> </template>
......
...@@ -12,6 +12,9 @@ Polymer({ ...@@ -12,6 +12,9 @@ Polymer({
/** @type {?print_preview.DestinationStore} */ /** @type {?print_preview.DestinationStore} */
destinationStore: Object, destinationStore: Object,
/** @type {!Array<!print_preview.RecentDestination>} */
recentDestinations: Array,
/** @type {!print_preview.UserInfo} */ /** @type {!print_preview.UserInfo} */
userInfo: Object, userInfo: Object,
......
...@@ -371,8 +371,7 @@ Polymer({ ...@@ -371,8 +371,7 @@ Polymer({
this.recentDestinations.splice(indexFound, 1); this.recentDestinations.splice(indexFound, 1);
// Add the most recent destination // Add the most recent destination
this.recentDestinations.splice(0, 0, newDestination); this.splice('recentDestinations', 0, 0, newDestination);
this.notifyPath('recentDestinations');
// Persist sticky settings. // Persist sticky settings.
this.stickySettingsChanged_(); this.stickySettingsChanged_();
......
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_search_field/cr_search_field_behavior.html">
<link rel="import" href="print_preview_shared_css.html">
<dom-module id="print-preview-search-box">
<template>
<style include="print-preview-shared">
:host {
display: flex;
position: relative;
user-select: none;
}
.search-box-icon {
display: inline-block;
height: 1em;
left: 8px;
position: absolute;
right: 8px;
top: 6px;
user-select: none;
width: 1em;
}
.search-box-input {
text-indent: 2em;
width: 100%;
}
.search-box-input::-webkit-search-cancel-button {
-webkit-appearance: none;
}
</style>
<img src="../images/search.png" class="search-box-icon" alt="">
<input type="search" id="searchInput" class="search-box-input"
on-search="onSearchTermSearch" on-input="onSearchTermInput"
incremental aria-label$="[[label]]" placeholder="[[label]]">
</template>
<script src="print_preview_search_box.js"></script>
</dom-module>
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function() {
'use strict';
/** @type {!RegExp} */
const SANITIZE_REGEX = /[-[\]{}()*+?.,\\^$|#\s]/g;
Polymer({
is: 'print-preview-search-box',
behaviors: [CrSearchFieldBehavior],
properties: {
/** @type {?RegExp} */
searchQuery: {
type: Object,
notify: true,
},
},
listeners: {
'search-changed': 'onSearchChanged_',
},
/** @return {!HTMLInputElement} */
getSearchInput: function() {
return this.$.searchInput;
},
/**
* @param {!CustomEvent} e Event containing the new search.
*/
onSearchChanged_: function(e) {
const safeQuery = e.detail.trim().replace(SANITIZE_REGEX, '\\$&');
this.searchQuery =
safeQuery.length > 0 ? new RegExp(`(${safeQuery})`, 'ig') : null;
},
});
})();
...@@ -220,9 +220,7 @@ ...@@ -220,9 +220,7 @@
type="chrome_html" /> type="chrome_html" />
<structure name="IDR_PRINT_PREVIEW_NEW_DESTINATION_DIALOG_HTML" <structure name="IDR_PRINT_PREVIEW_NEW_DESTINATION_DIALOG_HTML"
file="new/destination_dialog.html" file="new/destination_dialog.html"
type="chrome_html" type="chrome_html" />
flattenhtml="true"
allowexternalscript="true" />
<structure name="IDR_PRINT_PREVIEW_NEW_DESTINATION_DIALOG_JS" <structure name="IDR_PRINT_PREVIEW_NEW_DESTINATION_DIALOG_JS"
file="new/destination_dialog.js" file="new/destination_dialog.js"
type="chrome_html" /> type="chrome_html" />
...@@ -233,6 +231,14 @@ ...@@ -233,6 +231,14 @@
<structure name="IDR_PRINT_PREVIEW_NEW_DESTINATION_LIST_JS" <structure name="IDR_PRINT_PREVIEW_NEW_DESTINATION_LIST_JS"
file="new/destination_list.js" file="new/destination_list.js"
type="chrome_html" /> type="chrome_html" />
<structure name="IDR_PRINT_PREVIEW_NEW_PRINT_PREVIEW_SEARCH_BOX_HTML"
file="new/print_preview_search_box.html"
type="chrome_html"
flattenhtml="true"
allowexternalscript="true" />
<structure name="IDR_PRINT_PREVIEW_NEW_PRINT_PREVIEW_SEARCH_BOX_JS"
file="new/print_preview_search_box.js"
type="chrome_html" />
<structure name="IDR_PRINT_PREVIEW_NEW_PRINT_PREVIEW_SHARED_CSS_HTML" <structure name="IDR_PRINT_PREVIEW_NEW_PRINT_PREVIEW_SHARED_CSS_HTML"
file="new/print_preview_shared_css.html" file="new/print_preview_shared_css.html"
type="chrome_html" type="chrome_html"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment