Add error message for missing uploads folder.
This commit is contained in:
parent
01e0d7d454
commit
d0acf2fe7a
@ -32,7 +32,11 @@ Built with React, TypeScript, and Node.js.
|
||||
cd frontend && npm i -f
|
||||
cd ../backend && npm i -f
|
||||
```
|
||||
4. In `backend` directory, configure `.env.example` and rename the file to `.env`
|
||||
4. Add upload folder.
|
||||
```
|
||||
mkdir -p assets/upload
|
||||
```
|
||||
5. In `backend` directory, configure `.env.example` and rename the file to `.env`
|
||||
|
||||
---
|
||||
|
||||
|
@ -6,8 +6,8 @@ import { parse } from 'yaml';
|
||||
import fs from 'fs';
|
||||
global['config'] = parse(fs.readFileSync('../config.yaml', 'utf-8'));
|
||||
|
||||
import './modules/deps';
|
||||
import './modules/logger';
|
||||
import './modules/deps';
|
||||
import { User } from './data/models/user';
|
||||
|
||||
connect(process.env.MONGO_URI, {
|
||||
|
@ -22,7 +22,9 @@ function setupMulter(app: Application) {
|
||||
const uploadDir = resolve('./assets/upload');
|
||||
try {
|
||||
execSync(`mkdir -p ${uploadDir} 2>> /dev/null`);
|
||||
} catch { }
|
||||
} catch {
|
||||
log.error("Upload folder not created. Refer to the setup guide.");
|
||||
}
|
||||
|
||||
// uses storage rather than memory - 2 file operations per file upload
|
||||
const storage = multer.diskStorage({
|
||||
|
@ -23,7 +23,7 @@ const MessageHeader: FunctionComponent<MessageHeaderProps> = ({ author, message,
|
||||
<ContextMenuTrigger id={author.id}>
|
||||
<span
|
||||
style={{ color: highestRole?.color ?? 'var(--font)' }}
|
||||
className="text-base heading hover:underline cursor-pointer mr-2">{author.username}</span>
|
||||
className="context-menu text-base heading hover:underline cursor-pointer mr-2">{author.username}</span>
|
||||
</ContextMenuTrigger>
|
||||
<span className="text-xs muted">
|
||||
<MessageTimestamp message={message} />
|
||||
|
@ -76,7 +76,7 @@ const Message: React.FunctionComponent<MessageProps> = ({ message }: MessageProp
|
||||
|
||||
return (
|
||||
<ContextMenuTrigger key={message.id} id={message.id}>
|
||||
<div className={classNames('message flex', { 'mt-4': !isActuallyExtra })}>
|
||||
<div className={classNames('context-menu message flex', { 'mt-4': !isActuallyExtra })}>
|
||||
<div className="flex-shrink-0 left-side text-xs w-16 mr-2 pl-5 pt-1"><LeftSide /></div>
|
||||
<div className="relative flex-grow px-2">
|
||||
<div className="absolute toolbar right-0 -mt-3 z-10">
|
||||
|
@ -79,12 +79,14 @@ const ChannelSettingsPerms: React.FunctionComponent = () => {
|
||||
<nav className="pr-10">
|
||||
{overrideRoles.reverse().map(r => (
|
||||
<ContextMenuTrigger id={r.id} key={r.id}>
|
||||
<TabLink
|
||||
style={{ color: r.color }}
|
||||
tab={roleId}
|
||||
setTab={setRoleId}
|
||||
id={r.id}>{r.name}</TabLink>
|
||||
<RoleMenu role={r} />
|
||||
<div className="context-menu">
|
||||
<TabLink
|
||||
style={{ color: r.color }}
|
||||
tab={roleId}
|
||||
setTab={setRoleId}
|
||||
id={r.id}>{r.name}</TabLink>
|
||||
<RoleMenu role={r} />
|
||||
</div>
|
||||
</ContextMenuTrigger>
|
||||
))}
|
||||
|
||||
|
@ -99,7 +99,7 @@ const GuildSettingsRoles: React.FunctionComponent = () => {
|
||||
<ContextMenuTrigger id={r.id} key={r.id}>
|
||||
<TabLink
|
||||
className={classNames({
|
||||
'cursor-not-allowed opacity-25': !selfIsHigher(r),
|
||||
'context-menu cursor-not-allowed opacity-25': !selfIsHigher(r),
|
||||
})}
|
||||
key={r.id}
|
||||
style={{ color: r.color }}
|
||||
|
@ -59,7 +59,7 @@ const UserSettingsThemes: React.FunctionComponent = () => {
|
||||
const ThemeDetails: React.FunctionComponent = () => {
|
||||
const { register, setValue, handleSubmit } = useForm();
|
||||
const theme = themes.find(t => t.id === themeId);
|
||||
const creatorUser: Entity.User = useSelector(getUser(theme?.creatorId));
|
||||
const creatorUser: Entity.User = useSelector(getUser(theme.creatorId));
|
||||
if (!theme) return null;
|
||||
|
||||
const onApply = () => dispatch(updateSelf({ activeThemeId: themeId }));
|
||||
|
@ -41,7 +41,7 @@ const ChannelTabs: React.FunctionComponent = () => {
|
||||
|
||||
return <div className="p-2 pl-3">{users.map(u =>
|
||||
<ContextMenuTrigger key={u.id} id={u.id}>
|
||||
<div className="mb-1">
|
||||
<div className="context-menu mb-1">
|
||||
<FoundUsername user={u} size="sm" guild={activeGuild} />
|
||||
</div>
|
||||
</ContextMenuTrigger>
|
||||
@ -69,25 +69,27 @@ const ChannelTabs: React.FunctionComponent = () => {
|
||||
return (
|
||||
<>
|
||||
<ContextMenuTrigger key={channel.id} id={channel.id}>
|
||||
{/* <Draggable> */}
|
||||
<Link
|
||||
onClick={onClick}
|
||||
to={link}
|
||||
className={classNames(
|
||||
`cursor-pointer flex items-center rounded h-8 p-2 pl-3`,
|
||||
{ active: channel.id === activeChannel?.id },
|
||||
)}>
|
||||
<FontAwesomeIcon
|
||||
size="xs"
|
||||
<div className='context-menu'>
|
||||
{/* <Draggable> */}
|
||||
<Link
|
||||
onClick={onClick}
|
||||
to={link}
|
||||
className={classNames(
|
||||
`float-left scale-150 muted fill-current z-0`,
|
||||
(channel.type === 'VOICE') ? 'mr-2' : 'mr-3',
|
||||
)}
|
||||
icon={icon} />
|
||||
<ChannelTabContent />
|
||||
<ChannelMenu channel={channel} />
|
||||
</Link>
|
||||
{/* </Draggable> */}
|
||||
`cursor-pointer flex items-center rounded h-8 p-2 pl-3`,
|
||||
{ active: channel.id === activeChannel?.id },
|
||||
)}>
|
||||
<FontAwesomeIcon
|
||||
size="xs"
|
||||
className={classNames(
|
||||
`float-left scale-150 muted fill-current z-0`,
|
||||
(channel.type === 'VOICE') ? 'mr-2' : 'mr-3',
|
||||
)}
|
||||
icon={icon} />
|
||||
<ChannelTabContent />
|
||||
<ChannelMenu channel={channel} />
|
||||
</Link>
|
||||
{/* </Draggable> */}
|
||||
</div>
|
||||
</ContextMenuTrigger>
|
||||
<VCMembers />
|
||||
</>
|
||||
|
@ -11,19 +11,21 @@ const SidebarIcons: React.FunctionComponent = () => {
|
||||
|
||||
const guildIcons = guilds.map(g => (
|
||||
<ContextMenuTrigger key={g.id} id={g.id}>
|
||||
<Link to={`/channels/${g.id}`}>
|
||||
<SidebarIcon
|
||||
to={`/channels/${g.id}`}
|
||||
imageURL={g.iconURL}
|
||||
name={g.name}
|
||||
tooltip={g.name} />
|
||||
</Link>
|
||||
<GuildMenu guild={g} />
|
||||
<div className="context-menu">
|
||||
<Link to={`/channels/${g.id}`}>
|
||||
<SidebarIcon
|
||||
to={`/channels/${g.id}`}
|
||||
imageURL={g.iconURL}
|
||||
name={g.name}
|
||||
tooltip={g.name} />
|
||||
</Link>
|
||||
<GuildMenu guild={g} />
|
||||
</div>
|
||||
</ContextMenuTrigger>
|
||||
));
|
||||
|
||||
return (
|
||||
<div className="overflow-auto min-h-screen float-left p-3 flex flex-col bg-bg-tertiary">
|
||||
<div className="sidebar-icons overflow-auto min-h-screen float-left p-3 flex flex-col bg-bg-tertiary">
|
||||
<Link to="/channels/@me">
|
||||
<SidebarIcon
|
||||
to="/channels/@me"
|
||||
|
@ -37,10 +37,10 @@ const MemberList: React.FunctionComponent = () => {
|
||||
<ContextMenuTrigger
|
||||
id={u.id}
|
||||
key={u.id}>
|
||||
<div className="m-2">
|
||||
<div className="context-menu"> <div className="m-2">
|
||||
<FoundUsername guild={guild} user={u} />
|
||||
<GuildMemberMenu user={u} /></div>
|
||||
</div>
|
||||
<GuildMemberMenu user={u} />
|
||||
</ContextMenuTrigger>
|
||||
))}
|
||||
</div>
|
||||
|
@ -12,7 +12,7 @@ const Dropdown: React.FunctionComponent<DropdownProps> = (props) => {
|
||||
const dropdown = useSelector((s: Store.AppState) => s.ui.openDropdown);
|
||||
|
||||
return (
|
||||
<div className="w-full pt-3">
|
||||
<div className="dropdown bg-bg-tertiary w-full pt-3">
|
||||
<div className="flex justify-between items-center">
|
||||
<h1 className="flex-grow font-bold pl-2">{props.title}</h1>
|
||||
<FontAwesomeIcon icon={faChevronDown} />
|
||||
|
@ -21,7 +21,7 @@
|
||||
--bg-primary: transparent;
|
||||
--bg-secondary: transparent;
|
||||
--bg-secondary-alt: transparent;
|
||||
--bg-tertiary: #050219;
|
||||
--bg-tertiary: transparent;
|
||||
--bg-textarea: #40444b;
|
||||
--bg-modifier-accent: hsla(0, 0%, 100%, 0.06);
|
||||
--bg-modifier-selected: rgba(79, 84, 92, 0.32);
|
||||
@ -44,13 +44,44 @@ body {
|
||||
.member-list {
|
||||
background-image: url("https://newstarsgame.com/public/Purple/Layer%201/Space%20Background%201.png");
|
||||
}
|
||||
|
||||
.sidebar-tabs {
|
||||
background-image: url("https://newstarsgame.com/public/Purple/Layer%201/Space%20Background%2010.png");
|
||||
background-image: url("https://newstarsgame.com/public/Purple/Layer%201/Space%20Background%2010.png");
|
||||
}
|
||||
|
||||
.bg-bg-secondary {
|
||||
/* background-image: url("https://newstarsgame.com/public/Purple/Layer%202/Space%20Background%202.png"); */
|
||||
div.ReactModal__Content:not(.w-full),
|
||||
.sidebar-icons *,
|
||||
.context-menu,
|
||||
input,
|
||||
textarea,
|
||||
label+* {
|
||||
--warning: #f77d26;
|
||||
--normal: #dcddde;
|
||||
--link: hsl(197, calc(var(--saturation-factor, 1) * 100%), 47.8%);
|
||||
--channel: #8e9297;
|
||||
--saturation-factor: 1;
|
||||
--bg-primary: #110E28;
|
||||
--bg-secondary: #110E28;
|
||||
--bg-secondary-alt: #110E28;
|
||||
--bg-tertiary: #050219;
|
||||
--bg-textarea: #40444b;
|
||||
--bg-floating: #050219;
|
||||
}
|
||||
|
||||
.bg-bg-tertiary {
|
||||
.ReactModal__Overlay:hover {
|
||||
animation: fade-in .2s ease-in-out;
|
||||
}
|
||||
|
||||
div.ReactModal__Overlay {
|
||||
background-image: url("https://newstarsgame.com/public/Purple/Layer%202/Space%20Background%2010.png") !important;
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user