Skip to content

Commit

Permalink
Add lent item click actions & filtering
Browse files Browse the repository at this point in the history
Signed-off-by: Aron Heinecke <aron.heinecke@t-online.de>
  • Loading branch information
0xpr03 committed Apr 18, 2021
1 parent 8e4db00 commit 2fe49d5
Show file tree
Hide file tree
Showing 11 changed files with 265 additions and 23 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@
/config.toml
/out.txt
/testlabel.pdf
/lars.svg
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ data class AssignUser(
val first_name: String,
val last_name: String,
val username: String,
) : Parcelable
) : Parcelable {
fun asSelector(): Selectable.User = Selectable.User(id,name,"<todo>")
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class SelectorViewModel : ViewModel() {
*/
internal val lastType: MutableLiveData<Selectable.SelectableType?> = MutableLiveData(null)
/**
* Selected item, call resetSelected once a value got selected
* Selected item. Observe this to obtain selection of dialog. Call resetSelected once a value got selected
*/
val selected: MutableLiveData<SelectorFragment.SelectorData?> =
MutableLiveData()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package de.tu_darmstadt.seemoo.LARS.ui.lent

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import de.tu_darmstadt.seemoo.LARS.R
import de.tu_darmstadt.seemoo.LARS.data.model.Asset
import de.tu_darmstadt.seemoo.LARS.ui.info.AssetInfoBTFragment
import de.tu_darmstadt.seemoo.LARS.ui.user.AssetListFragment

/**
* Asset click action BSD fragment for LentFragment
*/
class LentClickActionBTFragment: BottomSheetDialogFragment() {
private lateinit var asset: Asset
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if(savedInstanceState == null) {
requireArguments().run {
asset = this.getParcelable(PARAM_ASSET)
}
} else {
asset = savedInstanceState.getParcelable(PARAM_ASSET)
}
}

override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putParcelable(PARAM_ASSET,asset)
}

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? { // Inflate the layout for this fragment
val viewModel: LentViewModel = ViewModelProvider(requireActivity())[LentViewModel::class.java]

val view = inflater.inflate(R.layout.fragment_lent_asset_action, container, false)
val btnFilter: Button = view.findViewById(R.id.frag_lent_asset_action_filter_button)
val btnInfo: Button = view.findViewById(R.id.frag_lent_asset_action_info_button)
val btnUserDetails: Button = view.findViewById(R.id.frag_lent_asset_action_userdetails_button)

val userName = asset?.assigned_to?.username ?: "<missing>"
btnFilter.text = getString(R.string.filter_by_user_x,userName)
btnUserDetails.text = getString(R.string.show_assets_of_x,userName)

btnFilter.setOnClickListener {
asset?.assigned_to?.run {
viewModel.filteredUser.value = this.asSelector()
}
dismiss()
}

btnInfo.setOnClickListener {
asset?.run {
AssetInfoBTFragment.newInstance(this).show(
parentFragmentManager,
"LentAssetInfoBTFragment"
)
}
dismiss()
}

btnUserDetails.setOnClickListener {
asset?.assigned_to?.run {
val (id,args) = AssetListFragment.newInstancePair(this.asSelector())
findNavController().navigate(id, args)
}
dismiss()
}
return view
}

companion object {
fun newInstance(asset: Asset): LentClickActionBTFragment {
val bundle = Bundle()
val fragment = LentClickActionBTFragment()
bundle.putParcelable(PARAM_ASSET,asset)
fragment.arguments = bundle
return fragment
}

private const val PARAM_ASSET = "asset"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package de.tu_darmstadt.seemoo.LARS.ui.lent
import android.os.Bundle
import android.util.Log
import android.view.*
import android.widget.Button
import android.widget.ProgressBar
import android.widget.Toast
import androidx.lifecycle.Observer
Expand All @@ -12,21 +13,24 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.floatingactionbutton.FloatingActionButton
import de.tu_darmstadt.seemoo.LARS.R
import de.tu_darmstadt.seemoo.LARS.Utils
import de.tu_darmstadt.seemoo.LARS.data.model.Asset
import de.tu_darmstadt.seemoo.LARS.data.model.Selectable
import de.tu_darmstadt.seemoo.LARS.ui.APIFragment
import de.tu_darmstadt.seemoo.LARS.ui.info.AssetInfoBTFragment
import de.tu_darmstadt.seemoo.LARS.ui.editor.SelectorFragment
import de.tu_darmstadt.seemoo.LARS.ui.editor.SelectorViewModel

/**
* Fragment of currently lent assets through user
*/
class LentFragment : APIFragment(), LentRecyclerViewAdapter.OnListInteractionListener {
private lateinit var viewManager: RecyclerView.LayoutManager
private lateinit var progressBar: ProgressBar
private lateinit var selectorViewModel: SelectorViewModel
private lateinit var lentViewModel: LentViewModel
private lateinit var recyclerView: RecyclerView
private lateinit var viewAdapter: LentRecyclerViewAdapter
private lateinit var lentButton: FloatingActionButton
private lateinit var filterCancelButton: Button

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -44,6 +48,7 @@ class LentFragment : APIFragment(), LentRecyclerViewAdapter.OnListInteractionLis
progressBar = root.findViewById(R.id.progressLoading)
progressBar.isIndeterminate = true
lentButton = root.findViewById(R.id.frag_lent_lentButton)
filterCancelButton = root.findViewById(R.id.frag_lent_stop_filter_button)
return root
}

Expand All @@ -55,24 +60,58 @@ class LentFragment : APIFragment(), LentRecyclerViewAdapter.OnListInteractionLis
progressBar.visibility = if (it) View.VISIBLE else View.GONE
})

