@@ -27,7 +27,7 @@ | |||
"rules": { | |||
"array-bracket-spacing": 2, | |||
"array-callback-return": 2, | |||
"arrow-parens": [2, "as-needed"], | |||
// "arrow-parens": [2, "as-needed"], | |||
"arrow-spacing": 2, | |||
"block-scoped-var": 2, | |||
"block-spacing": 2, |
@@ -68,7 +68,7 @@ | |||
"eslint-plugin-react": "^6.8.0", | |||
"expose-loader": "0.7.3", | |||
"extract-text-webpack-plugin": "2.1.2", | |||
"flow-bin": "0.47.0", | |||
"flow-bin": "^0.52.0", | |||
"fs-extra": "0.30.0", | |||
"handlebars-loader": "1.5.0", | |||
"html-webpack-plugin": "2.28.0", |
@@ -21,11 +21,16 @@ | |||
import { getJSON } from '../helpers/request'; | |||
import throwGlobalError from '../app/utils/throwGlobalError'; | |||
/*:: | |||
type GetApplicationLeakResponse = Array<{ | |||
date: string, | |||
project: string, | |||
projectName: string | |||
}>; | |||
*/ | |||
export const getApplicationLeak = (application: string): Promise<GetApplicationLeakResponse> => | |||
getJSON('/api/views/show_leak', { application }).then(r => r.leaks, throwGlobalError); | |||
export function getApplicationLeak( | |||
application /*: string */ | |||
) /*: Promise<GetApplicationLeakResponse> */ { | |||
return getJSON('/api/views/show_leak', { application }).then(r => r.leaks, throwGlobalError); | |||
} |
@@ -21,31 +21,45 @@ | |||
import { getJSON, post } from '../helpers/request'; | |||
import throwGlobalError from '../app/utils/throwGlobalError'; | |||
export const getActivity = (data?: Object): Promise<*> => getJSON('/api/ce/activity', data); | |||
export function getActivity(data /*: ?Object */) /*: Promise<*> */ { | |||
return getJSON('/api/ce/activity', data); | |||
} | |||
export const getStatus = (componentId?: string): Promise<*> => { | |||
export function getStatus(componentId /*: ?string */) /*: Promise<*> */ { | |||
const data = {}; | |||
if (componentId) { | |||
Object.assign(data, { componentId }); | |||
} | |||
return getJSON('/api/ce/activity_status', data); | |||
}; | |||
} | |||
export const getTask = (id: string, additionalFields?: Array<string>): Promise<*> => | |||
getJSON('/api/ce/task', { id, additionalFields }).then(r => r.task); | |||
export function getTask( | |||
id /*: string */, | |||
additionalFields /*: ?Array<string> */ | |||
) /*: Promise<*> */ { | |||
return getJSON('/api/ce/task', { id, additionalFields }).then(r => r.task); | |||
} | |||
export const cancelTask = (id: string): Promise<*> => | |||
post('/api/ce/cancel', { id }).then(() => getTask(id), () => getTask(id)); | |||
export function cancelTask(id /*: string */) /*: Promise<*> */ { | |||
return post('/api/ce/cancel', { id }).then(() => getTask(id), () => getTask(id)); | |||
} | |||
export const cancelAllTasks = (): Promise<*> => post('/api/ce/cancel_all'); | |||
export function cancelAllTasks() /*: Promise<*> */ { | |||
return post('/api/ce/cancel_all'); | |||
} | |||
export const getTasksForComponent = (componentKey: string): Promise<*> => | |||
getJSON('/api/ce/component', { componentKey }); | |||
export function getTasksForComponent(componentKey /*: string */) /*: Promise<*> */ { | |||
return getJSON('/api/ce/component', { componentKey }); | |||
} | |||
export const getTypes = (): Promise<*> => getJSON('/api/ce/task_types').then(r => r.taskTypes); | |||
export function getTypes() /*: Promise<*> */ { | |||
return getJSON('/api/ce/task_types').then(r => r.taskTypes); | |||
} | |||
export const getWorkers = (): Promise<{ canSetWorkerCount: boolean, value: number }> => | |||
getJSON('/api/ce/worker_count').catch(throwGlobalError); | |||
export function getWorkers() /*: Promise<{ canSetWorkerCount: boolean, value: number }> */ { | |||
return getJSON('/api/ce/worker_count').catch(throwGlobalError); | |||
} | |||
export const setWorkerCount = (count: number): Promise<void> => | |||
post('/api/ce/set_worker_count', { count }).catch(throwGlobalError); | |||
export function setWorkerCount(count /*: number */) /*: Promise<void> */ { | |||
return post('/api/ce/set_worker_count', { count }).catch(throwGlobalError); | |||
} |
@@ -21,57 +21,59 @@ | |||
import { getJSON, postJSON, post } from '../helpers/request'; | |||
import throwGlobalError from '../app/utils/throwGlobalError'; | |||
export function getComponents(data?: Object) { | |||
export function getComponents(data /*: ?Object */) { | |||
const url = '/api/projects/search'; | |||
return getJSON(url, data); | |||
} | |||
export function getProvisioned(data?: Object) { | |||
export function getProvisioned(data /*: ?Object */) { | |||
const url = '/api/projects/provisioned'; | |||
return getJSON(url, data); | |||
} | |||
export function getGhosts(data?: Object) { | |||
export function getGhosts(data /*: ?Object */) { | |||
const url = '/api/projects/ghosts'; | |||
return getJSON(url, data); | |||
} | |||
export function deleteComponents(data: { projects: string, organization?: string }) { | |||
export function deleteComponents(data /*: { projects: string, organization?: string } */) { | |||
const url = '/api/projects/bulk_delete'; | |||
return post(url, data); | |||
} | |||
export function deleteProject(project: string) { | |||
export function deleteProject(project /*: string */) { | |||
const url = '/api/projects/delete'; | |||
const data = { project }; | |||
return post(url, data); | |||
} | |||
export function createProject(data: { | |||
export function createProject( | |||
data /*: { | |||
branch?: string, | |||
name: string, | |||
project: string, | |||
organization?: string | |||
}) { | |||
} */ | |||
) { | |||
const url = '/api/projects/create'; | |||
return postJSON(url, data).catch(throwGlobalError); | |||
} | |||
export function searchProjectTags(data?: { ps?: number, q?: string }) { | |||
export function searchProjectTags(data /*: ?{ ps?: number, q?: string } */) { | |||
const url = '/api/project_tags/search'; | |||
return getJSON(url, data); | |||
} | |||
export function setProjectTags(data: { project: string, tags: string }) { | |||
export function setProjectTags(data /*: { project: string, tags: string } */) { | |||
const url = '/api/project_tags/set'; | |||
return post(url, data); | |||
} | |||
export function getComponentTree( | |||
strategy: string, | |||
componentKey: string, | |||
metrics: Array<string> = [], | |||
additional?: Object = {} | |||
strategy /*: string */, | |||
componentKey /*: string */, | |||
metrics /*: Array<string> */ = [], | |||
additional /*: ?Object */ = {} | |||
) { | |||
const url = '/api/measures/component_tree'; | |||
const data = Object.assign({}, additional, { | |||
@@ -82,62 +84,67 @@ export function getComponentTree( | |||
return getJSON(url, data); | |||
} | |||
export function getChildren(componentKey: string, metrics?: Array<string>, additional?: Object) { | |||
export function getChildren( | |||
componentKey /*: string */, | |||
metrics /*: Array<string> | void */, | |||
additional /*: ?Object */ | |||
) { | |||
return getComponentTree('children', componentKey, metrics, additional); | |||
} | |||
export function getComponentLeaves( | |||
componentKey: string, | |||
metrics?: Array<string>, | |||
additional?: Object | |||
componentKey /*: string */, | |||
metrics /*: Array<string> | void */, | |||
additional /*: ?Object */ | |||
) { | |||
return getComponentTree('leaves', componentKey, metrics, additional); | |||
} | |||
export function getComponent(componentKey: string, metrics: Array<string> = []) { | |||
export function getComponent(componentKey /*: string */, metrics /*: Array<string> */ = []) { | |||
const url = '/api/measures/component'; | |||
const data = { componentKey, metricKeys: metrics.join(',') }; | |||
return getJSON(url, data).then(r => r.component); | |||
} | |||
export function getTree(component: string, options?: Object = {}) { | |||
export function getTree(component /*: string */, options /*: ?Object */ = {}) { | |||
const url = '/api/components/tree'; | |||
const data = { ...options, component }; | |||
return getJSON(url, data); | |||
} | |||
export function getComponentShow(component: string) { | |||
export function getComponentShow(component /*: string */) { | |||
const url = '/api/components/show'; | |||
return getJSON(url, { component }); | |||
} | |||
export function getParents(component: string) { | |||
export function getParents(component /*: string */) { | |||
return getComponentShow(component).then(r => r.ancestors); | |||
} | |||
export function getBreadcrumbs(component: string) { | |||
export function getBreadcrumbs(component /*: string */) { | |||
return getComponentShow(component).then(r => { | |||
const reversedAncestors = [...r.ancestors].reverse(); | |||
return [...reversedAncestors, r.component]; | |||
}); | |||
} | |||
export function getComponentData(component: string) { | |||
export function getComponentData(component /*: string */) { | |||
return getComponentShow(component).then(r => r.component); | |||
} | |||
export function getMyProjects(data?: Object) { | |||
export function getMyProjects(data /*: ?Object */) { | |||
const url = '/api/projects/search_my_projects'; | |||
return getJSON(url, data); | |||
} | |||
export function searchProjects(data?: Object) { | |||
export function searchProjects(data /*: ?Object */) { | |||
const url = '/api/components/search_projects'; | |||
return getJSON(url, data); | |||
} | |||
export const searchComponents = (data?: { q?: string, qualifiers?: string, ps?: number }) => | |||
getJSON('/api/components/search', data); | |||
export function searchComponents(data /*: ?{ q?: string, qualifiers?: string, ps?: number } */) { | |||
return getJSON('/api/components/search', data); | |||
} | |||
/** | |||
* Change component's key | |||
@@ -145,7 +152,7 @@ export const searchComponents = (data?: { q?: string, qualifiers?: string, ps?: | |||
* @param {string} to | |||
* @returns {Promise} | |||
*/ | |||
export function changeKey(from: string, to: string) { | |||
export function changeKey(from /*: string */, to /*: string */) { | |||
const url = '/api/projects/update_key'; | |||
const data = { from, to }; | |||
return post(url, data); | |||
@@ -159,12 +166,18 @@ export function changeKey(from: string, to: string) { | |||
* @param {boolean} dryRun | |||
* @returns {Promise} | |||
*/ | |||
export function bulkChangeKey(project: string, from: string, to: string, dryRun?: boolean = false) { | |||
export function bulkChangeKey( | |||
project /*: string */, | |||
from /*: string */, | |||
to /*: string */, | |||
dryRun /*: ?boolean */ = false | |||
) { | |||
const url = '/api/projects/bulk_update_key'; | |||
const data = { project, from, to, dryRun }; | |||
return postJSON(url, data); | |||
} | |||
/*:: | |||
export type SuggestionsResponse = { | |||
organizations: Array<{ | |||
key: string, | |||
@@ -189,13 +202,14 @@ export type SuggestionsResponse = { | |||
}>, | |||
warning?: string | |||
}; | |||
export const getSuggestions = ( | |||
query?: string, | |||
recentlyBrowsed?: Array<string>, | |||
more?: string | |||
): Promise<SuggestionsResponse> => { | |||
const data: Object = {}; | |||
*/ | |||
export function getSuggestions( | |||
query /*: ?string */, | |||
recentlyBrowsed /*: ?Array<string> */, | |||
more /*: ?string */ | |||
) /*: Promise<SuggestionsResponse> */ { | |||
const data /*: Object */ = {}; | |||
if (query) { | |||
data.s = query; | |||
} | |||
@@ -206,13 +220,18 @@ export const getSuggestions = ( | |||
data.more = more; | |||
} | |||
return getJSON('/api/components/suggestions', data); | |||
}; | |||
} | |||
export const getComponentForSourceViewer = (component: string): Promise<*> => | |||
getJSON('/api/components/app', { component }); | |||
export function getComponentForSourceViewer(component /*: string */) /*: Promise<*> */ { | |||
return getJSON('/api/components/app', { component }); | |||
} | |||
export const getSources = (component: string, from?: number, to?: number): Promise<Array<*>> => { | |||
const data: Object = { key: component }; | |||
export function getSources( | |||
component /*: string */, | |||
from /*: ?number */, | |||
to /*: ?number */ | |||
) /*: Promise<Array<*>> */ { | |||
const data /*: Object */ = { key: component }; | |||
if (from) { | |||
Object.assign(data, { from }); | |||
} | |||
@@ -220,12 +239,14 @@ export const getSources = (component: string, from?: number, to?: number): Promi | |||
Object.assign(data, { to }); | |||
} | |||
return getJSON('/api/sources/lines', data).then(r => r.sources); | |||
}; | |||
} | |||
export const getDuplications = (component: string): Promise<*> => | |||
getJSON('/api/duplications/show', { key: component }); | |||
export function getDuplications(component /*: string */) /*: Promise<*> */ { | |||
return getJSON('/api/duplications/show', { key: component }); | |||
} | |||
export const getTests = (component: string, line: number | string): Promise<*> => | |||
getJSON('/api/tests/list', { sourceFileKey: component, sourceFileLineNumber: line }).then( | |||
export function getTests(component /*: string */, line /*: number | string */) /*: Promise<*> */ { | |||
return getJSON('/api/tests/list', { sourceFileKey: component, sourceFileLineNumber: line }).then( | |||
r => r.tests | |||
); | |||
} |
@@ -20,12 +20,14 @@ | |||
/* @flow */ | |||
import { post, getJSON } from '../helpers/request'; | |||
export const getFavorites = (): Promise<Object> => getJSON('/api/favorites/search'); | |||
export function getFavorites() /*: Promise<Object> */ { | |||
return getJSON('/api/favorites/search'); | |||
} | |||
export function addFavorite(component: string) { | |||
export function addFavorite(component /*: string */) { | |||
return post('/api/favorites/add', { component }); | |||
} | |||
export function removeFavorite(component: string) { | |||
export function removeFavorite(component /*: string */) { | |||
return post('/api/favorites/remove', { component }); | |||
} |
@@ -20,13 +20,16 @@ | |||
// @flow | |||
import { getJSON, post, postJSON } from '../helpers/request'; | |||
/*:: | |||
export type IssueResponse = { | |||
components?: Array<*>, | |||
issue: {}, | |||
rules?: Array<*>, | |||
users?: Array<*> | |||
}; | |||
*/ | |||
/*:: | |||
type IssuesResponse = { | |||
components?: Array<*>, | |||
debtTotal?: number, | |||
@@ -40,11 +43,13 @@ type IssuesResponse = { | |||
rules?: Array<*>, | |||
users?: Array<*> | |||
}; | |||
*/ | |||
export const searchIssues = (query: {}): Promise<IssuesResponse> => | |||
getJSON('/api/issues/search', query); | |||
export function searchIssues(query /*: {} */) /*: Promise<IssuesResponse> */ { | |||
return getJSON('/api/issues/search', query); | |||
} | |||
export function getFacets(query: {}, facets: Array<string>): Promise<*> { | |||
export function getFacets(query /*: {} */, facets /*: Array<string> */) /*: Promise<*> */ { | |||
const data = { | |||
...query, | |||
facets: facets.join(), | |||
@@ -56,43 +61,48 @@ export function getFacets(query: {}, facets: Array<string>): Promise<*> { | |||
}); | |||
} | |||
export function getFacet(query: {}, facet: string): Promise<*> { | |||
export function getFacet(query /*: {} */, facet /*: string */) /*: Promise<*> */ { | |||
return getFacets(query, [facet]).then(r => { | |||
return { facet: r.facets[0].values, response: r.response }; | |||
}); | |||
} | |||
export function getSeverities(query: {}): Promise<*> { | |||
export function getSeverities(query /*: {} */) /*: Promise<*> */ { | |||
return getFacet(query, 'severities').then(r => r.facet); | |||
} | |||
export function getTags(query: {}): Promise<*> { | |||
export function getTags(query /*: {} */) /*: Promise<*> */ { | |||
return getFacet(query, 'tags').then(r => r.facet); | |||
} | |||
export function extractAssignees(facet: Array<{ val: string }>, response: IssuesResponse) { | |||
export function extractAssignees( | |||
facet /*: Array<{ val: string }> */, | |||
response /*: IssuesResponse */ | |||
) { | |||
return facet.map(item => { | |||
const user = response.users ? response.users.find(user => user.login === item.val) : null; | |||
return { ...item, user }; | |||
}); | |||
} | |||
export function getAssignees(query: {}): Promise<*> { | |||
export function getAssignees(query /*: {} */) /*: Promise<*> */ { | |||
return getFacet(query, 'assignees').then(r => extractAssignees(r.facet, r.response)); | |||
} | |||
export function getIssuesCount(query: {}): Promise<*> { | |||
export function getIssuesCount(query /*: {} */) /*: Promise<*> */ { | |||
const data = { ...query, ps: 1, facetMode: 'effort' }; | |||
return searchIssues(data).then(r => { | |||
return { issues: r.paging.total, debt: r.debtTotal }; | |||
}); | |||
} | |||
export const searchIssueTags = ( | |||
data: { organization?: string, ps?: number, q?: string } = { ps: 500 } | |||
): Promise<Array<string>> => getJSON('/api/issues/tags', data).then(r => r.tags); | |||
export function searchIssueTags( | |||
data /*: { organization?: string, ps?: number, q?: string } */ = { ps: 500 } | |||
) /*: Promise<Array<string>> */ { | |||
return getJSON('/api/issues/tags', data).then(r => r.tags); | |||
} | |||
export function getIssueChangelog(issue: string): Promise<*> { | |||
export function getIssueChangelog(issue /*: string */) /*: Promise<*> */ { | |||
const url = '/api/issues/changelog'; | |||
return getJSON(url, { issue }).then(r => r.changelog); | |||
} | |||
@@ -102,54 +112,69 @@ export function getIssueFilters() { | |||
return getJSON(url).then(r => r.issueFilters); | |||
} | |||
export function addIssueComment(data: { issue: string, text: string }): Promise<IssueResponse> { | |||
export function addIssueComment( | |||
data /*: { issue: string, text: string } */ | |||
) /*: Promise<IssueResponse> */ { | |||
const url = '/api/issues/add_comment'; | |||
return postJSON(url, data); | |||
} | |||
export function deleteIssueComment(data: { comment: string }): Promise<IssueResponse> { | |||
export function deleteIssueComment(data /*: { comment: string } */) /*: Promise<IssueResponse> */ { | |||
const url = '/api/issues/delete_comment'; | |||
return postJSON(url, data); | |||
} | |||
export function editIssueComment(data: { comment: string, text: string }): Promise<IssueResponse> { | |||
export function editIssueComment( | |||
data /*: { comment: string, text: string } */ | |||
) /*: Promise<IssueResponse> */ { | |||
const url = '/api/issues/edit_comment'; | |||
return postJSON(url, data); | |||
} | |||
export function setIssueAssignee(data: { | |||
export function setIssueAssignee( | |||
data /*: { | |||
issue: string, | |||
assignee?: string | |||
}): Promise<IssueResponse> { | |||
} */ | |||
) /*: Promise<IssueResponse> */ { | |||
const url = '/api/issues/assign'; | |||
return postJSON(url, data); | |||
} | |||
export function setIssueSeverity(data: { issue: string, severity: string }): Promise<*> { | |||
export function setIssueSeverity( | |||
data /*: { issue: string, severity: string } */ | |||
) /*: Promise<*> */ { | |||
const url = '/api/issues/set_severity'; | |||
return postJSON(url, data); | |||
} | |||
export function setIssueTags(data: { issue: string, tags: string }): Promise<IssueResponse> { | |||
export function setIssueTags( | |||
data /*: { issue: string, tags: string } */ | |||
) /*: Promise<IssueResponse> */ { | |||
const url = '/api/issues/set_tags'; | |||
return postJSON(url, data); | |||
} | |||
export function setIssueTransition(data: { | |||
export function setIssueTransition( | |||
data /*: { | |||
issue: string, | |||
transition: string | |||
}): Promise<IssueResponse> { | |||
} */ | |||
) /*: Promise<IssueResponse> */ { | |||
const url = '/api/issues/do_transition'; | |||
return postJSON(url, data); | |||
} | |||
export function setIssueType(data: { issue: string, type: string }): Promise<IssueResponse> { | |||
export function setIssueType( | |||
data /*: { issue: string, type: string } */ | |||
) /*: Promise<IssueResponse> */ { | |||
const url = '/api/issues/set_type'; | |||
return postJSON(url, data); | |||
} | |||
export const bulkChangeIssues = (issueKeys: Array<string>, query: {}) => | |||
post('/api/issues/bulk_change', { | |||
export function bulkChangeIssues(issueKeys /*: Array<string> */, query /*: {} */) { | |||
return post('/api/issues/bulk_change', { | |||
issues: issueKeys.join(), | |||
...query | |||
}); | |||
} |
@@ -20,6 +20,7 @@ | |||
// @flow | |||
import { getJSON, post } from '../helpers/request'; | |||
/*:: | |||
export type GetNotificationsResponse = { | |||
notifications: Array<{ | |||
channel: string, | |||
@@ -32,22 +33,32 @@ export type GetNotificationsResponse = { | |||
globalTypes: Array<string>, | |||
perProjectTypes: Array<string> | |||
}; | |||
*/ | |||
export const getNotifications = (): Promise<GetNotificationsResponse> => | |||
getJSON('/api/notifications/list'); | |||
export function getNotifications() /*: Promise<GetNotificationsResponse> */ { | |||
return getJSON('/api/notifications/list'); | |||
} | |||
export const addNotification = (channel: string, type: string, project?: string): Promise<*> => { | |||
const data: Object = { channel, type }; | |||
export function addNotification( | |||
channel /*: string */, | |||
type /*: string */, | |||
project /*: ?string */ | |||
) /*: Promise<*> */ { | |||
const data /*: Object */ = { channel, type }; | |||
if (project) { | |||
Object.assign(data, { project }); | |||
} | |||
return post('/api/notifications/add', data); | |||
}; | |||
} | |||
export const removeNotification = (channel: string, type: string, project?: string): Promise<*> => { | |||
const data: Object = { channel, type }; | |||
export function removeNotification( | |||
channel /*: string */, | |||
type /*: string */, | |||
project /*: ?string */ | |||
) /*: Promise<*> */ { | |||
const data /*: Object */ = { channel, type }; | |||
if (project) { | |||
Object.assign(data, { project }); | |||
} | |||
return post('/api/notifications/remove', data); | |||
}; | |||
} |
@@ -19,22 +19,26 @@ | |||
*/ | |||
// @flow | |||
import { getJSON, post, postJSON } from '../helpers/request'; | |||
import type { Organization } from '../store/organizations/duck'; | |||
/*:: import type { Organization } from '../store/organizations/duck'; */ | |||
import throwGlobalError from '../app/utils/throwGlobalError'; | |||
export const getOrganizations = (organizations?: Array<string>) => { | |||
export function getOrganizations(organizations /*: ?Array<string> */) { | |||
const data = {}; | |||
if (organizations) { | |||
Object.assign(data, { organizations: organizations.join() }); | |||
} | |||
return getJSON('/api/organizations/search', data); | |||
}; | |||
} | |||
export const getMyOrganizations = () => | |||
getJSON('/api/organizations/search_my_organizations').then(r => r.organizations); | |||
export function getMyOrganizations() { | |||
return getJSON('/api/organizations/search_my_organizations').then(r => r.organizations); | |||
} | |||
/*:: | |||
type GetOrganizationType = null | Organization; | |||
*/ | |||
/*:: | |||
type GetOrganizationNavigation = { | |||
canAdmin: boolean, | |||
canDelete: boolean, | |||
@@ -43,39 +47,55 @@ type GetOrganizationNavigation = { | |||
pages: Array<{ key: string, name: string }>, | |||
adminPages: Array<{ key: string, name: string }> | |||
}; | |||
*/ | |||
export const getOrganization = (key: string): Promise<GetOrganizationType> => { | |||
export function getOrganization(key /*: string */) /*: Promise<GetOrganizationType> */ { | |||
return getOrganizations([key]) | |||
.then(r => r.organizations.find(o => o.key === key)) | |||
.catch(throwGlobalError); | |||
}; | |||
} | |||
export const getOrganizationNavigation = (key: string): Promise<GetOrganizationNavigation> => { | |||
export function getOrganizationNavigation( | |||
key /*: string */ | |||
) /*: Promise<GetOrganizationNavigation> */ { | |||
return getJSON('/api/navigation/organization', { organization: key }).then(r => r.organization); | |||
}; | |||
} | |||
export const createOrganization = (fields: {}): Promise<Organization> => | |||
postJSON('/api/organizations/create', fields).then(r => r.organization, throwGlobalError); | |||
export function createOrganization(fields /*: {} */) /*: Promise<Organization> */ { | |||
return postJSON('/api/organizations/create', fields).then(r => r.organization, throwGlobalError); | |||
} | |||
export const updateOrganization = (key: string, changes: {}) => | |||
post('/api/organizations/update', { key, ...changes }); | |||
export function updateOrganization(key /*: string */, changes /*: {} */) { | |||
return post('/api/organizations/update', { key, ...changes }); | |||
} | |||
export const deleteOrganization = (key: string) => | |||
post('/api/organizations/delete', { key }).catch(throwGlobalError); | |||
export function deleteOrganization(key /*: string */) { | |||
return post('/api/organizations/delete', { key }).catch(throwGlobalError); | |||
} | |||
export const searchMembers = (data: { | |||
export function searchMembers( | |||
data /*: { | |||
organization?: string, | |||
p?: number, | |||
ps?: number, | |||
q?: string, | |||
selected?: string | |||
}) => getJSON('/api/organizations/search_members', data); | |||
} */ | |||
) { | |||
return getJSON('/api/organizations/search_members', data); | |||
} | |||
export const addMember = (data: { login: string, organization: string }) => | |||
postJSON('/api/organizations/add_member', data).then(r => r.user); | |||
export function addMember(data /*: { login: string, organization: string } */) { | |||
return postJSON('/api/organizations/add_member', data).then(r => r.user); | |||
} | |||
export const removeMember = (data: { login: string, organization: string }) => | |||
post('/api/organizations/remove_member', data); | |||
export function removeMember(data /*: { login: string, organization: string } */) { | |||
return post('/api/organizations/remove_member', data); | |||
} | |||
export const changeProjectVisibility = (organization: string, projectVisibility: string) => | |||
post('/api/organizations/update_project_visibility', { organization, projectVisibility }); | |||
export function changeProjectVisibility( | |||
organization /*: string */, | |||
projectVisibility /*: string */ | |||
) { | |||
return post('/api/organizations/update_project_visibility', { organization, projectVisibility }); | |||
} |
@@ -23,13 +23,13 @@ import { getJSON, post, postJSON } from '../helpers/request'; | |||
const PAGE_SIZE = 100; | |||
export function grantPermissionToUser( | |||
projectKey: string | null, | |||
login: string, | |||
permission: string, | |||
organization?: string | |||
projectKey /*: string | null */, | |||
login /*: string */, | |||
permission /*: string */, | |||
organization /*: ?string */ | |||
) { | |||
const url = '/api/permissions/add_user'; | |||
const data: Object = { login, permission }; | |||
const data /*: Object */ = { login, permission }; | |||
if (projectKey) { | |||
data.projectKey = projectKey; | |||
} | |||
@@ -40,13 +40,13 @@ export function grantPermissionToUser( | |||
} | |||
export function revokePermissionFromUser( | |||
projectKey: string | null, | |||
login: string, | |||
permission: string, | |||
organization?: string | |||
projectKey /*: string | null */, | |||
login /*: string */, | |||
permission /*: string */, | |||
organization /*: ?string */ | |||
) { | |||
const url = '/api/permissions/remove_user'; | |||
const data: Object = { login, permission }; | |||
const data /*: Object */ = { login, permission }; | |||
if (projectKey) { | |||
data.projectKey = projectKey; | |||
} | |||
@@ -57,13 +57,13 @@ export function revokePermissionFromUser( | |||
} | |||
export function grantPermissionToGroup( | |||
projectKey: string | null, | |||
groupName: string, | |||
permission: string, | |||
organization?: string | |||
projectKey /*: string | null */, | |||
groupName /*: string */, | |||
permission /*: string */, | |||
organization /*: ?string */ | |||
) { | |||
const url = '/api/permissions/add_group'; | |||
const data: Object = { groupName, permission }; | |||
const data /*: Object */ = { groupName, permission }; | |||
if (projectKey) { | |||
data.projectKey = projectKey; | |||
} | |||
@@ -74,13 +74,13 @@ export function grantPermissionToGroup( | |||
} | |||
export function revokePermissionFromGroup( | |||
projectKey: string | null, | |||
groupName: string, | |||
permission: string, | |||
organization?: string | |||
projectKey /*: string | null */, | |||
groupName /*: string */, | |||
permission /*: string */, | |||
organization /*: ?string */ | |||
) { | |||
const url = '/api/permissions/remove_group'; | |||
const data: Object = { groupName, permission }; | |||
const data /*: Object */ = { groupName, permission }; | |||
if (projectKey) { | |||
data.projectKey = projectKey; | |||
} | |||
@@ -94,19 +94,22 @@ export function revokePermissionFromGroup( | |||
* Get list of permission templates | |||
* @returns {Promise} | |||
*/ | |||
export function getPermissionTemplates(organization?: string) { | |||
export function getPermissionTemplates(organization /*: ?string */) { | |||
const url = '/api/permissions/search_templates'; | |||
return organization ? getJSON(url, { organization }) : getJSON(url); | |||
} | |||
export const createPermissionTemplate = (data: Object) => | |||
postJSON('/api/permissions/create_template', data); | |||
export function createPermissionTemplate(data /*: Object */) { | |||
return postJSON('/api/permissions/create_template', data); | |||
} | |||
export const updatePermissionTemplate = (data: Object) => | |||
post('/api/permissions/update_template', data); | |||
export function updatePermissionTemplate(data /*: Object */) { | |||
return post('/api/permissions/update_template', data); | |||
} | |||
export const deletePermissionTemplate = (data: Object) => | |||
post('/api/permissions/delete_template', data); | |||
export function deletePermissionTemplate(data /*: Object */) { | |||
return post('/api/permissions/delete_template', data); | |||
} | |||
/** | |||
* Set default permission template for a given qualifier | |||
@@ -114,72 +117,79 @@ export const deletePermissionTemplate = (data: Object) => | |||
* @param {string} qualifier | |||
* @returns {Promise} | |||
*/ | |||
export function setDefaultPermissionTemplate(templateId: string, qualifier: string) { | |||
export function setDefaultPermissionTemplate(templateId /*: string */, qualifier /*: string */) { | |||
const url = '/api/permissions/set_default_template'; | |||
const data = { templateId, qualifier }; | |||
return post(url, data); | |||
} | |||
export function applyTemplateToProject(data: Object) { | |||
export function applyTemplateToProject(data /*: Object */) { | |||
const url = '/api/permissions/apply_template'; | |||
return post(url, data); | |||
} | |||
export function bulkApplyTemplate(data: Object) { | |||
export function bulkApplyTemplate(data /*: Object */) { | |||
const url = '/api/permissions/bulk_apply_template'; | |||
return post(url, data); | |||
} | |||
export function grantTemplatePermissionToUser(data: { | |||
export function grantTemplatePermissionToUser( | |||
data /*: { | |||
templateId: string, | |||
login: string, | |||
permission: string, | |||
organization?: string | |||
}) { | |||
} */ | |||
) { | |||
const url = '/api/permissions/add_user_to_template'; | |||
return post(url, data); | |||
} | |||
export function revokeTemplatePermissionFromUser(data: { | |||
export function revokeTemplatePermissionFromUser( | |||
data /*: { | |||
templateId: string, | |||
login: string, | |||
permission: string, | |||
organization?: string | |||
}) { | |||
} */ | |||
) { | |||
const url = '/api/permissions/remove_user_from_template'; | |||
return post(url, data); | |||
} | |||
export function grantTemplatePermissionToGroup(data: Object) { | |||
export function grantTemplatePermissionToGroup(data /*: Object */) { | |||
const url = '/api/permissions/add_group_to_template'; | |||
return post(url, data); | |||
} | |||
export function revokeTemplatePermissionFromGroup(data: Object) { | |||
export function revokeTemplatePermissionFromGroup(data /*: Object */) { | |||
const url = '/api/permissions/remove_group_from_template'; | |||
return post(url, data); | |||
} | |||
export function addProjectCreatorToTemplate(templateId: string, permission: string) { | |||
export function addProjectCreatorToTemplate(templateId /*: string */, permission /*: string */) { | |||
const url = '/api/permissions/add_project_creator_to_template'; | |||
const data = { templateId, permission }; | |||
return post(url, data); | |||
} | |||
export function removeProjectCreatorFromTemplate(templateId: string, permission: string) { | |||
export function removeProjectCreatorFromTemplate( | |||
templateId /*: string */, | |||
permission /*: string */ | |||
) { | |||
const url = '/api/permissions/remove_project_creator_from_template'; | |||
const data = { templateId, permission }; | |||
return post(url, data); | |||
} | |||
export function getPermissionsUsersForComponent( | |||
projectKey: string, | |||
query?: string, | |||
permission?: string, | |||
organization?: string | |||
projectKey /*: string */, | |||
query /*: ?string */, | |||
permission /*: ?string */, | |||
organization /*: ?string */ | |||
) { | |||
const url = '/api/permissions/users'; | |||
const data: Object = { projectKey, ps: PAGE_SIZE }; | |||
const data /*: Object */ = { projectKey, ps: PAGE_SIZE }; | |||
if (query) { | |||
data.q = query; | |||
} | |||
@@ -193,13 +203,13 @@ export function getPermissionsUsersForComponent( | |||
} | |||
export function getPermissionsGroupsForComponent( | |||
projectKey: string, | |||
query: string = '', | |||
permission?: string, | |||
organization?: string | |||
projectKey /*: string */, | |||
query /*: string */ = '', | |||
permission /*: ?string */, | |||
organization /*: ?string */ | |||
) { | |||
const url = '/api/permissions/groups'; | |||
const data: Object = { projectKey, ps: PAGE_SIZE }; | |||
const data /*: Object */ = { projectKey, ps: PAGE_SIZE }; | |||
if (query) { | |||
data.q = query; | |||
} | |||
@@ -213,12 +223,12 @@ export function getPermissionsGroupsForComponent( | |||
} | |||
export function getGlobalPermissionsUsers( | |||
query?: string, | |||
permission?: string, | |||
organization?: string | |||
query /*: ?string */, | |||
permission /*: ?string */, | |||
organization /*: ?string */ | |||
) { | |||
const url = '/api/permissions/users'; | |||
const data: Object = { ps: PAGE_SIZE }; | |||
const data /*: Object */ = { ps: PAGE_SIZE }; | |||
if (query) { | |||
data.q = query; | |||
} | |||
@@ -232,12 +242,12 @@ export function getGlobalPermissionsUsers( | |||
} | |||
export function getGlobalPermissionsGroups( | |||
query?: string, | |||
permission?: string, | |||
organization?: string | |||
query /*: ?string */, | |||
permission /*: ?string */, | |||
organization /*: ?string */ | |||
) { | |||
const url = '/api/permissions/groups'; | |||
const data: Object = { ps: PAGE_SIZE }; | |||
const data /*: Object */ = { ps: PAGE_SIZE }; | |||
if (query) { | |||
data.q = query; | |||
} | |||
@@ -251,13 +261,13 @@ export function getGlobalPermissionsGroups( | |||
} | |||
export function getPermissionTemplateUsers( | |||
templateId: string, | |||
query?: string, | |||
permission?: string, | |||
organization?: string | |||
templateId /*: string */, | |||
query /*: ?string */, | |||
permission /*: ?string */, | |||
organization /*: ?string */ | |||
) { | |||
const url = '/api/permissions/template_users'; | |||
const data: Object = { templateId, ps: PAGE_SIZE }; | |||
const data /*: Object */ = { templateId, ps: PAGE_SIZE }; | |||
if (query) { | |||
data.q = query; | |||
} | |||
@@ -271,13 +281,13 @@ export function getPermissionTemplateUsers( | |||
} | |||
export function getPermissionTemplateGroups( | |||
templateId: string, | |||
query?: string, | |||
permission?: string, | |||
organization?: string | |||
templateId /*: string */, | |||
query /*: ?string */, | |||
permission /*: ?string */, | |||
organization /*: ?string */ | |||
) { | |||
const url = '/api/permissions/template_groups'; | |||
const data: Object = { templateId, ps: PAGE_SIZE }; | |||
const data /*: Object */ = { templateId, ps: PAGE_SIZE }; | |||
if (query) { | |||
data.q = query; | |||
} | |||
@@ -290,7 +300,10 @@ export function getPermissionTemplateGroups( | |||
return getJSON(url, data).then(r => r.groups); | |||
} | |||
export function changeProjectVisibility(project: string, visibility: string): Promise<void> { | |||
export function changeProjectVisibility( | |||
project /*: string */, | |||
visibility /*: string */ | |||
) /*: Promise<void> */ { | |||
const url = '/api/projects/update_visibility'; | |||
const data = { project, visibility }; | |||
return post(url, data); |
@@ -21,6 +21,7 @@ | |||
import { getJSON, postJSON, post } from '../helpers/request'; | |||
import throwGlobalError from '../app/utils/throwGlobalError'; | |||
/*:: | |||
type GetProjectActivityResponse = { | |||
analyses: Array<Object>, | |||
paging: { | |||
@@ -29,19 +30,24 @@ type GetProjectActivityResponse = { | |||
pageSize: number | |||
} | |||
}; | |||
*/ | |||
/*:: | |||
type GetProjectActivityOptions = { | |||
project: string, | |||
category?: ?string, | |||
p?: ?number, | |||
ps?: ?number | |||
}; | |||
*/ | |||
export const getProjectActivity = ( | |||
data: GetProjectActivityOptions | |||
): Promise<GetProjectActivityResponse> => | |||
getJSON('/api/project_analyses/search', data).catch(throwGlobalError); | |||
export function getProjectActivity( | |||
data /*: GetProjectActivityOptions */ | |||
) /*: Promise<GetProjectActivityResponse> */ { | |||
return getJSON('/api/project_analyses/search', data).catch(throwGlobalError); | |||
} | |||
/*:: | |||
type CreateEventResponse = { | |||
analysis: string, | |||
key: string, | |||
@@ -49,14 +55,15 @@ type CreateEventResponse = { | |||
category: string, | |||
description?: string | |||
}; | |||
*/ | |||
export const createEvent = ( | |||
analysis: string, | |||
name: string, | |||
category?: string, | |||
description?: string | |||
): Promise<CreateEventResponse> => { | |||
const data: Object = { analysis, name }; | |||
export function createEvent( | |||
analysis /*: string */, | |||
name /*: string */, | |||
category /*: ?string */, | |||
description /*: ?string */ | |||
) /*: Promise<CreateEventResponse> */ { | |||
const data /*: Object */ = { analysis, name }; | |||
if (category) { | |||
data.category = category; | |||
} | |||
@@ -64,17 +71,18 @@ export const createEvent = ( | |||
data.description = description; | |||
} | |||
return postJSON('/api/project_analyses/create_event', data).then(r => r.event, throwGlobalError); | |||
}; | |||
} | |||
export const deleteEvent = (event: string): Promise<*> => | |||
post('/api/project_analyses/delete_event', { event }).catch(throwGlobalError); | |||
export function deleteEvent(event /*: string */) /*: Promise<*> */ { | |||
return post('/api/project_analyses/delete_event', { event }).catch(throwGlobalError); | |||
} | |||
export const changeEvent = ( | |||
event: string, | |||
name: ?string, | |||
description: ?string | |||
): Promise<CreateEventResponse> => { | |||
const data: Object = { event }; | |||
export function changeEvent( | |||
event /*: string */, | |||
name /*: ?string */, | |||
description /*: ?string */ | |||
) /*: Promise<CreateEventResponse> */ { | |||
const data /*: Object */ = { event }; | |||
if (name) { | |||
data.name = name; | |||
} | |||
@@ -82,7 +90,8 @@ export const changeEvent = ( | |||
data.description = description; | |||
} | |||
return postJSON('/api/project_analyses/update_event', data).then(r => r.event, throwGlobalError); | |||
}; | |||
} | |||
export const deleteAnalysis = (analysis: string): Promise<*> => | |||
post('/api/project_analyses/delete', { analysis }).catch(throwGlobalError); | |||
export function deleteAnalysis(analysis /*: string */) /*: Promise<*> */ { | |||
return post('/api/project_analyses/delete', { analysis }).catch(throwGlobalError); | |||
} |
@@ -20,17 +20,17 @@ | |||
// @flow | |||
import { request, checkStatus, parseJSON, getJSON, post, postJSON } from '../helpers/request'; | |||
export function searchQualityProfiles(data: { organization?: string, projectKey?: string }) { | |||
export function searchQualityProfiles(data /*: { organization?: string, projectKey?: string } */) { | |||
const url = '/api/qualityprofiles/search'; | |||
return getJSON(url, data).then(r => r.profiles); | |||
} | |||
export function getQualityProfiles(data: { compareToSonarWay?: boolean, profile: string }) { | |||
export function getQualityProfiles(data /*: { compareToSonarWay?: boolean, profile: string } */) { | |||
const url = '/api/qualityprofiles/show'; | |||
return getJSON(url, data); | |||
} | |||
export function createQualityProfile(data: Object) { | |||
export function createQualityProfile(data /*: Object */) { | |||
return request('/api/qualityprofiles/create') | |||
.setMethod('post') | |||
.setData(data) | |||
@@ -39,7 +39,7 @@ export function createQualityProfile(data: Object) { | |||
.then(parseJSON); | |||
} | |||
export function restoreQualityProfile(data: Object) { | |||
export function restoreQualityProfile(data /*: Object */) { | |||
return request('/api/qualityprofiles/restore') | |||
.setMethod('post') | |||
.setData(data) | |||
@@ -48,42 +48,42 @@ export function restoreQualityProfile(data: Object) { | |||
.then(parseJSON); | |||
} | |||
export function getProfileProjects(data: Object) { | |||
export function getProfileProjects(data /*: Object */) { | |||
const url = '/api/qualityprofiles/projects'; | |||
return getJSON(url, data); | |||
} | |||
export function getProfileInheritance(profileKey: string) { | |||
export function getProfileInheritance(profileKey /*: string */) { | |||
const url = '/api/qualityprofiles/inheritance'; | |||
const data = { profileKey }; | |||
return getJSON(url, data); | |||
} | |||
export function setDefaultProfile(profileKey: string) { | |||
export function setDefaultProfile(profileKey /*: string */) { | |||
const url = '/api/qualityprofiles/set_default'; | |||
const data = { profileKey }; | |||
return post(url, data); | |||
} | |||
export function renameProfile(key: string, name: string) { | |||
export function renameProfile(key /*: string */, name /*: string */) { | |||
const url = '/api/qualityprofiles/rename'; | |||
const data = { key, name }; | |||
return post(url, data); | |||
} | |||
export function copyProfile(fromKey: string, toName: string) { | |||
export function copyProfile(fromKey /*: string */, toName /*: string */) { | |||
const url = '/api/qualityprofiles/copy'; | |||
const data = { fromKey, toName }; | |||
return postJSON(url, data); | |||
} | |||
export function deleteProfile(profileKey: string) { | |||
export function deleteProfile(profileKey /*: string */) { | |||
const url = '/api/qualityprofiles/delete'; | |||
const data = { profileKey }; | |||
return post(url, data); | |||
} | |||
export function changeProfileParent(profileKey: string, parentKey: string) { | |||
export function changeProfileParent(profileKey /*: string */, parentKey /*: string */) { | |||
const url = '/api/qualityprofiles/change_parent'; | |||
const data = { profileKey, parentKey }; | |||
return post(url, data); | |||
@@ -99,24 +99,24 @@ export function getExporters() { | |||
return getJSON(url).then(r => r.exporters); | |||
} | |||
export function getProfileChangelog(data: Object) { | |||
export function getProfileChangelog(data /*: Object */) { | |||
const url = '/api/qualityprofiles/changelog'; | |||
return getJSON(url, data); | |||
} | |||
export function compareProfiles(leftKey: string, rightKey: string) { | |||
export function compareProfiles(leftKey /*: string */, rightKey /*: string */) { | |||
const url = '/api/qualityprofiles/compare'; | |||
const data = { leftKey, rightKey }; | |||
return getJSON(url, data); | |||
} | |||
export function associateProject(profileKey: string, projectKey: string) { | |||
export function associateProject(profileKey /*: string */, projectKey /*: string */) { | |||
const url = '/api/qualityprofiles/add_project'; | |||
const data = { profileKey, projectKey }; | |||
return post(url, data); | |||
} | |||
export function dissociateProject(profileKey: string, projectKey: string) { | |||
export function dissociateProject(profileKey /*: string */, projectKey /*: string */) { | |||
const url = '/api/qualityprofiles/remove_project'; | |||
const data = { profileKey, projectKey }; | |||
return post(url, data); |
@@ -20,6 +20,7 @@ | |||
// @flow | |||
import { getJSON } from '../helpers/request'; | |||
/*:: | |||
type Response = { | |||
measures: Array<{ | |||
metric: string, | |||
@@ -34,26 +35,28 @@ type Response = { | |||
total: number | |||
} | |||
}; | |||
*/ | |||
export const getTimeMachineData = ( | |||
component: string, | |||
metrics: Array<string>, | |||
other?: { p?: number, ps?: number, from?: string, to?: string } | |||
): Promise<Response> => | |||
getJSON('/api/measures/search_history', { | |||
export function getTimeMachineData( | |||
component /*: string */, | |||
metrics /*: Array<string> */, | |||
other /*: ?{ p?: number, ps?: number, from?: string, to?: string } */ | |||
) /*: Promise<Response> */ { | |||
return getJSON('/api/measures/search_history', { | |||
component, | |||
metrics: metrics.join(), | |||
ps: 1000, | |||
...other | |||
}); | |||
} | |||
export const getAllTimeMachineData = ( | |||
component: string, | |||
metrics: Array<string>, | |||
other?: { p?: number, from?: string, to?: string }, | |||
prev?: Response | |||
): Promise<Response> => | |||
getTimeMachineData(component, metrics, { ...other, ps: 1000 }).then((r: Response) => { | |||
export function getAllTimeMachineData( | |||
component /*: string */, | |||
metrics /*: Array<string> */, | |||
other /*: ?{ p?: number, from?: string, to?: string } */, | |||
prev /*: ?Response */ | |||
) /*: Promise<Response> */ { | |||
return getTimeMachineData(component, metrics, { ...other, ps: 1000 }).then(r => { | |||
const result = prev | |||
? { | |||
measures: prev.measures.map((measure, idx) => ({ | |||
@@ -74,3 +77,4 @@ export const getAllTimeMachineData = ( | |||
result | |||
); | |||
}); | |||
} |
@@ -26,7 +26,7 @@ import throwGlobalError from '../app/utils/throwGlobalError'; | |||
* @param {string} login | |||
* @returns {Promise} | |||
*/ | |||
export function getTokens(login: string) { | |||
export function getTokens(login /*: string */) { | |||
const url = '/api/user_tokens/search'; | |||
const data = { login }; | |||
return getJSON(url, data).then(r => r.userTokens); | |||
@@ -39,11 +39,11 @@ export function getTokens(login: string) { | |||
* @returns {Promise} | |||
*/ | |||
export function generateToken( | |||
tokenName: string, | |||
userLogin?: string | |||
): Promise<{ name: string, token: string }> { | |||
tokenName /*: string */, | |||
userLogin /*: ?string */ | |||
) /*: Promise<{ name: string, token: string }> */ { | |||
const url = '/api/user_tokens/generate'; | |||
const data: { [string]: string } = { name: tokenName }; | |||
const data /*: { [string]: string } */ = { name: tokenName }; | |||
if (userLogin) { | |||
data.login = userLogin; | |||
} | |||
@@ -56,9 +56,9 @@ export function generateToken( | |||
* @param {string} tokenName | |||
* @returns {Promise} | |||
*/ | |||
export function revokeToken(tokenName: string, userLogin?: string) { | |||
export function revokeToken(tokenName /*: string */, userLogin /*: ?string */) { | |||
const url = '/api/user_tokens/revoke'; | |||
const data: { [string]: string } = { name: tokenName }; | |||
const data /*: { [string]: string } */ = { name: tokenName }; | |||
if (userLogin) { | |||
data.login = userLogin; | |||
} |
@@ -20,33 +20,39 @@ | |||
//@flow | |||
import { getJSON, post } from '../helpers/request'; | |||
export function searchUsersGroups(data: { | |||
export function searchUsersGroups( | |||
data /*: { | |||
f?: string, | |||
organization?: string, | |||
p?: number, | |||
ps?: number, | |||
q?: string | |||
}) { | |||
} */ | |||
) { | |||
const url = '/api/user_groups/search'; | |||
return getJSON(url, data); | |||
} | |||
export function addUserToGroup(data: { | |||
export function addUserToGroup( | |||
data /*: { | |||
id?: string, | |||
name?: string, | |||
login?: string, | |||
organization?: string | |||
}) { | |||
} */ | |||
) { | |||
const url = '/api/user_groups/add_user'; | |||
return post(url, data); | |||
} | |||
export function removeUserFromGroup(data: { | |||
export function removeUserFromGroup( | |||
data /*: { | |||
id?: string, | |||
name?: string, | |||
login?: string, | |||
organization?: string | |||
}) { | |||
} */ | |||
) { | |||
const url = '/api/user_groups/remove_user'; | |||
return post(url, data); | |||
} |
@@ -25,18 +25,25 @@ export function getCurrentUser() { | |||
return getJSON(url); | |||
} | |||
export function changePassword(login: string, password: string, previousPassword?: string) { | |||
export function changePassword( | |||
login /*: string */, | |||
password /*: string */, | |||
previousPassword /*: ?string */ | |||
) { | |||
const url = '/api/users/change_password'; | |||
const data: { login: string, password: string, previousPassword?: string } = { login, password }; | |||
const data /*: { login: string, password: string, previousPassword?: string } */ = { | |||
login, | |||
password | |||
}; | |||
if (previousPassword != null) { | |||
data.previousPassword = previousPassword; | |||
} | |||
return post(url, data); | |||
} | |||
export function getUserGroups(login: string, organization?: string) { | |||
export function getUserGroups(login /*: string */, organization /*: ?string */) { | |||
const url = '/api/users/groups'; | |||
const data: { login: string, organization?: string, q?: string } = { login }; | |||
const data /*: { login: string, organization?: string, q?: string } */ = { login }; | |||
if (organization) { | |||
data.organization = organization; | |||
} | |||
@@ -48,15 +55,15 @@ export function getIdentityProviders() { | |||
return getJSON(url); | |||
} | |||
export function searchUsers(query: string, pageSize?: number) { | |||
export function searchUsers(query /*: string */, pageSize /*: ?number */) { | |||
const url = '/api/users/search'; | |||
const data: { q: string, ps?: number } = { q: query }; | |||
const data /*: { q: string, ps?: number } */ = { q: query }; | |||
if (pageSize != null) { | |||
data.ps = pageSize; | |||
} | |||
return getJSON(url, data); | |||
} | |||
export function skipOnboarding(): Promise<void> { | |||
export function skipOnboarding() /*: Promise<void> */ { | |||
return post('/api/users/skip_onboarding_tutorial'); | |||
} |
@@ -20,6 +20,7 @@ | |||
// @flow | |||
import { getJSON } from '../helpers/request'; | |||
/*:: | |||
export type Param = { | |||
key: string, | |||
defaultValue?: string, | |||
@@ -32,7 +33,9 @@ export type Param = { | |||
possibleValues?: Array<string>, | |||
required: boolean | |||
}; | |||
*/ | |||
/*:: | |||
export type Action = { | |||
key: string, | |||
description: string, | |||
@@ -47,7 +50,9 @@ export type Action = { | |||
}>, | |||
params?: Array<Param> | |||
}; | |||
*/ | |||
/*:: | |||
export type Domain = { | |||
actions: Array<Action>, | |||
description: string, | |||
@@ -55,8 +60,9 @@ export type Domain = { | |||
internal: boolean, | |||
path: string | |||
}; | |||
*/ | |||
export function fetchWebApi(showInternal: boolean = true): Promise<Array<Domain>> { | |||
export function fetchWebApi(showInternal /*: boolean */ = true) /*: Promise<Array<Domain>> */ { | |||
const url = '/api/webservices/list'; | |||
const data = { include_internals: showInternal }; | |||
@@ -70,7 +76,10 @@ export function fetchWebApi(showInternal: boolean = true): Promise<Array<Domain> | |||
); | |||
} | |||
export function fetchResponseExample(domain: string, action: string): Promise<{ example: string }> { | |||
export function fetchResponseExample( | |||
domain /*: string */, | |||
action /*: string */ | |||
) /*: Promise<{ example: string }> */ { | |||
const url = '/api/webservices/response_example'; | |||
const data = { controller: domain, action }; | |||
@@ -26,7 +26,7 @@ import { fetchCurrentUser } from '../../store/users/actions'; | |||
import { fetchLanguages, fetchAppState } from '../../store/rootActions'; | |||
class App extends React.PureComponent { | |||
mounted: boolean; | |||
/*:: mounted: boolean; */ | |||
static propTypes = { | |||
fetchAppState: PropTypes.func.isRequired, |
@@ -23,7 +23,7 @@ import GlobalNav from './nav/global/GlobalNav'; | |||
import GlobalFooterContainer from './GlobalFooterContainer'; | |||
import GlobalMessagesContainer from './GlobalMessagesContainer'; | |||
export default function GlobalContainer(props: Object) { | |||
export default function GlobalContainer(props /*: Object */) { | |||
// it is important to pass `location` down to `GlobalNav` to trigger render on url change | |||
return ( |
@@ -24,19 +24,18 @@ import GlobalFooterForSonarQubeDotCom from './GlobalFooterForSonarQubeDotCom'; | |||
import GlobalFooterBranding from './GlobalFooterBranding'; | |||
import { translate, translateWithParameters } from '../../helpers/l10n'; | |||
/*:: | |||
type Props = { | |||
hideLoggedInInfo?: boolean, | |||
productionDatabase: boolean, | |||
sonarqubeDotCom?: { value: string }, | |||
sonarqubeVersion?: string | |||
}; | |||
*/ | |||
export default function GlobalFooter({ | |||
hideLoggedInInfo, | |||
productionDatabase, | |||
sonarqubeDotCom, | |||
sonarqubeVersion | |||
}: Props) { | |||
export default function GlobalFooter( | |||
{ hideLoggedInInfo, productionDatabase, sonarqubeDotCom, sonarqubeVersion } /*: Props */ | |||
) { | |||
if (sonarqubeDotCom && sonarqubeDotCom.value === 'true') { | |||
return <GlobalFooterForSonarQubeDotCom hideLoggedInInfo={hideLoggedInInfo} />; | |||
} |
@@ -23,7 +23,7 @@ import GlobalLoading from './GlobalLoading'; | |||
import { requestMessages } from '../../helpers/l10n'; | |||
export default class LocalizationContainer extends React.PureComponent { | |||
mounted: boolean; | |||
/*:: mounted: boolean; */ | |||
state = { | |||
loading: true |
@@ -24,10 +24,12 @@ import GlobalLoading from './GlobalLoading'; | |||
import { getSystemStatus } from '../../api/system'; | |||
class MigrationContainer extends React.PureComponent { | |||
/*:: | |||
props: { | |||
children?: React.Element<*>, | |||
router: { push: (path: string) => void } | |||
}; | |||
*/ | |||
state = { | |||
loading: true |
@@ -23,6 +23,7 @@ import { getComponent } from '../../store/rootReducer'; | |||
import handleRequiredAuthorization from '../utils/handleRequiredAuthorization'; | |||
class ProjectAdminContainer extends React.PureComponent { | |||
/*:: | |||
props: { | |||
project: { | |||
configuration?: { | |||
@@ -30,6 +31,7 @@ class ProjectAdminContainer extends React.PureComponent { | |||
} | |||
} | |||
}; | |||
*/ | |||
componentDidMount() { | |||
this.checkPermissions(); |
@@ -29,6 +29,7 @@ import { parseError } from '../../apps/code/utils'; | |||
import handleRequiredAuthorization from '../utils/handleRequiredAuthorization'; | |||
class ProjectContainer extends React.PureComponent { | |||
/*:: | |||
props: { | |||
addGlobalErrorMessage: (message: string) => void, | |||
children?: React.Element<*>, | |||
@@ -43,6 +44,7 @@ class ProjectContainer extends React.PureComponent { | |||
fetchProject: string => Promise<*>, | |||
receiveComponents: (Array<*>) => void | |||
}; | |||
*/ | |||
componentDidMount() { | |||
this.fetchProject(); | |||
@@ -64,7 +66,7 @@ class ProjectContainer extends React.PureComponent { | |||
}); | |||
} | |||
handleProjectChange = (changes: {}) => { | |||
handleProjectChange = (changes /*: {} */) => { | |||
this.props.receiveComponents([{ ...this.props.project, ...changes }]); | |||
}; | |||
@@ -21,15 +21,17 @@ | |||
const STORAGE_KEY = 'sonar_recent_history'; | |||
const HISTORY_LIMIT = 10; | |||
/*:: | |||
type History = Array<{ | |||
key: string, | |||
name: string, | |||
icon: string, | |||
organization?: string | |||
}>; | |||
*/ | |||
export default class RecentHistory { | |||
static get(): History { | |||
static get() /*: History */ { | |||
if (!window.localStorage) { | |||
return []; | |||
} | |||
@@ -47,24 +49,24 @@ export default class RecentHistory { | |||
return history; | |||
} | |||
static set(newHistory: History): void { | |||
static set(newHistory /*: History */) /*: void */ { | |||
if (window.localStorage) { | |||
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(newHistory)); | |||
} | |||
} | |||
static clear(): void { | |||
static clear() /*: void */ { | |||
if (window.localStorage) { | |||
window.localStorage.removeItem(STORAGE_KEY); | |||
} | |||
} | |||
static add( | |||
componentKey: string, | |||
componentName: string, | |||
icon: string, | |||
organization?: string | |||
): void { | |||
componentKey /*: string */, | |||
componentName /*: string */, | |||
icon /*: string */, | |||
organization /*: string | void */ | |||
) /*: void */ { | |||
const sonarHistory = RecentHistory.get(); | |||
const newEntry = { key: componentKey, name: componentName, icon, organization }; | |||
let newHistory = sonarHistory.filter(entry => entry.key !== newEntry.key); | |||
@@ -73,7 +75,7 @@ export default class RecentHistory { | |||
RecentHistory.set(newHistory); | |||
} | |||
static remove(componentKey: string): void { | |||
static remove(componentKey /*: string */) /*: void */ { | |||
const history = RecentHistory.get(); | |||
const newHistory = history.filter(entry => entry.key !== componentKey); | |||
RecentHistory.set(newHistory); |
@@ -22,13 +22,15 @@ import React from 'react'; | |||
import GlobalFooterContainer from './GlobalFooterContainer'; | |||
import NavBar from '../../components/nav/NavBar'; | |||
/*:: | |||
type Props = { | |||
children?: React.Element<*> | Array<React.Element<*>>, | |||
hideLoggedInInfo?: boolean | |||
}; | |||
*/ | |||
export default class SimpleContainer extends React.PureComponent { | |||
props: Props; | |||
/*:: props: Props; */ | |||
componentDidMount() { | |||
const html = document.querySelector('html'); |
@@ -28,6 +28,7 @@ import { translate } from '../../../helpers/l10n'; | |||
import { getExtensionStart } from './utils'; | |||
import getStore from '../../utils/getStore'; | |||
/*:: | |||
type Props = { | |||
currentUser: Object, | |||
extension: { | |||
@@ -39,17 +40,18 @@ type Props = { | |||
options?: {}, | |||
router: Object | |||
}; | |||
*/ | |||
class Extension extends React.PureComponent { | |||
container: Object; | |||
props: Props; | |||
stop: ?Function; | |||
/*:: container: Object; */ | |||
/*:: props: Props; */ | |||
/*:: stop: ?Function; */ | |||
componentDidMount() { | |||
this.startExtension(); | |||
} | |||
componentDidUpdate(prevProps: Props) { | |||
componentDidUpdate(prevProps /*: Props */) { | |||
if (prevProps.extension !== this.props.extension) { | |||
this.stopExtension(); | |||
this.startExtension(); | |||
@@ -66,7 +68,7 @@ class Extension extends React.PureComponent { | |||
this.stopExtension(); | |||
} | |||
handleStart = (start: Function) => { | |||
handleStart = (start /*: Function */) => { | |||
const store = getStore(); | |||
this.stop = start({ | |||
store, |
@@ -24,6 +24,7 @@ import Extension from './Extension'; | |||
import ExtensionNotFound from './ExtensionNotFound'; | |||
import { getAppState } from '../../../store/rootReducer'; | |||
/*:: | |||
type Props = { | |||
adminPages: Array<{ key: string }>, | |||
params: { | |||
@@ -31,8 +32,9 @@ type Props = { | |||
pluginKey: string | |||
} | |||
}; | |||
*/ | |||
function GlobalAdminPageExtension(props: Props) { | |||
function GlobalAdminPageExtension(props /*: Props */) { | |||
const { extensionKey, pluginKey } = props.params; | |||
const extension = props.adminPages.find(p => p.key === `${pluginKey}/${extensionKey}`); | |||
return extension ? <Extension extension={extension} /> : <ExtensionNotFound />; |
@@ -24,6 +24,7 @@ import Extension from './Extension'; | |||
import ExtensionNotFound from './ExtensionNotFound'; | |||
import { getAppState } from '../../../store/rootReducer'; | |||
/*:: | |||
type Props = { | |||
globalPages: Array<{ key: string }>, | |||
params: { | |||
@@ -31,8 +32,9 @@ type Props = { | |||
pluginKey: string | |||
} | |||
}; | |||
*/ | |||
function GlobalPageExtension(props: Props) { | |||
function GlobalPageExtension(props /*: Props */) { | |||
const { extensionKey, pluginKey } = props.params; | |||
const extension = props.globalPages.find(p => p.key === `${pluginKey}/${extensionKey}`); | |||
return extension ? <Extension extension={extension} /> : <ExtensionNotFound />; |
@@ -24,8 +24,9 @@ import Extension from './Extension'; | |||
import ExtensionNotFound from './ExtensionNotFound'; | |||
import { getOrganizationByKey } from '../../../store/rootReducer'; | |||
import { fetchOrganization } from '../../../apps/organizations/actions'; | |||
import type { Organization } from '../../../store/organizations/duck'; | |||
/*:: import type { Organization } from '../../../store/organizations/duck'; */ | |||
/*:: | |||
type Props = { | |||
fetchOrganization: string => void, | |||
location: {}, | |||
@@ -36,9 +37,10 @@ type Props = { | |||
pluginKey: string | |||
} | |||
}; | |||
*/ | |||
class OrganizationPageExtension extends React.PureComponent { | |||
props: Props; | |||
/*:: props: Props; */ | |||
refreshOrganization = () => this.props.fetchOrganization(this.props.organization.key); | |||
@@ -62,7 +64,7 @@ class OrganizationPageExtension extends React.PureComponent { | |||
} | |||
} | |||
const mapStateToProps = (state, ownProps: Props) => ({ | |||
const mapStateToProps = (state, ownProps /*: Props */) => ({ | |||
organization: getOrganizationByKey(state, ownProps.params.organizationKey) | |||
}); | |||
@@ -21,7 +21,7 @@ | |||
import React from 'react'; | |||
import GlobalPageExtension from './GlobalPageExtension'; | |||
export default function PortfoliosPage(props: Object) { | |||
export default function PortfoliosPage(props /*: Object */) { | |||
return ( | |||
<div> | |||
<GlobalPageExtension |
@@ -25,6 +25,7 @@ import ExtensionNotFound from './ExtensionNotFound'; | |||
import { getComponent } from '../../../store/rootReducer'; | |||
import { addGlobalErrorMessage } from '../../../store/globalMessages/duck'; | |||
/*:: | |||
type Props = { | |||
component: { | |||
configuration?: { | |||
@@ -37,8 +38,9 @@ type Props = { | |||
pluginKey: string | |||
} | |||
}; | |||
*/ | |||
function ProjectAdminPageExtension(props: Props) { | |||
function ProjectAdminPageExtension(props /*: Props */) { | |||
const { extensionKey, pluginKey } = props.params; | |||
const { component } = props; | |||
const extension = | |||
@@ -49,7 +51,7 @@ function ProjectAdminPageExtension(props: Props) { | |||
: <ExtensionNotFound />; | |||
} | |||
const mapStateToProps = (state, ownProps: Props) => ({ | |||
const mapStateToProps = (state, ownProps /*: Props */) => ({ | |||
component: getComponent(state, ownProps.location.query.id) | |||
}); | |||
@@ -25,6 +25,7 @@ import ExtensionNotFound from './ExtensionNotFound'; | |||
import { getComponent } from '../../../store/rootReducer'; | |||
import { addGlobalErrorMessage } from '../../../store/globalMessages/duck'; | |||
/*:: | |||
type Props = { | |||
component: { | |||
extensions: Array<{ key: string }> | |||
@@ -35,8 +36,9 @@ type Props = { | |||
pluginKey: string | |||
} | |||
}; | |||
*/ | |||
function ProjectPageExtension(props: Props) { | |||
function ProjectPageExtension(props /*: Props */) { | |||
const { extensionKey, pluginKey } = props.params; | |||
const { component } = props; | |||
const extension = component.extensions.find(p => p.key === `${pluginKey}/${extensionKey}`); | |||
@@ -45,7 +47,7 @@ function ProjectPageExtension(props: Props) { | |||
: <ExtensionNotFound />; | |||
} | |||
const mapStateToProps = (state, ownProps: Props) => ({ | |||
const mapStateToProps = (state, ownProps /*: Props */) => ({ | |||
component: getComponent(state, ownProps.location.query.id) | |||
}); | |||
@@ -21,7 +21,7 @@ | |||
import React from 'react'; | |||
import ProjectPageExtension from './ProjectPageExtension'; | |||
export default function ViewDashboard(props: Object) { | |||
export default function ViewDashboard(props /*: Object */) { | |||
return ( | |||
<ProjectPageExtension | |||
location={props.location} |
@@ -20,17 +20,17 @@ | |||
// @flow | |||
import { getExtensionFromCache } from '../../utils/installExtensionsHandler'; | |||
const installScript = (key: string) => { | |||
function installScript(key /*: string */) { | |||
return new Promise(resolve => { | |||
const scriptTag = document.createElement('script'); | |||
scriptTag.src = `${window.baseUrl}/static/${key}.js`; | |||
scriptTag.onload = resolve; | |||
document.getElementsByTagName('body')[0].appendChild(scriptTag); | |||
}); | |||
}; | |||
} | |||
export const getExtensionStart = (key: string) => | |||
new Promise((resolve, reject) => { | |||
export function getExtensionStart(key /*: string */) { | |||
return new Promise((resolve, reject) => { | |||
const fromCache = getExtensionFromCache(key); | |||
if (fromCache) { | |||
return resolve(fromCache); | |||
@@ -45,3 +45,4 @@ export const getExtensionStart = (key: string) => | |||
} | |||
}); | |||
}); | |||
} |
@@ -27,27 +27,31 @@ import ShortcutsHelp from './ShortcutsHelp'; | |||
import TutorialsHelp from './TutorialsHelp'; | |||
import { translate } from '../../../helpers/l10n'; | |||
/*:: | |||
type Props = { | |||
currentUser: { isLoggedIn: boolean }, | |||
onClose: () => void, | |||
onTutorialSelect: () => void, | |||
sonarCloud?: boolean | |||
}; | |||
*/ | |||
/*:: | |||
type State = { | |||
section: string | |||
}; | |||
*/ | |||
export default class GlobalHelp extends React.PureComponent { | |||
props: Props; | |||
state: State = { section: 'shortcuts' }; | |||
/*:: props: Props; */ | |||
state /*: State */ = { section: 'shortcuts' }; | |||
handleCloseClick = (event: Event) => { | |||
handleCloseClick = (event /*: Event */) => { | |||
event.preventDefault(); | |||
this.props.onClose(); | |||
}; | |||
handleSectionClick = (event: Event & { currentTarget: HTMLElement }) => { | |||
handleSectionClick = (event /*: Event & { currentTarget: HTMLElement } */) => { | |||
event.preventDefault(); | |||
const { section } = event.currentTarget.dataset; | |||
this.setState({ section }); | |||
@@ -68,7 +72,7 @@ export default class GlobalHelp extends React.PureComponent { | |||
} | |||
}; | |||
renderMenuItem = (section: string) => | |||
renderMenuItem = (section /*: string */) => | |||
<li key={section}> | |||
<a | |||
className={classNames({ active: section === this.state.section })} |
@@ -22,9 +22,11 @@ import React from 'react'; | |||
import { Link } from 'react-router'; | |||
import { translate } from '../../../helpers/l10n'; | |||
/*:: | |||
type Props = { onClose: () => void }; | |||
*/ | |||
export default function LinksHelp({ onClose }: Props) { | |||
export default function LinksHelp({ onClose } /*: Props */) { | |||
return ( | |||
<div> | |||
<h2 className="spacer-top spacer-bottom"> |
@@ -22,9 +22,11 @@ import React from 'react'; | |||
import { Link } from 'react-router'; | |||
import { translate } from '../../../helpers/l10n'; | |||
/*:: | |||
type Props = { onClose: () => void }; | |||
*/ | |||
export default function LinksHelpSonarCloud({ onClose }: Props) { | |||
export default function LinksHelpSonarCloud({ onClose } /*: Props */) { | |||
return ( | |||
<div> | |||
<h2 className="spacer-top spacer-bottom"> |
@@ -21,10 +21,12 @@ | |||
import React from 'react'; | |||
import { translate } from '../../../helpers/l10n'; | |||
/*:: | |||
type Props = { onTutorialSelect: () => void }; | |||
*/ | |||
export default function TutorialsHelp({ onTutorialSelect }: Props) { | |||
const handleClick = (event: Event) => { | |||
export default function TutorialsHelp({ onTutorialSelect } /*: Props */) { | |||
const handleClick = (event /*: Event */) => { | |||
event.preventDefault(); | |||
onTutorialSelect(); | |||
}; |
@@ -65,6 +65,6 @@ it('display special links page for SonarCloud', () => { | |||
expect(wrapper.find('LinksHelpSonarCloud')).toHaveLength(1); | |||
}); | |||
function clickOnSection(wrapper: Object, section: string) { | |||
function clickOnSection(wrapper /*: Object */, section /*: string */) { | |||
click(wrapper.find(`[data-section="${section}"]`), { currentTarget: { dataset: { section } } }); | |||
} |
@@ -33,22 +33,26 @@ import { getCurrentUser, getAppState, getSettingValue } from '../../../../store/ | |||
import { translate } from '../../../../helpers/l10n'; | |||
import './GlobalNav.css'; | |||
/*:: | |||
type Props = { | |||
appState: { organizationsEnabled: boolean }, | |||
currentUser: { isLoggedIn: boolean, showOnboardingTutorial: true }, | |||
sonarCloud: boolean | |||
}; | |||
*/ | |||
/*:: | |||
type State = { | |||
helpOpen: boolean, | |||
onboardingTutorialOpen: boolean, | |||
onboardingTutorialTooltip: boolean | |||
}; | |||
*/ | |||
class GlobalNav extends React.PureComponent { | |||
interval: ?number; | |||
props: Props; | |||
state: State = { | |||
/*:: interval: ?number; */ | |||
/*:: props: Props; */ | |||
state /*: State */ = { | |||
helpOpen: false, | |||
onboardingTutorialOpen: false, | |||
onboardingTutorialTooltip: false |
@@ -26,12 +26,15 @@ import Avatar from '../../../../components/ui/Avatar'; | |||
import OrganizationLink from '../../../../components/ui/OrganizationLink'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
/*:: | |||
type CurrentUser = { | |||
email?: string, | |||
isLoggedIn: boolean, | |||
name: string | |||
}; | |||
*/ | |||
/*:: | |||
type Props = { | |||
appState: { | |||
organizationsEnabled: boolean | |||
@@ -42,27 +45,30 @@ type Props = { | |||
organizations: Array<{ key: string, name: string }>, | |||
router: { push: string => void } | |||
}; | |||
*/ | |||
/*:: | |||
type State = { | |||
open: boolean | |||
}; | |||
*/ | |||
export default class GlobalNavUser extends React.PureComponent { | |||
node: HTMLElement; | |||
props: Props; | |||
state: State = { open: false }; | |||
/*:: node: HTMLElement; */ | |||
/*:: props: Props; */ | |||
state /*: State */ = { open: false }; | |||
componentWillUnmount() { | |||
window.removeEventListener('click', this.handleClickOutside); | |||
} | |||
handleClickOutside = (event: { target: HTMLElement }) => { | |||
handleClickOutside = (event /*: { target: HTMLElement } */) => { | |||
if (!this.node || !this.node.contains(event.target)) { | |||
this.closeDropdown(); | |||
} | |||
}; | |||
handleLogin = (e: Event) => { | |||
handleLogin = (e /*: Event */) => { | |||
e.preventDefault(); | |||
const shouldReturnToCurrentPage = window.location.pathname !== `${window.baseUrl}/about`; | |||
if (shouldReturnToCurrentPage) { | |||
@@ -74,13 +80,13 @@ export default class GlobalNavUser extends React.PureComponent { | |||
} | |||
}; | |||
handleLogout = (e: Event) => { | |||
handleLogout = (e /*: Event */) => { | |||
e.preventDefault(); | |||
this.closeDropdown(); | |||
this.props.router.push('/sessions/logout'); | |||
}; | |||
toggleDropdown = (evt: Event) => { | |||
toggleDropdown = (evt /*: Event */) => { | |||
evt.preventDefault(); | |||
if (this.state.open) { | |||
this.closeDropdown(); |
@@ -26,7 +26,7 @@ import { debounce, keyBy, uniqBy } from 'lodash'; | |||
import SearchResults from './SearchResults'; | |||
import SearchResult from './SearchResult'; | |||
import { sortQualifiers } from './utils'; | |||
import type { Component, More, Results } from './utils'; | |||
/*:: import type { Component, More, Results } from './utils'; */ | |||
import RecentHistory from '../../components/RecentHistory'; | |||
import DeferredSpinner from '../../../components/common/DeferredSpinner'; | |||
import ClockIcon from '../../../components/common/ClockIcon'; | |||
@@ -36,11 +36,14 @@ import { scrollToElement } from '../../../helpers/scrolling'; | |||
import { getProjectUrl } from '../../../helpers/urls'; | |||
import './Search.css'; | |||
/*:: | |||
type Props = {| | |||
appState: { organizationsEnabled: boolean }, | |||
currentUser: { isLoggedIn: boolean } | |||
|}; | |||
*/ | |||
/*:: | |||
type State = { | |||
loading: boolean, | |||
loadingMore: ?string, | |||
@@ -53,20 +56,22 @@ type State = { | |||
selected: ?string, | |||
shortQuery: boolean | |||
}; | |||
*/ | |||
export default class Search extends React.PureComponent { | |||
input: HTMLElement; | |||
mounted: boolean; | |||
node: HTMLElement; | |||
nodes: { [string]: HTMLElement }; | |||
props: Props; | |||
state: State; | |||
/*:: input: HTMLElement; */ | |||
/*:: mounted: boolean; */ | |||
/*:: node: HTMLElement; */ | |||
/*:: nodes: { [string]: HTMLElement }; | |||
*/ | |||
/*:: props: Props; */ | |||
/*:: state: State; */ | |||
static contextTypes = { | |||
router: PropTypes.object | |||
}; | |||
constructor(props: Props) { | |||
constructor(props /*: Props */) { | |||
super(props); | |||
this.nodes = {}; | |||
this.search = debounce(this.search, 250); | |||
@@ -97,7 +102,7 @@ export default class Search extends React.PureComponent { | |||
this.nodes = {}; | |||
} | |||
componentDidUpdate(prevProps: Props, prevState: State) { | |||
componentDidUpdate(prevProps /*: Props */, prevState /*: State */) { | |||
if (prevState.selected !== this.state.selected) { | |||
this.scrollToSelected(); | |||
} | |||
@@ -109,7 +114,7 @@ export default class Search extends React.PureComponent { | |||
window.removeEventListener('click', this.handleClickOutside); | |||
} | |||
handleClickOutside = (event: { target: HTMLElement }) => { | |||
handleClickOutside = (event /*: { target: HTMLElement } */) => { | |||
if (!this.node || !this.node.contains(event.target)) { | |||
this.closeSearch(false); | |||
} | |||
@@ -123,7 +128,7 @@ export default class Search extends React.PureComponent { | |||
this.setState({ open: true }); | |||
}; | |||
closeSearch = (clear: boolean = true) => { | |||
closeSearch = (clear /*: boolean */ = true) => { | |||
if (this.input) { | |||
this.input.blur(); | |||
} | |||
@@ -146,7 +151,7 @@ export default class Search extends React.PureComponent { | |||
); | |||
}; | |||
getPlainComponentsList = (results: Results, more: More): Array<string> => | |||
getPlainComponentsList = (results /*: Results */, more /*: More */) => | |||
sortQualifiers(Object.keys(results)).reduce((components, qualifier) => { | |||
const next = [...components, ...results[qualifier].map(component => component.key)]; | |||
if (more[qualifier]) { | |||
@@ -155,7 +160,7 @@ export default class Search extends React.PureComponent { | |||
return next; | |||
}, []); | |||
mergeWithRecentlyBrowsed = (components: Array<Component>) => { | |||
mergeWithRecentlyBrowsed = (components /*: Array<Component> */) => { | |||
const recentlyBrowsed = RecentHistory.get().map(component => ({ | |||
...component, | |||
isRecentlyBrowsed: true, | |||
@@ -164,7 +169,7 @@ export default class Search extends React.PureComponent { | |||
return uniqBy([...components, ...recentlyBrowsed], 'key'); | |||
}; | |||
search = (query: string) => { | |||
search = (query /*: string */) => { | |||
if (query.length === 0 || query.length >= 2) { | |||
this.setState({ loading: true }); | |||
const recentlyBrowsed = RecentHistory.get().map(component => component.key); | |||
@@ -195,7 +200,7 @@ export default class Search extends React.PureComponent { | |||
} | |||
}; | |||
searchMore = (qualifier: string) => { | |||
searchMore = (qualifier /*: string */) => { | |||
if (this.state.query.length !== 1) { | |||
this.setState({ loading: true, loadingMore: qualifier }); | |||
const recentlyBrowsed = RecentHistory.get().map(component => component.key); | |||
@@ -220,14 +225,14 @@ export default class Search extends React.PureComponent { | |||
} | |||
}; | |||
handleQueryChange = (event: { currentTarget: HTMLInputElement }) => { | |||
handleQueryChange = (event /*: { currentTarget: HTMLInputElement } */) => { | |||
const query = event.currentTarget.value; | |||
this.setState({ query, shortQuery: query.length === 1 }); | |||
this.search(query); | |||
}; | |||
selectPrevious = () => { | |||
this.setState(({ more, results, selected }: State) => { | |||
this.setState(({ more, results, selected } /*: State */) => { | |||
if (selected) { | |||
const list = this.getPlainComponentsList(results, more); | |||
const index = list.indexOf(selected); | |||
@@ -237,7 +242,7 @@ export default class Search extends React.PureComponent { | |||
}; | |||
selectNext = () => { | |||
this.setState(({ more, results, selected }: State) => { | |||
this.setState(({ more, results, selected } /*: State */) => { | |||
if (selected) { | |||
const list = this.getPlainComponentsList(results, more); | |||
const index = list.indexOf(selected); | |||
@@ -267,7 +272,7 @@ export default class Search extends React.PureComponent { | |||
} | |||
}; | |||
handleKeyDown = (event: KeyboardEvent) => { | |||
handleKeyDown = (event /*: KeyboardEvent */) => { | |||
switch (event.keyCode) { | |||
case 13: | |||
event.preventDefault(); | |||
@@ -288,15 +293,15 @@ export default class Search extends React.PureComponent { | |||
} | |||
}; | |||
handleSelect = (selected: string) => { | |||
handleSelect = (selected /*: string */) => { | |||
this.setState({ selected }); | |||
}; | |||
innerRef = (component: string, node: HTMLElement) => { | |||
innerRef = (component /*: string */, node /*: HTMLElement */) => { | |||
this.nodes[component] = node; | |||
}; | |||
renderResult = (component: Component) => | |||
renderResult = (component /*: Component */) => | |||
<SearchResult | |||
appState={this.props.appState} | |||
component={component} |
@@ -20,13 +20,14 @@ | |||
// @flow | |||
import React from 'react'; | |||
import { Link } from 'react-router'; | |||
import type { Component } from './utils'; | |||
/*:: import type { Component } from './utils'; */ | |||
import FavoriteIcon from '../../../components/common/FavoriteIcon'; | |||
import QualifierIcon from '../../../components/shared/QualifierIcon'; | |||
import ClockIcon from '../../../components/common/ClockIcon'; | |||
import Tooltip from '../../../components/controls/Tooltip'; | |||
import { getProjectUrl } from '../../../helpers/urls'; | |||
/*:: | |||
type Props = {| | |||
appState: { organizationsEnabled: boolean }, | |||
component: Component, | |||
@@ -37,17 +38,20 @@ type Props = {| | |||
projects: { [string]: { name: string } }, | |||
selected: boolean | |||
|}; | |||
*/ | |||
/*:: | |||
type State = { | |||
tooltipVisible: boolean | |||
}; | |||
*/ | |||
const TOOLTIP_DELAY = 1000; | |||
export default class SearchResult extends React.PureComponent { | |||
interval: ?number; | |||
props: Props; | |||
state: State = { tooltipVisible: false }; | |||
/*:: interval: ?number; */ | |||
/*:: props: Props; */ | |||
state /*: State */ = { tooltipVisible: false }; | |||
componentDidMount() { | |||
if (this.props.selected) { | |||
@@ -55,7 +59,7 @@ export default class SearchResult extends React.PureComponent { | |||
} | |||
} | |||
componentWillReceiveProps(nextProps: Props) { | |||
componentWillReceiveProps(nextProps /*: Props */) { | |||
if (!this.props.selected && nextProps.selected) { | |||
this.scheduleTooltip(); | |||
} else if (this.props.selected && !nextProps.selected) { | |||
@@ -82,7 +86,7 @@ export default class SearchResult extends React.PureComponent { | |||
this.props.onSelect(this.props.component.key); | |||
}; | |||
renderOrganization = (component: Component) => { | |||
renderOrganization = (component /*: Component */) => { | |||
if (!this.props.appState.organizationsEnabled) { | |||
return null; | |||
} | |||
@@ -102,7 +106,7 @@ export default class SearchResult extends React.PureComponent { | |||
: null; | |||
}; | |||
renderProject = (component: Component) => { | |||
renderProject = (component /*: Component */) => { | |||
if (!['BRC', 'FIL', 'UTS'].includes(component.qualifier) || component.project == null) { | |||
return null; | |||
} |
@@ -21,9 +21,10 @@ | |||
import React from 'react'; | |||
import SearchShowMore from './SearchShowMore'; | |||
import { sortQualifiers } from './utils'; | |||
import type { Component, More, Results } from './utils'; | |||
/*:: import type { Component, More, Results } from './utils'; */ | |||
import { translate } from '../../../helpers/l10n'; | |||
/*:: | |||
type Props = {| | |||
allowMore: boolean, | |||
loadingMore: ?string, | |||
@@ -35,9 +36,10 @@ type Props = {| | |||
results: Results, | |||
selected: ?string | |||
|}; | |||
*/ | |||
export default class SearchResults extends React.PureComponent { | |||
props: Props; | |||
/*:: props: Props; */ | |||
render() { | |||
const qualifiers = Object.keys(this.props.results); |
@@ -23,6 +23,7 @@ import classNames from 'classnames'; | |||
import DeferredSpinner from '../../../components/common/DeferredSpinner'; | |||
import { translate, translateWithParameters } from '../../../helpers/l10n'; | |||
/*:: | |||
type Props = {| | |||
allowMore: boolean, | |||
loadingMore: ?string, | |||
@@ -31,11 +32,12 @@ type Props = {| | |||
qualifier: string, | |||
selected: boolean | |||
|}; | |||
*/ | |||
export default class SearchShowMore extends React.PureComponent { | |||
props: Props; | |||
/*:: props: Props; */ | |||
handleMoreClick = (event: MouseEvent & { currentTarget: HTMLElement }) => { | |||
handleMoreClick = (event /*: MouseEvent & { currentTarget: HTMLElement } */) => { | |||
event.preventDefault(); | |||
event.stopPropagation(); | |||
event.currentTarget.blur(); | |||
@@ -43,7 +45,7 @@ export default class SearchShowMore extends React.PureComponent { | |||
this.props.onMoreClick(qualifier); | |||
}; | |||
handleMoreMouseEnter = (event: { currentTarget: HTMLElement }) => { | |||
handleMoreMouseEnter = (event /*: { currentTarget: HTMLElement } */) => { | |||
const { qualifier } = event.currentTarget.dataset; | |||
this.props.onSelect(`qualifier###${qualifier}`); | |||
}; |
@@ -19,11 +19,11 @@ | |||
*/ | |||
import React from 'react'; | |||
import { shallow, mount } from 'enzyme'; | |||
import type { ShallowWrapper } from 'enzyme'; | |||
/*:: import type { ShallowWrapper } from 'enzyme'; */ | |||
import Search from '../Search'; | |||
import { elementKeydown, clickOutside } from '../../../../helpers/testUtils'; | |||
function render(props?: Object) { | |||
function render(props /*: ?Object */) { | |||
return shallow( | |||
<Search | |||
appState={{ organizationsEnabled: false }} | |||
@@ -33,21 +33,21 @@ function render(props?: Object) { | |||
); | |||
} | |||
function component(key: string, qualifier: string = 'TRK') { | |||
function component(key /*: string */, qualifier /*: string */ = 'TRK') { | |||
return { key, name: key, qualifier }; | |||
} | |||
function next(form: ShallowWrapper, expected: string) { | |||
function next(form /*: ShallowWrapper */, expected /*: string */) { | |||
elementKeydown(form.find('input'), 40); | |||
expect(form.state().selected).toBe(expected); | |||
} | |||
function prev(form: ShallowWrapper, expected: string) { | |||
function prev(form /*: ShallowWrapper */, expected /*: string */) { | |||
elementKeydown(form.find('input'), 38); | |||
expect(form.state().selected).toBe(expected); | |||
} | |||
function select(form: ShallowWrapper, expected: string) { | |||
function select(form /*: ShallowWrapper */, expected /*: string */) { | |||
form.instance().handleSelect(expected); | |||
expect(form.state().selected).toBe(expected); | |||
} |
@@ -22,7 +22,7 @@ import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import SearchResult from '../SearchResult'; | |||
function render(props?: Object) { | |||
function render(props /*: ?Object */) { | |||
return shallow( | |||
// $FlowFixMe | |||
<SearchResult |
@@ -71,6 +71,6 @@ it('renders "Show More" link', () => { | |||
).toMatchSnapshot(); | |||
}); | |||
function component(key: string, qualifier: string = 'TRK') { | |||
function component(key /*: string */, qualifier /*: string */ = 'TRK') { | |||
return { key, name: key, qualifier }; | |||
} |
@@ -22,10 +22,11 @@ import { sortBy } from 'lodash'; | |||
const ORDER = ['DEV', 'VW', 'SVW', 'APP', 'TRK', 'BRC', 'FIL', 'UTS']; | |||
export function sortQualifiers(qualifiers: Array<string>) { | |||
export function sortQualifiers(qualifiers /*: Array<string> */) { | |||
return sortBy(qualifiers, qualifier => ORDER.indexOf(qualifier)); | |||
} | |||
/*:: | |||
export type Component = { | |||
isFavorite?: boolean, | |||
isRecentlyBrowsed?: boolean, | |||
@@ -36,7 +37,12 @@ export type Component = { | |||
project?: string, | |||
qualifier: string | |||
}; | |||
*/ | |||
/*:: | |||
export type Results = { [qualifier: string]: Array<Component> }; | |||
*/ | |||
/*:: | |||
export type More = { [string]: number }; | |||
*/ |
@@ -20,7 +20,7 @@ | |||
// @flow | |||
const extensions = {}; | |||
const registerExtension = (key: string, start: Function) => { | |||
const registerExtension = (key /*: string */, start /*: Function */) => { | |||
extensions[key] = start; | |||
}; | |||
@@ -28,6 +28,6 @@ export default () => { | |||
window.registerExtension = registerExtension; | |||
}; | |||
export const getExtensionFromCache = (key: string) => { | |||
export const getExtensionFromCache = (key /*: string */) => { | |||
return extensions[key]; | |||
}; |
@@ -21,7 +21,7 @@ | |||
import getStore from './getStore'; | |||
import { onFail } from '../../store/rootActions'; | |||
export default function throwGlobalError(error: Object) { | |||
export default function throwGlobalError(error /*: Object */) { | |||
const store = getStore(); | |||
onFail(store.dispatch)(error); | |||
return Promise.reject(); |
@@ -17,11 +17,10 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
// @flow | |||
import { getValues } from '../../api/settings'; | |||
import { receiveValues } from '../settings/store/values/actions'; | |||
export const fetchAboutPageSettings = (): Function => (dispatch: Function): Promise<*> => { | |||
export const fetchAboutPageSettings = () => dispatch => { | |||
const keys = ['sonar.lf.aboutText']; | |||
return getValues(keys.join()).then(values => { |
@@ -39,6 +39,7 @@ import { fetchAboutPageSettings } from '../actions'; | |||
import AboutAppForSonarQubeDotComLazyLoader from './AboutAppForSonarQubeDotComLazyLoader'; | |||
import '../styles.css'; | |||
/*:: | |||
type State = { | |||
loading: boolean, | |||
projectsCount: number, | |||
@@ -48,11 +49,12 @@ type State = { | |||
} | |||
} | |||
}; | |||
*/ | |||
class AboutApp extends React.PureComponent { | |||
mounted: boolean; | |||
/*:: mounted: boolean; */ | |||
props: { | |||
/*:: props: { | |||
appState: { | |||
defaultOrganization: string, | |||
organizationsEnabled: boolean | |||
@@ -62,8 +64,9 @@ class AboutApp extends React.PureComponent { | |||
fetchAboutPageSettings: () => Promise<*>, | |||
sonarqubeDotCom?: { value: string } | |||
}; | |||
*/ | |||
state: State = { | |||
state /*: State */ = { | |||
loading: true, | |||
projectsCount: 0 | |||
}; |
@@ -31,6 +31,7 @@ import AboutScanners from './AboutScanners'; | |||
import SonarCloudGetStarted from './SonarCloudGetStarted'; | |||
import '../sonarqube-dot-com-styles.css'; | |||
/*:: | |||
type Props = { | |||
appState: { | |||
defaultOrganization: string, | |||
@@ -44,8 +45,9 @@ type Props = { | |||
projectsCount: number, | |||
vulnerabilities: number | |||
}; | |||
*/ | |||
export default function AboutAppForSonarQubeDotCom(props: Props) { | |||
export default function AboutAppForSonarQubeDotCom(props /*: Props */) { | |||
const { customText } = props; | |||
return ( |
@@ -23,12 +23,14 @@ import { Link } from 'react-router'; | |||
import { formatMeasure } from '../../../helpers/measures'; | |||
import { translate } from '../../../helpers/l10n'; | |||
/*:: | |||
type Props = { | |||
count: number, | |||
loading: boolean | |||
}; | |||
*/ | |||
export default function AboutProjects({ count, loading }: Props) { | |||
export default function AboutProjects({ count, loading } /*: Props */) { | |||
return ( | |||
<div className="about-page-projects"> | |||
{loading && <i className="spinner" />} |
@@ -22,14 +22,16 @@ import React from 'react'; | |||
import { Link } from 'react-router'; | |||
import { getRulesUrl } from '../../../helpers/urls'; | |||
/*:: | |||
type Props = { | |||
appState: { | |||
defaultOrganization: string, | |||
organizationsEnabled: boolean | |||
} | |||
}; | |||
*/ | |||
export default function AboutRulesForSonarQubeDotCom(props: Props) { | |||
export default function AboutRulesForSonarQubeDotCom(props /*: Props */) { | |||
const organization = props.appState.defaultOrganization; | |||
return ( |
@@ -29,14 +29,16 @@ const owaspTags = | |||
'owasp-a1,owasp-a2,owasp-a3,owasp-a4,owasp-a5,owasp-a6,owasp-a7,owasp-a8,owasp-a9,owasp-a10'; | |||
const sans25Tags = 'sans-top25-porous,sans-top25-risky,sans-top25-insecure'; | |||
/*:: | |||
type Props = { | |||
appState: { | |||
defaultOrganization: string, | |||
organizationsEnabled: boolean | |||
} | |||
}; | |||
*/ | |||
export default function AboutStandards(props: Props) { | |||
export default function AboutStandards(props /*: Props */) { | |||
const organization = props.appState.organizationsEnabled | |||
? props.appState.defaultOrganization | |||
: null; |
@@ -27,14 +27,18 @@ import BugIcon from '../../../components/icons-components/BugIcon'; | |||
import VulnerabilityIcon from '../../../components/icons-components/VulnerabilityIcon'; | |||
import CodeSmellIcon from '../../../components/icons-components/CodeSmellIcon'; | |||
/*:: | |||
type Props = { | |||
bugs: ?number, | |||
codeSmells: ?number, | |||
loading: boolean, | |||
vulnerabilities: ?number | |||
}; | |||
*/ | |||
export default function EntryIssueTypes({ bugs, codeSmells, loading, vulnerabilities }: Props) { | |||
export default function EntryIssueTypes( | |||
{ bugs, codeSmells, loading, vulnerabilities } /*: Props */ | |||
) { | |||
return ( | |||
<div className="about-page-projects"> | |||
{loading && <i className="spinner" />} |
@@ -27,19 +27,18 @@ import BugIconForSonarQubeDotCom from './BugIconForSonarQubeDotCom'; | |||
import VulnerabilityIconForSonarQubeDotCom from './VulnerabilityIconForSonarQubeDotCom'; | |||
import CodeSmellIconForSonarQubeDotCom from './CodeSmellIconForSonarQubeDotCom'; | |||
/*:: | |||
type Props = { | |||
bugs: ?number, | |||
codeSmells: ?number, | |||
loading: boolean, | |||
vulnerabilities: ?number | |||
}; | |||
*/ | |||
export default function EntryIssueTypesForSonarQubeDotCom({ | |||
bugs, | |||
codeSmells, | |||
loading, | |||
vulnerabilities | |||
}: Props) { | |||
export default function EntryIssueTypesForSonarQubeDotCom( | |||
{ bugs, codeSmells, loading, vulnerabilities } /*: Props */ | |||
) { | |||
return ( | |||
<div className="about-page-projects"> | |||
{loading && <i className="spinner" />} |
@@ -22,6 +22,7 @@ import React from 'react'; | |||
import OAuthProviders from '../../sessions/components/OAuthProviders'; | |||
import { getIdentityProviders } from '../../../api/users'; | |||
/*:: | |||
type State = { | |||
identityProviders: Array<{ | |||
backgroundColor: string, | |||
@@ -31,10 +32,11 @@ type State = { | |||
}>, | |||
loading: boolean | |||
}; | |||
*/ | |||
export default class SonarCloudGetStarted extends React.PureComponent { | |||
mounted: boolean; | |||
state: State = { | |||
/*:: mounted: boolean; */ | |||
state /*: State */ = { | |||
identityProviders: [], | |||
loading: true | |||
}; | |||
@@ -57,7 +59,7 @@ export default class SonarCloudGetStarted extends React.PureComponent { | |||
}); | |||
}; | |||
formatLabel = (name: string) => `Start with ${name}`; | |||
formatLabel = (name /*: string */) => `Start with ${name}`; | |||
render() { | |||
if (this.state.loading) { |
@@ -23,11 +23,13 @@ import { Link, IndexLink } from 'react-router'; | |||
import NavBarTabs from '../../../components/nav/NavBarTabs'; | |||
import { translate } from '../../../helpers/l10n'; | |||
/*:: | |||
type Props = { | |||
customOrganizations: boolean | |||
}; | |||
*/ | |||
export default function Nav({ customOrganizations }: Props) { | |||
export default function Nav({ customOrganizations } /*: Props */) { | |||
return ( | |||
<nav className="account-nav"> | |||
<NavBarTabs> |
@@ -26,14 +26,15 @@ import { | |||
getNotificationChannels, | |||
getNotificationGlobalTypes | |||
} from '../../../store/rootReducer'; | |||
import type { | |||
/*:: import type { | |||
Notification, | |||
NotificationsState, | |||
ChannelsState, | |||
TypesState | |||
} from '../../../store/notifications/duck'; | |||
} from '../../../store/notifications/duck'; */ | |||
import { addNotification, removeNotification } from './actions'; | |||
/*:: | |||
type Props = { | |||
notifications: NotificationsState, | |||
channels: ChannelsState, | |||
@@ -41,8 +42,9 @@ type Props = { | |||
addNotification: (n: Notification) => void, | |||
removeNotification: (n: Notification) => void | |||
}; | |||
*/ | |||
function GlobalNotifications(props: Props) { | |||
function GlobalNotifications(props /*: Props */) { | |||
return ( | |||
<section> | |||
<h2 className="spacer-bottom"> |
@@ -27,9 +27,10 @@ import { translate } from '../../../helpers/l10n'; | |||
import { fetchNotifications } from './actions'; | |||
class Notifications extends React.PureComponent { | |||
props: { | |||
/*:: props: { | |||
fetchNotifications: () => void | |||
}; | |||
*/ | |||
componentDidMount() { | |||
this.props.fetchNotifications(); |
@@ -20,15 +20,15 @@ | |||
import React from 'react'; | |||
import Checkbox from '../../../components/controls/Checkbox'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { | |||
/*:: import type { | |||
Notification, | |||
NotificationsState, | |||
ChannelsState, | |||
TypesState | |||
} from '../../../store/notifications/duck'; | |||
} from '../../../store/notifications/duck'; */ | |||
export default class NotificationsList extends React.PureComponent { | |||
props: { | |||
/*:: props: { | |||
onAdd: (n: Notification) => void, | |||
onRemove: (n: Notification) => void, | |||
channels: ChannelsState, | |||
@@ -36,14 +36,15 @@ export default class NotificationsList extends React.PureComponent { | |||
types: TypesState, | |||
notifications: NotificationsState | |||
}; | |||
*/ | |||
isEnabled(type: string, channel: string): boolean { | |||
isEnabled(type /*: string */, channel /*: string */) /*: boolean */ { | |||
return !!this.props.notifications.find( | |||
notification => notification.type === type && notification.channel === channel | |||
); | |||
} | |||
handleCheck(type: string, channel: string, checked: boolean) { | |||
handleCheck(type /*: string */, channel /*: string */, checked /*: boolean */) { | |||
if (checked) { | |||
this.props.onAdd({ type, channel }); | |||
} else { |
@@ -28,17 +28,17 @@ import { | |||
getNotificationChannels, | |||
getNotificationPerProjectTypes | |||
} from '../../../store/rootReducer'; | |||
import type { | |||
/*:: import type { | |||
Notification, | |||
NotificationsState, | |||
ChannelsState, | |||
TypesState | |||
} from '../../../store/notifications/duck'; | |||
} from '../../../store/notifications/duck'; */ | |||
import { addNotification, removeNotification } from './actions'; | |||
import { getProjectUrl } from '../../../helpers/urls'; | |||
class ProjectNotifications extends React.PureComponent { | |||
props: { | |||
/*:: props: { | |||
project: { | |||
key: string, | |||
name: string, | |||
@@ -50,6 +50,7 @@ class ProjectNotifications extends React.PureComponent { | |||
addNotification: (n: Notification) => void, | |||
removeNotification: (n: Notification) => void | |||
}; | |||
*/ | |||
handleAddNotification({ channel, type }) { | |||
this.props.addNotification({ |
@@ -27,28 +27,32 @@ import { translate } from '../../../helpers/l10n'; | |||
import { getSuggestions } from '../../../api/components'; | |||
import { getProjectsWithNotifications } from '../../../store/rootReducer'; | |||
/*:: | |||
type Props = { | |||
projects: Array<{ | |||
key: string, | |||
name: string | |||
}> | |||
}; | |||
*/ | |||
/*:: | |||
type State = { | |||
addedProjects: Array<{ | |||
key: string, | |||
name: string | |||
}> | |||
}; | |||
*/ | |||
class Projects extends React.PureComponent { | |||
props: Props; | |||
/*:: props: Props; */ | |||
state: State = { | |||
state /*: State */ = { | |||
addedProjects: [] | |||
}; | |||
componentWillReceiveProps(nextProps: Props) { | |||
componentWillReceiveProps(nextProps /*: Props */) { | |||
// remove all projects from `this.state.addedProjects` | |||
// that already exist in `nextProps.projects` | |||
const nextAddedProjects = differenceBy( |
@@ -19,17 +19,17 @@ | |||
*/ | |||
// @flow | |||
import * as api from '../../../api/notifications'; | |||
import type { GetNotificationsResponse } from '../../../api/notifications'; | |||
/*:: import type { GetNotificationsResponse } from '../../../api/notifications'; */ | |||
import { onFail, fetchOrganizations } from '../../../store/rootActions'; | |||
import { | |||
receiveNotifications, | |||
addNotification as addNotificationAction, | |||
removeNotification as removeNotificationAction | |||
} from '../../../store/notifications/duck'; | |||
import type { Notification } from '../../../store/notifications/duck'; | |||
/*:: import type { Notification } from '../../../store/notifications/duck'; */ | |||
export const fetchNotifications = () => (dispatch: Function) => { | |||
const onFulfil = (response: GetNotificationsResponse) => { | |||
export const fetchNotifications = () => (dispatch /*: Function */) => { | |||
const onFulfil = (response /*: GetNotificationsResponse */) => { | |||
const organizations = response.notifications | |||
.filter(n => n.organization) | |||
.map(n => n.organization); | |||
@@ -49,12 +49,12 @@ export const fetchNotifications = () => (dispatch: Function) => { | |||
return api.getNotifications().then(onFulfil, onFail(dispatch)); | |||
}; | |||
export const addNotification = (n: Notification) => (dispatch: Function) => | |||
export const addNotification = (n /*: Notification */) => (dispatch /*: Function */) => | |||
api | |||
.addNotification(n.channel, n.type, n.project) | |||
.then(() => dispatch(addNotificationAction(n)), onFail(dispatch)); | |||
export const removeNotification = (n: Notification) => (dispatch: Function) => | |||
export const removeNotification = (n /*: Notification */) => (dispatch /*: Function */) => | |||
api | |||
.removeNotification(n.channel, n.type, n.project) | |||
.then(() => dispatch(removeNotificationAction(n)), onFail(dispatch)); |
@@ -26,6 +26,7 @@ import { withRouter } from 'react-router'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { createOrganization } from '../../organizations/actions'; | |||
/*:: | |||
type State = { | |||
loading: boolean, | |||
avatar: string, | |||
@@ -35,14 +36,16 @@ type State = { | |||
name: string, | |||
url: string | |||
}; | |||
*/ | |||
class CreateOrganizationForm extends React.PureComponent { | |||
mounted: boolean; | |||
state: State; | |||
props: { | |||
/*:: mounted: boolean; */ | |||
/*:: state: State; */ | |||
/*:: props: { | |||
createOrganization: (fields: {}) => Promise<*>, | |||
router: { push: string => void } | |||
}; | |||
*/ | |||
constructor(props) { | |||
super(props); | |||
@@ -83,19 +86,19 @@ class CreateOrganizationForm extends React.PureComponent { | |||
this.closeForm(); | |||
}; | |||
handleAvatarInputChange = (e: Object) => { | |||
handleAvatarInputChange = (e /*: Object */) => { | |||
const { value } = e.target; | |||
this.setState({ avatar: value }); | |||
this.changeAvatarImage(value); | |||
}; | |||
changeAvatarImage = (value: string) => { | |||
changeAvatarImage = (value /*: string */) => { | |||
this.setState({ avatarImage: value }); | |||
}; | |||
handleSubmit = (e: Object) => { | |||
handleSubmit = (e /*: Object */) => { | |||
e.preventDefault(); | |||
const organization: Object = { name: this.state.name }; | |||
const organization /*: Object */ = { name: this.state.name }; | |||
if (this.state.avatar) { | |||
Object.assign(organization, { avatar: this.state.avatar }); | |||
} |
@@ -20,13 +20,15 @@ | |||
// @flow | |||
import React from 'react'; | |||
import OrganizationLink from '../../../components/ui/OrganizationLink'; | |||
import type { Organization } from '../../../store/organizations/duck'; | |||
/*:: import type { Organization } from '../../../store/organizations/duck'; */ | |||
/*:: | |||
type Props = { | |||
organization: Organization | |||
}; | |||
*/ | |||
export default function OrganizationCard(props: Props) { | |||
export default function OrganizationCard(props /*: Props */) { | |||
const { organization } = props; | |||
return ( |
@@ -21,13 +21,15 @@ | |||
import React from 'react'; | |||
import { sortBy } from 'lodash'; | |||
import OrganizationCard from './OrganizationCard'; | |||
import type { Organization } from '../../../store/organizations/duck'; | |||
/*:: import type { Organization } from '../../../store/organizations/duck'; */ | |||
/*:: | |||
type Props = { | |||
organizations: Array<Organization> | |||
}; | |||
*/ | |||
export default function OrganizationsList(props: Props) { | |||
export default function OrganizationsList(props /*: Props */) { | |||
return ( | |||
<ul className="account-projects-list"> | |||
{sortBy(props.organizations, organization => |
@@ -26,12 +26,12 @@ import OrganizationsList from './OrganizationsList'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { fetchIfAnyoneCanCreateOrganizations, fetchMyOrganizations } from './actions'; | |||
import { getAppState, getMyOrganizations, getSettingValue } from '../../../store/rootReducer'; | |||
import type { Organization } from '../../../store/organizations/duck'; | |||
/*:: import type { Organization } from '../../../store/organizations/duck'; */ | |||
class UserOrganizations extends React.PureComponent { | |||
mounted: boolean; | |||
/*:: mounted: boolean; */ | |||
props: { | |||
/*:: props: { | |||
anyoneCanCreate?: { value: string }, | |||
canAdmin: boolean, | |||
children?: React.Element<*>, | |||
@@ -39,8 +39,9 @@ class UserOrganizations extends React.PureComponent { | |||
fetchIfAnyoneCanCreateOrganizations: () => Promise<*>, | |||
fetchMyOrganizations: () => Promise<*> | |||
}; | |||
*/ | |||
state: { loading: boolean } = { | |||
state /*: { loading: boolean } */ = { | |||
loading: true | |||
}; | |||
@@ -17,13 +17,12 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
// @flow | |||
import * as api from '../../../api/organizations'; | |||
import { receiveMyOrganizations } from '../../../store/organizations/duck'; | |||
import { getValues } from '../../../api/settings'; | |||
import { receiveValues } from '../../settings/store/values/actions'; | |||
export const fetchMyOrganizations = (): Function => (dispatch: Function): Promise<*> => { | |||
export const fetchMyOrganizations = () => dispatch => { | |||
return api.getMyOrganizations().then(keys => { | |||
if (keys.length > 0) { | |||
return api.getOrganizations(keys).then(({ organizations }) => { | |||
@@ -35,9 +34,7 @@ export const fetchMyOrganizations = (): Function => (dispatch: Function): Promis | |||
}); | |||
}; | |||
export const fetchIfAnyoneCanCreateOrganizations = (): Function => ( | |||
dispatch: Function | |||
): Promise<*> => { | |||
export const fetchIfAnyoneCanCreateOrganizations = () => dispatch => { | |||
return getValues('sonar.organizations.anyoneCanCreate').then(values => { | |||
dispatch(receiveValues(values)); | |||
}); |
@@ -25,6 +25,7 @@ import UserGroups from './UserGroups'; | |||
import UserScmAccounts from './UserScmAccounts'; | |||
import { getCurrentUser, areThereCustomOrganizations } from '../../../store/rootReducer'; | |||
/*:: | |||
type Props = { | |||
customOrganizations: boolean, | |||
user: { | |||
@@ -36,8 +37,9 @@ type Props = { | |||
scmAccounts: Array<*> | |||
} | |||
}; | |||
*/ | |||
function Profile(props: Props) { | |||
function Profile(props /*: Props */) { | |||
const { customOrganizations, user } = props; | |||
return ( |
@@ -37,18 +37,21 @@ import { | |||
cancelTask as cancelTaskAPI | |||
} from '../../../api/ce'; | |||
import { updateTask, mapFiltersToParameters } from '../utils'; | |||
import { Task } from '../types'; | |||
/*:: import type { Task } from '../types'; */ | |||
import { getComponent } from '../../../store/rootReducer'; | |||
import '../background-tasks.css'; | |||
import { fetchOrganizations } from '../../../store/rootActions'; | |||
import { translate } from '../../../helpers/l10n'; | |||
/*:: | |||
type Props = { | |||
component: Object, | |||
location: Object, | |||
fetchOrganizations: (Array<string>) => string | |||
}; | |||
*/ | |||
/*:: | |||
type State = { | |||
loading: boolean, | |||
tasks: Array<*>, | |||
@@ -57,17 +60,18 @@ type State = { | |||
pendingCount: number, | |||
failingCount: number | |||
}; | |||
*/ | |||
class BackgroundTasksApp extends React.PureComponent { | |||
loadTasksDebounced: Function; | |||
mounted: boolean; | |||
props: Props; | |||
/*:: loadTasksDebounced: Function; */ | |||
/*:: mounted: boolean; */ | |||
/*:: props: Props; */ | |||
static contextTypes = { | |||
router: PropTypes.object.isRequired | |||
}; | |||
state: State = { | |||
state /*: State */ = { | |||
loading: true, | |||
tasks: [], | |||
@@ -92,7 +96,7 @@ class BackgroundTasksApp extends React.PureComponent { | |||
}); | |||
} | |||
componentDidUpdate(prevProps: Props) { | |||
componentDidUpdate(prevProps /*: Props */) { | |||
if ( | |||
prevProps.component !== this.props.component || | |||
prevProps.location !== this.props.location | |||
@@ -117,7 +121,7 @@ class BackgroundTasksApp extends React.PureComponent { | |||
const query = this.props.location.query.query || DEFAULT_FILTERS.query; | |||
const filters = { status, taskType, currents, minSubmittedAt, maxExecutedAt, query }; | |||
const parameters: Object = mapFiltersToParameters(filters); | |||
const parameters /*: Object */ = mapFiltersToParameters(filters); | |||
if (this.props.component) { | |||
parameters.componentId = this.props.component.id; | |||
@@ -144,7 +148,7 @@ class BackgroundTasksApp extends React.PureComponent { | |||
}); | |||
} | |||
handleFilterUpdate(nextState: Object) { | |||
handleFilterUpdate(nextState /*: Object */) { | |||
const nextQuery = { ...this.props.location.query, ...nextState }; | |||
// remove defaults | |||
@@ -160,7 +164,7 @@ class BackgroundTasksApp extends React.PureComponent { | |||
}); | |||
} | |||
handleCancelTask(task: Task) { | |||
handleCancelTask(task /*: Task */) { | |||
this.setState({ loading: true }); | |||
cancelTaskAPI(task.id).then(nextTask => { | |||
@@ -171,7 +175,7 @@ class BackgroundTasksApp extends React.PureComponent { | |||
}); | |||
} | |||
handleFilterTask(task: Task) { | |||
handleFilterTask(task /*: Task */) { | |||
this.handleFilterUpdate({ query: task.componentKey }); | |||
} | |||
@@ -22,7 +22,9 @@ import React from 'react'; | |||
import Checkbox from '../../../components/controls/Checkbox'; | |||
import { CURRENTS } from '../constants'; | |||
const CurrentsFilter = ({ value, onChange }: { value: ?string, onChange: string => void }) => { | |||
const CurrentsFilter = ( | |||
{ value, onChange } /*: { value: ?string, onChange: string => void } */ | |||
) => { | |||
function handleChange(value) { | |||
const newValue = value ? CURRENTS.ONLY_CURRENTS : CURRENTS.ALL; | |||
onChange(newValue); |
@@ -19,12 +19,12 @@ | |||
*/ | |||
/* @flow */ | |||
import React from 'react'; | |||
import { Task } from '../types'; | |||
/*:: import type { Task } from '../types'; */ | |||
import { translateWithParameters } from '../../../helpers/l10n'; | |||
const LIMIT = 1000; | |||
const Footer = ({ tasks }: { tasks: Task[] }) => { | |||
const Footer = ({ tasks } /*: { tasks: Task[] } */) => { | |||
if (tasks.length < LIMIT) { | |||
return null; | |||
} |
@@ -22,11 +22,13 @@ import React from 'react'; | |||
import Workers from './Workers'; | |||
import { translate } from '../../../helpers/l10n'; | |||
/*:: | |||
type Props = { | |||
component?: Object | |||
}; | |||
*/ | |||
export default function Header(props: Props) { | |||
export default function Header(props /*: Props */) { | |||
return ( | |||
<header className="page-header"> | |||
<h1 className="page-title"> |
@@ -23,19 +23,23 @@ import Modal from 'react-modal'; | |||
import { getTask } from '../../../api/ce'; | |||
import { translate } from '../../../helpers/l10n'; | |||
/*:: | |||
type Props = { | |||
onClose: () => void, | |||
task: { componentName: string, id: string, type: string } | |||
}; | |||
*/ | |||
/*:: | |||
type State = { | |||
scannerContext: ?string | |||
}; | |||
*/ | |||
export default class ScannerContext extends React.PureComponent { | |||
mounted: boolean; | |||
props: Props; | |||
state: State = { | |||
/*:: mounted: boolean; */ | |||
/*:: props: Props; */ | |||
state /*: State */ = { | |||
scannerContext: null | |||
}; | |||
@@ -56,7 +60,7 @@ export default class ScannerContext extends React.PureComponent { | |||
}); | |||
} | |||
handleCloseClick = (event: Event) => { | |||
handleCloseClick = (event /*: Event */) => { | |||
event.preventDefault(); | |||
this.props.onClose(); | |||
}; |
@@ -38,32 +38,32 @@ export default class Search extends React.PureComponent { | |||
onReload: PropTypes.func.isRequired | |||
}; | |||
handleStatusChange(status: string) { | |||
handleStatusChange(status /*: string */) { | |||
this.props.onFilterUpdate({ status }); | |||
} | |||
handleTypeChange(taskType: string) { | |||
handleTypeChange(taskType /*: string */) { | |||
this.props.onFilterUpdate({ taskType }); | |||
} | |||
handleCurrentsChange(currents: string) { | |||
handleCurrentsChange(currents /*: string */) { | |||
this.props.onFilterUpdate({ currents }); | |||
} | |||
handleDateChange(date: string) { | |||
handleDateChange(date /*: string */) { | |||
this.props.onFilterUpdate(date); | |||
} | |||
handleQueryChange(query: string) { | |||
handleQueryChange(query /*: string */) { | |||
this.props.onFilterUpdate({ query }); | |||
} | |||
handleReload(e: Object) { | |||
handleReload(e /*: Object */) { | |||
e.target.blur(); | |||
this.props.onReload(); | |||
} | |||
handleReset(e: Object) { | |||
handleReset(e /*: Object */) { | |||
e.preventDefault(); | |||
e.target.blur(); | |||
this.props.onFilterUpdate(DEFAULT_FILTERS); |
@@ -23,20 +23,24 @@ import Modal from 'react-modal'; | |||
import { getTask } from '../../../api/ce'; | |||
import { translate } from '../../../helpers/l10n'; | |||
/*:: | |||
type Props = { | |||
onClose: () => void, | |||
task: { componentName: string, errorMessage: string, id: string, type: string } | |||
}; | |||
*/ | |||
/*:: | |||
type State = { | |||
loading: boolean, | |||
stacktrace: ?string | |||
}; | |||
*/ | |||
export default class Stacktrace extends React.PureComponent { | |||
mounted: boolean; | |||
props: Props; | |||
state: State = { | |||
/*:: mounted: boolean; */ | |||
/*:: props: Props; */ | |||
state /*: State */ = { | |||
loading: true, | |||
stacktrace: null | |||
}; | |||
@@ -58,7 +62,7 @@ export default class Stacktrace extends React.PureComponent { | |||
}); | |||
} | |||
handleCloseClick = (event: Event) => { | |||
handleCloseClick = (event /*: Event */) => { | |||
event.preventDefault(); | |||
this.props.onClose(); | |||
}; |
@@ -21,26 +21,30 @@ | |||
import React from 'react'; | |||
import { translate } from '../../../helpers/l10n'; | |||
/*:: | |||
type Props = { | |||
failingCount: number, | |||
pendingCount: number, | |||
onShowFailing: () => void, | |||
onCancelAllPending: () => void | |||
}; | |||
*/ | |||
/*:: | |||
type State = Object; | |||
*/ | |||
export default class Stats extends React.PureComponent { | |||
props: Props; | |||
state: State; | |||
/*:: props: Props; */ | |||
/*:: state: State; */ | |||
handleCancelAllPending(e: Object) { | |||
handleCancelAllPending(e /*: Object */) { | |||
e.preventDefault(); | |||
e.target.blur(); | |||
this.props.onCancelAllPending(); | |||
} | |||
handleShowFailing(e: Object) { | |||
handleShowFailing(e /*: Object */) { | |||
e.preventDefault(); | |||
e.target.blur(); | |||
this.props.onShowFailing(); |
@@ -23,7 +23,7 @@ import Select from 'react-select'; | |||
import { STATUSES } from '../constants'; | |||
import { translate } from '../../../helpers/l10n'; | |||
const StatusFilter = ({ value, onChange }: { value: ?string, onChange: Function }) => { | |||
const StatusFilter = ({ value, onChange } /*: { value: ?string, onChange: Function } */) => { | |||
const options = [ | |||
{ value: STATUSES.ALL, label: translate('background_task.status.ALL') }, | |||
{ |
@@ -23,14 +23,16 @@ import { Link } from 'react-router'; | |||
import TaskType from './TaskType'; | |||
import QualifierIcon from '../../../components/shared/QualifierIcon'; | |||
import Organization from '../../../components/shared/Organization'; | |||
import { Task } from '../types'; | |||
/*:: import type { Task } from '../types'; */ | |||
/*:: | |||
type Props = { | |||
task: Task, | |||
types: Array<string> | |||
}; | |||
*/ | |||
export default function TaskComponent(props: Props) { | |||
export default function TaskComponent(props /*: Props */) { | |||
const { task, types } = props; | |||
if (!task.componentKey) { |
@@ -21,15 +21,13 @@ | |||
import moment from 'moment'; | |||
import React from 'react'; | |||
const TaskDate = ({ | |||
date, | |||
baseDate, | |||
format | |||
}: { | |||
const TaskDate = ( | |||
{ date, baseDate, format } /*: { | |||
date: string, | |||
baseDate: string, | |||
format: string | |||
}) => { | |||
} */ | |||
) => { | |||
const m = moment(date); | |||
const baseM = moment(baseDate); | |||
const diff = date && baseDate ? m.diff(baseM, 'days') : 0; |
@@ -20,13 +20,13 @@ | |||
/* @flow */ | |||
import moment from 'moment'; | |||
import React from 'react'; | |||
import { Task } from '../types'; | |||
/*:: import type { Task } from '../types'; */ | |||
function isAnotherDay(a, b) { | |||
return !moment(a).isSame(moment(b), 'day'); | |||
} | |||
const TaskDay = ({ task, prevTask }: { task: Task, prevTask: ?Task }) => { | |||
const TaskDay = ({ task, prevTask } /*: { task: Task, prevTask: ?Task } */) => { | |||
const shouldDisplay = !prevTask || isAnotherDay(task.submittedAt, prevTask.submittedAt); | |||
return ( |
@@ -20,9 +20,9 @@ | |||
/* @flow */ | |||
import React from 'react'; | |||
import { formatDuration } from '../utils'; | |||
import { Task } from '../types'; | |||
/*:: import type { Task } from '../types'; */ | |||
const TaskExecutionTime = ({ task }: { task: Task }) => { | |||
const TaskExecutionTime = ({ task } /*: { task: Task } */) => { | |||
return ( | |||
<td className="thin nowrap text-right"> | |||
{formatDuration(task.executionTimeMs)} |
@@ -22,9 +22,9 @@ import React from 'react'; | |||
import { STATUSES } from './../constants'; | |||
import PendingIcon from '../../../components/shared/pending-icon'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { Task } from '../types'; | |||
/*:: import type { Task } from '../types'; */ | |||
const TaskStatus = ({ task }: { task: Task }) => { | |||
const TaskStatus = ({ task } /*: { task: Task } */) => { | |||
let inner; | |||
switch (task.status) { |
@@ -19,10 +19,10 @@ | |||
*/ | |||
/* @flow */ | |||
import React from 'react'; | |||
import { Task } from '../types'; | |||
/*:: import type { Task } from '../types'; */ | |||
import { translate } from '../../../helpers/l10n'; | |||
const TaskType = ({ task }: { task: Task }) => { | |||
const TaskType = ({ task } /*: { task: Task } */) => { | |||
return ( | |||
<span className="note nowrap spacer-left"> | |||
{'['} |
@@ -23,6 +23,7 @@ import classNames from 'classnames'; | |||
import Task from './Task'; | |||
import { translate } from '../../../helpers/l10n'; | |||
/*:: | |||
type Props = { | |||
tasks: Array<*>, | |||
component: Object, | |||
@@ -31,12 +32,15 @@ type Props = { | |||
onCancelTask: Function, | |||
onFilterTask: Function | |||
}; | |||
*/ | |||
/*:: | |||
type State = Object; | |||
*/ | |||
export default class Tasks extends React.PureComponent { | |||
props: Props; | |||
state: State; | |||
/*:: props: Props; */ | |||
/*:: state: State; */ | |||
render() { | |||
const { tasks, component, types, loading, onCancelTask, onFilterTask } = this.props; |
@@ -23,15 +23,13 @@ import Select from 'react-select'; | |||
import { ALL_TYPES } from '../constants'; | |||
import { translate } from '../../../helpers/l10n'; | |||
const TypesFilter = ({ | |||
value, | |||
onChange, | |||
types | |||
}: { | |||
const TypesFilter = ( | |||
{ value, onChange, types } /*: { | |||
value: string, | |||
onChange: Function, | |||
types: string[] | |||
}) => { | |||
} */ | |||
) => { | |||
const options = types.map(t => { | |||
return { | |||
value: t, |
@@ -24,16 +24,18 @@ import Tooltip from '../../../components/controls/Tooltip'; | |||
import { getWorkers } from '../../../api/ce'; | |||
import { translate } from '../../../helpers/l10n'; | |||
/*:: | |||
type State = { | |||
canSetWorkerCount: boolean, | |||
formOpen: boolean, | |||
loading: boolean, | |||
workerCount: number | |||
}; | |||
*/ | |||
export default class Workers extends React.PureComponent { | |||
mounted: boolean; | |||
state: State = { | |||
/*:: mounted: boolean; */ | |||
state /*: State */ = { | |||
canSetWorkerCount: false, | |||
formOpen: false, | |||
loading: true, | |||
@@ -62,12 +64,12 @@ export default class Workers extends React.PureComponent { | |||
}); | |||
}; | |||
closeForm = (newWorkerCount?: number) => | |||
(newWorkerCount | |||
closeForm = (newWorkerCount /*: ?number */) => | |||
newWorkerCount | |||
? this.setState({ formOpen: false, workerCount: newWorkerCount }) | |||
: this.setState({ formOpen: false })); | |||
: this.setState({ formOpen: false }); | |||
handleChangeClick = (event: Event) => { | |||
handleChangeClick = (event /*: Event */) => { | |||
event.preventDefault(); | |||
this.setState({ formOpen: true }); | |||
}; | |||
@@ -87,7 +89,9 @@ export default class Workers extends React.PureComponent { | |||
{loading | |||
? <i className="spinner little-spacer-left" /> | |||
: <strong className="little-spacer-left">{workerCount}</strong>} | |||
: <strong className="little-spacer-left"> | |||
{workerCount} | |||
</strong>} | |||
{!loading && | |||
(canSetWorkerCount |
@@ -27,22 +27,26 @@ import { translate } from '../../../helpers/l10n'; | |||
const MAX_WORKERS = 10; | |||
/*:: | |||
type Props = { | |||
onClose: (newWorkerCount?: number) => void, | |||
workerCount: number | |||
}; | |||
*/ | |||
/*:: | |||
type State = { | |||
newWorkerCount: number, | |||
submitting: boolean | |||
}; | |||
*/ | |||
export default class WorkersForm extends React.PureComponent { | |||
mounted: boolean; | |||
props: Props; | |||
state: State; | |||
/*:: mounted: boolean; */ | |||
/*:: props: Props; */ | |||
/*:: state: State; */ | |||
constructor(props: Props) { | |||
constructor(props /*: Props */) { | |||
super(props); | |||
this.state = { | |||
newWorkerCount: props.workerCount, | |||
@@ -60,10 +64,10 @@ export default class WorkersForm extends React.PureComponent { | |||
handleClose = () => this.props.onClose(); | |||
handleWorkerCountChange = (option: { value: number }) => | |||
handleWorkerCountChange = (option /*: { value: number } */) => | |||
this.setState({ newWorkerCount: option.value }); | |||
handleSubmit = (event: Event) => { | |||
handleSubmit = (event /*: Event */) => { | |||
event.preventDefault(); | |||
this.setState({ submitting: true }); | |||
const { newWorkerCount } = this.state; | |||
@@ -92,7 +96,9 @@ export default class WorkersForm extends React.PureComponent { | |||
overlayClassName="modal-overlay" | |||
onRequestClose={this.handleClose}> | |||
<header className="modal-head"> | |||
<h2>{translate('background_tasks.change_number_of_workers')}</h2> | |||
<h2> | |||
{translate('background_tasks.change_number_of_workers')} | |||
</h2> | |||
</header> | |||
<form onSubmit={this.handleSubmit}> | |||
<div className="modal-body"> |
@@ -17,7 +17,9 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
/*:: | |||
export type Task = { | |||
incremental: boolean, | |||
id: string | |||
}; | |||
*/ |
@@ -19,13 +19,13 @@ | |||
*/ | |||
/* @flow */ | |||
import { STATUSES, ALL_TYPES, CURRENTS } from './constants'; | |||
import { Task } from './types'; | |||
/*:: import type { Task } from './types'; */ | |||
export function updateTask(tasks: Task[], newTask: Task) { | |||
export function updateTask(tasks /*: Task[] */, newTask /*: Task */) { | |||
return tasks.map(task => (task.id === newTask.id ? newTask : task)); | |||
} | |||
export function mapFiltersToParameters(filters: Object = {}) { | |||
export function mapFiltersToParameters(filters /*: Object */ = {}) { | |||
const parameters = {}; | |||
if (filters.status === STATUSES.ALL) { | |||
@@ -81,7 +81,7 @@ function format(int, suffix) { | |||
return `${int}${suffix}`; | |||
} | |||
export function formatDuration(value: ?number) { | |||
export function formatDuration(value /*: ?number */) { | |||
if (!value) { | |||
return ''; | |||
} |
@@ -27,8 +27,8 @@ import { translate } from '../../../helpers/l10n'; | |||
import init from '../init'; | |||
class CodingRulesAppContainer extends React.PureComponent { | |||
stop: ?() => void; | |||
props: { | |||
/*:: stop: ?() => void; */ | |||
/*:: props: { | |||
appState: { | |||
defaultOrganization: string, | |||
organizationsEnabled: boolean | |||
@@ -40,6 +40,7 @@ class CodingRulesAppContainer extends React.PureComponent { | |||
replace: string => void | |||
} | |||
}; | |||
*/ | |||
componentDidMount() { | |||
if (this.props.appState.organizationsEnabled && !this.props.params.organizationKey) { |
@@ -36,11 +36,13 @@ import { areThereCustomOrganizations } from '../../store/organizations/utils'; | |||
const App = new Marionette.Application(); | |||
App.on('start', function(options: { | |||
App.on('start', function( | |||
options /*: { | |||
el: HTMLElement, | |||
organization: ?string, | |||
isDefaultOrganization: boolean | |||
}) { | |||
} */ | |||
) { | |||
App.organization = options.organization; | |||
const data = options.organization ? { organization: options.organization } : {}; | |||
$.get(window.baseUrl + '/api/rules/app', data) | |||
@@ -110,7 +112,11 @@ App.on('start', function(options: { | |||
}); | |||
}); | |||
export default function(el: HTMLElement, organization: ?string, isDefaultOrganization: boolean) { | |||
export default function( | |||
el /*: HTMLElement */, | |||
organization /*: ?string */, | |||
isDefaultOrganization /*: boolean */ | |||
) { | |||
App.start({ el, organization, isDefaultOrganization }); | |||
return () => { |
@@ -26,13 +26,13 @@ import MeasureOverviewContainer from './MeasureOverviewContainer'; | |||
import Sidebar from '../sidebar/Sidebar'; | |||
import { hasBubbleChart, parseQuery, serializeQuery } from '../utils'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import type { Component, Query, Period } from '../types'; | |||
import type { RawQuery } from '../../../helpers/query'; | |||
import type { Metric } from '../../../store/metrics/actions'; | |||
import type { MeasureEnhanced } from '../../../components/measure/types'; | |||
/*:: import type { Component, Query, Period } from '../types'; */ | |||
/*:: import type { RawQuery } from '../../../helpers/query'; */ | |||
/*:: import type { Metric } from '../../../store/metrics/actions'; */ | |||
/*:: import type { MeasureEnhanced } from '../../../components/measure/types'; */ | |||
import '../style.css'; | |||
type Props = {| | |||
/*:: type Props = {| | |||
component: Component, | |||
currentUser: { isLoggedIn: boolean }, | |||
location: { pathname: string, query: RawQuery }, | |||
@@ -46,20 +46,20 @@ type Props = {| | |||
router: { | |||
push: ({ pathname: string, query?: RawQuery }) => void | |||
} | |||
|}; | |||
|}; */ | |||
type State = {| | |||
/*:: type State = {| | |||
loading: boolean, | |||
measures: Array<MeasureEnhanced>, | |||
leakPeriod: ?Period | |||
|}; | |||
|}; */ | |||
export default class App extends React.PureComponent { | |||
mounted: boolean; | |||
props: Props; | |||
state: State; | |||
/*:: mounted: boolean; */ | |||
/*:: props: Props; */ | |||
/*:: state: State; */ | |||
constructor(props: Props) { | |||
constructor(props /*: Props */) { | |||
super(props); | |||
this.state = { | |||
loading: true, | |||
@@ -79,7 +79,7 @@ export default class App extends React.PureComponent { | |||
} | |||
} | |||
componentWillReceiveProps(nextProps: Props) { | |||
componentWillReceiveProps(nextProps /*: Props */) { | |||
if ( | |||
nextProps.component.key !== this.props.component.key || | |||
nextProps.metrics !== this.props.metrics | |||
@@ -97,7 +97,7 @@ export default class App extends React.PureComponent { | |||
} | |||
} | |||
fetchMeasures = ({ component, fetchMeasures, metrics, metricsKey }: Props) => { | |||
fetchMeasures = ({ component, fetchMeasures, metrics, metricsKey } /*: Props */) => { | |||
this.setState({ loading: true }); | |||
const filteredKeys = metricsKey.filter( | |||
key => !metrics[key].hidden && !['DATA', 'DISTRIB'].includes(metrics[key].type) | |||
@@ -116,7 +116,7 @@ export default class App extends React.PureComponent { | |||
); | |||
}; | |||
updateQuery = (newQuery: Query) => { | |||
updateQuery = (newQuery /*: Query */) => { | |||
const query = serializeQuery({ | |||
...parseQuery(this.props.location.query), | |||
...newQuery |
@@ -32,8 +32,8 @@ import { fetchMetrics } from '../../../store/rootActions'; | |||
import { getMeasuresAndMeta } from '../../../api/measures'; | |||
import { getLeakPeriod } from '../../../helpers/periods'; | |||
import { enhanceMeasure } from '../../../components/measure/utils'; | |||
import type { Component, Period } from '../types'; | |||
import type { Measure, MeasureEnhanced } from '../../../components/measure/types'; | |||
/*:: import type { Component, Period } from '../types'; */ | |||
/*:: import type { Measure, MeasureEnhanced } from '../../../components/measure/types'; */ | |||
const mapStateToProps = (state, ownProps) => ({ | |||
component: getComponent(state, ownProps.location.query.id), | |||
@@ -42,7 +42,7 @@ const mapStateToProps = (state, ownProps) => ({ | |||
metricsKey: getMetricsKey(state) | |||
}); | |||
const banQualityGate = (component: Component): Array<Measure> => { | |||
function banQualityGate(component /*: Component */) /*: Array<Measure> */ { | |||
const bannedMetrics = []; | |||
if (!['VW', 'SVW'].includes(component.qualifier)) { | |||
bannedMetrics.push('alert_status'); | |||
@@ -51,18 +51,18 @@ const banQualityGate = (component: Component): Array<Measure> => { | |||
bannedMetrics.push('releasability_rating', 'releasability_effort'); | |||
} | |||
return component.measures.filter(measure => !bannedMetrics.includes(measure.metric)); | |||
}; | |||
} | |||
const fetchMeasures = (component: string, metricsKey: Array<string>) => ( | |||
const fetchMeasures = (component /*: string */, metricsKey /*: Array<string> */) => ( | |||
dispatch, | |||
getState | |||
): Promise<{ component: Component, measures: Array<MeasureEnhanced>, leakPeriod: ?Period }> => { | |||
) => { | |||
if (metricsKey.length <= 0) { | |||
return Promise.resolve({ component: {}, measures: [], leakPeriod: null }); | |||
} | |||
return getMeasuresAndMeta(component, metricsKey, { additionalFields: 'periods' }).then(r => { | |||
const measures: Array<MeasureEnhanced> = banQualityGate(r.component).map(measure => | |||
const measures = banQualityGate(r.component).map(measure => | |||
enhanceMeasure(measure, getMetrics(getState())) | |||
); | |||