Просмотр исходного кода

Merge pull request #274 from smiclea/ctor-refactor

Cleanup React components constructor
Dorin Paslaru 7 лет назад
Родитель
Сommit
aae8cc7d4f
45 измененных файлов с 319 добавлено и 425 удалено
  1. 50 16
      .eslintrc
  2. 2 1
      package.json
  3. 2 6
      src/components/atoms/PasswordValue/PasswordValue.jsx
  4. 2 6
      src/components/atoms/Switch/Switch.jsx
  5. 10 17
      src/components/molecules/AutocompleteDropdown/AutocompleteDropdown.jsx
  6. 8 15
      src/components/molecules/DatetimePicker/DatetimePicker.jsx
  7. 8 15
      src/components/molecules/Dropdown/Dropdown.jsx
  8. 6 11
      src/components/molecules/DropdownFilter/DropdownFilter.jsx
  9. 7 12
      src/components/molecules/DropdownLink/DropdownLink.jsx
  10. 2 7
      src/components/molecules/Modal/Modal.jsx
  11. 6 11
      src/components/molecules/NewItemDropdown/NewItemDropdown.jsx
  12. 4 9
      src/components/molecules/NotificationDropdown/NotificationDropdown.jsx
  13. 12 16
      src/components/molecules/SearchInput/SearchInput.jsx
  14. 2 6
      src/components/molecules/SideMenu/SideMenu.jsx
  15. 6 11
      src/components/molecules/UserDropdown/UserDropdown.jsx
  16. 5 9
      src/components/organisms/AssessmentMigrationOptions/AssessmentMigrationOptions.jsx
  17. 9 13
      src/components/organisms/Endpoint/Endpoint.jsx
  18. 2 6
      src/components/organisms/Executions/Executions.jsx
  19. 7 10
      src/components/organisms/FilterList/FilterList.jsx
  20. 3 7
      src/components/organisms/LoginForm/LoginForm.jsx
  21. 1 6
      src/components/organisms/Notifications/Notifications.jsx
  22. 9 12
      src/components/organisms/PageHeader/PageHeader.jsx
  23. 2 2
      src/components/organisms/ProjectDetailsContent/ProjectDetailsContent.jsx
  24. 2 6
      src/components/organisms/ReplicaDetailsContent/ReplicaDetailsContent.jsx
  25. 2 6
      src/components/organisms/ReplicaExecutionOptions/ReplicaExecutionOptions.jsx
  26. 18 21
      src/components/organisms/ReplicaMigrationOptions/ReplicaMigrationOptions.jsx
  27. 5 9
      src/components/organisms/Schedule/Schedule.jsx
  28. 4 8
      src/components/organisms/Tasks/Tasks.jsx
  29. 5 9
      src/components/organisms/WizardInstances/WizardInstances.jsx
  30. 2 7
      src/components/organisms/WizardOptions/WizardOptions.jsx
  31. 3 7
      src/components/organisms/WizardPageContent/WizardPageContent.jsx
  32. 8 12
      src/components/pages/AssessmentDetailsPage/AssessmentDetailsPage.jsx
  33. 3 3
      src/components/pages/AssessmentsPage/AssessmentsPage.jsx
  34. 7 11
      src/components/pages/EndpointDetailsPage/EndpointDetailsPage.jsx
  35. 12 16
      src/components/pages/EndpointsPage/EndpointsPage.jsx
  36. 5 9
      src/components/pages/MigrationDetailsPage/MigrationDetailsPage.jsx
  37. 7 11
      src/components/pages/MigrationsPage/MigrationsPage.jsx
  38. 3 3
      src/components/pages/ProjectsPage/ProjectsPage.jsx
  39. 10 14
      src/components/pages/ReplicaDetailsPage/ReplicaDetailsPage.jsx
  40. 6 10
      src/components/pages/ReplicasPage/ReplicasPage.jsx
  41. 3 3
      src/components/pages/UsersPage/UsersPage.jsx
  42. 8 11
      src/components/pages/WizardPage/WizardPage.jsx
  43. 5 9
      src/plugins/endpoint/azure/ContentPlugin.jsx
  44. 5 8
      src/plugins/endpoint/openstack/ContentPlugin.jsx
  45. 31 8
      yarn.lock

+ 50 - 16
.eslintrc

