Frontend: Themes now update properly
This commit is contained in:
parent
cde5a5a0f0
commit
72e7fa5177
@ -32,14 +32,17 @@ router.get('/:id', async (req, res) => {
|
||||
});
|
||||
|
||||
router.patch('/:id', updateUser, validateUser, async (req, res) => {
|
||||
const { name, styles } = req.body;
|
||||
const { name, styles, iconURL } = req.body;
|
||||
deps.themes.parse(styles);
|
||||
|
||||
const theme = await deps.themes.get(req.params.id);
|
||||
if (res.locals.user.id !== theme.creatorId)
|
||||
throw new APIError(403, 'You cannot manage this theme');
|
||||
|
||||
await theme.updateOne({ name, styles }, { runValidators: true });
|
||||
if (name) theme.name = name;
|
||||
if (styles) theme.styles = styles;
|
||||
if (iconURL) theme.name = name;
|
||||
await theme.save();
|
||||
|
||||
res.status(201).json(theme);
|
||||
});
|
||||
|
@ -4,7 +4,7 @@ import React, { useEffect, useState } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { uploadFile } from '../../../store/api';
|
||||
import { createTheme, deleteTheme, getTheme, updateTheme } from '../../../store/themes';
|
||||
import { createTheme, deleteTheme, getTheme, unlockTheme, updateTheme } from '../../../store/themes';
|
||||
import { openSaveChanges } from '../../../store/ui';
|
||||
import { updateSelf } from '../../../store/users';
|
||||
import FileInput from '../../inputs/file-input';
|
||||
@ -69,6 +69,8 @@ const UserSettingsThemes: React.FunctionComponent = () => {
|
||||
};
|
||||
|
||||
const AddTheme: React.FunctionComponent = () => {
|
||||
const [code, setCode] = useState('');
|
||||
|
||||
return (
|
||||
<div className="px-5 ml-4">
|
||||
<header className="mb-5">
|
||||
@ -82,11 +84,13 @@ const UserSettingsThemes: React.FunctionComponent = () => {
|
||||
label="Code"
|
||||
name="code"
|
||||
register={register}
|
||||
placeholder="discord" />
|
||||
placeholder="discord"
|
||||
onInput={e => setCode(e.currentTarget.value)} />
|
||||
<NormalButton
|
||||
className="bg-primary mt-8"
|
||||
onClick={() => {
|
||||
enableAddMode(false);
|
||||
dispatch(unlockTheme(code, (theme) => setTab(theme.id)));
|
||||
}}>Add</NormalButton>
|
||||
</div>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
@import './styles/theme-util.css';
|
||||
@import './styles/theme/theme-util.css';
|
||||
@import './styles/output.css';
|
||||
@import '~@fortawesome/fontawesome-svg-core/styles.css';
|
||||
|
||||
|
@ -19,7 +19,7 @@ export default (store) => (next) => async (action) => {
|
||||
headers,
|
||||
});
|
||||
|
||||
store.dispatch(actions.restCallSucceded(payload));
|
||||
store.dispatch(actions.restCallSucceded({ url, response: payload }));
|
||||
if (onSuccess)
|
||||
for (const type of onSuccess)
|
||||
store.dispatch({ type, payload });
|
||||
|
@ -4,9 +4,10 @@ import { createSlice } from '@reduxjs/toolkit';
|
||||
import { actions as api } from './api';
|
||||
import { notInArray } from './utils/filter';
|
||||
import { getHeaders } from './utils/rest-headers';
|
||||
import accordTheme from '!!raw-loader!../styles/accord-theme.css';
|
||||
import discordTheme from '!!raw-loader!../styles/discord-theme.css';
|
||||
import winterTheme from '!!raw-loader!../styles/winter-theme.css';
|
||||
import accordTheme from '!!raw-loader!../styles/theme/accord-theme.css';
|
||||
import discordTheme from '!!raw-loader!../styles/theme/discord-theme.css';
|
||||
import winterTheme from '!!raw-loader!../styles/theme/winter-theme.css';
|
||||
import themeTemplate from '!!raw-loader!../styles/theme/winter-theme.css';
|
||||
|
||||
const slice = createSlice({
|
||||
name: 'themes',
|
||||
@ -46,6 +47,10 @@ const slice = createSlice({
|
||||
fetched: (themes, { payload }: Store.Action<Entity.Theme[]>) => {
|
||||
themes.push(...payload.filter(notInArray(themes)));
|
||||
},
|
||||
updated: (themes, { payload }: Store.Action<Entity.Theme>) => {
|
||||
const index = themes.findIndex(t => t.id === payload.id);
|
||||
themes[index] = payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
export const actions = slice.actions;
|
||||
@ -55,37 +60,6 @@ export const getTheme = (id: string, themes: Entity.Theme[]) => {
|
||||
return themes.find(t => t.id === id);
|
||||
}
|
||||
|
||||
const themeTemplate = `:root {
|
||||
--primary: #7289da;
|
||||
--secondary: #99aab5;
|
||||
--tertiary: #43b582;
|
||||
|
||||
--heading: white;
|
||||
--font: #99aab5;
|
||||
--normal: #dcddde;
|
||||
--muted: #72767d;
|
||||
--link: hsl(197, calc(var(--saturation-factor, 1) * 100%), 47.8%);
|
||||
--channel: #8e9297;
|
||||
|
||||
--saturation-factor: 1;
|
||||
--success: hsl(139, calc(var(--saturation-factor, 1) * 47.3%), 43.9%);
|
||||
--danger: hsl(359, calc(var(--saturation-factor, 1) * 82.6%), 59.4%);
|
||||
|
||||
--bg-primary: #36393f;
|
||||
--bg-secondary: #2f3136;
|
||||
--bg-secondary-alt: #292b2f;
|
||||
--bg-tertiary: #202225;
|
||||
--bg-textarea: #40444b;
|
||||
--bg-modifier-accent: hsla(0, 0%, 100%, 0.06);
|
||||
--bg-modifier-selected: rgba(79, 84, 92, 0.32);
|
||||
--bg-floating: #18191c;
|
||||
|
||||
--elevation: 0 1px 0 rgba(4, 4, 5, 0.2), 0 1.5px 0 rgba(6, 6, 7, 0.05),
|
||||
0 2px 0 rgba(4, 4, 5, 0.05);
|
||||
|
||||
--font-primary: Whitney, 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
}`;
|
||||
|
||||
export const createTheme = (theme: Partial<Entity.Theme>, callback?: (theme: Entity.Theme) => any) => (dispatch) => {
|
||||
dispatch(api.restCallBegan({
|
||||
url: '/themes',
|
||||
@ -99,8 +73,12 @@ export const createTheme = (theme: Partial<Entity.Theme>, callback?: (theme: Ent
|
||||
}));
|
||||
}
|
||||
|
||||
export const unlockTheme = (id: string) => (dispatch) => {
|
||||
dispatch(api.restCallBegan({ url: `/themes/unlock/${id}`, headers: getHeaders() }));
|
||||
export const unlockTheme = (id: string, callback?: (theme: Entity.Theme) => any) => (dispatch) => {
|
||||
dispatch(api.restCallBegan({
|
||||
url: `/themes/unlock/${id}`,
|
||||
headers: getHeaders(),
|
||||
callback,
|
||||
}));
|
||||
}
|
||||
|
||||
export const updateTheme = (id: string, data: Partial<Entity.Theme>) => (dispatch) => {
|
||||
@ -109,6 +87,7 @@ export const updateTheme = (id: string, data: Partial<Entity.Theme>) => (dispatc
|
||||
headers: getHeaders(),
|
||||
method: 'patch',
|
||||
url: `/themes/${id}`,
|
||||
callback: (theme: Entity.Theme) => dispatch(actions.updated(theme)),
|
||||
}));
|
||||
}
|
||||
|
||||
|
30
frontend/src/styles/theme/theme-template.css
Normal file
30
frontend/src/styles/theme/theme-template.css
Normal file
@ -0,0 +1,30 @@
|
||||
:root {
|
||||
--primary: #7289da;
|
||||
--secondary: #99aab5;
|
||||
--tertiary: #43b582;
|
||||
|
||||
--heading: white;
|
||||
--font: #99aab5;
|
||||
--normal: #dcddde;
|
||||
--muted: #72767d;
|
||||
--link: hsl(197, calc(var(--saturation-factor, 1) * 100%), 47.8%);
|
||||
--channel: #8e9297;
|
||||
|
||||
--saturation-factor: 1;
|
||||
--success: hsl(139, calc(var(--saturation-factor, 1) * 47.3%), 43.9%);
|
||||
--danger: hsl(359, calc(var(--saturation-factor, 1) * 82.6%), 59.4%);
|
||||
|
||||
--bg-primary: #36393f;
|
||||
--bg-secondary: #2f3136;
|
||||
--bg-secondary-alt: #292b2f;
|
||||
--bg-tertiary: #202225;
|
||||
--bg-textarea: #40444b;
|
||||
--bg-modifier-accent: hsla(0, 0%, 100%, 0.06);
|
||||
--bg-modifier-selected: rgba(79, 84, 92, 0.32);
|
||||
--bg-floating: #18191c;
|
||||
|
||||
--elevation: 0 1px 0 rgba(4, 4, 5, 0.2), 0 1.5px 0 rgba(6, 6, 7, 0.05),
|
||||
0 2px 0 rgba(4, 4, 5, 0.05);
|
||||
|
||||
--font-primary: Whitney, 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user