From 951b8de9fc76821cf3140bd7e75c2d57ee8def21 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Wed, 7 Sep 2016 12:40:51 -0700 Subject: [PATCH] refactor(GUI): replace the orange alert ribbon with a modal (#689) As a way to simplify the design and make more use of available components rather than creating specialised ones, we replaced the `.alert-ribbon` component, which consisted of an orange alert appearing at the top of the screen for when a validation failed, the drive ran out of space, or other issues, with a modal. This change allowed us to remove the "warning"-related colors from the theme palette. Signed-off-by: Juan Cruz Viotti --- build/css/main.css | 91 ++++++------------- .../controllers/flash-error-modal.js | 52 +++++++++++ .../flash-error-modal/flash-error-modal.js | 35 +++++++ .../services/flash-error-modal.js | 47 ++++++++++ .../styles/_flash-error-modal.scss | 19 ++++ .../templates/flash-error-modal.tpl.html | 17 ++++ lib/gui/pages/main/controllers/flash.js | 7 +- lib/gui/pages/main/controllers/main.js | 18 ---- lib/gui/pages/main/main.js | 1 + lib/gui/pages/main/templates/main.tpl.html | 31 +------ lib/gui/scss/components/_alert-ribbon.scss | 66 -------------- lib/gui/scss/components/_button.scss | 4 - lib/gui/scss/main.scss | 3 +- lib/gui/scss/modules/_theme.scss | 2 - 14 files changed, 205 insertions(+), 188 deletions(-) create mode 100644 lib/gui/components/flash-error-modal/controllers/flash-error-modal.js create mode 100644 lib/gui/components/flash-error-modal/flash-error-modal.js create mode 100644 lib/gui/components/flash-error-modal/services/flash-error-modal.js create mode 100644 lib/gui/components/flash-error-modal/styles/_flash-error-modal.scss create mode 100644 lib/gui/components/flash-error-modal/templates/flash-error-modal.tpl.html delete mode 100644 lib/gui/scss/components/_alert-ribbon.scss diff --git a/build/css/main.css b/build/css/main.css index 27dcd58d..c3a0ca6d 100644 --- a/build/css/main.css +++ b/build/css/main.css @@ -4460,25 +4460,25 @@ a.thumbnail:focus, a.thumbnail.active { border-color: #ddd; } -.alert, .alert-ribbon { - padding: 13px; +.alert { + padding: 15px; margin-bottom: 18px; border: 1px solid transparent; border-radius: 4px; } - .alert h4, .alert-ribbon h4 { + .alert h4 { margin-top: 0; color: inherit; } - .alert .alert-link, .alert-ribbon .alert-link { + .alert .alert-link { font-weight: bold; } - .alert > p, .alert-ribbon > p, - .alert > ul, .alert-ribbon > ul { + .alert > p, + .alert > ul { margin-bottom: 0; } - .alert > p + p, .alert-ribbon > p + p { + .alert > p + p { margin-top: 5px; } .alert-dismissable, .alert-dismissible { - padding-right: 33px; } + padding-right: 35px; } .alert-dismissable .close, .alert-dismissible .close { position: relative; @@ -6153,16 +6153,6 @@ body { background-color: #2d78d2; color: #fff; } -.button-warning, -.button-warning:focus { - background-color: #e99852; - color: #fff; - outline: none; } - -.button-warning:hover { - background-color: #e37d25; - color: #fff; } - .button-danger, .button-danger:focus { background-color: #d9534f; @@ -6209,53 +6199,6 @@ body { background-color: #d9534f; border-color: #d9534f; } -/* - * Copyright 2016 Resin.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -.alert-ribbon { - background-color: #e99852; - color: #fff; - border-color: #f7dbc3; - width: 60%; - position: fixed; - text-align: center; - left: 0; - right: 0; - margin: 0 auto; - border: 0; - border-radius: 2px; - border-top-left-radius: 0; - border-top-right-radius: 0; - top: -100%; - transition: top .5s; } - .alert-ribbon > .glyphicon:first-child, .alert-ribbon > .tick:first-child { - margin-right: 5px; } - .alert-ribbon > .glyphicon:last-child, .alert-ribbon > .tick:last-child { - margin-left: 5px; } - .alert-ribbon .button-link { - padding: 0; - font-size: inherit; - vertical-align: baseline; - border-radius: 0; - border-bottom: 1px solid; - border-color: #fff; - color: #fff; } - -.alert-ribbon--open { - top: 0; } - /* * Copyright 2016 Resin.io * @@ -6489,6 +6432,24 @@ body { background-color: #f2f2f2; word-wrap: break-word; } +/* + * Copyright 2016 Resin.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +.modal-flash-error-modal .modal-title .glyphicon, .modal-flash-error-modal .modal-title .tick { + color: #d9534f; } + /* * Copyright 2016 Resin.io * diff --git a/lib/gui/components/flash-error-modal/controllers/flash-error-modal.js b/lib/gui/components/flash-error-modal/controllers/flash-error-modal.js new file mode 100644 index 00000000..144e5862 --- /dev/null +++ b/lib/gui/components/flash-error-modal/controllers/flash-error-modal.js @@ -0,0 +1,52 @@ +/* + * Copyright 2016 Resin.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +module.exports = function( + $uibModalInstance, + SelectionStateModel, + FlashStateModel, + AnalyticsService, + flashErrorData +) { + + /** + * @summary Flash error data + * @property + * @public + */ + this.data = flashErrorData; + + /** + * @summary Retry flash process + * @function + * @public + * + * @example + * FlashErrorModalController.retry(); + */ + this.retry = () => { + SelectionStateModel.clear({ + preserveImage: true + }); + + FlashStateModel.resetState(); + AnalyticsService.logEvent('Restart after failure'); + $uibModalInstance.dismiss(); + }; + +}; diff --git a/lib/gui/components/flash-error-modal/flash-error-modal.js b/lib/gui/components/flash-error-modal/flash-error-modal.js new file mode 100644 index 00000000..6e7318ad --- /dev/null +++ b/lib/gui/components/flash-error-modal/flash-error-modal.js @@ -0,0 +1,35 @@ +/* + * Copyright 2016 Resin.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +/** + * @module Etcher.Components.FlashErrorModal + */ + +const angular = require('angular'); +const MODULE_NAME = 'Etcher.Components.FlashErrorModal'; +const FlashErrorModal = angular.module(MODULE_NAME, [ + require('../modal/modal'), + require('../../models/selection-state'), + require('../../models/flash-state'), + require('../../modules/analytics') +]); + +FlashErrorModal.controller('FlashErrorModalController', require('./controllers/flash-error-modal')); +FlashErrorModal.service('FlashErrorModalService', require('./services/flash-error-modal')); + +module.exports = MODULE_NAME; diff --git a/lib/gui/components/flash-error-modal/services/flash-error-modal.js b/lib/gui/components/flash-error-modal/services/flash-error-modal.js new file mode 100644 index 00000000..cd17ec54 --- /dev/null +++ b/lib/gui/components/flash-error-modal/services/flash-error-modal.js @@ -0,0 +1,47 @@ +/* + * Copyright 2016 Resin.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const _ = require('lodash'); + +module.exports = function(ModalService) { + + /** + * @summary Open the flash error modal + * @function + * @public + * + * @param {String} message - flash error message + * @returns {Promise} + * + * @example + * FlashErrorModalService.show('The drive is not large enough!'); + */ + this.show = (message) => { + return ModalService.open({ + template: './components/flash-error-modal/templates/flash-error-modal.tpl.html', + controller: 'FlashErrorModalController as modal', + size: 'flash-error-modal', + resolve: { + flashErrorData: _.constant({ + message: message + }) + } + }).result; + }; + +}; diff --git a/lib/gui/components/flash-error-modal/styles/_flash-error-modal.scss b/lib/gui/components/flash-error-modal/styles/_flash-error-modal.scss new file mode 100644 index 00000000..6b742deb --- /dev/null +++ b/lib/gui/components/flash-error-modal/styles/_flash-error-modal.scss @@ -0,0 +1,19 @@ +/* + * Copyright 2016 Resin.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.modal-flash-error-modal .modal-title .glyphicon { + color: $palette-theme-danger-background; +} diff --git a/lib/gui/components/flash-error-modal/templates/flash-error-modal.tpl.html b/lib/gui/components/flash-error-modal/templates/flash-error-modal.tpl.html new file mode 100644 index 00000000..a31a206b --- /dev/null +++ b/lib/gui/components/flash-error-modal/templates/flash-error-modal.tpl.html @@ -0,0 +1,17 @@ + + + + + diff --git a/lib/gui/pages/main/controllers/flash.js b/lib/gui/pages/main/controllers/flash.js index 0c135628..24d613cb 100644 --- a/lib/gui/pages/main/controllers/flash.js +++ b/lib/gui/pages/main/controllers/flash.js @@ -23,6 +23,7 @@ module.exports = function( DriveScannerService, ImageWriterService, AnalyticsService, + FlashErrorModalService, ErrorService, OSNotificationService, OSWindowProgressService @@ -72,10 +73,14 @@ module.exports = function( OSNotificationService.send('Oops!', 'Looks like your flash has failed'); if (error.code === 'EVALIDATION') { + FlashErrorModalService.show('Your removable drive may be corrupted. Try inserting a different one and try again.'); AnalyticsService.logEvent('Validation error'); + } else if (error.code === 'ENOSPC') { + FlashErrorModalService.show('Not enough space on the drive. Please insert larger one and try again.'); } else { - AnalyticsService.logEvent('Flash error'); + FlashErrorModalService.show('Oops, seems something went wrong.'); ErrorService.reportException(error); + AnalyticsService.logEvent('Flash error'); } }) diff --git a/lib/gui/pages/main/controllers/main.js b/lib/gui/pages/main/controllers/main.js index 97b4adfe..53c7daf3 100644 --- a/lib/gui/pages/main/controllers/main.js +++ b/lib/gui/pages/main/controllers/main.js @@ -21,7 +21,6 @@ module.exports = function( DrivesModel, FlashStateModel, SettingsModel, - AnalyticsService, TooltipModalService, OSOpenExternalService ) { @@ -34,23 +33,6 @@ module.exports = function( this.external = OSOpenExternalService; this.tooltipModal = TooltipModalService; - /** - * @summary Restart after failure - * @function - * @public - * - * @example - * MainController.restartAfterFailure(); - */ - this.restartAfterFailure = () => { - SelectionStateModel.clear({ - preserveImage: true - }); - - FlashStateModel.resetState(); - AnalyticsService.logEvent('Restart after failure'); - }; - /** * @summary Determine if the drive step should be disabled * @function diff --git a/lib/gui/pages/main/main.js b/lib/gui/pages/main/main.js index 995b7686..554641de 100644 --- a/lib/gui/pages/main/main.js +++ b/lib/gui/pages/main/main.js @@ -33,6 +33,7 @@ const MainPage = angular.module(MODULE_NAME, [ require('../../components/drive-selector/drive-selector'), require('../../components/tooltip-modal/tooltip-modal'), + require('../../components/flash-error-modal/flash-error-modal'), require('../../components/progress-button/progress-button'), require('../../os/window-progress/window-progress'), diff --git a/lib/gui/pages/main/templates/main.tpl.html b/lib/gui/pages/main/templates/main.tpl.html index 60fc1aa1..ab7b0cd6 100644 --- a/lib/gui/pages/main/templates/main.tpl.html +++ b/lib/gui/pages/main/templates/main.tpl.html @@ -1,28 +1,4 @@
- -
- - - - Not enough space on the drive.
- Please insert larger one and - -
- - - Your removable drive may be corrupted. -
Try inserting a different one and - -
- - - Oops, seems something went wrong. - Click to retry - -
-
@@ -114,16 +90,11 @@ percentage="main.state.getFlashState().percentage" striped="{{ main.state.getFlashState().type == 'check' }}" ng-attr-active="{{ main.state.isFlashing() }}" - ng-show="!main.state.getLastFlashErrorCode()" ng-click="flash.flashImageToDrive(main.selection.getImagePath(), main.selection.getDrive())" - ng-disabled="main.shouldFlashStepBeDisabled()"> + ng-disabled="main.shouldFlashStepBeDisabled() || main.state.getLastFlashErrorCode()"> - -