@@ -22,22 +22,56 @@
     }
   },
   "rules": {
-    "react/sort-comp": [1, {
-      "order": [
-        "static-methods",
-        "type-annotations",
-        "lifecycle",
-        "/^set.+$/",
-        "/^get.+$/",
-        "/^is.+$/",
-        "/^has.+$/",
-        "/^handle.+$/",
-        "everything-else",
-        "render"
-      ]
-    }],
-    "semi": [2, "never"],
-    "comma-dangle": [2, "always-multiline"],
+    "react/sort-comp": [
+      1,
+      {
+        "order": [
+          "static-methods",
+          "displayName",
+          "propTypes",
+          "contextTypes",
+          "childContextTypes",
+          "mixins",
+          "statics",
+          "defaultProps",
+          "state",
+          "type-annotations",
+          "instance-variables",
+          "getters",
+          "setters",
+          "constructor",
+          "getDefaultProps",
+          "getInitialState",
+          "getChildContext",
+          "getDerivedStateFromProps",
+          "lifecycle",
+          "everything-else",
+          "^handle.+$",
+          "render"
+        ],
+        "groups": {
+          "lifecycle": [
+            "componentWillMount",
+            "componentDidMount",
+            "componentWillReceiveProps",
+            "shouldComponentUpdate",
+            "componentWillUpdate",
+            "getSnapshotBeforeUpdate",
+            "componentDidUpdate",
+            "componentDidCatch",
+            "componentWillUnmount"
+          ]
+        }
+      }
+    ],
+    "semi": [
+      2,
+      "never"
+    ],
+    "comma-dangle": [
+      2,
+      "always-multiline"
+    ],
     "newline-per-chained-call": 0,
     "class-methods-use-this": 0,
     "max-len": 0,

+ 2 - 1
package.json

@@ -46,7 +46,7 @@
     "eslint-plugin-flowtype": "^2.46.1",
     "eslint-plugin-import": "^2.7.0",
     "eslint-plugin-jsx-a11y": "^6.0.2",
-    "eslint-plugin-react": "^7.4.0",
+    "eslint-plugin-react": "7.10.0",
     "flow-bin": "0.78.0",
     "flow-typed": "2.5.1",
     "jest": "^21.2.1",
@@ -57,6 +57,7 @@
   },
   "dependencies": {
     "@webpack-blocks/webpack2": "^0.4.0",
+    "autobind-decorator": "^2.1.0",
     "axios": "^0.18.0",
     "babel-core": "^6.26.0",
     "babel-loader": "^7.1.2",

+ 2 - 6
src/components/atoms/PasswordValue/PasswordValue.jsx

@@ -54,12 +54,8 @@ type State = {
 }
 @observer
 class PasswordValue extends React.Component<Props, State> {
-  constructor() {
-    super()
-
-    this.state = {
-      show: false,
-    }
+  state = {
+    show: false,
   }
 
   handleShowClick() {

+ 2 - 6
src/components/atoms/Switch/Switch.jsx

@@ -140,12 +140,8 @@ class Switch extends React.Component<Props, State> {
     height: 24,
   }
 
-  constructor() {
-    super()
-
-    this.state = {
-      lastChecked: null,
-    }
+  state = {
+    lastChecked: null,
   }
 
   getLabel() {

+ 10 - 17
src/components/molecules/AutocompleteDropdown/AutocompleteDropdown.jsx

@@ -18,6 +18,7 @@ import React from 'react'
 import { observer } from 'mobx-react'
 import styled, { css } from 'styled-components'
 import ReactDOM from 'react-dom'
+import autobind from 'autobind-decorator'
 
 import AutocompleteInput from '../../atoms/AutocompleteInput'
 import { Tip, updateTipStyle, scrollItemIntoView } from '../Dropdown'
@@ -120,6 +121,13 @@ class AutocompleteDropdown extends React.Component<Props, State> {
     noItemsMessage: 'No results found',
   }
 
+  state = {
+    showDropdownList: false,
+    firstItemHover: false,
+    searchValue: '',
+    filteredItems: [],
+  }
+
   buttonRef: HTMLElement
   listRef: HTMLElement
   listItemsRef: HTMLElement
@@ -129,23 +137,6 @@ class AutocompleteDropdown extends React.Component<Props, State> {
   buttonRect: ClientRect
   itemMouseDown: boolean
 
-  constructor() {
-    super()
-
-    this.state = {
-      showDropdownList: false,
-      firstItemHover: false,
-      searchValue: '',
-      filteredItems: [],
-    }
-
-    // $FlowIssue
-    this.handlePageClick = this.handlePageClick.bind(this)
-
-    // $FlowIssue
-    this.handleScroll = this.handleScroll.bind(this)
-  }
-
   componentWillMount() {
     this.setState({
       filteredItems: this.props.items,
@@ -218,6 +209,7 @@ class AutocompleteDropdown extends React.Component<Props, State> {
     })
   }
 
+  @autobind
   handleScroll() {
     if (this.buttonRef) {
       if (DomUtils.isElementInViewport(this.buttonRef, this.scrollableParent)) {
@@ -229,6 +221,7 @@ class AutocompleteDropdown extends React.Component<Props, State> {
     }
   }
 
+  @autobind
   handlePageClick() {
     if (!this.itemMouseDown) {
       this.setState({ showDropdownList: false })

+ 8 - 15
src/components/molecules/DatetimePicker/DatetimePicker.jsx

@@ -20,6 +20,7 @@ import { observer } from 'mobx-react'
 import styled, { injectGlobal } from 'styled-components'
 import Datetime from 'react-datetime'
 import moment from 'moment'
+import autobind from 'autobind-decorator'
 
 import DropdownButton from '../../atoms/DropdownButton'
 
@@ -63,26 +64,16 @@ type State = {
 }
 @observer
 class DatetimePicker extends React.Component<Props, State> {
+  state = {
+    showPicker: false,
+    date: null,
+  }
+
   itemMouseDown: boolean
   portalRef: HTMLElement
   buttonRef: HTMLElement
   scrollableParent: HTMLElement
 
-  constructor() {
-    super()
-
-    this.state = {
-      showPicker: false,
-      date: null,
-    }
-
-    // $FlowIssue
-    this.handlePageClick = this.handlePageClick.bind(this)
-
-    // $FlowIssue
-    this.handleScroll = this.handleScroll.bind(this)
-  }
-
   componentWillMount() {
     if (this.props.value) {
       this.setState({ date: moment(this.props.value) })
@@ -136,6 +127,7 @@ class DatetimePicker extends React.Component<Props, State> {
     return this.props.isValidDate(currentDate, selectedDate)
   }
 
+  @autobind
   handleScroll() {
     if (this.buttonRef) {
       if (DomUtils.isElementInViewport(this.buttonRef, this.scrollableParent)) {
@@ -146,6 +138,7 @@ class DatetimePicker extends React.Component<Props, State> {
     }
   }
 
+  @autobind
   handlePageClick(e: Event) {
     let path = DomUtils.getEventPath(e)
 

+ 8 - 15
src/components/molecules/Dropdown/Dropdown.jsx

@@ -18,6 +18,7 @@ import React from 'react'
 import { observer } from 'mobx-react'
 import styled, { css } from 'styled-components'
 import ReactDOM from 'react-dom'
+import autobind from 'autobind-decorator'
 
 import DropdownButton from '../../atoms/DropdownButton'
 
@@ -203,6 +204,11 @@ class Dropdown extends React.Component<Props, State> {
     noSelectionMessage: 'Select an item',
   }
 
+  state = {
+    showDropdownList: false,
+    firstItemHover: false,
+  }
+
   buttonRef: HTMLElement
   listRef: HTMLElement
   listItemsRef: HTMLElement
@@ -212,21 +218,6 @@ class Dropdown extends React.Component<Props, State> {
   buttonRect: ClientRect
   itemMouseDown: boolean
 
-  constructor() {
-    super()
-
-    this.state = {
-      showDropdownList: false,
-      firstItemHover: false,
-    }
-
-    // $FlowIssue
-    this.handlePageClick = this.handlePageClick.bind(this)
-
-    // $FlowIssue
-    this.handleScroll = this.handleScroll.bind(this)
-  }
-
   componentDidMount() {
     window.addEventListener('mousedown', this.handlePageClick, false)
     if (this.buttonRef) {
@@ -271,6 +262,7 @@ class Dropdown extends React.Component<Props, State> {
     return (item[valueField] != null && item[valueField].toString()) || this.getLabel(item)
   }
 
+  @autobind
   handleScroll() {
     if (this.buttonRef) {
       if (DomUtils.isElementInViewport(this.buttonRef, this.scrollableParent)) {
@@ -282,6 +274,7 @@ class Dropdown extends React.Component<Props, State> {
     }
   }
 
+  @autobind
   handlePageClick() {
     if (!this.itemMouseDown) {
       this.setState({ showDropdownList: false })

+ 6 - 11
src/components/molecules/DropdownFilter/DropdownFilter.jsx

@@ -17,6 +17,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 import React from 'react'
 import { observer } from 'mobx-react'
 import styled from 'styled-components'
+import autobind from 'autobind-decorator'
 
 import SearchInput from '../SearchInput'
 
@@ -81,19 +82,12 @@ class DropdownFilter extends React.Component<Props, State> {
     searchPlaceholder: 'Filter',
   }
 
-  itemMouseDown: boolean
-
-  constructor() {
-    super()
-
-    // $FlowIssue
-    this.handlePageClick = this.handlePageClick.bind(this)
-
-    this.state = {
-      showDropdownList: false,
-    }
+  state = {
+    showDropdownList: false,
   }
 
+  itemMouseDown: boolean
+
   componentDidMount() {
     window.addEventListener('mousedown', this.handlePageClick, false)
   }
@@ -102,6 +96,7 @@ class DropdownFilter extends React.Component<Props, State> {
     window.removeEventListener('mousedown', this.handlePageClick, false)
   }
 
+  @autobind
   handlePageClick() {
     if (!this.itemMouseDown) {
       this.setState({ showDropdownList: false })

+ 7 - 12
src/components/molecules/DropdownLink/DropdownLink.jsx

@@ -18,6 +18,7 @@ import React from 'react'
 import { observer } from 'mobx-react'
 import styled, { css } from 'styled-components'
 import ReactDOM from 'react-dom'
+import autobind from 'autobind-decorator'
 
 import SearchInput from '../../molecules/SearchInput'
 
@@ -151,6 +152,11 @@ class DropdownLink extends React.Component<Props, State> {
     noItemsLabel: 'No items',
   }
 
+  state = {
+    showDropdownList: false,
+    searchText: '',
+  }
+
   itemMouseDown: boolean
   labelRef: HTMLElement
   listItemsRef: HTMLElement
@@ -159,18 +165,6 @@ class DropdownLink extends React.Component<Props, State> {
   tipRef: HTMLElement
   searchInputWrapperRef: HTMLElement
 
-  constructor() {
-    super()
-
-    this.state = {
-      showDropdownList: false,
-      searchText: '',
-    }
-
-    const self: any = this
-    self.handlePageClick = this.handlePageClick.bind(this)
-  }
-
   componentDidMount() {
     window.addEventListener('mousedown', this.handlePageClick, false)
     this.setLabelWidth()
@@ -214,6 +208,7 @@ class DropdownLink extends React.Component<Props, State> {
     )
   }
 
+  @autobind
   handlePageClick() {
     if (!this.itemMouseDown) {
       this.setState({ showDropdownList: false })

+ 2 - 7
src/components/molecules/Modal/Modal.jsx

@@ -18,6 +18,7 @@ import * as React from 'react'
 import { observer } from 'mobx-react'
 import styled from 'styled-components'
 import Modal from 'react-modal'
+import autobind from 'autobind-decorator'
 
 import Palette from '../../styleUtils/Palette'
 import StyleProps from '../../styleUtils/StyleProps'
@@ -52,13 +53,6 @@ class NewModal extends React.Component<Props> {
   windowScrollY: number
   modalDiv: ?HTMLDivElement
 
-  constructor() {
-    super()
-
-    const self: any = this
-    self.positionModal = this.positionModal.bind(this)
-  }
-
   componentWillMount() {
     if (this.props.componentRef) {
       this.props.componentRef(this)
@@ -122,6 +116,7 @@ class NewModal extends React.Component<Props> {
     window.scroll(0, this.windowScrollY)
   }
 
+  @autobind
   positionModal(scrollOffset: number) {
     // $FlowIssue
     let pageNode = this.modalDiv && this.modalDiv.node.firstChild

+ 6 - 11
src/components/molecules/NewItemDropdown/NewItemDropdown.jsx

@@ -17,6 +17,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 import React from 'react'
 import { observer } from 'mobx-react'
 import styled from 'styled-components'
+import autobind from 'autobind-decorator'
 
 import DropdownButton from '../../atoms/DropdownButton'
 
@@ -135,19 +136,12 @@ type State = {
 }
 @observer
 class NewItemDropdown extends React.Component<Props, State> {
-  itemMouseDown: boolean
-
-  constructor() {
-    super()
-
-    this.state = {
-      showDropdownList: false,
-    }
-
-    // $FlowIssue
-    this.handlePageClick = this.handlePageClick.bind(this)
+  state = {
+    showDropdownList: false,
   }
 
+  itemMouseDown: boolean
+
   componentDidMount() {
     window.addEventListener('mousedown', this.handlePageClick, false)
   }
@@ -156,6 +150,7 @@ class NewItemDropdown extends React.Component<Props, State> {
     window.removeEventListener('mousedown', this.handlePageClick, false)
   }
 
+  @autobind
   handlePageClick() {
     if (!this.itemMouseDown) {
       this.setState({ showDropdownList: false })

+ 4 - 9
src/components/molecules/NotificationDropdown/NotificationDropdown.jsx

@@ -17,6 +17,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 import React from 'react'
 import { observer } from 'mobx-react'
 import styled, { css } from 'styled-components'
+import autobind from 'autobind-decorator'
 
 import Palette from '../../styleUtils/Palette'
 import StyleProps from '../../styleUtils/StyleProps'
@@ -179,19 +180,12 @@ type State = {
 const testId = 'notificationDropdown'
 @observer
 class NotificationDropdown extends React.Component<Props, State> {
-  itemMouseDown: boolean
-
-  constructor() {
-    super()
-
-    // $FlowIssue
-    this.handlePageClick = this.handlePageClick.bind(this)
-  }
-
   state = {
     showDropdownList: false,
   }
 
+  itemMouseDown: boolean
+
   componentDidMount() {
     window.addEventListener('mousedown', this.handlePageClick, false)
   }
@@ -205,6 +199,7 @@ class NotificationDropdown extends React.Component<Props, State> {
     this.props.onClose()
   }
 
+  @autobind
   handlePageClick() {
     if (!this.itemMouseDown) {
       if (this.state.showDropdownList) {

+ 12 - 16
src/components/molecules/SearchInput/SearchInput.jsx

@@ -17,6 +17,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 import React from 'react'
 import { observer } from 'mobx-react'
 import styled, { css } from 'styled-components'
+import autobind from 'autobind-decorator'
 
 import SearchButton from '../../atoms/SearchButton'
 import TextInput from '../../atoms/TextInput'
@@ -24,7 +25,7 @@ import StatusIcon from '../../atoms/StatusIcon'
 
 import StyleProps from '../../styleUtils/StyleProps'
 
-const Input = styled(TextInput) `
+const Input = styled(TextInput)`
   padding-left: 32px;
   ${props => props.loading || (props.showClose && props.value) ? 'padding-right: 32px;' : ''}
   width: 50px;
@@ -42,12 +43,12 @@ const Wrapper = styled.div`
   width: ${props => props.open ? props.width : '50px'};
   ${props => props.open ? InputAnimation(props) : ''}
 `
-const SearchButtonStyled = styled(SearchButton) `
+const SearchButtonStyled = styled(SearchButton)`
   position: absolute;
   top: 8px;
   left: 8px;
 `
-const StatusIconStyled = styled(StatusIcon) `
+const StatusIconStyled = styled(StatusIcon)`
   position: absolute;
   right: 8px;
   top: 8px;
@@ -69,7 +70,7 @@ type Props = {
 type State = {
   open: boolean,
   hover?: boolean,
-  focus?: boolean,
+  focus: boolean,
 }
 @observer
 class SearchInput extends React.Component<Props, State> {
@@ -79,21 +80,15 @@ class SearchInput extends React.Component<Props, State> {
     value: '',
   }
 
+  state = {
+    open: false,
+    value: '',
+    focus: false,
+  }
+
   input: HTMLElement
   itemMouseDown: boolean
 
-  constructor() {
-    super()
-
-    this.state = {
-      open: false,
-      value: '',
-    }
-
-    // $FlowIssue
-    this.handlePageClick = this.handlePageClick.bind(this)
-  }
-
   componentDidMount() {
     window.addEventListener('mousedown', this.handlePageClick, false)
 
@@ -104,6 +99,7 @@ class SearchInput extends React.Component<Props, State> {
     window.removeEventListener('mousedown', this.handlePageClick, false)
   }
 
+  @autobind
   handlePageClick() {
     if (!this.itemMouseDown) {
       this.setState({ open: false })

+ 2 - 6
src/components/molecules/SideMenu/SideMenu.jsx

@@ -91,12 +91,8 @@ type State = {
 }
 @observer
 class SideMenu extends React.Component<Props, State> {
-  constructor() {
-    super()
-
-    this.state = {
-      open: false,
-    }
+  state = {
+    open: false,
   }
 
   handleHamburgerClick() {

+ 6 - 11
src/components/molecules/UserDropdown/UserDropdown.jsx

@@ -17,6 +17,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 import React from 'react'
 import { observer } from 'mobx-react'
 import styled, { css } from 'styled-components'
+import autobind from 'autobind-decorator'
 
 import Palette from '../../styleUtils/Palette'
 import StyleProps from '../../styleUtils/StyleProps'
@@ -114,19 +115,12 @@ type State = {
 }
 @observer
 class UserDropdown extends React.Component<Props, State> {
-  itemMouseDown: boolean
-
-  constructor() {
-    super()
-
-    this.state = {
-      showDropdownList: false,
-    }
-
-    // $FlowIssue
-    this.handlePageClick = this.handlePageClick.bind(this)
+  state = {
+    showDropdownList: false,
   }
 
+  itemMouseDown: boolean
+
   componentDidMount() {
     window.addEventListener('mousedown', this.handlePageClick, false)
   }
@@ -143,6 +137,7 @@ class UserDropdown extends React.Component<Props, State> {
     this.setState({ showDropdownList: false })
   }
 
+  @autobind
   handlePageClick() {
     if (!this.itemMouseDown) {
       this.setState({ showDropdownList: false })

+ 5 - 9
src/components/organisms/AssessmentMigrationOptions/AssessmentMigrationOptions.jsx

@@ -40,7 +40,7 @@ const Image = styled.div`
 const Fields = styled.div`
   margin-top: 64px;
 `
-const WizardOptionsFieldStyled = styled(WizardOptionsField) `
+const WizardOptionsFieldStyled = styled(WizardOptionsField)`
   width: 319px;
   justify-content: space-between;
   margin-bottom: 32px;
@@ -91,14 +91,10 @@ type State = {
 }
 @observer
 class AssessmentMigrationOptions extends React.Component<Props, State> {
-  constructor() {
-    super()
-
-    this.state = {
-      generalFields: [...generalFields],
-      migrationFields: [...migrationFields],
-      replicaFields: [...replicaFields],
-    }
+  state = {
+    generalFields: [...generalFields],
+    migrationFields: [...migrationFields],
+    replicaFields: [...replicaFields],
   }
 
   handleValueChange(field: Field, value: any) {

+ 9 - 13
src/components/organisms/Endpoint/Endpoint.jsx

@@ -128,6 +128,14 @@ class Endpoint extends React.Component<Props, State> {
     cancelButtonText: 'Cancel',
   }
 
+  state = {
+    invalidFields: [],
+    validating: false,
+    showErrorMessage: false,
+    endpoint: null,
+    isNew: null,
+  }
+
   scrollableRef: HTMLElement
   closeTimeout: TimeoutID
   contentPluginRef: DefaultContentPlugin
@@ -135,18 +143,6 @@ class Endpoint extends React.Component<Props, State> {
   providerStoreObserver: () => void
   endpointValidationObserver: () => void
 
-  constructor() {
-    super()
-
-    this.state = {
-      invalidFields: [],
-      validating: false,
-      showErrorMessage: false,
-      endpoint: null,
-      isNew: null,
-    }
-  }
-
   componentWillMount() {
     this.componentWillReceiveProps(this.props)
     this.providerStoreObserver = observe(providerStore, 'connectionInfoSchema', () => {
@@ -222,7 +218,7 @@ class Endpoint extends React.Component<Props, State> {
   }
 
   handleFieldsChange(items: { field: Field, value: any }[]) {
-    let endpoint: EndpointType = { ...this.state.endpoint }
+    let endpoint: any = { ...this.state.endpoint }
 
     items.forEach(item => {
       endpoint[item.field.name] = item.value

+ 2 - 6
src/components/organisms/Executions/Executions.jsx

@@ -98,12 +98,8 @@ type State = {
 }
 @observer
 class Executions extends React.Component<Props, State> {
-  constructor() {
-    super()
-
-    this.state = {
-      selectedExecution: null,
-    }
+  state = {
+    selectedExecution: null,
   }
 
   componentWillMount() {

+ 7 - 10
src/components/organisms/FilterList/FilterList.jsx

@@ -49,19 +49,16 @@ type State = {
   filterStatus: string,
   filterText: string,
   selectedItems: any[],
-  selectAllSelected?: boolean,
+  selectAllSelected: boolean,
 }
 @observer
 class FilterList extends React.Component<Props, State> {
-  constructor() {
-    super()
-
-    this.state = {
-      items: [],
-      filterStatus: 'all',
-      filterText: '',
-      selectedItems: [],
-    }
+  state = {
+    items: [],
+    filterStatus: 'all',
+    filterText: '',
+    selectedItems: [],
+    selectAllSelected: false,
   }
 
   componentWillMount() {

+ 3 - 7
src/components/organisms/LoginForm/LoginForm.jsx

@@ -99,13 +99,9 @@ class LoginForm extends React.Component<Props, State> {
     className: '',
   }
 
-  constructor() {
-    super()
-
-    this.state = {
-      username: '',
-      password: '',
-    }
+  state = {
+    username: '',
+    password: '',
   }
 
   handleUsernameChange(username: string) {

+ 1 - 6
src/components/organisms/Notifications/Notifications.jsx

@@ -33,13 +33,8 @@ const Wrapper = styled.div``
 
 @observer
 class Notifications extends React.Component<{}> {
-  notificationsCount: number
   notificationSystem: NotificationSystem
-
-  constructor() {
-    super()
-    this.notificationsCount = 0
-  }
+  notificationsCount = 0
 
   componentDidMount() {
     observe(notificationStore.alerts, change => {

+ 9 - 12
src/components/organisms/PageHeader/PageHeader.jsx

@@ -71,24 +71,21 @@ type State = {
   showEndpointModal: boolean,
   showUserModal: boolean,
   showProjectModal: boolean,
-  providerType?: string,
+  providerType: ?string,
 }
 @observer
 class PageHeader extends React.Component<Props, State> {
+  state = {
+    showChooseProviderModal: false,
+    showEndpointModal: false,
+    showUserModal: false,
+    showProjectModal: false,
+    providerType: null,
+  }
+
   pollTimeout: TimeoutID
   stopPolling: boolean
 
-  constructor() {
-    super()
-
-    this.state = {
-      showChooseProviderModal: false,
-      showEndpointModal: false,
-      showUserModal: false,
-      showProjectModal: false,
-    }
-  }
-
   componentWillMount() {
     this.stopPolling = false
     this.pollData()

+ 2 - 2
src/components/organisms/ProjectDetailsContent/ProjectDetailsContent.jsx

@@ -114,13 +114,13 @@ type State = {
 const testName = 'pdContent'
 @observer
 class ProjectDetailsContent extends React.Component<Props, State> {
-  selectedUser: ?User
-
   state = {
     showRemoveUserAlert: false,
     showDeleteProjectAlert: false,
   }
 
+  selectedUser: ?User
+
   handleRemoveUserAction(user: User) {
     this.selectedUser = user
     this.setState({ showRemoveUserAlert: true })

+ 2 - 6
src/components/organisms/ReplicaDetailsContent/ReplicaDetailsContent.jsx

@@ -91,12 +91,8 @@ type State = {
 }
 @observer
 class ReplicaDetailsContent extends React.Component<Props, State> {
-  constructor() {
-    super()
-
-    this.state = {
-      timezone: 'local',
-    }
+  state = {
+    timezone: 'local',
   }
 
   getLastExecution() {

+ 2 - 6
src/components/organisms/ReplicaExecutionOptions/ReplicaExecutionOptions.jsx

@@ -69,12 +69,8 @@ class ReplicaExecutionOptions extends React.Component<Props, State> {
     executionLabel: 'Execute',
   }
 
-  constructor() {
-    super()
-
-    this.state = {
-      fields: [...executionOptions],
-    }
+  state = {
+    fields: [...executionOptions],
   }
 
   componentDidMount() {

+ 18 - 21
src/components/organisms/ReplicaMigrationOptions/ReplicaMigrationOptions.jsx

@@ -50,7 +50,7 @@ const Buttons = styled.div`
   justify-content: space-between;
   width: 100%;
 `
-const WizardOptionsFieldStyled = styled(WizardOptionsField) `
+const WizardOptionsFieldStyled = styled(WizardOptionsField)`
   width: 319px;
   justify-content: space-between;
   margin-bottom: 32px;
@@ -63,28 +63,25 @@ type Props = {
 type State = {
   fields: Field[],
 }
+let defaultFields: Field[] = [
+  {
+    name: 'clone_disks',
+    type: 'strict-boolean',
+    value: true,
+  },
+  {
+    name: 'force',
+    type: 'strict-boolean',
+  },
+  {
+    name: 'skip_os_morphing',
+    type: 'strict-boolean',
+  },
+]
 @observer
 class ReplicaMigrationOptions extends React.Component<Props, State> {
-  constructor() {
-    super()
-
-    this.state = {
-      fields: [
-        {
-          name: 'clone_disks',
-          type: 'strict-boolean',
-          value: true,
-        },
-        {
-          name: 'force',
-          type: 'strict-boolean',
-        },
-        {
-          name: 'skip_os_morphing',
-          type: 'strict-boolean',
-        },
-      ],
-    }
+  state = {
+    fields: defaultFields,
   }
 
   componentDidMount() {

+ 5 - 9
src/components/organisms/Schedule/Schedule.jsx

@@ -134,15 +134,11 @@ class Schedule extends React.Component<Props, State> {
     unsavedSchedules: [],
   }
 
-  constructor() {
-    super()
-
-    this.state = {
-      showOptionsModal: false,
-      showDeleteConfirmation: false,
-      selectedSchedule: null,
-      executionOptions: null,
-    }
+  state = {
+    showOptionsModal: false,
+    showDeleteConfirmation: false,
+    selectedSchedule: null,
+    executionOptions: null,
   }
 
   handleDeleteClick(selectedSchedule: ScheduleType) {

+ 4 - 8
src/components/organisms/Tasks/Tasks.jsx

@@ -51,16 +51,12 @@ type State = {
 }
 @observer
 class Tasks extends React.Component<Props, State> {
-  dragStartPosition: ?{ x: number, y: number }
-
-  constructor() {
-    super()
-
-    this.state = {
-      openedItems: [],
-    }
+  state = {
+    openedItems: [],
   }
 
+  dragStartPosition: ?{ x: number, y: number }
+
   componentWillMount() {
     this.componentWillReceiveProps(this.props)
   }

+ 5 - 9
src/components/organisms/WizardInstances/WizardInstances.jsx

@@ -62,7 +62,7 @@ const InstanceContent = styled.div`
     background: ${Palette.grayscale[1]};
   }
 `
-const CheckboxStyled = styled(Checkbox) `
+const CheckboxStyled = styled(Checkbox)`
   opacity: 0;
   transition: all ${StyleProps.animations.swift};
 `
@@ -201,16 +201,12 @@ type State = {
 }
 @observer
 class WizardInstances extends React.Component<Props, State> {
-  timeout: TimeoutID
-
-  constructor() {
-    super()
-
-    this.state = {
-      searchText: '',
-    }
+  state = {
+    searchText: '',
   }
 
+  timeout: TimeoutID
+
   handleSeachInputChange(searchText: string) {
     this.setState({ searchText })
 

+ 2 - 7
src/components/organisms/WizardOptions/WizardOptions.jsx

@@ -17,6 +17,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 import React from 'react'
 import styled from 'styled-components'
 import { observer } from 'mobx-react'
+import autobind from 'autobind-decorator'
 
 import Tooltip from '../../atoms/Tooltip'
 import StyleProps from '../../styleUtils/StyleProps'
@@ -66,13 +67,6 @@ type Props = {
 }
 @observer
 class WizardOptions extends React.Component<Props> {
-  constructor() {
-    super()
-
-    // $FlowIssue
-    this.handleResize = this.handleResize.bind(this)
-  }
-
   componentDidMount() {
     window.addEventListener('resize', this.handleResize)
   }
@@ -124,6 +118,7 @@ class WizardOptions extends React.Component<Props> {
     return fieldsSchema
   }
 
+  @autobind
   handleResize() {
     this.setState({})
   }

+ 3 - 7
src/components/organisms/WizardPageContent/WizardPageContent.jsx

@@ -125,13 +125,9 @@ type State = {
 const testName = 'wpContent'
 @observer
 class WizardPageContent extends React.Component<Props, State> {
-  constructor() {
-    super()
-
-    this.state = {
-      useAdvancedOptions: false,
-      timezone: 'local',
-    }
+  state = {
+    useAdvancedOptions: false,
+    timezone: 'local',
   }
 
   componentDidMount() {

+ 8 - 12
src/components/pages/AssessmentDetailsPage/AssessmentDetailsPage.jsx

@@ -57,18 +57,14 @@ type State = {
 }
 @observer
 class AssessmentDetailsPage extends React.Component<Props, State> {
-  constructor() {
-    super()
-
-    this.state = {
-      sourceEndpoint: null,
-      selectedVms: [],
-      selectedNetworks: [],
-      showMigrationOptions: false,
-      executeButtonDisabled: false,
-      vmSizes: {},
-      vmSearchValue: '',
-    }
+  state = {
+    sourceEndpoint: null,
+    selectedVms: [],
+    selectedNetworks: [],
+    showMigrationOptions: false,
+    executeButtonDisabled: false,
+    vmSizes: {},
+    vmSearchValue: '',
   }
 
   componentWillMount() {

+ 3 - 3
src/components/pages/AssessmentsPage/AssessmentsPage.jsx

@@ -41,13 +41,13 @@ type Props = {}
 type State = { modalIsOpen: boolean }
 @observer
 class AssessmentsPage extends React.Component<Props, State> {
-  disablePolling: boolean
-  pollTimeout: TimeoutID
-
   state = {
     modalIsOpen: false,
   }
 
+  disablePolling: boolean
+  pollTimeout: TimeoutID
+
   componentWillMount() {
     document.title = 'Coriolis Planning'
 

+ 7 - 11
src/components/pages/EndpointDetailsPage/EndpointDetailsPage.jsx

@@ -51,17 +51,13 @@ type State = {
 }
 @observer
 class EndpointDetailsPage extends React.Component<Props, State> {
-  constructor() {
-    super()
-
-    this.state = {
-      showDeleteEndpointConfirmation: false,
-      showValidationModal: false,
-      showEndpointModal: false,
-      showEndpointInUseModal: false,
-      showEndpointInUseLoadingModal: false,
-      endpointUsage: { replicas: [], migrations: [] },
-    }
+  state = {
+    showDeleteEndpointConfirmation: false,
+    showValidationModal: false,
+    showEndpointModal: false,
+    showEndpointInUseModal: false,
+    showEndpointInUseLoadingModal: false,
+    endpointUsage: { replicas: [], migrations: [] },
   }
 
   componentDidMount() {

+ 12 - 16
src/components/pages/EndpointsPage/EndpointsPage.jsx

@@ -63,25 +63,21 @@ type State = {
 }
 @observer
 class EndpointsPage extends React.Component<{}, State> {
+  state = {
+    showDeleteEndpointsConfirmation: false,
+    confirmationItems: null,
+    showChooseProviderModal: false,
+    showEndpointModal: false,
+    providerType: null,
+    showEndpointsInUseModal: false,
+    modalIsOpen: false,
+    showDuplicateModal: false,
+    duplicating: false,
+  }
+
   pollTimeout: TimeoutID
   stopPolling: boolean
 
-  constructor() {
-    super()
-
-    this.state = {
-      showDeleteEndpointsConfirmation: false,
-      confirmationItems: null,
-      showChooseProviderModal: false,
-      showEndpointModal: false,
-      providerType: null,
-      showEndpointsInUseModal: false,
-      modalIsOpen: false,
-      showDuplicateModal: false,
-      duplicating: false,
-    }
-  }
-
   componentDidMount() {
     document.title = 'Coriolis Endpoints'
 

+ 5 - 9
src/components/pages/MigrationDetailsPage/MigrationDetailsPage.jsx

@@ -43,17 +43,13 @@ type State = {
 }
 @observer
 class MigrationDetailsPage extends React.Component<Props, State> {
-  pollInterval: IntervalID
-
-  constructor() {
-    super()
-
-    this.state = {
-      showDeleteMigrationConfirmation: false,
-      showCancelConfirmation: false,
-    }
+  state = {
+    showDeleteMigrationConfirmation: false,
+    showCancelConfirmation: false,
   }
 
+  pollInterval: IntervalID
+
   componentDidMount() {
     document.title = 'Migration Details'
 

+ 7 - 11
src/components/pages/MigrationsPage/MigrationsPage.jsx

@@ -50,20 +50,16 @@ type State = {
 }
 @observer
 class MigrationsPage extends React.Component<{}, State> {
+  state = {
+    showDeleteMigrationConfirmation: false,
+    showCancelMigrationConfirmation: false,
+    confirmationItems: null,
+    modalIsOpen: false,
+  }
+
   pollTimeout: TimeoutID
   stopPolling: boolean
 
-  constructor() {
-    super()
-
-    this.state = {
-      showDeleteMigrationConfirmation: false,
-      showCancelMigrationConfirmation: false,
-      confirmationItems: null,
-      modalIsOpen: false,
-    }
-  }
-
   componentDidMount() {
     document.title = 'Coriolis Migrations'
 

+ 3 - 3
src/components/pages/ProjectsPage/ProjectsPage.jsx

@@ -37,13 +37,13 @@ type State = {
 }
 @observer
 class ProjectsPage extends React.Component<{}, State> {
-  pollTimeout: TimeoutID
-  stopPolling: boolean
-
   state = {
     modalIsOpen: false,
   }
 
+  pollTimeout: TimeoutID
+  stopPolling: boolean
+
   componentDidMount() {
     document.title = 'Projects'
 

+ 10 - 14
src/components/pages/ReplicaDetailsPage/ReplicaDetailsPage.jsx

@@ -56,22 +56,18 @@ type State = {
 }
 @observer
 class ReplicaDetailsPage extends React.Component<Props, State> {
-  pollTimeout: TimeoutID
-
-  constructor() {
-    super()
-
-    this.state = {
-      showOptionsModal: false,
-      showMigrationModal: false,
-      showDeleteExecutionConfirmation: false,
-      showDeleteReplicaConfirmation: false,
-      showDeleteReplicaDisksConfirmation: false,
-      confirmationItem: null,
-      showCancelConfirmation: false,
-    }
+  state = {
+    showOptionsModal: false,
+    showMigrationModal: false,
+    showDeleteExecutionConfirmation: false,
+    showDeleteReplicaConfirmation: false,
+    showDeleteReplicaDisksConfirmation: false,
+    confirmationItem: null,
+    showCancelConfirmation: false,
   }
 
+  pollTimeout: TimeoutID
+
   componentDidMount() {
     document.title = 'Replica Details'
 

+ 6 - 10
src/components/pages/ReplicasPage/ReplicasPage.jsx

@@ -49,19 +49,15 @@ type State = {
 }
 @observer
 class ReplicasPage extends React.Component<{}, State> {
+  state = {
+    showDeleteReplicaConfirmation: false,
+    confirmationItems: null,
+    modalIsOpen: false,
+  }
+
   pollTimeout: TimeoutID
   stopPolling: boolean
 
-  constructor() {
-    super()
-
-    this.state = {
-      showDeleteReplicaConfirmation: false,
-      confirmationItems: null,
-      modalIsOpen: false,
-    }
-  }
-
   componentDidMount() {
     document.title = 'Coriolis Replicas'
 

+ 3 - 3
src/components/pages/UsersPage/UsersPage.jsx

@@ -37,13 +37,13 @@ type State = {
 }
 @observer
 class UsersPage extends React.Component<{}, State> {
-  pollTimeout: TimeoutID
-  stopPolling: boolean
-
   state = {
     modalIsOpen: false,
   }
 
+  pollTimeout: TimeoutID
+  stopPolling: boolean
+
   componentDidMount() {
     document.title = 'Users'
 

+ 8 - 11
src/components/pages/WizardPage/WizardPage.jsx

@@ -54,23 +54,20 @@ type State = {
   type: WizardType,
   showNewEndpointModal: boolean,
   nextButtonDisabled: boolean,
-  newEndpointType?: string,
+  newEndpointType: ?string,
   newEndpointFromSource?: boolean,
 }
 @observer
 class WizardPage extends React.Component<Props, State> {
-  contentRef: WizardPageContent
-
-  constructor() {
-    super()
-
-    this.state = {
-      type: 'migration',
-      showNewEndpointModal: false,
-      nextButtonDisabled: false,
-    }
+  state = {
+    type: 'migration',
+    showNewEndpointModal: false,
+    nextButtonDisabled: false,
+    newEndpointType: null,
   }
 
+  contentRef: WizardPageContent
+
   componentWillMount() {
     this.initializeState()
   }

+ 5 - 9
src/plugins/endpoint/azure/ContentPlugin.jsx

@@ -82,18 +82,14 @@ type State = {
   showPasteInput: boolean,
 }
 class ContentPlugin extends React.Component<Props, State> {
+  state = {
+    jsonConfig: '',
+    showPasteInput: false,
+  }
+
   cloudProfileChanged: boolean
   lastBlurValue: string
 
-  constructor() {
-    super()
-
-    this.state = {
-      jsonConfig: '',
-      showPasteInput: false,
-    }
-  }
-
   componentDidMount() {
     this.props.onRef(this)
   }

+ 5 - 8
src/plugins/endpoint/openstack/ContentPlugin.jsx

@@ -21,7 +21,7 @@ import ToggleButtonBar from '../../../components/atoms/ToggleButtonBar'
 import type { Field } from '../../../types/Field'
 import { Wrapper, Fields, FieldStyled, Row } from '../default/ContentPlugin'
 
-const ToggleButtonBarStyled = styled(ToggleButtonBar) `
+const ToggleButtonBarStyled = styled(ToggleButtonBar)`
   margin-top: 16px;
 `
 
@@ -42,13 +42,12 @@ type State = {
   useAdvancedOptions: boolean,
 }
 class ContentPlugin extends React.Component<Props, State> {
-  constructor() {
-    super()
-    this.state = {
-      useAdvancedOptions: false,
-    }
+  state = {
+    useAdvancedOptions: false,
   }
 
+  previouslySelectedChoices: string[] = []
+
   componentDidMount() {
     this.props.onRef(this)
   }
@@ -96,8 +95,6 @@ class ContentPlugin extends React.Component<Props, State> {
     this.setState({ useAdvancedOptions })
   }
 
-  previouslySelectedChoices: string[] = []
-
   findInvalidFields = () => {
     let inputChoices = ['user_domain', 'project_domain']
 

+ 31 - 8
yarn.lock

@@ -621,6 +621,10 @@ asynckit@^0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
 
+autobind-decorator@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/autobind-decorator/-/autobind-decorator-2.1.0.tgz#4451240dbfeff46361c506575a63ed40f0e5bc68"
+
 autoprefixer@^6.3.1:
   version "6.7.7"
   resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014"
@@ -2883,6 +2887,12 @@ doctrine@^2.0.0:
     esutils "^2.0.2"
     isarray "^1.0.0"
 
+doctrine@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
+  dependencies:
+    esutils "^2.0.2"
+
 dom-converter@~0.1:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.1.4.tgz#a45ef5727b890c9bffe6d7c876e7b19cb0e17f3b"
@@ -3273,14 +3283,14 @@ eslint-plugin-jsx-a11y@^6.0.2:
     emoji-regex "^6.1.0"
     jsx-ast-utils "^1.4.0"
 
-eslint-plugin-react@^7.4.0:
-  version "7.4.0"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.4.0.tgz#300a95861b9729c087d362dd64abcc351a74364a"
+eslint-plugin-react@7.10.0:
+  version "7.10.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.10.0.tgz#af5c1fef31c4704db02098f9be18202993828b50"
   dependencies:
-    doctrine "^2.0.0"
-    has "^1.0.1"
-    jsx-ast-utils "^2.0.0"
-    prop-types "^15.5.10"
+    doctrine "^2.1.0"
+    has "^1.0.3"
+    jsx-ast-utils "^2.0.1"
+    prop-types "^15.6.2"
 
 eslint-restricted-globals@^0.1.1:
   version "0.1.1"
@@ -4088,6 +4098,12 @@ has@^1.0.1:
   dependencies:
     function-bind "^1.0.2"
 
+has@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+  dependencies:
+    function-bind "^1.1.1"
+
 hash-base@^2.0.0:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1"
@@ -5080,7 +5096,7 @@ jsx-ast-utils@^1.4.0:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz#3867213e8dd79bf1e8f2300c0cfc1efb182c0df1"
 
-jsx-ast-utils@^2.0.0:
+jsx-ast-utils@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz#e801b1b39985e20fffc87b40e3748080e2dcac7f"
   dependencies:
@@ -6601,6 +6617,13 @@ prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.7,
     loose-envify "^1.3.1"
     object-assign "^4.1.1"
 
+prop-types@^15.6.2:
+  version "15.6.2"
+  resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102"
+  dependencies:
+    loose-envify "^1.3.1"
+    object-assign "^4.1.1"
+
 proxy-addr@~2.0.2:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec"