Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/actions/base-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,9 @@ export const snackbarSuccessHandler = (message) => (dispatch, state) =>
dispatch,
state
);

export const snackbarErrorMsg = (message) => (dispatch, state) =>
setSnackbarMessage({ ...message, type: "error", code: CODE_200 })(
dispatch,
state
);
85 changes: 74 additions & 11 deletions src/actions/sponsor-users-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,23 @@ import {
DEFAULT_ORDER_DIR,
DEFAULT_PER_PAGE,
DUMMY_ACTION,
IMPORT_SPONSOR_USERS_STATUS,
SPONSOR_USER_ASSIGNMENT_TYPE
} from "../utils/constants";
import { snackbarErrorHandler, snackbarSuccessHandler } from "./base-actions";
import {
snackbarErrorHandler,
snackbarErrorMsg,
snackbarSuccessHandler
} from "./base-actions";

export const RECEIVE_SPONSOR_USER_GROUPS = "RECEIVE_SPONSOR_USER_GROUPS";
export const REQUEST_SPONSOR_USER_REQUESTS = "REQUEST_SPONSOR_USER_REQUESTS";
export const RECEIVE_SPONSOR_USER_REQUESTS = "RECEIVE_SPONSOR_USER_REQUESTS";
export const REQUEST_SPONSOR_USERS = "REQUEST_SPONSOR_USERS";
export const RECEIVE_SPONSOR_USERS = "RECEIVE_SPONSOR_USERS";
export const IMPORT_SPONSOR_USERS_TRIGGERED = "IMPORT_SPONSOR_USERS_TRIGGERED";
export const RECEIVE_SPONSOR_USERS_IMPORT_STATUS =
"RECEIVE_SPONSOR_USERS_IMPORT_STATUS";
export const SPONSOR_USER_ADDED = "SPONSOR_USER_ADDED";
export const SPONSOR_USER_REQUEST_ACCEPTED = "SPONSOR_USER_REQUEST_ACCEPTED";
export const SPONSOR_USER_REQUEST_DELETED = "SPONSOR_USER_REQUEST_DELETED";
Expand Down Expand Up @@ -537,19 +545,74 @@ export const sendSponsorUserInvite = (email) => async (dispatch, getState) => {
});
};

