1
0
mirror of https://github.com/flarum/core.git synced 2025-08-06 16:36:47 +02:00

feat: make it easier to modify AppearancePage, BasicsPage, MailPage (#4037)

This commit is contained in:
IanM
2024-09-29 08:07:10 +01:00
committed by GitHub
parent 84414c6699
commit 7f657dac04
3 changed files with 256 additions and 169 deletions

View File

@@ -19,52 +19,7 @@ export default class AppearancePage extends AdminPage {
} }
content() { content() {
return ( return this.contentItems().toArray();
<>
<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>
</>
);
} }
colorItems() { colorItems() {
@@ -119,4 +74,77 @@ export default class AppearancePage extends AdminPage {
onsaved() { onsaved() {
window.location.reload(); 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;
}
} }

View File

@@ -3,7 +3,7 @@ import FieldSet from '../../common/components/FieldSet';
import ItemList from '../../common/utils/ItemList'; import ItemList from '../../common/utils/ItemList';
import AdminPage from './AdminPage'; import AdminPage from './AdminPage';
import type { IPageAttrs } from '../../common/components/Page'; import type { IPageAttrs } from '../../common/components/Page';
import type Mithril from 'mithril'; import Mithril from 'mithril';
export type HomePageItem = { path: string; label: Mithril.Children }; export type HomePageItem = { path: string; label: Mithril.Children };
@@ -44,78 +44,7 @@ export default class BasicsPage<CustomAttrs extends IPageAttrs = IPageAttrs> ext
content() { content() {
return [ return [
<div className="Form"> <div className="Form">
{this.buildSettingComponent({ {this.contentItems().toArray()}
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.submitButton()} {this.submitButton()}
</div>, </div>,
]; ];
@@ -135,4 +64,111 @@ export default class BasicsPage<CustomAttrs extends IPageAttrs = IPageAttrs> ext
return items; 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;
}
} }

View File

@@ -6,8 +6,9 @@ import LoadingIndicator from '../../common/components/LoadingIndicator';
import AdminPage from './AdminPage'; import AdminPage from './AdminPage';
import type { IPageAttrs } from '../../common/components/Page'; import type { IPageAttrs } from '../../common/components/Page';
import type { AlertIdentifier } from '../../common/states/AlertManagerState'; import type { AlertIdentifier } from '../../common/states/AlertManagerState';
import type Mithril from 'mithril'; import Mithril from 'mithril';
import type { SaveSubmitEvent } from './AdminPage'; import type { SaveSubmitEvent } from './AdminPage';
import ItemList from '../../common/utils/ItemList';
export interface MailSettings { export interface MailSettings {
data: { data: {
@@ -65,55 +66,7 @@ export default class MailPage<CustomAttrs extends IPageAttrs = IPageAttrs> exten
return <LoadingIndicator />; return <LoadingIndicator />;
} }
const fields = this.driverFields![this.setting('mail_driver')()]; return <div className="Form">{this.contentItems().toArray()}</div>;
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>
);
} }
sendTestEmail() { sendTestEmail() {
@@ -142,4 +95,74 @@ export default class MailPage<CustomAttrs extends IPageAttrs = IPageAttrs> exten
saveSettings(e: SaveSubmitEvent) { saveSettings(e: SaveSubmitEvent) {
return super.saveSettings(e).then(() => this.refresh()); 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;
}
} }