diff --git a/lib/src/main/java/com/kirkbushman/zammad/ZammadApi.kt b/lib/src/main/java/com/kirkbushman/zammad/ZammadApi.kt index 359fe2a..867c70f 100644 --- a/lib/src/main/java/com/kirkbushman/zammad/ZammadApi.kt +++ b/lib/src/main/java/com/kirkbushman/zammad/ZammadApi.kt @@ -240,6 +240,15 @@ interface ZammadApi { @HeaderMap header: HashMap ): Call + @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 + ): Call + @GET("/api/v1/online_notifications") fun onlineNotifications( @HeaderMap header: HashMap diff --git a/lib/src/main/java/com/kirkbushman/zammad/ZammadClient.kt b/lib/src/main/java/com/kirkbushman/zammad/ZammadClient.kt index 495b28a..aca1e03 100644 --- a/lib/src/main/java/com/kirkbushman/zammad/ZammadClient.kt +++ b/lib/src/main/java/com/kirkbushman/zammad/ZammadClient.kt @@ -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? { val authMap = getHeaderMap() diff --git a/lib/src/main/java/com/kirkbushman/zammad/models/TicketArticle.kt b/lib/src/main/java/com/kirkbushman/zammad/models/TicketArticle.kt index 631e58f..194ed90 100644 --- a/lib/src/main/java/com/kirkbushman/zammad/models/TicketArticle.kt +++ b/lib/src/main/java/com/kirkbushman/zammad/models/TicketArticle.kt @@ -64,7 +64,7 @@ data class TicketArticle( val internal: Boolean, @Json(name = "attachments") - val attachment: List, + val attachments: List, @Json(name = "created_by_id") override val createdById: Int, @@ -99,6 +99,6 @@ data class TicketArticle( } fun hasAttachments(): Boolean { - return attachment.isNotEmpty() + return attachments.isNotEmpty() } } diff --git a/sampleapp/src/main/AndroidManifest.xml b/sampleapp/src/main/AndroidManifest.xml index da097c2..eb7e9c2 100644 --- a/sampleapp/src/main/AndroidManifest.xml +++ b/sampleapp/src/main/AndroidManifest.xml @@ -31,6 +31,8 @@ + + diff --git a/sampleapp/src/main/java/com/kirkbushman/sampleapp/activities/ArticlesActivity.kt b/sampleapp/src/main/java/com/kirkbushman/sampleapp/activities/ArticlesActivity.kt index 4aea2c0..b24ba35 100644 --- a/sampleapp/src/main/java/com/kirkbushman/sampleapp/activities/ArticlesActivity.kt +++ b/sampleapp/src/main/java/com/kirkbushman/sampleapp/activities/ArticlesActivity.kt @@ -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 @@ -33,13 +33,19 @@ class ArticlesActivity : AppCompatActivity() { private val articles = ArrayList() 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) + } }) } diff --git a/sampleapp/src/main/java/com/kirkbushman/sampleapp/activities/AttachmentActivity.kt b/sampleapp/src/main/java/com/kirkbushman/sampleapp/activities/AttachmentActivity.kt new file mode 100644 index 0000000..5741658 --- /dev/null +++ b/sampleapp/src/main/java/com/kirkbushman/sampleapp/activities/AttachmentActivity.kt @@ -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 + }) + } +} diff --git a/sampleapp/src/main/java/com/kirkbushman/sampleapp/activities/AttachmentsActivity.kt b/sampleapp/src/main/java/com/kirkbushman/sampleapp/activities/AttachmentsActivity.kt new file mode 100644 index 0000000..3fcbf6e --- /dev/null +++ b/sampleapp/src/main/java/com/kirkbushman/sampleapp/activities/AttachmentsActivity.kt @@ -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() + + 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) + } +} diff --git a/sampleapp/src/main/java/com/kirkbushman/sampleapp/controllers/ArticlesController.kt b/sampleapp/src/main/java/com/kirkbushman/sampleapp/controllers/ArticlesController.kt index 5947bf8..ecc2b97 100644 --- a/sampleapp/src/main/java/com/kirkbushman/sampleapp/controllers/ArticlesController.kt +++ b/sampleapp/src/main/java/com/kirkbushman/sampleapp/controllers/ArticlesController.kt @@ -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() @@ -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) } } } } diff --git a/sampleapp/src/main/java/com/kirkbushman/sampleapp/controllers/AttachmentsController.kt b/sampleapp/src/main/java/com/kirkbushman/sampleapp/controllers/AttachmentsController.kt new file mode 100644 index 0000000..1a8a535 --- /dev/null +++ b/sampleapp/src/main/java/com/kirkbushman/sampleapp/controllers/AttachmentsController.kt @@ -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() + + fun setAttachments(attachments: Collection) { + 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) } + } + } + } +} diff --git a/sampleapp/src/main/java/com/kirkbushman/sampleapp/controllers/OnArticleCallback.kt b/sampleapp/src/main/java/com/kirkbushman/sampleapp/controllers/OnArticleCallback.kt new file mode 100644 index 0000000..1923b66 --- /dev/null +++ b/sampleapp/src/main/java/com/kirkbushman/sampleapp/controllers/OnArticleCallback.kt @@ -0,0 +1,6 @@ +package com.kirkbushman.sampleapp.controllers + +interface OnArticleCallback : OnClickCallback { + + fun onAttachmentsClick(position: Int) +} diff --git a/sampleapp/src/main/java/com/kirkbushman/sampleapp/models/ArticleModel.kt b/sampleapp/src/main/java/com/kirkbushman/sampleapp/models/ArticleModel.kt index 2d6e9e0..32fd684 100644 --- a/sampleapp/src/main/java/com/kirkbushman/sampleapp/models/ArticleModel.kt +++ b/sampleapp/src/main/java/com/kirkbushman/sampleapp/models/ArticleModel.kt @@ -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 @@ -18,17 +19,33 @@ abstract class ArticleModel : EpoxyModelWithHolder() { @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) } } @@ -38,4 +55,5 @@ class ArticleHolder : KotlinHolder() { val articleTo by bind(R.id.article_to) val articleSubject by bind(R.id.article_subject) val articleText by bind(R.id.article_text) + val attachmentsBttn by bind