FEATURE: add welcome topic cta banner (#17821)

This commit is contained in:
Arpit Jalan 2022-08-09 21:52:39 +05:30 committed by GitHub
parent 5138347e48
commit d57bea4de3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 169 additions and 8 deletions

View File

@ -0,0 +1,25 @@
import GlimmerComponent from "discourse/components/glimmer";
import { action } from "@ember/object";
import { getOwner } from "discourse-common/lib/get-owner";
import Topic from "discourse/models/topic";
import Composer from "discourse/models/composer";
export default class WelcomeTopicBanner extends GlimmerComponent {
@action
editWelcomeTopic() {
const topicController = getOwner(this).lookup("controller:topic");
Topic.find(this.siteSettings.welcome_topic_id, {}).then((topic) => {
this.store
.createRecord("topic", {
id: topic.id,
slug: topic.slug,
})
.postStream.loadPostByPostNumber(1)
.then((post) => {
post.topic.set("draft_key", Composer.EDIT);
topicController.send("editPost", post);
});
});
}
}

View File

@ -24,6 +24,13 @@ const controllerOpts = {
showTopicPostBadges: not("new"), showTopicPostBadges: not("new"),
redirectedReason: alias("currentUser.redirected_to_top.reason"), redirectedReason: alias("currentUser.redirected_to_top.reason"),
@discourseComputed("model.filter", "site.show_welcome_topic_banner")
showEditWelcomeTopicBanner(filter, showWelcomeTopicBanner) {
return (
this.currentUser?.staff && filter === "latest" && showWelcomeTopicBanner
);
},
expandGloballyPinned: false, expandGloballyPinned: false,
expandAllPinned: false, expandAllPinned: false,

View File

@ -0,0 +1,9 @@
<div class="welcome-topic-banner">
<div class="col-text">
<h1 class="title">{{i18n "welcome_topic_banner.title"}}</h1>
<p class="description">{{i18n "welcome_topic_banner.description"}}</p>
</div>
<div class="col-button">
<DButton @class="btn-primary welcome-topic-cta" @action={{action "editWelcomeTopic"}} @label="welcome_topic_banner.button_title" />
</div>
</div>

View File

@ -2,6 +2,10 @@
<div class="alert alert-info">{{this.redirectedReason}}</div> <div class="alert alert-info">{{this.redirectedReason}}</div>
{{/if}} {{/if}}
{{#if this.showEditWelcomeTopicBanner}}
<WelcomeTopicBanner />
{{/if}}
<TopicDismissButtons @position="top" @selectedTopics={{this.selected}} @model={{this.model}} @showResetNew={{this.showResetNew}} @showDismissRead={{this.showDismissRead}} @resetNew={{action "resetNew"}} /> <TopicDismissButtons @position="top" @selectedTopics={{this.selected}} @model={{this.model}} @showResetNew={{this.showResetNew}} @showDismissRead={{this.showDismissRead}} @resetNew={{action "resetNew"}} />
{{#if this.model.sharedDrafts}} {{#if this.model.sharedDrafts}}

View File

@ -0,0 +1,17 @@
import { acceptance, exists } from "discourse/tests/helpers/qunit-helpers";
import { test } from "qunit";
import { visit } from "@ember/test-helpers";
acceptance("Welcome Topic Banner", function (needs) {
needs.user();
needs.site({ show_welcome_topic_banner: true });
test("Navigation", async function (assert) {
await visit("/");
assert.ok(exists(".welcome-topic-banner"), "has the welcome topic banner");
assert.ok(
exists("button.welcome-topic-cta"),
"has the welcome topic edit button"
);
});
});

View File

@ -252,3 +252,22 @@
} }
} }
} }
.welcome-topic-banner {
border: 1px solid var(--primary-low);
box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.12);
padding: 10px;
display: flex;
flex-direction: row;
.col-text {
width: 70%;
}
.col-button {
width: 30%;
display: flex;
align-self: center;
justify-content: flex-end;
padding-right: 30px;
}
}

View File

@ -203,4 +203,10 @@ class Site
MessageBus.publish(SITE_JSON_CHANNEL, '') MessageBus.publish(SITE_JSON_CHANNEL, '')
end end
def self.show_welcome_topic_banner?(guardian)
return false unless guardian.is_admin?
return false unless guardian.user.id == User.first_login_admin_id
Post.find_by("topic_id = :topic_id AND post_number = 1 AND version = 1 AND created_at > :created_at", topic_id: SiteSetting.welcome_topic_id, created_at: 1.month.ago).present?
end
end end

View File

@ -1878,6 +1878,14 @@ class User < ActiveRecord::Base
end end
end end
def self.first_login_admin_id
User.where(admin: true)
.human_users
.joins(:user_auth_tokens)
.order('user_auth_tokens.created_at')
.pluck_first(:id)
end
private private
def stat def stat

View File

