Prevent a very long image name from breaking the UI (#479)

This PR introduces two changes to mitigate this problem and overall
provide a better UX:

- Show ellipses in the middle of the image name in the first step if
needed.

- Add a tooltip below the image selection label in the first step to
show a little modal displaying the full path to the image.

Fixes: https://github.com/resin-io/etcher/issues/418
Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
This commit is contained in:
Juan Cruz Viotti 2016-06-15 10:31:07 -04:00 committed by GitHub
parent 34ab982b24
commit 8aa7bcd952
10 changed files with 258 additions and 3 deletions

View File

@ -1254,7 +1254,7 @@ mark,
.text-right, .section-header {
text-align: right; }
.text-center, .alert, .alert-ribbon, .update-notifier-modal-body__content, .section-footer {
.text-center, .alert, .alert-ribbon, .update-notifier-modal-body__content, .modal-tooltip-modal .modal-body, .section-footer {
text-align: center; }
.text-justify {
@ -6454,6 +6454,49 @@ button.btn:focus, button.progress-button:focus {
.component-drive-selector-body .list-group-item[disabled] .list-group-item-heading {
color: #aaaaaa; }
/*
* 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-tooltip-modal {
max-width: 50%; }
.modal-tooltip-modal .modal-header {
border: none; }
.modal-tooltip-modal .modal-header .close {
position: absolute;
right: -9px;
top: -8px;
background-color: #333333;
color: #eeeeee;
opacity: 1;
font-weight: 200;
font-size: 150%;
padding: 0px 5px 3px;
text-shadow: none;
margin: 0;
border-radius: 50%; }
.modal-tooltip-modal .modal-content {
height: auto;
border-radius: 3px; }
.modal-tooltip-modal .modal-body {
margin: 0px 15px 15px;
color: #222222;
background-color: #eeeeee;
padding: 8px;
overflow: hidden;
word-wrap: break-word; }
/*
* Copyright 2016 Resin.io
*
@ -6558,6 +6601,12 @@ body {
.step-border-right {
right: -120px; }
.step-tooltip {
display: block;
margin: -5px auto -20px;
color: #85898c;
font-size: 10px; }
.step-footer {
margin-top: 10px;
margin-bottom: -40px;

View File

@ -27,6 +27,7 @@ const app = angular.module('Etcher', [
require('angular-ui-router'),
require('angular-ui-bootstrap'),
require('angular-moment'),
require('angular-middle-ellipses'),
// Etcher modules
require('./modules/drive-scanner'),
@ -44,6 +45,7 @@ const app = angular.module('Etcher', [
require('./components/drive-selector/drive-selector'),
require('./components/svg-icon/svg-icon'),
require('./components/update-notifier/update-notifier'),
require('./components/tooltip-modal/tooltip-modal'),
// Pages
require('./pages/finish/finish'),
@ -92,6 +94,7 @@ app.controller('AppController', function(
AnalyticsService,
DriveSelectorService,
UpdateNotifierService,
TooltipModalService,
OSWindowProgressService,
OSNotificationService,
OSDialogService
@ -102,6 +105,7 @@ app.controller('AppController', function(
this.drives = DrivesModel;
this.writer = ImageWriterService;
this.settings = SettingsModel.data;
this.tooltipModal = TooltipModalService;
this.success = true;
if (UpdateNotifierService.shouldCheckForUpdates()) {

View File

@ -0,0 +1,40 @@
/*
* 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, tooltipData) {
/**
* @summary Tooltip data
* @property
* @public
*/
this.data = tooltipData;
/**
* @summary Close the modal
* @function
* @public
*
* @example
* TooltipModalController.closeModal();
*/
this.closeModal = function() {
return $uibModalInstance.dismiss();
};
};

View File

@ -0,0 +1,51 @@
/*
* 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($uibModal) {
/**
* @summary Open the tooltip modal
* @function
* @public
*
* @param {Object} options - tooltip options
* @param {String} options.title - tooltip title
* @param {String} options.message - tooltip message
* @returns {Promise}
*
* @example
* TooltipModalService.show({
* title: 'Important tooltip',
* message: 'Tooltip contents'
* });
*/
this.show = function(options) {
return $uibModal.open({
animation: true,
templateUrl: './components/tooltip-modal/templates/tooltip-modal.tpl.html',
controller: 'TooltipModalController as modal',
size: 'tooltip-modal',
resolve: {
tooltipData: function() {
return options;
}
}
}).result;
};
};

View File

@ -0,0 +1,58 @@
/*
* 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-tooltip-modal {
max-width: 50%;
.modal-header {
border: none;
.close {
position: absolute;
$modal-tooltip-close-position: 8px;
right: -($modal-tooltip-close-position + 1px);
top: -$modal-tooltip-close-position;
background-color: $gray-dark;
color: $gray-lighter;
opacity: 1;
font-weight: 200;
font-size: 150%;
padding: 0px 5px 3px;
text-shadow: none;
margin: 0;
border-radius: 50%;
}
}
.modal-content {
height: auto;
border-radius: 3px;
}
.modal-body {
@extend .text-center;
margin: 0px 15px 15px;
color: $gray-darker;
background-color: $gray-lighter;
padding: 8px;
overflow: hidden;
word-wrap: break-word;
}
}

View File

@ -0,0 +1,6 @@
<div class="modal-header">
<button class="close" ng-click="modal.closeModal()">&times;</button>
<h4 class="modal-title">{{ ::modal.data.title }}</h4>
</div>
<div class="modal-body">{{ ::modal.data.message }}</div>

View File

@ -0,0 +1,32 @@
/*
* 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.TooltipModal
*/
const angular = require('angular');
const MODULE_NAME = 'Etcher.Components.TooltipModal';
const TooltipModal = angular.module(MODULE_NAME, [
require('angular-ui-bootstrap')
]);
TooltipModal.controller('TooltipModalController', require('./controllers/tooltip-modal'));
TooltipModal.service('TooltipModalService', require('./services/tooltip-modal'));
module.exports = MODULE_NAME;

View File

@ -15,8 +15,14 @@
uib-tooltip="{{ app.formats.getCompressedExtensions().join(', ') }}">compressed images</span>
</p>
</div>
<div ng-show="app.selection.hasImage()">
<div ng-bind="app.selection.getImagePath() | basename"></div>
<div ng-if="app.selection.hasImage()">
<div ng-bind="app.selection.getImagePath() | basename | middleEllipses:25"></div>
<button class="btn btn-link step-tooltip"
ng-click="app.tooltipModal.show({
title: 'IMAGE FILE NAME',
message: app.selection.getImagePath()
})">SHOW IN FULL</button>
<button class="btn btn-link step-footer"
ng-click="app.reselectImage()"

View File

@ -48,6 +48,7 @@ $alert-padding: 13px;
@import "../components/progress-button/styles/progress-button";
@import "../components/svg-icon/styles/svg-icon";
@import "../components/drive-selector/styles/drive-selector";
@import "../components/tooltip-modal/styles/tooltip-modal";
@import "../pages/settings/styles/settings";
@import "../pages/finish/styles/finish";
@ -134,6 +135,13 @@ body {
right: -120px;
}
.step-tooltip {
display: block;
margin: -5px auto -20px;
color: lighten($color-disabled, 5%);
font-size: 10px;
}
.step-footer {
margin-top: 10px;
margin-bottom: -40px;

View File

@ -50,6 +50,7 @@
},
"dependencies": {
"angular": "^1.5.3",
"angular-middle-ellipses": "^1.0.0",
"angular-moment": "^1.0.0-beta.6",
"angular-q-promisify": "^1.1.0",
"angular-ui-bootstrap": "^1.3.2",