merged master

This commit is contained in:
Daniel Klabbers 2018-05-14 09:23:06 +02:00
commit 19645785a3
55 changed files with 262 additions and 190 deletions

View File

@ -41,35 +41,35 @@ export default class AdminNav extends Component {
items.add('basics', AdminLinkButton.component({
href: app.route('basics'),
icon: 'fa fa-pencil-alt',
icon: 'fas fa-pencil-alt',
children: app.translator.trans('core.admin.nav.basics_button'),
description: app.translator.trans('core.admin.nav.basics_text')
}));
items.add('mail', AdminLinkButton.component({
href: app.route('mail'),
icon: 'fa fa-envelope',
icon: 'fas fa-envelope',
children: app.translator.trans('core.admin.nav.email_button'),
description: app.translator.trans('core.admin.nav.email_text')
}));
items.add('permissions', AdminLinkButton.component({
href: app.route('permissions'),
icon: 'fa fa-key',
icon: 'fas fa-key',
children: app.translator.trans('core.admin.nav.permissions_button'),
description: app.translator.trans('core.admin.nav.permissions_text')
}));
items.add('appearance', AdminLinkButton.component({
href: app.route('appearance'),
icon: 'fa fa-paint-brush',
icon: 'fas fa-paint-brush',
children: app.translator.trans('core.admin.nav.appearance_button'),
description: app.translator.trans('core.admin.nav.appearance_text')
}));
items.add('extensions', AdminLinkButton.component({
href: app.route('extensions'),
icon: 'fa fa-puzzle-piece',
icon: 'fas fa-puzzle-piece',
children: app.translator.trans('core.admin.nav.extensions_button'),
description: app.translator.trans('core.admin.nav.extensions_text')
}));

View File

@ -17,7 +17,7 @@ export default class ExtensionsPage extends Page {
<div className="container">
{Button.component({
children: app.translator.trans('core.admin.extensions.add_button'),
icon: 'fa fa-plus',
icon: 'fas fa-plus',
className: 'Button Button--primary',
onclick: () => app.modal.show(new AddExtensionModal())
})}
@ -42,7 +42,7 @@ export default class ExtensionsPage extends Page {
className="ExtensionListItem-controls"
buttonClassName="Button Button--icon Button--flat"
menuClassName="Dropdown-menu--right"
icon="fa fa-ellipsis-h">
icon="fas fa-ellipsis-h">
{controls}
</Dropdown>
) : ''}
@ -67,7 +67,7 @@ export default class ExtensionsPage extends Page {
if (app.extensionSettings[name]) {
items.add('settings', Button.component({
icon: 'fa fa-cog',
icon: 'fas fa-cog',
children: app.translator.trans('core.admin.extensions.settings_button'),
onclick: app.extensionSettings[name]
}));

View File

@ -52,9 +52,9 @@ export default class PermissionDropdown extends Dropdown {
const adminGroup = app.store.getById('groups', Group.ADMINISTRATOR_ID);
if (everyone) {
this.props.label = Badge.component({icon: 'fa fa-globe'});
this.props.label = Badge.component({icon: 'fas fa-globe'});
} else if (members) {
this.props.label = Badge.component({icon: 'fa fa-user'});
this.props.label = Badge.component({icon: 'fas fa-user'});
} else {
this.props.label = [
badgeForId(Group.ADMINISTRATOR_ID),
@ -66,8 +66,8 @@ export default class PermissionDropdown extends Dropdown {
if (this.props.allowGuest) {
this.props.children.push(
Button.component({
children: [Badge.component({icon: 'fa fa-globe'}), ' ', app.translator.trans('core.admin.permissions_controls.everyone_button')],
icon: everyone ? 'fa fa-check' : true,
children: [Badge.component({icon: 'fas fa-globe'}), ' ', app.translator.trans('core.admin.permissions_controls.everyone_button')],
icon: everyone ? 'fas fa-check' : true,
onclick: () => this.save([Group.GUEST_ID]),
disabled: this.isGroupDisabled(Group.GUEST_ID)
})
@ -76,8 +76,8 @@ export default class PermissionDropdown extends Dropdown {
this.props.children.push(
Button.component({
children: [Badge.component({icon: 'fa fa-user'}), ' ', app.translator.trans('core.admin.permissions_controls.members_button')],
icon: members ? 'fa fa-check' : true,
children: [Badge.component({icon: 'fas fa-user'}), ' ', app.translator.trans('core.admin.permissions_controls.members_button')],
icon: members ? 'fas fa-check' : true,
onclick: () => this.save([Group.MEMBER_ID]),
disabled: this.isGroupDisabled(Group.MEMBER_ID)
}),
@ -86,7 +86,7 @@ export default class PermissionDropdown extends Dropdown {
Button.component({
children: [badgeForId(adminGroup.id()), ' ', adminGroup.namePlural()],
icon: !everyone && !members ? 'fa fa-check' : true,
icon: !everyone && !members ? 'fas fa-check' : true,
disabled: !everyone && !members,
onclick: e => {
if (e.shiftKey) e.stopPropagation();
@ -101,7 +101,7 @@ export default class PermissionDropdown extends Dropdown {
.filter(group => [Group.ADMINISTRATOR_ID, Group.GUEST_ID, Group.MEMBER_ID].indexOf(group.id()) === -1)
.map(group => Button.component({
children: [badgeForId(group.id()), ' ', group.namePlural()],
icon: groupIds.indexOf(group.id()) !== -1 ? 'fa fa-check' : true,
icon: groupIds.indexOf(group.id()) !== -1 ? 'fas fa-check' : true,
onclick: (e) => {
if (e.shiftKey) e.stopPropagation();
this.toggle(group.id());

View File

@ -29,7 +29,7 @@ export default class PermissionGrid extends Component {
{scopes.map(scope => (
<th>
{scope.label}{' '}
{scope.onremove ? Button.component({icon: 'fa fa-times', className: 'Button Button--text PermissionGrid-removeScope', onclick: scope.onremove}) : ''}
{scope.onremove ? Button.component({icon: 'fas fa-times', className: 'Button Button--text PermissionGrid-removeScope', onclick: scope.onremove}) : ''}
</th>
))}
<th>{this.scopeControlItems().toArray()}</th>
@ -85,21 +85,21 @@ export default class PermissionGrid extends Component {
const items = new ItemList();
items.add('viewDiscussions', {
icon: 'fa fa-eye',
icon: 'fas fa-eye',
label: app.translator.trans('core.admin.permissions.view_discussions_label'),
permission: 'viewDiscussions',
allowGuest: true
}, 100);
items.add('viewUserList', {
icon: 'fa fa-users',
icon: 'fas fa-users',
label: app.translator.trans('core.admin.permissions.view_user_list_label'),
permission: 'viewUserList',
allowGuest: true
}, 100);
items.add('signUp', {
icon: 'fa fa-user-plus',
icon: 'fas fa-user-plus',
label: app.translator.trans('core.admin.permissions.sign_up_label'),
setting: () => SettingDropdown.component({
key: 'allow_sign_up',
@ -117,13 +117,13 @@ export default class PermissionGrid extends Component {
const items = new ItemList();
items.add('start', {
icon: 'fa fa-edit',
icon: 'fas fa-edit',
label: app.translator.trans('core.admin.permissions.start_discussions_label'),
permission: 'startDiscussion'
}, 100);
items.add('allowRenaming', {
icon: 'fa fa-i-cursor',
icon: 'fas fa-i-cursor',
label: app.translator.trans('core.admin.permissions.allow_renaming_label'),
setting: () => {
const minutes = parseInt(app.data.settings.allow_renaming, 10);
@ -149,13 +149,13 @@ export default class PermissionGrid extends Component {
const items = new ItemList();
items.add('reply', {
icon: 'fa fa-reply',
icon: 'fas fa-reply',
label: app.translator.trans('core.admin.permissions.reply_to_discussions_label'),
permission: 'discussion.reply'
}, 100);
items.add('allowPostEditing', {
icon: 'fa fa-pencil-alt',
icon: 'fas fa-pencil-alt',
label: app.translator.trans('core.admin.permissions.allow_post_editing_label'),
setting: () => {
const minutes = parseInt(app.data.settings.allow_post_editing, 10);
@ -181,13 +181,13 @@ export default class PermissionGrid extends Component {
const items = new ItemList();
items.add('viewIpsPosts', {
icon: 'fa fa-bullseye',
icon: 'fas fa-bullseye',
label: app.translator.trans('core.admin.permissions.view_post_ips_label'),
permission: 'discussion.viewIpsPosts'
}, 110);
items.add('renameDiscussions', {
icon: 'fa fa-i-cursor',
icon: 'fas fa-i-cursor',
label: app.translator.trans('core.admin.permissions.rename_discussions_label'),
permission: 'discussion.rename'
}, 100);
@ -199,19 +199,19 @@ export default class PermissionGrid extends Component {
}, 90);
items.add('deleteDiscussions', {
icon: 'fa fa-times',
icon: 'fas fa-times',
label: app.translator.trans('core.admin.permissions.delete_discussions_forever_label'),
permission: 'discussion.delete'
}, 80);
items.add('editPosts', {
icon: 'fa fa-pencil-alt',
icon: 'fas fa-pencil-alt',
label: app.translator.trans('core.admin.permissions.edit_and_delete_posts_label'),
permission: 'discussion.editPosts'
}, 70);
items.add('deletePosts', {
icon: 'fa fa-times',
icon: 'fas fa-times',
label: app.translator.trans('core.admin.permissions.delete_posts_forever_label'),
permission: 'discussion.deletePosts'
}, 60);

View File

@ -24,7 +24,7 @@ export default class PermissionsPage extends Page {
</button>
))}
<button className="Button Group Group--add" onclick={() => app.modal.show(new EditGroupModal())}>
{icon('fa fa-plus', {className: 'Group-icon'})}
{icon('fas fa-plus', {className: 'Group-icon'})}
<span className="Group-name">{app.translator.trans('core.admin.permissions.new_group_button')}</span>
</button>
</div>

View File

@ -42,7 +42,7 @@ export default class SessionDropdown extends Dropdown {
items.add('logOut',
Button.component({
icon: 'fa fa-sign-out-alt',
icon: 'fas fa-sign-out-alt',
children: app.translator.trans('core.admin.header.log_out_button'),
onclick: app.session.logout.bind(app.session)
}),

View File

@ -8,7 +8,7 @@ export default class SettingDropdown extends SelectDropdown {
props.className = 'SettingDropdown';
props.buttonClassName = 'Button Button--text';
props.caretIcon = 'fa fa-caret-down';
props.caretIcon = 'fas fa-caret-down';
props.defaultLabel = 'Custom';
props.children = props.options.map(({value, label}) => {
@ -16,7 +16,7 @@ export default class SettingDropdown extends SelectDropdown {
return Button.component({
children: label,
icon: active ? 'fa fa-check' : true,
icon: active ? 'fas fa-check' : true,
onclick: saveSettings.bind(this, {[props.key]: value}),
active
});

View File

@ -28,7 +28,7 @@ export default class StatusWidget extends DashboardWidget {
items.add('help', (
<a href="http://flarum.org/docs/troubleshooting" target="_blank">
{icon('fa fa-question-circle')} {app.translator.trans('core.admin.dashboard.help_link')}
{icon('fas fa-question-circle')} {app.translator.trans('core.admin.dashboard.help_link')}
</a>
));

View File

@ -53,7 +53,7 @@ export default class AvatarEditor extends Component {
ondragleave={this.disableDragover.bind(this)}
ondragend={this.disableDragover.bind(this)}
ondrop={this.dropUpload.bind(this)}>
{this.loading ? LoadingIndicator.component() : (user.avatarUrl() ? icon('fa fa-pencil-alt') : icon('fa fa-plus-circle'))}
{this.loading ? LoadingIndicator.component() : (user.avatarUrl() ? icon('fas fa-pencil-alt') : icon('fas fa-plus-circle'))}
</a>
<ul className="Dropdown-menu Menu">
{listItems(this.controlItems().toArray())}
@ -72,7 +72,7 @@ export default class AvatarEditor extends Component {
items.add('upload',
Button.component({
icon: 'fa fa-upload',
icon: 'fas fa-upload',
children: app.translator.trans('core.forum.user.avatar_upload_button'),
onclick: this.openPicker.bind(this)
})
@ -80,7 +80,7 @@ export default class AvatarEditor extends Component {
items.add('remove',
Button.component({
icon: 'fa fa-times',
icon: 'fas fa-times',
children: app.translator.trans('core.forum.user.avatar_remove_button'),
onclick: this.remove.bind(this)
})

View File

@ -142,7 +142,7 @@ export default class CommentPost extends Post {
items.add('toggle', (
Button.component({
className: 'Button Button--default Button--more',
icon: 'fa fa-ellipsis-h',
icon: 'fas fa-ellipsis-h',
onclick: this.toggleContent.bind(this)
})
));

View File

@ -422,28 +422,28 @@ class Composer extends Component {
if (this.position === Composer.PositionEnum.FULLSCREEN) {
items.add('exitFullScreen', ComposerButton.component({
icon: 'fa fa-compress',
icon: 'fas fa-compress',
title: app.translator.trans('core.forum.composer.exit_full_screen_tooltip'),
onclick: this.exitFullScreen.bind(this)
}));
} else {
if (this.position !== Composer.PositionEnum.MINIMIZED) {
items.add('minimize', ComposerButton.component({
icon: 'fa fa-minus minimize',
icon: 'fas fa-minus minimize',
title: app.translator.trans('core.forum.composer.minimize_tooltip'),
onclick: this.minimize.bind(this),
itemClassName: 'App-backControl'
}));
items.add('fullScreen', ComposerButton.component({
icon: 'fa fa-expand',
icon: 'fas fa-expand',
title: app.translator.trans('core.forum.composer.full_screen_tooltip'),
onclick: this.fullScreen.bind(this)
}));
}
items.add('close', ComposerButton.component({
icon: 'fa fa-times',
icon: 'fas fa-times',
title: app.translator.trans('core.forum.composer.close_tooltip'),
onclick: this.close.bind(this)
}));

View File

@ -81,7 +81,7 @@ export default class DiscussionListItem extends Component {
return (
<div {...attrs}>
{controls.length ? Dropdown.component({
icon: 'fa fa-ellipsis-v',
icon: 'fas fa-ellipsis-v',
children: controls,
className: 'DiscussionListItem-controls',
buttonClassName: 'Button Button--icon Button--flat Slidable-underneath Slidable-underneath--right'
@ -89,7 +89,7 @@ export default class DiscussionListItem extends Component {
<a className={'Slidable-underneath Slidable-underneath--left Slidable-underneath--elastic' + (isUnread ? '' : ' disabled')}
onclick={this.markAsRead.bind(this)}>
{icon('fa fa-check')}
{icon('fas fa-check')}
</a>
<div className={'DiscussionListItem-content Slidable-content' + (isUnread ? ' unread' : '') + (isRead ? ' read' : '')}>

View File

@ -240,7 +240,7 @@ export default class DiscussionPage extends Page {
items.add('controls',
SplitDropdown.component({
children: DiscussionControls.controls(this.discussion, this).toArray(),
icon: 'fa fa-ellipsis-v',
icon: 'fas fa-ellipsis-v',
className: 'App-primaryControl',
buttonClassName: 'Button--primary'
})

View File

@ -10,7 +10,7 @@ import Notification from 'flarum/components/Notification';
*/
export default class DiscussionRenamedNotification extends Notification {
icon() {
return 'fa fa-pencil-alt';
return 'fas fa-pencil-alt';
}
href() {

View File

@ -11,7 +11,7 @@ import extractText from 'flarum/utils/extractText';
*/
export default class DiscussionRenamedPost extends EventPost {
icon() {
return 'fa fa-pencil-alt';
return 'fas fa-pencil-alt';
}
description(data) {

View File

@ -35,7 +35,7 @@ export default class DiscussionsSearchSource {
<li className="Dropdown-header">{app.translator.trans('core.forum.search.discussions_heading')}</li>,
<li>
{LinkButton.component({
icon: 'fa fa-search',
icon: 'fas fa-search',
children: app.translator.trans('core.forum.search.all_discussions_button', {query}),
href: app.route('index', {q: query})
})}

View File

@ -52,7 +52,7 @@ export default class EditPostComposer extends ComposerBody {
items.add('title', (
<h3>
{icon('fa fa-pencil-alt')} {' '}
{icon('fas fa-pencil-alt')} {' '}
<a href={app.route.discussion(post.discussion(), post.number())} config={routeAndMinimize}>
{app.translator.trans('core.forum.composer_edit.post_link', {number: post.number(), discussion: post.discussion().title()})}
</a>

View File

@ -46,7 +46,7 @@ export default class HeaderSecondary extends Component {
locales.push(Button.component({
active: app.data.locale === locale,
children: app.data.locales[locale],
icon: app.data.locale === locale ? 'fa fa-check' : true,
icon: app.data.locale === locale ? 'fas fa-check' : true,
onclick: () => {
if (app.session.user) {
app.session.user.savePreferences({locale}).then(() => window.location.reload());

View File

@ -154,7 +154,7 @@ export default class IndexPage extends Page {
items.add('newDiscussion',
Button.component({
children: app.translator.trans(canStartDiscussion ? 'core.forum.index.start_discussion_button' : 'core.forum.index.cannot_start_discussion_button'),
icon: 'fa fa-edit',
icon: 'fas fa-edit',
className: 'Button Button--primary IndexPage-newDiscussion',
itemClassName: 'App-primaryControl',
onclick: this.newDiscussion.bind(this),
@ -221,7 +221,7 @@ export default class IndexPage extends Page {
return Button.component({
children: label,
icon: active ? 'fa fa-check' : true,
icon: active ? 'fas fa-check' : true,
onclick: this.changeSort.bind(this, value),
active: active,
})
@ -244,7 +244,7 @@ export default class IndexPage extends Page {
items.add('refresh',
Button.component({
title: app.translator.trans('core.forum.index.refresh_tooltip'),
icon: 'fa fa-sync',
icon: 'fas fa-sync',
className: 'Button Button--icon',
onclick: () => {
app.cache.discussionList.refresh();
@ -260,7 +260,7 @@ export default class IndexPage extends Page {
items.add('markAllAsRead',
Button.component({
title: app.translator.trans('core.forum.index.mark_all_as_read_tooltip'),
icon: 'fa fa-check',
icon: 'fas fa-check',
className: 'Button Button--icon',
onclick: this.markAllAsRead.bind(this)
})

View File

@ -1,10 +1,10 @@
import Modal from 'flarum/components/Modal';
import ForgotPasswordModal from 'flarum/components/ForgotPasswordModal';
import SignUpModal from 'flarum/components/SignUpModal';
import Alert from 'flarum/components/Alert';
import Button from 'flarum/components/Button';
import LogInButtons from 'flarum/components/LogInButtons';
import extractText from 'flarum/utils/extractText';
import ItemList from 'flarum/utils/ItemList';
/**
* The `LogInModal` component displays a modal dialog with a login form.
@ -51,54 +51,74 @@ export default class LogInModal extends Modal {
content() {
return [
<div className="Modal-body">
<LogInButtons/>
<div className="Form Form--centered">
<div className="Form-group">
<input className="FormControl" name="identification" type="text" placeholder={extractText(app.translator.trans('core.forum.log_in.username_or_email_placeholder'))}
bidi={this.identification}
disabled={this.loading} />
</div>
<div className="Form-group">
<input className="FormControl" name="password" type="password" placeholder={extractText(app.translator.trans('core.forum.log_in.password_placeholder'))}
bidi={this.password}
disabled={this.loading} />
</div>
<div className="Form-group">
<div>
<label className="checkbox">
<input type="checkbox" bidi={this.remember} disabled={this.loading} />
{app.translator.trans('core.forum.log_in.remember_me_label')}
</label>
</div>
</div>
<div className="Form-group">
{Button.component({
className: 'Button Button--primary Button--block',
type: 'submit',
loading: this.loading,
children: app.translator.trans('core.forum.log_in.submit_button')
})}
</div>
</div>
{this.body()}
</div>,
<div className="Modal-footer">
<p className="LogInModal-forgotPassword">
<a onclick={this.forgotPassword.bind(this)}>{app.translator.trans('core.forum.log_in.forgot_password_link')}</a>
</p>
{app.forum.attribute('allowSignUp') ? (
<p className="LogInModal-signUp">
{app.translator.trans('core.forum.log_in.sign_up_text', {a: <a onclick={this.signUp.bind(this)}/>})}
</p>
) : ''}
{this.footer()}
</div>
];
}
body() {
return [
<LogInButtons/>,
<div className="Form Form--centered">
{this.fields().toArray()}
</div>
];
}
fields() {
const items = new ItemList();
items.add('identification', <div className="Form-group">
<input className="FormControl" name="identification" type="text" placeholder={extractText(app.translator.trans('core.forum.log_in.username_or_email_placeholder'))}
bidi={this.identification}
disabled={this.loading} />
</div>, 30);
items.add('password', <div className="Form-group">
<input className="FormControl" name="password" type="password" placeholder={extractText(app.translator.trans('core.forum.log_in.password_placeholder'))}
bidi={this.password}
disabled={this.loading} />
</div>, 20);
items.add('remember', <div className="Form-group">
<div>
<label className="checkbox">
<input type="checkbox" bidi={this.remember} disabled={this.loading} />
{app.translator.trans('core.forum.log_in.remember_me_label')}
</label>
</div>
</div>, 10);
items.add('submit', <div className="Form-group">
{Button.component({
className: 'Button Button--primary Button--block',
type: 'submit',
loading: this.loading,
children: app.translator.trans('core.forum.log_in.submit_button')
})}
</div>, -10);
return items;
}
footer() {
return [
<p className="LogInModal-forgotPassword">
<a onclick={this.forgotPassword.bind(this)}>{app.translator.trans('core.forum.log_in.forgot_password_link')}</a>
</p>,
app.forum.attribute('allowSignUp') ? (
<p className="LogInModal-signUp">
{app.translator.trans('core.forum.log_in.sign_up_text', {a: <a onclick={this.signUp.bind(this)}/>})}
</p>
) : ''
];
}
/**
* Open the forgot password modal, prefilling it with an email if the user has
* entered one.

View File

@ -177,7 +177,7 @@ export default class NotificationGrid extends Component {
items.add('alert', {
name: 'alert',
icon: 'fa fa-bell',
icon: 'fas fa-bell',
label: app.translator.trans('core.forum.settings.notify_by_web_heading'),
});
@ -206,7 +206,7 @@ export default class NotificationGrid extends Component {
items.add('discussionRenamed', {
name: 'discussionRenamed',
icon: 'fa fa-pencil-alt',
icon: 'fas fa-pencil-alt',
label: app.translator.trans('core.forum.settings.notify_discussion_renamed_label')
});

View File

@ -34,7 +34,7 @@ export default class NotificationList extends Component {
<div className="App-primaryControl">
{Button.component({
className: 'Button Button--icon Button--link',
icon: 'fa fa-check',
icon: 'fas fa-check',
title: app.translator.trans('core.forum.notifications.mark_all_as_read_tooltip'),
onclick: this.markAllAsRead.bind(this)
})}

View File

@ -8,7 +8,7 @@ export default class NotificationsDropdown extends Dropdown {
props.buttonClassName = props.buttonClassName || 'Button Button--flat';
props.menuClassName = props.menuClassName || 'Dropdown-menu--right';
props.label = props.label || app.translator.trans('core.forum.notifications.tooltip');
props.icon = props.icon || 'fa fa-bell';
props.icon = props.icon || 'fas fa-bell';
super.initProps(props);
}

View File

@ -57,7 +57,7 @@ export default class Post extends Component {
className="Post-controls"
buttonClassName="Button Button--icon Button--flat"
menuClassName="Dropdown-menu--right"
icon="fa fa-ellipsis-h"
icon="fas fa-ellipsis-h"
onshow={() => this.$('.Post-actions').addClass('open')}
onhide={() => this.$('.Post-actions').removeClass('open')}>
{controls}

View File

@ -84,13 +84,13 @@ export default class PostStreamScrubber extends Component {
return (
<div className={'PostStreamScrubber Dropdown ' + (this.disabled() ? 'disabled ' : '') + (this.props.className || '')}>
<button className="Button Dropdown-toggle" data-toggle="dropdown">
{viewing} {icon('fa fa-sort')}
{viewing} {icon('fas fa-sort')}
</button>
<div className="Dropdown-menu dropdown-menu">
<div className="Scrubber">
<a className="Scrubber-first" onclick={this.goToFirst.bind(this)}>
{icon('fa fa-angle-double-up')} {app.translator.trans('core.forum.post_scrubber.original_post_link')}
{icon('fas fa-angle-double-up')} {app.translator.trans('core.forum.post_scrubber.original_post_link')}
</a>
<div className="Scrubber-scrollbar">
@ -110,7 +110,7 @@ export default class PostStreamScrubber extends Component {
</div>
<a className="Scrubber-last" onclick={this.goToLast.bind(this)}>
{icon('fa fa-angle-double-down')} {app.translator.trans('core.forum.post_scrubber.now_link')}
{icon('fas fa-angle-double-down')} {app.translator.trans('core.forum.post_scrubber.now_link')}
</a>
</div>
</div>

View File

@ -51,7 +51,7 @@ export default class ReplyComposer extends ComposerBody {
items.add('title', (
<h3>
{icon('fa fa-reply')} {' '}
{icon('fas fa-reply')} {' '}
<a href={app.route.discussion(discussion)} config={routeAndMinimize}>{discussion.title()}</a>
</h3>
));

View File

@ -92,7 +92,7 @@ export default class Search extends Component {
{this.loadingSources
? LoadingIndicator.component({size: 'tiny', className: 'Button Button--icon Button--link'})
: currentSearch
? <button className="Search-clear Button Button--icon Button--link" onclick={this.clear.bind(this)}>{icon('fa fa-times-circle')}</button>
? <button className="Search-clear Button Button--icon Button--link" onclick={this.clear.bind(this)}>{icon('fas fa-times-circle')}</button>
: ''}
</div>
<ul className="Dropdown-menu Search-results">

View File

@ -46,7 +46,7 @@ export default class SessionDropdown extends Dropdown {
items.add('profile',
LinkButton.component({
icon: 'fa fa-user',
icon: 'fas fa-user',
children: app.translator.trans('core.forum.header.profile_button'),
href: app.route.user(user)
}),
@ -55,7 +55,7 @@ export default class SessionDropdown extends Dropdown {
items.add('settings',
LinkButton.component({
icon: 'fa fa-cog',
icon: 'fas fa-cog',
children: app.translator.trans('core.forum.header.settings_button'),
href: app.route('settings')
}),
@ -65,7 +65,7 @@ export default class SessionDropdown extends Dropdown {
if (app.forum.attribute('adminUrl')) {
items.add('administration',
LinkButton.component({
icon: 'fa fa-wrench',
icon: 'fas fa-wrench',
children: app.translator.trans('core.forum.header.admin_button'),
href: app.forum.attribute('adminUrl'),
target: '_blank',
@ -79,7 +79,7 @@ export default class SessionDropdown extends Dropdown {
items.add('logOut',
Button.component({
icon: 'fa fa-sign-out-alt',
icon: 'fas fa-sign-out-alt',
children: app.translator.trans('core.forum.header.log_out_button'),
onclick: app.session.logout.bind(app.session)
}),

View File

@ -1,9 +1,9 @@
import Modal from 'flarum/components/Modal';
import LogInModal from 'flarum/components/LogInModal';
import avatar from 'flarum/helpers/avatar';
import Button from 'flarum/components/Button';
import LogInButtons from 'flarum/components/LogInButtons';
import extractText from 'flarum/utils/extractText';
import ItemList from 'flarum/utils/ItemList';
/**
* The `SignUpModal` component displays a modal dialog with a singup form.
@ -69,41 +69,49 @@ export default class SignUpModal extends Modal {
this.props.token ? '' : <LogInButtons/>,
<div className="Form Form--centered">
<div className="Form-group">
<input className="FormControl" name="username" type="text" placeholder={extractText(app.translator.trans('core.forum.sign_up.username_placeholder'))}
value={this.username()}
onchange={m.withAttr('value', this.username)}
disabled={this.loading || this.isProvided('username')} />
</div>
<div className="Form-group">
<input className="FormControl" name="email" type="email" placeholder={extractText(app.translator.trans('core.forum.sign_up.email_placeholder'))}
value={this.email()}
onchange={m.withAttr('value', this.email)}
disabled={this.loading || this.isProvided('email')} />
</div>
{this.props.token ? '' : (
<div className="Form-group">
<input className="FormControl" name="password" type="password" placeholder={extractText(app.translator.trans('core.forum.sign_up.password_placeholder'))}
value={this.password()}
onchange={m.withAttr('value', this.password)}
disabled={this.loading} />
</div>
)}
<div className="Form-group">
<Button
className="Button Button--primary Button--block"
type="submit"
loading={this.loading}>
{app.translator.trans('core.forum.sign_up.submit_button')}
</Button>
</div>
{this.fields().toArray()}
</div>
];
}
fields() {
const items = new ItemList();
items.add('username', <div className="Form-group">
<input className="FormControl" name="username" type="text" placeholder={extractText(app.translator.trans('core.forum.sign_up.username_placeholder'))}
value={this.username()}
onchange={m.withAttr('value', this.username)}
disabled={this.loading || this.isProvided('username')} />
</div>, 30);
items.add('email', <div className="Form-group">
<input className="FormControl" name="email" type="email" placeholder={extractText(app.translator.trans('core.forum.sign_up.email_placeholder'))}
value={this.email()}
onchange={m.withAttr('value', this.email)}
disabled={this.loading || this.isProvided('email')} />
</div>, 20);
if (!this.props.token) {
items.add('password', <div className="Form-group">
<input className="FormControl" name="password" type="password" placeholder={extractText(app.translator.trans('core.forum.sign_up.password_placeholder'))}
value={this.password()}
onchange={m.withAttr('value', this.password)}
disabled={this.loading} />
</div>, 10);
}
items.add('submit', <div className="Form-group">
<Button
className="Button Button--primary Button--block"
type="submit"
loading={this.loading}>
{app.translator.trans('core.forum.sign_up.submit_button')}
</Button>
</div>, -10);
return items;
}
footer() {
return [
<p className="SignUpModal-logIn">

View File

@ -20,7 +20,7 @@ export default class TerminalPost extends Component {
return (
<span>
{lastPost ? icon('fa fa-reply') : ''}{' '}
{lastPost ? icon('fas fa-reply') : ''}{' '}
{app.translator.trans('core.forum.discussion_list.' + (lastPost ? 'replied' : 'started') + '_text', {
user,
ago: humanTime(time)

View File

@ -70,7 +70,7 @@ export default class TextEditor extends Component {
items.add('submit',
Button.component({
children: this.props.submitLabel,
icon: 'fa fa-check',
icon: 'fas fa-check',
className: 'Button Button--primary',
itemClassName: 'App-primaryControl',
onclick: this.onsubmit.bind(this)
@ -80,7 +80,7 @@ export default class TextEditor extends Component {
if (this.props.preview) {
items.add('preview',
Button.component({
icon: 'fa fa-eye',
icon: 'fas fa-eye',
className: 'Button Button--icon',
onclick: this.props.preview,
title: app.translator.trans('core.forum.composer.preview_tooltip')

View File

@ -40,7 +40,7 @@ export default class UserCard extends Component {
menuClassName: 'Dropdown-menu--right',
buttonClassName: this.props.controlsButtonClassName,
label: app.translator.trans('core.forum.user_controls.button'),
icon: 'fa fa-ellipsis-v'
icon: 'fas fa-ellipsis-v'
}) : ''}
<div className="UserCard-profile">
@ -87,7 +87,7 @@ export default class UserCard extends Component {
items.add('lastSeen', (
<span className={'UserCard-lastSeen' + (online ? ' online' : '')}>
{online
? [icon('fa fa-circle'), ' ', app.translator.trans('core.forum.user.online_text')]
? [icon('fas fa-circle'), ' ', app.translator.trans('core.forum.user.online_text')]
: [icon('far fa-clock'), ' ', humanTime(lastSeenTime)]}
</span>
));

View File

@ -139,7 +139,7 @@ export default class UserPage extends Page {
LinkButton.component({
href: app.route('user.discussions', {username: user.username()}),
children: [app.translator.trans('core.forum.user.discussions_link'), <span className="Button-badge">{user.discussionsCount()}</span>],
icon: 'fa fa-bars'
icon: 'fas fa-bars'
}),
90
);
@ -150,7 +150,7 @@ export default class UserPage extends Page {
LinkButton.component({
href: app.route('settings'),
children: app.translator.trans('core.forum.user.settings_link'),
icon: 'fa fa-cog'
icon: 'fas fa-cog'
}),
-100
);

View File

@ -21,7 +21,7 @@ export default class WelcomeHero extends Component {
<header className="Hero WelcomeHero">
<div class="container">
{Button.component({
icon: 'fa fa-times',
icon: 'fas fa-times',
onclick: slideUp,
className: 'Hero-close Button Button--icon Button--link'
})}

View File

@ -24,7 +24,7 @@ export default function alertEmailConfirmation(app) {
url: app.forum.attribute('apiUrl') + '/users/' + user.id() + '/send-confirmation',
}).then(() => {
resendButton.props.loading = false;
resendButton.props.children = [icon('fa fa-check'), ' ', app.translator.trans('core.forum.user_email_confirmation.sent_message')];
resendButton.props.children = [icon('fas fa-check'), ' ', app.translator.trans('core.forum.user_email_confirmation.sent_message')];
resendButton.props.disabled = true;
m.redraw();
}).catch(() => {

View File

@ -55,12 +55,12 @@ export default {
items.add('reply',
!app.session.user || discussion.canReply()
? Button.component({
icon: 'fa fa-reply',
icon: 'fas fa-reply',
children: app.translator.trans(app.session.user ? 'core.forum.discussion_controls.reply_button' : 'core.forum.discussion_controls.log_in_to_reply_button'),
onclick: this.replyAction.bind(discussion, true, false)
})
: Button.component({
icon: 'fa fa-reply',
icon: 'fas fa-reply',
children: app.translator.trans('core.forum.discussion_controls.cannot_reply_button'),
className: 'disabled',
title: app.translator.trans('core.forum.discussion_controls.cannot_reply_text')
@ -85,7 +85,7 @@ export default {
if (discussion.canRename()) {
items.add('rename', Button.component({
icon: 'fa fa-pencil-alt',
icon: 'fas fa-pencil-alt',
children: app.translator.trans('core.forum.discussion_controls.rename_button'),
onclick: this.renameAction.bind(discussion)
}));
@ -117,7 +117,7 @@ export default {
} else {
if (discussion.canHide()) {
items.add('restore', Button.component({
icon: 'fa fa-reply',
icon: 'fas fa-reply',
children: app.translator.trans('core.forum.discussion_controls.restore_button'),
onclick: this.restoreAction.bind(discussion)
}));
@ -125,7 +125,7 @@ export default {
if (discussion.canDelete()) {
items.add('delete', Button.component({
icon: 'fa fa-times',
icon: 'fas fa-times',
children: app.translator.trans('core.forum.discussion_controls.delete_forever_button'),
onclick: this.deleteAction.bind(discussion)
}));

View File

@ -59,7 +59,7 @@ export default {
if (post.contentType() === 'comment' && post.canEdit()) {
if (!post.isHidden()) {
items.add('edit', Button.component({
icon: 'fa fa-pencil-alt',
icon: 'fas fa-pencil-alt',
children: app.translator.trans('core.forum.post_controls.edit_button'),
onclick: this.editAction.bind(post)
}));
@ -92,14 +92,14 @@ export default {
} else {
if (post.contentType() === 'comment' && post.canEdit()) {
items.add('restore', Button.component({
icon: 'fa fa-reply',
icon: 'fas fa-reply',
children: app.translator.trans('core.forum.post_controls.restore_button'),
onclick: this.restoreAction.bind(post)
}));
}
if (post.canDelete()) {
items.add('delete', Button.component({
icon: 'fa fa-times',
icon: 'fas fa-times',
children: app.translator.trans('core.forum.post_controls.delete_forever_button'),
onclick: this.deleteAction.bind(post, context)
}));

View File

@ -59,7 +59,7 @@ export default {
if (user.canEdit()) {
items.add('edit', Button.component({
icon: 'fa fa-pencil-alt',
icon: 'fas fa-pencil-alt',
children: app.translator.trans('core.forum.user_controls.edit_button'),
onclick: this.editAction.bind(user)
}));
@ -82,7 +82,7 @@ export default {
if (user.id() !== '1' && user.canDelete()) {
items.add('delete', Button.component({
icon: 'fa fa-times',
icon: 'fas fa-times',
children: app.translator.trans('core.forum.user_controls.delete_button'),
onclick: this.deleteAction.bind(user)
}));

View File

@ -37,7 +37,7 @@ export default class Alert extends Component {
if (dismissible || dismissible === undefined) {
dismissControl.push(
<Button
icon="fa fa-times"
icon="fas fa-times"
className="Button Button--link Button--icon Alert-dismiss"
onclick={ondismiss}/>
);

View File

@ -52,7 +52,7 @@ export default class Checkbox extends Component {
getDisplay() {
return this.loading
? LoadingIndicator.component({size: 'tiny'})
: icon(this.props.state ? 'fa fa-check' : 'fa fa-times');
: icon(this.props.state ? 'fas fa-check' : 'fas fa-times');
}
/**

View File

@ -26,7 +26,7 @@ export default class Dropdown extends Component {
props.buttonClassName = props.buttonClassName || '';
props.menuClassName = props.menuClassName || '';
props.label = props.label || '';
props.caretIcon = typeof props.caretIcon !== 'undefined' ? props.caretIcon : 'fa fa-caret-down';
props.caretIcon = typeof props.caretIcon !== 'undefined' ? props.caretIcon : 'fas fa-caret-down';
}
init() {

View File

@ -29,7 +29,7 @@ export default class Modal extends Component {
{this.isDismissible() ? (
<div className="Modal-close App-backControl">
{Button.component({
icon: 'fa fa-times',
icon: 'fas fa-times',
onclick: this.hide.bind(this),
className: 'Button Button--icon Button--link'
})}

View File

@ -52,7 +52,7 @@ export default class Navigation extends Component {
return LinkButton.component({
className: 'Button Navigation-back Button--icon',
href: history.backUrl(),
icon: 'fa fa-chevron-left',
icon: 'fas fa-chevron-left',
title: previous.title,
config: () => {},
onclick: e => {
@ -77,7 +77,7 @@ export default class Navigation extends Component {
return Button.component({
className: 'Button Button--icon Navigation-pin' + (pane.pinned ? ' active' : ''),
onclick: pane.togglePinned.bind(pane),
icon: 'fa fa-thumbtack'
icon: 'fas fa-thumbtack'
});
}
@ -100,7 +100,7 @@ export default class Navigation extends Component {
e.stopPropagation();
drawer.show();
},
icon: 'fa fa-bars'
icon: 'fas fa-bars'
});
}
}

View File

@ -18,7 +18,7 @@ export default class Select extends Component {
<select className="Select-input FormControl" onchange={onchange ? m.withAttr('value', onchange.bind(this)) : undefined} value={value}>
{Object.keys(options).map(key => <option value={key}>{options[key]}</option>)}
</select>
{icon('fa fa-sort', {className: 'Select-caret'})}
{icon('fas fa-sort', {className: 'Select-caret'})}
</span>
);
}

View File

@ -13,7 +13,7 @@ import icon from 'flarum/helpers/icon';
*/
export default class SelectDropdown extends Dropdown {
static initProps(props) {
props.caretIcon = typeof props.caretIcon !== 'undefined' ? props.caretIcon : 'fa fa-sort';
props.caretIcon = typeof props.caretIcon !== 'undefined' ? props.caretIcon : 'fas fa-sort';
super.initProps(props);

View File

@ -28,7 +28,7 @@ export default class SplitDropdown extends Dropdown {
className={'Dropdown-toggle Button Button--icon ' + this.props.buttonClassName}
data-toggle="dropdown">
{icon(this.props.icon, {className: 'Button-icon'})}
{icon('fa fa-caret-down', {className: 'Button-caret'})}
{icon('fas fa-caret-down', {className: 'Button-caret'})}
</button>
];
}

View File

@ -8,6 +8,6 @@ import icon from 'flarum/helpers/icon';
*/
export default function userOnline(user) {
if (user.lastSeenTime() && user.isOnline()) {
return <span className="UserOnline">{icon('fa fa-circle')}</span>;
return <span className="UserOnline">{icon('fas fa-circle')}</span>;
}
}

View File

@ -84,7 +84,7 @@ Object.assign(Discussion.prototype, {
const items = new ItemList();
if (this.isHidden()) {
items.add('hidden', <Badge type="hidden" icon="fa fa-trash" label={app.translator.trans('core.lib.badge.hidden_tooltip')}/>);
items.add('hidden', <Badge type="hidden" icon="fas fa-trash" label={app.translator.trans('core.lib.badge.hidden_tooltip')}/>);
}
return items;

View File

@ -119,22 +119,20 @@ class Application extends Container implements ApplicationContract
*
* @return bool
*/
public function isInstalled()
public function isInstalled(): bool
{
return $this->bound('flarum.config');
}
public function isUpToDate()
public function isUpToDate(): bool
{
$settings = $this->make(SettingsRepositoryInterface::class);
try {
$version = $settings->get('version');
} finally {
$isUpToDate = isset($version) && $version === $this->version();
return isset($version) && $version === $this->version();
}
return $isUpToDate;
}
/**

View File

@ -118,7 +118,7 @@ class Server
// (Right now it tries to resolve a database connection because of the injected settings repo instance)
// We could register a different settings repo when Flarum is not installed
//$pipe->pipe($this->app->make(HandleErrors::class, ['debug' => true]));
$pipe->pipe($this->app->make(StartSession::class));
//$pipe->pipe($this->app->make(StartSession::class));
$pipe->pipe($this->app->make(DispatchRoute::class, ['routes' => $this->app->make('flarum.install.routes')]));
return $pipe;

View File

@ -288,10 +288,10 @@ class InstallCommand extends AbstractCommand
Group::unguard();
$groups = [
[Group::ADMINISTRATOR_ID, 'Admin', 'Admins', '#B72A2A', 'fa fa-wrench'],
[Group::ADMINISTRATOR_ID, 'Admin', 'Admins', '#B72A2A', 'fas fa-wrench'],
[Group::GUEST_ID, 'Guest', 'Guests', null, null],
[Group::MEMBER_ID, 'Member', 'Members', null, null],
[Group::MODERATOR_ID, 'Mod', 'Mods', '#80349E', 'fa fa-bolt']
[Group::MODERATOR_ID, 'Mod', 'Mods', '#80349E', 'fas fa-bolt']
];
foreach ($groups as $group) {

View File

@ -0,0 +1,30 @@
<?php
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Flarum\Post\Event;
use Flarum\User\User;
class CheckingForFlooding
{
/**
* @var User
*/
public $actor;
/**
* @param User|null $actor
*/
public function __construct(User $actor = null)
{
$this->actor = $actor;
}
}

View File

@ -12,14 +12,26 @@
namespace Flarum\Post;
use DateTime;
use Flarum\Post\Event\CheckingForFlooding;
use Flarum\Post\Exception\FloodingException;
use Flarum\User\User;
use Illuminate\Contracts\Events\Dispatcher;
class Floodgate
{
/**
* @var Dispatcher
*/
protected $events;
public function __construct(Dispatcher $events)
{
$this->events = $events;
}
/**
* @param User $actor
* @throws \Flarum\Post\Exception\FloodingException
* @throws FloodingException
*/
public function assertNotFlooding(User $actor)
{
@ -32,8 +44,12 @@ class Floodgate
* @param User $actor
* @return bool
*/
public function isFlooding(User $actor)
public function isFlooding(User $actor): bool
{
return Post::where('user_id', $actor->id)->where('time', '>=', new DateTime('-10 seconds'))->exists();
$isFlooding = $this->events->until(
new CheckingForFlooding($actor)
);
return $isFlooding ?? Post::where('user_id', $actor->id)->where('time', '>=', new DateTime('-10 seconds'))->exists();
}
}

View File

@ -28,10 +28,10 @@ trait RetrievesAuthorizedUsers
public function getNormalUser()
{
User::unguard();
return User::firstOrCreate([
'username' => $this->userAttributes['username']
], $this->userAttributes);
User::unguarded(function () {
return User::firstOrCreate([
'username' => $this->userAttributes['username']
], $this->userAttributes);
});
}
}