Upload User and Guild Icons

This commit is contained in:
ADAMJR 2021-11-04 01:07:54 +00:00
parent ab2ca97192
commit 9c86483235
7 changed files with 70 additions and 49 deletions

View File

@ -1,6 +1,7 @@
import { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { useDispatch, useSelector } from 'react-redux';
import { deleteGuild, updateGuild } from '../../../store/guilds';
import { deleteGuild, updateGuild, uploadGuildIcon } from '../../../store/guilds';
import { openSaveChanges } from '../../../store/ui';
import NormalButton from '../../utils/buttons/normal-button';
import Category from '../../utils/category';
@ -37,11 +38,17 @@ const GuildSettingsOverview: React.FunctionComponent = () => {
options={{ value: guild.name }}
className="pt-5" />
<Input
label="Icon URL"
type="file"
accept="image/*"
label="Icon Image"
name="iconURL"
register={register}
className="pt-5"
register={(): any => {}}
options={{ value: guild.iconURL }}
className="pt-5" />
onChange={(e) => {
const file = e.currentTarget?.files?.[0];
if (file) dispatch(uploadGuildIcon(guild.id, file));
}} />
</section>
<Category

View File

@ -3,7 +3,7 @@ import { useForm } from 'react-hook-form';
import { useDispatch, useSelector } from 'react-redux';
import { toggleDevMode } from '../../../store/config';
import { openSaveChanges } from '../../../store/ui';
import { updateSelf, deleteSelf } from '../../../store/users';
import { updateSelf, deleteSelf, uploadUserAvatar } from '../../../store/users';
import NormalButton from '../../utils/buttons/normal-button';
import Category from '../../utils/category';
import Input from '../../utils/input/input';
@ -33,31 +33,30 @@ const UserSettingsOverview: React.FunctionComponent = () => {
</header>
<section className="w-1/2">
<div className="pt-5">
<Input
label="Username"
name="username"
register={register}
options={{ value: user.username }} />
</div>
<div className="pt-5">
<Input
label="Email"
name="email"
register={register}
options={{ value: user.email }} />
</div>
<div className="pt-5">
<Input
type="file"
accept="image/*"
label="Avatar Image"
name="avatarURL"
register={register}
options={{ value: user.avatarURL }} />
</div>
<Input
label="Username"
name="username"
register={register}
options={{ value: user.username }}
className="pt-5" />
<Input
label="Email"
name="email"
register={register}
options={{ value: user.email }}
className="pt-5" />
<Input
type="file"
accept="image/*"
label="Avatar Image"
className="pt-5"
name="avatarURL"
register={(): any => {}}
options={{ value: user.avatarURL }}
onChange={(e) => {
const file = e.currentTarget?.files?.[0];
if (file) dispatch(uploadUserAvatar(file));
}} />
</section>
<SaveChanges

View File

@ -22,4 +22,17 @@ export interface APIArgs {
export interface WSArgs {
data?: object;
event: keyof WS.To;
}
export const uploadFile = (file: File, callback?: (args: REST.From.Post['/upload']) => any) => (dispatch) => {
const formData = new FormData();
formData.append('file', file);
dispatch(actions.restCallBegan({
method: 'post',
url: '/upload',
data: formData,
headers: { 'Content-Type': 'multipart/form-data' },
callback,
}));
}

View File

@ -1,6 +1,6 @@
import { createSelector, createSlice } from '@reduxjs/toolkit';
import { WS } from '../types/ws';
import { actions as api } from './api';
import { actions as api, uploadFile } from './api';
import { unique } from './utils/filter';
const slice = createSlice({
@ -41,6 +41,12 @@ export const updateGuild = (guildId: string, payload: Partial<Entity.Guild>) =>
}));
}
export const uploadGuildIcon = (guildId: string, file: File) => (dispatch) => {
const uploadCallback = async ({ url }: REST.From.Post['/upload']) =>
dispatch(updateGuild(guildId, { iconURL: url }));
dispatch(uploadFile(file, uploadCallback));
}
export const deleteGuild = (guildId: string) => (dispatch) => {
dispatch(api.wsCallBegan({
event: 'GUILD_DELETE',

View File

@ -1,6 +1,6 @@
import { createSlice, createSelector } from '@reduxjs/toolkit';
import { WS } from '../types/ws';
import { actions as api } from './api';
import { actions as api, uploadFile } from './api';
import { unique } from './utils/filter';
import { headers } from './utils/rest-headers';
@ -57,17 +57,9 @@ export const createMessage = (channelId: string, payload: Partial<Entity.Message
// each file is uploaded individually as a separate API call
export const uploadFileAsMessage = (channelId: string, payload: Partial<Entity.Message>, file: File) => (dispatch) => {
const formData = new FormData();
formData.append('file', file);
dispatch(api.restCallBegan({
method: 'post',
url: '/upload',
data: formData,
headers: { 'Content-Type': 'multipart/form-data' },
callback: async ({ url }: { url: string, hash: string }) =>
dispatch(createMessage(channelId, payload, [url])),
}));
const uploadCallback = async ({ url }: REST.From.Post['/upload']) =>
dispatch(createMessage(channelId, payload, [url]));
dispatch(uploadFile(file, uploadCallback));
}
export const updateMessage = (id: string, payload: Partial<Entity.Message>) => (dispatch) => {

View File

@ -1,6 +1,6 @@
import { createSlice, createSelector } from '@reduxjs/toolkit';
import { WS } from '../types/ws';
import { actions as api } from './api';
import { actions as api, uploadFile } from './api';
import { actions as meta } from './meta';
import { unique } from './utils/filter';
import { token } from './utils/rest-headers';
@ -66,12 +66,18 @@ export const countUsers = () => (dispatch) => {
}));
}
export const uploadUserAvatar = (file: File) => (dispatch) => {
const uploadCallback = async ({ url }: REST.From.Post['/upload']) =>
dispatch(updateSelf({ avatarURL: url }));
dispatch(uploadFile(file, uploadCallback));
}
export const getUser = (id: string) =>
createSelector<Store.AppState, Entity.User[], Entity.User>(
state => state.entities.users,
users => users.find(u => u.id === id) ?? {
avatarURL: '/avatars/unknown.png',
discriminator: 0,
username: 'Unknown',
avatarURL: '/avatars/unknown.png',
} as Entity.User,
);

6
types/rest.d.ts vendored
View File

@ -36,10 +36,8 @@ declare namespace REST {
}
}
export interface Post {
'/auth/change-password': {
message: string;
token: string;
}
'/upload': { url: string, hash: string };
'/auth/change-password': { message: string, token: string }
}
}
}