From 3b0794606530f201bab6d0e0aec15d6f420b006a Mon Sep 17 00:00:00 2001 From: Lorenzo Alberto Maria Ambrosi Date: Thu, 14 Nov 2019 19:26:26 +0100 Subject: [PATCH] Convert settings modal to typescript Change-type: patch Changelog-entry: Convert settings modal to typescript Signed-off-by: Lorenzo Alberto Maria Ambrosi --- .gitattributes | 2 + lib/gui/app/app.js | 2 +- .../file-selector/file-selector/file-list.jsx | 2 +- .../settings/{index.js => index.ts} | 20 +- lib/gui/app/components/settings/settings.jsx | 233 ------------------ lib/gui/app/components/settings/settings.tsx | 233 ++++++++++++++++++ lib/gui/app/index.html | 37 +-- lib/gui/app/pages/main/styles/_main.scss | 20 +- lib/gui/css/main.css | 18 +- npm-shrinkwrap.json | 49 ++-- package.json | 5 +- tsconfig.json | 3 +- 12 files changed, 319 insertions(+), 305 deletions(-) rename lib/gui/app/components/settings/{index.js => index.ts} (64%) delete mode 100644 lib/gui/app/components/settings/settings.jsx create mode 100644 lib/gui/app/components/settings/settings.tsx diff --git a/.gitattributes b/.gitattributes index c291eb40..3f17f049 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,8 @@ # Javascript files must retain LF line-endings (to keep eslint happy) *.js text eol=lf *.jsx text eol=lf +*.ts text eol=lf +*.tsx text eol=lf # CSS and SCSS files must retain LF line-endings (to keep ensure-staged-sass.sh happy) *.css text eol=lf *.scss text eol=lf diff --git a/lib/gui/app/app.js b/lib/gui/app/app.js index a8f0ed51..c3ee1ddc 100644 --- a/lib/gui/app/app.js +++ b/lib/gui/app/app.js @@ -94,7 +94,7 @@ const app = angular.module('Etcher', [ // Pages require('./pages/main/main'), require('./pages/finish/finish'), - require('./components/settings'), + require('./components/settings/index.ts').MODULE_NAME, // OS require('./os/open-external/open-external'), diff --git a/lib/gui/app/components/file-selector/file-selector/file-list.jsx b/lib/gui/app/components/file-selector/file-selector/file-list.jsx index 74daf296..60f0ad11 100644 --- a/lib/gui/app/components/file-selector/file-selector/file-list.jsx +++ b/lib/gui/app/components/file-selector/file-selector/file-list.jsx @@ -189,7 +189,7 @@ const File = styled(UnstyledFile)` display: flex; justify-content: center; text-align: center; - font-size: 14px; + font-size: 16px; } > div:last-child { diff --git a/lib/gui/app/components/settings/index.js b/lib/gui/app/components/settings/index.ts similarity index 64% rename from lib/gui/app/components/settings/index.js rename to lib/gui/app/components/settings/index.ts index 9881e56b..ba82c00b 100644 --- a/lib/gui/app/components/settings/index.js +++ b/lib/gui/app/components/settings/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2019 resin.io + * 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. @@ -14,21 +14,15 @@ * limitations under the License. */ -'use strict' - /** * @module Etcher.Components.FeaturedProject */ -const angular = require('angular') -const { react2angular } = require('react2angular') +import * as angular from 'angular'; +import { react2angular } from 'react2angular'; +import { SettingsButton } from './settings'; -const MODULE_NAME = 'Etcher.Components.Settings' -const Settings = angular.module(MODULE_NAME, []) +export const MODULE_NAME = 'Etcher.Components.Settings'; +const Settings = angular.module(MODULE_NAME, []); -Settings.component( - 'settings', - react2angular(require('./settings.jsx').SettingsButton) -) - -module.exports = MODULE_NAME +Settings.component('settings', react2angular(SettingsButton)); diff --git a/lib/gui/app/components/settings/settings.jsx b/lib/gui/app/components/settings/settings.jsx deleted file mode 100644 index a2fdb8d1..00000000 --- a/lib/gui/app/components/settings/settings.jsx +++ /dev/null @@ -1,233 +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 React = require('react') -const { useState } = React -const propTypes = require('prop-types') -const _ = require('lodash') -const store = require('../../models/store') -const analytics = require('../../modules/analytics') -const settings = require('../../models/settings') -const { default: styled } = require('styled-components') -const { FaCog } = require('react-icons/fa') -const { - Badge, - Button, - Checkbox, - Modal, - Provider -} = require('rendition') -const { colors } = require('../../theme') - -const SettingsIcon = styled(FaCog) ` - width: 24px; - height: 24px; - - &&& { - color: ${colors.secondary.background}!important; - } -` - -const SettingsButton = () => { - const [ hideModal, setHideModal ] = useState(true) - - return ( - - - { hideModal ? null : ( - setHideModal(!value)}> - - ) } - - ) -} - -SettingsButton.propTypes = {} - -const WarningModal = ({ - message, - confirmLabel, - cancel, - done -}) => { - return ( - - {message} - - ) -} - -const SettingsModal = styled((props) => { - const [ currentSettings, setCurrentSettings ] = useState(settings.getAll()) - const [ warning, setWarning ] = useState({}) - - const toggleSetting = (setting, options) => { - const value = currentSettings[setting] - const dangerous = !_.isUndefined(options) - - analytics.logEvent('Toggle setting', { - setting, - value, - dangerous, - applicationSessionUuid: store.getState().toJS().applicationSessionUuid - }) - - if (value || !dangerous) { - settings.set(setting, !value) - setCurrentSettings({ - ...currentSettings, - [setting]: !value - }) - return setWarning({}) - } - - // Show warning since it's a dangerous setting - return setWarning({ - setting, - settingValue: value, - ...options - }) - } - - return ( - props.toggleModal(false)} - style={{ - width: 780, - height: 460 - }} - > -
-
- toggleSetting('errorReporting')}/> -
- -
- { - // eslint-disable-next-line lines-around-comment - /* On Windows, "Unmounting" basically means "ejecting". - * On top of that, Windows users are usually not even - * familiar with the meaning of "unmount", which comes - * from the UNIX world. */ - } - toggleSetting('unmountOnSuccess')}/> -
- -
- toggleSetting('validateWriteOnSuccess')}/> -
- -
- toggleSetting('trim')}/> -
- -
- toggleSetting('updatesEnabled')}/> -
- - { settings.get('disableUnsafeMode') ? null : ( -
- - Unsafe mode Dangerous - )} - checked={currentSettings.unsafeMode} - onChange={() => toggleSetting('unsafeMode', { - description: `Are you sure you want to turn this on? - You will be able to overwrite your system drives if you're not careful.`, - confirmLabel: 'Enable unsafe mode' - })}/> -
- ) } -
- - { _.isEmpty(warning) ? null : ( - { - settings.set(warning.setting, !warning.settingValue) - setCurrentSettings({ - ...currentSettings, - [warning.setting]: true - }) - setWarning({}) - }} - cancel={() => { - setWarning({}) - }}> - - ) } -
- ) -}) ` -> div:nth-child(3) { - justify-content: center; -} -` - -SettingsModal.propTypes = { - toggleModal: propTypes.func -} - -module.exports = { SettingsButton, SettingsModal } diff --git a/lib/gui/app/components/settings/settings.tsx b/lib/gui/app/components/settings/settings.tsx new file mode 100644 index 00000000..35075d0d --- /dev/null +++ b/lib/gui/app/components/settings/settings.tsx @@ -0,0 +1,233 @@ +/* + * 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 { faCog } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import * as _ from 'lodash'; +import * as os from 'os'; +import * as propTypes from 'prop-types'; +import * as React from 'react'; +import { Badge, Button, Checkbox, Modal, Provider } from 'rendition'; +import styled from 'styled-components'; +import * as settings from '../../models/settings'; +import * as store from '../../models/store'; +import * as analytics from '../../modules/analytics'; +import { colors } from '../../theme'; + +const { useState } = React; +const platform = os.platform(); + +export const SettingsButton = () => { + const [hideModal, setHideModal] = useState(true); + + return ( + + + {hideModal ? null : ( + setHideModal(!value)} /> + )} + + ); +}; + +SettingsButton.propTypes = {}; + +interface WarningModalProps { + message: string; + confirmLabel: string; + cancel: () => void; + done: () => void; +} + +const WarningModal = ({ + message, + confirmLabel, + cancel, + done, +}: WarningModalProps) => { + return ( + + {message} + + ); +}; + +interface Setting { + name: string; + label: string | JSX.Element; + options?: any; + hide?: boolean; +} + +const settingsList: Setting[] = [ + { + name: 'errorReporting', + label: 'Anonymously report errors and usage statistics to balena.io', + }, + { + name: 'unmountOnSuccess', + /** + * On Windows, "Unmounting" basically means "ejecting". + * On top of that, Windows users are usually not even + * familiar with the meaning of "unmount", which comes + * from the UNIX world. + */ + label: `${platform === 'win32' ? 'Eject' : 'Auto-unmount'} on success`, + }, + { + name: 'validateWriteOnSuccess', + label: 'Validate write on success', + }, + { + name: 'trim', + label: 'Trim ext{2,3,4} partitions before writing (raw images only)', + }, + { + name: 'updatesEnabled', + label: 'Auto-updates enabled', + }, + { + name: 'unsafeMode', + label: ( + + Unsafe mode{' '} + + Dangerous + + + ), + options: { + description: `Are you sure you want to turn this on? + You will be able to overwrite your system drives if you're not careful.`, + confirmLabel: 'Enable unsafe mode', + }, + hide: settings.get('disableUnsafeMode'), + }, +]; + +interface SettingsModalProps { + toggleModal: (value: boolean) => void; +} + +export const SettingsModal: any = styled( + ({ toggleModal }: SettingsModalProps) => { + const [currentSettings, setCurrentSettings] = useState(settings.getAll()); + const [warning, setWarning]: [ + any, + React.Dispatch>, + ] = useState({}); + + const toggleSetting = async (setting: string, options?: any) => { + const value = currentSettings[setting]; + const dangerous = !_.isUndefined(options); + + analytics.logEvent('Toggle setting', { + setting, + value, + dangerous, + applicationSessionUuid: store.getState().toJS().applicationSessionUuid, + }); + + if (value || !dangerous) { + await settings.set(setting, !value); + setCurrentSettings({ + ...currentSettings, + [setting]: !value, + }); + setWarning({}); + return; + } + + // Show warning since it's a dangerous setting + setWarning({ + setting, + settingValue: value, + ...options, + }); + }; + + return ( + toggleModal(false)} + style={{ + width: 780, + height: 420, + }} + > +
+ {_.map(settingsList, (setting: Setting, i: number) => { + return setting.hide ? null : ( +
+ toggleSetting(setting.name, setting.options)} + /> +
+ ); + })} +
+ + {_.isEmpty(warning) ? null : ( + { + settings.set(warning.setting, !warning.settingValue); + setCurrentSettings({ + ...currentSettings, + [warning.setting]: true, + }); + setWarning({}); + }} + cancel={() => { + setWarning({}); + }} + /> + )} +
+ ); + }, +)` + > div:nth-child(3) { + justify-content: center; + } +`; + +SettingsModal.propTypes = { + toggleModal: propTypes.func, +}; diff --git a/lib/gui/app/index.html b/lib/gui/app/index.html index 9b584621..2ca922d6 100644 --- a/lib/gui/app/index.html +++ b/lib/gui/app/index.html @@ -11,6 +11,15 @@
+ + @@ -24,34 +33,6 @@
- -