Browse Source

SONAR-13936 Fix issues sidebar search where in some case we trigger wrong API call.

tags/8.6.0.39681
Mathieu Suen 3 years ago
parent
commit
257acb97b7

+ 1
- 67
server/sonar-web/src/main/js/api/organizations.ts View File

@@ -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 { getJSON, post, postJSON } from 'sonar-ui-common/helpers/request';
import { getJSON } from 'sonar-ui-common/helpers/request';
import throwGlobalError from '../app/utils/throwGlobalError';

export function getOrganizations(data: {
@@ -51,69 +51,3 @@ export function getOrganizationNavigation(key: string): Promise<GetOrganizationN
throwGlobalError
);
}

export function getOrganizationsThatPreventDeletion(): Promise<{
organizations: T.Organization[];
}> {
return getJSON('/api/organizations/prevent_user_deletion').catch(throwGlobalError);
}

export function createOrganization(
data: T.OrganizationBase & { installationId?: string }
): Promise<T.Organization> {
return postJSON('/api/organizations/create', data).then(r => r.organization, throwGlobalError);
}

export function updateOrganization(key: string, changes: T.OrganizationBase) {
return post('/api/organizations/update', { key, ...changes }).catch(throwGlobalError);
}

export function deleteOrganization(key: string) {
return post('/api/organizations/delete', { key }).catch(throwGlobalError);
}

export function searchMembers(data: {
organization?: string;
p?: number;
ps?: number;
q?: string;
selected?: string;
}): Promise<{ paging: T.Paging; users: T.OrganizationMember[] }> {
return getJSON('/api/organizations/search_members', data).catch(throwGlobalError);
}

export function addMember(data: {
login: string;
organization: string;
}): Promise<T.OrganizationMember> {
return postJSON('/api/organizations/add_member', data).then(r => r.user, throwGlobalError);
}

export function removeMember(data: { login: string; organization: string }) {
return post('/api/organizations/remove_member', data).catch(throwGlobalError);
}

export interface OrganizationBilling {
nclocCount: number;
subscription: {
plan?: {
maxNcloc: number;
price: number;
};
nextBillingDate?: string;
status: 'active' | 'inactive' | 'suspended';
trial: boolean;
};
}

export function getOrganizationBilling(organization: string): Promise<OrganizationBilling> {
return getJSON('/api/billing/show', { organization, p: 1, ps: 1 });
}

export function setOrganizationMemberSync(data: { enabled: boolean; organization: string }) {
return post('/api/organizations/set_members_sync', data).catch(throwGlobalError);
}

export function syncMembers(organization: string) {
return post('/api/organizations/sync_members', { organization }).catch(throwGlobalError);
}

+ 1
- 1
server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx View File

@@ -160,7 +160,7 @@ export default class BulkChangeModal extends React.PureComponent<Props, State> {
};

