@@ -117,7 +117,7 @@ export interface ProfileProject { | |||
export function getProfileProjects( | |||
data: RequestData | |||
): Promise<{ more: boolean; results: ProfileProject[] }> { | |||
): Promise<{ more: boolean; paging: T.Paging; results: ProfileProject[] }> { | |||
return getJSON('/api/qualityprofiles/projects', data).catch(throwGlobalError); | |||
} | |||
@@ -52,7 +52,11 @@ export default function ProfileDetails(props: Props) { | |||
</div> | |||
<div className="quality-profile-grid-right"> | |||
<ProfileInheritance {...props} /> | |||
<ProfileProjects {...props} /> | |||
<ProfileProjects | |||
organization={props.organization} | |||
profile={profile} | |||
updateProfiles={props.updateProfiles} | |||
/> | |||
</div> | |||
</div> | |||
</div> |
@@ -64,7 +64,7 @@ export default class ProfileInheritance extends React.PureComponent<Props, State | |||
} | |||
componentDidUpdate(prevProps: Props) { | |||
if (prevProps.profile !== this.props.profile) { | |||
if (prevProps.profile.key !== this.props.profile.key) { | |||
this.loadData(); | |||
} | |||
} |
@@ -29,6 +29,7 @@ import { | |||
} from '../../../api/quality-profiles'; | |||
import { Button } from '../../../components/ui/buttons'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { Profile } from '../types'; | |||
export interface User { | |||
avatar?: string; | |||
@@ -42,7 +43,7 @@ export interface Group { | |||
interface Props { | |||
organization?: string; | |||
profile: { language: string; name: string }; | |||
profile: Pick<Profile, 'key' | 'language' | 'name'>; | |||
} | |||
interface State { | |||
@@ -64,7 +65,7 @@ export default class ProfilePermissions extends React.PureComponent<Props, State | |||
componentDidUpdate(prevProps: Props) { | |||
if ( | |||
prevProps.organization !== this.props.organization || | |||
prevProps.profile !== this.props.profile | |||
prevProps.profile.key !== this.props.profile.key | |||
) { | |||
this.fetchUsersAndGroups(); | |||
} |
@@ -36,9 +36,9 @@ interface Props { | |||
interface State { | |||
formOpen: boolean; | |||
loading: boolean; | |||
loadingMore: boolean; | |||
page: number; | |||
projects: Array<{ key: string; name: string; uuid: string }> | null; | |||
ready: boolean; | |||
projects: Array<{ key: string; name: string }>; | |||
total: number; | |||
} | |||
@@ -48,9 +48,9 @@ export default class ProfileProjects extends React.PureComponent<Props, State> { | |||
state: State = { | |||
formOpen: false, | |||
loading: true, | |||
loadingMore: false, | |||
page: 1, | |||
projects: null, | |||
ready: true, | |||
projects: [], | |||
total: 0 | |||
}; | |||
@@ -60,8 +60,8 @@ export default class ProfileProjects extends React.PureComponent<Props, State> { | |||
} | |||
componentDidUpdate(prevProps: Props) { | |||
if (prevProps.profile !== this.props.profile) { | |||
this.setState({ projects: null, page: 1 }, this.loadProjects); | |||
if (prevProps.profile.key !== this.props.profile.key) { | |||
this.loadProjects(); | |||
} | |||
} | |||
@@ -69,30 +69,43 @@ export default class ProfileProjects extends React.PureComponent<Props, State> { | |||
this.mounted = false; | |||
} | |||
stopLoading = () => { | |||
if (this.mounted) { | |||
this.setState({ loading: false }); | |||
} | |||
}; | |||
loadProjects() { | |||
if (this.props.profile.isDefault) { | |||
this.setState({ loading: false }); | |||
this.setState({ loading: false, projects: [] }); | |||
return; | |||
} | |||
this.setState({ loading: true }); | |||
const data = { key: this.props.profile.key, page: this.state.page }; | |||
getProfileProjects(data).then( | |||
(r: any) => { | |||
if (this.mounted) { | |||
this.setState(state => ({ | |||
projects: state.projects ? [...state.projects, ...r.results] : r.results, | |||
total: r.paging.total, | |||
loading: false, | |||
ready: true | |||
})); | |||
} | |||
}, | |||
() => {} | |||
); | |||
getProfileProjects(data).then(({ paging, results }) => { | |||
if (this.mounted) { | |||
this.setState({ | |||
projects: results, | |||
total: paging.total, | |||
loading: false | |||
}); | |||
} | |||
}, this.stopLoading); | |||
} | |||
loadMore = () => { | |||
this.setState(state => ({ ready: false, page: state.page + 1 }), this.loadProjects); | |||
this.setState({ loadingMore: true }); | |||
const data = { key: this.props.profile.key, page: this.state.page + 1 }; | |||
getProfileProjects(data).then(({ paging, results }) => { | |||
if (this.mounted) { | |||
this.setState(state => ({ | |||
projects: [...state.projects, ...results], | |||
total: paging.total, | |||
loadingMore: false | |||
})); | |||
} | |||
}, this.stopLoading); | |||
}; | |||
handleChangeClick = () => { | |||
@@ -105,10 +118,6 @@ export default class ProfileProjects extends React.PureComponent<Props, State> { | |||
}; | |||
renderDefault() { | |||
if (this.state.loading) { | |||
return <i className="spinner" />; | |||
} | |||
return ( | |||
<div> | |||
<span className="badge spacer-right">{translate('default')}</span> | |||
@@ -124,10 +133,6 @@ export default class ProfileProjects extends React.PureComponent<Props, State> { | |||
const { projects } = this.state; | |||
if (projects == null) { | |||
return null; | |||
} | |||
if (projects.length === 0) { | |||
return <div>{translate('quality_profiles.no_projects_associated_to_profile')}</div>; | |||
} | |||
@@ -136,7 +141,7 @@ export default class ProfileProjects extends React.PureComponent<Props, State> { | |||
<> | |||
<ul> | |||
{projects.map(project => ( | |||
<li className="spacer-top js-profile-project" data-key={project.key} key={project.uuid}> | |||
<li className="spacer-top js-profile-project" data-key={project.key} key={project.key}> | |||
<Link | |||
className="link-with-icon" | |||
to={{ pathname: '/dashboard', query: { id: project.key } }}> | |||
@@ -148,7 +153,7 @@ export default class ProfileProjects extends React.PureComponent<Props, State> { | |||
<ListFooter | |||
count={projects.length} | |||
loadMore={this.loadMore} | |||
ready={this.state.ready} | |||
ready={!this.state.loadingMore} | |||
total={this.state.total} | |||
/> | |||
</> |
@@ -71,7 +71,7 @@ export default class ProfileRules extends React.PureComponent<Props, State> { | |||
} | |||
componentDidUpdate(prevProps: Props) { | |||
if (prevProps.profile !== this.props.profile) { | |||
if (prevProps.profile.key !== this.props.profile.key) { | |||
this.loadRules(); | |||
} | |||
} |
@@ -31,7 +31,7 @@ jest.mock('../../../../api/quality-profiles', () => ({ | |||
const searchUsers = require('../../../../api/quality-profiles').searchUsers as jest.Mock<any>; | |||
const searchGroups = require('../../../../api/quality-profiles').searchGroups as jest.Mock<any>; | |||
const profile = { name: 'Sonar way', language: 'js' }; | |||
const profile = { key: 'sonar-way', name: 'Sonar way', language: 'js' }; | |||
beforeEach(() => { | |||
searchUsers.mockClear(); |
@@ -62,7 +62,6 @@ exports[`renders with edit permission 1`] = ` | |||
updateProfiles={[MockFunction]} | |||
/> | |||
<ProfileProjects | |||
exporters={Array []} | |||
organization="org" | |||
profile={ | |||
Object { | |||
@@ -71,7 +70,6 @@ exports[`renders with edit permission 1`] = ` | |||
}, | |||
} | |||
} | |||
profiles={Array []} | |||
updateProfiles={[MockFunction]} | |||
/> | |||
</div> | |||
@@ -113,10 +111,8 @@ exports[`renders without permissions 1`] = ` | |||
updateProfiles={[MockFunction]} | |||
/> | |||
<ProfileProjects | |||
exporters={Array []} | |||
organization="org" | |||
profile={Object {}} | |||
profiles={Array []} | |||
updateProfiles={[MockFunction]} | |||
/> | |||
</div> |
@@ -49,6 +49,7 @@ exports[`renders 2`] = ` | |||
onDelete={[Function]} | |||
profile={ | |||
Object { | |||
"key": "sonar-way", | |||
"language": "js", | |||
"name": "Sonar way", | |||
} | |||
@@ -70,6 +71,7 @@ exports[`renders 2`] = ` | |||
onDelete={[Function]} | |||
profile={ | |||
Object { | |||
"key": "sonar-way", | |||
"language": "js", | |||
"name": "Sonar way", | |||
} |