Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dashboard domain card UI #18240

Merged
merged 9 commits into from
Apr 13, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ sealed class MySiteCardAndItem(open val type: Type, open val activeQuickStartIte
POST_CARD_WITH_POST_ITEMS,
BLOGGING_PROMPT_CARD,
PROMOTE_WITH_BLAZE_CARD,
DASHBOARD_DOMAIN_CARD,
PAGES_CARD_ERROR,
PAGES_CARD
}
Expand Down Expand Up @@ -302,6 +303,14 @@ sealed class MySiteCardAndItem(open val type: Type, open val activeQuickStartIte
val onHideMenuItemClick: ListItemInteraction,
val onMoreMenuClick: ListItemInteraction,
): DashboardCard(dashboardCardType = DashboardCardType.PROMOTE_WITH_BLAZE_CARD)

data class DashboardDomainCard(
val title: UiString?,
val subtitle: UiString?,
val onClick: ListItemInteraction,
val onHideMenuItemClick: ListItemInteraction,
val onMoreMenuClick: ListItemInteraction,
): DashboardCard(dashboardCardType = DashboardCardType.DASHBOARD_DOMAIN_CARD)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.DiffUtil.Callback
import androidx.recyclerview.widget.RecyclerView.Adapter
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard.DashboardDomainCard
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard.PromoteWithBlazeCard
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard.BloggingPromptCard.BloggingPromptCardWithData
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard.ErrorCard
Expand All @@ -23,6 +24,7 @@ import org.wordpress.android.ui.mysite.cards.dashboard.error.ErrorWithinCardView
import org.wordpress.android.ui.mysite.cards.dashboard.pages.PagesCardViewHolder
import org.wordpress.android.ui.mysite.cards.dashboard.posts.PostCardViewHolder
import org.wordpress.android.ui.mysite.cards.dashboard.todaysstats.TodaysStatsCardViewHolder
import org.wordpress.android.ui.mysite.cards.domain.DashboardDomainCardViewHolder
import org.wordpress.android.ui.utils.UiHelpers
import org.wordpress.android.util.HtmlCompatWrapper
import org.wordpress.android.util.image.ImageManager
Expand Down Expand Up @@ -54,6 +56,7 @@ class CardsAdapter(
learnMoreClicked
)
DashboardCardType.PROMOTE_WITH_BLAZE_CARD.ordinal -> PromoteWithBlazeCardViewHolder(parent, uiHelpers)
DashboardCardType.DASHBOARD_DOMAIN_CARD.ordinal -> DashboardDomainCardViewHolder(parent, uiHelpers)
DashboardCardType.PAGES_CARD.ordinal -> PagesCardViewHolder(parent, uiHelpers)
else -> throw IllegalArgumentException("Unexpected view type")
}
Expand All @@ -69,6 +72,7 @@ class CardsAdapter(
is PostCardViewHolder<*> -> holder.bind(items[position] as PostCard)
is BloggingPromptCardViewHolder -> holder.bind(items[position] as BloggingPromptCardWithData)
is PromoteWithBlazeCardViewHolder -> holder.bind(items[position] as PromoteWithBlazeCard)
is DashboardDomainCardViewHolder -> holder.bind(items[position] as DashboardDomainCard)
is PagesCardViewHolder -> holder.bind(items[position] as PagesCard)
}
}
Expand Down Expand Up @@ -99,6 +103,7 @@ class CardsAdapter(
oldItem is PostCardWithoutPostItems && newItem is PostCardWithoutPostItems -> true
oldItem is BloggingPromptCardWithData && newItem is BloggingPromptCardWithData -> true
oldItem is PromoteWithBlazeCard && newItem is PromoteWithBlazeCard -> true
oldItem is DashboardDomainCard && newItem is DashboardDomainCard -> true
oldItem is PagesCard && newItem is PagesCard -> true
else -> throw UnsupportedOperationException("Diff not implemented yet")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import org.wordpress.android.ui.mysite.cards.dashboard.bloggingprompts.BloggingP
import org.wordpress.android.ui.mysite.cards.dashboard.pages.PagesCardBuilder
import org.wordpress.android.ui.mysite.cards.dashboard.posts.PostCardBuilder
import org.wordpress.android.ui.mysite.cards.dashboard.todaysstats.TodaysStatsCardBuilder
import org.wordpress.android.ui.mysite.cards.domain.DashboardDomainCardBuilder
import org.wordpress.android.ui.utils.ListItemInteraction
import javax.inject.Inject

Expand All @@ -18,6 +19,7 @@ class CardsBuilder @Inject constructor(
private val postCardBuilder: PostCardBuilder,
private val bloggingPromptCardBuilder: BloggingPromptCardBuilder,
private val promoteWithBlazeCardBuilder: PromoteWithBlazeCardBuilder,
private val dashboardDomainCardBuilder: DashboardDomainCardBuilder,
private val pagesCardBuilder: PagesCardBuilder
) {
fun build(
Expand All @@ -38,6 +40,10 @@ class CardsBuilder @Inject constructor(
add(it)
}

dashboardDomainCardBuilder.build(dashboardCardsBuilderParams.dashboardCardDomainBuilderParams)?.let {
add(it)
}

todaysStatsCardBuilder.build(dashboardCardsBuilderParams.todaysStatsCardBuilderParams)
?.let { add(it) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.wordpress.android.analytics.AnalyticsTracker.Stat
import org.wordpress.android.ui.blaze.BlazeFlowSource
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard.DashboardDomainCard
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard.BloggingPromptCard.BloggingPromptCardWithData
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard.ErrorCard
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard.PostCard
Expand Down Expand Up @@ -34,6 +35,7 @@ class CardsShownTracker @Inject constructor(
}
}

@Suppress("LongMethod")
private fun trackCardShown(card: DashboardCard) = when (card) {
is ErrorCard -> trackCardShown(
Pair(
Expand Down Expand Up @@ -83,6 +85,12 @@ class CardsShownTracker @Inject constructor(
Type.PROMOTE_WITH_BLAZE.label
)
)
is DashboardDomainCard -> trackCardShown(
Pair(
card.dashboardCardType.toTypeValue().label,
Type.DASHBOARD_CARD_DOMAIN.label
)
)
is DashboardCard.PagesCard -> trackCardShown(
Pair(
card.dashboardCardType.toTypeValue().label,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class CardsTracker @Inject constructor(
POST("post"),
BLOGGING_PROMPT("blogging_prompt"),
PROMOTE_WITH_BLAZE("promote_with_blaze"),
DASHBOARD_CARD_DOMAIN("dashboard_card_domain"),
PAGES("pages")
}

Expand Down Expand Up @@ -120,6 +121,7 @@ fun DashboardCardType.toTypeValue(): Type {
DashboardCardType.POST_CARD_WITH_POST_ITEMS -> Type.POST
DashboardCardType.BLOGGING_PROMPT_CARD -> Type.BLOGGING_PROMPT
DashboardCardType.PROMOTE_WITH_BLAZE_CARD -> Type.PROMOTE_WITH_BLAZE
DashboardCardType.DASHBOARD_DOMAIN_CARD -> Type.DASHBOARD_CARD_DOMAIN
DashboardCardType.PAGES_CARD -> Type.PAGES
DashboardCardType.PAGES_CARD_ERROR -> Type.ERROR
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.wordpress.android.ui.mysite.cards.domain

import org.wordpress.android.R
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard.DashboardDomainCard
import org.wordpress.android.ui.mysite.MySiteCardAndItemBuilderParams.DashboardCardDomainBuilderParams
import org.wordpress.android.ui.utils.ListItemInteraction
import org.wordpress.android.ui.utils.UiString
import javax.inject.Inject

class DashboardDomainCardBuilder @Inject constructor() {
fun build(params: DashboardCardDomainBuilderParams):DashboardDomainCard? {
return if (params.isEligible) {
DashboardDomainCard(
title = UiString.UiStringRes(R.string.dashboard_card_domain_title),
subtitle = UiString.UiStringRes(R.string.dashboard_card_domain_sub_title),
onClick = ListItemInteraction.create(params.onClick),
onHideMenuItemClick = ListItemInteraction.create(params.onHideMenuItemClick),
onMoreMenuClick = ListItemInteraction.create(params.onMoreMenuClick)
)
} else {
null
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.wordpress.android.ui.mysite.cards.domain

import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.PopupMenu
import org.wordpress.android.R
import org.wordpress.android.databinding.DashboardCardDomainBinding
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard.DashboardDomainCard
import org.wordpress.android.ui.mysite.cards.dashboard.CardViewHolder
import org.wordpress.android.ui.utils.ListItemInteraction
import org.wordpress.android.ui.utils.UiHelpers
import org.wordpress.android.util.extensions.viewBinding

class DashboardDomainCardViewHolder(
parent: ViewGroup,
private val uiHelpers: UiHelpers
) : CardViewHolder<DashboardCardDomainBinding>(
parent.viewBinding(DashboardCardDomainBinding::inflate)
) {
fun bind(card: DashboardDomainCard) = with(binding) {
uiHelpers.setTextOrHide(dashboardCardDomainTitle, card.title)
dashboardCardDomainCta.setOnClickListener { card.onClick.click() }
dashboardDomainCardMore.setOnClickListener {
showMoreMenu(
card.onHideMenuItemClick,
card.onMoreMenuClick,
dashboardDomainCardMore,
)
}
}

private fun showMoreMenu(
onHideMenuItemClick: ListItemInteraction,
onMoreMenuClick: ListItemInteraction,
anchor: View
) {
onMoreMenuClick.click()
val popupMenu = PopupMenu(itemView.context, anchor)
popupMenu.setOnMenuItemClickListener {
when (it.itemId) {
R.id.dashboard_card_domain_menu_item_hide_this -> {
onHideMenuItemClick.click()
return@setOnMenuItemClickListener true
}
else -> return@setOnMenuItemClickListener true
}
}
popupMenu.inflate(R.menu.dashboard_card_domain_menu)
popupMenu.show()
}
}
71 changes: 71 additions & 0 deletions WordPress/src/main/res/layout/dashboard_card_domain.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/dashboard_card_domain_cta"
style="@style/WordPress.CardView.Unelevated"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?attr/selectableItemBackground">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/margin_extra_large">

<ImageView
android:id="@+id/dashboard_domain_card_more"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/content_description_more"
android:focusable="true"
ravishanker marked this conversation as resolved.
Show resolved Hide resolved
android:src="@drawable/ic_more_vert_white_24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="?attr/wpColorOnSurfaceMedium"
tools:ignore="TouchTargetSizeCheck" />
ravishanker marked this conversation as resolved.
Show resolved Hide resolved

<com.google.android.material.textview.MaterialTextView
android:id="@+id/dashboard_card_domain_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/dashboard_card_domain_title"
android:textAlignment="viewStart"
android:textAppearance="@style/blaze_title"
ravishanker marked this conversation as resolved.
Show resolved Hide resolved
app:layout_constraintEnd_toStartOf="@+id/dashboard_domain_card_more"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<ImageView
android:id="@+id/dashboard_card_domain_icon"
android:src="@drawable/ic_domains_white_24dp"
android:background="@color/jetpack_green"
android:contentDescription="@string/content_description_more"
android:clickable="true"
android:focusable="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/dashboard_card_domain_title"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="TouchTargetSizeCheck"/>
ravishanker marked this conversation as resolved.
Show resolved Hide resolved

<com.google.android.material.textview.MaterialTextView
android:id="@+id/dashboard_card_domain_sub_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingStart="@dimen/margin_medium"
android:paddingEnd="@dimen/margin_medium"
android:paddingBottom="@dimen/margin_medium"
android:paddingTop="@dimen/margin_medium"
ravishanker marked this conversation as resolved.
Show resolved Hide resolved
android:text="@string/dashboard_card_domain_sub_title"
android:textAppearance="@style/blaze_sub_title"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/dashboard_card_domain_icon"
app:layout_constraintTop_toBottomOf="@+id/dashboard_card_domain_title"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>

7 changes: 7 additions & 0 deletions WordPress/src/main/res/menu/dashboard_card_domain_menu.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/dashboard_card_domain_menu_item_hide_this"
android:title="@string/dashboard_card_domain_menu_hide_this"
android:icon="@drawable/ic_not_visible_white_24dp"/>
</menu>
5 changes: 5 additions & 0 deletions WordPress/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4433,6 +4433,11 @@ translators: %s: Select control option value e.g: "Auto, 25%". -->
<string name="jetpack_full_plugin_install_onboarding_contact_support_button">Contact support</string>
<string name="jetpack_full_plugin_install_onboarding_dismiss_button_content_description">Close</string>

<!-- Dashboard Card Domain-->
<string name="dashboard_card_domain_title">Own your online identity with a custom domain</string>
<string name="dashboard_card_domain_sub_title">Stake your claim on your corner of the web with a site address that\'s easy to find, share, and follow.</string>
<string name="dashboard_card_domain_menu_hide_this">Hide this</string>

<!-- Promote Blaze Card-->
<string name="promote_blaze_card_title">Promote your content with Blaze</string>
<string name="promote_blaze_card_sub_title">Display your work across millions of sites.</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import org.wordpress.android.BaseUnitTest
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard.BloggingPromptCard
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard.BloggingPromptCard.BloggingPromptCardWithData
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard.DashboardDomainCard
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard.ErrorCard
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard.PostCard.FooterLink
import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.DashboardCards.DashboardCard.PostCard.PostCardWithPostItems
Expand All @@ -36,6 +37,7 @@ import org.wordpress.android.ui.mysite.cards.dashboard.posts.PostCardBuilder
import org.wordpress.android.ui.mysite.cards.dashboard.posts.PostCardType.CREATE_FIRST
import org.wordpress.android.ui.mysite.cards.dashboard.posts.PostCardType.DRAFT
import org.wordpress.android.ui.mysite.cards.dashboard.todaysstats.TodaysStatsCardBuilder
import org.wordpress.android.ui.mysite.cards.domain.DashboardDomainCardBuilder
import org.wordpress.android.ui.utils.UiString.UiStringText

@ExperimentalCoroutinesApi
Expand All @@ -53,6 +55,9 @@ class CardsBuilderTest : BaseUnitTest() {
@Mock
lateinit var promoteWithBlazeCardBuilder: PromoteWithBlazeCardBuilder

@Mock
lateinit var dashboardDomainCardBuilder: DashboardDomainCardBuilder

@Mock
lateinit var pagesCardBuilder: PagesCardBuilder

Expand All @@ -65,6 +70,7 @@ class CardsBuilderTest : BaseUnitTest() {
postCardBuilder,
bloggingPromptCardsBuilder,
promoteWithBlazeCardBuilder,
dashboardDomainCardBuilder,
pagesCardBuilder
)
}
Expand Down Expand Up @@ -182,6 +188,20 @@ class CardsBuilderTest : BaseUnitTest() {
assertThat(cards.findPromoteWithBlazeCard()).isNotNull
}

@Test
fun `given is not eligible for domain, when cards are built, then domain card is not built`() {
val cards = buildDashboardCards(isEligibleForDomainCard = false)

assertThat(cards.findDashboardDomainCard()).isNull()
}

@Test
fun `given is eligible for domain, when cards are built, then domain card is built`() {
val cards = buildDashboardCards(isEligibleForDomainCard = true)

assertThat(cards.findDashboardDomainCard()).isNotNull
}

@Test
fun `given has pages, when cards are built, then pages card is not built`() {
val cards = buildDashboardCards(hasPagesCard = false)
Expand Down Expand Up @@ -211,6 +231,9 @@ class CardsBuilderTest : BaseUnitTest() {
private fun DashboardCards.findPromoteWithBlazeCard() =
this.cards.find { it is PromoteWithBlazeCard } as? PromoteWithBlazeCard

private fun DashboardCards.findDashboardDomainCard() =
this.cards.find { it is DashboardDomainCard } as? DashboardDomainCard

private fun DashboardCards.findPagesCard() =
this.cards.find { it is PagesCardWithData } as? PagesCardWithData

Expand All @@ -222,6 +245,8 @@ class CardsBuilderTest : BaseUnitTest() {

private val promoteWithBlazeCard = mock<PromoteWithBlazeCard>()

private val dashboardDomainCard = mock<DashboardDomainCard>()

private val pagesCard = mock<PagesCardWithData>()

private fun createPostCards() = listOf(
Expand Down Expand Up @@ -259,6 +284,8 @@ class CardsBuilderTest : BaseUnitTest() {
doAnswer { if (hasBlogginPrompt) blogingPromptCard else null }.whenever(bloggingPromptCardsBuilder).build(any())
doAnswer { if (isEligibleForBlaze) promoteWithBlazeCard else null }.whenever(promoteWithBlazeCardBuilder)
.build(any())
doAnswer { if (isEligibleForDomainCard) dashboardDomainCard else null }.whenever(dashboardDomainCardBuilder)
.build(any())
doAnswer { if(hasPagesCard) pagesCard else null }.whenever(pagesCardBuilder).build(any())
return cardsBuilder.build(
dashboardCardsBuilderParams = DashboardCardsBuilderParams(
Expand Down
Loading