refactor: convert core modals to TypeScript (#3515)

* refactor: convert core modals to TypeScript
* chore: excplicitly specify return type instead
* chore: `yarn format`

Signed-off-by: Sami Mazouz <ilyasmazouz@gmail.com>
This commit is contained in:
Sami Mazouz 2022-07-13 21:42:45 +01:00 committed by GitHub
parent d86440506d
commit 1af506d4b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 81 additions and 55 deletions

View File

@ -134,8 +134,11 @@ export type SettingsComponentOptions =
*/
export type AdminHeaderAttrs = AdminHeaderOptions & Partial<Omit<Mithril.Attributes, 'class'>>;
export type SettingValue = string;
export type MutableSettings = Record<string, Stream<SettingValue>>;
export default abstract class AdminPage<CustomAttrs extends IPageAttrs = IPageAttrs> extends Page<CustomAttrs> {
settings: Record<string, Stream<string>> = {};
settings: MutableSettings = {};
loading: boolean = false;
view(vnode: Mithril.Vnode<CustomAttrs, this>): Mithril.Children {

View File

@ -1,18 +1,31 @@
import app from '../../admin/app';
import Modal from '../../common/components/Modal';
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
import Button from '../../common/components/Button';
import Badge from '../../common/components/Badge';
import Group from '../../common/models/Group';
import ItemList from '../../common/utils/ItemList';
import Switch from '../../common/components/Switch';
import Stream from '../../common/utils/Stream';
import Mithril from 'mithril';
import extractText from '../../common/utils/extractText';
export interface IEditGroupModalAttrs extends IInternalModalAttrs {
group?: Group;
}
/**
* The `EditGroupModal` component shows a modal dialog which allows the user
* to create or edit a group.
*/
export default class EditGroupModal extends Modal {
oninit(vnode) {
export default class EditGroupModal<CustomAttrs extends IEditGroupModalAttrs = IEditGroupModalAttrs> extends Modal<CustomAttrs> {
group!: Group;
nameSingular!: Stream<string>;
namePlural!: Stream<string>;
icon!: Stream<string>;
color!: Stream<string>;
isHidden!: Stream<boolean>;
oninit(vnode: Mithril.Vnode<CustomAttrs, this>) {
super.oninit(vnode);
this.group = this.attrs.group || app.store.createRecord('groups');
@ -134,7 +147,7 @@ export default class EditGroupModal extends Modal {
};
}
onsubmit(e) {
onsubmit(e: SubmitEvent) {
e.preventDefault();
this.loading = true;
@ -149,7 +162,7 @@ export default class EditGroupModal extends Modal {
}
deleteGroup() {
if (confirm(app.translator.trans('core.admin.edit_group.delete_confirmation'))) {
if (confirm(extractText(app.translator.trans('core.admin.edit_group.delete_confirmation')))) {
this.group.delete().then(() => m.redraw());
this.hide();
}

View File

@ -1,18 +1,18 @@
import app from '../../admin/app';
import Modal from '../../common/components/Modal';
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
import Button from '../../common/components/Button';
import Stream from '../../common/utils/Stream';
import saveSettings from '../utils/saveSettings';
import Mithril from 'mithril';
import { MutableSettings, SettingValue } from './AdminPage';
export default class SettingsModal extends Modal {
oninit(vnode) {
super.oninit(vnode);
export interface ISettingsModalAttrs extends IInternalModalAttrs {}
this.settings = {};
this.loading = false;
}
export default abstract class SettingsModal<CustomAttrs extends ISettingsModalAttrs = ISettingsModalAttrs> extends Modal<CustomAttrs> {
settings: MutableSettings = {};
loading: boolean = false;
form() {
form(): Mithril.Children {
return '';
}
@ -28,7 +28,7 @@ export default class SettingsModal extends Modal {
);
}
submitButton() {
submitButton(): Mithril.Children {
return (
<Button type="submit" className="Button Button--primary" loading={this.loading} disabled={!this.changed()}>
{app.translator.trans('core.admin.settings.submit_button')}
@ -36,14 +36,14 @@ export default class SettingsModal extends Modal {
);
}
setting(key, fallback = '') {
setting(key: string, fallback: string = ''): Stream<SettingValue> {
this.settings[key] = this.settings[key] || Stream(app.data.settings[key] || fallback);
return this.settings[key];
}
dirty() {
const dirty = {};
const dirty: Record<string, SettingValue> = {};
Object.keys(this.settings).forEach((key) => {
const value = this.settings[key]();
@ -60,7 +60,7 @@ export default class SettingsModal extends Modal {
return Object.keys(this.dirty()).length;
}
onsubmit(e) {
onsubmit(e: SubmitEvent) {
e.preventDefault();
this.loading = true;

View File

@ -1,35 +1,34 @@
import app from '../../forum/app';
import Modal from '../../common/components/Modal';
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
import Button from '../../common/components/Button';
import Stream from '../../common/utils/Stream';
import Mithril from 'mithril';
import RequestError from '../../common/utils/RequestError';
/**
* The `ChangeEmailModal` component shows a modal dialog which allows the user
* to change their email address.
*/
export default class ChangeEmailModal extends Modal {
oninit(vnode) {
export default class ChangeEmailModal<CustomAttrs extends IInternalModalAttrs = IInternalModalAttrs> extends Modal<CustomAttrs> {
/**
* The value of the email input.
*/
email!: Stream<string>;
/**
* The value of the password input.
*/
password!: Stream<string>;
/**
* Whether or not the email has been changed successfully.
*/
success: boolean = false;
oninit(vnode: Mithril.Vnode<CustomAttrs, this>) {
super.oninit(vnode);
/**
* Whether or not the email has been changed successfully.
*
* @type {Boolean}
*/
this.success = false;
/**
* The value of the email input.
*
* @type {function}
*/
this.email = Stream(app.session.user.email());
/**
* The value of the password input.
*
* @type {function}
*/
this.email = Stream(app.session.user!.email() || '');
this.password = Stream('');
}
@ -67,7 +66,7 @@ export default class ChangeEmailModal extends Modal {
type="email"
name="email"
className="FormControl"
placeholder={app.session.user.email()}
placeholder={app.session.user!.email()}
bidi={this.email}
disabled={this.loading}
/>
@ -98,12 +97,12 @@ export default class ChangeEmailModal extends Modal {
);
}
onsubmit(e) {
onsubmit(e: SubmitEvent) {
e.preventDefault();
// If the user hasn't actually entered a different email address, we don't
// need to do anything. Woot!
if (this.email() === app.session.user.email()) {
if (this.email() === app.session.user!.email()) {
this.hide();
return;
}
@ -111,8 +110,8 @@ export default class ChangeEmailModal extends Modal {
this.loading = true;
this.alertAttrs = null;
app.session.user
.save(
app.session
.user!.save(
{ email: this.email() },
{
errorHandler: this.onerror.bind(this),
@ -126,8 +125,8 @@ export default class ChangeEmailModal extends Modal {
.then(this.loaded.bind(this));
}
onerror(error) {
if (error.status === 401) {
onerror(error: RequestError) {
if (error.status === 401 && error.alert) {
error.alert.content = app.translator.trans('core.forum.change_email.incorrect_password_message');
}

View File

@ -1,12 +1,12 @@
import app from '../../forum/app';
import Modal from '../../common/components/Modal';
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
import Button from '../../common/components/Button';
/**
* The `ChangePasswordModal` component shows a modal dialog which allows the
* user to send themself a password reset email.
*/
export default class ChangePasswordModal extends Modal {
export default class ChangePasswordModal<CustomAttrs extends IInternalModalAttrs = IInternalModalAttrs> extends Modal<CustomAttrs> {
className() {
return 'ChangePasswordModal Modal--small';
}
@ -35,7 +35,7 @@ export default class ChangePasswordModal extends Modal {
);
}
onsubmit(e) {
onsubmit(e: SubmitEvent) {
e.preventDefault();
this.loading = true;
@ -44,7 +44,7 @@ export default class ChangePasswordModal extends Modal {
.request({
method: 'POST',
url: app.forum.attribute('apiUrl') + '/forgot',
body: { email: app.session.user.email() },
body: { email: app.session.user!.email() },
})
.then(this.hide.bind(this), this.loaded.bind(this));
}

View File

@ -1,13 +1,24 @@
import app from '../../forum/app';
import Modal from '../../common/components/Modal';
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
import Button from '../../common/components/Button';
import Stream from '../../common/utils/Stream';
import Mithril from 'mithril';
import Discussion from '../../common/models/Discussion';
export interface IRenameDiscussionModalAttrs extends IInternalModalAttrs {
discussion: Discussion;
currentTitle: string;
}
/**
* The 'RenameDiscussionModal' displays a modal dialog with an input to rename a discussion
*/
export default class RenameDiscussionModal extends Modal {
oninit(vnode) {
export default class RenameDiscussionModal<CustomAttrs extends IRenameDiscussionModalAttrs = IRenameDiscussionModalAttrs> extends Modal<CustomAttrs> {
discussion!: Discussion;
currentTitle!: string;
newTitle!: Stream<string>;
oninit(vnode: Mithril.Vnode<CustomAttrs, this>) {
super.oninit(vnode);
this.discussion = this.attrs.discussion;
@ -45,7 +56,7 @@ export default class RenameDiscussionModal extends Modal {
);
}
onsubmit(e) {
onsubmit(e: SubmitEvent): Promise<void> | void {
e.preventDefault();
this.loading = true;