@ -34,7 +34,8 @@ class SiteSerializer < ApplicationSerializer
:watched_words_link, :watched_words_link,
:categories, :categories,
:markdown_additional_options, :markdown_additional_options,
:displayed_about_plugin_stat_groups :displayed_about_plugin_stat_groups,
:show_welcome_topic_banner
) )
has_many :archetypes, embed: :objects, serializer: ArchetypeSerializer has_many :archetypes, embed: :objects, serializer: ArchetypeSerializer
@ -213,6 +214,10 @@ class SiteSerializer < ApplicationSerializer
About.displayed_plugin_stat_groups About.displayed_plugin_stat_groups
end end
def show_welcome_topic_banner
Site.show_welcome_topic_banner?(scope)
end
private private
def ordered_flags(flags) def ordered_flags(flags)

View File

@ -4136,6 +4136,11 @@ en:
one: "%{count} draft" one: "%{count} draft"
other: "%{count} drafts" other: "%{count} drafts"
welcome_topic_banner:
title: "Create your Welcome Topic"
description: 'Your welcome topic is the first thing new arrivals will read. Think of it as your one paragraph "elevator pitch" or "mission statement"'
button_title: "Start Editing"
# This section is exported to the javascript for i18n in the admin section # This section is exported to the javascript for i18n in the admin section
admin_js: admin_js:
type_to_filter: "type to filter..." type_to_filter: "type to filter..."

View File

@ -2325,6 +2325,7 @@ uncategorized:
welcome_topic_id: welcome_topic_id:
default: -1 default: -1
hidden: true hidden: true
client: true
lounge_welcome_topic_id: lounge_welcome_topic_id:
default: -1 default: -1
hidden: true hidden: true

View File

@ -106,13 +106,7 @@ class Wizard
return false return false
end end
first_admin_id = User.where(admin: true) if @user&.id && User.first_login_admin_id == @user.id
.human_users
.joins(:user_auth_tokens)
.order('user_auth_tokens.created_at')
.pluck_first(:id)
if @user&.id && first_admin_id == @user.id
!Wizard::Builder.new(@user).build.completed? !Wizard::Builder.new(@user).build.completed?
else else
false false

View File

@ -183,4 +183,50 @@ RSpec.describe Site do
expect(data["auth_providers"].map { |a| a["name"] }).to contain_exactly('facebook', 'twitter') expect(data["auth_providers"].map { |a| a["name"] }).to contain_exactly('facebook', 'twitter')
end end
describe ".show_welcome_topic_banner?" do
it "returns false when the user is not admin" do
first_post = Fabricate(:post, created_at: 25.days.ago)
SiteSetting.welcome_topic_id = first_post.topic.id
expect(Site.show_welcome_topic_banner?(Guardian.new(Fabricate(:user)))).to eq(false)
end
it "returns false when the user is not first admin who logs in" do
first_post = Fabricate(:post, created_at: 25.days.ago)
SiteSetting.welcome_topic_id = first_post.topic.id
expect(Site.show_welcome_topic_banner?(Guardian.new(Fabricate(:admin)))).to eq(false)
end
it "returns true when welcome topic is less than month old" do
admin = Fabricate(:admin)
UserAuthToken.generate!(user_id: admin.id)
first_post = Fabricate(:post, created_at: 25.days.ago)
SiteSetting.welcome_topic_id = first_post.topic.id
expect(Site.show_welcome_topic_banner?(Guardian.new(admin))).to eq(true)
end
it "returns false when welcome topic is more than month old" do
admin = Fabricate(:admin)
UserAuthToken.generate!(user_id: admin.id)
first_post = Fabricate(:post, created_at: 35.days.ago)
SiteSetting.welcome_topic_id = first_post.topic.id
expect(Site.show_welcome_topic_banner?(Guardian.new(admin))).to eq(false)
end
it "returns false when welcome topic has been edited" do
admin = Fabricate(:admin)
UserAuthToken.generate!(user_id: admin.id)
first_post = Fabricate(:post, version: 2, created_at: 25.days.ago)
SiteSetting.welcome_topic_id = first_post.topic.id
expect(Site.show_welcome_topic_banner?(Guardian.new(admin))).to eq(false)
end
end
end end

View File

@ -685,6 +685,9 @@
] ]
} }
}, },
"show_welcome_topic_banner": {
"type": "boolean"
},
"archetypes": { "archetypes": {
"type": "array", "type": "array",
"items": "items":

View File

@ -112,4 +112,16 @@ RSpec.describe SiteSerializer do
serialized = described_class.new(Site.new(admin_guardian), scope: admin_guardian, root: false).as_json serialized = described_class.new(Site.new(admin_guardian), scope: admin_guardian, root: false).as_json
expect(serialized[:shared_drafts_category_id]).to eq(nil) expect(serialized[:shared_drafts_category_id]).to eq(nil)
end end
it 'includes show_welcome_topic_banner' do
admin = Fabricate(:admin)
admin_guardian = Guardian.new(admin)
UserAuthToken.generate!(user_id: admin.id)
first_post = Fabricate(:post, created_at: 25.days.ago)
SiteSetting.welcome_topic_id = first_post.topic.id
serialized = described_class.new(Site.new(admin_guardian), scope: admin_guardian, root: false).as_json
expect(serialized[:show_welcome_topic_banner]).to eq(true)
end
end end