Skip to content
Open
4 changes: 2 additions & 2 deletions commands/TimeOffCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { statusCommand } from './subcommands/Status';

export class TimeOffCommand implements ISlashCommand {
public command = 'time-off';
public i18nParamsExample = '';
public i18nDescription = '';
public i18nParamsExample = 'Time_Off_Command_Params_Example';
public i18nDescription = 'Time_Off_Command_Description';
public providesPreview = false;

constructor(private readonly app: TimeOffApp) {}
Expand Down
11 changes: 6 additions & 5 deletions commands/subcommands/Help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ export async function helpCommand(app: TimeOffApp, context: SlashCommandContext,
const room = context.getRoom();

const message =
`*Time Off App Help*\n\n` +
`*Time-off Help*\n\n` +
`*Commands*\n` +
`• \`/time-off start\` - Start a new time off\n` +
`• \`/time-off end\` - End an existing time off\n` +
`• \`/time-off status\` - Check the current time off status\n` +
`• \`/time-off help\` - Display this help message\n`;
`• \`/time-off start\` starts new time off period\n` +
`• \`/time-off start [message]\` start a new time off period with a custom message\n` +
`• \`/time-off end\` ends current time off period\n` +
`• \`/time-off status\` shows current time off status\n` +
`• \`/time-off help\` shows this list\n`;

const notifier = new AppNotifier(app, read);
await notifier.notifyUser(room, sender, message);
Expand Down
11 changes: 5 additions & 6 deletions commands/subcommands/Start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,22 @@ export async function startCommand(
const room = context.getRoom();
const notifier = new AppNotifier(app, read);

let message = context.getArguments().join(' ').replace(CommandEnum.START, '');
if (!message) {
message = NOTIFICATION_MESSAGES.default_reply_message;
}
const customMessage = context.getArguments().join(' ').replace(CommandEnum.START, '').trim();

const timeOffEntry: ITimeOff = {
coreUserId: currentUser.id,
username: currentUser.username,
status: TimeOffStatus.ON_TIME_OFF,
message: message,
message: customMessage || undefined,
lastNotifiedAtBySenderId: {},
};

const timeOffRepository = new TimeOffRepository(app, read, persistence);
const timeOffService = new TimeOffService(timeOffRepository);
const savedTimeOff = await timeOffService.saveTimeOff(timeOffEntry);

const notificationMessage = !savedTimeOff ? NOTIFICATION_MESSAGES.error : NOTIFICATION_MESSAGES.started;
const notificationMessage = !savedTimeOff
? NOTIFICATION_MESSAGES.error
: NOTIFICATION_MESSAGES.started(customMessage || undefined);
await notifier.notifyUser(room, currentUser, notificationMessage);
}
4 changes: 3 additions & 1 deletion commands/subcommands/Status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ export async function statusCommand(
}

if (timeOffEntry.status === TimeOffStatus.ON_TIME_OFF) {
notificationMessage = `${NOTIFICATION_MESSAGES.status_in}${timeOffEntry.message}`;
notificationMessage = timeOffEntry.message
? `${NOTIFICATION_MESSAGES.status_in}${timeOffEntry.message}`
: NOTIFICATION_MESSAGES.status_in_no_message;
} else {
notificationMessage = `${NOTIFICATION_MESSAGES.status_out}`;
}
Expand Down
7 changes: 5 additions & 2 deletions handlers/PostMessageSentHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,13 @@ export class PostMessageSentHandler {
message: IMessage,
sender: IUser,
receiver: IUser,
timeOffMessage: string,
timeOffMessage?: string,
): Promise<void> {
const formattedMessage = TimeOffMessageFormatter.format(receiver.username, timeOffMessage);
await this.notifier.notifyUser(message.room, sender, timeOffMessage, formattedMessage);
const fallbackText = timeOffMessage
? `${receiver.username} is currently on time off. They left the following message: ${timeOffMessage}`
: `${receiver.username} is currently on time off.`;
await this.notifier.notifyUser(message.room, sender, fallbackText, formattedMessage);
}

private shouldSendNotification(timeOffEntry: ITimeOff | undefined, senderId: string): timeOffEntry is ITimeOff {
Expand Down
21 changes: 17 additions & 4 deletions helpers/NotificationMessage.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
export const NOTIFICATION_MESSAGES = {
started: `You are marked as Time Off, we will see you when you get back. Use \`/time-off end\` to end your time off.`,
default_reply_message: `I am out of office, I will get back to you soon.`,
started: (customMessage?: string): string => {
const intro = `*Time off on*\nI will automatically reply to any direct messages you receive to let the sender know you're on time off.`;
const reminder = `Remember to use the \`/time-off end\` command when you get back.`;

if (customMessage) {
const quoted = customMessage
.split('\n')
.map((line) => `> ${line}`)
.join('\n');
return `${intro}\n\nI will also include the following custom message:\n${quoted}\n\n${reminder}`;
}

return `${intro}\n\nYou have not set a custom reply message.\n\n${reminder}`;
},
ended: `Welcome back! You are no longer marked as Time Off.`,
not_started: `You are not marked as Time Off. Use \`/time-off start\` to start your time off.`,
not_started: `*Time-off off*\nI will not automatically reply to any direct messages you receive.`,
status_in: `You are currently marked as Time Off. Your message is: `,
status_out: `You are \`not\` marked as Time Off.`,
status_in_no_message: `You are currently marked as Time Off. You have not set a custom reply message.`,
status_out: `*Time-off off*\nI will not automatically reply to any direct messages you receive.`,
error: `An error occurred while updating your Time Off status. Please try again later.`,
};
37 changes: 24 additions & 13 deletions helpers/TimeOffMessageFormatter.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,36 @@
import { LayoutBlock } from '@rocket.chat/ui-kit';

export class TimeOffMessageFormatter {
public static format(username: string, message: string): LayoutBlock[] {
return [
public static format(username: string, message?: string): LayoutBlock[] {
const headerText = message
? `${username} is currently on time off. They left the following message:`
: `${username} is currently on time off.`;

const blocks: LayoutBlock[] = [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `${username} is currently *unavailable* to answer your message, however they left the following message:\n\n`,
text: headerText,
},
},
{
type: 'preview',
title: [],
description: [
{
type: 'mrkdwn',
text: message,
},
],
},
];

if (message) {
const quoted = message
.split('\n')
.map((line) => `> ${line}`)
.join('\n');

blocks.push({
type: 'section',
text: {
type: 'mrkdwn',
text: quoted,
},
});
}

return blocks;
}
}
4 changes: 4 additions & 0 deletions i18n/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"Time_Off_Command_Description": "Manage your time off — start, end, or check your status",
"Time_Off_Command_Params_Example": "start | end | status | help"
}
2 changes: 1 addition & 1 deletion interfaces/ITimeOff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { TimeOffStatus } from '../enums/Status';
export interface ITimeOff {
coreUserId: string;
username: string;
message: string;
message?: string;
status: TimeOffStatus;
lastNotifiedAtBySenderId?: Record<string, number>;
}
2 changes: 1 addition & 1 deletion notifiers/AppNotifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { LayoutBlock } from '@rocket.chat/ui-kit';
import { TimeOffApp } from '../TimeOffApp';

export class AppNotifier implements IAppNotifier {
private readonly TimeOffName: string = 'TimeOff Bot';
private readonly TimeOffName: string = 'Time-off';

constructor(private readonly app: TimeOffApp, private readonly read: IRead) {}

Expand Down
Loading