Skip to content

Commit

Permalink
added article attachments download, with sample
Browse files Browse the repository at this point in the history
  • Loading branch information
luca committed Aug 30, 2019
1 parent ef99651 commit 8558565
Show file tree
Hide file tree
Showing 16 changed files with 348 additions and 5 deletions.
9 changes: 9 additions & 0 deletions lib/src/main/java/com/kirkbushman/zammad/ZammadApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,15 @@ interface ZammadApi {
@HeaderMap header: HashMap<String, String>
): Call<TicketArticle>

@Streaming
@GET("/api/v1/ticket_attachment/{ticket_id}/{article_id}/{id}")
fun ticketArticleAttachment(
@Path("ticket_id") ticketId: Int,
@Path("article_id") articleId: Int,
@Path("id") attachmentId: Int,
@HeaderMap header: HashMap<String, String>
): Call<ResponseBody>

@GET("/api/v1/online_notifications")
fun onlineNotifications(
@HeaderMap header: HashMap<String, String>
Expand Down
24 changes: 24 additions & 0 deletions lib/src/main/java/com/kirkbushman/zammad/ZammadClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,30 @@ class ZammadClient(
return res.body()
}

fun ticketArticleAttachment(ticket: Ticket, ticketArticle: TicketArticle, articleAttachment: ArticleAttachment): String? {

return ticketArticleAttachment(ticket.id, ticketArticle.id, articleAttachment.id)
}

fun ticketArticleAttachment(ticketId: Int, articleId: Int, attachmentId: Int): String? {

val authMap = getHeaderMap()
val req = api.ticketArticleAttachment(
ticketId = ticketId,
articleId = articleId,
attachmentId = attachmentId,
header = authMap
)

val res = req.execute()

if (!res.isSuccessful) {
return null
}

return res.body()?.string()
}

fun onlineNotifications(): List<OnlineNotification>? {

val authMap = getHeaderMap()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ data class TicketArticle(
val internal: Boolean,

@Json(name = "attachments")
val attachment: List<ArticleAttachment>,
val attachments: List<ArticleAttachment>,

@Json(name = "created_by_id")
override val createdById: Int,
Expand Down Expand Up @@ -99,6 +99,6 @@ data class TicketArticle(
}

fun hasAttachments(): Boolean {
return attachment.isNotEmpty()
return attachments.isNotEmpty()
}
}
2 changes: 2 additions & 0 deletions sampleapp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
<activity android:name=".activities.TicketCreateActivity"></activity>
<activity android:name=".activities.TicketUpdateActivity"></activity>
<activity android:name=".activities.ActivitySearch"></activity>
<activity android:name=".activities.AttachmentActivity"></activity>
<activity android:name=".activities.AttachmentsActivity"></activity>
<activity android:name=".activities.UserActivity"></activity>
<activity android:name=".activities.UsersActivity"></activity>
<activity android:name=".activities.GroupActivity"></activity>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import androidx.appcompat.app.AppCompatActivity
import com.kirkbushman.sampleapp.R
import com.kirkbushman.sampleapp.SampleApplication
import com.kirkbushman.sampleapp.controllers.ArticlesController
import com.kirkbushman.sampleapp.controllers.OnClickCallback
import com.kirkbushman.sampleapp.controllers.OnArticleCallback
import com.kirkbushman.sampleapp.doAsync
import com.kirkbushman.zammad.models.Ticket
import com.kirkbushman.zammad.models.TicketArticle
Expand All @@ -33,13 +33,19 @@ class ArticlesActivity : AppCompatActivity() {

private val articles = ArrayList<TicketArticle>()
private val controller by lazy {
ArticlesController(object : OnClickCallback {
ArticlesController(object : OnArticleCallback {

override fun onClick(position: Int) {

val article = articles[position]
ArticleActivity.start(this@ArticlesActivity, article)
}

override fun onAttachmentsClick(position: Int) {

val article = articles[position]
AttachmentsActivity.start(this@ArticlesActivity, ticket, article)
}
})
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.kirkbushman.sampleapp.activities

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.kirkbushman.sampleapp.R
import com.kirkbushman.sampleapp.SampleApplication
import com.kirkbushman.sampleapp.doAsync
import com.kirkbushman.zammad.models.ArticleAttachment
import com.kirkbushman.zammad.models.Ticket
import com.kirkbushman.zammad.models.TicketArticle
import kotlinx.android.synthetic.main.activity_attachment.*

class AttachmentActivity : AppCompatActivity() {

companion object {

private const val PARAM_TICKET = "intent_param_ticket"
private const val PARAM_ARTICLE = "intent_param_article"
private const val PARAM_ATTACHMENT = "intent_param_attachment"

fun start(context: Context, ticket: Ticket, article: TicketArticle, attachment: ArticleAttachment) {

val intent = Intent(context, AttachmentActivity::class.java)
intent.putExtra(PARAM_TICKET, ticket)
intent.putExtra(PARAM_ARTICLE, article)
intent.putExtra(PARAM_ATTACHMENT, attachment)

context.startActivity(intent)
}
}

private val client by lazy { SampleApplication.instance.getClient() }

private val ticket by lazy { intent.getParcelableExtra(PARAM_TICKET) as Ticket }
private val article by lazy { intent.getParcelableExtra(PARAM_ARTICLE) as TicketArticle }
private val attachment by lazy { intent.getParcelableExtra(PARAM_ATTACHMENT) as ArticleAttachment }

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_attachment)

var fileContent = ""
doAsync(doWork = {

fileContent = client?.ticketArticleAttachment(ticket, article, attachment) ?: ""
}, onPost = {

attachment_text.text = fileContent
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.kirkbushman.sampleapp.activities

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.kirkbushman.sampleapp.R
import com.kirkbushman.sampleapp.controllers.AttachmentsController
import com.kirkbushman.sampleapp.controllers.OnClickCallback
import com.kirkbushman.zammad.models.ArticleAttachment
import com.kirkbushman.zammad.models.Ticket
import com.kirkbushman.zammad.models.TicketArticle
import kotlinx.android.synthetic.main.activity_attachments.*

class AttachmentsActivity : AppCompatActivity() {

companion object {

private const val PARAM_TICKET = "intent_param_ticket"
private const val PARAM_ARTICLE = "intent_param_article"

fun start(context: Context, ticket: Ticket, article: TicketArticle) {

val intent = Intent(context, AttachmentsActivity::class.java)
intent.putExtra(PARAM_TICKET, ticket)
intent.putExtra(PARAM_ARTICLE, article)

context.startActivity(intent)
}
}

private val ticket by lazy { intent.getParcelableExtra(PARAM_TICKET) as Ticket }
private val article by lazy { intent.getParcelableExtra(PARAM_ARTICLE) as TicketArticle }

private val attachments = ArrayList<ArticleAttachment>()

private val controller by lazy {
AttachmentsController(object : OnClickCallback {

override fun onClick(position: Int) {

val attachment = attachments[position]
AttachmentActivity.start(this@AttachmentsActivity, ticket, article, attachment)
}
})
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_attachments)

setSupportActionBar(toolbar)
supportActionBar?.let {
it.setDisplayHomeAsUpEnabled(true)
it.setDisplayShowHomeEnabled(true)
}

list.setHasFixedSize(true)
list.setController(controller)

attachments.addAll(article.attachments)
controller.setAttachments(attachments)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.kirkbushman.sampleapp.models.article
import com.kirkbushman.sampleapp.models.empty
import com.kirkbushman.zammad.models.TicketArticle

class ArticlesController(private val callback: OnClickCallback) : EpoxyController() {
class ArticlesController(private val callback: OnArticleCallback) : EpoxyController() {

private val articles = ArrayList<TicketArticle>()

Expand All @@ -29,6 +29,7 @@ class ArticlesController(private val callback: OnClickCallback) : EpoxyControlle
id(it.id)
article(it)
clickListener { _, _, _, position -> callback.onClick(position) }
attachmentsClick { _, _, _, position -> callback.onAttachmentsClick(position) }
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.kirkbushman.sampleapp.controllers

import com.airbnb.epoxy.EpoxyController
import com.kirkbushman.sampleapp.models.attachment
import com.kirkbushman.sampleapp.models.empty
import com.kirkbushman.zammad.models.ArticleAttachment

class AttachmentsController(private val callback: OnClickCallback) : EpoxyController() {

private val attachments = ArrayList<ArticleAttachment>()

fun setAttachments(attachments: Collection<ArticleAttachment>) {
this.attachments.clear()
this.attachments.addAll(attachments)
requestModelBuild()
}

override fun buildModels() {

if (attachments.isEmpty()) {
empty {
id("empty_items")
}
}

attachments.forEach {

attachment {
id(it.id)
attachment(it)
clickListener { _, _, _, position -> callback.onClick(position) }
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.kirkbushman.sampleapp.controllers

interface OnArticleCallback : OnClickCallback {

fun onAttachmentsClick(position: Int)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.kirkbushman.sampleapp.models

import android.view.View
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import com.airbnb.epoxy.EpoxyAttribute
Expand All @@ -18,17 +19,33 @@ abstract class ArticleModel : EpoxyModelWithHolder<ArticleHolder>() {
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
lateinit var clickListener: View.OnClickListener

@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
lateinit var attachmentsClick: View.OnClickListener

override fun bind(holder: ArticleHolder) {

holder.articleTo.text = article.to
holder.articleSubject.text = article.subject
holder.articleText.text = article.body

if (article.hasAttachments()) {
holder.attachmentsBttn.visibility = View.VISIBLE

val bttnText = "${article.attachments.size} Attachments"
holder.attachmentsBttn.setText(bttnText)
} else {
holder.attachmentsBttn.visibility = View.GONE
}

holder.container.setOnClickListener(clickListener)
holder.attachmentsBttn.setOnClickListener(attachmentsClick)
}

override fun unbind(holder: ArticleHolder) {
holder.attachmentsBttn.visibility = View.GONE

holder.container.setOnClickListener(null)
holder.attachmentsBttn.setOnClickListener(null)
}
}

Expand All @@ -38,4 +55,5 @@ class ArticleHolder : KotlinHolder() {
val articleTo by bind<TextView>(R.id.article_to)
val articleSubject by bind<TextView>(R.id.article_subject)
val articleText by bind<TextView>(R.id.article_text)
val attachmentsBttn by bind<Button>(R.id.attachments_bttn)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.kirkbushman.sampleapp.models

import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import com.airbnb.epoxy.EpoxyModelWithHolder
import com.kirkbushman.sampleapp.R
import com.kirkbushman.zammad.models.ArticleAttachment

@EpoxyModelClass(layout = R.layout.item_attachment)
abstract class AttachmentModel : EpoxyModelWithHolder<AttachmentHolder>() {

@EpoxyAttribute
lateinit var attachment: ArticleAttachment

@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
lateinit var clickListener: View.OnClickListener

override fun bind(holder: AttachmentHolder) {

holder.attachmentFilename.text = attachment.filename
holder.attachmentFilesize.text = attachment.size.toString()

holder.container.setOnClickListener(clickListener)
}

override fun unbind(holder: AttachmentHolder) {
holder.container.setOnClickListener(null)
}
}

class AttachmentHolder : KotlinHolder() {

val container by bind<LinearLayout>(R.id.container)
val attachmentFilename by bind<TextView>(R.id.attachment_filename)
val attachmentFilesize by bind<TextView>(R.id.attachment_filesize)
}
14 changes: 14 additions & 0 deletions sampleapp/src/main/res/layout/activity_attachment.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:id="@+id/attachment_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
/>

</ScrollView>
Loading

0 comments on commit 8558565

Please sign in to comment.