Skip to content

Commit

Permalink
Automatic pagination added to people, projects, uploads, and vaults f…
Browse files Browse the repository at this point in the history
…uns. Closes #2
  • Loading branch information
peterbanda committed Apr 27, 2020
1 parent 458b72d commit b8ceb24
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 17 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Scala Basecamp 3 Client

The service currently supports 6 calls
- *projects* (accountId: Int)
- *people* (accountId: Int)
- *uploads* (accountId: Int, bucket: Long, vault: Long)
- *vaults* (accountId: Int, bucket: Long, vault: Long)
- *projects* (accountId: Int) - with pagination
- *people* (accountId: Int) - with pagination
- *uploads* (accountId: Int, bucket: Long, vault: Long) - with pagination
- *vaults* (accountId: Int, bucket: Long, vault: Long) - with pagination
- *downloadFile* (accountId: Int, bucket: Long, upload: Long, fileName: String)
- *downloadFileStreamed* (accountId: Int, bucket: Long, upload: Long, fileName: String)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,30 @@ import scala.concurrent.Future
@ImplementedBy(classOf[Basecamp3ServiceImpl])
trait Basecamp3Service {

def projects(accountId: Int): Future[Seq[Project]]
def projects(
accountId: Int,
page: Option[Int] = None
): Future[Seq[Project]]

def people(accountId: Int): Future[Seq[Person]]
def people(
accountId: Int,
page: Option[Int] = None
): Future[Seq[Person]]

def uploads(accountId: Int, bucket: Long, vault: Long): Future[Seq[Upload]]
def uploads(
accountId: Int,
bucket: Long,
vault: Long,
page: Option[Int] = None
): Future[Seq[Upload]]

// vault ~ folder
def vaults(accountId: Int, bucket: Long, vault: Long): Future[Seq[Vault]]
def vaults(
accountId: Int,
bucket: Long,
vault: Long,
page: Option[Int] = None
): Future[Seq[Vault]]

def downloadFile(accountId: Int, bucket: Long, upload: Long, fileName: String): Future[ByteString]

Expand Down Expand Up @@ -73,25 +89,33 @@ protected class Basecamp3ServiceImpl @Inject()(config: Config) extends Basecamp3
new AhcWSClient(config)
}

override def projects(accountId: Int) =
getRequest[Project](EndPoint.projects, accountId)
override def projects(
accountId: Int,
page: Option[Int]
) =
getRequest[Project](EndPoint.projects, accountId, page)

override def people(accountId: Int) =
getRequest[Person](EndPoint.people, accountId)
override def people(
accountId: Int,
page: Option[Int]
) =
getRequest[Person](EndPoint.people, accountId, page)

override def uploads(
accountId: Int,
bucket: Long,
vault: Long
vault: Long,
page: Option[Int]
) =
getRequest[Upload](EndPoint.uploads(bucket, vault), accountId)
getRequest[Upload](EndPoint.uploads(bucket, vault), accountId, page)

override def vaults(
accountId: Int,
bucket: Long,
vault: Long
vault: Long,
page: Option[Int]
) =
getRequest[Vault](EndPoint.vaults(bucket, vault), accountId)
getRequest[Vault](EndPoint.vaults(bucket, vault), accountId, page)

override def downloadFile(
accountId: Int,
Expand Down Expand Up @@ -148,9 +172,40 @@ protected class Basecamp3ServiceImpl @Inject()(config: Config) extends Basecamp3
private def getRequest[T: Reads](
endPoint: EndPoint.Value,
accountId: Int,
page: Option[Int] = None,
withAuthorization: Boolean = true
): Future[Seq[T]] =
getRequestRaw(url(endPoint, accountId), withAuthorization).map { response =>
page.map( page =>
getRequestAux(endPoint, accountId, Some(page), withAuthorization)
).getOrElse(
getRequestInc(endPoint, accountId, 1, withAuthorization)
)

private def getRequestInc[T: Reads](
endPoint: EndPoint.Value,
accountId: Int,
page: Int,
withAuthorization: Boolean
): Future[Seq[T]] =
for {
results <- getRequestAux(endPoint, accountId, Some(page), withAuthorization)
moreResults <- if (results.nonEmpty)
getRequestInc(endPoint, accountId, page + 1, withAuthorization)
else
Future(Nil)
} yield
results ++ moreResults

private def getRequestAux[T: Reads](
endPoint: EndPoint.Value,
accountId: Int,
page: Option[Int] = None,
withAuthorization: Boolean = true
): Future[Seq[T]] = {
val baseUrl = url(endPoint, accountId)
val fullUrl = page.map(baseUrl + "?page=" + _).getOrElse(baseUrl)

getRequestRaw(fullUrl, withAuthorization).map { response =>
handleErrorResponse(response)
response.json match {
case array: JsArray =>
Expand All @@ -169,6 +224,7 @@ protected class Basecamp3ServiceImpl @Inject()(config: Config) extends Basecamp3
}.recover {
case e: TimeoutException => throw new Basecamp3Exception(s"Basecamp3Service.$endPoint timed out: ${e.getMessage}.")
}
}

private def getRequestRaw(
url: String,
Expand Down

0 comments on commit b8ceb24

Please sign in to comment.