Bug 1076767 - Add a spinner to the Import Contacts button whilst importing. r=jaws

This commit is contained in:
Paolo Amadini 2014-11-11 14:07:11 +00:00
Родитель 6ff08403e2
Коммит a80080c80a
12 изменённых файлов: 104 добавлений и 32 удалений

Просмотреть файл

@ -417,6 +417,8 @@ loop.contacts = (function(_, mozL10n) {
}, },
render: function() { render: function() {
let cx = React.addons.classSet;
let viewForItem = item => { let viewForItem = item => {
return ContactDetail({key: item._guid, contact: item, return ContactDetail({key: item._guid, contact: item,
handleContactAction: this.handleContactAction}) handleContactAction: this.handleContactAction})
@ -444,7 +446,6 @@ loop.contacts = (function(_, mozL10n) {
} }
} }
// TODO: bug 1076767 - add a spinner whilst importing contacts.
return ( return (
React.DOM.div(null, React.DOM.div(null,
React.DOM.div({className: "content-area"}, React.DOM.div({className: "content-area"},
@ -453,7 +454,11 @@ loop.contacts = (function(_, mozL10n) {
? mozL10n.get("importing_contacts_progress_button") ? mozL10n.get("importing_contacts_progress_button")
: mozL10n.get("import_contacts_button"), : mozL10n.get("import_contacts_button"),
disabled: this.state.importBusy, disabled: this.state.importBusy,
onClick: this.handleImportButtonClick}), onClick: this.handleImportButtonClick},
React.DOM.div({className: cx({"contact-import-spinner": true,
spinner: true,
busy: this.state.importBusy})})
),
Button({caption: mozL10n.get("new_contact_button"), Button({caption: mozL10n.get("new_contact_button"),
onClick: this.handleAddContactButtonClick}) onClick: this.handleAddContactButtonClick})
), ),

Просмотреть файл

@ -417,6 +417,8 @@ loop.contacts = (function(_, mozL10n) {
}, },
render: function() { render: function() {
let cx = React.addons.classSet;
let viewForItem = item => { let viewForItem = item => {
return <ContactDetail key={item._guid} contact={item} return <ContactDetail key={item._guid} contact={item}
handleContactAction={this.handleContactAction} /> handleContactAction={this.handleContactAction} />
@ -444,7 +446,6 @@ loop.contacts = (function(_, mozL10n) {
} }
} }
// TODO: bug 1076767 - add a spinner whilst importing contacts.
return ( return (
<div> <div>
<div className="content-area"> <div className="content-area">
@ -453,7 +454,11 @@ loop.contacts = (function(_, mozL10n) {
? mozL10n.get("importing_contacts_progress_button") ? mozL10n.get("importing_contacts_progress_button")
: mozL10n.get("import_contacts_button")} : mozL10n.get("import_contacts_button")}
disabled={this.state.importBusy} disabled={this.state.importBusy}
onClick={this.handleImportButtonClick} /> onClick={this.handleImportButtonClick}>
<div className={cx({"contact-import-spinner": true,
spinner: true,
busy: this.state.importBusy})} />
</Button>
<Button caption={mozL10n.get("new_contact_button")} <Button caption={mozL10n.get("new_contact_button")}
onClick={this.handleAddContactButtonClick} /> onClick={this.handleAddContactButtonClick} />
</ButtonGroup> </ButtonGroup>

Просмотреть файл

@ -399,18 +399,21 @@ loop.panel = (function(_, mozL10n) {
// readOnly attr will suppress a warning regarding this issue // readOnly attr will suppress a warning regarding this issue
// from the react lib. // from the react lib.
var cx = React.addons.classSet; var cx = React.addons.classSet;
var inputCSSClass = cx({
"pending": this.state.pending,
// Used in functional testing, signals that
// call url was received from loop server
"callUrl": !this.state.pending
});
return ( return (
React.DOM.div({className: "generate-url"}, React.DOM.div({className: "generate-url"},
React.DOM.header(null, __("share_link_header_text")), React.DOM.header(null, __("share_link_header_text")),
React.DOM.div({className: "generate-url-stack"},
React.DOM.input({type: "url", value: this.state.callUrl, readOnly: "true", React.DOM.input({type: "url", value: this.state.callUrl, readOnly: "true",
onCopy: this.handleLinkExfiltration, onCopy: this.handleLinkExfiltration,
className: inputCSSClass}), className: cx({"generate-url-input": true,
pending: this.state.pending,
// Used in functional testing, signals that
// call url was received from loop server
callUrl: !this.state.pending})}),
React.DOM.div({className: cx({"generate-url-spinner": true,
spinner: true,
busy: this.state.pending})})
),
ButtonGroup({additionalClass: "url-actions"}, ButtonGroup({additionalClass: "url-actions"},
Button({additionalClass: "button-email", Button({additionalClass: "button-email",
disabled: !this.state.callUrl, disabled: !this.state.callUrl,

Просмотреть файл

@ -399,18 +399,21 @@ loop.panel = (function(_, mozL10n) {
// readOnly attr will suppress a warning regarding this issue // readOnly attr will suppress a warning regarding this issue
// from the react lib. // from the react lib.
var cx = React.addons.classSet; var cx = React.addons.classSet;
var inputCSSClass = cx({
"pending": this.state.pending,
// Used in functional testing, signals that
// call url was received from loop server
"callUrl": !this.state.pending
});
return ( return (
<div className="generate-url"> <div className="generate-url">
<header>{__("share_link_header_text")}</header> <header>{__("share_link_header_text")}</header>
<div className="generate-url-stack">
<input type="url" value={this.state.callUrl} readOnly="true" <input type="url" value={this.state.callUrl} readOnly="true"
onCopy={this.handleLinkExfiltration} onCopy={this.handleLinkExfiltration}
className={inputCSSClass} /> className={cx({"generate-url-input": true,
pending: this.state.pending,
// Used in functional testing, signals that
// call url was received from loop server
callUrl: !this.state.pending})} />
<div className={cx({"generate-url-spinner": true,
spinner: true,
busy: this.state.pending})} />
</div>
<ButtonGroup additionalClass="url-actions"> <ButtonGroup additionalClass="url-actions">
<Button additionalClass="button-email" <Button additionalClass="button-email"
disabled={!this.state.callUrl} disabled={!this.state.callUrl}

Просмотреть файл

@ -2,6 +2,16 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
.contact-import-spinner {
display: none;
}
.contact-import-spinner.busy {
display: inline-block;
vertical-align: middle;
-moz-margin-start: 10px;
}
.content-area input.contact-filter { .content-area input.contact-filter {
margin-top: 14px; margin-top: 14px;
border-radius: 10000px; border-radius: 10000px;

Просмотреть файл

@ -46,7 +46,7 @@ body {
flex: 1; flex: 1;
text-align: center; text-align: center;
color: #ccc; color: #ccc;
border-right: 1px solid #ccc; -moz-border-end: 1px solid #ccc;
padding: 0 10px; padding: 0 10px;
height: 16px; height: 16px;
cursor: pointer; cursor: pointer;
@ -56,7 +56,7 @@ body {
} }
.tab-view > li:last-child { .tab-view > li:last-child {
border-right-style: none; -moz-border-end-style: none;
} }
.tab-view > li[data-tab-name="call"], .tab-view > li[data-tab-name="call"],
@ -307,6 +307,10 @@ body {
font-size: 12px; font-size: 12px;
} }
.button > .button-caption {
vertical-align: middle;
}
.button:hover { .button:hover {
background-color: #ebebeb; background-color: #ebebeb;
} }
@ -372,10 +376,41 @@ body[dir=rtl] .dropdown-menu-item {
background-color: #eee; background-color: #eee;
} }
/* Spinner */
@keyframes spinnerRotate {
to { transform: rotate(360deg); }
}
.spinner {
width: 16px;
height: 16px;
background-repeat: no-repeat;
background-size: 16px 16px;
}
.spinner.busy {
background-image: url(../img/spinner.png);
animation-name: spinnerRotate;
animation-duration: 1s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@media (min-resolution: 2dppx) {
.spinner.busy {
background-image: url(../img/spinner@2x.png);
}
}
/* Share tab */ /* Share tab */
.generate-url input { .generate-url-stack {
margin: 14px 0; margin: 14px 0;
position: relative;
}
.generate-url-input {
outline: 0; outline: 0;
border: 1px solid #ccc; /* Overriding background style for a text input (see border: 1px solid #ccc; /* Overriding background style for a text input (see
below) resets its borders to a weird beveled style; below) resets its borders to a weird beveled style;
@ -386,10 +421,18 @@ body[dir=rtl] .dropdown-menu-item {
font-size: 1em; font-size: 1em;
} }
.generate-url input.pending { .generate-url-spinner {
background-image: url(../img/loading-icon.gif); position: absolute;
background-repeat: no-repeat; pointer-events: none;
background-position: right; z-index: 1;
top: 4px;
left: auto;
right: 4px;
}
body[dir=rtl] .generate-url-spinner {
left: 4px;
right: auto;
} }
.generate-url .button { .generate-url .button {

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 2.5 KiB

Двоичные данные
browser/components/loop/content/shared/img/spinner.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 724 B

Двоичные данные
browser/components/loop/content/shared/img/spinner@2x.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Просмотреть файл

@ -728,7 +728,8 @@ loop.shared.views = (function(_, OT, l10n) {
React.DOM.button({onClick: this.props.onClick, React.DOM.button({onClick: this.props.onClick,
disabled: this.props.disabled, disabled: this.props.disabled,
className: cx(classObject)}, className: cx(classObject)},
this.props.caption React.DOM.span({className: "button-caption"}, this.props.caption),
this.props.children
) )
) )
} }

Просмотреть файл

@ -728,7 +728,8 @@ loop.shared.views = (function(_, OT, l10n) {
<button onClick={this.props.onClick} <button onClick={this.props.onClick}
disabled={this.props.disabled} disabled={this.props.disabled}
className={cx(classObject)}> className={cx(classObject)}>
{this.props.caption} <span className="button-caption">{this.props.caption}</span>
{this.props.children}
</button> </button>
) )
} }

Просмотреть файл

@ -32,7 +32,8 @@ browser.jar:
content/browser/loop/shared/img/sad.png (content/shared/img/sad.png) content/browser/loop/shared/img/sad.png (content/shared/img/sad.png)
content/browser/loop/shared/img/icon_32.png (content/shared/img/icon_32.png) content/browser/loop/shared/img/icon_32.png (content/shared/img/icon_32.png)
content/browser/loop/shared/img/icon_64.png (content/shared/img/icon_64.png) content/browser/loop/shared/img/icon_64.png (content/shared/img/icon_64.png)
content/browser/loop/shared/img/loading-icon.gif (content/shared/img/loading-icon.gif) content/browser/loop/shared/img/spinner.png (content/shared/img/spinner.png)
content/browser/loop/shared/img/spinner@2x.png (content/shared/img/spinner@2x.png)
content/browser/loop/shared/img/audio-inverse-14x14.png (content/shared/img/audio-inverse-14x14.png) content/browser/loop/shared/img/audio-inverse-14x14.png (content/shared/img/audio-inverse-14x14.png)
content/browser/loop/shared/img/audio-inverse-14x14@2x.png (content/shared/img/audio-inverse-14x14@2x.png) content/browser/loop/shared/img/audio-inverse-14x14@2x.png (content/shared/img/audio-inverse-14x14@2x.png)
content/browser/loop/shared/img/facemute-14x14.png (content/shared/img/facemute-14x14.png) content/browser/loop/shared/img/facemute-14x14.png (content/shared/img/facemute-14x14.png)