mirror of
https://github.com/discourse/discourse.git
synced 2025-03-01 08:49:20 +00:00
DEV: convert PrivateMessageMap widget to glimmer components (#25837)
* DEV: add map system test for private message map * DEV: convert PrivateMessageMap to glimmer components
This commit is contained in:
parent
13230ae4c2
commit
1a76c4e099
@ -0,0 +1,215 @@
|
|||||||
|
import Component from "@glimmer/component";
|
||||||
|
import { tracked } from "@glimmer/tracking";
|
||||||
|
import { hash } from "@ember/helper";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
import { inject as service } from "@ember/service";
|
||||||
|
import DButton from "discourse/components/d-button";
|
||||||
|
import avatar from "discourse/helpers/bound-avatar-template";
|
||||||
|
import { groupPath } from "discourse/lib/url";
|
||||||
|
import dIcon from "discourse-common/helpers/d-icon";
|
||||||
|
import I18n from "discourse-i18n";
|
||||||
|
import and from "truth-helpers/helpers/and";
|
||||||
|
|
||||||
|
export default class PrivateMessageMap extends Component {
|
||||||
|
@service site;
|
||||||
|
@tracked isEditing = false;
|
||||||
|
|
||||||
|
get participantsClasses() {
|
||||||
|
return !this.isEditing &&
|
||||||
|
this.site.mobileView &&
|
||||||
|
this.args.postAttrs.allowedGroups.length > 4
|
||||||
|
? "participants hide-names"
|
||||||
|
: "participants";
|
||||||
|
}
|
||||||
|
|
||||||
|
get canInvite() {
|
||||||
|
return this.args.postAttrs.canInvite;
|
||||||
|
}
|
||||||
|
|
||||||
|
get canRemove() {
|
||||||
|
return (
|
||||||
|
this.args.postAttrs.canRemoveAllowedUsers ||
|
||||||
|
this.args.postAttrs.canRemoveSelfId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get canShowControls() {
|
||||||
|
return this.canInvite || this.canRemove;
|
||||||
|
}
|
||||||
|
|
||||||
|
get actionAllowed() {
|
||||||
|
return this.canRemove ? this.toggleEditing : this.args.showInvite;
|
||||||
|
}
|
||||||
|
|
||||||
|
get actionAllowedLabel() {
|
||||||
|
if (this.canInvite && this.canRemove) {
|
||||||
|
return "private_message_info.edit";
|
||||||
|
}
|
||||||
|
if (!this.canInvite && this.canRemove) {
|
||||||
|
return "private_message_info.remove";
|
||||||
|
}
|
||||||
|
return "private_message_info.add";
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
toggleEditing() {
|
||||||
|
this.isEditing = !this.isEditing;
|
||||||
|
}
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class={{this.participantsClasses}}>
|
||||||
|
{{#each @postAttrs.allowedGroups as |group|}}
|
||||||
|
<PmMapUserGroup
|
||||||
|
@model={{group}}
|
||||||
|
@isEditing={{this.isEditing}}
|
||||||
|
@canRemoveAllowedUsers={{@postAttrs.canRemoveAllowedUsers}}
|
||||||
|
@removeAllowedGroup={{@removeAllowedGroup}}
|
||||||
|
/>
|
||||||
|
{{/each}}
|
||||||
|
{{#each @postAttrs.allowedUsers as |user|}}
|
||||||
|
<PmMapUser
|
||||||
|
@model={{user}}
|
||||||
|
@isEditing={{this.isEditing}}
|
||||||
|
@canRemoveAllowedUsers={{@postAttrs.canRemoveAllowedUsers}}
|
||||||
|
@canRemoveSelfId={{@postAttrs.canRemoveSelfId}}
|
||||||
|
@removeAllowedUser={{@removeAllowedUser}}
|
||||||
|
/>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if this.canShowControls}}
|
||||||
|
<div class="controls">
|
||||||
|
<DButton
|
||||||
|
@action={{this.actionAllowed}}
|
||||||
|
@label={{this.actionAllowedLabel}}
|
||||||
|
class="btn-default add-remove-participant-btn"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{{#if (and this.canInvite this.isEditing)}}
|
||||||
|
<DButton
|
||||||
|
@action={{@showInvite}}
|
||||||
|
@icon="plus"
|
||||||
|
class="btn-default add-participant-btn"
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</template>
|
||||||
|
}
|
||||||
|
|
||||||
|
class PmMapUserGroup extends Component {
|
||||||
|
get canRemoveLink() {
|
||||||
|
return this.args.isEditing && this.args.canRemoveAllowedUsers;
|
||||||
|
}
|
||||||
|
|
||||||
|
get groupUrl() {
|
||||||
|
return groupPath(this.args.model.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="user group">
|
||||||
|
<a href={{this.groupUrl}} class="group-link">
|
||||||
|
{{dIcon "users"}}
|
||||||
|
<span class="group-name">{{@model.name}}</span>
|
||||||
|
</a>
|
||||||
|
{{#if this.canRemoveLink}}
|
||||||
|
<PmRemoveGroupLink
|
||||||
|
@model={{@model}}
|
||||||
|
@removeAllowedGroup={{@removeAllowedGroup}}
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
}
|
||||||
|
|
||||||
|
class PmRemoveGroupLink extends Component {
|
||||||
|
@service dialog;
|
||||||
|
|
||||||
|
@action
|
||||||
|
showConfirmDialog() {
|
||||||
|
this.dialog.deleteConfirm({
|
||||||
|
message: I18n.t("private_message_info.remove_allowed_group", {
|
||||||
|
name: this.args.model.name,
|
||||||
|
}),
|
||||||
|
confirmButtonLabel: "private_message_info.remove_group",
|
||||||
|
didConfirm: () => this.args.removeAllowedGroup(this.args.model),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DButton
|
||||||
|
class="remove-invited"
|
||||||
|
@action={{this.showConfirmDialog}}
|
||||||
|
@icon="times"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
}
|
||||||
|
|
||||||
|
class PmMapUser extends Component {
|
||||||
|
get avatarTitle() {
|
||||||
|
return this.args.model.name || this.args.model.username;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isCurrentUser() {
|
||||||
|
return this.args.canRemoveSelfId === this.args.model.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
get canRemoveLink() {
|
||||||
|
return (
|
||||||
|
this.args.isEditing &&
|
||||||
|
(this.args.canRemoveAllowedUsers || this.isCurrentUser)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="user">
|
||||||
|
<a class="user-link" href={{@model.path}}>
|
||||||
|
<a
|
||||||
|
class="trigger-user-card"
|
||||||
|
data-user-card={{@model.username}}
|
||||||
|
title={{@model.username}}
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
{{avatar @model.avatar_template "tiny" (hash title=this.avatarTitle)}}
|
||||||
|
</a>
|
||||||
|
<span class="username">{{@model.username}}</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
{{#if this.canRemoveLink}}
|
||||||
|
<PmRemoveLink
|
||||||
|
@model={{@model}}
|
||||||
|
@isCurrentUser={{this.isCurrentUser}}
|
||||||
|
@removeAllowedUser={{@removeAllowedUser}}
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
}
|
||||||
|
|
||||||
|
class PmRemoveLink extends Component {
|
||||||
|
@service dialog;
|
||||||
|
|
||||||
|
@action
|
||||||
|
showConfirmDialog() {
|
||||||
|
const messageKey = this.args.isCurrentUser
|
||||||
|
? "private_message_info.leave_message"
|
||||||
|
: "private_message_info.remove_allowed_user";
|
||||||
|
|
||||||
|
this.dialog.deleteConfirm({
|
||||||
|
message: I18n.t(messageKey, {
|
||||||
|
name: this.args.model.username,
|
||||||
|
}),
|
||||||
|
confirmButtonLabel: this.args.isCurrentUser
|
||||||
|
? "private_message_info.leave"
|
||||||
|
: "private_message_info.remove_user",
|
||||||
|
didConfirm: () => this.args.removeAllowedUser(this.args.model),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
<template>
|
||||||
|
<DButton
|
||||||
|
class="remove-invited"
|
||||||
|
@action={{this.showConfirmDialog}}
|
||||||
|
@icon="times"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
}
|
@ -1,203 +0,0 @@
|
|||||||
import { h } from "virtual-dom";
|
|
||||||
import hbs from "discourse/widgets/hbs-compiler";
|
|
||||||
import { avatarFor, avatarImg } from "discourse/widgets/post";
|
|
||||||
import { createWidget } from "discourse/widgets/widget";
|
|
||||||
import getURL from "discourse-common/lib/get-url";
|
|
||||||
import { makeArray } from "discourse-common/lib/helpers";
|
|
||||||
import I18n from "discourse-i18n";
|
|
||||||
|
|
||||||
createWidget("pm-remove-group-link", {
|
|
||||||
tagName: "a.remove-invited.no-text.btn-icon.btn",
|
|
||||||
template: hbs`{{d-icon "times"}}`,
|
|
||||||
services: ["dialog"],
|
|
||||||
|
|
||||||
click() {
|
|
||||||
this.dialog.deleteConfirm({
|
|
||||||
message: I18n.t("private_message_info.remove_allowed_group", {
|
|
||||||
name: this.attrs.name,
|
|
||||||
}),
|
|
||||||
confirmButtonLabel: "private_message_info.remove_group",
|
|
||||||
didConfirm: () => this.sendWidgetAction("removeAllowedGroup", this.attrs),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
createWidget("pm-map-user-group", {
|
|
||||||
tagName: "div.user.group",
|
|
||||||
|
|
||||||
transform(attrs) {
|
|
||||||
return { href: getURL(`/g/${attrs.group.name}`) };
|
|
||||||
},
|
|
||||||
|
|
||||||
template: hbs`
|
|
||||||
<a href={{transformed.href}} class="group-link">
|
|
||||||
{{d-icon "users"}}
|
|
||||||
<span class="group-name">{{attrs.group.name}}</span>
|
|
||||||
</a>
|
|
||||||
{{#if attrs.isEditing}}
|
|
||||||
{{#if attrs.canRemoveAllowedUsers}}
|
|
||||||
{{pm-remove-group-link attrs=attrs.group}}
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
`,
|
|
||||||
});
|
|
||||||
|
|
||||||
createWidget("pm-remove-link", {
|
|
||||||
tagName: "a.remove-invited.no-text.btn-icon.btn",
|
|
||||||
template: hbs`{{d-icon "times"}}`,
|
|
||||||
services: ["dialog"],
|
|
||||||
|
|
||||||
click() {
|
|
||||||
const messageKey = this.attrs.isCurrentUser
|
|
||||||
? "leave_message"
|
|
||||||
: "remove_allowed_user";
|
|
||||||
|
|
||||||
this.dialog.deleteConfirm({
|
|
||||||
message: I18n.t(`private_message_info.${messageKey}`, {
|
|
||||||
name: this.attrs.user.username,
|
|
||||||
}),
|
|
||||||
confirmButtonLabel: this.attrs.isCurrentUser
|
|
||||||
? "private_message_info.leave"
|
|
||||||
: "private_message_info.remove_user",
|
|
||||||
didConfirm: () =>
|
|
||||||
this.sendWidgetAction("removeAllowedUser", this.attrs.user),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
createWidget("pm-map-user", {
|
|
||||||
tagName: "div.user",
|
|
||||||
|
|
||||||
html(attrs) {
|
|
||||||
const user = attrs.user;
|
|
||||||
const username = h("span.username", user.username);
|
|
||||||
|
|
||||||
let link;
|
|
||||||
|
|
||||||
if (this.site && this.site.mobileView) {
|
|
||||||
const avatar = avatarImg("tiny", {
|
|
||||||
template: user.avatar_template,
|
|
||||||
username: user.username,
|
|
||||||
});
|
|
||||||
link = h("a", { attributes: { href: user.get("path") } }, [
|
|
||||||
avatar,
|
|
||||||
username,
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
const avatar = avatarFor("tiny", {
|
|
||||||
template: user.avatar_template,
|
|
||||||
username: user.username,
|
|
||||||
});
|
|
||||||
|
|
||||||
link = h(
|
|
||||||
"a",
|
|
||||||
{ attributes: { class: "user-link", href: user.get("path") } },
|
|
||||||
[avatar, username]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = [link];
|
|
||||||
const isCurrentUser = attrs.canRemoveSelfId === user.get("id");
|
|
||||||
|
|
||||||
if (attrs.isEditing && (attrs.canRemoveAllowedUsers || isCurrentUser)) {
|
|
||||||
result.push(this.attach("pm-remove-link", { user, isCurrentUser }));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default createWidget("private-message-map", {
|
|
||||||
tagName: "section.information.private-message-map",
|
|
||||||
|
|
||||||
buildKey: (attrs) => `private-message-map-${attrs.id}`,
|
|
||||||
|
|
||||||
defaultState() {
|
|
||||||
return { isEditing: false };
|
|
||||||
},
|
|
||||||
|
|
||||||
html(attrs) {
|
|
||||||
const participants = [];
|
|
||||||
|
|
||||||
if (attrs.allowedGroups.length) {
|
|
||||||
participants.push(
|
|
||||||
attrs.allowedGroups.map((group) => {
|
|
||||||
return this.attach("pm-map-user-group", {
|
|
||||||
group,
|
|
||||||
canRemoveAllowedUsers: attrs.canRemoveAllowedUsers,
|
|
||||||
isEditing: this.state.isEditing,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attrs.allowedUsers.length) {
|
|
||||||
participants.push(
|
|
||||||
attrs.allowedUsers.map((au) => {
|
|
||||||
return this.attach("pm-map-user", {
|
|
||||||
user: au,
|
|
||||||
canRemoveAllowedUsers: attrs.canRemoveAllowedUsers,
|
|
||||||
canRemoveSelfId: attrs.canRemoveSelfId,
|
|
||||||
isEditing: this.state.isEditing,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let hideNamesClass = "";
|
|
||||||
if (
|
|
||||||
!this.state.isEditing &&
|
|
||||||
this.site.mobileView &&
|
|
||||||
makeArray(participants[0]).length > 4
|
|
||||||
) {
|
|
||||||
hideNamesClass = ".hide-names";
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = [h(`div.participants${hideNamesClass}`, participants)];
|
|
||||||
const controls = [];
|
|
||||||
|
|
||||||
const canRemove = attrs.canRemoveAllowedUsers || attrs.canRemoveSelfId;
|
|
||||||
|
|
||||||
if (attrs.canInvite || canRemove) {
|
|
||||||
let key;
|
|
||||||
let action = "toggleEditing";
|
|
||||||
|
|
||||||
if (attrs.canInvite && canRemove) {
|
|
||||||
key = "edit";
|
|
||||||
} else if (!attrs.canInvite && canRemove) {
|
|
||||||
key = "remove";
|
|
||||||
} else {
|
|
||||||
key = "add";
|
|
||||||
action = "showInvite";
|
|
||||||
}
|
|
||||||
|
|
||||||
controls.push(
|
|
||||||
this.attach("button", {
|
|
||||||
action,
|
|
||||||
label: `private_message_info.${key}`,
|
|
||||||
className: "btn btn-default add-remove-participant-btn",
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attrs.canInvite && this.state.isEditing) {
|
|
||||||
controls.push(
|
|
||||||
this.attach("button", {
|
|
||||||
action: "showInvite",
|
|
||||||
icon: "plus",
|
|
||||||
className: "btn btn-default no-text btn-icon add-participant-btn",
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (controls.length) {
|
|
||||||
result.push(h("div.controls", controls));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
|
|
||||||
toggleEditing() {
|
|
||||||
this.state.isEditing = !this.state.isEditing;
|
|
||||||
},
|
|
||||||
});
|
|
@ -171,7 +171,7 @@ export default createWidget("topic-map", {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (attrs.showPMMap) {
|
if (attrs.showPMMap) {
|
||||||
contents.push(this.attach("private-message-map", attrs));
|
contents.push(this.buildPrivateMessageMap(attrs));
|
||||||
}
|
}
|
||||||
return contents;
|
return contents;
|
||||||
},
|
},
|
||||||
@ -219,4 +219,25 @@ export default createWidget("topic-map", {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
buildPrivateMessageMap(attrs) {
|
||||||
|
return new RenderGlimmer(
|
||||||
|
this,
|
||||||
|
"section.information.private-message-map",
|
||||||
|
hbs`<TopicMap::PrivateMessageMap
|
||||||
|
@postAttrs={{@data.postAttrs}}
|
||||||
|
@showInvite={{@data.showInvite}}
|
||||||
|
@removeAllowedGroup={{@data.removeAllowedGroup}}
|
||||||
|
@removeAllowedUser={{@data.removeAllowedUser}}
|
||||||
|
/>`,
|
||||||
|
{
|
||||||
|
postAttrs: attrs,
|
||||||
|
showInvite: () => this.sendWidgetAction("showInvite"),
|
||||||
|
removeAllowedGroup: (group) =>
|
||||||
|
this.sendWidgetAction("removeAllowedGroup", group),
|
||||||
|
removeAllowedUser: (user) =>
|
||||||
|
this.sendWidgetAction("removeAllowedUser", user),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
57
spec/system/page_objects/components/private_message_map.rb
Normal file
57
spec/system/page_objects/components/private_message_map.rb
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module PageObjects
|
||||||
|
module Components
|
||||||
|
class PrivateMessageMap < PageObjects::Components::Base
|
||||||
|
PRIVATE_MESSAGE_MAP_KLASS = ".private-message-map"
|
||||||
|
def is_visible?
|
||||||
|
has_css?(PRIVATE_MESSAGE_MAP_KLASS)
|
||||||
|
end
|
||||||
|
|
||||||
|
def participants_details
|
||||||
|
find("#{PRIVATE_MESSAGE_MAP_KLASS} .participants").all(".user")
|
||||||
|
end
|
||||||
|
|
||||||
|
def participants_count
|
||||||
|
participants_details.length
|
||||||
|
end
|
||||||
|
|
||||||
|
def controls
|
||||||
|
find("#{PRIVATE_MESSAGE_MAP_KLASS} .controls")
|
||||||
|
end
|
||||||
|
|
||||||
|
def toggle_edit_participants_button
|
||||||
|
controls.click_button(class: "add-remove-participant-btn")
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_add_participants_button?
|
||||||
|
controls.has_button?(class: "add-participant-btn")
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_no_add_participants_button?
|
||||||
|
controls.has_no_button?(class: "add-participant-btn")
|
||||||
|
end
|
||||||
|
def click_add_participants_button
|
||||||
|
controls.click_button(class: "add-participant-btn")
|
||||||
|
end
|
||||||
|
|
||||||
|
def click_remove_participant_button(user)
|
||||||
|
find_link(user.username).sibling(".remove-invited").click
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_participant_details_for?(user)
|
||||||
|
find("#{PRIVATE_MESSAGE_MAP_KLASS} .participants").has_link?(
|
||||||
|
class: "user-link",
|
||||||
|
href: "/u/#{user.username}",
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_no_participant_details_for?(user)
|
||||||
|
find("#{PRIVATE_MESSAGE_MAP_KLASS} .participants").has_no_link?(
|
||||||
|
class: "user-link",
|
||||||
|
href: "/u/#{user.username}",
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
29
spec/system/page_objects/modals/private_message_invite.rb
Normal file
29
spec/system/page_objects/modals/private_message_invite.rb
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module PageObjects
|
||||||
|
module Modals
|
||||||
|
class PrivateMessageInvite < PageObjects::Modals::Base
|
||||||
|
MODAL_SELECTOR = ".add-pm-participants"
|
||||||
|
BODY_SELECTOR = ".invite.modal-panel"
|
||||||
|
|
||||||
|
def select_invitee(user)
|
||||||
|
select_kit = PageObjects::Components::SelectKit.new(".invite-user-input")
|
||||||
|
select_kit.expand
|
||||||
|
select_kit.search(user.username)
|
||||||
|
select_kit.select_row_by_value(user.username)
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_invitee_already_exists_error?
|
||||||
|
body.find(".alert-error").has_text?(I18n.t("topic_invite.user_exists"))
|
||||||
|
end
|
||||||
|
|
||||||
|
def click_primary_button
|
||||||
|
body.find(".btn-primary").click
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_successful_invite_message?
|
||||||
|
has_content?(I18n.t("js.topic.invite_private.success"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,27 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module PageObjects
|
||||||
|
module Modals
|
||||||
|
class PrivateMessageRemoveParticipant < PageObjects::Components::Base
|
||||||
|
def open?
|
||||||
|
has_css?("#dialog-holder .dialog-content")
|
||||||
|
end
|
||||||
|
|
||||||
|
def closed?
|
||||||
|
has_no_css?("#dialog-holder .dialog-content")
|
||||||
|
end
|
||||||
|
|
||||||
|
def body
|
||||||
|
find("#dialog-holder .dialog-content .dialog-body")
|
||||||
|
end
|
||||||
|
|
||||||
|
def confirm_removal
|
||||||
|
find("#dialog-holder .dialog-content .dialog-footer .btn-danger").click
|
||||||
|
end
|
||||||
|
|
||||||
|
def cancel
|
||||||
|
find("#dialog-holder .dialog-content .dialog-footer .btn-default").click
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -7,6 +7,7 @@ module PageObjects
|
|||||||
@composer_component = PageObjects::Components::Composer.new
|
@composer_component = PageObjects::Components::Composer.new
|
||||||
@fast_edit_component = PageObjects::Components::FastEditor.new
|
@fast_edit_component = PageObjects::Components::FastEditor.new
|
||||||
@topic_map_component = PageObjects::Components::TopicMap.new
|
@topic_map_component = PageObjects::Components::TopicMap.new
|
||||||
|
@private_message_map_component = PageObjects::Components::PrivateMessageMap.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def visit_topic(topic, post_number: nil)
|
def visit_topic(topic, post_number: nil)
|
||||||
@ -205,6 +206,10 @@ module PageObjects
|
|||||||
@topic_map_component.is_not_visible?
|
@topic_map_component.is_not_visible?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def has_private_message_map?
|
||||||
|
@private_message_map_component.is_visible?
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def topic_footer_button_id(button)
|
def topic_footer_button_id(button)
|
||||||
|
146
spec/system/private_message_map_spec.rb
Normal file
146
spec/system/private_message_map_spec.rb
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
describe "Topic Map - Private Message", type: :system do
|
||||||
|
fab!(:user) { Fabricate(:admin, refresh_auto_groups: true) }
|
||||||
|
fab!(:other_user) { Fabricate(:user, refresh_auto_groups: true) }
|
||||||
|
fab!(:last_post_user) { Fabricate(:user, refresh_auto_groups: true) }
|
||||||
|
fab!(:topic) do
|
||||||
|
Fabricate(
|
||||||
|
:private_message_topic,
|
||||||
|
created_at: 1.day.ago,
|
||||||
|
user: user,
|
||||||
|
topic_allowed_users: [
|
||||||
|
Fabricate.build(:topic_allowed_user, user: user),
|
||||||
|
Fabricate.build(:topic_allowed_user, user: other_user),
|
||||||
|
Fabricate.build(:topic_allowed_user, user: last_post_user),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
end
|
||||||
|
fab!(:original_post) { Fabricate(:post, topic: topic, user: user, created_at: 1.day.ago) }
|
||||||
|
|
||||||
|
let(:topic_page) { PageObjects::Pages::Topic.new }
|
||||||
|
let(:topic_map) { PageObjects::Components::TopicMap.new }
|
||||||
|
let(:private_message_map) { PageObjects::Components::PrivateMessageMap.new }
|
||||||
|
let(:private_message_invite_modal) { PageObjects::Modals::PrivateMessageInvite.new }
|
||||||
|
let(:private_message_remove_participant_modal) do
|
||||||
|
PageObjects::Modals::PrivateMessageRemoveParticipant.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def avatar_url(user, size)
|
||||||
|
URI(user.avatar_template_url.gsub("{size}", size.to_s)).path
|
||||||
|
end
|
||||||
|
|
||||||
|
it "updates the various topic stats, avatars" do
|
||||||
|
freeze_time
|
||||||
|
sign_in(user)
|
||||||
|
topic_page.visit_topic(topic)
|
||||||
|
|
||||||
|
# topic map appears after OP
|
||||||
|
expect(topic_page).to have_topic_map
|
||||||
|
|
||||||
|
# created avatar display
|
||||||
|
expect(topic_map.created_details).to have_selector("img[src=\"#{avatar_url(user, 24)}\"]")
|
||||||
|
expect(topic_map.created_relative_date).to eq "1d"
|
||||||
|
|
||||||
|
# replies, user count
|
||||||
|
expect {
|
||||||
|
Fabricate(:post, topic: topic, user: user, created_at: 1.day.ago)
|
||||||
|
sign_in(last_post_user)
|
||||||
|
topic_page.visit_topic_and_open_composer(topic)
|
||||||
|
topic_page.send_reply("this is a cool-cat post") # fabricating posts doesn't update the last post details
|
||||||
|
topic_page.visit_topic(topic)
|
||||||
|
}.to change(topic_map, :replies_count).by(2).and change(topic_map, :users_count).by(1)
|
||||||
|
|
||||||
|
#last reply avatar display
|
||||||
|
expect(topic_map.last_reply_details).to have_selector(
|
||||||
|
"img[src=\"#{avatar_url(last_post_user, 24)}\"]",
|
||||||
|
)
|
||||||
|
expect(topic_map.last_reply_relative_date).to eq "1m"
|
||||||
|
|
||||||
|
# avatars details with post counts
|
||||||
|
2.times { Fabricate(:post, topic: topic) }
|
||||||
|
Fabricate(:post, user: user, topic: topic)
|
||||||
|
Fabricate(:post, user: last_post_user, topic: topic)
|
||||||
|
page.refresh
|
||||||
|
avatars = topic_map.avatars_details
|
||||||
|
expect(avatars.length).to eq 3 # max no. of avatars in a collapsed map
|
||||||
|
expect(avatars[0]).to have_selector("img[src=\"#{avatar_url(user, 48)}\"]")
|
||||||
|
expect(avatars[0].find(".post-count").text).to eq "3"
|
||||||
|
expect(avatars[1]).to have_selector("img[src=\"#{avatar_url(last_post_user, 48)}\"]")
|
||||||
|
expect(avatars[1].find(".post-count").text).to eq "2"
|
||||||
|
expect(avatars[2]).to have_no_css(".post-count")
|
||||||
|
|
||||||
|
topic_map.expand
|
||||||
|
expect(topic_map).to have_no_avatars_details_in_map
|
||||||
|
expect(topic_map.expanded_map_avatars_details.length).to eq 4
|
||||||
|
|
||||||
|
# views count
|
||||||
|
expect {
|
||||||
|
sign_in(other_user)
|
||||||
|
topic_page.visit_topic(topic)
|
||||||
|
page.refresh
|
||||||
|
}.to change(topic_map, :views_count).by 1
|
||||||
|
|
||||||
|
# likes count
|
||||||
|
expect(topic_map).to have_no_likes
|
||||||
|
topic_page.click_like_reaction_for(original_post)
|
||||||
|
expect(topic_map.likes_count).to eq 1
|
||||||
|
end
|
||||||
|
|
||||||
|
it "has private message map that shows correct participants and allows editing of participant invites" do
|
||||||
|
freeze_time
|
||||||
|
sign_in(user)
|
||||||
|
topic_page.visit_topic(topic)
|
||||||
|
|
||||||
|
expect(topic_page).to have_private_message_map
|
||||||
|
|
||||||
|
# participants' links and avatars
|
||||||
|
private_message_map
|
||||||
|
.participants_details
|
||||||
|
.zip([user, other_user, last_post_user]) do |details, usr|
|
||||||
|
expect(details).to have_link(usr.username, href: "/u/#{usr.username}")
|
||||||
|
expect(details.find(".trigger-user-card")).to have_selector(
|
||||||
|
"img[src=\"#{avatar_url(usr, 24)}\"]",
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
# toggle ability to edit participants
|
||||||
|
private_message_map.toggle_edit_participants_button
|
||||||
|
expect(private_message_map).to have_add_participants_button
|
||||||
|
private_message_map.toggle_edit_participants_button
|
||||||
|
expect(private_message_map).to have_no_add_participants_button
|
||||||
|
|
||||||
|
# removing participants
|
||||||
|
private_message_map.toggle_edit_participants_button
|
||||||
|
private_message_map.participants_details.each do |details|
|
||||||
|
expect(details).to have_css(".remove-invited .d-icon-times")
|
||||||
|
end
|
||||||
|
private_message_map.click_remove_participant_button(last_post_user)
|
||||||
|
expect(private_message_remove_participant_modal).to be_open
|
||||||
|
expect(private_message_remove_participant_modal.body).to have_text(
|
||||||
|
I18n.t("js.private_message_info.remove_allowed_user", name: last_post_user.username),
|
||||||
|
)
|
||||||
|
private_message_remove_participant_modal.cancel
|
||||||
|
expect(private_message_remove_participant_modal).to be_closed
|
||||||
|
expect(private_message_map).to have_participant_details_for(last_post_user)
|
||||||
|
private_message_map.click_remove_participant_button(last_post_user)
|
||||||
|
expect(private_message_remove_participant_modal).to be_open
|
||||||
|
private_message_remove_participant_modal.confirm_removal
|
||||||
|
expect(private_message_map).to have_no_participant_details_for(last_post_user)
|
||||||
|
|
||||||
|
# adding participants
|
||||||
|
expect {
|
||||||
|
expect(private_message_map).to have_add_participants_button
|
||||||
|
private_message_map.click_add_participants_button
|
||||||
|
expect(private_message_invite_modal).to be_open
|
||||||
|
private_message_invite_modal.select_invitee(other_user)
|
||||||
|
private_message_invite_modal.click_primary_button
|
||||||
|
expect(private_message_invite_modal).to have_invitee_already_exists_error
|
||||||
|
private_message_invite_modal.select_invitee(last_post_user)
|
||||||
|
private_message_invite_modal.click_primary_button #sends invite
|
||||||
|
expect(private_message_invite_modal).to have_successful_invite_message
|
||||||
|
private_message_invite_modal.click_primary_button #closes modal
|
||||||
|
expect(private_message_invite_modal).to be_closed
|
||||||
|
}.to change(private_message_map, :participants_count).by 1
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user