mirror of
https://github.com/flarum/core.git
synced 2025-08-04 23:47:32 +02:00
refactor: convert page components to TypeScript (#3538)
* fix(a11y): color preview fields have no aria label * refactor: convert page components to TypeScript Co-authored-by: David Wheatley <hi@davwheat.dev> Signed-off-by: Sami Mazouz <ilyasmazouz@gmail.com>
This commit is contained in:
@@ -38,6 +38,8 @@ export interface AdminApplicationData extends ApplicationData {
|
|||||||
extensions: Record<string, Extension>;
|
extensions: Record<string, Extension>;
|
||||||
settings: Record<string, string>;
|
settings: Record<string, string>;
|
||||||
modelStatistics: Record<string, { total: number }>;
|
modelStatistics: Record<string, { total: number }>;
|
||||||
|
displayNameDrivers: string[];
|
||||||
|
slugDrivers: Record<string, string[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class AdminApplication extends Application {
|
export default class AdminApplication extends Application {
|
||||||
|
@@ -60,7 +60,7 @@ export type HTMLInputTypes =
|
|||||||
|
|
||||||
export interface CommonSettingsItemOptions extends Mithril.Attributes {
|
export interface CommonSettingsItemOptions extends Mithril.Attributes {
|
||||||
setting: string;
|
setting: string;
|
||||||
label: Mithril.Children;
|
label?: Mithril.Children;
|
||||||
help?: Mithril.Children;
|
help?: Mithril.Children;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
@@ -137,6 +137,8 @@ export type AdminHeaderAttrs = AdminHeaderOptions & Partial<Omit<Mithril.Attribu
|
|||||||
export type SettingValue = string;
|
export type SettingValue = string;
|
||||||
export type MutableSettings = Record<string, Stream<SettingValue>>;
|
export type MutableSettings = Record<string, Stream<SettingValue>>;
|
||||||
|
|
||||||
|
export type SaveSubmitEvent = SubmitEvent & { redraw: boolean };
|
||||||
|
|
||||||
export default abstract class AdminPage<CustomAttrs extends IPageAttrs = IPageAttrs> extends Page<CustomAttrs> {
|
export default abstract class AdminPage<CustomAttrs extends IPageAttrs = IPageAttrs> extends Page<CustomAttrs> {
|
||||||
settings: MutableSettings = {};
|
settings: MutableSettings = {};
|
||||||
loading: boolean = false;
|
loading: boolean = false;
|
||||||
@@ -162,7 +164,7 @@ export default abstract class AdminPage<CustomAttrs extends IPageAttrs = IPageAt
|
|||||||
*
|
*
|
||||||
* Calls `this.saveSettings` when the button is clicked.
|
* Calls `this.saveSettings` when the button is clicked.
|
||||||
*/
|
*/
|
||||||
submitButton(vnode: Mithril.Vnode<CustomAttrs, this>): Mithril.Children {
|
submitButton(): Mithril.Children {
|
||||||
return (
|
return (
|
||||||
<Button onclick={this.saveSettings.bind(this)} className="Button Button--primary" loading={this.loading} disabled={!this.isChanged()}>
|
<Button onclick={this.saveSettings.bind(this)} className="Button Button--primary" loading={this.loading} disabled={!this.isChanged()}>
|
||||||
{app.translator.trans('core.admin.settings.submit_button')}
|
{app.translator.trans('core.admin.settings.submit_button')}
|
||||||
@@ -385,7 +387,7 @@ export default abstract class AdminPage<CustomAttrs extends IPageAttrs = IPageAt
|
|||||||
/**
|
/**
|
||||||
* Saves the modified settings to the database.
|
* Saves the modified settings to the database.
|
||||||
*/
|
*/
|
||||||
saveSettings(e: SubmitEvent & { redraw: boolean }) {
|
saveSettings(e: SaveSubmitEvent) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
app.alerts.clear();
|
app.alerts.clear();
|
||||||
|
@@ -6,6 +6,7 @@ import EditCustomFooterModal from './EditCustomFooterModal';
|
|||||||
import UploadImageButton from './UploadImageButton';
|
import UploadImageButton from './UploadImageButton';
|
||||||
import AdminPage from './AdminPage';
|
import AdminPage from './AdminPage';
|
||||||
import ItemList from '../../common/utils/ItemList';
|
import ItemList from '../../common/utils/ItemList';
|
||||||
|
import type Mithril from 'mithril';
|
||||||
|
|
||||||
export default class AppearancePage extends AdminPage {
|
export default class AppearancePage extends AdminPage {
|
||||||
headerInfo() {
|
headerInfo() {
|
||||||
@@ -77,7 +78,7 @@ export default class AppearancePage extends AdminPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
colorItems() {
|
colorItems() {
|
||||||
const items = new ItemList();
|
const items = new ItemList<Mithril.Children>();
|
||||||
|
|
||||||
items.add('helpText', <div className="helpText">{app.translator.trans('core.admin.appearance.colors_text')}</div>, 80);
|
items.add('helpText', <div className="helpText">{app.translator.trans('core.admin.appearance.colors_text')}</div>, 80);
|
||||||
|
|
||||||
@@ -88,11 +89,13 @@ export default class AppearancePage extends AdminPage {
|
|||||||
type: 'color-preview',
|
type: 'color-preview',
|
||||||
setting: 'theme_primary_color',
|
setting: 'theme_primary_color',
|
||||||
placeholder: '#aaaaaa',
|
placeholder: '#aaaaaa',
|
||||||
|
ariaLabel: app.translator.trans('core.admin.appearance.colors_primary_label'),
|
||||||
})}
|
})}
|
||||||
{this.buildSettingComponent({
|
{this.buildSettingComponent({
|
||||||
type: 'color-preview',
|
type: 'color-preview',
|
||||||
setting: 'theme_secondary_color',
|
setting: 'theme_secondary_color',
|
||||||
placeholder: '#aaaaaa',
|
placeholder: '#aaaaaa',
|
||||||
|
ariaLabel: app.translator.trans('core.admin.appearance.colors_secondary_label'),
|
||||||
})}
|
})}
|
||||||
</div>,
|
</div>,
|
||||||
70
|
70
|
@@ -2,24 +2,27 @@ import app from '../../admin/app';
|
|||||||
import FieldSet from '../../common/components/FieldSet';
|
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 Mithril from 'mithril';
|
||||||
|
|
||||||
export default class BasicsPage extends AdminPage {
|
export type HomePageItem = { path: string; label: Mithril.Children };
|
||||||
oninit(vnode) {
|
|
||||||
|
export default class BasicsPage<CustomAttrs extends IPageAttrs = IPageAttrs> extends AdminPage<CustomAttrs> {
|
||||||
|
localeOptions: Record<string, string> = {};
|
||||||
|
displayNameOptions: Record<string, string> = {};
|
||||||
|
slugDriverOptions: Record<string, Record<string, string>> = {};
|
||||||
|
|
||||||
|
oninit(vnode: Mithril.Vnode<CustomAttrs, this>) {
|
||||||
super.oninit(vnode);
|
super.oninit(vnode);
|
||||||
|
|
||||||
this.localeOptions = {};
|
Object.keys(app.data.locales).forEach((i) => {
|
||||||
const locales = app.data.locales;
|
this.localeOptions[i] = `${app.data.locales[i]} (${i})`;
|
||||||
for (const i in locales) {
|
});
|
||||||
this.localeOptions[i] = `${locales[i]} (${i})`;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.displayNameOptions = {};
|
app.data.displayNameDrivers.forEach((identifier) => {
|
||||||
const displayNameDrivers = app.data.displayNameDrivers;
|
|
||||||
displayNameDrivers.forEach(function (identifier) {
|
|
||||||
this.displayNameOptions[identifier] = identifier;
|
this.displayNameOptions[identifier] = identifier;
|
||||||
}, this);
|
});
|
||||||
|
|
||||||
this.slugDriverOptions = {};
|
|
||||||
Object.keys(app.data.slugDrivers).forEach((model) => {
|
Object.keys(app.data.slugDrivers).forEach((model) => {
|
||||||
this.slugDriverOptions[model] = {};
|
this.slugDriverOptions[model] = {};
|
||||||
|
|
||||||
@@ -100,6 +103,7 @@ export default class BasicsPage extends AdminPage {
|
|||||||
|
|
||||||
{Object.keys(this.slugDriverOptions).map((model) => {
|
{Object.keys(this.slugDriverOptions).map((model) => {
|
||||||
const options = this.slugDriverOptions[model];
|
const options = this.slugDriverOptions[model];
|
||||||
|
|
||||||
if (Object.keys(options).length > 1) {
|
if (Object.keys(options).length > 1) {
|
||||||
return this.buildSettingComponent({
|
return this.buildSettingComponent({
|
||||||
type: 'select',
|
type: 'select',
|
||||||
@@ -109,6 +113,8 @@ export default class BasicsPage extends AdminPage {
|
|||||||
help: app.translator.trans('core.admin.basics.slug_driver_text', { model }),
|
help: app.translator.trans('core.admin.basics.slug_driver_text', { model }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
})}
|
})}
|
||||||
|
|
||||||
{this.submitButton()}
|
{this.submitButton()}
|
||||||
@@ -119,11 +125,9 @@ export default class BasicsPage extends AdminPage {
|
|||||||
/**
|
/**
|
||||||
* Build a list of options for the default homepage. Each option must be an
|
* Build a list of options for the default homepage. Each option must be an
|
||||||
* object with `path` and `label` properties.
|
* object with `path` and `label` properties.
|
||||||
*
|
|
||||||
* @return {ItemList<{ path: string, label: import('mithril').Children }>}
|
|
||||||
*/
|
*/
|
||||||
homePageItems() {
|
homePageItems() {
|
||||||
const items = new ItemList();
|
const items = new ItemList<HomePageItem>();
|
||||||
|
|
||||||
items.add('allDiscussions', {
|
items.add('allDiscussions', {
|
||||||
path: '/all',
|
path: '/all',
|
@@ -140,7 +140,7 @@ export default class ExtensionPage<Attrs extends ExtensionPageAttrs = ExtensionP
|
|||||||
{settings ? (
|
{settings ? (
|
||||||
<div className="Form">
|
<div className="Form">
|
||||||
{settings.map(this.buildSettingComponent.bind(this))}
|
{settings.map(this.buildSettingComponent.bind(this))}
|
||||||
<div className="Form-group">{this.submitButton(vnode)}</div>
|
<div className="Form-group">{this.submitButton()}</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<h3 className="ExtensionPage-subHeader">{app.translator.trans('core.admin.extension.no_settings')}</h3>
|
<h3 className="ExtensionPage-subHeader">{app.translator.trans('core.admin.extension.no_settings')}</h3>
|
||||||
|
@@ -4,12 +4,30 @@ import Button from '../../common/components/Button';
|
|||||||
import Alert from '../../common/components/Alert';
|
import Alert from '../../common/components/Alert';
|
||||||
import LoadingIndicator from '../../common/components/LoadingIndicator';
|
import LoadingIndicator from '../../common/components/LoadingIndicator';
|
||||||
import AdminPage from './AdminPage';
|
import AdminPage from './AdminPage';
|
||||||
|
import type { IPageAttrs } from '../../common/components/Page';
|
||||||
|
import type { AlertIdentifier } from '../../common/states/AlertManagerState';
|
||||||
|
import type Mithril from 'mithril';
|
||||||
|
import type { SaveSubmitEvent } from './AdminPage';
|
||||||
|
|
||||||
export default class MailPage extends AdminPage {
|
export interface MailSettings {
|
||||||
oninit(vnode) {
|
data: {
|
||||||
|
attributes: {
|
||||||
|
fields: Record<string, any>;
|
||||||
|
sending: boolean;
|
||||||
|
errors: any[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class MailPage<CustomAttrs extends IPageAttrs = IPageAttrs> extends AdminPage<CustomAttrs> {
|
||||||
|
sendingTest = false;
|
||||||
|
status?: { sending: boolean; errors: any };
|
||||||
|
driverFields?: Record<string, any>;
|
||||||
|
testEmailSuccessAlert?: AlertIdentifier;
|
||||||
|
|
||||||
|
oninit(vnode: Mithril.Vnode<CustomAttrs, this>) {
|
||||||
super.oninit(vnode);
|
super.oninit(vnode);
|
||||||
|
|
||||||
this.sendingTest = false;
|
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,14 +46,14 @@ export default class MailPage extends AdminPage {
|
|||||||
this.status = { sending: false, errors: {} };
|
this.status = { sending: false, errors: {} };
|
||||||
|
|
||||||
app
|
app
|
||||||
.request({
|
.request<MailSettings>({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: app.forum.attribute('apiUrl') + '/mail/settings',
|
url: app.forum.attribute('apiUrl') + '/mail/settings',
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
this.driverFields = response['data']['attributes']['fields'];
|
this.driverFields = response.data.attributes.fields;
|
||||||
this.status.sending = response['data']['attributes']['sending'];
|
this.status!.sending = response.data.attributes.sending;
|
||||||
this.status.errors = response['data']['attributes']['errors'];
|
this.status!.errors = response.data.attributes.errors;
|
||||||
|
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
m.redraw();
|
m.redraw();
|
||||||
@@ -47,7 +65,7 @@ export default class MailPage extends AdminPage {
|
|||||||
return <LoadingIndicator />;
|
return <LoadingIndicator />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fields = this.driverFields[this.setting('mail_driver')()];
|
const fields = this.driverFields![this.setting('mail_driver')()];
|
||||||
const fieldKeys = Object.keys(fields);
|
const fieldKeys = Object.keys(fields);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -60,10 +78,10 @@ export default class MailPage extends AdminPage {
|
|||||||
{this.buildSettingComponent({
|
{this.buildSettingComponent({
|
||||||
type: 'select',
|
type: 'select',
|
||||||
setting: 'mail_driver',
|
setting: 'mail_driver',
|
||||||
options: Object.keys(this.driverFields).reduce((memo, val) => ({ ...memo, [val]: val }), {}),
|
options: Object.keys(this.driverFields!).reduce((memo, val) => ({ ...memo, [val]: val }), {}),
|
||||||
label: app.translator.trans('core.admin.email.driver_heading'),
|
label: app.translator.trans('core.admin.email.driver_heading'),
|
||||||
})}
|
})}
|
||||||
{this.status.sending ||
|
{this.status!.sending ||
|
||||||
Alert.component(
|
Alert.component(
|
||||||
{
|
{
|
||||||
dismissible: false,
|
dismissible: false,
|
||||||
@@ -84,7 +102,7 @@ export default class MailPage extends AdminPage {
|
|||||||
setting: field,
|
setting: field,
|
||||||
options: fieldInfo,
|
options: fieldInfo,
|
||||||
}),
|
}),
|
||||||
this.status.errors[field] && <p className="ValidationError">{this.status.errors[field]}</p>,
|
this.status!.errors[field] && <p className="ValidationError">{this.status!.errors[field]}</p>,
|
||||||
];
|
];
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
@@ -93,7 +111,7 @@ export default class MailPage extends AdminPage {
|
|||||||
{this.submitButton()}
|
{this.submitButton()}
|
||||||
|
|
||||||
<FieldSet label={app.translator.trans('core.admin.email.send_test_mail_heading')} className="MailPage-MailSettings">
|
<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>
|
<div className="helpText">{app.translator.trans('core.admin.email.send_test_mail_text', { email: app.session.user!.email() })}</div>
|
||||||
{Button.component(
|
{Button.component(
|
||||||
{
|
{
|
||||||
className: 'Button Button--primary',
|
className: 'Button Button--primary',
|
||||||
@@ -108,10 +126,11 @@ export default class MailPage extends AdminPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sendTestEmail() {
|
sendTestEmail() {
|
||||||
if (this.saving || this.sendingTest) return;
|
if (this.sendingTest) return;
|
||||||
|
|
||||||
this.sendingTest = true;
|
this.sendingTest = true;
|
||||||
app.alerts.dismiss(this.testEmailSuccessAlert);
|
|
||||||
|
if (this.testEmailSuccessAlert) app.alerts.dismiss(this.testEmailSuccessAlert);
|
||||||
|
|
||||||
app
|
app
|
||||||
.request({
|
.request({
|
||||||
@@ -129,7 +148,7 @@ export default class MailPage extends AdminPage {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
saveSettings(e) {
|
saveSettings(e: SaveSubmitEvent) {
|
||||||
super.saveSettings(e).then(this.refresh());
|
return super.saveSettings(e).then(() => this.refresh());
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -20,8 +20,8 @@ export default class PermissionsPage extends AdminPage {
|
|||||||
return [
|
return [
|
||||||
<div className="PermissionsPage-groups">
|
<div className="PermissionsPage-groups">
|
||||||
{app.store
|
{app.store
|
||||||
.all('groups')
|
.all<Group>('groups')
|
||||||
.filter((group) => [Group.GUEST_ID, Group.MEMBER_ID].indexOf(group.id()) === -1)
|
.filter((group) => [Group.GUEST_ID, Group.MEMBER_ID].indexOf(group.id()!) === -1)
|
||||||
.map((group) => (
|
.map((group) => (
|
||||||
<button className="Button Group" onclick={() => app.modal.show(EditGroupModal, { group })}>
|
<button className="Button Group" onclick={() => app.modal.show(EditGroupModal, { group })}>
|
||||||
{GroupBadge.component({
|
{GroupBadge.component({
|
@@ -1,16 +1,18 @@
|
|||||||
import app from '../../forum/app';
|
import app from '../../forum/app';
|
||||||
import Page from '../../common/components/Page';
|
import Page, { IPageAttrs } from '../../common/components/Page';
|
||||||
import NotificationList from './NotificationList';
|
import NotificationList from './NotificationList';
|
||||||
|
import type Mithril from 'mithril';
|
||||||
|
import extractText from '../../common/utils/extractText';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `NotificationsPage` component shows the notifications list. It is only
|
* The `NotificationsPage` component shows the notifications list. It is only
|
||||||
* used on mobile devices where the notifications dropdown is within the drawer.
|
* used on mobile devices where the notifications dropdown is within the drawer.
|
||||||
*/
|
*/
|
||||||
export default class NotificationsPage extends Page {
|
export default class NotificationsPage<CustomAttrs extends IPageAttrs = IPageAttrs> extends Page<CustomAttrs> {
|
||||||
oninit(vnode) {
|
oninit(vnode: Mithril.Vnode<CustomAttrs, this>) {
|
||||||
super.oninit(vnode);
|
super.oninit(vnode);
|
||||||
|
|
||||||
app.history.push('notifications');
|
app.history.push('notifications', extractText(app.translator.trans('core.forum.notifications.title')));
|
||||||
|
|
||||||
app.notifications.load();
|
app.notifications.load();
|
||||||
|
|
@@ -1,5 +1,5 @@
|
|||||||
import app from '../../forum/app';
|
import app from '../../forum/app';
|
||||||
import UserPage from './UserPage';
|
import UserPage, { IUserPageAttrs } from './UserPage';
|
||||||
import ItemList from '../../common/utils/ItemList';
|
import ItemList from '../../common/utils/ItemList';
|
||||||
import Switch from '../../common/components/Switch';
|
import Switch from '../../common/components/Switch';
|
||||||
import Button from '../../common/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
@@ -8,18 +8,22 @@ import NotificationGrid from './NotificationGrid';
|
|||||||
import ChangePasswordModal from './ChangePasswordModal';
|
import ChangePasswordModal from './ChangePasswordModal';
|
||||||
import ChangeEmailModal from './ChangeEmailModal';
|
import ChangeEmailModal from './ChangeEmailModal';
|
||||||
import listItems from '../../common/helpers/listItems';
|
import listItems from '../../common/helpers/listItems';
|
||||||
|
import extractText from '../../common/utils/extractText';
|
||||||
|
import type Mithril from 'mithril';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `SettingsPage` component displays the user's settings control panel, in
|
* The `SettingsPage` component displays the user's settings control panel, in
|
||||||
* the context of their user profile.
|
* the context of their user profile.
|
||||||
*/
|
*/
|
||||||
export default class SettingsPage extends UserPage {
|
export default class SettingsPage<CustomAttrs extends IUserPageAttrs = IUserPageAttrs> extends UserPage<CustomAttrs> {
|
||||||
oninit(vnode) {
|
discloseOnlineLoading?: boolean;
|
||||||
|
|
||||||
|
oninit(vnode: Mithril.Vnode<CustomAttrs, this>) {
|
||||||
super.oninit(vnode);
|
super.oninit(vnode);
|
||||||
|
|
||||||
this.show(app.session.user);
|
this.show(app.session.user!);
|
||||||
|
|
||||||
app.setTitle(app.translator.trans('core.forum.settings.title'));
|
app.setTitle(extractText(app.translator.trans('core.forum.settings.title')));
|
||||||
}
|
}
|
||||||
|
|
||||||
content() {
|
content() {
|
||||||
@@ -32,17 +36,17 @@ export default class SettingsPage extends UserPage {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Build an item list for the user's settings controls.
|
* Build an item list for the user's settings controls.
|
||||||
*
|
|
||||||
* @return {ItemList<import('mithril').Children>}
|
|
||||||
*/
|
*/
|
||||||
settingsItems() {
|
settingsItems() {
|
||||||
const items = new ItemList();
|
const items = new ItemList<Mithril.Children>();
|
||||||
|
|
||||||
['account', 'notifications', 'privacy'].forEach((section) => {
|
['account', 'notifications', 'privacy'].forEach((section) => {
|
||||||
|
const sectionItems = `${section}Items` as 'accountItems' | 'notificationsItems' | 'privacyItems';
|
||||||
|
|
||||||
items.add(
|
items.add(
|
||||||
section,
|
section,
|
||||||
<FieldSet className={`Settings-${section}`} label={app.translator.trans(`core.forum.settings.${section}_heading`)}>
|
<FieldSet className={`Settings-${section}`} label={app.translator.trans(`core.forum.settings.${section}_heading`)}>
|
||||||
{this[`${section}Items`]().toArray()}
|
{this[sectionItems]().toArray()}
|
||||||
</FieldSet>
|
</FieldSet>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -52,11 +56,9 @@ export default class SettingsPage extends UserPage {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Build an item list for the user's account settings.
|
* Build an item list for the user's account settings.
|
||||||
*
|
|
||||||
* @return {ItemList<import('mithril').Children>}
|
|
||||||
*/
|
*/
|
||||||
accountItems() {
|
accountItems() {
|
||||||
const items = new ItemList();
|
const items = new ItemList<Mithril.Children>();
|
||||||
|
|
||||||
items.add(
|
items.add(
|
||||||
'changePassword',
|
'changePassword',
|
||||||
@@ -77,11 +79,9 @@ export default class SettingsPage extends UserPage {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Build an item list for the user's notification settings.
|
* Build an item list for the user's notification settings.
|
||||||
*
|
|
||||||
* @return {ItemList<import('mithril').Children>}
|
|
||||||
*/
|
*/
|
||||||
notificationsItems() {
|
notificationsItems() {
|
||||||
const items = new ItemList();
|
const items = new ItemList<Mithril.Children>();
|
||||||
|
|
||||||
items.add('notificationGrid', <NotificationGrid user={this.user} />);
|
items.add('notificationGrid', <NotificationGrid user={this.user} />);
|
||||||
|
|
||||||
@@ -90,20 +90,18 @@ export default class SettingsPage extends UserPage {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Build an item list for the user's privacy settings.
|
* Build an item list for the user's privacy settings.
|
||||||
*
|
|
||||||
* @return {ItemList<import('mithril').Children>}
|
|
||||||
*/
|
*/
|
||||||
privacyItems() {
|
privacyItems() {
|
||||||
const items = new ItemList();
|
const items = new ItemList<Mithril.Children>();
|
||||||
|
|
||||||
items.add(
|
items.add(
|
||||||
'discloseOnline',
|
'discloseOnline',
|
||||||
<Switch
|
<Switch
|
||||||
state={this.user.preferences().discloseOnline}
|
state={this.user!.preferences()?.discloseOnline}
|
||||||
onchange={(value) => {
|
onchange={(value: boolean) => {
|
||||||
this.discloseOnlineLoading = true;
|
this.discloseOnlineLoading = true;
|
||||||
|
|
||||||
this.user.savePreferences({ discloseOnline: value }).then(() => {
|
this.user!.savePreferences({ discloseOnline: value }).then(() => {
|
||||||
this.discloseOnlineLoading = false;
|
this.discloseOnlineLoading = false;
|
||||||
m.redraw();
|
m.redraw();
|
||||||
});
|
});
|
@@ -11,6 +11,8 @@ core:
|
|||||||
appearance:
|
appearance:
|
||||||
colored_header_label: Colored Header
|
colored_header_label: Colored Header
|
||||||
colors_heading: Colors
|
colors_heading: Colors
|
||||||
|
colors_primary_label: Primary Color
|
||||||
|
colors_secondary_label: Secondary Color
|
||||||
colors_text: "Choose two colors to theme your forum with. The first will be used as a highlight color, while the second will be used to style background elements."
|
colors_text: "Choose two colors to theme your forum with. The first will be used as a highlight color, while the second will be used to style background elements."
|
||||||
custom_footer_heading: Custom Footer
|
custom_footer_heading: Custom Footer
|
||||||
custom_footer_text: => core.ref.custom_footer_text
|
custom_footer_text: => core.ref.custom_footer_text
|
||||||
|
Reference in New Issue
Block a user