export const fetchSponsorUsersBySummit = async (summitId, companyId, page) => {
export const fetchSponsorUsersBySummit = async (
currentSummitId,
summitId,
companyId,
page
) => {
const accessToken = await getAccessTokenSafely();

return fetch(
`${window.SPONSOR_USERS_API_URL}/api/v1/sponsor-users?filter[]=summit_id==${summitId}&filter[]=company_id==${companyId}&access_token=${accessToken}&page=${page}&per_page=10&order=first_name&order_dir=asc`
`${window.SPONSOR_USERS_API_URL}/api/v1/sponsor-users?filter[]=not_summit_id==${currentSummitId}&filter[]=summit_id==${summitId}&filter[]=company_id==${companyId}&access_token=${accessToken}&page=${page}&per_page=10&order=first_name&order_dir=asc`
)
.then(fetchResponseHandler)
.then((json) => json)
.catch(fetchErrorHandler);
};

export const trackImportSponsorUsers = () => async (dispatch, getState) => {
const { sponsorUsersListState, currentSponsorState } = getState();
const { importTasks } = sponsorUsersListState;
const { entity: sponsor } = currentSponsorState;

const accessToken = await getAccessTokenSafely();
const params = {
access_token: accessToken
};

importTasks.forEach((taskId) => {
getRequest(
null,
createAction(RECEIVE_SPONSOR_USERS_IMPORT_STATUS),
`${window.SPONSOR_USERS_API_URL}/api/v1/tasks/${taskId}`,
authErrorHandler
)(params)(dispatch).then(({ response }) => {
if (response.status === IMPORT_SPONSOR_USERS_STATUS.SUCCESS) {
dispatch(
snackbarSuccessHandler({
title: T.translate("general.success"),
html: T.translate("sponsor_users.import_users.success")
})
);

if (response.result.errors.length > 0) {
dispatch(
snackbarErrorMsg({
title: T.translate("sponsor_users.import_users.fail"),
html: response.result.errors.map((e) => e.error).join("<br/>")
})
);
}
Comment on lines +587 to +596

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Guard against missing result or errors property.

If the API returns a successful status but response.result is undefined or result.errors is missing, accessing response.result.errors.length will throw a TypeError.

🛡️ Proposed defensive fix
-        if (response.result.errors.length > 0) {
+        if (response.result?.errors?.length > 0) {
           dispatch(
             snackbarErrorMsg({
               title: T.translate("sponsor_users.import_users.fail"),
               html: response.result.errors.map((e) => e.error).join("<br/>")
             })
           );
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
);
if (response.result.errors.length > 0) {
dispatch(
snackbarErrorMsg({
title: T.translate("sponsor_users.import_users.fail"),
html: response.result.errors.map((e) => e.error).join("<br/>")
})
);
}
);
if (response.result?.errors?.length > 0) {
dispatch(
snackbarErrorMsg({
title: T.translate("sponsor_users.import_users.fail"),
html: response.result.errors.map((e) => e.error).join("<br/>")
})
);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/actions/sponsor-users-actions.js` around lines 586 - 595, Guard the
access to response.result.errors before reading length to avoid TypeError; in
the block where you check response.result.errors (the code around
response.result.errors.length > 0 that dispatches snackbarErrorMsg), use a safe
check like verifying response.result exists and that response.result.errors is
an array (e.g., Array.isArray(response.result.errors) &&
response.result.errors.length > 0) and only build the html payload by joining
when it is an array. Update the condition and the html construction used in the
dispatch(snackbarErrorMsg(...)) invocation so it safely handles missing
result/errors (fall back to a generic message or empty string).


dispatch(getSponsorUsers(sponsor.id));
} else if (response.status === IMPORT_SPONSOR_USERS_STATUS.FAILURE) {
dispatch(
snackbarErrorMsg({
title: T.translate("sponsor_users.import_users.fail"),
html: response.error
})
);
}
});
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.
};

export const importSponsorUsers =
(sponsorId, companyId, summitId, userIds) => async (dispatch) => {
(targetSponsorId, targetCompanyId, sourceSummitId, userIds) =>
async (dispatch, getState) => {
const { currentSummitState } = getState();
const { currentSummit } = currentSummitState;
const accessToken = await getAccessTokenSafely();
let payload;

Expand All @@ -562,30 +625,30 @@ export const importSponsorUsers =
if (userIds === "all") {
payload = {
apply_to_all_users: true,
source_company_id: companyId,
source_summit_id: summitId
source_company_id: targetCompanyId, // target and source companyId is the same
source_summit_id: sourceSummitId,
target_summit_id: currentSummit.id
};
} else {
payload = {
summit_id: summitId,
sponsor_id: sponsorId,
target_summit_id: currentSummit.id,
sponsor_id: targetSponsorId,
user_ids: userIds
};
}

return postRequest(
null,
createAction(DUMMY_ACTION),
createAction(IMPORT_SPONSOR_USERS_TRIGGERED),
`${window.SPONSOR_USERS_API_URL}/api/v1/sponsor-users/import`,
payload,
snackbarErrorHandler
)(params)(dispatch)
.then(() => {
dispatch(stopLoading());
dispatch(
snackbarSuccessHandler({
title: T.translate("general.success"),
html: T.translate("sponsor_users.import_users.success")
html: T.translate("sponsor_users.import_users.running")
})
);
})
Expand Down
4 changes: 3 additions & 1 deletion src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2876,7 +2876,9 @@
"select_users": "Select Users",
"select_all_users": "Select All Users",
"import_users": "Import Users",
"success": "Users imported successfully."
"running": "Users import running on background.",
"success": "Users imported successfully.",
"fail": "Import failed"
}
},
"sponsorship_list": {
Expand Down
Loading
Loading