mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-25 12:16:37 +00:00
feat(GUI): env var toggle autoselecting all valid drives (#2306)
We introduce an environment variable `ETCHER_DISABLE_EXPLICIT_DRIVE_SELECTION` that both enables autoselection of drives and disables explicit drive selection by hiding the buttons allowing this. All valid drives are autoselected, i.e. any drive-image pair that does not result in an error, however warnings are accepted. Closes: https://github.com/resin-io/etcher/issues/2262 Change-Type: patch Changelog-Entry: Introduce env var to toggle autoselection of all drives.
This commit is contained in:
parent
f5fd2f2be3
commit
21cb7a4847
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
const _ = require('lodash')
|
const _ = require('lodash')
|
||||||
const angular = require('angular')
|
const angular = require('angular')
|
||||||
|
const prettyBytes = require('pretty-bytes')
|
||||||
const settings = require('../../../models/settings')
|
const settings = require('../../../models/settings')
|
||||||
const selectionState = require('../../../../../shared/models/selection-state')
|
const selectionState = require('../../../../../shared/models/selection-state')
|
||||||
const analytics = require('../../../modules/analytics')
|
const analytics = require('../../../modules/analytics')
|
||||||
@ -44,9 +45,35 @@ module.exports = function (DriveSelectorService) {
|
|||||||
return _.head(drives).description || 'Untitled Device'
|
return _.head(drives).description || 'Untitled Device'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-magic-numbers
|
||||||
|
if (drives.length === 0) {
|
||||||
|
return 'No targets found'
|
||||||
|
}
|
||||||
|
|
||||||
return `${drives.length} Devices`
|
return `${drives.length} Devices`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Get drive subtitle
|
||||||
|
* @function
|
||||||
|
* @public
|
||||||
|
*
|
||||||
|
* @returns {String} - drives subtitle
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* console.log(DriveSelectionController.getDrivesSubtitle())
|
||||||
|
* > '32 GB'
|
||||||
|
*/
|
||||||
|
this.getDrivesSubtitle = () => {
|
||||||
|
const drive = selectionState.getCurrentDrive()
|
||||||
|
|
||||||
|
if (drive) {
|
||||||
|
return prettyBytes(drive.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'Please insert at least one target device'
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Get drive list label
|
* @summary Get drive list label
|
||||||
* @function
|
* @function
|
||||||
@ -109,4 +136,18 @@ module.exports = function (DriveSelectorService) {
|
|||||||
* DriveSelectionController.getMemoizedSelectedDrives()
|
* DriveSelectionController.getMemoizedSelectedDrives()
|
||||||
*/
|
*/
|
||||||
this.getMemoizedSelectedDrives = utils.memoize(selectionState.getSelectedDrives, angular.equals)
|
this.getMemoizedSelectedDrives = utils.memoize(selectionState.getSelectedDrives, angular.equals)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Should the drive selection button be shown
|
||||||
|
* @function
|
||||||
|
* @public
|
||||||
|
*
|
||||||
|
* @returns {Boolean}
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* DriveSelectionController.shouldShowDrivesButton()
|
||||||
|
*/
|
||||||
|
this.shouldShowDrivesButton = () => {
|
||||||
|
return !process.env.ETCHER_DISABLE_EXPLICIT_DRIVE_SELECTION
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,10 @@ svg-icon > img[disabled] {
|
|||||||
color: $palette-theme-dark-disabled-foreground;
|
color: $palette-theme-dark-disabled-foreground;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.page-main .step-drive.text-warning {
|
||||||
|
color: $palette-theme-warning-background;
|
||||||
|
}
|
||||||
|
|
||||||
.page-main .relative {
|
.page-main .relative {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@ -123,8 +127,13 @@ svg-icon > img[disabled] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.page-main .step-name {
|
.page-main .step-name {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 39px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-right: 4.5px;
|
margin-right: 4.5px;
|
||||||
|
margin-bottom: 10px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: $palette-theme-primary-foreground;
|
color: $palette-theme-primary-foreground;
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-vertical-large">
|
<div class="space-vertical-large">
|
||||||
<div ng-if="!main.selection.hasDrive()">
|
<div ng-if="!main.selection.hasDrive() && drive.shouldShowDrivesButton()">
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<button class="button button-primary button-brick"
|
<button class="button button-primary button-brick"
|
||||||
@ -59,21 +59,24 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div ng-if="main.selection.hasDrive()">
|
<div ng-if="main.selection.hasDrive() || !drive.shouldShowDrivesButton()">
|
||||||
|
|
||||||
<div class="step-selection-text"
|
<div class="step-selection-text"
|
||||||
ng-class="{
|
ng-class="{
|
||||||
'text-disabled': main.shouldDriveStepBeDisabled()
|
'text-disabled': main.shouldDriveStepBeDisabled()
|
||||||
}">
|
}">
|
||||||
<span class="drive-step step-name"
|
<span class="step-drive step-name"
|
||||||
|
ng-class="{
|
||||||
|
'text-warning': !main.selection.getSelectedDevices().length
|
||||||
|
}"
|
||||||
uib-tooltip="{{ drive.getDriveListLabel() }}">
|
uib-tooltip="{{ drive.getDriveListLabel() }}">
|
||||||
<!-- middleEllipsis errors on undefined, therefore fallback to empty string -->
|
<!-- middleEllipsis errors on undefined, therefore fallback to empty string -->
|
||||||
{{ drive.getDrivesTitle() | middleEllipsis:20 }}
|
{{ drive.getDrivesTitle() | middleEllipsis:20 }}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
ng-if="main.selection.getSelectedDevices().length === 1"
|
ng-if="main.selection.getSelectedDevices().length <= 1"
|
||||||
class="step-drive step-size">
|
class="step-drive step-size">
|
||||||
{{ main.selection.getCurrentDrive().size | closestUnit }}
|
{{ drive.getDrivesSubtitle() }}
|
||||||
</span>
|
</span>
|
||||||
<span class="step-drive step-warning glyphicon glyphicon-exclamation-sign"
|
<span class="step-drive step-warning glyphicon glyphicon-exclamation-sign"
|
||||||
uib-tooltip="{{ main.constraints.getListDriveImageCompatibilityStatuses(main.selection.getSelectedDrives(), main.selection.getImage())[0].message }}"
|
uib-tooltip="{{ main.constraints.getListDriveImageCompatibilityStatuses(main.selection.getSelectedDrives(), main.selection.getImage())[0].message }}"
|
||||||
@ -81,8 +84,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<button class="button button-link step-footer"
|
<button class="button button-link step-footer"
|
||||||
tabindex="{{ main.selection.hasDrive() ? 2 : -1 }}"
|
tabindex="{{ main.selection.hasDrive() ? 2 : -1 }}"
|
||||||
ng-click="drive.reselectDrive()"
|
ng-hide="main.state.isFlashing() || !drive.shouldShowDrivesButton()"
|
||||||
ng-hide="main.state.isFlashing()">Change</button>
|
ng-click="drive.reselectDrive()">Change</button>
|
||||||
</div>
|
</div>
|
||||||
<div ng-if="main.selection.getSelectedDevices().length > 1"
|
<div ng-if="main.selection.getSelectedDevices().length > 1"
|
||||||
class="step-drive step-list">
|
class="step-drive step-list">
|
||||||
|
@ -6517,6 +6517,9 @@ svg-icon > img[disabled] {
|
|||||||
.page-main .text-disabled > span {
|
.page-main .text-disabled > span {
|
||||||
color: #787c7f; }
|
color: #787c7f; }
|
||||||
|
|
||||||
|
.page-main .step-drive.text-warning {
|
||||||
|
color: #ff912f; }
|
||||||
|
|
||||||
.page-main .relative {
|
.page-main .relative {
|
||||||
position: relative; }
|
position: relative; }
|
||||||
|
|
||||||
@ -6586,8 +6589,13 @@ svg-icon > img[disabled] {
|
|||||||
vertical-align: text-top; }
|
vertical-align: text-top; }
|
||||||
|
|
||||||
.page-main .step-name {
|
.page-main .step-name {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 39px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-right: 4.5px;
|
margin-right: 4.5px;
|
||||||
|
margin-bottom: 10px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #fff; }
|
color: #fff; }
|
||||||
|
|
||||||
|
@ -197,41 +197,43 @@ const storeReducer = (state = DEFAULT_STATE, action) => {
|
|||||||
return accState
|
return accState
|
||||||
}, newState)
|
}, newState)
|
||||||
|
|
||||||
|
const shouldAutoselectAll = Boolean(process.env.ETCHER_DISABLE_EXPLICIT_DRIVE_SELECTION)
|
||||||
const AUTOSELECT_DRIVE_COUNT = 1
|
const AUTOSELECT_DRIVE_COUNT = 1
|
||||||
const numberOfDrives = drives.length
|
|
||||||
const nonStaleSelectedDevices = nonStaleNewState.getIn([ 'selection', 'devices' ]).toJS()
|
const nonStaleSelectedDevices = nonStaleNewState.getIn([ 'selection', 'devices' ]).toJS()
|
||||||
const hasSelectedDevices = nonStaleSelectedDevices.length >= AUTOSELECT_DRIVE_COUNT
|
const hasSelectedDevices = nonStaleSelectedDevices.length >= AUTOSELECT_DRIVE_COUNT
|
||||||
if (numberOfDrives === AUTOSELECT_DRIVE_COUNT && !hasSelectedDevices) {
|
const shouldAutoselectOne = drives.length === AUTOSELECT_DRIVE_COUNT && !hasSelectedDevices
|
||||||
const [ drive ] = drives
|
|
||||||
|
|
||||||
|
if (shouldAutoselectOne || shouldAutoselectAll) {
|
||||||
// Even if there's no image selected, we need to call several
|
// Even if there's no image selected, we need to call several
|
||||||
// drive/image related checks, and `{}` works fine with them
|
// drive/image related checks, and `{}` works fine with them
|
||||||
const image = state.getIn([ 'selection', 'image' ], Immutable.fromJS({})).toJS()
|
const image = state.getIn([ 'selection', 'image' ], Immutable.fromJS({})).toJS()
|
||||||
|
|
||||||
if (_.every([
|
return _.reduce(drives, (accState, drive) => {
|
||||||
constraints.isDriveValid(drive, image),
|
if (_.every([
|
||||||
constraints.isDriveSizeRecommended(drive, image),
|
constraints.isDriveValid(drive, image),
|
||||||
|
constraints.isDriveSizeRecommended(drive, image),
|
||||||
|
|
||||||
// We don't want to auto-select large drives
|
// We don't want to auto-select large drives
|
||||||
!constraints.isDriveSizeLarge(drive),
|
!constraints.isDriveSizeLarge(drive),
|
||||||
|
|
||||||
// We don't want to auto-select system drives,
|
// We don't want to auto-select system drives,
|
||||||
// even when "unsafe mode" is enabled
|
// even when "unsafe mode" is enabled
|
||||||
!constraints.isSystemDrive(drive)
|
!constraints.isSystemDrive(drive)
|
||||||
|
|
||||||
])) {
|
]) || (shouldAutoselectAll && constraints.isDriveValid(drive, image))) {
|
||||||
// Auto-select this drive
|
// Auto-select this drive
|
||||||
return storeReducer(nonStaleNewState, {
|
return storeReducer(accState, {
|
||||||
type: ACTIONS.SELECT_DRIVE,
|
type: ACTIONS.SELECT_DRIVE,
|
||||||
|
data: drive.device
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deselect this drive in case it still is selected
|
||||||
|
return storeReducer(accState, {
|
||||||
|
type: ACTIONS.DESELECT_DRIVE,
|
||||||
data: drive.device
|
data: drive.device
|
||||||
})
|
})
|
||||||
}
|
}, nonStaleNewState)
|
||||||
|
|
||||||
// Deselect this drive in case it still is selected
|
|
||||||
return storeReducer(nonStaleNewState, {
|
|
||||||
type: ACTIONS.DESELECT_DRIVE,
|
|
||||||
data: drive.device
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nonStaleNewState
|
return nonStaleNewState
|
||||||
|
Loading…
x
Reference in New Issue
Block a user