mirror of
https://github.com/flarum/core.git
synced 2025-08-06 08:27:42 +02:00
feat: make it easier to modify AppearancePage, BasicsPage, MailPage (#4037)
This commit is contained in:
@@ -19,52 +19,7 @@ export default class AppearancePage extends AdminPage {
|
||||
}
|
||||
|
||||
content() {
|
||||
return (
|
||||
<>
|
||||
<div className="Form">
|
||||
<fieldset className="AppearancePage-colors">
|
||||
<legend>{app.translator.trans('core.admin.appearance.colors_heading')}</legend>
|
||||
{this.colorItems().toArray()}
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<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 className="Button" onclick={() => app.modal.show(EditCustomHeaderModal)}>
|
||||
{app.translator.trans('core.admin.appearance.edit_header_button')}
|
||||
</Button>
|
||||
</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 className="Button" onclick={() => app.modal.show(EditCustomFooterModal)}>
|
||||
{app.translator.trans('core.admin.appearance.edit_footer_button')}
|
||||
</Button>
|
||||
</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 className="Button" onclick={() => app.modal.show(EditCustomCssModal)}>
|
||||
{app.translator.trans('core.admin.appearance.edit_css_button')}
|
||||
</Button>
|
||||
</fieldset>
|
||||
</>
|
||||
);
|
||||
return this.contentItems().toArray();
|
||||
}
|
||||
|
||||
colorItems() {
|
||||
@@ -119,4 +74,77 @@ export default class AppearancePage extends AdminPage {
|
||||
onsaved() {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
contentItems(): ItemList<Mithril.Children> {
|
||||
const items = new ItemList<Mithril.Children>();
|
||||
|
||||
items.add(
|
||||
'colors',
|
||||
<div className="Form">
|
||||
<fieldset className="AppearancePage-colors">
|
||||
<legend>{app.translator.trans('core.admin.appearance.colors_heading')}</legend>
|
||||
{this.colorItems().toArray()}
|
||||
</fieldset>
|
||||
</div>,
|
||||
100
|
||||
);
|
||||
|
||||
items.add(
|
||||
'logo',
|
||||
<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>,
|
||||
90
|
||||
);
|
||||
|
||||
items.add(
|
||||
'favicon',
|
||||
<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>,
|
||||
80
|
||||
);
|
||||
|
||||
items.add(
|
||||
'custom-header',
|
||||
<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 className="Button" onclick={() => app.modal.show(EditCustomHeaderModal)}>
|
||||
{app.translator.trans('core.admin.appearance.edit_header_button')}
|
||||
</Button>
|
||||
</fieldset>,
|
||||
70
|
||||
);
|
||||
|
||||
items.add(
|
||||
'custom-footer',
|
||||
<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 className="Button" onclick={() => app.modal.show(EditCustomFooterModal)}>
|
||||
{app.translator.trans('core.admin.appearance.edit_footer_button')}
|
||||
</Button>
|
||||
</fieldset>,
|
||||
60
|
||||
);
|
||||
|
||||
items.add(
|
||||
'custom-css',
|
||||
<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 className="Button" onclick={() => app.modal.show(EditCustomCssModal)}>
|
||||
{app.translator.trans('core.admin.appearance.edit_css_button')}
|
||||
</Button>
|
||||
</fieldset>,
|
||||
50
|
||||
);
|
||||
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@ import FieldSet from '../../common/components/FieldSet';
|
||||
import ItemList from '../../common/utils/ItemList';
|
||||
import AdminPage from './AdminPage';
|
||||
import type { IPageAttrs } from '../../common/components/Page';
|
||||
import type Mithril from 'mithril';
|
||||
import Mithril from 'mithril';
|
||||
|
||||
export type HomePageItem = { path: string; label: Mithril.Children };
|
||||
|
||||
@@ -44,78 +44,7 @@ export default class BasicsPage<CustomAttrs extends IPageAttrs = IPageAttrs> ext
|
||||
content() {
|
||||
return [
|
||||
<div className="Form">
|
||||
{this.buildSettingComponent({
|
||||
type: 'text',
|
||||
setting: 'forum_title',
|
||||
label: app.translator.trans('core.admin.basics.forum_title_heading'),
|
||||
})}
|
||||
{this.buildSettingComponent({
|
||||
type: 'text',
|
||||
setting: 'forum_description',
|
||||
label: app.translator.trans('core.admin.basics.forum_description_heading'),
|
||||
help: app.translator.trans('core.admin.basics.forum_description_text'),
|
||||
})}
|
||||
|
||||
{Object.keys(this.localeOptions).length > 1 && (
|
||||
<>
|
||||
{this.buildSettingComponent({
|
||||
type: 'select',
|
||||
setting: 'default_locale',
|
||||
options: this.localeOptions,
|
||||
label: app.translator.trans('core.admin.basics.default_language_heading'),
|
||||
})}
|
||||
{this.buildSettingComponent({
|
||||
type: 'switch',
|
||||
setting: 'show_language_selector',
|
||||
label: app.translator.trans('core.admin.basics.show_language_selector_label'),
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
|
||||
<FieldSet className="BasicsPage-homePage Form-group" label={app.translator.trans('core.admin.basics.home_page_heading')}>
|
||||
<div className="helpText">{app.translator.trans('core.admin.basics.home_page_text')}</div>
|
||||
{this.homePageItems()
|
||||
.toArray()
|
||||
.map(({ path, label }) => (
|
||||
<label className="checkbox">
|
||||
<input type="radio" name="homePage" value={path} bidi={this.setting('default_route')} />
|
||||
{label}
|
||||
</label>
|
||||
))}
|
||||
</FieldSet>
|
||||
|
||||
<div className="Form-group BasicsPage-welcomeBanner-input">
|
||||
<label>{app.translator.trans('core.admin.basics.welcome_banner_heading')}</label>
|
||||
<div className="helpText">{app.translator.trans('core.admin.basics.welcome_banner_text')}</div>
|
||||
<input type="text" className="FormControl" bidi={this.setting('welcome_title')} />
|
||||
<textarea className="FormControl" bidi={this.setting('welcome_message')} />
|
||||
</div>
|
||||
|
||||
{Object.keys(this.displayNameOptions).length > 1 &&
|
||||
this.buildSettingComponent({
|
||||
type: 'select',
|
||||
setting: 'display_name_driver',
|
||||
options: this.displayNameOptions,
|
||||
label: app.translator.trans('core.admin.basics.display_name_heading'),
|
||||
help: app.translator.trans('core.admin.basics.display_name_text'),
|
||||
})}
|
||||
|
||||
{Object.keys(this.slugDriverOptions).map((model) => {
|
||||
const options = this.slugDriverOptions[model];
|
||||
|
||||
if (Object.keys(options).length > 1) {
|
||||
return this.buildSettingComponent({
|
||||
type: 'select',
|
||||
setting: `slug_driver_${model}`,
|
||||
options,
|
||||
label: app.translator.trans('core.admin.basics.slug_driver_heading', { model }),
|
||||
help: app.translator.trans('core.admin.basics.slug_driver_text', { model }),
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
})}
|
||||
|
||||
{this.contentItems().toArray()}
|
||||
{this.submitButton()}
|
||||
</div>,
|
||||
];
|
||||
@@ -135,4 +64,111 @@ export default class BasicsPage<CustomAttrs extends IPageAttrs = IPageAttrs> ext
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
contentItems(): ItemList<Mithril.Children> {
|
||||
const items = new ItemList<Mithril.Children>();
|
||||
|
||||
items.add(
|
||||
'forum-title',
|
||||
this.buildSettingComponent({
|
||||
type: 'text',
|
||||
setting: 'forum_title',
|
||||
label: app.translator.trans('core.admin.basics.forum_title_heading'),
|
||||
}),
|
||||
100
|
||||
);
|
||||
|
||||
items.add(
|
||||
'forum-description',
|
||||
this.buildSettingComponent({
|
||||
type: 'text',
|
||||
setting: 'forum_description',
|
||||
label: app.translator.trans('core.admin.basics.forum_description_heading'),
|
||||
help: app.translator.trans('core.admin.basics.forum_description_text'),
|
||||
}),
|
||||
90
|
||||
);
|
||||
|
||||
items.add(
|
||||
'default-locale',
|
||||
Object.keys(this.localeOptions).length > 1 && (
|
||||
<>
|
||||
{this.buildSettingComponent({
|
||||
type: 'select',
|
||||
setting: 'default_locale',
|
||||
options: this.localeOptions,
|
||||
label: app.translator.trans('core.admin.basics.default_language_heading'),
|
||||
})}
|
||||
{this.buildSettingComponent({
|
||||
type: 'switch',
|
||||
setting: 'show_language_selector',
|
||||
label: app.translator.trans('core.admin.basics.show_language_selector_label'),
|
||||
})}
|
||||
</>
|
||||
),
|
||||
80
|
||||
);
|
||||
|
||||
items.add(
|
||||
'home-page',
|
||||
<FieldSet className="BasicsPage-homePage Form-group" label={app.translator.trans('core.admin.basics.home_page_heading')}>
|
||||
<div className="helpText">{app.translator.trans('core.admin.basics.home_page_text')}</div>
|
||||
{this.homePageItems()
|
||||
.toArray()
|
||||
.map(({ path, label }) => (
|
||||
<label className="checkbox">
|
||||
<input type="radio" name="homePage" value={path} bidi={this.setting('default_route')} />
|
||||
{label}
|
||||
</label>
|
||||
))}
|
||||
</FieldSet>,
|
||||
70
|
||||
);
|
||||
|
||||
items.add(
|
||||
'welcome-banner',
|
||||
<div className="Form-group BasicsPage-welcomeBanner-input">
|
||||
<label>{app.translator.trans('core.admin.basics.welcome_banner_heading')}</label>
|
||||
<div className="helpText">{app.translator.trans('core.admin.basics.welcome_banner_text')}</div>
|
||||
<input type="text" className="FormControl" bidi={this.setting('welcome_title')} />
|
||||
<textarea className="FormControl" bidi={this.setting('welcome_message')} />
|
||||
</div>,
|
||||
60
|
||||
);
|
||||
|
||||
items.add(
|
||||
'display-name-driver',
|
||||
Object.keys(this.displayNameOptions).length > 1 &&
|
||||
this.buildSettingComponent({
|
||||
type: 'select',
|
||||
setting: 'display_name_driver',
|
||||
options: this.displayNameOptions,
|
||||
label: app.translator.trans('core.admin.basics.display_name_heading'),
|
||||
help: app.translator.trans('core.admin.basics.display_name_text'),
|
||||
}),
|
||||
50
|
||||
);
|
||||
|
||||
items.add(
|
||||
'slug-driver',
|
||||
Object.keys(this.slugDriverOptions).map((model) => {
|
||||
const options = this.slugDriverOptions[model];
|
||||
|
||||
if (Object.keys(options).length > 1) {
|
||||
return this.buildSettingComponent({
|
||||
type: 'select',
|
||||
setting: `slug_driver_${model}`,
|
||||
options,
|
||||
label: app.translator.trans('core.admin.basics.slug_driver_heading', { model }),
|
||||
help: app.translator.trans('core.admin.basics.slug_driver_text', { model }),
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}),
|
||||
40
|
||||
);
|
||||
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
@@ -6,8 +6,9 @@ import LoadingIndicator from '../../common/components/LoadingIndicator';
|
||||
import AdminPage from './AdminPage';
|
||||
import type { IPageAttrs } from '../../common/components/Page';
|
||||
import type { AlertIdentifier } from '../../common/states/AlertManagerState';
|
||||
import type Mithril from 'mithril';
|
||||
import Mithril from 'mithril';
|
||||
import type { SaveSubmitEvent } from './AdminPage';
|
||||
import ItemList from '../../common/utils/ItemList';
|
||||
|
||||
export interface MailSettings {
|
||||
data: {
|
||||
@@ -65,55 +66,7 @@ export default class MailPage<CustomAttrs extends IPageAttrs = IPageAttrs> exten
|
||||
return <LoadingIndicator />;
|
||||
}
|
||||
|
||||
const fields = this.driverFields![this.setting('mail_driver')()];
|
||||
const fieldKeys = Object.keys(fields);
|
||||
|
||||
return (
|
||||
<div className="Form">
|
||||
{this.buildSettingComponent({
|
||||
type: 'text',
|
||||
setting: 'mail_from',
|
||||
label: app.translator.trans('core.admin.email.addresses_heading'),
|
||||
})}
|
||||
{this.buildSettingComponent({
|
||||
type: 'select',
|
||||
setting: 'mail_driver',
|
||||
options: Object.keys(this.driverFields!).reduce((memo, val) => ({ ...memo, [val]: val }), {}),
|
||||
label: app.translator.trans('core.admin.email.driver_heading'),
|
||||
})}
|
||||
{this.status!.sending || <Alert dismissible={false}>{app.translator.trans('core.admin.email.not_sending_message')}</Alert>}
|
||||
|
||||
{!!fieldKeys.length && (
|
||||
<FieldSet label={app.translator.trans(`core.admin.email.${this.setting('mail_driver')()}_heading`)} className="MailPage-MailSettings">
|
||||
<div className="MailPage-MailSettings-input">
|
||||
{fieldKeys.map((field) => {
|
||||
const fieldInfo = fields[field];
|
||||
|
||||
return (
|
||||
<>
|
||||
{this.buildSettingComponent({
|
||||
type: typeof fieldInfo === 'string' ? 'text' : 'select',
|
||||
label: app.translator.trans(`core.admin.email.${field}_label`),
|
||||
setting: field,
|
||||
options: fieldInfo,
|
||||
})}
|
||||
{this.status!.errors[field] && <p className="ValidationError">{this.status!.errors[field]}</p>}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</FieldSet>
|
||||
)}
|
||||
{this.submitButton()}
|
||||
|
||||
<FieldSet label={app.translator.trans('core.admin.email.send_test_mail_heading')} className="MailPage-MailSettings">
|
||||
<div className="helpText">{app.translator.trans('core.admin.email.send_test_mail_text', { email: app.session.user!.email() })}</div>
|
||||
<Button className="Button Button--primary" disabled={this.sendingTest || this.isChanged()} onclick={() => this.sendTestEmail()}>
|
||||
{app.translator.trans('core.admin.email.send_test_mail_button')}
|
||||
</Button>
|
||||
</FieldSet>
|
||||
</div>
|
||||
);
|
||||
return <div className="Form">{this.contentItems().toArray()}</div>;
|
||||
}
|
||||
|
||||
sendTestEmail() {
|
||||
@@ -142,4 +95,74 @@ export default class MailPage<CustomAttrs extends IPageAttrs = IPageAttrs> exten
|
||||
saveSettings(e: SaveSubmitEvent) {
|
||||
return super.saveSettings(e).then(() => this.refresh());
|
||||
}
|
||||
|
||||
contentItems(): ItemList<Mithril.Children> {
|
||||
const items = new ItemList<Mithril.Children>();
|
||||
const fields = this.driverFields![this.setting('mail_driver')()];
|
||||
const fieldKeys = Object.keys(fields);
|
||||
|
||||
items.add(
|
||||
'mail-from',
|
||||
this.buildSettingComponent({
|
||||
type: 'text',
|
||||
setting: 'mail_from',
|
||||
label: app.translator.trans('core.admin.email.addresses_heading'),
|
||||
}),
|
||||
100
|
||||
);
|
||||
|
||||
items.add(
|
||||
'mail-driver',
|
||||
this.buildSettingComponent({
|
||||
type: 'select',
|
||||
setting: 'mail_driver',
|
||||
options: Object.keys(this.driverFields!).reduce((memo, val) => ({ ...memo, [val]: val }), {}),
|
||||
label: app.translator.trans('core.admin.email.driver_heading'),
|
||||
}),
|
||||
90
|
||||
);
|
||||
|
||||
!this.status!.sending &&
|
||||
items.add('not-sending', <Alert dismissible={false}>{app.translator.trans('core.admin.email.not_sending_message')}</Alert>, 80);
|
||||
|
||||
!!fieldKeys.length &&
|
||||
items.add(
|
||||
'driver-settings',
|
||||
<FieldSet label={app.translator.trans(`core.admin.email.${this.setting('mail_driver')()}_heading`)} className="MailPage-MailSettings">
|
||||
<div className="MailPage-MailSettings-input">
|
||||
{fieldKeys.map((field) => {
|
||||
const fieldInfo = fields[field];
|
||||
|
||||
return (
|
||||
<>
|
||||
{this.buildSettingComponent({
|
||||
type: typeof fieldInfo === 'string' ? 'text' : 'select',
|
||||
label: app.translator.trans(`core.admin.email.${field}_label`),
|
||||
setting: field,
|
||||
options: fieldInfo,
|
||||
})}
|
||||
{this.status!.errors[field] && <p className="ValidationError">{this.status!.errors[field]}</p>}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</FieldSet>,
|
||||
70
|
||||
);
|
||||
|
||||
items.add('submit-button', this.submitButton(), 60);
|
||||
|
||||
items.add(
|
||||
'email-test',
|
||||
<FieldSet label={app.translator.trans('core.admin.email.send_test_mail_heading')} className="MailPage-MailSettings">
|
||||
<div className="helpText">{app.translator.trans('core.admin.email.send_test_mail_text', { email: app.session.user!.email() })}</div>
|
||||
<Button className="Button Button--primary" disabled={this.sendingTest || this.isChanged()} onclick={() => this.sendTestEmail()}>
|
||||
{app.translator.trans('core.admin.email.send_test_mail_button')}
|
||||
</Button>
|
||||
</FieldSet>,
|
||||
0
|
||||
);
|
||||
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user