Skip to content

Commit

Permalink
MBL-2157: Add Similar Projects GQL query & Apollo client method
Browse files Browse the repository at this point in the history
- Add another `projectTransformer` function to
  GraphQLTransformers for a `fragment.SimilarProject`
- Add `percentFunded` property to Project data model

Co-authored-by: Tony Teate <[email protected]>
  • Loading branch information
tonyteate and tonyteate authored Mar 5, 2025
1 parent b55b734 commit 2e7adb0
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 1 deletion.
11 changes: 11 additions & 0 deletions app/src/main/graphql/fragments.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,17 @@ fragment project on Project {
slug
}

fragment similarProject on Project {
id
pid
name
slug
isLaunched
deadlineAt
percentFunded
imageUrl(width: $imageUrlWidth)
}

fragment reward on Reward {
id
name
Expand Down
15 changes: 15 additions & 0 deletions app/src/main/graphql/project.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -214,4 +214,19 @@ query BuildPaymentPlan($slug: String!, $amount: String!) {
}
}
}
}

query FetchSimilarProjects($first: Int = 4, $similarToPid: String!, $excludePid: Int!, $recommended: Boolean, $seed: Int, $imageUrlWidth: Int = 1024) {
projects(
first: $first
state: LIVE
similarToPid: $similarToPid
excludePids: [$excludePid]
seed: $seed
recommended: $recommended
) {
nodes {
...similarProject
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,10 @@ open class MockApolloClientV2 : ApolloClientTypeV2 {
return Result.success(SearchEnvelope())
}

override suspend fun fetchSimilarProjects(pid: Long): Result<List<Project>> {
return Result.success(listOf())
}

override fun cleanDisposables() {
TODO("Not yet implemented")
}
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/java/com/kickstarter/models/Project.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class Project private constructor(
private val launchedAt: DateTime?,
private val location: Location?,
private val name: String,
private val percentFunded: Int?,
private val permissions: List<Permission?>?,
private val pledged: Double,
private val photo: Photo?,
Expand Down Expand Up @@ -99,6 +100,7 @@ class Project private constructor(
fun launchedAt() = this.launchedAt
fun location() = this.location
fun name() = this.name
fun percentFunded() = this.percentFunded
fun permissions() = this.permissions
fun pledged() = this.pledged
fun photo() = this.photo
Expand Down Expand Up @@ -161,6 +163,7 @@ class Project private constructor(
private var launchedAt: DateTime? = null,
private var location: Location? = null,
private var name: String = "",
private var percentFunded: Int? = null,
private var permissions: List<Permission?>? = null,
private var pledged: Double = 0.0,
private var photo: Photo? = null,
Expand Down Expand Up @@ -225,6 +228,7 @@ class Project private constructor(
fun launchedAt(launchedAt: DateTime?) = apply { this.launchedAt = launchedAt }
fun location(location: Location?) = apply { this.location = location }
fun name(name: String?) = apply { this.name = name ?: "" }
fun percentFunded(percentFunded: Int?) = apply { this.percentFunded = percentFunded }
fun permissions(permissions: List<Permission?>?) = apply { this.permissions = permissions?.filterNotNull() ?: emptyList() }
fun pledged(pledged: Double?) = apply { this.pledged = pledged ?: 0.0 }
fun photo(photo: Photo?) = apply { this.photo = photo }
Expand Down Expand Up @@ -282,6 +286,7 @@ class Project private constructor(
launchedAt = launchedAt,
location = location,
name = name,
percentFunded = percentFunded,
permissions = permissions,
pledged = pledged,
photo = photo,
Expand Down Expand Up @@ -345,6 +350,7 @@ class Project private constructor(
launchedAt = launchedAt,
location = location,
name = name,
percentFunded = percentFunded,
permissions = permissions,
pledged = pledged,
photo = photo,
Expand Down Expand Up @@ -521,6 +527,7 @@ class Project private constructor(
launchedAt() == other.launchedAt() &&
location() == other.location() &&
name() == other.name() &&
percentFunded() == other.percentFunded() &&
permissions() == other.permissions() &&
pledged() == other.pledged() &&
photo() == other.photo() &&
Expand Down
24 changes: 23 additions & 1 deletion app/src/main/java/com/kickstarter/services/KSApolloClientV2.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import com.kickstarter.FetchCategoryQuery
import com.kickstarter.FetchProjectQuery
import com.kickstarter.FetchProjectRewardsQuery
import com.kickstarter.FetchProjectsQuery
import com.kickstarter.FetchSimilarProjectsQuery
import com.kickstarter.GetBackingQuery
import com.kickstarter.GetCommentQuery
import com.kickstarter.GetProjectAddOnsQuery
Expand Down Expand Up @@ -228,8 +229,9 @@ interface ApolloClientTypeV2 {
fun getPledgedProjectsOverviewPledges(inputData: PledgedProjectsOverviewQueryData): Observable<PledgedProjectsOverviewEnvelope>
fun getRewardsFromProject(slug: String): Observable<List<Reward>>
fun buildPaymentPlan(input: BuildPaymentPlanData): Observable<PaymentPlan>
suspend fun getSearchProjects(discoveryParams: DiscoveryParams, cursor: String? = null): Result<SearchEnvelope>
fun updateBackerCompleted(inputData: UpdateBackerCompletedData): Observable<Boolean>
suspend fun getSearchProjects(discoveryParams: DiscoveryParams, cursor: String? = null): Result<SearchEnvelope>
suspend fun fetchSimilarProjects(pid: Long): Result<List<Project>>
fun cleanDisposables()
}

Expand Down Expand Up @@ -1847,6 +1849,26 @@ class KSApolloClientV2(val service: ApolloClient, val gson: Gson) : ApolloClient
} ?: SearchEnvelope()
}

override suspend fun fetchSimilarProjects(pid: Long): Result<List<Project>> = executeForResult {
val query = FetchSimilarProjectsQuery(
first = Optional.present(4),
similarToPid = pid.toString(),
excludePid = pid.toInt(),
recommended = Optional.present(true),
seed = Optional.present(pid.toInt())
)
val response = this.service.query(query).execute()

if (response.hasErrors())
throw buildClientException(response.errors)

response.data?.let { responseData ->
responseData.projects?.nodes?.map {
projectTransformer(it?.similarProject)
}
} ?: emptyList()
}

sealed class KSApolloClientV2Exception(
message: String? = null,
cause: Throwable? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.kickstarter.fragment.FullProject
import com.kickstarter.fragment.PpoCard.DeliveryAddress
import com.kickstarter.fragment.ProjectCard
import com.kickstarter.fragment.RewardImage
import com.kickstarter.fragment.SimilarProject
import com.kickstarter.libs.Permission
import com.kickstarter.libs.utils.extensions.isNotNull
import com.kickstarter.libs.utils.extensions.isNull
Expand Down Expand Up @@ -833,6 +834,32 @@ fun backingTransformer(backingGr: com.kickstarter.fragment.Backing?): Backing {
.build()
}

/**
* Transform the Project GraphQL data structure into our own Project data model
* @param fragment.SimilarProject similarProjectFragment
* @return Project
*/
fun projectTransformer(similarProjectFragment: SimilarProject?): Project {
val id = decodeRelayId(similarProjectFragment?.id) ?: -1
val name = similarProjectFragment?.name
val slug = similarProjectFragment?.slug
val displayPrelaunch = (similarProjectFragment?.isLaunched ?: false).negate()
val deadline = similarProjectFragment?.deadlineAt
val percentFunded = similarProjectFragment?.percentFunded
val photo = getPhoto(similarProjectFragment?.imageUrl, null)

return Project.builder()
.currencyTrailingCode(false) // - This field is available on V1 Configuration Object
.displayPrelaunch(displayPrelaunch)
.deadline(deadline)
.id(id)
.name(name)
.percentFunded(percentFunded)
.photo(photo) // - now we get the full size for field from GraphQL, but V1 provided several image sizes
.slug(slug)
.build()
}

/**
* For addOns we receive this kind of data structure :[D, D, D, D, D, C, E, E]
* and we need to transform it in : D(5),C(1),E(2)
Expand Down

0 comments on commit 2e7adb0

Please sign in to comment.