diff options
21 files changed, 691 insertions, 132 deletions
diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 01508ac..5736c84 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -37,5 +37,6 @@ dependencies { implementation("androidx.fragment:fragment-ktx:1.4.0") implementation("io.ktor:ktor-client-serialization:1.6.6") implementation("com.github.zerobranch:SwipeLayout:1.3.1") + implementation("com.github.addisonElliott:SegmentedButton:3.1.9") implementation(group = "", name = "WhirlyGlobeMaply", ext = "aar") }
\ No newline at end of file diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt index 7929832..16cad74 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt @@ -1,11 +1,15 @@ package mx.trackermap.TrackerMap.android import android.app.Application +import mx.trackermap.TrackerMap.android.details.commands.UnitCommandsViewModel import mx.trackermap.TrackerMap.android.details.information.UnitInformationViewModel +import mx.trackermap.TrackerMap.android.details.reports.UnitReportsViewModel import mx.trackermap.TrackerMap.android.session.LoginViewModel import mx.trackermap.TrackerMap.android.units.UnitsViewModel +import mx.trackermap.TrackerMap.client.apis.CommandsApi import mx.trackermap.TrackerMap.client.apis.DevicesApi import mx.trackermap.TrackerMap.client.apis.PositionsApi +import mx.trackermap.TrackerMap.client.apis.ReportsApi import mx.trackermap.TrackerMap.client.apis.SessionApi import mx.trackermap.TrackerMap.controllers.UnitsController import org.koin.android.ext.koin.androidContext @@ -25,11 +29,16 @@ class TrackerApp : Application() { single { SessionApi(get()) } single { DevicesApi(get()) } single { PositionsApi(get()) } + single { CommandsApi(get()) } + single { ReportsApi(get()) } + single { UnitsController(get(), get()) } viewModel { LoginViewModel(get(), get()) } - viewModel { UnitInformationViewModel() } + viewModel { UnitInformationViewModel(get()) } + viewModel { UnitCommandsViewModel(get()) } single { UnitsViewModel(get()) } + viewModel { UnitReportsViewModel(get(), get()) } } startKoin { diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/DetailsActivity.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/DetailsActivity.kt index 12ab79e..07a7b05 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/DetailsActivity.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/DetailsActivity.kt @@ -7,13 +7,15 @@ import com.google.android.material.tabs.TabLayoutMediator import mx.trackermap.TrackerMap.android.databinding.DetailsActivityBinding import mx.trackermap.TrackerMap.android.devices.Action -class DetailsActivity: AppCompatActivity() { +class DetailsActivity : AppCompatActivity() { + private var _binding: DetailsActivityBinding? = null private val binding get() = _binding!! private lateinit var adapter: UnitDetailsAdapter private var deviceId: Int = 0 companion object { + val DEVICE_ID_EXTRA = "device_id" val ACTION_EXTRA = "action" } @@ -42,16 +44,19 @@ class DetailsActivity: AppCompatActivity() { adapter = UnitDetailsAdapter(this, deviceId) binding.detailsPager.adapter = adapter TabLayoutMediator(binding.detailsTabs, binding.detailsPager) { tab, position -> - tab.text = when(position) { + tab.text = when (position) { 0 -> "Details" 1 -> "Reports" else -> "Commands" } }.attach() - binding.detailsPager.setCurrentItem(when(initialSection) { - Action.DETAILS -> 0 - Action.REPORTS -> 1 - else -> 2 - }, false) + binding.detailsPager.setCurrentItem( + when (initialSection) { + Action.DETAILS -> 0 + Action.REPORTS -> 1 + else -> 2 + }, false + ) + binding.detailsPager.isUserInputEnabled = false } }
\ No newline at end of file diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsFragment.kt index 0391c16..bb0da4f 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsFragment.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsFragment.kt @@ -1,17 +1,23 @@ package mx.trackermap.TrackerMap.android.details.commands import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.AdapterView +import android.widget.ArrayAdapter import androidx.fragment.app.Fragment import mx.trackermap.TrackerMap.android.databinding.UnitDetailsCommandsBinding import mx.trackermap.TrackerMap.android.details.UnitDetailsAdapter +import org.koin.androidx.viewmodel.ext.android.viewModel class UnitCommandsFragment: Fragment() { private var _binding: UnitDetailsCommandsBinding? = null private val binding get() = _binding!! + private val unitCommandsViewModel: UnitCommandsViewModel by viewModel() + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -23,12 +29,36 @@ class UnitCommandsFragment: Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val id = arguments?.getInt(UnitDetailsAdapter.DEVICE_ID_ARG) - binding.unitCommandsText.text = "COMMANDS for ID - $id" + + setupObservers() + setupEvents() } override fun onDestroyView() { super.onDestroyView() _binding = null } + + private fun setupObservers() { + unitCommandsViewModel.commands.observe(this) { commands -> + Log.d("UnitCommandsFragment", "Device commands - $commands") + val context = activity!!.applicationContext + val adapter = ArrayAdapter<String>(context, android.R.layout.simple_list_item_1) + adapter.addAll(commands.map { it.description }) + binding.commandsList.adapter = adapter + } + + val id = arguments?.getInt(UnitDetailsAdapter.DEVICE_ID_ARG) + unitCommandsViewModel.fetchCommands(id) + } + + private fun setupEvents() { + binding.commandsList.setOnItemClickListener { _, _, index, _ -> + Log.d("UnitCommandsFragment", "Selected item at index - $index") + unitCommandsViewModel.selectCommand(index) + } + binding.sendCommandButton.setOnClickListener { + unitCommandsViewModel.sendCommand() + } + } }
\ No newline at end of file diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsViewModel.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsViewModel.kt new file mode 100644 index 0000000..06c0439 --- /dev/null +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsViewModel.kt @@ -0,0 +1,50 @@ +package mx.trackermap.TrackerMap.android.details.commands + +import android.util.Log +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.launch +import mx.trackermap.TrackerMap.client.apis.CommandsApi +import mx.trackermap.TrackerMap.client.models.Command +import org.koin.core.component.KoinComponent + +@DelicateCoroutinesApi +class UnitCommandsViewModel( + private val commandsApi: CommandsApi +) : ViewModel(), KoinComponent { + + var commands = MutableLiveData<List<Command>>() + private var selectedCommand: Command? = null + private var deviceId: Int? = null + + fun fetchCommands(deviceId: Int?) { + this.deviceId = deviceId + viewModelScope.launch { + val commands = commandsApi.commandsGet(deviceId = deviceId) + this@UnitCommandsViewModel.commands.value = commands.toList() + } + } + + fun selectCommand(index: Int) { + val command = commands.value?.get(index) + Log.d("UnitCommandsVM", "Selected Command - $command") + command?.deviceId = this.deviceId + + this.selectedCommand = command + } + + fun sendCommand() { + if (selectedCommand == null) { + Log.d("UnitCommandsVM", "No Command Selection") + return + } + + Log.d("UnitCommandsVM", "Sending command - $selectedCommand") + viewModelScope.launch { + val command = commandsApi.commandsSendPost(selectedCommand!!) + Log.d("UnitCommandsVM", "Command sent - $command") + } + } +}
\ No newline at end of file diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/information/UnitInformationViewModel.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/information/UnitInformationViewModel.kt index e7100e1..11daaaf 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/information/UnitInformationViewModel.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/information/UnitInformationViewModel.kt @@ -11,9 +11,11 @@ import mx.trackermap.TrackerMap.controllers.UnitsController import org.koin.core.component.KoinComponent import org.koin.core.component.inject -class UnitInformationViewModel: ViewModel(), KoinComponent { - @DelicateCoroutinesApi - private val unitsController: UnitsController by inject() +@DelicateCoroutinesApi +class UnitInformationViewModel constructor( + private val unitsController: UnitsController +) : ViewModel(), KoinComponent { + var unit = MutableLiveData<UnitInformation?>() init { diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt index a2faec8..9874a03 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt @@ -1,17 +1,29 @@ package mx.trackermap.TrackerMap.android.details.reports import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.PopupMenu +import android.widget.TableRow +import android.widget.TextView import androidx.fragment.app.Fragment +import mx.trackermap.TrackerMap.android.R import mx.trackermap.TrackerMap.android.databinding.UnitDetailsReportsBinding import mx.trackermap.TrackerMap.android.details.UnitDetailsAdapter +import mx.trackermap.TrackerMap.client.models.Event +import mx.trackermap.TrackerMap.client.models.Position +import mx.trackermap.TrackerMap.client.models.Stop +import org.koin.androidx.viewmodel.ext.android.viewModel + +class UnitReportsFragment : Fragment() { -class UnitReportsFragment: Fragment() { private var _binding: UnitDetailsReportsBinding? = null private val binding get() = _binding!! + private val unitReportsViewModel: UnitReportsViewModel by viewModel() + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -23,12 +35,107 @@ class UnitReportsFragment: Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val id = arguments?.getInt(UnitDetailsAdapter.DEVICE_ID_ARG) - binding.unitReportsText.text = "COMMANDS for ID - $id" + + unitReportsViewModel.deviceId.value = + arguments?.getInt(UnitDetailsAdapter.DEVICE_ID_ARG) ?: 0 + setupEvents() + setupObservers() } override fun onDestroyView() { super.onDestroyView() _binding = null } + + private fun setupEvents() { + binding.reportType.setOnPositionChangedListener { position -> + unitReportsViewModel.reportType.value = when (position) { + 0 -> UnitReportsViewModel.ReportType.POSITIONS + 1 -> UnitReportsViewModel.ReportType.EVENTS + else -> UnitReportsViewModel.ReportType.STOPS + } + } + binding.periodButton.setOnClickListener { + showPeriodPopUp(it) + } + unitReportsViewModel.reportPeriod.value = UnitReportsViewModel.ReportPeriod.DAY + unitReportsViewModel.reportType.value = UnitReportsViewModel.ReportType.POSITIONS + } + + private fun setupObservers() { + unitReportsViewModel.report.observe(this) { report -> + Log.d("UnitReportsFragment", "Report available: $report") + + when (report) { + is UnitReportsViewModel.Report.PositionsReport -> display(report.positions) + is UnitReportsViewModel.Report.EventsReport -> display(report.events) + is UnitReportsViewModel.Report.StopsReport -> display(report.stops) + } + } + + unitReportsViewModel.reportPeriod.observe(this) { period -> + Log.d("UnitReportsFragment", "Period changed: $period") + if (period == null) { + return@observe + } + + binding.periodButton.text = context?.getString( + when (period) { + UnitReportsViewModel.ReportPeriod.DAY -> R.string.day_period + UnitReportsViewModel.ReportPeriod.WEEK -> R.string.week_period + UnitReportsViewModel.ReportPeriod.MONTH -> R.string.month_period + } + ) + } + } + + private fun showPeriodPopUp(view: View) { + val popOver = PopupMenu(context, view) + popOver.menuInflater.inflate(R.menu.report_period_options, popOver.menu) + popOver.setOnMenuItemClickListener { item -> + unitReportsViewModel.reportPeriod.value = when (item.itemId) { + R.id.dayOption -> UnitReportsViewModel.ReportPeriod.DAY + R.id.weekOption -> UnitReportsViewModel.ReportPeriod.WEEK + else -> UnitReportsViewModel.ReportPeriod.MONTH + } + true + } + popOver.show() + } + + private fun display(positions: Array<Position>) { + Log.d("UnitReportsFragment", "Displaying positions: $positions") + + binding.eventsScroll.visibility = View.GONE + binding.reportMap.visibility = View.VISIBLE + } + + private fun display(events: Array<Event>) { + Log.d("UnitReportsFragment", "Displaying events: $events") + + binding.eventsScroll.visibility = View.VISIBLE + binding.reportMap.visibility = View.GONE + binding.eventsTable.removeViews(1, Math.max(0, binding.eventsTable.childCount - 1)) + + val context = context!! + events.forEach { event -> + val row = TableRow(context) + val eventText = TextView(context) + val datetimeText = TextView(context) + + row.addView(eventText) + row.addView(datetimeText) + binding.eventsTable.addView(row) + + eventText.text = event.type + datetimeText.text = event.eventTime + } + } + + private fun display(stops: Array<Stop>) { + Log.d("UnitReportsFragment", "Displaying stops: $stops") + + binding.eventsScroll.visibility = View.GONE + binding.reportMap.visibility = View.VISIBLE + } }
\ No newline at end of file diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsViewModel.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsViewModel.kt new file mode 100644 index 0000000..35ef343 --- /dev/null +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsViewModel.kt @@ -0,0 +1,142 @@ +package mx.trackermap.TrackerMap.android.details.reports + +import android.util.Log +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.asFlow +import androidx.lifecycle.viewModelScope +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Date +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch +import mx.trackermap.TrackerMap.client.apis.ReportsApi +import mx.trackermap.TrackerMap.client.models.Event +import mx.trackermap.TrackerMap.client.models.Position +import mx.trackermap.TrackerMap.client.models.Stop +import org.koin.core.component.KoinComponent + +class UnitReportsViewModel( + private val reportsApi: ReportsApi, + savedStateHandle: SavedStateHandle +) : ViewModel(), KoinComponent { + + sealed class Report { + class PositionsReport(val positions: Array<Position>) : Report() + class EventsReport(val events: Array<Event>) : Report() + class StopsReport(val stops: Array<Stop>) : Report() + } + + enum class ReportType { + POSITIONS, EVENTS, STOPS + } + + enum class ReportPeriod { + DAY, WEEK, MONTH + } + + var deviceId = savedStateHandle.getLiveData("deviceId", 0) + val reportType: MutableLiveData<ReportType> = savedStateHandle.getLiveData("reportType", null) + val reportPeriod: MutableLiveData<ReportPeriod> = + savedStateHandle.getLiveData("reportPeriod", null) + val report: MutableLiveData<Report> = MutableLiveData() + + val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") + + init { + viewModelScope.launch { + setupTypeObserver() + } + viewModelScope.launch { + setupPeriodObserver() + } + } + + private suspend fun setupTypeObserver() { + reportType.asFlow().collect { + fetchReport() + } + } + + private suspend fun setupPeriodObserver() { + reportPeriod.asFlow().collect { + fetchReport() + } + } + + private fun fetchReport() { + if (reportType.value == null || reportPeriod.value == null) { + return + } + + val (currentDate, previousDate) = getDates() + Log.d("UnitReportsVM", "Current report type: ${reportType.value.toString()}") + Log.d("UnitReportsVM", "Current report period: ${reportPeriod.value.toString()}") + Log.d("UnitReportsVM", "Current date:${dateFormat.format(currentDate)}") + Log.d("UnitReportsVM", "Previous date:${dateFormat.format(previousDate)}") + + viewModelScope.launch { + when (reportType.value!!) { + ReportType.POSITIONS -> fetchPositions(previousDate, currentDate) + ReportType.EVENTS -> fetchEvents(previousDate, currentDate) + ReportType.STOPS -> fetchStops(previousDate, currentDate) + } + } + } + + private fun getDates(): Pair<Date, Date> { + val calendar = Calendar.getInstance() + val currentDate = calendar.time + + calendar.add( + Calendar.DATE, when (reportPeriod.value!!) { + ReportPeriod.DAY -> -1 + ReportPeriod.WEEK -> -7 + ReportPeriod.MONTH -> -30 + } + ) + val previousDate = calendar.time + + return Pair(currentDate, previousDate) + } + + private suspend fun fetchPositions(from: Date, to: Date) { + Log.d("UnitReportsVM", "Fetching positions") + + val result = reportsApi.reportsRouteGet( + dateFormat.format(from), + dateFormat.format(to), + deviceId.value!! + ) + + Log.d("UnitReportsVM", "Positions report: $result") + report.postValue(Report.PositionsReport(result)) + } + + private suspend fun fetchEvents(from: Date, to: Date) { + Log.d("UnitReportsVM", "Fetching events") + + val result = reportsApi.reportsEventsGet( + dateFormat.format(from), + dateFormat.format(to), + deviceId.value!! + ) + + Log.d("UnitReportsVM", "Events report: $result") + report.postValue(Report.EventsReport(result)) + } + + private suspend fun fetchStops(from: Date, to: Date) { + Log.d("UnitReportsVM", "Fetching stops") + + val result = reportsApi.reportsStopsGet( + dateFormat.format(from), + dateFormat.format(to), + deviceId.value!! + ) + + Log.d("UnitReportsVM", "Stops report: $result") + report.postValue(Report.StopsReport(result)) + } +}
\ No newline at end of file diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesAdapter.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesAdapter.kt index 33dd5b9..b38b20b 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesAdapter.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesAdapter.kt @@ -84,4 +84,4 @@ class DevicesAdapter( override fun getItemCount(): Int = units.size inner class ViewHolder(val binding: UnitItemBinding) : RecyclerView.ViewHolder(binding.root) -}
\ No newline at end of file +} diff --git a/androidApp/src/main/res/layout/details_activity.xml b/androidApp/src/main/res/layout/details_activity.xml index 00ebdbf..f79ea69 100644 --- a/androidApp/src/main/res/layout/details_activity.xml +++ b/androidApp/src/main/res/layout/details_activity.xml @@ -1,25 +1,25 @@ <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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" - xmlns:app="http://schemas.android.com/apk/res-auto"> + android:layout_height="match_parent"> <com.google.android.material.tabs.TabLayout android:id="@+id/detailsTabs" android:layout_width="match_parent" android:layout_height="wrap_content" + app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintEnd_toEndOf="parent"/> + app:layout_constraintTop_toTopOf="parent" /> <androidx.viewpager2.widget.ViewPager2 android:id="@+id/detailsPager" android:layout_width="match_parent" android:layout_height="0dp" - app:layout_constraintTop_toBottomOf="@id/detailsTabs" - app:layout_constraintStart_toStartOf="parent" + app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintBottom_toBottomOf="parent"/> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/detailsTabs" /> </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file diff --git a/androidApp/src/main/res/layout/unit_details_commands.xml b/androidApp/src/main/res/layout/unit_details_commands.xml index dfd6516..e98b113 100644 --- a/androidApp/src/main/res/layout/unit_details_commands.xml +++ b/androidApp/src/main/res/layout/unit_details_commands.xml @@ -1,19 +1,30 @@ <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" - xmlns:tools="http://schemas.android.com/tools"> + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <ListView + android:id="@+id/commandsList" + android:layout_width="0dp" + android:layout_height="0dp" + android:choiceMode="singleChoice" + android:listSelector="@color/darkBackground" + app:layout_constraintBottom_toTopOf="@id/sendCommandButton" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> - <TextView - android:id="@+id/unitCommandsText" + <com.google.android.material.button.MaterialButton + android:id="@+id/sendCommandButton" android:layout_width="wrap_content" android:layout_height="wrap_content" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" + android:layout_marginBottom="@dimen/margin" + android:text="@string/send_command" app:layout_constraintBottom_toBottomOf="parent" - tools:text="COMMANDS"/> + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/commandsList" /> </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file diff --git a/androidApp/src/main/res/layout/unit_details_reports.xml b/androidApp/src/main/res/layout/unit_details_reports.xml index f1b52e3..cf3c7b2 100644 --- a/androidApp/src/main/res/layout/unit_details_reports.xml +++ b/androidApp/src/main/res/layout/unit_details_reports.xml @@ -1,19 +1,137 @@ <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" - xmlns:tools="http://schemas.android.com/tools"> + android:layout_width="match_parent" + android:layout_height="match_parent"> - <TextView - android:id="@+id/unitReportsText" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - app:layout_constraintTop_toTopOf="parent" + <View + android:id="@+id/reportMap" + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_margin="@dimen/margin" + android:background="@color/darkBackground" + android:visibility="gone" + app:layout_constraintBottom_toTopOf="@id/periodSection" + app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <ScrollView + android:id="@+id/eventsScroll" + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_margin="@dimen/margin" + android:visibility="gone" + app:layout_constraintBottom_toTopOf="@id/periodSection" app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent"> + + <TableLayout + android:id="@+id/eventsTable" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:isScrollContainer="true" + android:scrollbars="vertical" + android:stretchColumns="*"> + + <TableRow android:background="@color/colorPrimary"> + + <TextView + android:paddingHorizontal="@dimen/padding" + android:text="@string/table_event" + android:textColor="@color/background" /> + + <TextView + android:paddingHorizontal="@dimen/padding" + android:text="@string/table_datetime" + android:textColor="@color/background" /> + + </TableRow> + + </TableLayout> + </ScrollView> + + <LinearLayout + android:id="@+id/periodSection" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="@dimen/margin" + android:orientation="vertical" app:layout_constraintBottom_toBottomOf="parent" - tools:text="REPORTS"/> + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <TextView + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:gravity="center_vertical" + android:text="@string/period" + android:textColor="@color/colorPrimaryDark" + android:textSize="22sp" /> + + <com.google.android.material.button.MaterialButton + android:id="@+id/periodButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/select_period" + android:textColor="@color/colorPrimaryDark" + app:backgroundTint="@color/darkBackground" /> + + </LinearLayout> + + <com.addisonelliott.segmentedbutton.SegmentedButtonGroup + android:id="@+id/reportType" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/margin" + app:borderWidth="1dp" + app:dividerPadding="10dp" + app:dividerWidth="1dp" + app:position="0" + app:radius="30dp" + app:ripple="true" + app:selectedBackground="@color/colorPrimary"> + + <com.addisonelliott.segmentedbutton.SegmentedButton + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:padding="10dp" + app:drawableGravity="top" + app:selectedTextColor="@color/darkBackground" + app:text="@string/positions" + app:textColor="@color/colorPrimaryDark" /> + + <com.addisonelliott.segmentedbutton.SegmentedButton + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:padding="10dp" + app:drawableGravity="top" + app:selectedTextColor="@color/darkBackground" + app:text="@string/events" + app:textColor="@color/colorPrimaryDark" /> + + <com.addisonelliott.segmentedbutton.SegmentedButton + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:padding="10dp" + app:drawableGravity="top" + app:selectedTextColor="@color/darkBackground" + app:text="@string/stops" + app:textColor="@color/colorPrimaryDark" /> + + </com.addisonelliott.segmentedbutton.SegmentedButtonGroup> + + </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file diff --git a/androidApp/src/main/res/menu/report_period_options.xml b/androidApp/src/main/res/menu/report_period_options.xml new file mode 100644 index 0000000..cf54ec3 --- /dev/null +++ b/androidApp/src/main/res/menu/report_period_options.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu + xmlns:android="http://schemas.android.com/apk/res/android"> + + <item + android:id="@+id/dayOption" + android:title="@string/day_period" /> + + <item + android:id="@+id/weekOption" + android:title="@string/week_period" /> + + <item + android:id="@+id/monthOption" + android:title="@string/month_period" /> + +</menu>
\ No newline at end of file diff --git a/androidApp/src/main/res/values/dimen.xml b/androidApp/src/main/res/values/dimen.xml index 6ce7887..18fd0eb 100644 --- a/androidApp/src/main/res/values/dimen.xml +++ b/androidApp/src/main/res/values/dimen.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <resources> <dimen name="padding">8dp</dimen> + <dimen name="margin">16dp</dimen> <!-- CardView --> <dimen name="card_border_radius">20dp</dimen> diff --git a/androidApp/src/main/res/values/strings.xml b/androidApp/src/main/res/values/strings.xml index d68c68c..453bc16 100644 --- a/androidApp/src/main/res/values/strings.xml +++ b/androidApp/src/main/res/values/strings.xml @@ -24,11 +24,26 @@ <string name="unit_speed_format">%1$d km/h</string> + <!-- Details --> <string name="unit_details">Details</string> <string name="unit_reports">Reports</string> <string name="unit_commands">Commands</string> <string name="units_search">Type to search</string> + <!-- Commads --> <string name="key">Key</string> <string name="value">Value</string> -</resources>
\ No newline at end of file + <string name="send_command">Send Command</string> + + <!-- Reports --> + <string name="positions">Positions</string> + <string name="events">Events</string> + <string name="stops">Stops</string> + <string name="day_period">Day</string> + <string name="week_period">Week</string> + <string name="month_period">Month</string> + <string name="period">Period</string> + <string name="select_period">Select</string> + <string name="table_event">Event</string> + <string name="table_datetime">Datetime</string> +</resources> diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/CommandsApi.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/CommandsApi.kt index 8f60153..e840888 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/CommandsApi.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/CommandsApi.kt @@ -30,7 +30,14 @@ class CommandsApi(basePath: kotlin.String = "https://demo.traccar.org/api") : Ap */ @Suppress("UNCHECKED_CAST") suspend fun commandsGet(all: kotlin.Boolean? = null, userId: kotlin.Int? = null, deviceId: kotlin.Int? = null, groupId: kotlin.Int? = null, refresh: kotlin.Boolean? = null): kotlin.Array<Command> { - val localVariableQuery: MultiValueMap = mapOf("all" to listOf("$all"), "userId" to listOf("$userId"), "deviceId" to listOf("$deviceId"), "groupId" to listOf("$groupId"), "refresh" to listOf("$refresh")) + val query: MutableMap<String, List<String>> = mutableMapOf() + all?.let { query["all"] = listOf("$it") } + userId?.let { query["userId"] = listOf("$it") } + deviceId?.let { query["deviceId"] = listOf("$it") } + groupId?.let { query["groupId"] = listOf("$it") } + refresh?.let { query["refresh"] = listOf("$it") } + val localVariableQuery: MultiValueMap = query + val localVariableConfig = RequestConfig( RequestMethod.GET, "/commands", query = localVariableQuery diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/ReportsApi.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/ReportsApi.kt index 0caa945..43feaa6 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/ReportsApi.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/ReportsApi.kt @@ -13,7 +13,7 @@ package mx.trackermap.TrackerMap.client.apis import mx.trackermap.TrackerMap.client.models.Event import mx.trackermap.TrackerMap.client.models.Position -import mx.trackermap.TrackerMap.client.models.ReportStops +import mx.trackermap.TrackerMap.client.models.Stop import mx.trackermap.TrackerMap.client.models.ReportSummary import mx.trackermap.TrackerMap.client.models.ReportTrips @@ -24,142 +24,210 @@ class ReportsApi(basePath: kotlin.String = "https://demo.traccar.org/api") : Api /** * Fetch a list of Events within the time period for the Devices or Groups * At least one _deviceId_ or one _groupId_ must be passed - * @param from in IS0 8601 format. eg. `1963-11-22T18:30:00Z` - * @param to in IS0 8601 format. eg. `1963-11-22T18:30:00Z` + * @param from in IS0 8601 format. eg. `1963-11-22T18:30:00Z` + * @param to in IS0 8601 format. eg. `1963-11-22T18:30:00Z` * @param deviceId (optional) * @param groupId (optional) * @param type % can be used to return events of all types (optional) * @return kotlin.Array<Event> */ @Suppress("UNCHECKED_CAST") - suspend fun reportsEventsGet(from: java.time.LocalDateTime, to: java.time.LocalDateTime, deviceId: kotlin.Array<kotlin.Int>? = null, groupId: kotlin.Array<kotlin.Int>? = null, type: kotlin.Array<kotlin.String>? = null): kotlin.Array<Event> { - val localVariableQuery: MultiValueMap = mapOf("deviceId" to toMultiValue(deviceId!!.toList(), "multi"), "groupId" to toMultiValue(groupId!!.toList(), "multi"), "type" to toMultiValue(type!!.toList(), "csv"), "from" to listOf("$from"), "to" to listOf("$to")) + suspend fun reportsEventsGet( + from: String, + to: String, + deviceId: Int + ): kotlin.Array<Event> { + val localVariableQuery: MultiValueMap = mapOf( + "deviceId" to toMultiValue(listOf(deviceId), "multi"), + "from" to listOf(from), + "to" to listOf(to) + ) val localVariableConfig = RequestConfig( - RequestMethod.GET, - "/reports/events", query = localVariableQuery + RequestMethod.GET, + "/reports/events", query = localVariableQuery ) val response = request<kotlin.Array<Event>>( - localVariableConfig + localVariableConfig ) return when (response.responseType) { ResponseType.Success -> (response as Success<*>).data as kotlin.Array<Event> ResponseType.Informational -> TODO() ResponseType.Redirection -> TODO() - ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") - ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + ResponseType.ClientError -> throw ClientException( + (response as ClientError<*>).body as? String ?: "Client error" + ) + ResponseType.ServerError -> throw ServerException( + (response as ServerError<*>).message ?: "Server error" + ) } } + /** * Fetch a list of Positions within the time period for the Devices or Groups * At least one _deviceId_ or one _groupId_ must be passed - * @param from in IS0 8601 format. eg. `1963-11-22T18:30:00Z` - * @param to in IS0 8601 format. eg. `1963-11-22T18:30:00Z` + * @param from in IS0 8601 format. eg. `1963-11-22T18:30:00Z` + * @param to in IS0 8601 format. eg. `1963-11-22T18:30:00Z` * @param deviceId (optional) * @param groupId (optional) * @return kotlin.Array<Position> */ @Suppress("UNCHECKED_CAST") - suspend fun reportsRouteGet(from: java.time.LocalDateTime, to: java.time.LocalDateTime, deviceId: kotlin.Array<kotlin.Int>? = null, groupId: kotlin.Array<kotlin.Int>? = null): kotlin.Array<Position> { - val localVariableQuery: MultiValueMap = mapOf("deviceId" to toMultiValue(deviceId!!.toList(), "multi"), "groupId" to toMultiValue(groupId!!.toList(), "multi"), "from" to listOf("$from"), "to" to listOf("$to")) + suspend fun reportsRouteGet( + from: String, + to: String, + deviceId: Int + ): kotlin.Array<Position> { + val localVariableQuery: MultiValueMap = mapOf( + "deviceId" to toMultiValue(listOf(deviceId), "multi"), + "from" to listOf(from), + "to" to listOf(to) + ) val localVariableConfig = RequestConfig( - RequestMethod.GET, - "/reports/route", query = localVariableQuery + RequestMethod.GET, + "/reports/route", query = localVariableQuery ) val response = request<kotlin.Array<Position>>( - localVariableConfig + localVariableConfig ) return when (response.responseType) { ResponseType.Success -> (response as Success<*>).data as kotlin.Array<Position> ResponseType.Informational -> TODO() ResponseType.Redirection -> TODO() - ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") - ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + ResponseType.ClientError -> throw ClientException( + (response as ClientError<*>).body as? String ?: "Client error" + ) + ResponseType.ServerError -> throw ServerException( + (response as ServerError<*>).message ?: "Server error" + ) } } + /** * Fetch a list of ReportStops within the time period for the Devices or Groups * At least one _deviceId_ or one _groupId_ must be passed - * @param from in IS0 8601 format. eg. `1963-11-22T18:30:00Z` - * @param to in IS0 8601 format. eg. `1963-11-22T18:30:00Z` + * @param from in IS0 8601 format. eg. `1963-11-22T18:30:00Z` + * @param to in IS0 8601 format. eg. `1963-11-22T18:30:00Z` * @param deviceId (optional) * @param groupId (optional) * @return kotlin.Array<ReportStops> */ @Suppress("UNCHECKED_CAST") - suspend fun reportsStopsGet(from: java.time.LocalDateTime, to: java.time.LocalDateTime, deviceId: kotlin.Array<kotlin.Int>? = null, groupId: kotlin.Array<kotlin.Int>? = null): kotlin.Array<ReportStops> { - val localVariableQuery: MultiValueMap = mapOf("deviceId" to toMultiValue(deviceId!!.toList(), "multi"), "groupId" to toMultiValue(groupId!!.toList(), "multi"), "from" to listOf("$from"), "to" to listOf("$to")) + suspend fun reportsStopsGet( + from: String, + to: String, + deviceId: Int + ): kotlin.Array<Stop> { + val localVariableQuery: MultiValueMap = mapOf( + "deviceId" to toMultiValue(listOf(deviceId), "multi"), + "from" to listOf(from), + "to" to listOf(to) + ) val localVariableConfig = RequestConfig( - RequestMethod.GET, - "/reports/stops", query = localVariableQuery + RequestMethod.GET, + "/reports/stops", query = localVariableQuery ) - val response = request<kotlin.Array<ReportStops>>( - localVariableConfig + val response = request<kotlin.Array<Stop>>( + localVariableConfig ) return when (response.responseType) { - ResponseType.Success -> (response as Success<*>).data as kotlin.Array<ReportStops> + ResponseType.Success -> (response as Success<*>).data as kotlin.Array<Stop> ResponseType.Informational -> TODO() ResponseType.Redirection -> TODO() - ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") - ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + ResponseType.ClientError -> throw ClientException( + (response as ClientError<*>).body as? String ?: "Client error" + ) + ResponseType.ServerError -> throw ServerException( + (response as ServerError<*>).message ?: "Server error" + ) } } + /** * Fetch a list of ReportSummary within the time period for the Devices or Groups * At least one _deviceId_ or one _groupId_ must be passed - * @param from in IS0 8601 format. eg. `1963-11-22T18:30:00Z` - * @param to in IS0 8601 format. eg. `1963-11-22T18:30:00Z` + * @param from in IS0 8601 format. eg. `1963-11-22T18:30:00Z` + * @param to in IS0 8601 format. eg. `1963-11-22T18:30:00Z` * @param deviceId (optional) * @param groupId (optional) * @return kotlin.Array<ReportSummary> */ @Suppress("UNCHECKED_CAST") - suspend fun reportsSummaryGet(from: java.time.LocalDateTime, to: java.time.LocalDateTime, deviceId: kotlin.Array<kotlin.Int>? = null, groupId: kotlin.Array<kotlin.Int>? = null): kotlin.Array<ReportSummary> { - val localVariableQuery: MultiValueMap = mapOf("deviceId" to toMultiValue(deviceId!!.toList(), "multi"), "groupId" to toMultiValue(groupId!!.toList(), "multi"), "from" to listOf("$from"), "to" to listOf("$to")) + suspend fun reportsSummaryGet( + from: java.time.LocalDateTime, + to: java.time.LocalDateTime, + deviceId: kotlin.Array<kotlin.Int>? = null, + groupId: kotlin.Array<kotlin.Int>? = null + ): kotlin.Array<ReportSummary> { + val localVariableQuery: MultiValueMap = mapOf( + "deviceId" to toMultiValue(deviceId!!.toList(), "multi"), + "groupId" to toMultiValue(groupId!!.toList(), "multi"), + "from" to listOf("$from"), + "to" to listOf("$to") + ) val localVariableConfig = RequestConfig( - RequestMethod.GET, - "/reports/summary", query = localVariableQuery + RequestMethod.GET, + "/reports/summary", query = localVariableQuery ) val response = request<kotlin.Array<ReportSummary>>( - localVariableConfig + localVariableConfig ) return when (response.responseType) { ResponseType.Success -> (response as Success<*>).data as kotlin.Array<ReportSummary> ResponseType.Informational -> TODO() ResponseType.Redirection -> TODO() - ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") - ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + ResponseType.ClientError -> throw ClientException( + (response as ClientError<*>).body as? String ?: "Client error" + ) + ResponseType.ServerError -> throw ServerException( + (response as ServerError<*>).message ?: "Server error" + ) } } + /** * Fetch a list of ReportTrips within the time period for the Devices or Groups * At least one _deviceId_ or one _groupId_ must be passed - * @param from in IS0 8601 format. eg. `1963-11-22T18:30:00Z` - * @param to in IS0 8601 format. eg. `1963-11-22T18:30:00Z` + * @param from in IS0 8601 format. eg. `1963-11-22T18:30:00Z` + * @param to in IS0 8601 format. eg. `1963-11-22T18:30:00Z` * @param deviceId (optional) * @param groupId (optional) * @return kotlin.Array<ReportTrips> */ @Suppress("UNCHECKED_CAST") - suspend fun reportsTripsGet(from: java.time.LocalDateTime, to: java.time.LocalDateTime, deviceId: kotlin.Array<kotlin.Int>? = null, groupId: kotlin.Array<kotlin.Int>? = null): kotlin.Array<ReportTrips> { - val localVariableQuery: MultiValueMap = mapOf("deviceId" to toMultiValue(deviceId!!.toList(), "multi"), "groupId" to toMultiValue(groupId!!.toList(), "multi"), "from" to listOf("$from"), "to" to listOf("$to")) + suspend fun reportsTripsGet( + from: java.time.LocalDateTime, + to: java.time.LocalDateTime, + deviceId: kotlin.Array<kotlin.Int>? = null, + groupId: kotlin.Array<kotlin.Int>? = null + ): kotlin.Array<ReportTrips> { + val localVariableQuery: MultiValueMap = mapOf( + "deviceId" to toMultiValue(deviceId!!.toList(), "multi"), + "groupId" to toMultiValue(groupId!!.toList(), "multi"), + "from" to listOf("$from"), + "to" to listOf("$to") + ) val localVariableConfig = RequestConfig( - RequestMethod.GET, - "/reports/trips", query = localVariableQuery + RequestMethod.GET, + "/reports/trips", query = localVariableQuery ) val response = request<kotlin.Array<ReportTrips>>( - localVariableConfig + localVariableConfig ) return when (response.responseType) { ResponseType.Success -> (response as Success<*>).data as kotlin.Array<ReportTrips> ResponseType.Informational -> TODO() ResponseType.Redirection -> TODO() - ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") - ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + ResponseType.ClientError -> throw ClientException( + (response as ClientError<*>).body as? String ?: "Client error" + ) + ResponseType.ServerError -> throw ServerException( + (response as ServerError<*>).message ?: "Server error" + ) } } } diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Command.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Command.kt index c1c6a5d..37b22d4 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Command.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Command.kt @@ -11,6 +11,7 @@ */ package mx.trackermap.TrackerMap.client.models +import kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonPrimitive @@ -22,12 +23,11 @@ import kotlinx.serialization.json.JsonPrimitive * @param type * @param attributes */ +@Serializable data class Command ( - val id: Int? = null, - val deviceId: Int? = null, + var deviceId: Int? = null, val description: String? = null, val type: String? = null, val attributes: Map<String, JsonPrimitive> = mapOf() -) { -}
\ No newline at end of file +)
\ No newline at end of file diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Event.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Event.kt index e504600..741ae57 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Event.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Event.kt @@ -11,6 +11,7 @@ */ package mx.trackermap.TrackerMap.client.models +import kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonPrimitive @@ -25,12 +26,13 @@ import kotlinx.serialization.json.JsonPrimitive * @param maintenanceId * @param attributes */ +@Serializable data class Event ( val id: Int? = null, val type: String? = null, /* in IS0 8601 format. eg. `1963-11-22T18:30:00Z` */ - val eventTime: java.time.LocalDateTime? = null, + val eventTime: String? = null, val deviceId: Int? = null, val positionId: Int? = null, val geofenceId: Int? = null, diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/ReportStops.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Stop.kt index bdd4cbe..c06b864 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/ReportStops.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Stop.kt @@ -11,6 +11,8 @@ */ package mx.trackermap.TrackerMap.client.models +import kotlinx.serialization.Serializable + /** * @@ -25,20 +27,21 @@ package mx.trackermap.TrackerMap.client.models * @param spentFuel in liters * @param engineHours */ -data class ReportStops ( +@Serializable +data class Stop ( val deviceId: kotlin.Int? = null, val deviceName: kotlin.String? = null, val duration: kotlin.Int? = null, /* in IS0 8601 format. eg. `1963-11-22T18:30:00Z` */ - val startTime: java.time.LocalDateTime? = null, + val startTime: String? = null, val address: kotlin.String? = null, - val lat: java.math.BigDecimal? = null, - val lon: java.math.BigDecimal? = null, + val lat: Double? = null, + val lon: Double? = null, /* in IS0 8601 format. eg. `1963-11-22T18:30:00Z` */ - val endTime: java.time.LocalDateTime? = null, + val endTime: String? = null, /* in liters */ - val spentFuel: java.math.BigDecimal? = null, + val spentFuel: Double? = null, val engineHours: kotlin.Int? = null ) { }
\ No newline at end of file diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/CommandsController.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/CommandsController.kt deleted file mode 100644 index b710763..0000000 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/CommandsController.kt +++ /dev/null @@ -1,29 +0,0 @@ -package mx.trackermap.TrackerMap.controllers - -import mx.trackermap.TrackerMap.client.apis.CommandsApi -import mx.trackermap.TrackerMap.client.models.Command -import mx.trackermap.TrackerMap.client.models.Device - -class CommandsController( - val commandsApi: CommandsApi, - val sessionController: SessionController) -{ - var commands = emptyArray<Command>() - val deviceCommands = mutableMapOf<Int, Array<Command>>() - - suspend fun getAllCommands () { - sessionController.user?.id?.let { - commands = commandsApi.commandsGet(userId = it) - } - } - - suspend fun getDeviceCommands (device: Device) { - device.id?.let { - deviceCommands[it] = commandsApi.commandsSendGet (deviceId = device.id) - } - } - - suspend fun sendCommand (command: Command) { - commandsApi.commandsSendPost(command) - } -}
\ No newline at end of file |