mirror of
https://github.com/flarum/core.git
synced 2025-08-04 15:37:51 +02:00
Added Appearance page
This commit is contained in:
committed by
David Sevilla Martín
parent
e9ad848530
commit
ea880632e1
@@ -60,12 +60,15 @@ export default class AdminNav<T> extends Component<T> {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
// items.add('appearance', AdminLinkButton.component({
|
items.add(
|
||||||
// href: app.route('appearance'),
|
'appearance',
|
||||||
// icon: 'fas fa-paint-brush',
|
AdminLinkButton.component({
|
||||||
// children: app.translator.trans('core.admin.nav.appearance_button'),
|
href: app.route('appearance'),
|
||||||
// description: app.translator.trans('core.admin.nav.appearance_text')
|
icon: 'fas fa-paint-brush',
|
||||||
// }));
|
children: app.translator.trans('core.admin.nav.appearance_button'),
|
||||||
|
description: app.translator.trans('core.admin.nav.appearance_text'),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
// items.add('extensions', AdminLinkButton.component({
|
// items.add('extensions', AdminLinkButton.component({
|
||||||
// href: app.route('extensions'),
|
// href: app.route('extensions'),
|
||||||
|
131
js/src/admin/components/AppearancePage.tsx
Normal file
131
js/src/admin/components/AppearancePage.tsx
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
import app from '../app';
|
||||||
|
|
||||||
|
import Page from './Page';
|
||||||
|
import Button from '../../common/components/Button';
|
||||||
|
import Switch from '../../common/components/Switch';
|
||||||
|
import EditCustomCssModal from './EditCustomCssModal';
|
||||||
|
import EditCustomHeaderModal from './EditCustomHeaderModal';
|
||||||
|
import EditCustomFooterModal from './EditCustomFooterModal';
|
||||||
|
import UploadImageButton from './UploadImageButton';
|
||||||
|
import saveSettings from '../utils/saveSettings';
|
||||||
|
|
||||||
|
export default class AppearancePage extends Page {
|
||||||
|
loading = false;
|
||||||
|
primaryColor = m.prop(app.data.settings.theme_primary_color);
|
||||||
|
secondaryColor = m.prop(app.data.settings.theme_secondary_color);
|
||||||
|
darkMode = m.prop(app.data.settings.theme_dark_mode === '1');
|
||||||
|
coloredHeader = m.prop(app.data.settings.theme_colored_header === '1');
|
||||||
|
|
||||||
|
view() {
|
||||||
|
return (
|
||||||
|
<div className="AppearancePage">
|
||||||
|
<div className="container">
|
||||||
|
<form onsubmit={this.onsubmit.bind(this)}>
|
||||||
|
<fieldset className="AppearancePage-colors">
|
||||||
|
<legend>{app.translator.trans('core.admin.appearance.colors_heading')}</legend>
|
||||||
|
<div className="helpText">{app.translator.trans('core.admin.appearance.colors_text')}</div>
|
||||||
|
|
||||||
|
<div className="AppearancePage-colors-input">
|
||||||
|
<input
|
||||||
|
className="FormControl"
|
||||||
|
type="text"
|
||||||
|
placeholder="#aaaaaa"
|
||||||
|
value={this.primaryColor()}
|
||||||
|
onchange={m.withAttr('value', this.primaryColor)}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
className="FormControl"
|
||||||
|
type="text"
|
||||||
|
placeholder="#aaaaaa"
|
||||||
|
value={this.secondaryColor()}
|
||||||
|
onchange={m.withAttr('value', this.secondaryColor)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{Switch.component({
|
||||||
|
state: this.darkMode(),
|
||||||
|
children: app.translator.trans('core.admin.appearance.dark_mode_label'),
|
||||||
|
onchange: this.darkMode,
|
||||||
|
})}
|
||||||
|
|
||||||
|
{Switch.component({
|
||||||
|
state: this.coloredHeader(),
|
||||||
|
children: app.translator.trans('core.admin.appearance.colored_header_label'),
|
||||||
|
onchange: this.coloredHeader,
|
||||||
|
})}
|
||||||
|
|
||||||
|
{Button.component({
|
||||||
|
className: 'Button Button--primary',
|
||||||
|
type: 'submit',
|
||||||
|
children: app.translator.trans('core.admin.appearance.submit_button'),
|
||||||
|
loading: this.loading,
|
||||||
|
})}
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>{app.translator.trans('core.admin.appearance.logo_heading')}</legend>
|
||||||
|
<div className="helpText">{app.translator.trans('core.admin.appearance.logo_text')}</div>
|
||||||
|
<UploadImageButton name="logo" />
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>{app.translator.trans('core.admin.appearance.favicon_heading')}</legend>
|
||||||
|
<div className="helpText">{app.translator.trans('core.admin.appearance.favicon_text')}</div>
|
||||||
|
<UploadImageButton name="favicon" />
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>{app.translator.trans('core.admin.appearance.custom_header_heading')}</legend>
|
||||||
|
<div className="helpText">{app.translator.trans('core.admin.appearance.custom_header_text')}</div>
|
||||||
|
{Button.component({
|
||||||
|
className: 'Button',
|
||||||
|
children: app.translator.trans('core.admin.appearance.edit_header_button'),
|
||||||
|
onclick: () => app.modal.show(EditCustomHeaderModal),
|
||||||
|
})}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>{app.translator.trans('core.admin.appearance.custom_footer_heading')}</legend>
|
||||||
|
<div className="helpText">{app.translator.trans('core.admin.appearance.custom_footer_text')}</div>
|
||||||
|
{Button.component({
|
||||||
|
className: 'Button',
|
||||||
|
children: app.translator.trans('core.admin.appearance.edit_footer_button'),
|
||||||
|
onclick: () => app.modal.show(EditCustomFooterModal),
|
||||||
|
})}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>{app.translator.trans('core.admin.appearance.custom_styles_heading')}</legend>
|
||||||
|
<div className="helpText">{app.translator.trans('core.admin.appearance.custom_styles_text')}</div>
|
||||||
|
{Button.component({
|
||||||
|
className: 'Button',
|
||||||
|
children: app.translator.trans('core.admin.appearance.edit_css_button'),
|
||||||
|
onclick: () => app.modal.show(EditCustomCssModal),
|
||||||
|
})}
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onsubmit(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const hex = /^#[0-9a-f]{3}([0-9a-f]{3})?$/i;
|
||||||
|
|
||||||
|
if (!hex.test(this.primaryColor()) || !hex.test(this.secondaryColor())) {
|
||||||
|
alert(app.translator.trans('core.admin.appearance.enter_hex_message'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loading = true;
|
||||||
|
|
||||||
|
saveSettings({
|
||||||
|
theme_primary_color: this.primaryColor(),
|
||||||
|
theme_secondary_color: this.secondaryColor(),
|
||||||
|
theme_dark_mode: this.darkMode(),
|
||||||
|
theme_colored_header: this.coloredHeader(),
|
||||||
|
}).then(() => window.location.reload());
|
||||||
|
}
|
||||||
|
}
|
28
js/src/admin/components/EditCustomCssModal.tsx
Normal file
28
js/src/admin/components/EditCustomCssModal.tsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import SettingsModal from './SettingsModal';
|
||||||
|
|
||||||
|
export default class EditCustomCssModal extends SettingsModal {
|
||||||
|
className() {
|
||||||
|
return 'EditCustomCssModal Modal--large';
|
||||||
|
}
|
||||||
|
|
||||||
|
title() {
|
||||||
|
return app.translator.trans('core.admin.edit_css.title');
|
||||||
|
}
|
||||||
|
|
||||||
|
form() {
|
||||||
|
return [
|
||||||
|
<p>
|
||||||
|
{app.translator.trans('core.admin.edit_css.customize_text', {
|
||||||
|
a: <a href="https://github.com/flarum/core/tree/master/less" target="_blank" />,
|
||||||
|
})}
|
||||||
|
</p>,
|
||||||
|
<div className="Form-group">
|
||||||
|
<textarea className="FormControl" rows="30" bidi={this.setting('custom_less')} />
|
||||||
|
</div>,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
onsaved() {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}
|
24
js/src/admin/components/EditCustomFooterModal.tsx
Normal file
24
js/src/admin/components/EditCustomFooterModal.tsx
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import SettingsModal from './SettingsModal';
|
||||||
|
|
||||||
|
export default class EditCustomFooterModal extends SettingsModal {
|
||||||
|
className() {
|
||||||
|
return 'EditCustomFooterModal Modal--large';
|
||||||
|
}
|
||||||
|
|
||||||
|
title() {
|
||||||
|
return app.translator.trans('core.admin.edit_footer.title');
|
||||||
|
}
|
||||||
|
|
||||||
|
form() {
|
||||||
|
return [
|
||||||
|
<p>{app.translator.trans('core.admin.edit_footer.customize_text')}</p>,
|
||||||
|
<div className="Form-group">
|
||||||
|
<textarea className="FormControl" rows="30" bidi={this.setting('custom_footer')} />
|
||||||
|
</div>,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
onsaved() {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}
|
24
js/src/admin/components/EditCustomHeaderModal.tsx
Normal file
24
js/src/admin/components/EditCustomHeaderModal.tsx
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import SettingsModal from './SettingsModal';
|
||||||
|
|
||||||
|
export default class EditCustomHeaderModal extends SettingsModal {
|
||||||
|
className() {
|
||||||
|
return 'EditCustomHeaderModal Modal--large';
|
||||||
|
}
|
||||||
|
|
||||||
|
title() {
|
||||||
|
return app.translator.trans('core.admin.edit_header.title');
|
||||||
|
}
|
||||||
|
|
||||||
|
form() {
|
||||||
|
return [
|
||||||
|
<p>{app.translator.trans('core.admin.edit_header.customize_text')}</p>,
|
||||||
|
<div className="Form-group">
|
||||||
|
<textarea className="FormControl" rows="30" bidi={this.setting('custom_header')} />
|
||||||
|
</div>,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
onsaved() {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}
|
@@ -35,7 +35,7 @@ export default class UploadImageButton<T extends ButtonProps = ButtonProps> exte
|
|||||||
upload() {
|
upload() {
|
||||||
if (this.loading) return;
|
if (this.loading) return;
|
||||||
|
|
||||||
const $input = this.$('<input type="file">');
|
const $input = $('<input type="file">');
|
||||||
|
|
||||||
$input
|
$input
|
||||||
.appendTo('body')
|
.appendTo('body')
|
||||||
@@ -52,7 +52,7 @@ export default class UploadImageButton<T extends ButtonProps = ButtonProps> exte
|
|||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: this.resourceUrl(),
|
url: this.resourceUrl(),
|
||||||
serialize: (raw) => raw,
|
serialize: (raw) => raw,
|
||||||
data,
|
body: data,
|
||||||
}).then(this.success.bind(this), this.failure.bind(this));
|
}).then(this.success.bind(this), this.failure.bind(this));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@ import BasicsPage from './components/BasicsPage';
|
|||||||
import DashboardPage from './components/DashboardPage';
|
import DashboardPage from './components/DashboardPage';
|
||||||
import MailPage from './components/MailPage';
|
import MailPage from './components/MailPage';
|
||||||
import PermissionsPage from './components/PermissionsPage';
|
import PermissionsPage from './components/PermissionsPage';
|
||||||
|
import AppearancePage from './components/AppearancePage';
|
||||||
|
|
||||||
export default (app) => {
|
export default (app) => {
|
||||||
app.routes = {
|
app.routes = {
|
||||||
@@ -9,5 +10,6 @@ export default (app) => {
|
|||||||
basics: { path: '/basics', component: BasicsPage },
|
basics: { path: '/basics', component: BasicsPage },
|
||||||
mail: { path: '/mail', component: MailPage },
|
mail: { path: '/mail', component: MailPage },
|
||||||
permissions: { path: '/permissions', component: PermissionsPage },
|
permissions: { path: '/permissions', component: PermissionsPage },
|
||||||
|
appearance: { path: '/appearance', component: AppearancePage },
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user