mirror of
https://github.com/discourse/discourse.git
synced 2025-01-16 03:32:40 +08:00
FEATURE: add drafts dropdown menu (#30277)
This change adds a new dropdown trigger next to the "New Topic" button. When clicked a menu will display a list of topic/post drafts that can be clicked to resume the draft within the composer. The "New Topic" button will no longer change text to show "Open Draft" when a draft topic exists, it will still attempt to load the existing draft if one exists (this will change later when we support multiple drafts in a separate PR). The "My Posts" link in desktop sidebar will now be "My Drafts" and only appear when the current user has existing drafts.
This commit is contained in:
parent
0b3663a16a
commit
47c8197ea1
|
@ -16,4 +16,8 @@
|
|||
{{/if}}
|
||||
</:tooltip>
|
||||
</DButtonTooltip>
|
||||
|
||||
{{#if @showDrafts}}
|
||||
<TopicDraftsDropdown />
|
||||
{{/if}}
|
||||
{{/if}}
|
|
@ -102,6 +102,7 @@
|
|||
@label={{this.createTopicLabel}}
|
||||
@btnClass={{this.createTopicClass}}
|
||||
@canCreateTopicOnTag={{this.canCreateTopicOnTag}}
|
||||
@showDrafts={{if (gt this.draftCount 0) true false}}
|
||||
/>
|
||||
|
||||
<PluginOutlet
|
||||
|
|
|
@ -20,6 +20,8 @@ export default class DNavigation extends Component {
|
|||
|
||||
@setting("fixed_category_positions") fixedCategoryPositions;
|
||||
|
||||
createTopicLabel = "topic.create";
|
||||
|
||||
@dependentKeyCompat
|
||||
get filterType() {
|
||||
return filterTypeForMode(this.filterMode);
|
||||
|
@ -111,11 +113,6 @@ export default class DNavigation extends Component {
|
|||
return classNames.join(" ");
|
||||
}
|
||||
|
||||
@discourseComputed("hasDraft")
|
||||
createTopicLabel(hasDraft) {
|
||||
return hasDraft ? "topic.open_draft" : "topic.create";
|
||||
}
|
||||
|
||||
@discourseComputed("category.can_edit")
|
||||
showCategoryEdit(canEdit) {
|
||||
return canEdit;
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
@createTopic={{@createTopic}}
|
||||
@createTopicDisabled={{@createTopicDisabled}}
|
||||
@hasDraft={{this.currentUser.has_topic_draft}}
|
||||
@draftCount={{this.currentUser.draft_count}}
|
||||
@editCategory={{this.editCategory}}
|
||||
@showCategoryAdmin={{@showCategoryAdmin}}
|
||||
@createCategory={{this.createCategory}}
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { fn } from "@ember/helper";
|
||||
import { action } from "@ember/object";
|
||||
import { service } from "@ember/service";
|
||||
import DButton from "discourse/components/d-button";
|
||||
import DropdownMenu from "discourse/components/dropdown-menu";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import DMenu from "float-kit/components/d-menu";
|
||||
|
||||
const DRAFTS_LIMIT = 4;
|
||||
|
||||
export default class TopicDraftsDropdown extends Component {
|
||||
@service currentUser;
|
||||
@service composer;
|
||||
|
||||
@tracked drafts = [];
|
||||
|
||||
get draftCount() {
|
||||
return this.currentUser.draft_count;
|
||||
}
|
||||
|
||||
get otherDraftsCount() {
|
||||
return this.draftCount > DRAFTS_LIMIT ? this.draftCount - DRAFTS_LIMIT : 0;
|
||||
}
|
||||
|
||||
get otherDraftsText() {
|
||||
return this.otherDraftsCount > 0
|
||||
? i18n("drafts.dropdown.other_drafts", {
|
||||
count: this.otherDraftsCount,
|
||||
})
|
||||
: "";
|
||||
}
|
||||
|
||||
@action
|
||||
onRegisterApi(api) {
|
||||
this.dMenu = api;
|
||||
}
|
||||
|
||||
@action
|
||||
async onShowMenu() {
|
||||
try {
|
||||
const draftsStream = this.currentUser.userDraftsStream;
|
||||
draftsStream.reset();
|
||||
|
||||
await draftsStream.findItems(this.site);
|
||||
this.drafts = draftsStream.content.slice(0, DRAFTS_LIMIT);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Failed to fetch drafts with error:", error);
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
async resumeDraft(draft) {
|
||||
await this.dMenu.close();
|
||||
|
||||
if (draft.postUrl) {
|
||||
DiscourseURL.routeTo(draft.postUrl);
|
||||
} else {
|
||||
this.composer.open({
|
||||
draft,
|
||||
draftKey: draft.draft_key,
|
||||
draftSequence: draft.sequence,
|
||||
...draft.data,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
<template>
|
||||
<DMenu
|
||||
@identifier="topic-drafts-menu"
|
||||
@title={{i18n "drafts.dropdown.title"}}
|
||||
@icon="chevron-down"
|
||||
@onShow={{this.onShowMenu}}
|
||||
@onRegisterApi={{this.onRegisterApi}}
|
||||
@modalForMobile={{true}}
|
||||
class="btn-small"
|
||||
>
|
||||
<:content>
|
||||
<DropdownMenu as |dropdown|>
|
||||
{{#each this.drafts as |draft|}}
|
||||
<dropdown.item class="topic-drafts-item">
|
||||
<DButton
|
||||
@action={{fn this.resumeDraft draft}}
|
||||
@icon={{if draft.topic_id "reply" "layer-group"}}
|
||||
@translatedLabel={{draft.title}}
|
||||
class="btn-secondary"
|
||||
/>
|
||||
</dropdown.item>
|
||||
{{/each}}
|
||||
|
||||
<dropdown.divider />
|
||||
|
||||
<dropdown.item>
|
||||
<DButton
|
||||
@href="/my/activity/drafts"
|
||||
@model={{this.currentUser}}
|
||||
class="btn-link view-all-drafts"
|
||||
>
|
||||
<span
|
||||
data-other-drafts={{this.otherDraftsCount}}
|
||||
>{{this.otherDraftsText}}</span>
|
||||
<span>{{i18n "drafts.dropdown.view_all"}}</span>
|
||||
</DButton>
|
||||
</dropdown.item>
|
||||
</DropdownMenu>
|
||||
</:content>
|
||||
</DMenu>
|
||||
</template>
|
||||
}
|
|
@ -14,7 +14,7 @@ import {
|
|||
import SectionLink from "discourse/lib/sidebar/section-link";
|
||||
import AdminSectionLink from "discourse/lib/sidebar/user/community-section/admin-section-link";
|
||||
import InviteSectionLink from "discourse/lib/sidebar/user/community-section/invite-section-link";
|
||||
import MyPostsSectionLink from "discourse/lib/sidebar/user/community-section/my-posts-section-link";
|
||||
import MyDraftsSectionLink from "discourse/lib/sidebar/user/community-section/my-drafts-section-link";
|
||||
import ReviewSectionLink from "discourse/lib/sidebar/user/community-section/review-section-link";
|
||||
|
||||
const SPECIAL_LINKS_MAP = {
|
||||
|
@ -22,7 +22,7 @@ const SPECIAL_LINKS_MAP = {
|
|||
"/about": AboutSectionLink,
|
||||
"/u": UsersSectionLink,
|
||||
"/faq": FAQSectionLink,
|
||||
"/my/activity": MyPostsSectionLink,
|
||||
"/my/activity": MyDraftsSectionLink,
|
||||
"/review": ReviewSectionLink,
|
||||
"/badges": BadgesSectionLink,
|
||||
"/admin": AdminSectionLink,
|
||||
|
|
|
@ -4,13 +4,13 @@ import { i18n } from "discourse-i18n";
|
|||
|
||||
const USER_DRAFTS_CHANGED_EVENT = "user-drafts:changed";
|
||||
|
||||
export default class MyPostsSectionLink extends BaseSectionLink {
|
||||
export default class MyDraftsSectionLink extends BaseSectionLink {
|
||||
@tracked draftCount = this.currentUser?.draft_count;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
if (this.shouldDisplay) {
|
||||
if (this.currentUser) {
|
||||
this.appEvents.on(
|
||||
USER_DRAFTS_CHANGED_EVENT,
|
||||
this,
|
||||
|
@ -20,7 +20,7 @@ export default class MyPostsSectionLink extends BaseSectionLink {
|
|||
}
|
||||
|
||||
teardown() {
|
||||
if (this.shouldDisplay) {
|
||||
if (this.currentUser) {
|
||||
this.appEvents.off(
|
||||
USER_DRAFTS_CHANGED_EVENT,
|
||||
this,
|
||||
|
@ -38,21 +38,11 @@ export default class MyPostsSectionLink extends BaseSectionLink {
|
|||
}
|
||||
|
||||
get name() {
|
||||
return "my-posts";
|
||||
return "my-drafts";
|
||||
}
|
||||
|
||||
get route() {
|
||||
if (this._hasDraft) {
|
||||
return "userActivity.drafts";
|
||||
} else {
|
||||
return "userActivity.index";
|
||||
}
|
||||
}
|
||||
|
||||
get currentWhen() {
|
||||
if (this._hasDraft) {
|
||||
return "userActivity.index userActivity.drafts";
|
||||
}
|
||||
}
|
||||
|
||||
get model() {
|
||||
|
@ -60,24 +50,11 @@ export default class MyPostsSectionLink extends BaseSectionLink {
|
|||
}
|
||||
|
||||
get title() {
|
||||
if (this._hasDraft) {
|
||||
return i18n("sidebar.sections.community.links.my_posts.title_drafts");
|
||||
} else {
|
||||
return i18n("sidebar.sections.community.links.my_posts.title");
|
||||
}
|
||||
return i18n("sidebar.sections.community.links.my_drafts.title");
|
||||
}
|
||||
|
||||
get text() {
|
||||
if (this._hasDraft && this.currentUser?.new_new_view_enabled) {
|
||||
return i18n("sidebar.sections.community.links.my_posts.content_drafts");
|
||||
} else {
|
||||
return i18n(
|
||||
`sidebar.sections.community.links.${this.overridenName
|
||||
.toLowerCase()
|
||||
.replace(" ", "_")}.content`,
|
||||
{ defaultValue: this.overridenName }
|
||||
);
|
||||
}
|
||||
return i18n("sidebar.sections.community.links.my_drafts.content");
|
||||
}
|
||||
|
||||
get badgeText() {
|
||||
|
@ -88,7 +65,7 @@ export default class MyPostsSectionLink extends BaseSectionLink {
|
|||
if (this.currentUser.new_new_view_enabled) {
|
||||
return this.draftCount.toString();
|
||||
} else {
|
||||
return i18n("sidebar.sections.community.links.my_posts.draft_count", {
|
||||
return i18n("sidebar.sections.community.links.my_drafts.draft_count", {
|
||||
count: this.draftCount,
|
||||
});
|
||||
}
|
||||
|
@ -98,13 +75,6 @@ export default class MyPostsSectionLink extends BaseSectionLink {
|
|||
return this.draftCount > 0;
|
||||
}
|
||||
|
||||
get defaultPrefixValue() {
|
||||
if (this._hasDraft && this.currentUser?.new_new_view_enabled) {
|
||||
return "pencil";
|
||||
}
|
||||
return "user";
|
||||
}
|
||||
|
||||
get suffixCSSClass() {
|
||||
return "unread";
|
||||
}
|
||||
|
@ -120,6 +90,10 @@ export default class MyPostsSectionLink extends BaseSectionLink {
|
|||
}
|
||||
|
||||
get shouldDisplay() {
|
||||
return this.currentUser;
|
||||
return this.currentUser && this._hasDraft;
|
||||
}
|
||||
|
||||
get prefixValue() {
|
||||
return "far-pen-to-square";
|
||||
}
|
||||
}
|
|
@ -60,10 +60,6 @@ async function loadDraft(store, opts = {}) {
|
|||
Draft.clear(draftKey, draftSequence);
|
||||
}
|
||||
|
||||
if (!draft?.title && !draft?.reply) {
|
||||
return;
|
||||
}
|
||||
|
||||
let attrs = {
|
||||
draftKey,
|
||||
draftSequence,
|
||||
|
|
|
@ -908,7 +908,7 @@ acceptance("Composer", function (needs) {
|
|||
});
|
||||
|
||||
await visit("/latest");
|
||||
assert.dom("#create-topic").hasText(i18n("topic.open_draft"));
|
||||
assert.dom("#create-topic").hasText(i18n("topic.create"));
|
||||
|
||||
await click("#create-topic");
|
||||
assert.strictEqual(selectKit(".category-chooser").header().value(), "2");
|
||||
|
|
|
@ -503,50 +503,13 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||
.doesNotExist();
|
||||
});
|
||||
|
||||
test("clicking on my posts link", async function (assert) {
|
||||
await visit("/t/280");
|
||||
await click(
|
||||
".sidebar-section[data-section-name='community'] .sidebar-section-link[data-link-name='my-posts']"
|
||||
);
|
||||
test("clicking on my drafts link", async function (assert) {
|
||||
updateCurrentUser({ draft_count: 1 });
|
||||
|
||||
assert.strictEqual(
|
||||
currentURL(),
|
||||
`/u/${loggedInUser().username}/activity`,
|
||||
"should transition to the user's activity url"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(
|
||||
".sidebar-section[data-section-name='community'] .sidebar-section-link.active"
|
||||
)
|
||||
.exists({ count: 1 }, "only one link is marked as active");
|
||||
|
||||
assert
|
||||
.dom(
|
||||
".sidebar-section[data-section-name='community'] .sidebar-section-link[data-link-name='my-posts'].active"
|
||||
)
|
||||
.exists("the my posts link is marked as active");
|
||||
|
||||
await visit(`/u/${loggedInUser().username}/activity/drafts`);
|
||||
|
||||
assert
|
||||
.dom(
|
||||
".sidebar-section[data-section-name='community'] .sidebar-section-link[data-link-name='my-posts'].active"
|
||||
)
|
||||
.doesNotExist(
|
||||
"the my posts link is not marked as active when user has no drafts and visiting the user activity drafts URL"
|
||||
);
|
||||
});
|
||||
|
||||
test("clicking on my posts link when user has a draft", async function (assert) {
|
||||
await visit("/t/280");
|
||||
|
||||
await publishToMessageBus(`/user-drafts/${loggedInUser().id}`, {
|
||||
draft_count: 1,
|
||||
});
|
||||
|
||||
await click(
|
||||
".sidebar-section[data-section-name='community'] .sidebar-section-link[data-link-name='my-posts']"
|
||||
".sidebar-section[data-section-name='community'] .sidebar-section-link[data-link-name='my-drafts']"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
|
@ -563,45 +526,24 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||
|
||||
assert
|
||||
.dom(
|
||||
".sidebar-section[data-section-name='community'] .sidebar-section-link[data-link-name='my-posts'].active"
|
||||
".sidebar-section[data-section-name='community'] .sidebar-section-link[data-link-name='my-drafts'].active"
|
||||
)
|
||||
.exists("the my posts link is marked as active");
|
||||
|
||||
await visit(`/u/${loggedInUser().username}/activity`);
|
||||
|
||||
assert
|
||||
.dom(
|
||||
".sidebar-section[data-section-name='community'] .sidebar-section-link[data-link-name='my-posts'].active"
|
||||
)
|
||||
.exists("the my posts link is marked as active");
|
||||
.exists("the my drafts link is marked as active");
|
||||
});
|
||||
|
||||
test("my posts title changes when drafts are present", async function (assert) {
|
||||
test("my drafts link is visible when user has drafts", async function (assert) {
|
||||
updateCurrentUser({ draft_count: 1 });
|
||||
|
||||
await visit("/");
|
||||
|
||||
assert
|
||||
.dom(".sidebar-section-link[data-link-name='my-posts']")
|
||||
.hasAttribute(
|
||||
"title",
|
||||
i18n("sidebar.sections.community.links.my_posts.title"),
|
||||
"displays the default title when no drafts are present"
|
||||
);
|
||||
|
||||
await publishToMessageBus(`/user-drafts/${loggedInUser().id}`, {
|
||||
draft_count: 1,
|
||||
});
|
||||
|
||||
assert
|
||||
.dom(".sidebar-section-link[data-link-name='my-posts']")
|
||||
.hasAttribute(
|
||||
"title",
|
||||
i18n("sidebar.sections.community.links.my_posts.title_drafts"),
|
||||
"displays the draft title when drafts are present"
|
||||
);
|
||||
.dom(".sidebar-section-link[data-link-name='my-drafts']")
|
||||
.exists("my drafts link is displayed when drafts are present");
|
||||
});
|
||||
|
||||
test("my posts changes its text when drafts are present and new new view experiment is enabled", async function (assert) {
|
||||
updateCurrentUser({
|
||||
draft_count: 1,
|
||||
user_option: {
|
||||
sidebar_show_count_of_new_items: true,
|
||||
},
|
||||
|
@ -609,28 +551,17 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||
});
|
||||
await visit("/");
|
||||
|
||||
assert
|
||||
.dom(".sidebar-section-link[data-link-name='my-posts']")
|
||||
.hasText(
|
||||
i18n("sidebar.sections.community.links.my_posts.content"),
|
||||
"displays the default text when no drafts are present"
|
||||
);
|
||||
|
||||
await publishToMessageBus(`/user-drafts/${loggedInUser().id}`, {
|
||||
draft_count: 1,
|
||||
});
|
||||
|
||||
assert
|
||||
.dom(
|
||||
".sidebar-section-link[data-link-name='my-posts'] .sidebar-section-link-content-text"
|
||||
".sidebar-section-link[data-link-name='my-drafts'] .sidebar-section-link-content-text"
|
||||
)
|
||||
.hasText(
|
||||
i18n("sidebar.sections.community.links.my_posts.content_drafts"),
|
||||
i18n("sidebar.sections.community.links.my_drafts.content"),
|
||||
"displays the text that's appropriate for when drafts are present"
|
||||
);
|
||||
assert
|
||||
.dom(
|
||||
".sidebar-section-link[data-link-name='my-posts'] .sidebar-section-link-content-badge"
|
||||
".sidebar-section-link[data-link-name='my-drafts'] .sidebar-section-link-content-badge"
|
||||
)
|
||||
.hasText("1", "displays the draft count with no text");
|
||||
});
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
@import "date-picker";
|
||||
@import "date-time-input-range";
|
||||
@import "date-time-input";
|
||||
@import "drafts-dropdown-menu";
|
||||
@import "file-size-input";
|
||||
@import "footer-nav";
|
||||
@import "form-template-field";
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// Styles for the drafts dropdown menu
|
||||
|
||||
.topic-drafts-menu-trigger {
|
||||
margin-left: -0.4em;
|
||||
}
|
||||
|
||||
.topic-drafts-menu-content {
|
||||
margin-top: -0.4em;
|
||||
}
|
||||
|
||||
.topic-drafts-menu-content .dropdown-menu {
|
||||
.btn .d-button-label {
|
||||
@include ellipsis;
|
||||
}
|
||||
|
||||
.view-all-drafts {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
span:first-child {
|
||||
color: var(--primary-high);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
@import "drafts-dropdown-menu";
|
||||
@import "more-topics";
|
||||
@import "sidebar/edit-navigation-menu/tags-modal";
|
||||
@import "sidebar/sidebar-section";
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
.topic-drafts-menu-content .dropdown-menu {
|
||||
max-width: 300px;
|
||||
}
|
|
@ -14,9 +14,9 @@ class SidebarUrl < ActiveRecord::Base
|
|||
segment: SidebarUrl.segments["primary"],
|
||||
},
|
||||
{
|
||||
name: "My Posts",
|
||||
name: "My Drafts",
|
||||
path: "/my/activity",
|
||||
icon: "user",
|
||||
icon: "far-pen-to-square",
|
||||
segment: SidebarUrl.segments["primary"],
|
||||
},
|
||||
{ name: "Review", path: "/review", icon: "flag", segment: SidebarUrl.segments["primary"] },
|
||||
|
|
|
@ -497,6 +497,12 @@ en:
|
|||
confirm: "You already have a draft in progress. What would you like to do with it?"
|
||||
yes_value: "Discard"
|
||||
no_value: "Resume editing"
|
||||
dropdown:
|
||||
title: "Open the latest drafts menu"
|
||||
view_all: "view all"
|
||||
other_drafts:
|
||||
one: "+%{count} other draft"
|
||||
other: "+%{count} other drafts"
|
||||
|
||||
topic_count_all:
|
||||
one: "See %{count} new topic"
|
||||
|
@ -4973,11 +4979,9 @@ en:
|
|||
users:
|
||||
content: "Users"
|
||||
title: "List of all users"
|
||||
my_posts:
|
||||
content: "My Posts"
|
||||
content_drafts: "My Drafts"
|
||||
title: "My recent topic activity"
|
||||
title_drafts: "My unposted drafts"
|
||||
my_drafts:
|
||||
content: "My Drafts"
|
||||
title: "My unposted drafts"
|
||||
draft_count:
|
||||
one: "%{count} draft"
|
||||
other: "%{count} drafts"
|
||||
|
|
|
@ -24,7 +24,7 @@ RSpec.describe SidebarSection do
|
|||
expect(community_section.sidebar_section_links.all.map { |link| link.linkable.name }).to eq(
|
||||
[
|
||||
"Topics",
|
||||
"My Posts",
|
||||
"My Drafts",
|
||||
"Review",
|
||||
"Admin",
|
||||
"Invite",
|
||||
|
|
86
spec/system/drafts_dropdown_spec.rb
Normal file
86
spec/system/drafts_dropdown_spec.rb
Normal file
|
@ -0,0 +1,86 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
describe "Drafts dropdown", type: :system do
|
||||
fab!(:user) { Fabricate(:user, refresh_auto_groups: true) }
|
||||
let(:composer) { PageObjects::Components::Composer.new }
|
||||
let(:drafts_dropdown) { PageObjects::Components::DraftsMenu.new }
|
||||
let(:discard_draft_modal) { PageObjects::Modals::DiscardDraft.new }
|
||||
|
||||
before { sign_in(user) }
|
||||
|
||||
describe "with no drafts" do
|
||||
it "does not display drafts dropdown" do
|
||||
page.visit "/"
|
||||
expect(drafts_dropdown).to be_hidden
|
||||
end
|
||||
|
||||
it "does not have a my drafts link in sidebar" do
|
||||
page.visit "/"
|
||||
expect(page).to have_no_css(".sidebar-section-link[data-link-name='my-drafts']")
|
||||
end
|
||||
|
||||
it "adds a draft dropdown menu when a draft is available" do
|
||||
page.visit "/new-topic"
|
||||
composer.fill_content("This is a draft")
|
||||
|
||||
expect(drafts_dropdown).to be_visible
|
||||
end
|
||||
|
||||
it "shows a my drafts link in sidebar when a draft is saved" do
|
||||
page.visit "/new-topic"
|
||||
|
||||
composer.fill_content("This is a draft")
|
||||
composer.close
|
||||
|
||||
expect(discard_draft_modal).to be_open
|
||||
discard_draft_modal.click_save
|
||||
|
||||
visit "/"
|
||||
expect(page).to have_css(".sidebar-section-link[data-link-name='my-drafts']")
|
||||
end
|
||||
end
|
||||
|
||||
describe "with multiple drafts" do
|
||||
before do
|
||||
Draft.set(
|
||||
user,
|
||||
Draft::NEW_TOPIC,
|
||||
0,
|
||||
{
|
||||
title: "This is a test topic",
|
||||
reply: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
||||
}.to_json,
|
||||
)
|
||||
|
||||
5.times do |i|
|
||||
topic = Fabricate(:topic, user: user)
|
||||
Draft.set(user, topic.draft_key, 0, { reply: "test reply #{i}" }.to_json)
|
||||
end
|
||||
end
|
||||
|
||||
it "displays the correct draft count" do
|
||||
page.visit "/"
|
||||
drafts_dropdown.open
|
||||
|
||||
expect(drafts_dropdown).to be_open
|
||||
|
||||
expect(drafts_dropdown.draft_item_count).to eq(4)
|
||||
expect(drafts_dropdown.other_drafts_count).to eq(2)
|
||||
|
||||
drafts_dropdown.find(".topic-drafts-item:first-child").click
|
||||
|
||||
expect(drafts_dropdown).to be_closed
|
||||
|
||||
expect(composer).to be_opened
|
||||
composer.create
|
||||
|
||||
wait_for { Draft.count == 5 }
|
||||
|
||||
page.visit "/"
|
||||
drafts_dropdown.open
|
||||
|
||||
expect(drafts_dropdown.draft_item_count).to eq(4)
|
||||
expect(drafts_dropdown.other_drafts_count).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -23,7 +23,7 @@ RSpec.describe "Editing Sidebar Community Section", type: :system do
|
|||
visit("/latest")
|
||||
|
||||
expect(sidebar.primary_section_icons("community")).to eq(
|
||||
%w[layer-group user flag wrench paper-plane ellipsis-vertical],
|
||||
%w[layer-group flag wrench paper-plane ellipsis-vertical],
|
||||
)
|
||||
|
||||
modal = sidebar.click_community_section_more_button.click_customize_community_section_button
|
||||
|
@ -32,12 +32,10 @@ RSpec.describe "Editing Sidebar Community Section", type: :system do
|
|||
modal.save
|
||||
modal.confirm_update
|
||||
|
||||
expect(sidebar.primary_section_links("community")).to eq(
|
||||
["My Posts", "Topics", "Review", "Admin", "Invite", "More"],
|
||||
)
|
||||
expect(sidebar.primary_section_links("community")).to eq(%w[Topics Review Admin Invite More])
|
||||
|
||||
expect(sidebar.primary_section_icons("community")).to eq(
|
||||
%w[user paper-plane flag wrench paper-plane ellipsis-vertical],
|
||||
%w[paper-plane flag wrench paper-plane ellipsis-vertical],
|
||||
)
|
||||
|
||||
modal = sidebar.click_community_section_more_button.click_customize_community_section_button
|
||||
|
@ -45,12 +43,10 @@ RSpec.describe "Editing Sidebar Community Section", type: :system do
|
|||
|
||||
expect(sidebar).to have_section("Community")
|
||||
|
||||
expect(sidebar.primary_section_links("community")).to eq(
|
||||
["Topics", "My Posts", "Review", "Admin", "Invite", "More"],
|
||||
)
|
||||
expect(sidebar.primary_section_links("community")).to eq(%w[Topics Review Admin Invite More])
|
||||
|
||||
expect(sidebar.primary_section_icons("community")).to eq(
|
||||
%w[layer-group user flag wrench paper-plane ellipsis-vertical],
|
||||
%w[layer-group flag wrench paper-plane ellipsis-vertical],
|
||||
)
|
||||
end
|
||||
|
||||
|
|
37
spec/system/page_objects/components/drafts_menu.rb
Normal file
37
spec/system/page_objects/components/drafts_menu.rb
Normal file
|
@ -0,0 +1,37 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module PageObjects
|
||||
module Components
|
||||
class DraftsMenu < PageObjects::Components::Base
|
||||
MENU_SELECTOR = ".topic-drafts-menu"
|
||||
|
||||
def visible?
|
||||
has_css?(MENU_SELECTOR + "-trigger")
|
||||
end
|
||||
|
||||
def hidden?
|
||||
has_no_css?(MENU_SELECTOR + "-trigger")
|
||||
end
|
||||
|
||||
def open?
|
||||
has_css?(MENU_SELECTOR + "-content")
|
||||
end
|
||||
|
||||
def closed?
|
||||
has_no_css?(MENU_SELECTOR + "-content")
|
||||
end
|
||||
|
||||
def open
|
||||
find(MENU_SELECTOR + "-trigger").click
|
||||
end
|
||||
|
||||
def draft_item_count
|
||||
all(MENU_SELECTOR + "-content .topic-drafts-item").size
|
||||
end
|
||||
|
||||
def other_drafts_count
|
||||
find(MENU_SELECTOR + "-content .view-all-drafts span:first-child")["data-other-drafts"].to_i
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -15,6 +15,10 @@ module PageObjects
|
|||
def click_save
|
||||
footer.find("button.save-draft").click
|
||||
end
|
||||
|
||||
def click_discard
|
||||
footer.find("button.discard-draft").click
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -56,10 +56,8 @@ describe "Viewing sidebar as logged in user", type: :system do
|
|||
sign_in user
|
||||
visit("/latest")
|
||||
links = page.all("#sidebar-section-content-community .sidebar-section-link-wrapper a")
|
||||
expect(links.map(&:text)).to eq(%w[Tematy Wysłane])
|
||||
expect(links.map { |link| link[:title] }).to eq(
|
||||
["Wszystkie tematy", "Moja ostatnia aktywność w temacie"],
|
||||
)
|
||||
expect(links.map(&:text)).to eq(%w[Tematy])
|
||||
expect(links.map { |link| link[:title] }).to eq(["Wszystkie tematy"])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user