viewAdapter = LentRecyclerViewAdapter(this, lentViewModel.checkedOutAsset.value!!)
viewAdapter = LentRecyclerViewAdapter(this)
viewManager = LinearLayoutManager(context)
recyclerView = view.findViewById<RecyclerView>(R.id.lent_recycler).apply {
layoutManager = viewManager
adapter = viewAdapter
}

selectorViewModel = ViewModelProvider(requireActivity())[SelectorViewModel::class.java]
selectorViewModel.selected.observe(viewLifecycleOwner, Observer {
it?.run {
when (it.inputID) {
R.id.lent_filter -> lentViewModel.filteredUser.value = it.item as Selectable.User
else -> Log.w(
this@LentFragment::class.java.name,
"Unknown inputID for selector update"
)
}
selectorViewModel.resetSelected()
}
})

lentButton.setOnClickListener {
findNavController().navigate(LentingScanListFragment.instanceId())
}

lentViewModel.checkedOutAsset.observe(viewLifecycleOwner, Observer {
it?.run {
viewAdapter.notifyDataSetChanged()
recalcFilter(this)
Log.d(this::class.java.name, "List update ${it.size}");
}
})

lentViewModel.filteredUser.observe(viewLifecycleOwner, Observer {
lentViewModel.checkedOutAsset.value?.run {
recalcFilter(this)
}
filterCancelButton.visibility = if (it == null) View.GONE else View.VISIBLE
it?.run {
filterCancelButton.text = getString(R.string.filtering_by_x,it.name)
}
})

filterCancelButton.setOnClickListener {
lentViewModel.filteredUser.value = null
}

lentViewModel.filteredAssets.observe(viewLifecycleOwner, Observer {
it?.run {
viewAdapter.replaceElements(this)
}
})

