diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2017-03-30 14:09:03 +0200 |
---|---|---|
committer | Stas Vilchik <stas-vilchik@users.noreply.github.com> | 2017-04-03 10:38:52 +0200 |
commit | 2c890d852dd6c355a64679e1d603c17bfac29bc5 (patch) | |
tree | 541bf0a796a10944ecf5ce72f719edc2d0321cff /server/sonar-web/src/main/js/apps/quality-profiles | |
parent | 0f56fb56a40c1ee72f68dd170b12202e690086d9 (diff) | |
download | sonarqube-2c890d852dd6c355a64679e1d603c17bfac29bc5.tar.gz sonarqube-2c890d852dd6c355a64679e1d603c17bfac29bc5.zip |
SONAR-8927 Change format of quality profile permalinks
Diffstat (limited to 'server/sonar-web/src/main/js/apps/quality-profiles')
16 files changed, 161 insertions, 77 deletions
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogContainer.js b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogContainer.js index a1fe68f50af..119c4bd52be 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogContainer.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/ChangelogContainer.js @@ -125,23 +125,37 @@ export default class ChangelogContainer extends React.PureComponent { } handleFromDateChange = (fromDate?: string) => { - const path = getProfileChangelogPath(this.props.profile.key, this.props.organization, { - since: fromDate, - to: this.props.location.query.to - }); + const path = getProfileChangelogPath( + this.props.profile.name, + this.props.profile.language, + this.props.organization, + { + since: fromDate, + to: this.props.location.query.to + } + ); this.context.router.push(path); }; handleToDateChange = (toDate?: string) => { - const path = getProfileChangelogPath(this.props.profile.key, this.props.organization, { - since: this.props.location.query.since, - to: toDate - }); + const path = getProfileChangelogPath( + this.props.profile.name, + this.props.profile.language, + this.props.organization, + { + since: this.props.location.query.since, + to: toDate + } + ); this.context.router.push(path); }; handleReset = () => { - const path = getProfileChangelogPath(this.props.profile.key, this.props.organization); + const path = getProfileChangelogPath( + this.props.profile.name, + this.props.profile.language, + this.props.organization + ); this.context.router.push(path); }; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonContainer.js b/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonContainer.js index 6428c060684..24fba98b452 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonContainer.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/compare/ComparisonContainer.js @@ -93,7 +93,12 @@ export default class ComparisonContainer extends React.PureComponent { } handleCompare = (withKey: string) => { - const path = getProfileComparePath(this.props.profile.key, this.props.organization, withKey); + const path = getProfileComparePath( + this.props.profile.name, + this.props.profile.language, + this.props.organization, + withKey + ); this.context.router.push(path); }; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileActions.js b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileActions.js index d1398b7f90e..aacbe90c428 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileActions.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileActions.js @@ -31,6 +31,7 @@ import type { Profile } from '../propTypes'; type Props = { canAdmin: boolean, + fromList: boolean, organization: ?string, profile: Profile, updateProfiles: () => Promise<*> @@ -39,6 +40,10 @@ type Props = { export default class ProfileActions extends React.PureComponent { props: Props; + static defaultProps = { + fromList: false + }; + static contextTypes = { router: React.PropTypes.object }; @@ -46,7 +51,15 @@ export default class ProfileActions extends React.PureComponent { handleRenameClick = (e: SyntheticInputEvent) => { e.preventDefault(); new RenameProfileView({ profile: this.props.profile }) - .on('done', () => this.props.updateProfiles()) + .on('done', (newName: string) => { + this.props.updateProfiles().then(() => { + if (!this.props.fromList) { + this.context.router.replace( + getProfilePath(newName, this.props.profile.language, this.props.organization) + ); + } + }); + }) .render(); }; @@ -55,7 +68,9 @@ export default class ProfileActions extends React.PureComponent { new CopyProfileView({ profile: this.props.profile }) .on('done', profile => { this.props.updateProfiles().then(() => { - this.context.router.push(getProfilePath(profile.key, this.props.organization)); + this.context.router.push( + getProfilePath(profile.name, profile.language, this.props.organization) + ); }); }) .render(); @@ -107,7 +122,7 @@ export default class ProfileActions extends React.PureComponent { </li> <li> <Link - to={getProfileComparePath(profile.key, this.props.organization)} + to={getProfileComparePath(profile.name, profile.language, this.props.organization)} id="quality-profile-compare"> {translate('compare')} </Link> diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileContainer.js b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileContainer.js index d55f57dd8fe..0ee269b6a25 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileContainer.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileContainer.js @@ -28,19 +28,51 @@ import type { Profile } from '../propTypes'; type Props = { canAdmin: boolean, children: React.Element<*>, - location: { query: { key: string } }, + location: { + pathname: string, + query: { key?: string, language: string, name: string } + }, organization: ?string, profiles: Array<Profile>, + router: { replace: () => void }, updateProfiles: () => Promise<*> }; export default class ProfileContainer extends React.PureComponent { props: Props; + componentDidMount() { + const { location, profiles, router } = this.props; + if (location.query.key) { + // try to find a quality profile with the given key + // if managed to find one, redirect to a new version + // otherwise do nothing, `render` will show not found page + const profile = profiles.find(profile => profile.key === location.query.key); + if (profile) { + router.replace({ + pathname: location.pathname, + query: { language: profile.language, name: profile.name } + }); + } + } + } + render() { const { organization, profiles, location, ...other } = this.props; - const { key } = location.query; - const profile = profiles.find(profile => profile.key === key); + const { key, language, name } = location.query; + + if (key) { + // if there is a `key` parameter, + // then if we managed to find a quality profile with this key + // then we will be redirected in `componentDidMount` + // otherwise show `ProfileNotFound` + const profile = profiles.find(profile => profile.key === location.query.key); + return profile ? null : <ProfileNotFound organization={organization} />; + } + + const profile = profiles.find( + profile => profile.language === language && profile.name === name + ); if (!profile) { return <ProfileNotFound organization={organization} />; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileLink.js b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileLink.js index a60c37ab9b1..0eb92cb0105 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileLink.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileLink.js @@ -24,18 +24,19 @@ import { getProfilePath } from '../utils'; type Props = { children?: React.Element<*>, - organization: ?string, - profileKey: string + language: string, + name: string, + organization: ?string }; export default class ProfileLink extends React.PureComponent { props: Props; render() { - const { profileKey, organization, children, ...other } = this.props; + const { name, language, organization, children, ...other } = this.props; return ( <Link - to={getProfilePath(profileKey, organization)} + to={getProfilePath(name, language, organization)} activeClassName="link-no-underline" {...other}> {children} 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.js index c4073232a95..08aa98c6b32 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.js @@ -26,12 +26,12 @@ import ProfileHeader from '../../details/ProfileHeader'; import { createFakeProfile } from '../../utils'; it('should render ProfileHeader', () => { - const targetProfile = createFakeProfile({ key: 'profile1' }); - const profiles = [targetProfile, createFakeProfile({ key: 'profile2' })]; + const targetProfile = createFakeProfile({ language: 'js', name: 'fake' }); + const profiles = [targetProfile, createFakeProfile({ language: 'js', name: 'another' })]; const updateProfiles = jest.fn(); const output = shallow( <ProfileContainer - location={{ query: { key: 'profile1' } }} + location={{ query: { language: 'js', name: 'fake' } }} profiles={profiles} canAdmin={false} updateProfiles={updateProfiles}> @@ -46,10 +46,13 @@ it('should render ProfileHeader', () => { }); it('should render ProfileNotFound', () => { - const profiles = [createFakeProfile({ key: 'profile1' }), createFakeProfile({ key: 'profile2' })]; + const profiles = [ + createFakeProfile({ language: 'js', name: 'fake' }), + createFakeProfile({ language: 'js', name: 'another' }) + ]; const output = shallow( <ProfileContainer - location={{ query: { key: 'random' } }} + location={{ query: { language: 'js', name: 'random' } }} profiles={profiles} canAdmin={false} updateProfiles={() => true}> @@ -60,11 +63,11 @@ it('should render ProfileNotFound', () => { }); it('should render Helmet', () => { - const profiles = [createFakeProfile({ key: 'profile1', name: 'First Profile' })]; + const profiles = [createFakeProfile({ language: 'js', name: 'First Profile' })]; const updateProfiles = jest.fn(); const output = shallow( <ProfileContainer - location={{ query: { key: 'profile1' } }} + location={{ query: { language: 'js', name: 'First Profile' } }} profiles={profiles} canAdmin={false} updateProfiles={updateProfiles}> diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileHeader.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileHeader.js index 3a06c63e472..5c66dfcfcac 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileHeader.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileHeader.js @@ -108,9 +108,10 @@ export default class ProfileHeader extends React.PureComponent { <h1 className="page-title"> <ProfileLink - organization={organization} - profileKey={profile.key} - className="link-base-color"> + className="link-base-color" + language={profile.language} + name={profile.name} + organization={organization}> <span>{profile.name}</span> </ProfileLink> </h1> @@ -120,7 +121,9 @@ export default class ProfileHeader extends React.PureComponent { {this.renderUpdateDate()} {this.renderUsageDate()} <li> - <Link to={getProfileChangelogPath(profile.key, organization)} className="button"> + <Link + to={getProfileChangelogPath(profile.name, profile.language, organization)} + className="button"> {translate('changelog')} </Link> </li> diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritance.js b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritance.js index f6760f674f5..ea38598bd65 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritance.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritance.js @@ -34,26 +34,19 @@ type Props = { updateProfiles: () => Promise<*> }; +type ProfileInheritanceDetails = { + activeRuleCount: number, + key: string, + language: string, + name: string, + overridingRuleCount?: number +}; + type State = { - ancestors?: Array<{ - activeRuleCount: number, - key: string, - name: string, - overridingRuleCount?: number - }>, - children?: Array<{ - activeRuleCount: number, - key: string, - name: string, - overridingRuleCount?: number - }>, + ancestors?: Array<ProfileInheritanceDetails>, + children?: Array<ProfileInheritanceDetails>, loading: boolean, - profile?: { - activeRuleCount: number, - key: string, - name: string, - overridingRuleCount?: number - } + profile?: ProfileInheritanceDetails }; export default class ProfileInheritance extends React.PureComponent { @@ -129,6 +122,7 @@ export default class ProfileInheritance extends React.PureComponent { className="js-inheritance-ancestor" depth={index} key={ancestor.key} + language={this.props.profile.language} organization={this.props.organization} profile={ancestor} /> @@ -138,6 +132,7 @@ export default class ProfileInheritance extends React.PureComponent { className={currentClassName} depth={this.state.ancestors ? this.state.ancestors.length : 0} displayLink={false} + language={this.props.profile.language} organization={this.props.organization} profile={this.state.profile} /> @@ -148,6 +143,7 @@ export default class ProfileInheritance extends React.PureComponent { className="js-inheritance-child" depth={this.state.ancestors ? this.state.ancestors.length + 1 : 0} key={child.key} + language={this.props.profile.language} organization={this.props.organization} profile={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 index 5af9d91b207..6ae591d571c 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritanceBox.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritanceBox.js @@ -26,10 +26,12 @@ type Props = { className?: string, depth: number, displayLink?: boolean, + language: string, organization: ?string, profile: { activeRuleCount: number, key: string, + language: string, name: string, overridingRuleCount?: number } @@ -51,7 +53,10 @@ export default class ProfileInheritanceBox extends React.PureComponent { <td> <div style={{ paddingLeft: offset }}> {this.props.displayLink - ? <ProfileLink organization={this.props.organization} profileKey={profile.key}> + ? <ProfileLink + language={this.props.language} + name={profile.name} + organization={this.props.organization}> {profile.name} </ProfileLink> : profile.name} diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.js index 89d9d87beab..037c1e9f16f 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.js @@ -61,9 +61,10 @@ export default class EvolutionDeprecated extends React.PureComponent { <li key={profile.key} className="spacer-top"> <div className="text-ellipsis"> <ProfileLink - organization={this.props.organization} - profileKey={profile.key} - className="link-no-underline"> + className="link-no-underline" + language={profile.language} + name={profile.name} + organization={this.props.organization}> {profile.name} </ProfileLink> </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 index 29679aca1ae..63f0ff7bdef 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.js @@ -55,9 +55,10 @@ export default class EvolutionStagnant extends React.PureComponent { <li key={profile.key} className="spacer-top"> <div className="text-ellipsis"> <ProfileLink - organization={this.props.organization} - profileKey={profile.key} - className="link-no-underline"> + className="link-no-underline" + language={profile.language} + name={profile.name} + organization={this.props.organization}> {profile.name} </ProfileLink> </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.js index 48ff0383758..df6191a8300 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.js @@ -73,7 +73,9 @@ export default class PageHeader extends React.PureComponent { }) .on('done', profile => { this.props.updateProfiles().then(() => { - this.context.router.push(getProfilePath(profile.key, this.props.organization)); + this.context.router.push( + getProfilePath(profile.name, profile.language, this.props.organization) + ); }); }) .render(); diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListRow.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListRow.js index a38a5e9954f..8f3e21c793e 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListRow.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListRow.js @@ -48,7 +48,10 @@ export default class ProfilesListRow extends React.PureComponent { const offset = 25 * (profile.depth - 1); return ( <div style={{ paddingLeft: offset }}> - <ProfileLink organization={this.props.organization} profileKey={profile.key}> + <ProfileLink + language={profile.language} + name={profile.name} + organization={this.props.organization}> {profile.name} </ProfileLink> </div> @@ -161,6 +164,7 @@ export default class ProfilesListRow extends React.PureComponent { </button> <ProfileActions canAdmin={this.props.canAdmin} + fromList={true} organization={this.props.organization} profile={this.props.profile} updateProfiles={this.props.updateProfiles} 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.js index 57c5ca1baad..4c53b80384f 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/routes.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/routes.js @@ -17,6 +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. */ +import { withRouter } from 'react-router'; + const routes = [ { getComponent(state, callback) { @@ -39,7 +41,7 @@ const routes = [ { getComponent(_, callback) { require.ensure([], require => { - callback(null, require('./components/ProfileContainer').default); + callback(null, withRouter(require('./components/ProfileContainer').default)); }); }, childRoutes: [ diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/utils.js b/server/sonar-web/src/main/js/apps/quality-profiles/utils.js index 64bb0ea07d6..97ff96be524 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/utils.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/utils.js @@ -70,36 +70,38 @@ export const getProfilesPath = (organization: ?string) => organization ? `/organizations/${organization}/quality_profiles` : '/profiles'; export const getProfilesForLanguagePath = (language: string, organization: ?string) => ({ - pathname: organization ? `/organizations/${organization}/quality_profiles` : '/profiles', + pathname: getProfilesPath(organization), query: { language } }); -export const getProfilePath = (profile: string, organization: ?string) => ({ - pathname: organization - ? `/organizations/${organization}/quality_profiles/show` - : '/profiles/show', - query: { key: profile } +export const getProfilePath = (name: string, language: string, organization: ?string) => ({ + pathname: getProfilesPath(organization) + '/show', + query: { name, language } }); -export const getProfileComparePath = (profile: string, organization: ?string, withKey?: string) => { - const query: Object = { key: profile }; +export const getProfileComparePath = ( + name: string, + language: string, + organization: ?string, + withKey?: string +) => { + const query: Object = { language, name }; if (withKey) { Object.assign(query, { withKey }); } return { - pathname: organization - ? `/organizations/${organization}/quality_profiles/compare` - : '/profiles/compare', + pathname: getProfilesPath(organization) + '/compare', query }; }; export const getProfileChangelogPath = ( - profile: string, + name: string, + language: string, organization: ?string, filter?: { since?: string, to?: string } ) => { - const query: Object = { key: profile }; + const query: Object = { language, name }; if (filter) { if (filter.since) { Object.assign(query, { since: filter.since }); @@ -109,9 +111,7 @@ export const getProfileChangelogPath = ( } } return { - pathname: organization - ? `/organizations/${organization}/quality_profiles/changelog` - : '/profiles/changelog', + pathname: getProfilesPath(organization) + '/changelog', query }; }; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/views/RenameProfileView.js b/server/sonar-web/src/main/js/apps/quality-profiles/views/RenameProfileView.js index 308efa7c143..57e3e5c5e67 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/views/RenameProfileView.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/views/RenameProfileView.js @@ -33,9 +33,9 @@ export default ModalFormView.extend({ sendRequest() { const name = this.$('#rename-profile-name').val(); renameProfile(this.options.profile.key, name) - .then(profile => { + .then(() => { this.destroy(); - this.trigger('done', profile); + this.trigger('done', name); }) .catch(e => { if (e.response.status === 400) { |