Rework finish page with React

Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
This commit is contained in:
Lorenzo Alberto Maria Ambrosi 2019-11-25 16:15:47 +01:00
parent 9f4e0ce920
commit c9c9c50d6c
18 changed files with 415 additions and 318 deletions

View File

@ -91,7 +91,7 @@ const app = angular.module('Etcher', [
// Pages // Pages
require('./pages/main/main.ts').MODULE_NAME, require('./pages/main/main.ts').MODULE_NAME,
require('./pages/finish/finish'), require('./components/finish/index.ts').MODULE_NAME,
require('./components/settings/index.ts').MODULE_NAME, require('./components/settings/index.ts').MODULE_NAME,
// OS // OS

View File

@ -0,0 +1,127 @@
/*
* Copyright 2019 balena.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.
*/
import * as _ from 'lodash';
import * as React from 'react';
import * as uuidV4 from 'uuid/v4';
import * as messages from '../../../../shared/messages';
import * as flashState from '../../models/flash-state';
import * as selectionState from '../../models/selection-state';
import * as store from '../../models/store';
import * as analytics from '../../modules/analytics';
import * as updateLock from '../../modules/update-lock';
import * as FlashAnother from '../flash-another/flash-another';
import * as FlashResults from '../flash-results/flash-results';
import * as SVGIcon from '../svg-icon/svg-icon';
const restart = (options: any, $state: any) => {
const {
applicationSessionUuid,
flashingWorkflowUuid,
} = store.getState().toJS();
if (!options.preserveImage) {
selectionState.deselectImage();
}
selectionState.deselectAllDrives();
analytics.logEvent('Restart', {
...options,
applicationSessionUuid,
flashingWorkflowUuid,
});
// Re-enable lock release on inactivity
updateLock.resume();
// Reset the flashing workflow uuid
store.dispatch({
type: 'SET_FLASHING_WORKFLOW_UUID',
data: uuidV4(),
});
$state.go('main');
};
const formattedErrors = () => {
const errors = _.map(
_.get(flashState.getFlashResults(), ['results', 'errors']),
error => {
return `${error.device}: ${error.message || error.code}`;
},
);
return errors.join('\n');
};
function FinishPage({ $state }: any) {
const results = flashState.getFlashResults().results || {};
const progressMessage = messages.progress;
return (
<div className="page-finish row around-xs">
<div className="col-xs">
<div className="box center">
<FlashResults
results={results}
message={progressMessage}
errors={formattedErrors}
></FlashResults>
<FlashAnother
onClick={(options: any) => restart(options, $state)}
></FlashAnother>
</div>
<div className="box center">
<div className="fallback-banner">
<div className="caption caption-big">
Thanks for using
<span os-open-external="https://etcher.io?ref=etcher_offline_banner">
<SVGIcon
paths={['../../assets/etcher.svg']}
width="165px"
height="auto"
></SVGIcon>
</span>
</div>
<div className="caption caption-small fallback-footer">
made with
<SVGIcon
paths={['../../assets/love.svg']}
width="auto"
height="20px"
></SVGIcon>
by
<span os-open-external="https://resin.io?ref=etcher_success">
<SVGIcon
paths={['../../assets/balena.svg']}
width="auto"
height="20px"
></SVGIcon>
</span>
<div className="section-footer">
<span
className="caption caption-small footer-right"
manifest-bind="version"
os-open-external="https://github.com/resin-io/etcher/blob/master/CHANGELOG.md"
></span>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
export default FinishPage;

View File

@ -0,0 +1,35 @@
/*
* Copyright 2019 balena.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.
*/
/**
* @module Etcher.Pages.Finish
*/
import * as angular from 'angular';
import { react2angular } from 'react2angular';
import FinishPage from './finish';
export const MODULE_NAME = 'Etcher.Pages.Finish';
const Finish = angular.module(MODULE_NAME, []);
Finish.component('finish', react2angular(FinishPage, [], ['$state']));
Finish.config(($stateProvider: any) => {
$stateProvider.state('success', {
url: '/success',
template: '<finish style="width:100%"></finish>',
});
});

View File

@ -14,21 +14,15 @@
* limitations under the License. * limitations under the License.
*/ */
'use strict'
/** /**
* @module Etcher.Components.FlashAnother * @module Etcher.Components.FlashAnother
*/ */
const angular = require('angular') import * as angular from 'angular';
const { react2angular } = require('react2angular') import { react2angular } from 'react2angular';
import * as FlashAnother from './flash-another';
const MODULE_NAME = 'Etcher.Components.FlashAnother' export const MODULE_NAME = 'Etcher.Components.FlashAnother';
const FlashAnother = angular.module(MODULE_NAME, []) const FlashAnotherModule = angular.module(MODULE_NAME, []);
FlashAnother.component( FlashAnotherModule.component('flashAnother', react2angular(FlashAnother));
'flashAnother',
react2angular(require('./flash-another.jsx'))
)
module.exports = MODULE_NAME

View File

@ -14,13 +14,35 @@
* limitations under the License. * limitations under the License.
*/ */
/*
* 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' 'use strict'
// eslint-disable-next-line no-unused-vars
const React = require('react') const React = require('react')
const PropTypes = require('prop-types') const PropTypes = require('prop-types')
const _ = require('lodash') const _ = require('lodash')
const styled = require('styled-components').default const styled = require('styled-components').default
const { position, left, top, space } = require('styled-system') const {
position,
left,
top,
space
} = require('styled-system')
const { Underline } = require('./../../styled-components') const { Underline } = require('./../../styled-components')
const Div = styled.div ` const Div = styled.div `

View File

@ -14,21 +14,15 @@
* limitations under the License. * limitations under the License.
*/ */
'use strict'
/** /**
* @module Etcher.Components.FlashResults * @module Etcher.Components.FlashResults
*/ */
const angular = require('angular') import * as angular from 'angular';
const { react2angular } = require('react2angular') import { react2angular } from 'react2angular';
import * as FlashResults from './flash-results';
const MODULE_NAME = 'Etcher.Components.FlashResults' export const MODULE_NAME = 'Etcher.Components.FlashResults';
const FlashResults = angular.module(MODULE_NAME, []) const FlashResultsModule = angular.module(MODULE_NAME, []);
FlashResults.component( FlashResultsModule.component('flashResults', react2angular(FlashResults));
'flashResults',
react2angular(require('./flash-results.jsx'))
)
module.exports = MODULE_NAME

View File

@ -108,8 +108,8 @@ class SafeWebview extends react.PureComponent {
this.didGetResponseDetails = _.bind(this.didGetResponseDetails, this) this.didGetResponseDetails = _.bind(this.didGetResponseDetails, this)
const logWebViewMessage = (event) => { const logWebViewMessage = (event) => {
console.log('Message from SafeWebview:', event.message); console.log('Message from SafeWebview:', event.message)
}; }
this.eventTuples = [ this.eventTuples = [
[ 'did-fail-load', this.didFailLoad ], [ 'did-fail-load', this.didFailLoad ],
@ -174,6 +174,9 @@ class SafeWebview extends react.PureComponent {
this.setState({ this.setState({
shouldShow: false shouldShow: false
}) })
if (this.props.onWebviewShow) {
this.props.onWebviewShow(false)
}
} }
/** /**

View File

@ -10,6 +10,7 @@
<script src="../../../generated/gui.js"></script> <script src="../../../generated/gui.js"></script>
</head> </head>
<body> <body>
<header class="section-header" ng-controller="HeaderController as header"> <header class="section-header" ng-controller="HeaderController as header">
<span <span
id="app-logo" id="app-logo"
@ -31,7 +32,7 @@
</button> </button>
</header> </header>
<main class="wrapper" ui-view></main> <main ui-view></main>
<div class="section-loader" <div class="section-loader"
ng-controller="StateController as state" ng-controller="StateController as state"
@ -41,5 +42,6 @@
<safe-webview src="'https://www.balena.io/etcher/success-banner/'"> <safe-webview src="'https://www.balena.io/etcher/success-banner/'">
</safe-webview> </safe-webview>
</div> </div>
</body> </body>
</html> </html>

View File

@ -1,98 +0,0 @@
/*
* 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')
const uuidV4 = require('uuid/v4')
const store = require('../../../models/store')
const settings = require('../../../models/settings')
const flashState = require('../../../models/flash-state')
const selectionState = require('../../../models/selection-state')
const analytics = require('../../../modules/analytics')
const updateLock = require('../../../modules/update-lock')
const messages = require('../../../../../shared/messages')
module.exports = function ($state) {
/**
* @summary Settings model
* @type {Object}
* @public
*/
this.settings = settings
/**
* @summary Flash state
* @type {Object}
* @public
*/
this.flash = flashState
this.progressMessage = messages.progress
this.results = this.flash.getFlashResults().results || {}
/**
* @summary Restart the flashing process
* @function
* @public
*
* @param {Object} [options] - options
* @param {Boolean} [options.preserveImage=false] - preserve image
*
* @example
* FinishController.restart({ preserveImage: true });
*/
this.restart = (options) => {
if (!options.preserveImage) {
selectionState.deselectImage()
}
selectionState.deselectAllDrives()
analytics.logEvent('Restart', _.assign({
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
}, options))
// Re-enable lock release on inactivity
updateLock.resume()
// Reset the flashing workflow uuid
store.dispatch({
type: 'SET_FLASHING_WORKFLOW_UUID',
data: uuidV4()
})
$state.go('main')
}
/**
* @summary Format the result errors with newlines
* @function
* @public
*
* @returns {String} formatted errors
*
* @example
* const errors = FinishController.formattedErrors()
* console.log(errors)
*/
this.formattedErrors = () => {
const errors = _.map(_.get(flashState.getFlashResults(), [ 'results', 'errors' ]), (error) => {
return `${error.device}: ${error.message || error.code}`
})
return errors.join('\n')
}
}

View File

@ -1,46 +0,0 @@
/*
* 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'
/**
* The finish page represents the application state where
* the the flash/validation has completed.
*
* Its purpose is to display success or failure information,
* as well as the "next steps".
*
* @module Etcher.Pages.Finish
*/
const angular = require('angular')
const MODULE_NAME = 'Etcher.Pages.Finish'
const FinishPage = angular.module(MODULE_NAME, [
require('angular-ui-router')
])
FinishPage.controller('FinishController', require('./controllers/finish'))
FinishPage.config(($stateProvider) => {
$stateProvider
.state('success', {
url: '/success',
controller: 'FinishController as finish',
template: require('./templates/success.tpl.html')
})
})
module.exports = MODULE_NAME

View File

@ -15,12 +15,12 @@
*/ */
.page-finish { .page-finish {
margin-top: -15px; // margin-top: -15px;
flex: 1; // flex: 1;
}
.col-xs-5.inline-flex.items-baseline > span, .col-xs-5.inline-flex.items-baseline > div { .col-xs-5.inline-flex.items-baseline > span, .col-xs-5.inline-flex.items-baseline > div {
margin-bottom: -10px; margin-bottom: -10px;
}
} }
.page-finish .button-label { .page-finish .button-label {

View File

@ -1,45 +0,0 @@
<div class="page-finish row around-xs">
<div class="col-xs">
<div class="box center">
<flash-results
results="finish.results"
message="finish.progressMessage"
errors="finish.formattedErrors">
</flash-results>
<flash-another on-click="finish.restart">
</flash-another>
</div>
<div class="box center">
<div class="fallback-banner">
<div class="caption caption-big">Thanks for using
<span os-open-external="https://etcher.io?ref=etcher_offline_banner">
<svg-icon paths="[ '../../assets/etcher.svg' ]"
width="'165px'"
height="'auto'">
</svg-icon>
</span>
</div>
<div class="caption caption-small fallback-footer">
made with
<svg-icon paths="[ '../../assets/love.svg' ]"
width="'auto'"
height="'20px'"></svg-icon>
by
<span os-open-external="https://resin.io?ref=etcher_success">
<svg-icon paths="[ '../../assets/balena.svg' ]"
width="'auto'"
height="'20px'">
</svg-icon>
</span>
<div class="section-footer">
<span class="caption caption-small footer-right"
manifest-bind="version"
os-open-external="https://github.com/resin-io/etcher/blob/master/CHANGELOG.md"></span>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,70 @@
/*
* 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'
/**
* This page represents the application main page.
*
* @module Etcher.Pages.Main
*/
const angular = require('angular')
const MODULE_NAME = 'Etcher.Pages.Main'
require('angular-moment')
const MainPage = angular.module(MODULE_NAME, [
'angularMoment',
require('angular-ui-router'),
require('angular-seconds-to-date'),
require('../../components/drive-selector/drive-selector'),
require('../../components/tooltip-modal/tooltip-modal'),
require('../../components/flash-error-modal/flash-error-modal'),
require('../../components/progress-button'),
require('../../components/image-selector'),
require('../../components/warning-modal/warning-modal'),
require('../../components/file-selector'),
require('../../components/featured-project'),
require('../../components/reduced-flashing-infos'),
require('../../components/flash-another/index.ts').MODULE_NAME,
require('../../components/flash-results/index.ts').MODULE_NAME,
require('../../components/drive-selector'),
require('../../os/open-external/open-external'),
require('../../os/dropzone/dropzone'),
require('../../utils/byte-size/byte-size'),
require('../../utils/middle-ellipsis/filter')
])
MainPage.controller('MainController', require('./controllers/main'))
MainPage.controller('ImageSelectionController', require('./controllers/image-selection'))
MainPage.controller('DriveSelectionController', require('./controllers/drive-selection'))
MainPage.controller('FlashController', require('./controllers/flash'))
MainPage.config(($stateProvider) => {
$stateProvider
.state('main', {
url: '/main',
controller: 'MainController as main',
template: require('./templates/main.tpl.html')
})
})
module.exports = MODULE_NAME

View File

@ -21,6 +21,7 @@ img[disabled] {
.page-main { .page-main {
flex: 1; flex: 1;
align-self: center; align-self: center;
margin: 20px;
} }
.page-main > .col-xs { .page-main > .col-xs {
@ -92,11 +93,6 @@ img[disabled] {
width: $btn-min-width; width: $btn-min-width;
} }
.page-main .step-footer-underline {
border-bottom: 1px dotted;
padding-bottom: 2px;
}
.page-main .button.step-footer { .page-main .button.step-footer {
font-size: 16px; font-size: 16px;
color: $palette-theme-primary-background; color: $palette-theme-primary-background;
@ -169,8 +165,7 @@ img[disabled] {
.target-status-line { .target-status-line {
display: flex; display: flex;
align-items: baseline; align-items: baseline;
font-size: 16px; margin-bottom: 9px;
font-family: inherit;
> .target-status-dot { > .target-status-dot {
width: 12px; width: 12px;

View File

@ -224,6 +224,10 @@ body {
height: 24px; height: 24px;
margin: 0 10px; margin: 0 10px;
} }
* {
z-index: 1;
}
} }
featured-project { featured-project {

View File

@ -6306,7 +6306,8 @@ img[disabled] {
.page-main { .page-main {
flex: 1; flex: 1;
align-self: center; } align-self: center;
margin: 20px; }
.page-main > .col-xs { .page-main > .col-xs {
height: 165px; } height: 165px; }
@ -6366,10 +6367,6 @@ img[disabled] {
justify-content: space-between; justify-content: space-between;
width: 170px; } width: 170px; }
.page-main .step-footer-underline {
border-bottom: 1px dotted;
padding-bottom: 2px; }
.page-main .button.step-footer { .page-main .button.step-footer {
font-size: 16px; font-size: 16px;
color: #2297de; color: #2297de;
@ -6430,8 +6427,7 @@ img[disabled] {
.target-status-line { .target-status-line {
display: flex; display: flex;
align-items: baseline; align-items: baseline;
font-size: 16px; margin-bottom: 9px; }
font-family: inherit; }
.target-status-line > .target-status-dot { .target-status-line > .target-status-dot {
width: 12px; width: 12px;
height: 12px; height: 12px;
@ -6477,11 +6473,8 @@ img[disabled] {
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
.page-finish { .col-xs-5.inline-flex.items-baseline > span, .col-xs-5.inline-flex.items-baseline > div {
margin-top: -15px; margin-bottom: -10px; }
flex: 1; }
.page-finish .col-xs-5.inline-flex.items-baseline > span, .page-finish .col-xs-5.inline-flex.items-baseline > div {
margin-bottom: -10px; }
.page-finish .button-label { .page-finish .button-label {
margin: 0 auto 15px; margin: 0 auto 15px;
@ -9886,6 +9879,8 @@ body {
vertical-align: middle; vertical-align: middle;
height: 24px; height: 24px;
margin: 0 10px; } margin: 0 10px; }
.section-header * {
z-index: 1; }
featured-project webview { featured-project webview {
flex: 0 1; flex: 0 1;

152
npm-shrinkwrap.json generated
View File

@ -1521,9 +1521,9 @@
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
}, },
"acorn": { "acorn": {
"version": "5.7.3", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.0.tgz",
"integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", "integrity": "sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw==",
"dev": true "dev": true
}, },
"acorn-jsx": { "acorn-jsx": {
@ -2470,12 +2470,6 @@
"chainsaw": "~0.1.0" "chainsaw": "~0.1.0"
} }
}, },
"binary-extensions": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
"integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
"dev": true
},
"bindings": { "bindings": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
@ -2911,6 +2905,26 @@
"y18n": "^4.0.0" "y18n": "^4.0.0"
}, },
"dependencies": { "dependencies": {
"bluebird": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz",
"integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==",
"dev": true
},
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"lru-cache": { "lru-cache": {
"version": "5.1.1", "version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@ -4309,10 +4323,21 @@
} }
}, },
"data-uri-to-buffer": { "data-uri-to-buffer": {
"version": "1.2.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.0.tgz",
"integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", "integrity": "sha512-YbKCNLPPP4inc0E5If4OaalBc7gpaM2MRv77Pv2VThVComLKfbGYtJcdDCViDyp1Wd4SebhHLz94vp91zbK6bw==",
"dev": true "dev": true,
"requires": {
"@types/node": "^8.0.7"
},
"dependencies": {
"@types/node": {
"version": "8.10.40",
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.40.tgz",
"integrity": "sha512-RRSjdwz63kS4u7edIwJUn8NqKLLQ6LyqF/X4+4jp38MBT3Vwetewi2N4dgJEshLbDwNgOJXNYoOwzVZUSSLhkQ==",
"dev": true
}
}
}, },
"date-fns": { "date-fns": {
"version": "1.30.1", "version": "1.30.1",
@ -4776,9 +4801,9 @@
"dev": true "dev": true
}, },
"des.js": { "des.js": {
"version": "1.0.0", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz",
"integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==",
"dev": true, "dev": true,
"requires": { "requires": {
"inherits": "^2.0.1", "inherits": "^2.0.1",
@ -5415,9 +5440,9 @@
"dev": true "dev": true
}, },
"elliptic": { "elliptic": {
"version": "6.5.1", "version": "6.5.2",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz",
"integrity": "sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==", "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==",
"dev": true, "dev": true,
"requires": { "requires": {
"bn.js": "^4.4.0", "bn.js": "^4.4.0",
@ -8207,15 +8232,6 @@
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
}, },
"is-binary-path": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
"integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
"dev": true,
"requires": {
"binary-extensions": "^1.0.0"
}
},
"is-buffer": { "is-buffer": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
@ -10286,9 +10302,9 @@
}, },
"dependencies": { "dependencies": {
"buffer": { "buffer": {
"version": "4.9.1", "version": "4.9.2",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
"integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
"dev": true, "dev": true,
"requires": { "requires": {
"base64-js": "^1.0.2", "base64-js": "^1.0.2",
@ -14774,6 +14790,80 @@
"chokidar": "^2.0.2", "chokidar": "^2.0.2",
"graceful-fs": "^4.1.2", "graceful-fs": "^4.1.2",
"neo-async": "^2.5.0" "neo-async": "^2.5.0"
},
"dependencies": {
"anymatch": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
"integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
"dev": true,
"requires": {
"micromatch": "^3.1.4",
"normalize-path": "^2.1.1"
},
"dependencies": {
"normalize-path": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
"integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
"dev": true,
"requires": {
"remove-trailing-separator": "^1.0.1"
}
}
}
},
"binary-extensions": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
"integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
"dev": true
},
"chokidar": {
"version": "2.1.8",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
"integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
"dev": true,
"requires": {
"anymatch": "^2.0.0",
"async-each": "^1.0.1",
"braces": "^2.3.2",
"glob-parent": "^3.1.0",
"inherits": "^2.0.3",
"is-binary-path": "^1.0.0",
"is-glob": "^4.0.0",
"normalize-path": "^3.0.0",
"path-is-absolute": "^1.0.0",
"readdirp": "^2.2.1",
"upath": "^1.1.1"
}
},
"is-binary-path": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
"integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
"dev": true,
"requires": {
"binary-extensions": "^1.0.0"
}
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true
},
"readdirp": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
"integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.11",
"micromatch": "^3.1.10",
"readable-stream": "^2.0.2"
}
}
} }
}, },
"wdio-dot-reporter": { "wdio-dot-reporter": {

View File

@ -1,45 +0,0 @@
/*
* 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 m = require('mochainon')
const fs = require('fs')
const angular = require('angular')
describe('Browser: FinishPage', function () {
beforeEach(angular.mock.module(
require('../../../lib/gui/app/pages/finish/finish')
))
describe('page template', function () {
let $state
beforeEach(angular.mock.inject(function (_$state_) {
$state = _$state_
}))
it('should match the file contents', function () {
const {
template
} = $state.get('success')
const contents = fs.readFileSync('lib/gui/app/pages/finish/templates/success.tpl.html', {
encoding: 'utf-8'
})
m.chai.expect(template).to.equal(contents)
})
})
})