lentViewModel.error.observe(viewLifecycleOwner, Observer {
it?.run {
Toast.makeText(
Expand All @@ -87,33 +126,45 @@ class LentFragment : APIFragment(), LentRecyclerViewAdapter.OnListInteractionLis
lentViewModel.loadData(getAPI(),getUserID())
}


fun recalcFilter(arrayList: ArrayList<Asset>) {
val filterUser = lentViewModel.filteredUser.value
if (filterUser == null) {
lentViewModel.filteredAssets.value = arrayList
} else {
lentViewModel.filteredAssets.value = arrayList.filter { asset ->
if (asset.assigned_to != null) {
asset.assigned_to.id == filterUser.id
} else {
Log.w(this::class.java.name, "Asset without assigned user! ${asset.asset_tag}")
true
}
}
}
}

override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.checkin_base, menu)
inflater.inflate(R.menu.lent, menu)
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.checkin_sort -> {
// TODO
Utils.displayTodo(requireContext())
true
}
R.id.checkin_filter -> {
// TODO
Utils.displayTodo(requireContext())
R.id.lent_filter -> {
val (id, args) = SelectorFragment.newInstancePair(
lentViewModel.filteredUser.value,
R.id.lent_filter,
Selectable.SelectableType.User
)
findNavController().navigate(id, args)
true
}
else -> false
}
}

override fun onListItemClicked(item: Asset) {
AssetInfoBTFragment.newInstance(item).show(
LentClickActionBTFragment.newInstance(item).show(
parentFragmentManager,
"CheckinAssetInfoBTFragment"
"LentAssetActionBTFragment"
)
// TODO: allow also filtering by
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import de.tu_darmstadt.seemoo.LARS.ui.lib.RecyclerItemTouchHelper

class LentRecyclerViewAdapter(
private val mListener: OnListInteractionListener?,
private val assetList: ArrayList<Asset>
private val assetList: ArrayList<Asset> = ArrayList()
) :
RecyclerView.Adapter<LentRecyclerViewAdapter.ViewHolder>() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModel
import de.tu_darmstadt.seemoo.LARS.Utils
import de.tu_darmstadt.seemoo.LARS.data.APIInterface
import de.tu_darmstadt.seemoo.LARS.data.model.Asset
import de.tu_darmstadt.seemoo.LARS.data.model.Selectable
import io.sentry.core.Sentry
import retrofit2.Call
import retrofit2.Callback
Expand All @@ -15,10 +16,16 @@ import retrofit2.Response
class LentViewModel : ViewModel() {
private val _checkedOutAsssets: MutableLiveData<ArrayList<Asset>> = MutableLiveData(ArrayList())
val checkedOutAsset: LiveData<ArrayList<Asset>> = _checkedOutAsssets
val filteredAssets: MutableLiveData<List<Asset>> = MutableLiveData(listOf())
private val _loading: MutableLiveData<Boolean> = MutableLiveData()
val loading: LiveData<Boolean> = _loading
private val _error: MutableLiveData<String> = MutableLiveData()
val error: LiveData<String> = _error
/**
* User to filter after if set
*/
internal val filteredUser: MutableLiveData<Selectable.User?> = MutableLiveData(null)


fun resetError() {
_error.value = null
Expand Down
63 changes: 63 additions & 0 deletions app/src/main/res/layout/fragment_lent_asset_action.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="@string/lent_asset_bt_action"
android:textAlignment="viewStart"
android:textAllCaps="true"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textSize="16sp" />

<Button
android:id="@+id/frag_lent_asset_action_info_button"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="8dp"
android:text="Show asset info"
android:textAlignment="textStart"
android:textAllCaps="false"
app:icon="@android:drawable/ic_menu_info_details"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/frag_lent_asset_action_filter_button"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:textAlignment="textStart"
android:textAllCaps="false"
app:icon="@drawable/ic_filter_list_white_24dp"
app:iconPadding="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/frag_lent_asset_action_userdetails_button"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:textAlignment="textStart"
android:textAllCaps="false"
app:icon="@drawable/ic_filter_list_white_24dp"
app:iconPadding="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</LinearLayout>
Loading

0 comments on commit 2fe49d5

Please sign in to comment.