Skip to content

Commit

Permalink
FEATURE: suppress interested and not going buttons by default (#621)
Browse files Browse the repository at this point in the history
Interested and not going are generally not used.

To avoid adding this clutter to the UI we now suppress this.

Sites wishing to have these buttons can amend the `event_participation_buttons` site setting

Also:

- Add a show participants button even if there are no participants (so admins can populate events)
- Fix localization for event participation
- Allow toggling attendance by pressing the same button
- Removes leave event button from the dropdown menu
- Refactors outlets to allow maximum flexibility

---------

Co-authored-by: Joffrey JAFFEUX <[email protected]>
  • Loading branch information
SamSaffron and jjaffeux authored Oct 22, 2024
1 parent ef3e3cb commit b9fc1bd
Show file tree
Hide file tree
Showing 12 changed files with 363 additions and 244 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import Component from "@glimmer/component";
import avatar from "discourse/helpers/avatar";
import { formatUsername } from "discourse/lib/utilities";
import i18n from "discourse-common/helpers/i18n";

export default class DiscoursePostEventCreator extends Component {
get username() {
return this.args.user.name || formatUsername(this.args.user.username);
}

<template>
<span class="event-creator">
<a class="topic-invitee-avatar" data-user-card={{@user.username}}>
{{avatar @user imageSize="tiny"}}
<span class="username">{{this.username}}</span>
</a>
<span class="creators">
<span class="created-by">{{i18n
"discourse_calendar.discourse_post_event.event_ui.created_by"
}}</span>

<span class="event-creator">
<a class="topic-invitee-avatar" data-user-card={{@user.username}}>
{{avatar @user imageSize="tiny"}}
<span class="username">{{this.username}}</span>
</a>
</span>
</span>
</template>
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export default class DiscoursePostEventDates extends Component {

<template>
<section
class="event-dates"
class="event__section event-dates"
{{didInsert this.computeDates}}
>{{this.htmlDates}}</section>
</template>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Component from "@glimmer/component";
import i18n from "discourse-common/helpers/i18n";

export default class EventStatus extends Component {
get eventStatusLabel() {
return i18n(
`discourse_calendar.discourse_post_event.models.event.status.${this.args.event.status}.title`
);
}

get eventStatusDescription() {
return i18n(
`discourse_calendar.discourse_post_event.models.event.status.${this.args.event.status}.description`
);
}

get statusClass() {
return `status ${this.args.event.status}`;
}

<template>
{{#if @event.isExpired}}
<span class="status expired">
{{i18n "discourse_calendar.discourse_post_event.models.event.expired"}}
</span>
{{else if @event.isClosed}}
<span class="status closed">
{{i18n "discourse_calendar.discourse_post_event.models.event.closed"}}
</span>
{{else}}
<span class={{this.statusClass}} title={{this.eventStatusDescription}}>
{{this.eventStatusLabel}}
</span>
{{/if}}
</template>
}
131 changes: 37 additions & 94 deletions assets/javascripts/discourse/components/discourse-post-event/index.gjs
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
import Component from "@glimmer/component";
import { hash } from "@ember/helper";
import { service } from "@ember/service";
import { htmlSafe } from "@ember/template";
import { modifier } from "ember-modifier";
import PluginOutlet from "discourse/components/plugin-outlet";
import concatClass from "discourse/helpers/concat-class";
import routeAction from "discourse/helpers/route-action";
import { emojiUnescape } from "discourse/lib/text";
import { escapeExpression } from "discourse/lib/utilities";
import i18n from "discourse-common/helpers/i18n";
import icon from "discourse-common/helpers/d-icon";
import Creator from "./creator";
import Dates from "./dates";
import EventStatus from "./event-status";
import Invitees from "./invitees";
import MoreMenu from "./more-menu";
import Status from "./status";
import Url from "./url";

const Separator = <template><span class="separator">·</span></template>;
const StatusSeparator = <template><span class="separator">·</span></template>;

const InfoSection = <template>
<section class="event__section" ...attributes>
{{#if @icon}}
{{icon @icon}}
{{/if}}

{{yield}}
</section>
</template>;

export default class DiscoursePostEvent extends Component {
@service currentUser;
Expand All @@ -34,18 +44,6 @@ export default class DiscoursePostEvent extends Component {
return () => this.messageBus.unsubscribe(path);
});

get eventStatusLabel() {
return i18n(
`discourse_calendar.discourse_post_event.models.event.status.${this.args.event.status}.title`
);
}

get eventStatusDescription() {
return i18n(
`discourse_calendar.discourse_post_event.models.event.status.${this.args.event.status}.description`
);
}

get startsAtMonth() {
return moment(this.args.event.startsAt).format("MMM");
}
Expand All @@ -60,10 +58,6 @@ export default class DiscoursePostEvent extends Component {
);
}

get statusClass() {
return `status ${this.args.event.status}`;
}

get isPublicEvent() {
return this.args.event.status === "public";
}
Expand All @@ -76,39 +70,12 @@ export default class DiscoursePostEvent extends Component {
return this.currentUser && this.args.event.can_act_on_discourse_post_event;
}

get containerHeight() {
const datesHeight = 50;
const urlHeight = 50;
const headerHeight = 75;
const bordersHeight = 10;
const separatorsHeight = 4;
const margins = 10;

let widgetHeight =
datesHeight + headerHeight + bordersHeight + separatorsHeight + margins;

if (this.args.event.shouldDisplayInvitees && !this.args.event.minimal) {
widgetHeight += 110;
}

if (this.args.event.canUpdateAttendance) {
widgetHeight += 60;
}

if (this.args.event.url) {
widgetHeight += urlHeight;
}

return htmlSafe(`height: ${widgetHeight}px`);
}

<template>
<div
class={{concatClass
"discourse-post-event"
(if @event "is-loaded" "is-loading")
}}
style={{this.containerHeight}}
>
<div class="discourse-post-event-widget">
{{#if @event}}
Expand All @@ -123,39 +90,18 @@ export default class DiscoursePostEvent extends Component {
</span>
<div class="status-and-creators">
<PluginOutlet
@name="discourse-post-event-status"
@outletArgs={{hash event=@event Separator=Separator}}
@name="discourse-post-event-status-and-creators"
@outletArgs={{hash
event=@event
Separator=StatusSeparator
Status=(component EventStatus event=@event)
Creator=(component Creator user=@event.creator)
}}
>
{{#if @event.isExpired}}
<span class="status expired">
{{i18n
"discourse_calendar.discourse_post_event.models.event.expired"
}}
</span>
{{else if @event.isClosed}}
<span class="status closed">
{{i18n
"discourse_calendar.discourse_post_event.models.event.closed"
}}
</span>
{{else}}
<span
class={{this.statusClass}}
title={{this.eventStatusDescription}}
>
{{this.eventStatusLabel}}
</span>
{{/if}}
</PluginOutlet>

<Separator />

<span class="creators">
<span class="created-by">{{i18n
"discourse_calendar.discourse_post_event.event_ui.created_by"
}}</span>
<EventStatus @event={{@event}} />
<StatusSeparator />
<Creator @user={{@event.creator}} />
</span>
</PluginOutlet>
</div>
</div>

Expand All @@ -166,28 +112,25 @@ export default class DiscoursePostEvent extends Component {
</header>

{{#if @event.canUpdateAttendance}}
<section class="event-actions">
<section class="event__section event-actions">
<Status @event={{@event}} />
</section>
{{/if}}

{{#if @event.url}}
<hr />

<PluginOutlet
@name="discourse-post-event-info"
@outletArgs={{hash
event=@event
Section=(component InfoSection event=@event)
Url=(component Url url=@event.url)
Dates=(component Dates event=@event)
Invitees=(component Invitees event=@event)
}}
>
<Url @url={{@event.url}} />
{{/if}}

<hr />

<Dates @event={{@event}} />

{{#unless @event.minimal}}
{{#if @event.shouldDisplayInvitees}}
<hr />

<Invitees @event={{@event}} />
{{/if}}
{{/unless}}
<Dates @event={{@event}} />
<Invitees @event={{@event}} />
</PluginOutlet>
{{/if}}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Invitee from "./invitee";

export default class DiscoursePostEventInvitees extends Component {
@service modal;
@service siteSettings;

@action
showAllInvitees() {
Expand All @@ -20,43 +21,62 @@ export default class DiscoursePostEventInvitees extends Component {
});
}

get statsInfo() {
const stats = [];
const visibleStats = this.siteSettings.event_participation_buttons
.split("|")
.filter(Boolean);

if (this.args.event.isPrivate) {
visibleStats.push("invited");
}

visibleStats.forEach((button) => {
const localeKey = button.replace(" ", "_");
if (button === "not_going") {
button = "notGoing";
}

const count = this.args.event.stats[button] || 0;

const label = i18n(
`discourse_calendar.discourse_post_event.models.invitee.status.${localeKey}_count`,
{ count }
);

stats.push({
class: `event-status-${localeKey}`,
label,
});
});

return stats;
}

<template>
<section class="event-invitees">
<div class="header">
<div class="event-invitees-status">
<span>{{@event.stats.going}}
{{i18n
"discourse_calendar.discourse_post_event.models.invitee.status.going"
}}
-</span>
<span>{{@event.stats.interested}}
{{i18n
"discourse_calendar.discourse_post_event.models.invitee.status.interested"
}}
-</span>
<span>{{@event.stats.notGoing}}
{{i18n
"discourse_calendar.discourse_post_event.models.invitee.status.not_going"
}}</span>
{{#if @event.isPrivate}}
<span class="invited">- on
{{@event.stats.invited}}
users invited</span>
{{/if}}
</div>

<DButton
class="show-all btn-small"
@label="discourse_calendar.discourse_post_event.event_ui.show_all"
@action={{this.showAllInvitees}}
/>

</div>
<ul class="event-invitees-avatars">
{{#each @event.sampleInvitees as |invitee|}}
<Invitee @invitee={{invitee}} />
{{/each}}
</ul>
</section>
{{#unless @event.minimal}}
{{#if @event.shouldDisplayInvitees}}
<section class="event__section event-invitees">
<div class="header">
<div class="event-invitees-status">
{{#each this.statsInfo as |info|}}
<span class={{info.class}}>{{info.label}}</span>
{{/each}}
</div>

<DButton
class="show-all btn-small"
@label="discourse_calendar.discourse_post_event.event_ui.show_all"
@action={{this.showAllInvitees}}
/>
</div>
<ul class="event-invitees-avatars">
{{#each @event.sampleInvitees as |invitee|}}
<Invitee @invitee={{invitee}} />
{{/each}}
</ul>
</section>
{{/if}}
{{/unless}}
</template>
}
Loading

0 comments on commit b9fc1bd

Please sign in to comment.