mirror of
https://github.com/flarum/core.git
synced 2025-08-13 11:54:32 +02:00
Compare commits
11 Commits
tk/3787-fl
...
as/better-
Author | SHA1 | Date | |
---|---|---|---|
|
b475049269 | ||
|
392b90710c | ||
|
5b43e3cfd7 | ||
|
b9ed71700a | ||
|
6712fef3cf | ||
|
5fa968df2f | ||
|
b88db06a74 | ||
|
d34cf1d925 | ||
|
c6287e1520 | ||
|
222d9ccff7 | ||
|
c9fdd0753f |
@@ -13,6 +13,9 @@ export default class FlagList extends Component {
|
|||||||
this.state = this.attrs.state;
|
this.state = this.attrs.state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
const flags = this.state.cache || [];
|
const flags = this.state.cache || [];
|
||||||
|
|
||||||
|
@@ -24,6 +24,9 @@ export default class FlagPostModal extends Modal {
|
|||||||
return app.translator.trans('flarum-flags.forum.flag_post.title');
|
return app.translator.trans('flarum-flags.forum.flag_post.title');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
content() {
|
content() {
|
||||||
if (this.success) {
|
if (this.success) {
|
||||||
return (
|
return (
|
||||||
|
@@ -11,6 +11,9 @@ export default class FlagsDropdown extends NotificationsDropdown {
|
|||||||
super.initAttrs(attrs);
|
super.initAttrs(attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
getMenu() {
|
getMenu() {
|
||||||
return (
|
return (
|
||||||
<div className={'Dropdown-menu ' + this.attrs.menuClassName} onclick={this.menuClick.bind(this)}>
|
<div className={'Dropdown-menu ' + this.attrs.menuClassName} onclick={this.menuClick.bind(this)}>
|
||||||
|
@@ -18,6 +18,9 @@ export default class FlagsPage extends Page {
|
|||||||
this.bodyClass = 'App--flags';
|
this.bodyClass = 'App--flags';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
return (
|
return (
|
||||||
<div className="FlagsPage">
|
<div className="FlagsPage">
|
||||||
|
@@ -64,7 +64,7 @@ export default class Updater<Attrs> extends Component<Attrs> {
|
|||||||
super.oninit(vnode);
|
super.oninit(vnode);
|
||||||
}
|
}
|
||||||
|
|
||||||
view() {
|
view(): Mithril.Children {
|
||||||
const extensions = this.getExtensionUpdates();
|
const extensions = this.getExtensionUpdates();
|
||||||
let coreUpdate: UpdatedPackage | undefined = this.getCoreUpdate();
|
let coreUpdate: UpdatedPackage | undefined = this.getCoreUpdate();
|
||||||
let core: any;
|
let core: any;
|
||||||
|
@@ -26,7 +26,7 @@ export default class WhyNotModal<Attrs extends WhyNotModalAttrs = WhyNotModalAtt
|
|||||||
this.requestWhyNot();
|
this.requestWhyNot();
|
||||||
}
|
}
|
||||||
|
|
||||||
content() {
|
content(): Mithril.Children {
|
||||||
return <div className="Modal-body">{this.loading ? <LoadingIndicator /> : <pre className="WhyNotModal-contents">{this.whyNot}</pre>}</div>;
|
return <div className="Modal-body">{this.loading ? <LoadingIndicator /> : <pre className="WhyNotModal-contents">{this.whyNot}</pre>}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -46,6 +46,9 @@ export default class StatisticsWidget extends DashboardWidget {
|
|||||||
return 'StatisticsWidget';
|
return 'StatisticsWidget';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
content() {
|
content() {
|
||||||
const thisPeriod = this.periods[this.selectedPeriod];
|
const thisPeriod = this.periods[this.selectedPeriod];
|
||||||
|
|
||||||
|
@@ -7,7 +7,7 @@ import { slug } from 'flarum/common/utils/string';
|
|||||||
import Stream from 'flarum/common/utils/Stream';
|
import Stream from 'flarum/common/utils/Stream';
|
||||||
|
|
||||||
import tagLabel from '../../common/helpers/tagLabel';
|
import tagLabel from '../../common/helpers/tagLabel';
|
||||||
import type Mithril from 'mithril';
|
import Mithril from 'mithril';
|
||||||
import type Tag from '../../common/models/Tag';
|
import type Tag from '../../common/models/Tag';
|
||||||
import extractText from 'flarum/common/utils/extractText';
|
import extractText from 'flarum/common/utils/extractText';
|
||||||
import { ModelIdentifier } from 'flarum/common/Model';
|
import { ModelIdentifier } from 'flarum/common/Model';
|
||||||
@@ -50,13 +50,13 @@ export default class EditTagModal extends Modal<EditTagModalAttrs> {
|
|||||||
return 'EditTagModal Modal--small';
|
return 'EditTagModal Modal--small';
|
||||||
}
|
}
|
||||||
|
|
||||||
title() {
|
title(): Mithril.Children {
|
||||||
return this.name()
|
return this.name()
|
||||||
? tagLabel(app.store.createRecord('tags', { attributes: this.submitData() }))
|
? tagLabel(app.store.createRecord<Tag>('tags', { attributes: this.submitData() }))
|
||||||
: app.translator.trans('flarum-tags.admin.edit_tag.title');
|
: app.translator.trans('flarum-tags.admin.edit_tag.title');
|
||||||
}
|
}
|
||||||
|
|
||||||
content() {
|
content(): Mithril.Children {
|
||||||
return (
|
return (
|
||||||
<div className="Modal-body">
|
<div className="Modal-body">
|
||||||
<div className="Form">
|
<div className="Form">
|
||||||
@@ -67,7 +67,7 @@ export default class EditTagModal extends Modal<EditTagModalAttrs> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fields() {
|
fields() {
|
||||||
const items = new ItemList();
|
const items = new ItemList<Mithril.Children>();
|
||||||
|
|
||||||
items.add('name', <div className="Form-group">
|
items.add('name', <div className="Form-group">
|
||||||
<label>{app.translator.trans('flarum-tags.admin.edit_tag.name_label')}</label>
|
<label>{app.translator.trans('flarum-tags.admin.edit_tag.name_label')}</label>
|
||||||
|
@@ -51,6 +51,9 @@ export default class TagsPage extends ExtensionPage {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
content() {
|
content() {
|
||||||
if (this.loading) {
|
if (this.loading) {
|
||||||
return <LoadingIndicator />;
|
return <LoadingIndicator />;
|
||||||
@@ -63,7 +66,7 @@ export default class TagsPage extends ExtensionPage {
|
|||||||
const maxSecondaryTags = this.setting('flarum-tags.max_secondary_tags', 0);
|
const maxSecondaryTags = this.setting('flarum-tags.max_secondary_tags', 0);
|
||||||
|
|
||||||
const tags = sortTags(app.store.all('tags').filter(tag => !tag.parent()));
|
const tags = sortTags(app.store.all('tags').filter(tag => !tag.parent()));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="TagsContent">
|
<div className="TagsContent">
|
||||||
<div className="TagsContent-list">
|
<div className="TagsContent-list">
|
||||||
|
@@ -1,6 +1,9 @@
|
|||||||
|
import { ComponentAttrs } from 'flarum/common/Component';
|
||||||
import classList from 'flarum/common/utils/classList';
|
import classList from 'flarum/common/utils/classList';
|
||||||
|
import type Tag from '../models/Tag';
|
||||||
|
import type Mithril from 'mithril';
|
||||||
|
|
||||||
export default function tagIcon(tag, attrs = {}, settings = {}) {
|
export default function tagIcon(tag: Tag, attrs: ComponentAttrs = {}, settings: {useColor?: boolean} = {}): Mithril.Children {
|
||||||
const hasIcon = tag && tag.icon();
|
const hasIcon = tag && tag.icon();
|
||||||
const { useColor = true } = settings;
|
const { useColor = true } = settings;
|
||||||
|
|
@@ -1,8 +1,13 @@
|
|||||||
|
import app from 'flarum/common/app';
|
||||||
|
|
||||||
import extract from 'flarum/common/utils/extract';
|
import extract from 'flarum/common/utils/extract';
|
||||||
import Link from 'flarum/common/components/Link';
|
import Link from 'flarum/common/components/Link';
|
||||||
import tagIcon from './tagIcon';
|
import tagIcon from './tagIcon';
|
||||||
|
import type Tag from '../models/Tag';
|
||||||
|
import type { ComponentAttrs } from 'flarum/common/Component';
|
||||||
|
import type Mithril from 'mithril';
|
||||||
|
|
||||||
export default function tagLabel(tag, attrs = {}) {
|
export default function tagLabel(tag?: Tag, attrs: ComponentAttrs = {}): Mithril.Children {
|
||||||
attrs.style = attrs.style || {};
|
attrs.style = attrs.style || {};
|
||||||
attrs.className = 'TagLabel ' + (attrs.className || '');
|
attrs.className = 'TagLabel ' + (attrs.className || '');
|
||||||
|
|
||||||
@@ -28,11 +33,15 @@ export default function tagLabel(tag, attrs = {}) {
|
|||||||
attrs.className += ' untagged';
|
attrs.className += ' untagged';
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
const children = (
|
||||||
m((link ? Link : 'span'), attrs,
|
<span className="TagLabel-text">
|
||||||
<span className="TagLabel-text">
|
|
||||||
{tag && tag.icon() && tagIcon(tag, {}, {useColor: false})} {tagText}
|
{tag && tag.icon() && tagIcon(tag, {}, {useColor: false})} {tagText}
|
||||||
</span>
|
</span>
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (link) {
|
||||||
|
return <Link {...attrs}>{children}</Link>
|
||||||
|
}
|
||||||
|
|
||||||
|
return <span {...attrs}>{children}</span>;
|
||||||
}
|
}
|
@@ -1,15 +1,18 @@
|
|||||||
import extract from 'flarum/common/utils/extract';
|
import extract from 'flarum/common/utils/extract';
|
||||||
import tagLabel from './tagLabel';
|
import tagLabel from './tagLabel';
|
||||||
import sortTags from '../utils/sortTags';
|
import sortTags from '../utils/sortTags';
|
||||||
|
import type Tag from '../models/Tag';
|
||||||
|
import type { ComponentAttrs } from 'flarum/common/Component';
|
||||||
|
import type Mithril from 'mithril';
|
||||||
|
|
||||||
export default function tagsLabel(tags, attrs = {}) {
|
export default function tagsLabel(tags: Tag[], attrs: ComponentAttrs = {}): Mithril.Children {
|
||||||
const children = [];
|
const children = [];
|
||||||
const link = extract(attrs, 'link');
|
const link = extract(attrs, 'link');
|
||||||
|
|
||||||
attrs.className = 'TagsLabel ' + (attrs.className || '');
|
attrs.className = 'TagsLabel ' + (attrs.className || '');
|
||||||
|
|
||||||
if (tags) {
|
if (tags) {
|
||||||
sortTags(tags).forEach(tag => {
|
sortTags(tags).forEach((tag: Tag) => {
|
||||||
if (tag || tags.length === 1) {
|
if (tag || tags.length === 1) {
|
||||||
children.push(tagLabel(tag, {link}));
|
children.push(tagLabel(tag, {link}));
|
||||||
}
|
}
|
@@ -139,6 +139,9 @@ export default class TagDiscussionModal extends Modal<TagDiscussionModalAttrs> {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
content() {
|
content() {
|
||||||
if (this.tagsLoading || !this.tags) {
|
if (this.tagsLoading || !this.tags) {
|
||||||
return <LoadingIndicator />;
|
return <LoadingIndicator />;
|
||||||
|
@@ -2,6 +2,9 @@ import Component from 'flarum/common/Component';
|
|||||||
import tagIcon from '../../common/helpers/tagIcon';
|
import tagIcon from '../../common/helpers/tagIcon';
|
||||||
|
|
||||||
export default class TagHero extends Component {
|
export default class TagHero extends Component {
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
const tag = this.attrs.model;
|
const tag = this.attrs.model;
|
||||||
const color = tag.color();
|
const color = tag.color();
|
||||||
|
@@ -4,6 +4,9 @@ import classList from 'flarum/common/utils/classList';
|
|||||||
import tagIcon from '../../common/helpers/tagIcon';
|
import tagIcon from '../../common/helpers/tagIcon';
|
||||||
|
|
||||||
export default class TagLinkButton extends LinkButton {
|
export default class TagLinkButton extends LinkButton {
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view(vnode) {
|
view(vnode) {
|
||||||
const tag = this.attrs.model;
|
const tag = this.attrs.model;
|
||||||
const active = this.constructor.isActive(this.attrs);
|
const active = this.constructor.isActive(this.attrs);
|
||||||
|
@@ -35,6 +35,9 @@ export default class TagsPage extends Page {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
if (this.loading) {
|
if (this.loading) {
|
||||||
return <LoadingIndicator />;
|
return <LoadingIndicator />;
|
||||||
|
@@ -6,6 +6,9 @@ import classList from 'flarum/common/utils/classList';
|
|||||||
* @TODO move to core
|
* @TODO move to core
|
||||||
*/
|
*/
|
||||||
export default class ToggleButton extends Component {
|
export default class ToggleButton extends Component {
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view(vnode) {
|
view(vnode) {
|
||||||
const { className, isToggled, ...attrs } = this.attrs;
|
const { className, isToggled, ...attrs } = this.attrs;
|
||||||
const icon = isToggled ? 'far fa-check-circle' : 'far fa-circle';
|
const icon = isToggled ? 'far fa-check-circle' : 'far fa-circle';
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
declare module '@askvortsov/rich-icu-message-formatter' {
|
declare module '@askvortsov/rich-icu-message-formatter' {
|
||||||
|
import Mithril from 'mithril';
|
||||||
|
|
||||||
type IValues = Record<string, any>;
|
type IValues = Record<string, any>;
|
||||||
|
|
||||||
type ITypeHandler = (
|
type ITypeHandler = (
|
||||||
@@ -10,16 +12,13 @@ declare module '@askvortsov/rich-icu-message-formatter' {
|
|||||||
) => string;
|
) => string;
|
||||||
type IRichHandler = (tag: any, values: IValues, contents: string) => any;
|
type IRichHandler = (tag: any, values: IValues, contents: string) => any;
|
||||||
|
|
||||||
type ValueOrArray<T> = T | ValueOrArray<T>[];
|
|
||||||
type NestedStringArray = ValueOrArray<string>;
|
|
||||||
|
|
||||||
export class RichMessageFormatter {
|
export class RichMessageFormatter {
|
||||||
locale: string | null;
|
locale: string | null;
|
||||||
constructor(locale: string | null, typeHandlers: Record<string, ITypeHandler>, richHandler: IRichHandler);
|
constructor(locale: string | null, typeHandlers: Record<string, ITypeHandler>, richHandler: IRichHandler);
|
||||||
|
|
||||||
format(message: string, values: IValues): string;
|
format(message: string, values: IValues): string;
|
||||||
process(message: string, values: IValues): NestedStringArray;
|
process(message: string, values: IValues): Mithril.Children;
|
||||||
rich(message: string, values: IValues): NestedStringArray;
|
rich(message: string, values: IValues): Mithril.Children;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mithrilRichHandler(tag: any, values: IValues, contents: string): any;
|
export function mithrilRichHandler(tag: any, values: IValues, contents: string): any;
|
||||||
|
@@ -1,9 +1,15 @@
|
|||||||
import Component from '../../common/Component';
|
import Component, { ComponentAttrs } from '../../common/Component';
|
||||||
import classList from '../../common/utils/classList';
|
import classList from '../../common/utils/classList';
|
||||||
import icon from '../../common/helpers/icon';
|
import icon from '../../common/helpers/icon';
|
||||||
|
import type Mithril from 'mithril';
|
||||||
|
|
||||||
export default class AdminHeader extends Component {
|
export interface IAdminHeaderAttrs extends ComponentAttrs {
|
||||||
view(vnode) {
|
icon: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class AdminHeader<CustomAttrs extends IAdminHeaderAttrs = IAdminHeaderAttrs> extends Component<CustomAttrs> {
|
||||||
|
view(vnode: Mithril.Vnode<CustomAttrs, this>): Mithril.Children {
|
||||||
return [
|
return [
|
||||||
<div className={classList(['AdminHeader', this.attrs.className])}>
|
<div className={classList(['AdminHeader', this.attrs.className])}>
|
||||||
<div className="container">
|
<div className="container">
|
@@ -14,6 +14,9 @@ export default class AdminNav extends Component {
|
|||||||
this.query = Stream('');
|
this.query = Stream('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
return (
|
return (
|
||||||
<SelectDropdown className="AdminNav App-titleControl AdminNav-Main" buttonClassName="Button">
|
<SelectDropdown className="AdminNav App-titleControl AdminNav-Main" buttonClassName="Button">
|
||||||
|
@@ -17,6 +17,9 @@ export default class AppearancePage extends AdminPage {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
content() {
|
content() {
|
||||||
return [
|
return [
|
||||||
<div className="Form">
|
<div className="Form">
|
||||||
|
@@ -38,6 +38,9 @@ export default class BasicsPage extends AdminPage {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
content() {
|
content() {
|
||||||
return [
|
return [
|
||||||
<div className="Form">
|
<div className="Form">
|
||||||
|
@@ -10,6 +10,9 @@ export default class EditCustomCssModal extends SettingsModal {
|
|||||||
return app.translator.trans('core.admin.edit_css.title');
|
return app.translator.trans('core.admin.edit_css.title');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
form() {
|
form() {
|
||||||
return [
|
return [
|
||||||
<p>
|
<p>
|
||||||
|
@@ -10,6 +10,9 @@ export default class EditCustomFooterModal extends SettingsModal {
|
|||||||
return app.translator.trans('core.admin.edit_footer.title');
|
return app.translator.trans('core.admin.edit_footer.title');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
form() {
|
form() {
|
||||||
return [
|
return [
|
||||||
<p>{app.translator.trans('core.admin.edit_footer.customize_text')}</p>,
|
<p>{app.translator.trans('core.admin.edit_footer.customize_text')}</p>,
|
||||||
|
@@ -10,6 +10,9 @@ export default class EditCustomHeaderModal extends SettingsModal {
|
|||||||
return app.translator.trans('core.admin.edit_header.title');
|
return app.translator.trans('core.admin.edit_header.title');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
form() {
|
form() {
|
||||||
return [
|
return [
|
||||||
<p>{app.translator.trans('core.admin.edit_header.customize_text')}</p>,
|
<p>{app.translator.trans('core.admin.edit_header.customize_text')}</p>,
|
||||||
|
@@ -41,6 +41,9 @@ export default class EditGroupModal extends Modal {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
content() {
|
content() {
|
||||||
return (
|
return (
|
||||||
<div className="Modal-body">
|
<div className="Modal-body">
|
||||||
|
@@ -54,7 +54,7 @@ export default class ExtensionPage<Attrs extends ExtensionPageAttrs = ExtensionP
|
|||||||
return this.extension.id + '-Page';
|
return this.extension.id + '-Page';
|
||||||
}
|
}
|
||||||
|
|
||||||
view(vnode: Mithril.VnodeDOM<Attrs, this>) {
|
view(vnode: Mithril.VnodeDOM<Attrs, this>): Mithril.Children {
|
||||||
if (!this.extension) return null;
|
if (!this.extension) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -71,7 +71,7 @@ export default class ExtensionPage<Attrs extends ExtensionPageAttrs = ExtensionP
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
header() {
|
header(): Mithril.Children {
|
||||||
const isEnabled = this.isEnabled();
|
const isEnabled = this.isEnabled();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@@ -106,8 +106,8 @@ export default class ExtensionPage<Attrs extends ExtensionPageAttrs = ExtensionP
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
sections(vnode: Mithril.VnodeDOM<Attrs, this>) {
|
sections(vnode: Mithril.VnodeDOM<Attrs, this>): ItemList<Mithril.Children> {
|
||||||
const items = new ItemList();
|
const items = new ItemList<Mithril.Children>();
|
||||||
|
|
||||||
items.add('content', this.content(vnode));
|
items.add('content', this.content(vnode));
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ export default class ExtensionPage<Attrs extends ExtensionPageAttrs = ExtensionP
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
content(vnode: Mithril.VnodeDOM<Attrs, this>) {
|
content(vnode: Mithril.VnodeDOM<Attrs, this>): Mithril.Children {
|
||||||
const settings = app.extensionData.getSettings(this.extension.id);
|
const settings = app.extensionData.getSettings(this.extension.id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -150,7 +150,7 @@ export default class ExtensionPage<Attrs extends ExtensionPageAttrs = ExtensionP
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
topItems() {
|
topItems(): ItemList<Mithril.Children> {
|
||||||
const items = new ItemList<Mithril.Children>();
|
const items = new ItemList<Mithril.Children>();
|
||||||
|
|
||||||
items.add('version', <span className="ExtensionVersion">{this.extension.version}</span>);
|
items.add('version', <span className="ExtensionVersion">{this.extension.version}</span>);
|
||||||
|
@@ -16,6 +16,9 @@ export default class ExtensionsWidget extends DashboardWidget {
|
|||||||
return 'ExtensionsWidget';
|
return 'ExtensionsWidget';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
content() {
|
content() {
|
||||||
const categories = app.extensionCategories;
|
const categories = app.extensionCategories;
|
||||||
|
|
||||||
@@ -26,6 +29,9 @@ export default class ExtensionsWidget extends DashboardWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
extensionCategory(category) {
|
extensionCategory(category) {
|
||||||
return (
|
return (
|
||||||
<div className="ExtensionList-Category">
|
<div className="ExtensionList-Category">
|
||||||
@@ -35,6 +41,9 @@ export default class ExtensionsWidget extends DashboardWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
extensionWidget(extension) {
|
extensionWidget(extension) {
|
||||||
return (
|
return (
|
||||||
<li className={'ExtensionListItem ' + (!isExtensionEnabled(extension.id) ? 'disabled' : '')}>
|
<li className={'ExtensionListItem ' + (!isExtensionEnabled(extension.id) ? 'disabled' : '')}>
|
||||||
|
@@ -7,6 +7,9 @@ import listItems from '../../common/helpers/listItems';
|
|||||||
* default skin, these are shown just to the right of the forum title.
|
* default skin, these are shown just to the right of the forum title.
|
||||||
*/
|
*/
|
||||||
export default class HeaderPrimary extends Component {
|
export default class HeaderPrimary extends Component {
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
return <ul className="Header-controls">{listItems(this.items().toArray())}</ul>;
|
return <ul className="Header-controls">{listItems(this.items().toArray())}</ul>;
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,9 @@ import listItems from '../../common/helpers/listItems';
|
|||||||
* The `HeaderSecondary` component displays secondary header controls.
|
* The `HeaderSecondary` component displays secondary header controls.
|
||||||
*/
|
*/
|
||||||
export default class HeaderSecondary extends Component {
|
export default class HeaderSecondary extends Component {
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
return <ul className="Header-controls">{listItems(this.items().toArray())}</ul>;
|
return <ul className="Header-controls">{listItems(this.items().toArray())}</ul>;
|
||||||
}
|
}
|
||||||
|
@@ -42,6 +42,9 @@ export default class MailPage extends AdminPage {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
content() {
|
content() {
|
||||||
if (this.loading) {
|
if (this.loading) {
|
||||||
return <LoadingIndicator />;
|
return <LoadingIndicator />;
|
||||||
|
@@ -33,7 +33,7 @@ export interface ScopeItem {
|
|||||||
export interface IPermissionGridAttrs extends ComponentAttrs {}
|
export interface IPermissionGridAttrs extends ComponentAttrs {}
|
||||||
|
|
||||||
export default class PermissionGrid<CustomAttrs extends IPermissionGridAttrs = IPermissionGridAttrs> extends Component<CustomAttrs> {
|
export default class PermissionGrid<CustomAttrs extends IPermissionGridAttrs = IPermissionGridAttrs> extends Component<CustomAttrs> {
|
||||||
view(vnode: Mithril.Vnode<CustomAttrs, this>) {
|
view(vnode: Mithril.Vnode<CustomAttrs, this>): Mithril.Children {
|
||||||
const scopes = this.scopeItems().toArray();
|
const scopes = this.scopeItems().toArray();
|
||||||
|
|
||||||
const permissionCells = (permission: PermissionGridEntry | { children: PermissionGridEntry[] }) => {
|
const permissionCells = (permission: PermissionGridEntry | { children: PermissionGridEntry[] }) => {
|
||||||
|
@@ -16,6 +16,9 @@ export default class PermissionsPage extends AdminPage {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
content() {
|
content() {
|
||||||
return [
|
return [
|
||||||
<div className="PermissionsPage-groups">
|
<div className="PermissionsPage-groups">
|
||||||
|
@@ -38,7 +38,7 @@ export default class ReadmeModal<CustomAttrs extends IReadmeModalAttrs = IReadme
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
content() {
|
content(): Mithril.Children {
|
||||||
const text = app.translator.trans('core.admin.extension.readme.no_readme');
|
const text = app.translator.trans('core.admin.extension.readme.no_readme');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@@ -18,10 +18,16 @@ export default class SessionDropdown extends Dropdown {
|
|||||||
attrs.menuClassName = 'Dropdown-menu--right';
|
attrs.menuClassName = 'Dropdown-menu--right';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view(vnode) {
|
view(vnode) {
|
||||||
return super.view({ ...vnode, children: this.items().toArray() });
|
return super.view({ ...vnode, children: this.items().toArray() });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {import('mithril').Children}
|
||||||
|
*/
|
||||||
getButtonContent() {
|
getButtonContent() {
|
||||||
const user = app.session.user;
|
const user = app.session.user;
|
||||||
|
|
||||||
|
@@ -16,6 +16,9 @@ export default class SettingsModal extends Modal {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
content() {
|
content() {
|
||||||
return (
|
return (
|
||||||
<div className="Modal-body">
|
<div className="Modal-body">
|
||||||
@@ -28,6 +31,9 @@ export default class SettingsModal extends Modal {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
submitButton() {
|
submitButton() {
|
||||||
return (
|
return (
|
||||||
<Button type="submit" className="Button Button--primary" loading={this.loading} disabled={!this.changed()}>
|
<Button type="submit" className="Button Button--primary" loading={this.loading} disabled={!this.changed()}>
|
||||||
|
@@ -11,6 +11,9 @@ export default class StatusWidget extends DashboardWidget {
|
|||||||
return 'StatusWidget';
|
return 'StatusWidget';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
content() {
|
content() {
|
||||||
return <ul>{listItems(this.items().toArray())}</ul>;
|
return <ul>{listItems(this.items().toArray())}</ul>;
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,9 @@ import Button from '../../common/components/Button';
|
|||||||
export default class UploadImageButton extends Button {
|
export default class UploadImageButton extends Button {
|
||||||
loading = false;
|
loading = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view(vnode) {
|
view(vnode) {
|
||||||
this.attrs.loading = this.loading;
|
this.attrs.loading = this.loading;
|
||||||
this.attrs.className = (this.attrs.className || '') + ' Button';
|
this.attrs.className = (this.attrs.className || '') + ' Button';
|
||||||
|
@@ -77,7 +77,7 @@ export default class UserListPage extends AdminPage {
|
|||||||
/**
|
/**
|
||||||
* Component to render.
|
* Component to render.
|
||||||
*/
|
*/
|
||||||
content() {
|
content(): Mithril.Children {
|
||||||
if (typeof this.pageData === 'undefined') {
|
if (typeof this.pageData === 'undefined') {
|
||||||
this.loadPage(0);
|
this.loadPage(0);
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@ export interface AlertAttrs extends ComponentAttrs {
|
|||||||
* some controls, and may be dismissible.
|
* some controls, and may be dismissible.
|
||||||
*/
|
*/
|
||||||
export default class Alert<T extends AlertAttrs = AlertAttrs> extends Component<T> {
|
export default class Alert<T extends AlertAttrs = AlertAttrs> extends Component<T> {
|
||||||
view(vnode: Mithril.VnodeDOM<T, this>) {
|
view(vnode: Mithril.VnodeDOM<T, this>): Mithril.Children {
|
||||||
const attrs = Object.assign({}, this.attrs);
|
const attrs = Object.assign({}, this.attrs);
|
||||||
|
|
||||||
const type = extract(attrs, 'type');
|
const type = extract(attrs, 'type');
|
||||||
|
@@ -1,31 +0,0 @@
|
|||||||
import Component from '../Component';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The `AlertManager` component provides an area in which `Alert` components can
|
|
||||||
* be shown and dismissed.
|
|
||||||
*/
|
|
||||||
export default class AlertManager extends Component {
|
|
||||||
oninit(vnode) {
|
|
||||||
super.oninit(vnode);
|
|
||||||
|
|
||||||
this.state = this.attrs.state;
|
|
||||||
}
|
|
||||||
|
|
||||||
view() {
|
|
||||||
return (
|
|
||||||
<div class="AlertManager">
|
|
||||||
{Object.entries(this.state.getActiveAlerts()).map(([key, alert]) => {
|
|
||||||
const urgent = alert.attrs.type === 'error';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div class="AlertManager-alert" role="alert" aria-live={urgent ? 'assertive' : 'polite'}>
|
|
||||||
<alert.componentClass {...alert.attrs} ondismiss={this.state.dismiss.bind(this.state, key)}>
|
|
||||||
{alert.children}
|
|
||||||
</alert.componentClass>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
39
framework/core/js/src/common/components/AlertManager.tsx
Normal file
39
framework/core/js/src/common/components/AlertManager.tsx
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import type Mithril from 'mithril';
|
||||||
|
import Component, { ComponentAttrs } from '../Component';
|
||||||
|
import type AlertManagerState from '../states/AlertManagerState';
|
||||||
|
|
||||||
|
export interface IAlertManagerAttrs extends ComponentAttrs {
|
||||||
|
state: AlertManagerState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `AlertManager` component provides an area in which `Alert` components can
|
||||||
|
* be shown and dismissed.
|
||||||
|
*/
|
||||||
|
export default class AlertManager<CustomAttrs extends IAlertManagerAttrs = IAlertManagerAttrs> extends Component<CustomAttrs> {
|
||||||
|
alertsState!: AlertManagerState;
|
||||||
|
|
||||||
|
oninit(vnode: Mithril.Vnode<CustomAttrs, this>) {
|
||||||
|
super.oninit(vnode);
|
||||||
|
|
||||||
|
this.alertsState = this.attrs.state;
|
||||||
|
}
|
||||||
|
|
||||||
|
view(): Mithril.Children {
|
||||||
|
return (
|
||||||
|
<div class="AlertManager">
|
||||||
|
{Object.entries(this.alertsState.getActiveAlerts()).map(([key, alert]) => {
|
||||||
|
const urgent = alert.attrs.type === 'error';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="AlertManager-alert" role="alert" aria-live={urgent ? 'assertive' : 'polite'}>
|
||||||
|
<alert.componentClass {...alert.attrs} ondismiss={this.alertsState.dismiss.bind(this.alertsState, parseInt(key))}>
|
||||||
|
{alert.children}
|
||||||
|
</alert.componentClass>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -17,6 +17,9 @@ import classList from '../utils/classList';
|
|||||||
* All other attrs will be assigned as attributes on the badge element.
|
* All other attrs will be assigned as attributes on the badge element.
|
||||||
*/
|
*/
|
||||||
export default class Badge extends Component {
|
export default class Badge extends Component {
|
||||||
|
/**
|
||||||
|
* @returns {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
const { type, icon: iconName, label, color, style = {}, ...attrs } = this.attrs;
|
const { type, icon: iconName, label, color, style = {}, ...attrs } = this.attrs;
|
||||||
|
|
||||||
|
@@ -67,7 +67,7 @@ export interface IButtonAttrs extends ComponentAttrs {
|
|||||||
* styles can be applied by providing `className="Button"` to the Button component.
|
* styles can be applied by providing `className="Button"` to the Button component.
|
||||||
*/
|
*/
|
||||||
export default class Button<CustomAttrs extends IButtonAttrs = IButtonAttrs> extends Component<CustomAttrs> {
|
export default class Button<CustomAttrs extends IButtonAttrs = IButtonAttrs> extends Component<CustomAttrs> {
|
||||||
view(vnode: Mithril.VnodeDOM<CustomAttrs, this>) {
|
view(vnode: Mithril.VnodeDOM<CustomAttrs, this>): Mithril.Children {
|
||||||
let { type, title, 'aria-label': ariaLabel, icon: iconName, disabled, loading, className, class: _class, ...attrs } = this.attrs;
|
let { type, title, 'aria-label': ariaLabel, icon: iconName, disabled, loading, className, class: _class, ...attrs } = this.attrs;
|
||||||
|
|
||||||
// If no `type` attr provided, set to "button"
|
// If no `type` attr provided, set to "button"
|
||||||
|
@@ -17,6 +17,9 @@ import withAttr from '../utils/withAttr';
|
|||||||
* - `children` A text label to display next to the checkbox.
|
* - `children` A text label to display next to the checkbox.
|
||||||
*/
|
*/
|
||||||
export default class Checkbox extends Component {
|
export default class Checkbox extends Component {
|
||||||
|
/**
|
||||||
|
* @returns {import('mithril').Children}
|
||||||
|
*/
|
||||||
view(vnode) {
|
view(vnode) {
|
||||||
// Sometimes, false is stored in the DB as '0'. This is a temporary
|
// Sometimes, false is stored in the DB as '0'. This is a temporary
|
||||||
// conversion layer until a more robust settings encoding is introduced
|
// conversion layer until a more robust settings encoding is introduced
|
||||||
|
@@ -5,7 +5,7 @@ import classList from '../utils/classList';
|
|||||||
import icon from '../helpers/icon';
|
import icon from '../helpers/icon';
|
||||||
|
|
||||||
export default class ColorPreviewInput extends Component {
|
export default class ColorPreviewInput extends Component {
|
||||||
view(vnode: Mithril.Vnode<ComponentAttrs, this>) {
|
view(vnode: Mithril.Vnode<ComponentAttrs, this>): Mithril.Children {
|
||||||
const { className, id, ...attrs } = this.attrs;
|
const { className, id, ...attrs } = this.attrs;
|
||||||
|
|
||||||
attrs.type ||= 'text';
|
attrs.type ||= 'text';
|
||||||
|
@@ -36,6 +36,9 @@ export default class Dropdown extends Component {
|
|||||||
this.showing = false;
|
this.showing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {import('mithril').Children}
|
||||||
|
*/
|
||||||
view(vnode) {
|
view(vnode) {
|
||||||
const items = vnode.children ? listItems(vnode.children) : [];
|
const items = vnode.children ? listItems(vnode.children) : [];
|
||||||
const renderItems = this.attrs.lazyDraw ? this.showing : true;
|
const renderItems = this.attrs.lazyDraw ? this.showing : true;
|
||||||
@@ -134,6 +137,9 @@ export default class Dropdown extends Component {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {import('mithril').Children}
|
||||||
|
*/
|
||||||
getMenu(items) {
|
getMenu(items) {
|
||||||
return <ul className={'Dropdown-menu dropdown-menu ' + this.attrs.menuClassName}>{items}</ul>;
|
return <ul className={'Dropdown-menu dropdown-menu ' + this.attrs.menuClassName}>{items}</ul>;
|
||||||
}
|
}
|
||||||
|
@@ -45,11 +45,11 @@ export default class EditUserModal<CustomAttrs extends IEditUserModalAttrs = IEd
|
|||||||
return 'EditUserModal Modal--small';
|
return 'EditUserModal Modal--small';
|
||||||
}
|
}
|
||||||
|
|
||||||
title() {
|
title(): Mithril.Children {
|
||||||
return app.translator.trans('core.lib.edit_user.title');
|
return app.translator.trans('core.lib.edit_user.title');
|
||||||
}
|
}
|
||||||
|
|
||||||
content() {
|
content(): Mithril.Children {
|
||||||
const fields = this.fields().toArray();
|
const fields = this.fields().toArray();
|
||||||
return (
|
return (
|
||||||
<div className="Modal-body">
|
<div className="Modal-body">
|
||||||
@@ -58,8 +58,8 @@ export default class EditUserModal<CustomAttrs extends IEditUserModalAttrs = IEd
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fields() {
|
fields(): ItemList<Mithril.Children> {
|
||||||
const items = new ItemList();
|
const items = new ItemList<Mithril.Children>();
|
||||||
|
|
||||||
if (this.attrs.user.canEditCredentials()) {
|
if (this.attrs.user.canEditCredentials()) {
|
||||||
items.add(
|
items.add(
|
||||||
|
@@ -11,6 +11,9 @@ import listItems from '../helpers/listItems';
|
|||||||
* The children should be an array of items to show in the fieldset.
|
* The children should be an array of items to show in the fieldset.
|
||||||
*/
|
*/
|
||||||
export default class FieldSet extends Component {
|
export default class FieldSet extends Component {
|
||||||
|
/**
|
||||||
|
* @returns {import('mithril').Children}
|
||||||
|
*/
|
||||||
view(vnode) {
|
view(vnode) {
|
||||||
return (
|
return (
|
||||||
<fieldset className={this.attrs.className}>
|
<fieldset className={this.attrs.className}>
|
||||||
|
@@ -10,6 +10,9 @@ import extract from '../utils/extract';
|
|||||||
* `true` for the link to be external.
|
* `true` for the link to be external.
|
||||||
*/
|
*/
|
||||||
export default class Link extends Component {
|
export default class Link extends Component {
|
||||||
|
/**
|
||||||
|
* @returns {import('mithril').Children}
|
||||||
|
*/
|
||||||
view(vnode) {
|
view(vnode) {
|
||||||
let { options = {}, ...attrs } = vnode.attrs;
|
let { options = {}, ...attrs } = vnode.attrs;
|
||||||
|
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import app from '../../common/app';
|
import app from '../../common/app';
|
||||||
import Component, { ComponentAttrs } from '../Component';
|
import Component, { ComponentAttrs } from '../Component';
|
||||||
import classList from '../utils/classList';
|
import classList from '../utils/classList';
|
||||||
|
import type Mithril from 'mithril';
|
||||||
|
|
||||||
export interface LoadingIndicatorAttrs extends ComponentAttrs {
|
export interface LoadingIndicatorAttrs extends ComponentAttrs {
|
||||||
/**
|
/**
|
||||||
@@ -55,7 +56,7 @@ export interface LoadingIndicatorAttrs extends ComponentAttrs {
|
|||||||
* All other attrs will be assigned as attributes on the DOM element.
|
* All other attrs will be assigned as attributes on the DOM element.
|
||||||
*/
|
*/
|
||||||
export default class LoadingIndicator extends Component<LoadingIndicatorAttrs> {
|
export default class LoadingIndicator extends Component<LoadingIndicatorAttrs> {
|
||||||
view() {
|
view(): Mithril.Children {
|
||||||
const { display = 'block', size = 'medium', containerClassName, className, ...attrs } = this.attrs;
|
const { display = 'block', size = 'medium', containerClassName, className, ...attrs } = this.attrs;
|
||||||
|
|
||||||
const completeClassName = classList('LoadingIndicator', className);
|
const completeClassName = classList('LoadingIndicator', className);
|
||||||
|
@@ -81,7 +81,7 @@ export default abstract class Modal<ModalAttrs extends IInternalModalAttrs = IIn
|
|||||||
/**
|
/**
|
||||||
* @todo split into FormModal and Modal in 2.0
|
* @todo split into FormModal and Modal in 2.0
|
||||||
*/
|
*/
|
||||||
view() {
|
view(): Mithril.Children {
|
||||||
if (this.alertAttrs) {
|
if (this.alertAttrs) {
|
||||||
this.alertAttrs.dismissible = false;
|
this.alertAttrs.dismissible = false;
|
||||||
}
|
}
|
||||||
|
@@ -19,6 +19,9 @@ import LinkButton from './LinkButton';
|
|||||||
* there is no more history to pop.
|
* there is no more history to pop.
|
||||||
*/
|
*/
|
||||||
export default class Navigation extends Component {
|
export default class Navigation extends Component {
|
||||||
|
/**
|
||||||
|
* @returns {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
const { history, pane } = app;
|
const { history, pane } = app;
|
||||||
|
|
||||||
|
@@ -1,19 +0,0 @@
|
|||||||
import Component from '../Component';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The `Placeholder` component displays a muted text with some call to action,
|
|
||||||
* usually used as an empty state.
|
|
||||||
*
|
|
||||||
* ### Attrs
|
|
||||||
*
|
|
||||||
* - `text`
|
|
||||||
*/
|
|
||||||
export default class Placeholder extends Component {
|
|
||||||
view() {
|
|
||||||
return (
|
|
||||||
<div className="Placeholder">
|
|
||||||
<p>{this.attrs.text}</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
20
framework/core/js/src/common/components/Placeholder.tsx
Normal file
20
framework/core/js/src/common/components/Placeholder.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import type Mithril from 'mithril';
|
||||||
|
import Component, { ComponentAttrs } from '../Component';
|
||||||
|
|
||||||
|
interface IPlaceholderAttrs extends ComponentAttrs {
|
||||||
|
text: Mithril.Children;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `Placeholder` component displays a muted text with some call to action,
|
||||||
|
* usually used as an empty state.
|
||||||
|
*/
|
||||||
|
export default class Placeholder<CustomAttrs extends IPlaceholderAttrs = IPlaceholderAttrs> extends Component<CustomAttrs> {
|
||||||
|
view(): Mithril.Children {
|
||||||
|
return (
|
||||||
|
<div className="Placeholder">
|
||||||
|
<p>{this.attrs.text}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,3 +1,4 @@
|
|||||||
|
import type Mithril from 'mithril';
|
||||||
import type RequestError from '../utils/RequestError';
|
import type RequestError from '../utils/RequestError';
|
||||||
import Modal, { IInternalModalAttrs } from './Modal';
|
import Modal, { IInternalModalAttrs } from './Modal';
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@ export default class RequestErrorModal<CustomAttrs extends IRequestErrorModalAtt
|
|||||||
return this.attrs.error.xhr ? `${this.attrs.error.xhr.status} ${this.attrs.error.xhr.statusText}` : '';
|
return this.attrs.error.xhr ? `${this.attrs.error.xhr.status} ${this.attrs.error.xhr.statusText}` : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
content() {
|
content(): Mithril.Children {
|
||||||
const { error, formattedError } = this.attrs;
|
const { error, formattedError } = this.attrs;
|
||||||
|
|
||||||
let responseText;
|
let responseText;
|
||||||
|
@@ -16,6 +16,9 @@ import classList from '../utils/classList';
|
|||||||
* Other attributes are passed directly to the `<select>` element rendered to the DOM.
|
* Other attributes are passed directly to the `<select>` element rendered to the DOM.
|
||||||
*/
|
*/
|
||||||
export default class Select extends Component {
|
export default class Select extends Component {
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
const {
|
const {
|
||||||
options,
|
options,
|
||||||
|
@@ -41,6 +41,9 @@ export default class SelectDropdown extends Dropdown {
|
|||||||
attrs.className += ' Dropdown--select';
|
attrs.className += ' Dropdown--select';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
getButtonContent(children) {
|
getButtonContent(children) {
|
||||||
const activeChild = children.find(isActive);
|
const activeChild = children.find(isActive);
|
||||||
let label = (activeChild && activeChild.children) || this.attrs.defaultLabel;
|
let label = (activeChild && activeChild.children) || this.attrs.defaultLabel;
|
||||||
|
@@ -1,14 +1,13 @@
|
|||||||
|
import type Mithril from 'mithril';
|
||||||
import Component from '../Component';
|
import Component from '../Component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `Separator` component defines a menu separator item.
|
* The `Separator` component defines a menu separator item.
|
||||||
*/
|
*/
|
||||||
class Separator extends Component {
|
export default class Separator extends Component {
|
||||||
view() {
|
static isListItem = true;
|
||||||
|
|
||||||
|
view(): Mithril.Children {
|
||||||
return <li className="Dropdown-separator" />;
|
return <li className="Dropdown-separator" />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Separator.isListItem = true;
|
|
||||||
|
|
||||||
export default Separator;
|
|
@@ -14,6 +14,9 @@ export default class SplitDropdown extends Dropdown {
|
|||||||
attrs.menuClassName += ' Dropdown-menu--right';
|
attrs.menuClassName += ' Dropdown-menu--right';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
getButton(children) {
|
getButton(children) {
|
||||||
// Make a copy of the attrs of the first child component. We will assign
|
// Make a copy of the attrs of the first child component. We will assign
|
||||||
// these attrs to a new button, so that it has exactly the same behaviour as
|
// these attrs to a new button, so that it has exactly the same behaviour as
|
||||||
|
@@ -38,6 +38,9 @@ export default class TextEditor extends Component {
|
|||||||
this.disabled = !!this.attrs.disabled;
|
this.disabled = !!this.attrs.disabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
return (
|
return (
|
||||||
<div className="TextEditor">
|
<div className="TextEditor">
|
||||||
|
@@ -12,6 +12,9 @@ import Tooltip from './Tooltip';
|
|||||||
* - `title` - Tooltip for the button
|
* - `title` - Tooltip for the button
|
||||||
*/
|
*/
|
||||||
export default class TextEditorButton extends Button {
|
export default class TextEditorButton extends Button {
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view(vnode) {
|
view(vnode) {
|
||||||
const originalView = super.view(vnode);
|
const originalView = super.view(vnode);
|
||||||
|
|
||||||
|
@@ -13,7 +13,7 @@ export interface AlertState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class AlertManagerState {
|
export default class AlertManagerState {
|
||||||
protected activeAlerts: { [id: number]: AlertState } = {};
|
protected activeAlerts: { [id: AlertIdentifier]: AlertState } = {};
|
||||||
protected alertId = 0;
|
protected alertId = 0;
|
||||||
|
|
||||||
getActiveAlerts() {
|
getActiveAlerts() {
|
||||||
|
@@ -36,6 +36,9 @@ export default class AvatarEditor extends Component {
|
|||||||
this.isDraggedOver = false;
|
this.isDraggedOver = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
const user = this.attrs.user;
|
const user = this.attrs.user;
|
||||||
|
|
||||||
|
@@ -41,6 +41,9 @@ export default class ChangeEmailModal extends Modal {
|
|||||||
return app.translator.trans('core.forum.change_email.title');
|
return app.translator.trans('core.forum.change_email.title');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
content() {
|
content() {
|
||||||
if (this.success) {
|
if (this.success) {
|
||||||
return (
|
return (
|
||||||
|
@@ -15,6 +15,9 @@ export default class ChangePasswordModal extends Modal {
|
|||||||
return app.translator.trans('core.forum.change_password.title');
|
return app.translator.trans('core.forum.change_password.title');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
content() {
|
content() {
|
||||||
return (
|
return (
|
||||||
<div className="Modal-body">
|
<div className="Modal-body">
|
||||||
|
@@ -33,6 +33,9 @@ export default class Composer extends Component {
|
|||||||
this.prevPosition = this.state.position;
|
this.prevPosition = this.state.position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
const body = this.state.body;
|
const body = this.state.body;
|
||||||
const classes = {
|
const classes = {
|
||||||
|
@@ -47,6 +47,9 @@ export default class ComposerBody extends Component {
|
|||||||
this.composer.fields.content(this.attrs.originalContent || '');
|
this.composer.fields.content(this.attrs.originalContent || '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
return (
|
return (
|
||||||
<ConfirmDocumentUnload when={this.hasChanges.bind(this)}>
|
<ConfirmDocumentUnload when={this.hasChanges.bind(this)}>
|
||||||
|
@@ -20,6 +20,9 @@ export default class ComposerPostPreview extends Component {
|
|||||||
attrs.surround = attrs.surround || ((preview) => preview());
|
attrs.surround = attrs.surround || ((preview) => preview());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
return <div className={this.attrs.className} />;
|
return <div className={this.attrs.className} />;
|
||||||
}
|
}
|
||||||
|
@@ -10,6 +10,9 @@ import listItems from '../../common/helpers/listItems';
|
|||||||
* - `discussion`
|
* - `discussion`
|
||||||
*/
|
*/
|
||||||
export default class DiscussionHero extends Component {
|
export default class DiscussionHero extends Component {
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
return (
|
return (
|
||||||
<header className="Hero DiscussionHero">
|
<header className="Hero DiscussionHero">
|
||||||
|
@@ -13,6 +13,9 @@ import Placeholder from '../../common/components/Placeholder';
|
|||||||
* - `state` A DiscussionListState object that represents the discussion lists's state.
|
* - `state` A DiscussionListState object that represents the discussion lists's state.
|
||||||
*/
|
*/
|
||||||
export default class DiscussionList extends Component {
|
export default class DiscussionList extends Component {
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
/**
|
/**
|
||||||
* @type {import('../states/DiscussionListState').default}
|
* @type {import('../states/DiscussionListState').default}
|
||||||
|
@@ -62,7 +62,7 @@ export default class DiscussionListItem<CustomAttrs extends IDiscussionListItemA
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
view() {
|
view(): Mithril.Children {
|
||||||
const discussion = this.attrs.discussion;
|
const discussion = this.attrs.discussion;
|
||||||
const user = discussion.user();
|
const user = discussion.user();
|
||||||
const isUnread = discussion.isUnread();
|
const isUnread = discussion.isUnread();
|
||||||
@@ -164,10 +164,8 @@ export default class DiscussionListItem<CustomAttrs extends IDiscussionListItemA
|
|||||||
/**
|
/**
|
||||||
* Determine whether or not the number of replies should be shown instead of
|
* Determine whether or not the number of replies should be shown instead of
|
||||||
* the number of unread posts.
|
* the number of unread posts.
|
||||||
*
|
|
||||||
* @return {boolean}
|
|
||||||
*/
|
*/
|
||||||
showRepliesCount() {
|
showRepliesCount(): boolean {
|
||||||
return this.attrs.params.sort === 'replies';
|
return this.attrs.params.sort === 'replies';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +208,7 @@ export default class DiscussionListItem<CustomAttrs extends IDiscussionListItemA
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
replyCountItem() {
|
replyCountItem(): Mithril.Children {
|
||||||
const discussion = this.attrs.discussion;
|
const discussion = this.attrs.discussion;
|
||||||
const showUnread = !this.showRepliesCount() && discussion.isUnread();
|
const showUnread = !this.showRepliesCount() && discussion.isUnread();
|
||||||
|
|
||||||
|
@@ -17,6 +17,9 @@ const hotEdge = (e) => {
|
|||||||
* - `state` A DiscussionListState object that represents the discussion lists's state.
|
* - `state` A DiscussionListState object that represents the discussion lists's state.
|
||||||
*/
|
*/
|
||||||
export default class DiscussionListPane extends Component {
|
export default class DiscussionListPane extends Component {
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
if (!this.attrs.state.hasItems()) {
|
if (!this.attrs.state.hasItems()) {
|
||||||
return;
|
return;
|
||||||
|
@@ -79,7 +79,7 @@ export default class DiscussionPage<CustomAttrs extends IDiscussionPageAttrs = I
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
view() {
|
view(): Mithril.Children {
|
||||||
return (
|
return (
|
||||||
<div className="DiscussionPage">
|
<div className="DiscussionPage">
|
||||||
<DiscussionListPane state={app.discussions} />
|
<DiscussionListPane state={app.discussions} />
|
||||||
|
@@ -15,6 +15,9 @@ export default class DiscussionRenamedPost extends EventPost {
|
|||||||
return 'fas fa-pencil-alt';
|
return 'fas fa-pencil-alt';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
description(data) {
|
description(data) {
|
||||||
const renamed = app.translator.trans('core.forum.post_stream.discussion_renamed_text', data);
|
const renamed = app.translator.trans('core.forum.post_stream.discussion_renamed_text', data);
|
||||||
const oldName = app.translator.trans('core.forum.post_stream.discussion_renamed_old_tooltip', data);
|
const oldName = app.translator.trans('core.forum.post_stream.discussion_renamed_old_tooltip', data);
|
||||||
@@ -22,6 +25,9 @@ export default class DiscussionRenamedPost extends EventPost {
|
|||||||
return <span title={extractText(oldName)}>{renamed}</span>;
|
return <span title={extractText(oldName)}>{renamed}</span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {Record<string, unknown>}
|
||||||
|
*/
|
||||||
descriptionData() {
|
descriptionData() {
|
||||||
const post = this.attrs.post;
|
const post = this.attrs.post;
|
||||||
const oldTitle = post.content()[0];
|
const oldTitle = post.content()[0];
|
||||||
|
@@ -24,6 +24,9 @@ export default class DiscussionsUserPage extends UserPage {
|
|||||||
this.state.refresh();
|
this.state.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
content() {
|
content() {
|
||||||
return <div className="DiscussionsUserPage">{DiscussionList.component({ state: this.state })}</div>;
|
return <div className="DiscussionsUserPage">{DiscussionList.component({ state: this.state })}</div>;
|
||||||
}
|
}
|
||||||
|
@@ -36,7 +36,7 @@ export default class ForgotPasswordModal<CustomAttrs extends IForgotPasswordModa
|
|||||||
return app.translator.trans('core.forum.forgot_password.title');
|
return app.translator.trans('core.forum.forgot_password.title');
|
||||||
}
|
}
|
||||||
|
|
||||||
content() {
|
content(): Mithril.Children {
|
||||||
if (this.success) {
|
if (this.success) {
|
||||||
return (
|
return (
|
||||||
<div className="Modal-body">
|
<div className="Modal-body">
|
||||||
|
@@ -7,6 +7,9 @@ import listItems from '../../common/helpers/listItems';
|
|||||||
* default skin, these are shown just to the right of the forum title.
|
* default skin, these are shown just to the right of the forum title.
|
||||||
*/
|
*/
|
||||||
export default class HeaderPrimary extends Component {
|
export default class HeaderPrimary extends Component {
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
return <ul className="Header-controls">{listItems(this.items().toArray())}</ul>;
|
return <ul className="Header-controls">{listItems(this.items().toArray())}</ul>;
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,9 @@ import Search from '../components/Search';
|
|||||||
* right side of the header.
|
* right side of the header.
|
||||||
*/
|
*/
|
||||||
export default class HeaderSecondary extends Component {
|
export default class HeaderSecondary extends Component {
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
return <ul className="Header-controls">{listItems(this.items().toArray())}</ul>;
|
return <ul className="Header-controls">{listItems(this.items().toArray())}</ul>;
|
||||||
}
|
}
|
||||||
|
@@ -45,6 +45,9 @@ export default class IndexPage extends Page {
|
|||||||
this.scrollTopOnCreate = false;
|
this.scrollTopOnCreate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
return (
|
return (
|
||||||
<div className="IndexPage">
|
<div className="IndexPage">
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import type Mithril from 'mithril';
|
||||||
import Component from '../../common/Component';
|
import Component from '../../common/Component';
|
||||||
import avatar from '../../common/helpers/avatar';
|
import avatar from '../../common/helpers/avatar';
|
||||||
|
|
||||||
@@ -6,7 +7,7 @@ import avatar from '../../common/helpers/avatar';
|
|||||||
* indicating that the post is loading.
|
* indicating that the post is loading.
|
||||||
*/
|
*/
|
||||||
export default class LoadingPost extends Component {
|
export default class LoadingPost extends Component {
|
||||||
view() {
|
view(): Mithril.Children {
|
||||||
return (
|
return (
|
||||||
<div className="Post CommentPost LoadingPost">
|
<div className="Post CommentPost LoadingPost">
|
||||||
<header className="Post-header">
|
<header className="Post-header">
|
@@ -1,3 +1,4 @@
|
|||||||
|
import type Mithril from 'mithril';
|
||||||
import Component from '../../common/Component';
|
import Component from '../../common/Component';
|
||||||
import ItemList from '../../common/utils/ItemList';
|
import ItemList from '../../common/utils/ItemList';
|
||||||
|
|
||||||
@@ -5,16 +6,14 @@ import ItemList from '../../common/utils/ItemList';
|
|||||||
* The `LogInButtons` component displays a collection of social login buttons.
|
* The `LogInButtons` component displays a collection of social login buttons.
|
||||||
*/
|
*/
|
||||||
export default class LogInButtons extends Component {
|
export default class LogInButtons extends Component {
|
||||||
view() {
|
view(): Mithril.Children {
|
||||||
return <div className="LogInButtons">{this.items().toArray()}</div>;
|
return <div className="LogInButtons">{this.items().toArray()}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a list of LogInButton components.
|
* Build a list of LogInButton components.
|
||||||
*
|
|
||||||
* @return {ItemList<import('mithril').Children>}
|
|
||||||
*/
|
*/
|
||||||
items() {
|
items() {
|
||||||
return new ItemList();
|
return new ItemList<Mithril.Children>();
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -42,20 +42,20 @@ export default class LogInModal<CustomAttrs extends ILoginModalAttrs = ILoginMod
|
|||||||
return 'LogInModal Modal--small';
|
return 'LogInModal Modal--small';
|
||||||
}
|
}
|
||||||
|
|
||||||
title() {
|
title(): Mithril.Children {
|
||||||
return app.translator.trans('core.forum.log_in.title');
|
return app.translator.trans('core.forum.log_in.title');
|
||||||
}
|
}
|
||||||
|
|
||||||
content() {
|
content(): Mithril.Children {
|
||||||
return [<div className="Modal-body">{this.body()}</div>, <div className="Modal-footer">{this.footer()}</div>];
|
return [<div className="Modal-body">{this.body()}</div>, <div className="Modal-footer">{this.footer()}</div>];
|
||||||
}
|
}
|
||||||
|
|
||||||
body() {
|
body(): Mithril.Children {
|
||||||
return [<LogInButtons />, <div className="Form Form--centered">{this.fields().toArray()}</div>];
|
return [<LogInButtons />, <div className="Form Form--centered">{this.fields().toArray()}</div>];
|
||||||
}
|
}
|
||||||
|
|
||||||
fields() {
|
fields() {
|
||||||
const items = new ItemList();
|
const items = new ItemList<Mithril.Children>();
|
||||||
|
|
||||||
const identificationLabel = extractText(app.translator.trans('core.forum.log_in.username_or_email_placeholder'));
|
const identificationLabel = extractText(app.translator.trans('core.forum.log_in.username_or_email_placeholder'));
|
||||||
const passwordLabel = extractText(app.translator.trans('core.forum.log_in.password_placeholder'));
|
const passwordLabel = extractText(app.translator.trans('core.forum.log_in.password_placeholder'));
|
||||||
@@ -124,7 +124,7 @@ export default class LogInModal<CustomAttrs extends ILoginModalAttrs = ILoginMod
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
footer() {
|
footer(): Mithril.Children {
|
||||||
return [
|
return [
|
||||||
<p className="LogInModal-forgotPassword">
|
<p className="LogInModal-forgotPassword">
|
||||||
<a onclick={this.forgotPassword.bind(this)}>{app.translator.trans('core.forum.log_in.forgot_password_link')}</a>
|
<a onclick={this.forgotPassword.bind(this)}>{app.translator.trans('core.forum.log_in.forgot_password_link')}</a>
|
||||||
|
@@ -18,7 +18,7 @@ export interface INotificationAttrs extends ComponentAttrs {
|
|||||||
* Subclasses should implement the `icon`, `href`, and `content` methods.
|
* Subclasses should implement the `icon`, `href`, and `content` methods.
|
||||||
*/
|
*/
|
||||||
export default abstract class Notification<CustomAttrs extends INotificationAttrs = INotificationAttrs> extends Component<CustomAttrs> {
|
export default abstract class Notification<CustomAttrs extends INotificationAttrs = INotificationAttrs> extends Component<CustomAttrs> {
|
||||||
view(vnode: Mithril.Vnode<CustomAttrs, this>) {
|
view(vnode: Mithril.Vnode<CustomAttrs, this>): Mithril.Children {
|
||||||
const notification = this.attrs.notification;
|
const notification = this.attrs.notification;
|
||||||
const href = this.href();
|
const href = this.href();
|
||||||
|
|
||||||
|
@@ -38,6 +38,9 @@ export default class NotificationGrid extends Component {
|
|||||||
this.types = this.notificationTypes().toArray();
|
this.types = this.notificationTypes().toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
const preferences = this.attrs.user.preferences();
|
const preferences = this.attrs.user.preferences();
|
||||||
|
|
||||||
|
@@ -12,6 +12,9 @@ import ItemList from '../../common/utils/ItemList';
|
|||||||
* notifications, grouped by discussion.
|
* notifications, grouped by discussion.
|
||||||
*/
|
*/
|
||||||
export default class NotificationList extends Component {
|
export default class NotificationList extends Component {
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
const state = this.attrs.state;
|
const state = this.attrs.state;
|
||||||
|
|
||||||
|
@@ -18,6 +18,9 @@ export default class NotificationsDropdown extends Dropdown {
|
|||||||
super.initAttrs(attrs);
|
super.initAttrs(attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
getButton() {
|
getButton() {
|
||||||
const newNotifications = this.getNewCount();
|
const newNotifications = this.getNewCount();
|
||||||
const vdom = super.getButton();
|
const vdom = super.getButton();
|
||||||
@@ -30,6 +33,9 @@ export default class NotificationsDropdown extends Dropdown {
|
|||||||
return vdom;
|
return vdom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
getButtonContent() {
|
getButtonContent() {
|
||||||
const unread = this.getUnreadCount();
|
const unread = this.getUnreadCount();
|
||||||
|
|
||||||
@@ -40,6 +46,9 @@ export default class NotificationsDropdown extends Dropdown {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
getMenu() {
|
getMenu() {
|
||||||
return (
|
return (
|
||||||
<div className={classList('Dropdown-menu', this.attrs.menuClassName)} onclick={this.menuClick.bind(this)}>
|
<div className={classList('Dropdown-menu', this.attrs.menuClassName)} onclick={this.menuClick.bind(this)}>
|
||||||
|
@@ -17,6 +17,9 @@ export default class NotificationsPage extends Page {
|
|||||||
this.bodyClass = 'App--notifications';
|
this.bodyClass = 'App--notifications';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
return (
|
return (
|
||||||
<div className="NotificationsPage">
|
<div className="NotificationsPage">
|
||||||
|
@@ -45,7 +45,7 @@ export default abstract class Post<CustomAttrs extends IPostAttrs = IPostAttrs>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
view(vnode: Mithril.Vnode<CustomAttrs, this>) {
|
view(vnode: Mithril.Vnode<CustomAttrs, this>): Mithril.Children {
|
||||||
const attrs = this.elementAttrs();
|
const attrs = this.elementAttrs();
|
||||||
|
|
||||||
attrs.className = this.classes(attrs.className as string | undefined).join(' ');
|
attrs.className = this.classes(attrs.className as string | undefined).join(' ');
|
||||||
|
@@ -16,6 +16,9 @@ export default class PostEdited extends Component {
|
|||||||
super.oninit(vnode);
|
super.oninit(vnode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
const post = this.attrs.post;
|
const post = this.attrs.post;
|
||||||
const editedUser = post.editedUser();
|
const editedUser = post.editedUser();
|
||||||
|
@@ -13,6 +13,9 @@ import fullTime from '../../common/helpers/fullTime';
|
|||||||
* - `post`
|
* - `post`
|
||||||
*/
|
*/
|
||||||
export default class PostMeta extends Component {
|
export default class PostMeta extends Component {
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
const post = this.attrs.post;
|
const post = this.attrs.post;
|
||||||
const time = post.createdAt();
|
const time = post.createdAt();
|
||||||
|
@@ -14,6 +14,9 @@ import highlight from '../../common/helpers/highlight';
|
|||||||
* - `post`
|
* - `post`
|
||||||
*/
|
*/
|
||||||
export default class PostPreview extends Component {
|
export default class PostPreview extends Component {
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
const post = this.attrs.post;
|
const post = this.attrs.post;
|
||||||
const user = post.user();
|
const user = post.user();
|
||||||
|
@@ -26,6 +26,9 @@ export default class PostStream extends Component {
|
|||||||
this.scrollListener = new ScrollListener(this.onscroll.bind(this));
|
this.scrollListener = new ScrollListener(this.onscroll.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
let lastTime;
|
let lastTime;
|
||||||
|
|
||||||
|
@@ -23,6 +23,9 @@ export default class PostStreamScrubber extends Component {
|
|||||||
this.scrollListener = new ScrollListener(this.updateScrubberValues.bind(this, { fromScroll: true, forceHeightChange: true }));
|
this.scrollListener = new ScrollListener(this.updateScrubberValues.bind(this, { fromScroll: true, forceHeightChange: true }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
const count = this.stream.count();
|
const count = this.stream.count();
|
||||||
|
|
||||||
|
@@ -15,6 +15,9 @@ import listItems from '../../common/helpers/listItems';
|
|||||||
* - `post`
|
* - `post`
|
||||||
*/
|
*/
|
||||||
export default class PostUser extends Component {
|
export default class PostUser extends Component {
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
const post = this.attrs.post;
|
const post = this.attrs.post;
|
||||||
const user = post.user();
|
const user = post.user();
|
||||||
|
@@ -45,6 +45,9 @@ export default class PostsUserPage extends UserPage {
|
|||||||
this.loadUser(m.route.param('username'));
|
this.loadUser(m.route.param('username'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
content() {
|
content() {
|
||||||
if (this.posts.length === 0 && !this.loading) {
|
if (this.posts.length === 0 && !this.loading) {
|
||||||
return (
|
return (
|
||||||
|
@@ -19,10 +19,16 @@ export default class RenameDiscussionModal extends Modal {
|
|||||||
return 'RenameDiscussionModal Modal--small';
|
return 'RenameDiscussionModal Modal--small';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
title() {
|
title() {
|
||||||
return app.translator.trans('core.forum.rename_discussion.title');
|
return app.translator.trans('core.forum.rename_discussion.title');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
content() {
|
content() {
|
||||||
return (
|
return (
|
||||||
<div className="Modal-body">
|
<div className="Modal-body">
|
||||||
|
@@ -15,6 +15,9 @@ import listItems from '../../common/helpers/listItems';
|
|||||||
* - `discussion`
|
* - `discussion`
|
||||||
*/
|
*/
|
||||||
export default class ReplyPlaceholder extends Component {
|
export default class ReplyPlaceholder extends Component {
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view() {
|
view() {
|
||||||
if (app.composer.composingReplyTo(this.attrs.discussion)) {
|
if (app.composer.composingReplyTo(this.attrs.discussion)) {
|
||||||
return (
|
return (
|
||||||
|
@@ -117,7 +117,7 @@ export default class Search<T extends SearchAttrs = SearchAttrs> extends Compone
|
|||||||
this.searchState = this.attrs.state;
|
this.searchState = this.attrs.state;
|
||||||
}
|
}
|
||||||
|
|
||||||
view() {
|
view(): Mithril.Children {
|
||||||
const currentSearch = this.searchState.getInitialSearch();
|
const currentSearch = this.searchState.getInitialSearch();
|
||||||
|
|
||||||
// Initialize search sources in the view rather than the constructor so
|
// Initialize search sources in the view rather than the constructor so
|
||||||
|
@@ -22,10 +22,16 @@ export default class SessionDropdown extends Dropdown {
|
|||||||
attrs.accessibleToggleLabel = app.translator.trans('core.forum.header.session_dropdown_accessible_label');
|
attrs.accessibleToggleLabel = app.translator.trans('core.forum.header.session_dropdown_accessible_label');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
view(vnode) {
|
view(vnode) {
|
||||||
return super.view({ ...vnode, children: this.items().toArray() });
|
return super.view({ ...vnode, children: this.items().toArray() });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {import('mithril').Children}
|
||||||
|
*/
|
||||||
getButtonContent() {
|
getButtonContent() {
|
||||||
const user = app.session.user;
|
const user = app.session.user;
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user