Skip to content

Commit

Permalink
Message email (#927)
Browse files Browse the repository at this point in the history
* wip. email notifications

* Notification and push notif customization in settings

* don't send if it is not enabled by user

* on signup add all notification types that exist to the list

* merge from main (#931)

* fixes #928

* Revert "npm update"

This reverts commit fe61f21.

* achievement unlock improvements

* handle long user input

* truncate in multiplayer

---------

Co-authored-by: Spencer Spenst <spencerspenst@gmail.com>

* updated package lock

* small cleanup

* test for notification preferences

* fix test in signup

* reset password test fix

* make sure new users have notifications on

* rename notification preferences test

* add test for guest account

* Update initializeLocalDb.ts

* follow button tweak; package-lock revert

* cleanup package-lock again

* move to sep file

* level of the day

* fix a longstanding bug where we sent email digests to guest users

* tweak css

* fix test

* level of day email

* labels

* move level of the day to notifications tab

* email body css

* set emailLog.type notification type

* update deafult emailNotificationsList

* fix tests

---------

Co-authored-by: Spencer Spenst <spencerspenst@gmail.com>
  • Loading branch information
k2xl and sspenst authored Jul 10, 2023
1 parent b633fe7 commit 5d74dae
Show file tree
Hide file tree
Showing 27 changed files with 755 additions and 228 deletions.
40 changes: 20 additions & 20 deletions components/followButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,26 @@ interface FollowButtonProps {
}

export default function FollowButton({ isFollowing, onResponse, user }: FollowButtonProps) {
const [_isFollowing, setIsFollowing] = useState<boolean>(isFollowing);
const [_isFollowing, setIsFollowing] = useState(isFollowing);
const [disabled, setDisabled] = useState(false);

const onFollowButtonPress = async (ele: React.MouseEvent<HTMLButtonElement>) => {
// disable button and make it opacity 0.5
const targ = ele.currentTarget;
const onFollowButtonPress = async () => {
setDisabled(true);

targ.disabled = true;
targ.style.opacity = '0.5';
const queryParams = new URLSearchParams({
action: GraphType.FOLLOW,
id: user._id.toString(),
targetModel: 'User',
});

const res = await fetch('/api/follow', {
const res = await fetch(`/api/follow?${queryParams}`, {
method: !_isFollowing ? 'PUT' : 'DELETE',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include',

body: JSON.stringify({
action: GraphType.FOLLOW,
id: user._id,
targetModel: 'User',
}),
});

targ.disabled = false;
targ.style.opacity = '1';

if (res.status === 200) {
const resp: FollowData = await res.json();

Expand All @@ -50,13 +44,19 @@ export default function FollowButton({ isFollowing, onResponse, user }: FollowBu
toast.dismiss();
toast.error('Something went wrong following this user');
}

setDisabled(false);
};

return (
<button className={classNames(
'font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline cursor-pointer',
_isFollowing ? 'bg-button' : 'bg-blue-500 hover:bg-blue-700 text-white',
)} onClick={onFollowButtonPress}>
<button
className={classNames(
'font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline disabled:opacity-50',
_isFollowing ? 'bg-button' : 'bg-blue-500 hover:bg-blue-700 text-white',
)}
disabled={disabled}
onClick={onFollowButtonPress}
>
{!_isFollowing ? 'Follow' : 'Unfollow'}
</button>
);
Expand Down
56 changes: 1 addition & 55 deletions components/settings/settingsAccount.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import User from '@root/models/db/user';
import UserConfig from '@root/models/db/userConfig';
import React, { useCallback, useState } from 'react';
import React, { useState } from 'react';
import toast from 'react-hot-toast';
import Select from 'react-select';
import { EmailDigestSettingTypes } from '../../constants/emailDigest';

interface SettingsAccountProps {
user: User;
Expand All @@ -13,8 +11,6 @@ interface SettingsAccountProps {
export default function SettingsAccount({ user, userConfig }: SettingsAccountProps) {
const [currentPassword, setCurrentPassword] = useState<string>('');
const [email, setEmail] = useState<string>(user.email);
const [emailDigest, setEmailDigest] = useState<EmailDigestSettingTypes>(userConfig?.emailDigest ?? EmailDigestSettingTypes.ONLY_NOTIFICATIONS);
const [isUserConfigLoading, setIsUserConfigLoading] = useState<boolean>(false);
const [password, setPassword] = useState<string>('');
const [password2, setPassword2] = useState<string>('');
const [showPlayStats, setShowPlayStats] = useState(userConfig?.showPlayStats ?? false);
Expand Down Expand Up @@ -84,7 +80,6 @@ export default function SettingsAccount({ user, userConfig }: SettingsAccountPro
) {
toast.dismiss();
toast.loading(`Updating ${property}...`);
setIsUserConfigLoading(true);

fetch('/api/user-config', {
method: 'PUT',
Expand All @@ -107,8 +102,6 @@ export default function SettingsAccount({ user, userConfig }: SettingsAccountPro
console.error(err);
toast.dismiss();
toast.error(`Error updating ${property}`);
}).finally(() => {
setIsUserConfigLoading(false);
});
}

Expand Down Expand Up @@ -186,14 +179,6 @@ export default function SettingsAccount({ user, userConfig }: SettingsAccountPro

const inputClass = 'shadow appearance-none border mb-2 rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline';

const emailDigestLabels = useCallback(() => {
return {
[EmailDigestSettingTypes.DAILY]: 'Daily digest',
[EmailDigestSettingTypes.ONLY_NOTIFICATIONS]: 'Only for unread notifications',
[EmailDigestSettingTypes.NONE]: 'None',
};
}, []);

async function clearTours() {
const res = await fetch('/api/user-config', {
method: 'PUT',
Expand Down Expand Up @@ -249,45 +234,6 @@ export default function SettingsAccount({ user, userConfig }: SettingsAccountPro
</label>
</div>
</div>
<div>
<div className='block font-bold mb-2'>
Email Notifications
</div>
<div>
<Select
className='text-black w-full text-sm'
components={{
IndicatorSeparator: null,
}}
isDisabled={isUserConfigLoading}
isLoading={isUserConfigLoading}
loadingMessage={() => 'Loading...'}
onChange={option => {
if (!option) {
return;
}

updateUserConfig(
JSON.stringify({
emailDigest: option.value,
}), 'email notifications',
);

setEmailDigest(option.value);
}}
options={Object.keys(EmailDigestSettingTypes).map(emailDigestKey => {
return {
label: emailDigestLabels()[emailDigestKey as EmailDigestSettingTypes],
value: emailDigestKey as EmailDigestSettingTypes,
};
})}
value={{
label: emailDigestLabels()[emailDigest],
value: emailDigest,
}}
/>
</div>
</div>
<form className='flex flex-col items-start' onSubmit={updateUsername}>
<label className='block font-bold mb-2' htmlFor='username'>
Username
Expand Down
Loading

0 comments on commit 5d74dae

Please sign in to comment.