diff options
author | Stas Vilchik <stas.vilchik@sonarsource.com> | 2017-08-18 18:53:44 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-08-18 18:53:44 +0200 |
commit | 7983068e4d2a45531ba0942688e659adf9ee61a2 (patch) | |
tree | c481c4ef137cf8b1f4ac69d2917b51317d8c4dad /server/sonar-web/src/main/js/apps | |
parent | f98b26b3f33e0eb2788ca93a4b115585c527c737 (diff) | |
download | sonarqube-7983068e4d2a45531ba0942688e659adf9ee61a2.tar.gz sonarqube-7983068e4d2a45531ba0942688e659adf9ee61a2.zip |
translate all routes files to ts (#2378)
Diffstat (limited to 'server/sonar-web/src/main/js/apps')
-rw-r--r-- | server/sonar-web/src/main/js/apps/about/routes.ts (renamed from server/sonar-web/src/main/js/apps/about/routes.js) | 4 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/account/projects/ProjectCard.js | 94 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/account/projects/ProjectCard.tsx | 94 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/account/projects/Projects.js | 67 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/account/projects/Projects.tsx | 65 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/account/projects/ProjectsContainer.tsx (renamed from server/sonar-web/src/main/js/apps/account/projects/ProjectsContainer.js) | 34 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/account/projects/propTypes.js | 34 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/account/projects/types.ts | 32 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/account/routes.ts (renamed from server/sonar-web/src/main/js/apps/account/routes.js) | 16 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/background-tasks/routes.ts (renamed from server/sonar-web/src/main/js/apps/background-tasks/routes.js) | 4 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/code/routes.ts (renamed from server/sonar-web/src/main/js/apps/code/routes.js) | 4 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/coding-rules/routes.ts (renamed from server/sonar-web/src/main/js/apps/coding-rules/routes.js) | 4 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/component-measures/routes.ts (renamed from server/sonar-web/src/main/js/apps/component-measures/routes.js) | 8 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/component/components/App.tsx (renamed from server/sonar-web/src/main/js/apps/component/components/App.js) | 21 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/component/routes.ts (renamed from server/sonar-web/src/main/js/apps/component/routes.js) | 4 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/custom-measures/routes.ts (renamed from server/sonar-web/src/main/js/apps/custom-measures/routes.js) | 4 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/groups/routes.ts (renamed from server/sonar-web/src/main/js/apps/groups/routes.js) | 4 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/issues/routes.ts (renamed from server/sonar-web/src/main/js/apps/issues/routes.js) | 3 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/maintenance/components/MaintenanceAppContainer.tsx (renamed from server/sonar-web/src/main/js/apps/maintenance/components/MaintenanceAppContainer.js) | 2 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/maintenance/components/SetupAppContainer.tsx (renamed from server/sonar-web/src/main/js/apps/maintenance/components/SetupAppContainer.js) | 2 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/maintenance/routes.tsx (renamed from server/sonar-web/src/main/js/apps/maintenance/routes.js) | 2 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/metrics/components/MetricsAppContainer.tsx (renamed from server/sonar-web/src/main/js/apps/metrics/components/MetricsAppContainer.js) | 2 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/metrics/routes.ts (renamed from server/sonar-web/src/main/js/apps/metrics/routes.js) | 4 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/ApplicationQualityGate-test.js.snap | 2 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/overview/routes.ts (renamed from server/sonar-web/src/main/js/apps/overview/routes.js) | 4 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/permission-templates/routes.ts (renamed from server/sonar-web/src/main/js/apps/permission-templates/routes.js) | 4 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/permissions/routes.ts (renamed from server/sonar-web/src/main/js/apps/permissions/routes.js) | 6 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/projectActivity/routes.ts (renamed from server/sonar-web/src/main/js/apps/projectActivity/routes.js) | 4 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/projects-admin/routes.ts (renamed from server/sonar-web/src/main/js/apps/projects-admin/routes.js) | 4 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/projects/components/App.tsx (renamed from server/sonar-web/src/main/js/apps/projects/components/App.js) | 3 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/projects/routes.ts (renamed from server/sonar-web/src/main/js/apps/projects/routes.js) | 9 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-gates/routes.ts (renamed from server/sonar-web/src/main/js/apps/quality-gates/routes.js) | 8 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/__tests__/__snapshots__/utils-test.ts.snap (renamed from server/sonar-web/src/main/js/apps/quality-profiles/__tests__/__snapshots__/utils-test.js.snap) | 12 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/__tests__/utils-test.ts (renamed from server/sonar-web/src/main/js/apps/quality-profiles/__tests__/utils-test.js) | 7 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/changelog/Changelog.js | 122 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/changelog/Changelog.tsx | 109 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogContainer.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogContainer.js) | 112 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogEmpty.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogEmpty.js) | 17 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogSearch.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogSearch.js) | 29 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangesList.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangesList.js) | 41 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/changelog/ParameterChange.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/changelog/ParameterChange.js) | 43 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/changelog/SeverityChange.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/changelog/SeverityChange.js) | 28 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/Changelog-test.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/Changelog-test.js) | 20 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangelogSearch-test.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangelogSearch-test.js) | 2 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangesList-test.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangesList-test.js) | 2 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ParameterChange-test.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ParameterChange-test.js) | 4 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/SeverityChange-test.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/SeverityChange-test.js) | 2 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonContainer.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonContainer.js) | 70 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonEmpty.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonEmpty.js) | 17 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonForm.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonForm.js) | 27 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonResults.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonResults.js) | 40 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/compare/__tests__/ComparisonForm-test.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/compare/__tests__/ComparisonForm-test.js) | 5 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/compare/__tests__/ComparisonResults-test.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/compare/__tests__/ComparisonResults-test.js) | 4 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/components/App.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/components/App.js) | 42 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/components/AppContainer.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/components/AppContainer.js) | 8 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/components/BuiltInBadge.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/components/BuiltInBadge.js) | 25 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/components/CopyProfileForm.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/components/CopyProfileForm.js) | 50 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/components/DeleteProfileForm.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/components/DeleteProfileForm.js) | 41 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileActions.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileActions.js) | 64 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileContainer.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileContainer.js) | 35 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileDate.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileDate.js) | 37 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileLink.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileLink.js) | 41 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileNotFound.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileNotFound.js) | 39 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/components/RenameProfileForm.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/components/RenameProfileForm.js) | 48 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/components/__tests__/ProfileContainer-test.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/components/__tests__/ProfileContainer-test.js) | 25 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/ChangeParentForm.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/ChangeParentForm.js) | 61 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/ChangeProjectsForm.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/ChangeProjectsForm.js) | 38 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileDetails.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileDetails.js) | 55 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileExporters.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileExporters.js) | 27 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileHeader.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileHeader.js) | 25 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritance.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritance.js) | 100 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritanceBox.js | 93 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritanceBox.tsx | 82 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileProjects.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileProjects.js) | 53 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRules.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRules.js) | 62 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesDeprecatedWarning.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesDeprecatedWarning.js) | 13 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesRowOfType.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesRowOfType.js) | 25 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesRowTotal.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesRowTotal.js) | 23 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesSonarWayComparison.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRulesSonarWayComparison.js) | 21 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRules-test.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRules-test.js) | 29 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesDeprecatedWarning-test.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesDeprecatedWarning-test.js) | 3 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesRowOfType-test.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesRowOfType-test.js) | 3 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesRowTotal-test.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesRowTotal-test.js) | 3 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesSonarWayComparison-test.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesSonarWayComparison-test.js) | 3 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRules-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRules-test.js.snap) | 0 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesDeprecatedWarning-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesDeprecatedWarning-test.js.snap) | 0 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesRowOfType-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesRowOfType-test.js.snap) | 0 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesRowTotal-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesRowTotal-test.js.snap) | 0 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesSonarWayComparison-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesSonarWayComparison-test.js.snap) | 0 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/home/CreateProfileForm.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/CreateProfileForm.js) | 82 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/home/Evolution.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/Evolution.js) | 37 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.js | 96 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.tsx | 86 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionRules.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionRules.js) | 44 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.js | 80 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.tsx | 73 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/home/HomeContainer.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/HomeContainer.js) | 53 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.js) | 45 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.js) | 54 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListHeader.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListHeader.js) | 19 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListRow.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListRow.js) | 38 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/home/RestoreProfileForm.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/RestoreProfileForm.js) | 54 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/propTypes.js | 76 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/routes.ts (renamed from server/sonar-web/src/main/js/apps/quality-profiles/routes.js) | 14 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/types.ts | 53 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/quality-profiles/utils.ts (renamed from server/sonar-web/src/main/js/apps/quality-profiles/utils.js) | 50 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.js | 49 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.tsx | 50 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/sessions/routes.ts (renamed from server/sonar-web/src/main/js/apps/sessions/routes.js) | 8 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/settings/routes.ts (renamed from server/sonar-web/src/main/js/apps/settings/routes.js) | 10 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/system/routes.js | 28 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/system/routes.ts | 30 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/update-center/routes.ts (renamed from server/sonar-web/src/main/js/apps/update-center/routes.js) | 12 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/users/routes.ts (renamed from server/sonar-web/src/main/js/apps/users/routes.js) | 4 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/web-api/routes.ts (renamed from server/sonar-web/src/main/js/apps/web-api/routes.js) | 10 |
115 files changed, 1688 insertions, 1906 deletions
diff --git a/server/sonar-web/src/main/js/apps/about/routes.js b/server/sonar-web/src/main/js/apps/about/routes.ts index 0748dad497d..6da3a2d64ba 100644 --- a/server/sonar-web/src/main/js/apps/about/routes.js +++ b/server/sonar-web/src/main/js/apps/about/routes.ts @@ -17,9 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, IndexRouteProps } from 'react-router'; + const routes = [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { import('./components/AboutApp').then(i => callback(null, { component: i.default })); } } diff --git a/server/sonar-web/src/main/js/apps/account/projects/ProjectCard.js b/server/sonar-web/src/main/js/apps/account/projects/ProjectCard.js deleted file mode 100644 index 13826f80dc8..00000000000 --- a/server/sonar-web/src/main/js/apps/account/projects/ProjectCard.js +++ /dev/null @@ -1,94 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import React from 'react'; -import moment from 'moment'; -import { sortBy } from 'lodash'; -import { Link } from 'react-router'; -import Level from '../../../components/ui/Level'; -import { projectType } from './propTypes'; -import { translateWithParameters, translate } from '../../../helpers/l10n'; - -export default class ProjectCard extends React.PureComponent { - static propTypes = { - project: projectType.isRequired - }; - - render() { - const { project } = this.props; - const isAnalyzed = project.lastAnalysisDate != null; - const analysisMoment = isAnalyzed && moment(project.lastAnalysisDate); - const links = sortBy(project.links, 'type'); - - return ( - <div className="account-project-card clearfix"> - <aside className="account-project-side"> - {isAnalyzed - ? <div className="account-project-analysis" title={analysisMoment.format('LLL')}> - {translateWithParameters( - 'my_account.projects.analyzed_x', - analysisMoment.fromNow() - )} - </div> - : <div className="account-project-analysis"> - {translate('my_account.projects.never_analyzed')} - </div>} - - {project.qualityGate != null && - <div className="account-project-quality-gate"> - <Level level={project.qualityGate} /> - </div>} - </aside> - - <h3 className="account-project-name"> - <Link to={{ pathname: '/dashboard', query: { id: project.key } }}> - {project.name} - </Link> - </h3> - - {links.length > 0 && - <div className="account-project-links"> - <ul className="list-inline"> - {links.map(link => - <li key={link.type}> - <a - className="link-with-icon" - href={link.href} - title={link.name} - target="_blank" - rel="nofollow"> - <i className={`icon-color-link icon-${link.type}`} /> - </a> - </li> - )} - </ul> - </div>} - - <div className="account-project-key"> - {project.key} - </div> - - {!!project.description && - <div className="account-project-description"> - {project.description} - </div>} - </div> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/account/projects/ProjectCard.tsx b/server/sonar-web/src/main/js/apps/account/projects/ProjectCard.tsx new file mode 100644 index 00000000000..93a3a787715 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/account/projects/ProjectCard.tsx @@ -0,0 +1,94 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import * as moment from 'moment'; +import { sortBy } from 'lodash'; +import { Link } from 'react-router'; +import { IProject } from './types'; +import Level from '../../../components/ui/Level'; +import { translateWithParameters, translate } from '../../../helpers/l10n'; + +interface Props { + project: IProject; +} + +export default function ProjectCard(props: Props) { + const { project } = props; + const isAnalyzed = project.lastAnalysisDate != null; + const analysisMoment = isAnalyzed && moment(project.lastAnalysisDate); + const links = sortBy(project.links, 'type'); + + return ( + <div className="account-project-card clearfix"> + <aside className="account-project-side"> + {isAnalyzed + ? <div + className="account-project-analysis" + title={analysisMoment ? analysisMoment.format('LLL') : undefined}> + {translateWithParameters( + 'my_account.projects.analyzed_x', + analysisMoment ? analysisMoment.fromNow() : undefined + )} + </div> + : <div className="account-project-analysis"> + {translate('my_account.projects.never_analyzed')} + </div>} + + {project.qualityGate != null && + <div className="account-project-quality-gate"> + <Level level={project.qualityGate} /> + </div>} + </aside> + + <h3 className="account-project-name"> + <Link to={{ pathname: '/dashboard', query: { id: project.key } }}> + {project.name} + </Link> + </h3> + + {links.length > 0 && + <div className="account-project-links"> + <ul className="list-inline"> + {links.map(link => + <li key={link.type}> + <a + className="link-with-icon" + href={link.href} + title={link.name} + target="_blank" + rel="nofollow"> + <i className={`icon-color-link icon-${link.type}`} /> + </a> + </li> + )} + </ul> + </div>} + + <div className="account-project-key"> + {project.key} + </div> + + {!!project.description && + <div className="account-project-description"> + {project.description} + </div>} + </div> + ); +} diff --git a/server/sonar-web/src/main/js/apps/account/projects/Projects.js b/server/sonar-web/src/main/js/apps/account/projects/Projects.js deleted file mode 100644 index 89c151f73d5..00000000000 --- a/server/sonar-web/src/main/js/apps/account/projects/Projects.js +++ /dev/null @@ -1,67 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import React from 'react'; -import PropTypes from 'prop-types'; -import ProjectCard from './ProjectCard'; -import ListFooter from '../../../components/controls/ListFooter'; -import { projectsListType } from './propTypes'; -import { translate } from '../../../helpers/l10n'; - -export default class Projects extends React.PureComponent { - static propTypes = { - projects: projectsListType.isRequired, - total: PropTypes.number.isRequired, - loading: PropTypes.bool.isRequired, - loadMore: PropTypes.func.isRequired - }; - - render() { - const { projects } = this.props; - - return ( - <div id="account-projects"> - {projects.length === 0 - ? <div className="js-no-results"> - {translate('my_account.projects.no_results')} - </div> - : <p> - {translate('my_account.projects.description')} - </p>} - - {projects.length > 0 && - <ul className="account-projects-list"> - {projects.map(project => - <li key={project.key}> - <ProjectCard project={project} /> - </li> - )} - </ul>} - - {projects.length > 0 && - <ListFooter - count={projects.length} - total={this.props.total} - ready={!this.props.loading} - loadMore={this.props.loadMore} - />} - </div> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/account/projects/Projects.tsx b/server/sonar-web/src/main/js/apps/account/projects/Projects.tsx new file mode 100644 index 00000000000..e3681c3465d --- /dev/null +++ b/server/sonar-web/src/main/js/apps/account/projects/Projects.tsx @@ -0,0 +1,65 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import ProjectCard from './ProjectCard'; +import { IProject } from './types'; +import ListFooter from '../../../components/controls/ListFooter'; +import { translate } from '../../../helpers/l10n'; + +interface Props { + loading: boolean; + loadMore: () => void; + projects: IProject[]; + search: (query: string) => void; + total?: number; +} + +export default function Projects(props: Props) { + const { projects } = props; + + return ( + <div id="account-projects"> + {projects.length === 0 + ? <div className="js-no-results"> + {translate('my_account.projects.no_results')} + </div> + : <p> + {translate('my_account.projects.description')} + </p>} + + {projects.length > 0 && + <ul className="account-projects-list"> + {projects.map(project => + <li key={project.key}> + <ProjectCard project={project} /> + </li> + )} + </ul>} + + {projects.length > 0 && + <ListFooter + count={projects.length} + total={props.total || 0} + ready={!props.loading} + loadMore={props.loadMore} + />} + </div> + ); +} diff --git a/server/sonar-web/src/main/js/apps/account/projects/ProjectsContainer.js b/server/sonar-web/src/main/js/apps/account/projects/ProjectsContainer.tsx index 69aea617c93..b822768884d 100644 --- a/server/sonar-web/src/main/js/apps/account/projects/ProjectsContainer.js +++ b/server/sonar-web/src/main/js/apps/account/projects/ProjectsContainer.tsx @@ -17,24 +17,28 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import React from 'react'; +import * as React from 'react'; import Helmet from 'react-helmet'; import Projects from './Projects'; import { getMyProjects } from '../../../api/components'; import { translate } from '../../../helpers/l10n'; -export default class ProjectsContainer extends React.PureComponent { - state = { +interface State { + loading: boolean; + page: number; + projects?: any[]; + query: string; + total?: number; +} + +export default class ProjectsContainer extends React.PureComponent<{}, State> { + mounted: boolean; + state: State = { loading: true, page: 1, query: '' }; - componentWillMount() { - this.loadMore = this.loadMore.bind(this); - this.search = this.search.bind(this); - } - componentDidMount() { this.mounted = true; this.loadProjects(); @@ -46,15 +50,15 @@ export default class ProjectsContainer extends React.PureComponent { loadProjects(page = this.state.page, query = this.state.query) { this.setState({ loading: true }); - const data = { ps: 100 }; + const data: { [p: string]: any } = { ps: 100 }; if (page > 1) { data.p = page; } if (query) { data.q = query; } - return getMyProjects(data).then(r => { - const projects = page > 1 ? [...this.state.projects, ...r.projects] : r.projects; + return getMyProjects(data).then((r: any) => { + const projects = page > 1 ? [...(this.state.projects || []), ...r.projects] : r.projects; this.setState({ projects, query, @@ -65,13 +69,9 @@ export default class ProjectsContainer extends React.PureComponent { }); } - loadMore() { - return this.loadProjects(this.state.page + 1); - } + loadMore = () => this.loadProjects(this.state.page + 1); - search(query) { - return this.loadProjects(1, query); - } + search = (query: string) => this.loadProjects(1, query); render() { const helmet = <Helmet title={translate('my_account.projects')} />; diff --git a/server/sonar-web/src/main/js/apps/account/projects/propTypes.js b/server/sonar-web/src/main/js/apps/account/projects/propTypes.js deleted file mode 100644 index cae87b48906..00000000000 --- a/server/sonar-web/src/main/js/apps/account/projects/propTypes.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import PropTypes from 'prop-types'; - -const { shape, string, array, arrayOf } = PropTypes; - -export const projectType = shape({ - id: string.isRequired, - key: string.isRequired, - name: string.isRequired, - lastAnalysisDate: string, - description: string, - links: array.isRequired, - qualityGate: string -}); - -export const projectsListType = arrayOf(projectType); diff --git a/server/sonar-web/src/main/js/apps/account/projects/types.ts b/server/sonar-web/src/main/js/apps/account/projects/types.ts new file mode 100644 index 00000000000..76feb045c64 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/account/projects/types.ts @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +export interface IProject { + id: string; + key: string; + name: string; + lastAnalysisDate: string; + description: string; + links: Array<{ + href: string; + name: string; + type: string; + }>; + qualityGate: string; +} diff --git a/server/sonar-web/src/main/js/apps/account/routes.js b/server/sonar-web/src/main/js/apps/account/routes.ts index 2b92bf00f6b..90e66149504 100644 --- a/server/sonar-web/src/main/js/apps/account/routes.js +++ b/server/sonar-web/src/main/js/apps/account/routes.ts @@ -17,44 +17,46 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, IndexRouteProps, RouteComponent } from 'react-router'; + const routes = [ { - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./components/Account').then(i => callback(null, i.default)); }, childRoutes: [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { import('./profile/Profile').then(i => callback(null, { component: i.default })); } }, { path: 'security', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./components/Security').then(i => callback(null, i.default)); } }, { path: 'projects', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./projects/ProjectsContainer').then(i => callback(null, i.default)); } }, { path: 'notifications', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./notifications/Notifications').then(i => callback(null, i.default)); } }, { path: 'organizations', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./organizations/UserOrganizations').then(i => callback(null, i.default)); }, childRoutes: [ { path: 'create', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./organizations/CreateOrganizationForm').then(i => callback(null, i.default)); } } diff --git a/server/sonar-web/src/main/js/apps/background-tasks/routes.js b/server/sonar-web/src/main/js/apps/background-tasks/routes.ts index 3f46e626d9e..88e0a5e53bc 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/routes.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/routes.ts @@ -17,9 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, IndexRouteProps } from 'react-router'; + const routes = [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { import('./components/BackgroundTasksApp').then(i => callback(null, { component: i.default })); } } diff --git a/server/sonar-web/src/main/js/apps/code/routes.js b/server/sonar-web/src/main/js/apps/code/routes.ts index 4de41657b76..fcffeff191c 100644 --- a/server/sonar-web/src/main/js/apps/code/routes.js +++ b/server/sonar-web/src/main/js/apps/code/routes.ts @@ -17,9 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, IndexRouteProps } from 'react-router'; + const routes = [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { import('./components/App').then(i => callback(null, { component: i.default })); } } diff --git a/server/sonar-web/src/main/js/apps/coding-rules/routes.js b/server/sonar-web/src/main/js/apps/coding-rules/routes.ts index af91a4eab6d..798ee29934a 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/routes.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/routes.ts @@ -17,10 +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. */ +import { RouterState, RouteComponent } from 'react-router'; + const routes = [ { indexRoute: { - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./components/CodingRulesAppContainer').then(i => callback(null, i.default)); } } diff --git a/server/sonar-web/src/main/js/apps/component-measures/routes.js b/server/sonar-web/src/main/js/apps/component-measures/routes.ts index c0abc9f57d8..9f3813c87e2 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/routes.js +++ b/server/sonar-web/src/main/js/apps/component-measures/routes.ts @@ -17,15 +17,17 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, IndexRouteProps, RedirectFunction } from 'react-router'; + const routes = [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { import('./components/AppContainer').then(i => callback(null, { component: i.default })); } }, { path: 'domain/:domainName', - onEnter(nextState, replace) { + onEnter(nextState: RouterState, replace: RedirectFunction) { replace({ pathname: '/component_measures', query: { @@ -37,7 +39,7 @@ const routes = [ }, { path: 'metric/:metricKey(/:view)', - onEnter(nextState, replace) { + onEnter(nextState: RouterState, replace: RedirectFunction) { if (nextState.params.view === 'history') { replace({ pathname: '/project/activity', 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.tsx index e8c1c9f2128..a1fb59f825c 100644 --- a/server/sonar-web/src/main/js/apps/component/components/App.js +++ b/server/sonar-web/src/main/js/apps/component/components/App.tsx @@ -17,20 +17,19 @@ * 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 React from 'react'; +import * as React from 'react'; import SourceViewer from '../../../components/SourceViewer/SourceViewer'; -export default class App extends React.PureComponent { - /*:: props: { - location: { - query: { - id: string, - line?: string - } - } +interface Props { + location: { + query: { + id: string; + line?: string; + }; }; -*/ +} + +export default class App extends React.PureComponent<Props> { scrollToLine = () => { const { line } = this.props.location.query; if (line) { diff --git a/server/sonar-web/src/main/js/apps/component/routes.js b/server/sonar-web/src/main/js/apps/component/routes.ts index 9943b1d8380..c5105eeca4e 100644 --- a/server/sonar-web/src/main/js/apps/component/routes.js +++ b/server/sonar-web/src/main/js/apps/component/routes.ts @@ -17,10 +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. */ +import { RouterState, RouteComponent } from 'react-router'; + const routes = [ { indexRoute: { - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./components/App').then(i => callback(null, i.default)); } } diff --git a/server/sonar-web/src/main/js/apps/custom-measures/routes.js b/server/sonar-web/src/main/js/apps/custom-measures/routes.ts index e3aee2038cd..ad092ba1d48 100644 --- a/server/sonar-web/src/main/js/apps/custom-measures/routes.js +++ b/server/sonar-web/src/main/js/apps/custom-measures/routes.ts @@ -17,9 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, IndexRouteProps } from 'react-router'; + const routes = [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { import('./components/CustomMeasuresAppContainer').then(i => callback(null, { component: i.default }) ); diff --git a/server/sonar-web/src/main/js/apps/groups/routes.js b/server/sonar-web/src/main/js/apps/groups/routes.ts index 8829f80c94b..80ee5984d39 100644 --- a/server/sonar-web/src/main/js/apps/groups/routes.js +++ b/server/sonar-web/src/main/js/apps/groups/routes.ts @@ -17,9 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, IndexRouteProps } from 'react-router'; + const routes = [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { Promise.all([ import('./components/GroupsAppContainer').then(i => i.default), import('../organizations/forSingleOrganization').then(i => i.default) diff --git a/server/sonar-web/src/main/js/apps/issues/routes.js b/server/sonar-web/src/main/js/apps/issues/routes.ts index ffcdcb7a090..e915d90da0a 100644 --- a/server/sonar-web/src/main/js/apps/issues/routes.js +++ b/server/sonar-web/src/main/js/apps/issues/routes.ts @@ -17,11 +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. */ +import { RouterState, IndexRouteProps } from 'react-router'; import { onEnter } from './redirects'; const routes = [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { import('./components/AppContainer').then(i => callback(null, { component: i.default, onEnter }) ); diff --git a/server/sonar-web/src/main/js/apps/maintenance/components/MaintenanceAppContainer.js b/server/sonar-web/src/main/js/apps/maintenance/components/MaintenanceAppContainer.tsx index bf151b827ac..923d805efd7 100644 --- a/server/sonar-web/src/main/js/apps/maintenance/components/MaintenanceAppContainer.js +++ b/server/sonar-web/src/main/js/apps/maintenance/components/MaintenanceAppContainer.tsx @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import React from 'react'; +import * as React from 'react'; import init from '../init'; export default class MaintenanceAppContainer extends React.PureComponent { diff --git a/server/sonar-web/src/main/js/apps/maintenance/components/SetupAppContainer.js b/server/sonar-web/src/main/js/apps/maintenance/components/SetupAppContainer.tsx index c28492700ce..398ebb69fd6 100644 --- a/server/sonar-web/src/main/js/apps/maintenance/components/SetupAppContainer.js +++ b/server/sonar-web/src/main/js/apps/maintenance/components/SetupAppContainer.tsx @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import React from 'react'; +import * as React from 'react'; import init from '../init'; export default class SetupAppContainer extends React.PureComponent { diff --git a/server/sonar-web/src/main/js/apps/maintenance/routes.js b/server/sonar-web/src/main/js/apps/maintenance/routes.tsx index e6b19e9a5a3..df6cd941cd5 100644 --- a/server/sonar-web/src/main/js/apps/maintenance/routes.js +++ b/server/sonar-web/src/main/js/apps/maintenance/routes.tsx @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import React from 'react'; +import * as React from 'react'; import { IndexRoute } from 'react-router'; import MaintenanceAppContainer from './components/MaintenanceAppContainer'; import SetupAppContainer from './components/SetupAppContainer'; diff --git a/server/sonar-web/src/main/js/apps/metrics/components/MetricsAppContainer.js b/server/sonar-web/src/main/js/apps/metrics/components/MetricsAppContainer.tsx index f5f031e9839..0bf49c749d5 100644 --- a/server/sonar-web/src/main/js/apps/metrics/components/MetricsAppContainer.js +++ b/server/sonar-web/src/main/js/apps/metrics/components/MetricsAppContainer.tsx @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import React from 'react'; +import * as React from 'react'; import Helmet from 'react-helmet'; import init from '../init'; import { translate } from '../../../helpers/l10n'; diff --git a/server/sonar-web/src/main/js/apps/metrics/routes.js b/server/sonar-web/src/main/js/apps/metrics/routes.ts index 637dba72da9..c52951ea17b 100644 --- a/server/sonar-web/src/main/js/apps/metrics/routes.js +++ b/server/sonar-web/src/main/js/apps/metrics/routes.ts @@ -17,9 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, IndexRouteProps } from 'react-router'; + const routes = [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { import('./components/MetricsAppContainer').then(i => callback(null, { component: i.default }) ); diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/ApplicationQualityGate-test.js.snap b/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/ApplicationQualityGate-test.js.snap index 247c1251986..326b9ecefb1 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/ApplicationQualityGate-test.js.snap +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/ApplicationQualityGate-test.js.snap @@ -27,8 +27,6 @@ exports[`renders 2`] = ` overview.quality_gate <Level level="ERROR" - muted={false} - small={false} /> </h2> <div diff --git a/server/sonar-web/src/main/js/apps/overview/routes.js b/server/sonar-web/src/main/js/apps/overview/routes.ts index 02a7323043e..21e41c6b087 100644 --- a/server/sonar-web/src/main/js/apps/overview/routes.js +++ b/server/sonar-web/src/main/js/apps/overview/routes.ts @@ -17,9 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, IndexRouteProps } from 'react-router'; + const routes = [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { import('./components/AppContainer').then(i => callback(null, { component: i.default })); } } diff --git a/server/sonar-web/src/main/js/apps/permission-templates/routes.js b/server/sonar-web/src/main/js/apps/permission-templates/routes.ts index ce1b2679e4a..f00dc431c31 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/routes.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/routes.ts @@ -17,9 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, IndexRouteProps } from 'react-router'; + const routes = [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { Promise.all([ import('./components/AppContainer').then(i => i.default), import('../organizations/forSingleOrganization').then(i => i.default) diff --git a/server/sonar-web/src/main/js/apps/permissions/routes.js b/server/sonar-web/src/main/js/apps/permissions/routes.ts index 631a26985b1..85a62be0dd2 100644 --- a/server/sonar-web/src/main/js/apps/permissions/routes.js +++ b/server/sonar-web/src/main/js/apps/permissions/routes.ts @@ -17,9 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, IndexRouteProps } from 'react-router'; + export const globalPermissionsRoutes = [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { Promise.all([ import('./global/components/App').then(i => i.default), import('../organizations/forSingleOrganization').then(i => i.default) @@ -32,7 +34,7 @@ export const globalPermissionsRoutes = [ export const projectPermissionsRoutes = [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { import('./project/components/AppContainer').then(i => callback(null, { component: i.default }) ); diff --git a/server/sonar-web/src/main/js/apps/projectActivity/routes.js b/server/sonar-web/src/main/js/apps/projectActivity/routes.ts index 11233a7368b..47d7bda3dae 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/routes.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/routes.ts @@ -17,9 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, IndexRouteProps } from 'react-router'; + const routes = [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { import('./components/ProjectActivityAppContainer').then(i => callback(null, { component: i.default }) ); diff --git a/server/sonar-web/src/main/js/apps/projects-admin/routes.js b/server/sonar-web/src/main/js/apps/projects-admin/routes.ts index d17958371b6..447c6ae73dd 100644 --- a/server/sonar-web/src/main/js/apps/projects-admin/routes.js +++ b/server/sonar-web/src/main/js/apps/projects-admin/routes.ts @@ -17,9 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, IndexRouteProps } from 'react-router'; + const routes = [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { Promise.all([ import('./AppContainer').then(i => i.default), import('../organizations/forSingleOrganization').then(i => i.default) diff --git a/server/sonar-web/src/main/js/apps/projects/components/App.js b/server/sonar-web/src/main/js/apps/projects/components/App.tsx index 83b097ed170..471331fb0b9 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/App.js +++ b/server/sonar-web/src/main/js/apps/projects/components/App.tsx @@ -17,8 +17,7 @@ * 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 React from 'react'; +import * as React from 'react'; export default class App extends React.PureComponent { componentDidMount() { diff --git a/server/sonar-web/src/main/js/apps/projects/routes.js b/server/sonar-web/src/main/js/apps/projects/routes.ts index 1c3c76cc3d4..c6f3df309f5 100644 --- a/server/sonar-web/src/main/js/apps/projects/routes.js +++ b/server/sonar-web/src/main/js/apps/projects/routes.ts @@ -17,16 +17,17 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, IndexRouteProps, RouteComponent, RedirectFunction } from 'react-router'; import { saveAll } from '../../helpers/storage'; const routes = [ { - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./components/App').then(i => callback(null, i.default)); }, childRoutes: [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { import('./components/DefaultPageSelector').then(i => callback(null, { component: i.default }) ); @@ -34,14 +35,14 @@ const routes = [ }, { path: 'all', - onEnter(_, replace) { + onEnter(_: RouterState, replace: RedirectFunction) { saveAll(); replace('/projects'); } }, { path: 'favorite', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./components/FavoriteProjectsContainer').then(i => callback(null, i.default)); } } diff --git a/server/sonar-web/src/main/js/apps/quality-gates/routes.js b/server/sonar-web/src/main/js/apps/quality-gates/routes.ts index 8664f1f39bb..f1d203bc354 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/routes.js +++ b/server/sonar-web/src/main/js/apps/quality-gates/routes.ts @@ -17,20 +17,22 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, IndexRouteProps, RouteComponent } from 'react-router'; + const routes = [ { - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./containers/QualityGatesAppContainer').then(i => callback(null, i.default)); }, childRoutes: [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { import('./components/Intro').then(i => callback(null, { component: i.default })); } }, { path: 'show/:id', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./containers/DetailsContainer').then(i => callback(null, i.default)); } } diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/__tests__/__snapshots__/utils-test.js.snap b/server/sonar-web/src/main/js/apps/quality-profiles/__tests__/__snapshots__/utils-test.ts.snap index 63a0a9ee7e0..a833c80f2e3 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/__tests__/__snapshots__/utils-test.js.snap +++ b/server/sonar-web/src/main/js/apps/quality-profiles/__tests__/__snapshots__/utils-test.ts.snap @@ -109,6 +109,18 @@ Array [ Object { "childrenCount": 0, "depth": 1, + "key": "foo", + "name": "foo", + "parentKey": "bar", + }, +] +`; + +exports[`#sortProfiles sorts partial set of inherited profiles 2`] = ` +Array [ + Object { + "childrenCount": 0, + "depth": 1, "key": "profile1", "name": "profile1", "parentKey": "x", diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/__tests__/utils-test.js b/server/sonar-web/src/main/js/apps/quality-profiles/__tests__/utils-test.ts index 57157f7de3a..433702eab06 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/__tests__/utils-test.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/__tests__/utils-test.ts @@ -18,9 +18,10 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { sortProfiles } from '../utils'; +import { IProfile } from '../types'; -function createProfile(key, parentKey) { - return { name: key, key, parentKey }; +function createProfile(key: string, parentKey?: string) { + return { name: key, key, parentKey } as IProfile; } describe('#sortProfiles', () => { @@ -54,7 +55,7 @@ describe('#sortProfiles', () => { it('sorts partial set of inherited profiles', () => { const foo = createProfile('foo', 'bar'); - expect(sortProfiles([foo]), ['foo']); + expect(sortProfiles([foo])).toMatchSnapshot(); const profile1 = createProfile('profile1', 'x'); const profile2 = createProfile('profile2'); 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 deleted file mode 100644 index 7eeb76ee8f8..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/Changelog.js +++ /dev/null @@ -1,122 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * 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 React from 'react'; -import { Link } from 'react-router'; -import moment from 'moment'; -import ChangesList from './ChangesList'; -import { translate } from '../../../helpers/l10n'; -import { getRulesUrl } from '../../../helpers/urls'; - -/*:: -type Props = { - events: Array<{ - action: string, - authorName: string, - date: string, - params?: {}, - ruleKey: string, - ruleName: string - }>, - organization: ?string -}; -*/ - -export default class Changelog extends React.PureComponent { - /*:: props: Props; */ - - render() { - let isEvenRow = false; - - const rows = this.props.events.map((event, index) => { - const prev = index > 0 ? this.props.events[index - 1] : null; - const isSameDate = prev != null && moment(prev.date).diff(event.date, 'seconds') < 10; - const isBulkChange = - prev != null && - isSameDate && - prev.authorName === event.authorName && - prev.action === event.action; - - if (!isBulkChange) { - isEvenRow = !isEvenRow; - } - - const className = 'js-profile-changelog-event ' + (isEvenRow ? 'even' : 'odd'); - - return ( - <tr key={index} className={className}> - <td className="thin nowrap"> - {!isBulkChange && moment(event.date).format('LLL')} - </td> - - <td className="thin nowrap"> - {!isBulkChange && - (event.authorName - ? <span> - {event.authorName} - </span> - : <span className="note">System</span>)} - </td> - - <td className="thin nowrap"> - {!isBulkChange && translate('quality_profiles.changelog', event.action)} - </td> - - <td style={{ lineHeight: '1.5' }}> - <Link to={getRulesUrl({ rule_key: event.ruleKey }, this.props.organization)}> - {event.ruleName} - </Link> - </td> - - <td className="thin nowrap"> - <ChangesList changes={event.params} /> - </td> - </tr> - ); - }); - - return ( - <table className="data zebra-hover"> - <thead> - <tr> - <th className="thin nowrap"> - {translate('date')} <i className="icon-sort-desc" /> - </th> - <th className="thin nowrap"> - {translate('user')} - </th> - <th className="thin nowrap"> - {translate('action')} - </th> - <th> - {translate('rule')} - </th> - <th className="thin nowrap"> - {translate('parameters')} - </th> - </tr> - </thead> - <tbody> - {rows} - </tbody> - </table> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/Changelog.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/Changelog.tsx new file mode 100644 index 00000000000..6c152925cca --- /dev/null +++ b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/Changelog.tsx @@ -0,0 +1,109 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { Link } from 'react-router'; +import * as moment from 'moment'; +import ChangesList from './ChangesList'; +import { translate } from '../../../helpers/l10n'; +import { getRulesUrl } from '../../../helpers/urls'; +import { IProfileChangelogEvent } from '../types'; + +interface Props { + events: IProfileChangelogEvent[]; + organization: string | null; +} + +export default function Changelog(props: Props) { + let isEvenRow = false; + + const rows = props.events.map((event, index) => { + const prev = index > 0 ? props.events[index - 1] : null; + const isSameDate = prev != null && moment(prev.date).diff(event.date, 'seconds') < 10; + const isBulkChange = + prev != null && + isSameDate && + prev.authorName === event.authorName && + prev.action === event.action; + + if (!isBulkChange) { + isEvenRow = !isEvenRow; + } + + const className = 'js-profile-changelog-event ' + (isEvenRow ? 'even' : 'odd'); + + return ( + <tr key={index} className={className}> + <td className="thin nowrap"> + {!isBulkChange && moment(event.date).format('LLL')} + </td> + + <td className="thin nowrap"> + {!isBulkChange && + (event.authorName + ? <span> + {event.authorName} + </span> + : <span className="note">System</span>)} + </td> + + <td className="thin nowrap"> + {!isBulkChange && translate('quality_profiles.changelog', event.action)} + </td> + + <td style={{ lineHeight: '1.5' }}> + <Link to={getRulesUrl({ rule_key: event.ruleKey }, props.organization)}> + {event.ruleName} + </Link> + </td> + + <td className="thin nowrap"> + {event.params && <ChangesList changes={event.params} />} + </td> + </tr> + ); + }); + + return ( + <table className="data zebra-hover"> + <thead> + <tr> + <th className="thin nowrap"> + {translate('date')} <i className="icon-sort-desc" /> + </th> + <th className="thin nowrap"> + {translate('user')} + </th> + <th className="thin nowrap"> + {translate('action')} + </th> + <th> + {translate('rule')} + </th> + <th className="thin nowrap"> + {translate('parameters')} + </th> + </tr> + </thead> + <tbody> + {rows} + </tbody> + </table> + ); +} 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.tsx index 6bca8f58b0f..aa54dd0c89c 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.tsx @@ -17,48 +17,42 @@ * 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 React from 'react'; -import PropTypes from 'prop-types'; +import * as React from 'react'; +import * as PropTypes from 'prop-types'; import Changelog from './Changelog'; import ChangelogSearch from './ChangelogSearch'; 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 { IProfile, IProfileChangelogEvent } from '../types'; -/*:: -type Props = { +interface Props { location: { query: { - since?: string, - to?: string - } - }, - 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; */ + since?: string; + to?: string; + }; + }; + organization: string | null; + profile: IProfile; +} + +interface State { + events?: IProfileChangelogEvent[]; + loading: boolean; + page?: number; + total?: number; +} + +export default class ChangelogContainer extends React.PureComponent<Props, State> { + mounted: boolean; static contextTypes = { router: PropTypes.object }; - state /*: State */ = { + state: State = { loading: true }; @@ -67,7 +61,7 @@ export default class ChangelogContainer extends React.PureComponent { this.loadChangelog(); } - componentDidUpdate(prevProps /*: Props */) { + componentDidUpdate(prevProps: Props) { if (prevProps.location !== this.props.location) { this.loadChangelog(); } @@ -80,7 +74,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: any = { profileKey: this.props.profile.key }; if (query.since) { data.since = query.since; } @@ -88,7 +82,7 @@ export default class ChangelogContainer extends React.PureComponent { data.to = query.to; } - getProfileChangelog(data).then(r => { + getProfileChangelog(data).then((r: any) => { if (this.mounted) { this.setState({ events: r.events, @@ -100,36 +94,38 @@ export default class ChangelogContainer extends React.PureComponent { }); } - loadMore(e /*: SyntheticInputEvent */) { - e.preventDefault(); - e.target.blur(); + loadMore(event: React.SyntheticEvent<HTMLElement>) { + event.preventDefault(); + event.currentTarget.blur(); + + if (this.state.page != null) { + this.setState({ loading: true }); + const { query } = this.props.location; + const data: any = { + profileKey: this.props.profile.key, + p: this.state.page + 1 + }; + if (query.since) { + data.since = query.since; + } + if (query.to) { + data.to = query.to; + } - this.setState({ loading: true }); - const { query } = this.props.location; - const data /*: Object */ = { - profileKey: this.props.profile.key, - p: this.state.page + 1 - }; - if (query.since) { - data.since = query.since; - } - if (query.to) { - data.to = query.to; + getProfileChangelog(data).then((r: any) => { + if (this.mounted && this.state.events) { + this.setState({ + events: [...this.state.events, ...r.events], + total: r.total, + page: r.p, + loading: false + }); + } + }); } - - getProfileChangelog(data).then(r => { - if (this.mounted && this.state.events) { - this.setState({ - events: [...this.state.events, ...r.events], - total: r.total, - page: r.p, - loading: false - }); - } - }); } - handleFromDateChange = (fromDate /*: string | void */) => { + handleFromDateChange = (fromDate?: string) => { const path = getProfileChangelogPath( this.props.profile.name, this.props.profile.language, @@ -142,7 +138,7 @@ export default class ChangelogContainer extends React.PureComponent { this.context.router.push(path); }; - handleToDateChange = (toDate /*: string | void */) => { + handleToDateChange = (toDate?: string) => { const path = getProfileChangelogPath( this.props.profile.name, this.props.profile.language, diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogEmpty.js b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogEmpty.tsx index 96db0d8c8eb..b8a9fbaa35e 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogEmpty.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogEmpty.tsx @@ -17,16 +17,13 @@ * 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 React from 'react'; +import * as React from 'react'; import { translate } from '../../../helpers/l10n'; -export default class ChangelogEmpty extends React.PureComponent { - render() { - return ( - <div className="big-spacer-top"> - {translate('no_results')} - </div> - ); - } +export default function ChangelogEmpty() { + return ( + <div className="big-spacer-top"> + {translate('no_results')} + </div> + ); } 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.tsx index c0abdb0155a..e59479fccf3 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.tsx @@ -17,27 +17,22 @@ * 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 React from 'react'; +import * as React from 'react'; import DateInput from '../../../components/controls/DateInput'; import { translate } from '../../../helpers/l10n'; -/*:: -type Props = { - fromDate?: string, - toDate?: string, - onFromDateChange: () => void, - onReset: () => void, - onToDateChange: () => void -}; -*/ - -export default class ChangelogSearch extends React.PureComponent { - /*:: props: Props; */ +interface Props { + fromDate?: string; + toDate?: string; + onFromDateChange: () => void; + onReset: () => void; + onToDateChange: () => void; +} - handleResetClick(e /*: SyntheticInputEvent */) { - e.preventDefault(); - e.target.blur(); +export default class ChangelogSearch extends React.PureComponent<Props> { + handleResetClick(event: React.SyntheticEvent<HTMLElement>) { + event.preventDefault(); + event.currentTarget.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.tsx index c910ebb54ab..c800e44e918 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.tsx @@ -17,33 +17,24 @@ * 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 React from 'react'; +import * as 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; */ - - render() { - const { changes } = this.props; +interface Props { + changes: { [change: string]: string | null }; +} - return ( - <ul> - {Object.keys(changes).map(key => - <li key={key}> - {key === 'severity' - ? <SeverityChange severity={changes[key]} /> - : <ParameterChange name={key} value={changes[key]} />} - </li> - )} - </ul> - ); - } +export default function ChangesList({ changes }: Props) { + return ( + <ul> + {Object.keys(changes).map(key => + <li key={key}> + {key === 'severity' + ? <SeverityChange severity={changes[key]} /> + : <ParameterChange name={key} value={changes[key]} />} + </li> + )} + </ul> + ); } 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.tsx index 9ee9d2bd80f..d62d11d7c25 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.tsx @@ -17,38 +17,29 @@ * 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 React from 'react'; +import * as React from 'react'; import { translateWithParameters } from '../../../helpers/l10n'; -/*:: -type Props = { - name: string, - value: ?string -}; -*/ - -export default class ParameterChange extends React.PureComponent { - /*:: props: Props; */ - - render() { - const { name, value } = this.props; - - if (value == null) { - return ( - <div style={{ whiteSpace: 'normal' }}> - {translateWithParameters( - 'quality_profiles.changelog.parameter_reset_to_default_value', - name - )} - </div> - ); - } +interface Props { + name: string; + value: string | null; +} +export default function ParameterChange({ name, value }: Props) { + if (value == null) { return ( <div style={{ whiteSpace: 'normal' }}> - {translateWithParameters('quality_profiles.parameter_set_to', name, value)} + {translateWithParameters( + 'quality_profiles.changelog.parameter_reset_to_default_value', + name + )} </div> ); } + + return ( + <div style={{ whiteSpace: 'normal' }}> + {translateWithParameters('quality_profiles.parameter_set_to', name, value)} + </div> + ); } 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.tsx index 546c46610c2..3c744e731a9 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.tsx @@ -17,26 +17,18 @@ * 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 React from 'react'; +import * as 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; */ +interface Props { + severity: string | null; +} - render() { - return ( - <div> - {translate('quality_profiles.severity_set_to')}{' '} - <SeverityHelper severity={this.props.severity} /> - </div> - ); - } +export default function SeverityChange({ severity }: Props) { + return ( + <div> + {translate('quality_profiles.severity_set_to')} <SeverityHelper severity={severity} /> + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/Changelog-test.js b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/Changelog-test.tsx index 32774553ba1..ed8fb6b6106 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/Changelog-test.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/Changelog-test.tsx @@ -18,11 +18,12 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { shallow } from 'enzyme'; -import React from 'react'; +import * as React from 'react'; import Changelog from '../Changelog'; import ChangesList from '../ChangesList'; +import { IProfileChangelogEvent } from '../../types'; -function createEvent(overrides) { +function createEvent(overrides?: { [p: string]: any }): IProfileChangelogEvent { return { date: '2016-01-01', authorName: 'John', @@ -30,50 +31,51 @@ function createEvent(overrides) { ruleKey: 'squid1234', ruleName: 'Do not do this', params: {}, + organization: null, ...overrides }; } it('should render events', () => { const events = [createEvent(), createEvent()]; - const changelog = shallow(<Changelog events={events} />); + const changelog = shallow(<Changelog events={events} organization={null} />); expect(changelog.find('tbody').find('tr').length).toBe(2); }); it('should render event date', () => { const events = [createEvent()]; - const changelog = shallow(<Changelog events={events} />); + const changelog = shallow(<Changelog events={events} organization={null} />); expect(changelog.text()).toContain('2016'); }); it('should render author', () => { const events = [createEvent()]; - const changelog = shallow(<Changelog events={events} />); + const changelog = shallow(<Changelog events={events} organization={null} />); expect(changelog.text()).toContain('John'); }); it('should render system author', () => { const events = [createEvent({ authorName: undefined })]; - const changelog = shallow(<Changelog events={events} />); + const changelog = shallow(<Changelog events={events} organization={null} />); expect(changelog.text()).toContain('System'); }); it('should render action', () => { const events = [createEvent()]; - const changelog = shallow(<Changelog events={events} />); + const changelog = shallow(<Changelog events={events} organization={null} />); expect(changelog.text()).toContain('ACTIVATED'); }); it('should render rule', () => { const events = [createEvent()]; - const changelog = shallow(<Changelog events={events} />); + const changelog = shallow(<Changelog events={events} organization={null} />); expect(changelog.find('Link').prop('to')).toContain('rule_key=squid1234'); }); it('should render ChangesList', () => { const params = { severity: 'BLOCKER' }; const events = [createEvent({ params })]; - const changelog = shallow(<Changelog events={events} />); + const changelog = shallow(<Changelog events={events} organization={null} />); const changesList = changelog.find(ChangesList); expect(changesList.length).toBe(1); expect(changesList.prop('changes')).toBe(params); diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangelogSearch-test.js b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangelogSearch-test.tsx index be461db98d4..78dd87a4b9f 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangelogSearch-test.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangelogSearch-test.tsx @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { shallow } from 'enzyme'; -import React from 'react'; +import * as React from 'react'; import ChangelogSearch from '../ChangelogSearch'; import DateInput from '../../../../components/controls/DateInput'; import { click } from '../../../../helpers/testUtils'; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangesList-test.js b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangesList-test.tsx index 7ccb56ee199..82ddc9af0a0 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangesList-test.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangesList-test.tsx @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { shallow } from 'enzyme'; -import React from 'react'; +import * as React from 'react'; import ChangesList from '../ChangesList'; import SeverityChange from '../SeverityChange'; import ParameterChange from '../ParameterChange'; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ParameterChange-test.js b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ParameterChange-test.tsx index 25032b3e07a..de80150b085 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ParameterChange-test.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ParameterChange-test.tsx @@ -18,11 +18,11 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { shallow } from 'enzyme'; -import React from 'react'; +import * as React from 'react'; import ParameterChange from '../ParameterChange'; it('should render different messages', () => { - const first = shallow(<ParameterChange name="foo" />); + const first = shallow(<ParameterChange name="foo" value={null} />); const second = shallow(<ParameterChange name="foo" value="bar" />); expect(first.text()).not.toBe(second.text()); }); diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/SeverityChange-test.js b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/SeverityChange-test.tsx index 8597dd0ab8c..bc5f6553420 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/SeverityChange-test.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/SeverityChange-test.tsx @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { shallow } from 'enzyme'; -import React from 'react'; +import * as React from 'react'; import SeverityChange from '../SeverityChange'; import SeverityHelper from '../../../../components/shared/SeverityHelper'; 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.tsx index 718d80dcc3d..003fd55a6d3 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.tsx @@ -17,45 +17,45 @@ * 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 React from 'react'; -import PropTypes from 'prop-types'; +import * as React from 'react'; +import * as PropTypes from 'prop-types'; import ComparisonForm from './ComparisonForm'; import ComparisonResults from './ComparisonResults'; import { compareProfiles } from '../../../api/quality-profiles'; import { getProfileComparePath } from '../utils'; -/*:: 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 }, - right?: { name: string }, - inLeft?: Array<*>, - inRight?: Array<*>, - modified?: Array<*> -}; -*/ - -export default class ComparisonContainer extends React.PureComponent { - /*:: mounted: boolean; */ - /*:: props: Props; */ - /*:: state: State; */ +import { IProfile } from '../types'; + +interface Props { + location: { query: { withKey?: string } }; + organization: string | null; + profile: IProfile; + profiles: IProfile[]; +} + +type Params = { [p: string]: string }; + +interface State { + loading: boolean; + left?: { name: string }; + right?: { name: string }; + inLeft?: Array<{ key: string; name: string; severity: string }>; + inRight?: Array<{ key: string; name: string; severity: string }>; + modified?: Array<{ + key: string; + name: string; + left: { params: Params; severity: string }; + right: { params: Params; severity: string }; + }>; +} + +export default class ComparisonContainer extends React.PureComponent<Props, State> { + mounted: boolean; static contextTypes = { router: PropTypes.object }; - constructor(props /*: Props */) { + constructor(props: Props) { super(props); this.state = { loading: false }; } @@ -65,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(); } @@ -83,7 +83,7 @@ export default class ComparisonContainer extends React.PureComponent { } this.setState({ loading: true }); - compareProfiles(this.props.profile.key, withKey).then(r => { + compareProfiles(this.props.profile.key, withKey).then((r: any) => { if (this.mounted) { this.setState({ left: r.left, @@ -97,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, @@ -126,6 +126,10 @@ export default class ComparisonContainer extends React.PureComponent { </header> {left != null && + inLeft != null && + right != null && + inRight != null && + modified != null && <ComparisonResults left={left} right={right} diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonEmpty.js b/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonEmpty.tsx index b3a19a37f5c..a6a2c390289 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonEmpty.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonEmpty.tsx @@ -17,16 +17,13 @@ * 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 React from 'react'; +import * as React from 'react'; import { translate } from '../../../helpers/l10n'; -export default class ComparisonEmpty extends React.PureComponent { - render() { - return ( - <div className="big-spacer-top"> - {translate('quality_profile.empty_comparison')} - </div> - ); - } +export default function ComparisonEmpty() { + return ( + <div className="big-spacer-top"> + {translate('quality_profile.empty_comparison')} + </div> + ); } 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.tsx index c0a0086f006..11c4fb25639 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.tsx @@ -17,25 +17,20 @@ * 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 React from 'react'; -import Select from 'react-select'; +import * as React from 'react'; +import * as Select from 'react-select'; import { translate } from '../../../helpers/l10n'; -/*:: import type { Profile } from '../propTypes'; */ +import { IProfile } from '../types'; -/*:: -type Props = { - profile: Profile, - profiles: Array<Profile>, - onCompare: string => void, - withKey: string -}; -*/ - -export default class ComparisonForm extends React.PureComponent { - /*:: props: Props; */ +interface Props { + profile: IProfile; + profiles: IProfile[]; + onCompare: (rule: string) => void; + withKey?: string; +} - handleChange(option /*: { value: string } */) { +export default class ComparisonForm extends React.PureComponent<Props> { + 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.tsx index b13c88ecace..f29c2ec1c2b 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.tsx @@ -17,33 +17,31 @@ * 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 React from 'react'; +import * as React from 'react'; import { Link } from 'react-router'; import ComparisonEmpty from './ComparisonEmpty'; import SeverityIcon from '../../../components/shared/SeverityIcon'; import { translateWithParameters } from '../../../helpers/l10n'; import { getRulesUrl } from '../../../helpers/urls'; -/*:: -type Params = { [string]: string }; -*/ +type Params = { [p: string]: string }; -/*:: -type Props = { - left: { name: string }, - right: { name: string }, - inLeft: Array<*>, - inRight: Array<*>, - modified: Array<*>, - organization: ?string -}; -*/ - -export default class ComparisonResults extends React.PureComponent { - /*:: props: Props; */ +interface Props { + left: { name: string }; + right: { name: string }; + inLeft: Array<{ key: string; name: string; severity: string }>; + inRight: Array<{ key: string; name: string; severity: string }>; + modified: Array<{ + key: string; + name: string; + left: { params: Params; severity: string }; + right: { params: Params; severity: string }; + }>; + organization: string | null; +} - renderRule(rule /*: { key: string, name: string } */, severity /*: string */) { +export default class ComparisonResults extends React.PureComponent<Props> { + renderRule(rule: { key: string; name: string }, severity: string) { return ( <div> <SeverityIcon severity={severity} />{' '} @@ -52,7 +50,7 @@ export default class ComparisonResults extends React.PureComponent { ); } - renderParameters(params /*: Params */) { + renderParameters(params: Params) { if (!params) { return null; } @@ -135,7 +133,7 @@ export default class ComparisonResults extends React.PureComponent { } const header = ( <tr key="modified-header"> - <td colSpan="2" className="text-center"> + <td colSpan={2} className="text-center"> <h6> {translateWithParameters( 'quality_profiles.x_rules_have_different_configuration', diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/compare/__tests__/ComparisonForm-test.js b/server/sonar-web/src/main/js/apps/quality-profiles/compare/__tests__/ComparisonForm-test.tsx index b972451e628..55edbd993fe 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/compare/__tests__/ComparisonForm-test.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/compare/__tests__/ComparisonForm-test.tsx @@ -18,8 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { shallow } from 'enzyme'; -import React from 'react'; -import Select from 'react-select'; +import * as React from 'react'; import ComparisonForm from '../ComparisonForm'; import { createFakeProfile } from '../../utils'; @@ -38,7 +37,7 @@ it('should render Select with right options', () => { profiles={profiles} onCompare={() => true} /> - ).find(Select); + ).find('Select'); expect(output.length).toBe(1); expect(output.prop('value')).toBe('another'); expect(output.prop('options')).toEqual([{ value: 'another', label: 'another name' }]); diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/compare/__tests__/ComparisonResults-test.js b/server/sonar-web/src/main/js/apps/quality-profiles/compare/__tests__/ComparisonResults-test.tsx index d346aa2f480..c3200b06612 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/compare/__tests__/ComparisonResults-test.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/compare/__tests__/ComparisonResults-test.tsx @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { shallow } from 'enzyme'; -import React from 'react'; +import * as React from 'react'; import { Link } from 'react-router'; import ComparisonResults from '../ComparisonResults'; import ComparisonEmpty from '../ComparisonEmpty'; @@ -32,6 +32,7 @@ it('should render ComparisonEmpty', () => { inLeft={[]} inRight={[]} modified={[]} + organization={null} /> ); expect(output.is(ComparisonEmpty)).toBe(true); @@ -65,6 +66,7 @@ it('should compare', () => { inLeft={inLeft} inRight={inRight} modified={modified} + organization={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.tsx index b0f80ee623b..44013b73e70 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.tsx @@ -17,37 +17,31 @@ * 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 React from 'react'; +import * as React from 'react'; import { searchQualityProfiles, getExporters } from '../../../api/quality-profiles'; import { sortProfiles } from '../utils'; import { translate } from '../../../helpers/l10n'; import OrganizationHelmet from '../../../components/common/OrganizationHelmet'; -/*:: import type { Exporter } from '../propTypes'; */ import '../styles.css'; +import { IExporter, IProfile } from '../types'; -/*:: -type Props = { - children: React.Element<*>, - currentUser: { permissions: { global: Array<string> } }, - languages: Array<*>, - onRequestFail: Object => void, - organization: { name: string, canAdmin?: boolean, key: string } | null -}; -*/ +interface Props { + children: React.ReactElement<any>; + currentUser: { permissions: { global: Array<string> } }; + languages: Array<{}>; + onRequestFail: (reasong: any) => void; + organization: { name: string; canAdmin?: boolean; key: string } | null; +} -/*:: -type State = { - loading: boolean, - exporters?: Array<Exporter>, - profiles?: Array<*> -}; -*/ +interface State { + loading: boolean; + exporters?: IExporter[]; + profiles?: IProfile[]; +} -export default class App extends React.PureComponent { - /*:: mounted: boolean; */ - /*:: props: Props; */ - state /*: State */ = { loading: true }; +export default class App extends React.PureComponent<Props, State> { + mounted: boolean; + state: State = { loading: true }; componentWillMount() { const html = document.querySelector('html'); @@ -90,7 +84,7 @@ export default class App extends React.PureComponent { } updateProfiles = () => { - return this.fetchProfiles().then(profiles => { + return this.fetchProfiles().then((profiles: any) => { if (this.mounted) { this.setState({ profiles: sortProfiles(profiles) }); } diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/components/AppContainer.js b/server/sonar-web/src/main/js/apps/quality-profiles/components/AppContainer.tsx index a9809ffe0dc..9eb3af6d784 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/components/AppContainer.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/components/AppContainer.tsx @@ -22,7 +22,7 @@ import App from './App'; import { getLanguages, getCurrentUser, getOrganizationByKey } from '../../../store/rootReducer'; import { onFail } from '../../../store/rootActions'; -const mapStateToProps = (state, ownProps) => ({ +const mapStateToProps = (state: any, ownProps: any) => ({ currentUser: getCurrentUser(state), languages: getLanguages(state), organization: ownProps.params.organizationKey @@ -30,8 +30,8 @@ const mapStateToProps = (state, ownProps) => ({ : null }); -const mapDispatchToProps = dispatch => ({ - onRequestFail: error => onFail(dispatch)(error) +const mapDispatchToProps = (dispatch: any) => ({ + onRequestFail: (error: any) => onFail(dispatch)(error) }); -export default connect(mapStateToProps, mapDispatchToProps)(App); +export default connect(mapStateToProps, mapDispatchToProps)(App as any); 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.tsx index fa2e1635620..7a70614d3e5 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.tsx @@ -17,22 +17,19 @@ * 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 React from 'react'; -import classNames from 'classnames'; +import * as React from 'react'; +import * as classNames from 'classnames'; import Tooltip from '../../../components/controls/Tooltip'; import { translate } from '../../../helpers/l10n'; -/*:: -type Props = {| - className?: string, - tooltip?: boolean -|}; -*/ +interface Props { + className?: string; + tooltip?: boolean; +} -export default function BuiltInBadge(props /*: Props */) { +export default function BuiltInBadge({ className, tooltip = true }: Props) { const badge = ( - <div className={classNames('outline-badge', props.className)}> + <div className={classNames('outline-badge', className)}> {translate('quality_profiles.built_in')} </div> ); @@ -44,13 +41,9 @@ export default function BuiltInBadge(props /*: Props */) { </span> ); - return props.tooltip + return tooltip ? <Tooltip overlay={overlay}> {badge} </Tooltip> : badge; } - -BuiltInBadge.defaultProps = { - tooltip: true -}; 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.tsx index 4ad268e4982..4d24898081d 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.tsx @@ -17,33 +17,27 @@ * 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 React from 'react'; +import * as React from 'react'; import Modal from 'react-modal'; -/*:: import type { Profile } from '../propTypes'; */ import { copyProfile } from '../../../api/quality-profiles'; import { translate, translateWithParameters } from '../../../helpers/l10n'; +import { IProfile } from '../types'; -/*:: -type Props = { - onClose: () => void, - onCopy: string => void, - onRequestFail: Object => void, - profile: Profile -}; -*/ +interface Props { + onClose: () => void; + onCopy: (name: string) => void; + onRequestFail: (reasong: any) => void; + profile: IProfile; +} -/*:: -type State = { - loading: boolean, - name: ?string -}; -*/ +interface State { + loading: boolean; + name: string | null; +} -export default class CopyProfileForm extends React.PureComponent { - /*:: mounted: boolean; */ - /*:: props: Props; */ - state /*: State */ = { loading: false, name: null }; +export default class CopyProfileForm extends React.PureComponent<Props, State> { + mounted: boolean; + state: State = { loading: false, name: null }; componentDidMount() { this.mounted = true; @@ -53,16 +47,16 @@ export default class CopyProfileForm extends React.PureComponent { this.mounted = false; } - handleCancelClick = (event /*: Event */) => { + handleCancelClick = (event: React.SyntheticEvent<HTMLElement>) => { event.preventDefault(); this.props.onClose(); }; - handleNameChange = (event /*: { currentTarget: HTMLInputElement } */) => { + handleNameChange = (event: React.SyntheticEvent<HTMLInputElement>) => { this.setState({ name: event.currentTarget.value }); }; - handleFormSubmit = (event /*: Event */) => { + handleFormSubmit = (event: React.SyntheticEvent<HTMLElement>) => { event.preventDefault(); const { name } = this.state; @@ -70,8 +64,8 @@ export default class CopyProfileForm extends React.PureComponent { if (name != null) { this.setState({ loading: true }); copyProfile(this.props.profile.key, name).then( - profile => this.props.onCopy(profile.name), - error => { + (profile: any) => this.props.onCopy(profile.name), + (error: any) => { if (this.mounted) { this.setState({ loading: false }); } @@ -113,11 +107,11 @@ export default class CopyProfileForm extends React.PureComponent { <input autoFocus={true} id="copy-profile-name" - maxLength="100" + maxLength={100} name="name" onChange={this.handleNameChange} required={true} - size="50" + size={50} type="text" value={this.state.name != null ? this.state.name : profile.name} /> 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.tsx index 975ca0a32db..5a7b22719db 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.tsx @@ -17,32 +17,27 @@ * 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 React from 'react'; +import * as React from 'react'; import Modal from 'react-modal'; -/*:: import type { Profile } from '../propTypes'; */ import { deleteProfile } from '../../../api/quality-profiles'; import { translate, translateWithParameters } from '../../../helpers/l10n'; +import { IProfile } from '../types'; -/*:: -type Props = { - onClose: () => void, - onDelete: () => void, - onRequestFail: Object => void, - profile: Profile -}; -*/ +interface Props { + onClose: () => void; + onDelete: () => void; + onRequestFail: (reason: any) => void; + profile: IProfile; +} -/*:: -type State = { - loading: boolean -}; -*/ +interface State { + loading: boolean; + name: string | null; +} -export default class DeleteProfileForm extends React.PureComponent { - /*:: mounted: boolean; */ - /*:: props: Props; */ - state /*: State */ = { loading: false, name: null }; +export default class DeleteProfileForm extends React.PureComponent<Props, State> { + mounted: boolean; + state: State = { loading: false, name: null }; componentDidMount() { this.mounted = true; @@ -52,15 +47,15 @@ export default class DeleteProfileForm extends React.PureComponent { this.mounted = false; } - handleCancelClick = (event /*: Event */) => { + handleCancelClick = (event: React.SyntheticEvent<HTMLElement>) => { event.preventDefault(); this.props.onClose(); }; - handleFormSubmit = (event /*: Event */) => { + handleFormSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => { event.preventDefault(); this.setState({ loading: true }); - deleteProfile(this.props.profile.key).then(this.props.onDelete, error => { + deleteProfile(this.props.profile.key).then(this.props.onDelete, (error: any) => { if (this.mounted) { this.setState({ loading: false }); } 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.tsx index 8a2b2f805f0..6d1ad5c0120 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.tsx @@ -17,9 +17,8 @@ * 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 React from 'react'; -import PropTypes from 'prop-types'; +import * as React from 'react'; +import * as PropTypes from 'prop-types'; import { Link } from 'react-router'; import RenameProfileForm from './RenameProfileForm'; import CopyProfileForm from './CopyProfileForm'; @@ -28,31 +27,24 @@ 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'; */ - -/*:: -type Props = { - canAdmin: boolean, - fromList: boolean, - onRequestFail: Object => void, - organization: ?string, - profile: Profile, - updateProfiles: () => Promise<*> -}; -*/ - -/*:: -type State = { - copyFormOpen: boolean, - deleteFormOpen: boolean, - renameFormOpen: boolean -}; -*/ - -export default class ProfileActions extends React.PureComponent { - /*:: props: Props; */ - /*:: state: State; */ +import { IProfile } from '../types'; + +interface Props { + canAdmin: boolean; + fromList?: boolean; + onRequestFail: (reasong: any) => void; + organization: string | null; + profile: IProfile; + updateProfiles: () => Promise<void>; +} + +interface State { + copyFormOpen: boolean; + deleteFormOpen: boolean; + renameFormOpen: boolean; +} +export default class ProfileActions extends React.PureComponent<Props, State> { static defaultProps = { fromList: false }; @@ -61,7 +53,7 @@ export default class ProfileActions extends React.PureComponent { router: PropTypes.object }; - constructor(props /*: Props */) { + constructor(props: Props) { super(props); this.state = { copyFormOpen: false, @@ -70,12 +62,12 @@ export default class ProfileActions extends React.PureComponent { }; } - handleRenameClick = (event /*: Event */) => { + handleRenameClick = (event: React.SyntheticEvent<HTMLElement>) => { event.preventDefault(); this.setState({ renameFormOpen: true }); }; - handleProfileRename = (name /*: string */) => { + handleProfileRename = (name: string) => { this.closeRenameForm(); this.props.updateProfiles().then(() => { if (!this.props.fromList) { @@ -90,12 +82,12 @@ export default class ProfileActions extends React.PureComponent { this.setState({ renameFormOpen: false }); }; - handleCopyClick = (event /*: Event */) => { + handleCopyClick = (event: React.SyntheticEvent<HTMLElement>) => { 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) @@ -107,12 +99,12 @@ export default class ProfileActions extends React.PureComponent { this.setState({ copyFormOpen: false }); }; - handleSetDefaultClick = (e /*: SyntheticInputEvent */) => { + handleSetDefaultClick = (e: React.SyntheticEvent<HTMLElement>) => { e.preventDefault(); setDefaultProfile(this.props.profile.key).then(this.props.updateProfiles); }; - handleDeleteClick = (event /*: Event */) => { + handleDeleteClick = (event: React.SyntheticEvent<HTMLElement>) => { event.preventDefault(); this.setState({ deleteFormOpen: true }); }; @@ -131,7 +123,9 @@ export default class ProfileActions extends React.PureComponent { // FIXME use org, name and lang const backupUrl = - window.baseUrl + '/api/qualityprofiles/backup?profileKey=' + encodeURIComponent(profile.key); + (window as any).baseUrl + + '/api/qualityprofiles/backup?profileKey=' + + encodeURIComponent(profile.key); const activateMoreUrl = getRulesUrl( { 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.tsx index f44f53c9e35..ee6d302acdd 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.tsx @@ -17,32 +17,27 @@ * 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 React from 'react'; +import * as React from 'react'; import Helmet from 'react-helmet'; import ProfileNotFound from './ProfileNotFound'; import ProfileHeader from '../details/ProfileHeader'; -/*:: import type { Profile } from '../propTypes'; */ +import { IProfile } from '../types'; -/*:: -type Props = { - canAdmin: boolean, - children: React.Element<*>, +interface Props { + canAdmin: boolean; + children: React.ReactElement<any>; location: { - pathname: string, - query: { key?: string, language: string, name: string } - }, - onRequestFail: Object => void, - organization: ?string, - profiles: Array<Profile>, - router: { replace: ({}) => void }, - updateProfiles: () => Promise<*> -}; -*/ - -export default class ProfileContainer extends React.PureComponent { - /*:: props: Props; */ + pathname: string; + query: { key?: string; language: string; name: string }; + }; + onRequestFail: (reasong: any) => void; + organization: string | null; + profiles: IProfile[]; + router: { replace: ({}) => void }; + updateProfiles: () => Promise<void>; +} +export default class ProfileContainer extends React.PureComponent<Props> { componentDidMount() { const { location, profiles, router } = this.props; if (location.query.key) { 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.tsx index ae878a4ba6b..947b15e419c 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.tsx @@ -17,35 +17,20 @@ * 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 React from 'react'; -import moment from 'moment'; +import * as React from 'react'; +import * as moment from 'moment'; import { translate } from '../../../helpers/l10n'; -/*:: -type Props = { - date?: string -}; -*/ - -export default class ProfileDate extends React.PureComponent { - /*:: props: Props; */ - - render() { - const { date } = this.props; - - if (!date) { - return ( - <span> - {translate('never')} - </span> - ); - } +interface Props { + date?: string; +} - return ( - <span title={moment(date).format('LLL')} data-toggle="tooltip"> +export default function ProfileDate({ date }: Props) { + return date + ? <span title={moment(date).format('LLL')} data-toggle="tooltip"> {moment(date).fromNow()} </span> - ); - } + : <span> + {translate('never')} + </span>; } 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.tsx index 2ff0534c108..8b69532ad74 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.tsx @@ -17,32 +17,25 @@ * 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 React from 'react'; +import * as 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; */ +interface Props { + className?: string; + children?: React.ReactElement<any> | string; + language: string; + name: string; + organization: string | null; +} - render() { - const { name, language, organization, children, ...other } = this.props; - return ( - <Link - to={getProfilePath(name, language, organization)} - activeClassName="link-no-underline" - {...other}> - {children} - </Link> - ); - } +export default function ProfileLink({ name, language, organization, children, ...other }: Props) { + return ( + <Link + to={getProfilePath(name, language, organization)} + activeClassName="link-no-underline" + {...other}> + {children} + </Link> + ); } 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.tsx index 7dce1cc0ce1..a6fd496502c 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.tsx @@ -17,34 +17,27 @@ * 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 React from 'react'; +import * as React from 'react'; 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; */ +interface Props { + organization: string | null; +} - render() { - return ( - <div className="quality-profile-not-found"> - <div className="note spacer-bottom"> - <IndexLink to={getProfilesPath(this.props.organization)} className="text-muted"> - {translate('quality_profiles.page')} - </IndexLink> - </div> +export default function ProfileNotFound(props: Props) { + return ( + <div className="quality-profile-not-found"> + <div className="note spacer-bottom"> + <IndexLink to={getProfilesPath(props.organization)} className="text-muted"> + {translate('quality_profiles.page')} + </IndexLink> + </div> - <div> - {translate('quality_profiles.not_found')} - </div> + <div> + {translate('quality_profiles.not_found')} </div> - ); - } + </div> + ); } 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.tsx index 37d63394d21..1d1491975ec 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.tsx @@ -17,33 +17,27 @@ * 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 React from 'react'; +import * as React from 'react'; import Modal from 'react-modal'; -/*:: import type { Profile } from '../propTypes'; */ import { renameProfile } from '../../../api/quality-profiles'; import { translate, translateWithParameters } from '../../../helpers/l10n'; +import { IProfile } from '../types'; -/*:: -type Props = { - onClose: () => void, - onRename: string => void, - onRequestFail: Object => void, - profile: Profile -}; -*/ +interface Props { + onClose: () => void; + onRename: (name: string) => void; + onRequestFail: (reason: any) => void; + profile: IProfile; +} -/*:: -type State = { - loading: boolean, - name: ?string -}; -*/ +interface State { + loading: boolean; + name: string | null; +} -export default class RenameProfileForm extends React.PureComponent { - /*:: mounted: boolean; */ - /*:: props: Props; */ - state /*: State */ = { loading: false, name: null }; +export default class RenameProfileForm extends React.PureComponent<Props, State> { + mounted: boolean; + state: State = { loading: false, name: null }; componentDidMount() { this.mounted = true; @@ -53,16 +47,16 @@ export default class RenameProfileForm extends React.PureComponent { this.mounted = false; } - handleCancelClick = (event /*: Event */) => { + handleCancelClick = (event: React.SyntheticEvent<HTMLElement>) => { event.preventDefault(); this.props.onClose(); }; - handleNameChange = (event /*: { currentTarget: HTMLInputElement } */) => { + handleNameChange = (event: React.SyntheticEvent<HTMLInputElement>) => { this.setState({ name: event.currentTarget.value }); }; - handleFormSubmit = (event /*: Event */) => { + handleFormSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => { event.preventDefault(); const { name } = this.state; @@ -71,7 +65,7 @@ export default class RenameProfileForm extends React.PureComponent { this.setState({ loading: true }); renameProfile(this.props.profile.key, name).then( () => this.props.onRename(name), - error => { + (error: any) => { if (this.mounted) { this.setState({ loading: false }); } @@ -113,11 +107,11 @@ export default class RenameProfileForm extends React.PureComponent { <input autoFocus={true} id="rename-profile-name" - maxLength="100" + maxLength={100} name="name" onChange={this.handleNameChange} required={true} - size="50" + size={50} type="text" value={this.state.name != null ? this.state.name : profile.name} /> diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/components/__tests__/ProfileContainer-test.js b/server/sonar-web/src/main/js/apps/quality-profiles/components/__tests__/ProfileContainer-test.tsx index 08aa98c6b32..1c0efc638ab 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/components/__tests__/ProfileContainer-test.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/components/__tests__/ProfileContainer-test.tsx @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { shallow } from 'enzyme'; -import React from 'react'; +import * as React from 'react'; import Helmet from 'react-helmet'; import ProfileContainer from '../ProfileContainer'; import ProfileNotFound from '../ProfileNotFound'; @@ -31,9 +31,12 @@ it('should render ProfileHeader', () => { const updateProfiles = jest.fn(); const output = shallow( <ProfileContainer - location={{ query: { language: 'js', name: 'fake' } }} - profiles={profiles} canAdmin={false} + location={{ pathname: '', query: { language: 'js', name: 'fake' } }} + onRequestFail={jest.fn()} + organization={null} + profiles={profiles} + router={{} as any} updateProfiles={updateProfiles}> <div /> </ProfileContainer> @@ -52,10 +55,13 @@ it('should render ProfileNotFound', () => { ]; const output = shallow( <ProfileContainer - location={{ query: { language: 'js', name: 'random' } }} - profiles={profiles} canAdmin={false} - updateProfiles={() => true}> + location={{ pathname: '', query: { language: 'js', name: 'random' } }} + onRequestFail={jest.fn()} + organization={null} + profiles={profiles} + router={{} as any} + updateProfiles={jest.fn()}> <div /> </ProfileContainer> ); @@ -67,9 +73,12 @@ it('should render Helmet', () => { const updateProfiles = jest.fn(); const output = shallow( <ProfileContainer - location={{ query: { language: 'js', name: 'First Profile' } }} - profiles={profiles} canAdmin={false} + location={{ pathname: '', query: { language: 'js', name: 'First Profile' } }} + onRequestFail={jest.fn()} + organization={null} + profiles={profiles} + router={{} as any} updateProfiles={updateProfiles}> <div /> </ProfileContainer> 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.tsx index f7d019e63d8..fd8292c7d97 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.tsx @@ -17,36 +17,30 @@ * 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 React from 'react'; +import * as React from 'react'; import Modal from 'react-modal'; -import Select from 'react-select'; +import * as 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 { IProfile } from '../types'; -/*:: -type Props = { - onChange: () => void, - onClose: () => void, - onRequestFail: Object => void, - profile: Profile, - profiles: Array<Profile> -}; -*/ +interface Props { + onChange: () => void; + onClose: () => void; + onRequestFail: (reasong: any) => void; + profile: IProfile; + profiles: IProfile[]; +} -/*:: -type State = { - loading: boolean, - selected: ?string -}; -*/ +interface State { + loading: boolean; + selected: string | null; +} -export default class ChangeParentForm extends React.PureComponent { - /*:: mounted: boolean; */ - /*:: props: Props; */ - state /*: State */ = { +export default class ChangeParentForm extends React.PureComponent<Props, State> { + mounted: boolean; + state: State = { loading: false, selected: null }; @@ -59,28 +53,30 @@ export default class ChangeParentForm extends React.PureComponent { this.mounted = false; } - handleCancelClick = (event /*: Event */) => { + handleCancelClick = (event: React.SyntheticEvent<HTMLElement>) => { event.preventDefault(); this.props.onClose(); }; - handleSelectChange = (option /*: { value: string } */) => { + handleSelectChange = (option: { value: string }) => { this.setState({ selected: option.value }); }; - handleFormSubmit = (event /*: Event */) => { + handleFormSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => { event.preventDefault(); const parent = this.state.selected; if (parent != null) { this.setState({ loading: true }); - changeProfileParent(this.props.profile.key, parent).then(this.props.onChange).catch(error => { - if (this.mounted) { - this.setState({ loading: false }); - } - this.props.onRequestFail(error); - }); + changeProfileParent(this.props.profile.key, parent) + .then(this.props.onChange) + .catch((error: any) => { + if (this.mounted) { + this.setState({ loading: false }); + } + this.props.onRequestFail(error); + }); } }; @@ -122,7 +118,6 @@ export default class ChangeParentForm extends React.PureComponent { </label> <Select clearable={false} - id="change-profile-parent" name="parentKey" onChange={this.handleSelectChange} options={options} 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.tsx index a3277635118..19085883c03 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.tsx @@ -17,27 +17,23 @@ * 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 React from 'react'; +import * as React from 'react'; import Modal from 'react-modal'; -import escapeHtml from 'escape-html'; -/*:: import type { Profile } from '../propTypes'; */ +import * as escapeHtml from 'escape-html'; import SelectList from '../../../components/SelectList'; import { translate } from '../../../helpers/l10n'; +import { IProfile } from '../types'; -/*:: -type Props = { - onClose: () => void, - organization: ?string, - profile: Profile -}; -*/ +interface Props { + onClose: () => void; + organization: string | null; + profile: IProfile; +} -export default class ChangeProjectsForm extends React.PureComponent { - /*:: container: HTMLElement; */ - /*:: props: Props; */ +export default class ChangeProjectsForm extends React.PureComponent<Props> { + container: HTMLElement; - handleCloseClick = (event /*: Event */) => { + handleCloseClick = (event: React.SyntheticEvent<HTMLElement>) => { event.preventDefault(); this.props.onClose(); }; @@ -46,17 +42,17 @@ export default class ChangeProjectsForm extends React.PureComponent { const { key } = this.props.profile; const searchUrl = - window.baseUrl + '/api/qualityprofiles/projects?key=' + encodeURIComponent(key); + (window as any).baseUrl + '/api/qualityprofiles/projects?key=' + encodeURIComponent(key); - new SelectList({ + new (SelectList as any)({ searchUrl, el: this.container, width: '100%', readOnly: false, focusSearch: false, - dangerouslyUnescapedHtmlFormat: item => escapeHtml(item.name), - selectUrl: window.baseUrl + '/api/qualityprofiles/add_project', - deselectUrl: window.baseUrl + '/api/qualityprofiles/remove_project', + dangerouslyUnescapedHtmlFormat: (item: { name: string }) => escapeHtml(item.name), + selectUrl: (window as any).baseUrl + '/api/qualityprofiles/add_project', + deselectUrl: (window as any).baseUrl + '/api/qualityprofiles/remove_project', extra: { profileKey: key }, selectParameter: 'projectUuid', selectParameterValue: 'uuid', @@ -91,7 +87,7 @@ export default class ChangeProjectsForm extends React.PureComponent { </div> <div className="modal-body"> - <div id="profile-projects" ref={node => (this.container = node)} /> + <div id="profile-projects" ref={node => (this.container = node as HTMLElement)} /> </div> <div className="modal-foot"> 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.tsx index b157db49a68..a01130a889b 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.tsx @@ -17,43 +17,36 @@ * 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 React from 'react'; +import * as React from 'react'; import ProfileRules from './ProfileRules'; import ProfileProjects from './ProfileProjects'; import ProfileInheritance from './ProfileInheritance'; import ProfileExporters from './ProfileExporters'; -/*:: import type { Profile, Exporter } from '../propTypes'; */ +import { IExporter, IProfile } from '../types'; -/*:: -type Props = { - canAdmin: boolean, - exporters: Array<Exporter>, - onRequestFail: Object => void, - organization: ?string, - profile: Profile, - profiles: Array<Profile>, - updateProfiles: () => Promise<*> -}; -*/ - -export default class ProfileDetails extends React.PureComponent { - /*:: props: Props; */ +interface Props { + canAdmin: boolean; + exporters: IExporter[]; + onRequestFail: (reasong: any) => void; + organization: string | null; + profile: IProfile; + profiles: IProfile[]; + updateProfiles: () => Promise<void>; +} - render() { - return ( - <div> - <div className="quality-profile-grid"> - <div className="quality-profile-grid-left"> - <ProfileRules {...this.props} /> - <ProfileExporters {...this.props} /> - </div> - <div className="quality-profile-grid-right"> - <ProfileInheritance {...this.props} /> - <ProfileProjects {...this.props} /> - </div> +export default function ProfileDetails(props: Props) { + return ( + <div> + <div className="quality-profile-grid"> + <div className="quality-profile-grid-left"> + <ProfileRules {...props} /> + <ProfileExporters {...props} /> + </div> + <div className="quality-profile-grid-right"> + <ProfileInheritance {...props} /> + <ProfileProjects {...props} /> </div> </div> - ); - } + </div> + ); } 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.tsx index 04f3c58df29..71913fae114 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.tsx @@ -17,28 +17,23 @@ * 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 { stringify } from 'querystring'; -import React from 'react'; +import * as React from 'react'; import { translate } from '../../../helpers/l10n'; -/*:: import type { Profile, Exporter } from '../propTypes'; */ +import { IProfile, IExporter } from '../types'; -/*:: -type Props = { - exporters: Array<Exporter>, - organization: ?string, - profile: Profile -}; -*/ - -export default class ProfileExporters extends React.PureComponent { - /*:: props: Props; */ +interface Props { + exporters: IExporter[]; + organization: string | null; + profile: IProfile; +} - getExportUrl(exporter /*: Exporter */) { +export default class ProfileExporters extends React.PureComponent<Props> { + getExportUrl(exporter: IExporter) { const { organization, profile } = this.props; const path = '/api/qualityprofiles/export'; - const parameters /*: { [string]: string } */ = { + const parameters = { exporterKey: exporter.key, language: profile.language, name: profile.name @@ -46,7 +41,7 @@ export default class ProfileExporters extends React.PureComponent { if (organization) { Object.assign(parameters, { organization }); } - return window.baseUrl + path + '?' + stringify(parameters); + return (window as any).baseUrl + path + '?' + stringify(parameters); } render() { 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.tsx index f5691c5ccea..ba0598251d6 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.tsx @@ -17,8 +17,7 @@ * 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 React from 'react'; +import * as React from 'react'; import { Link, IndexLink } from 'react-router'; import ProfileLink from '../components/ProfileLink'; import ProfileActions from '../components/ProfileActions'; @@ -31,21 +30,17 @@ import { getProfilesForLanguagePath, getProfileChangelogPath } from '../utils'; -/*:: import type { Profile } from '../propTypes'; */ +import { IProfile } from '../types'; -/*:: -type Props = { - canAdmin: boolean, - onRequestFail: Object => void, - organization: ?string, - profile: Profile, - updateProfiles: () => Promise<*> -}; -*/ - -export default class ProfileHeader extends React.PureComponent { - /*:: props: Props; */ +interface Props { + canAdmin: boolean; + onRequestFail: (reasong: any) => void; + profile: IProfile; + organization: string | null; + updateProfiles: () => Promise<void>; +} +export default class ProfileHeader extends React.PureComponent<Props> { renderUpdateDate() { const { profile } = this.props; let inner = ( 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.tsx index 9669bd0aa11..a7c6173deec 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.tsx @@ -17,51 +17,44 @@ * 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 React from 'react'; -import classNames from 'classnames'; +import * as React from 'react'; +import * as classNames from 'classnames'; import ProfileInheritanceBox from './ProfileInheritanceBox'; import ChangeParentForm from './ChangeParentForm'; import { translate } from '../../../helpers/l10n'; import { getProfileInheritance } from '../../../api/quality-profiles'; -/*:: import type { Profile } from '../propTypes'; */ - -/*:: -type Props = { - canAdmin: boolean, - onRequestFail: Object => void, - organization: ?string, - profile: Profile, - profiles: Array<Profile>, - updateProfiles: () => Promise<*> -}; -*/ - -/*:: -type ProfileInheritanceDetails = { - activeRuleCount: number, - isBuiltIn: boolean, - key: string, - language: string, - name: string, - overridingRuleCount?: number -}; -*/ - -/*:: -type State = { - ancestors?: Array<ProfileInheritanceDetails>, - children?: Array<ProfileInheritanceDetails>, - formOpen: boolean, - loading: boolean, - profile?: ProfileInheritanceDetails -}; -*/ - -export default class ProfileInheritance extends React.PureComponent { - /*:: mounted: boolean; */ - /*:: props: Props; */ - state /*: State */ = { +import { IProfile } from '../types'; + +interface Props { + canAdmin: boolean; + onRequestFail: (reason: any) => void; + organization: string | null; + profile: IProfile; + profiles: IProfile[]; + updateProfiles: () => Promise<void>; +} + +interface ProfileInheritanceDetails { + activeRuleCount: number; + isBuiltIn: boolean; + key: string; + language: string; + name: string; + overridingRuleCount?: number; +} + +interface State { + ancestors?: Array<ProfileInheritanceDetails>; + children?: Array<ProfileInheritanceDetails>; + formOpen: boolean; + loading: boolean; + profile?: ProfileInheritanceDetails; +} + +export default class ProfileInheritance extends React.PureComponent<Props, State> { + mounted: boolean; + + state: State = { formOpen: false, loading: true }; @@ -71,7 +64,7 @@ export default class ProfileInheritance extends React.PureComponent { this.loadData(); } - componentDidUpdate(prevProps /*: Props */) { + componentDidUpdate(prevProps: Props) { if (prevProps.profile !== this.props.profile) { this.loadData(); } @@ -82,7 +75,7 @@ export default class ProfileInheritance extends React.PureComponent { } loadData() { - getProfileInheritance(this.props.profile.key).then(r => { + getProfileInheritance(this.props.profile.key).then((r: any) => { if (this.mounted) { const { ancestors, children } = r; this.setState({ @@ -95,7 +88,7 @@ export default class ProfileInheritance extends React.PureComponent { }); } - handleChangeParentClick = (event /*: Event */) => { + handleChangeParentClick = (event: React.SyntheticEvent<HTMLElement>) => { event.preventDefault(); this.setState({ formOpen: true }); }; @@ -153,15 +146,16 @@ export default class ProfileInheritance extends React.PureComponent { /> )} - <ProfileInheritanceBox - className={currentClassName} - depth={ancestors ? ancestors.length : 0} - displayLink={false} - extendsBuiltIn={extendsBuiltIn} - language={profile.language} - organization={this.props.organization} - profile={this.state.profile} - /> + {this.state.profile != null && + <ProfileInheritanceBox + className={currentClassName} + depth={ancestors ? ancestors.length : 0} + displayLink={false} + extendsBuiltIn={extendsBuiltIn} + language={profile.language} + organization={this.props.organization} + profile={this.state.profile} + />} {this.state.children != null && this.state.children.map(child => 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 deleted file mode 100644 index 1adf7c7322b..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritanceBox.js +++ /dev/null @@ -1,93 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * 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 React from 'react'; -import ProfileLink from '../components/ProfileLink'; -import BuiltInBadge from '../components/BuiltInBadge'; -import Tooltip from '../../../components/controls/Tooltip'; -import { translate, translateWithParameters } from '../../../helpers/l10n'; - -/*:: -type Props = {| - className?: string, - depth: number, - displayLink?: boolean, - extendsBuiltIn?: boolean, - language: string, - organization: ?string, - profile: { - activeRuleCount: number, - isBuiltIn: boolean, - key: string, - language: string, - name: string, - overridingRuleCount?: number - } -|}; -*/ - -export default class ProfileInheritanceBox extends React.PureComponent { - /*:: props: Props; */ - - static defaultProps = { - displayLink: true - }; - - render() { - const { profile, className, extendsBuiltIn } = this.props; - const offset = 25 * this.props.depth; - - return ( - <tr className={className}> - <td> - <div style={{ paddingLeft: offset }}> - {this.props.displayLink - ? <ProfileLink - language={this.props.language} - name={profile.name} - organization={this.props.organization}> - {profile.name} - </ProfileLink> - : profile.name} - {profile.isBuiltIn && <BuiltInBadge className="spacer-left" />} - {extendsBuiltIn && - <Tooltip overlay={translate('quality_profiles.extends_built_in')}> - <i className="icon-help spacer-left" /> - </Tooltip>} - </div> - </td> - - <td> - {translateWithParameters('quality_profile.x_active_rules', profile.activeRuleCount)} - </td> - - <td> - {profile.overridingRuleCount != null && - <p> - {translateWithParameters( - 'quality_profiles.x_overridden_rules', - profile.overridingRuleCount - )} - </p>} - </td> - </tr> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritanceBox.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritanceBox.tsx new file mode 100644 index 00000000000..2455e39ae03 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritanceBox.tsx @@ -0,0 +1,82 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import ProfileLink from '../components/ProfileLink'; +import BuiltInBadge from '../components/BuiltInBadge'; +import Tooltip from '../../../components/controls/Tooltip'; +import { translate, translateWithParameters } from '../../../helpers/l10n'; + +interface Props { + className?: string; + depth: number; + displayLink?: boolean; + extendsBuiltIn?: boolean; + language: string; + organization: string | null; + profile: { + activeRuleCount: number; + isBuiltIn: boolean; + key: string; + language: string; + name: string; + overridingRuleCount?: number; + }; +} + +export default function ProfileInheritanceBox({ displayLink = true, ...props }: Props) { + const { profile, className, extendsBuiltIn } = props; + const offset = 25 * props.depth; + + return ( + <tr className={className}> + <td> + <div style={{ paddingLeft: offset }}> + {displayLink + ? <ProfileLink + language={props.language} + name={profile.name} + organization={props.organization}> + {profile.name} + </ProfileLink> + : profile.name} + {profile.isBuiltIn && <BuiltInBadge className="spacer-left" />} + {extendsBuiltIn && + <Tooltip overlay={translate('quality_profiles.extends_built_in')}> + <i className="icon-help spacer-left" /> + </Tooltip>} + </div> + </td> + + <td> + {translateWithParameters('quality_profile.x_active_rules', profile.activeRuleCount)} + </td> + + <td> + {profile.overridingRuleCount != null && + <p> + {translateWithParameters( + 'quality_profiles.x_overridden_rules', + profile.overridingRuleCount + )} + </p>} + </td> + </tr> + ); +} 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.tsx index 984b7995b0f..92d30c277ba 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.tsx @@ -17,37 +17,32 @@ * 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 React from 'react'; +import * as React from 'react'; import { Link } from 'react-router'; 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'; */ - -/*:: -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 */ = { +import { IProfile } from '../types'; + +interface Props { + canAdmin: boolean; + organization: string | null; + profile: IProfile; + updateProfiles: () => Promise<void>; +} + +interface State { + formOpen: boolean; + loading: boolean; + more?: boolean; + projects: Array<{ key: string; name: string; uuid: string }> | null; +} + +export default class ProfileProjects extends React.PureComponent<Props, State> { + mounted: boolean; + + state: State = { formOpen: false, loading: true, projects: null @@ -58,7 +53,7 @@ export default class ProfileProjects extends React.PureComponent { this.loadProjects(); } - componentDidUpdate(prevProps /*: Props */) { + componentDidUpdate(prevProps: Props) { if (prevProps.profile !== this.props.profile) { this.loadProjects(); } @@ -74,7 +69,7 @@ export default class ProfileProjects extends React.PureComponent { } const data = { key: this.props.profile.key }; - getProfileProjects(data).then(r => { + getProfileProjects(data).then((r: any) => { if (this.mounted) { this.setState({ projects: r.results, @@ -85,7 +80,7 @@ export default class ProfileProjects extends React.PureComponent { }); } - handleChangeClick = (event /*: Event */) => { + handleChangeClick = (event: React.SyntheticEvent<HTMLElement>) => { 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.tsx index ceb3fbed7c1..2fc1879190c 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.tsx @@ -17,8 +17,7 @@ * 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 React from 'react'; +import * as React from 'react'; import { Link } from 'react-router'; import { keyBy } from 'lodash'; import ProfileRulesRowOfType from './ProfileRulesRowOfType'; @@ -29,33 +28,34 @@ 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 { IProfile } from '../types'; const TYPES = ['BUG', 'VULNERABILITY', 'CODE_SMELL']; -/*:: -type Props = { - canAdmin: boolean, - organization: ?string, - profile: Profile -}; -*/ - -/*:: -type State = { - activatedTotal: ?number, - activatedByType?: { [string]: ?{ val: string, count: ?number } }, - allByType?: { [string]: ?{ val: string, count: ?number } }, - compareToSonarWay: ?{ profile: string, profileName: string, missingRuleCount: number }, - loading: boolean, - total: ?number -}; -*/ - -export default class ProfileRules extends React.PureComponent { - /*:: mounted: boolean; */ - /*:: props: Props; */ - state /*: State */ = { +interface Props { + canAdmin: boolean; + organization: string | null; + profile: IProfile; +} + +interface ByType { + val: string; + count: number | null; +} + +interface State { + activatedTotal: number | null; + activatedByType: { [type: string]: ByType }; + allByType: { [type: string]: ByType }; + compareToSonarWay: { profile: string; profileName: string; missingRuleCount: number } | null; + loading: boolean; + total: number | null; +} + +export default class ProfileRules extends React.PureComponent<Props, State> { + mounted: boolean; + + state: State = { activatedTotal: null, activatedByType: keyBy(TYPES.map(t => ({ val: t, count: null })), 'val'), allByType: keyBy(TYPES.map(t => ({ val: t, count: null })), 'val'), @@ -69,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(); } @@ -117,8 +117,8 @@ export default class ProfileRules extends React.PureComponent { const [allRules, activatedRules, showProfile] = responses; this.setState({ activatedTotal: activatedRules.total, - allByType: keyBy(takeFacet(allRules, 'types'), 'val'), - activatedByType: keyBy(takeFacet(activatedRules, 'types'), 'val'), + allByType: keyBy<ByType>(takeFacet(allRules, 'types'), 'val'), + activatedByType: keyBy<ByType>(takeFacet(activatedRules, 'types'), 'val'), compareToSonarWay: showProfile && showProfile.compareToSonarWay, loading: false, total: allRules.total @@ -127,13 +127,13 @@ export default class ProfileRules extends React.PureComponent { }); } - getRulesCountForType(type /*: string */) /*: ?number */ { + getRulesCountForType(type: string) { return this.state.activatedByType && this.state.activatedByType[type] ? this.state.activatedByType[type].count : null; } - getRulesTotalForType(type /*: string */) /*: ?number */ { + getRulesTotalForType(type: string) { 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.tsx index a74e0829787..3e69b0c86be 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.tsx @@ -17,18 +17,19 @@ * 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 React from 'react'; +import * as React from 'react'; import { Link } from 'react-router'; import Tooltip from '../../../components/controls/Tooltip'; import { getDeprecatedActiveRulesUrl } from '../../../helpers/urls'; import { translate } from '../../../helpers/l10n'; -/*:: -type Props = { activeDeprecatedRules: number, organization: ?string, profile: string }; -*/ +interface Props { + activeDeprecatedRules: number; + organization: string | null; + 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.tsx index a899b495348..b13a5ed9797 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.tsx @@ -17,25 +17,22 @@ * 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 React from 'react'; +import * as React from 'react'; import { Link } from 'react-router'; import IssueTypeIcon from '../../../components/ui/IssueTypeIcon'; 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, - type: string -}; -*/ +interface Props { + count: number | null; + organization: string | null; + qprofile: string; + total: number | null; + 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 @@ -60,14 +57,14 @@ export default function ProfileRulesRowOfType(props /*: Props */) { <td className="thin nowrap text-right"> {props.count != null && <Link to={activeRulesUrl}> - {formatMeasure(props.count, 'SHORT_INT')} + {formatMeasure(props.count, 'SHORT_INT', null)} </Link>} </td> <td className="thin nowrap text-right"> {inactiveCount != null && (inactiveCount > 0 ? <Link to={inactiveRulesUrl} className="small text-muted"> - {formatMeasure(inactiveCount, 'SHORT_INT')} + {formatMeasure(inactiveCount, 'SHORT_INT', null)} </Link> : <span className="note text-muted">0</span>)} </td> 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.tsx index 1cb16d7623c..4f97d20776b 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.tsx @@ -17,23 +17,20 @@ * 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 React from 'react'; +import * as React from 'react'; import { Link } from 'react-router'; 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 -}; -*/ +interface Props { + count: number | null; + organization: string | null; + qprofile: string; + total: number | null; +} -export default function ProfileRulesRowTotal(props /*: Props */) { +export default function ProfileRulesRowTotal(props: Props) { const activeRulesUrl = getRulesUrl( { qprofile: props.qprofile, activation: 'true' }, props.organization @@ -58,7 +55,7 @@ export default function ProfileRulesRowTotal(props /*: Props */) { {props.count != null && <Link to={activeRulesUrl}> <strong> - {formatMeasure(props.count, 'SHORT_INT')} + {formatMeasure(props.count, 'SHORT_INT', null)} </strong> </Link>} </td> @@ -67,7 +64,7 @@ export default function ProfileRulesRowTotal(props /*: Props */) { (inactiveCount > 0 ? <Link to={inactiveRulesUrl} className="small text-muted"> <strong> - {formatMeasure(inactiveCount, 'SHORT_INT')} + {formatMeasure(inactiveCount, 'SHORT_INT', null)} </strong> </Link> : <span className="note text-muted">0</span>)} 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.tsx index 1e4a4c27c46..cc7470d93ab 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.tsx @@ -17,24 +17,21 @@ * 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 React from 'react'; +import * as React from 'react'; import { Link } from 'react-router'; import Tooltip from '../../../components/controls/Tooltip'; import { getRulesUrl } from '../../../helpers/urls'; import { translate } from '../../../helpers/l10n'; -/*:: -type Props = { - language: string, - organization: ?string, - profile: string, - sonarway: string, - sonarWayMissingRules: number -}; -*/ +interface Props { + language: string; + organization: string | null; + profile: string; + 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/details/__tests__/ProfileRules-test.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRules-test.tsx index cd62b6a21d6..91e5ed96cfc 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRules-test.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRules-test.tsx @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import React from 'react'; +import * as React from 'react'; import { shallow } from 'enzyme'; import ProfileRules from '../ProfileRules'; import { doAsync } from '../../../../helpers/testUtils'; @@ -68,11 +68,9 @@ const apiResponseActive = { }; // Mock api some api functions -// eslint-disable-next-line -apiRules.searchRules = data => +(apiRules as any).searchRules = (data: any) => Promise.resolve(data.activation === 'true' ? apiResponseActive : apiResponseAll); -// eslint-disable-next-line -apiQP.getQualityProfiles = () => +(apiQP as any).getQualityProfiles = () => Promise.resolve({ compareToSonarWay: { profile: 'sonarway', @@ -83,8 +81,9 @@ apiQP.getQualityProfiles = () => it('should render the quality profiles rules with sonarway comparison', () => { const wrapper = shallow(<ProfileRules canAdmin={false} organization="foo" profile={PROFILE} />); - wrapper.instance().mounted = true; - wrapper.instance().loadRules(); + const instance = wrapper.instance() as any; + instance.mounted = true; + instance.loadRules(); return doAsync(() => { wrapper.update(); expect(wrapper.find('ProfileRulesSonarWayComparison')).toHaveLength(1); @@ -123,13 +122,13 @@ it('should not show a button to activate more rules on built in profiles', () => }); it('should not show sonarway comparison for built in profiles', () => { - // eslint-disable-next-line - apiQP.getQualityProfiles = jest.fn(() => Promise.resolve()); + (apiQP as any).getQualityProfiles = jest.fn(() => Promise.resolve()); const wrapper = shallow( <ProfileRules canAdmin={true} organization={null} profile={{ ...PROFILE, isBuiltIn: true }} /> ); - wrapper.instance().mounted = true; - wrapper.instance().loadRules(); + const instance = wrapper.instance() as any; + instance.mounted = true; + instance.loadRules(); return doAsync(() => { wrapper.update(); expect(apiQP.getQualityProfiles).toHaveBeenCalledTimes(0); @@ -138,8 +137,7 @@ it('should not show sonarway comparison for built in profiles', () => { }); it('should not show sonarway comparison if there is no missing rules', () => { - // eslint-disable-next-line - apiQP.getQualityProfiles = jest.fn(() => + (apiQP as any).getQualityProfiles = jest.fn(() => Promise.resolve({ compareToSonarWay: { profile: 'sonarway', @@ -149,8 +147,9 @@ it('should not show sonarway comparison if there is no missing rules', () => { }) ); const wrapper = shallow(<ProfileRules canAdmin={true} organization={null} profile={PROFILE} />); - wrapper.instance().mounted = true; - wrapper.instance().loadRules(); + const instance = wrapper.instance() as any; + instance.mounted = true; + instance.loadRules(); return doAsync(() => { wrapper.update(); expect(apiQP.getQualityProfiles).toHaveBeenCalledTimes(1); diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesDeprecatedWarning-test.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesDeprecatedWarning-test.tsx index 9a3387280e9..c306d6856c3 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesDeprecatedWarning-test.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesDeprecatedWarning-test.tsx @@ -17,8 +17,7 @@ * 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 React from 'react'; +import * as React from 'react'; import { shallow } from 'enzyme'; import ProfileRulesDeprecatedWarning from '../ProfileRulesDeprecatedWarning'; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesRowOfType-test.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesRowOfType-test.tsx index dea445e01bf..b8a3bc56505 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesRowOfType-test.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesRowOfType-test.tsx @@ -17,8 +17,7 @@ * 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 React from 'react'; +import * as React from 'react'; import { shallow } from 'enzyme'; import ProfileRulesRowOfType from '../ProfileRulesRowOfType'; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesRowTotal-test.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesRowTotal-test.tsx index 20f2d697d5f..3428f58ea6b 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesRowTotal-test.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesRowTotal-test.tsx @@ -17,8 +17,7 @@ * 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 React from 'react'; +import * as React from 'react'; import { shallow } from 'enzyme'; import ProfileRulesRowTotal from '../ProfileRulesRowTotal'; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesSonarWayComparison-test.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesSonarWayComparison-test.tsx index ef992d630ba..50914b7a094 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesSonarWayComparison-test.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRulesSonarWayComparison-test.tsx @@ -17,8 +17,7 @@ * 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 React from 'react'; +import * as React from 'react'; import { shallow } from 'enzyme'; import ProfileRulesSonarWayComparison from '../ProfileRulesSonarWayComparison'; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRules-test.js.snap b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRules-test.tsx.snap index 22be4264e2a..22be4264e2a 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRules-test.js.snap +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRules-test.tsx.snap diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesDeprecatedWarning-test.js.snap b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesDeprecatedWarning-test.tsx.snap index 54fa91cc49d..54fa91cc49d 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesDeprecatedWarning-test.js.snap +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesDeprecatedWarning-test.tsx.snap diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesRowOfType-test.js.snap b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesRowOfType-test.tsx.snap index 62866095c17..62866095c17 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesRowOfType-test.js.snap +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesRowOfType-test.tsx.snap diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesRowTotal-test.js.snap b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesRowTotal-test.tsx.snap index f8686659326..f8686659326 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesRowTotal-test.js.snap +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesRowTotal-test.tsx.snap diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesSonarWayComparison-test.js.snap b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesSonarWayComparison-test.tsx.snap index 481846b23ad..481846b23ad 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesSonarWayComparison-test.js.snap +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileRulesSonarWayComparison-test.tsx.snap 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.tsx index d95984ce033..8f6d589cff8 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.tsx @@ -17,39 +17,33 @@ * 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 React from 'react'; +import * as React from 'react'; import Modal from 'react-modal'; -import Select from 'react-select'; +import * as Select from 'react-select'; 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, - onCreate: Function, - onRequestFail: Object => void, - organization: ?string -}; -*/ - -/*:: -type State = { - importers: Array<{ key: string, languages: Array<string>, name: string }>, - language?: string, - loading: boolean, - name: string, - preloading: boolean -}; -*/ - -export default class CreateProfileForm extends React.PureComponent { +interface Props { + languages: Array<{ key: string; name: string }>; + onClose: () => void; + onCreate: Function; + onRequestFail: (reasong: any) => void; + organization: string | null; +} + +interface State { + importers: Array<{ key: string; languages: Array<string>; name: string }>; + language?: string; + loading: boolean; + name: string; + preloading: boolean; +} + +export default class CreateProfileForm extends React.PureComponent<Props, State> { /*:: form: HTMLFormElement; */ - /*:: mounted: boolean; */ - /*:: props: Props; */ - state /*: State */ = { importers: [], loading: false, name: '', preloading: true }; + mounted: boolean; + state: State = { importers: [], loading: false, name: '', preloading: true }; componentDidMount() { this.mounted = true; @@ -61,39 +55,41 @@ export default class CreateProfileForm extends React.PureComponent { } fetchImporters() { - getImporters().then(importers => { - if (this.mounted) { - this.setState({ importers, preloading: false }); + getImporters().then( + (importers: Array<{ key: string; languages: Array<string>; name: string }>) => { + if (this.mounted) { + this.setState({ importers, preloading: false }); + } } - }); + ); } - handleCancelClick = (event /*: Event */) => { + handleCancelClick = (event: React.SyntheticEvent<HTMLElement>) => { event.preventDefault(); this.props.onClose(); }; - handleNameChange = (event /*: { currentTarget: HTMLInputElement } */) => { + handleNameChange = (event: React.SyntheticEvent<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: React.SyntheticEvent<HTMLFormElement>) => { event.preventDefault(); this.setState({ loading: true }); - const data = new FormData(this.form); + const data = new FormData(event.currentTarget); if (this.props.organization) { data.append('organization', this.props.organization); } createQualityProfile(data).then( - response => this.props.onCreate(response.profile), - error => { + (response: any) => this.props.onCreate(response.profile), + (error: any) => { if (this.mounted) { this.setState({ loading: false }); } @@ -118,10 +114,7 @@ export default class CreateProfileForm extends React.PureComponent { className="modal" overlayClassName="modal-overlay" onRequestClose={this.props.onClose}> - <form - id="create-profile-form" - onSubmit={this.handleFormSubmit} - ref={node => (this.form = node)}> + <form id="create-profile-form" onSubmit={this.handleFormSubmit}> <div className="modal-head"> <h2> {header} @@ -141,11 +134,11 @@ export default class CreateProfileForm extends React.PureComponent { <input autoFocus={true} id="create-profile-name" - maxLength="100" + maxLength={100} name="name" onChange={this.handleNameChange} required={true} - size="50" + size={50} type="text" value={this.state.name} /> @@ -157,7 +150,6 @@ export default class CreateProfileForm extends React.PureComponent { </label> <Select clearable={false} - id="create-profile-language" name="language" onChange={this.handleLanguageChange} options={languages.map(language => ({ 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.tsx index 4be28f3dd04..f238580d1e2 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.tsx @@ -17,32 +17,23 @@ * 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 React from 'react'; +import * as React from 'react'; import EvolutionDeprecated from './EvolutionDeprecated'; import EvolutionStagnant from './EvolutionStagnant'; import EvolutionRules from './EvolutionRules'; -/*:: import type { Profile } from '../propTypes'; */ +import { IProfile } from '../types'; -/*:: -type Props = { - organization: ?string, - profiles: Array<Profile> -}; -*/ - -export default class Evolution extends React.PureComponent { - /*:: props: Props; */ - - render() { - const { organization, profiles } = this.props; +interface Props { + organization: string | null; + profiles: IProfile[]; +} - return ( - <div className="quality-profiles-evolution"> - <EvolutionDeprecated organization={organization} profiles={profiles} /> - <EvolutionStagnant organization={organization} profiles={profiles} /> - <EvolutionRules organization={organization} /> - </div> - ); - } +export default function Evolution({ organization, profiles }: Props) { + return ( + <div className="quality-profiles-evolution"> + <EvolutionDeprecated organization={organization} profiles={profiles} /> + <EvolutionStagnant organization={organization} profiles={profiles} /> + <EvolutionRules organization={organization} /> + </div> + ); } 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 deleted file mode 100644 index a3eaef27bd2..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.js +++ /dev/null @@ -1,96 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * 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 React from 'react'; -import { Link } from 'react-router'; -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'; */ - -/*:: -type Props = { - organization: ?string, - profiles: Array<Profile> -}; -*/ - -export default class EvolutionDeprecated extends React.PureComponent { - /*:: props: Props; */ - - render() { - const profilesWithDeprecations = this.props.profiles.filter( - profile => profile.activeDeprecatedRuleCount > 0 - ); - - if (profilesWithDeprecations.length === 0) { - return null; - } - - const sortedProfiles = sortBy(profilesWithDeprecations, p => -p.activeDeprecatedRuleCount); - - return ( - <div className="quality-profile-box quality-profiles-evolution-deprecated"> - <div className="spacer-bottom"> - <strong> - {translate('quality_profiles.deprecated_rules')} - </strong> - </div> - <div className="spacer-bottom"> - {translateWithParameters( - 'quality_profiles.deprecated_rules_are_still_activated', - profilesWithDeprecations.length - )} - </div> - <ul> - {sortedProfiles.map(profile => - <li key={profile.key} className="spacer-top"> - <div className="text-ellipsis"> - <ProfileLink - className="link-no-underline" - language={profile.language} - name={profile.name} - organization={this.props.organization}> - {profile.name} - </ProfileLink> - </div> - <div className="note"> - {profile.languageName} - {', '} - <Link - to={getDeprecatedActiveRulesUrl( - { qprofile: profile.key }, - this.props.organization - )} - className="text-muted"> - {translateWithParameters( - 'quality_profile.x_rules', - profile.activeDeprecatedRuleCount - )} - </Link> - </div> - </li> - )} - </ul> - </div> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.tsx new file mode 100644 index 00000000000..0f8da8a3e9a --- /dev/null +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.tsx @@ -0,0 +1,86 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { Link } from 'react-router'; +import { sortBy } from 'lodash'; +import ProfileLink from '../components/ProfileLink'; +import { getDeprecatedActiveRulesUrl } from '../../../helpers/urls'; +import { translateWithParameters, translate } from '../../../helpers/l10n'; +import { IProfile } from '../types'; + +interface Props { + organization: string | null; + profiles: IProfile[]; +} + +export default function EvolutionDeprecated(props: Props) { + const profilesWithDeprecations = props.profiles.filter( + profile => profile.activeDeprecatedRuleCount > 0 + ); + + if (profilesWithDeprecations.length === 0) { + return null; + } + + const sortedProfiles = sortBy(profilesWithDeprecations, p => -p.activeDeprecatedRuleCount); + + return ( + <div className="quality-profile-box quality-profiles-evolution-deprecated"> + <div className="spacer-bottom"> + <strong> + {translate('quality_profiles.deprecated_rules')} + </strong> + </div> + <div className="spacer-bottom"> + {translateWithParameters( + 'quality_profiles.deprecated_rules_are_still_activated', + profilesWithDeprecations.length + )} + </div> + <ul> + {sortedProfiles.map(profile => + <li key={profile.key} className="spacer-top"> + <div className="text-ellipsis"> + <ProfileLink + className="link-no-underline" + language={profile.language} + name={profile.name} + organization={props.organization}> + {profile.name} + </ProfileLink> + </div> + <div className="note"> + {profile.languageName} + {', '} + <Link + to={getDeprecatedActiveRulesUrl({ qprofile: profile.key }, props.organization)} + className="text-muted"> + {translateWithParameters( + 'quality_profile.x_rules', + profile.activeDeprecatedRuleCount + )} + </Link> + </div> + </li> + )} + </ul> + </div> + ); +} 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.tsx index 042c04a73b6..c9e3e1f46e1 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.tsx @@ -17,10 +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. */ -// @flow -import React from 'react'; +import * as React from 'react'; import { Link } from 'react-router'; -import moment from 'moment'; +import * as moment from 'moment'; import { sortBy } from 'lodash'; import { searchRules } from '../../../api/rules'; import { translateWithParameters, translate } from '../../../helpers/l10n'; @@ -31,24 +30,33 @@ const RULES_LIMIT = 10; const PERIOD_START_MOMENT = moment().subtract(1, 'year'); -function parseRules(r) { +function parseRules(r: any) { const { rules, actives } = r; - return rules.map(rule => { + return rules.map((rule: any) => { const activations = actives[rule.key]; return { ...rule, activations: activations ? activations.length : 0 }; }); } -/*:: -type Props = { - organization: ?string -}; -*/ +interface Props { + organization: string | null; +} + +interface IRule { + activations: number; + key: string; + langName: string; + name: string; +} + +interface State { + latestRules?: Array<IRule>; + latestRulesTotal?: number; +} -export default class EvolutionRules extends React.PureComponent { - /*:: mounted: boolean; */ - /*:: props: Props; */ - state = {}; +export default class EvolutionRules extends React.PureComponent<Props, State> { + mounted: boolean; + state: State = {}; componentDidMount() { this.mounted = true; @@ -68,10 +76,10 @@ export default class EvolutionRules extends React.PureComponent { f: 'name,langName,actives' }; - searchRules(data).then(r => { + searchRules(data).then((r: any) => { if (this.mounted) { this.setState({ - latestRules: sortBy(parseRules(r), 'langName'), + latestRules: sortBy<IRule>(parseRules(r), 'langName'), latestRulesTotal: r.total }); } @@ -79,7 +87,7 @@ export default class EvolutionRules extends React.PureComponent { } render() { - if (!this.state.latestRulesTotal) { + if (!this.state.latestRulesTotal || !this.state.latestRules) { return null; } @@ -125,7 +133,7 @@ export default class EvolutionRules extends React.PureComponent { {this.state.latestRulesTotal > RULES_LIMIT && <div className="spacer-top"> <Link to={newRulesUrl} className="small"> - {translate('see_all')} {formatMeasure(this.state.latestRulesTotal, 'SHORT_INT')} + {translate('see_all')} {formatMeasure(this.state.latestRulesTotal, 'SHORT_INT', null)} </Link> </div>} </div> 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 deleted file mode 100644 index 1eda4c0b8e3..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.js +++ /dev/null @@ -1,80 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * 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 React from 'react'; -import moment from 'moment'; -import ProfileLink from '../components/ProfileLink'; -import { translate } from '../../../helpers/l10n'; -import { isStagnant } from '../utils'; -/*:: import type { Profile } from '../propTypes'; */ - -/*:: -type Props = { - organization: ?string, - profiles: Array<Profile> -}; -*/ - -export default class EvolutionStagnant extends React.PureComponent { - /*:: props: Props; */ - - render() { - // TODO filter built-in out - - const outdated = this.props.profiles.filter(isStagnant); - - if (outdated.length === 0) { - return null; - } - - return ( - <div className="quality-profile-box quality-profiles-evolution-stagnant"> - <div className="spacer-bottom"> - <strong> - {translate('quality_profiles.stagnant_profiles')} - </strong> - </div> - <div className="spacer-bottom"> - {translate('quality_profiles.not_updated_more_than_year')} - </div> - <ul> - {outdated.map(profile => - <li key={profile.key} className="spacer-top"> - <div className="text-ellipsis"> - <ProfileLink - className="link-no-underline" - language={profile.language} - name={profile.name} - organization={this.props.organization}> - {profile.name} - </ProfileLink> - </div> - <div className="note"> - {profile.languageName} - {', '} - updated on {moment(profile.rulesUpdatedAt).format('LL')} - </div> - </li> - )} - </ul> - </div> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.tsx new file mode 100644 index 00000000000..8b3fc2eae90 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.tsx @@ -0,0 +1,73 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import * as moment from 'moment'; +import ProfileLink from '../components/ProfileLink'; +import { translate } from '../../../helpers/l10n'; +import { isStagnant } from '../utils'; +import { IProfile } from '../types'; + +interface Props { + organization: string | null; + profiles: IProfile[]; +} + +export default function EvolutionStagnan(props: Props) { + // TODO filter built-in out + + const outdated = props.profiles.filter(isStagnant); + + if (outdated.length === 0) { + return null; + } + + return ( + <div className="quality-profile-box quality-profiles-evolution-stagnant"> + <div className="spacer-bottom"> + <strong> + {translate('quality_profiles.stagnant_profiles')} + </strong> + </div> + <div className="spacer-bottom"> + {translate('quality_profiles.not_updated_more_than_year')} + </div> + <ul> + {outdated.map(profile => + <li key={profile.key} className="spacer-top"> + <div className="text-ellipsis"> + <ProfileLink + className="link-no-underline" + language={profile.language} + name={profile.name} + organization={props.organization}> + {profile.name} + </ProfileLink> + </div> + <div className="note"> + {profile.languageName} + {', '} + updated on {moment(profile.rulesUpdatedAt).format('LL')} + </div> + </li> + )} + </ul> + </div> + ); +} 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.tsx index 95f63d8cd4c..cd3b21502a5 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.tsx @@ -17,42 +17,35 @@ * 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 React from 'react'; +import * as React from 'react'; import PageHeader from './PageHeader'; import Evolution from './Evolution'; import ProfilesList from './ProfilesList'; -/*:: import type { Profile } from '../propTypes'; */ +import { IProfile } from '../types'; -/*:: -type Props = { - canAdmin: boolean, - languages: Array<{ key: string, name: string }>, - location: { query: { [string]: string } }, - onRequestFail: Object => void, - organization?: string, - profiles: Array<Profile>, - updateProfiles: () => Promise<*> -}; -*/ - -export default class HomeContainer extends React.PureComponent { - /*:: props: Props; */ +interface Props { + canAdmin: boolean; + languages: Array<{ key: string; name: string }>; + location: { query: { [p: string]: string } }; + onRequestFail: (reason: any) => void; + organization: string | null; + profiles: Array<IProfile>; + updateProfiles: () => Promise<void>; +} - render() { - return ( - <div> - <PageHeader {...this.props} /> +export default function HomeContainer(props: Props) { + return ( + <div> + <PageHeader {...props} /> - <div className="page-with-sidebar"> - <div className="page-main"> - <ProfilesList {...this.props} /> - </div> - <div className="page-sidebar"> - <Evolution {...this.props} /> - </div> + <div className="page-with-sidebar"> + <div className="page-main"> + <ProfilesList {...props} /> + </div> + <div className="page-sidebar"> + <Evolution {...props} /> </div> </div> - ); - } + </div> + ); } 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.tsx index 44ba30feeb7..0f3b2b9c19f 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.tsx @@ -17,51 +17,44 @@ * 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 React from 'react'; -import PropTypes from 'prop-types'; +import * as React from 'react'; +import * as PropTypes from 'prop-types'; import CreateProfileForm from './CreateProfileForm'; import RestoreProfileForm from './RestoreProfileForm'; -/*:: import type { Profile } from '../propTypes'; */ import { getProfilePath } from '../utils'; import { translate } from '../../../helpers/l10n'; +import { IProfile } from '../types'; -/*:: -type Props = { - canAdmin: boolean, - languages: Array<{ key: string, name: string }>, - onRequestFail: Object => void, - organization: ?string, - updateProfiles: () => Promise<*> -}; -*/ - -/*:: -type State = { - createFormOpen: boolean, - restoreFormOpen: boolean -}; -*/ +interface Props { + canAdmin: boolean; + languages: Array<{ key: string; name: string }>; + onRequestFail: (reason: any) => void; + organization: string | null; + updateProfiles: () => Promise<void>; +} -export default class PageHeader extends React.PureComponent { - /*:: props: Props; */ +interface State { + createFormOpen: boolean; + restoreFormOpen: boolean; +} +export default class PageHeader extends React.PureComponent<Props, State> { static contextTypes = { router: PropTypes.object }; - state /*: State */ = { + state = { createFormOpen: false, restoreFormOpen: false }; - handleCreateClick = (event /*: Event & { currentTarget: HTMLButtonElement } */) => { + handleCreateClick = (event: React.SyntheticEvent<HTMLElement>) => { event.preventDefault(); event.currentTarget.blur(); this.setState({ createFormOpen: true }); }; - handleCreate = (profile /*: Profile */) => { + handleCreate = (profile: IProfile) => { this.props.updateProfiles().then(() => { this.context.router.push( getProfilePath(profile.name, profile.language, this.props.organization) @@ -73,7 +66,7 @@ export default class PageHeader extends React.PureComponent { this.setState({ createFormOpen: false }); }; - handleRestoreClick = (event /*: Event */) => { + handleRestoreClick = (event: React.SyntheticEvent<HTMLElement>) => { 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.tsx index b912a9662a5..6f4c8f8c17b 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.tsx @@ -17,31 +17,25 @@ * 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 React from 'react'; +import * as React from 'react'; import { groupBy, pick, sortBy } from 'lodash'; 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 { IProfile } from '../types'; -/*:: -type Props = { - canAdmin: boolean, - languages: Array<{ key: string, name: string }>, - location: { query: { [string]: string } }, - onRequestFail: Object => void, - organization: ?string, - profiles: Array<Profile>, - updateProfiles: () => Promise<*> -}; -*/ - -export default class ProfilesList extends React.PureComponent { - /*:: props: Props; */ +interface Props { + canAdmin: boolean; + languages: Array<{ key: string; name: string }>; + location: { query: { [p: string]: string } }; + onRequestFail: (reason: any) => void; + organization: string | null; + profiles: IProfile[]; + updateProfiles: () => Promise<void>; +} - renderProfiles(profiles /*: Array<Profile> */) { +export default class ProfilesList extends React.PureComponent<Props> { + renderProfiles(profiles: IProfile[]) { return profiles.map(profile => <ProfilesListRow canAdmin={this.props.canAdmin} @@ -54,7 +48,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) { @@ -91,8 +85,14 @@ export default class ProfilesList extends React.PureComponent { const { profiles, languages } = this.props; const { language } = this.props.location.query; - const profilesIndex = groupBy(profiles, profile => profile.language); - const profilesToShow = language ? pick(profilesIndex, language) : profilesIndex; + const profilesIndex: { [language: string]: IProfile[] } = groupBy<IProfile>( + profiles, + profile => profile.language + ); + + const profilesToShow: { [language: string]: IProfile[] } = language + ? pick(profilesIndex, language) + : profilesIndex; const languagesToShow = sortBy(Object.keys(profilesToShow)); @@ -115,12 +115,10 @@ export default class ProfilesList extends React.PureComponent { {profilesToShow[languageKey] != null && this.renderHeader(languageKey, profilesToShow[languageKey].length)} - <TooltipsContainer> - <tbody> - {profilesToShow[languageKey] != null && - this.renderProfiles(profilesToShow[languageKey])} - </tbody> - </TooltipsContainer> + <tbody> + {profilesToShow[languageKey] != null && + this.renderProfiles(profilesToShow[languageKey])} + </tbody> </table> </div> )} 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.tsx index ab76d1a4df3..15b98d6a2d4 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.tsx @@ -17,23 +17,18 @@ * 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 React from 'react'; +import * as React from 'react'; 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; */ +interface Props { + currentFilter?: string; + languages: Array<{ key: string; name: string }>; + organization: string | null; +} +export default class ProfilesListHeader extends React.PureComponent<Props> { renderFilterToggle() { const { languages, currentFilter } = this.props; const currentLanguage = currentFilter && languages.find(l => l.key === currentFilter); 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.tsx index f9d18056d2e..2d982c34db4 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.tsx @@ -17,8 +17,7 @@ * 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 React from 'react'; +import * as React from 'react'; import { Link } from 'react-router'; import ProfileLink from '../components/ProfileLink'; import ProfileDate from '../components/ProfileDate'; @@ -27,21 +26,18 @@ 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 { IProfile } from '../types'; +import Tooltip from '../../../components/controls/Tooltip'; -/*:: -type Props = { - canAdmin: boolean, - onRequestFail: Object => void, - organization: ?string, - profile: Profile, - updateProfiles: () => Promise<*> -}; -*/ - -export default class ProfilesListRow extends React.PureComponent { - /*:: props: Props; */ +interface Props { + canAdmin: boolean; + onRequestFail: (reason: any) => void; + organization: string | null; + profile: IProfile; + updateProfiles: () => Promise<void>; +} +export default class ProfilesListRow extends React.PureComponent<Props> { renderName() { const { profile } = this.props; const offset = 25 * (profile.depth - 1); @@ -100,13 +96,11 @@ export default class ProfilesListRow extends React.PureComponent { <div> {profile.activeDeprecatedRuleCount > 0 && <span className="spacer-right"> - <Link - to={deprecatedRulesUrl} - className="badge badge-normal-size badge-danger-light" - title={translate('quality_profiles.deprecated_rules')} - data-toggle="tooltip"> - {profile.activeDeprecatedRuleCount} - </Link> + <Tooltip overlay={translate('quality_profiles.deprecated_rules')}> + <Link to={deprecatedRulesUrl} className="badge badge-normal-size badge-danger-light"> + {profile.activeDeprecatedRuleCount} + </Link> + </Tooltip> </span>} <Link to={activeRulesUrl}> 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.tsx index 26411abb34c..5f12d61f662 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.tsx @@ -17,35 +17,28 @@ * 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 React from 'react'; +import * as React from 'react'; 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 -}; -*/ +interface Props { + onClose: () => void; + onRequestFail: (reason: any) => void; + onRestore: () => void; + organization: string | null; +} -/*:: -type State = { - loading: boolean, - profile?: { name: string }, - ruleFailures?: number, - ruleSuccesses?: number -}; -*/ +interface 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 }; +export default class RestoreProfileForm extends React.PureComponent<Props, State> { + mounted: boolean; + state: State = { loading: false }; componentDidMount() { this.mounted = true; @@ -55,23 +48,23 @@ export default class RestoreProfileForm extends React.PureComponent { this.mounted = false; } - handleCancelClick = (event /*: Event */) => { + handleCancelClick = (event: React.SyntheticEvent<HTMLElement>) => { event.preventDefault(); this.props.onClose(); }; - handleFormSubmit = (event /*: Event */) => { + handleFormSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => { event.preventDefault(); this.setState({ loading: true }); - const data = new FormData(this.form); + const data = new FormData(event.currentTarget); if (this.props.organization) { data.append('organization', this.props.organization); } restoreQualityProfile(data).then( - response => { + (response: any) => { if (this.mounted) { this.setState({ loading: false, @@ -82,7 +75,7 @@ export default class RestoreProfileForm extends React.PureComponent { } this.props.onRestore(); }, - error => { + (error: any) => { if (this.mounted) { this.setState({ loading: false }); } @@ -103,10 +96,7 @@ export default class RestoreProfileForm extends React.PureComponent { className="modal" overlayClassName="modal-overlay" onRequestClose={this.props.onClose}> - <form - id="restore-profile-form" - onSubmit={this.handleFormSubmit} - ref={node => (this.form = node)}> + <form id="restore-profile-form" onSubmit={this.handleFormSubmit}> <div className="modal-head"> <h2> {header} 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 deleted file mode 100644 index dbf1364fca2..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-profiles/propTypes.js +++ /dev/null @@ -1,76 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * 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 { shape, string, number, bool, arrayOf } from 'prop-types'; - -/*:: -export type Profile = { - key: string, - name: string, - isBuiltIn: boolean, - isDefault: boolean, - isInherited: boolean, - language: string, - languageName: string, - activeRuleCount: number, - activeDeprecatedRuleCount: number, - projectCount?: number, - parentKey?: string, - parentName?: string, - userUpdatedAt?: string, - lastUsed?: string, - rulesUpdatedAt: string, - depth: number, - childrenCount: number -}; -*/ - -/*:: -export type Exporter = { - key: string, - name: string, - languages: Array<string> -}; -*/ - -export const ProfileType = shape({ - key: string.isRequired, - name: string.isRequired, - isDefault: bool.isRequired, - isInherited: bool.isRequired, - language: string.isRequired, - languageName: string.isRequired, - activeRuleCount: number.isRequired, - activeDeprecatedRuleCount: number.isRequired, - projectCount: number, - parentKey: string, - parentName: string, - userUpdatedAt: string, - lastUsed: string -}); - -export const ProfilesListType = arrayOf(ProfileType); - -const LanguageType = shape({ - key: string.isRequired, - name: string.isRequired -}); - -export const LanguagesListType = arrayOf(LanguageType); diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/routes.js b/server/sonar-web/src/main/js/apps/quality-profiles/routes.ts index 1d7b96fe647..cac3704b319 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/routes.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/routes.ts @@ -17,11 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { withRouter } from 'react-router'; +import { withRouter, RouterState, IndexRouteProps, RouteComponent } from 'react-router'; const routes = [ { - getComponent(state, callback) { + getComponent(state: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./components/AppContainer').then(i => i.default).then(AppContainer => { if (state.params.organizationKey) { callback(null, AppContainer); @@ -32,30 +32,30 @@ const routes = [ } }); }, - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { import('./home/HomeContainer').then(i => callback(null, { component: i.default })); }, childRoutes: [ { - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./components/ProfileContainer').then(i => callback(null, withRouter(i.default))); }, childRoutes: [ { path: 'show', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./details/ProfileDetails').then(i => callback(null, i.default)); } }, { path: 'changelog', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./changelog/ChangelogContainer').then(i => callback(null, i.default)); } }, { path: 'compare', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./compare/ComparisonContainer').then(i => callback(null, i.default)); } } diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/types.ts b/server/sonar-web/src/main/js/apps/quality-profiles/types.ts new file mode 100644 index 00000000000..73e4384706d --- /dev/null +++ b/server/sonar-web/src/main/js/apps/quality-profiles/types.ts @@ -0,0 +1,53 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +export interface IProfile { + key: string; + name: string; + isBuiltIn: boolean; + isDefault: boolean; + isInherited: boolean; + language: string; + languageName: string; + activeRuleCount: number; + activeDeprecatedRuleCount: number; + projectCount?: number; + parentKey?: string; + parentName?: string; + userUpdatedAt?: string; + lastUsed?: string; + rulesUpdatedAt: string; + depth: number; + childrenCount: number; +} + +export interface IExporter { + key: string; + name: string; + languages: string[]; +} + +export interface IProfileChangelogEvent { + action: string; + authorName: string; + date: string; + params?: { [change: string]: string | null }; + ruleKey: string; + ruleName: string; +} 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.ts index 60ec46e6572..890f3879e63 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/utils.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/utils.ts @@ -17,22 +17,21 @@ * 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 { sortBy } from 'lodash'; -import moment from 'moment'; -/*:: import type { Profile } from './propTypes'; */ +import * as moment from 'moment'; +import { IProfile } from './types'; -export function sortProfiles(profiles /*: Array<Profile> */) { - const result = []; +export function sortProfiles(profiles: IProfile[]) { + const result: IProfile[] = []; const sorted = sortBy(profiles, 'name'); - function retrieveChildren(parent) { + function retrieveChildren(parent: IProfile | null) { return sorted.filter( p => (parent == null && p.parentKey == null) || (parent != null && p.parentKey === parent.key) ); } - function putProfile(profile = null, depth = 1) { + function putProfile(profile: IProfile | null = null, depth: number = 1) { const children = retrieveChildren(profile); if (profile != null) { @@ -51,7 +50,7 @@ export function sortProfiles(profiles /*: Array<Profile> */) { return result; } -export function createFakeProfile(overrides /*: {} */) { +export function createFakeProfile(overrides?: any) { return { key: 'key', name: 'name', @@ -66,37 +65,30 @@ export function createFakeProfile(overrides /*: {} */) { }; } -export function isStagnant(profile /*: Profile */) { +export function isStagnant(profile: IProfile) { return moment().diff(moment(profile.userUpdatedAt), 'years') >= 1; } -export const getProfilesPath = (organization /*: ?string */) => +export const getProfilesPath = (organization: string | null) => organization ? `/organizations/${organization}/quality_profiles` : '/profiles'; -export const getProfilesForLanguagePath = ( - language /*: string */, - organization /*: ?string */ -) => ({ +export const getProfilesForLanguagePath = (language: string, organization: string | null) => ({ pathname: getProfilesPath(organization), query: { language } }); -export const getProfilePath = ( - name /*: string */, - language /*: string */, - organization /*: ?string */ -) => ({ +export const getProfilePath = (name: string, language: string, organization: string | null) => ({ pathname: getProfilesPath(organization) + '/show', query: { name, language } }); export const getProfileComparePath = ( - name /*: string */, - language /*: string */, - organization /*: ?string */, - withKey /*: ?string */ + name: string, + language: string, + organization: string | null, + withKey?: string ) => { - const query /*: Object */ = { language, name }; + const query = { language, name }; if (withKey) { Object.assign(query, { withKey }); } @@ -107,12 +99,12 @@ export const getProfileComparePath = ( }; export const getProfileChangelogPath = ( - name /*: string */, - language /*: string */, - organization /*: ?string */, - filter /*: ?{ since?: string, to?: string } */ + name: string, + language: string, + organization: string | null, + filter?: { since?: string; to?: string } ) => { - const query /*: Object */ = { language, name }; + const query = { 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/Unauthorized.js b/server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.js deleted file mode 100644 index a8f98da3fd1..00000000000 --- a/server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.js +++ /dev/null @@ -1,49 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * 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 React from 'react'; -import PropTypes from 'prop-types'; - -export default class Unauthorized extends React.PureComponent { - static propTypes = { - location: PropTypes.object.isRequired - }; - - render() { - const { message } = this.props.location.query; - - return ( - <div className="text-center"> - <p id="unauthorized"> - {"You're not authorized to access this page. Please contact the administrator."} - </p> - - {!!message && - <p className="spacer-top"> - Reason : {message} - </p>} - - <div className="big-spacer-top"> - <a href={window.baseUrl + '/'}>Home</a> - </div> - </div> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.tsx b/server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.tsx new file mode 100644 index 00000000000..edfa3d62d26 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.tsx @@ -0,0 +1,50 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { Link } from 'react-router'; + +interface Props { + location: { + query: { + message: string; + }; + }; +} + +export default function Unauthorized(props: Props) { + const { message } = props.location.query; + + return ( + <div className="text-center"> + <p id="unauthorized"> + {"You're not authorized to access this page. Please contact the administrator."} + </p> + + {!!message && + <p className="spacer-top"> + Reason : {message} + </p>} + + <div className="big-spacer-top"> + <Link to="/">Home</Link> + </div> + </div> + ); +} diff --git a/server/sonar-web/src/main/js/apps/sessions/routes.js b/server/sonar-web/src/main/js/apps/sessions/routes.ts index 32e367c391f..ce1a2e80c70 100644 --- a/server/sonar-web/src/main/js/apps/sessions/routes.js +++ b/server/sonar-web/src/main/js/apps/sessions/routes.ts @@ -17,22 +17,24 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, RouteComponent } from 'react-router'; + const routes = [ { path: 'new', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./components/LoginFormContainer').then(i => callback(null, i.default)); } }, { path: 'logout', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./components/Logout').then(i => callback(null, i.default)); } }, { path: 'unauthorized', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./components/Unauthorized').then(i => callback(null, i.default)); } } diff --git a/server/sonar-web/src/main/js/apps/settings/routes.js b/server/sonar-web/src/main/js/apps/settings/routes.ts index 9a408f19fe8..54afd122a3d 100644 --- a/server/sonar-web/src/main/js/apps/settings/routes.js +++ b/server/sonar-web/src/main/js/apps/settings/routes.ts @@ -17,27 +17,29 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, RouteComponent, IndexRouteProps } from 'react-router'; + const routes = [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { import('./components/AppContainer').then(i => callback(null, { component: i.default })); } }, { path: 'licenses', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./licenses/LicensesApp').then(i => callback(null, i.default)); } }, { path: 'encryption', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./encryption/EncryptionAppContainer').then(i => callback(null, i.default)); } }, { path: 'server_id', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./serverId/ServerIdAppContainer').then(i => callback(null, i.default)); } } diff --git a/server/sonar-web/src/main/js/apps/system/routes.js b/server/sonar-web/src/main/js/apps/system/routes.js deleted file mode 100644 index 0ab080a46f4..00000000000 --- a/server/sonar-web/src/main/js/apps/system/routes.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -const routes = [ - { - getIndexRoute(_, callback) { - import('./main').then(i => callback(null, { component: i.default })); - } - } -]; - -export default routes; diff --git a/server/sonar-web/src/main/js/apps/system/routes.ts b/server/sonar-web/src/main/js/apps/system/routes.ts new file mode 100644 index 00000000000..9f7f40c4cd2 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/system/routes.ts @@ -0,0 +1,30 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { RouterState, IndexRouteProps } from 'react-router'; + +const routes = [ + { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { + import('./main').then(i => callback(null, { component: (i as any).default })); + } + } +]; + +export default routes; diff --git a/server/sonar-web/src/main/js/apps/update-center/routes.js b/server/sonar-web/src/main/js/apps/update-center/routes.ts index 81c884ae5d6..e41cfdc073a 100644 --- a/server/sonar-web/src/main/js/apps/update-center/routes.js +++ b/server/sonar-web/src/main/js/apps/update-center/routes.ts @@ -17,9 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, RouteComponent, IndexRouteProps } from 'react-router'; + const routes = [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { import('./components/UpdateCenterAppContainer').then(i => callback(null, { component: i.default }) ); @@ -27,25 +29,25 @@ const routes = [ }, { path: 'installed', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./components/UpdateCenterAppContainer').then(i => callback(null, i.default)); } }, { path: 'updates', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./components/UpdateCenterAppContainer').then(i => callback(null, i.default)); } }, { path: 'available', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./components/UpdateCenterAppContainer').then(i => callback(null, i.default)); } }, { path: 'system', - getComponent(_, callback) { + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { import('./components/UpdateCenterAppContainer').then(i => callback(null, i.default)); } } diff --git a/server/sonar-web/src/main/js/apps/users/routes.js b/server/sonar-web/src/main/js/apps/users/routes.ts index b07c3c9c5c2..88751d8b803 100644 --- a/server/sonar-web/src/main/js/apps/users/routes.js +++ b/server/sonar-web/src/main/js/apps/users/routes.ts @@ -17,9 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, IndexRouteProps } from 'react-router'; + const routes = [ { - getIndexRoute(_, callback) { + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { import('./components/UsersAppContainer').then(i => callback(null, { component: i.default })); } } diff --git a/server/sonar-web/src/main/js/apps/web-api/routes.js b/server/sonar-web/src/main/js/apps/web-api/routes.ts index 5993b47eea4..a76c3f27e93 100644 --- a/server/sonar-web/src/main/js/apps/web-api/routes.js +++ b/server/sonar-web/src/main/js/apps/web-api/routes.ts @@ -17,16 +17,18 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { RouterState, RouteComponent, IndexRouteProps } from 'react-router'; + const routes = [ { - getIndexRoute(_, callback) { - import('./components/WebApiApp').then(i => callback(null, { component: i.default })); + getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) { + import('./components/WebApiApp').then(i => callback(null, { component: (i as any).default })); } }, { path: '**', - getComponent(_, callback) { - import('./components/WebApiApp').then(i => callback(null, i.default)); + getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) { + import('./components/WebApiApp').then(i => callback(null, (i as any).default)); } } ]; |