Skip to content

Commit

Permalink
Merge pull request #8 from MahmoudMabrok/feat/events
Browse files Browse the repository at this point in the history
feat: add event api and ui
  • Loading branch information
MahmoudMabrok authored Jan 7, 2024
2 parents 14d8db6 + d53953e commit 4d75a84
Show file tree
Hide file tree
Showing 12 changed files with 320 additions and 69 deletions.
1 change: 1 addition & 0 deletions composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ kotlin {
implementation(libs.moko.mvvm)
implementation(libs.ktor.core)
implementation(libs.contentNegotiation)
implementation(libs.logging)
implementation(libs.serializationKotlinxJson)
implementation(libs.composeIcons.featherIcons)
implementation(libs.kotlinx.serialization.json)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package tools.mo3ta.githubactivity.components

import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
Expand All @@ -26,7 +30,14 @@ import tools.mo3ta.githubactivity.model.UserDetails
@OptIn(ExperimentalLayoutApi::class)
@Composable
fun BasicUserData(userDetails: UserDetails?, stars: Int? = 0) {
Column {
Column(
modifier = Modifier
.fillMaxWidth()
.border(2.dp, MaterialTheme.colorScheme.primary, RoundedCornerShape(4.dp))
.padding(horizontal = 8.dp, vertical = 16.dp)
) {


userDetails?.avatar_url?.let {
KamelImage(
asyncPainterResource(it),
Expand All @@ -51,7 +62,8 @@ fun BasicUserData(userDetails: UserDetails?, stars: Int? = 0) {
Text(
it,
modifier = Modifier.align(Alignment.CenterHorizontally),
style = MaterialTheme.typography.labelSmall
style = MaterialTheme.typography.labelSmall,
color = Color.LightGray
)
}
userDetails?.email?.let {
Expand All @@ -69,29 +81,35 @@ fun BasicUserData(userDetails: UserDetails?, stars: Int? = 0) {
)
}
Spacer(modifier = Modifier.size(16.dp))
FlowRow {

FlowRow(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly
) {
userDetails?.public_repos?.let {
LabeledData("Public Repo", it.toString(), modifier = Modifier.wrapContentSize())
}
userDetails?.followers?.let {
LabeledData("Follower", it.toString(), modifier = Modifier.weight(1f))
LabeledData("Follower", it.toString(), modifier = Modifier.wrapContentSize())
}
userDetails?.following?.let {
LabeledData("Following", it.toString(), modifier = Modifier.weight(1f))
LabeledData("Following", it.toString(), modifier = Modifier.wrapContentSize())
}

stars?.let { LabeledData("Stars", it.toString(), modifier = Modifier.weight(1f)) }

userDetails?.public_gists?.let {
LabeledData("Public Gists", it.toString(), modifier = Modifier.weight(1f))
stars?.let {
LabeledData(
"Stars",
it.toString(),
modifier = Modifier.wrapContentSize()
)
}

userDetails?.company?.let {
LabeledData("Company", it, modifier = Modifier.weight(1f))
LabeledData("Company", it, modifier = Modifier.wrapContentSize())
}

userDetails?.location?.let {
LabeledData("Location", it, modifier = Modifier.weight(1f))
LabeledData("Location", it, modifier = Modifier.wrapContentSize())
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,32 @@ package tools.mo3ta.githubactivity.components

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Card
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

@Composable
fun LabeledData(title: String, value: String, modifier: Modifier = Modifier) {

Column(
modifier = modifier.padding(horizontal = 16.dp, vertical = 4.dp)
) {
Text(
value,
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.align(Alignment.CenterHorizontally)
)
Text(
title,
style = MaterialTheme.typography.titleSmall,
modifier = Modifier.align(Alignment.CenterHorizontally),
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
Card(modifier) {
Column(
modifier = modifier.padding(horizontal = 16.dp, vertical = 4.dp)
) {
Text(
value,
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.align(Alignment.CenterHorizontally)
)
Text(
title,
style = MaterialTheme.typography.titleSmall,
modifier = Modifier.align(Alignment.CenterHorizontally),
color = Color.LightGray
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package tools.mo3ta.githubactivity.components

import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import tools.mo3ta.githubactivity.model.UserEvents


@OptIn(ExperimentalLayoutApi::class)
@Composable
fun UserEventsData(events: UserEvents?) {
events?.let {
Column(
modifier = Modifier
.fillMaxWidth()
.border(2.dp, MaterialTheme.colorScheme.primary, RoundedCornerShape(4.dp))
.padding(horizontal = 8.dp, vertical = 16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("UserEvents")

Spacer(modifier = Modifier.size(16.dp))

FlowRow(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalArrangement = Arrangement.Center
) {
LabeledData(
"Total Push",
events.pullRequestOpened.toString(),
modifier = Modifier.wrapContentSize()
)
LabeledData(
"PR created",
events.pullRequestOpened.toString(),
modifier = Modifier.wrapContentSize()
)
LabeledData(
"PR Approved",
events.pullRequestApproved.toString(),
modifier = Modifier.wrapContentSize()
)
LabeledData(
"Review Comments",
events.reviewCommentAdded.toString(),
modifier = Modifier.wrapContentSize()
)
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,52 @@ package tools.mo3ta.githubactivity.data

import io.ktor.client.HttpClient
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.plugins.logging.Logging
import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.json.Json
import tools.mo3ta.githubactivity.model.RepoDetails
import tools.mo3ta.githubactivity.model.UserDetails
import tools.mo3ta.githubactivity.model.UserEvent

interface GithubService {

suspend fun getUserDetails(
userName: String): UserDetails
userName: String
): UserDetails

suspend fun loadUserRepos(
userName: String,
pageNumber: Int): List<RepoDetails>
userName: String,
pageNumber: Int
): List<RepoDetails>

suspend fun loadUserEvents(
userName: String,
pageNumber: Int
): List<UserEvent>

fun closeClient()

companion object {
fun create(
githubKey: String,
enterprise: String,
isEnterprise: Boolean = false,
githubKey: String,
enterprise: String,
isEnterprise: Boolean = false,
):
GithubService {
return GithubServiceImp(
httpClient = HttpClient {
install(ContentNegotiation) {
json(json = Json {
ignoreUnknownKeys = true
})
}
},
githubKey,
enterprise,
isEnterprise
httpClient = HttpClient {
install(ContentNegotiation) {
json(json = Json {
ignoreUnknownKeys = true
})
}
install(Logging) {
level = io.ktor.client.plugins.logging.LogLevel.ALL
}
},
githubKey,
enterprise,
isEnterprise
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,50 +8,85 @@ import io.ktor.client.request.parameter
import io.ktor.http.HttpHeaders
import tools.mo3ta.githubactivity.model.RepoDetails
import tools.mo3ta.githubactivity.model.UserDetails
import tools.mo3ta.githubactivity.model.UserEvent
import tools.mo3ta.githubactivity.utils.NetworkUtils.prepareUrl

class GithubServiceImp(
val httpClient: HttpClient,
val githubKey: String,
enterprise: String,
isEnterprise: Boolean = false
val httpClient: HttpClient,
val githubKey: String,
enterprise: String,
isEnterprise: Boolean = false
) : GithubService {

val baseUrl = prepareUrl(isEnterprise,
enterprise)
val baseUrl = prepareUrl(
isEnterprise,
enterprise
)

override suspend fun getUserDetails(
userName: String): UserDetails {
userName: String
): UserDetails {
return httpClient
.get("https://$baseUrl/users/${userName}") {
headers {
if (githubKey.isNotEmpty()) {
append(HttpHeaders.Authorization,
"Bearer $githubKey")
}
.get("https://$baseUrl/users/${userName}") {
headers {
if (githubKey.isNotEmpty()) {
append(
HttpHeaders.Authorization,
"Bearer $githubKey"
)
}
}.body()
}
}.body()
}

override suspend fun loadUserRepos(
userName: String,
pageNumber: Int
userName: String,
pageNumber: Int
): List<RepoDetails> {
return httpClient
.get("https://$baseUrl/users/${userName}/repos") {
headers {
if (githubKey.isNotEmpty()) {
append(HttpHeaders.Authorization,
"Bearer $githubKey")
}
.get("https://$baseUrl/users/${userName}/repos") {
headers {
if (githubKey.isNotEmpty()) {
append(
HttpHeaders.Authorization,
"Bearer $githubKey"
)
}
parameter("page",
pageNumber.toString())
parameter("per_page",
100.toString())
}.body()
}
parameter(
"page",
pageNumber.toString()
)
parameter(
"per_page",
100.toString()
)
}.body()
}

override suspend fun loadUserEvents(userName: String, pageNumber: Int): List<UserEvent> {
return httpClient
.get("https://$baseUrl/users/${userName}/events") {
headers {
if (githubKey.isNotEmpty()) {
append(
HttpHeaders.Authorization,
"Bearer $githubKey"
)
}
}
parameter(
"page",
pageNumber.toString()
)
parameter(
"per_page",
100.toString()
)
}.body()
}


override fun closeClient() {
httpClient.close()
}
Expand Down
Loading

0 comments on commit 4d75a84

Please sign in to comment.