diff options
Diffstat (limited to 'server/sonar-web/src/main/js')
517 files changed, 4429 insertions, 2892 deletions
diff --git a/server/sonar-web/src/main/js/api/application.js b/server/sonar-web/src/main/js/api/application.js index bbc9016c1cb..5aed51768a1 100644 --- a/server/sonar-web/src/main/js/api/application.js +++ b/server/sonar-web/src/main/js/api/application.js @@ -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); +} diff --git a/server/sonar-web/src/main/js/api/ce.js b/server/sonar-web/src/main/js/api/ce.js index 4fa75478b1d..3c426b0d0e6 100644 --- a/server/sonar-web/src/main/js/api/ce.js +++ b/server/sonar-web/src/main/js/api/ce.js @@ -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); +} diff --git a/server/sonar-web/src/main/js/api/components.js b/server/sonar-web/src/main/js/api/components.js index 8c94bf752f4..50f87afea82 100644 --- a/server/sonar-web/src/main/js/api/components.js +++ b/server/sonar-web/src/main/js/api/components.js @@ -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 ); +} diff --git a/server/sonar-web/src/main/js/api/favorites.js b/server/sonar-web/src/main/js/api/favorites.js index 77cef860c49..4b2683dcc59 100644 --- a/server/sonar-web/src/main/js/api/favorites.js +++ b/server/sonar-web/src/main/js/api/favorites.js @@ -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 }); } diff --git a/server/sonar-web/src/main/js/api/issues.js b/server/sonar-web/src/main/js/api/issues.js index 598fdce00de..468df8c5da9 100644 --- a/server/sonar-web/src/main/js/api/issues.js +++ b/server/sonar-web/src/main/js/api/issues.js @@ -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 }); +} diff --git a/server/sonar-web/src/main/js/api/notifications.js b/server/sonar-web/src/main/js/api/notifications.js index 10c8749f59e..8361401b60b 100644 --- a/server/sonar-web/src/main/js/api/notifications.js +++ b/server/sonar-web/src/main/js/api/notifications.js @@ -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); -}; +} diff --git a/server/sonar-web/src/main/js/api/organizations.js b/server/sonar-web/src/main/js/api/organizations.js index 8daf98ac96d..940d698fac7 100644 --- a/server/sonar-web/src/main/js/api/organizations.js +++ b/server/sonar-web/src/main/js/api/organizations.js @@ -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 }); +} diff --git a/server/sonar-web/src/main/js/api/permissions.js b/server/sonar-web/src/main/js/api/permissions.js index 9598197dfe7..e6f043dc970 100644 --- a/server/sonar-web/src/main/js/api/permissions.js +++ b/server/sonar-web/src/main/js/api/permissions.js @@ -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); diff --git a/server/sonar-web/src/main/js/api/projectActivity.js b/server/sonar-web/src/main/js/api/projectActivity.js index 19dd91243dc..ffb3200c08e 100644 --- a/server/sonar-web/src/main/js/api/projectActivity.js +++ b/server/sonar-web/src/main/js/api/projectActivity.js @@ -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); +} diff --git a/server/sonar-web/src/main/js/api/quality-profiles.js b/server/sonar-web/src/main/js/api/quality-profiles.js index 950c2c68c3a..f3fbf7cbd46 100644 --- a/server/sonar-web/src/main/js/api/quality-profiles.js +++ b/server/sonar-web/src/main/js/api/quality-profiles.js @@ -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); diff --git a/server/sonar-web/src/main/js/api/time-machine.js b/server/sonar-web/src/main/js/api/time-machine.js index 6ed6de5bc77..c2f03a80d35 100644 --- a/server/sonar-web/src/main/js/api/time-machine.js +++ b/server/sonar-web/src/main/js/api/time-machine.js @@ -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 ); }); +} diff --git a/server/sonar-web/src/main/js/api/user-tokens.js b/server/sonar-web/src/main/js/api/user-tokens.js index 3947b07f1be..8c46657979e 100644 --- a/server/sonar-web/src/main/js/api/user-tokens.js +++ b/server/sonar-web/src/main/js/api/user-tokens.js @@ -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; } diff --git a/server/sonar-web/src/main/js/api/user_groups.js b/server/sonar-web/src/main/js/api/user_groups.js index fdbe521e94f..71c07fd802b 100644 --- a/server/sonar-web/src/main/js/api/user_groups.js +++ b/server/sonar-web/src/main/js/api/user_groups.js @@ -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); } diff --git a/server/sonar-web/src/main/js/api/users.js b/server/sonar-web/src/main/js/api/users.js index e603c77ef7b..d7d6c8a45e2 100644 --- a/server/sonar-web/src/main/js/api/users.js +++ b/server/sonar-web/src/main/js/api/users.js @@ -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'); } diff --git a/server/sonar-web/src/main/js/api/web-api.js b/server/sonar-web/src/main/js/api/web-api.js index 270759ad1f7..f9323bd67d1 100644 --- a/server/sonar-web/src/main/js/api/web-api.js +++ b/server/sonar-web/src/main/js/api/web-api.js @@ -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 }; diff --git a/server/sonar-web/src/main/js/app/components/App.js b/server/sonar-web/src/main/js/app/components/App.js index 21b2e7e6f96..a99a24f1d17 100644 --- a/server/sonar-web/src/main/js/app/components/App.js +++ b/server/sonar-web/src/main/js/app/components/App.js @@ -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, diff --git a/server/sonar-web/src/main/js/app/components/GlobalContainer.js b/server/sonar-web/src/main/js/app/components/GlobalContainer.js index 68c4c0f7374..43f8b058ec3 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalContainer.js +++ b/server/sonar-web/src/main/js/app/components/GlobalContainer.js @@ -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 ( diff --git a/server/sonar-web/src/main/js/app/components/GlobalFooter.js b/server/sonar-web/src/main/js/app/components/GlobalFooter.js index a6a0c34dd45..d24ae3ab27b 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalFooter.js +++ b/server/sonar-web/src/main/js/app/components/GlobalFooter.js @@ -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} />; } diff --git a/server/sonar-web/src/main/js/app/components/LocalizationContainer.js b/server/sonar-web/src/main/js/app/components/LocalizationContainer.js index 107d5ad9798..2144033ef9d 100644 --- a/server/sonar-web/src/main/js/app/components/LocalizationContainer.js +++ b/server/sonar-web/src/main/js/app/components/LocalizationContainer.js @@ -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 diff --git a/server/sonar-web/src/main/js/app/components/MigrationContainer.js b/server/sonar-web/src/main/js/app/components/MigrationContainer.js index 72c6b5a2ad0..ef24c09e991 100644 --- a/server/sonar-web/src/main/js/app/components/MigrationContainer.js +++ b/server/sonar-web/src/main/js/app/components/MigrationContainer.js @@ -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 diff --git a/server/sonar-web/src/main/js/app/components/ProjectAdminContainer.js b/server/sonar-web/src/main/js/app/components/ProjectAdminContainer.js index 4891093f745..40b591a198d 100644 --- a/server/sonar-web/src/main/js/app/components/ProjectAdminContainer.js +++ b/server/sonar-web/src/main/js/app/components/ProjectAdminContainer.js @@ -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(); diff --git a/server/sonar-web/src/main/js/app/components/ProjectContainer.js b/server/sonar-web/src/main/js/app/components/ProjectContainer.js index 06898e30d8d..b40bd8f9b25 100644 --- a/server/sonar-web/src/main/js/app/components/ProjectContainer.js +++ b/server/sonar-web/src/main/js/app/components/ProjectContainer.js @@ -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 }]); }; diff --git a/server/sonar-web/src/main/js/app/components/RecentHistory.js b/server/sonar-web/src/main/js/app/components/RecentHistory.js index 368eaf31748..1bc7d308621 100644 --- a/server/sonar-web/src/main/js/app/components/RecentHistory.js +++ b/server/sonar-web/src/main/js/app/components/RecentHistory.js @@ -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); diff --git a/server/sonar-web/src/main/js/app/components/SimpleContainer.js b/server/sonar-web/src/main/js/app/components/SimpleContainer.js index a2d22afea2d..02596356d31 100644 --- a/server/sonar-web/src/main/js/app/components/SimpleContainer.js +++ b/server/sonar-web/src/main/js/app/components/SimpleContainer.js @@ -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'); diff --git a/server/sonar-web/src/main/js/app/components/extensions/Extension.js b/server/sonar-web/src/main/js/app/components/extensions/Extension.js index 93dac302b0e..7afb2b642e8 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/Extension.js +++ b/server/sonar-web/src/main/js/app/components/extensions/Extension.js @@ -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, diff --git a/server/sonar-web/src/main/js/app/components/extensions/GlobalAdminPageExtension.js b/server/sonar-web/src/main/js/app/components/extensions/GlobalAdminPageExtension.js index 056623556f1..eff718d6168 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/GlobalAdminPageExtension.js +++ b/server/sonar-web/src/main/js/app/components/extensions/GlobalAdminPageExtension.js @@ -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 />; diff --git a/server/sonar-web/src/main/js/app/components/extensions/GlobalPageExtension.js b/server/sonar-web/src/main/js/app/components/extensions/GlobalPageExtension.js index c31c9c81608..5d82eae4917 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/GlobalPageExtension.js +++ b/server/sonar-web/src/main/js/app/components/extensions/GlobalPageExtension.js @@ -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 />; diff --git a/server/sonar-web/src/main/js/app/components/extensions/OrganizationPageExtension.js b/server/sonar-web/src/main/js/app/components/extensions/OrganizationPageExtension.js index c0428df1cba..ab2931ac382 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/OrganizationPageExtension.js +++ b/server/sonar-web/src/main/js/app/components/extensions/OrganizationPageExtension.js @@ -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) }); diff --git a/server/sonar-web/src/main/js/app/components/extensions/PortfoliosPage.js b/server/sonar-web/src/main/js/app/components/extensions/PortfoliosPage.js index a7f96db6cf6..5556c90027d 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/PortfoliosPage.js +++ b/server/sonar-web/src/main/js/app/components/extensions/PortfoliosPage.js @@ -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 diff --git a/server/sonar-web/src/main/js/app/components/extensions/ProjectAdminPageExtension.js b/server/sonar-web/src/main/js/app/components/extensions/ProjectAdminPageExtension.js index 2b271712002..3a432553dd8 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/ProjectAdminPageExtension.js +++ b/server/sonar-web/src/main/js/app/components/extensions/ProjectAdminPageExtension.js @@ -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) }); diff --git a/server/sonar-web/src/main/js/app/components/extensions/ProjectPageExtension.js b/server/sonar-web/src/main/js/app/components/extensions/ProjectPageExtension.js index ddf910693b3..dd216b54bac 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/ProjectPageExtension.js +++ b/server/sonar-web/src/main/js/app/components/extensions/ProjectPageExtension.js @@ -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) }); diff --git a/server/sonar-web/src/main/js/app/components/extensions/ViewDashboard.js b/server/sonar-web/src/main/js/app/components/extensions/ViewDashboard.js index f1c5419f6b2..050cab3594a 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/ViewDashboard.js +++ b/server/sonar-web/src/main/js/app/components/extensions/ViewDashboard.js @@ -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} diff --git a/server/sonar-web/src/main/js/app/components/extensions/utils.js b/server/sonar-web/src/main/js/app/components/extensions/utils.js index 7294bea0c83..bb3049c7730 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/utils.js +++ b/server/sonar-web/src/main/js/app/components/extensions/utils.js @@ -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) => } }); }); +} diff --git a/server/sonar-web/src/main/js/app/components/help/GlobalHelp.js b/server/sonar-web/src/main/js/app/components/help/GlobalHelp.js index ffc57095a47..7e4b14609b5 100644 --- a/server/sonar-web/src/main/js/app/components/help/GlobalHelp.js +++ b/server/sonar-web/src/main/js/app/components/help/GlobalHelp.js @@ -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 })} diff --git a/server/sonar-web/src/main/js/app/components/help/LinksHelp.js b/server/sonar-web/src/main/js/app/components/help/LinksHelp.js index c541d5fd7a5..627f7d49dcd 100644 --- a/server/sonar-web/src/main/js/app/components/help/LinksHelp.js +++ b/server/sonar-web/src/main/js/app/components/help/LinksHelp.js @@ -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"> diff --git a/server/sonar-web/src/main/js/app/components/help/LinksHelpSonarCloud.js b/server/sonar-web/src/main/js/app/components/help/LinksHelpSonarCloud.js index 3ce8b842da5..3275528cf3c 100644 --- a/server/sonar-web/src/main/js/app/components/help/LinksHelpSonarCloud.js +++ b/server/sonar-web/src/main/js/app/components/help/LinksHelpSonarCloud.js @@ -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"> diff --git a/server/sonar-web/src/main/js/app/components/help/TutorialsHelp.js b/server/sonar-web/src/main/js/app/components/help/TutorialsHelp.js index 82cc931e9f5..ee97ec26116 100644 --- a/server/sonar-web/src/main/js/app/components/help/TutorialsHelp.js +++ b/server/sonar-web/src/main/js/app/components/help/TutorialsHelp.js @@ -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(); }; diff --git a/server/sonar-web/src/main/js/app/components/help/__tests__/GlobalHelp-test.js b/server/sonar-web/src/main/js/app/components/help/__tests__/GlobalHelp-test.js index 76f95d4accb..772448f1c3d 100644 --- a/server/sonar-web/src/main/js/app/components/help/__tests__/GlobalHelp-test.js +++ b/server/sonar-web/src/main/js/app/components/help/__tests__/GlobalHelp-test.js @@ -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 } } }); } diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.js b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.js index 5ad2c836f37..72b1df3f5c6 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.js @@ -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 diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js index 830a351b05e..eee3fca4b6e 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js @@ -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(); diff --git a/server/sonar-web/src/main/js/app/components/search/Search.js b/server/sonar-web/src/main/js/app/components/search/Search.js index fff7cdd5011..84c35015e94 100644 --- a/server/sonar-web/src/main/js/app/components/search/Search.js +++ b/server/sonar-web/src/main/js/app/components/search/Search.js @@ -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} diff --git a/server/sonar-web/src/main/js/app/components/search/SearchResult.js b/server/sonar-web/src/main/js/app/components/search/SearchResult.js index 0488535cba6..f6381a3645d 100644 --- a/server/sonar-web/src/main/js/app/components/search/SearchResult.js +++ b/server/sonar-web/src/main/js/app/components/search/SearchResult.js @@ -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; } diff --git a/server/sonar-web/src/main/js/app/components/search/SearchResults.js b/server/sonar-web/src/main/js/app/components/search/SearchResults.js index ceffcd262db..dfc5870e519 100644 --- a/server/sonar-web/src/main/js/app/components/search/SearchResults.js +++ b/server/sonar-web/src/main/js/app/components/search/SearchResults.js @@ -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); diff --git a/server/sonar-web/src/main/js/app/components/search/SearchShowMore.js b/server/sonar-web/src/main/js/app/components/search/SearchShowMore.js index a36c98368ce..b736a7b2bdc 100644 --- a/server/sonar-web/src/main/js/app/components/search/SearchShowMore.js +++ b/server/sonar-web/src/main/js/app/components/search/SearchShowMore.js @@ -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}`); }; diff --git a/server/sonar-web/src/main/js/app/components/search/__tests__/Search-test.js b/server/sonar-web/src/main/js/app/components/search/__tests__/Search-test.js index 07a2e347e3a..822d42b58f1 100644 --- a/server/sonar-web/src/main/js/app/components/search/__tests__/Search-test.js +++ b/server/sonar-web/src/main/js/app/components/search/__tests__/Search-test.js @@ -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); } diff --git a/server/sonar-web/src/main/js/app/components/search/__tests__/SearchResult-test.js b/server/sonar-web/src/main/js/app/components/search/__tests__/SearchResult-test.js index 70d38fd2ad5..0ff0d8672f9 100644 --- a/server/sonar-web/src/main/js/app/components/search/__tests__/SearchResult-test.js +++ b/server/sonar-web/src/main/js/app/components/search/__tests__/SearchResult-test.js @@ -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 diff --git a/server/sonar-web/src/main/js/app/components/search/__tests__/SearchResults-test.js b/server/sonar-web/src/main/js/app/components/search/__tests__/SearchResults-test.js index c08bba6e14b..51bcac37395 100644 --- a/server/sonar-web/src/main/js/app/components/search/__tests__/SearchResults-test.js +++ b/server/sonar-web/src/main/js/app/components/search/__tests__/SearchResults-test.js @@ -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 }; } diff --git a/server/sonar-web/src/main/js/app/components/search/utils.js b/server/sonar-web/src/main/js/app/components/search/utils.js index ebeea69e645..5b7dd3a4d4b 100644 --- a/server/sonar-web/src/main/js/app/components/search/utils.js +++ b/server/sonar-web/src/main/js/app/components/search/utils.js @@ -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 }; +*/ diff --git a/server/sonar-web/src/main/js/app/utils/installExtensionsHandler.js b/server/sonar-web/src/main/js/app/utils/installExtensionsHandler.js index 144a335d162..494fc93b92d 100644 --- a/server/sonar-web/src/main/js/app/utils/installExtensionsHandler.js +++ b/server/sonar-web/src/main/js/app/utils/installExtensionsHandler.js @@ -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]; }; diff --git a/server/sonar-web/src/main/js/app/utils/throwGlobalError.js b/server/sonar-web/src/main/js/app/utils/throwGlobalError.js index 75cedec4e68..d0441a65c94 100644 --- a/server/sonar-web/src/main/js/app/utils/throwGlobalError.js +++ b/server/sonar-web/src/main/js/app/utils/throwGlobalError.js @@ -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(); diff --git a/server/sonar-web/src/main/js/apps/about/actions.js b/server/sonar-web/src/main/js/apps/about/actions.js index 18f1d88f09d..1596ccdc8e9 100644 --- a/server/sonar-web/src/main/js/apps/about/actions.js +++ b/server/sonar-web/src/main/js/apps/about/actions.js @@ -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 => { diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutApp.js b/server/sonar-web/src/main/js/apps/about/components/AboutApp.js index 715543e99a4..7aec02cb77f 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutApp.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutApp.js @@ -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 }; diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutAppForSonarQubeDotCom.js b/server/sonar-web/src/main/js/apps/about/components/AboutAppForSonarQubeDotCom.js index 80041d540bb..67f3b803d99 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutAppForSonarQubeDotCom.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutAppForSonarQubeDotCom.js @@ -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 ( diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutProjects.js b/server/sonar-web/src/main/js/apps/about/components/AboutProjects.js index 876eb9c74e1..c160383e9d4 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutProjects.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutProjects.js @@ -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" />} diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutRulesForSonarQubeDotCom.js b/server/sonar-web/src/main/js/apps/about/components/AboutRulesForSonarQubeDotCom.js index 3496a27e3d3..1669da98c6a 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutRulesForSonarQubeDotCom.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutRulesForSonarQubeDotCom.js @@ -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 ( diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutStandards.js b/server/sonar-web/src/main/js/apps/about/components/AboutStandards.js index 4fc1b9633ad..893aed8e51f 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutStandards.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutStandards.js @@ -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; diff --git a/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypes.js b/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypes.js index 8ad560410b1..caa1d57279e 100644 --- a/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypes.js +++ b/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypes.js @@ -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" />} diff --git a/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypesForSonarQubeDotCom.js b/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypesForSonarQubeDotCom.js index 1bc8bd60d06..1bdfba96a4e 100644 --- a/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypesForSonarQubeDotCom.js +++ b/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypesForSonarQubeDotCom.js @@ -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" />} diff --git a/server/sonar-web/src/main/js/apps/about/components/SonarCloudGetStarted.js b/server/sonar-web/src/main/js/apps/about/components/SonarCloudGetStarted.js index e467dfc3874..aaf4f8faa87 100644 --- a/server/sonar-web/src/main/js/apps/about/components/SonarCloudGetStarted.js +++ b/server/sonar-web/src/main/js/apps/about/components/SonarCloudGetStarted.js @@ -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) { diff --git a/server/sonar-web/src/main/js/apps/account/components/Nav.js b/server/sonar-web/src/main/js/apps/account/components/Nav.js index d8d39380cd5..14bd9fbdaa1 100644 --- a/server/sonar-web/src/main/js/apps/account/components/Nav.js +++ b/server/sonar-web/src/main/js/apps/account/components/Nav.js @@ -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> diff --git a/server/sonar-web/src/main/js/apps/account/notifications/GlobalNotifications.js b/server/sonar-web/src/main/js/apps/account/notifications/GlobalNotifications.js index 28d3181d25b..d4209080839 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/GlobalNotifications.js +++ b/server/sonar-web/src/main/js/apps/account/notifications/GlobalNotifications.js @@ -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"> diff --git a/server/sonar-web/src/main/js/apps/account/notifications/Notifications.js b/server/sonar-web/src/main/js/apps/account/notifications/Notifications.js index b8c596cba1d..3a150bf551a 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/Notifications.js +++ b/server/sonar-web/src/main/js/apps/account/notifications/Notifications.js @@ -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(); diff --git a/server/sonar-web/src/main/js/apps/account/notifications/NotificationsList.js b/server/sonar-web/src/main/js/apps/account/notifications/NotificationsList.js index e9655c829f4..ae82df2cd4c 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/NotificationsList.js +++ b/server/sonar-web/src/main/js/apps/account/notifications/NotificationsList.js @@ -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 { diff --git a/server/sonar-web/src/main/js/apps/account/notifications/ProjectNotifications.js b/server/sonar-web/src/main/js/apps/account/notifications/ProjectNotifications.js index d774571bb83..eb59f445ca3 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/ProjectNotifications.js +++ b/server/sonar-web/src/main/js/apps/account/notifications/ProjectNotifications.js @@ -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({ diff --git a/server/sonar-web/src/main/js/apps/account/notifications/Projects.js b/server/sonar-web/src/main/js/apps/account/notifications/Projects.js index d3b647ede1b..b4fbe9adf1f 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/Projects.js +++ b/server/sonar-web/src/main/js/apps/account/notifications/Projects.js @@ -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( diff --git a/server/sonar-web/src/main/js/apps/account/notifications/actions.js b/server/sonar-web/src/main/js/apps/account/notifications/actions.js index 4ef2e0e3a25..4b359d4c4c8 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/actions.js +++ b/server/sonar-web/src/main/js/apps/account/notifications/actions.js @@ -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)); diff --git a/server/sonar-web/src/main/js/apps/account/organizations/CreateOrganizationForm.js b/server/sonar-web/src/main/js/apps/account/organizations/CreateOrganizationForm.js index 513ae8d5b7f..3d15de3d760 100644 --- a/server/sonar-web/src/main/js/apps/account/organizations/CreateOrganizationForm.js +++ b/server/sonar-web/src/main/js/apps/account/organizations/CreateOrganizationForm.js @@ -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 }); } diff --git a/server/sonar-web/src/main/js/apps/account/organizations/OrganizationCard.js b/server/sonar-web/src/main/js/apps/account/organizations/OrganizationCard.js index ee3efcc80eb..5dc72aef546 100644 --- a/server/sonar-web/src/main/js/apps/account/organizations/OrganizationCard.js +++ b/server/sonar-web/src/main/js/apps/account/organizations/OrganizationCard.js @@ -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 ( diff --git a/server/sonar-web/src/main/js/apps/account/organizations/OrganizationsList.js b/server/sonar-web/src/main/js/apps/account/organizations/OrganizationsList.js index afc2da9ffe0..67469b32a0f 100644 --- a/server/sonar-web/src/main/js/apps/account/organizations/OrganizationsList.js +++ b/server/sonar-web/src/main/js/apps/account/organizations/OrganizationsList.js @@ -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 => diff --git a/server/sonar-web/src/main/js/apps/account/organizations/UserOrganizations.js b/server/sonar-web/src/main/js/apps/account/organizations/UserOrganizations.js index e480e8a5517..a22a14408d7 100644 --- a/server/sonar-web/src/main/js/apps/account/organizations/UserOrganizations.js +++ b/server/sonar-web/src/main/js/apps/account/organizations/UserOrganizations.js @@ -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 }; diff --git a/server/sonar-web/src/main/js/apps/account/organizations/actions.js b/server/sonar-web/src/main/js/apps/account/organizations/actions.js index 345efe30660..da353d90380 100644 --- a/server/sonar-web/src/main/js/apps/account/organizations/actions.js +++ b/server/sonar-web/src/main/js/apps/account/organizations/actions.js @@ -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)); }); diff --git a/server/sonar-web/src/main/js/apps/account/profile/Profile.js b/server/sonar-web/src/main/js/apps/account/profile/Profile.js index f4216612dcb..368377bb35c 100644 --- a/server/sonar-web/src/main/js/apps/account/profile/Profile.js +++ b/server/sonar-web/src/main/js/apps/account/profile/Profile.js @@ -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 ( diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.js b/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.js index d68069722f3..cda4776cf7c 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.js @@ -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 }); } diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/CurrentsFilter.js b/server/sonar-web/src/main/js/apps/background-tasks/components/CurrentsFilter.js index 677d7bcc48f..dbc2767f132 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/CurrentsFilter.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/CurrentsFilter.js @@ -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); diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Footer.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Footer.js index ced62322f91..efb4829e85a 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Footer.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Footer.js @@ -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; } diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Header.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Header.js index e91b1b1188b..986924b6754 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Header.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Header.js @@ -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"> diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/ScannerContext.js b/server/sonar-web/src/main/js/apps/background-tasks/components/ScannerContext.js index a2432dad135..f5286bccfd8 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/ScannerContext.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/ScannerContext.js @@ -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(); }; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Search.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Search.js index 2ffdc3a2db6..39c75d43210 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Search.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Search.js @@ -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); diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Stacktrace.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Stacktrace.js index a89fe73ab6e..9f00597e2b7 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Stacktrace.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Stacktrace.js @@ -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(); }; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Stats.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Stats.js index 4c57544f5a5..0983059a320 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Stats.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Stats.js @@ -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(); diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/StatusFilter.js b/server/sonar-web/src/main/js/apps/background-tasks/components/StatusFilter.js index ac88dff66ae..602e9c7e3d3 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/StatusFilter.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/StatusFilter.js @@ -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') }, { diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskComponent.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskComponent.js index fdd7aeedc7a..839f2c7b0e2 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskComponent.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskComponent.js @@ -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) { diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDate.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDate.js index 0e5c2348f1f..117702bafd9 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDate.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDate.js @@ -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; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDay.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDay.js index bfb5ff53cd9..8307b341f36 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDay.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDay.js @@ -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 ( diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskExecutionTime.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskExecutionTime.js index 594be8d2208..ee2eedb43e5 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskExecutionTime.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskExecutionTime.js @@ -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)} diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskStatus.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskStatus.js index 5feb8665762..5a19455b17b 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskStatus.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskStatus.js @@ -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) { diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskType.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskType.js index a06c44a7793..da9f6c36f41 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskType.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskType.js @@ -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"> {'['} diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js index 622409ca796..8eb3e2c68bf 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js @@ -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; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TypesFilter.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TypesFilter.js index 5ca1ee54c67..44add2f8869 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/TypesFilter.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TypesFilter.js @@ -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, diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Workers.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Workers.js index b37622a54f7..cbcfb1d39f1 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Workers.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Workers.js @@ -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 diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/WorkersForm.js b/server/sonar-web/src/main/js/apps/background-tasks/components/WorkersForm.js index 2f66fe8ab3d..83464c862b3 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/WorkersForm.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/WorkersForm.js @@ -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"> diff --git a/server/sonar-web/src/main/js/apps/background-tasks/types.js b/server/sonar-web/src/main/js/apps/background-tasks/types.js index 48ad0c98f5c..e272937867f 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/types.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/types.js @@ -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 }; +*/ diff --git a/server/sonar-web/src/main/js/apps/background-tasks/utils.js b/server/sonar-web/src/main/js/apps/background-tasks/utils.js index 963fb60aea4..132223c04e0 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/utils.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/utils.js @@ -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 ''; } diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/CodingRulesAppContainer.js b/server/sonar-web/src/main/js/apps/coding-rules/components/CodingRulesAppContainer.js index 020977d998a..f9f316d9b1f 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/components/CodingRulesAppContainer.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/components/CodingRulesAppContainer.js @@ -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) { diff --git a/server/sonar-web/src/main/js/apps/coding-rules/init.js b/server/sonar-web/src/main/js/apps/coding-rules/init.js index d3f6fcd3587..a156574703d 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/init.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/init.js @@ -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 () => { diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/App.js b/server/sonar-web/src/main/js/apps/component-measures/components/App.js index f68593c3277..8bdd6bceea1 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/App.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/App.js @@ -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 diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/AppContainer.js b/server/sonar-web/src/main/js/apps/component-measures/components/AppContainer.js index 38672597858..f3d91451c47 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/AppContainer.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/AppContainer.js @@ -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())) ); diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/Breadcrumb.js b/server/sonar-web/src/main/js/apps/component-measures/components/Breadcrumb.js index 99882ca4a7a..4e8adbf33ee 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/Breadcrumb.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/Breadcrumb.js @@ -21,19 +21,19 @@ import React from 'react'; import Tooltip from '../../../components/controls/Tooltip'; import { collapsePath, limitComponentName } from '../../../helpers/path'; -import type { Component } from '../types'; +/*:: import type { Component } from '../types'; */ -type Props = { +/*:: type Props = { canBrowse: boolean, component: Component, isLast: boolean, handleSelect: string => void -}; +}; */ export default class Breadcrumb extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleClick = (e: Event & { target: HTMLElement }) => { + handleClick = (e /*: Event & { target: HTMLElement } */) => { e.preventDefault(); e.target.blur(); this.props.handleSelect(this.props.component.key); diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/Breadcrumbs.js b/server/sonar-web/src/main/js/apps/component-measures/components/Breadcrumbs.js index cf42bbd29a3..0a5920f55c9 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/Breadcrumbs.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/Breadcrumbs.js @@ -22,24 +22,24 @@ import React from 'react'; import key from 'keymaster'; import Breadcrumb from './Breadcrumb'; import { getBreadcrumbs } from '../../../api/components'; -import type { Component } from '../types'; +/*:: import type { Component } from '../types'; */ -type Props = {| +/*:: type Props = {| backToFirst: boolean, className?: string, component: Component, handleSelect: string => void, rootComponent: Component -|}; +|}; */ -type State = { +/*:: type State = { breadcrumbs: Array<Component> -}; +}; */ export default class Breadcrumbs extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { breadcrumbs: [] }; @@ -49,7 +49,7 @@ export default class Breadcrumbs extends React.PureComponent { this.attachShortcuts(); } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if (this.props.component !== nextProps.component) { this.fetchBreadcrumbs(nextProps); } @@ -75,7 +75,7 @@ export default class Breadcrumbs extends React.PureComponent { key.unbind('left', 'measures-files'); } - fetchBreadcrumbs = ({ component, rootComponent }: Props) => { + fetchBreadcrumbs = ({ component, rootComponent } /*: Props */) => { const isRoot = component.key === rootComponent.key; if (isRoot) { if (this.mounted) { diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/FilesCounter.js b/server/sonar-web/src/main/js/apps/component-measures/components/FilesCounter.js index 4dc60a071d1..fb35bc21e13 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/FilesCounter.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/FilesCounter.js @@ -22,13 +22,13 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; import { formatMeasure } from '../../../helpers/measures'; -type Props = { +/*:: type Props = { className?: string, current: ?number, total: number -}; +}; */ -export default function FilesCounter({ className, current, total }: Props) { +export default function FilesCounter({ className, current, total } /*: Props */) { return ( <span className={className}> <strong> diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/LeakPeriodLegend.js b/server/sonar-web/src/main/js/apps/component-measures/components/LeakPeriodLegend.js index dbf0ae7ffd0..ef72a1d213b 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/LeakPeriodLegend.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/LeakPeriodLegend.js @@ -24,15 +24,15 @@ import moment from 'moment'; import Tooltip from '../../../components/controls/Tooltip'; import { getPeriodLabel, getPeriodDate } from '../../../helpers/periods'; import { translate, translateWithParameters } from '../../../helpers/l10n'; -import type { Component, Period } from '../types'; +/*:: import type { Component, Period } from '../types'; */ -type Props = { +/*:: type Props = { className?: string, component: Component, period: Period -}; +}; */ -export default function LeakPeriodLegend({ className, component, period }: Props) { +export default function LeakPeriodLegend({ className, component, period } /*: Props */) { const leakClass = classNames('domain-measures-leak-header', className); if (component.qualifier === 'APP') { return ( diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContent.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContent.js index 3b5552955bb..52e14671cf2 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContent.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContent.js @@ -35,11 +35,14 @@ import { complementary } from '../config/complementary'; import { enhanceComponent, isFileType, isViewType } from '../utils'; import { getProjectUrl } from '../../../helpers/urls'; import { isDiffMetric } from '../../../helpers/measures'; -import type { Component, ComponentEnhanced, Paging, Period } from '../types'; -import type { MeasureEnhanced } from '../../../components/measure/types'; -import type { Metric } from '../../../store/metrics/actions'; +/*:: import type { Component, ComponentEnhanced, Paging, Period } from '../types'; */ +/*:: import type { MeasureEnhanced } from '../../../components/measure/types'; */ +/*:: import type { Metric } from '../../../store/metrics/actions'; */ -type Props = {| +// Switching to the following type will make flow crash with : +// https://github.com/facebook/flow/issues/3147 +// router: { push: ({ pathname: string, query?: RawQuery }) => void } +/*:: type Props = {| className?: string, component: Component, currentUser: { isLoggedIn: boolean }, @@ -49,32 +52,27 @@ type Props = {| metric: Metric, metrics: { [string]: Metric }, rootComponent: Component, - router: Object /* - Switching to the following type will make flow crash with : - https://github.com/facebook/flow/issues/3147 - { - push: ({ pathname: string, query?: RawQuery }) => void - }*/, + router: Object, secondaryMeasure: ?MeasureEnhanced, updateLoading: ({ [string]: boolean }) => void, updateSelected: string => void, updateView: string => void, view: string -|}; +|}; */ -type State = { +/*:: type State = { components: Array<ComponentEnhanced>, metric: ?Metric, paging?: Paging, selected: ?string, view: ?string -}; +}; */ export default class MeasureContent extends React.PureComponent { - container: HTMLElement; - mounted: boolean; - props: Props; - state: State = { + /*:: container: HTMLElement; */ + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { components: [], metric: null, paging: null, @@ -87,7 +85,7 @@ export default class MeasureContent extends React.PureComponent { this.fetchComponents(this.props); } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if (nextProps.component !== this.props.component || nextProps.metric !== this.props.metric) { this.fetchComponents(nextProps); } @@ -97,7 +95,7 @@ export default class MeasureContent extends React.PureComponent { this.mounted = false; } - getSelectedIndex = (): ?number => { + getSelectedIndex = () => { const componentKey = isFileType(this.props.component) ? this.props.component.key : this.state.selected; @@ -105,10 +103,14 @@ export default class MeasureContent extends React.PureComponent { return index !== -1 ? index : null; }; - getComponentRequestParams = (view: string, metric: Metric, options: Object = {}) => { + getComponentRequestParams = ( + view /*: string */, + metric /*: Metric */, + options /*: Object */ = {} + ) => { const strategy = view === 'list' ? 'leaves' : 'children'; const metricKeys = [metric.key]; - const opts: Object = { metricSortFilter: 'withMeasuresOnly' }; + const opts /*: Object */ = { metricSortFilter: 'withMeasuresOnly' }; if (view === 'treemap') { metricKeys.push('ncloc'); opts.asc = false; @@ -129,7 +131,7 @@ export default class MeasureContent extends React.PureComponent { return { metricKeys, opts: { ...opts, ...options }, strategy }; }; - fetchComponents = ({ component, metric, metrics, view }: Props) => { + fetchComponents = ({ component, metric, metrics, view } /*: Props */) => { if (isFileType(component)) { return this.setState({ metric: null, view: null }); } @@ -140,7 +142,7 @@ export default class MeasureContent extends React.PureComponent { r => { if (metric === this.props.metric) { if (this.mounted) { - this.setState(({ selected }: State) => ({ + this.setState(({ selected } /*: State */) => ({ components: r.components.map(component => enhanceComponent(component, metric, metrics) ), @@ -191,7 +193,7 @@ export default class MeasureContent extends React.PureComponent { ); }; - onOpenComponent = (componentKey: string) => { + onOpenComponent = (componentKey /*: string */) => { if (isViewType(this.props.rootComponent)) { const component = this.state.components.find( component => component.refKey === componentKey || component.key === componentKey @@ -210,7 +212,7 @@ export default class MeasureContent extends React.PureComponent { } }; - onSelectComponent = (componentKey: string) => this.setState({ selected: componentKey }); + onSelectComponent = (componentKey /*: string */) => this.setState({ selected: componentKey }); renderContent() { const { component, leakPeriod } = this.props; diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContentContainer.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContentContainer.js index a8999c53cac..5c4fbdea60e 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContentContainer.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContentContainer.js @@ -20,12 +20,12 @@ // @flow import React from 'react'; import MeasureContent from './MeasureContent'; -import type { Component, Period, Query } from '../types'; -import type { MeasureEnhanced } from '../../../components/measure/types'; -import type { Metric } from '../../../store/metrics/actions'; -import type { RawQuery } from '../../../helpers/query'; +/*:: import type { Component, Period, Query } from '../types'; */ +/*:: import type { MeasureEnhanced } from '../../../components/measure/types'; */ +/*:: import type { Metric } from '../../../store/metrics/actions'; */ +/*:: import type { RawQuery } from '../../../helpers/query'; */ -type Props = {| +/*:: type Props = {| className?: string, currentUser: { isLoggedIn: boolean }, rootComponent: Component, @@ -42,9 +42,9 @@ type Props = {| selected: ?string, updateQuery: Query => void, view: string -|}; +|}; */ -type State = { +/*:: type State = { component: ?Component, loading: { measure: boolean, @@ -52,12 +52,12 @@ type State = { }, measure: ?MeasureEnhanced, secondaryMeasure: ?MeasureEnhanced -}; +}; */ export default class MeasureContentContainer extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { component: null, loading: { measure: false, @@ -72,7 +72,7 @@ export default class MeasureContentContainer extends React.PureComponent { this.fetchMeasure(this.props); } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { const { component } = this.state; const componentChanged = !component || @@ -87,7 +87,7 @@ export default class MeasureContentContainer extends React.PureComponent { this.mounted = false; } - fetchMeasure = ({ rootComponent, fetchMeasures, metric, selected }: Props) => { + fetchMeasure = ({ rootComponent, fetchMeasures, metric, selected } /*: Props */) => { this.updateLoading({ measure: true }); const metricKeys = [metric.key]; @@ -112,18 +112,18 @@ export default class MeasureContentContainer extends React.PureComponent { ); }; - updateLoading = (loading: { [string]: boolean }) => { + updateLoading = (loading /*: { [string]: boolean } */) => { if (this.mounted) { this.setState(state => ({ loading: { ...state.loading, ...loading } })); } }; - updateSelected = (component: string) => + updateSelected = (component /*: string */) => this.props.updateQuery({ selected: component !== this.props.rootComponent.key ? component : null }); - updateView = (view: string) => this.props.updateQuery({ view }); + updateView = (view /*: string */) => this.props.updateQuery({ view }); render() { if (!this.state.component) { diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureFavoriteContainer.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureFavoriteContainer.js index 62b3c228641..7f896d636cd 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureFavoriteContainer.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureFavoriteContainer.js @@ -24,20 +24,20 @@ import FavoriteContainer from '../../../components/controls/FavoriteContainer'; import { getComponentForSourceViewer } from '../../../api/components'; import { receiveFavorites } from '../../../store/favorites/duck'; -type FavComponent = { key: string, canMarkAsFavorite: boolean, fav: boolean }; +/*:: type FavComponent = { key: string, canMarkAsFavorite: boolean, fav: boolean }; */ -type Props = { +/*:: type Props = { className?: string, component: string, onReceiveComponent: (component: FavComponent) => void -}; +}; */ -type State = { component: ?FavComponent }; +/*:: type State = { component: ?FavComponent }; */ class MeasureFavoriteContainer extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { component: null }; @@ -46,7 +46,7 @@ class MeasureFavoriteContainer extends React.PureComponent { this.fetchComponentFavorite(this.props); } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if (nextProps.component !== this.props.component) { this.fetchComponentFavorite(nextProps); } @@ -56,7 +56,7 @@ class MeasureFavoriteContainer extends React.PureComponent { this.mounted = false; } - fetchComponentFavorite({ component, onReceiveComponent }: Props) { + fetchComponentFavorite({ component, onReceiveComponent } /*: Props */) { getComponentForSourceViewer(component).then(component => { this.setState({ component }); onReceiveComponent(component); @@ -77,7 +77,7 @@ class MeasureFavoriteContainer extends React.PureComponent { const mapStateToProps = null; const mapDispatchToProps = { - onReceiveComponent: (component: FavComponent) => dispatch => { + onReceiveComponent: (component /*: FavComponent */) => dispatch => { if (component.canMarkAsFavorite) { const favorites = []; const notFavorites = []; diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureHeader.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureHeader.js index d3b4d6af7d1..558495e853b 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureHeader.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureHeader.js @@ -31,10 +31,10 @@ import { isFileType } from '../utils'; import { getLocalizedMetricName, translate, translateWithParameters } from '../../../helpers/l10n'; import { getComponentMeasureHistory } from '../../../helpers/urls'; import { isDiffMetric } from '../../../helpers/measures'; -import type { Component, Period } from '../types'; -import type { MeasureEnhanced } from '../../../components/measure/types'; +/*:: import type { Component, Period } from '../types'; */ +/*:: import type { MeasureEnhanced } from '../../../components/measure/types'; */ -type Props = {| +/*:: type Props = {| component: Component, components: Array<Component>, leakPeriod?: Period, @@ -42,12 +42,12 @@ type Props = {| measure: MeasureEnhanced, secondaryMeasure: ?MeasureEnhanced, selectedIdx: ?number -|}; +|}; */ export default class MeasureHeader extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleSelectPrevious = (e: Event & { target: HTMLElement }) => { + handleSelectPrevious = (e /*: Event & { target: HTMLElement } */) => { e.target.blur(); if (this.props.selectedIdx != null) { const prevComponent = this.props.components[this.props.selectedIdx - 1]; @@ -57,7 +57,7 @@ export default class MeasureHeader extends React.PureComponent { } }; - handleSelectNext = (e: Event & { target: HTMLElement }) => { + handleSelectNext = (e /*: Event & { target: HTMLElement } */) => { e.target.blur(); if (this.props.selectedIdx != null) { const prevComponent = this.props.components[this.props.selectedIdx + 1]; diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverview.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverview.js index 59ade74dd24..8ce27606f07 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverview.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverview.js @@ -27,10 +27,10 @@ import PageActions from './PageActions'; import SourceViewer from '../../../components/SourceViewer/SourceViewer'; import { getComponentLeaves } from '../../../api/components'; import { enhanceComponent, getBubbleMetrics, isFileType } from '../utils'; -import type { Component, ComponentEnhanced, Paging, Period } from '../types'; -import type { Metric } from '../../../store/metrics/actions'; +/*:: import type { Component, ComponentEnhanced, Paging, Period } from '../types'; */ +/*:: import type { Metric } from '../../../store/metrics/actions'; */ -type Props = {| +/*:: type Props = {| className?: string, component: Component, currentUser: { isLoggedIn: boolean }, @@ -41,19 +41,19 @@ type Props = {| rootComponent: Component, updateLoading: ({ [string]: boolean }) => void, updateSelected: string => void -|}; +|}; */ -type State = { +/*:: type State = { components: Array<ComponentEnhanced>, paging?: Paging -}; +}; */ const BUBBLES_LIMIT = 500; export default class MeasureOverview extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { components: [], paging: null }; @@ -63,7 +63,7 @@ export default class MeasureOverview extends React.PureComponent { this.fetchComponents(this.props); } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if ( nextProps.component !== this.props.component || nextProps.metrics !== this.props.metrics || @@ -77,7 +77,7 @@ export default class MeasureOverview extends React.PureComponent { this.mounted = false; } - fetchComponents = (props: Props) => { + fetchComponents = (props /*: Props */) => { const { component, domain, metrics } = props; if (isFileType(component)) { return this.setState({ components: [], paging: null }); diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverviewContainer.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverviewContainer.js index 0cfcd966fbb..345ccc78dc3 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverviewContainer.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverviewContainer.js @@ -23,11 +23,11 @@ import MeasureOverview from './MeasureOverview'; import { getComponentShow } from '../../../api/components'; import { getProjectUrl } from '../../../helpers/urls'; import { isViewType } from '../utils'; -import type { Component, Period, Query } from '../types'; -import type { RawQuery } from '../../../helpers/query'; -import type { Metric } from '../../../store/metrics/actions'; +/*:: import type { Component, Period, Query } from '../types'; */ +/*:: import type { RawQuery } from '../../../helpers/query'; */ +/*:: import type { Metric } from '../../../store/metrics/actions'; */ -type Props = {| +/*:: type Props = {| className?: string, rootComponent: Component, currentUser: { isLoggedIn: boolean }, @@ -39,20 +39,20 @@ type Props = {| }, selected: ?string, updateQuery: Query => void -|}; +|}; */ -type State = { +/*:: type State = { component: ?Component, loading: { component: boolean, bubbles: boolean } -}; +}; */ export default class MeasureOverviewContainer extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { component: null, loading: { component: false, @@ -65,7 +65,7 @@ export default class MeasureOverviewContainer extends React.PureComponent { this.fetchComponent(this.props); } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { const { component } = this.state; const componentChanged = !component || @@ -80,7 +80,7 @@ export default class MeasureOverviewContainer extends React.PureComponent { this.mounted = false; } - fetchComponent = ({ rootComponent, selected }: Props) => { + fetchComponent = ({ rootComponent, selected } /*: Props */) => { if (!selected || rootComponent.key === selected) { this.setState({ component: rootComponent }); this.updateLoading({ component: false }); @@ -98,13 +98,13 @@ export default class MeasureOverviewContainer extends React.PureComponent { ); }; - updateLoading = (loading: { [string]: boolean }) => { + updateLoading = (loading /*: { [string]: boolean } */) => { if (this.mounted) { this.setState(state => ({ loading: { ...state.loading, ...loading } })); } }; - updateSelected = (component: string) => { + updateSelected = (component /*: string */) => { if (this.state.component && isViewType(this.state.component)) { this.props.router.push(getProjectUrl(component)); } else { diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureViewSelect.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureViewSelect.js index e17f12a8589..8736d86e44f 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureViewSelect.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureViewSelect.js @@ -25,17 +25,17 @@ import TreeIcon from '../../../components/icons-components/TreeIcon'; import TreemapIcon from '../../../components/icons-components/TreemapIcon'; import { hasList, hasTree, hasTreemap } from '../utils'; import { translate } from '../../../helpers/l10n'; -import type { Metric } from '../../../store/metrics/actions'; +/*:: import type { Metric } from '../../../store/metrics/actions'; */ -type Props = { +/*:: type Props = { className?: string, metric: Metric, handleViewChange: (view: string) => void, view: string -}; +}; */ export default class MeasureViewSelect extends React.PureComponent { - props: Props; + /*:: props: Props; */ getOptions = () => { const { metric } = this.props; @@ -79,9 +79,9 @@ export default class MeasureViewSelect extends React.PureComponent { return options; }; - handleChange = (option: { value: string }) => this.props.handleViewChange(option.value); + handleChange = (option /*: { value: string } */) => this.props.handleViewChange(option.value); - renderValue = (value: { icon: Element<*> }) => value.icon; + renderValue = (value /*: { icon: Element<*> } */) => value.icon; render() { return ( diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MetricNotFound.js b/server/sonar-web/src/main/js/apps/component-measures/components/MetricNotFound.js index 2dff010b0a0..9b2cb8ee27c 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MetricNotFound.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MetricNotFound.js @@ -21,7 +21,7 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -export default function MetricNotFound({ className }: { className?: string }) { +export default function MetricNotFound({ className } /*: { className?: string } */) { return ( <div className={className}> <div className="alert alert-danger"> diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/PageActions.js b/server/sonar-web/src/main/js/apps/component-measures/components/PageActions.js index eb1f1bf1038..1d5d4abcef3 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/PageActions.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/PageActions.js @@ -22,17 +22,17 @@ import React from 'react'; import DeferredSpinner from '../../../components/common/DeferredSpinner'; import FilesCounter from './FilesCounter'; import { translate } from '../../../helpers/l10n'; -import type { Paging } from '../types'; +/*:: import type { Paging } from '../types'; */ -type Props = {| +/*:: type Props = {| current: ?number, loading: boolean, isFile: ?boolean, paging: ?Paging, view?: string -|}; +|}; */ -export default function PageActions(props: Props) { +export default function PageActions(props /*: Props */) { const { isFile, paging } = props; const showShortcuts = ['list', 'tree'].includes(props.view); return ( diff --git a/server/sonar-web/src/main/js/apps/component-measures/drilldown/BubbleChart.js b/server/sonar-web/src/main/js/apps/component-measures/drilldown/BubbleChart.js index 35bef4f20d4..99b8d0b5947 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/drilldown/BubbleChart.js +++ b/server/sonar-web/src/main/js/apps/component-measures/drilldown/BubbleChart.js @@ -31,23 +31,23 @@ import { } from '../../../helpers/l10n'; import { getBubbleMetrics, isProjectOverview } from '../utils'; import { RATING_COLORS } from '../../../helpers/constants'; -import type { Component, ComponentEnhanced } from '../types'; -import type { Metric } from '../../../store/metrics/actions'; +/*:: import type { Component, ComponentEnhanced } from '../types'; */ +/*:: import type { Metric } from '../../../store/metrics/actions'; */ const HEIGHT = 500; -type Props = {| +/*:: type Props = {| component: Component, components: Array<ComponentEnhanced>, domain: string, metrics: { [string]: Metric }, updateSelected: string => void -|}; +|}; */ export default class BubbleChart extends React.PureComponent { - props: Props; + /*:: props: Props; */ - getMeasureVal = (component: ComponentEnhanced, metric: Metric) => { + getMeasureVal = (component /*: ComponentEnhanced */, metric /*: Metric */) => { const measure = component.measures.find(measure => measure.metric.key === metric.key); if (measure) { return Number(isDiffMetric(metric.key) ? measure.leak : measure.value); @@ -55,15 +55,15 @@ export default class BubbleChart extends React.PureComponent { }; getTooltip( - componentName: string, - x: number, - y: number, - size: number, - colors: ?Array<?number>, - xMetric: Metric, - yMetric: Metric, - sizeMetric: Metric, - colorsMetric: ?Array<Metric> + componentName /*: string */, + x /*: number */, + y /*: number */, + size /*: number */, + colors /*: ?Array<?number> */, + xMetric /*: Metric */, + yMetric /*: Metric */, + sizeMetric /*: Metric */, + colorsMetric /*: ?Array<Metric> */ ) { const inner = [ componentName, @@ -83,14 +83,14 @@ export default class BubbleChart extends React.PureComponent { return `<div class="text-left">${inner.join('<br/>')}</div>`; } - handleBubbleClick = (component: ComponentEnhanced) => + handleBubbleClick = (component /*: ComponentEnhanced */) => this.props.updateSelected(component.refKey || component.key); renderBubbleChart( - xMetric: Metric, - yMetric: Metric, - sizeMetric: Metric, - colorsMetric: ?Array<Metric> + xMetric /*: Metric */, + yMetric /*: Metric */, + sizeMetric /*: Metric */, + colorsMetric /*: ?Array<Metric> */ ) { const items = this.props.components .map(component => { @@ -139,7 +139,11 @@ export default class BubbleChart extends React.PureComponent { ); } - renderChartHeader(domain: string, sizeMetric: Metric, colorsMetric: ?Array<Metric>) { + renderChartHeader( + domain /*: string */, + sizeMetric /*: Metric */, + colorsMetric /*: ?Array<Metric> */ + ) { const title = isProjectOverview(domain) ? translate('component_measures.overview', domain, 'title') : translateWithParameters( @@ -176,7 +180,7 @@ export default class BubbleChart extends React.PureComponent { ); } - renderChartFooter(domain: string) { + renderChartFooter(domain /*: string */) { const description = `component_measures.overview.${domain}.description`; const translatedDescription = translate(description); if (description === translatedDescription) { diff --git a/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentCell.js b/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentCell.js index d894e4419cd..d38768555a9 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentCell.js +++ b/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentCell.js @@ -22,17 +22,17 @@ import React from 'react'; import QualifierIcon from '../../../components/icons-components/QualifierIcon'; import { splitPath } from '../../../helpers/path'; import { getComponentUrl } from '../../../helpers/urls'; -import type { ComponentEnhanced } from '../types'; +/*:: import type { ComponentEnhanced } from '../types'; */ -type Props = { +/*:: type Props = { component: ComponentEnhanced, onClick: string => void -}; +}; */ export default class ComponentCell extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleClick = (e: MouseEvent) => { + handleClick = (e /*: MouseEvent */) => { const isLeftClickEvent = e.button === 0; const isModifiedEvent = !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey); diff --git a/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsList.js b/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsList.js index b075104a424..2d28cb63de7 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsList.js +++ b/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsList.js @@ -23,24 +23,20 @@ import ComponentsListRow from './ComponentsListRow'; import EmptyResult from './EmptyResult'; import { complementary } from '../config/complementary'; import { getLocalizedMetricName } from '../../../helpers/l10n'; -import type { ComponentEnhanced } from '../types'; -import type { Metric } from '../../../store/metrics/actions'; +/*:: import type { ComponentEnhanced } from '../types'; */ +/*:: import type { Metric } from '../../../store/metrics/actions'; */ -type Props = {| +/*:: type Props = {| components: Array<ComponentEnhanced>, onClick: string => void, metric: Metric, metrics: { [string]: Metric }, selectedComponent?: ?string -|}; +|}; */ -export default function ComponentsList({ - components, - onClick, - metrics, - metric, - selectedComponent -}: Props) { +export default function ComponentsList( + { components, onClick, metrics, metric, selectedComponent } /*: Props */ +) { if (!components.length) { return <EmptyResult />; } diff --git a/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsListRow.js b/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsListRow.js index 46c6839ca19..bc38573e3ad 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsListRow.js +++ b/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsListRow.js @@ -22,18 +22,18 @@ import React from 'react'; import classNames from 'classnames'; import ComponentCell from './ComponentCell'; import MeasureCell from './MeasureCell'; -import type { ComponentEnhanced } from '../types'; -import type { Metric } from '../../../store/metrics/actions'; +/*:: import type { ComponentEnhanced } from '../types'; */ +/*:: import type { Metric } from '../../../store/metrics/actions'; */ -type Props = {| +/*:: type Props = {| component: ComponentEnhanced, isSelected: boolean, onClick: string => void, otherMetrics: Array<Metric>, metric: Metric -|}; +|}; */ -export default function ComponentsListRow(props: Props) { +export default function ComponentsListRow(props /*: Props */) { const { component } = props; const otherMeasures = props.otherMetrics.map(metric => { const measure = component.measures.find(measure => measure.metric.key === metric.key); diff --git a/server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.js b/server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.js index 5c95697b671..b1f8aebad51 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.js +++ b/server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.js @@ -24,10 +24,10 @@ import { throttle } from 'lodash'; import ComponentsList from './ComponentsList'; import ListFooter from '../../../components/controls/ListFooter'; import { scrollToElement } from '../../../helpers/scrolling'; -import type { ComponentEnhanced, Paging } from '../types'; -import type { Metric } from '../../../store/metrics/actions'; +/*:: import type { ComponentEnhanced, Paging } from '../types'; */ +/*:: import type { Metric } from '../../../store/metrics/actions'; */ -type Props = {| +/*:: type Props = {| components: Array<ComponentEnhanced>, fetchMore: () => void, handleSelect: string => void, @@ -37,13 +37,13 @@ type Props = {| paging: ?Paging, selectedKey: ?string, selectedIdx: ?number -|}; +|}; */ export default class ListView extends React.PureComponent { - listContainer: HTMLElement; - props: Props; + /*:: listContainer: HTMLElement; */ + /*:: props: Props; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.selectNext = throttle(this.selectNext, 100); this.selectPrevious = throttle(this.selectPrevious, 100); @@ -53,7 +53,7 @@ export default class ListView extends React.PureComponent { this.attachShortcuts(); } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if ( this.listContainer && this.props.selectedKey != null && diff --git a/server/sonar-web/src/main/js/apps/component-measures/drilldown/MeasureCell.js b/server/sonar-web/src/main/js/apps/component-measures/drilldown/MeasureCell.js index 4d05b885f25..e920c2a41e2 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/drilldown/MeasureCell.js +++ b/server/sonar-web/src/main/js/apps/component-measures/drilldown/MeasureCell.js @@ -20,15 +20,15 @@ // @flow import React from 'react'; import Measure from '../../../components/measure/Measure'; -import type { Component } from '../types'; -import type { Metric } from '../../../store/metrics/actions'; +/*:: import type { Component } from '../types'; */ +/*:: import type { Metric } from '../../../store/metrics/actions'; */ -type Props = { +/*:: type Props = { component: Component, metric: Metric -}; +}; */ -export default function MeasureCell({ component, metric }: Props) { +export default function MeasureCell({ component, metric } /*: Props */) { return ( <td className="thin nowrap text-right"> <span id={'component-measures-component-measure-' + component.key + '-' + metric.key}> diff --git a/server/sonar-web/src/main/js/apps/component-measures/drilldown/TreeMapView.js b/server/sonar-web/src/main/js/apps/component-measures/drilldown/TreeMapView.js index 30fcc2f0dc7..d6b2542f09b 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/drilldown/TreeMapView.js +++ b/server/sonar-web/src/main/js/apps/component-measures/drilldown/TreeMapView.js @@ -29,40 +29,40 @@ import TreeMap from '../../../components/charts/TreeMap'; import { translate, translateWithParameters, getLocalizedMetricName } from '../../../helpers/l10n'; import { formatMeasure, isDiffMetric } from '../../../helpers/measures'; import { getComponentUrl } from '../../../helpers/urls'; -import type { Metric } from '../../../store/metrics/actions'; -import type { ComponentEnhanced } from '../types'; -import type { TreeMapItem } from '../../../components/charts/TreeMap'; +/*:: import type { Metric } from '../../../store/metrics/actions'; */ +/*:: import type { ComponentEnhanced } from '../types'; */ +/*:: import type { TreeMapItem } from '../../../components/charts/TreeMap'; */ -type Props = {| +/*:: type Props = {| components: Array<ComponentEnhanced>, handleSelect: string => void, metric: Metric -|}; +|}; */ -type State = { +/*:: type State = { treemapItems: Array<TreeMapItem> -}; +}; */ const HEIGHT = 500; const COLORS = ['#00aa00', '#b0d513', '#eabe06', '#ed7d20', '#d4333f']; const LEVEL_COLORS = ['#d4333f', '#ed7d20', '#00aa00', '#b4b4b4']; export default class TreeMapView extends React.PureComponent { - props: Props; - state: State; + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { treemapItems: this.getTreemapComponents(props) }; } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if (nextProps.components !== this.props.components || nextProps.metric !== this.props.metric) { this.setState({ treemapItems: this.getTreemapComponents(nextProps) }); } } - getTreemapComponents = ({ components, metric }: Props): Array<TreeMapItem> => { + getTreemapComponents = ({ components, metric } /*: Props */) => { const colorScale = this.getColorScale(metric); return components .map(component => { @@ -102,7 +102,7 @@ export default class TreeMapView extends React.PureComponent { getLevelColorScale = () => scaleOrdinal().domain(['ERROR', 'WARN', 'OK', 'NONE']).range(LEVEL_COLORS); - getPercentColorScale = (metric: Metric) => { + getPercentColorScale = (metric /*: Metric */) => { const color = scaleLinear().domain([0, 25, 50, 75, 100]); color.range(metric.direction === 1 ? COLORS.reverse() : COLORS); return color; @@ -110,7 +110,7 @@ export default class TreeMapView extends React.PureComponent { getRatingColorScale = () => scaleLinear().domain([1, 2, 3, 4, 5]).range(COLORS); - getColorScale = (metric: Metric) => { + getColorScale = (metric /*: Metric */) => { if (metric.type === 'LEVEL') { return this.getLevelColorScale(); } @@ -121,11 +121,11 @@ export default class TreeMapView extends React.PureComponent { }; getTooltip = ( - componentName: string, - colorMetric: Metric, - sizeMetric: Metric, - colorValue: ?number, - sizeValue: number + componentName /*: string */, + colorMetric /*: Metric */, + sizeMetric /*: Metric */, + colorValue /*: ?number */, + sizeValue /*: number */ ) => { const formatted = colorMetric != null && colorValue != null ? formatMeasure(colorValue, colorMetric.type) : '—'; diff --git a/server/sonar-web/src/main/js/apps/component-measures/sidebar/DomainFacet.js b/server/sonar-web/src/main/js/apps/component-measures/sidebar/DomainFacet.js index 7bdea166fd9..ac8949d88f6 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/sidebar/DomainFacet.js +++ b/server/sonar-web/src/main/js/apps/component-measures/sidebar/DomainFacet.js @@ -34,25 +34,25 @@ import { translate, translateWithParameters } from '../../../helpers/l10n'; -import type { MeasureEnhanced } from '../../../components/measure/types'; +/*:: import type { MeasureEnhanced } from '../../../components/measure/types'; */ -type Props = {| +/*:: type Props = {| onChange: (metric: string) => void, onToggle: (property: string) => void, open: boolean, domain: { name: string, measures: Array<MeasureEnhanced> }, selected: string -|}; +|}; */ export default class DomainFacet extends React.PureComponent { - props: Props; + /*:: props: Props; */ handleHeaderClick = () => this.props.onToggle(this.props.domain.name); hasFacetSelected = ( - domain: { name: string }, - measures: Array<MeasureEnhanced>, - selected: string + domain /*: { name: string } */, + measures /*: Array<MeasureEnhanced> */, + selected /*: string */ ) => { const measureSelected = measures.find(measure => measure.metric.key === selected); const overviewSelected = domain.name === selected && hasBubbleChart(domain.name); diff --git a/server/sonar-web/src/main/js/apps/component-measures/sidebar/FacetMeasureValue.js b/server/sonar-web/src/main/js/apps/component-measures/sidebar/FacetMeasureValue.js index eae569c72e0..ee8f52f6097 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/sidebar/FacetMeasureValue.js +++ b/server/sonar-web/src/main/js/apps/component-measures/sidebar/FacetMeasureValue.js @@ -21,9 +21,9 @@ import React from 'react'; import Measure from '../../../components/measure/Measure'; import { isDiffMetric } from '../../../helpers/measures'; -import type { MeasureEnhanced } from '../../../components/measure/types'; +/*:: import type { MeasureEnhanced } from '../../../components/measure/types'; */ -export default function FacetMeasureValue({ measure }: { measure: MeasureEnhanced }) { +export default function FacetMeasureValue({ measure } /*: { measure: MeasureEnhanced } */) { if (isDiffMetric(measure.metric.key)) { return ( <div diff --git a/server/sonar-web/src/main/js/apps/component-measures/sidebar/ProjectOverviewFacet.js b/server/sonar-web/src/main/js/apps/component-measures/sidebar/ProjectOverviewFacet.js index 6f921576e23..ded7b731082 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/sidebar/ProjectOverviewFacet.js +++ b/server/sonar-web/src/main/js/apps/component-measures/sidebar/ProjectOverviewFacet.js @@ -25,13 +25,13 @@ import FacetItemsList from '../../../components/facet/FacetItemsList'; import Tooltip from '../../../components/controls/Tooltip'; import { translate } from '../../../helpers/l10n'; -type Props = {| +/*:: type Props = {| onChange: (metric: string) => void, selected: string, value: string -|}; +|}; */ -export default function ProjectOverviewFacet({ value, selected, onChange }: Props) { +export default function ProjectOverviewFacet({ value, selected, onChange } /*: Props */) { const facetName = translate('component_measures.overview', value, 'facet'); return ( <FacetBox> diff --git a/server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.js b/server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.js index 465439125af..8163d5638bd 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.js +++ b/server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.js @@ -22,35 +22,38 @@ import React from 'react'; import ProjectOverviewFacet from './ProjectOverviewFacet'; import DomainFacet from './DomainFacet'; import { getDefaultView, groupByDomains, KNOWN_DOMAINS, PROJECT_OVERVEW } from '../utils'; -import type { MeasureEnhanced } from '../../../components/measure/types'; -import type { Query } from '../types'; +/*:: import type { MeasureEnhanced } from '../../../components/measure/types'; */ +/*:: import type { Query } from '../types'; */ -type Props = {| +/*:: type Props = {| measures: Array<MeasureEnhanced>, selectedMetric: string, updateQuery: Query => void -|}; +|}; */ -type State = {| +/*:: type State = {| openFacets: { [string]: boolean } -|}; +|}; */ export default class Sidebar extends React.PureComponent { - props: Props; - state: State; + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { openFacets: this.getOpenFacets({}, props) }; } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if (nextProps.selectedMetric !== this.props.selectedMetric) { this.setState(state => this.getOpenFacets(state.openFacets, nextProps)); } } - getOpenFacets = (openFacets: { [string]: boolean }, { measures, selectedMetric }: Props) => { + getOpenFacets = ( + openFacets /*: { [string]: boolean } */, + { measures, selectedMetric } /*: Props */ + ) => { const newOpenFacets = { ...openFacets }; const measure = measures.find(measure => measure.metric.key === selectedMetric); if (measure && measure.metric && measure.metric.domain) { @@ -61,15 +64,15 @@ export default class Sidebar extends React.PureComponent { return newOpenFacets; }; - toggleFacet = (name: string) => { - this.setState(({ openFacets }: State) => ({ + toggleFacet = (name /*: string */) => { + this.setState(({ openFacets } /*: State */) => ({ openFacets: { ...openFacets, [name]: !openFacets[name] } })); }; - resetSelection = (metric: string) => ({ selected: null, view: getDefaultView(metric) }); + resetSelection = (metric /*: string */) => ({ selected: null, view: getDefaultView(metric) }); - changeMetric = (metric: string) => + changeMetric = (metric /*: string */) => this.props.updateQuery({ metric, ...this.resetSelection(metric) }); render() { diff --git a/server/sonar-web/src/main/js/apps/component-measures/types.js b/server/sonar-web/src/main/js/apps/component-measures/types.js index 340baf37de1..04052b1c0d0 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/types.js +++ b/server/sonar-web/src/main/js/apps/component-measures/types.js @@ -17,9 +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. */ -import type { Measure, MeasureEnhanced } from '../../components/measure/types'; +/*:: import type { Measure, MeasureEnhanced } from '../../components/measure/types'; */ -type ComponentIntern = { +/*:: type ComponentIntern = { isFavorite?: boolean, isRecentlyBrowsed?: boolean, key: string, @@ -28,31 +28,31 @@ type ComponentIntern = { organization?: string, project?: string, qualifier: string -}; +}; */ -export type Component = ComponentIntern & { measures?: Array<Measure> }; +/*:: export type Component = ComponentIntern & { measures?: Array<Measure> }; */ -export type ComponentEnhanced = ComponentIntern & { +/*:: export type ComponentEnhanced = ComponentIntern & { value?: ?string, leak?: ?string, measures: Array<MeasureEnhanced> -}; +}; */ -export type Paging = { +/*:: export type Paging = { pageIndex: number, pageSize: number, total: number -}; +}; */ -export type Period = { +/*:: export type Period = { index: number, date: string, mode: string, parameter?: string -}; +}; */ -export type Query = { +/*:: export type Query = { metric: ?string, selected: ?string, view: string -}; +}; */ diff --git a/server/sonar-web/src/main/js/apps/component-measures/utils.js b/server/sonar-web/src/main/js/apps/component-measures/utils.js index 0ae0a1dfa15..80c89c75718 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/utils.js +++ b/server/sonar-web/src/main/js/apps/component-measures/utils.js @@ -24,10 +24,10 @@ import { cleanQuery, parseAsString, serializeString } from '../../helpers/query' import { domains } from './config/domains'; import { bubbles } from './config/bubbles'; import { enhanceMeasure } from '../../components/measure/utils'; -import type { Component, ComponentEnhanced, Query } 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, ComponentEnhanced, Query } from './types'; */ +/*:: import type { RawQuery } from '../../helpers/query'; */ +/*:: import type { Metric } from '../../store/metrics/actions'; */ +/*:: import type { MeasureEnhanced } from '../../components/measure/types'; */ export const PROJECT_OVERVEW = 'project_overview'; export const DEFAULT_VIEW = 'list'; @@ -55,14 +55,16 @@ const BANNED_MEASURES = [ 'new_info_violations' ]; -export function filterMeasures(measures: Array<MeasureEnhanced>): Array<MeasureEnhanced> { +export function filterMeasures( + measures /*: Array<MeasureEnhanced> */ +) /*: Array<MeasureEnhanced> */ { return measures.filter(measure => !BANNED_MEASURES.includes(measure.metric.key)); } export function sortMeasures( - domainName: string, - measures: Array<MeasureEnhanced> -): Array<MeasureEnhanced> { + domainName /*: string */, + measures /*: Array<MeasureEnhanced> */ +) /*: Array<MeasureEnhanced> */ { const config = domains[domainName] || {}; const configOrder = config.order || []; return sortBy(measures, [ @@ -74,29 +76,28 @@ export function sortMeasures( ]); } -export const enhanceComponent = ( - component: Component, - metric: ?Metric, - metrics: { [string]: Metric } -): ComponentEnhanced => { +export function enhanceComponent( + component /*: Component */, + metric /*: ?Metric */, + metrics /*: { [string]: Metric } */ +) /*: ComponentEnhanced */ { const enhancedMeasures = component.measures.map(measure => enhanceMeasure(measure, metrics)); // $FlowFixMe metric can't be null since there is a guard for it const measure = metric && enhancedMeasures.find(measure => measure.metric.key === metric.key); const value = measure ? measure.value : null; const leak = measure ? measure.leak : null; return { ...component, value, leak, measures: enhancedMeasures }; -}; +} -export const isFileType = (component: Component): boolean => - ['FIL', 'UTS'].includes(component.qualifier); +export function isFileType(component /*: Component */) /*: boolean */ { + return ['FIL', 'UTS'].includes(component.qualifier); +} -export const isViewType = (component: Component): boolean => - ['VW', 'SVW', 'APP'].includes(component.qualifier); +export function isViewType(component /*: Component */) /*: boolean */ { + return ['VW', 'SVW', 'APP'].includes(component.qualifier); +} -export const groupByDomains = memoize((measures: Array<MeasureEnhanced>): Array<{ - name: string, - measures: Array<MeasureEnhanced> -}> => { +export const groupByDomains = memoize((measures /*: Array<MeasureEnhanced> */) => { const domains = toPairs(groupBy(measures, measure => measure.metric.domain)).map(r => { const [name, measures] = r; const sortedMeasures = sortBy(measures, measure => getLocalizedMetricName(measure.metric)); @@ -112,26 +113,34 @@ export const groupByDomains = memoize((measures: Array<MeasureEnhanced>): Array< ]); }); -export const getDefaultView = (metric: string): string => { +export function getDefaultView(metric /*: string */) /*: string */ { if (!hasList(metric)) { return 'tree'; } return DEFAULT_VIEW; -}; +} -export const hasList = (metric: string): boolean => - !['releasability_rating', 'releasability_effort'].includes(metric); +export function hasList(metric /*: string */) /*: boolean */ { + return !['releasability_rating', 'releasability_effort'].includes(metric); +} -export const hasTree = (metric: string): boolean => metric !== 'alert_status'; +export function hasTree(metric /*: string */) /*: boolean */ { + return metric !== 'alert_status'; +} -export const hasTreemap = (metric: string, type: string): boolean => - ['PERCENT', 'RATING', 'LEVEL'].includes(type) && hasTree(metric); +export function hasTreemap(metric /*: string */, type /*: string */) /*: boolean */ { + return ['PERCENT', 'RATING', 'LEVEL'].includes(type) && hasTree(metric); +} -export const hasBubbleChart = (domainName: string): boolean => bubbles[domainName] != null; +export function hasBubbleChart(domainName /*: string */) /*: boolean */ { + return bubbles[domainName] != null; +} -export const hasFacetStat = (metric: string): boolean => metric !== 'alert_status'; +export function hasFacetStat(metric /*: string */) /*: boolean */ { + return metric !== 'alert_status'; +} -export const getBubbleMetrics = (domain: string, metrics: { [string]: Metric }) => { +export function getBubbleMetrics(domain /*: string */, metrics /*: { [string]: Metric } */) { const conf = bubbles[domain]; return { xMetric: metrics[conf.x], @@ -139,11 +148,13 @@ export const getBubbleMetrics = (domain: string, metrics: { [string]: Metric }) sizeMetric: metrics[conf.size], colorsMetric: conf.colors ? conf.colors.map(color => metrics[color]) : null }; -}; +} -export const isProjectOverview = (metric: string) => metric === PROJECT_OVERVEW; +export function isProjectOverview(metric /*: string */) { + return metric === PROJECT_OVERVEW; +} -const parseView = memoize((rawView?: string, metric: string) => { +const parseView = memoize((rawView /*:: ? */ /*: string */, metric /*: string */) => { const view = parseAsString(rawView) || DEFAULT_VIEW; if (!hasTree(metric)) { return 'list'; @@ -153,7 +164,7 @@ const parseView = memoize((rawView?: string, metric: string) => { return view; }); -export const parseQuery = memoize((urlQuery: RawQuery): Query => { +export const parseQuery = memoize((urlQuery /*: RawQuery */) => { const metric = parseAsString(urlQuery['metric']) || DEFAULT_METRIC; return { metric, @@ -162,7 +173,7 @@ export const parseQuery = memoize((urlQuery: RawQuery): Query => { }; }); -export const serializeQuery = memoize((query: Query): RawQuery => { +export const serializeQuery = memoize((query /*: Query */) => { return cleanQuery({ metric: query.metric === DEFAULT_METRIC ? null : serializeString(query.metric), selected: serializeString(query.selected), diff --git a/server/sonar-web/src/main/js/apps/component/components/App.js b/server/sonar-web/src/main/js/apps/component/components/App.js index 35211b6b119..e8c1c9f2128 100644 --- a/server/sonar-web/src/main/js/apps/component/components/App.js +++ b/server/sonar-web/src/main/js/apps/component/components/App.js @@ -22,7 +22,7 @@ import React from 'react'; import SourceViewer from '../../../components/SourceViewer/SourceViewer'; export default class App extends React.PureComponent { - props: { + /*:: props: { location: { query: { id: string, @@ -30,6 +30,7 @@ export default class App extends React.PureComponent { } } }; +*/ scrollToLine = () => { const { line } = this.props.location.query; if (line) { diff --git a/server/sonar-web/src/main/js/apps/issues/actions.js b/server/sonar-web/src/main/js/apps/issues/actions.js index 70f151a50d5..2303befa564 100644 --- a/server/sonar-web/src/main/js/apps/issues/actions.js +++ b/server/sonar-web/src/main/js/apps/issues/actions.js @@ -18,9 +18,9 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // @flow -import type { State } from './components/App'; +/*:: import type { State } from './components/App'; */ -export const enableLocationsNavigator = (state: State) => { +export const enableLocationsNavigator = (state /*: State */) => { const { openIssue } = state; if (openIssue && (openIssue.secondaryLocations.length > 0 || openIssue.flows.length > 0)) { return { @@ -35,7 +35,7 @@ export const disableLocationsNavigator = () => ({ locationsNavigator: false }); -export const selectLocation = (nextIndex: ?number) => (state: State) => { +export const selectLocation = (nextIndex /*: ?number */) => (state /*: State */) => { const { selectedLocationIndex: index, openIssue } = state; if (openIssue) { if (!state.locationsNavigator) { @@ -52,7 +52,7 @@ export const selectLocation = (nextIndex: ?number) => (state: State) => { } }; -export const selectNextLocation = (state: State) => { +export const selectNextLocation = (state /*: State */) => { const { selectedFlowIndex, selectedLocationIndex: index, openIssue } = state; if (openIssue) { const locations = @@ -63,25 +63,25 @@ export const selectNextLocation = (state: State) => { } }; -export const selectPreviousLocation = (state: State) => { +export const selectPreviousLocation = (state /*: State */) => { const { selectedLocationIndex: index, openIssue } = state; if (openIssue) { return { selectedLocationIndex: index != null && index > 0 ? index - 1 : index }; } }; -export const selectFlow = (nextIndex: ?number) => () => { +export const selectFlow = (nextIndex /*: ?number */) => () => { return { selectedFlowIndex: nextIndex, selectedLocationIndex: 0 }; }; -export const selectNextFlow = (state: State) => { +export const selectNextFlow = (state /*: State */) => { const { openIssue, selectedFlowIndex } = state; if (openIssue && selectedFlowIndex != null && openIssue.flows.length > selectedFlowIndex + 1) { return { selectedFlowIndex: selectedFlowIndex + 1, selectedLocationIndex: 0 }; } }; -export const selectPreviousFlow = (state: State) => { +export const selectPreviousFlow = (state /*: State */) => { const { openIssue, selectedFlowIndex } = state; if (openIssue && selectedFlowIndex != null && selectedFlowIndex > 0) { return { selectedFlowIndex: selectedFlowIndex - 1, selectedLocationIndex: 0 }; diff --git a/server/sonar-web/src/main/js/apps/issues/components/App.js b/server/sonar-web/src/main/js/apps/issues/components/App.js index 3f5dc5a0290..06746b240b0 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/App.js +++ b/server/sonar-web/src/main/js/apps/issues/components/App.js @@ -43,7 +43,7 @@ import { mapFacet, saveMyIssues } from '../utils'; -import type { +/*:: import type { Query, Paging, Facet, @@ -52,15 +52,16 @@ import type { ReferencedLanguage, Component, CurrentUser -} from '../utils'; +} from '../utils'; */ import ListFooter from '../../../components/controls/ListFooter'; import EmptySearch from '../../../components/common/EmptySearch'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { scrollToElement } from '../../../helpers/scrolling'; -import type { Issue } from '../../../components/issue/types'; -import type { RawQuery } from '../../../helpers/query'; +/*:: import type { Issue } from '../../../components/issue/types'; */ +/*:: import type { RawQuery } from '../../../helpers/query'; */ import '../styles.css'; +/*:: export type Props = { component?: Component, currentUser: CurrentUser, @@ -73,7 +74,9 @@ export type Props = { replace: ({ pathname: string, query?: RawQuery }) => void } }; +*/ +/*:: export type State = { bulkChange: 'all' | 'selected' | null, checked: Array<string>, @@ -94,15 +97,16 @@ export type State = { selectedFlowIndex: ?number, selectedLocationIndex: ?number }; +*/ const DEFAULT_QUERY = { resolved: 'false' }; 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 = { bulkChange: null, @@ -137,7 +141,7 @@ export default class App extends React.PureComponent { this.fetchFirstIssues(); } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { const openIssue = this.getOpenIssue(nextProps, this.state.issues); if (openIssue != null && openIssue.key !== this.state.selected) { @@ -159,7 +163,7 @@ export default class App extends React.PureComponent { }); } - componentDidUpdate(prevProps: Props, prevState: State) { + componentDidUpdate(prevProps /*: Props */, prevState /*: State */) { const { query } = this.props.location; const { query: prevQuery } = prevProps.location; if ( @@ -213,7 +217,7 @@ export default class App extends React.PureComponent { window.removeEventListener('keyup', this.handleKeyUp); } - handleKeyDown = (event: KeyboardEvent) => { + handleKeyDown = (event /*: KeyboardEvent */) => { if (key.getScope() !== 'issues') { return; } @@ -240,7 +244,7 @@ export default class App extends React.PureComponent { } }; - handleKeyUp = (event: KeyboardEvent) => { + handleKeyUp = (event /*: KeyboardEvent */) => { if (key.getScope() !== 'issues') { return; } @@ -250,13 +254,13 @@ export default class App extends React.PureComponent { } }; - getSelectedIndex(): ?number { + getSelectedIndex() /*: ?number */ { const { issues, selected } = this.state; const index = issues.findIndex(issue => issue.key === selected); return index !== -1 ? index : null; } - getOpenIssue = (props: Props, issues: Array<Issue>): ?Issue => { + getOpenIssue = (props /*: Props */, issues /*: Array<Issue> */) => { const open = getOpen(props.location.query); return open ? issues.find(issue => issue.key === open) : null; }; @@ -293,7 +297,7 @@ export default class App extends React.PureComponent { } }; - openIssue = (issue: string) => { + openIssue = (issue /*: string */) => { const path = { pathname: this.props.location.pathname, query: { @@ -332,7 +336,7 @@ export default class App extends React.PureComponent { } }; - scrollToSelectedIssue = (smooth: boolean = true) => { + scrollToSelectedIssue = (smooth /*: boolean */ = true) => { const { selected } = this.state; if (selected) { const element = document.querySelector(`[data-issue="${selected}"]`); @@ -342,7 +346,7 @@ export default class App extends React.PureComponent { } }; - fetchIssues = (additional?: {}, requestFacets?: boolean = false): Promise<*> => { + fetchIssues = (additional /*: ?{} */, requestFacets /*: ?boolean */ = false) => { const { component, organization } = this.props; const { myIssues, openFacets, query } = this.state; @@ -351,15 +355,18 @@ export default class App extends React.PureComponent { : undefined; const parameters = { - componentKeys: component && component.key, s: 'FILE_LINE', ...serializeQuery(query), - ps: 100, + ps: '100', organization: organization && organization.key, facets, ...additional }; + if (component) { + Object.assign(parameters, { componentKeys: component.key }); + } + // only sorting by CREATION_DATE is allowed, so let's sort DESC if (query.sort) { Object.assign(parameters, { asc: 'false' }); @@ -397,11 +404,11 @@ export default class App extends React.PureComponent { }); } - fetchIssuesPage = (p: number): Promise<*> => { + fetchIssuesPage = (p /*: number */) => { return this.fetchIssues({ p }); }; - fetchIssuesUntil = (p: number, done: (Array<Issue>, Paging) => boolean) => { + fetchIssuesUntil = (p /*: number */, done /*: (Array<Issue>, Paging) => boolean */) => { return this.fetchIssuesPage(p).then(response => { const { issues, paging } = response; @@ -437,20 +444,16 @@ export default class App extends React.PureComponent { }); }; - fetchIssuesForComponent = ( - component: string, - from: number, - to: number - ): Promise<Array<Issue>> => { + fetchIssuesForComponent = (component /*: string */, from /*: number */, to /*: number */) => { const { issues, openIssue, paging } = this.state; if (!openIssue || !paging) { return Promise.reject(); } - const isSameComponent = (issue: Issue): boolean => issue.component === openIssue.component; + const isSameComponent = (issue /*: Issue */) => issue.component === openIssue.component; - const done = (issues: Array<Issue>, paging: Paging): boolean => { + const done = (issues /*: Array<Issue> */, paging /*: Paging */) => { if (paging.total <= paging.pageIndex * paging.pageSize) { return true; } @@ -478,7 +481,7 @@ export default class App extends React.PureComponent { }); }; - fetchFacet = (facet: string) => { + fetchFacet = (facet /*: string */) => { return this.fetchIssues({ ps: 1, facets: mapFacet(facet) }).then(({ facets, ...other }) => { if (this.mounted) { this.setState(state => ({ @@ -517,7 +520,7 @@ export default class App extends React.PureComponent { return Promise.resolve({ issues, paging }); }; - handleFilterChange = (changes: {}) => { + handleFilterChange = (changes /*: {} */) => { this.props.router.push({ pathname: this.props.location.pathname, query: { @@ -528,7 +531,7 @@ export default class App extends React.PureComponent { }); }; - handleMyIssuesChange = (myIssues: boolean) => { + handleMyIssuesChange = (myIssues /*: boolean */) => { this.closeFacet('assignees'); if (!this.props.component) { saveMyIssues(myIssues); @@ -543,13 +546,13 @@ export default class App extends React.PureComponent { }); }; - closeFacet = (property: string) => { + closeFacet = (property /*: string */) => { this.setState(state => ({ openFacets: { ...state.openFacets, [property]: false } })); }; - handleFacetToggle = (property: string) => { + handleFacetToggle = (property /*: string */) => { this.setState(state => ({ openFacets: { ...state.openFacets, [property]: !state.openFacets[property] } })); @@ -569,7 +572,7 @@ export default class App extends React.PureComponent { }); }; - handleIssueCheck = (issue: string) => { + handleIssueCheck = (issue /*: string */) => { this.setState(state => ({ checked: state.checked.includes(issue) ? without(state.checked, issue) @@ -577,13 +580,13 @@ export default class App extends React.PureComponent { })); }; - handleIssueChange = (issue: Issue) => { + handleIssueChange = (issue /*: Issue */) => { this.setState(state => ({ issues: state.issues.map(candidate => (candidate.key === issue.key ? issue : candidate)) })); }; - openBulkChange = (mode: 'all' | 'selected') => { + openBulkChange = (mode /*: 'all' | 'selected' */) => { this.setState({ bulkChange: mode }); key.setScope('issues-bulk-change'); }; @@ -593,13 +596,13 @@ export default class App extends React.PureComponent { this.setState({ bulkChange: null }); }; - handleBulkChangeClick = (e: Event & { target: HTMLElement }) => { + handleBulkChangeClick = (e /*: Event & { target: HTMLElement } */) => { e.preventDefault(); e.target.blur(); this.openBulkChange('all'); }; - handleBulkChangeSelectedClick = (e: Event & { target: HTMLElement }) => { + handleBulkChangeSelectedClick = (e /*: Event & { target: HTMLElement } */) => { e.preventDefault(); e.target.blur(); this.openBulkChange('selected'); @@ -622,14 +625,14 @@ export default class App extends React.PureComponent { }); }; - selectLocation = (index: ?number) => this.setState(actions.selectLocation(index)); + selectLocation = (index /*: ?number */) => this.setState(actions.selectLocation(index)); selectNextLocation = () => this.setState(actions.selectNextLocation); selectPreviousLocation = () => this.setState(actions.selectPreviousLocation); - selectFlow = (index: ?number) => this.setState(actions.selectFlow(index)); + selectFlow = (index /*: ?number */) => this.setState(actions.selectFlow(index)); selectNextFlow = () => this.setState(actions.selectNextFlow); selectPreviousFlow = () => this.setState(actions.selectPreviousFlow); - renderBulkChange(openIssue: ?Issue) { + renderBulkChange(openIssue /*: ?Issue */) { const { component, currentUser } = this.props; const { bulkChange, checked, paging } = this.state; @@ -733,7 +736,7 @@ export default class App extends React.PureComponent { ); } - renderSide(openIssue: ?Issue) { + renderSide(openIssue /*: ?Issue */) { const top = this.props.component || this.props.organization ? 95 : 30; return ( diff --git a/server/sonar-web/src/main/js/apps/issues/components/AppContainer.js b/server/sonar-web/src/main/js/apps/issues/components/AppContainer.js index 0ce4f8bb598..9d1ab75594b 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/AppContainer.js +++ b/server/sonar-web/src/main/js/apps/issues/components/AppContainer.js @@ -20,7 +20,7 @@ // @flow import { connect } from 'react-redux'; import { withRouter } from 'react-router'; -import type { Dispatch } from 'redux'; +/*:: import type { Dispatch } from 'redux'; */ import { uniq } from 'lodash'; import App from './App'; import { onFail } from '../../../store/rootActions'; @@ -29,7 +29,7 @@ import { getOrganizations } from '../../../api/organizations'; import { receiveOrganizations } from '../../../store/organizations/duck'; import { searchIssues } from '../../../api/issues'; import { parseIssueFromResponse } from '../../../helpers/issues'; -import type { RawQuery } from '../../../helpers/query'; +/*:: import type { RawQuery } from '../../../helpers/query'; */ const mapStateToProps = (state, ownProps) => ({ component: ownProps.location.query.id @@ -50,7 +50,7 @@ const fetchIssueOrganizations = issues => dispatch => { ); }; -const fetchIssues = (query: RawQuery) => dispatch => +const fetchIssues = (query /*: RawQuery */) => dispatch => searchIssues({ ...query, additionalFields: '_all' }) .then(response => { const parsedIssues = response.issues.map(issue => @@ -61,7 +61,8 @@ const fetchIssues = (query: RawQuery) => dispatch => .then(response => dispatch(fetchIssueOrganizations(response.issues)).then(() => response)) .catch(onFail(dispatch)); -const onRequestFail = (error: Error) => (dispatch: Dispatch<*>) => onFail(dispatch)(error); +const onRequestFail = (error /*: Error */) => (dispatch /*: Dispatch<*> */) => + onFail(dispatch)(error); const mapDispatchToProps = { fetchIssues, onRequestFail }; diff --git a/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js b/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js index 250c8ed2a6d..e5002e86251 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js +++ b/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js @@ -32,9 +32,10 @@ import IssueTypeIcon from '../../../components/ui/IssueTypeIcon'; import { searchIssueTags, bulkChangeIssues } from '../../../api/issues'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { searchAssignees } from '../utils'; -import type { Paging, Component, CurrentUser } from '../utils'; -import type { Issue } from '../../../components/issue/types'; +/*:: import type { Paging, Component, CurrentUser } from '../utils'; */ +/*:: import type { Issue } from '../../../components/issue/types'; */ +/*:: type Props = {| component?: Component, currentUser: CurrentUser, @@ -44,7 +45,9 @@ type Props = {| onRequestFail: Error => void, organization?: { key: string } |}; +*/ +/*:: type State = {| issues: Array<Issue>, // used for initial loading of issues @@ -65,16 +68,17 @@ type State = {| transition?: string, type?: string |}; +*/ -const hasAction = (action: string) => (issue: Issue): boolean => +const hasAction = (action /*: string */) => (issue /*: Issue */) => issue.actions && issue.actions.includes(action); export default class BulkChangeModal extends React.PureComponent { - mounted: boolean; - props: Props; - state: State; + /*:: mounted: boolean; */ + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); let organization = props.component && props.component.organization; if (props.organization && !organization) { @@ -105,7 +109,7 @@ export default class BulkChangeModal extends React.PureComponent { this.mounted = false; } - handleCloseClick = (e: Event & { target: HTMLElement }) => { + handleCloseClick = (e /*: Event & { target: HTMLElement } */) => { e.preventDefault(); e.target.blur(); this.props.onClose(); @@ -115,7 +119,7 @@ export default class BulkChangeModal extends React.PureComponent { return this.props.fetchIssues({ additionalFields: 'actions,transitions', ps: 250 }); }; - handleAssigneeSearch = (query: string) => { + handleAssigneeSearch = (query /*: string */) => { if (query.length > 1) { return searchAssignees(query, this.state.organization); } else { @@ -144,11 +148,11 @@ export default class BulkChangeModal extends React.PureComponent { } }; - handleAssigneeSelect = (assignee: string) => { + handleAssigneeSelect = (assignee /*: string */) => { this.setState({ assignee }); }; - handleFieldCheck = (field: string) => (checked: boolean) => { + handleFieldCheck = (field /*: string */) => (checked /*: boolean */) => { if (!checked) { this.setState({ [field]: undefined }); } else if (field === 'notifications') { @@ -156,19 +160,21 @@ export default class BulkChangeModal extends React.PureComponent { } }; - handleFieldChange = (field: string) => (event: { target: HTMLInputElement }) => { + handleFieldChange = (field /*: string */) => (event /*: { target: HTMLInputElement } */) => { this.setState({ [field]: event.target.value }); }; - handleSelectFieldChange = (field: string) => ({ value }: { value: string }) => { + handleSelectFieldChange = (field /*: string */) => ({ value } /*: { value: string } */) => { this.setState({ [field]: value }); }; - handleMultiSelectFieldChange = (field: string) => (options: Array<{ value: string }>) => { + handleMultiSelectFieldChange = (field /*: string */) => ( + options /*: Array<{ value: string }> */ + ) => { this.setState({ [field]: options.map(option => option.value) }); }; - handleSubmit = (e: Event) => { + handleSubmit = (e /*: Event */) => { e.preventDefault(); const query = pickBy( { @@ -192,14 +198,16 @@ export default class BulkChangeModal extends React.PureComponent { this.setState({ submitting: false }); this.props.onDone(); }, - (error: Error) => { + (error /*: Error */) => { this.setState({ submitting: false }); this.props.onRequestFail(error); } ); }; - getAvailableTransitions(issues: Array<Issue>): Array<{ transition: string, count: number }> { + getAvailableTransitions( + issues /*: Array<Issue> */ + ) /*: Array<{ transition: string, count: number }> */ { const transitions = {}; issues.forEach(issue => { if (issue.transitions) { @@ -240,15 +248,20 @@ export default class BulkChangeModal extends React.PureComponent { </div> </div>; - renderCheckbox = (field: string) => + renderCheckbox = (field /*: string */) => <Checkbox checked={this.state[field] != null} onCheck={this.handleFieldCheck(field)} />; - renderAffected = (affected: number) => + renderAffected = (affected /*: number */) => <div className="pull-right note"> ({translateWithParameters('issue_bulk_change.x_issues', affected)}) </div>; - renderField = (field: string, label: string, affected: ?number, input: Object) => + renderField = ( + field /*: string */, + label /*: string */, + affected /*: ?number */, + input /*: Object */ + ) => <div className="modal-field" id={`issues-bulk-change-${field}`}> <label htmlFor={field}> {translate(label)} @@ -258,7 +271,7 @@ export default class BulkChangeModal extends React.PureComponent { {affected != null && this.renderAffected(affected)} </div>; - renderAssigneeOption = (option: { avatar?: string, email?: string, label: string }) => + renderAssigneeOption = (option /*: { avatar?: string, email?: string, label: string } */) => <span> {(option.avatar != null || option.email != null) && <Avatar @@ -272,7 +285,7 @@ export default class BulkChangeModal extends React.PureComponent { </span>; renderAssigneeField = () => { - const affected: number = this.state.issues.filter(hasAction('assign')).length; + const affected /*: number */ = this.state.issues.filter(hasAction('assign')).length; if (affected === 0) { return null; @@ -293,7 +306,7 @@ export default class BulkChangeModal extends React.PureComponent { }; renderTypeField = () => { - const affected: number = this.state.issues.filter(hasAction('set_type')).length; + const affected /*: number */ = this.state.issues.filter(hasAction('set_type')).length; if (affected === 0) { return null; @@ -302,7 +315,7 @@ export default class BulkChangeModal extends React.PureComponent { const types = ['BUG', 'VULNERABILITY', 'CODE_SMELL']; const options = types.map(type => ({ label: translate('issue.type', type), value: type })); - const optionRenderer = (option: { label: string, value: string }) => + const optionRenderer = (option /*: { label: string, value: string } */) => <span> <IssueTypeIcon className="little-spacer-right" query={option.value} /> {option.label} @@ -325,7 +338,7 @@ export default class BulkChangeModal extends React.PureComponent { }; renderSeverityField = () => { - const affected: number = this.state.issues.filter(hasAction('set_severity')).length; + const affected /*: number */ = this.state.issues.filter(hasAction('set_severity')).length; if (affected === 0) { return null; @@ -354,7 +367,7 @@ export default class BulkChangeModal extends React.PureComponent { }; renderAddTagsField = () => { - const affected: number = this.state.issues.filter(hasAction('set_tags')).length; + const affected /*: number */ = this.state.issues.filter(hasAction('set_tags')).length; if (this.state.tags == null || affected === 0) { return null; @@ -378,7 +391,7 @@ export default class BulkChangeModal extends React.PureComponent { }; renderRemoveTagsField = () => { - const affected: number = this.state.issues.filter(hasAction('set_tags')).length; + const affected /*: number */ = this.state.issues.filter(hasAction('set_tags')).length; if (this.state.tags == null || affected === 0) { return null; @@ -437,7 +450,7 @@ export default class BulkChangeModal extends React.PureComponent { }; renderCommentField = () => { - const affected: number = this.state.issues.filter(hasAction('comment')).length; + const affected /*: number */ = this.state.issues.filter(hasAction('comment')).length; if (affected === 0) { return null; @@ -478,7 +491,7 @@ export default class BulkChangeModal extends React.PureComponent { renderForm = () => { const { issues, paging, submitting } = this.state; - const limitReached: boolean = + const limitReached /*: boolean */ = paging != null && paging.total > paging.pageIndex * paging.pageSize; return ( diff --git a/server/sonar-web/src/main/js/apps/issues/components/ComponentBreadcrumbs.js b/server/sonar-web/src/main/js/apps/issues/components/ComponentBreadcrumbs.js index e4103100db0..b8a770b5e0e 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/ComponentBreadcrumbs.js +++ b/server/sonar-web/src/main/js/apps/issues/components/ComponentBreadcrumbs.js @@ -23,16 +23,18 @@ import { Link } from 'react-router'; import Organization from '../../../components/shared/Organization'; import { collapsePath, limitComponentName } from '../../../helpers/path'; import { getProjectUrl } from '../../../helpers/urls'; -import type { Component } from '../utils'; +/*:: import type { Component } from '../utils'; */ +/*:: type Props = { component?: Component, issue: Object, organization?: { key: string } }; +*/ export default class ComponentBreadcrumbs extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const { component, issue, organization } = this.props; diff --git a/server/sonar-web/src/main/js/apps/issues/components/FiltersHeader.js b/server/sonar-web/src/main/js/apps/issues/components/FiltersHeader.js index 8971b5e76e1..3e6448ed6d4 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/FiltersHeader.js +++ b/server/sonar-web/src/main/js/apps/issues/components/FiltersHeader.js @@ -21,15 +21,17 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { displayReset: boolean, onReset: () => void }; +*/ export default class FiltersHeader extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleResetClick = (e: Event & { currentTarget: HTMLElement }) => { + handleResetClick = (e /*: Event & { currentTarget: HTMLElement } */) => { e.preventDefault(); e.currentTarget.blur(); this.props.onReset(); diff --git a/server/sonar-web/src/main/js/apps/issues/components/IssuesCounter.js b/server/sonar-web/src/main/js/apps/issues/components/IssuesCounter.js index 6fa5a9d4b3b..7d43bccc987 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/IssuesCounter.js +++ b/server/sonar-web/src/main/js/apps/issues/components/IssuesCounter.js @@ -22,12 +22,14 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; import { formatMeasure } from '../../../helpers/measures'; +/*:: type Props = { current: ?number, total: number }; +*/ -const IssuesCounter = (props: Props) => +const IssuesCounter = (props /*: Props */) => <span> <strong> {props.current != null && diff --git a/server/sonar-web/src/main/js/apps/issues/components/IssuesList.js b/server/sonar-web/src/main/js/apps/issues/components/IssuesList.js index b0e56815484..88ba739aa8b 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/IssuesList.js +++ b/server/sonar-web/src/main/js/apps/issues/components/IssuesList.js @@ -20,9 +20,10 @@ // @flow import React from 'react'; import ListItem from './ListItem'; -import type { Issue } from '../../../components/issue/types'; -import type { Component } from '../utils'; +/*:: import type { Issue } from '../../../components/issue/types'; */ +/*:: import type { Component } from '../utils'; */ +/*:: type Props = {| checked: Array<string>, component?: Component, @@ -34,9 +35,10 @@ type Props = {| organization?: { key: string }, selectedIssue: ?Issue |}; +*/ export default class IssuesList extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const { checked, component, issues, selectedIssue } = this.props; diff --git a/server/sonar-web/src/main/js/apps/issues/components/IssuesSourceViewer.js b/server/sonar-web/src/main/js/apps/issues/components/IssuesSourceViewer.js index 48aa84d718a..498f2e377ce 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/IssuesSourceViewer.js +++ b/server/sonar-web/src/main/js/apps/issues/components/IssuesSourceViewer.js @@ -21,8 +21,9 @@ import React from 'react'; import SourceViewer from '../../../components/SourceViewer/SourceViewer'; import { scrollToElement } from '../../../helpers/scrolling'; -import type { Issue } from '../../../components/issue/types'; +/*:: import type { Issue } from '../../../components/issue/types'; */ +/*:: type Props = {| loadIssues: (string, number, number) => Promise<*>, onIssueChange: Issue => void, @@ -32,12 +33,13 @@ type Props = {| selectedFlowIndex: ?number, selectedLocationIndex: ?number |}; +*/ export default class IssuesSourceViewer extends React.PureComponent { - node: HTMLElement; - props: Props; + /*:: node: HTMLElement; */ + /*:: props: Props; */ - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if ( prevProps.openIssue !== this.props.openIssue && prevProps.openIssue.component === this.props.openIssue.component @@ -46,14 +48,14 @@ export default class IssuesSourceViewer extends React.PureComponent { } } - scrollToIssue = (smooth: boolean = true) => { + scrollToIssue = (smooth /*: boolean */ = true) => { const element = this.node.querySelector(`[data-issue="${this.props.openIssue.key}"]`); if (element) { this.handleScroll(element, smooth); } }; - handleScroll = (element: HTMLElement, smooth: boolean = true) => { + handleScroll = (element /*: HTMLElement */, smooth /*: boolean */ = true) => { const offset = window.innerHeight / 2; scrollToElement(element, { topOffset: offset - 100, bottomOffset: offset, smooth }); }; diff --git a/server/sonar-web/src/main/js/apps/issues/components/ListItem.js b/server/sonar-web/src/main/js/apps/issues/components/ListItem.js index 050a34093b2..7189ff6f84a 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/ListItem.js +++ b/server/sonar-web/src/main/js/apps/issues/components/ListItem.js @@ -21,9 +21,10 @@ import React from 'react'; import ComponentBreadcrumbs from './ComponentBreadcrumbs'; import Issue from '../../../components/issue/Issue'; -import type { Issue as IssueType } from '../../../components/issue/types'; -import type { Component } from '../utils'; +/*:: import type { Issue as IssueType } from '../../../components/issue/types'; */ +/*:: import type { Component } from '../utils'; */ +/*:: type Props = {| checked: boolean, component?: Component, @@ -36,16 +37,19 @@ type Props = {| previousIssue: ?Object, selected: boolean |}; +*/ +/*:: type State = { similarIssues: boolean }; +*/ export default class ListItem extends React.PureComponent { - props: Props; - state: State = { similarIssues: false }; + /*:: props: Props; */ + state /*: State */ = { similarIssues: false }; - handleFilter = (property: string, issue: IssueType) => { + handleFilter = (property /*: string */, issue /*: IssueType */) => { const { onFilterChange } = this.props; const issuesReset = { issues: [] }; diff --git a/server/sonar-web/src/main/js/apps/issues/components/MyIssuesFilter.js b/server/sonar-web/src/main/js/apps/issues/components/MyIssuesFilter.js index 7812c0dee9a..898d151cfe5 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/MyIssuesFilter.js +++ b/server/sonar-web/src/main/js/apps/issues/components/MyIssuesFilter.js @@ -21,15 +21,17 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = {| myIssues: boolean, onMyIssuesChange: boolean => void |}; +*/ export default class MyIssuesFilter extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleClick = (myIssues: boolean) => (e: Event & { currentTarget: HTMLElement }) => { + handleClick = (myIssues /*: boolean */) => (e /*: Event & { currentTarget: HTMLElement } */) => { e.preventDefault(); e.currentTarget.blur(); this.props.onMyIssuesChange(myIssues); diff --git a/server/sonar-web/src/main/js/apps/issues/components/PageActions.js b/server/sonar-web/src/main/js/apps/issues/components/PageActions.js index 467ba68edfc..64366643914 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/PageActions.js +++ b/server/sonar-web/src/main/js/apps/issues/components/PageActions.js @@ -21,18 +21,20 @@ import React from 'react'; import IssuesCounter from './IssuesCounter'; import ReloadButton from './ReloadButton'; -import type { Paging } from '../utils'; +/*:: import type { Paging } from '../utils'; */ import { translate } from '../../../helpers/l10n'; +/*:: type Props = {| loading: boolean, onReload: () => void, paging: ?Paging, selectedIndex: ?number |}; +*/ export default class PageActions extends React.PureComponent { - props: Props; + /*:: props: Props; */ renderShortcuts() { return ( diff --git a/server/sonar-web/src/main/js/apps/issues/components/ReloadButton.js b/server/sonar-web/src/main/js/apps/issues/components/ReloadButton.js index 09b5a0d2069..cc95565d101 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/ReloadButton.js +++ b/server/sonar-web/src/main/js/apps/issues/components/ReloadButton.js @@ -23,10 +23,12 @@ import classNames from 'classnames'; import Tooltip from '../../../components/controls/Tooltip'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = {| className?: string, onClick: () => void |}; +*/ /* eslint-disable max-len */ const icon = ( @@ -36,8 +38,8 @@ const icon = ( ); /* eslint-enable max-len */ -export default function ReloadButton(props: Props) { - const handleClick = (event: Event) => { +export default function ReloadButton(props /*: Props */) { + const handleClick = (event /*: Event */) => { event.preventDefault(); props.onClick(); }; diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/BackButton.js b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/BackButton.js index a4424b47942..17d7b6f1f47 100644 --- a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/BackButton.js +++ b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/BackButton.js @@ -23,10 +23,12 @@ import classNames from 'classnames'; import Tooltip from '../../../components/controls/Tooltip'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = {| className?: string, onClick: () => void |}; +*/ /* eslint-disable max-len */ const icon = ( @@ -36,8 +38,8 @@ const icon = ( ); /* eslint-enable max-len */ -export default function BackButton(props: Props) { - const handleClick = (event: Event) => { +export default function BackButton(props /*: Props */) { + const handleClick = (event /*: Event */) => { event.preventDefault(); props.onClick(); }; diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssue.js b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssue.js index 5fdeec3da53..caa30f853bf 100644 --- a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssue.js +++ b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssue.js @@ -21,8 +21,9 @@ import React from 'react'; import ConciseIssueBox from './ConciseIssueBox'; import ConciseIssueComponent from './ConciseIssueComponent'; -import type { Issue } from '../../../components/issue/types'; +/*:: import type { Issue } from '../../../components/issue/types'; */ +/*:: type Props = {| issue: Issue, onFlowSelect: number => void, @@ -34,9 +35,10 @@ type Props = {| selectedFlowIndex: ?number, selectedLocationIndex: ?number |}; +*/ export default class ConciseIssue extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const { issue, previousIssue, selected } = this.props; diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueBox.js b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueBox.js index e9e1c5fdce0..3d741603f62 100644 --- a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueBox.js +++ b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueBox.js @@ -24,8 +24,9 @@ import ConciseIssueLocations from './ConciseIssueLocations'; import ConciseIssueLocationsNavigator from './ConciseIssueLocationsNavigator'; import SeverityHelper from '../../../components/shared/SeverityHelper'; import TypeHelper from '../../../components/shared/TypeHelper'; -import type { Issue } from '../../../components/issue/types'; +/*:: import type { Issue } from '../../../components/issue/types'; */ +/*:: type Props = {| issue: Issue, onClick: string => void, @@ -36,11 +37,12 @@ type Props = {| selectedFlowIndex: ?number, selectedLocationIndex: ?number |}; +*/ export default class ConciseIssueBox extends React.PureComponent { - messageElement: HTMLElement; - rootElement: HTMLElement; - props: Props; + /*:: messageElement: HTMLElement; */ + /*:: rootElement: HTMLElement; */ + /*:: props: Props; */ componentDidMount() { if (this.props.selected) { @@ -48,7 +50,7 @@ export default class ConciseIssueBox extends React.PureComponent { } } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if (this.props.selected && prevProps.selected !== this.props.selected) { this.handleScroll(); } @@ -73,7 +75,7 @@ export default class ConciseIssueBox extends React.PureComponent { } }; - handleClick = (event: Event) => { + handleClick = (event /*: Event */) => { event.preventDefault(); this.props.onClick(this.props.issue.key); }; diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueComponent.js b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueComponent.js index ab8ecd13226..35d46db0fff 100644 --- a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueComponent.js +++ b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueComponent.js @@ -21,11 +21,13 @@ import React from 'react'; import { collapsePath } from '../../../helpers/path'; +/*:: type Props = { path: string }; +*/ -const ConciseIssueComponent = (props: Props) => +const ConciseIssueComponent = (props /*: Props */) => <div className="concise-issue-component note text-ellipsis"> {collapsePath(props.path, 20)} </div>; diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueLocationBadge.js b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueLocationBadge.js index 794cef4a105..7ecfd86f5b1 100644 --- a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueLocationBadge.js +++ b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueLocationBadge.js @@ -24,13 +24,15 @@ import LocationIndex from '../../../components/common/LocationIndex'; import { translateWithParameters } from '../../../helpers/l10n'; import { formatMeasure } from '../../../helpers/measures'; +/*:: type Props = {| count: number, onClick?: () => void, selected?: boolean |}; +*/ -export default function ConciseIssueLocationBadge(props: Props) { +export default function ConciseIssueLocationBadge(props /*: Props */) { return ( <Tooltip mouseEnterDelay={0.5} diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueLocations.js b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueLocations.js index cf1144a24bc..d9ca0594f50 100644 --- a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueLocations.js +++ b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueLocations.js @@ -20,25 +20,29 @@ // @flow import React from 'react'; import ConciseIssueLocationBadge from './ConciseIssueLocationBadge'; -import type { Issue } from '../../../components/issue/types'; +/*:: import type { Issue } from '../../../components/issue/types'; */ +/*:: type Props = {| issue: Issue, onFlowSelect: number => void, selectedFlowIndex: ?number |}; +*/ +/*:: type State = { collapsed: boolean }; +*/ const LIMIT = 3; export default class ConciseIssueLocations extends React.PureComponent { - props: Props; - state: State = { collapsed: true }; + /*:: props: Props; */ + state /*: State */ = { collapsed: true }; - handleExpandClick = (event: Event) => { + handleExpandClick = (event /*: Event */) => { event.preventDefault(); this.setState({ collapsed: false }); }; diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueLocationsNavigator.js b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueLocationsNavigator.js index bbe2beb7237..fdc31fe2533 100644 --- a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueLocationsNavigator.js +++ b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueLocationsNavigator.js @@ -20,8 +20,9 @@ // @flow import React from 'react'; import ConciseIssueLocationsNavigatorLocation from './ConciseIssueLocationsNavigatorLocation'; -import type { Issue } from '../../../components/issue/types'; +/*:: import type { Issue } from '../../../components/issue/types'; */ +/*:: type Props = {| issue: Issue, onLocationSelect: number => void, @@ -29,11 +30,12 @@ type Props = {| selectedFlowIndex: ?number, selectedLocationIndex: ?number |}; +*/ export default class ConciseIssueLocationsNavigator extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleClick = (index: number) => (event: Event) => { + handleClick = (index /*: number */) => (event /*: Event */) => { event.preventDefault(); this.props.onLocationSelect(index); }; diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueLocationsNavigatorLocation.js b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueLocationsNavigatorLocation.js index 099e7804d2c..e4af455b43b 100644 --- a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueLocationsNavigatorLocation.js +++ b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssueLocationsNavigatorLocation.js @@ -22,6 +22,7 @@ import React from 'react'; import LocationIndex from '../../../components/common/LocationIndex'; import LocationMessage from '../../../components/common/LocationMessage'; +/*:: type Props = { index: number, message: string, @@ -29,10 +30,11 @@ type Props = { scroll: HTMLElement => void, selected: boolean }; +*/ export default class ConciseIssueLocationsNavigatorLocation extends React.PureComponent { - node: HTMLElement; - props: Props; + /*:: node: HTMLElement; */ + /*:: props: Props; */ componentDidMount() { if (this.props.selected) { @@ -40,13 +42,13 @@ export default class ConciseIssueLocationsNavigatorLocation extends React.PureCo } } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if (this.props.selected && prevProps.selected !== this.props.selected) { this.props.scroll(this.node); } } - handleClick = (event: Event) => { + handleClick = (event /*: Event */) => { event.preventDefault(); this.props.onClick(this.props.index); }; diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssuesList.js b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssuesList.js index 611d14deca0..f8700d6035d 100644 --- a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssuesList.js +++ b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssuesList.js @@ -21,8 +21,9 @@ import React from 'react'; import ConciseIssue from './ConciseIssue'; import { scrollToElement } from '../../../helpers/scrolling'; -import type { Issue } from '../../../components/issue/types'; +/*:: import type { Issue } from '../../../components/issue/types'; */ +/*:: type Props = {| issues: Array<Issue>, onFlowSelect: number => void, @@ -32,11 +33,12 @@ type Props = {| selectedFlowIndex: ?number, selectedLocationIndex: ?number |}; +*/ export default class ConciseIssuesList extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleScroll = (element: HTMLElement, bottomOffset: number = 100) => { + handleScroll = (element /*: HTMLElement */, bottomOffset /*: number */ = 100) => { const scrollableElement = document.querySelector('.layout-page-side'); if (element && scrollableElement) { scrollToElement(element, { topOffset: 150, bottomOffset, parent: scrollableElement }); diff --git a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssuesListHeader.js b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssuesListHeader.js index aed9b836953..a38dd89363a 100644 --- a/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssuesListHeader.js +++ b/server/sonar-web/src/main/js/apps/issues/conciseIssuesList/ConciseIssuesListHeader.js @@ -22,8 +22,9 @@ import React from 'react'; import BackButton from './BackButton'; import ReloadButton from '../components/ReloadButton'; import IssuesCounter from '../components/IssuesCounter'; -import type { Paging } from '../utils'; +/*:: import type { Paging } from '../utils'; */ +/*:: type Props = {| loading: boolean, onBackClick: () => void, @@ -31,8 +32,9 @@ type Props = {| paging?: Paging, selectedIndex: ?number |}; +*/ -export default function ConciseIssuesListHeader(props: Props) { +export default function ConciseIssuesListHeader(props /*: Props */) { const { paging, selectedIndex } = props; return ( diff --git a/server/sonar-web/src/main/js/apps/issues/redirects.js b/server/sonar-web/src/main/js/apps/issues/redirects.js index a66bb570a7b..51d3e0214ed 100644 --- a/server/sonar-web/src/main/js/apps/issues/redirects.js +++ b/server/sonar-web/src/main/js/apps/issues/redirects.js @@ -19,10 +19,10 @@ */ // @flow import { parseQuery, areMyIssuesSelected, serializeQuery } from './utils'; -import type { RawQuery } from '../../helpers/query'; +/*:: import type { RawQuery } from '../../helpers/query'; */ -const parseHash = (hash: string): RawQuery => { - const query: RawQuery = {}; +function parseHash(hash /*: string */) /*: RawQuery */ { + const query /*: RawQuery */ = {}; const parts = hash.split('|'); parts.forEach(part => { const tokens = part.split('='); @@ -37,9 +37,9 @@ const parseHash = (hash: string): RawQuery => { } }); return query; -}; +} -export const onEnter = (state: Object, replace: Function) => { +export function onEnter(state /*: Object */, replace /*: Function */) { const { hash } = window.location; if (hash.length > 1) { const query = parseHash(hash.substr(1)); @@ -52,4 +52,4 @@ export const onEnter = (state: Object, replace: Function) => { query: normalizedQuery }); } -}; +} diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/AssigneeFacet.js b/server/sonar-web/src/main/js/apps/issues/sidebar/AssigneeFacet.js index 94407c286b6..6ed62ddc478 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/AssigneeFacet.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/AssigneeFacet.js @@ -28,8 +28,9 @@ import FacetItemsList from '../../../components/facet/FacetItemsList'; import FacetFooter from '../../../components/facet/FacetFooter'; import { searchAssignees, formatFacetStat } from '../utils'; import { translate } from '../../../helpers/l10n'; -import type { ReferencedUser, Component } from '../utils'; +/*:: import type { ReferencedUser, Component } from '../utils'; */ +/*:: type Props = {| assigned: boolean, assignees: Array<string>, @@ -42,9 +43,10 @@ type Props = {| stats?: { [string]: number }, referencedUsers: { [string]: ReferencedUser } |}; +*/ export default class AssigneeFacet extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { open: true @@ -52,7 +54,7 @@ export default class AssigneeFacet extends React.PureComponent { property = 'assignees'; - handleItemClick = (itemValue: string) => { + handleItemClick = (itemValue /*: string */) => { if (itemValue === '') { // unassigned this.props.onChange({ assigned: !this.props.assigned, assignees: [] }); @@ -74,7 +76,7 @@ export default class AssigneeFacet extends React.PureComponent { this.props.onChange({ assigned: true, assignees: [] }); }; - handleSearch = (query: string) => { + handleSearch = (query /*: string */) => { let organization = this.props.component && this.props.component.organization; if (this.props.organization && !organization) { organization = this.props.organization.key; @@ -82,16 +84,16 @@ export default class AssigneeFacet extends React.PureComponent { return searchAssignees(query, organization); }; - handleSelect = (assignee: string) => { + handleSelect = (assignee /*: string */) => { const { assignees } = this.props; this.props.onChange({ assigned: true, [this.property]: uniq([...assignees, assignee]) }); }; - isAssigneeActive(assignee: string) { + isAssigneeActive(assignee /*: string */) { return assignee === '' ? !this.props.assigned : this.props.assignees.includes(assignee); } - getAssigneeName(assignee: string): React.Element<*> | string { + getAssigneeName(assignee /*: string */) /*: React.Element<*> | string */ { if (assignee === '') { return translate('unassigned'); } else { @@ -114,12 +116,12 @@ export default class AssigneeFacet extends React.PureComponent { } } - getStat(assignee: string): ?number { + getStat(assignee /*: string */) /*: ?number */ { const { stats } = this.props; return stats ? stats[assignee] : null; } - renderOption = (option: { avatar: string, label: string }) => { + renderOption = (option /*: { avatar: string, label: string } */) => { return ( <span> {option.avatar != null && diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/AuthorFacet.js b/server/sonar-web/src/main/js/apps/issues/sidebar/AuthorFacet.js index 8cb5c1f05ab..6aa249a574b 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/AuthorFacet.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/AuthorFacet.js @@ -27,6 +27,7 @@ import FacetItemsList from '../../../components/facet/FacetItemsList'; import { formatFacetStat } from '../utils'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = {| facetMode: string, onChange: (changes: {}) => void, @@ -35,9 +36,10 @@ type Props = {| stats?: { [string]: number }, authors: Array<string> |}; +*/ export default class AuthorFacet extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { open: true @@ -45,7 +47,7 @@ export default class AuthorFacet extends React.PureComponent { property = 'authors'; - handleItemClick = (itemValue: string) => { + handleItemClick = (itemValue /*: string */) => { const { authors } = this.props; const newValue = sortBy( authors.includes(itemValue) ? without(authors, itemValue) : [...authors, itemValue] @@ -61,7 +63,7 @@ export default class AuthorFacet extends React.PureComponent { this.props.onChange({ [this.property]: [] }); }; - getStat(author: string): ?number { + getStat(author /*: string */) /*: ?number */ { const { stats } = this.props; return stats ? stats[author] : null; } diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/CreationDateFacet.js b/server/sonar-web/src/main/js/apps/issues/sidebar/CreationDateFacet.js index f7cc13735a9..3a30ccd1ec4 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/CreationDateFacet.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/CreationDateFacet.js @@ -28,8 +28,9 @@ import { BarChart } from '../../../components/charts/bar-chart'; import DateInput from '../../../components/controls/DateInput'; import { translate } from '../../../helpers/l10n'; import { formatMeasure } from '../../../helpers/measures'; -import type { Component } from '../utils'; +/*:: import type { Component } from '../utils'; */ +/*:: type Props = {| component?: Component, createdAfter: string, @@ -43,11 +44,12 @@ type Props = {| sinceLeakPeriod: boolean, stats?: { [string]: number } |}; +*/ const DATE_FORMAT = 'YYYY-MM-DDTHH:mm:ssZZ'; export default class CreationDateFacet extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { open: true @@ -55,7 +57,7 @@ export default class CreationDateFacet extends React.PureComponent { property = 'createdAt'; - hasValue = (): boolean => + hasValue = () => this.props.createdAfter.length > 0 || this.props.createdAt.length > 0 || this.props.createdBefore.length > 0 || @@ -70,7 +72,7 @@ export default class CreationDateFacet extends React.PureComponent { this.resetTo({}); }; - resetTo = (changes: {}) => { + resetTo = (changes /*: {} */) => { this.props.onChange({ createdAfter: undefined, createdAt: undefined, @@ -81,20 +83,22 @@ export default class CreationDateFacet extends React.PureComponent { }); }; - handleBarClick = ({ - createdAfter, - createdBefore - }: { + handleBarClick = ( + { + createdAfter, + createdBefore + } /*: { createdAfter: Object, createdBefore?: Object - }) => { + } */ + ) => { this.resetTo({ createdAfter: createdAfter.format(DATE_FORMAT), createdBefore: createdBefore && createdBefore.format(DATE_FORMAT) }); }; - handlePeriodChange = (property: string) => (value: string) => { + handlePeriodChange = (property /*: string */) => (value /*: string */) => { this.props.onChange({ createdAt: undefined, createdInLast: undefined, @@ -103,7 +107,7 @@ export default class CreationDateFacet extends React.PureComponent { }); }; - handlePeriodClick = (period: string) => { + handlePeriodClick = (period /*: string */) => { this.resetTo({ createdInLast: period }); }; diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/DirectoryFacet.js b/server/sonar-web/src/main/js/apps/issues/sidebar/DirectoryFacet.js index 35d8b70b2ac..030a8b3bb35 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/DirectoryFacet.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/DirectoryFacet.js @@ -27,8 +27,9 @@ import FacetItemsList from '../../../components/facet/FacetItemsList'; import QualifierIcon from '../../../components/shared/QualifierIcon'; import { translate } from '../../../helpers/l10n'; import { formatFacetStat } from '../utils'; -import type { ReferencedComponent } from '../utils'; +/*:: import type { ReferencedComponent } from '../utils'; */ +/*:: type Props = {| facetMode: string, onChange: (changes: { [string]: Array<string> }) => void, @@ -38,9 +39,10 @@ type Props = {| referencedComponents: { [string]: ReferencedComponent }, directories: Array<string> |}; +*/ export default class DirectoryFacet extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { open: true @@ -48,7 +50,7 @@ export default class DirectoryFacet extends React.PureComponent { property = 'directories'; - handleItemClick = (itemValue: string) => { + handleItemClick = (itemValue /*: string */) => { const { directories } = this.props; const newValue = sortBy( directories.includes(itemValue) @@ -66,12 +68,12 @@ export default class DirectoryFacet extends React.PureComponent { this.props.onChange({ [this.property]: [] }); }; - getStat(directory: string): ?number { + getStat(directory /*: string */) /*: ?number */ { const { stats } = this.props; return stats ? stats[directory] : null; } - renderName(directory: string): React.Element<*> | string { + renderName(directory /*: string */) /*: React.Element<*> | string */ { // `referencedComponents` are indexed by uuid // so we have to browse them all to find a matching one const { referencedComponents } = this.props; diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/FacetMode.js b/server/sonar-web/src/main/js/apps/issues/sidebar/FacetMode.js index 64419abdf81..59c963a1178 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/FacetMode.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/FacetMode.js @@ -25,17 +25,19 @@ import FacetItem from '../../../components/facet/FacetItem'; import FacetItemsList from '../../../components/facet/FacetItemsList'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = {| facetMode: string, onChange: (changes: {}) => void |}; +*/ export default class FacetMode extends React.PureComponent { - props: Props; + /*:: props: Props; */ property = 'facetMode'; - handleItemClick = (itemValue: string) => { + handleItemClick = (itemValue /*: string */) => { this.props.onChange({ [this.property]: itemValue }); }; diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/FileFacet.js b/server/sonar-web/src/main/js/apps/issues/sidebar/FileFacet.js index 33af07a4212..aeb00d0fc0f 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/FileFacet.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/FileFacet.js @@ -28,8 +28,9 @@ import QualifierIcon from '../../../components/shared/QualifierIcon'; import { translate } from '../../../helpers/l10n'; import { collapsePath } from '../../../helpers/path'; import { formatFacetStat } from '../utils'; -import type { ReferencedComponent } from '../utils'; +/*:: import type { ReferencedComponent } from '../utils'; */ +/*:: type Props = {| facetMode: string, onChange: (changes: { [string]: Array<string> }) => void, @@ -39,9 +40,10 @@ type Props = {| referencedComponents: { [string]: ReferencedComponent }, files: Array<string> |}; +*/ export default class FileFacet extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { open: true @@ -49,7 +51,7 @@ export default class FileFacet extends React.PureComponent { property = 'files'; - handleItemClick = (itemValue: string) => { + handleItemClick = (itemValue /*: string */) => { const { files } = this.props; const newValue = sortBy( files.includes(itemValue) ? without(files, itemValue) : [...files, itemValue] @@ -65,12 +67,12 @@ export default class FileFacet extends React.PureComponent { this.props.onChange({ [this.property]: [] }); }; - getStat(file: string): ?number { + getStat(file /*: string */) /*: ?number */ { const { stats } = this.props; return stats ? stats[file] : null; } - renderName(file: string): React.Element<*> | string { + renderName(file /*: string */) /*: React.Element<*> | string */ { const { referencedComponents } = this.props; const name = referencedComponents[file] ? collapsePath(referencedComponents[file].path, 15) diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/LanguageFacet.js b/server/sonar-web/src/main/js/apps/issues/sidebar/LanguageFacet.js index 37406c5f00e..317cca77f28 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/LanguageFacet.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/LanguageFacet.js @@ -27,8 +27,9 @@ import FacetItemsList from '../../../components/facet/FacetItemsList'; import LanguageFacetFooter from './LanguageFacetFooter'; import { translate } from '../../../helpers/l10n'; import { formatFacetStat } from '../utils'; -import type { ReferencedLanguage } from '../utils'; +/*:: import type { ReferencedLanguage } from '../utils'; */ +/*:: type Props = {| facetMode: string, onChange: (changes: { [string]: Array<string> }) => void, @@ -38,9 +39,10 @@ type Props = {| referencedLanguages: { [string]: ReferencedLanguage }, languages: Array<string> |}; +*/ export default class LanguageFacet extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { open: true @@ -48,7 +50,7 @@ export default class LanguageFacet extends React.PureComponent { property = 'languages'; - handleItemClick = (itemValue: string) => { + handleItemClick = (itemValue /*: string */) => { const { languages } = this.props; const newValue = sortBy( languages.includes(itemValue) ? without(languages, itemValue) : [...languages, itemValue] @@ -64,17 +66,17 @@ export default class LanguageFacet extends React.PureComponent { this.props.onChange({ [this.property]: [] }); }; - getLanguageName(language: string): string { + getLanguageName(language /*: string */) /*: string */ { const { referencedLanguages } = this.props; return referencedLanguages[language] ? referencedLanguages[language].name : language; } - getStat(language: string): ?number { + getStat(language /*: string */) /*: ?number */ { const { stats } = this.props; return stats ? stats[language] : null; } - handleSelect = (language: string) => { + handleSelect = (language /*: string */) => { const { languages } = this.props; this.props.onChange({ [this.property]: uniq([...languages, language]) }); }; diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/LanguageFacetFooter.js b/server/sonar-web/src/main/js/apps/issues/sidebar/LanguageFacetFooter.js index f79d264f06b..639b521597b 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/LanguageFacetFooter.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/LanguageFacetFooter.js @@ -24,17 +24,21 @@ import { connect } from 'react-redux'; import { translate } from '../../../helpers/l10n'; import { getLanguages } from '../../../store/rootReducer'; +/*:: type Option = { label: string, value: string }; +*/ +/*:: type Props = {| languages: Array<{ key: string, name: string }>, onSelect: (value: string) => void |}; +*/ class LanguageFacetFooter extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleChange = (option: Option) => { + handleChange = (option /*: Option */) => { this.props.onSelect(option.value); }; diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/ModuleFacet.js b/server/sonar-web/src/main/js/apps/issues/sidebar/ModuleFacet.js index 8f7df010f83..6a01a9f51fd 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/ModuleFacet.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/ModuleFacet.js @@ -27,8 +27,9 @@ import FacetItemsList from '../../../components/facet/FacetItemsList'; import QualifierIcon from '../../../components/shared/QualifierIcon'; import { translate } from '../../../helpers/l10n'; import { formatFacetStat } from '../utils'; -import type { ReferencedComponent } from '../utils'; +/*:: import type { ReferencedComponent } from '../utils'; */ +/*:: type Props = {| facetMode: string, onChange: (changes: { [string]: Array<string> }) => void, @@ -38,9 +39,10 @@ type Props = {| referencedComponents: { [string]: ReferencedComponent }, modules: Array<string> |}; +*/ export default class ModuleFacet extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { open: true @@ -48,7 +50,7 @@ export default class ModuleFacet extends React.PureComponent { property = 'modules'; - handleItemClick = (itemValue: string) => { + handleItemClick = (itemValue /*: string */) => { const { modules } = this.props; const newValue = sortBy( modules.includes(itemValue) ? without(modules, itemValue) : [...modules, itemValue] @@ -64,12 +66,12 @@ export default class ModuleFacet extends React.PureComponent { this.props.onChange({ [this.property]: [] }); }; - getStat(module: string): ?number { + getStat(module /*: string */) /*: ?number */ { const { stats } = this.props; return stats ? stats[module] : null; } - renderName(module: string): React.Element<*> | string { + renderName(module /*: string */) /*: React.Element<*> | string */ { const { referencedComponents } = this.props; const name = referencedComponents[module] ? referencedComponents[module].name : module; return ( diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/ProjectFacet.js b/server/sonar-web/src/main/js/apps/issues/sidebar/ProjectFacet.js index dbbf3f4784b..ab329263ce6 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/ProjectFacet.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/ProjectFacet.js @@ -30,8 +30,9 @@ import QualifierIcon from '../../../components/shared/QualifierIcon'; import { searchProjects, getTree } from '../../../api/components'; import { translate } from '../../../helpers/l10n'; import { formatFacetStat } from '../utils'; -import type { ReferencedComponent, Component } from '../utils'; +/*:: import type { ReferencedComponent, Component } from '../utils'; */ +/*:: type Props = {| component?: Component, facetMode: string, @@ -43,9 +44,10 @@ type Props = {| referencedComponents: { [string]: ReferencedComponent }, projects: Array<string> |}; +*/ export default class ProjectFacet extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { open: true @@ -53,7 +55,7 @@ export default class ProjectFacet extends React.PureComponent { property = 'projects'; - handleItemClick = (itemValue: string) => { + handleItemClick = (itemValue /*: string */) => { const { projects } = this.props; const newValue = sortBy( projects.includes(itemValue) ? without(projects, itemValue) : [...projects, itemValue] @@ -69,7 +71,7 @@ export default class ProjectFacet extends React.PureComponent { this.props.onChange({ [this.property]: [] }); }; - handleSearch = (query: string) => { + handleSearch = (query /*: string */) => { const { component, organization } = this.props; if (component != null && ['VW', 'SVW', 'APP'].includes(component.qualifier)) { return getTree(component.key, { ps: 50, q: query, qualifiers: 'TRK' }).then(response => @@ -94,17 +96,17 @@ export default class ProjectFacet extends React.PureComponent { ); }; - handleSelect = (rule: string) => { + handleSelect = (rule /*: string */) => { const { projects } = this.props; this.props.onChange({ [this.property]: uniq([...projects, rule]) }); }; - getStat(project: string): ?number { + getStat(project /*: string */) /*: ?number */ { const { stats } = this.props; return stats ? stats[project] : null; } - renderName(project: string): React.Element<*> | string { + renderName(project /*: string */) /*: React.Element<*> | string */ { const { organization, referencedComponents } = this.props; return referencedComponents[project] ? <span> @@ -122,7 +124,7 @@ export default class ProjectFacet extends React.PureComponent { </span>; } - renderOption = (option: { label: string, organization: string }) => { + renderOption = (option /*: { label: string, organization: string } */) => { return ( <span> <Organization link={false} organizationKey={option.organization} /> diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/ResolutionFacet.js b/server/sonar-web/src/main/js/apps/issues/sidebar/ResolutionFacet.js index c6a949b3fb5..5c09c1489bc 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/ResolutionFacet.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/ResolutionFacet.js @@ -27,6 +27,7 @@ import FacetItemsList from '../../../components/facet/FacetItemsList'; import { translate } from '../../../helpers/l10n'; import { formatFacetStat } from '../utils'; +/*:: type Props = {| facetMode: string, onChange: (changes: {}) => void, @@ -36,9 +37,10 @@ type Props = {| resolutions: Array<string>, stats?: { [string]: number } |}; +*/ export default class ResolutionFacet extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { open: true @@ -46,7 +48,7 @@ export default class ResolutionFacet extends React.PureComponent { property = 'resolutions'; - handleItemClick = (itemValue: string) => { + handleItemClick = (itemValue /*: string */) => { if (itemValue === '') { // unresolved this.props.onChange({ resolved: !this.props.resolved, resolutions: [] }); @@ -70,20 +72,20 @@ export default class ResolutionFacet extends React.PureComponent { this.props.onChange({ resolved: false, resolutions: [] }); }; - isFacetItemActive(resolution: string) { + isFacetItemActive(resolution /*: string */) { return resolution === '' ? !this.props.resolved : this.props.resolutions.includes(resolution); } - getFacetItemName(resolution: string) { + getFacetItemName(resolution /*: string */) { return resolution === '' ? translate('unresolved') : translate('issue.resolution', resolution); } - getStat(resolution: string): ?number { + getStat(resolution /*: string */) /*: ?number */ { const { stats } = this.props; return stats ? stats[resolution] : null; } - renderItem = (resolution: string) => { + renderItem = (resolution /*: string */) => { const active = this.isFacetItemActive(resolution); const stat = this.getStat(resolution); diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/RuleFacet.js b/server/sonar-web/src/main/js/apps/issues/sidebar/RuleFacet.js index 9cb922314ee..22e4e4194c3 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/RuleFacet.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/RuleFacet.js @@ -29,6 +29,7 @@ import { searchRules } from '../../../api/rules'; import { translate } from '../../../helpers/l10n'; import { formatFacetStat } from '../utils'; +/*:: type Props = {| facetMode: string, languages: Array<string>, @@ -39,9 +40,10 @@ type Props = {| referencedRules: { [string]: { name: string } }, rules: Array<string> |}; +*/ export default class RuleFacet extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { open: true @@ -49,7 +51,7 @@ export default class RuleFacet extends React.PureComponent { property = 'rules'; - handleItemClick = (itemValue: string) => { + handleItemClick = (itemValue /*: string */) => { const { rules } = this.props; const newValue = sortBy( rules.includes(itemValue) ? without(rules, itemValue) : [...rules, itemValue] @@ -65,7 +67,7 @@ export default class RuleFacet extends React.PureComponent { this.props.onChange({ [this.property]: [] }); }; - handleSearch = (query: string) => { + handleSearch = (query /*: string */) => { const { languages } = this.props; return searchRules({ f: 'name,langName', @@ -76,17 +78,17 @@ export default class RuleFacet extends React.PureComponent { ); }; - handleSelect = (rule: string) => { + handleSelect = (rule /*: string */) => { const { rules } = this.props; this.props.onChange({ [this.property]: uniq([...rules, rule]) }); }; - getRuleName(rule: string): string { + getRuleName(rule /*: string */) /*: string */ { const { referencedRules } = this.props; return referencedRules[rule] ? referencedRules[rule].name : rule; } - getStat(rule: string): ?number { + getStat(rule /*: string */) /*: ?number */ { const { stats } = this.props; return stats ? stats[rule] : null; } diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/SeverityFacet.js b/server/sonar-web/src/main/js/apps/issues/sidebar/SeverityFacet.js index 69765762b8e..96685a9c50b 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/SeverityFacet.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/SeverityFacet.js @@ -28,6 +28,7 @@ import SeverityHelper from '../../../components/shared/SeverityHelper'; import { translate } from '../../../helpers/l10n'; import { formatFacetStat } from '../utils'; +/*:: type Props = {| facetMode: string, onChange: (changes: { [string]: Array<string> }) => void, @@ -36,9 +37,10 @@ type Props = {| severities: Array<string>, stats?: { [string]: number } |}; +*/ export default class SeverityFacet extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { open: true @@ -46,7 +48,7 @@ export default class SeverityFacet extends React.PureComponent { property = 'severities'; - handleItemClick = (itemValue: string) => { + handleItemClick = (itemValue /*: string */) => { const { severities } = this.props; const newValue = orderBy( severities.includes(itemValue) ? without(severities, itemValue) : [...severities, itemValue] @@ -62,12 +64,12 @@ export default class SeverityFacet extends React.PureComponent { this.props.onChange({ [this.property]: [] }); }; - getStat(severity: string): ?number { + getStat(severity /*: string */) /*: ?number */ { const { stats } = this.props; return stats ? stats[severity] : null; } - renderItem = (severity: string) => { + renderItem = (severity /*: string */) => { const active = this.props.severities.includes(severity); const stat = this.getStat(severity); diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/Sidebar.js b/server/sonar-web/src/main/js/apps/issues/sidebar/Sidebar.js index 98e3cde5543..28164b903b1 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/Sidebar.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/Sidebar.js @@ -34,15 +34,16 @@ import SeverityFacet from './SeverityFacet'; import StatusFacet from './StatusFacet'; import TagFacet from './TagFacet'; import TypeFacet from './TypeFacet'; -import type { +/*:: import type { Query, Facet, ReferencedComponent, ReferencedUser, ReferencedLanguage, Component -} from '../utils'; +} from '../utils'; */ +/*:: type Props = {| component?: Component, facets: { [string]: Facet }, @@ -57,14 +58,15 @@ type Props = {| referencedRules: { [string]: { name: string } }, referencedUsers: { [string]: ReferencedUser } |}; +*/ export default class Sidebar extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const { component, facets, openFacets, query } = this.props; - const displayProjectsFacet: boolean = + const displayProjectsFacet /*: boolean */ = component == null || !['TRK', 'BRC', 'DIR', 'DEV_PRJ'].includes(component.qualifier); const displayModulesFacet = component != null && component.qualifier !== 'DIR'; const displayDirectoriesFacet = component != null && component.qualifier !== 'DIR'; diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/StatusFacet.js b/server/sonar-web/src/main/js/apps/issues/sidebar/StatusFacet.js index 3ca01cf3c09..c2bc9188681 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/StatusFacet.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/StatusFacet.js @@ -27,6 +27,7 @@ import FacetItemsList from '../../../components/facet/FacetItemsList'; import { translate } from '../../../helpers/l10n'; import { formatFacetStat } from '../utils'; +/*:: type Props = {| facetMode: string, onChange: (changes: { [string]: Array<string> }) => void, @@ -35,9 +36,10 @@ type Props = {| stats?: { [string]: number }, statuses: Array<string> |}; +*/ export default class StatusFacet extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { open: true @@ -45,7 +47,7 @@ export default class StatusFacet extends React.PureComponent { property = 'statuses'; - handleItemClick = (itemValue: string) => { + handleItemClick = (itemValue /*: string */) => { const { statuses } = this.props; const newValue = orderBy( statuses.includes(itemValue) ? without(statuses, itemValue) : [...statuses, itemValue] @@ -61,12 +63,12 @@ export default class StatusFacet extends React.PureComponent { this.props.onChange({ [this.property]: [] }); }; - getStat(status: string): ?number { + getStat(status /*: string */) /*: ?number */ { const { stats } = this.props; return stats ? stats[status] : null; } - renderStatus(status: string) { + renderStatus(status /*: string */) { return ( <span> <i className={`icon-status-${status.toLowerCase()}`} /> {translate('issue.status', status)} @@ -74,7 +76,7 @@ export default class StatusFacet extends React.PureComponent { ); } - renderItem = (status: string) => { + renderItem = (status /*: string */) => { const active = this.props.statuses.includes(status); const stat = this.getStat(status); diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/TagFacet.js b/server/sonar-web/src/main/js/apps/issues/sidebar/TagFacet.js index f4f210c2ea6..3cd3c174c92 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/TagFacet.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/TagFacet.js @@ -27,9 +27,10 @@ import FacetItemsList from '../../../components/facet/FacetItemsList'; import FacetFooter from '../../../components/facet/FacetFooter'; import { searchIssueTags } from '../../../api/issues'; import { translate } from '../../../helpers/l10n'; -import type { Component } from '../utils'; +/*:: import type { Component } from '../utils'; */ import { formatFacetStat } from '../utils'; +/*:: type Props = {| component?: Component, facetMode: string, @@ -40,9 +41,10 @@ type Props = {| stats?: { [string]: number }, tags: Array<string> |}; +*/ export default class TagFacet extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { open: true @@ -50,7 +52,7 @@ export default class TagFacet extends React.PureComponent { property = 'tags'; - handleItemClick = (itemValue: string) => { + handleItemClick = (itemValue /*: string */) => { const { tags } = this.props; const newValue = sortBy( tags.includes(itemValue) ? without(tags, itemValue) : [...tags, itemValue] @@ -66,7 +68,7 @@ export default class TagFacet extends React.PureComponent { this.props.onChange({ [this.property]: [] }); }; - handleSearch = (query: string) => { + handleSearch = (query /*: string */) => { let organization = this.props.component && this.props.component.organization; if (this.props.organization && !organization) { organization = this.props.organization.key; @@ -76,17 +78,17 @@ export default class TagFacet extends React.PureComponent { ); }; - handleSelect = (tag: string) => { + handleSelect = (tag /*: string */) => { const { tags } = this.props; this.props.onChange({ [this.property]: uniq([...tags, tag]) }); }; - getStat(tag: string): ?number { + getStat(tag /*: string */) /*: ?number */ { const { stats } = this.props; return stats ? stats[tag] : null; } - renderTag(tag: string) { + renderTag(tag /*: string */) { return ( <span> <i className="icon-tags icon-gray little-spacer-right" /> diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/TypeFacet.js b/server/sonar-web/src/main/js/apps/issues/sidebar/TypeFacet.js index 92eb4914359..b0099e1e19b 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/TypeFacet.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/TypeFacet.js @@ -28,6 +28,7 @@ import IssueTypeIcon from '../../../components/ui/IssueTypeIcon'; import { translate } from '../../../helpers/l10n'; import { formatFacetStat } from '../utils'; +/*:: type Props = {| facetMode: string, onChange: (changes: { [string]: Array<string> }) => void, @@ -36,9 +37,10 @@ type Props = {| stats?: { [string]: number }, types: Array<string> |}; +*/ export default class TypeFacet extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { open: true @@ -46,7 +48,7 @@ export default class TypeFacet extends React.PureComponent { property = 'types'; - handleItemClick = (itemValue: string) => { + handleItemClick = (itemValue /*: string */) => { const { types } = this.props; const newValue = orderBy( types.includes(itemValue) ? without(types, itemValue) : [...types, itemValue] @@ -62,12 +64,12 @@ export default class TypeFacet extends React.PureComponent { this.props.onChange({ [this.property]: [] }); }; - getStat(type: string): ?number { + getStat(type /*: string */) /*: ?number */ { const { stats } = this.props; return stats ? stats[type] : null; } - renderItem = (type: string) => { + renderItem = (type /*: string */) => { const active = this.props.types.includes(type); const stat = this.getStat(type); diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AssigneeFacet-test.js b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AssigneeFacet-test.js index 2ce4f76254c..9bd376753f4 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AssigneeFacet-test.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AssigneeFacet-test.js @@ -23,7 +23,7 @@ import AssigneeFacet from '../AssigneeFacet'; jest.mock('../../../../store/rootReducer', () => ({})); -const renderAssigneeFacet = (props?: {}) => +const renderAssigneeFacet = (props /*: ?{} */) => shallow( <AssigneeFacet assigned={true} diff --git a/server/sonar-web/src/main/js/apps/issues/utils.js b/server/sonar-web/src/main/js/apps/issues/utils.js index adf2d8aba6e..e0532e1e814 100644 --- a/server/sonar-web/src/main/js/apps/issues/utils.js +++ b/server/sonar-web/src/main/js/apps/issues/utils.js @@ -31,8 +31,9 @@ import { serializeString, serializeStringArray } from '../../helpers/query'; -import type { RawQuery } from '../../helpers/query'; +/*:: import type { RawQuery } from '../../helpers/query'; */ +/*:: export type Query = {| assigned: boolean, assignees: Array<string>, @@ -58,47 +59,54 @@ export type Query = {| tags: Array<string>, types: Array<string> |}; +*/ +/*:: export type Paging = { pageIndex: number, pageSize: number, total: number }; +*/ // allow sorting by CREATION_DATE only -const parseAsSort = (sort: string): string => (sort === 'CREATION_DATE' ? 'CREATION_DATE' : ''); - -export const parseQuery = (query: RawQuery): Query => ({ - assigned: parseAsBoolean(query.assigned), - assignees: parseAsArray(query.assignees, parseAsString), - authors: parseAsArray(query.authors, parseAsString), - createdAfter: parseAsString(query.createdAfter), - createdAt: parseAsString(query.createdAt), - createdBefore: parseAsString(query.createdBefore), - createdInLast: parseAsString(query.createdInLast), - directories: parseAsArray(query.directories, parseAsString), - facetMode: parseAsFacetMode(query.facetMode), - files: parseAsArray(query.fileUuids, parseAsString), - issues: parseAsArray(query.issues, parseAsString), - languages: parseAsArray(query.languages, parseAsString), - modules: parseAsArray(query.moduleUuids, parseAsString), - projects: parseAsArray(query.projectUuids, parseAsString), - resolved: parseAsBoolean(query.resolved), - resolutions: parseAsArray(query.resolutions, parseAsString), - rules: parseAsArray(query.rules, parseAsString), - sort: parseAsSort(query.s), - severities: parseAsArray(query.severities, parseAsString), - sinceLeakPeriod: parseAsBoolean(query.sinceLeakPeriod, false), - statuses: parseAsArray(query.statuses, parseAsString), - tags: parseAsArray(query.tags, parseAsString), - types: parseAsArray(query.types, parseAsString) -}); - -export const getOpen = (query: RawQuery) => query.open; - -export const areMyIssuesSelected = (query: RawQuery): boolean => query.myIssues === 'true'; - -export const serializeQuery = (query: Query): RawQuery => { +const parseAsSort = (sort /*: string */) => (sort === 'CREATION_DATE' ? 'CREATION_DATE' : ''); + +export function parseQuery(query /*: RawQuery */) /*: Query */ { + return { + assigned: parseAsBoolean(query.assigned), + assignees: parseAsArray(query.assignees, parseAsString), + authors: parseAsArray(query.authors, parseAsString), + createdAfter: parseAsString(query.createdAfter), + createdAt: parseAsString(query.createdAt), + createdBefore: parseAsString(query.createdBefore), + createdInLast: parseAsString(query.createdInLast), + directories: parseAsArray(query.directories, parseAsString), + facetMode: parseAsFacetMode(query.facetMode), + files: parseAsArray(query.fileUuids, parseAsString), + issues: parseAsArray(query.issues, parseAsString), + languages: parseAsArray(query.languages, parseAsString), + modules: parseAsArray(query.moduleUuids, parseAsString), + projects: parseAsArray(query.projectUuids, parseAsString), + resolved: parseAsBoolean(query.resolved), + resolutions: parseAsArray(query.resolutions, parseAsString), + rules: parseAsArray(query.rules, parseAsString), + sort: parseAsSort(query.s), + severities: parseAsArray(query.severities, parseAsString), + sinceLeakPeriod: parseAsBoolean(query.sinceLeakPeriod, false), + statuses: parseAsArray(query.statuses, parseAsString), + tags: parseAsArray(query.tags, parseAsString), + types: parseAsArray(query.types, parseAsString) + }; +} + +export function getOpen(query /*: RawQuery */) /*: string */ { + return query.open; +} + +export const areMyIssuesSelected = (query /*: RawQuery */) => query.myIssues === 'true'; + +export function serializeQuery(query /*: Query */) /*: RawQuery */ { const filter = { assigned: query.assigned ? undefined : 'false', assignees: serializeStringArray(query.assignees), @@ -125,28 +133,32 @@ export const serializeQuery = (query: Query): RawQuery => { types: serializeStringArray(query.types) }; return cleanQuery(filter); -}; +} -export const areQueriesEqual = (a: RawQuery, b: RawQuery) => +export const areQueriesEqual = (a /*: RawQuery */, b /*: RawQuery */) => queriesEqual(parseQuery(a), parseQuery(b)); +/*:: type RawFacet = { property: string, values: Array<{ val: string, count: number }> }; +*/ +/*:: export type Facet = { [string]: number }; +*/ -export const mapFacet = (facet: string): string => { +export function mapFacet(facet /*: string */) /*: string */ { const propertyMapping = { files: 'fileUuids', modules: 'moduleUuids', projects: 'projectUuids' }; return propertyMapping[facet] || facet; -}; +} -export const parseFacets = (facets: Array<RawFacet>): { [string]: Facet } => { +export function parseFacets(facets /*: Array<RawFacet> */) /*: { [string]: Facet } */ { // for readability purpose const propertyMapping = { fileUuids: 'files', @@ -164,42 +176,52 @@ export const parseFacets = (facets: Array<RawFacet>): { [string]: Facet } => { result[finalProperty] = values; }); return result; -}; +} -export const formatFacetStat = (stat: ?number, mode: string): ?string => { +export function formatFacetStat(stat /*: ?number */, mode /*: string */) /*: string | void */ { if (stat != null) { return formatMeasure(stat, mode === 'effort' ? 'SHORT_WORK_DUR' : 'SHORT_INT'); } -}; +} +/*:: export type ReferencedComponent = { key: string, name: string, organization: string, path: string }; +*/ +/*:: export type ReferencedUser = { avatar: string, name: string }; +*/ +/*:: export type ReferencedLanguage = { name: string }; +*/ +/*:: export type Component = { key: string, name: string, organization: string, qualifier: string }; +*/ +/*:: export type CurrentUser = | { isLoggedIn: false } | { isLoggedIn: true, email?: string, login: string, name: string }; +*/ -export const searchAssignees = (query: string, organization?: string) => { +export const searchAssignees = (query /*: string */, organization /*: ?string */) => { return organization ? searchMembers({ organization, ps: 50, q: query }).then(response => response.users.map(user => ({ @@ -223,12 +245,12 @@ const LOCALSTORAGE_KEY = 'sonarqube.issues.default'; const LOCALSTORAGE_MY = 'my'; const LOCALSTORAGE_ALL = 'all'; -export const isMySet = (): boolean => { +export const isMySet = () => { const setting = window.localStorage.getItem(LOCALSTORAGE_KEY); return setting === LOCALSTORAGE_MY; }; -const save = (value: string) => { +const save = (value /*: string */) => { try { window.localStorage.setItem(LOCALSTORAGE_KEY, value); } catch (e) { @@ -237,5 +259,5 @@ const save = (value: string) => { } }; -export const saveMyIssues = (myIssues: boolean) => +export const saveMyIssues = (myIssues /*: boolean */) => save(myIssues ? LOCALSTORAGE_MY : LOCALSTORAGE_ALL); diff --git a/server/sonar-web/src/main/js/apps/organizations/actions.js b/server/sonar-web/src/main/js/apps/organizations/actions.js index d8401044cad..9050442d5e8 100644 --- a/server/sonar-web/src/main/js/apps/organizations/actions.js +++ b/server/sonar-web/src/main/js/apps/organizations/actions.js @@ -27,22 +27,24 @@ import { onFail } from '../../store/rootActions'; import { getOrganizationMembersState } from '../../store/rootReducer'; import { addGlobalSuccessMessage } from '../../store/globalMessages/duck'; import { translate, translateWithParameters } from '../../helpers/l10n'; -import type { Organization } from '../../store/organizations/duck'; -import type { Member } from '../../store/organizationsMembers/actions'; +/*:: import type { Organization } from '../../store/organizations/duck'; */ +/*:: import type { Member } from '../../store/organizationsMembers/actions'; */ const PAGE_SIZE = 50; -const onRejected = (dispatch: Function) => (error: Object) => { +const onRejected = (dispatch /*: Function */) => (error /*: Object */) => { onFail(dispatch)(error); return Promise.reject(); }; -const onMembersFail = (organization: string, dispatch: Function) => (error: Object) => { +const onMembersFail = (organization /*: string */, dispatch /*: Function */) => ( + error /*: Object */ +) => { onFail(dispatch)(error); dispatch(membersActions.updateState(organization, { loading: false })); }; -export const fetchOrganization = (key: string): Function => (dispatch: Function): Promise<*> => { +export const fetchOrganization = (key /*: string */) => (dispatch /*: Function */) => { const onFulfilled = ([organization, navigation]) => { if (organization) { const organizationWithPermissions = { ...organization, ...navigation }; @@ -56,16 +58,16 @@ export const fetchOrganization = (key: string): Function => (dispatch: Function) ); }; -export const fetchOrganizationGroups = (organization: string): Function => ( - dispatch: Function -): Promise<*> => { +export const fetchOrganizationGroups = (organization /*: string */) => ( + dispatch /*: Function */ +) => { return searchUsersGroups({ organization }).then(response => { dispatch(actions.receiveOrganizationGroups(organization, response.groups)); }, onFail(dispatch)); }; -export const createOrganization = (fields: {}): Function => (dispatch: Function): Promise<*> => { - const onFulfilled = (organization: Organization) => { +export const createOrganization = (fields /*: Object */) => (dispatch /*: Function */) => { + const onFulfilled = (organization /*: Organization */) => { dispatch(actions.createOrganization(organization)); dispatch( addGlobalSuccessMessage(translateWithParameters('organization.created', organization.name)) @@ -75,9 +77,9 @@ export const createOrganization = (fields: {}): Function => (dispatch: Function) return api.createOrganization(fields).then(onFulfilled, onRejected(dispatch)); }; -export const updateOrganization = (key: string, changes: {}): Function => ( - dispatch: Function -): Promise<*> => { +export const updateOrganization = (key /*: string */, changes /*: {} */) => ( + dispatch /*: Function */ +) => { const onFulfilled = () => { dispatch(actions.updateOrganization(key, changes)); dispatch(addGlobalSuccessMessage(translate('organization.updated'))); @@ -86,7 +88,7 @@ export const updateOrganization = (key: string, changes: {}): Function => ( return api.updateOrganization(key, changes).then(onFulfilled, onFail(dispatch)); }; -export const deleteOrganization = (key: string): Function => (dispatch: Function): Promise<*> => { +export const deleteOrganization = (key /*: string */) => (dispatch /*: Function */) => { const onFulfilled = () => { dispatch(actions.deleteOrganization(key)); dispatch(addGlobalSuccessMessage(translate('organization.deleted'))); @@ -96,14 +98,14 @@ export const deleteOrganization = (key: string): Function => (dispatch: Function }; const fetchMembers = ( - dispatch: Function, - receiveAction: Function, - key: string, - query?: string, - page?: number + dispatch /*: Function */, + receiveAction /*: Function */, + key /*: string */, + query /*: ?string */, + page /*: ?number */ ) => { dispatch(membersActions.updateState(key, { loading: true })); - const data: Object = { + const data /*: Object */ = { organization: key, ps: PAGE_SIZE }; @@ -125,12 +127,13 @@ const fetchMembers = ( }, onMembersFail(key, dispatch)); }; -export const fetchOrganizationMembers = (key: string, query?: string) => (dispatch: Function) => - fetchMembers(dispatch, membersActions.receiveMembers, key, query); +export const fetchOrganizationMembers = (key /*: string */, query /*: ?string */) => ( + dispatch /*: Function */ +) => fetchMembers(dispatch, membersActions.receiveMembers, key, query); -export const fetchMoreOrganizationMembers = (key: string, query?: string) => ( - dispatch: Function, - getState: Function +export const fetchMoreOrganizationMembers = (key /*: string */, query /*: ?string */) => ( + dispatch /*: Function */, + getState /*: Function */ ) => fetchMembers( dispatch, @@ -140,26 +143,32 @@ export const fetchMoreOrganizationMembers = (key: string, query?: string) => ( getOrganizationMembersState(getState(), key).pageIndex + 1 ); -export const addOrganizationMember = (key: string, member: Member) => (dispatch: Function) => { +export const addOrganizationMember = (key /*: string */, member /*: Member */) => ( + dispatch /*: Function */ +) => { return api .addMember({ login: member.login, organization: key }) .then(user => dispatch(membersActions.addMember(key, user)), onFail(dispatch)); }; -export const removeOrganizationMember = (key: string, member: Member) => (dispatch: Function) => { +export const removeOrganizationMember = (key /*: string */, member /*: Member */) => ( + dispatch /*: Function */ +) => { dispatch(membersActions.removeMember(key, member)); - return api.removeMember({ login: member.login, organization: key }).catch((error: Object) => { + return api.removeMember({ login: member.login, organization: key }).catch(( + error /*: Object */ + ) => { onFail(dispatch)(error); dispatch(membersActions.addMember(key, member)); }); }; export const updateOrganizationMemberGroups = ( - organization: Organization, - member: Member, - add: Array<string>, - remove: Array<string> -) => (dispatch: Function) => { + organization /*: Organization */, + member /*: Member */, + add /*: Array<string> */, + remove /*: Array<string> */ +) => (dispatch /*: Function */) => { dispatch( receiveUser({ ...member, diff --git a/server/sonar-web/src/main/js/apps/organizations/components/MembersList.js b/server/sonar-web/src/main/js/apps/organizations/components/MembersList.js index 1d70e46c067..ff31beaa424 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/MembersList.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/MembersList.js @@ -20,9 +20,10 @@ //@flow import React from 'react'; import MembersListItem from './MembersListItem'; -import type { Member } from '../../../store/organizationsMembers/actions'; -import type { Organization, OrgGroup } from '../../../store/organizations/duck'; +/*:: import type { Member } from '../../../store/organizationsMembers/actions'; */ +/*:: import type { Organization, OrgGroup } from '../../../store/organizations/duck'; */ +/*:: type Props = { members: Array<Member>, organizationGroups: Array<OrgGroup>, @@ -30,9 +31,10 @@ type Props = { removeMember: Member => void, updateMemberGroups: (member: Member, add: Array<string>, remove: Array<string>) => void }; +*/ export default class MembersList extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { return ( diff --git a/server/sonar-web/src/main/js/apps/organizations/components/MembersListHeader.js b/server/sonar-web/src/main/js/apps/organizations/components/MembersListHeader.js index 51e91986524..b2337ae8499 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/MembersListHeader.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/MembersListHeader.js @@ -23,13 +23,15 @@ import UsersSearch from '../../users/components/UsersSearch'; import { formatMeasure } from '../../../helpers/measures'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { handleSearch: (query?: string) => void, total?: number }; +*/ export default class MembersListHeader extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const { total } = this.props; diff --git a/server/sonar-web/src/main/js/apps/organizations/components/MembersListItem.js b/server/sonar-web/src/main/js/apps/organizations/components/MembersListItem.js index 3ee6a16d9de..9432c2ac707 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/MembersListItem.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/MembersListItem.js @@ -24,9 +24,10 @@ import { translateWithParameters } from '../../../helpers/l10n'; import { formatMeasure } from '../../../helpers/measures'; import RemoveMemberForm from './forms/RemoveMemberForm'; import ManageMemberGroupsForm from './forms/ManageMemberGroupsForm'; -import type { Member } from '../../../store/organizationsMembers/actions'; -import type { Organization, OrgGroup } from '../../../store/organizations/duck'; +/*:: import type { Member } from '../../../store/organizationsMembers/actions'; */ +/*:: import type { Organization, OrgGroup } from '../../../store/organizations/duck'; */ +/*:: type Props = { member: Member, organization: Organization, @@ -34,11 +35,12 @@ type Props = { removeMember: Member => void, updateMemberGroups: (member: Member, add: Array<string>, remove: Array<string>) => void }; +*/ -const AVATAR_SIZE: number = 36; +const AVATAR_SIZE /*: number */ = 36; export default class MembersListItem extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const { member, organization } = this.props; diff --git a/server/sonar-web/src/main/js/apps/organizations/components/MembersPageHeader.js b/server/sonar-web/src/main/js/apps/organizations/components/MembersPageHeader.js index b0c175f8b82..f664c395547 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/MembersPageHeader.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/MembersPageHeader.js @@ -20,14 +20,16 @@ //@flow import React from 'react'; +/*:: type Props = { loading: boolean, total?: number, children?: React.Element<*> }; +*/ export default class MembersPageHeader extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { return ( diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationAdmin.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationAdmin.js index 19fd1852e9a..a58a5315717 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationAdmin.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationAdmin.js @@ -24,10 +24,11 @@ import { getOrganizationByKey } from '../../../store/rootReducer'; import handleRequiredAuthorization from '../../../app/utils/handleRequiredAuthorization'; class OrganizationAdmin extends React.PureComponent { - props: { + /*:: props: { children?: React.Element<*>, organization: { canAdmin: boolean } }; +*/ componentDidMount() { this.checkPermissions(); diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationDelete.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationDelete.js index 0269d9640a9..78c7637a840 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationDelete.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationDelete.js @@ -28,7 +28,7 @@ import { getOrganizationByKey } from '../../../store/rootReducer'; import { deleteOrganization } from '../actions'; class OrganizationDelete extends React.PureComponent { - props: { + /*:: props: { organization: { key: string, name: string @@ -38,13 +38,14 @@ class OrganizationDelete extends React.PureComponent { }, deleteOrganization: string => Promise<*> }; +*/ state = { deleting: false, loading: false }; - handleSubmit = (e: Object) => { + handleSubmit = (e /*: Object */) => { e.preventDefault(); this.setState({ loading: true }); this.props.deleteOrganization(this.props.organization.key).then(() => { diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationEdit.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationEdit.js index 51c3494308e..1a406fa3109 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationEdit.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationEdit.js @@ -23,21 +23,23 @@ import Helmet from 'react-helmet'; import { connect } from 'react-redux'; import { debounce } from 'lodash'; import { translate } from '../../../helpers/l10n'; -import type { Organization } from '../../../store/organizations/duck'; +/*:: import type { Organization } from '../../../store/organizations/duck'; */ import { getOrganizationByKey } from '../../../store/rootReducer'; import { updateOrganization } from '../actions'; +/*:: type Props = { organization: Organization, updateOrganization: (string, Object) => Promise<*> }; +*/ class OrganizationEdit extends React.PureComponent { - mounted: boolean; + /*:: mounted: boolean; */ - props: Props; + /*:: props: Props; */ - state: { + /*:: state: { loading: boolean, avatar: string, avatarImage: string, @@ -45,8 +47,9 @@ class OrganizationEdit extends React.PureComponent { name: string, url: string }; +*/ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { loading: false, @@ -68,17 +71,17 @@ class OrganizationEdit extends React.PureComponent { this.mounted = false; } - 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 changes = { avatar: this.state.avatar, diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationFavoriteProjects.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationFavoriteProjects.js index 0707e5ae59d..ef55c9023d0 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationFavoriteProjects.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationFavoriteProjects.js @@ -22,7 +22,7 @@ import React from 'react'; import FavoriteProjectsContainer from '../../projects/components/FavoriteProjectsContainer'; export default class OrganizationFavoriteProjects extends React.PureComponent { - props: { + /*:: props: { children?: React.Element<*>, currentUser: { isLoggedIn: boolean }, location: Object, @@ -30,6 +30,7 @@ export default class OrganizationFavoriteProjects extends React.PureComponent { key: string } }; +*/ componentDidMount() { const html = document.querySelector('html'); diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationGroupCheckbox.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationGroupCheckbox.js index 4c831405c7a..71d5325d121 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationGroupCheckbox.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationGroupCheckbox.js @@ -20,18 +20,20 @@ //@flow import React from 'react'; import Checkbox from '../../../components/controls/Checkbox'; -import type { OrgGroup } from '../../../store/organizations/duck'; +/*:: import type { OrgGroup } from '../../../store/organizations/duck'; */ +/*:: type Props = { group: OrgGroup, checked: boolean, onCheck: (string, boolean) => void }; +*/ export default class OrganizationGroupCheckbox extends React.PureComponent { - props: Props; + /*:: props: Props; */ - onCheck = (checked: boolean) => { + onCheck = (checked /*: boolean */) => { const { group } = this.props; if (!group.default) { this.props.onCheck(group.name, checked); diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationGroups.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationGroups.js index 4f751110345..4d46eedb5b1 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationGroups.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationGroups.js @@ -24,12 +24,13 @@ import { connect } from 'react-redux'; import init from '../../groups/init'; import { getOrganizationByKey } from '../../../store/rootReducer'; import { translate } from '../../../helpers/l10n'; -import type { Organization } from '../../../store/organizations/duck'; +/*:: import type { Organization } from '../../../store/organizations/duck'; */ class OrganizationGroups extends React.PureComponent { - props: { + /*:: props: { organization: Organization }; +*/ componentDidMount() { init(this.refs.container, this.props.organization); diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationMembers.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationMembers.js index 71f7d3f9551..d6248f2579e 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationMembers.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationMembers.js @@ -26,9 +26,10 @@ import MembersList from './MembersList'; import AddMemberForm from './forms/AddMemberForm'; import ListFooter from '../../../components/controls/ListFooter'; import { translate } from '../../../helpers/l10n'; -import type { Organization, OrgGroup } from '../../../store/organizations/duck'; -import type { Member } from '../../../store/organizationsMembers/actions'; +/*:: import type { Organization, OrgGroup } from '../../../store/organizations/duck'; */ +/*:: import type { Member } from '../../../store/organizationsMembers/actions'; */ +/*:: type Props = { members: Array<Member>, memberLogins: Array<string>, @@ -47,9 +48,10 @@ type Props = { remove: Array<string> ) => void }; +*/ export default class OrganizationMembers extends React.PureComponent { - props: Props; + /*:: props: Props; */ componentDidMount() { this.handleSearchMembers(); @@ -58,7 +60,7 @@ export default class OrganizationMembers extends React.PureComponent { } } - handleSearchMembers = (query?: string) => { + handleSearchMembers = (query /*: string | void */) => { this.props.fetchOrganizationMembers(this.props.organization.key, query); }; @@ -66,15 +68,19 @@ export default class OrganizationMembers extends React.PureComponent { this.props.fetchMoreOrganizationMembers(this.props.organization.key, this.props.status.query); }; - addMember = (member: Member) => { + addMember = (member /*: Member */) => { this.props.addOrganizationMember(this.props.organization.key, member); }; - removeMember = (member: Member) => { + removeMember = (member /*: Member */) => { this.props.removeOrganizationMember(this.props.organization.key, member); }; - updateMemberGroups = (member: Member, add: Array<string>, remove: Array<string>) => { + updateMemberGroups = ( + member /*: Member */, + add /*: Array<string> */, + remove /*: Array<string> */ + ) => { this.props.updateOrganizationMemberGroups(this.props.organization, member, add, remove); }; diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPage.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPage.js index de6ded0a88b..4c10db34e07 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPage.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPage.js @@ -25,12 +25,15 @@ import OrganizationNavigation from '../navigation/OrganizationNavigation'; import NotFound from '../../../app/components/NotFound'; import { fetchOrganization } from '../actions'; import { getOrganizationByKey } from '../../../store/rootReducer'; -import type { Organization } from '../../../store/organizations/duck'; +/*:: import type { Organization } from '../../../store/organizations/duck'; */ +/*:: type OwnProps = { params: { organizationKey: string } }; +*/ +/*:: type Props = { children?: React.Element<*>, location: Object, @@ -38,22 +41,25 @@ type Props = { params: { organizationKey: string }, fetchOrganization: string => Promise<*> }; +*/ +/*:: type State = { loading: boolean }; +*/ class OrganizationPage extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { loading: true }; + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { loading: true }; componentDidMount() { this.mounted = true; this.updateOrganization(this.props.params.organizationKey); } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if (nextProps.params.organizationKey !== this.props.params.organizationKey) { this.updateOrganization(nextProps.params.organizationKey); } @@ -63,7 +69,7 @@ class OrganizationPage extends React.PureComponent { this.mounted = false; } - updateOrganization = (organizationKey: string) => { + updateOrganization = (organizationKey /*: string */) => { if (this.mounted) { this.setState({ loading: true }); } @@ -95,7 +101,7 @@ class OrganizationPage extends React.PureComponent { } } -const mapStateToProps = (state, ownProps: OwnProps) => ({ +const mapStateToProps = (state, ownProps /*: OwnProps */) => ({ organization: getOrganizationByKey(state, ownProps.params.organizationKey) }); diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissionTemplates.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissionTemplates.js index f00469c5ebd..201c72151be 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissionTemplates.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissionTemplates.js @@ -22,14 +22,16 @@ import React from 'react'; import { connect } from 'react-redux'; import AppContainer from '../../permission-templates/components/AppContainer'; import { getOrganizationByKey } from '../../../store/rootReducer'; -import type { Organization } from '../../../store/organizations/duck'; +/*:: import type { Organization } from '../../../store/organizations/duck'; */ +/*:: type Props = { location: {}, organization: Organization }; +*/ -function OrganizationPermissionTemplates(props: Props) { +function OrganizationPermissionTemplates(props /*: Props */) { return <AppContainer location={props.location} organization={props.organization} />; } diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.js index e78bad3db9b..cab087b3e55 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.js @@ -22,13 +22,15 @@ import React from 'react'; import { connect } from 'react-redux'; import GlobalPermissionsApp from '../../permissions/global/components/App'; import { getOrganizationByKey } from '../../../store/rootReducer'; -import type { Organization } from '../../../store/organizations/duck'; +/*:: import type { Organization } from '../../../store/organizations/duck'; */ +/*:: type Props = { organization: Organization }; +*/ -function OrganizationPermissions(props: Props) { +function OrganizationPermissions(props /*: Props */) { return <GlobalPermissionsApp organization={props.organization} />; } diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationProjects.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationProjects.js index cf16b4fe52f..a9ef3fca16f 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationProjects.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationProjects.js @@ -22,7 +22,7 @@ import React from 'react'; import AllProjectsContainer from '../../projects/components/AllProjectsContainer'; export default class OrganizationProjects extends React.PureComponent { - props: { + /*:: props: { children?: React.Element<*>, currentUser: { isLoggedIn: boolean }, location: Object, @@ -30,6 +30,7 @@ export default class OrganizationProjects extends React.PureComponent { key: string } }; +*/ componentDidMount() { const html = document.querySelector('html'); diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationProjectsManagement.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationProjectsManagement.js index ef06e033d86..8222ab2df1c 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationProjectsManagement.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationProjectsManagement.js @@ -22,13 +22,15 @@ import React from 'react'; import { connect } from 'react-redux'; import AppContainer from '../../projects-admin/AppContainer'; import { getOrganizationByKey } from '../../../store/rootReducer'; -import type { Organization } from '../../../store/organizations/duck'; +/*:: import type { Organization } from '../../../store/organizations/duck'; */ +/*:: type Props = { organization: Organization }; +*/ -function OrganizationProjectsManagement(props: Props) { +function OrganizationProjectsManagement(props /*: Props */) { return <AppContainer organization={props.organization} />; } diff --git a/server/sonar-web/src/main/js/apps/organizations/components/forms/AddMemberForm.js b/server/sonar-web/src/main/js/apps/organizations/components/forms/AddMemberForm.js index d31c8fa4581..4e7720037a9 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/forms/AddMemberForm.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/forms/AddMemberForm.js @@ -23,24 +23,28 @@ import Modal from 'react-modal'; import UsersSelectSearch from '../../../users/components/UsersSelectSearch'; import { searchMembers } from '../../../../api/organizations'; import { translate } from '../../../../helpers/l10n'; -import type { Organization } from '../../../../store/organizations/duck'; -import type { Member } from '../../../../store/organizationsMembers/actions'; +/*:: import type { Organization } from '../../../../store/organizations/duck'; */ +/*:: import type { Member } from '../../../../store/organizationsMembers/actions'; */ +/*:: type Props = { addMember: (member: Member) => void, organization: Organization, memberLogins: Array<string> }; +*/ +/*:: type State = { open: boolean, selectedMember?: Member }; +*/ export default class AddMemberForm extends React.PureComponent { - props: Props; + /*:: props: Props; */ - state: State = { + state /*: State */ = { open: false }; @@ -52,7 +56,7 @@ export default class AddMemberForm extends React.PureComponent { this.setState({ open: false, selectedMember: undefined }); }; - handleSearch = (query?: string, ps: number): Promise<*> => { + handleSearch = (query /*: ?string */, ps /*: number */) => { const data = { organization: this.props.organization.key, ps, selected: 'deselected' }; if (!query) { return searchMembers(data); @@ -60,7 +64,7 @@ export default class AddMemberForm extends React.PureComponent { return searchMembers({ ...data, q: query }); }; - handleSubmit = (e: Object) => { + handleSubmit = (e /*: Object */) => { e.preventDefault(); if (this.state.selectedMember) { this.props.addMember(this.state.selectedMember); @@ -68,7 +72,7 @@ export default class AddMemberForm extends React.PureComponent { } }; - selectedMemberChange = (member: Member) => { + selectedMemberChange = (member /*: Member */) => { this.setState({ selectedMember: member }); }; diff --git a/server/sonar-web/src/main/js/apps/organizations/components/forms/ManageMemberGroupsForm.js b/server/sonar-web/src/main/js/apps/organizations/components/forms/ManageMemberGroupsForm.js index f04c903173e..7ff2d49fb2d 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/forms/ManageMemberGroupsForm.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/forms/ManageMemberGroupsForm.js @@ -24,30 +24,34 @@ import { keyBy, pickBy } from 'lodash'; import { getUserGroups } from '../../../../api/users'; import { translate, translateWithParameters } from '../../../../helpers/l10n'; import OrganizationGroupCheckbox from '../OrganizationGroupCheckbox'; -import type { Member } from '../../../../store/organizationsMembers/actions'; -import type { Organization, OrgGroup } from '../../../../store/organizations/duck'; +/*:: import type { Member } from '../../../../store/organizationsMembers/actions'; */ +/*:: import type { Organization, OrgGroup } from '../../../../store/organizations/duck'; */ +/*:: type Props = { member: Member, organization: Organization, organizationGroups: Array<OrgGroup>, updateMemberGroups: (member: Member, add: Array<string>, remove: Array<string>) => void }; +*/ +/*:: type State = { open: boolean, userGroups?: {}, loading?: boolean }; +*/ export default class ManageMemberGroupsForm extends React.PureComponent { - props: Props; + /*:: props: Props; */ - state: State = { + state /*: State */ = { open: false }; - openForm = (evt: MouseEvent) => { + openForm = (evt /*: MouseEvent */) => { evt.preventDefault(); this.loadUserGroups(); this.setState({ open: true }); @@ -64,7 +68,7 @@ export default class ManageMemberGroupsForm extends React.PureComponent { }); }; - isGroupSelected = (groupName: string) => { + isGroupSelected = (groupName /*: string */) => { if (this.state.userGroups) { const group = this.state.userGroups[groupName] || {}; if (group.status) { @@ -76,8 +80,8 @@ export default class ManageMemberGroupsForm extends React.PureComponent { return false; }; - onCheck = (groupName: string, checked: boolean) => { - this.setState((prevState: State) => { + onCheck = (groupName /*: string */, checked /*: boolean */) => { + this.setState((prevState /*: State */) => { const userGroups = prevState.userGroups || {}; const group = userGroups[groupName] || {}; let status = ''; @@ -90,7 +94,7 @@ export default class ManageMemberGroupsForm extends React.PureComponent { }); }; - handleSubmit = (e: Object) => { + handleSubmit = (e /*: Object */) => { e.preventDefault(); this.props.updateMemberGroups( this.props.member, diff --git a/server/sonar-web/src/main/js/apps/organizations/components/forms/RemoveMemberForm.js b/server/sonar-web/src/main/js/apps/organizations/components/forms/RemoveMemberForm.js index 02eb6e6848f..3adb1be7f8c 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/forms/RemoveMemberForm.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/forms/RemoveMemberForm.js @@ -21,27 +21,31 @@ import React from 'react'; import Modal from 'react-modal'; import { translate, translateWithParameters } from '../../../../helpers/l10n'; -import type { Member } from '../../../../store/organizationsMembers/actions'; -import type { Organization } from '../../../../store/organizations/duck'; +/*:: import type { Member } from '../../../../store/organizationsMembers/actions'; */ +/*:: import type { Organization } from '../../../../store/organizations/duck'; */ +/*:: type Props = { member: Member, organization: Organization, removeMember: (member: Member) => void }; +*/ +/*:: type State = { open: boolean }; +*/ export default class RemoveMemberForm extends React.PureComponent { - props: Props; + /*:: props: Props; */ - state: State = { + state /*: State */ = { open: false }; - openForm = (evt: MouseEvent) => { + openForm = (evt /*: MouseEvent */) => { evt.preventDefault(); this.setState({ open: true }); }; @@ -50,7 +54,7 @@ export default class RemoveMemberForm extends React.PureComponent { this.setState({ open: false }); }; - handleSubmit = (e: Object) => { + handleSubmit = (e /*: Object */) => { e.preventDefault(); this.props.removeMember(this.props.member); this.closeForm(); diff --git a/server/sonar-web/src/main/js/apps/organizations/forSingleOrganization.js b/server/sonar-web/src/main/js/apps/organizations/forSingleOrganization.js index 5936b86e244..fc2d996baed 100644 --- a/server/sonar-web/src/main/js/apps/organizations/forSingleOrganization.js +++ b/server/sonar-web/src/main/js/apps/organizations/forSingleOrganization.js @@ -23,7 +23,7 @@ import { connect } from 'react-redux'; import { withRouter } from 'react-router'; import { areThereCustomOrganizations } from '../../store/rootReducer'; -const forSingleOrganization = (ComposedComponent: Object) => { +const forSingleOrganization = (ComposedComponent /*: Object */) => { class X extends React.PureComponent { static displayName = `forSingleOrganization(${ComposedComponent.displayName})}`; diff --git a/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.js b/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.js index 382ea88ac87..08732baa04d 100644 --- a/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.js +++ b/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.js @@ -26,7 +26,7 @@ import ContextNavBar from '../../../components/nav/ContextNavBar'; import NavBarTabs from '../../../components/nav/NavBarTabs'; import OrganizationIcon from '../../../components/icons-components/OrganizationIcon'; import { getQualityGatesUrl } from '../../../helpers/urls'; -import type { Organization } from '../../../store/organizations/duck'; +/*:: import type { Organization } from '../../../store/organizations/duck'; */ const ADMIN_PATHS = [ 'edit', @@ -38,12 +38,13 @@ const ADMIN_PATHS = [ ]; export default class OrganizationNavigation extends React.PureComponent { - props: { + /*:: props: { location: { pathname: string }, organization: Organization }; +*/ - renderAdministration(adminActive: boolean) { + renderAdministration(adminActive /*: boolean */) { const { organization } = this.props; return ( @@ -101,7 +102,7 @@ export default class OrganizationNavigation extends React.PureComponent { return extensions.map(this.renderExtension); } - renderExtension = (extension: { key: string, name: string }) => { + renderExtension = (extension /*: { key: string, name: string } */) => { const { organization } = this.props; const pathname = `/organizations/${organization.key}/extension/${extension.key}`; return ( @@ -113,7 +114,7 @@ export default class OrganizationNavigation extends React.PureComponent { ); }; - renderExtensions(moreActive: boolean) { + renderExtensions(moreActive /*: boolean */) { const extensions = this.props.organization.pages || []; if (extensions.length > 0) { return ( diff --git a/server/sonar-web/src/main/js/apps/overview/components/App.js b/server/sonar-web/src/main/js/apps/overview/components/App.js index 32cf004a8ce..37e04ee3742 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/App.js +++ b/server/sonar-web/src/main/js/apps/overview/components/App.js @@ -24,6 +24,7 @@ import OverviewApp from './OverviewApp'; import EmptyOverview from './EmptyOverview'; import SourceViewer from '../../../components/SourceViewer/SourceViewer'; +/*:: type Props = { component: { analysisDate?: string, @@ -34,10 +35,11 @@ type Props = { }, router: Object }; +*/ export default class App extends React.PureComponent { - props: Props; - state: Object; + /*:: props: Props; */ + /*:: state: Object; */ static contextTypes = { router: PropTypes.object diff --git a/server/sonar-web/src/main/js/apps/overview/components/ApplicationLeakPeriodLegend.js b/server/sonar-web/src/main/js/apps/overview/components/ApplicationLeakPeriodLegend.js index 3b43a02e39f..3c9785aa8be 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/ApplicationLeakPeriodLegend.js +++ b/server/sonar-web/src/main/js/apps/overview/components/ApplicationLeakPeriodLegend.js @@ -24,18 +24,22 @@ import FormattedDate from '../../../components/ui/FormattedDate'; import { getApplicationLeak } from '../../../api/application'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { component: { key: string } }; +*/ +/*:: type State = { leaks: ?Array<{ date: string, project: string, projectName: string }> }; +*/ export default class ApplicationLeakPeriodLegend extends React.Component { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { leaks: null }; @@ -43,7 +47,7 @@ export default class ApplicationLeakPeriodLegend extends React.Component { this.mounted = true; } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if (nextProps.component.key !== this.props.component.key) { this.setState({ leaks: null }); } @@ -53,7 +57,7 @@ export default class ApplicationLeakPeriodLegend extends React.Component { this.mounted = false; } - fetchLeaks = (visible: boolean) => { + fetchLeaks = (visible /*: boolean */) => { if (visible && this.state.leaks == null) { getApplicationLeak(this.props.component.key).then( leaks => { diff --git a/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.js b/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.js index 3b5037fdb09..014194440b3 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.js +++ b/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.js @@ -22,11 +22,13 @@ import React from 'react'; import { Link } from 'react-router'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { component: { key: string } }; +*/ -export default function EmptyOverview({ component }: Props) { +export default function EmptyOverview({ component } /*: Props */) { const rawMessage = translate('provisioning.no_analysis.delete'); const head = rawMessage.substr(0, rawMessage.indexOf('{0}')); const tail = rawMessage.substr(rawMessage.indexOf('{0}') + 3); diff --git a/server/sonar-web/src/main/js/apps/overview/components/LeakPeriodLegend.js b/server/sonar-web/src/main/js/apps/overview/components/LeakPeriodLegend.js index 6d3f53657ef..88d26edef84 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/LeakPeriodLegend.js +++ b/server/sonar-web/src/main/js/apps/overview/components/LeakPeriodLegend.js @@ -24,42 +24,53 @@ import Tooltip from '../../../components/controls/Tooltip'; import { getPeriodDate, getPeriodLabel } from '../../../helpers/periods'; import { translateWithParameters } from '../../../helpers/l10n'; +/*:: type DaysPeriod = { date: string, mode: 'days', parameter: string }; +*/ +/*:: type DatePeriod = { date: string, mode: 'date', parameter: string }; +*/ +/*:: type VersionPeriod = { date: string, mode: 'version', parameter: string }; +*/ +/*:: type PreviousAnalysisPeriod = { date: string, mode: 'previous_analysis' }; +*/ +/*:: type PreviousVersionPeriod = { date: string, mode: 'previous_version' }; +*/ +/*:: type Period = | DaysPeriod | DatePeriod | VersionPeriod | PreviousAnalysisPeriod - | PreviousVersionPeriod; + | PreviousVersionPeriod; */ -export default function LeakPeriodLegend({ period }: { period: Period }) { +export default function LeakPeriodLegend({ period } /*: { period: Period } */) { const leakPeriodLabel = getPeriodLabel(period); if (period.mode === 'days') { diff --git a/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js b/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js index aea20cf3d40..dc43acba02c 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js +++ b/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js @@ -36,13 +36,16 @@ import { getLeakPeriod } from '../../../helpers/periods'; import { getCustomGraph, getGraph } from '../../../helpers/storage'; import { METRICS, HISTORY_METRICS_LIST } from '../utils'; import { DEFAULT_GRAPH, getDisplayedHistoryMetrics } from '../../projectActivity/utils'; -import type { Component, History, MeasuresList, Period } from '../types'; +/*:: import type { Component, History, MeasuresList, Period } from '../types'; */ import '../styles.css'; +/*:: type Props = { component: Component }; +*/ +/*:: type State = { history?: History, historyStartDate?: Date, @@ -50,11 +53,12 @@ type State = { measures: MeasuresList, periods?: Array<Period> }; +*/ export default class OverviewApp extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { loading: true, measures: [] }; @@ -68,7 +72,7 @@ export default class OverviewApp extends React.PureComponent { this.loadMeasures(this.props.component.key).then(() => this.loadHistory(this.props.component)); } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if (this.props.component.key !== prevProps.component.key) { this.loadMeasures(this.props.component.key).then(() => this.loadHistory(this.props.component) @@ -84,7 +88,7 @@ export default class OverviewApp extends React.PureComponent { } } - loadMeasures(componentKey: string) { + loadMeasures(componentKey /*: string */) { this.setState({ loading: true }); return getMeasuresAndMeta(componentKey, METRICS, { @@ -100,7 +104,7 @@ export default class OverviewApp extends React.PureComponent { }, throwGlobalError); } - loadHistory(component: Component) { + loadHistory(component /*: Component */) { let graphMetrics = getDisplayedHistoryMetrics(getGraph(), getCustomGraph()); if (!graphMetrics || graphMetrics.length <= 0) { graphMetrics = getDisplayedHistoryMetrics(DEFAULT_GRAPH, []); @@ -109,7 +113,7 @@ export default class OverviewApp extends React.PureComponent { const metrics = uniq(HISTORY_METRICS_LIST.concat(graphMetrics)); return getAllTimeMachineData(component.key, metrics).then(r => { if (this.mounted) { - const history: History = {}; + const history /*: History */ = {}; r.measures.forEach(measure => { const measureHistory = measure.history.map(analysis => ({ date: moment(analysis.date).toDate(), diff --git a/server/sonar-web/src/main/js/apps/overview/events/AnalysesList.js b/server/sonar-web/src/main/js/apps/overview/events/AnalysesList.js index 5e6004a3aae..e3549293bfd 100644 --- a/server/sonar-web/src/main/js/apps/overview/events/AnalysesList.js +++ b/server/sonar-web/src/main/js/apps/overview/events/AnalysesList.js @@ -25,35 +25,39 @@ import PreviewGraph from './PreviewGraph'; import { getMetrics } from '../../../api/metrics'; import { getProjectActivity } from '../../../api/projectActivity'; import { translate } from '../../../helpers/l10n'; -import type { Analysis as AnalysisType } from '../../projectActivity/types'; -import type { History, Metric } from '../types'; +/*:: import type { Analysis as AnalysisType } from '../../projectActivity/types'; */ +/*:: import type { History, Metric } from '../types'; */ +/*:: type Props = { history: ?History, project: string, qualifier: string, router: { push: ({ pathname: string, query?: {} }) => void } }; +*/ +/*:: type State = { analyses: Array<AnalysisType>, loading: boolean, metrics: Array<Metric> }; +*/ const PAGE_SIZE = 3; export default class AnalysesList extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { analyses: [], loading: true, metrics: [] }; + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { analyses: [], loading: true, metrics: [] }; componentDidMount() { this.mounted = true; this.fetchData(); } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if (prevProps.project !== this.props.project) { this.fetchData(); } @@ -75,7 +79,7 @@ export default class AnalysesList extends React.PureComponent { }); } - renderList(analyses: Array<AnalysisType>) { + renderList(analyses /*: Array<AnalysisType> */) { if (!analyses.length) { return ( <p className="spacer-top note"> diff --git a/server/sonar-web/src/main/js/apps/overview/events/Analysis.js b/server/sonar-web/src/main/js/apps/overview/events/Analysis.js index ccd0ac4df7d..ef1b6d37e8d 100644 --- a/server/sonar-web/src/main/js/apps/overview/events/Analysis.js +++ b/server/sonar-web/src/main/js/apps/overview/events/Analysis.js @@ -23,19 +23,21 @@ import { sortBy } from 'lodash'; import Event from './Event'; import FormattedDate from '../../../components/ui/FormattedDate'; import { translate } from '../../../helpers/l10n'; -import type { Analysis as AnalysisType, Event as EventType } from '../../projectActivity/types'; +/*:: import type { Analysis as AnalysisType, Event as EventType } from '../../projectActivity/types'; */ +/*:: type Props = { analysis: AnalysisType, qualifier: string }; +*/ -export default function Analysis(props: Props) { +export default function Analysis(props /*: Props */) { const { analysis } = props; - const sortedEvents: Array<EventType> = sortBy( + const sortedEvents /*: Array<EventType> */ = sortBy( analysis.events, // versions first - (event: EventType) => (event.category === 'VERSION' ? 0 : 1), + (event /*: EventType */) => (event.category === 'VERSION' ? 0 : 1), // then the rest sorted by category 'category' ); diff --git a/server/sonar-web/src/main/js/apps/overview/events/Event.js b/server/sonar-web/src/main/js/apps/overview/events/Event.js index 8c89d0ea62d..be23bc7bc07 100644 --- a/server/sonar-web/src/main/js/apps/overview/events/Event.js +++ b/server/sonar-web/src/main/js/apps/overview/events/Event.js @@ -20,10 +20,10 @@ // @flow import React from 'react'; import Tooltip from '../../../components/controls/Tooltip'; -import type { Event as EventType } from '../../projectActivity/types'; +/*:: import type { Event as EventType } from '../../projectActivity/types'; */ import { translate } from '../../../helpers/l10n'; -export default function Event(props: { event: EventType }) { +export default function Event(props /*: { event: EventType } */) { const { event } = props; if (event.category === 'VERSION') { diff --git a/server/sonar-web/src/main/js/apps/overview/events/PreviewGraph.js b/server/sonar-web/src/main/js/apps/overview/events/PreviewGraph.js index 56b92e0397d..03c890da665 100644 --- a/server/sonar-web/src/main/js/apps/overview/events/PreviewGraph.js +++ b/server/sonar-web/src/main/js/apps/overview/events/PreviewGraph.js @@ -34,16 +34,19 @@ import { import { getCustomGraph, getGraph } from '../../../helpers/storage'; import { formatMeasure, getShortType } from '../../../helpers/measures'; import { translate } from '../../../helpers/l10n'; -import type { Serie } from '../../../components/charts/AdvancedTimeline'; -import type { History, Metric } from '../types'; +/*:: import type { Serie } from '../../../components/charts/AdvancedTimeline'; */ +/*:: import type { History, Metric } from '../types'; */ +/*:: type Props = { history: ?History, metrics: Array<Metric>, project: string, router: { push: ({ pathname: string, query?: {} }) => void } }; +*/ +/*:: type State = { customMetrics: Array<string>, graph: string, @@ -52,16 +55,17 @@ type State = { tooltipIdx: ?number, tooltipXPos: ?number }; +*/ const GRAPH_PADDING = [4, 0, 4, 0]; const MAX_GRAPH_NB = 1; const MAX_SERIES_PER_GRAPH = 3; export default class PreviewGraph extends React.PureComponent { - props: Props; - state: State; + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); const graph = getGraph(); const customMetrics = getCustomGraph(); @@ -80,7 +84,7 @@ export default class PreviewGraph extends React.PureComponent { }; } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if (nextProps.history !== this.props.history || nextProps.metrics !== this.props.metrics) { const graph = getGraph(); const customMetrics = getCustomGraph(); @@ -97,11 +101,11 @@ export default class PreviewGraph extends React.PureComponent { } } - formatValue = (tick: number | string) => + formatValue = (tick /*: number | string */) => formatMeasure(tick, getShortType(getSeriesMetricType(this.state.series))); - getDisplayedMetrics = (graph: string, customMetrics: Array<string>): Array<string> => { - const metrics: Array<string> = getDisplayedHistoryMetrics(graph, customMetrics); + getDisplayedMetrics = (graph /*: string */, customMetrics /*: Array<string> */) => { + const metrics /*: Array<string> */ = getDisplayedHistoryMetrics(graph, customMetrics); if (!metrics || metrics.length <= 0) { return getDisplayedHistoryMetrics(DEFAULT_GRAPH, customMetrics); } @@ -109,11 +113,11 @@ export default class PreviewGraph extends React.PureComponent { }; getSeries = ( - history: ?History, - graph: string, - customMetrics: Array<string>, - metrics: Array<Metric> - ): Array<Serie> => { + history /*: ?History */, + graph /*: string */, + customMetrics /*: Array<string> */, + metrics /*: Array<Metric> */ + ) => { const myHistory = history; if (!myHistory) { return []; @@ -136,8 +140,11 @@ export default class PreviewGraph extends React.PureComponent { this.props.router.push({ pathname: '/project/activity', query: { id: this.props.project } }); }; - updateTooltip = (selectedDate: ?Date, tooltipXPos: ?number, tooltipIdx: ?number) => - this.setState({ selectedDate, tooltipXPos, tooltipIdx }); + updateTooltip = ( + selectedDate /*: ?Date */, + tooltipXPos /*: ?number */, + tooltipIdx /*: ?number */ + ) => this.setState({ selectedDate, tooltipXPos, tooltipIdx }); renderTimeline() { const { graph, selectedDate, series, tooltipIdx, tooltipXPos } = this.state; diff --git a/server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltips.js b/server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltips.js index 7c348aa5f20..d4bc3609a6d 100644 --- a/server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltips.js +++ b/server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltips.js @@ -21,9 +21,10 @@ import React from 'react'; import BubblePopup from '../../../components/common/BubblePopup'; import FormattedDate from '../../../components/ui/FormattedDate'; import PreviewGraphTooltipsContent from './PreviewGraphTooltipsContent'; -import type { Metric } from '../types'; -import type { Serie } from '../../../components/charts/AdvancedTimeline'; +/*:: import type { Metric } from '../types'; */ +/*:: import type { Serie } from '../../../components/charts/AdvancedTimeline'; */ +/*:: type Props = { formatValue: (number | string) => string, graph: string, @@ -34,11 +35,12 @@ type Props = { tooltipIdx: number, tooltipPos: number }; +*/ const TOOLTIP_WIDTH = 160; export default class PreviewGraphTooltips extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const { tooltipIdx } = this.props; diff --git a/server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltipsContent.js b/server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltipsContent.js index dfdab1902b5..31f38957d36 100644 --- a/server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltipsContent.js +++ b/server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltipsContent.js @@ -21,13 +21,15 @@ import React from 'react'; import ChartLegendIcon from '../../../components/icons-components/ChartLegendIcon'; +/*:: type Props = { style: string, translatedName: string, value: string }; +*/ -export default function PreviewGraphTooltipsContent({ style, translatedName, value }: Props) { +export default function PreviewGraphTooltipsContent({ style, translatedName, value } /*: Props */) { return ( <tr className="overview-analysis-graph-tooltip-line"> <td className="thin"> diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaLink.js b/server/sonar-web/src/main/js/apps/overview/meta/MetaLink.js index c777e17f7ca..569a28d75f0 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/MetaLink.js +++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaLink.js @@ -22,33 +22,38 @@ import React from 'react'; import { isProvided, isClickable } from '../../project-admin/links/utils'; import BugTrackerIcon from '../../../components/ui/BugTrackerIcon'; +/*:: type Link = { id: string, name: string, url: string, type: string }; +*/ +/*:: type State = {| expanded: boolean |}; +*/ export default class MetaLink extends React.PureComponent { - props: { + /*:: props: { link: Link }; +*/ - state: State = { + state /*: State */ = { expanded: false }; - handleClick = (e: Object) => { + handleClick = (e /*: Object */) => { e.preventDefault(); e.target.blur(); - this.setState((s: State): State => ({ expanded: !s.expanded })); + this.setState((s /*: State */) => ({ expanded: !s.expanded })); }; - renderLinkIcon(link: Link) { + renderLinkIcon(link /*: Link */) { if (link.type === 'issue') { return <BugTrackerIcon />; } diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaQualityProfiles.js b/server/sonar-web/src/main/js/apps/overview/meta/MetaQualityProfiles.js index d5762751007..648080544b0 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/MetaQualityProfiles.js +++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaQualityProfiles.js @@ -28,14 +28,15 @@ import { searchRules } from '../../../api/rules'; import { getLanguages } from '../../../store/rootReducer'; class MetaQualityProfiles extends React.PureComponent { - mounted: boolean; + /*:: mounted: boolean; */ - props: { + /*:: props: { component: { organization: string }, customOrganizations: boolean, languages: { [string]: { name: string } }, profiles: Array<{ key: string, language: string, name: string }> }; +*/ state = { deprecatedByKey: {} diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaTags.js b/server/sonar-web/src/main/js/apps/overview/meta/MetaTags.js index 6ae8f29baa7..b9d67b8e474 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/MetaTags.js +++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaTags.js @@ -23,6 +23,7 @@ import { translate } from '../../../helpers/l10n'; import TagsList from '../../../components/tags/TagsList'; import ProjectTagsSelectorContainer from '../../projects/components/ProjectTagsSelectorContainer'; +/*:: type Props = { component: { key: string, @@ -32,18 +33,21 @@ type Props = { } } }; +*/ +/*:: type State = { popupOpen: boolean, popupPosition: { top: number, right: number } }; +*/ export default class MetaTags extends React.PureComponent { - card: HTMLElement; - tagsList: HTMLElement; - tagsSelector: HTMLElement; - props: Props; - state: State = { + /*:: card: HTMLElement; */ + /*:: tagsList: HTMLElement; */ + /*:: tagsSelector: HTMLElement; */ + /*:: props: Props; */ + state /*: State */ = { popupOpen: false, popupPosition: { top: 0, @@ -67,20 +71,20 @@ export default class MetaTags extends React.PureComponent { window.removeEventListener('click', this.handleOutsideClick); } - handleKey = (evt: KeyboardEvent) => { + handleKey = (evt /*: KeyboardEvent */) => { // Escape key if (evt.keyCode === 27) { this.setState({ popupOpen: false }); } }; - handleOutsideClick = (evt: SyntheticInputEvent) => { + handleOutsideClick = (evt /*: SyntheticInputEvent */) => { if (!this.tagsSelector || !this.tagsSelector.contains(evt.target)) { this.setState({ popupOpen: false }); } }; - handleClick = (evt: MouseEvent) => { + handleClick = (evt /*: MouseEvent */) => { evt.stopPropagation(); this.setState(state => ({ popupOpen: !state.popupOpen })); }; @@ -90,7 +94,10 @@ export default class MetaTags extends React.PureComponent { return configuration && configuration.showSettings; } - getPopupPos(eltPos: { height: number, width: number }, containerPos: { width: number }) { + getPopupPos( + eltPos /*: { height: number, width: number } */, + containerPos /*: { width: number } */ + ) { return { top: eltPos.height, right: containerPos.width - eltPos.width diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/ApplicationQualityGate.js b/server/sonar-web/src/main/js/apps/overview/qualityGate/ApplicationQualityGate.js index 80229f4cc22..d91aaefa229 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/ApplicationQualityGate.js +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/ApplicationQualityGate.js @@ -25,10 +25,13 @@ import Level from '../../../components/ui/Level'; import { getApplicationQualityGate } from '../../../api/quality-gates'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { component: { key: string } }; +*/ +/*:: type State = { loading: boolean, metrics?: { [string]: Object }, @@ -40,11 +43,12 @@ type State = { }>, status?: string }; +*/ export default class ApplicationQualityGate extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { loading: true }; @@ -53,7 +57,7 @@ export default class ApplicationQualityGate extends React.PureComponent { this.fetchDetails(); } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if (prevProps.component.key !== this.props.component.key) { this.fetchDetails(); } diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/ApplicationQualityGateProject.js b/server/sonar-web/src/main/js/apps/overview/qualityGate/ApplicationQualityGateProject.js index 26f941e9d21..0a83760305b 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/ApplicationQualityGateProject.js +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/ApplicationQualityGateProject.js @@ -26,6 +26,7 @@ import { formatMeasure, isDiffMetric } from '../../../helpers/measures'; import { getProjectUrl } from '../../../helpers/urls'; import './ApplicationQualityGateProject.css'; +/*:: type Condition = { comparator: string, errorThreshold?: string, @@ -35,7 +36,9 @@ type Condition = { value: string, warningThreshold?: string }; +*/ +/*:: type Props = { metrics: { [string]: { @@ -51,11 +54,12 @@ type Props = { status: string } }; +*/ export default class ApplicationQualityGateProject extends React.PureComponent { - props: Props; + /*:: props: Props; */ - renderCondition = (condition: Condition) => { + renderCondition = (condition /*: Condition */) => { const metric = this.props.metrics[condition.metric]; const metricName = getLocalizedMetricName(metric); const threshold = condition.errorThreshold || condition.warningThreshold; diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.js b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.js index 5bfcb90b203..cb5795332f9 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.js +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.js @@ -23,22 +23,24 @@ import QualityGateConditions from './QualityGateConditions'; import EmptyQualityGate from './EmptyQualityGate'; import { translate } from '../../../helpers/l10n'; import Level from '../../../components/ui/Level'; -import type { Component, MeasuresList } from '../types'; +/*:: import type { Component, MeasuresList } from '../types'; */ -function parseQualityGateDetails(rawDetails: string) { +function parseQualityGateDetails(rawDetails /*: string */) { return JSON.parse(rawDetails); } -function isProject(component: Component) { +function isProject(component /*: Component */) { return component.qualifier === 'TRK'; } +/*:: type Props = { component: Component, measures: MeasuresList }; +*/ -export default function QualityGate({ component, measures }: Props) { +export default function QualityGate({ component, measures } /*: Props */) { const statusMeasure = measures.find(measure => measure.metric.key === 'alert_status'); const detailsMeasure = measures.find(measure => measure.metric.key === 'quality_gate_details'); diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.js b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.js index e00bb556764..66ea85d9289 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.js +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.js @@ -27,11 +27,11 @@ import IssueTypeIcon from '../../../components/ui/IssueTypeIcon'; import { getPeriodValue, isDiffMetric, formatMeasure } from '../../../helpers/measures'; import { translate } from '../../../helpers/l10n'; import { getComponentIssuesUrl } from '../../../helpers/urls'; -import type { Component } from '../types'; -import type { MeasureEnhanced } from '../../../components/measure/types'; +/*:: import type { Component } from '../types'; */ +/*:: import type { MeasureEnhanced } from '../../../components/measure/types'; */ export default class QualityGateCondition extends React.PureComponent { - props: { + /*:: props: { component: Component, condition: { level: string, @@ -42,8 +42,9 @@ export default class QualityGateCondition extends React.PureComponent { warning: string } }; +*/ - getDecimalsNumber(threshold: number, value: number): ?number { + getDecimalsNumber(threshold /*: number */, value /*: number */) /*: ?number */ { const delta = Math.abs(threshold - value); if (delta < 0.1 && delta > 0) { //$FlowFixMe The matching result can't be null because of the previous check @@ -51,8 +52,8 @@ export default class QualityGateCondition extends React.PureComponent { } } - getIssuesUrl(sinceLeakPeriod: boolean, customQuery: {}) { - const query: Object = { + getIssuesUrl(sinceLeakPeriod /*: boolean */, customQuery /*: {} */) { + const query /*: Object */ = { resolved: 'false', ...customQuery }; @@ -62,11 +63,11 @@ export default class QualityGateCondition extends React.PureComponent { return getComponentIssuesUrl(this.props.component.key, query); } - getUrlForCodeSmells(sinceLeakPeriod: boolean) { + getUrlForCodeSmells(sinceLeakPeriod /*: boolean */) { return this.getIssuesUrl(sinceLeakPeriod, { types: 'CODE_SMELL' }); } - getUrlForBugsOrVulnerabilities(type: string, sinceLeakPeriod: boolean) { + getUrlForBugsOrVulnerabilities(type /*: string */, sinceLeakPeriod /*: boolean */) { const RATING_TO_SEVERITIES_MAPPING = [ 'BLOCKER,CRITICAL,MAJOR,MINOR', 'BLOCKER,CRITICAL,MAJOR', @@ -83,13 +84,13 @@ export default class QualityGateCondition extends React.PureComponent { }); } - getUrlForType(type: string, sinceLeakPeriod: boolean) { + getUrlForType(type /*: string */, sinceLeakPeriod /*: boolean */) { return type === 'CODE_SMELL' ? this.getUrlForCodeSmells(sinceLeakPeriod) : this.getUrlForBugsOrVulnerabilities(type, sinceLeakPeriod); } - wrapWithLink(children: React.Element<*>) { + wrapWithLink(children /*: React.Element<*> */) { const { component, condition } = this.props; const className = classNames( diff --git a/server/sonar-web/src/main/js/apps/overview/types.js b/server/sonar-web/src/main/js/apps/overview/types.js index cde34fb2095..bc3c77aaea7 100644 --- a/server/sonar-web/src/main/js/apps/overview/types.js +++ b/server/sonar-web/src/main/js/apps/overview/types.js @@ -19,14 +19,19 @@ */ //@flow +/*:: export type Component = { id: string, key: string, qualifier: string }; +*/ +/*:: export type History = { [string]: Array<{ date: Date, value: string }> }; +*/ +/*:: export type Metric = { custom?: boolean, hidden?: boolean, @@ -34,18 +39,24 @@ export type Metric = { name: string, type: string }; +*/ +/*:: export type Measure = { metric: Metric, value?: string, periods?: Array<Period> }; +*/ +/*:: export type Period = { index: number, date: string, mode: string, parameter?: string }; +*/ -export type MeasuresList = Array<Measure>; +/*:: +export type MeasuresList = Array<Measure>; */ diff --git a/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.js b/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.js index 231992c4b73..f340d7e27c1 100644 --- a/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.js +++ b/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.js @@ -112,11 +112,13 @@ const mapStateToProps = state => ({ selectedPermission: getPermissionsAppSelectedPermission(state) }); +/*:: type OwnProps = { organization?: { key: string } }; +*/ -const mapDispatchToProps = (dispatch: Function, ownProps: OwnProps) => { +const mapDispatchToProps = (dispatch /*: Function */, ownProps /*: OwnProps */) => { const organizationKey = ownProps.organization ? ownProps.organization.key : undefined; return { loadHolders: () => dispatch(loadHolders(organizationKey)), diff --git a/server/sonar-web/src/main/js/apps/permissions/global/components/App.js b/server/sonar-web/src/main/js/apps/permissions/global/components/App.js index da906b66606..4b7ea9f15e1 100644 --- a/server/sonar-web/src/main/js/apps/permissions/global/components/App.js +++ b/server/sonar-web/src/main/js/apps/permissions/global/components/App.js @@ -26,7 +26,7 @@ import PageError from '../../shared/components/PageError'; import { translate } from '../../../../helpers/l10n'; import '../../styles.css'; -export default function App(props: { organization?: {} }) { +export default function App(props /*: { organization?: {} } */) { return ( <div className="page page-limited"> <Helmet title={translate('global_permissions.permission')} /> diff --git a/server/sonar-web/src/main/js/apps/permissions/global/components/PageHeader.js b/server/sonar-web/src/main/js/apps/permissions/global/components/PageHeader.js index 933fbb7421e..940c1cb731b 100644 --- a/server/sonar-web/src/main/js/apps/permissions/global/components/PageHeader.js +++ b/server/sonar-web/src/main/js/apps/permissions/global/components/PageHeader.js @@ -23,10 +23,11 @@ import { translate } from '../../../../helpers/l10n'; import { isPermissionsAppLoading } from '../../../../store/rootReducer'; class PageHeader extends React.PureComponent { - props: { + /*:: props: { loading?: boolean, organization?: {} }; +*/ static defaultProps = { loading: false diff --git a/server/sonar-web/src/main/js/apps/permissions/global/store/actions.js b/server/sonar-web/src/main/js/apps/permissions/global/store/actions.js index 19a153e8b4c..639097378a0 100644 --- a/server/sonar-web/src/main/js/apps/permissions/global/store/actions.js +++ b/server/sonar-web/src/main/js/apps/permissions/global/store/actions.js @@ -38,10 +38,17 @@ import { getPermissionsAppSelectedPermission } from '../../../../store/rootReducer'; +/*:: type Dispatch = Object => void; +*/ +/*:: type GetState = () => Object; +*/ -export const loadHolders = (organization?: string) => (dispatch: Dispatch, getState: GetState) => { +export const loadHolders = (organization /*: ?string */) => ( + dispatch /*: Dispatch */, + getState /*: GetState */ +) => { const query = getPermissionsAppQuery(getState()); const filter = getPermissionsAppFilter(getState()); const selectedPermission = getPermissionsAppSelectedPermission(getState()); @@ -76,21 +83,25 @@ export const loadHolders = (organization?: string) => (dispatch: Dispatch, getSt }); }; -export const updateQuery = (query: string = '', organization?: string) => (dispatch: Dispatch) => { +export const updateQuery = (query /*: string */ = '', organization /*: ?string */) => ( + dispatch /*: Dispatch */ +) => { dispatch({ type: UPDATE_QUERY, query }); if (query.length === 0 || query.length > 2) { dispatch(loadHolders(organization)); } }; -export const updateFilter = (filter: string, organization?: string) => (dispatch: Dispatch) => { +export const updateFilter = (filter /*: string */, organization /*: ?string */) => ( + dispatch /*: Dispatch */ +) => { dispatch({ type: UPDATE_FILTER, filter }); dispatch(loadHolders(organization)); }; -export const selectPermission = (permission: string, organization?: string) => ( - dispatch: Dispatch, - getState: GetState +export const selectPermission = (permission /*: string */, organization /*: ?string */) => ( + dispatch /*: Dispatch */, + getState /*: GetState */ ) => { const selectedPermission = getPermissionsAppSelectedPermission(getState()); if (selectedPermission !== permission) { @@ -101,9 +112,11 @@ export const selectPermission = (permission: string, organization?: string) => ( dispatch(loadHolders(organization)); }; -export const grantToUser = (login: string, permission: string, organization?: string) => ( - dispatch: Dispatch -) => { +export const grantToUser = ( + login /*: string */, + permission /*: string */, + organization /*: ?string */ +) => (dispatch /*: Dispatch */) => { api .grantPermissionToUser(null, login, permission, organization) .then(() => { @@ -114,9 +127,11 @@ export const grantToUser = (login: string, permission: string, organization?: st }); }; -export const revokeFromUser = (login: string, permission: string, organization?: string) => ( - dispatch: Dispatch -) => { +export const revokeFromUser = ( + login /*: string */, + permission /*: string */, + organization /*: ?string */ +) => (dispatch /*: Dispatch */) => { api .revokePermissionFromUser(null, login, permission, organization) .then(() => { @@ -127,9 +142,11 @@ export const revokeFromUser = (login: string, permission: string, organization?: }); }; -export const grantToGroup = (groupName: string, permission: string, organization?: string) => ( - dispatch: Dispatch -) => { +export const grantToGroup = ( + groupName /*: string */, + permission /*: string */, + organization /*: ?string */ +) => (dispatch /*: Dispatch */) => { api .grantPermissionToGroup(null, groupName, permission, organization) .then(() => { @@ -144,9 +161,11 @@ export const grantToGroup = (groupName: string, permission: string, organization }); }; -export const revokeFromGroup = (groupName: string, permission: string, organization?: string) => ( - dispatch: Dispatch -) => { +export const revokeFromGroup = ( + groupName /*: string */, + permission /*: string */, + organization /*: ?string */ +) => (dispatch /*: Dispatch */) => { api .revokePermissionFromGroup(null, groupName, permission, organization) .then(() => { diff --git a/server/sonar-web/src/main/js/apps/permissions/project/components/AllHoldersList.js b/server/sonar-web/src/main/js/apps/permissions/project/components/AllHoldersList.js index f91e5f9c39f..7cd6a7a54e0 100644 --- a/server/sonar-web/src/main/js/apps/permissions/project/components/AllHoldersList.js +++ b/server/sonar-web/src/main/js/apps/permissions/project/components/AllHoldersList.js @@ -25,6 +25,7 @@ import HoldersList from '../../shared/components/HoldersList'; import { translate } from '../../../../helpers/l10n'; import { PERMISSIONS_ORDER_BY_QUALIFIER } from '../constants'; +/*:: type Props = {| component: { configuration?: { @@ -57,11 +58,12 @@ type Props = {| permissions: Array<string> }> |}; +*/ export default class AllHoldersList extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleToggleUser = (user: Object, permission: string) => { + handleToggleUser = (user /*: Object */, permission /*: string */) => { const hasPermission = user.permissions.includes(permission); if (hasPermission) { @@ -71,7 +73,7 @@ export default class AllHoldersList extends React.PureComponent { } }; - handleToggleGroup = (group: Object, permission: string) => { + handleToggleGroup = (group /*: Object */, permission /*: string */) => { const hasPermission = group.permissions.includes(permission); if (hasPermission) { @@ -81,7 +83,7 @@ export default class AllHoldersList extends React.PureComponent { } }; - handleSelectPermission = (permission?: string) => { + handleSelectPermission = (permission /*: string | void */) => { this.props.onPermissionSelect(permission); }; diff --git a/server/sonar-web/src/main/js/apps/permissions/project/components/App.js b/server/sonar-web/src/main/js/apps/permissions/project/components/App.js index 13d1290f721..c3e2fd8f5aa 100644 --- a/server/sonar-web/src/main/js/apps/permissions/project/components/App.js +++ b/server/sonar-web/src/main/js/apps/permissions/project/components/App.js @@ -31,6 +31,7 @@ import * as api from '../../../../api/permissions'; import { translate } from '../../../../helpers/l10n'; import '../../styles.css'; +/*:: export type Props = {| component: { configuration?: { @@ -46,7 +47,9 @@ export type Props = {| onComponentChange: (changes: {}) => void, onRequestFail: Object => void |}; +*/ +/*:: export type State = {| disclaimer: boolean, filter: string, @@ -63,13 +66,14 @@ export type State = {| permissions: Array<string> }> |}; +*/ 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 = { disclaimer: false, @@ -139,13 +143,13 @@ export default class App extends React.PureComponent { } }; - handleFilterChange = (filter: string) => { + handleFilterChange = (filter /*: string */) => { if (this.mounted) { this.setState({ filter }, this.loadHolders); } }; - handleQueryChange = (query: string) => { + handleQueryChange = (query /*: string */) => { if (this.mounted) { this.setState({ query }, () => { if (query.length === 0 || query.length > 2) { @@ -155,10 +159,10 @@ export default class App extends React.PureComponent { } }; - handlePermissionSelect = (selectedPermission?: string) => { + handlePermissionSelect = (selectedPermission /*: ?string */) => { if (this.mounted) { this.setState( - (state: State) => ({ + (state /*: State */) => ({ selectedPermission: state.selectedPermission === selectedPermission ? undefined : selectedPermission }), @@ -167,7 +171,7 @@ export default class App extends React.PureComponent { } }; - addPermissionToGroup = (group: string, permission: string) => + addPermissionToGroup = (group /*: string */, permission /*: string */) => this.state.groups.map( candidate => candidate.name === group @@ -175,7 +179,7 @@ export default class App extends React.PureComponent { : candidate ); - addPermissionToUser = (user: string, permission: string) => + addPermissionToUser = (user /*: string */, permission /*: string */) => this.state.users.map( candidate => candidate.login === user @@ -183,7 +187,7 @@ export default class App extends React.PureComponent { : candidate ); - removePermissionFromGroup = (group: string, permission: string) => + removePermissionFromGroup = (group /*: string */, permission /*: string */) => this.state.groups.map( candidate => candidate.name === group @@ -191,7 +195,7 @@ export default class App extends React.PureComponent { : candidate ); - removePermissionFromUser = (user: string, permission: string) => + removePermissionFromUser = (user /*: string */, permission /*: string */) => this.state.users.map( candidate => candidate.login === user @@ -199,7 +203,7 @@ export default class App extends React.PureComponent { : candidate ); - grantPermissionToGroup = (group: string, permission: string) => { + grantPermissionToGroup = (group /*: string */, permission /*: string */) => { if (this.mounted) { this.setState({ loading: true, groups: this.addPermissionToGroup(group, permission) }); api @@ -221,7 +225,7 @@ export default class App extends React.PureComponent { } }; - grantPermissionToUser = (user: string, permission: string) => { + grantPermissionToUser = (user /*: string */, permission /*: string */) => { if (this.mounted) { this.setState({ loading: true, users: this.addPermissionToUser(user, permission) }); api @@ -243,7 +247,7 @@ export default class App extends React.PureComponent { } }; - revokePermissionFromGroup = (group: string, permission: string) => { + revokePermissionFromGroup = (group /*: string */, permission /*: string */) => { if (this.mounted) { this.setState({ loading: true, groups: this.removePermissionFromGroup(group, permission) }); api @@ -265,7 +269,7 @@ export default class App extends React.PureComponent { } }; - revokePermissionFromUser = (user: string, permission: string) => { + revokePermissionFromUser = (user /*: string */, permission /*: string */) => { if (this.mounted) { this.setState({ loading: true, users: this.removePermissionFromUser(user, permission) }); api @@ -287,7 +291,7 @@ export default class App extends React.PureComponent { } }; - handleVisibilityChange = (visibility: string) => { + handleVisibilityChange = (visibility /*: string */) => { if (visibility === 'public') { this.openDisclaimer(); } else { diff --git a/server/sonar-web/src/main/js/apps/permissions/project/components/PageHeader.js b/server/sonar-web/src/main/js/apps/permissions/project/components/PageHeader.js index 2cbe207fabb..62c5eff5ffb 100644 --- a/server/sonar-web/src/main/js/apps/permissions/project/components/PageHeader.js +++ b/server/sonar-web/src/main/js/apps/permissions/project/components/PageHeader.js @@ -22,6 +22,7 @@ import React from 'react'; import { translate } from '../../../../helpers/l10n'; import ApplyTemplateView from '../views/ApplyTemplateView'; +/*:: type Props = {| component: { configuration?: { @@ -35,11 +36,12 @@ type Props = {| loadHolders: () => void, loading: boolean |}; +*/ export default class PageHeader extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleApplyTemplate = (e: Event & { target: HTMLButtonElement }) => { + handleApplyTemplate = (e /*: Event & { target: HTMLButtonElement } */) => { e.preventDefault(); e.target.blur(); const { component, loadHolders } = this.props; diff --git a/server/sonar-web/src/main/js/apps/permissions/project/components/PublicProjectDisclaimer.js b/server/sonar-web/src/main/js/apps/permissions/project/components/PublicProjectDisclaimer.js index ed5ee186b7b..b74b802b673 100644 --- a/server/sonar-web/src/main/js/apps/permissions/project/components/PublicProjectDisclaimer.js +++ b/server/sonar-web/src/main/js/apps/permissions/project/components/PublicProjectDisclaimer.js @@ -22,6 +22,7 @@ import React from 'react'; import Modal from 'react-modal'; import { translate, translateWithParameters } from '../../../../helpers/l10n'; +/*:: type Props = { component: { name: string @@ -29,16 +30,17 @@ type Props = { onClose: () => void, onConfirm: () => void }; +*/ export default class PublicProjectDisclaimer extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleCancelClick = (event: Event) => { + handleCancelClick = (event /*: Event */) => { event.preventDefault(); this.props.onClose(); }; - handleConfirmClick = (event: Event) => { + handleConfirmClick = (event /*: Event */) => { event.preventDefault(); this.props.onConfirm(); this.props.onClose(); diff --git a/server/sonar-web/src/main/js/apps/project-admin/deletion/Form.js b/server/sonar-web/src/main/js/apps/project-admin/deletion/Form.js index b4e381e7373..3dc4dc144c6 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/deletion/Form.js +++ b/server/sonar-web/src/main/js/apps/project-admin/deletion/Form.js @@ -63,7 +63,7 @@ export default class Form extends React.PureComponent { .catch(this.stopLoading); }; - handleCloseClick = (event: Event) => { + handleCloseClick = (event /*: Event */) => { event.preventDefault(); this.closeModal(); }; diff --git a/server/sonar-web/src/main/js/apps/project-admin/deletion/Header.js b/server/sonar-web/src/main/js/apps/project-admin/deletion/Header.js index 8269e2ac6af..ce84b8c6e73 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/deletion/Header.js +++ b/server/sonar-web/src/main/js/apps/project-admin/deletion/Header.js @@ -21,7 +21,7 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -export default function Header(props: { component: { qualifier: string } }) { +export default function Header(props /*: { component: { qualifier: string } } */) { const { qualifier } = props.component; const description = ['VW', 'SVW'].includes(qualifier) ? translate('portfolio_deletion.page.description') diff --git a/server/sonar-web/src/main/js/apps/project-admin/quality-profiles/QualityProfiles.js b/server/sonar-web/src/main/js/apps/project-admin/quality-profiles/QualityProfiles.js index 00e93a54471..4551f410a25 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/quality-profiles/QualityProfiles.js +++ b/server/sonar-web/src/main/js/apps/project-admin/quality-profiles/QualityProfiles.js @@ -32,6 +32,7 @@ import { } from '../../../store/rootReducer'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { allProfiles: Array<{}>, component: { key: string, organization: string }, @@ -40,9 +41,10 @@ type Props = { profiles: Array<{}>, setProjectProfile: (string, string, string) => void }; +*/ class QualityProfiles extends React.PureComponent { - props: Props; + /*:: props: Props; */ componentDidMount() { if (this.props.customOrganizations) { diff --git a/server/sonar-web/src/main/js/apps/projectActivity/actions.js b/server/sonar-web/src/main/js/apps/projectActivity/actions.js index db482073f4e..97229ce74c3 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/actions.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/actions.js @@ -18,10 +18,12 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // @flow -import type { Event } from './types'; -import type { State } from './components/ProjectActivityAppContainer'; +/*:: import type { Event } from './types'; */ +/*:: import type { State } from './components/ProjectActivityAppContainer'; */ -export const addCustomEvent = (analysis: string, event: Event) => (state: State) => ({ +export const addCustomEvent = (analysis /*: string */, event /*: Event */) => ( + state /*: State */ +) => ({ analyses: state.analyses.map(item => { if (item.key !== analysis) { return item; @@ -30,7 +32,9 @@ export const addCustomEvent = (analysis: string, event: Event) => (state: State) }) }); -export const deleteEvent = (analysis: string, event: string) => (state: State) => ({ +export const deleteEvent = (analysis /*: string */, event /*: string */) => ( + state /*: State */ +) => ({ analyses: state.analyses.map(item => { if (item.key !== analysis) { return item; @@ -42,7 +46,9 @@ export const deleteEvent = (analysis: string, event: string) => (state: State) = }) }); -export const changeEvent = (analysis: string, event: Event) => (state: State) => ({ +export const changeEvent = (analysis /*: string */, event /*: Event */) => ( + state /*: State */ +) => ({ analyses: state.analyses.map(item => { if (item.key !== analysis) { return item; @@ -56,6 +62,6 @@ export const changeEvent = (analysis: string, event: Event) => (state: State) => }) }); -export const deleteAnalysis = (analysis: string) => (state: State) => ({ +export const deleteAnalysis = (analysis /*: string */) => (state /*: State */) => ({ analyses: state.analyses.filter(item => item.key !== analysis) }); diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/Event.js b/server/sonar-web/src/main/js/apps/projectActivity/components/Event.js index df9bb12f972..55251df9328 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/Event.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/Event.js @@ -24,8 +24,9 @@ import ChangeEventForm from './forms/ChangeEventForm'; import RemoveEventForm from './forms/RemoveEventForm'; import DeleteIcon from '../../../components/icons-components/DeleteIcon'; import ChangeIcon from '../../../components/icons-components/ChangeIcon'; -import type { Event as EventType } from '../types'; +/*:: import type { Event as EventType } from '../types'; */ +/*:: type Props = { analysis: string, canAdmin: boolean, @@ -34,16 +35,19 @@ type Props = { event: EventType, isFirst: boolean }; +*/ +/*:: type State = { changing: boolean, deleting: boolean }; +*/ export default class Event extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { changing: false, deleting: false }; @@ -56,7 +60,7 @@ export default class Event extends React.PureComponent { this.mounted = false; } - startChanging = (e: MouseEvent) => { + startChanging = (e /*: MouseEvent */) => { e.stopPropagation(); this.setState({ changing: true }); }; @@ -67,7 +71,7 @@ export default class Event extends React.PureComponent { } }; - startDeleting = (e: MouseEvent) => { + startDeleting = (e /*: MouseEvent */) => { e.stopPropagation(); this.setState({ deleting: true }); }; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/EventInner.js b/server/sonar-web/src/main/js/apps/projectActivity/components/EventInner.js index 15e53e3a994..bdd3dd81fd1 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/EventInner.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/EventInner.js @@ -22,9 +22,9 @@ import React from 'react'; import ProjectEventIcon from '../../../components/icons-components/ProjectEventIcon'; import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; import { translate } from '../../../helpers/l10n'; -import type { Event as EventType } from '../types'; +/*:: import type { Event as EventType } from '../types'; */ -export default function EventInner(props: { event: EventType }) { +export default function EventInner(props /*: { event: EventType } */) { const { event } = props; return ( diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/Events.js b/server/sonar-web/src/main/js/apps/projectActivity/components/Events.js index 5e8aa73566b..b68e776f112 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/Events.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/Events.js @@ -21,8 +21,9 @@ import React from 'react'; import { sortBy } from 'lodash'; import Event from './Event'; -import type { Event as EventType } from '../types'; +/*:: import type { Event as EventType } from '../types'; */ +/*:: type Props = { analysis?: string, canAdmin?: boolean, @@ -31,8 +32,9 @@ type Props = { events: Array<EventType>, isFirst?: boolean }; +*/ -export default function Events(props: Props) { +export default function Events(props /*: Props */) { const sortedEvents = sortBy( props.events, // versions last diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphHistory.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphHistory.js index 64cbfe5d0ab..b3cf468b3f7 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphHistory.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphHistory.js @@ -24,9 +24,10 @@ import GraphsTooltips from './GraphsTooltips'; import GraphsLegendCustom from './GraphsLegendCustom'; import GraphsLegendStatic from './GraphsLegendStatic'; import { formatMeasure, getShortType } from '../../../helpers/measures'; -import type { Event, MeasureHistory } from '../types'; -import type { Serie } from '../../../components/charts/AdvancedTimeline'; +/*:: import type { Event, MeasureHistory } from '../types'; */ +/*:: import type { Serie } from '../../../components/charts/AdvancedTimeline'; */ +/*:: type Props = { events: Array<Event>, graph: string, @@ -44,23 +45,30 @@ type Props = { updateSelectedDate: (selectedDate: ?Date) => void, updateTooltip: (selectedDate: ?Date) => void }; +*/ +/*:: type State = { tooltipIdx: ?number, tooltipXPos: ?number }; +*/ export default class GraphHistory extends React.PureComponent { - props: Props; - state: State = { + /*:: props: Props; */ + state /*: State */ = { tooltipIdx: null, tooltipXPos: null }; - formatValue = (tick: string | number) => + formatValue = (tick /*: string | number */) => formatMeasure(tick, getShortType(this.props.metricsType)); - updateTooltip = (selectedDate: ?Date, tooltipXPos: ?number, tooltipIdx: ?number) => { + updateTooltip = ( + selectedDate /*: ?Date */, + tooltipXPos /*: ?number */, + tooltipIdx /*: ?number */ + ) => { this.props.updateTooltip(selectedDate); this.setState({ tooltipXPos, tooltipIdx }); }; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsHistory.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsHistory.js index 3fae4284ddd..25247318719 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsHistory.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsHistory.js @@ -23,9 +23,10 @@ import { isEqual, sortBy } from 'lodash'; import GraphHistory from './GraphHistory'; import { EVENT_TYPES, getSeriesMetricType, hasHistoryData, isCustomGraph } from '../utils'; import { translate } from '../../../helpers/l10n'; -import type { Analysis, MeasureHistory } from '../types'; -import type { Serie } from '../../../components/charts/AdvancedTimeline'; +/*:: import type { Analysis, MeasureHistory } from '../types'; */ +/*:: import type { Serie } from '../../../components/charts/AdvancedTimeline'; */ +/*:: type Props = { analyses: Array<Analysis>, eventFilter: string, @@ -42,23 +43,26 @@ type Props = { updateGraphZoom: (from: ?Date, to: ?Date) => void, updateSelectedDate: (selectedDate: ?Date) => void }; +*/ +/*:: type State = { selectedDate?: ?Date }; +*/ export default class GraphsHistory extends React.PureComponent { - props: Props; - state: State; + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { selectedDate: props.selectedDate }; } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if (!isEqual(nextProps.selectedDate, this.props.selectedDate)) { this.setState({ selectedDate: nextProps.selectedDate }); } @@ -102,7 +106,7 @@ export default class GraphsHistory extends React.PureComponent { return []; }; - updateTooltip = (selectedDate: ?Date) => this.setState({ selectedDate }); + updateTooltip = (selectedDate /*: ?Date */) => this.setState({ selectedDate }); render() { const { graph, series } = this.props; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendCustom.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendCustom.js index 018565d2e9c..3130d415397 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendCustom.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendCustom.js @@ -23,14 +23,16 @@ import GraphsLegendItem from './GraphsLegendItem'; import Tooltip from '../../../components/controls/Tooltip'; import { hasDataValues } from '../utils'; import { translate } from '../../../helpers/l10n'; -import type { Serie } from '../../../components/charts/AdvancedTimeline'; +/*:: import type { Serie } from '../../../components/charts/AdvancedTimeline'; */ +/*:: type Props = { removeMetric: string => void, series: Array<Serie & { translatedName: string }> }; +*/ -export default function GraphsLegendCustom({ removeMetric, series }: Props) { +export default function GraphsLegendCustom({ removeMetric, series } /*: Props */) { return ( <div className="project-activity-graph-legends"> {series.map((serie, idx) => { diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendItem.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendItem.js index a458455a85c..3d7e16fad8b 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendItem.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendItem.js @@ -24,6 +24,7 @@ import AlertWarnIcon from '../../../components/icons-components/AlertWarnIcon'; import ChartLegendIcon from '../../../components/icons-components/ChartLegendIcon'; import CloseIcon from '../../../components/icons-components/CloseIcon'; +/*:: type Props = { className?: string, metric: string, @@ -32,11 +33,12 @@ type Props = { style: string, removeMetric?: string => void }; +*/ export default class GraphsLegendItem extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleClick = (e: Event) => { + handleClick = (e /*: Event */) => { e.preventDefault(); if (this.props.removeMetric) { this.props.removeMetric(this.props.metric); diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendStatic.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendStatic.js index c48119607cf..2b8c85ed7b9 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendStatic.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendStatic.js @@ -21,11 +21,13 @@ import React from 'react'; import GraphsLegendItem from './GraphsLegendItem'; +/*:: type Props = { series: Array<{ name: string, translatedName: string }> }; +*/ -export default function GraphsLegendStatic({ series }: Props) { +export default function GraphsLegendStatic({ series } /*: Props */) { return ( <div className="project-activity-graph-legends"> {series.map((serie, idx) => diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltips.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltips.js index a64755f5b64..4eb0e719a28 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltips.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltips.js @@ -27,9 +27,10 @@ import GraphsTooltipsContentCoverage from './GraphsTooltipsContentCoverage'; import GraphsTooltipsContentDuplication from './GraphsTooltipsContentDuplication'; import GraphsTooltipsContentIssues from './GraphsTooltipsContentIssues'; import { DEFAULT_GRAPH } from '../utils'; -import type { Event, MeasureHistory } from '../types'; -import type { Serie } from '../../../components/charts/AdvancedTimeline'; +/*:: import type { Event, MeasureHistory } from '../types'; */ +/*:: import type { Serie } from '../../../components/charts/AdvancedTimeline'; */ +/*:: type Props = { events: Array<Event>, formatValue: (number | string) => string, @@ -41,11 +42,12 @@ type Props = { tooltipIdx: number, tooltipPos: number }; +*/ const TOOLTIP_WIDTH = 250; export default class GraphsTooltips extends React.PureComponent { - props: Props; + /*:: props: Props; */ renderContent() { const { tooltipIdx } = this.props; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContent.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContent.js index 288bc539b18..369482b4fbd 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContent.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContent.js @@ -22,14 +22,16 @@ import React from 'react'; import classNames from 'classnames'; import ChartLegendIcon from '../../../components/icons-components/ChartLegendIcon'; +/*:: type Props = { name: string, style: string, translatedName: string, value: string }; +*/ -export default function GraphsTooltipsContent({ name, style, translatedName, value }: Props) { +export default function GraphsTooltipsContent({ name, style, translatedName, value } /*: Props */) { return ( <tr key={name} className="project-activity-graph-tooltip-line"> <td className="thin"> diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContentCoverage.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContentCoverage.js index 7ada640c64f..77c630376f7 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContentCoverage.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContentCoverage.js @@ -21,19 +21,19 @@ import React from 'react'; import { formatMeasure } from '../../../helpers/measures'; import { translate } from '../../../helpers/l10n'; -import type { MeasureHistory } from '../types'; +/*:: import type { MeasureHistory } from '../types'; */ +/*:: type Props = { addSeparator: boolean, measuresHistory: Array<MeasureHistory>, tooltipIdx: number }; +*/ -export default function GraphsTooltipsContentCoverage({ - addSeparator, - measuresHistory, - tooltipIdx -}: Props) { +export default function GraphsTooltipsContentCoverage( + { addSeparator, measuresHistory, tooltipIdx } /*: Props */ +) { const uncovered = measuresHistory.find(measure => measure.metric === 'uncovered_lines'); const coverage = measuresHistory.find(measure => measure.metric === 'coverage'); if (!uncovered || !uncovered.history[tooltipIdx] || !coverage || !coverage.history[tooltipIdx]) { diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContentDuplication.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContentDuplication.js index ed613969195..3fb31334c8b 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContentDuplication.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContentDuplication.js @@ -21,19 +21,19 @@ import React from 'react'; import { formatMeasure } from '../../../helpers/measures'; import { translate } from '../../../helpers/l10n'; -import type { MeasureHistory } from '../types'; +/*:: import type { MeasureHistory } from '../types'; */ +/*:: type Props = { addSeparator: boolean, measuresHistory: Array<MeasureHistory>, tooltipIdx: number }; +*/ -export default function GraphsTooltipsContentDuplication({ - addSeparator, - measuresHistory, - tooltipIdx -}: Props) { +export default function GraphsTooltipsContentDuplication( + { addSeparator, measuresHistory, tooltipIdx } /*: Props */ +) { const duplicationDensity = measuresHistory.find( measure => measure.metric === 'duplicated_lines_density' ); diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContentEvents.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContentEvents.js index d23ac08368f..675e6382be8 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContentEvents.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContentEvents.js @@ -21,14 +21,16 @@ import React from 'react'; import ProjectEventIcon from '../../../components/icons-components/ProjectEventIcon'; import { translate } from '../../../helpers/l10n'; -import type { Event } from '../types'; +/*:: import type { Event } from '../types'; */ +/*:: type Props = { addSeparator: boolean, events: Array<Event> }; +*/ -export default function GraphsTooltipsContentEvents({ addSeparator, events }: Props) { +export default function GraphsTooltipsContentEvents({ addSeparator, events } /*: Props */) { return ( <tbody> {addSeparator && diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContentIssues.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContentIssues.js index cad11cf2085..bbe85d7a25f 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContentIssues.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContentIssues.js @@ -22,8 +22,9 @@ import React from 'react'; import classNames from 'classnames'; import ChartLegendIcon from '../../../components/icons-components/ChartLegendIcon'; import Rating from '../../../components/ui/Rating'; -import type { MeasureHistory } from '../types'; +/*:: import type { MeasureHistory } from '../types'; */ +/*:: type Props = { measuresHistory: Array<MeasureHistory>, name: string, @@ -32,6 +33,7 @@ type Props = { translatedName: string, value: string }; +*/ const METRIC_RATING = { bugs: 'reliability_rating', @@ -39,7 +41,7 @@ const METRIC_RATING = { code_smells: 'sqale_rating' }; -export default function GraphsTooltipsContentIssues(props: Props) { +export default function GraphsTooltipsContentIssues(props /*: Props */) { const rating = props.measuresHistory.find( measure => measure.metric === METRIC_RATING[props.name] ); diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsZoom.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsZoom.js index 3acdafc99ad..810fcf755fd 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsZoom.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsZoom.js @@ -22,8 +22,9 @@ import React from 'react'; import { AutoSizer } from 'react-virtualized'; import ZoomTimeLine from '../../../components/charts/ZoomTimeLine'; import { hasHistoryData } from '../utils'; -import type { Serie } from '../../../components/charts/AdvancedTimeline'; +/*:: import type { Serie } from '../../../components/charts/AdvancedTimeline'; */ +/*:: type Props = { graphEndDate: ?Date, graphStartDate: ?Date, @@ -34,8 +35,9 @@ type Props = { showAreas?: boolean, updateGraphZoom: (from: ?Date, to: ?Date) => void }; +*/ -export default function GraphsZoom(props: Props) { +export default function GraphsZoom(props /*: Props */) { const { loading } = props; if (loading || !hasHistoryData(props.series)) { return null; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js index a7e94e0ef84..ffb96775dc9 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js @@ -30,9 +30,10 @@ import { getAnalysesByVersionByDay, selectedDateQueryChanged } from '../utils'; -import type { RawQuery } from '../../../helpers/query'; -import type { Analysis, Query } from '../types'; +/*:: import type { RawQuery } from '../../../helpers/query'; */ +/*:: import type { Analysis, Query } from '../types'; */ +/*:: type Props = { addCustomEvent: (analysis: string, name: string, category?: string) => Promise<*>, addVersion: (analysis: string, version: string) => Promise<*>, @@ -46,16 +47,17 @@ type Props = { loading: boolean, project: { qualifier: string }, query: Query, - updateQuery: RawQuery => void + updateQuery: Object => void }; +*/ export default class ProjectActivityAnalysesList extends React.PureComponent { - analyses: HTMLCollection<HTMLElement>; - badges: HTMLCollection<HTMLElement>; - props: Props; - scrollContainer: HTMLElement; + /*:: analyses: HTMLCollection<HTMLElement>; */ + /*:: badges: HTMLCollection<HTMLElement>; */ + /*:: props: Props; */ + /*:: scrollContainer: HTMLElement; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.handleScroll = throttle(this.handleScroll, 20); } @@ -65,7 +67,7 @@ export default class ProjectActivityAnalysesList extends React.PureComponent { this.analyses = document.getElementsByClassName('project-activity-analysis'); } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if (!this.scrollContainer) { return; } @@ -82,7 +84,7 @@ export default class ProjectActivityAnalysesList extends React.PureComponent { handleScroll = () => this.updateStickyBadges(true); - resetScrollTop = (newScrollTop: number, forceBadgeAlignement?: boolean) => { + resetScrollTop = (newScrollTop /*: number */, forceBadgeAlignement /*: ?boolean */) => { this.scrollContainer.scrollTop = newScrollTop; for (let i = 1; i < this.badges.length; i++) { this.badges[i].removeAttribute('originOffsetTop'); @@ -91,7 +93,7 @@ export default class ProjectActivityAnalysesList extends React.PureComponent { this.updateStickyBadges(forceBadgeAlignement); }; - scrollToDate = (targetDate: ?Date) => { + scrollToDate = (targetDate /*: ?Date */) => { if (!this.scrollContainer || !targetDate) { return; } @@ -109,7 +111,7 @@ export default class ProjectActivityAnalysesList extends React.PureComponent { } }; - updateStickyBadges = (forceBadgeAlignement?: boolean) => { + updateStickyBadges = (forceBadgeAlignement /*: ?boolean */) => { if (this.scrollContainer && this.badges) { const scrollTop = this.scrollContainer.scrollTop; if (scrollTop != null) { @@ -138,7 +140,7 @@ export default class ProjectActivityAnalysesList extends React.PureComponent { } }; - updateSelectedDate = (date: Date) => this.props.updateQuery({ selectedDate: date }); + updateSelectedDate = (date /*: Date */) => this.props.updateQuery({ selectedDate: date }); render() { const byVersionByDay = getAnalysesByVersionByDay(this.props.analyses, this.props.query); diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysis.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysis.js index 72067b95261..f52a59b5943 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysis.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysis.js @@ -25,8 +25,9 @@ import AddEventForm from './forms/AddEventForm'; import RemoveAnalysisForm from './forms/RemoveAnalysisForm'; import FormattedDate from '../../../components/ui/FormattedDate'; import { translate } from '../../../helpers/l10n'; -import type { Analysis } from '../types'; +/*:: import type { Analysis } from '../types'; */ +/*:: type Props = { addCustomEvent: (analysis: string, name: string, category?: string) => Promise<*>, addVersion: (analysis: string, version: string) => Promise<*>, @@ -40,13 +41,14 @@ type Props = { selected: boolean, updateSelectedDate: Date => void }; +*/ export default class ProjectActivityAnalysis extends React.PureComponent { - props: Props; + /*:: props: Props; */ handleClick = () => this.props.updateSelectedDate(this.props.analysis.date); - stopPropagation = (e: Event) => e.stopPropagation(); + stopPropagation = (e /*: Event */) => e.stopPropagation(); render() { const { analysis, isFirst, canAdmin } = this.props; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js index fb825ed45ad..717678a0561 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js @@ -26,8 +26,9 @@ import ProjectActivityAnalysesList from './ProjectActivityAnalysesList'; import ProjectActivityGraphs from './ProjectActivityGraphs'; import { translate } from '../../../helpers/l10n'; import './projectActivity.css'; -import type { Analysis, MeasureHistory, Metric, Query } from '../types'; +/*:: import type { Analysis, MeasureHistory, Metric, Query } from '../types'; */ +/*:: type Props = { addCustomEvent: (analysis: string, name: string, category?: string) => Promise<*>, addVersion: (analysis: string, version: string) => Promise<*>, @@ -49,8 +50,9 @@ type Props = { query: Query, updateQuery: (newQuery: Query) => void }; +*/ -export default function ProjectActivityApp(props: Props) { +export default function ProjectActivityApp(props /*: Props */) { const { analyses, measuresHistory, query } = props; const { configuration } = props.project; const canAdmin = configuration ? configuration.showHistory : false; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAppContainer.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAppContainer.js index 0ca8c21f1a6..8572a4be9b5 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAppContainer.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAppContainer.js @@ -39,9 +39,10 @@ import { serializeQuery, serializeUrlQuery } from '../utils'; -import type { RawQuery } from '../../../helpers/query'; -import type { Analysis, MeasureHistory, Metric, Paging, Query } from '../types'; +/*:: import type { RawQuery } from '../../../helpers/query'; */ +/*:: import type { Analysis, MeasureHistory, Metric, Paging, Query } from '../types'; */ +/*:: type Props = { location: { pathname: string, query: RawQuery }, project: { @@ -55,7 +56,9 @@ type Props = { replace: ({ pathname: string, query?: RawQuery }) => void } }; +*/ +/*:: export type State = { analyses: Array<Analysis>, analysesLoading: boolean, @@ -66,13 +69,14 @@ export type State = { paging?: Paging, query: Query }; +*/ class ProjectActivityAppContainer 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 = { analyses: [], @@ -105,7 +109,7 @@ class ProjectActivityAppContainer extends React.PureComponent { } } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if (nextProps.location.query !== this.props.location.query) { const query = parseQuery(nextProps.location.query); if (query.graph !== this.state.query.graph || customMetricsChanged(this.state.query, query)) { @@ -125,7 +129,7 @@ class ProjectActivityAppContainer extends React.PureComponent { elem && elem.classList.remove('dashboard-page'); } - addCustomEvent = (analysis: string, name: string, category?: string): Promise<*> => + addCustomEvent = (analysis /*: string */, name /*: string */, category /*: ?string */) => api .createEvent(analysis, name, category) .then( @@ -133,10 +137,10 @@ class ProjectActivityAppContainer extends React.PureComponent { this.mounted && this.setState(actions.addCustomEvent(analysis, event)) ); - addVersion = (analysis: string, version: string): Promise<*> => + addVersion = (analysis /*: string */, version /*: string */) => this.addCustomEvent(analysis, version, 'VERSION'); - changeEvent = (event: string, name: string): Promise<*> => + changeEvent = (event /*: string */, name /*: string */) => api .changeEvent(event, name) .then( @@ -144,7 +148,7 @@ class ProjectActivityAppContainer extends React.PureComponent { this.mounted && this.setState(actions.changeEvent(analysis, event)) ); - deleteAnalysis = (analysis: string): Promise<*> => + deleteAnalysis = (analysis /*: string */) => api.deleteAnalysis(analysis).then(() => { if (this.mounted) { this.updateGraphData(this.state.query.graph, this.state.query.customMetrics); @@ -152,19 +156,19 @@ class ProjectActivityAppContainer extends React.PureComponent { } }); - deleteEvent = (analysis: string, event: string): Promise<*> => + deleteEvent = (analysis /*: string */, event /*: string */) => api .deleteEvent(event) .then(() => this.mounted && this.setState(actions.deleteEvent(analysis, event))); fetchActivity = ( - project: string, - p: number, - ps: number, - additional?: { + project /*: string */, + p /*: number */, + ps /*: number */, + additional /*: ?{ [string]: string - } - ): Promise<{ analyses: Array<Analysis>, paging: Paging }> => { + } */ + ) => { const parameters = { project, p, ps }; return api .getProjectActivity({ ...parameters, ...additional }) @@ -174,7 +178,7 @@ class ProjectActivityAppContainer extends React.PureComponent { })); }; - fetchMeasuresHistory = (metrics: Array<string>): Promise<Array<MeasureHistory>> => { + fetchMeasuresHistory = (metrics /*: Array<string> */) => { if (metrics.length <= 0) { return Promise.resolve([]); } @@ -191,12 +195,12 @@ class ProjectActivityAppContainer extends React.PureComponent { ); }; - fetchMetrics = (): Promise<Array<Metric>> => getMetrics().catch(throwGlobalError); + fetchMetrics = () => getMetrics().catch(throwGlobalError); loadAllActivities = ( - project: string, - prevResult?: { analyses: Array<Analysis>, paging: Paging } - ): Promise<{ analyses: Array<Analysis>, paging: Paging }> => { + project /*: string */, + prevResult /*: ?{ analyses: Array<Analysis>, paging: Paging } */ + ) => { if ( prevResult && prevResult.paging.pageIndex * prevResult.paging.pageSize >= prevResult.paging.total @@ -215,7 +219,7 @@ class ProjectActivityAppContainer extends React.PureComponent { }); }; - firstLoadData(query: Query) { + firstLoadData(query /*: Query */) { const graphMetrics = getHistoryMetrics(query.graph, query.customMetrics); Promise.all([ this.fetchActivity(query.project, 1, 100, serializeQuery(query)), @@ -246,15 +250,15 @@ class ProjectActivityAppContainer extends React.PureComponent { }); } - updateGraphData = (graph: string, customMetrics: Array<string>) => { + updateGraphData = (graph /*: string */, customMetrics /*: Array<string> */) => { const graphMetrics = getHistoryMetrics(graph, customMetrics); this.setState({ graphLoading: true }); - this.fetchMeasuresHistory(graphMetrics).then((measuresHistory: Array<MeasureHistory>) => + this.fetchMeasuresHistory(graphMetrics).then((measuresHistory /*: Array<MeasureHistory> */) => this.setState({ graphLoading: false, measuresHistory }) ); }; - updateQuery = (newQuery: Query) => { + updateQuery = (newQuery /*: Query */) => { const query = serializeUrlQuery({ ...this.state.query, ...newQuery diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityDateInput.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityDateInput.js index 3a0212037ac..1ece1355970 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityDateInput.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityDateInput.js @@ -23,24 +23,26 @@ import moment from 'moment'; import DateInput from '../../../components/controls/DateInput'; import { parseAsDate } from '../../../helpers/query'; import { translate } from '../../../helpers/l10n'; -import type { RawQuery } from '../../../helpers/query'; +/*:: import type { RawQuery } from '../../../helpers/query'; */ +/*:: type Props = { from: ?Date, to: ?Date, onChange: RawQuery => void }; +*/ export default class ProjectActivityDateInput extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleFromDateChange = (from: string) => this.props.onChange({ from: parseAsDate(from) }); + handleFromDateChange = (from /*: string */) => this.props.onChange({ from: parseAsDate(from) }); - handleToDateChange = (to: string) => this.props.onChange({ to: parseAsDate(to) }); + handleToDateChange = (to /*: string */) => this.props.onChange({ to: parseAsDate(to) }); handleResetClick = () => this.props.onChange({ from: null, to: null }); - formatDate = (date: ?Date) => (date ? moment(date).format('YYYY-MM-DD') : null); + formatDate = (date /*: ?Date */) => (date ? moment(date).format('YYYY-MM-DD') : null); render() { return ( diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityEventSelectOption.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityEventSelectOption.js index a77c653b147..cac4aae8a01 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityEventSelectOption.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityEventSelectOption.js @@ -21,8 +21,11 @@ import React from 'react'; import ProjectEventIcon from '../../../components/icons-components/ProjectEventIcon'; +/*:: export type Option = { label: string, value: string }; +*/ +/*:: type Props = { option: Option, children?: Element | Text, @@ -31,21 +34,22 @@ type Props = { onFocus: (Option, MouseEvent) => void, onSelect: (Option, MouseEvent) => void }; +*/ export default class ProjectActivityEventSelectOption extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleMouseDown = (event: MouseEvent) => { + handleMouseDown = (event /*: MouseEvent */) => { event.preventDefault(); event.stopPropagation(); this.props.onSelect(this.props.option, event); }; - handleMouseEnter = (event: MouseEvent) => { + handleMouseEnter = (event /*: MouseEvent */) => { this.props.onFocus(this.props.option, event); }; - handleMouseMove = (event: MouseEvent) => { + handleMouseMove = (event /*: MouseEvent */) => { if (this.props.isFocused) { return; } diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityEventSelectValue.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityEventSelectValue.js index 08665bf06e4..e06d0827f8d 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityEventSelectValue.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityEventSelectValue.js @@ -20,14 +20,16 @@ //@flow import React from 'react'; import ProjectEventIcon from '../../../components/icons-components/ProjectEventIcon'; -import type { Option } from './ProjectActivityEventSelectOption'; +/*:: import type { Option } from './ProjectActivityEventSelectOption'; */ +/*:: type Props = { value: Option, children?: Element | Text }; +*/ -export default function ProjectActivityEventSelectValue(props: Props) { +export default function ProjectActivityEventSelectValue(props /*: Props */) { const { value } = props; return ( <div className="Select-value" title={value.label}> diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityGraphs.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityGraphs.js index 08feb4a5953..e97d205640e 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityGraphs.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityGraphs.js @@ -33,10 +33,11 @@ import { isCustomGraph, splitSeriesInGraphs } from '../utils'; -import type { RawQuery } from '../../../helpers/query'; -import type { Analysis, MeasureHistory, Metric, Query } from '../types'; -import type { Serie } from '../../../components/charts/AdvancedTimeline'; +/*:: import type { RawQuery } from '../../../helpers/query'; */ +/*:: import type { Analysis, MeasureHistory, Metric, Query } from '../types'; */ +/*:: import type { Serie } from '../../../components/charts/AdvancedTimeline'; */ +/*:: type Props = { analyses: Array<Analysis>, leakPeriodDate: Date, @@ -46,22 +47,25 @@ type Props = { query: Query, updateQuery: RawQuery => void }; +*/ +/*:: type State = { graphStartDate: ?Date, graphEndDate: ?Date, series: Array<Serie>, graphs: Array<Array<Serie>> }; +*/ const MAX_GRAPH_NB = 2; const MAX_SERIES_PER_GRAPH = 3; export default class ProjectActivityGraphs extends React.PureComponent { - props: Props; - state: State; + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); const series = generateSeries( props.measuresHistory, @@ -77,7 +81,7 @@ export default class ProjectActivityGraphs extends React.PureComponent { this.updateQueryDateRange = debounce(this.updateQueryDateRange, 500); } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { let newSeries; let newGraphs; if ( @@ -109,10 +113,10 @@ export default class ProjectActivityGraphs extends React.PureComponent { } getStateZoomDates = ( - props: ?Props, - nextProps: Props, - newSeries: ?Array<Serie> - ): ?{ graphEndDate: ?Date, graphStartDate: ?Date } => { + props /*: ?Props */, + nextProps /*: Props */, + newSeries /*: ?Array<Serie> */ + ) => { const newDates = { from: nextProps.query.from || null, to: nextProps.query.to || null }; if (!props || datesQueryChanged(props.query, nextProps.query)) { return { graphEndDate: newDates.to, graphStartDate: newDates.from }; @@ -132,7 +136,7 @@ export default class ProjectActivityGraphs extends React.PureComponent { } }; - getMetricsTypeFilter = (): ?Array<string> => { + getMetricsTypeFilter = () => { if (this.state.graphs.length < MAX_GRAPH_NB) { return null; } @@ -141,19 +145,19 @@ export default class ProjectActivityGraphs extends React.PureComponent { .map(graph => graph[0].type); }; - addCustomMetric = (metric: string) => { + addCustomMetric = (metric /*: string */) => { const customMetrics = [...this.props.query.customMetrics, metric]; saveCustomGraph(customMetrics); this.props.updateQuery({ customMetrics }); }; - removeCustomMetric = (removedMetric: string) => { + removeCustomMetric = (removedMetric /*: string */) => { const customMetrics = this.props.query.customMetrics.filter(metric => metric !== removedMetric); saveCustomGraph(customMetrics); this.props.updateQuery({ customMetrics }); }; - updateGraph = (graph: string) => { + updateGraph = (graph /*: string */) => { saveGraph(graph); if (isCustomGraph(graph) && this.props.query.customMetrics.length <= 0) { this.props.updateQuery({ graph, customMetrics: getCustomGraph() }); @@ -162,7 +166,7 @@ export default class ProjectActivityGraphs extends React.PureComponent { } }; - updateGraphZoom = (graphStartDate: ?Date, graphEndDate: ?Date) => { + updateGraphZoom = (graphStartDate /*: ?Date */, graphEndDate /*: ?Date */) => { if (graphEndDate != null && graphStartDate != null) { const msDiff = Math.abs(graphEndDate.valueOf() - graphStartDate.valueOf()); // 12 hours minimum between the two dates @@ -175,9 +179,9 @@ export default class ProjectActivityGraphs extends React.PureComponent { this.updateQueryDateRange([graphStartDate, graphEndDate]); }; - updateSelectedDate = (selectedDate: ?Date) => this.props.updateQuery({ selectedDate }); + updateSelectedDate = (selectedDate /*: ?Date */) => this.props.updateQuery({ selectedDate }); - updateQueryDateRange = (dates: Array<?Date>) => { + updateQueryDateRange = (dates /*: Array<?Date> */) => { if (dates[0] == null || dates[1] == null) { this.props.updateQuery({ from: dates[0], to: dates[1] }); } else { diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityGraphsHeader.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityGraphsHeader.js index 3b536c25956..f9f298e9ab3 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityGraphsHeader.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityGraphsHeader.js @@ -23,8 +23,9 @@ import Select from 'react-select'; import AddGraphMetric from './forms/AddGraphMetric'; import { isCustomGraph, GRAPH_TYPES } from '../utils'; import { translate } from '../../../helpers/l10n'; -import type { Metric } from '../types'; +/*:: import type { Metric } from '../types'; */ +/*:: type Props = { addCustomMetric: string => void, graph: string, @@ -33,11 +34,12 @@ type Props = { selectedMetrics: Array<string>, updateGraph: string => void }; +*/ export default class ProjectActivityGraphsHeader extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleGraphChange = (option: { value: string }) => { + handleGraphChange = (option /*: { value: string } */) => { if (option.value !== this.props.graph) { this.props.updateGraph(option.value); } diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageFooter.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageFooter.js index 77428e38105..3ba5fd319a2 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageFooter.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageFooter.js @@ -20,15 +20,19 @@ // @flow import React from 'react'; import ListFooter from '../../../components/controls/ListFooter'; -import type { Paging } from '../types'; +/*:: import type { Paging } from '../types'; */ +/*:: type Props = { analyses: Array<*>, fetchMoreActivity: () => void, paging?: Paging }; +*/ -export default function ProjectActivityPageFooter({ analyses, fetchMoreActivity, paging }: Props) { +export default function ProjectActivityPageFooter( + { analyses, fetchMoreActivity, paging } /*: Props */ +) { if (!paging || analyses.length === 0) { return null; } diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageHeader.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageHeader.js index 969af31ee63..57183279074 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageHeader.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageHeader.js @@ -25,8 +25,9 @@ import ProjectActivityEventSelectValue from './ProjectActivityEventSelectValue'; import ProjectActivityDateInput from './ProjectActivityDateInput'; import { EVENT_TYPES, APPLICATION_EVENT_TYPES } from '../utils'; import { translate } from '../../../helpers/l10n'; -import type { RawQuery } from '../../../helpers/query'; +/*:: import type { RawQuery } from '../../../helpers/query'; */ +/*:: type Props = { category?: string, from: ?Date, @@ -34,12 +35,13 @@ type Props = { to: ?Date, updateQuery: RawQuery => void }; +*/ export default class ProjectActivityPageHeader extends React.PureComponent { - options: Array<{ label: string, value: string }>; - props: Props; + /*:: options: Array<{ label: string, value: string }>; */ + /*:: props: Props; */ - handleCategoryChange = (option: ?{ value: string }) => + handleCategoryChange = (option /*: ?{ value: string } */) => this.props.updateQuery({ category: option ? option.value : '' }); render() { diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddEventForm.js b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddEventForm.js index bcfc6672789..62195f9d69d 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddEventForm.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddEventForm.js @@ -21,24 +21,28 @@ import React from 'react'; import Modal from 'react-modal'; import { translate } from '../../../../helpers/l10n'; -import type { Analysis } from '../../types'; +/*:: import type { Analysis } from '../../types'; */ +/*:: type Props = { addEvent: (analysis: string, name: string, category?: string) => Promise<*>, analysis: Analysis, addEventButtonText: string }; +*/ +/*:: type State = { open: boolean, processing: boolean, name: string }; +*/ export default class AddEventForm extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { open: false, processing: false, name: '' @@ -52,7 +56,7 @@ export default class AddEventForm extends React.PureComponent { this.mounted = false; } - openForm = (e: Event) => { + openForm = (e /*: Event */) => { e.preventDefault(); e.stopPropagation(); if (this.mounted) { @@ -66,7 +70,7 @@ export default class AddEventForm extends React.PureComponent { } }; - changeInput = (e: Object) => { + changeInput = (e /*: Object */) => { if (this.mounted) { this.setState({ name: e.target.value }); } @@ -84,7 +88,7 @@ export default class AddEventForm extends React.PureComponent { } }; - handleSubmit = (e: Object) => { + handleSubmit = (e /*: Object */) => { e.preventDefault(); this.setState({ processing: true }); this.props diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddGraphMetric.js b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddGraphMetric.js index 3ab48063f12..7dec82030c7 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddGraphMetric.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddGraphMetric.js @@ -29,8 +29,9 @@ import { translate, translateWithParameters } from '../../../../helpers/l10n'; -import type { Metric } from '../../types'; +/*:: import type { Metric } from '../../types'; */ +/*:: type Props = { addMetric: (metric: string) => void, className?: string, @@ -38,19 +39,22 @@ type Props = { metricsTypeFilter: ?Array<string>, selectedMetrics: Array<string> }; +*/ +/*:: type State = { open: boolean, selectedMetric?: string }; +*/ export default class AddGraphMetric extends React.PureComponent { - props: Props; - state: State = { + /*:: props: Props; */ + state /*: State */ = { open: false }; - getMetricsOptions = (metricsTypeFilter: ?Array<string>) => { + getMetricsOptions = (metricsTypeFilter /*: ?Array<string> */) => { return this.props.metrics .filter(metric => { if ( @@ -65,7 +69,7 @@ export default class AddGraphMetric extends React.PureComponent { } return true; }) - .map((metric: Metric) => ({ + .map((metric /*: Metric */) => ({ value: metric.key, label: getLocalizedMetricName(metric) })); @@ -84,10 +88,10 @@ export default class AddGraphMetric extends React.PureComponent { }); }; - handleChange = (option: { value: string, label: string }) => + handleChange = (option /*: { value: string, label: string } */) => this.setState({ selectedMetric: option.value }); - handleSubmit = (e: Object) => { + handleSubmit = (e /*: Object */) => { e.preventDefault(); if (this.state.selectedMetric) { this.props.addMetric(this.state.selectedMetric); diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/ChangeEventForm.js b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/ChangeEventForm.js index 40c19cba887..ffd358c47d9 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/ChangeEventForm.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/ChangeEventForm.js @@ -21,26 +21,30 @@ import React from 'react'; import Modal from 'react-modal'; import { translate } from '../../../../helpers/l10n'; -import type { Event } from '../../types'; +/*:: import type { Event } from '../../types'; */ +/*:: type Props = { changeEvent: (event: string, name: string) => Promise<*>, changeEventButtonText: string, event: Event, onClose: () => void }; +*/ +/*:: type State = { processing: boolean, name: string }; +*/ export default class ChangeEventForm 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 = { processing: false, @@ -63,7 +67,7 @@ export default class ChangeEventForm extends React.PureComponent { this.props.onClose(); }; - changeInput = (e: Object) => { + changeInput = (e /*: Object */) => { if (this.mounted) { this.setState({ name: e.target.value }); } @@ -82,7 +86,7 @@ export default class ChangeEventForm extends React.PureComponent { this.props.onClose(); }; - handleSubmit = (e: Object) => { + handleSubmit = (e /*: Object */) => { e.preventDefault(); this.setState({ processing: true }); this.props diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveAnalysisForm.js b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveAnalysisForm.js index d8a12f791c5..481f7f2be61 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveAnalysisForm.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveAnalysisForm.js @@ -21,22 +21,26 @@ import React from 'react'; import Modal from 'react-modal'; import { translate } from '../../../../helpers/l10n'; -import type { Analysis } from '../../types'; +/*:: import type { Analysis } from '../../types'; */ +/*:: type Props = { analysis: Analysis, deleteAnalysis: (analysis: string) => Promise<*> }; +*/ +/*:: type State = { open: boolean, processing: boolean }; +*/ export default class RemoveAnalysisForm extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { open: false, processing: false }; @@ -49,7 +53,7 @@ export default class RemoveAnalysisForm extends React.PureComponent { this.mounted = false; } - openForm = (e: Event) => { + openForm = (e /*: Event */) => { e.preventDefault(); e.stopPropagation(); if (this.mounted) { @@ -75,7 +79,7 @@ export default class RemoveAnalysisForm extends React.PureComponent { } }; - handleSubmit = (e: Event) => { + handleSubmit = (e /*: Event */) => { e.preventDefault(); this.setState({ processing: true }); this.props diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveEventForm.js b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveEventForm.js index ac50df35dc7..3ba867116a5 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveEventForm.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveEventForm.js @@ -21,8 +21,9 @@ import React from 'react'; import Modal from 'react-modal'; import { translate } from '../../../../helpers/l10n'; -import type { Event } from '../../types'; +/*:: import type { Event } from '../../types'; */ +/*:: type Props = { analysis: string, deleteEvent: (analysis: string, event: string) => Promise<*>, @@ -31,15 +32,18 @@ type Props = { removeEventQuestion: string, onClose: () => void }; +*/ +/*:: type State = { processing: boolean }; +*/ export default class RemoveEventForm extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { processing: false }; @@ -68,7 +72,7 @@ export default class RemoveEventForm extends React.PureComponent { this.props.onClose(); }; - handleSubmit = (e: Object) => { + handleSubmit = (e /*: Object */) => { e.preventDefault(); this.setState({ processing: true }); this.props diff --git a/server/sonar-web/src/main/js/apps/projectActivity/types.js b/server/sonar-web/src/main/js/apps/projectActivity/types.js index ab6c9fa78a3..750518982d1 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/types.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/types.js @@ -19,23 +19,32 @@ */ // @flow +/*:: export type Event = { key: string, name: string, category: string, description?: string }; +*/ +/*:: export type Analysis = { key: string, date: Date, events: Array<Event> }; +*/ +/*:: export type HistoryItem = { date: Date, value: string }; +*/ +/*:: export type MeasureHistory = { metric: string, history: Array<HistoryItem> }; +*/ +/*:: export type Metric = { custom?: boolean, hidden?: boolean, @@ -43,13 +52,17 @@ export type Metric = { name: string, type: string }; +*/ +/*:: export type Paging = { pageIndex: number, pageSize: number, total: number }; +*/ +/*:: export type Query = { category: string, customMetrics: Array<string>, @@ -59,3 +72,4 @@ export type Query = { to?: Date, selectedDate?: Date }; +*/ diff --git a/server/sonar-web/src/main/js/apps/projectActivity/utils.js b/server/sonar-web/src/main/js/apps/projectActivity/utils.js index 7a126be384a..4e85eb3ced6 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/utils.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/utils.js @@ -30,9 +30,9 @@ import { serializeString } from '../../helpers/query'; import { getLocalizedMetricName, translate } from '../../helpers/l10n'; -import type { Analysis, MeasureHistory, Metric, Query } from './types'; -import type { RawQuery } from '../../helpers/query'; -import type { Serie } from '../../components/charts/AdvancedTimeline'; +/*:: import type { Analysis, MeasureHistory, Metric, Query } from './types'; */ +/*:: import type { RawQuery } from '../../helpers/query'; */ +/*:: import type { Serie } from '../../components/charts/AdvancedTimeline'; */ export const EVENT_TYPES = ['VERSION', 'QUALITY_GATE', 'QUALITY_PROFILE', 'OTHER']; export const APPLICATION_EVENT_TYPES = ['QUALITY_GATE', 'OTHER']; @@ -53,34 +53,36 @@ export const GRAPHS_METRICS = { duplications: GRAPHS_METRICS_DISPLAYED['duplications'].concat(['duplicated_lines_density']) }; -export const activityQueryChanged = (prevQuery: Query, nextQuery: Query): boolean => +export const activityQueryChanged = (prevQuery /*: Query */, nextQuery /*: Query */) => prevQuery.category !== nextQuery.category || datesQueryChanged(prevQuery, nextQuery); -export const customMetricsChanged = (prevQuery: Query, nextQuery: Query): boolean => +export const customMetricsChanged = (prevQuery /*: Query */, nextQuery /*: Query */) => !isEqual(prevQuery.customMetrics, nextQuery.customMetrics); -export const datesQueryChanged = (prevQuery: Query, nextQuery: Query): boolean => +export const datesQueryChanged = (prevQuery /*: Query */, nextQuery /*: Query */) => !isEqual(prevQuery.from, nextQuery.from) || !isEqual(prevQuery.to, nextQuery.to); -export const hasDataValues = (serie: Serie) => serie.data.some(point => point.y || point.y === 0); +export const hasDataValues = (serie /*: Serie */) => + serie.data.some(point => point.y || point.y === 0); -export const hasHistoryData = (series: Array<Serie>) => +export const hasHistoryData = (series /*: Array<Serie> */) => series.some(serie => serie.data && serie.data.length > 1); -export const hasHistoryDataValue = (series: Array<Serie>) => +export const hasHistoryDataValue = (series /*: Array<Serie> */) => series.some(serie => serie.data && serie.data.length > 1 && hasDataValues(serie)); -export const historyQueryChanged = (prevQuery: Query, nextQuery: Query): boolean => - prevQuery.graph !== nextQuery.graph; +export function historyQueryChanged(prevQuery /*: Query */, nextQuery /*: Query */) /*: boolean */ { + return prevQuery.graph !== nextQuery.graph; +} -export const isCustomGraph = (graph: string) => graph === 'custom'; +export const isCustomGraph = (graph /*: string */) => graph === 'custom'; -export const selectedDateQueryChanged = (prevQuery: Query, nextQuery: Query): boolean => +export const selectedDateQueryChanged = (prevQuery /*: Query */, nextQuery /*: Query */) => !isEqual(prevQuery.selectedDate, nextQuery.selectedDate); export const generateCoveredLinesMetric = ( - uncoveredLines: MeasureHistory, - measuresHistory: Array<MeasureHistory> + uncoveredLines /*: MeasureHistory */, + measuresHistory /*: Array<MeasureHistory> */ ) => { const linesToCover = measuresHistory.find(measure => measure.metric === 'lines_to_cover'); return { @@ -96,12 +98,12 @@ export const generateCoveredLinesMetric = ( }; }; -export const generateSeries = ( - measuresHistory: Array<MeasureHistory>, - graph: string, - metrics: Array<Metric>, - displayedMetrics: Array<string> -): Array<Serie> => { +export function generateSeries( + measuresHistory /*: Array<MeasureHistory> */, + graph /*: string */, + metrics /*: Array<Metric> */, + displayedMetrics /*: Array<string> */ +) /*: Array<Serie> */ { if (displayedMetrics.length <= 0) { return []; } @@ -125,27 +127,20 @@ export const generateSeries = ( }), serie => displayedMetrics.indexOf(serie.name) ); -}; +} export const splitSeriesInGraphs = ( - series: Array<Serie>, - maxGraph: number, - maxSeries: number -): Array<Array<Serie>> => + series /*: Array<Serie> */, + maxGraph /*: number */, + maxSeries /*: number */ +) => flatMap(groupBy(series, serie => serie.type), type => chunk(type, maxSeries)).slice(0, maxGraph); -export const getSeriesMetricType = (series: Array<Serie>): string => +export const getSeriesMetricType = (series /*: Array<Serie> */) => series.length > 0 ? series[0].type : 'INT'; -export const getAnalysesByVersionByDay = ( - analyses: Array<Analysis>, - query: Query -): Array<{ - version: ?string, - key: ?string, - byDay: { [string]: Array<Analysis> } -}> => - analyses.reduce((acc, analysis) => { +export function getAnalysesByVersionByDay(analyses /*: Array<Analysis> */, query /*: Query */) { + return analyses.reduce((acc, analysis) => { let currentVersion = acc[acc.length - 1]; const versionEvent = analysis.events.find(event => event.category === 'VERSION'); if (versionEvent) { @@ -181,41 +176,45 @@ export const getAnalysesByVersionByDay = ( } return acc; }, []); +} export const getDisplayedHistoryMetrics = ( - graph: string, - customMetrics: Array<string> -): Array<string> => (isCustomGraph(graph) ? customMetrics : GRAPHS_METRICS_DISPLAYED[graph]); + graph /*: string */, + customMetrics /*: Array<string> */ +) => (isCustomGraph(graph) ? customMetrics : GRAPHS_METRICS_DISPLAYED[graph]); -export const getHistoryMetrics = (graph: string, customMetrics: Array<string>): Array<string> => +export const getHistoryMetrics = (graph /*: string */, customMetrics /*: Array<string> */) => isCustomGraph(graph) ? customMetrics : GRAPHS_METRICS[graph]; -const parseGraph = (value?: string): string => { +const parseGraph = (value /*: ?string */) => { const graph = parseAsString(value); return GRAPH_TYPES.includes(graph) ? graph : DEFAULT_GRAPH; }; -const serializeGraph = (value: string): ?string => (value === DEFAULT_GRAPH ? undefined : value); +const serializeGraph = (value /*: string */) => (value === DEFAULT_GRAPH ? undefined : value); -export const parseQuery = (urlQuery: RawQuery): Query => ({ - category: parseAsString(urlQuery['category']), - customMetrics: parseAsArray(urlQuery['custom_metrics'], parseAsString), - from: parseAsDate(urlQuery['from']), - graph: parseGraph(urlQuery['graph']), - project: parseAsString(urlQuery['id']), - to: parseAsDate(urlQuery['to']), - selectedDate: parseAsDate(urlQuery['selected_date']) -}); +export function parseQuery(urlQuery /*: RawQuery */) /*: Query */ { + return { + category: parseAsString(urlQuery['category']), + customMetrics: parseAsArray(urlQuery['custom_metrics'], parseAsString), + from: parseAsDate(urlQuery['from']), + graph: parseGraph(urlQuery['graph']), + project: parseAsString(urlQuery['id']), + to: parseAsDate(urlQuery['to']), + selectedDate: parseAsDate(urlQuery['selected_date']) + }; +} -export const serializeQuery = (query: Query): RawQuery => - cleanQuery({ +export function serializeQuery(query /*: Query */) /*: RawQuery */ { + return cleanQuery({ category: serializeString(query.category), from: serializeDate(query.from), project: serializeString(query.project), to: serializeDate(query.to) }); +} -export const serializeUrlQuery = (query: Query): RawQuery => { +export function serializeUrlQuery(query /*: Query */) /*: RawQuery */ { return cleanQuery({ category: serializeString(query.category), custom_metrics: serializeStringArray(query.customMetrics), @@ -225,4 +224,4 @@ export const serializeUrlQuery = (query: Query): RawQuery => { to: serializeDate(query.to), selected_date: serializeDate(query.selectedDate) }); -}; +} diff --git a/server/sonar-web/src/main/js/apps/projects-admin/ChangeVisibilityForm.js b/server/sonar-web/src/main/js/apps/projects-admin/ChangeVisibilityForm.js index 99f70766510..b04c4c3e8ae 100644 --- a/server/sonar-web/src/main/js/apps/projects-admin/ChangeVisibilityForm.js +++ b/server/sonar-web/src/main/js/apps/projects-admin/ChangeVisibilityForm.js @@ -23,40 +23,44 @@ import Modal from 'react-modal'; import classNames from 'classnames'; import UpgradeOrganizationBox from '../../components/common/UpgradeOrganizationBox'; import { translate } from '../../helpers/l10n'; -import type { Organization } from '../../store/organizations/duck'; +/*:: import type { Organization } from '../../store/organizations/duck'; */ +/*:: type Props = { onClose: () => void, onConfirm: string => void, organization: Organization }; +*/ +/*:: type State = { visibility: string }; +*/ export default class ChangeVisibilityForm extends React.PureComponent { - props: Props; - state: State; + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { visibility: props.organization.projectVisibility }; } - handleCancelClick = (event: Event) => { + handleCancelClick = (event /*: Event */) => { event.preventDefault(); this.props.onClose(); }; - handleConfirmClick = (event: Event) => { + handleConfirmClick = (event /*: Event */) => { event.preventDefault(); this.props.onConfirm(this.state.visibility); this.props.onClose(); }; - handleVisibilityClick = (visibility: string) => ( - event: Event & { currentTarget: HTMLElement } + handleVisibilityClick = (visibility /*: string */) => ( + event /*: Event & { currentTarget: HTMLElement } */ ) => { event.preventDefault(); event.currentTarget.blur(); diff --git a/server/sonar-web/src/main/js/apps/projects-admin/CreateProjectForm.js b/server/sonar-web/src/main/js/apps/projects-admin/CreateProjectForm.js index adb2353292a..fa8e2ea0f6d 100644 --- a/server/sonar-web/src/main/js/apps/projects-admin/CreateProjectForm.js +++ b/server/sonar-web/src/main/js/apps/projects-admin/CreateProjectForm.js @@ -26,15 +26,18 @@ import VisibilitySelector from '../../components/common/VisibilitySelector'; import { createProject } from '../../api/components'; import { translate } from '../../helpers/l10n'; import { getProjectUrl } from '../../helpers/urls'; -import type { Organization } from '../../store/organizations/duck'; +/*:: import type { Organization } from '../../store/organizations/duck'; */ +/*:: type Props = {| onClose: () => void, onProjectCreated: () => void, onRequestFail: Object => void, organization?: Organization |}; +*/ +/*:: type State = { branch: string, createdProject?: Object, @@ -43,13 +46,14 @@ type State = { name: string, visibility: string }; +*/ export default class CreateProjectForm 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 = { branch: '', @@ -68,24 +72,24 @@ export default class CreateProjectForm extends React.PureComponent { this.mounted = false; } - handleCancelClick = (event: Event) => { + handleCancelClick = (event /*: Event */) => { event.preventDefault(); this.props.onClose(); }; - handleInputChange = (event: { currentTarget: HTMLInputElement }) => { + handleInputChange = (event /*: { currentTarget: HTMLInputElement } */) => { const { name, value } = event.currentTarget; this.setState({ [name]: value }); }; - handleVisibilityChange = (visibility: string) => { + handleVisibilityChange = (visibility /*: string */) => { this.setState({ visibility }); }; - handleFormSubmit = (event: Event) => { + handleFormSubmit = (event /*: Event */) => { event.preventDefault(); - const data: { [string]: string } = { + const data /*: { [string]: string } */ = { name: this.state.name, branch: this.state.branch, project: this.state.key, diff --git a/server/sonar-web/src/main/js/apps/projects-admin/header.js b/server/sonar-web/src/main/js/apps/projects-admin/header.js index 8538e20cd73..9fdf7d45ba0 100644 --- a/server/sonar-web/src/main/js/apps/projects-admin/header.js +++ b/server/sonar-web/src/main/js/apps/projects-admin/header.js @@ -21,29 +21,33 @@ import React from 'react'; import ChangeVisibilityForm from './ChangeVisibilityForm'; import { translate } from '../../helpers/l10n'; -import type { Organization } from '../../store/organizations/duck'; +/*:: import type { Organization } from '../../store/organizations/duck'; */ +/*:: type Props = {| hasProvisionPermission: boolean, onProjectCreate: () => void, onVisibilityChange: string => void, organization: Organization |}; +*/ +/*:: type State = { visibilityForm: boolean }; +*/ export default class Header extends React.PureComponent { - props: Props; - state: State = { visibilityForm: false }; + /*:: props: Props; */ + state /*: State */ = { visibilityForm: false }; - handleCreateProjectClick = (event: Event) => { + handleCreateProjectClick = (event /*: Event */) => { event.preventDefault(); this.props.onProjectCreate(); }; - handleChangeVisibilityClick = (event: Event) => { + handleChangeVisibilityClick = (event /*: Event */) => { event.preventDefault(); this.setState({ visibilityForm: true }); }; diff --git a/server/sonar-web/src/main/js/apps/projects-admin/main.js b/server/sonar-web/src/main/js/apps/projects-admin/main.js index 01b9b56fb11..eea76fcf10d 100644 --- a/server/sonar-web/src/main/js/apps/projects-admin/main.js +++ b/server/sonar-web/src/main/js/apps/projects-admin/main.js @@ -29,15 +29,18 @@ import ListFooter from '../../components/controls/ListFooter'; import { PAGE_SIZE, TYPE } from './constants'; import { getComponents, getProvisioned, getGhosts, deleteComponents } from '../../api/components'; import { translate } from '../../helpers/l10n'; -import type { Organization } from '../../store/organizations/duck'; +/*:: import type { Organization } from '../../store/organizations/duck'; */ +/*:: type Props = {| hasProvisionPermission: boolean, onVisibilityChange: string => void, onRequestFail: Object => void, organization: Organization |}; +*/ +/*:: type State = { createProjectForm: boolean, ready: boolean, @@ -49,12 +52,13 @@ type State = { type: string, selection: Array<string> }; +*/ export default class Main extends React.PureComponent { - props: Props; - state: State; + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { createProjectForm: false, @@ -75,7 +79,7 @@ export default class Main extends React.PureComponent { } getFilters = () => { - const filters: { [string]: string | number } = { + const filters /*: { [string]: string | number } */ = { organization: this.props.organization.key, ps: PAGE_SIZE }; @@ -151,7 +155,7 @@ export default class Main extends React.PureComponent { this.setState({ ready: false, page: this.state.page + 1 }, this.requestProjects); }; - onSearch = (query: string) => { + onSearch = (query /*: string */) => { this.setState( { ready: false, @@ -163,7 +167,7 @@ export default class Main extends React.PureComponent { ); }; - onTypeChanged = (newType: string) => { + onTypeChanged = (newType /*: string */) => { this.setState( { ready: false, @@ -177,7 +181,7 @@ export default class Main extends React.PureComponent { ); }; - onQualifierChanged = (newQualifier: string) => { + onQualifierChanged = (newQualifier /*: string */) => { this.setState( { ready: false, @@ -191,12 +195,12 @@ export default class Main extends React.PureComponent { ); }; - onProjectSelected = (project: { key: string }) => { + onProjectSelected = (project /*: { key: string } */) => { const newSelection = uniq([].concat(this.state.selection, project.key)); this.setState({ selection: newSelection }); }; - onProjectDeselected = (project: { key: string }) => { + onProjectDeselected = (project /*: { key: string } */) => { const newSelection = without(this.state.selection, project.key); this.setState({ selection: newSelection }); }; diff --git a/server/sonar-web/src/main/js/apps/projects/components/AllProjects.js b/server/sonar-web/src/main/js/apps/projects/components/AllProjects.js index 37472169965..b08dbaff992 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/AllProjects.js +++ b/server/sonar-web/src/main/js/apps/projects/components/AllProjects.js @@ -29,9 +29,10 @@ import { parseUrlQuery } from '../store/utils'; import { translate } from '../../../helpers/l10n'; import * as utils from '../utils'; import * as storage from '../../../helpers/storage'; -import type { RawQuery } from '../../../helpers/query'; +/*:: import type { RawQuery } from '../../../helpers/query'; */ import '../styles.css'; +/*:: type Props = {| isFavorite: boolean, location: { pathname: string, query: RawQuery }, @@ -43,14 +44,17 @@ type Props = {| }, currentUser?: { isLoggedIn: boolean } |}; +*/ +/*:: type State = { query: RawQuery }; +*/ export default class AllProjects extends React.PureComponent { - props: Props; - state: State = { query: {} }; + /*:: props: Props; */ + state /*: State */ = { query: {} }; componentDidMount() { this.handleQueryChange(true); @@ -58,7 +62,7 @@ export default class AllProjects extends React.PureComponent { footer && footer.classList.add('search-navigator-footer'); } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if (prevProps.location.query !== this.props.location.query) { this.handleQueryChange(false); } @@ -91,8 +95,10 @@ export default class AllProjects extends React.PureComponent { return options; }; - handlePerspectiveChange = ({ view, visualization }: { view: string, visualization?: string }) => { - const query: { view: ?string, visualization: ?string, sort?: ?string } = { + handlePerspectiveChange = ( + { view, visualization } /*: { view: string, visualization?: string } */ + ) => { + const query /*: { view: ?string, visualization: ?string, sort?: ?string } */ = { view: view === 'overall' ? undefined : view, visualization }; @@ -114,13 +120,13 @@ export default class AllProjects extends React.PureComponent { storage.saveVisualization(visualization); }; - handleSortChange = (sort: string, desc: boolean) => { + handleSortChange = (sort /*: string */, desc /*: boolean */) => { const asString = (desc ? '-' : '') + sort; this.updateLocationQuery({ sort: asString }); storage.saveSort(asString); }; - handleQueryChange(initialMount: boolean) { + handleQueryChange(initialMount /*: boolean */) { const query = parseUrlQuery(this.props.location.query); const savedOptions = this.getSavedOptions(); const savedOptionsSet = savedOptions.sort || savedOptions.view || savedOptions.visualization; @@ -134,7 +140,7 @@ export default class AllProjects extends React.PureComponent { } } - updateLocationQuery = (newQuery: { [string]: ?string }) => { + updateLocationQuery = (newQuery /*: { [string]: ?string } */) => { this.props.router.push({ pathname: this.props.location.pathname, query: { diff --git a/server/sonar-web/src/main/js/apps/projects/components/DefaultPageSelector.js b/server/sonar-web/src/main/js/apps/projects/components/DefaultPageSelector.js index d306afcd9db..d040e9e7330 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/DefaultPageSelector.js +++ b/server/sonar-web/src/main/js/apps/projects/components/DefaultPageSelector.js @@ -25,8 +25,9 @@ import AllProjectsContainer from './AllProjectsContainer'; import { getCurrentUser } from '../../../store/rootReducer'; import { isFavoriteSet, isAllSet } from '../../../helpers/storage'; import { searchProjects } from '../../../api/components'; -import type { RawQuery } from '../../../helpers/query'; +/*:: import type { RawQuery } from '../../../helpers/query'; */ +/*:: type Props = { currentUser: { isLoggedIn: boolean }, location: { query: {} }, @@ -34,17 +35,20 @@ type Props = { replace: (location: { pathname?: string, query?: RawQuery }) => void } }; +*/ +/*:: type State = { shouldBeRedirected?: boolean, shouldForceSorting?: string }; +*/ class DefaultPageSelector extends React.PureComponent { - props: Props; - state: State; + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = {}; } @@ -53,7 +57,7 @@ class DefaultPageSelector extends React.PureComponent { this.defineIfShouldBeRedirected(); } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if (prevProps.location !== this.props.location) { this.defineIfShouldBeRedirected(); } else if (this.state.shouldBeRedirected === true) { diff --git a/server/sonar-web/src/main/js/apps/projects/components/FavoriteFilter.js b/server/sonar-web/src/main/js/apps/projects/components/FavoriteFilter.js index d3eb8d65b83..b2e9de9b6e4 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/FavoriteFilter.js +++ b/server/sonar-web/src/main/js/apps/projects/components/FavoriteFilter.js @@ -22,8 +22,9 @@ import React from 'react'; import { IndexLink, Link } from 'react-router'; import { translate } from '../../../helpers/l10n'; import { saveAll, saveFavorite } from '../../../helpers/storage'; -import type { RawQuery } from '../../../helpers/query'; +/*:: import type { RawQuery } from '../../../helpers/query'; */ +/*:: type Props = { user: { isLoggedIn?: boolean @@ -31,9 +32,10 @@ type Props = { organization?: { key: string }, query: RawQuery }; +*/ export default class FavoriteFilter extends React.PureComponent { - props: Props; + /*:: props: Props; */ handleSaveFavorite = () => { if (!this.props.organization) { diff --git a/server/sonar-web/src/main/js/apps/projects/components/PageHeader.js b/server/sonar-web/src/main/js/apps/projects/components/PageHeader.js index 588920ead76..7fddfd1553b 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/PageHeader.js +++ b/server/sonar-web/src/main/js/apps/projects/components/PageHeader.js @@ -25,8 +25,9 @@ import Tooltip from '../../../components/controls/Tooltip'; import PerspectiveSelect from './PerspectiveSelect'; import ProjectsSortingSelect from './ProjectsSortingSelect'; import { translate } from '../../../helpers/l10n'; -import type { RawQuery } from '../../../helpers/query'; +/*:: import type { RawQuery } from '../../../helpers/query'; */ +/*:: type Props = {| currentUser?: { isLoggedIn: boolean }, isFavorite?: boolean, @@ -40,8 +41,9 @@ type Props = {| view: string, visualization?: string |}; +*/ -export default function PageHeader(props: Props) { +export default function PageHeader(props /*: Props */) { const renderSortingSelect = () => { const { projectsAppState, projects, currentUser, view } = props; const limitReached = diff --git a/server/sonar-web/src/main/js/apps/projects/components/PageSidebar.js b/server/sonar-web/src/main/js/apps/projects/components/PageSidebar.js index ab9dcd4326a..28c3f42a14d 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/PageSidebar.js +++ b/server/sonar-web/src/main/js/apps/projects/components/PageSidebar.js @@ -37,8 +37,9 @@ import SecurityFilter from '../filters/SecurityFilter'; import SizeFilter from '../filters/SizeFilter'; import TagsFilterContainer from '../filters/TagsFilterContainer'; import { translate } from '../../../helpers/l10n'; -import type { RawQuery } from '../../../helpers/query'; +/*:: import type { RawQuery } from '../../../helpers/query'; */ +/*:: type Props = { isFavorite: boolean, organization?: { key: string }, @@ -46,14 +47,11 @@ type Props = { view: string, visualization: string }; +*/ -export default function PageSidebar({ - query, - isFavorite, - organization, - view, - visualization -}: Props) { +export default function PageSidebar( + { query, isFavorite, organization, view, visualization } /*: Props */ +) { const isFiltered = Object.keys(query) .filter(key => !['view', 'visualization', 'sort'].includes(key)) .some(key => query[key] != null); @@ -62,11 +60,12 @@ export default function PageSidebar({ const pathname = basePathName + (isFavorite ? '/favorite' : ''); const facetProps = { query, isFavorite, organization }; - let linkQuery: ?{ view: string, visualization?: string }; + let linkQuery; if (view !== 'overall') { linkQuery = { view }; if (view === 'visualizations') { + // $FlowFixMe linkQuery.visualization = visualization; } } diff --git a/server/sonar-web/src/main/js/apps/projects/components/PerspectiveSelect.js b/server/sonar-web/src/main/js/apps/projects/components/PerspectiveSelect.js index 6dff8ffa6de..c892a1eafba 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/PerspectiveSelect.js +++ b/server/sonar-web/src/main/js/apps/projects/components/PerspectiveSelect.js @@ -24,20 +24,24 @@ import PerspectiveSelectOption from './PerspectiveSelectOption'; import { translate } from '../../../helpers/l10n'; import { VIEWS, VISUALIZATIONS } from '../utils'; +/*:: export type Option = { label: string, type: string, value: string }; +*/ +/*:: type Props = {| className?: string, onChange: ({ view: string, visualization?: string }) => void, view: string, visualization?: string |}; +*/ export default class PerspectiveSelect extends React.PureComponent { - options: Array<Option>; - props: Props; + /*:: options: Array<Option>; */ + /*:: props: Props; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.options = [ ...VIEWS.map(opt => ({ @@ -53,7 +57,7 @@ export default class PerspectiveSelect extends React.PureComponent { ]; } - handleChange = (option: Option) => { + handleChange = (option /*: Option */) => { if (option.type === 'view') { this.props.onChange({ view: option.value }); } else if (option.type === 'visualization') { diff --git a/server/sonar-web/src/main/js/apps/projects/components/PerspectiveSelectOption.js b/server/sonar-web/src/main/js/apps/projects/components/PerspectiveSelectOption.js index bef22ae59a9..6fd3307a98d 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/PerspectiveSelectOption.js +++ b/server/sonar-web/src/main/js/apps/projects/components/PerspectiveSelectOption.js @@ -21,8 +21,9 @@ import React from 'react'; import BubblesIcon from '../../../components/icons-components/BubblesIcon'; import ListIcon from '../../../components/icons-components/ListIcon'; -import type { Option } from './PerspectiveSelect'; +/*:: import type { Option } from './PerspectiveSelect'; */ +/*:: type Props = { option: Option, children?: Element | Text, @@ -31,21 +32,22 @@ type Props = { onFocus: (Option, MouseEvent) => void, onSelect: (Option, MouseEvent) => void }; +*/ export default class PerspectiveSelectOption extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleMouseDown = (event: MouseEvent) => { + handleMouseDown = (event /*: MouseEvent */) => { event.preventDefault(); event.stopPropagation(); this.props.onSelect(this.props.option, event); }; - handleMouseEnter = (event: MouseEvent) => { + handleMouseEnter = (event /*: MouseEvent */) => { this.props.onFocus(this.props.option, event); }; - handleMouseMove = (event: MouseEvent) => { + handleMouseMove = (event /*: MouseEvent */) => { if (this.props.isFocused) { return; } diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardContainer.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardContainer.js index 9e71d2559ba..a47d8a82e33 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardContainer.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardContainer.js @@ -23,7 +23,7 @@ import ProjectCardLeak from './ProjectCardLeak'; import ProjectCardOverall from './ProjectCardOverall'; import { getComponent, getComponentMeasures } from '../../../store/rootReducer'; -function ProjectCard(props: { type?: string }) { +function ProjectCard(props /*: { type?: string } */) { if (props.type === 'leak') { return <ProjectCardLeak {...props} />; } diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeak.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeak.js index 6de5f6a687f..b6af4d5cd10 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeak.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeak.js @@ -30,6 +30,7 @@ import TagsList from '../../../components/tags/TagsList'; import PrivateBadge from '../../../components/common/PrivateBadge'; import { translate, translateWithParameters } from '../../../helpers/l10n'; +/*:: type Props = { measures: { [string]: string }, organization?: { key: string }, @@ -44,8 +45,9 @@ type Props = { visibility?: boolean } }; +*/ -export default function ProjectCardLeak({ measures, organization, project }: Props) { +export default function ProjectCardLeak({ measures, organization, project } /*: Props */) { if (project == null) { return null; } diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeakMeasures.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeakMeasures.js index 36de893963f..88d1afde4f3 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeakMeasures.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeakMeasures.js @@ -26,11 +26,13 @@ import Rating from '../../../components/ui/Rating'; import VulnerabilityIcon from '../../../components/icons-components/VulnerabilityIcon'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { measures?: { [string]: string } }; +*/ -export default function ProjectCardLeakMeasures({ measures }: Props) { +export default function ProjectCardLeakMeasures({ measures } /*: Props */) { if (measures == null) { return null; } diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverall.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverall.js index 49c9d27fcc8..5d8cddae025 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverall.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverall.js @@ -30,6 +30,7 @@ import TagsList from '../../../components/tags/TagsList'; import PrivateBadge from '../../../components/common/PrivateBadge'; import { translate, translateWithParameters } from '../../../helpers/l10n'; +/*:: type Props = { measures: { [string]: string }, organization?: { key: string }, @@ -43,8 +44,9 @@ type Props = { visibility?: boolean } }; +*/ -export default function ProjectCardOverall({ measures, organization, project }: Props) { +export default function ProjectCardOverall({ measures, organization, project } /*: Props */) { if (project == null) { return null; } diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverallMeasures.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverallMeasures.js index 701e707657b..fbfce28ae57 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverallMeasures.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverallMeasures.js @@ -27,11 +27,13 @@ import DuplicationsRating from '../../../components/ui/DuplicationsRating'; import SizeRating from '../../../components/ui/SizeRating'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { measures?: { [string]: string } }; +*/ -export default function ProjectCardOverallMeasures({ measures }: Props) { +export default function ProjectCardOverallMeasures({ measures } /*: Props */) { if (measures == null) { return null; } diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardQualityGate.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardQualityGate.js index 585c2648e1c..d73a9223c2c 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardQualityGate.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardQualityGate.js @@ -24,7 +24,7 @@ import Tooltip from '../../../components/controls/Tooltip'; import { formatMeasure } from '../../../helpers/measures'; import { translateWithParameters } from '../../../helpers/l10n'; -export default function ProjectCardQualityGate({ status }: { status?: string }) { +export default function ProjectCardQualityGate({ status } /*: { status?: string } */) { if (!status) { return null; } diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectTagsSelectorContainer.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectTagsSelectorContainer.js index 14b7d37e613..2cb4ab4e54a 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectTagsSelectorContainer.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectTagsSelectorContainer.js @@ -25,24 +25,28 @@ import TagsSelector from '../../../components/tags/TagsSelector'; import { searchProjectTags } from '../../../api/components'; import { setProjectTags } from '../store/actions'; +/*:: type Props = { position: {}, project: string, selectedTags: Array<string>, setProjectTags: (string, Array<string>) => void }; +*/ +/*:: type State = { searchResult: Array<string> }; +*/ const LIST_SIZE = 10; class ProjectTagsSelectorContainer extends React.PureComponent { - props: Props; - state: State; + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { searchResult: [] }; this.onSearch = debounce(this.onSearch, 250); @@ -52,7 +56,7 @@ class ProjectTagsSelectorContainer extends React.PureComponent { this.onSearch(''); } - onSearch = (query: string) => { + onSearch = (query /*: string */) => { searchProjectTags({ q: query || '', ps: Math.min(this.props.selectedTags.length - 1 + LIST_SIZE, 100) @@ -63,11 +67,11 @@ class ProjectTagsSelectorContainer extends React.PureComponent { }); }; - onSelect = (tag: string) => { + onSelect = (tag /*: string */) => { this.props.setProjectTags(this.props.project, [...this.props.selectedTags, tag]); }; - onUnselect = (tag: string) => { + onUnselect = (tag /*: string */) => { this.props.setProjectTags(this.props.project, without(this.props.selectedTags, tag)); }; diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectsList.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectsList.js index 1b2f615bced..c806f94b6d7 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectsList.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectsList.js @@ -24,6 +24,7 @@ import NoFavoriteProjects from './NoFavoriteProjects'; import EmptyInstance from './EmptyInstance'; import EmptySearch from '../../../components/common/EmptySearch'; +/*:: type Props = { projects?: Array<string>, isFavorite: boolean, @@ -31,9 +32,10 @@ type Props = { organization?: { key: string }, cardType?: string }; +*/ export default class ProjectsList extends React.PureComponent { - props: Props; + /*:: props: Props; */ renderNoProjects() { if (this.props.isFavorite && !this.props.isFiltered) { diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelect.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelect.js index fa9fb3b7f00..f4f21fa2bd2 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelect.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelect.js @@ -28,8 +28,11 @@ import Tooltip from '../../../components/controls/Tooltip'; import { translate } from '../../../helpers/l10n'; import { SORTING_METRICS, SORTING_LEAK_METRICS, parseSorting } from '../utils'; +/*:: export type Option = { label: string, value: string, class?: string, short?: string }; +*/ +/*:: type Props = { className?: string, onChange: (sort: string, desc: boolean) => void, @@ -37,22 +40,25 @@ type Props = { view: string, defaultOption: string }; +*/ +/*:: type State = { sortValue: string, sortDesc: boolean }; +*/ export default class ProjectsSortingSelect extends React.PureComponent { - props: Props; - state: State; + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = parseSorting(props.selectedSort); } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if (prevProps.selectedSort !== this.props.selectedSort) { this.setState(parseSorting(this.props.selectedSort)); } @@ -60,23 +66,23 @@ export default class ProjectsSortingSelect extends React.PureComponent { getOptions = () => { const sortMetrics = this.props.view === 'leak' ? SORTING_LEAK_METRICS : SORTING_METRICS; - return sortBy( - sortMetrics, - opt => (opt.value === this.props.defaultOption ? 0 : 1) - ).map((opt: { value: string, class?: string }) => ({ + return sortBy(sortMetrics, opt => (opt.value === this.props.defaultOption ? 0 : 1)).map(( + opt /*: { value: string, class?: string } */ + ) => ({ value: opt.value, label: translate('projects.sorting', opt.value), class: opt.class })); }; - handleDescToggle = (evt: Event & { currentTarget: HTMLElement }) => { + handleDescToggle = (evt /*: Event & { currentTarget: HTMLElement } */) => { evt.preventDefault(); evt.currentTarget.blur(); this.props.onChange(this.state.sortValue, !this.state.sortDesc); }; - handleSortChange = (option: Option) => this.props.onChange(option.value, this.state.sortDesc); + handleSortChange = (option /*: Option */) => + this.props.onChange(option.value, this.state.sortDesc); render() { const { sortDesc } = this.state; diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelectOption.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelectOption.js index 9789a3d30fb..aebb6bb478b 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelectOption.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectsSortingSelectOption.js @@ -20,8 +20,9 @@ //@flow import React from 'react'; import classNames from 'classnames'; -import type { Option } from './ProjectsSortingSelect'; +/*:: import type { Option } from './ProjectsSortingSelect'; */ +/*:: type Props = { option: Option, children?: Element | Text, @@ -30,21 +31,22 @@ type Props = { onFocus: (Option, MouseEvent) => void, onSelect: (Option, MouseEvent) => void }; +*/ export default class ProjectsSortingSelectOption extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleMouseDown = (event: MouseEvent) => { + handleMouseDown = (event /*: MouseEvent */) => { event.preventDefault(); event.stopPropagation(); this.props.onSelect(this.props.option, event); }; - handleMouseEnter = (event: MouseEvent) => { + handleMouseEnter = (event /*: MouseEvent */) => { this.props.onFocus(this.props.option, event); }; - handleMouseMove = (event: MouseEvent) => { + handleMouseMove = (event /*: MouseEvent */) => { if (this.props.isFocused) { return; } diff --git a/server/sonar-web/src/main/js/apps/projects/filters/Filter.js b/server/sonar-web/src/main/js/apps/projects/filters/Filter.js index a00b11ef2a3..d39cd7ee2d2 100644 --- a/server/sonar-web/src/main/js/apps/projects/filters/Filter.js +++ b/server/sonar-web/src/main/js/apps/projects/filters/Filter.js @@ -68,7 +68,7 @@ export default class Filter extends React.PureComponent { ); } - blurOnClick = (evt: Event & { currentTarget: HTMLElement }) => evt.currentTarget.blur(); + blurOnClick = (evt /*: Event & { currentTarget: HTMLElement } */) => evt.currentTarget.blur(); getPath(option) { const { property, value } = this.props; diff --git a/server/sonar-web/src/main/js/apps/projects/filters/FilterHeader.js b/server/sonar-web/src/main/js/apps/projects/filters/FilterHeader.js index 11d9d790662..51b3512ca0e 100644 --- a/server/sonar-web/src/main/js/apps/projects/filters/FilterHeader.js +++ b/server/sonar-web/src/main/js/apps/projects/filters/FilterHeader.js @@ -20,13 +20,15 @@ //@flow import React from 'react'; +/*:: type Props = { name: string, children?: React.Element<*> }; +*/ export default class FilterHeader extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { return ( diff --git a/server/sonar-web/src/main/js/apps/projects/filters/LanguagesFilter.js b/server/sonar-web/src/main/js/apps/projects/filters/LanguagesFilter.js index 6548c9441e0..833a7d810e7 100644 --- a/server/sonar-web/src/main/js/apps/projects/filters/LanguagesFilter.js +++ b/server/sonar-web/src/main/js/apps/projects/filters/LanguagesFilter.js @@ -27,6 +27,7 @@ import SearchableFilterOption from './SearchableFilterOption'; import { getLanguageByKey } from '../../../store/languages/reducer'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { query: {}, languages: {}, @@ -37,14 +38,18 @@ type Props = { organization?: {}, maxFacetValue?: number }; +*/ const LIST_SIZE = 10; export default class LanguagesFilter extends React.PureComponent { - props: Props; + /*:: props: Props; */ property = 'languages'; - getSearchOptions(facet?: {}, languages: {}): Array<{ label: string, value: string }> { + getSearchOptions( + facet /*: ?{} */, + languages /*: {} */ + ) /*: Array<{ label: string, value: string }> */ { let languageKeys = Object.keys(languages); if (facet) { languageKeys = difference(languageKeys, Object.keys(facet)); @@ -54,13 +59,13 @@ export default class LanguagesFilter extends React.PureComponent { .map(key => ({ label: languages[key].name, value: key })); } - getSortedOptions(facet: {} = {}) { + getSortedOptions(facet /*: {} */ = {}) { return sortBy(Object.keys(facet), [option => -facet[option], option => option]); } - getFacetValueForOption = (facet: {} = {}, option: string) => facet[option]; + getFacetValueForOption = (facet /*: {} */ = {}, option /*: string */) => facet[option]; - renderOption = (option: string) => + renderOption = (option /*: string */) => <SearchableFilterOption optionKey={option} option={getLanguageByKey(this.props.languages, option)} diff --git a/server/sonar-web/src/main/js/apps/projects/filters/SearchFilter.js b/server/sonar-web/src/main/js/apps/projects/filters/SearchFilter.js index 506bec6175f..5439403b3ad 100644 --- a/server/sonar-web/src/main/js/apps/projects/filters/SearchFilter.js +++ b/server/sonar-web/src/main/js/apps/projects/filters/SearchFilter.js @@ -21,28 +21,32 @@ import React from 'react'; import { translate, translateWithParameters } from '../../../helpers/l10n'; +/*:: type Props = { className?: string, handleSearch: (userString?: string) => void, query: { search?: string } }; +*/ +/*:: type State = { userQuery?: string }; +*/ export default class SearchFilter extends React.PureComponent { - props: Props; - state: State; + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { userQuery: props.query.search }; } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if ( this.props.query.search === this.state.userQuery && nextProps.query.search !== this.props.query.search @@ -53,7 +57,7 @@ export default class SearchFilter extends React.PureComponent { } } - handleQueryChange = ({ target }: { target: HTMLInputElement }) => { + handleQueryChange = ({ target } /*: { target: HTMLInputElement } */) => { this.setState({ userQuery: target.value }); if (!target.value || target.value.length >= 2) { this.props.handleSearch(target.value); diff --git a/server/sonar-web/src/main/js/apps/projects/filters/SearchFilterContainer.js b/server/sonar-web/src/main/js/apps/projects/filters/SearchFilterContainer.js index 74b16a51ae3..6e64dbf9bec 100644 --- a/server/sonar-web/src/main/js/apps/projects/filters/SearchFilterContainer.js +++ b/server/sonar-web/src/main/js/apps/projects/filters/SearchFilterContainer.js @@ -24,6 +24,7 @@ import { debounce } from 'lodash'; import { getFilterUrl } from './utils'; import SearchFilter from './SearchFilter'; +/*:: type Props = {| className?: string, query: { search?: string }, @@ -31,17 +32,18 @@ type Props = {| isFavorite?: boolean, organization?: {} |}; +*/ class SearchFilterContainer extends React.PureComponent { - handleSearch: (userQuery?: string) => void; - props: Props; + /*:: handleSearch: (userQuery?: string) => void; */ + /*:: props: Props; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.handleSearch = debounce(this.handleSearch.bind(this), 250); } - handleSearch(userQuery?: string) { + handleSearch(userQuery /*: ?string */) { const path = getFilterUrl(this.props, { search: userQuery || null }); this.props.router.push(path); } diff --git a/server/sonar-web/src/main/js/apps/projects/filters/SearchableFilterFooter.js b/server/sonar-web/src/main/js/apps/projects/filters/SearchableFilterFooter.js index e5b739e8429..25b7ff076d7 100644 --- a/server/sonar-web/src/main/js/apps/projects/filters/SearchableFilterFooter.js +++ b/server/sonar-web/src/main/js/apps/projects/filters/SearchableFilterFooter.js @@ -23,6 +23,7 @@ import Select from 'react-select'; import { getFilterUrl } from './utils'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { property: string, query: {}, @@ -34,11 +35,12 @@ type Props = { isFavorite?: boolean, organization?: {} }; +*/ export default class SearchableFilterFooter extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleOptionChange: ({ value: string }) => void = ({ value }) => { + handleOptionChange /*: ({ value: string }) => void */ = ({ value }) => { const urlOptions = (this.props.query[this.props.property] || []).concat(value).join(','); const path = getFilterUrl(this.props, { [this.props.property]: urlOptions }); this.props.router.push(path); diff --git a/server/sonar-web/src/main/js/apps/projects/filters/TagsFilter.js b/server/sonar-web/src/main/js/apps/projects/filters/TagsFilter.js index 7fb48d31783..22c5bfcb377 100644 --- a/server/sonar-web/src/main/js/apps/projects/filters/TagsFilter.js +++ b/server/sonar-web/src/main/js/apps/projects/filters/TagsFilter.js @@ -27,6 +27,7 @@ import SearchableFilterOption from './SearchableFilterOption'; import { searchProjectTags } from '../../../api/components'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { query: {}, router: { push: ({ pathname: string, query?: {} }) => void }, @@ -36,21 +37,24 @@ type Props = { organization?: {}, maxFacetValue?: number }; +*/ +/*:: type State = { isLoading: boolean, search: string, tags: Array<string> }; +*/ const LIST_SIZE = 10; export default class TagsFilter extends React.PureComponent { - props: Props; - state: State; - property: string; + /*:: props: Props; */ + /*:: state: State; */ + /*:: property: string; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { isLoading: false, @@ -61,7 +65,10 @@ export default class TagsFilter extends React.PureComponent { this.handleSearch = debounce(this.handleSearch.bind(this), 250); } - getSearchOptions(facet?: {}, tags: Array<string>): Array<{ label: string, value: string }> { + getSearchOptions( + facet /*: ?{} */, + tags /*: Array<string> */ + ) /*: Array<{ label: string, value: string }> */ { let tagsCopy = [...tags]; if (facet) { tagsCopy = difference(tagsCopy, Object.keys(facet)); @@ -69,7 +76,7 @@ export default class TagsFilter extends React.PureComponent { return tagsCopy.slice(0, LIST_SIZE).map(tag => ({ label: tag, value: tag })); } - handleSearch = (search?: string) => { + handleSearch = (search /*: ?string */) => { if (search !== this.state.search) { search = search || ''; this.setState({ search, isLoading: true }); @@ -82,13 +89,13 @@ export default class TagsFilter extends React.PureComponent { } }; - getSortedOptions(facet: {} = {}) { + getSortedOptions(facet /*: {} */ = {}) { return sortBy(Object.keys(facet), [option => -facet[option], option => option]); } - getFacetValueForOption = (facet: {}, option: string) => facet[option]; + getFacetValueForOption = (facet /*: {} */, option /*: string */) => facet[option]; - renderOption = (option: string) => <SearchableFilterOption optionKey={option} />; + renderOption = (option /*: string */) => <SearchableFilterOption optionKey={option} />; render() { return ( diff --git a/server/sonar-web/src/main/js/apps/projects/utils.js b/server/sonar-web/src/main/js/apps/projects/utils.js index 02f2ae59d59..b322061f662 100644 --- a/server/sonar-web/src/main/js/apps/projects/utils.js +++ b/server/sonar-web/src/main/js/apps/projects/utils.js @@ -70,11 +70,11 @@ export const VISUALIZATIONS = [ 'duplications' ]; -export const localizeSorting = (sort?: string) => { +export const localizeSorting = (sort /*: ?string */) => { return translate('projects.sort', sort || 'name'); }; -export const parseSorting = (sort: string): { sortValue: string, sortDesc: boolean } => { +export function parseSorting(sort /*: string */) /*: { sortValue: string, sortDesc: boolean } */ { const desc = sort[0] === '-'; return { sortValue: desc ? sort.substr(1) : sort, sortDesc: desc }; -}; +} diff --git a/server/sonar-web/src/main/js/apps/projects/visualizations/Risk.js b/server/sonar-web/src/main/js/apps/projects/visualizations/Risk.js index d69b6bfce49..880b07fa10a 100644 --- a/server/sonar-web/src/main/js/apps/projects/visualizations/Risk.js +++ b/server/sonar-web/src/main/js/apps/projects/visualizations/Risk.js @@ -26,12 +26,14 @@ import { translate, translateWithParameters } from '../../../helpers/l10n'; import { RATING_COLORS } from '../../../helpers/constants'; import { getProjectUrl } from '../../../helpers/urls'; +/*:: type Project = { key: string, measures: { [string]: string }, name: string, organization?: { name: string } }; +*/ const X_METRIC = 'sqale_index'; const X_METRIC_TYPE = 'SHORT_WORK_DUR'; @@ -44,24 +46,25 @@ const COLOR_METRIC_2 = 'security_rating'; const COLOR_METRIC_TYPE = 'RATING'; export default class Risk extends React.PureComponent { - props: { + /*:: props: { displayOrganizations: boolean, projects: Array<Project> }; +*/ - getMetricTooltip(metric: { key: string, type: string }, value: ?number) { + getMetricTooltip(metric /*: { key: string, type: string } */, value /*: ?number */) { const name = translate('metric', metric.key, 'name'); const formattedValue = value != null ? formatMeasure(value, metric.type) : '–'; return `<div>${name}: ${formattedValue}</div>`; } getTooltip( - project: Project, - x: ?number, - y: ?number, - size: ?number, - color1: ?number, - color2: ?number + project /*: Project */, + x /*: ?number */, + y /*: ?number */, + size /*: ?number */, + color1 /*: ?number */, + color2 /*: ?number */ ) { const fullProjectName = this.props.displayOrganizations && project.organization diff --git a/server/sonar-web/src/main/js/apps/projects/visualizations/SimpleBubbleChart.js b/server/sonar-web/src/main/js/apps/projects/visualizations/SimpleBubbleChart.js index 44ddf736040..a1ccdf18a0b 100644 --- a/server/sonar-web/src/main/js/apps/projects/visualizations/SimpleBubbleChart.js +++ b/server/sonar-web/src/main/js/apps/projects/visualizations/SimpleBubbleChart.js @@ -26,17 +26,21 @@ import { translate, translateWithParameters } from '../../../helpers/l10n'; import { RATING_COLORS } from '../../../helpers/constants'; import { getProjectUrl } from '../../../helpers/urls'; +/*:: type Metric = { key: string, type: string }; +*/ +/*:: type Project = { key: string, measures: { [string]: string }, name: string, organization?: { name: string } }; +*/ export default class SimpleBubbleChart extends React.PureComponent { - props: { + /*:: props: { displayOrganizations: boolean, projects: Array<Project>, sizeMetric: Metric, @@ -45,14 +49,21 @@ export default class SimpleBubbleChart extends React.PureComponent { yMetric: Metric, colorMetric?: string }; +*/ - getMetricTooltip(metric: Metric, value: ?number) { + getMetricTooltip(metric /*: Metric */, value /*: ?number */) { const name = translate('metric', metric.key, 'name'); const formattedValue = value != null ? formatMeasure(value, metric.type) : '–'; return `<div>${name}: ${formattedValue}</div>`; } - getTooltip(project: Project, x: ?number, y: ?number, size: ?number, color?: number) { + getTooltip( + project /*: Project */, + x /*: ?number */, + y /*: ?number */, + size /*: ?number */, + color /*: ?number */ + ) { const fullProjectName = this.props.displayOrganizations && project.organization ? `${project.organization.name} / <strong>${project.name}</strong>` diff --git a/server/sonar-web/src/main/js/apps/projects/visualizations/Visualizations.js b/server/sonar-web/src/main/js/apps/projects/visualizations/Visualizations.js index ee32e11c30f..661a67d0b21 100644 --- a/server/sonar-web/src/main/js/apps/projects/visualizations/Visualizations.js +++ b/server/sonar-web/src/main/js/apps/projects/visualizations/Visualizations.js @@ -29,15 +29,16 @@ import { localizeSorting } from '../utils'; import { translate, translateWithParameters } from '../../../helpers/l10n'; export default class Visualizations extends React.PureComponent { - props: { + /*:: props: { displayOrganizations: boolean, projects?: Array<*>, sort?: string, total?: number, visualization: string }; +*/ - renderVisualization(projects: Array<*>) { + renderVisualization(projects /*: Array<*> */) { const visualizationToComponent = { risk: Risk, reliability: Reliability, diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/Changelog.js b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/Changelog.js index 01ae2464b8e..7eeb76ee8f8 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/Changelog.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/Changelog.js @@ -25,6 +25,7 @@ import ChangesList from './ChangesList'; import { translate } from '../../../helpers/l10n'; import { getRulesUrl } from '../../../helpers/urls'; +/*:: type Props = { events: Array<{ action: string, @@ -36,9 +37,10 @@ type Props = { }>, organization: ?string }; +*/ export default class Changelog extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { let isEvenRow = false; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogContainer.js b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogContainer.js index d7088601445..6bca8f58b0f 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogContainer.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogContainer.js @@ -26,8 +26,9 @@ import ChangelogEmpty from './ChangelogEmpty'; import { getProfileChangelog } from '../../../api/quality-profiles'; import { translate } from '../../../helpers/l10n'; import { getProfileChangelogPath } from '../utils'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ +/*:: type Props = { location: { query: { @@ -38,23 +39,26 @@ type Props = { organization: ?string, profile: Profile }; +*/ +/*:: type State = { events?: Array<*>, loading: boolean, page?: number, total?: number }; +*/ export default class ChangelogContainer extends React.PureComponent { - mounted: boolean; - props: Props; + /*:: mounted: boolean; */ + /*:: props: Props; */ static contextTypes = { router: PropTypes.object }; - state: State = { + state /*: State */ = { loading: true }; @@ -63,7 +67,7 @@ export default class ChangelogContainer extends React.PureComponent { this.loadChangelog(); } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if (prevProps.location !== this.props.location) { this.loadChangelog(); } @@ -76,7 +80,7 @@ export default class ChangelogContainer extends React.PureComponent { loadChangelog() { this.setState({ loading: true }); const { query } = this.props.location; - const data: Object = { profileKey: this.props.profile.key }; + const data /*: Object */ = { profileKey: this.props.profile.key }; if (query.since) { data.since = query.since; } @@ -96,13 +100,13 @@ export default class ChangelogContainer extends React.PureComponent { }); } - loadMore(e: SyntheticInputEvent) { + loadMore(e /*: SyntheticInputEvent */) { e.preventDefault(); e.target.blur(); this.setState({ loading: true }); const { query } = this.props.location; - const data: Object = { + const data /*: Object */ = { profileKey: this.props.profile.key, p: this.state.page + 1 }; @@ -125,7 +129,7 @@ export default class ChangelogContainer extends React.PureComponent { }); } - handleFromDateChange = (fromDate?: string) => { + handleFromDateChange = (fromDate /*: string | void */) => { const path = getProfileChangelogPath( this.props.profile.name, this.props.profile.language, @@ -138,7 +142,7 @@ export default class ChangelogContainer extends React.PureComponent { this.context.router.push(path); }; - handleToDateChange = (toDate?: string) => { + handleToDateChange = (toDate /*: string | void */) => { const path = getProfileChangelogPath( this.props.profile.name, this.props.profile.language, diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogSearch.js b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogSearch.js index 89d2099a229..c0abdb0155a 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogSearch.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogSearch.js @@ -22,6 +22,7 @@ import React from 'react'; import DateInput from '../../../components/controls/DateInput'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { fromDate?: string, toDate?: string, @@ -29,11 +30,12 @@ type Props = { onReset: () => void, onToDateChange: () => void }; +*/ export default class ChangelogSearch extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleResetClick(e: SyntheticInputEvent) { + handleResetClick(e /*: SyntheticInputEvent */) { e.preventDefault(); e.target.blur(); this.props.onReset(); diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangesList.js b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangesList.js index f905a86df53..c910ebb54ab 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangesList.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangesList.js @@ -22,12 +22,14 @@ import React from 'react'; import SeverityChange from './SeverityChange'; import ParameterChange from './ParameterChange'; +/*:: type Props = { changes: { [string]: ?string } }; +*/ export default class ChangesList extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const { changes } = this.props; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ParameterChange.js b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ParameterChange.js index d4e01d55b72..9ee9d2bd80f 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ParameterChange.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ParameterChange.js @@ -21,13 +21,15 @@ import React from 'react'; import { translateWithParameters } from '../../../helpers/l10n'; +/*:: type Props = { name: string, value: ?string }; +*/ export default class ParameterChange extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const { name, value } = this.props; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/SeverityChange.js b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/SeverityChange.js index d1ead07091a..546c46610c2 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/SeverityChange.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/SeverityChange.js @@ -22,12 +22,14 @@ import React from 'react'; import SeverityHelper from '../../../components/shared/SeverityHelper'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { severity: ?string }; +*/ export default class SeverityChange extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { return ( diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonContainer.js b/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonContainer.js index a7258bce199..718d80dcc3d 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonContainer.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonContainer.js @@ -24,15 +24,18 @@ import ComparisonForm from './ComparisonForm'; import ComparisonResults from './ComparisonResults'; import { compareProfiles } from '../../../api/quality-profiles'; import { getProfileComparePath } from '../utils'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ +/*:: type Props = { location: { query: { withKey?: string } }, organization: ?string, profile: Profile, profiles: Array<Profile> }; +*/ +/*:: type State = { loading: boolean, left?: { name: string }, @@ -41,17 +44,18 @@ type State = { inRight?: Array<*>, modified?: Array<*> }; +*/ export default class ComparisonContainer extends React.PureComponent { - mounted: boolean; - props: Props; - state: State; + /*:: mounted: boolean; */ + /*:: props: Props; */ + /*:: state: State; */ static contextTypes = { router: PropTypes.object }; - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { loading: false }; } @@ -61,7 +65,7 @@ export default class ComparisonContainer extends React.PureComponent { this.loadResults(); } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if (prevProps.profile !== this.props.profile || prevProps.location !== this.props.location) { this.loadResults(); } @@ -93,7 +97,7 @@ export default class ComparisonContainer extends React.PureComponent { }); } - handleCompare = (withKey: string) => { + handleCompare = (withKey /*: string */) => { const path = getProfileComparePath( this.props.profile.name, this.props.profile.language, diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonForm.js b/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonForm.js index 4f3d4870fea..c0a0086f006 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonForm.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonForm.js @@ -21,19 +21,21 @@ import React from 'react'; import Select from 'react-select'; import { translate } from '../../../helpers/l10n'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ +/*:: type Props = { profile: Profile, profiles: Array<Profile>, onCompare: string => void, withKey: string }; +*/ export default class ComparisonForm extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleChange(option: { value: string }) { + handleChange(option /*: { value: string } */) { this.props.onCompare(option.value); } diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonResults.js b/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonResults.js index 208346cc636..b13c88ecace 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonResults.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonResults.js @@ -25,8 +25,11 @@ import SeverityIcon from '../../../components/shared/SeverityIcon'; import { translateWithParameters } from '../../../helpers/l10n'; import { getRulesUrl } from '../../../helpers/urls'; +/*:: type Params = { [string]: string }; +*/ +/*:: type Props = { left: { name: string }, right: { name: string }, @@ -35,11 +38,12 @@ type Props = { modified: Array<*>, organization: ?string }; +*/ export default class ComparisonResults extends React.PureComponent { - props: Props; + /*:: props: Props; */ - renderRule(rule: { key: string, name: string }, severity: string) { + renderRule(rule /*: { key: string, name: string } */, severity /*: string */) { return ( <div> <SeverityIcon severity={severity} />{' '} @@ -48,7 +52,7 @@ export default class ComparisonResults extends React.PureComponent { ); } - renderParameters(params: Params) { + renderParameters(params /*: Params */) { if (!params) { return null; } diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/components/App.js b/server/sonar-web/src/main/js/apps/quality-profiles/components/App.js index 81cb730053a..b0f80ee623b 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/components/App.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/components/App.js @@ -23,9 +23,10 @@ import { searchQualityProfiles, getExporters } from '../../../api/quality-profil import { sortProfiles } from '../utils'; import { translate } from '../../../helpers/l10n'; import OrganizationHelmet from '../../../components/common/OrganizationHelmet'; -import type { Exporter } from '../propTypes'; +/*:: import type { Exporter } from '../propTypes'; */ import '../styles.css'; +/*:: type Props = { children: React.Element<*>, currentUser: { permissions: { global: Array<string> } }, @@ -33,17 +34,20 @@ type Props = { onRequestFail: Object => void, organization: { name: string, canAdmin?: boolean, key: string } | null }; +*/ +/*:: type State = { loading: boolean, exporters?: Array<Exporter>, profiles?: Array<*> }; +*/ export default class App extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { loading: true }; + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { loading: true }; componentWillMount() { const html = document.querySelector('html'); diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/components/BuiltInBadge.js b/server/sonar-web/src/main/js/apps/quality-profiles/components/BuiltInBadge.js index 1e85d72c473..fa2e1635620 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/components/BuiltInBadge.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/components/BuiltInBadge.js @@ -23,12 +23,14 @@ import classNames from 'classnames'; import Tooltip from '../../../components/controls/Tooltip'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = {| className?: string, tooltip?: boolean |}; +*/ -export default function BuiltInBadge(props: Props) { +export default function BuiltInBadge(props /*: Props */) { const badge = ( <div className={classNames('outline-badge', props.className)}> {translate('quality_profiles.built_in')} diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/components/CopyProfileForm.js b/server/sonar-web/src/main/js/apps/quality-profiles/components/CopyProfileForm.js index ca7cf6363e3..4ad268e4982 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/components/CopyProfileForm.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/components/CopyProfileForm.js @@ -20,26 +20,30 @@ // @flow import React from 'react'; import Modal from 'react-modal'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ import { copyProfile } from '../../../api/quality-profiles'; import { translate, translateWithParameters } from '../../../helpers/l10n'; +/*:: type Props = { onClose: () => void, onCopy: string => void, onRequestFail: Object => void, profile: Profile }; +*/ +/*:: type State = { loading: boolean, name: ?string }; +*/ export default class CopyProfileForm extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { loading: false, name: null }; + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { loading: false, name: null }; componentDidMount() { this.mounted = true; @@ -49,16 +53,16 @@ export default class CopyProfileForm extends React.PureComponent { this.mounted = false; } - handleCancelClick = (event: Event) => { + handleCancelClick = (event /*: Event */) => { event.preventDefault(); this.props.onClose(); }; - handleNameChange = (event: { currentTarget: HTMLInputElement }) => { + handleNameChange = (event /*: { currentTarget: HTMLInputElement } */) => { this.setState({ name: event.currentTarget.value }); }; - handleFormSubmit = (event: Event) => { + handleFormSubmit = (event /*: Event */) => { event.preventDefault(); const { name } = this.state; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/components/DeleteProfileForm.js b/server/sonar-web/src/main/js/apps/quality-profiles/components/DeleteProfileForm.js index d83588a3baa..975ca0a32db 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/components/DeleteProfileForm.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/components/DeleteProfileForm.js @@ -20,25 +20,29 @@ // @flow import React from 'react'; import Modal from 'react-modal'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ import { deleteProfile } from '../../../api/quality-profiles'; import { translate, translateWithParameters } from '../../../helpers/l10n'; +/*:: type Props = { onClose: () => void, onDelete: () => void, onRequestFail: Object => void, profile: Profile }; +*/ +/*:: type State = { loading: boolean }; +*/ export default class DeleteProfileForm extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { loading: false, name: null }; + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { loading: false, name: null }; componentDidMount() { this.mounted = true; @@ -48,12 +52,12 @@ export default class DeleteProfileForm extends React.PureComponent { this.mounted = false; } - handleCancelClick = (event: Event) => { + handleCancelClick = (event /*: Event */) => { event.preventDefault(); this.props.onClose(); }; - handleFormSubmit = (event: Event) => { + handleFormSubmit = (event /*: Event */) => { event.preventDefault(); this.setState({ loading: true }); deleteProfile(this.props.profile.key).then(this.props.onDelete, error => { diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileActions.js b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileActions.js index 723a283b51c..8a2b2f805f0 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileActions.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileActions.js @@ -28,8 +28,9 @@ import { translate } from '../../../helpers/l10n'; import { getRulesUrl } from '../../../helpers/urls'; import { setDefaultProfile } from '../../../api/quality-profiles'; import { getProfilePath, getProfileComparePath, getProfilesPath } from '../utils'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ +/*:: type Props = { canAdmin: boolean, fromList: boolean, @@ -38,16 +39,19 @@ type Props = { profile: Profile, updateProfiles: () => Promise<*> }; +*/ +/*:: type State = { copyFormOpen: boolean, deleteFormOpen: boolean, renameFormOpen: boolean }; +*/ export default class ProfileActions extends React.PureComponent { - props: Props; - state: State; + /*:: props: Props; */ + /*:: state: State; */ static defaultProps = { fromList: false @@ -57,7 +61,7 @@ export default class ProfileActions extends React.PureComponent { router: PropTypes.object }; - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { copyFormOpen: false, @@ -66,12 +70,12 @@ export default class ProfileActions extends React.PureComponent { }; } - handleRenameClick = (event: Event) => { + handleRenameClick = (event /*: Event */) => { event.preventDefault(); this.setState({ renameFormOpen: true }); }; - handleProfileRename = (name: string) => { + handleProfileRename = (name /*: string */) => { this.closeRenameForm(); this.props.updateProfiles().then(() => { if (!this.props.fromList) { @@ -86,12 +90,12 @@ export default class ProfileActions extends React.PureComponent { this.setState({ renameFormOpen: false }); }; - handleCopyClick = (event: Event) => { + handleCopyClick = (event /*: Event */) => { event.preventDefault(); this.setState({ copyFormOpen: true }); }; - handleProfileCopy = (name: string) => { + handleProfileCopy = (name /*: string */) => { this.props.updateProfiles().then(() => { this.context.router.push( getProfilePath(name, this.props.profile.language, this.props.organization) @@ -103,12 +107,12 @@ export default class ProfileActions extends React.PureComponent { this.setState({ copyFormOpen: false }); }; - handleSetDefaultClick = (e: SyntheticInputEvent) => { + handleSetDefaultClick = (e /*: SyntheticInputEvent */) => { e.preventDefault(); setDefaultProfile(this.props.profile.key).then(this.props.updateProfiles); }; - handleDeleteClick = (event: Event) => { + handleDeleteClick = (event /*: Event */) => { event.preventDefault(); this.setState({ deleteFormOpen: true }); }; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileContainer.js b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileContainer.js index 25ddb0e6391..f44f53c9e35 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileContainer.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileContainer.js @@ -22,8 +22,9 @@ import React from 'react'; import Helmet from 'react-helmet'; import ProfileNotFound from './ProfileNotFound'; import ProfileHeader from '../details/ProfileHeader'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ +/*:: type Props = { canAdmin: boolean, children: React.Element<*>, @@ -37,9 +38,10 @@ type Props = { router: { replace: ({}) => void }, updateProfiles: () => Promise<*> }; +*/ export default class ProfileContainer extends React.PureComponent { - props: Props; + /*:: props: Props; */ componentDidMount() { const { location, profiles, router } = this.props; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileDate.js b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileDate.js index 67d3ad79a87..ae878a4ba6b 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileDate.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileDate.js @@ -22,12 +22,14 @@ import React from 'react'; import moment from 'moment'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { date?: string }; +*/ export default class ProfileDate extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const { date } = this.props; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileLink.js b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileLink.js index 0eb92cb0105..2ff0534c108 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileLink.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileLink.js @@ -22,15 +22,17 @@ import React from 'react'; import { Link } from 'react-router'; import { getProfilePath } from '../utils'; +/*:: type Props = { children?: React.Element<*>, language: string, name: string, organization: ?string }; +*/ export default class ProfileLink extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const { name, language, organization, children, ...other } = this.props; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileNotFound.js b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileNotFound.js index 7401007841d..7dce1cc0ce1 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileNotFound.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileNotFound.js @@ -23,12 +23,14 @@ import { IndexLink } from 'react-router'; import { translate } from '../../../helpers/l10n'; import { getProfilesPath } from '../utils'; +/*:: type Props = { organization: ?string }; +*/ export default class ProfileNotFound extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { return ( diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/components/RenameProfileForm.js b/server/sonar-web/src/main/js/apps/quality-profiles/components/RenameProfileForm.js index a75ba8197ec..37d63394d21 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/components/RenameProfileForm.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/components/RenameProfileForm.js @@ -20,26 +20,30 @@ // @flow import React from 'react'; import Modal from 'react-modal'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ import { renameProfile } from '../../../api/quality-profiles'; import { translate, translateWithParameters } from '../../../helpers/l10n'; +/*:: type Props = { onClose: () => void, onRename: string => void, onRequestFail: Object => void, profile: Profile }; +*/ +/*:: type State = { loading: boolean, name: ?string }; +*/ export default class RenameProfileForm extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { loading: false, name: null }; + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { loading: false, name: null }; componentDidMount() { this.mounted = true; @@ -49,16 +53,16 @@ export default class RenameProfileForm extends React.PureComponent { this.mounted = false; } - handleCancelClick = (event: Event) => { + handleCancelClick = (event /*: Event */) => { event.preventDefault(); this.props.onClose(); }; - handleNameChange = (event: { currentTarget: HTMLInputElement }) => { + handleNameChange = (event /*: { currentTarget: HTMLInputElement } */) => { this.setState({ name: event.currentTarget.value }); }; - handleFormSubmit = (event: Event) => { + handleFormSubmit = (event /*: Event */) => { event.preventDefault(); const { name } = this.state; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ChangeParentForm.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/ChangeParentForm.js index a14e64384b8..f7d019e63d8 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ChangeParentForm.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ChangeParentForm.js @@ -24,8 +24,9 @@ import Select from 'react-select'; import { sortBy } from 'lodash'; import { changeProfileParent } from '../../../api/quality-profiles'; import { translate } from '../../../helpers/l10n'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ +/*:: type Props = { onChange: () => void, onClose: () => void, @@ -33,16 +34,19 @@ type Props = { profile: Profile, profiles: Array<Profile> }; +*/ +/*:: type State = { loading: boolean, selected: ?string }; +*/ export default class ChangeParentForm extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { loading: false, selected: null }; @@ -55,16 +59,16 @@ export default class ChangeParentForm extends React.PureComponent { this.mounted = false; } - handleCancelClick = (event: Event) => { + handleCancelClick = (event /*: Event */) => { event.preventDefault(); this.props.onClose(); }; - handleSelectChange = (option: { value: string }) => { + handleSelectChange = (option /*: { value: string } */) => { this.setState({ selected: option.value }); }; - handleFormSubmit = (event: Event) => { + handleFormSubmit = (event /*: Event */) => { event.preventDefault(); const parent = this.state.selected; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ChangeProjectsForm.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/ChangeProjectsForm.js index 821bb7c80e2..a3277635118 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ChangeProjectsForm.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ChangeProjectsForm.js @@ -21,21 +21,23 @@ import React from 'react'; import Modal from 'react-modal'; import escapeHtml from 'escape-html'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ import SelectList from '../../../components/SelectList'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { onClose: () => void, organization: ?string, profile: Profile }; +*/ export default class ChangeProjectsForm extends React.PureComponent { - container: HTMLElement; - props: Props; + /*:: container: HTMLElement; */ + /*:: props: Props; */ - handleCloseClick = (event: Event) => { + handleCloseClick = (event /*: Event */) => { event.preventDefault(); this.props.onClose(); }; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileDetails.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileDetails.js index 9417f4cf0c9..b157db49a68 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileDetails.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileDetails.js @@ -23,8 +23,9 @@ import ProfileRules from './ProfileRules'; import ProfileProjects from './ProfileProjects'; import ProfileInheritance from './ProfileInheritance'; import ProfileExporters from './ProfileExporters'; -import type { Profile, Exporter } from '../propTypes'; +/*:: import type { Profile, Exporter } from '../propTypes'; */ +/*:: type Props = { canAdmin: boolean, exporters: Array<Exporter>, @@ -34,9 +35,10 @@ type Props = { profiles: Array<Profile>, updateProfiles: () => Promise<*> }; +*/ export default class ProfileDetails extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { return ( diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileExporters.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileExporters.js index 2d387eff92c..04f3c58df29 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileExporters.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileExporters.js @@ -21,22 +21,24 @@ import { stringify } from 'querystring'; import React from 'react'; import { translate } from '../../../helpers/l10n'; -import type { Profile, Exporter } from '../propTypes'; +/*:: import type { Profile, Exporter } from '../propTypes'; */ +/*:: type Props = { exporters: Array<Exporter>, organization: ?string, profile: Profile }; +*/ export default class ProfileExporters extends React.PureComponent { - props: Props; + /*:: props: Props; */ - getExportUrl(exporter: Exporter) { + getExportUrl(exporter /*: Exporter */) { const { organization, profile } = this.props; const path = '/api/qualityprofiles/export'; - const parameters: { [string]: string } = { + const parameters /*: { [string]: string } */ = { exporterKey: exporter.key, language: profile.language, name: profile.name diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileHeader.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileHeader.js index 3f802ef13ee..f5691c5ccea 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileHeader.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileHeader.js @@ -31,8 +31,9 @@ import { getProfilesForLanguagePath, getProfileChangelogPath } from '../utils'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ +/*:: type Props = { canAdmin: boolean, onRequestFail: Object => void, @@ -40,9 +41,10 @@ type Props = { profile: Profile, updateProfiles: () => Promise<*> }; +*/ export default class ProfileHeader extends React.PureComponent { - props: Props; + /*:: props: Props; */ renderUpdateDate() { const { profile } = this.props; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritance.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritance.js index d94b46b7680..9669bd0aa11 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritance.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritance.js @@ -24,8 +24,9 @@ import ProfileInheritanceBox from './ProfileInheritanceBox'; import ChangeParentForm from './ChangeParentForm'; import { translate } from '../../../helpers/l10n'; import { getProfileInheritance } from '../../../api/quality-profiles'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ +/*:: type Props = { canAdmin: boolean, onRequestFail: Object => void, @@ -34,7 +35,9 @@ type Props = { profiles: Array<Profile>, updateProfiles: () => Promise<*> }; +*/ +/*:: type ProfileInheritanceDetails = { activeRuleCount: number, isBuiltIn: boolean, @@ -43,7 +46,9 @@ type ProfileInheritanceDetails = { name: string, overridingRuleCount?: number }; +*/ +/*:: type State = { ancestors?: Array<ProfileInheritanceDetails>, children?: Array<ProfileInheritanceDetails>, @@ -51,11 +56,12 @@ type State = { loading: boolean, profile?: ProfileInheritanceDetails }; +*/ export default class ProfileInheritance extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { formOpen: false, loading: true }; @@ -65,7 +71,7 @@ export default class ProfileInheritance extends React.PureComponent { this.loadData(); } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if (prevProps.profile !== this.props.profile) { this.loadData(); } @@ -89,7 +95,7 @@ export default class ProfileInheritance extends React.PureComponent { }); } - handleChangeParentClick = (event: Event) => { + handleChangeParentClick = (event /*: Event */) => { event.preventDefault(); this.setState({ formOpen: true }); }; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritanceBox.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritanceBox.js index 04a804cc869..1adf7c7322b 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritanceBox.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritanceBox.js @@ -24,6 +24,7 @@ import BuiltInBadge from '../components/BuiltInBadge'; import Tooltip from '../../../components/controls/Tooltip'; import { translate, translateWithParameters } from '../../../helpers/l10n'; +/*:: type Props = {| className?: string, depth: number, @@ -40,9 +41,10 @@ type Props = {| overridingRuleCount?: number } |}; +*/ export default class ProfileInheritanceBox extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { displayLink: true diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileProjects.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileProjects.js index 0c59dec26be..984b7995b0f 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileProjects.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileProjects.js @@ -24,26 +24,30 @@ import ChangeProjectsForm from './ChangeProjectsForm'; import QualifierIcon from '../../../components/shared/QualifierIcon'; import { getProfileProjects } from '../../../api/quality-profiles'; import { translate } from '../../../helpers/l10n'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ +/*:: type Props = { canAdmin: boolean, organization: ?string, profile: Profile, updateProfiles: () => Promise<*> }; +*/ +/*:: type State = { formOpen: boolean, loading: boolean, more?: boolean, projects: ?Array<*> }; +*/ export default class ProfileProjects extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { formOpen: false, loading: true, projects: null @@ -54,7 +58,7 @@ export default class ProfileProjects extends React.PureComponent { this.loadProjects(); } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if (prevProps.profile !== this.props.profile) { this.loadProjects(); } @@ -81,7 +85,7 @@ export default class ProfileProjects extends React.PureComponent { }); } - handleChangeClick = (event: Event) => { + handleChangeClick = (event /*: Event */) => { event.preventDefault(); this.setState({ formOpen: true }); }; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRules.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRules.js index fe68a8385d8..ceb3fbed7c1 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRules.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRules.js @@ -29,16 +29,19 @@ import { searchRules, takeFacet } from '../../../api/rules'; import { getQualityProfiles } from '../../../api/quality-profiles'; import { getRulesUrl } from '../../../helpers/urls'; import { translate } from '../../../helpers/l10n'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ const TYPES = ['BUG', 'VULNERABILITY', 'CODE_SMELL']; +/*:: type Props = { canAdmin: boolean, organization: ?string, profile: Profile }; +*/ +/*:: type State = { activatedTotal: ?number, activatedByType?: { [string]: ?{ val: string, count: ?number } }, @@ -47,11 +50,12 @@ type State = { loading: boolean, total: ?number }; +*/ export default class ProfileRules extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { activatedTotal: null, activatedByType: keyBy(TYPES.map(t => ({ val: t, count: null })), 'val'), allByType: keyBy(TYPES.map(t => ({ val: t, count: null })), 'val'), @@ -65,7 +69,7 @@ export default class ProfileRules extends React.PureComponent { this.loadRules(); } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if (prevProps.profile !== this.props.profile) { this.loadRules(); } @@ -123,13 +127,13 @@ export default class ProfileRules extends React.PureComponent { }); } - getRulesCountForType(type: string): ?number { + getRulesCountForType(type /*: string */) /*: ?number */ { return this.state.activatedByType && this.state.activatedByType[type] ? this.state.activatedByType[type].count : null; } - getRulesTotalForType(type: string): ?number { + getRulesTotalForType(type /*: string */) /*: ?number */ { return this.state.allByType && this.state.allByType[type] ? this.state.allByType[type].count : null; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesDeprecatedWarning.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesDeprecatedWarning.js index d50c81c227b..a74e0829787 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesDeprecatedWarning.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesDeprecatedWarning.js @@ -24,9 +24,11 @@ import Tooltip from '../../../components/controls/Tooltip'; import { getDeprecatedActiveRulesUrl } from '../../../helpers/urls'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { activeDeprecatedRules: number, organization: ?string, profile: string }; +*/ -export default function ProfileRulesDeprecatedWarning(props: Props) { +export default function ProfileRulesDeprecatedWarning(props /*: Props */) { const url = getDeprecatedActiveRulesUrl({ qprofile: props.profile }, props.organization); return ( <div className="quality-profile-rules-deprecated clearfix"> diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesRowOfType.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesRowOfType.js index e6e04e59627..a899b495348 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesRowOfType.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesRowOfType.js @@ -25,6 +25,7 @@ import { formatMeasure } from '../../../helpers/measures'; import { getRulesUrl } from '../../../helpers/urls'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { count: ?number, organization: ?string, @@ -32,8 +33,9 @@ type Props = { total: ?number, type: string }; +*/ -export default function ProfileRulesRowOfType(props: Props) { +export default function ProfileRulesRowOfType(props /*: Props */) { const activeRulesUrl = getRulesUrl( { qprofile: props.qprofile, activation: 'true', types: props.type }, props.organization diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesRowTotal.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesRowTotal.js index f17bc2a8c86..1cb16d7623c 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesRowTotal.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesRowTotal.js @@ -24,14 +24,16 @@ import { formatMeasure } from '../../../helpers/measures'; import { getRulesUrl } from '../../../helpers/urls'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { count: ?number, organization: ?string, qprofile: string, total: ?number }; +*/ -export default function ProfileRulesRowTotal(props: Props) { +export default function ProfileRulesRowTotal(props /*: Props */) { const activeRulesUrl = getRulesUrl( { qprofile: props.qprofile, activation: 'true' }, props.organization diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesSonarWayComparison.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesSonarWayComparison.js index 9dae0f2c518..1e4a4c27c46 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesSonarWayComparison.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesSonarWayComparison.js @@ -24,6 +24,7 @@ import Tooltip from '../../../components/controls/Tooltip'; import { getRulesUrl } from '../../../helpers/urls'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { language: string, organization: ?string, @@ -31,8 +32,9 @@ type Props = { sonarway: string, sonarWayMissingRules: number }; +*/ -export default function ProfileRulesSonarWayComparison(props: Props) { +export default function ProfileRulesSonarWayComparison(props /*: Props */) { const url = getRulesUrl( { qprofile: props.profile, diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/CreateProfileForm.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/CreateProfileForm.js index 895fc4ca6c4..d95984ce033 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/CreateProfileForm.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/CreateProfileForm.js @@ -25,6 +25,7 @@ import { sortBy } from 'lodash'; import { getImporters, createQualityProfile } from '../../../api/quality-profiles'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { languages: Array<{ key: string, name: string }>, onClose: () => void, @@ -32,7 +33,9 @@ type Props = { onRequestFail: Object => void, organization: ?string }; +*/ +/*:: type State = { importers: Array<{ key: string, languages: Array<string>, name: string }>, language?: string, @@ -40,12 +43,13 @@ type State = { name: string, preloading: boolean }; +*/ export default class CreateProfileForm extends React.PureComponent { - form: HTMLFormElement; - mounted: boolean; - props: Props; - state: State = { importers: [], loading: false, name: '', preloading: true }; + /*:: form: HTMLFormElement; */ + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { importers: [], loading: false, name: '', preloading: true }; componentDidMount() { this.mounted = true; @@ -64,20 +68,20 @@ export default class CreateProfileForm extends React.PureComponent { }); } - handleCancelClick = (event: Event) => { + handleCancelClick = (event /*: Event */) => { event.preventDefault(); this.props.onClose(); }; - handleNameChange = (event: { currentTarget: HTMLInputElement }) => { + handleNameChange = (event /*: { currentTarget: HTMLInputElement } */) => { this.setState({ name: event.currentTarget.value }); }; - handleLanguageChange = (option: { value: string }) => { + handleLanguageChange = (option /*: { value: string } */) => { this.setState({ language: option.value }); }; - handleFormSubmit = (event: Event) => { + handleFormSubmit = (event /*: Event */) => { event.preventDefault(); this.setState({ loading: true }); diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/Evolution.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/Evolution.js index eca194a8209..4be28f3dd04 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/Evolution.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/Evolution.js @@ -22,15 +22,17 @@ import React from 'react'; import EvolutionDeprecated from './EvolutionDeprecated'; import EvolutionStagnant from './EvolutionStagnant'; import EvolutionRules from './EvolutionRules'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ +/*:: type Props = { organization: ?string, profiles: Array<Profile> }; +*/ export default class Evolution extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const { organization, profiles } = this.props; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.js index 239d492b8b8..a3eaef27bd2 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.js @@ -24,15 +24,17 @@ import { sortBy } from 'lodash'; import ProfileLink from '../components/ProfileLink'; import { getDeprecatedActiveRulesUrl } from '../../../helpers/urls'; import { translateWithParameters, translate } from '../../../helpers/l10n'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ +/*:: type Props = { organization: ?string, profiles: Array<Profile> }; +*/ export default class EvolutionDeprecated extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const profilesWithDeprecations = this.props.profiles.filter( diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionRules.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionRules.js index 54c74a6febd..042c04a73b6 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionRules.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionRules.js @@ -39,13 +39,15 @@ function parseRules(r) { }); } +/*:: type Props = { organization: ?string }; +*/ export default class EvolutionRules extends React.PureComponent { - mounted: boolean; - props: Props; + /*:: mounted: boolean; */ + /*:: props: Props; */ state = {}; componentDidMount() { diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.js index 8e65b78868f..1eda4c0b8e3 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.js @@ -23,15 +23,17 @@ import moment from 'moment'; import ProfileLink from '../components/ProfileLink'; import { translate } from '../../../helpers/l10n'; import { isStagnant } from '../utils'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ +/*:: type Props = { organization: ?string, profiles: Array<Profile> }; +*/ export default class EvolutionStagnant extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { // TODO filter built-in out diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/HomeContainer.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/HomeContainer.js index 70389154ed4..95f63d8cd4c 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/HomeContainer.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/HomeContainer.js @@ -22,8 +22,9 @@ import React from 'react'; import PageHeader from './PageHeader'; import Evolution from './Evolution'; import ProfilesList from './ProfilesList'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ +/*:: type Props = { canAdmin: boolean, languages: Array<{ key: string, name: string }>, @@ -33,9 +34,10 @@ type Props = { profiles: Array<Profile>, updateProfiles: () => Promise<*> }; +*/ export default class HomeContainer extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { return ( diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.js index 734dbde494b..44ba30feeb7 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.js @@ -22,10 +22,11 @@ import React from 'react'; import PropTypes from 'prop-types'; import CreateProfileForm from './CreateProfileForm'; import RestoreProfileForm from './RestoreProfileForm'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ import { getProfilePath } from '../utils'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { canAdmin: boolean, languages: Array<{ key: string, name: string }>, @@ -33,31 +34,34 @@ type Props = { organization: ?string, updateProfiles: () => Promise<*> }; +*/ +/*:: type State = { createFormOpen: boolean, restoreFormOpen: boolean }; +*/ export default class PageHeader extends React.PureComponent { - props: Props; + /*:: props: Props; */ static contextTypes = { router: PropTypes.object }; - state: State = { + state /*: State */ = { createFormOpen: false, restoreFormOpen: false }; - handleCreateClick = (event: Event & { currentTarget: HTMLButtonElement }) => { + handleCreateClick = (event /*: Event & { currentTarget: HTMLButtonElement } */) => { event.preventDefault(); event.currentTarget.blur(); this.setState({ createFormOpen: true }); }; - handleCreate = (profile: Profile) => { + handleCreate = (profile /*: Profile */) => { this.props.updateProfiles().then(() => { this.context.router.push( getProfilePath(profile.name, profile.language, this.props.organization) @@ -69,7 +73,7 @@ export default class PageHeader extends React.PureComponent { this.setState({ createFormOpen: false }); }; - handleRestoreClick = (event: Event) => { + handleRestoreClick = (event /*: Event */) => { event.preventDefault(); this.setState({ restoreFormOpen: true }); }; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.js index baf66452149..b912a9662a5 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.js @@ -24,8 +24,9 @@ import ProfilesListRow from './ProfilesListRow'; import ProfilesListHeader from './ProfilesListHeader'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ +/*:: type Props = { canAdmin: boolean, languages: Array<{ key: string, name: string }>, @@ -35,11 +36,12 @@ type Props = { profiles: Array<Profile>, updateProfiles: () => Promise<*> }; +*/ export default class ProfilesList extends React.PureComponent { - props: Props; + /*:: props: Props; */ - renderProfiles(profiles: Array<Profile>) { + renderProfiles(profiles /*: Array<Profile> */) { return profiles.map(profile => <ProfilesListRow canAdmin={this.props.canAdmin} @@ -52,7 +54,7 @@ export default class ProfilesList extends React.PureComponent { ); } - renderHeader(languageKey: string, profilesCount: number) { + renderHeader(languageKey /*: string */, profilesCount /*: number */) { const language = this.props.languages.find(l => l.key === languageKey); if (!language) { diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListHeader.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListHeader.js index b05b6ff01c8..ab76d1a4df3 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListHeader.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListHeader.js @@ -23,14 +23,16 @@ import { IndexLink } from 'react-router'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { getProfilesPath, getProfilesForLanguagePath } from '../utils'; +/*:: type Props = { currentFilter?: string, languages: Array<{ key: string, name: string }>, organization: ?string }; +*/ export default class ProfilesListHeader extends React.PureComponent { - props: Props; + /*:: props: Props; */ renderFilterToggle() { const { languages, currentFilter } = this.props; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListRow.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListRow.js index afdebe740a4..f9d18056d2e 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListRow.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListRow.js @@ -27,8 +27,9 @@ import BuiltInBadge from '../components/BuiltInBadge'; import { translate } from '../../../helpers/l10n'; import { getRulesUrl } from '../../../helpers/urls'; import { isStagnant } from '../utils'; -import type { Profile } from '../propTypes'; +/*:: import type { Profile } from '../propTypes'; */ +/*:: type Props = { canAdmin: boolean, onRequestFail: Object => void, @@ -36,9 +37,10 @@ type Props = { profile: Profile, updateProfiles: () => Promise<*> }; +*/ export default class ProfilesListRow extends React.PureComponent { - props: Props; + /*:: props: Props; */ renderName() { const { profile } = this.props; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/RestoreProfileForm.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/RestoreProfileForm.js index 973e2947bff..26411abb34c 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/RestoreProfileForm.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/RestoreProfileForm.js @@ -23,25 +23,29 @@ import Modal from 'react-modal'; import { restoreQualityProfile } from '../../../api/quality-profiles'; import { translate, translateWithParameters } from '../../../helpers/l10n'; +/*:: type Props = { onClose: () => void, onRequestFail: Object => void, onRestore: Function, organization: ?string }; +*/ +/*:: type State = { loading: boolean, profile?: { name: string }, ruleFailures?: number, ruleSuccesses?: number }; +*/ export default class RestoreProfileForm extends React.PureComponent { - form: HTMLFormElement; - mounted: boolean; - props: Props; - state: State = { loading: false }; + /*:: form: HTMLFormElement; */ + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { loading: false }; componentDidMount() { this.mounted = true; @@ -51,12 +55,12 @@ export default class RestoreProfileForm extends React.PureComponent { this.mounted = false; } - handleCancelClick = (event: Event) => { + handleCancelClick = (event /*: Event */) => { event.preventDefault(); this.props.onClose(); }; - handleFormSubmit = (event: Event) => { + handleFormSubmit = (event /*: Event */) => { event.preventDefault(); this.setState({ loading: true }); diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/propTypes.js b/server/sonar-web/src/main/js/apps/quality-profiles/propTypes.js index bdc59bbecc0..dbf1364fca2 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/propTypes.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/propTypes.js @@ -20,6 +20,7 @@ // @flow import { shape, string, number, bool, arrayOf } from 'prop-types'; +/*:: export type Profile = { key: string, name: string, @@ -39,12 +40,15 @@ export type Profile = { depth: number, childrenCount: number }; +*/ +/*:: export type Exporter = { key: string, name: string, languages: Array<string> }; +*/ export const ProfileType = shape({ key: string.isRequired, diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/utils.js b/server/sonar-web/src/main/js/apps/quality-profiles/utils.js index a98b28b9acb..60ec46e6572 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/utils.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/utils.js @@ -20,9 +20,9 @@ // @flow import { sortBy } from 'lodash'; import moment from 'moment'; -import type { Profile } from './propTypes'; +/*:: import type { Profile } from './propTypes'; */ -export function sortProfiles(profiles: Array<Profile>) { +export function sortProfiles(profiles /*: Array<Profile> */) { const result = []; const sorted = sortBy(profiles, 'name'); @@ -51,7 +51,7 @@ export function sortProfiles(profiles: Array<Profile>) { return result; } -export function createFakeProfile(overrides: {}) { +export function createFakeProfile(overrides /*: {} */) { return { key: 'key', name: 'name', @@ -66,30 +66,37 @@ export function createFakeProfile(overrides: {}) { }; } -export function isStagnant(profile: Profile) { +export function isStagnant(profile /*: Profile */) { return moment().diff(moment(profile.userUpdatedAt), 'years') >= 1; } -export const getProfilesPath = (organization: ?string) => +export const getProfilesPath = (organization /*: ?string */) => organization ? `/organizations/${organization}/quality_profiles` : '/profiles'; -export const getProfilesForLanguagePath = (language: string, organization: ?string) => ({ +export const getProfilesForLanguagePath = ( + language /*: string */, + organization /*: ?string */ +) => ({ pathname: getProfilesPath(organization), query: { language } }); -export const getProfilePath = (name: string, language: string, organization: ?string) => ({ +export const getProfilePath = ( + name /*: string */, + language /*: string */, + organization /*: ?string */ +) => ({ pathname: getProfilesPath(organization) + '/show', query: { name, language } }); export const getProfileComparePath = ( - name: string, - language: string, - organization: ?string, - withKey?: string + name /*: string */, + language /*: string */, + organization /*: ?string */, + withKey /*: ?string */ ) => { - const query: Object = { language, name }; + const query /*: Object */ = { language, name }; if (withKey) { Object.assign(query, { withKey }); } @@ -100,12 +107,12 @@ export const getProfileComparePath = ( }; export const getProfileChangelogPath = ( - name: string, - language: string, - organization: ?string, - filter?: { since?: string, to?: string } + name /*: string */, + language /*: string */, + organization /*: ?string */, + filter /*: ?{ since?: string, to?: string } */ ) => { - const query: Object = { language, name }; + const query /*: Object */ = { language, name }; if (filter) { if (filter.since) { Object.assign(query, { since: filter.since }); diff --git a/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.js b/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.js index 440fc7269d7..361a4404774 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.js +++ b/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.js @@ -23,6 +23,7 @@ import OAuthProviders from './OAuthProviders'; import GlobalMessagesContainer from '../../../app/components/GlobalMessagesContainer'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { identityProviders: Array<{ backgroundColor: string, @@ -32,18 +33,21 @@ type Props = { }>, onSubmit: (string, string) => void }; +*/ +/*:: type State = { collapsed: boolean, login: string, password: string }; +*/ export default class LoginForm extends React.PureComponent { - props: Props; - state: State; + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { collapsed: props.identityProviders.length > 0, @@ -52,12 +56,12 @@ export default class LoginForm extends React.PureComponent { }; } - handleSubmit = (event: Event) => { + handleSubmit = (event /*: Event */) => { event.preventDefault(); this.props.onSubmit(this.state.login, this.state.password); }; - handleMoreOptionsClick = (event: Event) => { + handleMoreOptionsClick = (event /*: Event */) => { event.preventDefault(); this.setState({ collapsed: false }); }; diff --git a/server/sonar-web/src/main/js/apps/sessions/components/LoginFormContainer.js b/server/sonar-web/src/main/js/apps/sessions/components/LoginFormContainer.js index 257f00a8259..fe2197fdf6f 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/LoginFormContainer.js +++ b/server/sonar-web/src/main/js/apps/sessions/components/LoginFormContainer.js @@ -27,7 +27,7 @@ import { getAppState } from '../../../store/rootReducer'; import { getIdentityProviders } from '../../../api/users'; class LoginFormContainer extends React.PureComponent { - mounted: boolean; + /*:: mounted: boolean; */ static propTypes = { location: PropTypes.object.isRequired @@ -55,7 +55,7 @@ class LoginFormContainer extends React.PureComponent { window.location = returnTo; }; - handleSubmit = (login: string, password: string) => { + handleSubmit = (login /*: string */, password /*: string */) => { this.props.doLogin(login, password).then(this.handleSuccessfulLogin, () => { /* do nothing */ }); diff --git a/server/sonar-web/src/main/js/apps/sessions/components/OAuthProviders.js b/server/sonar-web/src/main/js/apps/sessions/components/OAuthProviders.js index 096637eb543..3ce1cd7f7c4 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/OAuthProviders.js +++ b/server/sonar-web/src/main/js/apps/sessions/components/OAuthProviders.js @@ -21,6 +21,7 @@ import React from 'react'; import { translateWithParameters } from '../../../helpers/l10n'; +/*:: type Props = { formatLabel?: string => string, identityProviders: Array<{ @@ -30,12 +31,13 @@ type Props = { name: string }> }; +*/ -export default function OAuthProviders(props: Props) { +export default function OAuthProviders(props /*: Props */) { return ( <section className="oauth-providers"> <ul> - {props.identityProviders.map(identityProvider => ( + {props.identityProviders.map(identityProvider => <li key={identityProvider.key}> <a href={`${window.baseUrl}/sessions/init/${identityProvider.key}`} @@ -48,16 +50,18 @@ export default function OAuthProviders(props: Props) { height="20" src={window.baseUrl + identityProvider.iconPath} /> - {/* $FlowFixMe formatLabel is always defined through defaultProps */} - <span>{props.formatLabel(identityProvider.name)}</span> + <span> + {/* $FlowFixMe formatLabel is always defined through defaultProps */} + {props.formatLabel(identityProvider.name)} + </span> </a> </li> - ))} + )} </ul> </section> ); } OAuthProviders.defaultProps = { - formatLabel: (name: string) => translateWithParameters('login.login_with_x', name) + formatLabel: (name /*: string */) => translateWithParameters('login.login_with_x', name) }; diff --git a/server/sonar-web/src/main/js/apps/sessions/components/SimpleSessionsContainer.js b/server/sonar-web/src/main/js/apps/sessions/components/SimpleSessionsContainer.js index 2c6820f55f7..3350e400475 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/SimpleSessionsContainer.js +++ b/server/sonar-web/src/main/js/apps/sessions/components/SimpleSessionsContainer.js @@ -21,11 +21,13 @@ import React from 'react'; import SimpleContainer from '../../../app/components/SimpleContainer'; +/*:: type Props = { children?: React.Element<*> | Array<React.Element<*>> }; +*/ -export default function SimpleSessionsContainer({ children }: Props) { +export default function SimpleSessionsContainer({ children } /*: Props */) { return ( <SimpleContainer hideLoggedInInfo={true}> {children} diff --git a/server/sonar-web/src/main/js/apps/settings/components/App.js b/server/sonar-web/src/main/js/apps/settings/components/App.js index 9d45c3749e7..ab5cf8414ff 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/App.js +++ b/server/sonar-web/src/main/js/apps/settings/components/App.js @@ -30,20 +30,24 @@ import { getSettingsAppDefaultCategory } from '../../../store/rootReducer'; import { translate } from '../../../helpers/l10n'; import '../styles.css'; +/*:: type Props = { component: { key: string }, defaultCategory: ?string, fetchSettings(componentKey: ?string): Promise<*>, location: { query: {} } }; +*/ +/*:: type State = { loaded: boolean }; +*/ class App extends React.PureComponent { - props: Props; - state: State = { loaded: false }; + /*:: props: Props; */ + state /*: State */ = { loaded: false }; componentDidMount() { const html = document.querySelector('html'); diff --git a/server/sonar-web/src/main/js/apps/settings/components/CategoriesList.js b/server/sonar-web/src/main/js/apps/settings/components/CategoriesList.js index aee685e3d61..60365bb3562 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/CategoriesList.js +++ b/server/sonar-web/src/main/js/apps/settings/components/CategoriesList.js @@ -23,22 +23,26 @@ import { sortBy } from 'lodash'; import { IndexLink } from 'react-router'; import { getCategoryName } from '../utils'; +/*:: type Category = { key: string, name: string }; +*/ +/*:: type Props = { categories: Category[], component?: { key: string }, defaultCategory: string, selectedCategory: string }; +*/ export default class CategoriesList extends React.PureComponent { - rops: Props; + /*:: rops: Props; */ - renderLink(category: Category) { + renderLink(category /*: Category */) { const query = {}; if (category.key !== this.props.defaultCategory) { diff --git a/server/sonar-web/src/main/js/apps/settings/components/Definition.js b/server/sonar-web/src/main/js/apps/settings/components/Definition.js index 9b613bc6d79..76498574df1 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/Definition.js +++ b/server/sonar-web/src/main/js/apps/settings/components/Definition.js @@ -43,8 +43,8 @@ import { } from '../../../store/rootReducer'; class Definition extends React.PureComponent { - mounted: boolean; - timeout: number; + /*:: mounted: boolean; */ + /*:: timeout: number; */ static propTypes = { component: PropTypes.object, diff --git a/server/sonar-web/src/main/js/apps/settings/components/DefinitionChanges.js b/server/sonar-web/src/main/js/apps/settings/components/DefinitionChanges.js index 67545155421..ea1de230bb3 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/DefinitionChanges.js +++ b/server/sonar-web/src/main/js/apps/settings/components/DefinitionChanges.js @@ -28,13 +28,13 @@ export default class DefinitionChanges extends React.PureComponent { onCancel: PropTypes.func.isRequired }; - handleSaveClick(e: Object) { + handleSaveClick(e /*: Object */) { e.preventDefault(); e.target.blur(); this.props.onSave(); } - handleCancelChange(e: Object) { + handleCancelChange(e /*: Object */) { e.preventDefault(); e.target.blur(); this.props.onCancel(); diff --git a/server/sonar-web/src/main/js/apps/settings/components/DefinitionDefaults.js b/server/sonar-web/src/main/js/apps/settings/components/DefinitionDefaults.js index 01ef2658324..6fc6808bdb6 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/DefinitionDefaults.js +++ b/server/sonar-web/src/main/js/apps/settings/components/DefinitionDefaults.js @@ -30,7 +30,7 @@ export default class DefinitionDefaults extends React.PureComponent { onReset: PropTypes.func.isRequired }; - handleReset(e: Object) { + handleReset(e /*: Object */) { e.preventDefault(); e.target.blur(); this.props.onReset(); diff --git a/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.js b/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.js index 532a03ba4b1..b8299136778 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.js +++ b/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.js @@ -31,7 +31,7 @@ export default class SubCategoryDefinitionsList extends React.PureComponent { settings: PropTypes.array.isRequired }; - renderEmailForm(subCategoryKey: string) { + renderEmailForm(subCategoryKey /*: string */) { const isEmailSettings = this.props.category === 'general' && subCategoryKey === 'email'; if (!isEmailSettings) { return null; diff --git a/server/sonar-web/src/main/js/apps/settings/store/definitions/actions.js b/server/sonar-web/src/main/js/apps/settings/store/definitions/actions.js index 0cd91edd518..d4a163d2b58 100644 --- a/server/sonar-web/src/main/js/apps/settings/store/definitions/actions.js +++ b/server/sonar-web/src/main/js/apps/settings/store/definitions/actions.js @@ -18,16 +18,16 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // @flow -import type { Definition } from '../../types'; +/*:: import type { Definition } from '../../types'; */ -export const RECEIVE_DEFINITIONS: string = 'RECEIVE_DEFINITIONS'; +export const RECEIVE_DEFINITIONS /*: string */ = 'RECEIVE_DEFINITIONS'; /** * Receive definitions action creator * @param {Array} definitions * @returns {Object} */ -export const receiveDefinitions = (definitions: Definition[]) => ({ +export const receiveDefinitions = (definitions /*: Definition[] */) => ({ type: RECEIVE_DEFINITIONS, definitions }); diff --git a/server/sonar-web/src/main/js/apps/settings/store/definitions/reducer.js b/server/sonar-web/src/main/js/apps/settings/store/definitions/reducer.js index 08a736f5c3f..24ec06e441f 100644 --- a/server/sonar-web/src/main/js/apps/settings/store/definitions/reducer.js +++ b/server/sonar-web/src/main/js/apps/settings/store/definitions/reducer.js @@ -21,13 +21,17 @@ import { keyBy, sortBy, uniqBy } from 'lodash'; import { RECEIVE_DEFINITIONS } from './actions'; import { DEFAULT_CATEGORY, getCategoryName } from '../../utils'; -import type { Definition } from '../../types'; +/*:: import type { Definition } from '../../types'; */ +/*:: type State = { [key: string]: Definition }; +*/ +/*:: type Action = { type: string, definitions: Definition[] }; +*/ -const reducer = (state: State = {}, action: Action) => { +const reducer = (state /*: State */ = {}, action /*: Action */) => { if (action.type === RECEIVE_DEFINITIONS) { return keyBy(action.definitions, 'key'); } @@ -37,22 +41,25 @@ const reducer = (state: State = {}, action: Action) => { export default reducer; -export const getDefinition = (state: State, key: string): Definition => state[key]; +export function getDefinition(state /*: State */, key /*: string */) /*: Definition */ { + return state[key]; +} -export const getAllDefinitions = (state: State): Definition[] => - Object.keys(state).map(key => state[key]); +export function getAllDefinitions(state /*: State */) /*: Definition[] */ { + return Object.keys(state).map(key => state[key]); +} -export const getDefinitionsForCategory = (state: State, category: string) => +export const getDefinitionsForCategory = (state /*: State */, category /*: string */) => getAllDefinitions(state).filter( definition => definition.category.toLowerCase() === category.toLowerCase() ); -export const getAllCategories = (state: State) => +export const getAllCategories = (state /*: State */) => uniqBy(getAllDefinitions(state).map(definition => definition.category), category => category.toLowerCase() ); -export const getDefaultCategory = (state: State) => { +export const getDefaultCategory = (state /*: State */) => { const categories = getAllCategories(state); if (categories.includes(DEFAULT_CATEGORY)) { return DEFAULT_CATEGORY; diff --git a/server/sonar-web/src/main/js/apps/settings/store/rootReducer.js b/server/sonar-web/src/main/js/apps/settings/store/rootReducer.js index c11af77b997..d483892a9aa 100644 --- a/server/sonar-web/src/main/js/apps/settings/store/rootReducer.js +++ b/server/sonar-web/src/main/js/apps/settings/store/rootReducer.js @@ -24,9 +24,10 @@ import values, * as fromValues from './values/reducer'; import settingsPage, * as fromSettingsPage from './settingsPage/reducer'; import licenses, * as fromLicenses from './licenses/reducer'; import globalMessages, * as fromGlobalMessages from '../../../store/globalMessages/duck'; -import type { State as GlobalMessagesState } from '../../../store/globalMessages/duck'; +/*:: import type { State as GlobalMessagesState } from '../../../store/globalMessages/duck'; */ import encryptionPage from './encryptionPage/reducer'; +/*:: type State = { definitions: {}, encryptionPage: {}, @@ -35,6 +36,7 @@ type State = { settingsPage: {}, values: {} }; +*/ const rootReducer = combineReducers({ definitions, @@ -47,38 +49,40 @@ const rootReducer = combineReducers({ export default rootReducer; -export const getDefinition = (state: State, key: string) => +export const getDefinition = (state /*: State */, key /*: string */) => fromDefinitions.getDefinition(state.definitions, key); -export const getAllCategories = (state: State) => +export const getAllCategories = (state /*: State */) => fromDefinitions.getAllCategories(state.definitions); -export const getDefaultCategory = (state: State) => +export const getDefaultCategory = (state /*: State */) => fromDefinitions.getDefaultCategory(state.definitions); -export const getValue = (state: State, key: string) => fromValues.getValue(state.values, key); +export const getValue = (state /*: State */, key /*: string */) => + fromValues.getValue(state.values, key); -export const getSettingsForCategory = (state: State, category: string) => +export const getSettingsForCategory = (state /*: State */, category /*: string */) => fromDefinitions.getDefinitionsForCategory(state.definitions, category).map(definition => ({ ...getValue(state, definition.key), definition })); -export const getChangedValue = (state: State, key: string) => +export const getChangedValue = (state /*: State */, key /*: string */) => fromSettingsPage.getChangedValue(state.settingsPage, key); -export const isLoading = (state: State, key: string) => +export const isLoading = (state /*: State */, key /*: string */) => fromSettingsPage.isLoading(state.settingsPage, key); -export const getLicenseByKey = (state: State, key: string) => +export const getLicenseByKey = (state /*: State */, key /*: string */) => fromLicenses.getLicenseByKey(state.licenses, key); -export const getAllLicenseKeys = (state: State) => fromLicenses.getAllLicenseKeys(state.licenses); +export const getAllLicenseKeys = (state /*: State */) => + fromLicenses.getAllLicenseKeys(state.licenses); -export const getValidationMessage = (state: State, key: string) => +export const getValidationMessage = (state /*: State */, key /*: string */) => fromSettingsPage.getValidationMessage(state.settingsPage, key); -export const getEncryptionState = (state: State) => state.encryptionPage; +export const getEncryptionState = (state /*: State */) => state.encryptionPage; -export const getGlobalMessages = (state: State) => +export const getGlobalMessages = (state /*: State */) => fromGlobalMessages.getGlobalMessages(state.globalMessages); diff --git a/server/sonar-web/src/main/js/apps/settings/store/values/actions.js b/server/sonar-web/src/main/js/apps/settings/store/values/actions.js index 01a6d3a8f01..e9087a0b6d5 100644 --- a/server/sonar-web/src/main/js/apps/settings/store/values/actions.js +++ b/server/sonar-web/src/main/js/apps/settings/store/values/actions.js @@ -18,16 +18,16 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // @flow -import type { SettingValue } from '../../types'; +/*:: import type { SettingValue } from '../../types'; */ -export const RECEIVE_VALUES: string = 'RECEIVE_VALUES'; +export const RECEIVE_VALUES /*: string */ = 'RECEIVE_VALUES'; /** * Receive settings action creator * @param {Array} settings * @returns {Object} */ -export const receiveValues = (settings: SettingValue[]) => ({ +export const receiveValues = (settings /*: SettingValue[] */) => ({ type: RECEIVE_VALUES, settings }); diff --git a/server/sonar-web/src/main/js/apps/settings/store/values/reducer.js b/server/sonar-web/src/main/js/apps/settings/store/values/reducer.js index d11c40e34e2..d8e42984fd7 100644 --- a/server/sonar-web/src/main/js/apps/settings/store/values/reducer.js +++ b/server/sonar-web/src/main/js/apps/settings/store/values/reducer.js @@ -21,9 +21,11 @@ import { keyBy } from 'lodash'; import { RECEIVE_VALUES } from './actions'; +/*:: type State = { [key: string]: {} }; +*/ -const reducer = (state: State = {}, action: Object) => { +const reducer = (state /*: State */ = {}, action /*: Object */) => { if (action.type === RECEIVE_VALUES) { const settingsByKey = keyBy(action.settings, 'key'); return { ...state, ...settingsByKey }; @@ -42,4 +44,4 @@ const reducer = (state: State = {}, action: Object) => { export default reducer; -export const getValue = (state: State, key: string) => state[key]; +export const getValue = (state /*: State */, key /*: string */) => state[key]; diff --git a/server/sonar-web/src/main/js/apps/settings/types.js b/server/sonar-web/src/main/js/apps/settings/types.js index 6d3d744ed1a..21d2452de62 100644 --- a/server/sonar-web/src/main/js/apps/settings/types.js +++ b/server/sonar-web/src/main/js/apps/settings/types.js @@ -18,12 +18,16 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // @flow +/*:: export type Definition = { key: string, category: string }; +*/ +/*:: export type SettingValue = { key: string, value?: string }; +*/ diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/AnalysisStep.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/AnalysisStep.js index a3b938727d6..bf535694f94 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/AnalysisStep.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/AnalysisStep.js @@ -21,7 +21,7 @@ import React from 'react'; import Step from './Step'; import LanguageStep from './LanguageStep'; -import type { Result } from './LanguageStep'; +/*:: import type { Result } from './LanguageStep'; */ import JavaMaven from './commands/JavaMaven'; import JavaGradle from './commands/JavaGradle'; import DotNet from './commands/DotNet'; @@ -30,6 +30,7 @@ import ClangGCC from './commands/ClangGCC'; import Other from './commands/Other'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = {| onFinish: (projectKey?: string) => void, onReset: () => void, @@ -39,16 +40,19 @@ type Props = {| stepNumber: number, token: string |}; +*/ +/*:: type State = { result?: Result }; +*/ export default class AnalysisStep extends React.PureComponent { - props: Props; - state: State = {}; + /*:: props: Props; */ + state /*: State */ = {}; - handleLanguageSelect = (result?: Result) => { + handleLanguageSelect = (result /*: Result | void */) => { this.setState({ result }); const projectKey = result && result.language !== 'java' ? result.projectKey : undefined; this.props.onFinish(projectKey); @@ -81,7 +85,7 @@ export default class AnalysisStep extends React.PureComponent { ); }; - renderFormattedCommand = (...lines: Array<string>) => + renderFormattedCommand = (...lines /*: Array<string> */) => <pre> {lines.join(' ' + '\\' + '\n' + ' ')} </pre>; diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/LanguageStep.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/LanguageStep.js index 55e030422fb..282b86150ae 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/LanguageStep.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/LanguageStep.js @@ -23,13 +23,16 @@ import NewProjectForm from './NewProjectForm'; import RadioToggle from '../../../components/controls/RadioToggle'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = {| onDone: (result: Result) => void, onReset: () => void, organization?: string, sonarCloud: boolean |}; +*/ +/*:: type State = { language?: string, javaBuild?: string, @@ -37,15 +40,17 @@ type State = { os?: string, projectKey?: string }; +*/ -export type Result = State; +/*:: +export type Result = State; */ export default class LanguageStep extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { sonarCloud: false }; - state: State = {}; + state /*: State */ = {}; isConfigured = () => { const { language, javaBuild, cFamilyCompiler, os, projectKey } = this.state; @@ -66,23 +71,23 @@ export default class LanguageStep extends React.PureComponent { } }; - handleLanguageChange = (language: string) => { + handleLanguageChange = (language /*: string */) => { this.setState({ language }, this.handleChange); }; - handleJavaBuildChange = (javaBuild: string) => { + handleJavaBuildChange = (javaBuild /*: string */) => { this.setState({ javaBuild }, this.handleChange); }; - handleCFamilyCompilerChange = (cFamilyCompiler: string) => { + handleCFamilyCompilerChange = (cFamilyCompiler /*: string */) => { this.setState({ cFamilyCompiler }, this.handleChange); }; - handleOSChange = (os: string) => { + handleOSChange = (os /*: string */) => { this.setState({ os }, this.handleChange); }; - handleProjectKeyDone = (projectKey: string) => { + handleProjectKeyDone = (projectKey /*: string */) => { this.setState({ projectKey }, this.handleChange); }; diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/NewOrganizationForm.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/NewOrganizationForm.js index dd7594e8ed5..4ef88d7077f 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/NewOrganizationForm.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/NewOrganizationForm.js @@ -28,25 +28,29 @@ import { } from '../../../api/organizations'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = {| onDelete: () => void, onDone: (organization: string) => void, organization?: string |}; +*/ +/*:: type State = { done: boolean, loading: boolean, organization: string, unique: boolean }; +*/ export default class NewOrganizationForm 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 = { done: props.organization != null, @@ -71,7 +75,7 @@ export default class NewOrganizationForm extends React.PureComponent { } }; - validateOrganization = (organization: string) => { + validateOrganization = (organization /*: string */) => { getOrganization(organization).then(response => { if (this.mounted) { this.setState({ unique: response == null }); @@ -79,16 +83,16 @@ export default class NewOrganizationForm extends React.PureComponent { }); }; - sanitizeOrganization = (organization: string) => + sanitizeOrganization = (organization /*: string */) => organization.toLowerCase().replace(/[^a-z0-9-]/, '').replace(/^-/, ''); - handleOrganizationChange = (event: { target: HTMLInputElement }) => { + handleOrganizationChange = (event /*: { target: HTMLInputElement } */) => { const organization = this.sanitizeOrganization(event.target.value); this.setState({ organization }); this.validateOrganization(organization); }; - handleOrganizationCreate = (event: Event) => { + handleOrganizationCreate = (event /*: Event */) => { event.preventDefault(); const { organization } = this.state; if (organization) { @@ -102,7 +106,7 @@ export default class NewOrganizationForm extends React.PureComponent { } }; - handleOrganizationDelete = (event: Event) => { + handleOrganizationDelete = (event /*: Event */) => { event.preventDefault(); const { organization } = this.state; if (organization) { diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/NewProjectForm.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/NewProjectForm.js index 5f7a87855ca..65a73530d21 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/NewProjectForm.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/NewProjectForm.js @@ -23,25 +23,29 @@ import CloseIcon from '../../../components/icons-components/CloseIcon'; import { createProject, deleteProject } from '../../../api/components'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = {| onDelete: () => void, onDone: (projectKey: string) => void, organization?: string, projectKey?: string |}; +*/ +/*:: type State = { done: boolean, loading: boolean, projectKey: string }; +*/ export default class NewProjectForm 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 = { done: props.projectKey != null, @@ -64,16 +68,16 @@ export default class NewProjectForm extends React.PureComponent { } }; - sanitizeProjectKey = (projectKey: string) => projectKey.replace(/[^a-zA-Z0-9-_\.:]/, ''); + sanitizeProjectKey = (projectKey /*: string */) => projectKey.replace(/[^a-zA-Z0-9-_\.:]/, ''); - handleProjectKeyChange = (event: { target: HTMLInputElement }) => { + handleProjectKeyChange = (event /*: { target: HTMLInputElement } */) => { this.setState({ projectKey: this.sanitizeProjectKey(event.target.value) }); }; - handleProjectCreate = (event: Event) => { + handleProjectCreate = (event /*: Event */) => { event.preventDefault(); const { projectKey } = this.state; - const data: { [string]: string } = { + const data /*: { [string]: string } */ = { name: projectKey, project: projectKey }; @@ -89,7 +93,7 @@ export default class NewProjectForm extends React.PureComponent { }, this.stopLoading); }; - handleProjectDelete = (event: Event) => { + handleProjectDelete = (event /*: Event */) => { event.preventDefault(); const { projectKey } = this.state; this.setState({ loading: true }); diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/Onboarding.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/Onboarding.js index 4d3cc475152..4b250ce081c 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/Onboarding.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/Onboarding.js @@ -31,13 +31,16 @@ import { getProjectUrl } from '../../../helpers/urls'; import handleRequiredAuthentication from '../../../app/utils/handleRequiredAuthentication'; import './styles.css'; +/*:: type Props = {| currentUser: { login: string, isLoggedIn: boolean }, onFinish: () => void, organizationsEnabled: boolean, sonarCloud: boolean |}; +*/ +/*:: type State = { finished: boolean, organization?: string, @@ -46,17 +49,18 @@ type State = { step: string, token?: string }; +*/ export default class Onboarding extends React.PureComponent { - mounted: boolean; - props: Props; - state: State; + /*:: mounted: boolean; */ + /*:: props: Props; */ + /*:: state: State; */ static contextTypes = { router: PropTypes.object }; - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { finished: false, @@ -101,11 +105,11 @@ export default class Onboarding extends React.PureComponent { this.setState({ projectKey: undefined }); }; - handleTokenDone = (token: string) => { + handleTokenDone = (token /*: string */) => { this.setState({ step: 'analysis', token }); }; - handleOrganizationDone = (organization: string) => { + handleOrganizationDone = (organization /*: string */) => { this.setState({ organization, step: 'token' }); }; @@ -113,12 +117,12 @@ export default class Onboarding extends React.PureComponent { handleOrganizationOpen = () => this.setState({ step: 'organization' }); - handleSkipClick = (event: Event) => { + handleSkipClick = (event /*: Event */) => { event.preventDefault(); this.finishOnboarding(); }; - handleFinish = (projectKey?: string) => this.setState({ finished: true, projectKey }); + handleFinish = (projectKey /*: string | void */) => this.setState({ finished: true, projectKey }); handleReset = () => this.setState({ finished: false }); diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.js index a402d0bdb58..de339bd70cb 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingModal.js @@ -22,18 +22,22 @@ import React from 'react'; import Modal from 'react-modal'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = {| onFinish: () => void |}; +*/ +/*:: type State = { OnboardingContainer?: Object }; +*/ export default class OnboardingModal extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = {}; + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = {}; componentDidMount() { this.mounted = true; @@ -44,7 +48,7 @@ export default class OnboardingModal extends React.PureComponent { this.mounted = false; } - receiveComponent = (OnboardingContainer: Object) => { + receiveComponent = (OnboardingContainer /*: Object */) => { if (this.mounted) { this.setState({ OnboardingContainer }); } diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OrganizationStep.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/OrganizationStep.js index 16ad05c181a..6979adf8198 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OrganizationStep.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/OrganizationStep.js @@ -27,6 +27,7 @@ import NewOrganizationForm from './NewOrganizationForm'; import { getMyOrganizations } from '../../../api/organizations'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = {| currentUser: { login: string, isLoggedIn: boolean }, finished: boolean, @@ -35,7 +36,9 @@ type Props = {| open: boolean, stepNumber: number |}; +*/ +/*:: type State = { loading: boolean, newOrganization?: string, @@ -44,11 +47,12 @@ type State = { personalOrganization?: string, selection: 'personal' | 'existing' | 'new' }; +*/ export default class OrganizationStep extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { loading: true, existingOrganizations: [], selection: 'personal' @@ -103,22 +107,22 @@ export default class OrganizationStep extends React.PureComponent { } }; - handlePersonalClick = (event: Event) => { + handlePersonalClick = (event /*: Event */) => { event.preventDefault(); this.setState({ selection: 'personal' }); }; - handleExistingClick = (event: Event) => { + handleExistingClick = (event /*: Event */) => { event.preventDefault(); this.setState({ selection: 'existing' }); }; - handleNewClick = (event: Event) => { + handleNewClick = (event /*: Event */) => { event.preventDefault(); this.setState({ selection: 'new' }); }; - handleOrganizationCreate = (newOrganization: string) => { + handleOrganizationCreate = (newOrganization /*: string */) => { this.setState({ newOrganization }); }; @@ -126,11 +130,11 @@ export default class OrganizationStep extends React.PureComponent { this.setState({ newOrganization: undefined }); }; - handleExistingOrganizationSelect = ({ value }: { value: string }) => { + handleExistingOrganizationSelect = ({ value } /*: { value: string } */) => { this.setState({ existingOrganization: value }); }; - handleContinueClick = (event: Event) => { + handleContinueClick = (event /*: Event */) => { event.preventDefault(); const organization = this.getSelectedOrganization(); if (organization) { diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/ProjectKeyStep.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/ProjectKeyStep.js index 9a173d999f5..002626b16ee 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/ProjectKeyStep.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/ProjectKeyStep.js @@ -22,25 +22,29 @@ import React from 'react'; import { createProject, deleteProject } from '../../../api/components'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { onDelete: () => void, onDone: (projectKey: string) => void, organization?: string, projectKey?: string }; +*/ +/*:: type State = { done: boolean, loading: boolean, projectKey: string }; +*/ export default class ProjectKeyStep 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 = { done: props.projectKey != null, @@ -63,16 +67,16 @@ export default class ProjectKeyStep extends React.PureComponent { } }; - sanitizeProjectKey = (projectKey: string) => projectKey.replace(/[^a-zA-Z0-9-_\.:]/, ''); + sanitizeProjectKey = (projectKey /*: string */) => projectKey.replace(/[^a-zA-Z0-9-_\.:]/, ''); - handleProjectKeyChange = (event: { target: HTMLInputElement }) => { + handleProjectKeyChange = (event /*: { target: HTMLInputElement } */) => { this.setState({ projectKey: this.sanitizeProjectKey(event.target.value) }); }; - handleProjectCreate = (event: Event) => { + handleProjectCreate = (event /*: Event */) => { event.preventDefault(); const { projectKey } = this.state; - const data: { [string]: string } = { + const data /*: { [string]: string } */ = { name: projectKey, project: projectKey }; @@ -88,7 +92,7 @@ export default class ProjectKeyStep extends React.PureComponent { }, this.stopLoading); }; - handleProjectDelete = (event: Event) => { + handleProjectDelete = (event /*: Event */) => { event.preventDefault(); const { projectKey } = this.state; this.setState({ loading: true }); diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/ProjectWatcher.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/ProjectWatcher.js index 920547fcab0..9fd26c54007 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/ProjectWatcher.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/ProjectWatcher.js @@ -26,23 +26,27 @@ import { translate } from '../../../helpers/l10n'; const INTERVAL = 5000; const TIMEOUT = 10 * 60 * 1000; // 10 min +/*:: type Props = { onFinish: () => void, onTimeout: () => void, projectKey: string }; +*/ +/*:: type State = { inQueue: boolean, status: ?string }; +*/ export default class ProjectWatcher extends React.PureComponent { - interval: number; - mounted: boolean; - props: Props; - timeout: number; - state: State = { + /*:: interval: number; */ + /*:: mounted: boolean; */ + /*:: props: Props; */ + /*:: timeout: number; */ + state /*: State */ = { inQueue: false, status: null }; diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/Step.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/Step.js index e2ae5cc9c40..a814a008aee 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/Step.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/Step.js @@ -21,6 +21,7 @@ import React from 'react'; import classNames from 'classnames'; +/*:: type Props = {| finished: boolean, onOpen: () => void, @@ -30,8 +31,9 @@ type Props = {| stepNumber: number, stepTitle: string |}; +*/ -export default function Step(props: Props) { +export default function Step(props /*: Props */) { const className = classNames('boxed-group', 'onboarding-step', { 'is-open': props.open, 'is-finished': props.finished @@ -39,7 +41,7 @@ export default function Step(props: Props) { const clickable = !props.open && props.finished; - const handleClick = (event: Event) => { + const handleClick = (event /*: Event */) => { event.preventDefault; props.onOpen(); }; diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/TokenStep.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/TokenStep.js index 0209d26b6c8..6c903e32ae2 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/TokenStep.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/TokenStep.js @@ -24,6 +24,7 @@ import CloseIcon from '../../../components/icons-components/CloseIcon'; import { generateToken, revokeToken } from '../../../api/user-tokens'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = {| finished: boolean, open: boolean, @@ -31,17 +32,20 @@ type Props = {| onOpen: () => void, stepNumber: number |}; +*/ +/*:: type State = { loading: boolean, tokenName?: string, token?: string }; +*/ export default class TokenStep extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { loading: false }; @@ -53,11 +57,11 @@ export default class TokenStep extends React.PureComponent { this.mounted = false; } - handleTokenNameChange = (event: { target: HTMLInputElement }) => { + handleTokenNameChange = (event /*: { target: HTMLInputElement } */) => { this.setState({ tokenName: event.target.value }); }; - handleTokenGenerate = (event: Event) => { + handleTokenGenerate = (event /*: Event */) => { event.preventDefault(); const { tokenName } = this.state; if (tokenName) { @@ -77,7 +81,7 @@ export default class TokenStep extends React.PureComponent { } }; - handleTokenRevoke = (event: Event) => { + handleTokenRevoke = (event /*: Event */) => { event.preventDefault(); const { tokenName } = this.state; if (tokenName) { @@ -97,7 +101,7 @@ export default class TokenStep extends React.PureComponent { } }; - handleContinueClick = (event: Event) => { + handleContinueClick = (event /*: Event */) => { event.preventDefault(); if (this.state.token) { this.props.onContinue(this.state.token); diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/BuildWrapper.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/BuildWrapper.js index 3b0624e4629..d24e0917abd 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/BuildWrapper.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/BuildWrapper.js @@ -21,10 +21,12 @@ import React from 'react'; import { translate } from '../../../../helpers/l10n'; +/*:: type Props = { className?: string, os: string }; +*/ const filenames = { linux: 'build-wrapper-win-x86.zip', @@ -32,7 +34,7 @@ const filenames = { mac: 'build-wrapper-macosx-x86.zip' }; -export default function BuildWrapper(props: Props) { +export default function BuildWrapper(props /*: Props */) { return ( <div className={props.className}> <h4 className="spacer-bottom"> diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/ClangGCC.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/ClangGCC.js index 7940263931c..2833ad4832c 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/ClangGCC.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/ClangGCC.js @@ -24,6 +24,7 @@ import SQScanner from './SQScanner'; import BuildWrapper from './BuildWrapper'; import { translate } from '../../../../helpers/l10n'; +/*:: type Props = { host: string, os: string, @@ -31,6 +32,7 @@ type Props = { projectKey: string, token: string }; +*/ const executables = { linux: 'build-wrapper-linux-x86-64', @@ -38,7 +40,7 @@ const executables = { mac: 'build-wrapper-macosx-x86' }; -export default function ClangGCC(props: Props) { +export default function ClangGCC(props /*: Props */) { const command1 = `${executables[props.os]} --out-dir bw-output make clean all`; const command2 = [ diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Command.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Command.js index ef1fb50431c..f5336761d0c 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Command.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Command.js @@ -23,22 +23,26 @@ import Clipboard from 'clipboard'; import Tooltip from '../../../../components/controls/Tooltip'; import { translate } from '../../../../helpers/l10n'; +/*:: type Props = { command: string | Array<?string> }; +*/ +/*:: type State = { tooltipShown: boolean }; +*/ const s = ' \\' + '\n '; export default class Command extends React.PureComponent { - clipboard: Object; - copyButton: HTMLButtonElement; - mounted: boolean; - props: Props; - state: State = { tooltipShown: false }; + /*:: clipboard: Object; */ + /*:: copyButton: HTMLButtonElement; */ + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { tooltipShown: false }; componentDidMount() { this.mounted = true; diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/DotNet.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/DotNet.js index 8885458953b..22d42c83e47 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/DotNet.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/DotNet.js @@ -23,14 +23,16 @@ import Command from './Command'; import MSBuildScanner from './MSBuildScanner'; import { translate } from '../../../../helpers/l10n'; +/*:: type Props = {| host: string, organization?: string, projectKey: string, token: string |}; +*/ -export default function DotNet(props: Props) { +export default function DotNet(props /*: Props */) { const command1 = [ 'SonarQube.Scanner.MSBuild.exe begin', `/k:"${props.projectKey}"`, diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/JavaGradle.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/JavaGradle.js index 7bec8730768..00b6ff5ba90 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/JavaGradle.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/JavaGradle.js @@ -22,13 +22,15 @@ import React from 'react'; import Command from './Command'; import { translate } from '../../../../helpers/l10n'; +/*:: type Props = {| host: string, organization?: string, token: string |}; +*/ -export default function JavaGradle(props: Props) { +export default function JavaGradle(props /*: Props */) { const config = 'plugins {\n id "org.sonarqube" version "2.5"\n}'; const command = [ diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/JavaMaven.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/JavaMaven.js index bbe6a513686..74f1e5b0729 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/JavaMaven.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/JavaMaven.js @@ -22,13 +22,15 @@ import React from 'react'; import Command from './Command'; import { translate } from '../../../../helpers/l10n'; +/*:: type Props = {| host: string, organization?: string, token: string |}; +*/ -export default function JavaMaven(props: Props) { +export default function JavaMaven(props /*: Props */) { const command = [ 'mvn sonar:sonar', props.organization && `-Dsonar.organization=${props.organization}`, diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/MSBuildScanner.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/MSBuildScanner.js index 2716e636090..725ceb936b9 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/MSBuildScanner.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/MSBuildScanner.js @@ -21,11 +21,13 @@ import React from 'react'; import { translate } from '../../../../helpers/l10n'; +/*:: type Props = { className?: string }; +*/ -export default function MSBuildScanner(props: Props) { +export default function MSBuildScanner(props /*: Props */) { return ( <div className={props.className}> <h4 className="spacer-bottom"> diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Msvc.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Msvc.js index fe18afad6e3..b73c4b2a947 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Msvc.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Msvc.js @@ -24,14 +24,16 @@ import MSBuildScanner from './MSBuildScanner'; import BuildWrapper from './BuildWrapper'; import { translate } from '../../../../helpers/l10n'; +/*:: type Props = {| host: string, organization?: string, projectKey: string, token: string |}; +*/ -export default function Msvc(props: Props) { +export default function Msvc(props /*: Props */) { const command1 = [ 'SonarQube.Scanner.MSBuild.exe begin', `/k:"${props.projectKey}"`, diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Other.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Other.js index 534be2f8584..0bb64ab425c 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Other.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Other.js @@ -23,6 +23,7 @@ import Command from './Command'; import SQScanner from './SQScanner'; import { translate } from '../../../../helpers/l10n'; +/*:: type Props = {| host: string, organization?: string, @@ -30,8 +31,9 @@ type Props = {| projectKey: string, token: string |}; +*/ -export default function Other(props: Props) { +export default function Other(props /*: Props */) { const command = [ props.os === 'win' ? 'sonar-scanner.bat' : 'sonar-scanner', `-Dsonar.projectKey=${props.projectKey}`, diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/SQScanner.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/SQScanner.js index d36c6379259..65c242597f2 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/SQScanner.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/SQScanner.js @@ -21,12 +21,14 @@ import React from 'react'; import { translate } from '../../../../helpers/l10n'; +/*:: type Props = { className?: string, os: string }; +*/ -export default function SQScanner(props: Props) { +export default function SQScanner(props /*: Props */) { return ( <div className={props.className}> <h4 className="spacer-bottom"> diff --git a/server/sonar-web/src/main/js/apps/users/components/UsersSearch.js b/server/sonar-web/src/main/js/apps/users/components/UsersSearch.js index 8d336b0c44f..32916a9f8ac 100644 --- a/server/sonar-web/src/main/js/apps/users/components/UsersSearch.js +++ b/server/sonar-web/src/main/js/apps/users/components/UsersSearch.js @@ -23,20 +23,24 @@ import { debounce } from 'lodash'; import classNames from 'classnames'; import { translate, translateWithParameters } from '../../../helpers/l10n'; +/*:: type Props = { onSearch: (query?: string) => void, className?: string }; +*/ +/*:: type State = { query?: string }; +*/ export default class UsersSearch extends React.PureComponent { - props: Props; - state: State; + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { query: '' @@ -44,11 +48,11 @@ export default class UsersSearch extends React.PureComponent { this.handleSearch = debounce(this.handleSearch, 250); } - handleSearch = (query: string) => { + handleSearch = (query /*: string */) => { this.props.onSearch(query); }; - handleInputChange = ({ target }: { target: HTMLInputElement }) => { + handleInputChange = ({ target } /*: { target: HTMLInputElement } */) => { this.setState({ query: target.value }); if (!target.value || target.value.length >= 2) { this.handleSearch(target.value); diff --git a/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearch.js b/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearch.js index dd64d1159bf..de77c5ed23b 100644 --- a/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearch.js +++ b/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearch.js @@ -25,6 +25,7 @@ import { translate, translateWithParameters } from '../../../helpers/l10n'; import UsersSelectSearchOption from './UsersSelectSearchOption'; import UsersSelectSearchValue from './UsersSelectSearchValue'; +/*:: export type Option = { login: string, name: string, @@ -32,7 +33,9 @@ export type Option = { avatar?: string, groupCount?: number }; +*/ +/*:: type Props = { autoFocus?: boolean, excludedUsers: Array<string>, @@ -40,21 +43,24 @@ type Props = { searchUsers: (string, number) => Promise<*>, selectedUser?: Option }; +*/ +/*:: type State = { isLoading: boolean, search: string, searchResult: Array<Option> }; +*/ const LIST_SIZE = 10; export default class UsersSelectSearch extends React.PureComponent { - mounted: boolean; - props: Props; - state: State; + /*:: mounted: boolean; */ + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.handleSearch = debounce(this.handleSearch, 250); this.state = { searchResult: [], isLoading: false, search: '' }; @@ -64,7 +70,7 @@ export default class UsersSelectSearch extends React.PureComponent { this.handleSearch(this.state.search); } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if (this.props.excludedUsers !== nextProps.excludedUsers) { this.handleSearch(this.state.search); } @@ -74,10 +80,10 @@ export default class UsersSelectSearch extends React.PureComponent { this.mounted = false; } - filterSearchResult = ({ users }: { users: Array<Option> }) => + filterSearchResult = ({ users } /*: { users: Array<Option> } */) => users.filter(user => !this.props.excludedUsers.includes(user.login)).slice(0, LIST_SIZE); - handleSearch = (search: string) => { + handleSearch = (search /*: string */) => { this.props .searchUsers(search, Math.min(this.props.excludedUsers.length + LIST_SIZE, 500)) .then(this.filterSearchResult) @@ -88,7 +94,7 @@ export default class UsersSelectSearch extends React.PureComponent { }); }; - handleInputChange = (search: string) => { + handleInputChange = (search /*: string */) => { if (search == null || search.length === 1) { this.setState({ search }); } else { diff --git a/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearchOption.js b/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearchOption.js index 5636a042c10..e148e31d78c 100644 --- a/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearchOption.js +++ b/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearchOption.js @@ -20,8 +20,9 @@ //@flow import React from 'react'; import Avatar from '../../../components/ui/Avatar'; -import type { Option } from './UsersSelectSearch'; +/*:: import type { Option } from './UsersSelectSearch'; */ +/*:: type Props = { option: Option, children?: Element | Text, @@ -30,23 +31,24 @@ type Props = { onFocus: (Option, MouseEvent) => void, onSelect: (Option, MouseEvent) => void }; +*/ -const AVATAR_SIZE: number = 20; +const AVATAR_SIZE /*: number */ = 20; export default class UsersSelectSearchOption extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleMouseDown = (event: MouseEvent) => { + handleMouseDown = (event /*: MouseEvent */) => { event.preventDefault(); event.stopPropagation(); this.props.onSelect(this.props.option, event); }; - handleMouseEnter = (event: MouseEvent) => { + handleMouseEnter = (event /*: MouseEvent */) => { this.props.onFocus(this.props.option, event); }; - handleMouseMove = (event: MouseEvent) => { + handleMouseMove = (event /*: MouseEvent */) => { if (this.props.isFocused) { return; } diff --git a/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearchValue.js b/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearchValue.js index d8e43c15f7e..b9823f264a7 100644 --- a/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearchValue.js +++ b/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearchValue.js @@ -20,17 +20,19 @@ //@flow import React from 'react'; import Avatar from '../../../components/ui/Avatar'; -import type { Option } from './UsersSelectSearch'; +/*:: import type { Option } from './UsersSelectSearch'; */ +/*:: type Props = { value: Option, children?: Element | Text }; +*/ -const AVATAR_SIZE: number = 20; +const AVATAR_SIZE /*: number */ = 20; export default class UsersSelectSearchValue extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const user = this.props.value; diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Action.js b/server/sonar-web/src/main/js/apps/web-api/components/Action.js index a0f5999bb9d..6e84e8a8a5b 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/Action.js +++ b/server/sonar-web/src/main/js/apps/web-api/components/Action.js @@ -29,31 +29,35 @@ import DeprecatedBadge from './DeprecatedBadge'; import InternalBadge from './InternalBadge'; import LinkIcon from '../../../components/icons-components/LinkIcon'; import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; -import type { Action as ActionType, Domain as DomainType } from '../../../api/web-api'; +/*:: import type { Action as ActionType, Domain as DomainType } from '../../../api/web-api'; */ +/*:: type Props = { action: ActionType, domain: DomainType, showDeprecated: boolean, showInternal: boolean }; +*/ +/*:: type State = { showChangelog: boolean, showParams: boolean, showResponse: boolean }; +*/ export default class Action extends React.PureComponent { - props: Props; + /*:: props: Props; */ - state: State = { + state /*: State */ = { showChangelog: false, showParams: false, showResponse: false }; - handleShowParamsClick = (e: SyntheticInputEvent) => { + handleShowParamsClick = (e /*: SyntheticInputEvent */) => { e.preventDefault(); this.setState({ showChangelog: false, @@ -62,7 +66,7 @@ export default class Action extends React.PureComponent { }); }; - handleShowResponseClick = (e: SyntheticInputEvent) => { + handleShowResponseClick = (e /*: SyntheticInputEvent */) => { e.preventDefault(); this.setState({ showChangelog: false, @@ -71,7 +75,7 @@ export default class Action extends React.PureComponent { }); }; - handleChangelogClick = (e: SyntheticInputEvent) => { + handleChangelogClick = (e /*: SyntheticInputEvent */) => { e.preventDefault(); this.setState({ showChangelog: !this.state.showChangelog, diff --git a/server/sonar-web/src/main/js/apps/web-api/components/ActionChangelog.js b/server/sonar-web/src/main/js/apps/web-api/components/ActionChangelog.js index 1b0b5b9e0c0..ff5b42b5213 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/ActionChangelog.js +++ b/server/sonar-web/src/main/js/apps/web-api/components/ActionChangelog.js @@ -20,15 +20,17 @@ // @flow import React from 'react'; +/*:: type Props = { changelog: Array<{ description: string, version: string }> }; +*/ export default class ActionChangelog extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { return ( diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Domain.js b/server/sonar-web/src/main/js/apps/web-api/components/Domain.js index a421f123144..e7240504008 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/Domain.js +++ b/server/sonar-web/src/main/js/apps/web-api/components/Domain.js @@ -23,17 +23,19 @@ import Action from './Action'; import DeprecatedBadge from './DeprecatedBadge'; import InternalBadge from './InternalBadge'; import { getActionKey, actionsFilter } from '../utils'; -import type { Domain as DomainType } from '../../../api/web-api'; +/*:: import type { Domain as DomainType } from '../../../api/web-api'; */ +/*:: type Props = { domain: DomainType, showDeprecated: boolean, showInternal: boolean, searchQuery: string }; +*/ export default class Domain extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const { domain, showInternal, showDeprecated, searchQuery } = this.props; diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Menu.js b/server/sonar-web/src/main/js/apps/web-api/components/Menu.js index a3069a0f7bb..521817badff 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/Menu.js +++ b/server/sonar-web/src/main/js/apps/web-api/components/Menu.js @@ -25,8 +25,9 @@ import DeprecatedBadge from './DeprecatedBadge'; import InternalBadge from './InternalBadge'; import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; import { isDomainPathActive, actionsFilter } from '../utils'; -import type { Domain as DomainType } from '../../../api/web-api'; +/*:: import type { Domain as DomainType } from '../../../api/web-api'; */ +/*:: type Props = { domains: Array<DomainType>, showDeprecated: boolean, @@ -34,9 +35,10 @@ type Props = { searchQuery: string, splat: string }; +*/ export default class Menu extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const { domains, showInternal, showDeprecated, searchQuery, splat } = this.props; diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Params.js b/server/sonar-web/src/main/js/apps/web-api/components/Params.js index cda32ebceeb..f2e7751c3c0 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/Params.js +++ b/server/sonar-web/src/main/js/apps/web-api/components/Params.js @@ -21,14 +21,15 @@ import React from 'react'; import InternalBadge from './InternalBadge'; import DeprecatedBadge from './DeprecatedBadge'; -import type { Param } from '../../../api/web-api'; +/*:: import type { Param } from '../../../api/web-api'; */ export default class Params extends React.PureComponent { - props: { + /*:: props: { showDeprecated: boolean, showInternal: boolean, params: Array<Param> }; +*/ render() { const { showDeprecated, showInternal, params } = this.props; diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Search.js b/server/sonar-web/src/main/js/apps/web-api/components/Search.js index f5971512023..859ad7704e8 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/Search.js +++ b/server/sonar-web/src/main/js/apps/web-api/components/Search.js @@ -24,6 +24,7 @@ import Checkbox from '../../../components/controls/Checkbox'; import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { showDeprecated: boolean, showInternal: boolean, @@ -31,23 +32,26 @@ type Props = { onToggleInternal: () => void, onToggleDeprecated: () => void }; +*/ +/*:: type State = { query: string }; +*/ export default class Search extends React.PureComponent { - actuallySearch: () => void; - props: Props; - state: State; + /*:: actuallySearch: () => void; */ + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { query: '' }; this.actuallySearch = debounce(this.actuallySearch, 250); } - handleSearch = (e: SyntheticInputEvent) => { + handleSearch = (e /*: SyntheticInputEvent */) => { const { value } = e.target; this.setState({ query: value }); this.actuallySearch(); diff --git a/server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.js b/server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.js index 186bda54c7a..a8e8eadb27e 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.js +++ b/server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.js @@ -28,20 +28,22 @@ import Search from './Search'; import Domain from './Domain'; import { getActionKey, isDomainPathActive } from '../utils'; import { translate } from '../../../helpers/l10n'; -import type { Domain as DomainType } from '../../../api/web-api'; +/*:: import type { Domain as DomainType } from '../../../api/web-api'; */ import '../styles/web-api.css'; +/*:: type State = { domains: Array<DomainType>, searchQuery: string, showDeprecated: boolean, showInternal: boolean }; +*/ export default class WebApiApp extends React.PureComponent { - mounted: boolean; - scrollToAction: () => void; - state: State = { + /*:: mounted: boolean; */ + /*:: scrollToAction: () => void; */ + state /*: State */ = { domains: [], searchQuery: '', showDeprecated: false, @@ -70,7 +72,7 @@ export default class WebApiApp extends React.PureComponent { } } - fetchList(cb?: () => void) { + fetchList(cb /*: void | () => void */) { fetchWebApi().then(domains => { if (this.mounted) { this.setState({ domains }, cb); @@ -83,7 +85,7 @@ export default class WebApiApp extends React.PureComponent { this.scrollToElement(splat); }; - scrollToElement(id: string) { + scrollToElement(id /*: string */) { const element = document.getElementById(id); if (element) { @@ -115,7 +117,7 @@ export default class WebApiApp extends React.PureComponent { } } - handleSearch = (searchQuery: string) => { + handleSearch = (searchQuery /*: string */) => { this.setState({ searchQuery }); }; diff --git a/server/sonar-web/src/main/js/apps/web-api/utils.js b/server/sonar-web/src/main/js/apps/web-api/utils.js index bd6efd34467..5610c47142b 100644 --- a/server/sonar-web/src/main/js/apps/web-api/utils.js +++ b/server/sonar-web/src/main/js/apps/web-api/utils.js @@ -18,14 +18,14 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ //@flow -import type { Domain, Action } from '../../api/web-api'; +/*:: import type { Domain, Action } from '../../api/web-api'; */ export function actionsFilter( - showDeprecated: boolean, - showInternal: boolean, - searchQuery: string, - domain: Domain, - action: Action + showDeprecated /*: boolean */, + showInternal /*: boolean */, + searchQuery /*: string */, + domain /*: Domain */, + action /*: Action */ ) { const lowSearchQuery = searchQuery.toLowerCase(); return ( @@ -36,11 +36,11 @@ export function actionsFilter( ); } -export function getActionKey(domainPath: string, actionKey: string) { +export function getActionKey(domainPath /*: string */, actionKey /*: string */) { return domainPath + '/' + actionKey; } -export const isDomainPathActive = (path: string, splat: string) => { +export const isDomainPathActive = (path /*: string */, splat /*: string */) => { const pathTokens = path.split('/'); const splatTokens = splat.split('/'); diff --git a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewer.js b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewer.js index 7e301a6bae1..7da0f6f853b 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewer.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewer.js @@ -24,11 +24,13 @@ import { receiveFavorites } from '../../store/favorites/duck'; const mapStateToProps = null; -const onReceiveComponent = (component: { +const onReceiveComponent = ( + component /*: { key: string, canMarkAsFavorite: boolean, fav: boolean -}) => dispatch => { +} */ +) => dispatch => { if (component.canMarkAsFavorite) { const favorites = []; const notFavorites = []; diff --git a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.js b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.js index 3dab0e0698a..217e33ce936 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.js @@ -36,7 +36,7 @@ import { duplicationsByLine, symbolsByLine } from './helpers/indexing'; -import type { LinearIssueLocation } from './helpers/indexing'; +/*:: import type { LinearIssueLocation } from './helpers/indexing'; */ import { getComponentForSourceViewer, getSources, @@ -45,12 +45,13 @@ import { } from '../../api/components'; import { translate } from '../../helpers/l10n'; import { scrollToElement } from '../../helpers/scrolling'; -import type { SourceLine } from './types'; -import type { Issue, FlowLocation } from '../issue/types'; +/*:: import type { SourceLine } from './types'; */ +/*:: import type { Issue, FlowLocation } from '../issue/types'; */ import './styles.css'; // TODO react-virtualized +/*:: type Props = { aroundLine?: number, component: string, @@ -71,7 +72,9 @@ type Props = { scroll?: HTMLElement => void, selectedIssue?: string }; +*/ +/*:: type State = { component?: Object, displayDuplications: boolean, @@ -101,22 +104,27 @@ type State = { sourceRemoved: boolean, symbolsByLine: { [number]: Array<string> } }; +*/ const LINES = 500; -const loadComponent = (key: string): Promise<*> => { +function loadComponent(key /*: string */) /*: Promise<*> */ { return getComponentForSourceViewer(key); -}; +} -const loadSources = (key: string, from?: number, to?: number): Promise<Array<*>> => { +function loadSources( + key /*: string */, + from /*: ?number */, + to /*: ?number */ +) /*: Promise<Array<*>> */ { return getSources(key, from, to); -}; +} export default class SourceViewerBase extends React.PureComponent { - mounted: boolean; - node: HTMLElement; - props: Props; - state: State; + /*:: mounted: boolean; */ + /*:: node: HTMLElement; */ + /*:: props: Props; */ + /*:: state: State; */ static defaultProps = { displayAllIssues: false, @@ -125,7 +133,7 @@ export default class SourceViewerBase extends React.PureComponent { loadSources }; - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { displayDuplications: false, @@ -155,13 +163,13 @@ export default class SourceViewerBase extends React.PureComponent { this.fetchComponent(); } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if (nextProps.onIssueSelect != null && nextProps.selectedIssue !== this.props.selectedIssue) { this.setState({ selectedIssue: nextProps.selectedIssue }); } } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if (prevProps.component !== this.props.component) { this.fetchComponent(); } else if ( @@ -187,7 +195,7 @@ export default class SourceViewerBase extends React.PureComponent { this.mounted = false; } - scrollToLine(line: number) { + scrollToLine(line /*: number */) { const lineElement = this.node.querySelector( `.source-line-code[data-line-number="${line}"] .source-line-issue-locations` ); @@ -196,11 +204,11 @@ export default class SourceViewerBase extends React.PureComponent { } } - computeCoverageStatus(lines: Array<SourceLine>): Array<SourceLine> { + computeCoverageStatus(lines /*: Array<SourceLine> */) /*: Array<SourceLine> */ { return lines.map(line => ({ ...line, coverageStatus: getCoverageStatus(line) })); } - isLineOutsideOfRange(lineNumber: number) { + isLineOutsideOfRange(lineNumber /*: number */) { const { sources } = this.state; if (sources != null && sources.length > 0) { const firstLine = sources[0]; @@ -397,7 +405,7 @@ export default class SourceViewerBase extends React.PureComponent { }); }; - loadDuplications = (line: SourceLine) => { + loadDuplications = (line /*: SourceLine */) => { getDuplications(this.props.component).then(r => { if (this.mounted) { this.setState( @@ -423,14 +431,14 @@ export default class SourceViewerBase extends React.PureComponent { measuresOverlay.render(); }; - handleCoverageClick = (line: SourceLine, element: HTMLElement) => { + handleCoverageClick = (line /*: SourceLine */, element /*: HTMLElement */) => { getTests(this.props.component, line.line).then(tests => { const popup = new CoveragePopupView({ line, tests, triggerEl: element }); popup.render(); }); }; - handleDuplicationClick = (index: number, line: number) => { + handleDuplicationClick = (index /*: number */, line /*: number */) => { const duplication = this.state.duplications && this.state.duplications[index]; let blocks = (duplication && duplication.blocks) || []; const inRemovedComponent = blocks.some(b => b._ref == null); @@ -462,7 +470,7 @@ export default class SourceViewerBase extends React.PureComponent { } }; - displayLinePopup(line: number, element: HTMLElement) { + displayLinePopup(line /*: number */, element /*: HTMLElement */) { const popup = new LineActionsPopupView({ line, triggerEl: element, @@ -471,14 +479,14 @@ export default class SourceViewerBase extends React.PureComponent { popup.render(); } - handleLineClick = (line: SourceLine, element: HTMLElement) => { + handleLineClick = (line /*: SourceLine */, element /*: HTMLElement */) => { this.setState(prevState => ({ highlightedLine: prevState.highlightedLine === line.line ? null : line })); this.displayLinePopup(line.line, element); }; - handleSymbolClick = (symbols: Array<string>) => { + handleSymbolClick = (symbols /*: Array<string> */) => { this.setState(state => { const shouldDisable = intersection(state.highlightedSymbols, symbols).length > 0; const highlightedSymbols = shouldDisable ? [] : symbols; @@ -486,12 +494,12 @@ export default class SourceViewerBase extends React.PureComponent { }); }; - handleSCMClick = (line: SourceLine, element: HTMLElement) => { + handleSCMClick = (line /*: SourceLine */, element /*: HTMLElement */) => { const popup = new SCMPopupView({ triggerEl: element, line }); popup.render(); }; - handleIssueSelect = (issue: string) => { + handleIssueSelect = (issue /*: string */) => { if (this.props.onIssueSelect) { this.props.onIssueSelect(issue); } else { @@ -507,19 +515,19 @@ export default class SourceViewerBase extends React.PureComponent { } }; - handleOpenIssues = (line: SourceLine) => { + handleOpenIssues = (line /*: SourceLine */) => { this.setState(state => ({ openIssuesByLine: { ...state.openIssuesByLine, [line.line]: true } })); }; - handleCloseIssues = (line: SourceLine) => { + handleCloseIssues = (line /*: SourceLine */) => { this.setState(state => ({ openIssuesByLine: { ...state.openIssuesByLine, [line.line]: false } })); }; - handleIssueChange = (issue: Issue) => { + handleIssueChange = (issue /*: Issue */) => { this.setState(state => { const issues = state.issues.map( candidate => (candidate.key === issue.key ? issue : candidate) @@ -531,7 +539,7 @@ export default class SourceViewerBase extends React.PureComponent { } }; - renderCode(sources: Array<SourceLine>) { + renderCode(sources /*: Array<SourceLine> */) { const hasSourcesBefore = sources.length > 0 && sources[0].line > 1; return ( <SourceViewerCode diff --git a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerCode.js b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerCode.js index b8708d91d7f..b739c6b0840 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerCode.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerCode.js @@ -23,9 +23,9 @@ import { intersection } from 'lodash'; import Line from './components/Line'; import { translate } from '../../helpers/l10n'; import { getLinearLocations } from './helpers/issueLocations'; -import type { Duplication, SourceLine } from './types'; -import type { Issue, FlowLocation } from '../issue/types'; -import type { LinearIssueLocation } from './helpers/indexing'; +/*:: import type { Duplication, SourceLine } from './types'; */ +/*:: import type { Issue, FlowLocation } from '../issue/types'; */ +/*:: import type { LinearIssueLocation } from './helpers/indexing'; */ const EMPTY_ARRAY = []; @@ -36,7 +36,7 @@ const ZERO_LINE = { }; export default class SourceViewerCode extends React.PureComponent { - props: {| + /*:: props: {| displayAllIssues: boolean, duplications?: Array<Duplication>, duplicationsByLine: { [number]: Array<number> }, @@ -73,22 +73,23 @@ export default class SourceViewerCode extends React.PureComponent { sources: Array<SourceLine>, symbolsByLine: { [number]: Array<string> } |}; +*/ - getDuplicationsForLine(line: SourceLine) { + getDuplicationsForLine(line /*: SourceLine */) { return this.props.duplicationsByLine[line.line] || EMPTY_ARRAY; } - getIssuesForLine(line: SourceLine): Array<Issue> { + getIssuesForLine(line /*: SourceLine */) /*: Array<Issue> */ { return this.props.issuesByLine[line.line] || EMPTY_ARRAY; } - getIssueLocationsForLine(line: SourceLine) { + getIssueLocationsForLine(line /*: SourceLine */) { return this.props.issueLocationsByLine[line.line] || EMPTY_ARRAY; } getSecondaryIssueLocationsForLine( - line: SourceLine - ): Array<{ from: number, to: number, line: number, index: number, startLine: number }> { + line /*: SourceLine */ + ) /*: Array<{ from: number, to: number, line: number, index: number, startLine: number }> */ { const { highlightedLocations } = this.props; if (!highlightedLocations) { return EMPTY_ARRAY; @@ -102,12 +103,12 @@ export default class SourceViewerCode extends React.PureComponent { } renderLine = ( - line: SourceLine, - index: number, - displayCoverage: boolean, - displayDuplications: boolean, - displayFiltered: boolean, - displayIssues: boolean + line /*: SourceLine */, + index /*: number */, + displayCoverage /*: boolean */, + displayDuplications /*: boolean */, + displayFiltered /*: boolean */, + displayIssues /*: boolean */ ) => { const { filterLine, highlightedLocationMessage, selectedIssue, sources } = this.props; const filtered = filterLine ? filterLine(line) : null; diff --git a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeader.js b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeader.js index 0a0e2b3c21b..9391f3dedf9 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeader.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeader.js @@ -28,7 +28,7 @@ import { translate } from '../../helpers/l10n'; import { formatMeasure } from '../../helpers/measures'; export default class SourceViewerHeader extends React.PureComponent { - props: { + /*:: props: { component: { canMarkAsFavorite: boolean, key: string, @@ -49,13 +49,14 @@ export default class SourceViewerHeader extends React.PureComponent { }, showMeasures: () => void }; +*/ - showMeasures = (e: SyntheticInputEvent) => { + showMeasures = (e /*: SyntheticInputEvent */) => { e.preventDefault(); this.props.showMeasures(); }; - openInWorkspace = (e: SyntheticInputEvent) => { + openInWorkspace = (e /*: SyntheticInputEvent */) => { e.preventDefault(); const { key } = this.props.component; const Workspace = require('../workspace/main').default; diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/Line.js b/server/sonar-web/src/main/js/components/SourceViewer/components/Line.js index 664297c4774..0e66fbbe50a 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/Line.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/Line.js @@ -28,10 +28,11 @@ import LineDuplications from './LineDuplications'; import LineDuplicationBlock from './LineDuplicationBlock'; import LineIssuesIndicator from './LineIssuesIndicator'; import LineCode from './LineCode'; -import type { SourceLine } from '../types'; -import type { LinearIssueLocation } from '../helpers/indexing'; -import type { Issue } from '../../issue/types'; +/*:: import type { SourceLine } from '../types'; */ +/*:: import type { LinearIssueLocation } from '../helpers/indexing'; */ +/*:: import type { Issue } from '../../issue/types'; */ +/*:: type Props = {| displayAllIssues: boolean, displayCoverage: boolean, @@ -72,9 +73,10 @@ type Props = {| }>, selectedIssue: string | null |}; +*/ export default class Line extends React.PureComponent { - props: Props; + /*:: props: Props; */ handleIssuesIndicatorClick = () => { if (this.props.openIssues) { diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.js b/server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.js index 1183a2b83b8..e9493b8a8b9 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.js @@ -24,11 +24,12 @@ import LineIssuesList from './LineIssuesList'; import LocationIndex from '../../common/LocationIndex'; import LocationMessage from '../../common/LocationMessage'; import { splitByTokens, highlightSymbol, highlightIssueLocations } from '../helpers/highlight'; -import type { Tokens } from '../helpers/highlight'; -import type { SourceLine } from '../types'; -import type { LinearIssueLocation } from '../helpers/indexing'; -import type { Issue } from '../../issue/types'; +/*:: import type { Tokens } from '../helpers/highlight'; */ +/*:: import type { SourceLine } from '../types'; */ +/*:: import type { LinearIssueLocation } from '../helpers/indexing'; */ +/*:: import type { Issue } from '../../issue/types'; */ +/*:: type Props = {| highlightedLocationMessage?: { index: number, text: string }, highlightedSymbols?: Array<string>, @@ -50,19 +51,22 @@ type Props = {| selectedIssue: string | null, showIssues: boolean |}; +*/ +/*:: type State = { tokens: Tokens }; +*/ export default class LineCode extends React.PureComponent { - activeMarkerNode: ?HTMLElement; - codeNode: HTMLElement; - props: Props; - state: State; - symbols: NodeList<HTMLElement>; + /*:: activeMarkerNode: ?HTMLElement; */ + /*:: codeNode: HTMLElement; */ + /*:: props: Props; */ + /*:: state: State; */ + /*:: symbols: NodeList<HTMLElement>; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { tokens: splitByTokens(props.line.code || '') @@ -76,7 +80,7 @@ export default class LineCode extends React.PureComponent { } } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if (nextProps.line.code !== this.props.line.code) { this.setState({ tokens: splitByTokens(nextProps.line.code || '') @@ -88,7 +92,7 @@ export default class LineCode extends React.PureComponent { this.detachEvents(); } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { this.attachEvents(); if ( this.props.highlightedLocationMessage && @@ -119,7 +123,7 @@ export default class LineCode extends React.PureComponent { } } - handleSymbolClick = (e: Object) => { + handleSymbolClick = (e /*: Object */) => { e.preventDefault(); const keys = e.currentTarget.className.match(/sym-\d+/g); if (keys.length > 0) { @@ -127,7 +131,7 @@ export default class LineCode extends React.PureComponent { } }; - renderMarker(index: number, message: ?string) { + renderMarker(index /*: number */, message /*: ?string */) { const { onLocationSelect } = this.props; const onClick = onLocationSelect ? () => onLocationSelect(index) : undefined; const ref = message != null ? node => (this.activeMarkerNode = node) : undefined; diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/LineCoverage.js b/server/sonar-web/src/main/js/components/SourceViewer/components/LineCoverage.js index f069427afe0..70d3bc3d258 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/LineCoverage.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/LineCoverage.js @@ -21,17 +21,19 @@ import React from 'react'; import Tooltip from '../../controls/Tooltip'; import { translate } from '../../../helpers/l10n'; -import type { SourceLine } from '../types'; +/*:: import type { SourceLine } from '../types'; */ +/*:: type Props = { line: SourceLine, onClick: (SourceLine, HTMLElement) => void }; +*/ export default class LineCoverage extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleClick = (e: SyntheticInputEvent) => { + handleClick = (e /*: SyntheticInputEvent */) => { e.preventDefault(); this.props.onClick(this.props.line, e.target); }; diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/LineDuplicationBlock.js b/server/sonar-web/src/main/js/components/SourceViewer/components/LineDuplicationBlock.js index ee1373fdde5..c079ee52490 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/LineDuplicationBlock.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/LineDuplicationBlock.js @@ -22,19 +22,21 @@ import React from 'react'; import classNames from 'classnames'; import Tooltip from '../../controls/Tooltip'; import { translate } from '../../../helpers/l10n'; -import type { SourceLine } from '../types'; +/*:: import type { SourceLine } from '../types'; */ +/*:: type Props = { duplicated: boolean, index: number, line: SourceLine, onClick: (index: number, lineNumber: number) => void }; +*/ export default class LineDuplicationBlock extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleClick = (e: SyntheticInputEvent) => { + handleClick = (e /*: SyntheticInputEvent */) => { e.preventDefault(); this.props.onClick(this.props.index, this.props.line.line); }; diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/LineDuplications.js b/server/sonar-web/src/main/js/components/SourceViewer/components/LineDuplications.js index d1f802c6337..2e394b89b9c 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/LineDuplications.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/LineDuplications.js @@ -22,17 +22,19 @@ import React from 'react'; import classNames from 'classnames'; import Tooltip from '../../controls/Tooltip'; import { translate } from '../../../helpers/l10n'; -import type { SourceLine } from '../types'; +/*:: import type { SourceLine } from '../types'; */ +/*:: type Props = { line: SourceLine, onClick: SourceLine => void }; +*/ export default class LineDuplications extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleClick = (e: SyntheticInputEvent) => { + handleClick = (e /*: SyntheticInputEvent */) => { e.preventDefault(); this.props.onClick(this.props.line); }; diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/LineIssuesIndicator.js b/server/sonar-web/src/main/js/components/SourceViewer/components/LineIssuesIndicator.js index 283dc54709a..1c3db0733f5 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/LineIssuesIndicator.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/LineIssuesIndicator.js @@ -22,19 +22,21 @@ import React from 'react'; import classNames from 'classnames'; import SeverityIcon from '../../shared/SeverityIcon'; import { sortBySeverity } from '../../../helpers/issues'; -import type { SourceLine } from '../types'; -import type { Issue } from '../../issue/types'; +/*:: import type { SourceLine } from '../types'; */ +/*:: import type { Issue } from '../../issue/types'; */ +/*:: type Props = { issues: Array<Issue>, line: SourceLine, onClick: () => void }; +*/ export default class LineIssuesIndicator extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleClick = (e: SyntheticInputEvent) => { + handleClick = (e /*: SyntheticInputEvent */) => { e.preventDefault(); this.props.onClick(); }; diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/LineIssuesList.js b/server/sonar-web/src/main/js/components/SourceViewer/components/LineIssuesList.js index 64fd1202ca5..7a498665fae 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/LineIssuesList.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/LineIssuesList.js @@ -20,17 +20,19 @@ // @flow import React from 'react'; import Issue from '../../issue/Issue'; -import type { Issue as IssueType } from '../../issue/types'; +/*:: import type { Issue as IssueType } from '../../issue/types'; */ +/*:: type Props = { issues: Array<IssueType>, onIssueChange: IssueType => void, onIssueClick: (issueKey: string) => void, selectedIssue: string | null }; +*/ export default class LineIssuesList extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const { issues, onIssueClick, selectedIssue } = this.props; diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/LineNumber.js b/server/sonar-web/src/main/js/components/SourceViewer/components/LineNumber.js index 6222d6335c1..b486370e6ae 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/LineNumber.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/LineNumber.js @@ -19,17 +19,19 @@ */ // @flow import React from 'react'; -import type { SourceLine } from '../types'; +/*:: import type { SourceLine } from '../types'; */ +/*:: type Props = { line: SourceLine, onClick: (SourceLine, HTMLElement) => void }; +*/ export default class LineNumber extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleClick = (e: SyntheticInputEvent) => { + handleClick = (e /*: SyntheticInputEvent */) => { e.preventDefault(); this.props.onClick(this.props.line, e.target); }; diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/LineSCM.js b/server/sonar-web/src/main/js/components/SourceViewer/components/LineSCM.js index 2f2728e0b52..abcaa287007 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/LineSCM.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/LineSCM.js @@ -19,23 +19,25 @@ */ // @flow import React from 'react'; -import type { SourceLine } from '../types'; +/*:: import type { SourceLine } from '../types'; */ +/*:: type Props = { line: SourceLine, previousLine?: SourceLine, onClick: (SourceLine, HTMLElement) => void }; +*/ export default class LineSCM extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleClick = (e: SyntheticInputEvent) => { + handleClick = (e /*: SyntheticInputEvent */) => { e.preventDefault(); this.props.onClick(this.props.line, e.target); }; - isSCMChanged(s: SourceLine, p?: SourceLine) { + isSCMChanged(s /*: SourceLine */, p /*: ?SourceLine */) { let changed = true; if (p != null && s.scmAuthor != null && p.scmAuthor != null) { changed = s.scmAuthor !== p.scmAuthor || s.scmDate !== p.scmDate; diff --git a/server/sonar-web/src/main/js/components/SourceViewer/helpers/getCoverageStatus.js b/server/sonar-web/src/main/js/components/SourceViewer/helpers/getCoverageStatus.js index 2f99ed81675..7b8ab889aab 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/helpers/getCoverageStatus.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/helpers/getCoverageStatus.js @@ -18,9 +18,9 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // @flow -import type { SourceLine } from '../types'; +/*:: import type { SourceLine } from '../types'; */ -const getCoverageStatus = (s: SourceLine): string | null => { +export default function getCoverageStatus(s /*: SourceLine */) /*: string | null */ { let status = null; if (s.lineHits != null && s.lineHits > 0) { status = 'partially-covered'; @@ -32,6 +32,4 @@ const getCoverageStatus = (s: SourceLine): string | null => { status = 'uncovered'; } return status; -}; - -export default getCoverageStatus; +} diff --git a/server/sonar-web/src/main/js/components/SourceViewer/helpers/highlight.js b/server/sonar-web/src/main/js/components/SourceViewer/helpers/highlight.js index 1666f781644..f21dde8b300 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/helpers/highlight.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/helpers/highlight.js @@ -21,12 +21,15 @@ import escapeHtml from 'escape-html'; import { uniq } from 'lodash'; +/*:: export type Token = { className: string, markers: Array<number>, text: string }; -export type Tokens = Array<Token>; +*/ +/*:: +export type Tokens = Array<Token>; */ const ISSUE_LOCATION_CLASS = 'source-line-code-issue'; -export const splitByTokens = (code: string, rootClassName: string = ''): Tokens => { +export function splitByTokens(code /*: string */, rootClassName /*: string */ = '') /*: Tokens */ { const container = document.createElement('div'); let tokens = []; container.innerHTML = code; @@ -43,9 +46,9 @@ export const splitByTokens = (code: string, rootClassName: string = ''): Tokens } }); return tokens; -}; +} -export const highlightSymbol = (tokens: Tokens, symbol: string): Tokens => { +export function highlightSymbol(tokens /*: Tokens */, symbol /*: string */) /*: Tokens */ { const symbolRegExp = new RegExp(`\\b${symbol}\\b`); return tokens.map( token => @@ -53,7 +56,7 @@ export const highlightSymbol = (tokens: Tokens, symbol: string): Tokens => { ? { ...token, className: `${token.className} highlighted` } : token ); -}; +} /** * Intersect two ranges @@ -62,14 +65,14 @@ export const highlightSymbol = (tokens: Tokens, symbol: string): Tokens => { * @param s2 Start position of the second range * @param e2 End position of the second range */ -const intersect = ( - s1: number, - e1: number, - s2: number, - e2: number -): { from: number, to: number } => { +function intersect( + s1 /*: number */, + e1 /*: number */, + s2 /*: number */, + e2 /*: number */ +) /*: { from: number, to: number } */ { return { from: Math.max(s1, s2), to: Math.min(e1, e2) }; -}; +} /** * Get the substring of a string @@ -78,19 +81,24 @@ const intersect = ( * @param to "To" offset * @param acc Global offset to eliminate */ -const part = (str: string, from: number, to: number, acc: number): string => { +function part( + str /*: string */, + from /*: number */, + to /*: number */, + acc /*: number */ +) /*: string */ { // we do not want negative number as the first argument of `substr` return from >= acc ? str.substr(from - acc, to - from) : str.substr(0, to - from); -}; +} /** * Highlight issue locations in the list of tokens */ -export const highlightIssueLocations = ( - tokens: Tokens, - issueLocations: Array<*>, - rootClassName: string = ISSUE_LOCATION_CLASS -): Tokens => { +export function highlightIssueLocations( + tokens /*: Tokens */, + issueLocations /*: Array<*> */, + rootClassName /*: string */ = ISSUE_LOCATION_CLASS +) /*: Tokens */ { issueLocations.forEach(location => { const nextTokens = []; let acc = 0; @@ -126,10 +134,10 @@ export const highlightIssueLocations = ( tokens = nextTokens.slice(); }); return tokens; -}; +} -export const generateHTML = (tokens: Tokens): string => { +export function generateHTML(tokens /*: Tokens */) /*: string */ { return tokens .map(token => `<span class="${token.className}">${escapeHtml(token.text)}</span>`) .join(''); -}; +} diff --git a/server/sonar-web/src/main/js/components/SourceViewer/helpers/indexing.js b/server/sonar-web/src/main/js/components/SourceViewer/helpers/indexing.js index eac2170df15..a3f60881124 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/helpers/indexing.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/helpers/indexing.js @@ -21,29 +21,35 @@ import { flatten } from 'lodash'; import { splitByTokens } from './highlight'; import { getLinearLocations } from './issueLocations'; -import type { Issue } from '../../issue/types'; -import type { SourceLine } from '../types'; +/*:: import type { Issue } from '../../issue/types'; */ +/*:: import type { SourceLine } from '../types'; */ +/*:: export type LinearIssueLocation = { from: number, line: number, to: number, index?: number }; +*/ +/*:: export type IndexedIssueLocation = { from: number, line: number, to: number }; +*/ +/*:: export type IndexedIssueLocationMessage = { flowIndex: number, locationIndex: number, msg?: string }; +*/ -export const issuesByLine = (issues: Array<Issue>) => { +export const issuesByLine = (issues /*: Array<Issue> */) => { const index = {}; issues.forEach(issue => { const line = issue.textRange ? issue.textRange.endLine : 0; @@ -55,7 +61,9 @@ export const issuesByLine = (issues: Array<Issue>) => { return index; }; -export const locationsByLine = (issues: Array<Issue>): { [number]: Array<LinearIssueLocation> } => { +export function locationsByLine( + issues /*: Array<Issue> */ +) /*: { [number]: Array<LinearIssueLocation> } */ { const index = {}; issues.forEach(issue => { getLinearLocations(issue.textRange).forEach(location => { @@ -66,9 +74,9 @@ export const locationsByLine = (issues: Array<Issue>): { [number]: Array<LinearI }); }); return index; -}; +} -export const duplicationsByLine = (duplications: Array<*> | null) => { +export const duplicationsByLine = (duplications /*: Array<*> | null */) => { if (duplications == null) { return {}; } @@ -91,7 +99,7 @@ export const duplicationsByLine = (duplications: Array<*> | null) => { return duplicationsByLine; }; -export const symbolsByLine = (sources: Array<SourceLine>) => { +export const symbolsByLine = (sources /*: Array<SourceLine> */) => { const index = {}; sources.forEach(line => { const tokens = splitByTokens(line.code); diff --git a/server/sonar-web/src/main/js/components/SourceViewer/helpers/issueLocations.js b/server/sonar-web/src/main/js/components/SourceViewer/helpers/issueLocations.js index 0a1eb45bc3f..64b1c3a61fa 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/helpers/issueLocations.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/helpers/issueLocations.js @@ -18,11 +18,11 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // @flow -import type { TextRange, Issue } from '../../issue/types'; +/*:: import type { TextRange, Issue } from '../../issue/types'; */ -export const getLinearLocations = ( - textRange?: TextRange -): Array<{ line: number, from: number, to: number }> => { +export function getLinearLocations( + textRange /*: ?TextRange */ +) /*: Array<{ line: number, from: number, to: number }> */ { if (!textRange) { return []; } @@ -36,17 +36,19 @@ export const getLinearLocations = ( locations.push({ line, from, to }); } return locations; -}; +} -export const getIssueLocations = ( - issue: Issue -): Array<{ +/*:: +type Location = { msg: string, flowIndex: number, locationIndex: number, textRange?: TextRange, index?: number -}> => { +} +*/ + +export function getIssueLocations(issue /*: Issue */) /*: Array<Location> */ { const allLocations = []; issue.flows.forEach((locations, flowIndex) => { if (locations) { @@ -64,4 +66,4 @@ export const getIssueLocations = ( } }); return allLocations; -}; +} diff --git a/server/sonar-web/src/main/js/components/SourceViewer/helpers/loadIssues.js b/server/sonar-web/src/main/js/components/SourceViewer/helpers/loadIssues.js index 737b9acedda..8d86b7c4a19 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/helpers/loadIssues.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/helpers/loadIssues.js @@ -21,25 +21,30 @@ import { searchIssues } from '../../../api/issues'; import { parseIssueFromResponse } from '../../../helpers/issues'; +/*:: export type Query = { [string]: string }; +*/ -export type Issues = Array<*>; +/*:: +export type Issues = Array<*>; */ // maximum possible value const PAGE_SIZE = 500; -const buildQuery = (component: string): Query => ({ - additionalFields: '_all', - resolved: 'false', - componentKeys: component, - s: 'FILE_LINE' -}); +function buildQuery(component /*: string */) /*: Query */ { + return { + additionalFields: '_all', + resolved: 'false', + componentKeys: component, + s: 'FILE_LINE' + }; +} -export const loadPage = ( - query: Query, - page: number, - pageSize: number = PAGE_SIZE -): Promise<Issues> => { +export function loadPage( + query /*: Query */, + page /*: number */, + pageSize /*: number */ = PAGE_SIZE +) /*: Promise<Issues> */ { return searchIssues({ ...query, p: page, @@ -47,14 +52,14 @@ export const loadPage = ( }).then(r => r.issues.map(issue => parseIssueFromResponse(issue, r.components, r.users, r.rules)) ); -}; +} -export const loadPageAndNext = ( - query: Query, - toLine: number, - page: number, - pageSize: number = PAGE_SIZE -): Promise<Issues> => { +export function loadPageAndNext( + query /*: Query */, + toLine /*: number */, + page /*: number */, + pageSize /*: number */ = PAGE_SIZE +) /*: Promise<Issues> */ { return loadPage(query, page).then(issues => { if (issues.length === 0) { return []; @@ -73,15 +78,19 @@ export const loadPageAndNext = ( return [...issues, ...nextIssues]; }); }); -}; +} -const loadIssues = (component: string, fromLine: number, toLine: number): Promise<Issues> => { +function loadIssues( + component /*: string */, + fromLine /*: number */, + toLine /*: number */ +) /*: Promise<Issues> */ { const query = buildQuery(component); return new Promise(resolve => { loadPageAndNext(query, toLine, 1).then(issues => { resolve(issues); }); }); -}; +} export default loadIssues; diff --git a/server/sonar-web/src/main/js/components/SourceViewer/types.js b/server/sonar-web/src/main/js/components/SourceViewer/types.js index 3dd00eeb553..cbcbaf3e2da 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/types.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/types.js @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // @flow +/*:: export type SourceLine = { code: string, conditions?: number, @@ -30,7 +31,9 @@ export type SourceLine = { scmDate?: string, scmRevision?: string }; +*/ +/*:: export type Duplication = { blocks: Array<{ _ref: string, @@ -38,3 +41,4 @@ export type Duplication = { size: number }> }; +*/ diff --git a/server/sonar-web/src/main/js/components/charts/AdvancedTimeline.js b/server/sonar-web/src/main/js/components/charts/AdvancedTimeline.js index 9578a6726f6..d58d2e4479b 100644 --- a/server/sonar-web/src/main/js/components/charts/AdvancedTimeline.js +++ b/server/sonar-web/src/main/js/components/charts/AdvancedTimeline.js @@ -25,11 +25,20 @@ import { bisector, extent, max } from 'd3-array'; import { scaleLinear, scalePoint, scaleTime } from 'd3-scale'; import { line as d3Line, area, curveBasis } from 'd3-shape'; +/*:: type Event = { className?: string, name: string, date: Date }; +*/ +/*:: export type Point = { x: Date, y: number | string }; +*/ +/*:: export type Serie = { name: string, data: Array<Point>, type: string }; +*/ +/*:: type Scale = Function; +*/ +/*:: type Props = { basisCurve?: boolean, endDate: ?Date, @@ -54,7 +63,9 @@ type Props = { updateZoom?: (start: ?Date, endDate: ?Date) => void, zoomSpeed: number }; +*/ +/*:: type State = { maxXRange: Array<number>, mouseOver?: boolean, @@ -65,10 +76,11 @@ type State = { yScale: Scale, xScale: Scale }; +*/ export default class AdvancedTimeline extends React.PureComponent { - props: Props; - state: State; + /*:: props: Props; */ + /*:: state: State; */ static defaultProps = { eventSize: 8, @@ -76,7 +88,7 @@ export default class AdvancedTimeline extends React.PureComponent { zoomSpeed: 1 }; - constructor(props: Props) { + constructor(props /*: Props */) { super(props); const scales = this.getScales(props); const selectedDatePos = this.getSelectedDatePos(scales.xScale, props.selectedDate); @@ -85,7 +97,7 @@ export default class AdvancedTimeline extends React.PureComponent { this.handleZoomUpdate = throttle(this.handleZoomUpdate, 40); } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { let scales; let selectedDatePos; if ( @@ -121,13 +133,13 @@ export default class AdvancedTimeline extends React.PureComponent { } } - getRatingScale = (availableHeight: number) => + getRatingScale = (availableHeight /*: number */) => scalePoint().domain([5, 4, 3, 2, 1]).range([availableHeight, 0]); - getLevelScale = (availableHeight: number) => + getLevelScale = (availableHeight /*: number */) => scalePoint().domain(['ERROR', 'WARN', 'OK']).range([availableHeight, 0]); - getYScale = (props: Props, availableHeight: number, flatData: Array<Point>) => { + getYScale = (props /*: Props */, availableHeight /*: number */, flatData /*: Array<Point> */) => { if (props.metricType === 'RATING') { return this.getRatingScale(availableHeight); } else if (props.metricType === 'LEVEL') { @@ -140,7 +152,11 @@ export default class AdvancedTimeline extends React.PureComponent { } }; - getXScale = ({ startDate, endDate }: Props, availableWidth: number, flatData: Array<Point>) => { + getXScale = ( + { startDate, endDate } /*: Props */, + availableWidth /*: number */, + flatData /*: Array<Point> */ + ) => { const dateRange = extent(flatData, d => d.x); const start = startDate && startDate > dateRange[0] ? startDate : dateRange[0]; const end = endDate && endDate < dateRange[1] ? endDate : dateRange[1]; @@ -151,17 +167,17 @@ export default class AdvancedTimeline extends React.PureComponent { }; }; - getScales = (props: Props) => { + getScales = (props /*: Props */) => { const availableWidth = props.width - props.padding[1] - props.padding[3]; const availableHeight = props.height - props.padding[0] - props.padding[2]; - const flatData = flatten(props.series.map((serie: Serie) => serie.data)); + const flatData = flatten(props.series.map((serie /*: Serie */) => serie.data)); return { ...this.getXScale(props, availableWidth, flatData), yScale: this.getYScale(props, availableHeight, flatData) }; }; - getSelectedDatePos = (xScale: Scale, selectedDate: ?Date) => { + getSelectedDatePos = (xScale /*: Scale */, selectedDate /*: ?Date */) => { const firstSerie = this.props.series[0]; if (selectedDate && firstSerie) { const idx = firstSerie.data.findIndex( @@ -181,12 +197,12 @@ export default class AdvancedTimeline extends React.PureComponent { return { selectedDate: null, selectedDateXPos: null, selectedDateIdx: null }; }; - getEventMarker = (size: number) => { + getEventMarker = (size /*: number */) => { const half = size / 2; return `M${half} 0 L${size} ${half} L ${half} ${size} L0 ${half} L${half} 0 L${size} ${half}`; }; - getMouseOverlayPos = (target: HTMLElement) => { + getMouseOverlayPos = (target /*: HTMLElement */) => { if (this.state.mouseOverlayPos) { return this.state.mouseOverlayPos; } @@ -195,7 +211,7 @@ export default class AdvancedTimeline extends React.PureComponent { return pos; }; - handleWheel = (evt: WheelEvent & { target: HTMLElement }) => { + handleWheel = (evt /*: WheelEvent & { target: HTMLElement } */) => { evt.preventDefault(); const { maxXRange, xScale } = this.state; const parentBbox = this.getMouseOverlayPos(evt.target); @@ -209,20 +225,20 @@ export default class AdvancedTimeline extends React.PureComponent { this.handleZoomUpdate(startDate, endDate); }; - handleZoomUpdate = (startDate: ?Date, endDate: ?Date) => { + handleZoomUpdate = (startDate /*: ?Date */, endDate /*: ?Date */) => { if (this.props.updateZoom) { this.props.updateZoom(startDate, endDate); } }; - handleMouseMove = (evt: MouseEvent & { target: HTMLElement }) => { + handleMouseMove = (evt /*: MouseEvent & { target: HTMLElement } */) => { const parentBbox = this.getMouseOverlayPos(evt.target); this.updateTooltipPos(evt.pageX - parentBbox.left); }; handleMouseEnter = () => this.setState({ mouseOver: true }); - handleMouseOut = (evt: Event & { relatedTarget: HTMLElement }) => { + handleMouseOut = (evt /*: Event & { relatedTarget: HTMLElement } */) => { const { updateTooltip } = this.props; const targetClass = evt.relatedTarget && typeof evt.relatedTarget.className === 'string' @@ -251,7 +267,7 @@ export default class AdvancedTimeline extends React.PureComponent { } }; - updateTooltipPos = (xPos: number) => { + updateTooltipPos = (xPos /*: number */) => { const firstSerie = this.props.series[0]; if (this.state.mouseOver && firstSerie) { const { updateTooltip } = this.props; @@ -465,7 +481,7 @@ export default class AdvancedTimeline extends React.PureComponent { ); }; - renderMouseEventsOverlay = (zoomEnabled: boolean) => { + renderMouseEventsOverlay = (zoomEnabled /*: boolean */) => { const mouseEvents = {}; if (zoomEnabled) { mouseEvents.onWheel = this.handleWheel; diff --git a/server/sonar-web/src/main/js/components/charts/BubbleChart.js b/server/sonar-web/src/main/js/components/charts/BubbleChart.js index a17e603b151..3426761dc5f 100644 --- a/server/sonar-web/src/main/js/components/charts/BubbleChart.js +++ b/server/sonar-web/src/main/js/components/charts/BubbleChart.js @@ -26,16 +26,18 @@ import { sortBy, uniq } from 'lodash'; import AutoSizer from 'react-virtualized/dist/commonjs/AutoSizer'; import { TooltipsContainer } from '../mixins/tooltips-mixin'; +/*:: type Scale = { (number): number, range: () => [number, number], ticks: number => Array<number> }; +*/ const TICKS_COUNT = 5; export class Bubble extends React.PureComponent { - props: { + /*:: props: { color?: string, link?: string, onClick: (?string) => void, @@ -44,6 +46,7 @@ export class Bubble extends React.PureComponent { x: number, y: number }; +*/ handleClick = () => { if (this.props.onClick) { @@ -92,7 +95,7 @@ export class Bubble extends React.PureComponent { } export default class BubbleChart extends React.PureComponent { - props: {| + /*:: props: {| items: Array<{| x: number, y: number, @@ -115,6 +118,7 @@ export default class BubbleChart extends React.PureComponent { xDomain?: [number, number], yDomain?: [number, number] |}; +*/ static defaultProps = { sizeRange: [5, 45], @@ -127,7 +131,7 @@ export default class BubbleChart extends React.PureComponent { formatYTick: d => d }; - getXRange(xScale: Scale, sizeScale: Scale, availableWidth: number) { + getXRange(xScale /*: Scale */, sizeScale /*: Scale */, availableWidth /*: number */) { const minX = min(this.props.items, d => xScale(d.x) - sizeScale(d.size)); const maxX = max(this.props.items, d => xScale(d.x) + sizeScale(d.size)); const dMinX = minX < 0 ? xScale.range()[0] - minX : xScale.range()[0]; @@ -135,7 +139,7 @@ export default class BubbleChart extends React.PureComponent { return [dMinX, availableWidth - dMaxX]; } - getYRange(yScale: Scale, sizeScale: Scale, availableHeight: number) { + getYRange(yScale /*: Scale */, sizeScale /*: Scale */, availableHeight /*: number */) { const minY = min(this.props.items, d => yScale(d.y) - sizeScale(d.size)); const maxY = max(this.props.items, d => yScale(d.y) + sizeScale(d.size)); const dMinY = minY < 0 ? yScale.range()[1] - minY : yScale.range()[1]; @@ -143,14 +147,14 @@ export default class BubbleChart extends React.PureComponent { return [availableHeight - dMaxY, dMinY]; } - getTicks(scale: Scale, format: number => string) { + getTicks(scale /*: Scale */, format /*: number => string */) { const ticks = scale.ticks(TICKS_COUNT).map(tick => format(tick)); const uniqueTicksCount = uniq(ticks).length; const ticksCount = uniqueTicksCount < TICKS_COUNT ? uniqueTicksCount - 1 : TICKS_COUNT; return scale.ticks(ticksCount); } - renderXGrid(ticks: Array<number>, xScale: Scale, yScale: Scale) { + renderXGrid(ticks /*: Array<number> */, xScale /*: Scale */, yScale /*: Scale */) { if (!this.props.displayXGrid) { return null; } @@ -169,7 +173,7 @@ export default class BubbleChart extends React.PureComponent { ); } - renderYGrid(ticks: Array<number>, xScale: Scale, yScale: Scale) { + renderYGrid(ticks /*: Array<number> */, xScale /*: Scale */, yScale /*: Scale */) { if (!this.props.displayYGrid) { return null; } @@ -188,7 +192,7 @@ export default class BubbleChart extends React.PureComponent { ); } - renderXTicks(xTicks: Array<number>, xScale: Scale, yScale: Scale) { + renderXTicks(xTicks /*: Array<number> */, xScale /*: Scale */, yScale /*: Scale */) { if (!this.props.displayXTicks) { return null; } @@ -211,7 +215,7 @@ export default class BubbleChart extends React.PureComponent { ); } - renderYTicks(yTicks: Array<number>, xScale: Scale, yScale: Scale) { + renderYTicks(yTicks /*: Array<number> */, xScale /*: Scale */, yScale /*: Scale */) { if (!this.props.displayYTicks) { return null; } @@ -240,7 +244,7 @@ export default class BubbleChart extends React.PureComponent { ); } - renderChart(width: number) { + renderChart(width /*: number */) { const availableWidth = width - this.props.padding[1] - this.props.padding[3]; const availableHeight = this.props.height - this.props.padding[0] - this.props.padding[2]; diff --git a/server/sonar-web/src/main/js/components/charts/ColorBoxLegend.js b/server/sonar-web/src/main/js/components/charts/ColorBoxLegend.js index 390b3ccc838..da60f2f7ab1 100644 --- a/server/sonar-web/src/main/js/components/charts/ColorBoxLegend.js +++ b/server/sonar-web/src/main/js/components/charts/ColorBoxLegend.js @@ -22,14 +22,16 @@ import React from 'react'; import classNames from 'classnames'; import { formatMeasure } from '../../helpers/measures'; -type Props = { +/*:: type Props = { className?: string, colorScale: Object, colorNA?: string, metricType: string -}; +}; */ -export default function ColorBoxLegend({ className, colorScale, colorNA, metricType }: Props) { +export default function ColorBoxLegend( + { className, colorScale, colorNA, metricType } /*: Props */ +) { const colorDomain = colorScale.domain(); const colorRange = colorScale.range(); return ( diff --git a/server/sonar-web/src/main/js/components/charts/ColorGradientLegend.js b/server/sonar-web/src/main/js/components/charts/ColorGradientLegend.js index 18dec37a7d7..224170b67f0 100644 --- a/server/sonar-web/src/main/js/components/charts/ColorGradientLegend.js +++ b/server/sonar-web/src/main/js/components/charts/ColorGradientLegend.js @@ -20,7 +20,7 @@ // @flow import React from 'react'; -type Props = { +/*:: type Props = { className?: string, colorScale: Object, colorNA?: string, @@ -28,19 +28,21 @@ type Props = { padding?: Array<number>, height: number, width: number -}; +}; */ const NA_SPACING = 4; -export default function ColorGradientLegend({ - className, - colorScale, - colorNA, - direction, - padding = [12, 24, 0, 0], - height, - width -}: Props) { +export default function ColorGradientLegend( + { + className, + colorScale, + colorNA, + direction, + padding = [12, 24, 0, 0], + height, + width + } /*: Props */ +) { let colorDomain = colorScale.domain(); let colorRange = colorScale.range(); if (direction !== 1) { diff --git a/server/sonar-web/src/main/js/components/charts/ColorRatingsLegend.js b/server/sonar-web/src/main/js/components/charts/ColorRatingsLegend.js index a5caf0e534a..67017ea7d80 100644 --- a/server/sonar-web/src/main/js/components/charts/ColorRatingsLegend.js +++ b/server/sonar-web/src/main/js/components/charts/ColorRatingsLegend.js @@ -23,7 +23,7 @@ import classNames from 'classnames'; import { formatMeasure } from '../../helpers/measures'; import { RATING_COLORS } from '../../helpers/constants'; -export default function ColorRatingsLegend({ className }: { className?: string }) { +export default function ColorRatingsLegend({ className } /*: { className?: string } */) { return ( <div className={classNames('color-box-legend', className)}> {[1, 2, 3, 4, 5].map(rating => diff --git a/server/sonar-web/src/main/js/components/charts/TreeMap.js b/server/sonar-web/src/main/js/components/charts/TreeMap.js index 887f3fa7322..21ae66da1bb 100644 --- a/server/sonar-web/src/main/js/components/charts/TreeMap.js +++ b/server/sonar-web/src/main/js/components/charts/TreeMap.js @@ -23,7 +23,7 @@ import { treemap as d3Treemap, hierarchy as d3Hierarchy } from 'd3-hierarchy'; import TreeMapRect from './TreeMapRect'; import { translate } from '../../helpers/l10n'; -export type TreeMapItem = { +/*:: export type TreeMapItem = { key: string, size: number, color: string, @@ -31,19 +31,19 @@ export type TreeMapItem = { tooltip?: string | React.Element<*>, label: string, link?: string -}; +}; */ -type Props = {| +/*:: type Props = {| items: Array<TreeMapItem>, onRectangleClick?: string => void, height: number, width: number -|}; +|}; */ export default class TreeMap extends React.PureComponent { - props: Props; + /*:: props: Props; */ - mostCommitPrefix = (labels: Array<string>) => { + mostCommitPrefix = (labels /*: Array<string> */) => { const sortedLabels = labels.slice(0).sort(); const firstLabel = sortedLabels[0]; const firstLabelLength = firstLabel.length; diff --git a/server/sonar-web/src/main/js/components/charts/TreeMapRect.js b/server/sonar-web/src/main/js/components/charts/TreeMapRect.js index 498f4cb5976..9834d35077c 100644 --- a/server/sonar-web/src/main/js/components/charts/TreeMapRect.js +++ b/server/sonar-web/src/main/js/components/charts/TreeMapRect.js @@ -27,7 +27,7 @@ import Tooltip from '../controls/Tooltip'; const SIZE_SCALE = scaleLinear().domain([3, 15]).range([11, 18]).clamp(true); -type Props = {| +/*:: type Props = {| x: number, y: number, width: number, @@ -41,12 +41,12 @@ type Props = {| link?: string, onClick?: string => void, placement?: string -|}; +|}; */ export default class TreeMapRect extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleLinkClick = (e: Event) => e.stopPropagation(); + handleLinkClick = (e /*: Event */) => e.stopPropagation(); handleRectClick = () => { if (this.props.onClick != null) { diff --git a/server/sonar-web/src/main/js/components/charts/ZoomTimeLine.js b/server/sonar-web/src/main/js/components/charts/ZoomTimeLine.js index d9b1e7562d7..22205dfdf73 100644 --- a/server/sonar-web/src/main/js/components/charts/ZoomTimeLine.js +++ b/server/sonar-web/src/main/js/components/charts/ZoomTimeLine.js @@ -25,11 +25,14 @@ import { extent, max } from 'd3-array'; import { scaleLinear, scalePoint, scaleTime } from 'd3-scale'; import { line as d3Line, area, curveBasis } from 'd3-shape'; import Draggable, { DraggableCore } from 'react-draggable'; -import type { DraggableData } from 'react-draggable'; -import type { Point, Serie } from './AdvancedTimeline'; +/*:: import type { DraggableData } from 'react-draggable'; */ +/*:: import type { Point, Serie } from './AdvancedTimeline'; */ +/*:: type Scale = Function; +*/ +/*:: type Props = { basisCurve?: boolean, endDate: ?Date, @@ -43,34 +46,37 @@ type Props = { startDate: ?Date, updateZoom: (start: ?Date, endDate: ?Date) => void }; +*/ +/*:: type State = { overlayLeftPos: ?number, newZoomStart: ?number }; +*/ export default class ZoomTimeLine extends React.PureComponent { - props: Props; - state: State; + /*:: props: Props; */ + /*:: state: State; */ static defaultProps = { padding: [0, 0, 18, 0], showXTicks: true }; - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { overlayLeftPos: null, newZoomStart: null }; this.handleZoomUpdate = throttle(this.handleZoomUpdate, 40); } - getRatingScale = (availableHeight: number) => + getRatingScale = (availableHeight /*: number */) => scalePoint().domain([5, 4, 3, 2, 1]).range([availableHeight, 0]); - getLevelScale = (availableHeight: number) => + getLevelScale = (availableHeight /*: number */) => scalePoint().domain(['ERROR', 'WARN', 'OK']).range([availableHeight, 0]); - getYScale = (availableHeight: number, flatData: Array<Point>) => { + getYScale = (availableHeight /*: number */, flatData /*: Array<Point> */) => { if (this.props.metricType === 'RATING') { return this.getRatingScale(availableHeight); } else if (this.props.metricType === 'LEVEL') { @@ -80,34 +86,34 @@ export default class ZoomTimeLine extends React.PureComponent { } }; - getXScale = (availableWidth: number, flatData: Array<Point>) => + getXScale = (availableWidth /*: number */, flatData /*: Array<Point> */) => scaleTime().domain(extent(flatData, d => d.x)).range([0, availableWidth]).clamp(true); getScales = () => { const availableWidth = this.props.width - this.props.padding[1] - this.props.padding[3]; const availableHeight = this.props.height - this.props.padding[0] - this.props.padding[2]; - const flatData = flatten(this.props.series.map((serie: Serie) => serie.data)); + const flatData = flatten(this.props.series.map((serie /*: Serie */) => serie.data)); return { xScale: this.getXScale(availableWidth, flatData), yScale: this.getYScale(availableHeight, flatData) }; }; - getEventMarker = (size: number) => { + getEventMarker = (size /*: number */) => { const half = size / 2; return `M${half} 0 L${size} ${half} L ${half} ${size} L0 ${half} L${half} 0 L${size} ${half}`; }; - handleDoubleClick = (xScale: Scale, xDim: Array<number>) => () => { + handleDoubleClick = (xScale /*: Scale */, xDim /*: Array<number> */) => () => { this.handleZoomUpdate(xScale, xDim); }; handleSelectionDrag = ( - xScale: Scale, - width: number, - xDim: Array<number>, - checkDelta?: boolean - ) => (e: Event, data: DraggableData) => { + xScale /*: Scale */, + width /*: number */, + xDim /*: Array<number> */, + checkDelta /*: ?boolean */ + ) => (e /*: Event */, data /*: DraggableData */) => { if (!checkDelta || data.deltaX) { const x = Math.max(xDim[0], Math.min(data.x, xDim[1] - width)); this.handleZoomUpdate(xScale, [x, width + x]); @@ -115,19 +121,22 @@ export default class ZoomTimeLine extends React.PureComponent { }; handleSelectionHandleDrag = ( - xScale: Scale, - fixedX: number, - xDim: Array<number>, - handleDirection: string, - checkDelta?: boolean - ) => (e: Event, data: DraggableData) => { + xScale /*: Scale */, + fixedX /*: number */, + xDim /*: Array<number> */, + handleDirection /*: string */, + checkDelta /*: ?boolean */ + ) => (e /*: Event */, data /*: DraggableData */) => { if (!checkDelta || data.deltaX) { const x = Math.max(xDim[0], Math.min(data.x, xDim[1])); this.handleZoomUpdate(xScale, handleDirection === 'right' ? [fixedX, x] : [x, fixedX]); } }; - handleNewZoomDragStart = (xDim: Array<number>) => (e: Event, data: DraggableData) => { + handleNewZoomDragStart = (xDim /*: Array<number> */) => ( + e /*: Event */, + data /*: DraggableData */ + ) => { const overlayLeftPos = data.node.getBoundingClientRect().left; this.setState({ overlayLeftPos, @@ -135,7 +144,10 @@ export default class ZoomTimeLine extends React.PureComponent { }); }; - handleNewZoomDrag = (xScale: Scale, xDim: Array<number>) => (e: Event, data: DraggableData) => { + handleNewZoomDrag = (xScale /*: Scale */, xDim /*: Array<number> */) => ( + e /*: Event */, + data /*: DraggableData */ + ) => { const { newZoomStart, overlayLeftPos } = this.state; if (newZoomStart != null && overlayLeftPos != null && data.deltaX) { this.handleZoomUpdate( @@ -145,9 +157,9 @@ export default class ZoomTimeLine extends React.PureComponent { } }; - handleNewZoomDragEnd = (xScale: Scale, xDim: Array<number>) => ( - e: Event, - data: DraggableData + handleNewZoomDragEnd = (xScale /*: Scale */, xDim /*: Array<number> */) => ( + e /*: Event */, + data /*: DraggableData */ ) => { const { newZoomStart, overlayLeftPos } = this.state; if (newZoomStart != null && overlayLeftPos != null) { @@ -157,7 +169,7 @@ export default class ZoomTimeLine extends React.PureComponent { } }; - handleZoomUpdate = (xScale: Scale, xArray: Array<number>) => { + handleZoomUpdate = (xScale /*: Scale */, xArray /*: Array<number> */) => { const xRange = xScale.range(); const startDate = xArray[0] > xRange[0] && xArray[0] < xRange[xRange.length - 1] @@ -172,7 +184,7 @@ export default class ZoomTimeLine extends React.PureComponent { } }; - renderBaseLine = (xScale: Scale, yScale: Scale) => { + renderBaseLine = (xScale /*: Scale */, yScale /*: Scale */) => { return ( <line className="line-chart-grid" @@ -184,7 +196,7 @@ export default class ZoomTimeLine extends React.PureComponent { ); }; - renderTicks = (xScale: Scale, yScale: Scale) => { + renderTicks = (xScale /*: Scale */, yScale /*: Scale */) => { const format = xScale.tickFormat(7); const ticks = xScale.ticks(7); const y = yScale.range()[0]; @@ -203,7 +215,7 @@ export default class ZoomTimeLine extends React.PureComponent { ); }; - renderLeak = (xScale: Scale, yScale: Scale) => { + renderLeak = (xScale /*: Scale */, yScale /*: Scale */) => { if (!this.props.leakPeriodDate) { return null; } @@ -219,7 +231,7 @@ export default class ZoomTimeLine extends React.PureComponent { ); }; - renderLines = (xScale: Scale, yScale: Scale) => { + renderLines = (xScale /*: Scale */, yScale /*: Scale */) => { const lineGenerator = d3Line() .defined(d => d.y || d.y === 0) .x(d => xScale(d.x)) @@ -240,7 +252,7 @@ export default class ZoomTimeLine extends React.PureComponent { ); }; - renderAreas = (xScale: Scale, yScale: Scale) => { + renderAreas = (xScale /*: Scale */, yScale /*: Scale */) => { const areaGenerator = area() .defined(d => d.y || d.y === 0) .x(d => xScale(d.x)) @@ -262,14 +274,16 @@ export default class ZoomTimeLine extends React.PureComponent { ); }; - renderZoomHandle = (options: { + renderZoomHandle = ( + options /*: { xScale: Scale, xPos: number, fixedPos: number, yDim: Array<number>, xDim: Array<number>, direction: string - }) => + } */ + ) => <Draggable axis="x" bounds={{ left: options.xDim[0], right: options.xDim[1] }} @@ -296,7 +310,7 @@ export default class ZoomTimeLine extends React.PureComponent { /> </Draggable>; - renderZoom = (xScale: Scale, yScale: Scale) => { + renderZoom = (xScale /*: Scale */, yScale /*: Scale */) => { const xRange = xScale.range(); const yRange = yScale.range(); const xDim = [xRange[0], xRange[xRange.length - 1]]; diff --git a/server/sonar-web/src/main/js/components/common/BubblePopupHelper.js b/server/sonar-web/src/main/js/components/common/BubblePopupHelper.js index 9a6b17f561e..48fa517be01 100644 --- a/server/sonar-web/src/main/js/components/common/BubblePopupHelper.js +++ b/server/sonar-web/src/main/js/components/common/BubblePopupHelper.js @@ -20,6 +20,7 @@ import React from 'react'; import classNames from 'classnames'; +/*:: type Props = { className?: string, children?: React.Element<*>, @@ -32,14 +33,17 @@ type Props = { position: 'bottomleft' | 'bottomright', togglePopup: (?boolean) => void }; +*/ +/*:: type State = { position: { top: number, right: number } }; +*/ export default class BubblePopupHelper extends React.PureComponent { - props: Props; - state: State = { + /*:: props: Props; */ + state /*: State */ = { position: { top: 0, right: 0 @@ -50,7 +54,7 @@ export default class BubblePopupHelper extends React.PureComponent { this.setState({ position: this.getPosition(this.props) }); } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if (!this.props.isOpen && nextProps.isOpen) { window.addEventListener('keydown', this.handleKey, false); window.addEventListener('click', this.handleOutsideClick, false); @@ -60,24 +64,24 @@ export default class BubblePopupHelper extends React.PureComponent { } } - handleKey = (evt: KeyboardEvent) => { + handleKey = (evt /*: KeyboardEvent */) => { // Escape key if (evt.keyCode === 27) { this.props.togglePopup(false); } }; - handleOutsideClick = (evt: SyntheticInputEvent) => { + handleOutsideClick = (evt /*: SyntheticInputEvent */) => { if (!this.popupContainer || !this.popupContainer.contains(evt.target)) { this.props.togglePopup(false); } }; - handleClick(evt: SyntheticInputEvent) { + handleClick(evt /*: SyntheticInputEvent */) { evt.stopPropagation(); } - getPosition(props: Props) { + getPosition(props /*: Props */) { const containerPos = this.container.getBoundingClientRect(); const { position } = props; const offset = props.offset || { vertical: 0, horizontal: 0 }; diff --git a/server/sonar-web/src/main/js/components/common/ClockIcon.js b/server/sonar-web/src/main/js/components/common/ClockIcon.js index 8e3a2cecfa8..05741ee667c 100644 --- a/server/sonar-web/src/main/js/components/common/ClockIcon.js +++ b/server/sonar-web/src/main/js/components/common/ClockIcon.js @@ -21,12 +21,14 @@ import React from 'react'; import classNames from 'classnames'; +/*:: type Props = { className?: string, size?: number }; +*/ -export default function ClockIcon(props: Props) { +export default function ClockIcon(props /*: Props */) { /* eslint max-len: 0 */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/common/DeferredSpinner.js b/server/sonar-web/src/main/js/components/common/DeferredSpinner.js index 070f705f7be..4224bdf786a 100644 --- a/server/sonar-web/src/main/js/components/common/DeferredSpinner.js +++ b/server/sonar-web/src/main/js/components/common/DeferredSpinner.js @@ -21,27 +21,31 @@ import React from 'react'; import classNames from 'classnames'; +/*:: type Props = { children?: React.Element<*>, className?: string, loading?: boolean, timeout: number }; +*/ +/*:: type State = { showSpinner: boolean }; +*/ export default class DeferredSpinner extends React.PureComponent { - props: Props; - state: State; - timer: number; + /*:: props: Props; */ + /*:: state: State; */ + /*:: timer: number; */ static defaultProps = { timeout: 100 }; - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { showSpinner: false }; } @@ -52,7 +56,7 @@ export default class DeferredSpinner extends React.PureComponent { } } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if (this.props.loading === false && nextProps.loading === true) { this.stopTimer(); this.startTimer(); diff --git a/server/sonar-web/src/main/js/components/common/FavoriteIcon.js b/server/sonar-web/src/main/js/components/common/FavoriteIcon.js index 5d16a8d4b70..725f2ce960e 100644 --- a/server/sonar-web/src/main/js/components/common/FavoriteIcon.js +++ b/server/sonar-web/src/main/js/components/common/FavoriteIcon.js @@ -21,13 +21,15 @@ import React from 'react'; import classNames from 'classnames'; +/*:: type Props = { className?: string, favorite: boolean, size?: number }; +*/ -export default function FavoriteIcon(props: Props) { +export default function FavoriteIcon(props /*: Props */) { /* eslint max-len: 0 */ return ( <span diff --git a/server/sonar-web/src/main/js/components/common/LocationIndex.js b/server/sonar-web/src/main/js/components/common/LocationIndex.js index ecc4027b124..2effb6e44ca 100644 --- a/server/sonar-web/src/main/js/components/common/LocationIndex.js +++ b/server/sonar-web/src/main/js/components/common/LocationIndex.js @@ -22,13 +22,15 @@ import React from 'react'; import classNames from 'classnames'; import './LocationIndex.css'; +/*:: type Props = { children?: React.Element<*>, onClick?: () => void, selected?: boolean }; +*/ -export default function LocationIndex(props: Props) { +export default function LocationIndex(props /*: Props */) { const { children, onClick, selected, ...other } = props; const clickAttributes = onClick ? { onClick, role: 'button', tabIndex: 0 } : {}; diff --git a/server/sonar-web/src/main/js/components/common/LocationMessage.js b/server/sonar-web/src/main/js/components/common/LocationMessage.js index 54f021e0dd3..32dc5976dad 100644 --- a/server/sonar-web/src/main/js/components/common/LocationMessage.js +++ b/server/sonar-web/src/main/js/components/common/LocationMessage.js @@ -22,12 +22,14 @@ import React from 'react'; import classNames from 'classnames'; import './LocationMessage.css'; +/*:: type Props = { children?: React.Element<*>, selected: boolean }; +*/ -export default function LocationMessage(props: Props) { +export default function LocationMessage(props /*: Props */) { return ( <div className={classNames('location-message', { selected: props.selected })}> {props.children} diff --git a/server/sonar-web/src/main/js/components/common/MarkdownTips.js b/server/sonar-web/src/main/js/components/common/MarkdownTips.js index 323838e06c5..b57bce846f0 100644 --- a/server/sonar-web/src/main/js/components/common/MarkdownTips.js +++ b/server/sonar-web/src/main/js/components/common/MarkdownTips.js @@ -23,7 +23,7 @@ import { getMarkdownHelpUrl } from '../../helpers/urls'; import { translate } from '../../helpers/l10n'; export default class MarkdownTips extends React.PureComponent { - handleClick(evt: MouseEvent) { + handleClick(evt /*: MouseEvent */) { evt.preventDefault(); window.open(getMarkdownHelpUrl(), 'Markdown', 'height=300,width=600,scrollbars=1,resizable=1'); } diff --git a/server/sonar-web/src/main/js/components/common/MultiSelect.js b/server/sonar-web/src/main/js/components/common/MultiSelect.js index 5e618e45e1f..161fa8473d9 100644 --- a/server/sonar-web/src/main/js/components/common/MultiSelect.js +++ b/server/sonar-web/src/main/js/components/common/MultiSelect.js @@ -23,6 +23,7 @@ import { difference } from 'lodash'; import MultiSelectOption from './MultiSelectOption'; import { translate } from '../../helpers/l10n'; +/*:: type Props = { selectedElements: Array<string>, elements: Array<string>, @@ -32,26 +33,29 @@ type Props = { onUnselect: string => void, validateSearchInput: string => string }; +*/ +/*:: type State = { query: string, selectedElements: Array<string>, unselectedElements: Array<string>, activeIdx: number }; +*/ export default class MultiSelect extends React.PureComponent { - container: HTMLElement; - searchInput: HTMLInputElement; - props: Props; - state: State; + /*:: container: HTMLElement; */ + /*:: searchInput: HTMLInputElement; */ + /*:: props: Props; */ + /*:: state: State; */ static defaultProps = { listSize: 10, - validateSearchInput: (value: string) => value + validateSearchInput: (value /*: string */) => value }; - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { query: '', @@ -67,7 +71,7 @@ export default class MultiSelect extends React.PureComponent { this.container.addEventListener('keydown', this.handleKeyboard, true); } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if ( this.props.elements !== nextProps.elements || this.props.selectedElements !== nextProps.selectedElements @@ -90,7 +94,7 @@ export default class MultiSelect extends React.PureComponent { this.container.removeEventListener('keydown', this.handleKeyboard); } - handleSelectChange = (item: string, selected: boolean) => { + handleSelectChange = (item /*: string */, selected /*: boolean */) => { if (selected) { this.onSelectItem(item); } else { @@ -98,17 +102,17 @@ export default class MultiSelect extends React.PureComponent { } }; - handleSearchChange = ({ target }: { target: HTMLInputElement }) => { + handleSearchChange = ({ target } /*: { target: HTMLInputElement } */) => { this.onSearchQuery(this.props.validateSearchInput(target.value)); }; - handleElementHover = (element: string) => { + handleElementHover = (element /*: string */) => { this.setState((prevState, props) => { return { activeIdx: this.getAllElements(props, prevState).indexOf(element) }; }); }; - handleKeyboard = (evt: KeyboardEvent) => { + handleKeyboard = (evt /*: KeyboardEvent */) => { switch (evt.keyCode) { case 40: // down this.setState(this.selectNextElement); @@ -132,28 +136,28 @@ export default class MultiSelect extends React.PureComponent { } }; - onSearchQuery(query: string) { + onSearchQuery(query /*: string */) { this.setState({ query, activeIdx: 0 }); this.props.onSearch(query); } - onSelectItem(item: string) { + onSelectItem(item /*: string */) { if (this.isNewElement(item, this.props)) { this.onSearchQuery(''); } this.props.onSelect(item); } - onUnselectItem(item: string) { + onUnselectItem(item /*: string */) { this.props.onUnselect(item); } - isNewElement(elem: string, { selectedElements, elements }: Props) { + isNewElement(elem /*: string */, { selectedElements, elements } /*: Props */) { return elem && selectedElements.indexOf(elem) === -1 && elements.indexOf(elem) === -1; } - updateSelectedElements(props: Props) { - this.setState((state: State) => { + updateSelectedElements(props /*: Props */) { + this.setState((state /*: State */) => { if (state.query) { return { selectedElements: [...props.selectedElements.filter(elem => elem.includes(state.query))] @@ -164,8 +168,8 @@ export default class MultiSelect extends React.PureComponent { }); } - updateUnselectedElements(props: Props) { - this.setState((state: State) => { + updateUnselectedElements(props /*: Props */) { + this.setState((state /*: State */) => { if (props.listSize < state.selectedElements.length) { return { unselectedElements: [] }; } else { @@ -179,7 +183,7 @@ export default class MultiSelect extends React.PureComponent { }); } - getAllElements(props: Props, state: State) { + getAllElements(props /*: Props */, state /*: State */) { if (this.isNewElement(state.query, props)) { return [...state.selectedElements, ...state.unselectedElements, state.query]; } else { @@ -187,11 +191,11 @@ export default class MultiSelect extends React.PureComponent { } } - setElementActive(idx: number) { + setElementActive(idx /*: number */) { this.setState({ activeIdx: idx }); } - selectNextElement = (state: State, props: Props) => { + selectNextElement = (state /*: State */, props /*: Props */) => { const { activeIdx } = state; const allElements = this.getAllElements(props, state); if (activeIdx < 0 || activeIdx >= allElements.length - 1) { @@ -201,7 +205,7 @@ export default class MultiSelect extends React.PureComponent { } }; - selectPreviousElement = (state: State, props: Props) => { + selectPreviousElement = (state /*: State */, props /*: Props */) => { const { activeIdx } = state; const allElements = this.getAllElements(props, state); if (activeIdx <= 0) { @@ -212,7 +216,7 @@ export default class MultiSelect extends React.PureComponent { } }; - toggleSelect(item: string) { + toggleSelect(item /*: string */) { if (this.props.selectedElements.indexOf(item) === -1) { this.onSelectItem(item); } else { diff --git a/server/sonar-web/src/main/js/components/common/MultiSelectOption.js b/server/sonar-web/src/main/js/components/common/MultiSelectOption.js index c9fb52632eb..da0a3c64885 100644 --- a/server/sonar-web/src/main/js/components/common/MultiSelectOption.js +++ b/server/sonar-web/src/main/js/components/common/MultiSelectOption.js @@ -21,6 +21,7 @@ import React from 'react'; import classNames from 'classnames'; +/*:: type Props = { element: string, selected: boolean, @@ -29,9 +30,10 @@ type Props = { onSelectChange: (string, boolean) => void, onHover: string => void }; +*/ export default class MultiSelectOption extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { selected: false, @@ -39,7 +41,7 @@ export default class MultiSelectOption extends React.PureComponent { active: false }; - handleSelect = (evt: SyntheticInputEvent) => { + handleSelect = (evt /*: SyntheticInputEvent */) => { evt.stopPropagation(); evt.preventDefault(); evt.target.blur(); diff --git a/server/sonar-web/src/main/js/components/common/OrganizationHelmet.js b/server/sonar-web/src/main/js/components/common/OrganizationHelmet.js index ffffec47d4b..4446ebf9a84 100644 --- a/server/sonar-web/src/main/js/components/common/OrganizationHelmet.js +++ b/server/sonar-web/src/main/js/components/common/OrganizationHelmet.js @@ -21,12 +21,14 @@ import React from 'react'; import Helmet from 'react-helmet'; +/*:: type Props = { title: string, organization?: ?{ name: string } }; +*/ -export default function OrganizationHelmet({ title, organization }: Props) { +export default function OrganizationHelmet({ title, organization } /*: Props */) { const defaultTitle = title + (organization ? ' - ' + organization.name : ''); return <Helmet defaultTitle={defaultTitle} titleTemplate={'%s - ' + defaultTitle} />; } diff --git a/server/sonar-web/src/main/js/components/common/PrivateBadge.js b/server/sonar-web/src/main/js/components/common/PrivateBadge.js index 301391d19bf..0336cf7609e 100644 --- a/server/sonar-web/src/main/js/components/common/PrivateBadge.js +++ b/server/sonar-web/src/main/js/components/common/PrivateBadge.js @@ -23,12 +23,14 @@ import classNames from 'classnames'; import Tooltip from '../controls/Tooltip'; import { translate } from '../../helpers/l10n'; +/*:: type Props = { className?: string, tooltipPlacement?: string }; +*/ -export default function PrivateBadge({ className, tooltipPlacement = 'bottom' }: Props) { +export default function PrivateBadge({ className, tooltipPlacement = 'bottom' } /*: Props */) { return ( <Tooltip overlay={translate('visibility.private.description')} placement={tooltipPlacement}> <div className={classNames('outline-badge', className)}> diff --git a/server/sonar-web/src/main/js/components/common/SelectList.js b/server/sonar-web/src/main/js/components/common/SelectList.js index d4096080c66..02483a86e55 100644 --- a/server/sonar-web/src/main/js/components/common/SelectList.js +++ b/server/sonar-web/src/main/js/components/common/SelectList.js @@ -23,25 +23,29 @@ import key from 'keymaster'; import { uniqueId } from 'lodash'; import SelectListItem from './SelectListItem'; +/*:: type Props = { children?: SelectListItem, items: Array<string>, currentItem: string, onSelect: string => void }; +*/ +/*:: type State = { active: string }; +*/ export default class SelectList extends React.PureComponent { - currentKeyScope: string; - previousFilter: Function; - previousKeyScope: string; - props: Props; - state: State; + /*:: currentKeyScope: string; */ + /*:: previousFilter: Function; */ + /*:: previousKeyScope: string; */ + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { active: props.currentItem @@ -52,7 +56,7 @@ export default class SelectList extends React.PureComponent { this.attachShortcuts(); } - componentWillReceiveProps(nextProps: Props) { + componentWillReceiveProps(nextProps /*: Props */) { if ( nextProps.currentItem !== this.props.currentItem && !nextProps.items.includes(this.state.active) @@ -73,7 +77,7 @@ export default class SelectList extends React.PureComponent { // sometimes there is a *focused* search field next to the SelectList component // we need to allow shortcuts in this case, but only for the used keys - key.filter = (event: KeyboardEvent & { target: HTMLElement }) => { + key.filter = (event /*: KeyboardEvent & { target: HTMLElement } */) => { const tagName = (event.target || event.srcElement).tagName; const isInput = tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA'; return [13, 38, 40].includes(event.keyCode) || !isInput; @@ -103,15 +107,15 @@ export default class SelectList extends React.PureComponent { key.filter = this.previousFilter; }; - handleSelect = (item: string) => { + handleSelect = (item /*: string */) => { this.props.onSelect(item); }; - handleHover = (item: string) => { + handleHover = (item /*: string */) => { this.setState({ active: item }); }; - selectNextElement = (state: State, props: Props) => { + selectNextElement = (state /*: State */, props /*: Props */) => { const idx = props.items.indexOf(state.active); if (idx < 0) { return { active: props.items[0] }; @@ -119,7 +123,7 @@ export default class SelectList extends React.PureComponent { return { active: props.items[(idx + 1) % props.items.length] }; }; - selectPreviousElement = (state: State, props: Props) => { + selectPreviousElement = (state /*: State */, props /*: Props */) => { const idx = props.items.indexOf(state.active); if (idx <= 0) { return { active: props.items[props.items.length - 1] }; diff --git a/server/sonar-web/src/main/js/components/common/SelectListItem.js b/server/sonar-web/src/main/js/components/common/SelectListItem.js index e5bc30cdca6..0fa49725305 100644 --- a/server/sonar-web/src/main/js/components/common/SelectListItem.js +++ b/server/sonar-web/src/main/js/components/common/SelectListItem.js @@ -22,6 +22,7 @@ import React from 'react'; import classNames from 'classnames'; import Tooltip from '../controls/Tooltip'; +/*:: type Props = { active?: string, children?: React.Element<*>, @@ -30,11 +31,12 @@ type Props = { onHover?: string => void, title?: string }; +*/ export default class SelectListItem extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleSelect = (evt: SyntheticInputEvent) => { + handleSelect = (evt /*: SyntheticInputEvent */) => { evt.preventDefault(); this.props.onSelect && this.props.onSelect(this.props.item); }; diff --git a/server/sonar-web/src/main/js/components/common/UpgradeOrganizationBox.js b/server/sonar-web/src/main/js/components/common/UpgradeOrganizationBox.js index eceab041969..35e56013aef 100644 --- a/server/sonar-web/src/main/js/components/common/UpgradeOrganizationBox.js +++ b/server/sonar-web/src/main/js/components/common/UpgradeOrganizationBox.js @@ -23,11 +23,13 @@ import { Link } from 'react-router'; import { translate, hasMessage } from '../../helpers/l10n'; import './UpgradeOrganizationBox.css'; +/*:: type Props = { organization: string }; +*/ -export default function UpgradeOrganizationBox(props: Props) { +export default function UpgradeOrganizationBox(props /*: Props */) { return ( <div className="boxed-group boxed-group-inner upgrade-organization-box"> <h3 className="spacer-bottom"> diff --git a/server/sonar-web/src/main/js/components/common/VisibilitySelector.js b/server/sonar-web/src/main/js/components/common/VisibilitySelector.js index dd35ad56609..40233097c9c 100644 --- a/server/sonar-web/src/main/js/components/common/VisibilitySelector.js +++ b/server/sonar-web/src/main/js/components/common/VisibilitySelector.js @@ -22,23 +22,25 @@ import React from 'react'; import classNames from 'classnames'; import { translate } from '../../helpers/l10n'; +/*:: type Props = {| canTurnToPrivate: boolean, className?: string, onChange: string => void, visibility: string |}; +*/ export default class VisibilitySelector extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handlePublicClick = (event: Event & { currentTarget: HTMLElement }) => { + handlePublicClick = (event /*: Event & { currentTarget: HTMLElement } */) => { event.preventDefault(); event.currentTarget.blur(); this.props.onChange('public'); }; - handlePrivateClick = (event: Event & { currentTarget: HTMLElement }) => { + handlePrivateClick = (event /*: Event & { currentTarget: HTMLElement } */) => { event.preventDefault(); event.currentTarget.blur(); this.props.onChange('private'); diff --git a/server/sonar-web/src/main/js/components/controls/SearchSelect.js b/server/sonar-web/src/main/js/components/controls/SearchSelect.js index 38515273b6c..f8eaf43665b 100644 --- a/server/sonar-web/src/main/js/components/controls/SearchSelect.js +++ b/server/sonar-web/src/main/js/components/controls/SearchSelect.js @@ -23,8 +23,11 @@ import Select from 'react-select'; import { debounce } from 'lodash'; import { translate, translateWithParameters } from '../../helpers/l10n'; +/*:: type Option = { label: string, value: string }; +*/ +/*:: type Props = {| autofocus: boolean, minimumQueryLength: number, @@ -34,17 +37,20 @@ type Props = {| resetOnBlur: boolean, value?: string |}; +*/ +/*:: type State = { loading: boolean, options: Array<Option>, query: string }; +*/ export default class SearchSelect extends React.PureComponent { - mounted: boolean; - props: Props; - state: State; + /*:: mounted: boolean; */ + /*:: props: Props; */ + /*:: state: State; */ static defaultProps = { autofocus: true, @@ -52,7 +58,7 @@ export default class SearchSelect extends React.PureComponent { resetOnBlur: true }; - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { loading: false, options: [], query: '' }; this.search = debounce(this.search, 250); @@ -66,7 +72,7 @@ export default class SearchSelect extends React.PureComponent { this.mounted = false; } - search = (query: string) => { + search = (query /*: string */) => { this.props.onSearch(query).then(options => { if (this.mounted) { this.setState({ loading: false, options }); @@ -78,11 +84,11 @@ export default class SearchSelect extends React.PureComponent { this.setState({ options: [], query: '' }); }; - handleChange = (option: Option) => { + handleChange = (option /*: Option */) => { this.props.onSelect(option.value); }; - handleInputChange = (query: string = '') => { + handleInputChange = (query /*: string */ = '') => { if (query.length >= this.props.minimumQueryLength) { this.setState({ loading: true, query }); this.search(query); diff --git a/server/sonar-web/src/main/js/components/controls/Tooltip.js b/server/sonar-web/src/main/js/components/controls/Tooltip.js index bc300da8190..68197750050 100644 --- a/server/sonar-web/src/main/js/components/controls/Tooltip.js +++ b/server/sonar-web/src/main/js/components/controls/Tooltip.js @@ -22,9 +22,10 @@ import React from 'react'; import TooltipCore from 'rc-tooltip'; export default class Tooltip extends React.PureComponent { - props: { + /*:: props: { placement?: string }; +*/ static defaultProps = { placement: 'bottom' diff --git a/server/sonar-web/src/main/js/components/facet/FacetBox.js b/server/sonar-web/src/main/js/components/facet/FacetBox.js index 92b7afb58db..bc77ac7b6f1 100644 --- a/server/sonar-web/src/main/js/components/facet/FacetBox.js +++ b/server/sonar-web/src/main/js/components/facet/FacetBox.js @@ -20,11 +20,13 @@ // @flow import React from 'react'; +/*:: type Props = {| children?: React.Element<*> |}; +*/ -export default function FacetBox(props: Props) { +export default function FacetBox(props /*: Props */) { return ( <div className="search-navigator-facet-box"> {props.children} diff --git a/server/sonar-web/src/main/js/components/facet/FacetFooter.js b/server/sonar-web/src/main/js/components/facet/FacetFooter.js index d11af837202..fd19bfa89c5 100644 --- a/server/sonar-web/src/main/js/components/facet/FacetFooter.js +++ b/server/sonar-web/src/main/js/components/facet/FacetFooter.js @@ -21,17 +21,21 @@ import React from 'react'; import SearchSelect from '../controls/SearchSelect'; +/*:: type Option = { label: string, value: string }; +*/ +/*:: type Props = {| minimumQueryLength?: number, onSearch: (query: string) => Promise<Array<Option>>, onSelect: (value: string) => void, renderOption?: (option: Object) => React.Element<*> |}; +*/ export default class FacetFooter extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { return ( diff --git a/server/sonar-web/src/main/js/components/facet/FacetHeader.js b/server/sonar-web/src/main/js/components/facet/FacetHeader.js index 46cdf6e43dd..b80cec0f7a6 100644 --- a/server/sonar-web/src/main/js/components/facet/FacetHeader.js +++ b/server/sonar-web/src/main/js/components/facet/FacetHeader.js @@ -24,6 +24,7 @@ import Tooltip from '../controls/Tooltip'; import HelpIcon from '../icons-components/HelpIcon'; import { translate } from '../../helpers/l10n'; +/*:: type Props = {| helper?: string, name: string, @@ -32,15 +33,16 @@ type Props = {| open: boolean, values?: number |}; +*/ export default class FacetHeader extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { open: true }; - handleClearClick = (event: Event & { currentTarget: HTMLElement }) => { + handleClearClick = (event /*: Event & { currentTarget: HTMLElement } */) => { event.preventDefault(); event.currentTarget.blur(); if (this.props.onClear) { @@ -48,7 +50,7 @@ export default class FacetHeader extends React.PureComponent { } }; - handleClick = (event: Event & { currentTarget: HTMLElement }) => { + handleClick = (event /*: Event & { currentTarget: HTMLElement } */) => { event.preventDefault(); event.currentTarget.blur(); if (this.props.onClick) { @@ -102,7 +104,7 @@ export default class FacetHeader extends React.PureComponent { } render() { - const showClearButton: boolean = !!this.props.values && this.props.onClear != null; + const showClearButton /*: boolean */ = !!this.props.values && this.props.onClear != null; return ( <div> diff --git a/server/sonar-web/src/main/js/components/facet/FacetItem.js b/server/sonar-web/src/main/js/components/facet/FacetItem.js index 4ecaf7650d4..0c238732209 100644 --- a/server/sonar-web/src/main/js/components/facet/FacetItem.js +++ b/server/sonar-web/src/main/js/components/facet/FacetItem.js @@ -21,6 +21,7 @@ import React from 'react'; import classNames from 'classnames'; +/*:: type Props = {| active: boolean, disabled: boolean, @@ -30,16 +31,17 @@ type Props = {| stat?: ?(string | React.Element<*>), value: string |}; +*/ export default class FacetItem extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { disabled: false, halfWidth: false }; - handleClick = (event: Event & { currentTarget: HTMLElement }) => { + handleClick = (event /*: Event & { currentTarget: HTMLElement } */) => { event.preventDefault(); this.props.onClick(this.props.value); }; diff --git a/server/sonar-web/src/main/js/components/facet/FacetItemsList.js b/server/sonar-web/src/main/js/components/facet/FacetItemsList.js index 5d36d9934e3..8267eaa6582 100644 --- a/server/sonar-web/src/main/js/components/facet/FacetItemsList.js +++ b/server/sonar-web/src/main/js/components/facet/FacetItemsList.js @@ -20,11 +20,13 @@ // @flow import React from 'react'; +/*:: type Props = {| children?: Array<React.Element<*>> |}; +*/ -export default function FacetItemsList(props: Props) { +export default function FacetItemsList(props /*: Props */) { return ( <div className="search-navigator-facet-list"> {props.children} diff --git a/server/sonar-web/src/main/js/components/facet/__tests__/FacetItem-test.js b/server/sonar-web/src/main/js/components/facet/__tests__/FacetItem-test.js index 2b602b29357..4e58f9728e3 100644 --- a/server/sonar-web/src/main/js/components/facet/__tests__/FacetItem-test.js +++ b/server/sonar-web/src/main/js/components/facet/__tests__/FacetItem-test.js @@ -23,7 +23,7 @@ import { shallow } from 'enzyme'; import { click } from '../../../helpers/testUtils'; import FacetItem from '../FacetItem'; -const renderFacetItem = (props: {}) => +const renderFacetItem = (props /*: {} */) => shallow( <FacetItem active={false} name="foo" onClick={jest.fn()} stat={null} value="bar" {...props} /> ); diff --git a/server/sonar-web/src/main/js/components/icons-components/AlertWarnIcon.js b/server/sonar-web/src/main/js/components/icons-components/AlertWarnIcon.js index 3ecabfa4c5a..026cef37a94 100644 --- a/server/sonar-web/src/main/js/components/icons-components/AlertWarnIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/AlertWarnIcon.js @@ -20,9 +20,11 @@ // @flow import React from 'react'; +/*:: type Props = { className?: string, size?: number }; +*/ -export default function AlertWarnIcon({ className, size = 16 }: Props) { +export default function AlertWarnIcon({ className, size = 16 } /*: Props */) { /* eslint-disable max-len */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/icons-components/BubblesIcon.js b/server/sonar-web/src/main/js/components/icons-components/BubblesIcon.js index 317a01d32fa..5c0033d036d 100644 --- a/server/sonar-web/src/main/js/components/icons-components/BubblesIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/BubblesIcon.js @@ -20,9 +20,11 @@ // @flow import React from 'react'; +/*:: type Props = { className?: string, size?: number }; +*/ -export default function BubblesIcon({ className, size = 16 }: Props) { +export default function BubblesIcon({ className, size = 16 } /*: Props */) { return ( <svg xmlns="http://www.w3.org/2000/svg" diff --git a/server/sonar-web/src/main/js/components/icons-components/BugIcon.js b/server/sonar-web/src/main/js/components/icons-components/BugIcon.js index dc1d5c7f90b..48726f839d0 100644 --- a/server/sonar-web/src/main/js/components/icons-components/BugIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/BugIcon.js @@ -20,9 +20,11 @@ // @flow import React from 'react'; +/*:: type Props = { className?: string, size?: number }; +*/ -export default function BugIcon({ className, size = 16 }: Props) { +export default function BugIcon({ className, size = 16 } /*: Props */) { /* eslint-disable max-len */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/icons-components/ChangeIcon.js b/server/sonar-web/src/main/js/components/icons-components/ChangeIcon.js index f6d5f894e4f..e6b7498ab33 100644 --- a/server/sonar-web/src/main/js/components/icons-components/ChangeIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/ChangeIcon.js @@ -20,9 +20,11 @@ // @flow import React from 'react'; +/*:: type Props = { className?: string, size?: number }; +*/ -export default function ChangeIcon({ className, size = 12 }: Props) { +export default function ChangeIcon({ className, size = 12 } /*: Props */) { /* eslint-disable max-len */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/icons-components/ChartLegendIcon.js b/server/sonar-web/src/main/js/components/icons-components/ChartLegendIcon.js index 76602133108..93b40513c93 100644 --- a/server/sonar-web/src/main/js/components/icons-components/ChartLegendIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/ChartLegendIcon.js @@ -20,9 +20,11 @@ // @flow import React from 'react'; +/*:: type Props = { className?: string, size?: number }; +*/ -export default function ChartLegendIcon({ className, size = 16 }: Props) { +export default function ChartLegendIcon({ className, size = 16 } /*: Props */) { /* eslint-disable max-len */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/icons-components/CloseIcon.js b/server/sonar-web/src/main/js/components/icons-components/CloseIcon.js index 8722eba0318..7fb48b8b3f2 100644 --- a/server/sonar-web/src/main/js/components/icons-components/CloseIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/CloseIcon.js @@ -20,9 +20,11 @@ // @flow import React from 'react'; +/*:: type Props = { className?: string, size?: number }; +*/ -export default function CloseIcon({ className, size = 16 }: Props) { +export default function CloseIcon({ className, size = 16 } /*: Props */) { /* eslint-disable max-len */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/icons-components/CodeSmellIcon.js b/server/sonar-web/src/main/js/components/icons-components/CodeSmellIcon.js index 640a14ca39c..108e4203e75 100644 --- a/server/sonar-web/src/main/js/components/icons-components/CodeSmellIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/CodeSmellIcon.js @@ -20,9 +20,11 @@ // @flow import React from 'react'; +/*:: type Props = { className?: string, size?: number }; +*/ -export default function CodeSmellIcon({ className, size = 16 }: Props) { +export default function CodeSmellIcon({ className, size = 16 } /*: Props */) { /* eslint-disable max-len */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/icons-components/DeleteIcon.js b/server/sonar-web/src/main/js/components/icons-components/DeleteIcon.js index 049cc565aaa..9c90a1a9511 100644 --- a/server/sonar-web/src/main/js/components/icons-components/DeleteIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/DeleteIcon.js @@ -20,9 +20,11 @@ // @flow import React from 'react'; +/*:: type Props = { className?: string, size?: number }; +*/ -export default function DeleteIcon({ className, size = 12 }: Props) { +export default function DeleteIcon({ className, size = 12 } /*: Props */) { /* eslint-disable max-len */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/icons-components/HelpIcon.js b/server/sonar-web/src/main/js/components/icons-components/HelpIcon.js index af6304198d3..6a50ee17f88 100644 --- a/server/sonar-web/src/main/js/components/icons-components/HelpIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/HelpIcon.js @@ -20,9 +20,11 @@ // @flow import React from 'react'; +/*:: type Props = { className?: string, size?: number }; +*/ -export default function HelpIcon({ className, size = 16 }: Props) { +export default function HelpIcon({ className, size = 16 } /*: Props */) { /* eslint-disable max-len */ return ( <svg className={className} viewBox="0 0 16 16" width={size} height={size}> diff --git a/server/sonar-web/src/main/js/components/icons-components/HistoryIcon.js b/server/sonar-web/src/main/js/components/icons-components/HistoryIcon.js index 7fed99c67bc..fa0afc2a5de 100644 --- a/server/sonar-web/src/main/js/components/icons-components/HistoryIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/HistoryIcon.js @@ -20,9 +20,11 @@ // @flow import React from 'react'; +/*:: type Props = { className?: string, size?: number }; +*/ -export default function IconHistory({ className, size = 16 }: Props) { +export default function IconHistory({ className, size = 16 } /*: Props */) { /* eslint max-len: 0 */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/icons-components/LinkIcon.js b/server/sonar-web/src/main/js/components/icons-components/LinkIcon.js index b94b53d12f4..7d09ef2b635 100644 --- a/server/sonar-web/src/main/js/components/icons-components/LinkIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/LinkIcon.js @@ -20,9 +20,9 @@ // @flow import React from 'react'; -type Props = { className?: string, size?: number }; +/*:: type Props = { className?: string, size?: number }; */ -export default function LinkIcon({ className, size = 14 }: Props) { +export default function LinkIcon({ className, size = 14 } /*: Props */) { /* eslint-disable max-len */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/icons-components/ListIcon.js b/server/sonar-web/src/main/js/components/icons-components/ListIcon.js index c2a6593d7e2..66c62be5dcc 100644 --- a/server/sonar-web/src/main/js/components/icons-components/ListIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/ListIcon.js @@ -20,9 +20,11 @@ // @flow import React from 'react'; +/*:: type Props = { className?: string, size?: number }; +*/ -export default function ListIcon({ className, size = 16 }: Props) { +export default function ListIcon({ className, size = 16 } /*: Props */) { /* eslint-disable max-len */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/icons-components/OrganizationIcon.js b/server/sonar-web/src/main/js/components/icons-components/OrganizationIcon.js index 225b3f92b5c..93d2280351e 100644 --- a/server/sonar-web/src/main/js/components/icons-components/OrganizationIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/OrganizationIcon.js @@ -20,9 +20,11 @@ // @flow import React from 'react'; +/*:: type Props = { className?: string, size?: number }; +*/ -export default function OrganizationIcon({ className, size = 16 }: Props) { +export default function OrganizationIcon({ className, size = 16 } /*: Props */) { /* eslint-disable max-len */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/icons-components/ProjectEventIcon.js b/server/sonar-web/src/main/js/components/icons-components/ProjectEventIcon.js index 747cc2bfbce..b2a99892e17 100644 --- a/server/sonar-web/src/main/js/components/icons-components/ProjectEventIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/ProjectEventIcon.js @@ -20,9 +20,11 @@ // @flow import React from 'react'; +/*:: type Props = { className?: string, size?: number }; +*/ -export default function ProjectEventIcon({ className, size = 14 }: Props) { +export default function ProjectEventIcon({ className, size = 14 } /*: Props */) { /* eslint-disable max-len */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/icons-components/QualifierIcon.js b/server/sonar-web/src/main/js/components/icons-components/QualifierIcon.js index 460b387d165..be71c1f128a 100644 --- a/server/sonar-web/src/main/js/components/icons-components/QualifierIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/QualifierIcon.js @@ -22,7 +22,7 @@ import React from 'react'; const DEFAULT_COLOR = '#2D88C0'; -const ICONS: Object = { +const ICONS /*: Object */ = { dir: (color = '#F90') => <path fill={color} @@ -91,9 +91,9 @@ ICONS.pac = ICONS.dir; ICONS.dev_prj = ICONS.trk; ICONS.cla = ICONS.uts; -type Props = { className?: string, color?: string, qualifier: string, size?: number }; +/*:: type Props = { className?: string, color?: string, qualifier: string, size?: number }; */ -export default function QualifierIcon({ className, color, qualifier, size = 16 }: Props) { +export default function QualifierIcon({ className, color, qualifier, size = 16 } /*: Props */) { const icon = ICONS[qualifier.toLowerCase()]; if (!icon) { return null; diff --git a/server/sonar-web/src/main/js/components/icons-components/SortAscIcon.js b/server/sonar-web/src/main/js/components/icons-components/SortAscIcon.js index afaa0752c4a..b426db01fef 100644 --- a/server/sonar-web/src/main/js/components/icons-components/SortAscIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/SortAscIcon.js @@ -20,9 +20,11 @@ // @flow import React from 'react'; +/*:: type Props = { className?: string, size?: number }; +*/ -export default function SortAscIcon({ className, size = 16 }: Props) { +export default function SortAscIcon({ className, size = 16 } /*: Props */) { /* eslint-disable max-len */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/icons-components/SortDescIcon.js b/server/sonar-web/src/main/js/components/icons-components/SortDescIcon.js index 75c8e788514..041054adf4f 100644 --- a/server/sonar-web/src/main/js/components/icons-components/SortDescIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/SortDescIcon.js @@ -20,9 +20,11 @@ // @flow import React from 'react'; +/*:: type Props = { className?: string, size?: number }; +*/ -export default function SortDescIcon({ className, size = 16 }: Props) { +export default function SortDescIcon({ className, size = 16 } /*: Props */) { /* eslint-disable max-len */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/icons-components/TreeIcon.js b/server/sonar-web/src/main/js/components/icons-components/TreeIcon.js index 4aea3bef2d2..53ff8dbf8aa 100644 --- a/server/sonar-web/src/main/js/components/icons-components/TreeIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/TreeIcon.js @@ -20,9 +20,9 @@ // @flow import React from 'react'; -type Props = { className?: string, size?: number }; +/*:: type Props = { className?: string, size?: number }; */ -export default function TreeIcon({ className, size = 16 }: Props) { +export default function TreeIcon({ className, size = 16 } /*: Props */) { /* eslint-disable max-len */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/icons-components/TreemapIcon.js b/server/sonar-web/src/main/js/components/icons-components/TreemapIcon.js index 3dc977b2c3c..524112c41db 100644 --- a/server/sonar-web/src/main/js/components/icons-components/TreemapIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/TreemapIcon.js @@ -20,9 +20,9 @@ // @flow import React from 'react'; -type Props = { className?: string, size?: number }; +/*:: type Props = { className?: string, size?: number }; */ -export default function TreemapIcon({ className, size = 14 }: Props) { +export default function TreemapIcon({ className, size = 14 } /*: Props */) { /* eslint-disable max-len */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/icons-components/VulnerabilityIcon.js b/server/sonar-web/src/main/js/components/icons-components/VulnerabilityIcon.js index 154378c6fa2..1d3b5b18e26 100644 --- a/server/sonar-web/src/main/js/components/icons-components/VulnerabilityIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/VulnerabilityIcon.js @@ -20,9 +20,11 @@ // @flow import React from 'react'; +/*:: type Props = { className?: string, size?: number }; +*/ -export default function VulnerabilityIcon({ className, size = 16 }: Props) { +export default function VulnerabilityIcon({ className, size = 16 } /*: Props */) { /* eslint-disable max-len */ return ( <svg diff --git a/server/sonar-web/src/main/js/components/issue/Issue.js b/server/sonar-web/src/main/js/components/issue/Issue.js index f21644f1e59..42f1a54a072 100644 --- a/server/sonar-web/src/main/js/components/issue/Issue.js +++ b/server/sonar-web/src/main/js/components/issue/Issue.js @@ -25,8 +25,9 @@ import IssueView from './IssueView'; import { updateIssue } from './actions'; import { setIssueAssignee } from '../../api/issues'; import { onFail } from '../../store/rootActions'; -import type { Issue } from './types'; +/*:: import type { Issue } from './types'; */ +/*:: type Props = {| checked?: boolean, issue: Issue, @@ -36,15 +37,18 @@ type Props = {| onFilter?: (property: string, issue: Issue) => void, selected: boolean |}; +*/ +/*:: type State = { currentPopup: string }; +*/ export default class BaseIssue extends React.PureComponent { - mounted: boolean; - props: Props; - state: State; + /*:: mounted: boolean; */ + /*:: props: Props; */ + /*:: state: State; */ static contextTypes = { store: PropTypes.object @@ -54,7 +58,7 @@ export default class BaseIssue extends React.PureComponent { selected: false }; - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { currentPopup: '' @@ -68,13 +72,13 @@ export default class BaseIssue extends React.PureComponent { } } - componentWillUpdate(nextProps: Props) { + componentWillUpdate(nextProps /*: Props */) { if (!nextProps.selected && this.props.selected) { this.unbindShortcuts(); } } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { if (!prevProps.selected && this.props.selected) { this.bindShortcuts(); } @@ -123,9 +127,9 @@ export default class BaseIssue extends React.PureComponent { key.unbind('t', 'issues'); } - togglePopup = (popupName: string, open?: boolean) => { + togglePopup = (popupName /*: string */, open /*: ?boolean */) => { if (this.mounted) { - this.setState((prevState: State) => { + this.setState((prevState /*: State */) => { if (prevState.currentPopup !== popupName && open !== false) { return { currentPopup: popupName }; } else if (prevState.currentPopup === popupName && open !== true) { @@ -136,7 +140,7 @@ export default class BaseIssue extends React.PureComponent { } }; - handleAssignement = (login: string) => { + handleAssignement = (login /*: string */) => { const { issue } = this.props; if (issue.assignee !== login) { updateIssue( @@ -148,7 +152,7 @@ export default class BaseIssue extends React.PureComponent { this.togglePopup('assign', false); }; - handleFail = (error: Error) => { + handleFail = (error /*: Error */) => { onFail(this.context.store.dispatch)(error); }; diff --git a/server/sonar-web/src/main/js/components/issue/IssueView.js b/server/sonar-web/src/main/js/components/issue/IssueView.js index edcd1e32a42..be2f91af2ef 100644 --- a/server/sonar-web/src/main/js/components/issue/IssueView.js +++ b/server/sonar-web/src/main/js/components/issue/IssueView.js @@ -25,8 +25,9 @@ import IssueActionsBar from './components/IssueActionsBar'; import IssueCommentLine from './components/IssueCommentLine'; import { updateIssue } from './actions'; import { deleteIssueComment, editIssueComment } from '../../api/issues'; -import type { Issue } from './types'; +/*:: import type { Issue } from './types'; */ +/*:: type Props = {| checked?: boolean, currentPopup: string, @@ -40,11 +41,12 @@ type Props = {| selected: boolean, togglePopup: (string, boolean | void) => void |}; +*/ export default class IssueView extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleCheck = (event: Event) => { + handleCheck = (event /*: Event */) => { event.preventDefault(); event.stopPropagation(); if (this.props.onCheck) { @@ -52,18 +54,18 @@ export default class IssueView extends React.PureComponent { } }; - handleClick = (event: Event & { target: HTMLElement }) => { + handleClick = (event /*: Event & { target: HTMLElement } */) => { event.preventDefault(); if (this.props.onClick) { this.props.onClick(this.props.issue.key); } }; - editComment = (comment: string, text: string) => { + editComment = (comment /*: string */, text /*: string */) => { updateIssue(this.props.onChange, this.props.onFail, editIssueComment({ comment, text })); }; - deleteComment = (comment: string) => { + deleteComment = (comment /*: string */) => { updateIssue(this.props.onChange, this.props.onFail, deleteIssueComment({ comment })); }; diff --git a/server/sonar-web/src/main/js/components/issue/actions.js b/server/sonar-web/src/main/js/components/issue/actions.js index 6a8deedc1ca..74bbafabf6e 100644 --- a/server/sonar-web/src/main/js/components/issue/actions.js +++ b/server/sonar-web/src/main/js/components/issue/actions.js @@ -19,14 +19,14 @@ */ // @flow import { parseIssueFromResponse } from '../../helpers/issues'; -import type { Issue } from './types'; +/*:: import type { Issue } from './types'; */ export const updateIssue = ( - onChange: Issue => void, - onFail: Error => void, - resultPromise: Promise<*>, - oldIssue?: Issue, - newIssue?: Issue + onChange /*: Issue => void */, + onFail /*: Error => void */, + resultPromise /*: Promise<*> */, + oldIssue /*: ?Issue */, + newIssue /*: ?Issue */ ) => { const optimisticUpdate = oldIssue != null && newIssue != null; if (optimisticUpdate) { diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueActionsBar.js b/server/sonar-web/src/main/js/components/issue/components/IssueActionsBar.js index 87464c953a7..2c119cbb393 100644 --- a/server/sonar-web/src/main/js/components/issue/components/IssueActionsBar.js +++ b/server/sonar-web/src/main/js/components/issue/components/IssueActionsBar.js @@ -27,8 +27,9 @@ import IssueTransition from './IssueTransition'; import IssueType from './IssueType'; import { updateIssue } from '../actions'; import { translate, translateWithParameters } from '../../../helpers/l10n'; -import type { Issue } from '../types'; +/*:: import type { Issue } from '../types'; */ +/*:: type Props = { issue: Issue, currentPopup: string, @@ -37,18 +38,21 @@ type Props = { onFail: Error => void, togglePopup: (string, boolean | void) => void }; +*/ +/*:: type State = { commentPlaceholder: string }; +*/ export default class IssueActionsBar extends React.PureComponent { - props: Props; - state: State = { + /*:: props: Props; */ + state /*: State */ = { commentPlaceholder: '' }; - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps /*: Props */) { const { resolution } = this.props.issue; if (!prevProps.issue.resolution && ['FALSE-POSITIVE', 'WONTFIX'].includes(resolution)) { this.toggleComment(true, translate('issue.comment.tell_why')); @@ -56,10 +60,10 @@ export default class IssueActionsBar extends React.PureComponent { } setIssueProperty = ( - property: string, - popup: string, - apiCall: Object => Promise<*>, - value: string + property /*: string */, + popup /*: string */, + apiCall /*: Object => Promise<*> */, + value /*: string */ ) => { const { issue } = this.props; if (issue[property] !== value) { @@ -75,7 +79,7 @@ export default class IssueActionsBar extends React.PureComponent { this.props.togglePopup(popup, false); }; - toggleComment = (open?: boolean, placeholder?: string) => { + toggleComment = (open /*: boolean | void */, placeholder /*: string | void */) => { this.setState({ commentPlaceholder: placeholder || '' }); this.props.togglePopup('comment', open); }; diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueAssign.js b/server/sonar-web/src/main/js/components/issue/components/IssueAssign.js index a3e2e5e8203..249c9ae969d 100644 --- a/server/sonar-web/src/main/js/components/issue/components/IssueAssign.js +++ b/server/sonar-web/src/main/js/components/issue/components/IssueAssign.js @@ -23,8 +23,9 @@ import Avatar from '../../../components/ui/Avatar'; import BubblePopupHelper from '../../../components/common/BubblePopupHelper'; import SetAssigneePopup from '../popups/SetAssigneePopup'; import { translate } from '../../../helpers/l10n'; -import type { Issue } from '../types'; +/*:: import type { Issue } from '../types'; */ +/*:: type Props = { isOpen: boolean, issue: Issue, @@ -33,11 +34,12 @@ type Props = { onFail: Error => void, togglePopup: (string, boolean | void) => void }; +*/ export default class IssueAssign extends React.PureComponent { - props: Props; + /*:: props: Props; */ - toggleAssign = (open?: boolean) => { + toggleAssign = (open /*: boolean | void */) => { this.props.togglePopup('assign', open); }; diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueChangelog.js b/server/sonar-web/src/main/js/components/issue/components/IssueChangelog.js index 8c582920d3e..721c83ff7e4 100644 --- a/server/sonar-web/src/main/js/components/issue/components/IssueChangelog.js +++ b/server/sonar-web/src/main/js/components/issue/components/IssueChangelog.js @@ -22,8 +22,9 @@ import React from 'react'; import moment from 'moment'; import BubblePopupHelper from '../../../components/common/BubblePopupHelper'; import ChangelogPopup from '../popups/ChangelogPopup'; -import type { Issue } from '../types'; +/*:: import type { Issue } from '../types'; */ +/*:: type Props = { isOpen: boolean, issue: Issue, @@ -31,16 +32,17 @@ type Props = { togglePopup: (string, boolean | void) => void, onFail: Error => void }; +*/ export default class IssueChangelog extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleClick = (evt: SyntheticInputEvent) => { + handleClick = (evt /*: SyntheticInputEvent */) => { evt.preventDefault(); this.toggleChangelog(); }; - toggleChangelog = (open?: boolean) => { + toggleChangelog = (open /*: boolean | void */) => { this.props.togglePopup('changelog', open); }; diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueChangelogDiff.js b/server/sonar-web/src/main/js/components/issue/components/IssueChangelogDiff.js index bfe753329e3..4c11eb707e6 100644 --- a/server/sonar-web/src/main/js/components/issue/components/IssueChangelogDiff.js +++ b/server/sonar-web/src/main/js/components/issue/components/IssueChangelogDiff.js @@ -22,13 +22,15 @@ import React from 'react'; import { formatMeasure } from '../../../helpers/measures'; import { translate, translateWithParameters } from '../../../helpers/l10n'; +/*:: export type ChangelogDiff = { key: string, oldValue?: string, newValue?: string }; +*/ -export default function IssueChangelogDiff(props: { diff: ChangelogDiff }) { +export default function IssueChangelogDiff(props /*: { diff: ChangelogDiff } */) { const { diff } = props; if (diff.key === 'file') { return ( @@ -42,9 +44,9 @@ export default function IssueChangelogDiff(props: { diff: ChangelogDiff }) { ); } - let message: string; + let message; if (diff.newValue != null) { - let newValue: string = diff.newValue; + let newValue /*: string */ = diff.newValue; if (diff.key === 'effort') { newValue = formatMeasure(diff.newValue, 'WORK_DUR'); } @@ -61,7 +63,7 @@ export default function IssueChangelogDiff(props: { diff: ChangelogDiff }) { } if (diff.oldValue != null) { - let oldValue: string = diff.oldValue; + let oldValue /*: string */ = diff.oldValue; if (diff.key === 'effort') { oldValue = formatMeasure(diff.oldValue, 'WORK_DUR'); } diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueCommentAction.js b/server/sonar-web/src/main/js/components/issue/components/IssueCommentAction.js index cac1cf29a37..718d456df06 100644 --- a/server/sonar-web/src/main/js/components/issue/components/IssueCommentAction.js +++ b/server/sonar-web/src/main/js/components/issue/components/IssueCommentAction.js @@ -24,8 +24,9 @@ import BubblePopupHelper from '../../../components/common/BubblePopupHelper'; import CommentPopup from '../popups/CommentPopup'; import { addIssueComment } from '../../../api/issues'; import { translate } from '../../../helpers/l10n'; -import type { Issue } from '../types'; +/*:: import type { Issue } from '../types'; */ +/*:: type Props = {| commentPlaceholder: string, currentPopup: string, @@ -34,11 +35,12 @@ type Props = {| onFail: Error => void, toggleComment: (open?: boolean, placeholder?: string) => void |}; +*/ export default class IssueCommentAction extends React.PureComponent { - props: Props; + /*:: props: Props; */ - addComment = (text: string) => { + addComment = (text /*: string */) => { updateIssue( this.props.onChange, this.props.onFail, diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueCommentLine.js b/server/sonar-web/src/main/js/components/issue/components/IssueCommentLine.js index 1ad62e60eb6..ee41dddc847 100644 --- a/server/sonar-web/src/main/js/components/issue/components/IssueCommentLine.js +++ b/server/sonar-web/src/main/js/components/issue/components/IssueCommentLine.js @@ -24,25 +24,29 @@ import Avatar from '../../../components/ui/Avatar'; import BubblePopupHelper from '../../../components/common/BubblePopupHelper'; import CommentDeletePopup from '../popups/CommentDeletePopup'; import CommentPopup from '../popups/CommentPopup'; -import type { IssueComment } from '../types'; +/*:: import type { IssueComment } from '../types'; */ +/*:: type Props = { comment: IssueComment, onDelete: string => void, onEdit: (string, string) => void }; +*/ +/*:: type State = { openPopup: string }; +*/ export default class IssueCommentLine extends React.PureComponent { - props: Props; - state: State = { + /*:: props: Props; */ + state /*: State */ = { openPopup: '' }; - handleEdit = (text: string) => { + handleEdit = (text /*: string */) => { this.props.onEdit(this.props.comment.key, text); this.toggleEditPopup(false); }; @@ -52,8 +56,8 @@ export default class IssueCommentLine extends React.PureComponent { this.toggleDeletePopup(false); }; - togglePopup = (popupName: string, force?: boolean) => { - this.setState((prevState: State) => { + togglePopup = (popupName /*: string */, force /*: ?boolean */) => { + this.setState((prevState /*: State */) => { if (prevState.openPopup !== popupName && force !== false) { return { openPopup: popupName }; } else if (prevState.openPopup === popupName && force !== true) { @@ -63,9 +67,9 @@ export default class IssueCommentLine extends React.PureComponent { }); }; - toggleDeletePopup = (force?: boolean) => this.togglePopup('delete', force); + toggleDeletePopup = (force /*: ?boolean */) => this.togglePopup('delete', force); - toggleEditPopup = (force?: boolean) => this.togglePopup('edit', force); + toggleEditPopup = (force /*: ?boolean */) => this.togglePopup('edit', force); render() { const { comment } = this.props; diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueMessage.js b/server/sonar-web/src/main/js/components/issue/components/IssueMessage.js index ccbd4f1ec89..62620d4c74f 100644 --- a/server/sonar-web/src/main/js/components/issue/components/IssueMessage.js +++ b/server/sonar-web/src/main/js/components/issue/components/IssueMessage.js @@ -22,13 +22,14 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; export default class IssueMessage extends React.PureComponent { - props: { + /*:: props: { message: string, rule: string, organization: string }; +*/ - handleClick = (e: MouseEvent) => { + handleClick = (e /*: MouseEvent */) => { e.preventDefault(); e.stopPropagation(); const Workspace = require('../../workspace/main').default; diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueSeverity.js b/server/sonar-web/src/main/js/components/issue/components/IssueSeverity.js index d91fa74625d..f62747e913f 100644 --- a/server/sonar-web/src/main/js/components/issue/components/IssueSeverity.js +++ b/server/sonar-web/src/main/js/components/issue/components/IssueSeverity.js @@ -23,8 +23,9 @@ import BubblePopupHelper from '../../../components/common/BubblePopupHelper'; import SetSeverityPopup from '../popups/SetSeverityPopup'; import SeverityHelper from '../../../components/shared/SeverityHelper'; import { setIssueSeverity } from '../../../api/issues'; -import type { Issue } from '../types'; +/*:: import type { Issue } from '../types'; */ +/*:: type Props = { canSetSeverity: boolean, isOpen: boolean, @@ -32,15 +33,16 @@ type Props = { setIssueProperty: (string, string, apiCall: (Object) => Promise<*>, string) => void, togglePopup: (string, boolean | void) => void }; +*/ export default class IssueSeverity extends React.PureComponent { - props: Props; + /*:: props: Props; */ - toggleSetSeverity = (open?: boolean) => { + toggleSetSeverity = (open /*: boolean | void */) => { this.props.togglePopup('set-severity', open); }; - setSeverity = (severity: string) => + setSeverity = (severity /*: string */) => this.props.setIssueProperty('severity', 'set-severity', setIssueSeverity, severity); render() { diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueTags.js b/server/sonar-web/src/main/js/components/issue/components/IssueTags.js index 6e0365be9aa..2b5f15f0207 100644 --- a/server/sonar-web/src/main/js/components/issue/components/IssueTags.js +++ b/server/sonar-web/src/main/js/components/issue/components/IssueTags.js @@ -25,8 +25,9 @@ import SetIssueTagsPopup from '../popups/SetIssueTagsPopup'; import TagsList from '../../../components/tags/TagsList'; import { setIssueTags } from '../../../api/issues'; import { translate } from '../../../helpers/l10n'; -import type { Issue } from '../types'; +/*:: import type { Issue } from '../types'; */ +/*:: type Props = {| canSetTags: boolean, isOpen: boolean, @@ -35,15 +36,16 @@ type Props = {| onFail: Error => void, togglePopup: (string, boolean | void) => void |}; +*/ export default class IssueTags extends React.PureComponent { - props: Props; + /*:: props: Props; */ - toggleSetTags = (open?: boolean) => { + toggleSetTags = (open /*: boolean | void */) => { this.props.togglePopup('edit-tags', open); }; - setTags = (tags: Array<string>) => { + setTags = (tags /*: Array<string> */) => { const { issue } = this.props; const newIssue = { ...issue, tags }; updateIssue( diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueTitleBar.js b/server/sonar-web/src/main/js/components/issue/components/IssueTitleBar.js index 38e0043eba3..c6958f6a768 100644 --- a/server/sonar-web/src/main/js/components/issue/components/IssueTitleBar.js +++ b/server/sonar-web/src/main/js/components/issue/components/IssueTitleBar.js @@ -29,8 +29,9 @@ import Tooltip from '../../controls/Tooltip'; import { getComponentIssuesUrl } from '../../../helpers/urls'; import { formatMeasure } from '../../../helpers/measures'; import { translate, translateWithParameters } from '../../../helpers/l10n'; -import type { Issue } from '../types'; +/*:: import type { Issue } from '../types'; */ +/*:: type Props = {| issue: Issue, currentPopup: string, @@ -38,10 +39,11 @@ type Props = {| onFilter?: (property: string, issue: Issue) => void, togglePopup: (string, boolean | void) => void |}; +*/ -const stopPropagation = (event: Event) => event.stopPropagation(); +const stopPropagation = (event /*: Event */) => event.stopPropagation(); -export default function IssueTitleBar(props: Props) { +export default function IssueTitleBar(props /*: Props */) { const { issue } = props; const hasSimilarIssuesFilter = props.onFilter != null; diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueTransition.js b/server/sonar-web/src/main/js/components/issue/components/IssueTransition.js index 5b51aab6102..319ccd7c843 100644 --- a/server/sonar-web/src/main/js/components/issue/components/IssueTransition.js +++ b/server/sonar-web/src/main/js/components/issue/components/IssueTransition.js @@ -24,8 +24,9 @@ import BubblePopupHelper from '../../../components/common/BubblePopupHelper'; import SetTransitionPopup from '../popups/SetTransitionPopup'; import StatusHelper from '../../../components/shared/StatusHelper'; import { setIssueTransition } from '../../../api/issues'; -import type { Issue } from '../types'; +/*:: import type { Issue } from '../types'; */ +/*:: type Props = { hasTransitions: boolean, isOpen: boolean, @@ -34,11 +35,12 @@ type Props = { onFail: Error => void, togglePopup: (string, boolean | void) => void }; +*/ export default class IssueTransition extends React.PureComponent { - props: Props; + /*:: props: Props; */ - setTransition = (transition: string) => { + setTransition = (transition /*: string */) => { updateIssue( this.props.onChange, this.props.onFail, @@ -47,7 +49,7 @@ export default class IssueTransition extends React.PureComponent { this.toggleSetTransition(); }; - toggleSetTransition = (open?: boolean) => { + toggleSetTransition = (open /*: boolean | void */) => { this.props.togglePopup('transition', open); }; diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueType.js b/server/sonar-web/src/main/js/components/issue/components/IssueType.js index 7281352fab4..bb08a1c56e4 100644 --- a/server/sonar-web/src/main/js/components/issue/components/IssueType.js +++ b/server/sonar-web/src/main/js/components/issue/components/IssueType.js @@ -24,8 +24,9 @@ import IssueTypeIcon from '../../../components/ui/IssueTypeIcon'; import SetTypePopup from '../popups/SetTypePopup'; import { setIssueType } from '../../../api/issues'; import { translate } from '../../../helpers/l10n'; -import type { Issue } from '../types'; +/*:: import type { Issue } from '../types'; */ +/*:: type Props = { canSetSeverity: boolean, isOpen: boolean, @@ -33,15 +34,17 @@ type Props = { setIssueProperty: (string, string, apiCall: (Object) => Promise<*>, string) => void, togglePopup: (string, boolean | void) => void }; +*/ export default class IssueType extends React.PureComponent { - props: Props; + /*:: props: Props; */ - toggleSetType = (open?: boolean) => { + toggleSetType = (open /*: boolean | void */) => { this.props.togglePopup('set-type', open); }; - setType = (type: string) => this.props.setIssueProperty('type', 'set-type', setIssueType, type); + setType = (type /*: string */) => + this.props.setIssueProperty('type', 'set-type', setIssueType, type); render() { const { issue } = this.props; diff --git a/server/sonar-web/src/main/js/components/issue/components/SimilarIssuesFilter.js b/server/sonar-web/src/main/js/components/issue/components/SimilarIssuesFilter.js index f7086c8018d..8a6148bde7d 100644 --- a/server/sonar-web/src/main/js/components/issue/components/SimilarIssuesFilter.js +++ b/server/sonar-web/src/main/js/components/issue/components/SimilarIssuesFilter.js @@ -22,8 +22,9 @@ import React from 'react'; import BubblePopupHelper from '../../../components/common/BubblePopupHelper'; import SimilarIssuesPopup from '../popups/SimilarIssuesPopup'; import { translate } from '../../../helpers/l10n'; -import type { Issue } from '../types'; +/*:: import type { Issue } from '../types'; */ +/*:: type Props = {| isOpen: boolean, issue: Issue, @@ -31,21 +32,22 @@ type Props = {| onFail: Error => void, onFilter: (property: string, issue: Issue) => void |}; +*/ export default class SimilarIssuesFilter extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleClick = (evt: SyntheticInputEvent) => { + handleClick = (evt /*: SyntheticInputEvent */) => { evt.preventDefault(); this.togglePopup(); }; - handleFilter = (property: string, issue: Issue) => { + handleFilter = (property /*: string */, issue /*: Issue */) => { this.togglePopup(false); this.props.onFilter(property, issue); }; - togglePopup = (open?: boolean) => { + togglePopup = (open /*: boolean | void */) => { this.props.togglePopup('similarIssues', open); }; diff --git a/server/sonar-web/src/main/js/components/issue/popups/ChangelogPopup.js b/server/sonar-web/src/main/js/components/issue/popups/ChangelogPopup.js index 735411774cf..6f0ca9ac054 100644 --- a/server/sonar-web/src/main/js/components/issue/popups/ChangelogPopup.js +++ b/server/sonar-web/src/main/js/components/issue/popups/ChangelogPopup.js @@ -25,9 +25,10 @@ import { translate } from '../../../helpers/l10n'; import Avatar from '../../../components/ui/Avatar'; import BubblePopup from '../../../components/common/BubblePopup'; import IssueChangelogDiff from '../components/IssueChangelogDiff'; -import type { ChangelogDiff } from '../components/IssueChangelogDiff'; -import type { Issue } from '../types'; +/*:: import type { ChangelogDiff } from '../components/IssueChangelogDiff'; */ +/*:: import type { Issue } from '../types'; */ +/*:: type Changelog = { avatar?: string, creationDate: string, @@ -35,21 +36,26 @@ type Changelog = { user: string, userName: string }; +*/ +/*:: type Props = { issue: Issue, onFail: Error => void, popupPosition?: {} }; +*/ +/*:: type State = { changelogs: Array<Changelog> }; +*/ export default class ChangelogPopup extends React.PureComponent { - mounted: boolean; - props: Props; - state: State = { + /*:: mounted: boolean; */ + /*:: props: Props; */ + state /*: State */ = { changelogs: [] }; diff --git a/server/sonar-web/src/main/js/components/issue/popups/CommentDeletePopup.js b/server/sonar-web/src/main/js/components/issue/popups/CommentDeletePopup.js index 23a2dc4c154..428efc6a6b9 100644 --- a/server/sonar-web/src/main/js/components/issue/popups/CommentDeletePopup.js +++ b/server/sonar-web/src/main/js/components/issue/popups/CommentDeletePopup.js @@ -22,12 +22,14 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; import BubblePopup from '../../../components/common/BubblePopup'; +/*:: type Props = { onDelete: () => void, popupPosition?: {} }; +*/ -export default function CommentDeletePopup(props: Props) { +export default function CommentDeletePopup(props /*: Props */) { return ( <BubblePopup position={props.popupPosition} customClass="bubble-popup-bottom-right"> <div className="text-right"> diff --git a/server/sonar-web/src/main/js/components/issue/popups/CommentPopup.js b/server/sonar-web/src/main/js/components/issue/popups/CommentPopup.js index befea8fef19..fec009c190c 100644 --- a/server/sonar-web/src/main/js/components/issue/popups/CommentPopup.js +++ b/server/sonar-web/src/main/js/components/issue/popups/CommentPopup.js @@ -23,8 +23,9 @@ import classNames from 'classnames'; import BubblePopup from '../../../components/common/BubblePopup'; import MarkdownTips from '../../../components/common/MarkdownTips'; import { translate } from '../../../helpers/l10n'; -import type { IssueComment } from '../types'; +/*:: import type { IssueComment } from '../types'; */ +/*:: type Props = { comment?: IssueComment, customClass?: string, @@ -33,23 +34,26 @@ type Props = { placeholder: string, popupPosition?: {} }; +*/ +/*:: type State = { textComment: string }; +*/ export default class CommentPopup extends React.PureComponent { - props: Props; - state: State; + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.state = { textComment: props.comment ? props.comment.markdown : '' }; } - handleCommentChange = (evt: SyntheticInputEvent) => { + handleCommentChange = (evt /*: SyntheticInputEvent */) => { this.setState({ textComment: evt.target.value }); }; @@ -59,12 +63,12 @@ export default class CommentPopup extends React.PureComponent { } }; - handleCancelClick = (evt: MouseEvent) => { + handleCancelClick = (evt /*: MouseEvent */) => { evt.preventDefault(); this.props.toggleComment(false); }; - handleKeyboard = (evt: KeyboardEvent) => { + handleKeyboard = (evt /*: KeyboardEvent */) => { if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) { // Ctrl + Enter this.handleCommentClick(); diff --git a/server/sonar-web/src/main/js/components/issue/popups/SetAssigneePopup.js b/server/sonar-web/src/main/js/components/issue/popups/SetAssigneePopup.js index 7a6bdc6107d..531da13d63d 100644 --- a/server/sonar-web/src/main/js/components/issue/popups/SetAssigneePopup.js +++ b/server/sonar-web/src/main/js/components/issue/popups/SetAssigneePopup.js @@ -29,37 +29,43 @@ import { areThereCustomOrganizations } from '../../../store/organizations/utils' import { searchMembers } from '../../../api/organizations'; import { searchUsers } from '../../../api/users'; import { translate } from '../../../helpers/l10n'; -import type { Issue } from '../types'; +/*:: import type { Issue } from '../types'; */ +/*:: type User = { avatar?: string, email?: string, login: string, name: string }; +*/ +/*:: type Props = { issue: Issue, onFail: Error => void, onSelect: string => void, popupPosition?: {} }; +*/ +/*:: type State = { query: string, users: Array<User>, currentUser: string }; +*/ const LIST_SIZE = 10; export default class SetAssigneePopup extends React.PureComponent { - defaultUsersArray: Array<User>; - organizationEnabled: boolean; - props: Props; - state: State; + /*:: defaultUsersArray: Array<User>; */ + /*:: organizationEnabled: boolean; */ + /*:: props: Props; */ + /*:: state: State; */ - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.organizationEnabled = areThereCustomOrganizations(); this.searchUsers = debounce(this.searchUsers, 250); @@ -78,7 +84,7 @@ export default class SetAssigneePopup extends React.PureComponent { }; } - searchMembers = (query: string) => { + searchMembers = (query /*: string */) => { searchMembers({ organization: this.props.issue.projectOrganization, q: query, @@ -86,18 +92,18 @@ export default class SetAssigneePopup extends React.PureComponent { }).then(this.handleSearchResult, this.props.onFail); }; - searchUsers = (query: string) => { + searchUsers = (query /*: string */) => { searchUsers(query, LIST_SIZE).then(this.handleSearchResult, this.props.onFail); }; - handleSearchResult = (data: Object) => { + handleSearchResult = (data /*: Object */) => { this.setState({ users: data.users, currentUser: data.users.length > 0 ? data.users[0].login : '' }); }; - handleSearchChange = (evt: SyntheticInputEvent) => { + handleSearchChange = (evt /*: SyntheticInputEvent */) => { const query = evt.target.value; if (query.length < 2) { this.setState({ diff --git a/server/sonar-web/src/main/js/components/issue/popups/SetIssueTagsPopup.js b/server/sonar-web/src/main/js/components/issue/popups/SetIssueTagsPopup.js index 19951d07529..a9ac6e5d328 100644 --- a/server/sonar-web/src/main/js/components/issue/popups/SetIssueTagsPopup.js +++ b/server/sonar-web/src/main/js/components/issue/popups/SetIssueTagsPopup.js @@ -23,6 +23,7 @@ import { debounce, without } from 'lodash'; import TagsSelector from '../../../components/tags/TagsSelector'; import { searchIssueTags } from '../../../api/issues'; +/*:: type Props = { popupPosition?: {}, onFail: Error => void, @@ -30,19 +31,22 @@ type Props = { selectedTags: Array<string>, setTags: (Array<string>) => void }; +*/ +/*:: type State = { searchResult: Array<string> }; +*/ const LIST_SIZE = 10; export default class SetIssueTagsPopup 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 = { searchResult: [] }; this.onSearch = debounce(this.onSearch, 250); @@ -57,23 +61,23 @@ export default class SetIssueTagsPopup extends React.PureComponent { this.mounted = false; } - onSearch = (query: string) => { + onSearch = (query /*: string */) => { searchIssueTags({ q: query || '', ps: Math.min(this.props.selectedTags.length - 1 + LIST_SIZE, 100), organization: this.props.organization - }).then((tags: Array<string>) => { + }).then((tags /*: Array<string> */) => { if (this.mounted) { this.setState({ searchResult: tags }); } }, this.props.onFail); }; - onSelect = (tag: string) => { + onSelect = (tag /*: string */) => { this.props.setTags([...this.props.selectedTags, tag]); }; - onUnselect = (tag: string) => { + onUnselect = (tag /*: string */) => { this.props.setTags(without(this.props.selectedTags, tag)); }; diff --git a/server/sonar-web/src/main/js/components/issue/popups/SetSeverityPopup.js b/server/sonar-web/src/main/js/components/issue/popups/SetSeverityPopup.js index bc5969532be..033ea8e72a8 100644 --- a/server/sonar-web/src/main/js/components/issue/popups/SetSeverityPopup.js +++ b/server/sonar-web/src/main/js/components/issue/popups/SetSeverityPopup.js @@ -24,18 +24,20 @@ import BubblePopup from '../../../components/common/BubblePopup'; import SelectList from '../../../components/common/SelectList'; import SelectListItem from '../../../components/common/SelectListItem'; import SeverityIcon from '../../../components/shared/SeverityIcon'; -import type { Issue } from '../types'; +/*:: import type { Issue } from '../types'; */ +/*:: type Props = { issue: Issue, onSelect: string => void, popupPosition?: {} }; +*/ const SEVERITY = ['BLOCKER', 'CRITICAL', 'MAJOR', 'MINOR', 'INFO']; export default class SetSeverityPopup extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { return ( diff --git a/server/sonar-web/src/main/js/components/issue/popups/SetTransitionPopup.js b/server/sonar-web/src/main/js/components/issue/popups/SetTransitionPopup.js index dc1703d15ec..eb2ef57ac02 100644 --- a/server/sonar-web/src/main/js/components/issue/popups/SetTransitionPopup.js +++ b/server/sonar-web/src/main/js/components/issue/popups/SetTransitionPopup.js @@ -24,14 +24,16 @@ import SelectList from '../../../components/common/SelectList'; import SelectListItem from '../../../components/common/SelectListItem'; import { translate } from '../../../helpers/l10n'; +/*:: type Props = { transitions: Array<string>, onSelect: string => void, popupPosition?: {} }; +*/ export default class SetTransitionPopup extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { const { transitions } = this.props; diff --git a/server/sonar-web/src/main/js/components/issue/popups/SetTypePopup.js b/server/sonar-web/src/main/js/components/issue/popups/SetTypePopup.js index 64e780fdbbe..e3c4d466f28 100644 --- a/server/sonar-web/src/main/js/components/issue/popups/SetTypePopup.js +++ b/server/sonar-web/src/main/js/components/issue/popups/SetTypePopup.js @@ -24,18 +24,20 @@ import BubblePopup from '../../../components/common/BubblePopup'; import IssueTypeIcon from '../../../components/ui/IssueTypeIcon'; import SelectList from '../../../components/common/SelectList'; import SelectListItem from '../../../components/common/SelectListItem'; -import type { Issue } from '../types'; +/*:: import type { Issue } from '../types'; */ +/*:: type Props = { issue: Issue, onSelect: string => void, popupPosition?: {} }; +*/ const TYPES = ['BUG', 'VULNERABILITY', 'CODE_SMELL']; export default class SetTypePopup extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { return ( diff --git a/server/sonar-web/src/main/js/components/issue/popups/SimilarIssuesPopup.js b/server/sonar-web/src/main/js/components/issue/popups/SimilarIssuesPopup.js index e6dddbc21ff..4a2642f01ac 100644 --- a/server/sonar-web/src/main/js/components/issue/popups/SimilarIssuesPopup.js +++ b/server/sonar-web/src/main/js/components/issue/popups/SimilarIssuesPopup.js @@ -29,18 +29,20 @@ import IssueTypeIcon from '../../../components/ui/IssueTypeIcon'; import Avatar from '../../../components/ui/Avatar'; import { translate } from '../../../helpers/l10n'; import { fileFromPath, limitComponentName } from '../../../helpers/path'; -import type { Issue } from '../types'; +/*:: import type { Issue } from '../types'; */ +/*:: type Props = {| issue: Issue, onFilter: (property: string, issue: Issue) => void, popupPosition?: {} |}; +*/ export default class SimilarIssuesPopup extends React.PureComponent { - props: Props; + /*:: props: Props; */ - handleSelect = (property: string) => { + handleSelect = (property /*: string */) => { this.props.onFilter(property, this.props.issue); }; diff --git a/server/sonar-web/src/main/js/components/issue/types.js b/server/sonar-web/src/main/js/components/issue/types.js index 8788dc4d206..b9b2684b769 100644 --- a/server/sonar-web/src/main/js/components/issue/types.js +++ b/server/sonar-web/src/main/js/components/issue/types.js @@ -18,18 +18,23 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // @flow +/*:: export type TextRange = { startLine: number, startOffset: number, endLine: number, endOffset: number }; +*/ +/*:: export type FlowLocation = { msg: string, textRange: TextRange }; +*/ +/*:: export type IssueComment = { author?: string, authorActive?: boolean, @@ -42,7 +47,9 @@ export type IssueComment = { markdown: string, updatable: boolean }; +*/ +/*:: export type Issue = { actions: Array<string>, assignee?: string, @@ -81,3 +88,4 @@ export type Issue = { transitions?: Array<string>, type: string }; +*/ diff --git a/server/sonar-web/src/main/js/components/measure/Measure.js b/server/sonar-web/src/main/js/components/measure/Measure.js index 3ce72c83ee0..513d54e5699 100644 --- a/server/sonar-web/src/main/js/components/measure/Measure.js +++ b/server/sonar-web/src/main/js/components/measure/Measure.js @@ -24,15 +24,15 @@ import Level from '../ui/Level'; import Tooltips from '../controls/Tooltip'; import { formatMeasure, isDiffMetric } from '../../helpers/measures'; import { formatLeak, getRatingTooltip } from './utils'; -import type { MeasureEnhanced } from './types'; +/*:: import type { MeasureEnhanced } from './types'; */ -type Props = { +/*:: type Props = { className?: string, decimals?: ?number, measure: MeasureEnhanced -}; +}; */ -export default function Measure({ className, decimals, measure }: Props) { +export default function Measure({ className, decimals, measure } /*: Props */) { const metric = measure.metric; if (metric.type === 'LEVEL') { diff --git a/server/sonar-web/src/main/js/components/measure/types.js b/server/sonar-web/src/main/js/components/measure/types.js index 1883833c97a..5c3cdbef56f 100644 --- a/server/sonar-web/src/main/js/components/measure/types.js +++ b/server/sonar-web/src/main/js/components/measure/types.js @@ -18,16 +18,16 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // @flow -import type { Metric } from '../../store/metrics/actions'; +/*:: import type { Metric } from '../../store/metrics/actions'; */ -type MeasureIntern = { +/*:: type MeasureIntern = { value?: string, periods?: Array<{ index: number, value: string }> -}; +}; */ -export type Measure = MeasureIntern & { metric: string }; +/*:: export type Measure = MeasureIntern & { metric: string }; */ -export type MeasureEnhanced = MeasureIntern & { metric: Metric, leak?: ?string }; +/*:: export type MeasureEnhanced = MeasureIntern & { metric: Metric, leak?: ?string }; */ diff --git a/server/sonar-web/src/main/js/components/measure/utils.js b/server/sonar-web/src/main/js/components/measure/utils.js index 92fefd654ce..62fef4790d0 100644 --- a/server/sonar-web/src/main/js/components/measure/utils.js +++ b/server/sonar-web/src/main/js/components/measure/utils.js @@ -24,22 +24,24 @@ import { getRatingTooltip as nextGetRatingTooltip, isDiffMetric } from '../../helpers/measures'; -import type { Measure, MeasureEnhanced } from './types'; -import type { Metric } from '../../store/metrics/actions'; +/*:: import type { Measure, MeasureEnhanced } from './types'; */ +/*:: import type { Metric } from '../../store/metrics/actions'; */ const KNOWN_RATINGS = ['sqale_rating', 'reliability_rating', 'security_rating']; -export const enhanceMeasure = ( - measure: Measure, - metrics: { [string]: Metric } -): MeasureEnhanced => ({ - value: measure.value, - periods: measure.periods, - metric: metrics[measure.metric], - leak: getLeakValue(measure) -}); +export function enhanceMeasure( + measure /*: Measure */, + metrics /*: { [string]: Metric } */ +) /*: MeasureEnhanced */ { + return { + value: measure.value, + periods: measure.periods, + metric: metrics[measure.metric], + leak: getLeakValue(measure) + }; +} -export function formatLeak(value: ?string, metric: Metric, options: Object) { +export function formatLeak(value /*: ?string*/, metric /*: Metric*/, options /*: Object*/) { if (isDiffMetric(metric.key)) { return formatMeasure(value, metric.type, options); } else { @@ -47,7 +49,7 @@ export function formatLeak(value: ?string, metric: Metric, options: Object) { } } -export function getLeakValue(measure: ?Measure): ?string { +export function getLeakValue(measure /*: ?Measure*/) /*: ?string*/ { if (!measure || !measure.periods) { return null; } @@ -55,7 +57,7 @@ export function getLeakValue(measure: ?Measure): ?string { return period ? period.value : null; } -export function getRatingTooltip(metricKey: string, value: ?string) { +export function getRatingTooltip(metricKey /*: string */, value /*: ?string*/) { const finalMetricKey = isDiffMetric(metricKey) ? metricKey.substr(4) : metricKey; if (KNOWN_RATINGS.includes(finalMetricKey)) { return nextGetRatingTooltip(finalMetricKey, value); diff --git a/server/sonar-web/src/main/js/components/nav/ContextNavBar.js b/server/sonar-web/src/main/js/components/nav/ContextNavBar.js index 003a0614810..20690b55881 100644 --- a/server/sonar-web/src/main/js/components/nav/ContextNavBar.js +++ b/server/sonar-web/src/main/js/components/nav/ContextNavBar.js @@ -23,11 +23,13 @@ import classNames from 'classnames'; import NavBar from './NavBar'; import './ContextNavBar.css'; +/*:: type Props = { className?: string, height: number }; +*/ -export default function ContextNavBar({ className, ...other }: Props) { +export default function ContextNavBar({ className, ...other } /*: Props */) { return <NavBar className={classNames('navbar-context', className)} {...other} />; } diff --git a/server/sonar-web/src/main/js/components/nav/NavBar.js b/server/sonar-web/src/main/js/components/nav/NavBar.js index beb4466edbc..180ca0df9e5 100644 --- a/server/sonar-web/src/main/js/components/nav/NavBar.js +++ b/server/sonar-web/src/main/js/components/nav/NavBar.js @@ -22,13 +22,15 @@ import React from 'react'; import classNames from 'classnames'; import './NavBar.css'; +/*:: type Props = { children?: React.Element<*>, className?: string, height: number }; +*/ -export default function NavBar({ children, className, height, ...other }: Props) { +export default function NavBar({ children, className, height, ...other } /*: Props */) { return ( <nav {...other} className={classNames('navbar', className)} style={{ height }}> <div className="navbar-inner" style={{ height }}> diff --git a/server/sonar-web/src/main/js/components/nav/NavBarTabs.js b/server/sonar-web/src/main/js/components/nav/NavBarTabs.js index f1d8e296278..4f03f4c7b9a 100644 --- a/server/sonar-web/src/main/js/components/nav/NavBarTabs.js +++ b/server/sonar-web/src/main/js/components/nav/NavBarTabs.js @@ -22,12 +22,14 @@ import React from 'react'; import classNames from 'classnames'; import './NavBarTabs.css'; +/*:: type Props = { children?: React.Element<*>, className?: string }; +*/ -export default function NavBarTabs({ children, className, ...other }: Props) { +export default function NavBarTabs({ children, className, ...other } /*: Props */) { return ( <ul {...other} className={classNames('navbar-tabs', className)}> {children} diff --git a/server/sonar-web/src/main/js/components/shared/Organization.js b/server/sonar-web/src/main/js/components/shared/Organization.js index aae52f11127..3debbb2a878 100644 --- a/server/sonar-web/src/main/js/components/shared/Organization.js +++ b/server/sonar-web/src/main/js/components/shared/Organization.js @@ -23,10 +23,13 @@ import { connect } from 'react-redux'; import { getOrganizationByKey, areThereCustomOrganizations } from '../../store/rootReducer'; import OrganizationLink from '../ui/OrganizationLink'; +/*:: type OwnProps = { organizationKey: string }; +*/ +/*:: type Props = { link?: boolean, linkClassName?: string, @@ -34,9 +37,10 @@ type Props = { organization: { key: string, name: string } | null, shouldBeDisplayed: boolean }; +*/ class Organization extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { link: true @@ -62,7 +66,7 @@ class Organization extends React.PureComponent { } } -const mapStateToProps = (state, ownProps: OwnProps) => ({ +const mapStateToProps = (state, ownProps /*: OwnProps */) => ({ organization: getOrganizationByKey(state, ownProps.organizationKey), shouldBeDisplayed: areThereCustomOrganizations(state) }); diff --git a/server/sonar-web/src/main/js/components/shared/QualifierIcon.js b/server/sonar-web/src/main/js/components/shared/QualifierIcon.js index 82ed9f7e5e1..e00dc8ab41f 100644 --- a/server/sonar-web/src/main/js/components/shared/QualifierIcon.js +++ b/server/sonar-web/src/main/js/components/shared/QualifierIcon.js @@ -20,13 +20,15 @@ import React from 'react'; import classNames from 'classnames'; +/*:: type Props = { className?: string, qualifier: ?string }; +*/ export default class QualifierIcon extends React.PureComponent { - props: Props; + /*:: props: Props; */ render() { if (!this.props.qualifier) { diff --git a/server/sonar-web/src/main/js/components/shared/SeverityHelper.js b/server/sonar-web/src/main/js/components/shared/SeverityHelper.js index 2ac4e149f1e..6b9171e40c8 100644 --- a/server/sonar-web/src/main/js/components/shared/SeverityHelper.js +++ b/server/sonar-web/src/main/js/components/shared/SeverityHelper.js @@ -22,7 +22,7 @@ import React from 'react'; import SeverityIcon from './SeverityIcon'; import { translate } from '../../helpers/l10n'; -export default function SeverityHelper(props: { severity: ?string, className?: string }) { +export default function SeverityHelper(props /*: { severity: ?string, className?: string } */) { const { severity } = props; if (!severity) { return null; diff --git a/server/sonar-web/src/main/js/components/shared/SeverityIcon.js b/server/sonar-web/src/main/js/components/shared/SeverityIcon.js index aea18812a32..2b254650b1a 100644 --- a/server/sonar-web/src/main/js/components/shared/SeverityIcon.js +++ b/server/sonar-web/src/main/js/components/shared/SeverityIcon.js @@ -21,7 +21,7 @@ import React from 'react'; import classNames from 'classnames'; -export default function SeverityIcon(props: { severity: ?string, className?: string }) { +export default function SeverityIcon(props /*: { severity: ?string, className?: string } */) { if (!props.severity) { return null; } diff --git a/server/sonar-web/src/main/js/components/shared/StatusHelper.js b/server/sonar-web/src/main/js/components/shared/StatusHelper.js index a355348f720..b6e55f388ec 100644 --- a/server/sonar-web/src/main/js/components/shared/StatusHelper.js +++ b/server/sonar-web/src/main/js/components/shared/StatusHelper.js @@ -22,11 +22,13 @@ import React from 'react'; import StatusIcon from './StatusIcon'; import { translate } from '../../helpers/l10n'; -export default function StatusHelper(props: { +export default function StatusHelper( + props /*: { resolution?: string, status: string, className?: string -}) { +} */ +) { const resolution = props.resolution != null && ` (${translate('issue.resolution', props.resolution)})`; return ( diff --git a/server/sonar-web/src/main/js/components/shared/StatusIcon.js b/server/sonar-web/src/main/js/components/shared/StatusIcon.js index b98b4cccfd3..60403fbac42 100644 --- a/server/sonar-web/src/main/js/components/shared/StatusIcon.js +++ b/server/sonar-web/src/main/js/components/shared/StatusIcon.js @@ -21,7 +21,7 @@ import React from 'react'; import classNames from 'classnames'; -export default function StatusIcon(props: { status: string, className?: string }) { +export default function StatusIcon(props /*: { status: string, className?: string } */) { const className = classNames('icon-status-' + props.status.toLowerCase(), props.className); return <i className={className} />; } diff --git a/server/sonar-web/src/main/js/components/shared/TypeHelper.js b/server/sonar-web/src/main/js/components/shared/TypeHelper.js index 030337e5242..e734f22a8d5 100644 --- a/server/sonar-web/src/main/js/components/shared/TypeHelper.js +++ b/server/sonar-web/src/main/js/components/shared/TypeHelper.js @@ -22,11 +22,13 @@ import React from 'react'; import IssueTypeIcon from '../ui/IssueTypeIcon'; import { translate } from '../../helpers/l10n'; +/*:: type Props = { type: string }; +*/ -const TypeHelper = (props: Props) => +const TypeHelper = (props /*: Props */) => <span> <IssueTypeIcon className="little-spacer-right" query={props.type} /> {translate('issue.type', props.type)} diff --git a/server/sonar-web/src/main/js/components/shared/WithStore.js b/server/sonar-web/src/main/js/components/shared/WithStore.js index c406d118aff..73b18dc67ea 100644 --- a/server/sonar-web/src/main/js/components/shared/WithStore.js +++ b/server/sonar-web/src/main/js/components/shared/WithStore.js @@ -22,19 +22,22 @@ import React from 'react'; import PropTypes from 'prop-types'; import getStore from '../../app/utils/getStore'; +/*:: type Props = { children: React.Element<*> }; +*/ export default class WithStore extends React.PureComponent { - props: Props; - store: {}; + /*:: props: Props; */ + /*:: store: {}; +*/ static childContextTypes = { store: PropTypes.object }; - constructor(props: Props) { + constructor(props /*: Props */) { super(props); this.store = getStore(); } diff --git a/server/sonar-web/src/main/js/components/tags/TagsList.js b/server/sonar-web/src/main/js/components/tags/TagsList.js index 2c568cee8f6..36cd65af6d4 100644 --- a/server/sonar-web/src/main/js/components/tags/TagsList.js +++ b/server/sonar-web/src/main/js/components/tags/TagsList.js @@ -22,14 +22,16 @@ import React from 'react'; import classNames from 'classnames'; import './TagsList.css'; +/*:: type Props = { tags: Array<string>, allowUpdate: boolean, customClass?: string }; +*/ export default class TagsList extends React.PureComponent { - props: Props; + /*:: props: Props; */ static defaultProps = { allowUpdate: false diff --git a/server/sonar-web/src/main/js/components/tags/TagsSelector.js b/server/sonar-web/src/main/js/components/tags/TagsSelector.js index 2525ccd5733..979f6e3aeef 100644 --- a/server/sonar-web/src/main/js/components/tags/TagsSelector.js +++ b/server/sonar-web/src/main/js/components/tags/TagsSelector.js @@ -23,6 +23,7 @@ import BubblePopup from '../common/BubblePopup'; import MultiSelect from '../common/MultiSelect'; import './TagsList.css'; +/*:: type Props = { position: {}, tags: Array<string>, @@ -32,12 +33,14 @@ type Props = { onSelect: string => void, onUnselect: string => void }; +*/ export default class TagsSelector extends React.PureComponent { - validateTag: string => string; - props: Props; + /*:: validateTag: string => string; */ - validateTag(value: string) { + /*:: props: Props; */ + + validateTag(value /*: string */) { // Allow only a-z, 0-9, '+', '-', '#', '.' return value.toLowerCase().replace(/[^a-z0-9\+\-#.]/gi, ''); } diff --git a/server/sonar-web/src/main/js/components/ui/CoverageRating.js b/server/sonar-web/src/main/js/components/ui/CoverageRating.js index 6a88cc2aa63..6fe1c7cc09e 100644 --- a/server/sonar-web/src/main/js/components/ui/CoverageRating.js +++ b/server/sonar-web/src/main/js/components/ui/CoverageRating.js @@ -36,11 +36,12 @@ const SIZE_TO_THICKNESS_MAPPING = { }; export default class CoverageRating extends React.PureComponent { - props: { + /*:: props: { value: number | string, size?: 'small' | 'normal' | 'big' | 'huge', muted?: boolean }; +*/ static defaultProps = { size: 'normal', diff --git a/server/sonar-web/src/main/js/components/ui/DuplicationsRating.js b/server/sonar-web/src/main/js/components/ui/DuplicationsRating.js index 43bed152558..628adac1d1b 100644 --- a/server/sonar-web/src/main/js/components/ui/DuplicationsRating.js +++ b/server/sonar-web/src/main/js/components/ui/DuplicationsRating.js @@ -24,11 +24,12 @@ import { inRange } from 'lodash'; import './DuplicationsRating.css'; export default class DuplicationsRating extends React.PureComponent { - props: { + /*:: props: { value: number, size?: 'small' | 'normal' | 'big' | 'huge', muted?: boolean }; +*/ static defaultProps = { small: false, diff --git a/server/sonar-web/src/main/js/components/ui/FormattedDate.js b/server/sonar-web/src/main/js/components/ui/FormattedDate.js index 04b0abc49ae..f25d00307f3 100644 --- a/server/sonar-web/src/main/js/components/ui/FormattedDate.js +++ b/server/sonar-web/src/main/js/components/ui/FormattedDate.js @@ -22,12 +22,13 @@ import React from 'react'; import moment from 'moment'; export default class FormattedDate extends React.PureComponent { - props: { + /*:: props: { className?: string, date: string | number, format?: string, tooltipFormat?: string }; +*/ static defaultProps = { format: 'LLL' diff --git a/server/sonar-web/src/main/js/components/ui/IssueTypeIcon.js b/server/sonar-web/src/main/js/components/ui/IssueTypeIcon.js index 8fce48ba236..83feca0536e 100644 --- a/server/sonar-web/src/main/js/components/ui/IssueTypeIcon.js +++ b/server/sonar-web/src/main/js/components/ui/IssueTypeIcon.js @@ -24,10 +24,11 @@ import VulnerabilityIcon from '../icons-components/VulnerabilityIcon'; import CodeSmellIcon from '../icons-components/CodeSmellIcon'; export default class IssueTypeIcon extends React.PureComponent { - props: { + /*:: props: { className?: string, query: string }; +*/ renderIcon() { switch (this.props.query.toLowerCase()) { diff --git a/server/sonar-web/src/main/js/components/ui/OrganizationLink.js b/server/sonar-web/src/main/js/components/ui/OrganizationLink.js index 1126da0a70c..9251d1ae863 100644 --- a/server/sonar-web/src/main/js/components/ui/OrganizationLink.js +++ b/server/sonar-web/src/main/js/components/ui/OrganizationLink.js @@ -21,12 +21,14 @@ import React from 'react'; import { Link } from 'react-router'; -export default function OrganizationLink(props: { +export default function OrganizationLink( + props /*: { children?: React.Element<*>, organization: { key: string } -}) { +} */ +) { const { children, organization, ...other } = props; return ( diff --git a/server/sonar-web/src/main/js/components/ui/SizeRating.js b/server/sonar-web/src/main/js/components/ui/SizeRating.js index 545db164fc2..c4fd00c2bb6 100644 --- a/server/sonar-web/src/main/js/components/ui/SizeRating.js +++ b/server/sonar-web/src/main/js/components/ui/SizeRating.js @@ -24,11 +24,12 @@ import { inRange } from 'lodash'; import './SizeRating.css'; export default class SizeRating extends React.PureComponent { - props: { + /*:: props: { value: number, small?: boolean, muted?: boolean }; +*/ static defaultProps = { small: false, diff --git a/server/sonar-web/src/main/js/components/workspace/main.js b/server/sonar-web/src/main/js/components/workspace/main.js index bb834be5a3a..cfc93f499b5 100644 --- a/server/sonar-web/src/main/js/components/workspace/main.js +++ b/server/sonar-web/src/main/js/components/workspace/main.js @@ -78,7 +78,7 @@ Workspace.prototype = { return this.open({ ...options, __type__: 'component' }); }, - openRule(options: { key: string, organization: string }) { + openRule(options /*: { key: string, organization: string } */) { return this.open({ ...options, __type__: 'rule' }); }, diff --git a/server/sonar-web/src/main/js/helpers/cookies.js b/server/sonar-web/src/main/js/helpers/cookies.js index ad2cef2a945..8255c5924da 100644 --- a/server/sonar-web/src/main/js/helpers/cookies.js +++ b/server/sonar-web/src/main/js/helpers/cookies.js @@ -20,7 +20,7 @@ // @flow let cookies; -export function getCookie(name: string) { +export function getCookie(name /*: string */) { if (cookies) { return cookies[name]; } diff --git a/server/sonar-web/src/main/js/helpers/csv.js b/server/sonar-web/src/main/js/helpers/csv.js index c07e0c868d2..cc49b2f3ec0 100644 --- a/server/sonar-web/src/main/js/helpers/csv.js +++ b/server/sonar-web/src/main/js/helpers/csv.js @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // @flow -export function csvEscape(value: string): string { +export function csvEscape(value /*: string */) /*: string */ { const escaped = value.replace(/"/g, '\\"'); return `"${escaped}"`; } diff --git a/server/sonar-web/src/main/js/helpers/issues.js b/server/sonar-web/src/main/js/helpers/issues.js index 92603e52e17..a03d7ac807f 100644 --- a/server/sonar-web/src/main/js/helpers/issues.js +++ b/server/sonar-web/src/main/js/helpers/issues.js @@ -20,23 +20,30 @@ // @flow import { flatten, sortBy } from 'lodash'; import { SEVERITIES } from './constants'; -import type { Issue, FlowLocation } from '../components/issue/types'; +/*:: import type { Issue, FlowLocation } from '../components/issue/types'; */ +/*:: type TextRange = { startLine: number, endLine: number, startOffset: number, endOffset: number }; +*/ +/*:: type Comment = { login: string }; +*/ +/*:: type User = { login: string }; +*/ +/*:: type RawIssue = { assignee?: string, author: string, @@ -53,16 +60,18 @@ type RawIssue = { subProject?: string, textRange?: TextRange }; +*/ -export const sortBySeverity = (issues: Array<*>) => - sortBy(issues, issue => SEVERITIES.indexOf(issue.severity)); +export function sortBySeverity(issues /*: Array<*> */) { + return sortBy(issues, issue => SEVERITIES.indexOf(issue.severity)); +} -const injectRelational = ( - issue: RawIssue | Comment, - source?: Array<*>, - baseField: string, - lookupField: string -) => { +function injectRelational( + issue /*: RawIssue | Comment */, + source /*: ?Array<*> */, + baseField /*: string */, + lookupField /*: string */ +) { const newFields = {}; const baseValue = issue[baseField]; if (baseValue != null && source != null) { @@ -75,9 +84,9 @@ const injectRelational = ( } } return newFields; -}; +} -const injectCommentsRelational = (issue: RawIssue, users?: Array<User>) => { +function injectCommentsRelational(issue /*: RawIssue */, users /*: ?Array<User> */) { if (!issue.comments) { return {}; } @@ -89,13 +98,13 @@ const injectCommentsRelational = (issue: RawIssue, users?: Array<User>) => { }; }); return { comments }; -}; +} -const prepareClosed = (issue: RawIssue) => { +function prepareClosed(issue /*: RawIssue */) { return issue.status === 'CLOSED' ? { flows: undefined } : {}; -}; +} -const ensureTextRange = (issue: RawIssue) => { +function ensureTextRange(issue /*: RawIssue */) { return issue.line && !issue.textRange ? { textRange: { @@ -106,18 +115,18 @@ const ensureTextRange = (issue: RawIssue) => { } } : {}; -}; +} -const reverseLocations = (locations: Array<*>) => { +function reverseLocations(locations /*: Array<*> */) { const x = [...locations]; x.reverse(); return x; -}; +} -const splitFlows = ( - issue: RawIssue +function splitFlows( + issue /*: RawIssue */ // $FlowFixMe textRange is not null -): { secondaryLocations: Array<FlowLocation>, flows: Array<Array<FlowLocation>> } => { +) /*: { secondaryLocations: Array<FlowLocation>, flows: Array<Array<FlowLocation>> } */ { const parsedFlows = (issue.flows || []) .filter(flow => flow.locations != null) // $FlowFixMe flow.locations is not null @@ -128,14 +137,14 @@ const splitFlows = ( return onlySecondaryLocations ? { secondaryLocations: flatten(parsedFlows), flows: [] } : { secondaryLocations: [], flows: parsedFlows.map(reverseLocations) }; -}; +} -export const parseIssueFromResponse = ( - issue: Object, - components?: Array<*>, - users?: Array<*>, - rules?: Array<*> -): Issue => { +export function parseIssueFromResponse( + issue /*: Object */, + components /*: ?Array<*> */, + users /*: ?Array<*> */, + rules /*: ?Array<*> */ +) /*: Issue */ { const { secondaryLocations, flows } = splitFlows(issue); return { ...issue, @@ -150,4 +159,4 @@ export const parseIssueFromResponse = ( secondaryLocations, flows }; -}; +} diff --git a/server/sonar-web/src/main/js/helpers/l10n.js b/server/sonar-web/src/main/js/helpers/l10n.js index 706fad82906..1f5ebda6796 100644 --- a/server/sonar-web/src/main/js/helpers/l10n.js +++ b/server/sonar-web/src/main/js/helpers/l10n.js @@ -23,12 +23,15 @@ import { getJSON } from './request'; let messages = {}; -export function translate(...keys: string[]) { +export function translate(...keys /*: string[] */) { const messageKey = keys.join('.'); return messages[messageKey] || messageKey; } -export function translateWithParameters(messageKey: string, ...parameters: Array<string | number>) { +export function translateWithParameters( + messageKey /*: string */, + ...parameters /*: Array<string | number> */ +) { const message = messages[messageKey]; if (message) { return parameters @@ -39,12 +42,12 @@ export function translateWithParameters(messageKey: string, ...parameters: Array } } -export function hasMessage(...keys: string[]) { +export function hasMessage(...keys /*: string[] */) { const messageKey = keys.join('.'); return messages[messageKey] != null; } -export function configureMoment(language?: string) { +export function configureMoment(language /*: ?string */) { moment.locale(language || getPreferredLanguage()); } @@ -112,7 +115,7 @@ export function requestMessages() { ); } -export function resetBundle(bundle: Object) { +export function resetBundle(bundle /*: Object */) { messages = bundle; } @@ -122,19 +125,19 @@ export function installGlobal() { window.requestMessages = requestMessages; } -export function getLocalizedDashboardName(baseName: string) { +export function getLocalizedDashboardName(baseName /*: string */) { const l10nKey = `dashboard.${baseName}.name`; const l10nLabel = translate(l10nKey); return l10nLabel !== l10nKey ? l10nLabel : baseName; } -export function getLocalizedMetricName(metric: { key: string, name: string }) { +export function getLocalizedMetricName(metric /*: { key: string, name: string } */) { const bundleKey = `metric.${metric.key}.name`; const fromBundle = translate(bundleKey); return fromBundle !== bundleKey ? fromBundle : metric.name; } -export function getLocalizedMetricDomain(domainName: string) { +export function getLocalizedMetricDomain(domainName /*: string */) { const bundleKey = `metric_domain.${domainName}`; const fromBundle = translate(bundleKey); return fromBundle !== bundleKey ? fromBundle : domainName; diff --git a/server/sonar-web/src/main/js/helpers/query.js b/server/sonar-web/src/main/js/helpers/query.js index a8be9843cfc..f7c0f2b6a9c 100644 --- a/server/sonar-web/src/main/js/helpers/query.js +++ b/server/sonar-web/src/main/js/helpers/query.js @@ -17,12 +17,15 @@ * 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 { isNil, omitBy } from 'lodash'; import moment from 'moment'; -export type RawQuery = { [string]: string }; +/*:: +export type RawQuery = { [string]: any }; +*/ -const arraysEqual = <T>(a: Array<T>, b: Array<T>) => { +function arraysEqual(a, b) { if (a.length !== b.length) { return false; } @@ -32,9 +35,9 @@ const arraysEqual = <T>(a: Array<T>, b: Array<T>) => { } } return true; -}; +} -export const queriesEqual = <T>(a: T, b: T): boolean => { +export function queriesEqual(a /*: Object */, b /*: Object */) /*: boolean */ { const keysA = Object.keys(a); const keysB = Object.keys(b); @@ -48,35 +51,48 @@ export const queriesEqual = <T>(a: T, b: T): boolean => { ? arraysEqual(a[key], b[key]) : a[key] === b[key] ); -}; +} -export const cleanQuery = (query: { [string]: ?string }): RawQuery => omitBy(query, isNil); +export function cleanQuery(query /*: { [string]: ?string } */) /*: RawQuery */ { + return omitBy(query, isNil); +} -export const parseAsBoolean = (value: ?string, defaultValue: boolean = true): boolean => - value === 'false' ? false : value === 'true' ? true : defaultValue; +export function parseAsBoolean( + value /*: ?string */, + defaultValue /*: boolean */ = true +) /*: boolean */ { + return value === 'false' ? false : value === 'true' ? true : defaultValue; +} -export const parseAsDate = (value: ?string): ?Date => { +export function parseAsDate(value /*: ?string */) /*: Date | void */ { const date = moment(value); if (value && date) { return date.toDate(); } -}; +} -export const parseAsFacetMode = (facetMode: string) => - facetMode === 'debt' || facetMode === 'effort' ? 'effort' : 'count'; +export function parseAsFacetMode(facetMode /*: string */) { + return facetMode === 'debt' || facetMode === 'effort' ? 'effort' : 'count'; +} -export const parseAsString = (value: ?string): string => value || ''; +export function parseAsString(value /*: ?string */) /*: string */ { + return value || ''; +} -export const parseAsArray = <T>(value: ?string, itemParser: string => T): Array<T> => - value ? value.split(',').map(itemParser) : []; +export function parseAsArray(value /*: ?string */, itemParser /*: string => * */) /*: Array<*> */ { + return value ? value.split(',').map(itemParser) : []; +} -export const serializeDate = (value: ?Date): ?string => { +export function serializeDate(value /*: ?Date */) /*: string | void */ { if (value != null && value.toISOString) { return moment(value).format('YYYY-MM-DDTHH:mm:ssZZ'); } -}; +} -export const serializeString = (value: string): ?string => value || undefined; +export function serializeString(value /*: string */) /*: ?string */ { + return value || undefined; +} -export const serializeStringArray = (value: ?Array<string>): ?string => - value && value.length ? value.join() : undefined; +export function serializeStringArray(value /*: ?Array<string> */) /*: ?string */ { + return value && value.length ? value.join() : undefined; +} diff --git a/server/sonar-web/src/main/js/helpers/request.js b/server/sonar-web/src/main/js/helpers/request.js index 941532e4b57..f49a5881bdc 100644 --- a/server/sonar-web/src/main/js/helpers/request.js +++ b/server/sonar-web/src/main/js/helpers/request.js @@ -22,16 +22,18 @@ import { stringify } from 'querystring'; import { omitBy, isNil } from 'lodash'; import { getCookie } from './cookies'; +/*:: type Response = { json: () => Promise<Object>, status: number }; +*/ -export function getCSRFTokenName(): string { +export function getCSRFTokenName() /*: string */ { return 'X-XSRF-TOKEN'; } -export function getCSRFTokenValue(): string { +export function getCSRFTokenValue() /*: string */ { const cookieName = 'XSRF-TOKEN'; const cookieValue = getCookie(cookieName); if (!cookieValue) { @@ -44,24 +46,24 @@ export function getCSRFTokenValue(): string { * Return an object containing a special http request header used to prevent CSRF attacks. * @returns {Object} */ -export function getCSRFToken(): Object { +export function getCSRFToken() /*: Object */ { // Fetch API in Edge doesn't work with empty header, // so we ensure non-empty value const value = getCSRFTokenValue(); return value ? { [getCSRFTokenName()]: value } : {}; } -export function omitNil(obj: Object): Object { +export function omitNil(obj /*: Object */) /*: Object */ { return omitBy(obj, isNil); } /** * Default options for any request */ -const DEFAULT_OPTIONS: { +const DEFAULT_OPTIONS /*: { credentials: string, method: string -} = { +} */ = { method: 'GET', credentials: 'same-origin' }; @@ -69,9 +71,9 @@ const DEFAULT_OPTIONS: { /** * Default request headers */ -const DEFAULT_HEADERS: { +const DEFAULT_HEADERS /*: { 'Accept': string -} = { +} */ = { Accept: 'application/json' }; @@ -79,21 +81,19 @@ const DEFAULT_HEADERS: { * Request */ class Request { - url: string; - options: { - method?: string - }; - headers: Object; - data: ?Object; - - constructor(url: string): void { + /*:: url: string; */ + /*:: options: { method?: string }; */ + /*:: headers: Object; */ + /*:: data: ?Object; */ + + constructor(url /*: string */) /*: void */ { this.url = url; this.options = {}; this.headers = {}; } submit() { - let url: string = this.url; + let url /*: string */ = this.url; const options = { ...DEFAULT_OPTIONS, ...this.options }; const customHeaders = {}; @@ -122,17 +122,17 @@ class Request { return window.fetch(window.baseUrl + url, options); } - setMethod(method: string): Request { + setMethod(method /*: string */) /*: Request */ { this.options.method = method; return this; } - setData(data?: Object): Request { + setData(data /*: ?Object */) /*: Request */ { this.data = data; return this; } - setHeader(name: string, value: string): Request { + setHeader(name /*: string */, value /*: string */) /*: Request */ { this.headers[name] = value; return this; } @@ -143,7 +143,7 @@ class Request { * @param {string} url * @returns {Request} */ -export function request(url: string): Request { +export function request(url /*: string */) /*: Request */ { return new Request(url); } @@ -152,7 +152,7 @@ export function request(url: string): Request { * @param response * @returns {*} */ -export function checkStatus(response: Response): Promise<Object> { +export function checkStatus(response /*: Response */) /*: Promise<Object> */ { return new Promise((resolve, reject) => { if (response.status === 401) { // workaround cyclic dependencies @@ -172,7 +172,7 @@ export function checkStatus(response: Response): Promise<Object> { * @param response * @returns {object} */ -export function parseJSON(response: Response): Promise<Object> { +export function parseJSON(response /*: Response */) /*: Promise<Object> */ { return response.json(); } @@ -181,7 +181,7 @@ export function parseJSON(response: Response): Promise<Object> { * @param url * @param data */ -export function getJSON(url: string, data?: Object): Promise<Object> { +export function getJSON(url /*: string */, data /*: ?Object */) /*: Promise<Object> */ { return request(url).setData(data).submit().then(checkStatus).then(parseJSON); } @@ -190,7 +190,7 @@ export function getJSON(url: string, data?: Object): Promise<Object> { * @param url * @param data */ -export function postJSON(url: string, data?: Object): Promise<Object> { +export function postJSON(url /*: string */, data /*: ?Object */) /*: Promise<Object> */ { return request(url).setMethod('POST').setData(data).submit().then(checkStatus).then(parseJSON); } @@ -199,7 +199,7 @@ export function postJSON(url: string, data?: Object): Promise<Object> { * @param url * @param data */ -export function post(url: string, data?: Object): Promise<void> { +export function post(url /*: string */, data /*: ?Object */) /*: Promise<void> */ { return request(url).setMethod('POST').setData(data).submit().then(checkStatus); } @@ -208,7 +208,7 @@ export function post(url: string, data?: Object): Promise<void> { * @param url * @param data */ -export function requestDelete(url: string, data?: Object): Promise<Object> { +export function requestDelete(url /*: string */, data /*: ?Object */) /*: Promise<Object> */ { return request(url).setMethod('DELETE').setData(data).submit().then(checkStatus); } @@ -217,6 +217,6 @@ export function requestDelete(url: string, data?: Object): Promise<Object> { * @param response * @returns {Promise} */ -export function delay(response: *): Promise<*> { +export function delay(response /*: * */) /*: Promise<*> */ { return new Promise(resolve => setTimeout(() => resolve(response), 1200)); } diff --git a/server/sonar-web/src/main/js/helpers/scrolling.js b/server/sonar-web/src/main/js/helpers/scrolling.js index 2530db103eb..7e1fd53c926 100644 --- a/server/sonar-web/src/main/js/helpers/scrolling.js +++ b/server/sonar-web/src/main/js/helpers/scrolling.js @@ -24,19 +24,19 @@ const SCROLLING_DURATION = 100; const SCROLLING_INTERVAL = 10; const SCROLLING_STEPS = SCROLLING_DURATION / SCROLLING_INTERVAL; -const getScrollPosition = (element: HTMLElement): number => { +function getScrollPosition(element /*: HTMLElement */) /*: number */ { return element === window ? window.scrollY : element.scrollTop; -}; +} -const scrollElement = (element: HTMLElement, position: number) => { +function scrollElement(element /*: HTMLElement */, position /*: number */) { if (element === window) { window.scrollTo(0, position); } else { element.scrollTop = position; } -}; +} -let smoothScrollTop = (y: number, parent) => { +let smoothScrollTop = (y /*: number */, parent) => { let scrollTop = getScrollPosition(parent); const scrollingDown = y > scrollTop; const step = Math.ceil(Math.abs(y - scrollTop) / SCROLLING_STEPS); @@ -62,13 +62,13 @@ let smoothScrollTop = (y: number, parent) => { smoothScrollTop = debounce(smoothScrollTop, SCROLLING_DURATION, { leading: true }); export const scrollToElement = ( - element: HTMLElement, - options: { + element /*: HTMLElement */, + options /*: { topOffset?: number, bottomOffset?: number, parent?: HTMLElement, smooth?: boolean - } + } */ ) => { const opts = { topOffset: 0, bottomOffset: 0, parent: window, smooth: true, ...options }; const { parent } = opts; @@ -77,7 +77,7 @@ export const scrollToElement = ( const scrollTop = getScrollPosition(parent); - const height: number = + const height /*: number */ = parent === window ? window.innerHeight : parent.getBoundingClientRect().height; const parentTop = parent === window ? 0 : parent.getBoundingClientRect().top; diff --git a/server/sonar-web/src/main/js/helpers/storage.js b/server/sonar-web/src/main/js/helpers/storage.js index 763aa3d64b1..404daf59a67 100644 --- a/server/sonar-web/src/main/js/helpers/storage.js +++ b/server/sonar-web/src/main/js/helpers/storage.js @@ -29,7 +29,7 @@ const PROJECTS_SORT = 'sonarqube.projects.sort'; const PROJECT_ACTIVITY_GRAPH = 'sonarqube.project_activity.graph'; const PROJECT_ACTIVITY_GRAPH_CUSTOM = 'sonarqube.project_activity.graph.custom'; -const save = (key: string, value: ?string) => { +const save = (key /*: string */, value /*: ?string */) => { try { if (value) { window.localStorage.setItem(key, value); @@ -42,35 +42,54 @@ const save = (key: string, value: ?string) => { } }; -export const saveFavorite = () => save(PROJECTS_DEFAULT_FILTER, PROJECTS_FAVORITE); -export const isFavoriteSet = (): boolean => { +export function saveFavorite() { + save(PROJECTS_DEFAULT_FILTER, PROJECTS_FAVORITE); +} +export function isFavoriteSet() /*: boolean */ { const setting = window.localStorage.getItem(PROJECTS_DEFAULT_FILTER); return setting === PROJECTS_FAVORITE; -}; +} -export const saveAll = () => save(PROJECTS_DEFAULT_FILTER, PROJECTS_ALL); -export const isAllSet = (): boolean => { +export function saveAll() { + save(PROJECTS_DEFAULT_FILTER, PROJECTS_ALL); +} +export function isAllSet() /*: boolean */ { const setting = window.localStorage.getItem(PROJECTS_DEFAULT_FILTER); return setting === PROJECTS_ALL; -}; +} -export const saveView = (view: ?string) => save(PROJECTS_VIEW, view); -export const getView = () => window.localStorage.getItem(PROJECTS_VIEW); +export function saveView(view /*: ?string */) { + save(PROJECTS_VIEW, view); +} +export function getView() { + return window.localStorage.getItem(PROJECTS_VIEW); +} -export const saveVisualization = (visualization: ?string) => +export function saveVisualization(visualization /*: ?string */) { save(PROJECTS_VISUALIZATION, visualization); -export const getVisualization = () => window.localStorage.getItem(PROJECTS_VISUALIZATION); +} +export function getVisualization() { + window.localStorage.getItem(PROJECTS_VISUALIZATION); +} -export const saveSort = (sort: ?string) => save(PROJECTS_SORT, sort); -export const getSort = () => window.localStorage.getItem(PROJECTS_SORT); +export function saveSort(sort /*: ?string */) { + save(PROJECTS_SORT, sort); +} +export function getSort() { + window.localStorage.getItem(PROJECTS_SORT); +} -export const saveCustomGraph = (metrics: ?Array<string>) => +export function saveCustomGraph(metrics /*: ?Array<string> */) { save(PROJECT_ACTIVITY_GRAPH_CUSTOM, metrics ? metrics.join(',') : ''); -export const getCustomGraph = (): Array<string> => { +} +export function getCustomGraph() /*: Array<string> */ { const customGraphs = window.localStorage.getItem(PROJECT_ACTIVITY_GRAPH_CUSTOM); return customGraphs ? customGraphs.split(',') : []; -}; +} -export const saveGraph = (graph: ?string) => save(PROJECT_ACTIVITY_GRAPH, graph); -export const getGraph = (): string => - window.localStorage.getItem(PROJECT_ACTIVITY_GRAPH) || 'issues'; +export function saveGraph(graph /*: ?string */) { + save(PROJECT_ACTIVITY_GRAPH, graph); +} +export function getGraph() /*: string */ { + return window.localStorage.getItem(PROJECT_ACTIVITY_GRAPH) || 'issues'; +} diff --git a/server/sonar-web/src/main/js/helpers/urls.js b/server/sonar-web/src/main/js/helpers/urls.js index e60862b2673..0dd024094e6 100644 --- a/server/sonar-web/src/main/js/helpers/urls.js +++ b/server/sonar-web/src/main/js/helpers/urls.js @@ -97,21 +97,25 @@ export function getQualityProfileUrl(name, language, organization) { return getProfilePath(name, language, organization); } -export const getQualityGateUrl = (key: string, organization?: string) => ({ - pathname: getQualityGatesUrl(organization).pathname + '/show/' + encodeURIComponent(key) -}); +export function getQualityGateUrl(key /*: string */, organization /*: ?string */) { + return { + pathname: getQualityGatesUrl(organization).pathname + '/show/' + encodeURIComponent(key) + }; +} -export const getQualityGatesUrl = (organization?: string) => ({ - pathname: - (organization ? '/organizations/' + encodeURIComponent(organization) : '') + '/quality_gates' -}); +export function getQualityGatesUrl(organization /*: ?string */) { + return { + pathname: + (organization ? '/organizations/' + encodeURIComponent(organization) : '') + '/quality_gates' + }; +} /** * Generate URL for the rules page * @param {object} query * @returns {string} */ -export function getRulesUrl(query, organization?: string) { +export function getRulesUrl(query, organization /*: ?string */) { const path = organization ? `/organizations/${organization}/rules` : '/coding_rules'; if (query) { @@ -131,7 +135,7 @@ export function getRulesUrl(query, organization?: string) { * @param {object} query * @returns {string} */ -export function getDeprecatedActiveRulesUrl(query = {}, organization?: string) { +export function getDeprecatedActiveRulesUrl(query = {}, organization /*: ?string */) { const baseQuery = { activation: 'true', statuses: 'DEPRECATED' }; return getRulesUrl({ ...query, ...baseQuery }, organization); } diff --git a/server/sonar-web/src/main/js/store/appState/duck.js b/server/sonar-web/src/main/js/store/appState/duck.js index 3ddcf2f52cb..2358bb011fc 100644 --- a/server/sonar-web/src/main/js/store/appState/duck.js +++ b/server/sonar-web/src/main/js/store/appState/duck.js @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // @flow +/*:: type AppState = { adminPages?: Array<*>, authenticationError: boolean, @@ -25,32 +26,44 @@ type AppState = { organizationsEnabled: boolean, qualifiers: ?Array<string> }; +*/ +/*:: type SetAppStateAction = { type: 'SET_APP_STATE', appState: AppState }; +*/ +/*:: type SetAdminPagesAction = { type: 'SET_ADMIN_PAGES', adminPages: Array<*> }; +*/ -export type Action = SetAppStateAction | SetAdminPagesAction; +/*:: +export type Action = SetAppStateAction | SetAdminPagesAction; */ -export const setAppState = (appState: AppState): SetAppStateAction => ({ - type: 'SET_APP_STATE', - appState -}); +export function setAppState(appState /*: AppState */) /*: SetAppStateAction */ { + return { + type: 'SET_APP_STATE', + appState + }; +} -export const setAdminPages = (adminPages: Array<*>): SetAdminPagesAction => ({ - type: 'SET_ADMIN_PAGES', - adminPages -}); +export function setAdminPages(adminPages /*: Array<*> */) /*: SetAdminPagesAction */ { + return { + type: 'SET_ADMIN_PAGES', + adminPages + }; +} -export const requireAuthorization = () => ({ - type: 'REQUIRE_AUTHORIZATION' -}); +export function requireAuthorization() { + return { + type: 'REQUIRE_AUTHORIZATION' + }; +} const defaultValue = { authenticationError: false, @@ -59,7 +72,7 @@ const defaultValue = { qualifiers: null }; -export default (state: AppState = defaultValue, action: Action) => { +export default function(state /*: AppState */ = defaultValue, action /*: Action */) { if (action.type === 'SET_APP_STATE') { return { ...state, ...action.appState }; } @@ -73,6 +86,8 @@ export default (state: AppState = defaultValue, action: Action) => { } return state; -}; +} -export const getRootQualifiers = (state: AppState) => state.qualifiers; +export function getRootQualifiers(state /*: AppState */) { + return state.qualifiers; +} diff --git a/server/sonar-web/src/main/js/store/favorites/duck.js b/server/sonar-web/src/main/js/store/favorites/duck.js index 73abccaeef1..44bb1ff9b83 100644 --- a/server/sonar-web/src/main/js/store/favorites/duck.js +++ b/server/sonar-web/src/main/js/store/favorites/duck.js @@ -20,27 +20,39 @@ // @flow import { uniq, without } from 'lodash'; +/*:: type Favorite = { key: string }; +*/ +/*:: type ReceiveFavoritesAction = { type: 'RECEIVE_FAVORITES', favorites: Array<Favorite>, notFavorites: Array<Favorite> }; +*/ +/*:: type AddFavoriteAction = { type: 'ADD_FAVORITE', componentKey: string }; +*/ +/*:: type RemoveFavoriteAction = { type: 'REMOVE_FAVORITE', componentKey: string }; +*/ +/*:: type Action = ReceiveFavoritesAction | AddFavoriteAction | RemoveFavoriteAction; +*/ +/*:: type State = Array<string>; +*/ export const actions = { RECEIVE_FAVORITES: 'RECEIVE_FAVORITES', @@ -48,26 +60,32 @@ export const actions = { REMOVE_FAVORITE: 'REMOVE_FAVORITE' }; -export const receiveFavorites = ( - favorites: Array<Favorite>, - notFavorites: Array<Favorite> = [] -): ReceiveFavoritesAction => ({ - type: actions.RECEIVE_FAVORITES, - favorites, - notFavorites -}); +export function receiveFavorites( + favorites /*: Array<Favorite> */, + notFavorites /*: Array<Favorite> */ = [] +) /*: ReceiveFavoritesAction */ { + return { + type: actions.RECEIVE_FAVORITES, + favorites, + notFavorites + }; +} -export const addFavorite = (componentKey: string): AddFavoriteAction => ({ - type: actions.ADD_FAVORITE, - componentKey -}); +export function addFavorite(componentKey /*: string */) /*: AddFavoriteAction */ { + return { + type: actions.ADD_FAVORITE, + componentKey + }; +} -export const removeFavorite = (componentKey: string): RemoveFavoriteAction => ({ - type: actions.REMOVE_FAVORITE, - componentKey -}); +export function removeFavorite(componentKey /*: string */) /*: RemoveFavoriteAction */ { + return { + type: actions.REMOVE_FAVORITE, + componentKey + }; +} -export default (state: State = [], action: Action): State => { +export default function(state /*: State */ = [], action /*: Action */) /*: State */ { if (action.type === actions.RECEIVE_FAVORITES) { const toAdd = action.favorites.map(f => f.key); const toRemove = action.notFavorites.map(f => f.key); @@ -83,6 +101,8 @@ export default (state: State = [], action: Action): State => { } return state; -}; +} -export const isFavorite = (state: State, componentKey: string) => state.includes(componentKey); +export function isFavorite(state /*: State */, componentKey /*: string */) { + return state.includes(componentKey); +} diff --git a/server/sonar-web/src/main/js/store/globalMessages/duck.js b/server/sonar-web/src/main/js/store/globalMessages/duck.js index b74b8efdfaa..57dd1060f54 100644 --- a/server/sonar-web/src/main/js/store/globalMessages/duck.js +++ b/server/sonar-web/src/main/js/store/globalMessages/duck.js @@ -20,17 +20,25 @@ // @flow import { uniqueId } from 'lodash'; +/*:: type Level = 'ERROR' | 'SUCCESS'; +*/ +/*:: type Message = { id: string, message: string, level: Level }; +*/ +/*:: export type State = Array<Message>; +*/ +/*:: type Action = Object; +*/ export const ERROR = 'ERROR'; export const SUCCESS = 'SUCCESS'; @@ -40,35 +48,51 @@ const ADD_GLOBAL_MESSAGE = 'ADD_GLOBAL_MESSAGE'; const CLOSE_GLOBAL_MESSAGE = 'CLOSE_GLOBAL_MESSAGE'; const CLOSE_ALL_GLOBAL_MESSAGES = 'CLOSE_ALL_GLOBAL_MESSAGES'; -const addGlobalMessageActionCreator = (id: string, message: string, level: Level) => ({ - type: ADD_GLOBAL_MESSAGE, - message, - level, - id -}); - -export const closeGlobalMessage = (id: string) => ({ - type: CLOSE_GLOBAL_MESSAGE, - id -}); - -export const closeAllGlobalMessages = (id: string) => ({ - type: CLOSE_ALL_GLOBAL_MESSAGES, - id -}); - -const addGlobalMessage = (message: string, level: Level) => (dispatch: Function) => { - const id = uniqueId('global-message-'); - dispatch(addGlobalMessageActionCreator(id, message, level)); - setTimeout(() => dispatch(closeGlobalMessage(id)), 5000); -}; - -export const addGlobalErrorMessage = (message: string) => addGlobalMessage(message, ERROR); - -export const addGlobalSuccessMessage = (message: string) => addGlobalMessage(message, SUCCESS); +function addGlobalMessageActionCreator( + id /*: string */, + message /*: string */, + level /*: Level */ +) { + return { + type: ADD_GLOBAL_MESSAGE, + message, + level, + id + }; +} + +export function closeGlobalMessage(id /*: string */) { + return { + type: CLOSE_GLOBAL_MESSAGE, + id + }; +} + +export function closeAllGlobalMessages(id /*: string */) { + return { + type: CLOSE_ALL_GLOBAL_MESSAGES, + id + }; +} + +function addGlobalMessage(message /*: string */, level /*: Level */) { + return function(dispatch /*: Function */) { + const id = uniqueId('global-message-'); + dispatch(addGlobalMessageActionCreator(id, message, level)); + setTimeout(() => dispatch(closeGlobalMessage(id)), 5000); + }; +} + +export function addGlobalErrorMessage(message /*: string */) { + return addGlobalMessage(message, ERROR); +} + +export function addGlobalSuccessMessage(message /*: string */) { + return addGlobalMessage(message, SUCCESS); +} /* Reducer */ -const globalMessages = (state: State = [], action: Action = {}) => { +export default function(state /*: State */ = [], action /*: Action */ = {}) { switch (action.type) { case ADD_GLOBAL_MESSAGE: return [ @@ -99,9 +123,9 @@ const globalMessages = (state: State = [], action: Action = {}) => { default: return state; } -}; - -export default globalMessages; +} /* Selectors */ -export const getGlobalMessages = (state: State) => state; +export function getGlobalMessages(state /*: State */) { + return state; +} diff --git a/server/sonar-web/src/main/js/store/metrics/actions.js b/server/sonar-web/src/main/js/store/metrics/actions.js index c144c2e1527..cf35d52eb29 100644 --- a/server/sonar-web/src/main/js/store/metrics/actions.js +++ b/server/sonar-web/src/main/js/store/metrics/actions.js @@ -18,8 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // @flow - -export type Metric = { +/*:: export type Metric = { custom?: boolean, decimalScale?: number, description?: string, @@ -30,11 +29,11 @@ export type Metric = { name: string, qualitative?: boolean, type: string -}; +}; */ export const RECEIVE_METRICS = 'RECEIVE_METRICS'; -export const receiveMetrics = (metrics: Array<Metric>) => ({ +export const receiveMetrics = (metrics /*: Array<Metric> */) => ({ type: RECEIVE_METRICS, metrics }); diff --git a/server/sonar-web/src/main/js/store/metrics/reducer.js b/server/sonar-web/src/main/js/store/metrics/reducer.js index edc8750186c..f1c4bf73c38 100644 --- a/server/sonar-web/src/main/js/store/metrics/reducer.js +++ b/server/sonar-web/src/main/js/store/metrics/reducer.js @@ -21,20 +21,22 @@ import { combineReducers } from 'redux'; import { keyBy } from 'lodash'; import { RECEIVE_METRICS } from './actions'; -import type { Metric } from './actions'; +/*:: import type { Metric } from './actions'; */ +/*:: type StateByKey = { [string]: Metric }; type StateKeys = Array<string>; type State = { byKey: StateByKey, keys: StateKeys }; +*/ -const byKey = (state: StateByKey = {}, action = {}) => { +const byKey = (state /*: StateByKey */ = {}, action = {}) => { if (action.type === RECEIVE_METRICS) { return keyBy(action.metrics, 'key'); } return state; }; -const keys = (state: StateKeys = [], action = {}) => { +const keys = (state /*: StateKeys */ = [], action = {}) => { if (action.type === RECEIVE_METRICS) { return action.metrics.map(f => f.key); } @@ -44,6 +46,6 @@ const keys = (state: StateKeys = [], action = {}) => { export default combineReducers({ byKey, keys }); -export const getMetrics = (state: State) => state.byKey; -export const getMetricByKey = (state: State, key: string) => state.byKey[key]; -export const getMetricsKey = (state: State) => state.keys; +export const getMetrics = (state /*: State */) => state.byKey; +export const getMetricByKey = (state /*: State */, key /*: string */) => state.byKey[key]; +export const getMetricsKey = (state /*: State */) => state.keys; diff --git a/server/sonar-web/src/main/js/store/notifications/duck.js b/server/sonar-web/src/main/js/store/notifications/duck.js index 1a3f554fbd5..11f695f63c5 100644 --- a/server/sonar-web/src/main/js/store/notifications/duck.js +++ b/server/sonar-web/src/main/js/store/notifications/duck.js @@ -21,6 +21,7 @@ import { combineReducers } from 'redux'; import { uniqBy, uniqWith } from 'lodash'; +/*:: export type Notification = { channel: string, type: string, @@ -28,21 +29,33 @@ export type Notification = { projectName?: string, organization?: string }; +*/ +/*:: export type NotificationsState = Array<Notification>; +*/ +/*:: export type ChannelsState = Array<string>; +*/ +/*:: export type TypesState = Array<string>; +*/ +/*:: type AddNotificationAction = { type: 'ADD_NOTIFICATION', notification: Notification }; +*/ +/*:: type RemoveNotificationAction = { type: 'REMOVE_NOTIFICATION', notification: Notification }; +*/ +/*:: type ReceiveNotificationsAction = { type: 'RECEIVE_NOTIFICATIONS', notifications: NotificationsState, @@ -50,52 +63,67 @@ type ReceiveNotificationsAction = { globalTypes: TypesState, perProjectTypes: TypesState }; +*/ +/*:: type Action = AddNotificationAction | RemoveNotificationAction | ReceiveNotificationsAction; - -export const addNotification = (notification: Notification): AddNotificationAction => ({ - type: 'ADD_NOTIFICATION', - notification -}); - -export const removeNotification = (notification: Notification): RemoveNotificationAction => ({ - type: 'REMOVE_NOTIFICATION', - notification -}); - -export const receiveNotifications = ( - notifications: NotificationsState, - channels: ChannelsState, - globalTypes: TypesState, - perProjectTypes: TypesState -): ReceiveNotificationsAction => ({ - type: 'RECEIVE_NOTIFICATIONS', - notifications, - channels, - globalTypes, - perProjectTypes -}); - -const onAddNotification = (state: NotificationsState, notification: Notification) => { - const isNotificationsEqual = (a: Notification, b: Notification) => - a.channel === b.channel && a.type === b.type && a.project === b.project; +*/ + +export function addNotification(notification /*: Notification */) /*: AddNotificationAction */ { + return { + type: 'ADD_NOTIFICATION', + notification + }; +} + +export function removeNotification( + notification /*: Notification */ +) /*: RemoveNotificationAction */ { + return { + type: 'REMOVE_NOTIFICATION', + notification + }; +} + +export function receiveNotifications( + notifications /*: NotificationsState */, + channels /*: ChannelsState */, + globalTypes /*: TypesState */, + perProjectTypes /*: TypesState */ +) /*: ReceiveNotificationsAction */ { + return { + type: 'RECEIVE_NOTIFICATIONS', + notifications, + channels, + globalTypes, + perProjectTypes + }; +} + +function onAddNotification(state /*: NotificationsState */, notification /*: Notification */) { + function isNotificationsEqual(a /*: Notification */, b /*: Notification */) { + return a.channel === b.channel && a.type === b.type && a.project === b.project; + } return uniqWith([...state, notification], isNotificationsEqual); -}; +} -const onRemoveNotification = (state: NotificationsState, notification: Notification) => { +function onRemoveNotification(state /*: NotificationsState */, notification /*: Notification */) { return state.filter( n => n.channel !== notification.channel || n.type !== notification.type || n.project !== notification.project ); -}; +} -const onReceiveNotifications = (state: NotificationsState, notifications: NotificationsState) => { +function onReceiveNotifications( + state /*: NotificationsState */, + notifications /*: NotificationsState */ +) { return [...notifications]; -}; +} -const notifications = (state: NotificationsState = [], action: Action) => { +function notifications(state /*: NotificationsState */ = [], action /*: Action */) { switch (action.type) { case 'ADD_NOTIFICATION': return onAddNotification(state, action.notification); @@ -106,45 +134,48 @@ const notifications = (state: NotificationsState = [], action: Action) => { default: return state; } -}; +} -const channels = (state: ChannelsState = [], action: Action) => { +function channels(state /*: ChannelsState */ = [], action /*: Action */) { if (action.type === 'RECEIVE_NOTIFICATIONS') { return action.channels; } else { return state; } -}; +} -const globalTypes = (state: TypesState = [], action: Action) => { +function globalTypes(state /*: TypesState */ = [], action /*: Action */) { if (action.type === 'RECEIVE_NOTIFICATIONS') { return action.globalTypes; } else { return state; } -}; +} -const perProjectTypes = (state: TypesState = [], action: Action) => { +function perProjectTypes(state /*: TypesState */ = [], action /*: Action */) { if (action.type === 'RECEIVE_NOTIFICATIONS') { return action.perProjectTypes; } else { return state; } -}; +} +/*:: type State = { notifications: NotificationsState, channels: ChannelsState, globalTypes: TypesState, perProjectTypes: TypesState }; +*/ export default combineReducers({ notifications, channels, globalTypes, perProjectTypes }); -export const getGlobal = (state: State): NotificationsState => - state.notifications.filter(n => !n.project); +export function getGlobal(state /*: State */) /*: NotificationsState */ { + return state.notifications.filter(n => !n.project); +} -export const getProjects = (state: State): Array<{ key: string, name: string }> => { +export function getProjects(state /*: State */) /*: Array<{ key: string, name: string }> */ { // $FlowFixMe const allProjects = state.notifications.filter(n => n.project != null).map(n => ({ key: n.project, @@ -153,13 +184,20 @@ export const getProjects = (state: State): Array<{ key: string, name: string }> })); return uniqBy(allProjects, project => project.key); -}; +} -export const getForProject = (state: State, project: string): NotificationsState => - state.notifications.filter(n => n.project === project); +export function getForProject(state /*: State */, project /*: string */) /*: NotificationsState */ { + return state.notifications.filter(n => n.project === project); +} -export const getChannels = (state: State): ChannelsState => state.channels; +export function getChannels(state /*: State */) /*: ChannelsState */ { + return state.channels; +} -export const getGlobalTypes = (state: State): TypesState => state.globalTypes; +export function getGlobalTypes(state /*: State */) /*: TypesState */ { + return state.globalTypes; +} -export const getPerProjectTypes = (state: State): TypesState => state.perProjectTypes; +export function getPerProjectTypes(state /*: State */) /*: TypesState */ { + return state.perProjectTypes; +} diff --git a/server/sonar-web/src/main/js/store/organizations/duck.js b/server/sonar-web/src/main/js/store/organizations/duck.js index 5c8ee446cf7..fa8af85260f 100644 --- a/server/sonar-web/src/main/js/store/organizations/duck.js +++ b/server/sonar-web/src/main/js/store/organizations/duck.js @@ -21,6 +21,7 @@ import { combineReducers } from 'redux'; import { omit, uniq, without } from 'lodash'; +/*:: export type Organization = { adminPages?: Array<{ key: string, name: string }>, avatar?: string, @@ -35,7 +36,9 @@ export type Organization = { projectVisibility: string, url?: string }; +*/ +/*:: export type OrgGroup = { id: string, default: boolean, @@ -43,114 +46,153 @@ export type OrgGroup = { membersCount: number, name: string }; +*/ +/*:: type ReceiveOrganizationsAction = { type: 'RECEIVE_ORGANIZATIONS', organizations: Array<Organization> }; +*/ +/*:: type ReceiveMyOrganizationsAction = { type: 'RECEIVE_MY_ORGANIZATIONS', organizations: Array<Organization> }; +*/ +/*:: type ReceiveOrganizationGroups = { type: 'RECEIVE_ORGANIZATION_GROUPS', key: string, groups: Array<OrgGroup> }; +*/ +/*:: type CreateOrganizationAction = { type: 'CREATE_ORGANIZATION', organization: Organization }; +*/ +/*:: type UpdateOrganizationAction = { type: 'UPDATE_ORGANIZATION', key: string, changes: {} }; +*/ +/*:: type DeleteOrganizationAction = { type: 'DELETE_ORGANIZATION', key: string }; +*/ +/*:: type Action = | ReceiveOrganizationsAction | ReceiveMyOrganizationsAction | ReceiveOrganizationGroups | CreateOrganizationAction | UpdateOrganizationAction - | DeleteOrganizationAction; + | DeleteOrganizationAction; */ +/*:: type ByKeyState = { [key: string]: Organization }; +*/ +/*:: type GroupsState = { [key: string]: Array<OrgGroup> }; +*/ +/*:: type MyState = Array<string>; +*/ +/*:: type State = { byKey: ByKeyState, my: MyState, groups: GroupsState }; +*/ -export const receiveOrganizations = ( - organizations: Array<Organization> -): ReceiveOrganizationsAction => ({ - type: 'RECEIVE_ORGANIZATIONS', - organizations -}); +export function receiveOrganizations( + organizations /*: Array<Organization> */ +) /*: ReceiveOrganizationsAction */ { + return { + type: 'RECEIVE_ORGANIZATIONS', + organizations + }; +} -export const receiveMyOrganizations = ( - organizations: Array<Organization> -): ReceiveMyOrganizationsAction => ({ - type: 'RECEIVE_MY_ORGANIZATIONS', - organizations -}); +export function receiveMyOrganizations( + organizations /*: Array<Organization> */ +) /*: ReceiveMyOrganizationsAction */ { + return { + type: 'RECEIVE_MY_ORGANIZATIONS', + organizations + }; +} -export const receiveOrganizationGroups = ( - key: string, - groups: Array<OrgGroup> -): receiveOrganizationGroups => ({ - type: 'RECEIVE_ORGANIZATION_GROUPS', - key, - groups -}); +export function receiveOrganizationGroups( + key /*: string */, + groups /*: Array<OrgGroup> */ +) /*: receiveOrganizationGroups */ { + return { + type: 'RECEIVE_ORGANIZATION_GROUPS', + key, + groups + }; +} -export const createOrganization = (organization: Organization): CreateOrganizationAction => ({ - type: 'CREATE_ORGANIZATION', - organization -}); +export function createOrganization( + organization /*: Organization */ +) /*: CreateOrganizationAction */ { + return { + type: 'CREATE_ORGANIZATION', + organization + }; +} -export const updateOrganization = (key: string, changes: {}): UpdateOrganizationAction => ({ - type: 'UPDATE_ORGANIZATION', - key, - changes -}); +export function updateOrganization( + key /*: string */, + changes /*: {} */ +) /*: UpdateOrganizationAction */ { + return { + type: 'UPDATE_ORGANIZATION', + key, + changes + }; +} -export const deleteOrganization = (key: string): DeleteOrganizationAction => ({ - type: 'DELETE_ORGANIZATION', - key -}); +export function deleteOrganization(key /*: string */) /*: DeleteOrganizationAction */ { + return { + type: 'DELETE_ORGANIZATION', + key + }; +} -const onReceiveOrganizations = ( - state: ByKeyState, - action: ReceiveOrganizationsAction | ReceiveMyOrganizationsAction -): ByKeyState => { +function onReceiveOrganizations( + state /*: ByKeyState */, + action /*: ReceiveOrganizationsAction | ReceiveMyOrganizationsAction */ +) /*: ByKeyState */ { const nextState = { ...state }; action.organizations.forEach(organization => { nextState[organization.key] = { ...state[organization.key], ...organization }; }); return nextState; -}; +} -const byKey = (state: ByKeyState = {}, action: Action) => { +function byKey(state /*: ByKeyState */ = {}, action /*: Action */) { switch (action.type) { case 'RECEIVE_ORGANIZATIONS': case 'RECEIVE_MY_ORGANIZATIONS': @@ -171,9 +213,9 @@ const byKey = (state: ByKeyState = {}, action: Action) => { default: return state; } -}; +} -const my = (state: MyState = [], action: Action) => { +function my(state /*: MyState */ = [], action /*: Action */) { switch (action.type) { case 'RECEIVE_MY_ORGANIZATIONS': return uniq([...state, ...action.organizations.map(o => o.key)]); @@ -184,26 +226,34 @@ const my = (state: MyState = [], action: Action) => { default: return state; } -}; +} -const groups = (state: GroupsState = {}, action: Action) => { +function groups(state /*: GroupsState */ = {}, action /*: Action */) { switch (action.type) { case 'RECEIVE_ORGANIZATION_GROUPS': return { ...state, [action.key]: action.groups }; default: return state; } -}; +} export default combineReducers({ byKey, my, groups }); -export const getOrganizationByKey = (state: State, key: string): Organization => state.byKey[key]; +export function getOrganizationByKey(state /*: State */, key /*: string */) /*: Organization */ { + return state.byKey[key]; +} -export const getOrganizationGroupsByKey = (state: State, key: string): Array<OrgGroup> => - state.groups[key] || []; +export function getOrganizationGroupsByKey( + state /*: State */, + key /*: string */ +) /*: Array<OrgGroup> */ { + return state.groups[key] || []; +} -export const getMyOrganizations = (state: State): Array<Organization> => - state.my.map(key => getOrganizationByKey(state, key)); +export function getMyOrganizations(state /*: State */) /*: Array<Organization> */ { + return state.my.map(key => getOrganizationByKey(state, key)); +} -export const areThereCustomOrganizations = (state: State): boolean => - Object.keys(state.byKey).length > 1; +export function areThereCustomOrganizations(state /*: State */) /*: boolean */ { + return Object.keys(state.byKey).length > 1; +} diff --git a/server/sonar-web/src/main/js/store/organizations/utils.js b/server/sonar-web/src/main/js/store/organizations/utils.js index a17f80f47cf..f98e88e2085 100644 --- a/server/sonar-web/src/main/js/store/organizations/utils.js +++ b/server/sonar-web/src/main/js/store/organizations/utils.js @@ -24,14 +24,14 @@ import { areThereCustomOrganizations as customOrganizations } from '../rootReducer'; -export const getOrganization = (key: string) => { +export function getOrganization(key /*: string */) { const store = getStore(); const state = store.getState(); return getOrganizationByKey(state, key); -}; +} -export const areThereCustomOrganizations = () => { +export function areThereCustomOrganizations() { const store = getStore(); const state = store.getState(); return customOrganizations(state); -}; +} diff --git a/server/sonar-web/src/main/js/store/organizationsMembers/actions.js b/server/sonar-web/src/main/js/store/organizationsMembers/actions.js index abb41e71624..3698ed4c66f 100644 --- a/server/sonar-web/src/main/js/store/organizationsMembers/actions.js +++ b/server/sonar-web/src/main/js/store/organizationsMembers/actions.js @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ //@flow +/*:: export type Member = { login: string, name: string, @@ -25,13 +26,16 @@ export type Member = { email?: string, groupCount?: number }; +*/ +/*:: type MembersState = { paging?: number, total?: number, loading?: boolean, query?: string | null }; +*/ export const actions = { UPDATE_STATE: 'organizations/UPDATE_STATE', @@ -42,9 +46,9 @@ export const actions = { }; export const receiveMembers = ( - organizationKey: string, - members: Array<Member>, - stateChanges: MembersState + organizationKey /*: string */, + members /*: Array<Member> */, + stateChanges /*: MembersState */ ) => ({ type: actions.RECEIVE_MEMBERS, organization: organizationKey, @@ -53,9 +57,9 @@ export const receiveMembers = ( }); export const receiveMoreMembers = ( - organizationKey: string, - members: Array<Member>, - stateChanges: MembersState + organizationKey /*: string */, + members /*: Array<Member> */, + stateChanges /*: MembersState */ ) => ({ type: actions.RECEIVE_MORE_MEMBERS, organization: organizationKey, @@ -63,19 +67,19 @@ export const receiveMoreMembers = ( stateChanges }); -export const addMember = (organizationKey: string, member: Member) => ({ +export const addMember = (organizationKey /*: string */, member /*: Member */) => ({ type: actions.ADD_MEMBER, organization: organizationKey, member }); -export const removeMember = (organizationKey: string, member: Member) => ({ +export const removeMember = (organizationKey /*: string */, member /*: Member */) => ({ type: actions.REMOVE_MEMBER, organization: organizationKey, member }); -export const updateState = (organizationKey: string, stateChanges: MembersState) => ({ +export const updateState = (organizationKey /*: string */, stateChanges /*: MembersState */) => ({ type: actions.UPDATE_STATE, organization: organizationKey, stateChanges diff --git a/server/sonar-web/src/main/js/store/rootActions.js b/server/sonar-web/src/main/js/store/rootActions.js index b4558241c65..1ec61770048 100644 --- a/server/sonar-web/src/main/js/store/rootActions.js +++ b/server/sonar-web/src/main/js/store/rootActions.js @@ -45,7 +45,7 @@ export const fetchMetrics = () => dispatch => { return getMetrics().then(metrics => dispatch(receiveMetrics(metrics)), onFail(dispatch)); }; -export const fetchOrganizations = (organizations?: Array<string>) => dispatch => +export const fetchOrganizations = (organizations /*: Array<string> | void */) => dispatch => getOrganizations(organizations).then( r => dispatch(receiveOrganizations(r.organizations)), onFail(dispatch) |