From e497662d7c337fcc7c5293e2a38fd63cf8783bfd Mon Sep 17 00:00:00 2001 From: Stas Vilchik Date: Thu, 8 Feb 2018 12:05:28 +0100 Subject: [PATCH] SONAR-10375 Project's homepage sidebar improvements (#3032) --- server/sonar-web/src/main/js/app/theme.js | 2 + .../js/apps/overview/badges/BadgesModal.tsx | 4 +- .../__snapshots__/BadgesModal-test.tsx.snap | 6 +- .../apps/overview/components/OverviewApp.tsx | 2 +- .../js/apps/overview/events/AnalysesList.tsx | 4 +- .../src/main/js/apps/overview/meta/Meta.tsx | 67 +++++++++---------- .../{MetaOrganizationKey.js => MetaKey.tsx} | 31 ++++----- .../main/js/apps/overview/meta/MetaLinks.tsx | 2 + .../{MetaKey.js => MetaOrganizationKey.tsx} | 30 ++++----- ...MetaQualityGate.js => MetaQualityGate.tsx} | 21 +++--- ...ityProfiles.js => MetaQualityProfiles.tsx} | 58 ++++++++-------- .../main/js/apps/overview/meta/MetaSize.tsx | 2 +- .../main/js/apps/overview/meta/MetaTags.tsx | 4 +- .../__snapshots__/MetaTags-test.tsx.snap | 10 +-- .../src/main/js/apps/overview/styles.css | 24 +++++-- .../resources/org/sonar/l10n/core.properties | 13 ++++ 16 files changed, 161 insertions(+), 119 deletions(-) rename server/sonar-web/src/main/js/apps/overview/meta/{MetaOrganizationKey.js => MetaKey.tsx} (60%) rename server/sonar-web/src/main/js/apps/overview/meta/{MetaKey.js => MetaOrganizationKey.tsx} (61%) rename server/sonar-web/src/main/js/apps/overview/meta/{MetaQualityGate.js => MetaQualityGate.tsx} (77%) rename server/sonar-web/src/main/js/apps/overview/meta/{MetaQualityProfiles.js => MetaQualityProfiles.tsx} (72%) diff --git a/server/sonar-web/src/main/js/app/theme.js b/server/sonar-web/src/main/js/app/theme.js index b5ebfb7b796..04f518b8060 100644 --- a/server/sonar-web/src/main/js/app/theme.js +++ b/server/sonar-web/src/main/js/app/theme.js @@ -70,6 +70,8 @@ module.exports = { contextNavHeightRaw: 9 * grid, + pagePadding: '20px', + // different defaultShadow: '0 6px 12px rgba(0, 0, 0, 0.175)', diff --git a/server/sonar-web/src/main/js/apps/overview/badges/BadgesModal.tsx b/server/sonar-web/src/main/js/apps/overview/badges/BadgesModal.tsx index b86c74027f4..4a4e572f7c3 100644 --- a/server/sonar-web/src/main/js/apps/overview/badges/BadgesModal.tsx +++ b/server/sonar-web/src/main/js/apps/overview/badges/BadgesModal.tsx @@ -65,7 +65,7 @@ export default class BadgesModal extends React.PureComponent { const header = translate('overview.badges.title'); const fullBadgeOptions = { branch, project, ...badgeOptions }; return ( - <> +
@@ -106,7 +106,7 @@ export default class BadgesModal extends React.PureComponent { )} - +
); } } diff --git a/server/sonar-web/src/main/js/apps/overview/badges/__tests__/__snapshots__/BadgesModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/badges/__tests__/__snapshots__/BadgesModal-test.tsx.snap index f43e19a5715..e813fd772bd 100644 --- a/server/sonar-web/src/main/js/apps/overview/badges/__tests__/__snapshots__/BadgesModal-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/overview/badges/__tests__/__snapshots__/BadgesModal-test.tsx.snap @@ -1,14 +1,16 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`should display the modal after click 1`] = ` - +
- +
`; exports[`should display the modal after click 2`] = ` diff --git a/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.tsx b/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.tsx index 44285fe03da..4e7dd8c57b5 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.tsx +++ b/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.tsx @@ -191,7 +191,7 @@ export class OverviewApp extends React.PureComponent { -
+
{ return (
-

{translate('project_activity.page')}

+

+ {translate('overview.project_activity', this.props.component.qualifier)} +

{ const isProject = qualifier === 'TRK'; const isPrivate = visibility === Visibility.Private; - const hasDescription = !!description; - const hasQualityProfiles = Array.isArray(qualityProfiles) && qualityProfiles.length > 0; - const hasQualityGate = !!qualityGate; - - const shouldShowQualityProfiles = isProject && hasQualityProfiles; - const shouldShowQualityGate = isProject && hasQualityGate; - const hasOrganization = component.organization != null && organizationsEnabled; - return (
- {hasDescription && ( -
{description}
- )} - - - - {isProject && ( - - )} +
+

+ {translate('overview.about_this_project', qualifier)} +

+ {description !== undefined &&

{description}

} + {isProject && ( + + )} + +
{ qualifier={component.qualifier} /> - {shouldShowQualityGate && ( - - )} - - {shouldShowQualityProfiles && ( - + {isProject && ( +
+ {qualityGate && ( + + )} + + {qualityProfiles && + qualityProfiles.length > 0 && ( + + )} +
)} {isProject && } - - - {hasOrganization && } +
+ + {organizationsEnabled && } +
{onSonarCloud && isProject && diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaOrganizationKey.js b/server/sonar-web/src/main/js/apps/overview/meta/MetaKey.tsx similarity index 60% rename from server/sonar-web/src/main/js/apps/overview/meta/MetaOrganizationKey.js rename to server/sonar-web/src/main/js/apps/overview/meta/MetaKey.tsx index 30bd9aa417b..4d6c5748748 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/MetaOrganizationKey.js +++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaKey.tsx @@ -17,22 +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. */ -import React from 'react'; +import * as React from 'react'; +import ClipboardButton from '../../../components/controls/ClipboardButton'; import { translate } from '../../../helpers/l10n'; -const MetaOrganizationKey = ({ component }) => { +interface Props { + componentKey: string; + qualifier: string; +} + +export default function MetaKey({ componentKey, qualifier }: Props) { return ( -
-

{translate('organization_key')}

- e.target.select()} - /> -
+ <> +

{translate('overview.project_key', qualifier)}

+
+ + +
+ ); -}; - -export default MetaOrganizationKey; +} diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaLinks.tsx b/server/sonar-web/src/main/js/apps/overview/meta/MetaLinks.tsx index 66980dda926..907d76a3877 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/MetaLinks.tsx +++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaLinks.tsx @@ -22,6 +22,7 @@ import MetaLink from './MetaLink'; import { getProjectLinks, ProjectLink } from '../../../api/projectLinks'; import { orderLinks } from '../../project-admin/links/utils'; import { LightComponent } from '../../../app/types'; +import { translate } from '../../../helpers/l10n'; interface Props { component: LightComponent; @@ -71,6 +72,7 @@ export default class MetaLinks extends React.PureComponent { return (
+

{translate('overview.external_links')}

    {orderedLinks.map(link => )}
diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaKey.js b/server/sonar-web/src/main/js/apps/overview/meta/MetaOrganizationKey.tsx similarity index 61% rename from server/sonar-web/src/main/js/apps/overview/meta/MetaKey.js rename to server/sonar-web/src/main/js/apps/overview/meta/MetaOrganizationKey.tsx index cfb43f2d58e..9d8ca5a8000 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/MetaKey.js +++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaOrganizationKey.tsx @@ -17,22 +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 React from 'react'; +import * as React from 'react'; import { translate } from '../../../helpers/l10n'; +import ClipboardButton from '../../../components/controls/ClipboardButton'; -const MetaKey = ({ component }) => { +interface Props { + organization: string; +} + +export default function MetaOrganizationKey({ organization }: Props) { return ( -
-

{translate('key')}

- e.target.select()} - /> -
+ <> +

{translate('organization_key')}

+
+ + +
+ ); -}; - -export default MetaKey; +} diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaQualityGate.js b/server/sonar-web/src/main/js/apps/overview/meta/MetaQualityGate.tsx similarity index 77% rename from server/sonar-web/src/main/js/apps/overview/meta/MetaQualityGate.js rename to server/sonar-web/src/main/js/apps/overview/meta/MetaQualityGate.tsx index 2181137c139..bd713048330 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/MetaQualityGate.js +++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaQualityGate.tsx @@ -17,26 +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 React from 'react'; +import * as React from 'react'; import { Link } from 'react-router'; import { translate } from '../../../helpers/l10n'; import { getQualityGateUrl } from '../../../helpers/urls'; -const MetaQualityGate = ({ gate, organization }) => { +interface Props { + organization?: string; + qualityGate: { isDefault?: boolean; key: string; name: string }; +} + +export default function MetaQualityGate({ qualityGate, organization }: Props) { return ( -
+ <>

{translate('overview.quality_gate')}

  • - {gate.isDefault && ( + {qualityGate.isDefault && ( {'(' + translate('default') + ')'} )} - {gate.name} + {qualityGate.name}
-
+ ); -}; - -export default MetaQualityGate; +} diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaQualityProfiles.js b/server/sonar-web/src/main/js/apps/overview/meta/MetaQualityProfiles.tsx similarity index 72% rename from server/sonar-web/src/main/js/apps/overview/meta/MetaQualityProfiles.js rename to server/sonar-web/src/main/js/apps/overview/meta/MetaQualityProfiles.tsx index c39bcf3846d..c9648810b85 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/MetaQualityProfiles.js +++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaQualityProfiles.tsx @@ -17,31 +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 { connect } from 'react-redux'; import { Link } from 'react-router'; +import * as classNames from 'classnames'; import Tooltip from '../../../components/controls/Tooltip'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { getQualityProfileUrl } from '../../../helpers/urls'; import { searchRules } from '../../../api/rules'; import { getLanguages } from '../../../store/rootReducer'; -class MetaQualityProfiles extends React.PureComponent { - /*:: mounted: boolean; */ +interface StateProps { + languages: { [key: string]: { name: string } }; +} - /*:: props: { - component: { organization: string }, - customOrganizations: boolean, - languages: { [string]: { name: string } }, - organization: string | void; - profiles: Array<{ key: string, language: string, name: string }> - }; -*/ +interface OwnProps { + headerClassName?: string; + organization?: string; + profiles: { key: string; language: string; name: string }[]; +} - state = { - deprecatedByKey: {} - }; +interface State { + deprecatedByKey: { [key: string]: number }; +} + +class MetaQualityProfiles extends React.PureComponent { + mounted: boolean; + state: State = { deprecatedByKey: {} }; componentDidMount() { this.mounted = true; @@ -59,7 +61,7 @@ class MetaQualityProfiles extends React.PureComponent { Promise.all(requests).then( responses => { if (this.mounted) { - const deprecatedByKey = {}; + const deprecatedByKey: { [key: string]: number } = {}; responses.forEach((count, i) => { const profileKey = this.props.profiles[i].key; deprecatedByKey[profileKey] = count; @@ -71,7 +73,7 @@ class MetaQualityProfiles extends React.PureComponent { ); } - loadDeprecatedRulesForProfile(profileKey) { + loadDeprecatedRulesForProfile(profileKey: string) { const data = { activation: 'true', organization: this.props.organization, @@ -82,18 +84,16 @@ class MetaQualityProfiles extends React.PureComponent { return searchRules(data).then(r => r.total); } - getDeprecatedRulesCount(profile) { + getDeprecatedRulesCount(profile: { key: string }) { const count = this.state.deprecatedByKey[profile.key]; return count || 0; } - renderProfile(profile) { + renderProfile(profile: { key: string; language: string; name: string }) { const languageFromStore = this.props.languages[profile.language]; const languageName = languageFromStore ? languageFromStore.name : profile.language; - const path = this.props.customOrganizations - ? getQualityProfileUrl(profile.name, profile.language, this.props.component.organization) - : getQualityProfileUrl(profile.name, profile.language); + const path = getQualityProfileUrl(profile.name, profile.language, this.props.organization); const inner = (
@@ -117,22 +117,24 @@ class MetaQualityProfiles extends React.PureComponent { } render() { - const { profiles } = this.props; + const { headerClassName, profiles } = this.props; return ( -
-

{translate('overview.quality_profiles')}

+ <> +

+ {translate('overview.quality_profiles')} +

    {profiles.map(profile => this.renderProfile(profile))}
-
+ ); } } -const mapStateToProps = state => ({ +const mapStateToProps = (state: any) => ({ languages: getLanguages(state) }); -export default connect(mapStateToProps)(MetaQualityProfiles); +export default connect(mapStateToProps)(MetaQualityProfiles); diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.tsx b/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.tsx index 6465c861817..335d0b48795 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.tsx +++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.tsx @@ -89,7 +89,7 @@ export default class MetaSize extends React.PureComponent { } return ( -
+
{this.props.component.qualifier === 'APP' && this.renderProjects()} {this.renderLoC(ncloc)} {this.renderLoCDistribution()} diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaTags.tsx b/server/sonar-web/src/main/js/apps/overview/meta/MetaTags.tsx index e0caea4f6fb..209b8a97880 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/MetaTags.tsx +++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaTags.tsx @@ -99,7 +99,7 @@ export default class MetaTags extends React.PureComponent { if (this.canUpdateTags()) { return ( -
(this.card = card)}> +
(this.card = card)}>