mirror of
https://github.com/flarum/core.git
synced 2025-08-04 23:47:32 +02:00
chore: extract FormModal
from Modal
(#3922)
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import app from 'flarum/forum/app';
|
import app from 'flarum/forum/app';
|
||||||
import Modal from 'flarum/common/components/Modal';
|
import FormModal from 'flarum/common/components/FormModal';
|
||||||
import Form from 'flarum/common/components/Form';
|
import Form from 'flarum/common/components/Form';
|
||||||
import Button from 'flarum/common/components/Button';
|
import Button from 'flarum/common/components/Button';
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ import Stream from 'flarum/common/utils/Stream';
|
|||||||
import withAttr from 'flarum/common/utils/withAttr';
|
import withAttr from 'flarum/common/utils/withAttr';
|
||||||
import ItemList from 'flarum/common/utils/ItemList';
|
import ItemList from 'flarum/common/utils/ItemList';
|
||||||
|
|
||||||
export default class FlagPostModal extends Modal {
|
export default class FlagPostModal extends FormModal {
|
||||||
oninit(vnode) {
|
oninit(vnode) {
|
||||||
super.oninit(vnode);
|
super.oninit(vnode);
|
||||||
|
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
import app from 'flarum/forum/app';
|
import app from 'flarum/forum/app';
|
||||||
import Modal from 'flarum/common/components/Modal';
|
import FormModal from 'flarum/common/components/FormModal';
|
||||||
import Button from 'flarum/common/components/Button';
|
import Button from 'flarum/common/components/Button';
|
||||||
import Stream from 'flarum/common/utils/Stream';
|
import Stream from 'flarum/common/utils/Stream';
|
||||||
import Form from '@flarum/core/src/common/components/Form';
|
import Form from '@flarum/core/src/common/components/Form';
|
||||||
|
|
||||||
export default class NicknameModal extends Modal {
|
export default class NicknameModal extends FormModal {
|
||||||
oninit(vnode) {
|
oninit(vnode) {
|
||||||
super.oninit(vnode);
|
super.oninit(vnode);
|
||||||
this.nickname = Stream(app.session.user.displayName());
|
this.nickname = Stream(app.session.user.displayName());
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import app from 'flarum/admin/app';
|
import app from 'flarum/admin/app';
|
||||||
import ItemList from 'flarum/common/utils/ItemList';
|
import ItemList from 'flarum/common/utils/ItemList';
|
||||||
import generateElementId from 'flarum/admin/utils/generateElementId';
|
import generateElementId from 'flarum/admin/utils/generateElementId';
|
||||||
import Modal, { IInternalModalAttrs } from 'flarum/common/components/Modal';
|
import FormModal, { IFormModalAttrs } from 'flarum/common/components/FormModal';
|
||||||
|
|
||||||
import Mithril from 'mithril';
|
import Mithril from 'mithril';
|
||||||
import Button from 'flarum/common/components/Button';
|
import Button from 'flarum/common/components/Button';
|
||||||
@@ -22,7 +22,7 @@ export interface IDateSelection {
|
|||||||
end: number;
|
end: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IStatisticsWidgetDateSelectionModalAttrs extends IInternalModalAttrs {
|
export interface IStatisticsWidgetDateSelectionModalAttrs extends IFormModalAttrs {
|
||||||
onModalSubmit: (dates: IDateSelection) => void;
|
onModalSubmit: (dates: IDateSelection) => void;
|
||||||
value?: IDateSelection;
|
value?: IDateSelection;
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,7 @@ interface IStatisticsWidgetDateSelectionModalState {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class StatisticsWidgetDateSelectionModal extends Modal<IStatisticsWidgetDateSelectionModalAttrs> {
|
export default class StatisticsWidgetDateSelectionModal extends FormModal<IStatisticsWidgetDateSelectionModalAttrs> {
|
||||||
/* @ts-expect-error core typings don't allow us to set the type of the state attr :( */
|
/* @ts-expect-error core typings don't allow us to set the type of the state attr :( */
|
||||||
state: IStatisticsWidgetDateSelectionModalState = {
|
state: IStatisticsWidgetDateSelectionModalState = {
|
||||||
inputs: {
|
inputs: {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import app from 'flarum/forum/app';
|
import app from 'flarum/forum/app';
|
||||||
import Modal from 'flarum/common/components/Modal';
|
import FormModal from 'flarum/common/components/FormModal';
|
||||||
import Button from 'flarum/common/components/Button';
|
import Button from 'flarum/common/components/Button';
|
||||||
import Stream from 'flarum/common/utils/Stream';
|
import Stream from 'flarum/common/utils/Stream';
|
||||||
import withAttr from 'flarum/common/utils/withAttr';
|
import withAttr from 'flarum/common/utils/withAttr';
|
||||||
@@ -9,7 +9,7 @@ import { getPermanentSuspensionDate } from '../helpers/suspensionHelper';
|
|||||||
import Form from '@flarum/core/src/common/components/Form';
|
import Form from '@flarum/core/src/common/components/Form';
|
||||||
import FieldSet from '@flarum/core/src/common/components/FieldSet';
|
import FieldSet from '@flarum/core/src/common/components/FieldSet';
|
||||||
|
|
||||||
export default class SuspendUserModal extends Modal {
|
export default class SuspendUserModal extends FormModal {
|
||||||
oninit(vnode) {
|
oninit(vnode) {
|
||||||
super.oninit(vnode);
|
super.oninit(vnode);
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import app from 'flarum/admin/app';
|
import app from 'flarum/admin/app';
|
||||||
import Modal, { IInternalModalAttrs } from 'flarum/common/components/Modal';
|
import FormModal, { IFormModalAttrs } from 'flarum/common/components/FormModal';
|
||||||
import Button from 'flarum/common/components/Button';
|
import Button from 'flarum/common/components/Button';
|
||||||
import ColorPreviewInput from 'flarum/common/components/ColorPreviewInput';
|
import ColorPreviewInput from 'flarum/common/components/ColorPreviewInput';
|
||||||
import ItemList from 'flarum/common/utils/ItemList';
|
import ItemList from 'flarum/common/utils/ItemList';
|
||||||
@@ -12,7 +12,7 @@ import type Mithril from 'mithril';
|
|||||||
import tagLabel from '../../common/helpers/tagLabel';
|
import tagLabel from '../../common/helpers/tagLabel';
|
||||||
import type Tag from '../../common/models/Tag';
|
import type Tag from '../../common/models/Tag';
|
||||||
|
|
||||||
export interface EditTagModalAttrs extends IInternalModalAttrs {
|
export interface EditTagModalAttrs extends IFormModalAttrs {
|
||||||
primary?: boolean;
|
primary?: boolean;
|
||||||
model?: Tag;
|
model?: Tag;
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ export interface EditTagModalAttrs extends IInternalModalAttrs {
|
|||||||
* The `EditTagModal` component shows a modal dialog which allows the user
|
* The `EditTagModal` component shows a modal dialog which allows the user
|
||||||
* to create or edit a tag.
|
* to create or edit a tag.
|
||||||
*/
|
*/
|
||||||
export default class EditTagModal extends Modal<EditTagModalAttrs> {
|
export default class EditTagModal extends FormModal<EditTagModalAttrs> {
|
||||||
tag!: Tag;
|
tag!: Tag;
|
||||||
|
|
||||||
name!: Stream<string>;
|
name!: Stream<string>;
|
||||||
|
@@ -5,7 +5,7 @@ import extractText from 'flarum/common/utils/extractText';
|
|||||||
import highlight from 'flarum/common/helpers/highlight';
|
import highlight from 'flarum/common/helpers/highlight';
|
||||||
import KeyboardNavigatable from 'flarum/common/utils/KeyboardNavigatable';
|
import KeyboardNavigatable from 'flarum/common/utils/KeyboardNavigatable';
|
||||||
import LoadingIndicator from 'flarum/common/components/LoadingIndicator';
|
import LoadingIndicator from 'flarum/common/components/LoadingIndicator';
|
||||||
import Modal from 'flarum/common/components/Modal';
|
import FormModal from 'flarum/common/components/FormModal';
|
||||||
import Stream from 'flarum/common/utils/Stream';
|
import Stream from 'flarum/common/utils/Stream';
|
||||||
|
|
||||||
import sortTags from '../utils/sortTags';
|
import sortTags from '../utils/sortTags';
|
||||||
@@ -14,7 +14,7 @@ import tagIcon from '../helpers/tagIcon';
|
|||||||
import ToggleButton from '../../forum/components/ToggleButton';
|
import ToggleButton from '../../forum/components/ToggleButton';
|
||||||
|
|
||||||
import type Tag from '../models/Tag';
|
import type Tag from '../models/Tag';
|
||||||
import type { IInternalModalAttrs } from 'flarum/common/components/Modal';
|
import type { IFormModalAttrs } from 'flarum/common/components/FormModal';
|
||||||
import type Mithril from 'mithril';
|
import type Mithril from 'mithril';
|
||||||
|
|
||||||
export interface ITagSelectionModalLimits {
|
export interface ITagSelectionModalLimits {
|
||||||
@@ -34,7 +34,7 @@ export interface ITagSelectionModalLimits {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITagSelectionModalAttrs extends IInternalModalAttrs {
|
export interface ITagSelectionModalAttrs extends IFormModalAttrs {
|
||||||
/** Custom modal className to use. */
|
/** Custom modal className to use. */
|
||||||
className?: string;
|
className?: string;
|
||||||
/** Modal title, defaults to 'Choose Tags'. */
|
/** Modal title, defaults to 'Choose Tags'. */
|
||||||
@@ -64,7 +64,7 @@ export type ITagSelectionModalState = undefined;
|
|||||||
export default class TagSelectionModal<
|
export default class TagSelectionModal<
|
||||||
CustomAttrs extends ITagSelectionModalAttrs = ITagSelectionModalAttrs,
|
CustomAttrs extends ITagSelectionModalAttrs = ITagSelectionModalAttrs,
|
||||||
CustomState extends ITagSelectionModalState = ITagSelectionModalState
|
CustomState extends ITagSelectionModalState = ITagSelectionModalState
|
||||||
> extends Modal<CustomAttrs, CustomState> {
|
> extends FormModal<CustomAttrs, CustomState> {
|
||||||
protected loading = true;
|
protected loading = true;
|
||||||
protected tags!: Tag[];
|
protected tags!: Tag[];
|
||||||
protected selected: Tag[] = [];
|
protected selected: Tag[] = [];
|
||||||
@@ -108,7 +108,7 @@ export default class TagSelectionModal<
|
|||||||
.onSelect(this.select.bind(this))
|
.onSelect(this.select.bind(this))
|
||||||
.onRemove(() => this.selected.splice(this.selected.length - 1, 1));
|
.onRemove(() => this.selected.splice(this.selected.length - 1, 1));
|
||||||
|
|
||||||
app.tagList.load(['parent']).then((tags) => {
|
app.tagList.load(['parent']).then((tags: Tag[]) => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
|
||||||
if (this.attrs.selectableTags) {
|
if (this.attrs.selectableTags) {
|
||||||
|
@@ -21,7 +21,7 @@ export default class TagListState {
|
|||||||
async query(includes: string[] = []): Promise<Tag[]> {
|
async query(includes: string[] = []): Promise<Tag[]> {
|
||||||
this.loadedIncludes ??= new Set();
|
this.loadedIncludes ??= new Set();
|
||||||
|
|
||||||
return app.store.find<Tag[]>('tags', { include: includes.join(',') }).then((val) => {
|
return app.store.find<Tag[]>('tags', { include: includes.join(',') }).then((val: Tag) => {
|
||||||
includes.forEach((include) => this.loadedIncludes!.add(include));
|
includes.forEach((include) => this.loadedIncludes!.add(include));
|
||||||
return val;
|
return val;
|
||||||
});
|
});
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import app from '../../admin/app';
|
import app from '../../admin/app';
|
||||||
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
|
import FormModal, { IFormModalAttrs } from '../../common/components/FormModal';
|
||||||
import Button from '../../common/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import extractText from '../../common/utils/extractText';
|
import extractText from '../../common/utils/extractText';
|
||||||
import ItemList from '../../common/utils/ItemList';
|
import ItemList from '../../common/utils/ItemList';
|
||||||
@@ -9,7 +9,7 @@ import Switch from '../../common/components/Switch';
|
|||||||
import { generateRandomString } from '../../common/utils/string';
|
import { generateRandomString } from '../../common/utils/string';
|
||||||
import Form from '../../common/components/Form';
|
import Form from '../../common/components/Form';
|
||||||
|
|
||||||
export interface ICreateUserModalAttrs extends IInternalModalAttrs {
|
export interface ICreateUserModalAttrs extends IFormModalAttrs {
|
||||||
username?: string;
|
username?: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
password?: string;
|
password?: string;
|
||||||
@@ -24,7 +24,7 @@ export type SignupBody = {
|
|||||||
password: string;
|
password: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class CreateUserModal<CustomAttrs extends ICreateUserModalAttrs = ICreateUserModalAttrs> extends Modal<CustomAttrs> {
|
export default class CreateUserModal<CustomAttrs extends ICreateUserModalAttrs = ICreateUserModalAttrs> extends FormModal<CustomAttrs> {
|
||||||
/**
|
/**
|
||||||
* The value of the username input.
|
* The value of the username input.
|
||||||
*/
|
*/
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import app from '../../admin/app';
|
import app from '../../admin/app';
|
||||||
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
|
import FormModal, { IFormModalAttrs } from '../../common/components/FormModal';
|
||||||
import Button from '../../common/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import Badge from '../../common/components/Badge';
|
import Badge from '../../common/components/Badge';
|
||||||
import Group from '../../common/models/Group';
|
import Group from '../../common/models/Group';
|
||||||
@@ -11,7 +11,7 @@ import extractText from '../../common/utils/extractText';
|
|||||||
import ColorPreviewInput from '../../common/components/ColorPreviewInput';
|
import ColorPreviewInput from '../../common/components/ColorPreviewInput';
|
||||||
import Form from '../../common/components/Form';
|
import Form from '../../common/components/Form';
|
||||||
|
|
||||||
export interface IEditGroupModalAttrs extends IInternalModalAttrs {
|
export interface IEditGroupModalAttrs extends IFormModalAttrs {
|
||||||
group?: Group;
|
group?: Group;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ export interface IEditGroupModalAttrs extends IInternalModalAttrs {
|
|||||||
* The `EditGroupModal` component shows a modal dialog which allows the user
|
* The `EditGroupModal` component shows a modal dialog which allows the user
|
||||||
* to create or edit a group.
|
* to create or edit a group.
|
||||||
*/
|
*/
|
||||||
export default class EditGroupModal<CustomAttrs extends IEditGroupModalAttrs = IEditGroupModalAttrs> extends Modal<CustomAttrs> {
|
export default class EditGroupModal<CustomAttrs extends IEditGroupModalAttrs = IEditGroupModalAttrs> extends FormModal<CustomAttrs> {
|
||||||
group!: Group;
|
group!: Group;
|
||||||
nameSingular!: Stream<string>;
|
nameSingular!: Stream<string>;
|
||||||
namePlural!: Stream<string>;
|
namePlural!: Stream<string>;
|
||||||
|
@@ -19,8 +19,4 @@ export default class LoadingModal<ModalAttrs extends ILoadingModalAttrs = ILoadi
|
|||||||
content() {
|
content() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
onsubmit(e: Event): void {
|
|
||||||
throw new Error('LoadingModal should not throw errors.');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import app from '../../admin/app';
|
import app from '../../admin/app';
|
||||||
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
|
import FormModal, { IFormModalAttrs } from '../../common/components/FormModal';
|
||||||
import Button from '../../common/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import Stream from '../../common/utils/Stream';
|
import Stream from '../../common/utils/Stream';
|
||||||
import saveSettings from '../utils/saveSettings';
|
import saveSettings from '../utils/saveSettings';
|
||||||
@@ -7,9 +7,9 @@ import Mithril from 'mithril';
|
|||||||
import { MutableSettings, SettingValue } from './AdminPage';
|
import { MutableSettings, SettingValue } from './AdminPage';
|
||||||
import Form from '../../common/components/Form';
|
import Form from '../../common/components/Form';
|
||||||
|
|
||||||
export interface ISettingsModalAttrs extends IInternalModalAttrs {}
|
export interface ISettingsModalAttrs extends IFormModalAttrs {}
|
||||||
|
|
||||||
export default abstract class SettingsModal<CustomAttrs extends ISettingsModalAttrs = ISettingsModalAttrs> extends Modal<CustomAttrs> {
|
export default abstract class SettingsModal<CustomAttrs extends ISettingsModalAttrs = ISettingsModalAttrs> extends FormModal<CustomAttrs> {
|
||||||
settings: MutableSettings = {};
|
settings: MutableSettings = {};
|
||||||
loading: boolean = false;
|
loading: boolean = false;
|
||||||
|
|
||||||
|
@@ -65,6 +65,7 @@ import './components/SelectDropdown';
|
|||||||
import './components/ModalManager';
|
import './components/ModalManager';
|
||||||
import './components/Button';
|
import './components/Button';
|
||||||
import './components/Modal';
|
import './components/Modal';
|
||||||
|
import './components/FormModal';
|
||||||
import './components/GroupBadge';
|
import './components/GroupBadge';
|
||||||
import './components/TextEditor';
|
import './components/TextEditor';
|
||||||
import './components/TextEditorButton';
|
import './components/TextEditorButton';
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import app from '../../common/app';
|
import app from '../../common/app';
|
||||||
import Modal, { IInternalModalAttrs } from './Modal';
|
import FormModal, { IFormModalAttrs } from '../../common/components/FormModal';
|
||||||
import Button from './Button';
|
import Button from './Button';
|
||||||
import GroupBadge from './GroupBadge';
|
import GroupBadge from './GroupBadge';
|
||||||
import Group from '../models/Group';
|
import Group from '../models/Group';
|
||||||
@@ -11,11 +11,11 @@ import type User from '../models/User';
|
|||||||
import type { SaveAttributes, SaveRelationships } from '../Model';
|
import type { SaveAttributes, SaveRelationships } from '../Model';
|
||||||
import Form from './Form';
|
import Form from './Form';
|
||||||
|
|
||||||
export interface IEditUserModalAttrs extends IInternalModalAttrs {
|
export interface IEditUserModalAttrs extends IFormModalAttrs {
|
||||||
user: User;
|
user: User;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class EditUserModal<CustomAttrs extends IEditUserModalAttrs = IEditUserModalAttrs> extends Modal<CustomAttrs> {
|
export default class EditUserModal<CustomAttrs extends IEditUserModalAttrs = IEditUserModalAttrs> extends FormModal<CustomAttrs> {
|
||||||
protected username!: Stream<string>;
|
protected username!: Stream<string>;
|
||||||
protected email!: Stream<string>;
|
protected email!: Stream<string>;
|
||||||
protected isEmailConfirmed!: Stream<boolean>;
|
protected isEmailConfirmed!: Stream<boolean>;
|
||||||
|
51
framework/core/js/src/common/components/FormModal.tsx
Normal file
51
framework/core/js/src/common/components/FormModal.tsx
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import Modal from './Modal';
|
||||||
|
import type { IInternalModalAttrs } from './Modal';
|
||||||
|
import RequestError from '../utils/RequestError';
|
||||||
|
import Mithril from 'mithril';
|
||||||
|
|
||||||
|
export interface IFormModalAttrs extends IInternalModalAttrs {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `FormModal` component displays a modal dialog, wrapped in a form.
|
||||||
|
* Subclasses should implement the `className`, `title`, and `content` methods.
|
||||||
|
*/
|
||||||
|
export default abstract class FormModal<ModalAttrs extends IFormModalAttrs = IFormModalAttrs, CustomState = undefined> extends Modal<
|
||||||
|
ModalAttrs,
|
||||||
|
CustomState
|
||||||
|
> {
|
||||||
|
wrapper(children: Mithril.Children): Mithril.Children {
|
||||||
|
return <form onsubmit={this.onsubmit.bind(this)}>{children}</form>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the modal form's submit event.
|
||||||
|
*/
|
||||||
|
onsubmit(e: SubmitEvent): void {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback executed when the modal is shown and ready to be interacted with.
|
||||||
|
*
|
||||||
|
* @remark Focuses the first input in the modal.
|
||||||
|
*/
|
||||||
|
onready(): void {
|
||||||
|
this.$().find('input, select, textarea').first().trigger('focus').trigger('select');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows an alert describing an error returned from the API, and gives focus to
|
||||||
|
* the first relevant field involved in the error.
|
||||||
|
*/
|
||||||
|
onerror(error: RequestError): void {
|
||||||
|
this.alertAttrs = error.alert;
|
||||||
|
|
||||||
|
m.redraw();
|
||||||
|
|
||||||
|
if (error.status === 422 && error.response?.errors) {
|
||||||
|
this.$('form [name=' + (error.response.errors as any[])[0].source.pointer.replace('/data/attributes/', '') + ']').trigger('select');
|
||||||
|
} else {
|
||||||
|
this.onready();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -5,7 +5,6 @@ import Button from './Button';
|
|||||||
|
|
||||||
import type Mithril from 'mithril';
|
import type Mithril from 'mithril';
|
||||||
import type ModalManagerState from '../states/ModalManagerState';
|
import type ModalManagerState from '../states/ModalManagerState';
|
||||||
import type RequestError from '../utils/RequestError';
|
|
||||||
import type ModalManager from './ModalManager';
|
import type ModalManager from './ModalManager';
|
||||||
import fireDebugWarning from '../helpers/fireDebugWarning';
|
import fireDebugWarning from '../helpers/fireDebugWarning';
|
||||||
import classList from '../utils/classList';
|
import classList from '../utils/classList';
|
||||||
@@ -101,25 +100,34 @@ export default abstract class Modal<ModalAttrs extends IInternalModalAttrs = IIn
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{this.wrapper(this.inner())}
|
||||||
<form onsubmit={this.onsubmit.bind(this)}>
|
|
||||||
<div className="Modal-header">
|
|
||||||
<h3 className="App-titleControl App-titleControl--text">{this.title()}</h3>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{!!this.alertAttrs && (
|
|
||||||
<div className="Modal-alert">
|
|
||||||
<Alert {...this.alertAttrs} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{this.content()}
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected wrapper(children: Mithril.Children): Mithril.Children {
|
||||||
|
return <>{children}</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected inner(): Mithril.Children {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="Modal-header">
|
||||||
|
<h3 className="App-titleControl App-titleControl--text">{this.title()}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{!!this.alertAttrs && (
|
||||||
|
<div className="Modal-alert">
|
||||||
|
<Alert {...this.alertAttrs} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{this.content()}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the class name to apply to the modal.
|
* Get the class name to apply to the modal.
|
||||||
*/
|
*/
|
||||||
@@ -135,20 +143,11 @@ export default abstract class Modal<ModalAttrs extends IInternalModalAttrs = IIn
|
|||||||
*/
|
*/
|
||||||
abstract content(): Mithril.Children;
|
abstract content(): Mithril.Children;
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the modal form's submit event.
|
|
||||||
*/
|
|
||||||
onsubmit(e: SubmitEvent): void {
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback executed when the modal is shown and ready to be interacted with.
|
* Callback executed when the modal is shown and ready to be interacted with.
|
||||||
*
|
|
||||||
* @remark Focuses the first input in the modal.
|
|
||||||
*/
|
*/
|
||||||
onready(): void {
|
onready(): void {
|
||||||
this.$().find('input, select, textarea').first().trigger('focus').trigger('select');
|
// ...
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -166,22 +165,6 @@ export default abstract class Modal<ModalAttrs extends IInternalModalAttrs = IIn
|
|||||||
m.redraw();
|
m.redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows an alert describing an error returned from the API, and gives focus to
|
|
||||||
* the first relevant field involved in the error.
|
|
||||||
*/
|
|
||||||
onerror(error: RequestError): void {
|
|
||||||
this.alertAttrs = error.alert;
|
|
||||||
|
|
||||||
m.redraw();
|
|
||||||
|
|
||||||
if (error.status === 422 && error.response?.errors) {
|
|
||||||
this.$('form [name=' + (error.response.errors as any[])[0].source.pointer.replace('/data/attributes/', '') + ']').trigger('select');
|
|
||||||
} else {
|
|
||||||
this.onready();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private get dismissibleOptions(): IDismissibleOptions {
|
private get dismissibleOptions(): IDismissibleOptions {
|
||||||
return (this.constructor as typeof Modal).dismissibleOptions;
|
return (this.constructor as typeof Modal).dismissibleOptions;
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import app from '../../forum/app';
|
import app from '../../forum/app';
|
||||||
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
|
import FormModal, { IFormModalAttrs } from '../../common/components/FormModal';
|
||||||
import Button from '../../common/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import Stream from '../../common/utils/Stream';
|
import Stream from '../../common/utils/Stream';
|
||||||
import type Mithril from 'mithril';
|
import type Mithril from 'mithril';
|
||||||
@@ -11,7 +11,7 @@ import Form from '../../common/components/Form';
|
|||||||
* The `ChangeEmailModal` component shows a modal dialog which allows the user
|
* The `ChangeEmailModal` component shows a modal dialog which allows the user
|
||||||
* to change their email address.
|
* to change their email address.
|
||||||
*/
|
*/
|
||||||
export default class ChangeEmailModal<CustomAttrs extends IInternalModalAttrs = IInternalModalAttrs> extends Modal<CustomAttrs> {
|
export default class ChangeEmailModal<CustomAttrs extends IFormModalAttrs = IFormModalAttrs> extends FormModal<CustomAttrs> {
|
||||||
/**
|
/**
|
||||||
* The value of the email input.
|
* The value of the email input.
|
||||||
*/
|
*/
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import app from '../../forum/app';
|
import app from '../../forum/app';
|
||||||
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
|
import FormModal, { IFormModalAttrs } from '../../common/components/FormModal';
|
||||||
import Button from '../../common/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import Mithril from 'mithril';
|
import Mithril from 'mithril';
|
||||||
import ItemList from '../../common/utils/ItemList';
|
import ItemList from '../../common/utils/ItemList';
|
||||||
@@ -9,7 +9,7 @@ import Form from '../../common/components/Form';
|
|||||||
* The `ChangePasswordModal` component shows a modal dialog which allows the
|
* The `ChangePasswordModal` component shows a modal dialog which allows the
|
||||||
* user to send themself a password reset email.
|
* user to send themself a password reset email.
|
||||||
*/
|
*/
|
||||||
export default class ChangePasswordModal<CustomAttrs extends IInternalModalAttrs = IInternalModalAttrs> extends Modal<CustomAttrs> {
|
export default class ChangePasswordModal<CustomAttrs extends IFormModalAttrs = IFormModalAttrs> extends FormModal<CustomAttrs> {
|
||||||
className() {
|
className() {
|
||||||
return 'ChangePasswordModal Modal--small';
|
return 'ChangePasswordModal Modal--small';
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import app from '../../forum/app';
|
import app from '../../forum/app';
|
||||||
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
|
import FormModal, { IFormModalAttrs } from '../../common/components/FormModal';
|
||||||
import Button from '../../common/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import extractText from '../../common/utils/extractText';
|
import extractText from '../../common/utils/extractText';
|
||||||
import Stream from '../../common/utils/Stream';
|
import Stream from '../../common/utils/Stream';
|
||||||
@@ -8,7 +8,7 @@ import RequestError from '../../common/utils/RequestError';
|
|||||||
import ItemList from '../../common/utils/ItemList';
|
import ItemList from '../../common/utils/ItemList';
|
||||||
import Form from '../../common/components/Form';
|
import Form from '../../common/components/Form';
|
||||||
|
|
||||||
export interface IForgotPasswordModalAttrs extends IInternalModalAttrs {
|
export interface IForgotPasswordModalAttrs extends IFormModalAttrs {
|
||||||
email?: string;
|
email?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ export interface IForgotPasswordModalAttrs extends IInternalModalAttrs {
|
|||||||
* The `ForgotPasswordModal` component displays a modal which allows the user to
|
* The `ForgotPasswordModal` component displays a modal which allows the user to
|
||||||
* enter their email address and request a link to reset their password.
|
* enter their email address and request a link to reset their password.
|
||||||
*/
|
*/
|
||||||
export default class ForgotPasswordModal<CustomAttrs extends IForgotPasswordModalAttrs = IForgotPasswordModalAttrs> extends Modal<CustomAttrs> {
|
export default class ForgotPasswordModal<CustomAttrs extends IForgotPasswordModalAttrs = IForgotPasswordModalAttrs> extends FormModal<CustomAttrs> {
|
||||||
/**
|
/**
|
||||||
* The value of the email input.
|
* The value of the email input.
|
||||||
*/
|
*/
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import app from '../../forum/app';
|
import app from '../../forum/app';
|
||||||
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
|
import FormModal, { IFormModalAttrs } from '../../common/components/FormModal';
|
||||||
import Button from '../../common/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import LogInButtons from './LogInButtons';
|
import LogInButtons from './LogInButtons';
|
||||||
import extractText from '../../common/utils/extractText';
|
import extractText from '../../common/utils/extractText';
|
||||||
@@ -9,13 +9,13 @@ import type Mithril from 'mithril';
|
|||||||
import RequestError from '../../common/utils/RequestError';
|
import RequestError from '../../common/utils/RequestError';
|
||||||
import type { LoginParams } from '../../common/Session';
|
import type { LoginParams } from '../../common/Session';
|
||||||
|
|
||||||
export interface ILoginModalAttrs extends IInternalModalAttrs {
|
export interface ILoginModalAttrs extends IFormModalAttrs {
|
||||||
identification?: string;
|
identification?: string;
|
||||||
password?: string;
|
password?: string;
|
||||||
remember?: boolean;
|
remember?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class LogInModal<CustomAttrs extends ILoginModalAttrs = ILoginModalAttrs> extends Modal<CustomAttrs> {
|
export default class LogInModal<CustomAttrs extends ILoginModalAttrs = ILoginModalAttrs> extends FormModal<CustomAttrs> {
|
||||||
/**
|
/**
|
||||||
* The value of the identification input.
|
* The value of the identification input.
|
||||||
*/
|
*/
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import app from '../app';
|
import app from '../app';
|
||||||
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
|
import FormModal, { IFormModalAttrs } from '../../common/components/FormModal';
|
||||||
import Button from '../../common/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import Stream from '../../common/utils/Stream';
|
import Stream from '../../common/utils/Stream';
|
||||||
import type AccessToken from '../../common/models/AccessToken';
|
import type AccessToken from '../../common/models/AccessToken';
|
||||||
@@ -7,11 +7,11 @@ import type { SaveAttributes } from '../../common/Model';
|
|||||||
import type Mithril from 'mithril';
|
import type Mithril from 'mithril';
|
||||||
import Form from '../../common/components/Form';
|
import Form from '../../common/components/Form';
|
||||||
|
|
||||||
export interface INewAccessTokenModalAttrs extends IInternalModalAttrs {
|
export interface INewAccessTokenModalAttrs extends IFormModalAttrs {
|
||||||
onsuccess: (token: AccessToken) => void;
|
onsuccess: (token: AccessToken) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class NewAccessTokenModal<CustomAttrs extends INewAccessTokenModalAttrs = INewAccessTokenModalAttrs> extends Modal<CustomAttrs> {
|
export default class NewAccessTokenModal<CustomAttrs extends INewAccessTokenModalAttrs = INewAccessTokenModalAttrs> extends FormModal<CustomAttrs> {
|
||||||
protected titleInput = Stream('');
|
protected titleInput = Stream('');
|
||||||
|
|
||||||
className(): string {
|
className(): string {
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
import app from '../../forum/app';
|
import app from '../../forum/app';
|
||||||
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
|
import FormModal, { IFormModalAttrs } from '../../common/components/FormModal';
|
||||||
import Button from '../../common/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import Stream from '../../common/utils/Stream';
|
import Stream from '../../common/utils/Stream';
|
||||||
import Mithril from 'mithril';
|
import Mithril from 'mithril';
|
||||||
import Discussion from '../../common/models/Discussion';
|
import Discussion from '../../common/models/Discussion';
|
||||||
import Form from '../../common/components/Form';
|
import Form from '../../common/components/Form';
|
||||||
|
|
||||||
export interface IRenameDiscussionModalAttrs extends IInternalModalAttrs {
|
export interface IRenameDiscussionModalAttrs extends IFormModalAttrs {
|
||||||
discussion: Discussion;
|
discussion: Discussion;
|
||||||
currentTitle: string;
|
currentTitle: string;
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,9 @@ export interface IRenameDiscussionModalAttrs extends IInternalModalAttrs {
|
|||||||
/**
|
/**
|
||||||
* The 'RenameDiscussionModal' displays a modal dialog with an input to rename a discussion
|
* The 'RenameDiscussionModal' displays a modal dialog with an input to rename a discussion
|
||||||
*/
|
*/
|
||||||
export default class RenameDiscussionModal<CustomAttrs extends IRenameDiscussionModalAttrs = IRenameDiscussionModalAttrs> extends Modal<CustomAttrs> {
|
export default class RenameDiscussionModal<
|
||||||
|
CustomAttrs extends IRenameDiscussionModalAttrs = IRenameDiscussionModalAttrs
|
||||||
|
> extends FormModal<CustomAttrs> {
|
||||||
discussion!: Discussion;
|
discussion!: Discussion;
|
||||||
currentTitle!: string;
|
currentTitle!: string;
|
||||||
newTitle!: Stream<string>;
|
newTitle!: Stream<string>;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import app from '../../forum/app';
|
import app from '../../forum/app';
|
||||||
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
|
import FormModal, { IFormModalAttrs } from '../../common/components/FormModal';
|
||||||
import Button from '../../common/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import LogInButtons from './LogInButtons';
|
import LogInButtons from './LogInButtons';
|
||||||
import extractText from '../../common/utils/extractText';
|
import extractText from '../../common/utils/extractText';
|
||||||
@@ -7,7 +7,7 @@ import ItemList from '../../common/utils/ItemList';
|
|||||||
import Stream from '../../common/utils/Stream';
|
import Stream from '../../common/utils/Stream';
|
||||||
import type Mithril from 'mithril';
|
import type Mithril from 'mithril';
|
||||||
|
|
||||||
export interface ISignupModalAttrs extends IInternalModalAttrs {
|
export interface ISignupModalAttrs extends IFormModalAttrs {
|
||||||
username?: string;
|
username?: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
password?: string;
|
password?: string;
|
||||||
@@ -20,7 +20,7 @@ export type SignupBody = {
|
|||||||
email: string;
|
email: string;
|
||||||
} & ({ token: string } | { password: string });
|
} & ({ token: string } | { password: string });
|
||||||
|
|
||||||
export default class SignUpModal<CustomAttrs extends ISignupModalAttrs = ISignupModalAttrs> extends Modal<CustomAttrs> {
|
export default class SignUpModal<CustomAttrs extends ISignupModalAttrs = ISignupModalAttrs> extends FormModal<CustomAttrs> {
|
||||||
/**
|
/**
|
||||||
* The value of the username input.
|
* The value of the username input.
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user