diff --git a/framework/core/js/src/admin/components/AppearancePage.tsx b/framework/core/js/src/admin/components/AppearancePage.tsx index 12cfb7c9cf..1433ca0131 100644 --- a/framework/core/js/src/admin/components/AppearancePage.tsx +++ b/framework/core/js/src/admin/components/AppearancePage.tsx @@ -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; + } } diff --git a/framework/core/js/src/admin/components/BasicsPage.tsx b/framework/core/js/src/admin/components/BasicsPage.tsx index fb1e83c342..3381c70ac6 100644 --- a/framework/core/js/src/admin/components/BasicsPage.tsx +++ b/framework/core/js/src/admin/components/BasicsPage.tsx @@ -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; + } } diff --git a/framework/core/js/src/admin/components/MailPage.tsx b/framework/core/js/src/admin/components/MailPage.tsx index 3d31f263d6..3f7221aad2 100644 --- a/framework/core/js/src/admin/components/MailPage.tsx +++ b/framework/core/js/src/admin/components/MailPage.tsx @@ -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; + } }