diff --git a/packages/lib/slack/service.ts b/packages/lib/slack/service.ts
index 0a985cfbe7..aff1f5598e 100644
--- a/packages/lib/slack/service.ts
+++ b/packages/lib/slack/service.ts
@@ -7,32 +7,51 @@ import { TIntegrationSlack, TIntegrationSlackCredential } from "@formbricks/type
import { deleteIntegration, getIntegrationByType } from "../integration/service";
export const fetchChannels = async (slackIntegration: TIntegration): Promise => {
- const response = await fetch("https://slack.com/api/conversations.list", {
- method: "GET",
- headers: {
- Authorization: `Bearer ${slackIntegration.config.key.access_token}`,
- "Content-Type": "application/x-www-form-urlencoded",
- },
- });
+ let channels: TIntegrationItem[] = [];
+ // `nextCursor` is a pagination token returned by the Slack API. It indicates the presence of additional pages of data.
+ // When `nextCursor` is not empty, it should be included in subsequent requests to fetch the next page of data.
+ let nextCursor: string | undefined = undefined;
- if (!response.ok) {
- throw new Error("Network response was not ok");
- }
-
- const data = await response.json();
-
- if (!data.ok) {
- if (data.error === "token_expired") {
- // temporary fix to reset integration if token rotation is enabled
- await deleteIntegration(slackIntegration.id);
+ do {
+ const url = new URL("https://slack.com/api/conversations.list");
+ url.searchParams.append("limit", "200");
+ if (nextCursor) {
+ url.searchParams.append("cursor", nextCursor);
}
- throw new Error(data.error);
- }
- return data.channels.map((channel: { name: string; id: string }) => ({
- name: channel.name,
- id: channel.id,
- }));
+ const response = await fetch(url.toString(), {
+ method: "GET",
+ headers: {
+ Authorization: `Bearer ${slackIntegration.config.key.access_token}`,
+ "Content-Type": "application/x-www-form-urlencoded",
+ },
+ });
+
+ if (!response.ok) {
+ throw new Error("Network response was not ok");
+ }
+
+ const data = await response.json();
+
+ if (!data.ok) {
+ if (data.error === "token_expired") {
+ // Temporary fix to reset integration if token rotation is enabled
+ await deleteIntegration(slackIntegration.id);
+ }
+ throw new Error(data.error);
+ }
+
+ channels = channels.concat(
+ data.channels.map((channel: { name: string; id: string }) => ({
+ name: channel.name,
+ id: channel.id,
+ }))
+ );
+
+ nextCursor = data.response_metadata?.next_cursor;
+ } while (nextCursor);
+
+ return channels;
};
export const getSlackChannels = async (environmentId: string): Promise => {
diff --git a/packages/ui/DropdownSelector/index.tsx b/packages/ui/DropdownSelector/index.tsx
index 4a55a2a4c4..04fdcafefd 100644
--- a/packages/ui/DropdownSelector/index.tsx
+++ b/packages/ui/DropdownSelector/index.tsx
@@ -51,10 +51,11 @@ export const DropdownSelector = ({
{!disabled && (
- {items &&
- items.map((item) => (
+ {items
+ .sort((a, b) => a.name.localeCompare(b.name))
+ .map((item) => (