mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-24 19:56:37 +00:00
Merge pull request #1921 from resin-io/link-to-windows-usbboot-drivers
feat(GUI): link to drivers when clicking a driverless usbboot device
This commit is contained in:
commit
408ab99774
32
lib/gui/app/components/confirm-modal/confirm-modal.js
Normal file
32
lib/gui/app/components/confirm-modal/confirm-modal.js
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2018 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.ConfirmModal
|
||||
*/
|
||||
|
||||
const angular = require('angular')
|
||||
const MODULE_NAME = 'Etcher.Components.ConfirmModal'
|
||||
const ConfirmModal = angular.module(MODULE_NAME, [
|
||||
require('../modal/modal')
|
||||
])
|
||||
|
||||
ConfirmModal.controller('ConfirmModalController', require('./controllers/confirm-modal'))
|
||||
ConfirmModal.service('ConfirmModalService', require('./services/confirm-modal'))
|
||||
|
||||
module.exports = MODULE_NAME
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2018 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, options) {
|
||||
/**
|
||||
* @summary Modal options
|
||||
* @type {Object}
|
||||
* @public
|
||||
*/
|
||||
this.options = options
|
||||
|
||||
/**
|
||||
* @summary Reject the warning prompt
|
||||
* @function
|
||||
* @public
|
||||
*
|
||||
* @example
|
||||
* WarningModalController.reject();
|
||||
*/
|
||||
this.reject = () => {
|
||||
$uibModalInstance.close(false)
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Accept the warning prompt
|
||||
* @function
|
||||
* @public
|
||||
*
|
||||
* @example
|
||||
* WarningModalController.accept();
|
||||
*/
|
||||
this.accept = () => {
|
||||
$uibModalInstance.close(true)
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2018 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 ($sce, ModalService) {
|
||||
/**
|
||||
* @summary show the confirm modal
|
||||
* @function
|
||||
* @public
|
||||
*
|
||||
* @param {Object} options - options
|
||||
* @param {String} options.description - danger message
|
||||
* @param {String} options.confirmationLabel - confirmation button text
|
||||
* @param {String} options.rejectionLabel - rejection button text
|
||||
* @fulfil {Boolean} - whether the user accepted or rejected the confirm
|
||||
* @returns {Promise}
|
||||
*
|
||||
* @example
|
||||
* ConfirmModalService.show({
|
||||
* description: 'Don\'t do this!',
|
||||
* confirmationLabel: 'Yes, continue!'
|
||||
* });
|
||||
*/
|
||||
this.show = (options = {}) => {
|
||||
options.description = $sce.trustAsHtml(options.description)
|
||||
return ModalService.open({
|
||||
name: 'confirm',
|
||||
template: require('../templates/confirm-modal.tpl.html'),
|
||||
controller: 'ConfirmModalController as modal',
|
||||
size: 'confirm-modal',
|
||||
resolve: {
|
||||
options: _.constant(options)
|
||||
}
|
||||
}).result
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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-confirm-modal .modal-content {
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
.modal-confirm-modal .modal-title .glyphicon {
|
||||
color: $palette-theme-danger-background;
|
||||
}
|
||||
|
||||
.modal-confirm-modal .modal-body {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">
|
||||
<span>{{ ::modal.options.title }}</span>
|
||||
</h4>
|
||||
<button class="close"
|
||||
tabindex="11"
|
||||
ng-click="modal.reject()">×</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<p>{{ ::modal.options.message }}</p>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<div class="modal-menu">
|
||||
<button ng-if="modal.options.rejectionLabel" class="button button-block"
|
||||
tabindex="12"
|
||||
ng-class="{
|
||||
'button-default': modal.options.cancelButton === 'default',
|
||||
'button-primary': modal.options.cancelButton === 'primary',
|
||||
'button-warning': modal.options.cancelButton === 'warning',
|
||||
'button-danger': modal.options.cancelButton === 'danger',
|
||||
}"
|
||||
ng-click="modal.reject()">{{ ::modal.options.rejectionLabel }}</button>
|
||||
<button class="button button-block"
|
||||
tabindex="13"
|
||||
ng-class="{
|
||||
'button-default': modal.options.confirmButton === 'default',
|
||||
'button-primary': modal.options.confirmButton === 'primary',
|
||||
'button-warning': modal.options.confirmButton === 'warning',
|
||||
'button-danger': modal.options.confirmButton === 'danger',
|
||||
}"
|
||||
ng-click="modal.accept()">{{ ::modal.options.confirmationLabel }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
const angular = require('angular')
|
||||
const _ = require('lodash')
|
||||
const Bluebird = require('bluebird')
|
||||
const constraints = require('../../../../../shared/drive-constraints')
|
||||
const analytics = require('../../../modules/analytics')
|
||||
const availableDrives = require('../../../../../shared/models/available-drives')
|
||||
@ -26,7 +27,9 @@ const utils = require('../../../../../shared/utils')
|
||||
|
||||
module.exports = function (
|
||||
$q,
|
||||
$uibModalInstance
|
||||
$uibModalInstance,
|
||||
ConfirmModalService,
|
||||
OSOpenExternalService
|
||||
) {
|
||||
/**
|
||||
* @summary The drive selector state
|
||||
@ -98,9 +101,51 @@ module.exports = function (
|
||||
|
||||
selectionState.toggleDrive(drive.device)
|
||||
}
|
||||
|
||||
return Bluebird.resolve()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Prompt the user to install missing usbboot drivers
|
||||
* @function
|
||||
* @public
|
||||
*
|
||||
* @param {Object} drive - drive
|
||||
* @returns {Promise} - resolved promise
|
||||
*
|
||||
* @example
|
||||
* DriveSelectorController.installMissingDrivers({
|
||||
* linkTitle: 'Go to example.com',
|
||||
* linkMessage: 'Examples are great, right?',
|
||||
* linkCTA: 'Call To Action',
|
||||
* link: 'https://example.com'
|
||||
* });
|
||||
*/
|
||||
this.installMissingDrivers = (drive) => {
|
||||
if (drive.link) {
|
||||
analytics.logEvent('Open driver link modal', {
|
||||
url: drive.link
|
||||
})
|
||||
|
||||
return ConfirmModalService.show({
|
||||
confirmationLabel: 'Yes, continue',
|
||||
rejectionLabel: 'Cancel',
|
||||
title: drive.linkTitle,
|
||||
confirmButton: 'primary',
|
||||
message: drive.linkMessage || `Etcher will open ${drive.link} in your browser`
|
||||
}).then((shouldContinue) => {
|
||||
if (shouldContinue) {
|
||||
OSOpenExternalService.open(drive.link)
|
||||
}
|
||||
}).catch((error) => {
|
||||
analytics.logException(error)
|
||||
})
|
||||
}
|
||||
|
||||
return Bluebird.resolve()
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Close the modal and resolve the selected drive
|
||||
* @function
|
||||
|
@ -24,7 +24,9 @@ const angular = require('angular')
|
||||
const MODULE_NAME = 'Etcher.Components.DriveSelector'
|
||||
const DriveSelector = angular.module(MODULE_NAME, [
|
||||
require('../modal/modal'),
|
||||
require('../../utils/byte-size/byte-size')
|
||||
require('../confirm-modal/confirm-modal'),
|
||||
require('../../utils/byte-size/byte-size'),
|
||||
require('../../os/open-external/open-external')
|
||||
])
|
||||
|
||||
DriveSelector.controller('DriveSelectorController', require('./controllers/drive-selector'))
|
||||
|
@ -23,7 +23,8 @@
|
||||
<span class="word-keep"
|
||||
ng-show="drive.size"> - {{ drive.size | closestUnit }}</span>
|
||||
</h4>
|
||||
<p class="list-group-item-text">{{ drive.displayName }}</p>
|
||||
<p class="list-group-item-text" ng-if="!drive.link">{{ drive.displayName }}</p>
|
||||
<p class="list-group-item-text" ng-if="drive.link">{{ drive.displayName }} - <b><a ng-click="modal.installMissingDrivers(drive)">{{ drive.linkCTA }}</a></b></p>
|
||||
|
||||
<footer class="list-group-item-footer">
|
||||
|
||||
|
@ -273,6 +273,14 @@ class USBBootAdapter extends EventEmitter {
|
||||
disabled: true,
|
||||
icon: 'warning',
|
||||
size: null,
|
||||
link: 'https://www.raspberrypi.org/documentation/hardware/computemodule/cm-emmc-flashing.md',
|
||||
linkCTA: 'Install',
|
||||
linkTitle: 'Install missing drivers',
|
||||
linkMessage: [
|
||||
'Would you like to download the necessary drivers from the Raspberry Pi Foundation?',
|
||||
'This will open your browser.\n\n',
|
||||
'Once opened, download and run the installer from the "Windows Installer" section to install the drivers.'
|
||||
].join(' '),
|
||||
adaptor: USBBootAdapter.id
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user