diff --git a/changes/issue-3575-multiple-requests b/changes/issue-3575-multiple-requests new file mode 100644 index 0000000000..296ab6ecd9 --- /dev/null +++ b/changes/issue-3575-multiple-requests @@ -0,0 +1 @@ +* Correct instances of multiple requests for same resource \ No newline at end of file diff --git a/cypress/integration/premium/team_maintainer_observer.spec.ts b/cypress/integration/premium/team_maintainer_observer.spec.ts index 780934b141..bfa68d053d 100644 --- a/cypress/integration/premium/team_maintainer_observer.spec.ts +++ b/cypress/integration/premium/team_maintainer_observer.spec.ts @@ -228,10 +228,7 @@ describe( .contains("button", /schedule/i) .click(); - cy.visit("/schedule/manage"); - - cy.wait(2000); // eslint-disable-line cypress/no-unnecessary-waiting - cy.findByText(/detect presence/i).should("exist"); + cy.get(".flash-message--success").should("exist"); cy.visit("/hosts/manage"); cy.contains(".table-container .data-table__table th", "Team").should( diff --git a/frontend/components/TeamsDropdown/TeamsDropdown.tsx b/frontend/components/TeamsDropdown/TeamsDropdown.tsx index f46e3973c9..a6c92da192 100644 --- a/frontend/components/TeamsDropdown/TeamsDropdown.tsx +++ b/frontend/components/TeamsDropdown/TeamsDropdown.tsx @@ -34,7 +34,8 @@ const generateDropdownOptions = ( interface ITeamsDropdownProps { currentUserTeams: ITeam[]; selectedTeamId: number; - includeAll?: boolean; + includeAll?: boolean; // Include "All Teams" option for all users + disableAll?: boolean; // Disable "All Teams" option for global users isDisabled?: boolean; onChange: (newSelectedValue: number) => void; onOpen?: () => void; @@ -46,7 +47,8 @@ const baseClass = "component__team-dropdown"; const TeamsDropdown = ({ currentUserTeams, selectedTeamId, - includeAll, + includeAll = false, + disableAll = false, isDisabled, onChange, onOpen, @@ -56,7 +58,10 @@ const TeamsDropdown = ({ const teamOptions = useMemo( () => - generateDropdownOptions(currentUserTeams, isOnGlobalTeam || includeAll), + generateDropdownOptions( + currentUserTeams, + (isOnGlobalTeam && !disableAll) || includeAll + ), [currentUserTeams, isOnGlobalTeam] ); diff --git a/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/MembersPage/MembersPage.tsx b/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/MembersPage/MembersPage.tsx index 508fc4bce5..9159d3f918 100644 --- a/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/MembersPage/MembersPage.tsx +++ b/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/MembersPage/MembersPage.tsx @@ -233,14 +233,13 @@ const MembersPage = ({ setIsFormSubmitting(true); if (formData.newUserType === NewUserType.AdminInvited) { - // Do some data formatting adding `invited_by` for the request to be correct and deleteing uncessary fields const requestData = { ...formData, invited_by: formData.currentUserId, }; - delete requestData.currentUserId; // this field is not needed for the request - delete requestData.newUserType; // this field is not needed for the request - delete requestData.password; // this field is not needed for the request + delete requestData.currentUserId; + delete requestData.newUserType; + delete requestData.password; dispatch(inviteActions.create(requestData)) .then(() => { dispatch( @@ -270,12 +269,11 @@ const MembersPage = ({ setIsFormSubmitting(false); }); } else { - // Do some data formatting deleteing uncessary fields const requestData = { ...formData, }; - delete requestData.currentUserId; // this field is not needed for the request - delete requestData.newUserType; // this field is not needed for the request + delete requestData.currentUserId; + delete requestData.newUserType; dispatch(userActions.createUserWithoutInvitation(requestData)) .then(() => { dispatch( @@ -325,8 +323,6 @@ const MembersPage = ({ .then(() => { dispatch(renderFlash("success", `Successfully edited ${userName}.`)); if (currentUser && userEditing && currentUser.id === userEditing.id) { - // If user edits self and removes "admin" role, - // redirect to home const currentTeam = formData.teams.filter( (thisTeam) => thisTeam.id === teamId ); @@ -354,17 +350,17 @@ const MembersPage = ({ ); useEffect(() => { + // Fetch users when Redux team_id state changes fetchUsers(tableQueryData); }, [team_id]); - // NOTE: this will fire on initial render, so we use this to get the list of - // users for this team, as well as use it as a handler when the table query - // changes. const onQueryChange = useCallback( (queryData) => { - setSearchString(queryData.searchQuery); - tableQueryData = { ...queryData, teamId }; - fetchUsers(queryData); + if (users) { + setSearchString(queryData.searchQuery); + tableQueryData = { ...queryData, teamId }; + fetchUsers(queryData); + } }, [fetchUsers, teamId, setSearchString] ); diff --git a/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/TeamDetailsWrapper.tsx b/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/TeamDetailsWrapper.tsx index dd6d804d01..65d271c81c 100644 --- a/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/TeamDetailsWrapper.tsx +++ b/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/TeamDetailsWrapper.tsx @@ -254,6 +254,7 @@ const TeamDetailsWrapper = ({ selectedTeamId={toNumber(routeParams.team_id)} currentUserTeams={adminTeams || []} isDisabled={isLoadingTeams} + disableAll onChange={(newSelectedValue: number) => handleTeamSelect(newSelectedValue) } diff --git a/frontend/pages/admin/TeamManagementPage/TeamManagementPage.tsx b/frontend/pages/admin/TeamManagementPage/TeamManagementPage.tsx index 6bcb5027a1..c7a29c72ff 100644 --- a/frontend/pages/admin/TeamManagementPage/TeamManagementPage.tsx +++ b/frontend/pages/admin/TeamManagementPage/TeamManagementPage.tsx @@ -70,16 +70,17 @@ const TeamManagementPage = (): JSX.Element => { [showEditTeamModal, setShowEditTeamModal, setTeamEditing] ); - // NOTE: called once on the initial render of this component. const onQueryChange = useCallback( (queryData) => { - setSearchString(queryData.searchQuery); - const { pageIndex, pageSize, searchQuery } = queryData; - teamsAPI.loadAll({ - page: pageIndex, - perPage: pageSize, - globalFilter: searchQuery, - }); + if (teams) { + setSearchString(queryData.searchQuery); + const { pageIndex, pageSize, searchQuery } = queryData; + teamsAPI.loadAll({ + page: pageIndex, + perPage: pageSize, + globalFilter: searchQuery, + }); + } }, [dispatch, setSearchString] ); diff --git a/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.tsx b/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.tsx index ad5c53c803..89a383e20f 100644 --- a/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.tsx +++ b/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.tsx @@ -231,6 +231,10 @@ const ManageHostsPage = ({ ); const [tableQueryData, setTableQueryData] = useState(); const [clearSelectionCount, setClearSelectionCount] = useState(0); + const [ + currentQueryOptions, + setCurrentQueryOptions, + ] = useState(); // ======== end states @@ -477,15 +481,17 @@ const ManageHostsPage = ({ policyId, policyResponse, softwareId, + page: tableQueryData ? tableQueryData.pageIndex : 0, + perPage: tableQueryData ? tableQueryData.pageSize : 100, }; - if (tableQueryData) { - options.page = tableQueryData.pageIndex; - options.perPage = tableQueryData.pageSize; + if (isEqual(options, currentQueryOptions)) { + return; } retrieveHosts(options); retrieveHostCount(options); + setCurrentQueryOptions(options); }, [location, labels]); const handleLabelChange = ({ slug }: ILabel): boolean => { @@ -657,11 +663,9 @@ const ManageHostsPage = ({ // NOTE: this is called once on initial render and every time the query changes const onTableQueryChange = async (newTableQuery: ITableQueryProps) => { if (isEqual(newTableQuery, tableQueryData)) { - return false; + return; } - setIsHostsLoading(true); - setTableQueryData({ ...newTableQuery }); const { diff --git a/frontend/pages/schedule/ManageSchedulePage/ManageSchedulePage.tsx b/frontend/pages/schedule/ManageSchedulePage/ManageSchedulePage.tsx index 3adf4ba6c2..ce5e02c050 100644 --- a/frontend/pages/schedule/ManageSchedulePage/ManageSchedulePage.tsx +++ b/frontend/pages/schedule/ManageSchedulePage/ManageSchedulePage.tsx @@ -195,15 +195,6 @@ const ManageSchedulePage = ({ handleTeamSelect(teams[0].id); } - // TODO: move team scheduled queries and global scheduled queries into services entities, remove redux - useEffect(() => { - dispatch( - selectedTeamId - ? teamScheduledQueryActions.loadAll(selectedTeamId) - : globalScheduledQueryActions.loadAll() - ); - }, [dispatch, selectedTeamId]); - const allScheduledQueries = useSelector((state: IRootState) => { if (selectedTeamId) { return state.entities.team_scheduled_queries;