diff options
Diffstat (limited to 'server/sonar-web/src/main/js/app/components')
33 files changed, 164 insertions, 103 deletions
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 }; +*/ |