handleAssigneeSearch = (query: string) => {
return searchAssignees(query, this.state.organization).then(({ results }) =>
return searchAssignees(query).then(({ results }) =>
results.map(r => {
const userInfo = r.name || r.login;


+ 1
- 2
server/sonar-web/src/main/js/apps/issues/sidebar/AssigneeFacet.tsx View File

@@ -34,7 +34,6 @@ interface Props {
onChange: (changes: Partial<Query>) => void;
onToggle: (property: string) => void;
open: boolean;
organization: string | undefined;
query: Query;
stats: T.Dict<number> | undefined;
referencedUsers: T.Dict<T.UserBase>;
@@ -42,7 +41,7 @@ interface Props {

export default class AssigneeFacet extends React.PureComponent<Props> {
handleSearch = (query: string, page?: number) => {
return searchAssignees(query, this.props.organization, page);
return searchAssignees(query, page);
};

handleItemClick = (itemValue: string, multiple: boolean) => {

+ 0
- 1
server/sonar-web/src/main/js/apps/issues/sidebar/Sidebar.tsx View File

@@ -248,7 +248,6 @@ export class Sidebar extends React.PureComponent<Props> {
onChange={this.props.onFilterChange}
onToggle={this.props.onFacetToggle}
open={!!openFacets.assignees}
organization={organizationKey}
query={query}
referencedUsers={this.props.referencedUsers}
stats={facets.assignees}

+ 0
- 1
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/AssigneeFacet-test.tsx View File

@@ -92,7 +92,6 @@ function shallowRender(props?: Partial<AssigneeFacet['props']>) {
onChange={jest.fn()}
onToggle={jest.fn()}
open={true}
organization={undefined}
query={{} as Query}
referencedUsers={{ foo: { avatar: 'avatart-foo', login: 'name-foo', name: 'Name Foo' } }}
stats={{ '': 5, foo: 13, bar: 7, baz: 6 }}

+ 4
- 8
server/sonar-web/src/main/js/apps/issues/utils.ts View File

@@ -31,7 +31,6 @@ import {
} from 'sonar-ui-common/helpers/query';
import { scrollToElement } from 'sonar-ui-common/helpers/scrolling';
import { get, save } from 'sonar-ui-common/helpers/storage';
import { searchMembers } from '../../api/organizations';
import { searchUsers } from '../../api/users';
import { SecurityStandard, StandardType } from '../../types/security';

@@ -212,15 +211,12 @@ export interface ReferencedRule {

export const searchAssignees = (
query: string,
organization: string | undefined,
page = 1
): Promise<{ paging: T.Paging; results: T.UserBase[] }> => {
return organization
? searchMembers({ organization, p: page, ps: 50, q: query }).then(({ paging, users }) => ({
paging,
results: users
}))
: searchUsers({ p: page, q: query }).then(({ paging, users }) => ({ paging, results: users }));
return searchUsers({ p: page, q: query }).then(({ paging, users }) => ({
paging,
results: users
}));
};

const LOCALSTORAGE_MY = 'my';

+ 1
- 15
server/sonar-web/src/main/js/components/issue/popups/SetAssigneePopup.tsx View File

@@ -22,9 +22,7 @@ import * as React from 'react';
import { DropdownOverlay } from 'sonar-ui-common/components/controls/Dropdown';
import SearchBox from 'sonar-ui-common/components/controls/SearchBox';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { searchMembers } from '../../../api/organizations';
import { searchUsers } from '../../../api/users';
import { isSonarCloud } from '../../../helpers/system';
import { isLoggedIn, isUserActive } from '../../../helpers/users';
import SelectList from '../../common/SelectList';
import SelectListItem from '../../common/SelectListItem';
@@ -63,14 +61,6 @@ export class SetAssigneePopup extends React.PureComponent<Props, State> {
};
}

searchMembers = (query: string) => {
searchMembers({
organization: this.props.issue.projectOrganization,
q: query,
ps: LIST_SIZE
}).then(this.handleSearchResult, () => {});
};

searchUsers = (query: string) => {
searchUsers({ q: query, ps: LIST_SIZE }).then(this.handleSearchResult, () => {});
};
@@ -92,11 +82,7 @@ export class SetAssigneePopup extends React.PureComponent<Props, State> {
});
} else {
this.setState({ query });
if (isSonarCloud()) {
this.searchMembers(query);
} else {
this.searchUsers(query);
}
this.searchUsers(query);
}
};


+ 0
- 24
server/sonar-web/src/main/js/components/issue/popups/__tests__/SetAssigneePopup-test.tsx View File

@@ -20,25 +20,10 @@
import { shallow } from 'enzyme';
import * as React from 'react';
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import { searchMembers } from '../../../../api/organizations';
import { searchUsers } from '../../../../api/users';
import { isSonarCloud } from '../../../../helpers/system';
import { mockLoggedInUser, mockUser } from '../../../../helpers/testMocks';
import { SetAssigneePopup } from '../SetAssigneePopup';

jest.mock('../../../../helpers/system', () => ({
isSonarCloud: jest.fn().mockReturnValue(false)
}));

jest.mock('../../../../api/organizations', () => {
const { mockUser } = jest.requireActual('../../../../helpers/testMocks');
return {
searchMembers: jest.fn().mockResolvedValue({
users: [mockUser(), mockUser({ active: false, login: 'foo', name: undefined })]
})
};
});

jest.mock('../../../../api/users', () => {
const { mockUser } = jest.requireActual('../../../../helpers/testMocks');
return { searchUsers: jest.fn().mockResolvedValue({ users: [mockUser()] }) };
@@ -60,15 +45,6 @@ it('should allow to search for a user on SQ', async () => {
expect(wrapper.state('users')).toEqual([mockUser()]);
});

it('should allow to search for a user on SC', async () => {
(isSonarCloud as jest.Mock).mockReturnValueOnce(true);
const wrapper = shallowRender();
wrapper.find('SearchBox').prop<Function>('onChange')('o');
await waitAndUpdate(wrapper);
expect(searchMembers).toBeCalledWith({ organization: 'foo', q: 'o', ps: 10 });
expect(wrapper.state('users')).toEqual([mockUser()]);
});

function shallowRender(props: Partial<SetAssigneePopup['props']> = {}) {
return shallow(
<SetAssigneePopup

Loading…
Cancel
Save