Skip to content

Commit

Permalink
fix: messages inconsistencies (#4174)
Browse files Browse the repository at this point in the history
* fix: messages inconsistencies

* fix

* chore: message at the page

* fix: permission grid styling broken

* fix
  • Loading branch information
SychO9 authored Jan 31, 2025
1 parent 7136ad0 commit 89ff984
Show file tree
Hide file tree
Showing 15 changed files with 97 additions and 40 deletions.
2 changes: 1 addition & 1 deletion extensions/messages/extend.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
(new Extend\ApiResource(Resource\UserResource::class))
->fields(fn () => [
Schema\Boolean::make('canSendAnyMessage')
->get(fn (object $model, Context $context) => $context->getActor()->can('sendAnyMessage')),
->get(fn (User $user, Context $context) => $user->can('sendAnyMessage')),
Schema\Integer::make('messageCount')
->get(function (object $model, Context $context) {
return Dialog::whereVisibleTo($context->getActor())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@ declare module 'flarum/forum/states/ComposerState' {
composingMessageTo(dialog: Dialog): boolean;
}
}

declare module 'flarum/common/models/User' {
export default interface User {
canSendAnyMessage(): boolean;
}
}
4 changes: 4 additions & 0 deletions extensions/messages/js/src/common/extend.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import DialogMessage from './models/DialogMessage';
import Dialog from './models/Dialog';
import Extend from 'flarum/common/extenders';
import User from 'flarum/common/models/User';

export default [
new Extend.Store()
.add('dialogs', Dialog) //
.add('dialog-messages', DialogMessage), //

new Extend.Model(User) //
.attribute<boolean>('canSendAnyMessage'),
];
13 changes: 8 additions & 5 deletions extensions/messages/js/src/forum/components/DialogSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,14 @@ export default class DialogSection<CustomAttrs extends IDialogStreamAttrs = IDia
<div className="DialogSection-header">
<Avatar user={recipient} />
<div className="DialogSection-header-info">
{(recipient && (
<Link href={app.route.user(recipient!)}>
<h2>{username(recipient)}</h2>
</Link>
)) || <h2>{username(recipient)}</h2>}
<h2 className="DialogSection-header-info-title">
{(recipient && <Link href={app.route.user(recipient!)}>{username(recipient)}</Link>) || username(recipient)}
{recipient && recipient.canSendAnyMessage() ? null : (
<span className="DialogSection-header-info-helperText">
{app.translator.trans('flarum-messages.forum.dialog_section.cannot_reply_text')}
</span>
)}
</h2>
<div className="badges">{listItems(recipient?.badges().toArray() || [])}</div>
</div>
<div className="DialogSection-header-actions">{this.actionItems().toArray()}</div>
Expand Down
4 changes: 2 additions & 2 deletions extensions/messages/js/src/forum/components/MessageStream.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ export default class MessageStream<CustomAttrs extends IDialogStreamAttrs = IDia

messages.forEach((message, index) => items.push(this.messageItem(message, index)));

if (ReplyPlaceholder) {
if (app.session.user!.canSendAnyMessage() && ReplyPlaceholder) {
items.push(
<div className="MessageStream-item" key="reply" /*data-index={this.attrs.state.count()}*/>
<div className="MessageStream-item" key="reply">
<ReplyPlaceholder
discussion={this.attrs.dialog}
onclick={() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ export default class MessagesSidebar<CustomAttrs extends IMessagesSidebarAttrs =
items(): ItemList<Mithril.Children> {
const items = super.items();

const canSendAnyMessage = app.session.user!.attribute<boolean>('canSendAnyMessage');

items.remove('newDiscussion');

items.add(
Expand All @@ -27,9 +25,11 @@ export default class MessagesSidebar<CustomAttrs extends IMessagesSidebarAttrs =
onclick={() => {
return this.newMessageAction();
}}
disabled={!canSendAnyMessage}
disabled={!app.session.user!.canSendAnyMessage()}
>
{app.translator.trans('flarum-messages.forum.messages_page.new_message_button')}
{app.session.user!.canSendAnyMessage()
? app.translator.trans('flarum-messages.forum.messages_page.send_message_button')
: app.translator.trans('flarum-messages.forum.messages_page.cannot_send_message_button')}
</Button>,
10
);
Expand Down
8 changes: 5 additions & 3 deletions extensions/messages/js/src/forum/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Button from 'flarum/common/components/Button';
import type Dialog from '../common/models/Dialog';
import DialogsDropdown from './components/DialogsDropdown';
import DialogListState from './states/DialogListState';
import type User from 'flarum/common/models/User';

export { default as extend } from './extend';

Expand Down Expand Up @@ -44,14 +45,14 @@ app.initializers.add('flarum-messages', () => {
});

extend(HeaderSecondary.prototype, 'items', function (items) {
if (app.session.user?.attribute<boolean>('canSendAnyMessage')) {
if (app.session.user?.canSendAnyMessage()) {
items.add('messages', <DialogsDropdown state={app.dropdownDialogs} />, 15);
}
});

// @ts-ignore
extend(UserControls, 'userControls', (items, user) => {
if (app.session.user?.attribute<boolean>('canSendAnyMessage')) {
extend(UserControls, 'userControls', (items, user: User) => {
if (app.session.user?.canSendAnyMessage()) {
items.add(
'sendMessage',
<Button
Expand All @@ -66,6 +67,7 @@ app.initializers.add('flarum-messages', () => {
.then(() => app.composer.show());
});
}}
helperText={user.canSendAnyMessage() ? null : app.translator.trans('flarum-messages.forum.user_controls.cannot_reply_text')}
>
{app.translator.trans('flarum-messages.forum.user_controls.send_message_button')}
</Button>
Expand Down
11 changes: 11 additions & 0 deletions extensions/messages/less/forum.less
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,17 @@
gap: 6px;
}

.DialogSection-header-info-title {
display: flex;
flex-direction: column;
}

.DialogSection-header-info-helperText {
font-size: 0.8rem;
font-weight: normal;
color: var(--control-color);
}

.DialogSection-back {
display: flex;

Expand Down
8 changes: 5 additions & 3 deletions extensions/messages/locale/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ flarum-messages:

dialog_section:
back_label: Go back
cannot_reply_text: This user cannot reply
controls:
details_button: Details
controls_toggle_label: Dialog control actions
Expand All @@ -42,14 +43,14 @@ flarum-messages:
oldest_button: Oldest

messages_page:
empty_text: You have no messages yet. When you send or receive messages, they
will appear here.
cannot_send_message_button: Can't Send a Message
empty_text: No new messages
hero:
title: Messages
subtitle: Your private conversations with other users
mark_all_as_read_tooltip: Mark all as read
new_message_button: Send a Message
refresh_tooltip: Refresh
send_message_button: Send a Message
stream:
load_previous_button: Load previous messages
start_of_the_conversation: Start of the conversation
Expand All @@ -64,6 +65,7 @@ flarum-messages:

user_controls:
send_message_button: Send a message
cannot_reply_text: This user cannot reply

notifications:
message_received_text: Message Received notification from {user}
Expand Down
6 changes: 3 additions & 3 deletions extensions/tags/js/src/admin/addTagsPermissionScope.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,14 @@ export default function () {
'tag',
<Dropdown
className="Dropdown--restrictByTag"
buttonClassName="Button Button--text"
buttonClassName="Button Button--link"
label={app.translator.trans('flarum-tags.admin.permissions.restrict_by_tag_heading')}
icon="fas fa-plus"
caretIcon={null}
>
{tags.map((tag) => (
<Button icon={true} onclick={() => tag.save({ isRestricted: true })}>
{[tagIcon(tag, { className: 'Button-icon' }), ' ', tag.name()]}
<Button icon={tagIcon(tag, { className: 'Button-icon' })} onclick={() => tag.save({ isRestricted: true })}>
{tag.name()}
</Button>
))}
</Dropdown>
Expand Down
28 changes: 23 additions & 5 deletions framework/core/js/src/common/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ export interface IButtonAttrs extends ComponentAttrs {
* Class(es) of an optional icon to be rendered within the button.
*
* If provided, the button will gain a `has-icon` class.
*
* You may also provide a rendered icon element directly.
*/
icon?: string;
icon?: string | boolean | Mithril.Children;
/**
* Disables button from user input.
*
Expand Down Expand Up @@ -42,6 +44,12 @@ export interface IButtonAttrs extends ComponentAttrs {
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type
*/
type?: string;
/**
* Helper text. Displayed under the button label.
*
* Default: `null`
*/
helperText?: Mithril.Children;
}

/**
Expand All @@ -56,7 +64,7 @@ export interface IButtonAttrs extends ComponentAttrs {
*/
export default class Button<CustomAttrs extends IButtonAttrs = IButtonAttrs> extends Component<CustomAttrs> {
view(vnode: Mithril.VnodeDOM<CustomAttrs, this>) {
let { type, 'aria-label': ariaLabel, icon: iconName, disabled, loading, className, class: _class, ...attrs } = this.attrs;
let { type, 'aria-label': ariaLabel, icon: iconName, disabled, loading, className, class: _class, helperText, ...attrs } = this.attrs;

// If no `type` attr provided, set to "button"
type ||= 'button';
Expand All @@ -74,6 +82,7 @@ export default class Button<CustomAttrs extends IButtonAttrs = IButtonAttrs> ext
hasIcon: iconName,
disabled: disabled || loading,
loading: loading,
hasSubContent: !!this.getButtonSubContent(),
});

const buttonAttrs = {
Expand Down Expand Up @@ -104,12 +113,21 @@ export default class Button<CustomAttrs extends IButtonAttrs = IButtonAttrs> ext
* Get the template for the button's content.
*/
protected getButtonContent(children: Mithril.Children): Mithril.ChildArray {
const iconName = this.attrs.icon;
const icon = this.attrs.icon;

return [
iconName && <Icon name={iconName} className="Button-icon" />,
children && <span className="Button-label">{children}</span>,
icon && (typeof icon === 'string' || icon === true ? <Icon name={icon} className="Button-icon" /> : icon),
children && (
<span className="Button-label">
<span className="Button-labelText">{children}</span>
{this.getButtonSubContent()}
</span>
),
this.attrs.loading && <LoadingIndicator size="small" display="inline" />,
];
}

protected getButtonSubContent(): Mithril.Children {
return this.attrs.helperText ? <span className="Button-helperText">{this.attrs.helperText}</span> : null;
}
}
11 changes: 10 additions & 1 deletion framework/core/js/src/common/components/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export interface IDropdownAttrs extends ComponentAttrs {
caretIcon?: string;
/** The label of the dropdown toggle button. Defaults to 'Controls'. */
label: Mithril.Children;
/** The helper text to display under the button label. */
helperText: Mithril.Children;
/** The label used to describe the dropdown toggle button to assistive readers. Defaults to 'Toggle dropdown menu'. */
accessibleToggleLabel?: string;
/** An optional tooltip to show when hovering over the dropdown toggle button. */
Expand Down Expand Up @@ -157,11 +159,18 @@ export default class Dropdown<CustomAttrs extends IDropdownAttrs = IDropdownAttr
getButtonContent(children: Mithril.ChildArray): Mithril.ChildArray {
return [
this.attrs.icon ? <Icon name={this.attrs.icon} className="Button-icon" /> : '',
<span className="Button-label">{this.attrs.label}</span>,
<span className="Button-label">
<span className="Button-labelText">{this.attrs.label}</span>
{this.getButtonSubContent()}
</span>,
this.attrs.caretIcon ? <Icon name={this.attrs.caretIcon} className="Button-caret" /> : '',
];
}

protected getButtonSubContent(): Mithril.Children {
return this.attrs.helperText ? <span className="Button-helperText">{this.attrs.helperText}</span> : null;
}

getMenu(items: Mithril.Vnode<any, any>[]): Mithril.Vnode<any, any> {
return <ul className={'Dropdown-menu dropdown-menu ' + this.attrs.menuClassName}>{items}</ul>;
}
Expand Down
16 changes: 4 additions & 12 deletions framework/core/less/admin/PermissionsPage.less
Original file line number Diff line number Diff line change
Expand Up @@ -94,23 +94,19 @@
}
}
.Dropdown {
display: block;

.Dropdown-toggle {
width: 100%;
display: block;
text-align: left;
float: none;
margin: -2px 0;
}
.Dropdown-menu {
margin: 0;
margin: 6px 0 0;
}
}
.Button {
text-decoration: none;

.Badge {
margin: -3px 2px -3px 0;
margin: 0 2px 0 0;
}
}
td:not(:hover) .Select-caret,
Expand All @@ -126,12 +122,8 @@
margin: -1px 0;
}
.PermissionDropdown {
.Dropdown-toggle {
padding: 5px 0;
margin: -5px 0;
}
.Badge {
margin: -3px 3px -3px 0;
margin: 0 3px 0 0;
box-shadow: none;
}
}
Expand Down
6 changes: 6 additions & 0 deletions framework/core/less/common/Button.less
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,12 @@
line-height: inherit;
overflow: hidden;
text-overflow: ellipsis;
display: flex;
flex-direction: column;
}
.Button-helperText {
font-size: 0.73rem;
color: var(--muted-more-color);
}
.Button-icon {
line-height: inherit;
Expand Down
6 changes: 5 additions & 1 deletion framework/core/less/common/Dropdown.less
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
> a, > button, > span {
padding: 8px 15px;
display: flex;
align-items: center;
gap: 9px;
align-items: center;
width: 100%;
color: var(--text-color);
border-radius: 0;
Expand All @@ -51,6 +51,10 @@
flex-shrink: 0;
}

&.hasSubContent {
align-items: flex-start;
}

&.disabled {
opacity: 0.4;
background: none !important;
Expand Down

0 comments on commit 89ff984

Please sign in to comment.