Skip to content
Open
30 changes: 27 additions & 3 deletions apps/backend/src/api/routes/settings.controller.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import { Body, Controller, Delete, Get, Param, Post } from '@nestjs/common';
import { GetOrgFromRequest } from '@gitroom/nestjs-libraries/user/org.from.request';
import { Organization } from '@prisma/client';
import { Organization, User } from '@prisma/client';
import { StarsService } from '@gitroom/nestjs-libraries/database/prisma/stars/stars.service';
import { CheckPolicies } from '@gitroom/backend/services/auth/permissions/permissions.ability';
import { OrganizationService } from '@gitroom/nestjs-libraries/database/prisma/organizations/organization.service';
import { AddTeamMemberDto } from '@gitroom/nestjs-libraries/dtos/settings/add.team.member.dto';
import { ApiTags } from '@nestjs/swagger';
import { AuthorizationActions, Sections } from '@gitroom/backend/services/auth/permissions/permission.exception.class';
import {
AuthorizationActions,
Sections,
} from '@gitroom/backend/services/auth/permissions/permission.exception.class';
import { UsersService } from '@gitroom/nestjs-libraries/database/prisma/users/users.service';
import { GetUserFromRequest } from '@gitroom/nestjs-libraries/user/user.from.request';

@ApiTags('Settings')
@Controller('/settings')
export class SettingsController {
constructor(
private _starsService: StarsService,
private _organizationService: OrganizationService
private _organizationService: OrganizationService,
private _usersService: UsersService
) {}

@Get('/github')
Expand Down Expand Up @@ -133,4 +139,22 @@ export class SettingsController {
) {
return this._organizationService.deleteTeamMember(org, id);
}

@Get('/email-notifications')
async getEmailNotifications(@GetUserFromRequest() user: User) {
const userValue = await this._usersService.getEmailNotifications(user.id);
return { enabled: userValue.emailNotifications };
}

@Post('/email-notifications')
@CheckPolicies(
[AuthorizationActions.Create, Sections.TEAM_MEMBERS],
[AuthorizationActions.Create, Sections.ADMIN]
)
async updateEmailNotifications(
@GetUserFromRequest() user: User,
@Body('enabled') enabled: boolean
) {
return this._usersService.updateEmailNotifications(user.id, enabled);
}
}
8 changes: 8 additions & 0 deletions apps/frontend/src/components/layout/settings.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { SignaturesComponent } from '@gitroom/frontend/components/settings/signa
import { Autopost } from '@gitroom/frontend/components/autopost/autopost';
import { useT } from '@gitroom/react/translation/get.transation.service.client';
import { SVGLine } from '@gitroom/frontend/components/launches/launches.component';
import { EmailNotificationsComponent } from '../settings/email.notifications.component';
export const SettingsPopup: FC<{
getRef?: Ref<any>;
}> = (props) => {
Expand Down Expand Up @@ -115,6 +116,7 @@ export const SettingsPopup: FC<{
if (user?.tier?.public_api && isGeneral && showLogout) {
arr.push({ tab: 'api', label: t('public_api', 'Public API') });
}
arr.push({ tab: 'email', label: t('email_notifications', 'Email Notifications') });

return arr;
}, [user, isGeneral, showLogout, t]);
Expand Down Expand Up @@ -206,6 +208,12 @@ export const SettingsPopup: FC<{
<PublicComponent />
</div>
)}

{tab === 'email' && (
<div>
<EmailNotificationsComponent />
</div>
)}
</div>
</form>
</FormProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { FC, useCallback } from 'react';
import { useFetch } from '@gitroom/helpers/utils/custom.fetch';
import useSWR from 'swr';
import { Button } from '@gitroom/react/form/button';
import { useToaster } from '@gitroom/react/toaster/toaster';
import { useT } from '@gitroom/react/translation/get.transation.service.client';

export const EmailNotificationsComponent: FC = () => {
const fetch = useFetch();
const toast = useToaster();
const t = useT();

const load = useCallback(async () => {
return (await fetch('/settings/email-notifications')).json();
}, []);

const { data, mutate } = useSWR('email-notifications', load);

const toggle = useCallback(async () => {
try {
const res = await fetch('/settings/email-notifications', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
enabled: !data?.enabled,
}),
});

if (!res.ok) throw new Error('Failed to update');

toast.show(
t(
'email_notifications_updated',
'Email notifications updated successfully'
),
'success'
);
mutate();
} catch (err) {
toast.show(
t('email_notifications_failed', 'Failed to update email notifications'),
'warning'
);
}
}, [data, mutate]);

return (
<div className="flex flex-col">
<h3 className="text-[20px]">
{t('email_notifications', 'Email Notifications')}
</h3>
<div className="text-customColor18 mt-[4px]">
{t(
'control_email_settings',
'Enable or disable whether you want to receive email notifications.'
)}
</div>
<div className="my-[16px] bg-sixth border-fifth border rounded-[4px] p-[24px] flex items-center justify-between">
<div className="flex flex-col">
<div className="text-[16px] font-medium">
{t('receive_emails', 'Receive emails?')}
</div>
<div className="text-customColor18 text-sm">
{t(
'receive_emails_description',
'You’ll be notified by email when necessary updates occur.'
)}
</div>
</div>
<Button onClick={toggle}>
{data?.enabled ? t('disable', 'Disable') : t('enable', 'Enable')}
</Button>
</div>
</div>
);
};
Loading
Loading