Skip to content

Commit

Permalink
feat: implement bulk creating sessions (#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
dgurkaynak committed Aug 30, 2022
1 parent 7d4887e commit b38304d
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 63 deletions.
147 changes: 89 additions & 58 deletions src/routes/interactivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ export class InteractivityRoute {

switch (callbackId) {
case 'newSessionModal:submit': {
return InteractivityRoute.createSession({ payload, team, res });
return InteractivityRoute.submitNewSessionModal({ payload, team, res });
}

default: {
Expand All @@ -565,7 +565,7 @@ export class InteractivityRoute {
/**
* A user submits the `new session` modal.
*/
static async createSession({
static async submitNewSessionModal({
payload, // action request payload
team,
res,
Expand Down Expand Up @@ -615,13 +615,28 @@ export class InteractivityRoute {
});
throw new Error(SessionControllerErrorCode.TITLE_REQUIRED);
}
const title = (titleInputState as any)[Object.keys(titleInputState)[0]]

const rawTitle = (titleInputState as any)[Object.keys(titleInputState)[0]]
.value;
if (typeof rawTitle !== 'string') {
throw new Error(SessionControllerErrorCode.TITLE_REQUIRED);
}

const titles: string[] = [];
rawTitle.split(/\r?\n/).forEach((rawLine) => {
const trimmed = rawLine.trim();
if (trimmed.length === 0) return;
titles.push(trimmed);
});

if (!title || title.trim().length == 0) {
if (titles.length === 0) {
throw new Error(SessionControllerErrorCode.TITLE_REQUIRED);
}

if (titles.length > 10) {
throw new Error(SessionControllerErrorCode.MAX_TITLE_LIMIT_EXCEEDED);
}

//////////////////////////
// Get the participants //
//////////////////////////
Expand Down Expand Up @@ -729,60 +744,78 @@ export class InteractivityRoute {
(option) => option.value == 'average'
);

// Create session struct
const session: ISession = {
id: generateId(),
votingDuration: votingDurationMs,
endsAt: Date.now() + votingDurationMs,
title,
points,
votes: {},
state: 'active',
teamId: team.id,
channelId,
userId: payload.user.id,
participants,
rawPostMessageResponse: undefined,
protected: isProtected,
average: calculateAverage,
};
// Async tasks for slack `postMessage`
const tasks = titles.map(async (title) => {
// Create session struct
const session: ISession = {
id: generateId(),
votingDuration: votingDurationMs,
endsAt: Date.now() + votingDurationMs,
title,
points,
votes: {},
state: 'active',
teamId: team.id,
channelId,
userId: payload.user.id,
participants,
rawPostMessageResponse: undefined,
protected: isProtected,
average: calculateAverage,
};

logger.info({
msg: `Creating a new session`,
team: {
id: team.id,
name: team.name,
},
user: {
id: payload.user.id,
name: payload.user.name,
},
channelId,
sessionId: session.id,
});
logger.info({
msg: `Creating a new session`,
team: {
id: team.id,
name: team.name,
},
user: {
id: payload.user.id,
name: payload.user.name,
},
channelId,
sessionId: session.id,
bulkCount: titles.length,
});

const postMessageResponse = await SessionController.postMessage(
session,
team
);
session.rawPostMessageResponse = postMessageResponse as any;
const postMessageResponse = await SessionController.postMessage(
session,
team
);
session.rawPostMessageResponse = postMessageResponse as any;

SessionStore.upsert(session);

if (process.env.COUNTLY_APP_KEY) {
Countly.add_event({
key: 'topic_created',
count: 1,
segmentation: {
participants: session.participants.length,
votingDuration: votingDurationMs,
bulkCount: titles.length,
},
});
}
});

SessionStore.upsert(session);
await Promise.all(tasks);

res.send();

const [upsertSettingErr] = await to(
TeamStore.upsertSettings(team.id, session.channelId, {
[ChannelSettingKey.PARTICIPANTS]: session.participants.join(' '),
[ChannelSettingKey.POINTS]: session.points
TeamStore.upsertSettings(team.id, channelId, {
[ChannelSettingKey.PARTICIPANTS]: participants.join(' '),
[ChannelSettingKey.POINTS]: points
.map((point) => {
if (!point.includes(' ')) return point;
if (point.includes(`"`)) return `'${point}'`;
return `"${point}"`;
})
.join(' '),
[ChannelSettingKey.PROTECTED]: JSON.stringify(session.protected),
[ChannelSettingKey.AVERAGE]: JSON.stringify(session.average),
[ChannelSettingKey.PROTECTED]: JSON.stringify(isProtected),
[ChannelSettingKey.AVERAGE]: JSON.stringify(calculateAverage),
[ChannelSettingKey.VOTING_DURATION]: prettyMilliseconds(
votingDurationMs
),
Expand All @@ -791,21 +824,11 @@ export class InteractivityRoute {
if (upsertSettingErr) {
logger.error({
msg: `Could not upsert settings after creating new session`,
session,
teamId: team.id,
channelId,
err: upsertSettingErr,
});
}

if (process.env.COUNTLY_APP_KEY) {
Countly.add_event({
key: 'topic_created',
count: 1,
segmentation: {
participants: session.participants.length,
votingDuration: votingDurationMs,
},
});
}
} catch (err) {
let shouldLog = true;
let logLevel: 'info' | 'warn' | 'error' = 'error';
Expand Down Expand Up @@ -874,7 +897,15 @@ export class InteractivityRoute {
};
} else if (err.message == SessionControllerErrorCode.TITLE_REQUIRED) {
shouldLog = false;
errorMessage = `Title is required`;
errorMessage = `At least one title is required`;
modalErrors = {
title: errorMessage,
};
} else if (
err.message == SessionControllerErrorCode.MAX_TITLE_LIMIT_EXCEEDED
) {
shouldLog = false;
errorMessage = `You can bulk-create up to 10 sessions`;
modalErrors = {
title: errorMessage,
};
Expand Down
18 changes: 13 additions & 5 deletions src/session/session-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const DEFAULT_POINTS = [
export enum SessionControllerErrorCode {
NO_PARTICIPANTS = 'no_participants',
TITLE_REQUIRED = 'title_required',
MAX_TITLE_LIMIT_EXCEEDED = 'max_title_limit_exceeded',
UNEXPECTED_PAYLOAD = 'unexpected_payload',
INVALID_POINTS = 'invalid_points',
SESSION_NOT_ACTIVE = 'session_not_active',
Expand Down Expand Up @@ -147,6 +148,7 @@ export class SessionController {
block_id: 'title',
element: {
type: 'plain_text_input',
multiline: true,
placeholder: {
type: 'plain_text',
text: 'Write a topic for this voting session',
Expand All @@ -159,6 +161,12 @@ export class SessionController {
text: 'Title',
emoji: true,
},
hint: {
type: 'plain_text',
text:
'You can bulk-create voting sessions, every line will correspond to a new separate session (up to 10)',
emoji: true,
},
},
{
type: 'input',
Expand Down Expand Up @@ -197,14 +205,14 @@ export class SessionController {
})
.join(' '),
},
hint: {
label: {
type: 'plain_text',
text: 'Enter points separated by space',
text: 'Points',
emoji: true,
},
label: {
hint: {
type: 'plain_text',
text: 'Points',
text: 'Enter points separated by space',
emoji: true,
},
},
Expand Down Expand Up @@ -573,7 +581,7 @@ function buildMessageAttachmentsForEnding(session: ISession) {
name: 'action',
text: 'Delete message',
type: 'button',
value: JSON.stringify({b: 1}), // button type, 0 => restart, 1 => delete
value: JSON.stringify({ b: 1 }), // button type, 0 => restart, 1 => delete
style: 'danger',
},
],
Expand Down

0 comments on commit b38304d

Please sign in to comment.