Browse Source

Merge pull request #181 from smiclea/flow

Add 'flow' support to 'utils' files
Dorin Paslaru 8 years ago
parent
commit
c4587a8a6f

+ 1 - 1
src/components/molecules/SideMenu/index.jsx

@@ -110,7 +110,7 @@ class SideMenu extends React.Component<Props, State> {
           dangerouslySetInnerHTML={{ __html: hamburgerImage() }}
           dangerouslySetInnerHTML={{ __html: hamburgerImage() }}
         />
         />
         <Menu open={this.state.open}>
         <Menu open={this.state.open}>
-          {navigationMenu.filter(i => !i.disabled).map(item => {
+          {navigationMenu.filter(i => i.disabled ? !i.disabled : true).map(item => {
             return (
             return (
               <MenuItem key={item.value} href={`/#/${item.value}`}>{item.label}</MenuItem>
               <MenuItem key={item.value} href={`/#/${item.value}`}>{item.label}</MenuItem>
             )
             )

+ 1 - 1
src/components/organisms/Navigation/index.jsx

@@ -51,7 +51,7 @@ class Navigation extends React.Component<{currentPage: string}> {
   renderMenu() {
   renderMenu() {
     return (
     return (
       <Menu>
       <Menu>
-        {navigationMenu.filter(i => !i.disabled).map(item => {
+        {navigationMenu.filter(i => i.disabled ? !i.disabled : true).map(item => {
           return (
           return (
             <MenuItem
             <MenuItem
               key={item.value}
               key={item.value}

+ 2 - 0
src/config.js

@@ -12,6 +12,8 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 */
 
 
+// @flow
+
 export const coriolisUrl = (window.env && window.env.CORIOLIS_URL) || '/'
 export const coriolisUrl = (window.env && window.env.CORIOLIS_URL) || '/'
 
 
 export const servicesUrl = {
 export const servicesUrl = {

+ 1 - 1
src/index.js

@@ -24,7 +24,7 @@ import App from './components/App.jsx'
 
 
 const renderApp = () => React.createElement(
 const renderApp = () => React.createElement(
   HashRouter,
   HashRouter,
-  { basename },
+  { basename: basename || '' },
   React.createElement(App, null)
   React.createElement(App, null)
 )
 )
 
 

+ 1 - 1
src/sources/UserSource.js

@@ -87,7 +87,7 @@ class UserSource {
       },
       },
     }
     }
 
 
-    Api.setDefaultHeader({ 'X-Auth-Token': null })
+    Api.setDefaultHeader('X-Auth-Token', null)
 
 
     return new Promise((resolve, reject) => {
     return new Promise((resolve, reject) => {
       Api.sendAjaxRequest({
       Api.sendAjaxRequest({

+ 1 - 0
src/types/Schedule.js

@@ -27,4 +27,5 @@ export type Schedule = {
   enabled?: ?boolean,
   enabled?: ?boolean,
   schedule?: ScheduleInfo,
   schedule?: ScheduleInfo,
   expiration_date?: Date,
   expiration_date?: Date,
+  shutdown_instances?: boolean,
 }
 }

+ 23 - 7
src/utils/ApiCaller.js

@@ -12,10 +12,24 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 */
 
 
+// @flow
+
 import NotificationStore from '../stores/NotificationStore'
 import NotificationStore from '../stores/NotificationStore'
 
 
 let apiInstance = null
 let apiInstance = null
 
 
+type RequestOptions = {
+  method: string,
+  url: string,
+  requestId?: string,
+  headers?: {[string]: mixed},
+}
+
+type RequestInfo = {
+  requestId: string,
+  request: XMLHttpRequest,
+}
+
 class ApiCaller {
 class ApiCaller {
   defaultHeaders = {
   defaultHeaders = {
     'Content-Type': 'application/json',
     'Content-Type': 'application/json',
@@ -31,19 +45,19 @@ class ApiCaller {
     return apiInstance
     return apiInstance
   }
   }
 
 
-  addRequest(request) {
-    this.requests.unshift(request)
+  addRequest(requestInfo: RequestInfo) {
+    this.requests.unshift(requestInfo)
     if (this.requests.length > 100) {
     if (this.requests.length > 100) {
       this.requests.pop()
       this.requests.pop()
     }
     }
   }
   }
 
 
-  cancelRequest(requestInfo) {
+  cancelRequest(requestInfo: RequestInfo) {
     requestInfo.request.abort()
     requestInfo.request.abort()
     this.requests = this.requests.filter(r => r.requestId !== requestInfo.requestId)
     this.requests = this.requests.filter(r => r.requestId !== requestInfo.requestId)
   }
   }
 
 
-  sendAjaxRequest(options) {
+  sendAjaxRequest(options: RequestOptions): Promise<any> {
     return new Promise((resolve, reject) => {
     return new Promise((resolve, reject) => {
       let request = new XMLHttpRequest()
       let request = new XMLHttpRequest()
 
 
@@ -57,7 +71,7 @@ class ApiCaller {
 
 
       if (options.headers) {
       if (options.headers) {
         Object.keys(options.headers).forEach((key) => {
         Object.keys(options.headers).forEach((key) => {
-          headers[key] = options.headers[key]
+          headers[key] = options.headers ? options.headers[key] : ''
         })
         })
       }
       }
 
 
@@ -111,6 +125,7 @@ class ApiCaller {
 
 
           if (result.data && result.data.error && result.data.error.message &&
           if (result.data && result.data.error && result.data.error.message &&
             (result.status !== 401 || window.location.hash !== loginUrl)) {
             (result.status !== 401 || window.location.hash !== loginUrl)) {
+            // $FlowIgnore
             NotificationStore.notify(result.data.error.message, 'error')
             NotificationStore.notify(result.data.error.message, 'error')
           }
           }
 
 
@@ -129,6 +144,7 @@ class ApiCaller {
           connection to the server.`, 'error')
           connection to the server.`, 'error')
         }
         }
 
 
+        // $FlowIgnore
         console.log('%cError Response: ', 'color: #D0021B', result.data) // eslint-disable-line no-console
         console.log('%cError Response: ', 'color: #D0021B', result.data) // eslint-disable-line no-console
         reject({ status: 500, data: 'Connection error' })
         reject({ status: 500, data: 'Connection error' })
       }
       }
@@ -141,7 +157,7 @@ class ApiCaller {
     }
     }
   }
   }
 
 
-  static processHeaders(rawHeaders) {
+  static processHeaders(rawHeaders: string) {
     let headers = {}
     let headers = {}
     let lines = rawHeaders.split('\n')
     let lines = rawHeaders.split('\n')
     lines.forEach((line) => {
     lines.forEach((line) => {
@@ -153,7 +169,7 @@ class ApiCaller {
     return headers
     return headers
   }
   }
 
 
-  setDefaultHeader(name, value) {
+  setDefaultHeader(name: string, value: ?string) {
     if (value == null) {
     if (value == null) {
       delete this.defaultHeaders[name]
       delete this.defaultHeaders[name]
     } else {
     } else {

+ 12 - 3
src/utils/AzureApiCaller.js

@@ -12,13 +12,22 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 */
 
 
+// @flow
+
 import request from 'ajax-request'
 import request from 'ajax-request'
 
 
 let apiInstance = null
 let apiInstance = null
 let defaultApiVersion = '2017-11-11-preview'
 let defaultApiVersion = '2017-11-11-preview'
 let azureUrl = 'https://management.azure.com/'
 let azureUrl = 'https://management.azure.com/'
 
 
+type RequestOptions = {
+  headers?: {[string]: mixed},
+  url: string,
+}
+
 class AzureApiCaller {
 class AzureApiCaller {
+  headers: {[string]: mixed}
+
   constructor() {
   constructor() {
     if (!apiInstance) {
     if (!apiInstance) {
       apiInstance = this
       apiInstance = this
@@ -29,12 +38,12 @@ class AzureApiCaller {
     return apiInstance
     return apiInstance
   }
   }
 
 
-  rejectError(error, reject) {
+  rejectError(error: string, reject: (error: any) => void) {
     console.error('%c', 'color: #D0021B', error) // eslint-disable-line no-console
     console.error('%c', 'color: #D0021B', error) // eslint-disable-line no-console
     reject(error)
     reject(error)
   }
   }
 
 
-  send(options, apiVersion) {
+  send(options: RequestOptions, apiVersion?: string): Promise<any> {
     return new Promise((resolve, reject) => {
     return new Promise((resolve, reject) => {
       options.headers = {
       options.headers = {
         ...options.headers,
         ...options.headers,
@@ -74,7 +83,7 @@ class AzureApiCaller {
     })
     })
   }
   }
 
 
-  setHeader(name, value) {
+  setHeader(name: string, value: ?string) {
     this.headers[name] = value
     this.headers[name] = value
   }
   }
 }
 }

+ 11 - 7
src/utils/DomUtils.js

@@ -12,15 +12,19 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 */
 
 
+// @flow
+
 class DomUtils {
 class DomUtils {
-  static getEventPath(event) {
+  static getEventPath(event: Event): HTMLElement[] {
     let path = []
     let path = []
     let node = event.target
     let node = event.target
     while (node !== document.body && node.parentNode) {
     while (node !== document.body && node.parentNode) {
       path.push(node)
       path.push(node)
+      // $FlowIssue
       node = node.parentNode
       node = node.parentNode
     }
     }
 
 
+    // $FlowIgnore
     return path
     return path
   }
   }
 
 
@@ -29,14 +33,14 @@ class DomUtils {
    * @param {string} text The text to copy
    * @param {string} text The text to copy
    * @return True if successful, false otherwise
    * @return True if successful, false otherwise
    */
    */
-  static copyTextToClipboard(text) {
+  static copyTextToClipboard(text: string): boolean {
     let textArea = document.createElement('textarea')
     let textArea = document.createElement('textarea')
     textArea.style.position = 'fixed'
     textArea.style.position = 'fixed'
-    textArea.style.top = 0
-    textArea.style.left = 0
+    textArea.style.top = '0'
+    textArea.style.left = '0'
     textArea.style.width = '2em'
     textArea.style.width = '2em'
     textArea.style.height = '2em'
     textArea.style.height = '2em'
-    textArea.style.padding = 0
+    textArea.style.padding = '0'
     textArea.style.border = 'none'
     textArea.style.border = 'none'
     textArea.style.outline = 'none'
     textArea.style.outline = 'none'
     textArea.style.boxShadow = 'none'
     textArea.style.boxShadow = 'none'
@@ -44,7 +48,7 @@ class DomUtils {
 
 
     textArea.value = text
     textArea.value = text
 
 
-    document.body.appendChild(textArea)
+    if (document.body) document.body.appendChild(textArea)
 
 
     textArea.select()
     textArea.select()
 
 
@@ -55,7 +59,7 @@ class DomUtils {
     } catch (e) {
     } catch (e) {
       successful = false
       successful = false
     } finally {
     } finally {
-      document.body.removeChild(textArea)
+      if (document.body) document.body.removeChild(textArea)
     }
     }
     return successful
     return successful
   }
   }

+ 7 - 5
src/utils/KeyboardManager.js

@@ -12,6 +12,8 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 */
 
 
+// @flow
+
 let eventAdded = false
 let eventAdded = false
 let listeners = []
 let listeners = []
 const keyDownHandler = evt => {
 const keyDownHandler = evt => {
@@ -24,10 +26,10 @@ const keyDownHandler = evt => {
 }
 }
 export default class KeyboardManager {
 export default class KeyboardManager {
   static eventAdded = false
   static eventAdded = false
-  static onKeyDown(id, callback, priority) {
+  static onKeyDown(id: string, callback: ?(event: KeyboardEvent) => void, priority?: number) {
     if (!eventAdded) {
     if (!eventAdded) {
       eventAdded = true
       eventAdded = true
-      document.addEventListener('keydown', evt => { keyDownHandler(evt) })
+      document.addEventListener('keydown', (evt: KeyboardEvent) => { keyDownHandler(evt) })
     }
     }
 
 
     let listener = listeners.find(l => l.id === id)
     let listener = listeners.find(l => l.id === id)
@@ -37,7 +39,7 @@ export default class KeyboardManager {
     listeners.push({ id, callback, priority: priority || 0 })
     listeners.push({ id, callback, priority: priority || 0 })
   }
   }
 
 
-  static onEnter(id, callback, priority) {
+  static onEnter(id: string, callback: (evt: KeyboardEvent) => void, priority?: number) {
     this.onKeyDown(`${id}-enter`, evt => {
     this.onKeyDown(`${id}-enter`, evt => {
       if (evt.keyCode === 13) {
       if (evt.keyCode === 13) {
         callback(evt)
         callback(evt)
@@ -45,7 +47,7 @@ export default class KeyboardManager {
     }, priority)
     }, priority)
   }
   }
 
 
-  static onEsc(id, callback, priority) {
+  static onEsc(id: string, callback: (evt: KeyboardEvent) => void, priority?: number) {
     this.onKeyDown(`${id}-esc`, evt => {
     this.onKeyDown(`${id}-esc`, evt => {
       if (evt.keyCode === 27) {
       if (evt.keyCode === 27) {
         callback(evt)
         callback(evt)
@@ -53,7 +55,7 @@ export default class KeyboardManager {
     }, priority)
     }, priority)
   }
   }
 
 
-  static removeKeyDown(id) {
+  static removeKeyDown(id: string) {
     listeners = listeners.filter(l => l.id !== id && l.id !== `${id}-enter` && l.id !== `${id}-esc`)
     listeners = listeners.filter(l => l.id !== id && l.id !== `${id}-enter` && l.id !== `${id}-esc`)
   }
   }
 }
 }

+ 6 - 4
src/utils/LabelDictionary.js

@@ -12,6 +12,8 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 */
 
 
+// @flow
+
 class LabelDictionary {
 class LabelDictionary {
   static dictionary = {
   static dictionary = {
     username: 'Username',
     username: 'Username',
@@ -97,8 +99,8 @@ class LabelDictionary {
     use_replica: 'Use replica',
     use_replica: 'Use replica',
   }
   }
 
 
-  static get(fieldName) {
-    let labelInfo = this.dictionary[fieldName]
+  static get(fieldName: ?string): string {
+    let labelInfo = fieldName ? this.dictionary[fieldName] : null
     if (labelInfo) {
     if (labelInfo) {
       if (typeof labelInfo === 'string') {
       if (typeof labelInfo === 'string') {
         return labelInfo
         return labelInfo
@@ -108,12 +110,12 @@ class LabelDictionary {
       }
       }
     }
     }
 
 
-    let words = fieldName.split('_')
+    let words = fieldName ? fieldName.split('_') : []
     words = words.map(word => word.charAt(0).toUpperCase() + word.substr(1))
     words = words.map(word => word.charAt(0).toUpperCase() + word.substr(1))
     return words.join(' ')
     return words.join(' ')
   }
   }
 
 
-  static getDescription(fieldName) {
+  static getDescription(fieldName: string): string {
     let labelInfo = this.dictionary[fieldName]
     let labelInfo = this.dictionary[fieldName]
 
 
     if (labelInfo && typeof labelInfo === 'object') {
     if (labelInfo && typeof labelInfo === 'object') {