From ef7a88961841752cb1a38a39f5e0cc298b463f56 Mon Sep 17 00:00:00 2001 From: Iván Ávalos Date: Tue, 15 Feb 2022 21:01:41 -0600 Subject: WIP: reports --- iosApp/iosApp.xcodeproj/project.pbxproj | 4 ++ .../iosApp/Details/Reports/UnitReportsView.swift | 22 ++++++- .../Details/Reports/UnitReportsViewModel.swift | 71 ++++++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 iosApp/iosApp/Details/Reports/UnitReportsViewModel.swift (limited to 'iosApp') diff --git a/iosApp/iosApp.xcodeproj/project.pbxproj b/iosApp/iosApp.xcodeproj/project.pbxproj index b3e7b29..aa509da 100644 --- a/iosApp/iosApp.xcodeproj/project.pbxproj +++ b/iosApp/iosApp.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2152FB032600AC8F00CF470E /* iOSApp.swift */; }; 7555FF83242A565900829871 /* RootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7555FF82242A565900829871 /* RootView.swift */; }; E312E74F27B366060018C5DE /* DevicesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E312E74E27B366060018C5DE /* DevicesViewModel.swift */; }; + E3141B8B27B9E91F00CE777C /* UnitReportsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3141B8A27B9E91F00CE777C /* UnitReportsViewModel.swift */; }; E3385A4F27B0D8A10025311C /* UnitCommandsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3385A4E27B0D8A10025311C /* UnitCommandsViewModel.swift */; }; E33A236027A4FD2C00DD647F /* UnitMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E33A235F27A4FD2C00DD647F /* UnitMapView.swift */; }; E33A236527A530F300DD647F /* SmallLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = E33A236427A530F300DD647F /* SmallLabelStyle.swift */; }; @@ -65,6 +66,7 @@ 7555FF82242A565900829871 /* RootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootView.swift; sourceTree = ""; }; 7555FF8C242A565B00829871 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E312E74E27B366060018C5DE /* DevicesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevicesViewModel.swift; sourceTree = ""; }; + E3141B8A27B9E91F00CE777C /* UnitReportsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitReportsViewModel.swift; sourceTree = ""; }; E3385A4E27B0D8A10025311C /* UnitCommandsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitCommandsViewModel.swift; sourceTree = ""; }; E33A235F27A4FD2C00DD647F /* UnitMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitMapView.swift; sourceTree = ""; }; E33A236427A530F300DD647F /* SmallLabelStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmallLabelStyle.swift; sourceTree = ""; }; @@ -205,6 +207,7 @@ isa = PBXGroup; children = ( E396282527AFBD4E005D070E /* UnitReportsView.swift */, + E3141B8A27B9E91F00CE777C /* UnitReportsViewModel.swift */, ); path = Reports; sourceTree = ""; @@ -379,6 +382,7 @@ E34A2F4827A7878200AD8AEB /* HyperlinkText.swift in Sources */, 2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */, E39ABC4627A4EBD500965D05 /* DevicesView.swift in Sources */, + E3141B8B27B9E91F00CE777C /* UnitReportsViewModel.swift in Sources */, E38F242027A27B550069FC45 /* LoadingView.swift in Sources */, E38F241E27A270D50069FC45 /* UnitsView.swift in Sources */, 7555FF83242A565900829871 /* RootView.swift in Sources */, diff --git a/iosApp/iosApp/Details/Reports/UnitReportsView.swift b/iosApp/iosApp/Details/Reports/UnitReportsView.swift index 3e01e00..322e853 100644 --- a/iosApp/iosApp/Details/Reports/UnitReportsView.swift +++ b/iosApp/iosApp/Details/Reports/UnitReportsView.swift @@ -17,11 +17,31 @@ */ import SwiftUI import shared +import SwiftUIX struct UnitReportsView: View { + @StateObject var unitReportsViewModel: UnitReportsViewModel + var unit: UnitInformation + init (unit: UnitInformation) { + self.unit = unit + self._unitReportsViewModel = StateObject( + wrappedValue: UnitReportsViewModel(deviceId: unit.device.id)) + } + var body: some View { - Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + VStack { + MapView(layer: $unitReportsViewModel.layer, + markers: $unitReportsViewModel.markers, + selected: $unitReportsViewModel.selectedMarker) + VStack { + HStack { + Text("period") + } + }.padding() + }.onAppear { + unitReportsViewModel.fetchReport() + } } } diff --git a/iosApp/iosApp/Details/Reports/UnitReportsViewModel.swift b/iosApp/iosApp/Details/Reports/UnitReportsViewModel.swift new file mode 100644 index 0000000..8f67d7a --- /dev/null +++ b/iosApp/iosApp/Details/Reports/UnitReportsViewModel.swift @@ -0,0 +1,71 @@ +// +// UnitReportsViewModel.swift +// iosApp +// +// Created by Iván on 13/02/22. +// Copyright © 2022 orgName. All rights reserved. +// + +import Foundation +import Combine +import shared + +class UnitReportsViewModel: ObservableObject { + @Inject var reportController: ReportController + + @Published var deviceId: Int32? = nil + @Published var reportType: ReportController.ReportType = .positions + @Published var reportPeriod: ReportDates.ReportPeriod = .today + @Published var report: ReportController.Report? = nil { + didSet { + switch report { + case let report as ReportController.ReportPositionsReport: + markers = report.positions.compactMap { p in Marker.companion.fromPosition(position: p)} + case is ReportController.ReportEventsReport: + markers = [] + case let report as ReportController.ReportStopsReport: + markers = report.stops.compactMap { s in Marker.companion.fromStop(stop: s) } + default: + break + } + } + } + @Published var layer = MapLayer.companion.defaultLayer + @Published var markers = [Marker]() + @Published var selectedMarker: Marker? = nil + + init(deviceId id: Int32?) { + deviceId = id + let collector = Collector(callback: setReport) + reportController.reportFlow.collect(collector: collector) { _, _ in } + } + + func setReport (report: ReportController.Report) { + self.report = report + } + + func fetchReport(xlsx: Bool = false) { + if let id = deviceId { + reportController.fetchReport(deviceId: id, + reportType: reportType, + reportPeriod: reportPeriod, + xlsx: xlsx, eventTypes: [ + .deviceInactive, + .deviceMoving, + .deviceStopped, + .deviceOverspeed, + .deviceFuelDrop, + .commandResult, + .geofenceEnter, + .geofenceExit, + .alarm, + .ignitionOn, + .ignitionOff, + .maintenance, + .textMessage, + .driverChanged, + .unknown + ]) + } + } +} -- cgit v1.2.3 From 438c0a9cbb1bcb594028cc4c7fcedfe4a802ef6f Mon Sep 17 00:00:00 2001 From: Iván Ávalos Date: Sun, 27 Feb 2022 00:05:29 -0600 Subject: Initial implementation of reports --- iosApp/iosApp/Details/DetailsView.swift | 2 +- .../iosApp/Details/Reports/UnitReportsView.swift | 55 ++++++++++++++++++++-- .../Details/Reports/UnitReportsViewModel.swift | 14 ++++-- iosApp/iosApp/Devices/DeviceRow.swift | 10 ++-- iosApp/iosApp/Map/MapView.swift | 5 +- iosApp/iosApp/Map/MapViewController.swift | 17 ++++--- iosApp/iosApp/Units/UnitsView.swift | 2 +- iosApp/iosApp/en.lproj/Localizable.strings | 15 ++++++ iosApp/iosApp/es-419.lproj/Localizable.strings | 15 ++++++ .../TrackerMap/controllers/ReportController.kt | 6 +-- 10 files changed, 117 insertions(+), 24 deletions(-) (limited to 'iosApp') diff --git a/iosApp/iosApp/Details/DetailsView.swift b/iosApp/iosApp/Details/DetailsView.swift index c869369..9b75aec 100644 --- a/iosApp/iosApp/Details/DetailsView.swift +++ b/iosApp/iosApp/Details/DetailsView.swift @@ -50,7 +50,7 @@ struct DetailsView: View { .navigationBarTitleView( Picker(selection: $action) { Text("details").tag(DeviceRow.Action.details) - //Text("reports").tag(DeviceRow.Action.reports) + Text("reports").tag(DeviceRow.Action.reports) Text("commands").tag(DeviceRow.Action.commands) } label: { EmptyView() diff --git a/iosApp/iosApp/Details/Reports/UnitReportsView.swift b/iosApp/iosApp/Details/Reports/UnitReportsView.swift index 322e853..b73c9e7 100644 --- a/iosApp/iosApp/Details/Reports/UnitReportsView.swift +++ b/iosApp/iosApp/Details/Reports/UnitReportsView.swift @@ -34,11 +34,60 @@ struct UnitReportsView: View { VStack { MapView(layer: $unitReportsViewModel.layer, markers: $unitReportsViewModel.markers, - selected: $unitReportsViewModel.selectedMarker) + selected: $unitReportsViewModel.selectedMarker, + isReport: true) VStack { HStack { - Text("period") - } + Text("report-period") + Spacer() + Picker(selection: $unitReportsViewModel.reportPeriod) { + Text("period-today").tag(ReportDates.ReportPeriod.today) + Text("period-last-24").tag(ReportDates.ReportPeriod.last24) + Text("period-yesterday").tag(ReportDates.ReportPeriod.yesterday) + Text("period-this-week").tag(ReportDates.ReportPeriod.thisWeek) + Text("period-last-7").tag(ReportDates.ReportPeriod.last7) + Text("period-this-month").tag(ReportDates.ReportPeriod.thisMonth) + Text("period-last-30").tag(ReportDates.ReportPeriod.last30) + } label: { + switch unitReportsViewModel.reportPeriod { + case .today: + Text("period-today") + case .last24: + Text("period-last-24") + case .yesterday: + Text("period-yesterday") + case .thisWeek: + Text("period-this-week") + case .last7: + Text("period-last-7") + case .thisMonth: + Text("period-this-month") + case .last30: + Text("period-last-30") + default: + Text("period-today") + } + } + }.padding() + Picker(selection: $unitReportsViewModel.reportType) { + Text("report-positions").tag(ReportController.ReportType.positions) + Text("report-events").tag(ReportController.ReportType.events) + Text("report-stops").tag(ReportController.ReportType.stops) + } label: { + EmptyView() + }.pickerStyle(SegmentedPickerStyle()) + + HStack { + Group { + Button {} label: { + Text("report-save") + } + + Button {} label: { + Text("report-share") + } + }.frame(maxWidth: .infinity) + }.padding() }.padding() }.onAppear { unitReportsViewModel.fetchReport() diff --git a/iosApp/iosApp/Details/Reports/UnitReportsViewModel.swift b/iosApp/iosApp/Details/Reports/UnitReportsViewModel.swift index 8f67d7a..5e85e89 100644 --- a/iosApp/iosApp/Details/Reports/UnitReportsViewModel.swift +++ b/iosApp/iosApp/Details/Reports/UnitReportsViewModel.swift @@ -14,8 +14,16 @@ class UnitReportsViewModel: ObservableObject { @Inject var reportController: ReportController @Published var deviceId: Int32? = nil - @Published var reportType: ReportController.ReportType = .positions - @Published var reportPeriod: ReportDates.ReportPeriod = .today + @Published var reportType: ReportController.ReportType = .positions { + didSet { + fetchReport() + } + } + @Published var reportPeriod: ReportDates.ReportPeriod = .today { + didSet { + fetchReport() + } + } @Published var report: ReportController.Report? = nil { didSet { switch report { @@ -65,7 +73,7 @@ class UnitReportsViewModel: ObservableObject { .textMessage, .driverChanged, .unknown - ]) + ]) { _, _ in } } } } diff --git a/iosApp/iosApp/Devices/DeviceRow.swift b/iosApp/iosApp/Devices/DeviceRow.swift index 0439fff..ee3298d 100644 --- a/iosApp/iosApp/Devices/DeviceRow.swift +++ b/iosApp/iosApp/Devices/DeviceRow.swift @@ -172,9 +172,9 @@ struct DeviceRow: View { Label("details", systemImage: "info.circle") } - //let reports = Button { callback(.reports) } label: { - // Label("reports", systemImage: "clock") - //} + let reports = Button { callback(.reports) } label: { + Label("reports", systemImage: "clock") + } let commands = Button { callback(.commands) } label: { Label("commands", systemImage: "paperplane") @@ -182,12 +182,12 @@ struct DeviceRow: View { if isCell { commands - // reports + reports details } else { Group { details - // reports + reports commands } .frame(maxWidth: .infinity) diff --git a/iosApp/iosApp/Map/MapView.swift b/iosApp/iosApp/Map/MapView.swift index e52c034..05bd9f9 100644 --- a/iosApp/iosApp/Map/MapView.swift +++ b/iosApp/iosApp/Map/MapView.swift @@ -26,6 +26,7 @@ struct MapView: UIViewControllerRepresentable { @Binding var layer: MapLayer @Binding var markers: [Marker] @Binding var selected: Marker? + var isReport: Bool = false var markerCallback: MarkerCallback? class Coordinator { @@ -52,9 +53,9 @@ struct MapView: UIViewControllerRepresentable { if context.coordinator.oldMarkers != markers { print("center = \(context.coordinator.shouldCenter)") uiViewController.display(markers: markers, - isReport: false, + isReport: isReport, center: context.coordinator.shouldCenter) - context.coordinator.shouldCenter = false + context.coordinator.shouldCenter = false || isReport } context.coordinator.oldMarkers = markers diff --git a/iosApp/iosApp/Map/MapViewController.swift b/iosApp/iosApp/Map/MapViewController.swift index 131a511..2b4c7d4 100644 --- a/iosApp/iosApp/Map/MapViewController.swift +++ b/iosApp/iosApp/Map/MapViewController.swift @@ -211,7 +211,8 @@ class OurMaplyViewController: MaplyViewController { let vectorDesc: [AnyHashable : Any] = [ kMaplyColor: colorReport, - kMaplyVecWidth: 20.0 + kMaplyVecWidth: 10.0, + kMaplyWideVecImpl: kMaplyWideVecImplPerf ] let labelDesc: [AnyHashable : Any] = [ @@ -289,15 +290,19 @@ class OurMaplyViewController: MaplyViewController { "type": "FeatureCollection", "features": [ [ - "type": "LineString", - "coordinates": points.map({ point in - [point.x, point.y] - }) + "type": "Feature", + "properties": [], + "geometry": [ + "type": "LineString", + "coordinates": markers.map({ marker in + [marker.longitude, marker.latitude] + }) + ] ] ] ] if let vector = MaplyVectorObject(fromGeoJSONDictionary: geoJSON) { - if let objs = addVectors([vector], desc: vectorDesc, mode: .any) { + if let objs = addWideVectors([vector], desc: vectorDesc, mode: .any) { objects.append(objs) } } diff --git a/iosApp/iosApp/Units/UnitsView.swift b/iosApp/iosApp/Units/UnitsView.swift index a91511e..c14ae43 100644 --- a/iosApp/iosApp/Units/UnitsView.swift +++ b/iosApp/iosApp/Units/UnitsView.swift @@ -76,7 +76,7 @@ struct UnitsView: View { } } .navigationViewStyle(StackNavigationViewStyle()) - .sheet(isPresented: $unitsViewModel.showDetails) { + .fullScreenCover(isPresented: $unitsViewModel.showDetails) { print("Dismissed") } content: { DetailsView(isPresented: $unitsViewModel.showDetails, diff --git a/iosApp/iosApp/en.lproj/Localizable.strings b/iosApp/iosApp/en.lproj/Localizable.strings index 392bc1c..56a934b 100644 --- a/iosApp/iosApp/en.lproj/Localizable.strings +++ b/iosApp/iosApp/en.lproj/Localizable.strings @@ -53,6 +53,21 @@ "open-location-browser" = "Open location in browser"; "maps-url-template" = "https://www.google.com/maps/place/{y},{x}?z=19"; +"report-period" = "Period"; +"report-positions" = "Positions"; +"report-events" = "Events"; +"report-stops" = "Stops"; +"report-save" = "Save"; +"report-share" = "Share"; + +"period-today" = "Today"; +"period-last-24" = "Last 24H"; +"period-yesterday" = "Yesterday"; +"period-this-week" = "Week"; +"period-last-7" = "Last 7d"; +"period-this-month" = "Month"; +"period-last-30" = "Last 30d"; + "send-command" = "Send command"; "send-command-confirm" = "Are you sure you want to send the command?"; diff --git a/iosApp/iosApp/es-419.lproj/Localizable.strings b/iosApp/iosApp/es-419.lproj/Localizable.strings index 401582e..eae03df 100644 --- a/iosApp/iosApp/es-419.lproj/Localizable.strings +++ b/iosApp/iosApp/es-419.lproj/Localizable.strings @@ -53,6 +53,21 @@ "open-location-browser" = "Abrir ubicación en navegador"; "maps-url-template" = "https://www.google.com/maps/place/{y},{x}?z=19"; +"report-period" = "Periodo"; +"report-positions" = "Posiciones"; +"report-events" = "Eventos"; +"report-stops" = "Paradas"; +"report-save" = "Guardar"; +"report-share" = "Compartir"; + +"period-today" = "Hoy"; +"period-last-24" = "Últimas 24H"; +"period-yesterday" = "Ayer"; +"period-this-week" = "Semana"; +"period-last-7" = "Últimos 7d"; +"period-this-month" = "Mes"; +"period-last-30" = "Últimos 30d"; + "send-command" = "Enviar comando"; "send-command-confirm" = "¿Está seguro que desea enviar el comando?"; diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/ReportController.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/ReportController.kt index b2e97e6..29c4229 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/ReportController.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/ReportController.kt @@ -49,7 +49,7 @@ class ReportController( val reportFlow: MutableStateFlow = MutableStateFlow(Report.LoadingReport) - fun fetchReport( + suspend fun fetchReport( deviceId: Int, reportType: ReportType?, reportPeriod: ReportDates.ReportPeriod?, @@ -65,13 +65,13 @@ class ReportController( if (!xlsx) { reportFlow.value = Report.LoadingReport } - GlobalScope.launch { + // GlobalScope.launch { when (reportType) { ReportType.POSITIONS -> fetchPositions(deviceId, previousDate, currentDate, xlsx) ReportType.EVENTS -> fetchEvents(deviceId, previousDate, currentDate, eventTypes, xlsx) ReportType.STOPS -> fetchStops(deviceId, previousDate, currentDate, xlsx) } - } + // } } private suspend fun fetchPositions( -- cgit v1.2.3 From 596efb5f3b9d9e13407222f4672853363e81a0fc Mon Sep 17 00:00:00 2001 From: Iván Ávalos Date: Sun, 27 Feb 2022 01:29:49 -0600 Subject: Added report map icons and initial impl. of events table --- iosApp/iosApp.xcodeproj/project.pbxproj | 17 +++++ .../xcshareddata/swiftpm/Package.resolved | 9 +++ .../MapReportEnd.imageset/Contents.json | 21 ++++++ .../MapReportEnd.imageset/map_report_end.svg | 11 ++++ .../MapReportPosition.imageset/Contents.json | 21 ++++++ .../map_report_position.svg | 11 ++++ .../MapReportStart.imageset/Contents.json | 21 ++++++ .../MapReportStart.imageset/map_report_start.svg | 11 ++++ .../iosApp/Details/Reports/UnitReportsView.swift | 76 ++++++++++++++++++++-- iosApp/iosApp/Map/MapViewController.swift | 10 +-- iosApp/iosApp/Shared/MarkerTransformations.swift | 4 ++ iosApp/iosApp/en.lproj/Localizable.strings | 24 +++++++ iosApp/iosApp/es-419.lproj/Localizable.strings | 24 +++++++ 13 files changed, 251 insertions(+), 9 deletions(-) create mode 100644 iosApp/iosApp/Assets.xcassets/MapReportEnd.imageset/Contents.json create mode 100644 iosApp/iosApp/Assets.xcassets/MapReportEnd.imageset/map_report_end.svg create mode 100644 iosApp/iosApp/Assets.xcassets/MapReportPosition.imageset/Contents.json create mode 100644 iosApp/iosApp/Assets.xcassets/MapReportPosition.imageset/map_report_position.svg create mode 100644 iosApp/iosApp/Assets.xcassets/MapReportStart.imageset/Contents.json create mode 100644 iosApp/iosApp/Assets.xcassets/MapReportStart.imageset/map_report_start.svg (limited to 'iosApp') diff --git a/iosApp/iosApp.xcodeproj/project.pbxproj b/iosApp/iosApp.xcodeproj/project.pbxproj index abdf916..196675f 100644 --- a/iosApp/iosApp.xcodeproj/project.pbxproj +++ b/iosApp/iosApp.xcodeproj/project.pbxproj @@ -45,6 +45,7 @@ E39ABC4327A4E88C00965D05 /* UnitsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39ABC4227A4E88C00965D05 /* UnitsViewModel.swift */; }; E39ABC4627A4EBD500965D05 /* DevicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39ABC4527A4EBD500965D05 /* DevicesView.swift */; }; E39ABC4827A4EDEC00965D05 /* DeviceRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39ABC4727A4EDEC00965D05 /* DeviceRow.swift */; }; + E3C651E727CB5426002F6F4C /* Tabler in Frameworks */ = {isa = PBXBuildFile; productRef = E3C651E627CB5426002F6F4C /* Tabler */; }; E3E77EE6279E6CE400150070 /* FlowCollector.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3E77EE5279E6CE400150070 /* FlowCollector.swift */; }; /* End PBXBuildFile section */ @@ -110,6 +111,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + E3C651E727CB5426002F6F4C /* Tabler in Frameworks */, E36A5A8627B4BFC40070DED5 /* FirebaseMessaging in Frameworks */, E33A236A27A6898700DD647F /* SwiftUIX in Frameworks */, E396281D27AF5723005D070E /* WhirlyGlobe.xcframework in Frameworks */, @@ -289,6 +291,7 @@ packageProductDependencies = ( E33A236927A6898700DD647F /* SwiftUIX */, E36A5A8527B4BFC40070DED5 /* FirebaseMessaging */, + E3C651E627CB5426002F6F4C /* Tabler */, ); productName = iosApp; productReference = 7555FF7B242A565900829871 /* iosApp.app */; @@ -323,6 +326,7 @@ packageReferences = ( E33A236827A6898700DD647F /* XCRemoteSwiftPackageReference "SwiftUIX" */, E36A5A8427B4BFC40070DED5 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, + E3C651E527CB5425002F6F4C /* XCRemoteSwiftPackageReference "SwiftTabler" */, ); productRefGroup = 7555FF7C242A565900829871 /* Products */; projectDirPath = ""; @@ -648,6 +652,14 @@ minimumVersion = 8.0.0; }; }; + E3C651E527CB5425002F6F4C /* XCRemoteSwiftPackageReference "SwiftTabler" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/openalloc/SwiftTabler"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.6.0; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ @@ -661,6 +673,11 @@ package = E36A5A8427B4BFC40070DED5 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; productName = FirebaseMessaging; }; + E3C651E627CB5426002F6F4C /* Tabler */ = { + isa = XCSwiftPackageProductDependency; + package = E3C651E527CB5425002F6F4C /* XCRemoteSwiftPackageReference "SwiftTabler" */; + productName = Tabler; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 7555FF73242A565900829871 /* Project object */; diff --git a/iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 7032494..3c172cd 100644 --- a/iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -109,6 +109,15 @@ "version": "1.18.0" } }, + { + "package": "SwiftTabler", + "repositoryURL": "https://github.com/openalloc/SwiftTabler", + "state": { + "branch": null, + "revision": "3a6c0ba6c1e1e9bcd29c2fb628dc7f1037307ec5", + "version": "0.6.0" + } + }, { "package": "SwiftUIX", "repositoryURL": "https://github.com/ivan-avalos/SwiftUIX", diff --git a/iosApp/iosApp/Assets.xcassets/MapReportEnd.imageset/Contents.json b/iosApp/iosApp/Assets.xcassets/MapReportEnd.imageset/Contents.json new file mode 100644 index 0000000..40c489c --- /dev/null +++ b/iosApp/iosApp/Assets.xcassets/MapReportEnd.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "map_report_end.svg", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iosApp/iosApp/Assets.xcassets/MapReportEnd.imageset/map_report_end.svg b/iosApp/iosApp/Assets.xcassets/MapReportEnd.imageset/map_report_end.svg new file mode 100644 index 0000000..ec134ba --- /dev/null +++ b/iosApp/iosApp/Assets.xcassets/MapReportEnd.imageset/map_report_end.svg @@ -0,0 +1,11 @@ + + + + diff --git a/iosApp/iosApp/Assets.xcassets/MapReportPosition.imageset/Contents.json b/iosApp/iosApp/Assets.xcassets/MapReportPosition.imageset/Contents.json new file mode 100644 index 0000000..3a7979a --- /dev/null +++ b/iosApp/iosApp/Assets.xcassets/MapReportPosition.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "map_report_position.svg", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iosApp/iosApp/Assets.xcassets/MapReportPosition.imageset/map_report_position.svg b/iosApp/iosApp/Assets.xcassets/MapReportPosition.imageset/map_report_position.svg new file mode 100644 index 0000000..c6d39ac --- /dev/null +++ b/iosApp/iosApp/Assets.xcassets/MapReportPosition.imageset/map_report_position.svg @@ -0,0 +1,11 @@ + + + + diff --git a/iosApp/iosApp/Assets.xcassets/MapReportStart.imageset/Contents.json b/iosApp/iosApp/Assets.xcassets/MapReportStart.imageset/Contents.json new file mode 100644 index 0000000..3a1438a --- /dev/null +++ b/iosApp/iosApp/Assets.xcassets/MapReportStart.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "map_report_start.svg", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iosApp/iosApp/Assets.xcassets/MapReportStart.imageset/map_report_start.svg b/iosApp/iosApp/Assets.xcassets/MapReportStart.imageset/map_report_start.svg new file mode 100644 index 0000000..59a6142 --- /dev/null +++ b/iosApp/iosApp/Assets.xcassets/MapReportStart.imageset/map_report_start.svg @@ -0,0 +1,11 @@ + + + + diff --git a/iosApp/iosApp/Details/Reports/UnitReportsView.swift b/iosApp/iosApp/Details/Reports/UnitReportsView.swift index b73c9e7..1ca1a87 100644 --- a/iosApp/iosApp/Details/Reports/UnitReportsView.swift +++ b/iosApp/iosApp/Details/Reports/UnitReportsView.swift @@ -18,6 +18,9 @@ import SwiftUI import shared import SwiftUIX +import Tabler + +extension EventInformation: Identifiable {} struct UnitReportsView: View { @StateObject var unitReportsViewModel: UnitReportsViewModel @@ -30,12 +33,77 @@ struct UnitReportsView: View { wrappedValue: UnitReportsViewModel(deviceId: unit.device.id)) } + private var eventsGridItems: [GridItem] = [ + GridItem(.flexible(), alignment: .leading), + GridItem(.flexible(), alignment: .leading), + GridItem(.flexible(), alignment: .leading), + GridItem(.flexible(), alignment: .leading), + ] + + @ViewBuilder + private func eventsHeader(_ ctx: TablerSortContext) -> some View { + Text("events-table-datetime") + Text("events-table-event") + Text("events-table-geofence") + Text("events-table-address") + } + + @ViewBuilder + private func eventsRow(_ element: EventInformation) -> some View { + if let eventTime = element.event.eventTime { + Text(Formatter.companion.formatDate(str: eventTime)) + } else { Text("") } + + if let eventType = element.event.type { + switch EventInformation.companion.stringToReportType(s: eventType) { + case .deviceOnline: Text("event-device-online") + case .deviceUnknown: Text("event-device-unknown") + case .deviceOffline: Text("event-device-offline") + case .deviceInactive: Text("event-device-inactive") + case .deviceMoving: Text("event-device-moving") + case .deviceStopped: Text("event-device-stopped") + case .deviceOverspeed: Text("event-device-overspeed") + case .deviceFuelDrop: Text("event-device-fuel-drop") + case .commandResult: Text("event-command-result") + case .geofenceEnter: Text("event-geofence-enter") + case .geofenceExit: Text("event-geofence-exit") + case .alarm: Text("event-alarm") + case .ignitionOn: Text("event-ignition-on") + case .ignitionOff: Text("event-ignition-off") + case .maintenance: Text("event-maintenance") + case .textMessage: Text("event-text-message") + case .driverChanged: Text("event-driver-changed") + default: Text("event-unknown") + } + } else { Text("") } + + if let geofenceName = element.geofence?.name { + Text(geofenceName) + } else { Text("") } + + if let positionAddress = element.position?.address { + Text(positionAddress) + } else { Text("") } + } + var body: some View { VStack { - MapView(layer: $unitReportsViewModel.layer, - markers: $unitReportsViewModel.markers, - selected: $unitReportsViewModel.selectedMarker, - isReport: true) + if unitReportsViewModel.reportType == .events { + if let report = unitReportsViewModel.report as? ReportController.ReportEventsReport { + TablerList(TablerListConfig(gridItems: eventsGridItems), + headerContent: eventsHeader, + rowContent: eventsRow, + results: report.events) + } else { + Spacer() + } + } else { + MapView(layer: $unitReportsViewModel.layer, + markers: $unitReportsViewModel.markers, + selected: $unitReportsViewModel.selectedMarker, + isReport: true) + } + VStack { HStack { Text("report-period") diff --git a/iosApp/iosApp/Map/MapViewController.swift b/iosApp/iosApp/Map/MapViewController.swift index 2b4c7d4..f068bf4 100644 --- a/iosApp/iosApp/Map/MapViewController.swift +++ b/iosApp/iosApp/Map/MapViewController.swift @@ -205,13 +205,13 @@ class OurMaplyViewController: MaplyViewController { } let fontSize = 11.0 - let colorReport = UIColor.green + let colorReport = UIColor(red: 0.0, green: 0.5, blue: 0.0, alpha: 1.0) let colorLabel = UIColor.secondaryLabel let colorLabelOutline = UIColor.systemBackground let vectorDesc: [AnyHashable : Any] = [ kMaplyColor: colorReport, - kMaplyVecWidth: 10.0, + kMaplyVecWidth: 15.0, kMaplyWideVecImpl: kMaplyWideVecImplPerf ] @@ -233,7 +233,7 @@ class OurMaplyViewController: MaplyViewController { // For reports, position, start and end icons must be different switch i { case markers.startIndex: type = .reportStart - case markers.endIndex: type = .reportEnd + case markers.endIndex - 1: type = .reportEnd default: type = .reportPosition } } else { @@ -246,8 +246,8 @@ class OurMaplyViewController: MaplyViewController { // For reports, position, start and end sizes must be different switch i { case markers.startIndex: size = 50.0 - case markers.endIndex: size = 50.0 - default: size = 25.0 + case markers.endIndex - 1: size = 50.0 + default: size = 26.0 } } screenMarker.size = CGSize(width: size, height: size) diff --git a/iosApp/iosApp/Shared/MarkerTransformations.swift b/iosApp/iosApp/Shared/MarkerTransformations.swift index 2e71980..1e51907 100644 --- a/iosApp/iosApp/Shared/MarkerTransformations.swift +++ b/iosApp/iosApp/Shared/MarkerTransformations.swift @@ -42,6 +42,10 @@ class MarkerTransformations { case .trolleybus: imageName = "MapTrolleybus" case .truck: imageName = "MapTruck" case .van: imageName = "MapVan" + + case .reportStart: imageName = "MapReportStart" + case .reportPosition: imageName = "MapReportPosition" + case .reportEnd: imageName = "MapReportEnd" default: break } return imageName diff --git a/iosApp/iosApp/en.lproj/Localizable.strings b/iosApp/iosApp/en.lproj/Localizable.strings index 56a934b..fee132b 100644 --- a/iosApp/iosApp/en.lproj/Localizable.strings +++ b/iosApp/iosApp/en.lproj/Localizable.strings @@ -68,6 +68,30 @@ "period-this-month" = "Month"; "period-last-30" = "Last 30d"; +"events-table-event" = "Event"; +"events-table-datetime" = "Datetime"; +"events-table-geofence" = "Geofence"; +"events-table-address" = "Address"; + +"event-device-online" = "Status online"; +"event-device-unknown" = "Status unknown"; +"event-device-offline" = "Status offline"; +"event-device-inactive" = "Device inactive"; +"event-device-moving" = "Device moving"; +"event-device-stopped" = "Device stopped"; +"event-device-overspeed" = "Speed limit exceeded"; +"event-device-fuel-drop" = "Fuel drop"; +"event-command-result" = "Command result"; +"event-geofence-enter" = "Geofence entered"; +"event-geofence-exit" = "Geofence exited"; +"event-alarm" = "Alarm"; +"event-ignition-on" = "Ignition on"; +"event-ignition-off" = "Ignition off"; +"event-maintenance" = "Maintenance required"; +"event-text-message" = "Text message received"; +"event-driver-changed" = "Driver changed"; +"event-unknown" = "Unknown event"; + "send-command" = "Send command"; "send-command-confirm" = "Are you sure you want to send the command?"; diff --git a/iosApp/iosApp/es-419.lproj/Localizable.strings b/iosApp/iosApp/es-419.lproj/Localizable.strings index eae03df..0105e5d 100644 --- a/iosApp/iosApp/es-419.lproj/Localizable.strings +++ b/iosApp/iosApp/es-419.lproj/Localizable.strings @@ -68,6 +68,30 @@ "period-this-month" = "Mes"; "period-last-30" = "Últimos 30d"; +"events-table-event" = "Evento"; +"events-table-datetime" = "Fecha y hora"; +"events-table-geofence" = "Geocerca"; +"events-table-address" = "Dirección"; + +"event-device-online" = "Unidad en línea"; +"event-device-unknown" = "Unidad en estado desconocido"; +"event-device-offline" = "Unidad fuera de línea"; +"event-device-inactive" = "Unidad inactiva"; +"event-device-moving" = "Unidad en movimiento"; +"event-device-stopped" = "Unidad detenida"; +"event-device-overspeed" = "Excedido el límite de velocidad"; +"event-device-fuel-drop" = "Pérdida de combustible"; +"event-command-result" = "Resultado del comando"; +"event-geofence-enter" = "Entrada en la geocerca"; +"event-geofence-exit" = "Salida de la geocerca"; +"event-alarm" = "Alarma"; +"event-ignition-on" = "Ignición encendida"; +"event-ignition-off" = "Ignición apagada"; +"event-maintenance" = "Se requiere mantenimiento"; +"event-text-message" = "Mensaje de texto recibido"; +"event-driver-changed" = "El conductor ha cambiado"; +"event-unknown" = "Evento desconocido"; + "send-command" = "Enviar comando"; "send-command-confirm" = "¿Está seguro que desea enviar el comando?"; -- cgit v1.2.3 From eafb9788615fb733419f64f1b6501b5880922058 Mon Sep 17 00:00:00 2001 From: Iván Ávalos Date: Sun, 27 Feb 2022 01:36:33 -0600 Subject: Temporarily removed non-functional save and share buttons --- .../iosApp/Details/Reports/UnitReportsView.swift | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'iosApp') diff --git a/iosApp/iosApp/Details/Reports/UnitReportsView.swift b/iosApp/iosApp/Details/Reports/UnitReportsView.swift index 1ca1a87..910cea4 100644 --- a/iosApp/iosApp/Details/Reports/UnitReportsView.swift +++ b/iosApp/iosApp/Details/Reports/UnitReportsView.swift @@ -145,17 +145,17 @@ struct UnitReportsView: View { EmptyView() }.pickerStyle(SegmentedPickerStyle()) - HStack { - Group { - Button {} label: { - Text("report-save") - } - - Button {} label: { - Text("report-share") - } - }.frame(maxWidth: .infinity) - }.padding() + //HStack { + // Group { + // Button {} label: { + // Text("report-save") + // } + // + // Button {} label: { + // Text("report-share") + // } + // }.frame(maxWidth: .infinity) + //}.padding() }.padding() }.onAppear { unitReportsViewModel.fetchReport() -- cgit v1.2.3 From 117778e29941e3623a2d8c6f9f099ce9b5d2df4b Mon Sep 17 00:00:00 2001 From: Iván Ávalos Date: Sun, 27 Feb 2022 03:20:22 -0600 Subject: Polygon geofences implemented successfuly --- iosApp/iosApp.xcodeproj/project.pbxproj | 17 ++++ .../xcshareddata/swiftpm/Package.resolved | 18 ++++ .../iosApp/Details/Reports/UnitReportsView.swift | 1 + .../Details/Reports/UnitReportsViewModel.swift | 15 +++ iosApp/iosApp/Map/MapView.swift | 9 +- iosApp/iosApp/Map/MapViewController.swift | 103 ++++++++++++++++++++- iosApp/iosApp/Map/UnitMapView.swift | 1 + iosApp/iosApp/Units/UnitsViewModel.swift | 7 +- 8 files changed, 167 insertions(+), 4 deletions(-) (limited to 'iosApp') diff --git a/iosApp/iosApp.xcodeproj/project.pbxproj b/iosApp/iosApp.xcodeproj/project.pbxproj index 196675f..8aefd98 100644 --- a/iosApp/iosApp.xcodeproj/project.pbxproj +++ b/iosApp/iosApp.xcodeproj/project.pbxproj @@ -46,6 +46,7 @@ E39ABC4627A4EBD500965D05 /* DevicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39ABC4527A4EBD500965D05 /* DevicesView.swift */; }; E39ABC4827A4EDEC00965D05 /* DeviceRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = E39ABC4727A4EDEC00965D05 /* DeviceRow.swift */; }; E3C651E727CB5426002F6F4C /* Tabler in Frameworks */ = {isa = PBXBuildFile; productRef = E3C651E627CB5426002F6F4C /* Tabler */; }; + E3C651EA27CB61EE002F6F4C /* GEOSwift in Frameworks */ = {isa = PBXBuildFile; productRef = E3C651E927CB61EE002F6F4C /* GEOSwift */; }; E3E77EE6279E6CE400150070 /* FlowCollector.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3E77EE5279E6CE400150070 /* FlowCollector.swift */; }; /* End PBXBuildFile section */ @@ -114,6 +115,7 @@ E3C651E727CB5426002F6F4C /* Tabler in Frameworks */, E36A5A8627B4BFC40070DED5 /* FirebaseMessaging in Frameworks */, E33A236A27A6898700DD647F /* SwiftUIX in Frameworks */, + E3C651EA27CB61EE002F6F4C /* GEOSwift in Frameworks */, E396281D27AF5723005D070E /* WhirlyGlobe.xcframework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -292,6 +294,7 @@ E33A236927A6898700DD647F /* SwiftUIX */, E36A5A8527B4BFC40070DED5 /* FirebaseMessaging */, E3C651E627CB5426002F6F4C /* Tabler */, + E3C651E927CB61EE002F6F4C /* GEOSwift */, ); productName = iosApp; productReference = 7555FF7B242A565900829871 /* iosApp.app */; @@ -327,6 +330,7 @@ E33A236827A6898700DD647F /* XCRemoteSwiftPackageReference "SwiftUIX" */, E36A5A8427B4BFC40070DED5 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, E3C651E527CB5425002F6F4C /* XCRemoteSwiftPackageReference "SwiftTabler" */, + E3C651E827CB61EE002F6F4C /* XCRemoteSwiftPackageReference "GEOSwift" */, ); productRefGroup = 7555FF7C242A565900829871 /* Products */; projectDirPath = ""; @@ -660,6 +664,14 @@ minimumVersion = 0.6.0; }; }; + E3C651E827CB61EE002F6F4C /* XCRemoteSwiftPackageReference "GEOSwift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/GEOSwift/GEOSwift"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 9.0.0; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ @@ -678,6 +690,11 @@ package = E3C651E527CB5425002F6F4C /* XCRemoteSwiftPackageReference "SwiftTabler" */; productName = Tabler; }; + E3C651E927CB61EE002F6F4C /* GEOSwift */ = { + isa = XCSwiftPackageProductDependency; + package = E3C651E827CB61EE002F6F4C /* XCRemoteSwiftPackageReference "GEOSwift" */; + productName = GEOSwift; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 7555FF73242A565900829871 /* Project object */; diff --git a/iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 3c172cd..2b63f64 100644 --- a/iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -28,6 +28,24 @@ "version": "8.12.1" } }, + { + "package": "geos", + "repositoryURL": "https://github.com/GEOSwift/geos.git", + "state": { + "branch": null, + "revision": "dc3a1e798e7ebb3cee1b6b219af2b0783820ff60", + "version": "7.0.0" + } + }, + { + "package": "GEOSwift", + "repositoryURL": "https://github.com/GEOSwift/GEOSwift", + "state": { + "branch": null, + "revision": "ab813f1acbd92986e8733356b73b3f6d4ddc08e0", + "version": "9.0.0" + } + }, { "package": "GoogleAppMeasurement", "repositoryURL": "https://github.com/google/GoogleAppMeasurement.git", diff --git a/iosApp/iosApp/Details/Reports/UnitReportsView.swift b/iosApp/iosApp/Details/Reports/UnitReportsView.swift index 910cea4..5a34ea5 100644 --- a/iosApp/iosApp/Details/Reports/UnitReportsView.swift +++ b/iosApp/iosApp/Details/Reports/UnitReportsView.swift @@ -100,6 +100,7 @@ struct UnitReportsView: View { } else { MapView(layer: $unitReportsViewModel.layer, markers: $unitReportsViewModel.markers, + geofences: $unitReportsViewModel.flatGeofences, selected: $unitReportsViewModel.selectedMarker, isReport: true) } diff --git a/iosApp/iosApp/Details/Reports/UnitReportsViewModel.swift b/iosApp/iosApp/Details/Reports/UnitReportsViewModel.swift index 5e85e89..4731a57 100644 --- a/iosApp/iosApp/Details/Reports/UnitReportsViewModel.swift +++ b/iosApp/iosApp/Details/Reports/UnitReportsViewModel.swift @@ -12,6 +12,7 @@ import shared class UnitReportsViewModel: ObservableObject { @Inject var reportController: ReportController + @Inject var geofencesController: GeofencesController @Published var deviceId: Int32? = nil @Published var reportType: ReportController.ReportType = .positions { @@ -42,16 +43,30 @@ class UnitReportsViewModel: ObservableObject { @Published var markers = [Marker]() @Published var selectedMarker: Marker? = nil + @Published var geofences: [Int: Geofence] = [:] { + didSet { + flatGeofences = Array(geofences.values) + } + } + @Published var flatGeofences: [Geofence] = [] + init(deviceId id: Int32?) { deviceId = id let collector = Collector(callback: setReport) reportController.reportFlow.collect(collector: collector) { _, _ in } + + let geofencesCollector = Collector<[Int: Geofence]>(callback: setGeofences) + geofencesController.geofencesFlow.collect(collector: geofencesCollector) { unit, error in } } func setReport (report: ReportController.Report) { self.report = report } + private func setGeofences(geofences: [Int: Geofence]) { + self.geofences = geofences + } + func fetchReport(xlsx: Bool = false) { if let id = deviceId { reportController.fetchReport(deviceId: id, diff --git a/iosApp/iosApp/Map/MapView.swift b/iosApp/iosApp/Map/MapView.swift index 05bd9f9..84bdc05 100644 --- a/iosApp/iosApp/Map/MapView.swift +++ b/iosApp/iosApp/Map/MapView.swift @@ -25,6 +25,7 @@ struct MapView: UIViewControllerRepresentable { @Binding var layer: MapLayer @Binding var markers: [Marker] + @Binding var geofences: [Geofence] @Binding var selected: Marker? var isReport: Bool = false var markerCallback: MarkerCallback? @@ -32,6 +33,7 @@ struct MapView: UIViewControllerRepresentable { class Coordinator { var shouldCenter: Bool = true var oldMarkers: [Marker] = [] + var oldGeofences: [Geofence] = [] } func makeCoordinator() -> Coordinator { @@ -51,7 +53,6 @@ struct MapView: UIViewControllerRepresentable { // MARK: - Set markers if context.coordinator.oldMarkers != markers { - print("center = \(context.coordinator.shouldCenter)") uiViewController.display(markers: markers, isReport: isReport, center: context.coordinator.shouldCenter) @@ -59,6 +60,12 @@ struct MapView: UIViewControllerRepresentable { } context.coordinator.oldMarkers = markers + // MARK: - Set geofences + if context.coordinator.oldGeofences != geofences { + uiViewController.display(geofences: geofences) + } + context.coordinator.oldGeofences = geofences + // MARK: - Center selected marker if let selected = selected { uiViewController.focusOn(marker: selected) diff --git a/iosApp/iosApp/Map/MapViewController.swift b/iosApp/iosApp/Map/MapViewController.swift index f068bf4..3c38b89 100644 --- a/iosApp/iosApp/Map/MapViewController.swift +++ b/iosApp/iosApp/Map/MapViewController.swift @@ -18,9 +18,23 @@ import UIKit import WhirlyGlobe import shared +import GEOSwift typealias MarkerCallback = (Int32?) -> () +extension Geometry { + func getCoordinates() -> [Point] { + switch self { + case let .polygon(polygon): + return polygon.exterior.points + case let .lineString(lineString): + return lineString.points + default: + return [] + } + } +} + class MapViewController: UIViewController { var markerCallback: MarkerCallback? = nil var mapLayer: MapLayer = MapLayer.companion.defaultLayer @@ -84,6 +98,12 @@ class MapViewController: UIViewController { } } + func display(geofences: [Geofence]) { + mapView.runOnInit { + self.mapView.display(geofences: geofences) + } + } + func focusOn(marker: Marker) { mapView.runOnInit { self.mapView.focusOn(marker: marker) @@ -206,8 +226,8 @@ class OurMaplyViewController: MaplyViewController { let fontSize = 11.0 let colorReport = UIColor(red: 0.0, green: 0.5, blue: 0.0, alpha: 1.0) - let colorLabel = UIColor.secondaryLabel - let colorLabelOutline = UIColor.systemBackground + let colorLabel = UIColor.darkGray + let colorLabelOutline = UIColor.white let vectorDesc: [AnyHashable : Any] = [ kMaplyColor: colorReport, @@ -319,6 +339,85 @@ class OurMaplyViewController: MaplyViewController { } } + func display(geofences: [Geofence]) { + clear(geofences: true) + + let fontSize = 11.0 + let colorFill = UIColor(red: 0.10, green: 0.46, blue: 0.82, alpha: 1.00) + let colorLabel = UIColor(red: 0.10, green: 0.46, blue: 0.82, alpha: 1.00) + let colorLabelOutline = UIColor.white + + let vectorDesc: [AnyHashable : Any] = [ + kMaplyColor: colorFill, + kMaplyVecWidth: 12.0, + kMaplyWideVecImpl: kMaplyWideVecImplPerf + ] + + let labelDesc: [AnyHashable : Any] = [ + kMaplyFont: UIFont.boldSystemFont(ofSize: fontSize), + kMaplyTextColor: colorLabel, + kMaplyTextOutlineColor: colorLabelOutline, + kMaplyTextOutlineSize: 3.0 + ] + + let shapes = [MaplyShape]() + var vectors = [MaplyVectorObject]() + var labels = [MaplyScreenLabel]() + + geofences.forEach { geofence in + if let area = geofence.area { + print ("Draw geofence with area = \(area)") + if let geometry = try? Geometry(wkt: area) { + switch geometry { + case .polygon(_): + let geoJSON: [AnyHashable : Any] = [ + "type": "FeatureCollection", + "features": [ + [ + "type": "Feature", + "properties": [], + "geometry": [ + "type": "Polygon", + "coordinates": [ + geometry.getCoordinates().map { coordinate in + [coordinate.y, coordinate.x] + } + ] + ] + ] + ] + ] + if let vector = MaplyVectorObject(fromGeoJSONDictionary: geoJSON) { + vectors.append(vector) + } + default: + break + } + + if let centroid = try? geometry.centroid() { + let label = MaplyScreenLabel() + label.text = geofence.name + label.loc = MaplyCoordinateMakeWithDegrees(Float(centroid.y), + Float(centroid.x)) + label.layoutImportance = .infinity + + labels.append(label) + } + } + } + } + + if let objs = addShapes(shapes, desc: nil, mode: .any) { + geofenceObjects.append(objs) + } + if let objs = addWideVectors(vectors, desc: vectorDesc, mode: .any) { + geofenceObjects.append(objs) + } + if let objs = addScreenLabels(labels, desc: labelDesc, mode: .any) { + geofenceObjects.append(objs) + } + } + func setZoomLimits(minZoom: Int32, maxZoom: Int32) { setZoomLimitsMin( height(forMapScale: Float(truncating: diff --git a/iosApp/iosApp/Map/UnitMapView.swift b/iosApp/iosApp/Map/UnitMapView.swift index 533ac13..f416554 100644 --- a/iosApp/iosApp/Map/UnitMapView.swift +++ b/iosApp/iosApp/Map/UnitMapView.swift @@ -25,6 +25,7 @@ struct UnitMapView: View { ZStack { MapView(layer: $unitsViewModel.mapLayerType, markers: $unitsViewModel.markers, + geofences: $unitsViewModel.flatGeofences, selected: $unitsViewModel.selectedMarker, markerCallback: unitsViewModel.selectUnitWith) if let unit = unitsViewModel.selectedUnit { diff --git a/iosApp/iosApp/Units/UnitsViewModel.swift b/iosApp/iosApp/Units/UnitsViewModel.swift index 47adeb7..8ba6a4b 100644 --- a/iosApp/iosApp/Units/UnitsViewModel.swift +++ b/iosApp/iosApp/Units/UnitsViewModel.swift @@ -60,7 +60,12 @@ class UnitsViewModel: ObservableObject { } @Published var selectedMarker: Marker? = nil @Published var mapLayerType: MapLayer = .companion.defaultLayer - @Published var geofences: [Int: Geofence] = [:] + @Published var geofences: [Int: Geofence] = [:] { + didSet { + flatGeofences = Array(geofences.values) + } + } + @Published var flatGeofences: [Geofence] = [] init() { unitsController.fetchUnits(scope: mainScope) -- cgit v1.2.3 From bb604a0c95fe344a5a5f4392c6bd33bc941b2ce5 Mon Sep 17 00:00:00 2001 From: Iván Ávalos Date: Tue, 1 Mar 2022 21:52:16 -0600 Subject: Failed to add horizontal scroll to events table --- iosApp/iosApp.xcodeproj/project.pbxproj | 4 +++ .../xcshareddata/swiftpm/Package.resolved | 6 ++-- .../iosApp/Details/Reports/UnitReportsView.swift | 24 ++++++++----- iosApp/iosApp/Shared/SidewaysScroller.swift | 42 ++++++++++++++++++++++ 4 files changed, 64 insertions(+), 12 deletions(-) create mode 100644 iosApp/iosApp/Shared/SidewaysScroller.swift (limited to 'iosApp') diff --git a/iosApp/iosApp.xcodeproj/project.pbxproj b/iosApp/iosApp.xcodeproj/project.pbxproj index 8aefd98..8e5838d 100644 --- a/iosApp/iosApp.xcodeproj/project.pbxproj +++ b/iosApp/iosApp.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 7555FF83242A565900829871 /* RootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7555FF82242A565900829871 /* RootView.swift */; }; E312E74F27B366060018C5DE /* DevicesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E312E74E27B366060018C5DE /* DevicesViewModel.swift */; }; E3141B8B27B9E91F00CE777C /* UnitReportsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3141B8A27B9E91F00CE777C /* UnitReportsViewModel.swift */; }; + E31D721527CF159900CDA320 /* SidewaysScroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = E31D721427CF159900CDA320 /* SidewaysScroller.swift */; }; E3385A4F27B0D8A10025311C /* UnitCommandsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3385A4E27B0D8A10025311C /* UnitCommandsViewModel.swift */; }; E33A236027A4FD2C00DD647F /* UnitMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E33A235F27A4FD2C00DD647F /* UnitMapView.swift */; }; E33A236527A530F300DD647F /* SmallLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = E33A236427A530F300DD647F /* SmallLabelStyle.swift */; }; @@ -73,6 +74,7 @@ 7555FF8C242A565B00829871 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E312E74E27B366060018C5DE /* DevicesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevicesViewModel.swift; sourceTree = ""; }; E3141B8A27B9E91F00CE777C /* UnitReportsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitReportsViewModel.swift; sourceTree = ""; }; + E31D721427CF159900CDA320 /* SidewaysScroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidewaysScroller.swift; sourceTree = ""; }; E3385A4E27B0D8A10025311C /* UnitCommandsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitCommandsViewModel.swift; sourceTree = ""; }; E33A235F27A4FD2C00DD647F /* UnitMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitMapView.swift; sourceTree = ""; }; E33A236427A530F300DD647F /* SmallLabelStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmallLabelStyle.swift; sourceTree = ""; }; @@ -268,6 +270,7 @@ E33A236627A64E4500DD647F /* MarkerTransformations.swift */, E33A237227A7581A00DD647F /* Utils.swift */, E34A2F4727A7878200AD8AEB /* HyperlinkText.swift */, + E31D721427CF159900CDA320 /* SidewaysScroller.swift */, ); path = Shared; sourceTree = ""; @@ -410,6 +413,7 @@ E3141B8B27B9E91F00CE777C /* UnitReportsViewModel.swift in Sources */, E38F242027A27B550069FC45 /* LoadingView.swift in Sources */, E38F241E27A270D50069FC45 /* UnitsView.swift in Sources */, + E31D721527CF159900CDA320 /* SidewaysScroller.swift in Sources */, 7555FF83242A565900829871 /* RootView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 2b63f64..f925bad 100644 --- a/iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -132,8 +132,8 @@ "repositoryURL": "https://github.com/openalloc/SwiftTabler", "state": { "branch": null, - "revision": "3a6c0ba6c1e1e9bcd29c2fb628dc7f1037307ec5", - "version": "0.6.0" + "revision": "03d8c9f20d34142b0bb9a31f15b3e6d8c47b39c7", + "version": "0.6.4" } }, { @@ -141,7 +141,7 @@ "repositoryURL": "https://github.com/ivan-avalos/SwiftUIX", "state": { "branch": "master", - "revision": "9b02351a947aa5ac1d2b3a5d576f9591960a89fc", + "revision": "fa1358cc48610d1de52de29111923a52e92a17d9", "version": null } } diff --git a/iosApp/iosApp/Details/Reports/UnitReportsView.swift b/iosApp/iosApp/Details/Reports/UnitReportsView.swift index 5a34ea5..9973189 100644 --- a/iosApp/iosApp/Details/Reports/UnitReportsView.swift +++ b/iosApp/iosApp/Details/Reports/UnitReportsView.swift @@ -33,15 +33,19 @@ struct UnitReportsView: View { wrappedValue: UnitReportsViewModel(deviceId: unit.device.id)) } + private var eventsConfig: TablerListConfig { + TablerListConfig(gridItems: eventsGridItems) + } + private var eventsGridItems: [GridItem] = [ - GridItem(.flexible(), alignment: .leading), - GridItem(.flexible(), alignment: .leading), - GridItem(.flexible(), alignment: .leading), - GridItem(.flexible(), alignment: .leading), + GridItem(.flexible(minimum: 100), alignment: .leading), + GridItem(.flexible(minimum: 100), alignment: .leading), + GridItem(.flexible(minimum: 100), alignment: .leading), + GridItem(.flexible(minimum: 100), alignment: .leading), ] @ViewBuilder - private func eventsHeader(_ ctx: TablerSortContext) -> some View { + private func eventsHeader(_ ctx: Binding>) -> some View { Text("events-table-datetime") Text("events-table-event") Text("events-table-geofence") @@ -90,10 +94,12 @@ struct UnitReportsView: View { VStack { if unitReportsViewModel.reportType == .events { if let report = unitReportsViewModel.report as? ReportController.ReportEventsReport { - TablerList(TablerListConfig(gridItems: eventsGridItems), - headerContent: eventsHeader, - rowContent: eventsRow, - results: report.events) + SidewaysScroller(minWidth: 400) { + TablerList(eventsConfig, + headerContent: eventsHeader, + rowContent: eventsRow, + results: report.events) + } } else { Spacer() } diff --git a/iosApp/iosApp/Shared/SidewaysScroller.swift b/iosApp/iosApp/Shared/SidewaysScroller.swift new file mode 100644 index 0000000..262b121 --- /dev/null +++ b/iosApp/iosApp/Shared/SidewaysScroller.swift @@ -0,0 +1,42 @@ +// +// SidewaysScroller.swift +// +// Copyright 2022 FlowAllocator LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +import SwiftUI + +/// wrap a view in a horizontal scroll view, for display of large tables on compact display area +public struct SidewaysScroller: View { + var minWidth: CGFloat + @ViewBuilder var content: () -> Content + + public init(minWidth: CGFloat, + @ViewBuilder content: @escaping () -> Content) + { + self.minWidth = minWidth + self.content = content + } + + public var body: some View { + GeometryReader { geo in + ScrollView(.horizontal) { + VStack(alignment: .leading) { + content() + } + .frame(minWidth: max(minWidth, geo.size.width)) + } + } + } +} -- cgit v1.2.3 From 9b8eee4362c368e682bfe18d5cef44d6b9d109bf Mon Sep 17 00:00:00 2001 From: Iván Ávalos Date: Tue, 1 Mar 2022 22:18:00 -0600 Subject: Fixed horizontal scroll and bumped version to 1.1 --- iosApp/iosApp.xcodeproj/project.pbxproj | 2 ++ iosApp/iosApp/Details/Reports/UnitReportsView.swift | 6 +++--- iosApp/iosApp/Info.plist | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'iosApp') diff --git a/iosApp/iosApp.xcodeproj/project.pbxproj b/iosApp/iosApp.xcodeproj/project.pbxproj index 8e5838d..dc4bdc2 100644 --- a/iosApp/iosApp.xcodeproj/project.pbxproj +++ b/iosApp/iosApp.xcodeproj/project.pbxproj @@ -570,6 +570,7 @@ "$(inherited)", "@executable_path/Frameworks", ); + MARKETING_VERSION = 1.1; OTHER_LDFLAGS = ( "$(inherited)", "-framework", @@ -606,6 +607,7 @@ "$(inherited)", "@executable_path/Frameworks", ); + MARKETING_VERSION = 1.1; OTHER_LDFLAGS = ( "$(inherited)", "-framework", diff --git a/iosApp/iosApp/Details/Reports/UnitReportsView.swift b/iosApp/iosApp/Details/Reports/UnitReportsView.swift index 9973189..2143b3b 100644 --- a/iosApp/iosApp/Details/Reports/UnitReportsView.swift +++ b/iosApp/iosApp/Details/Reports/UnitReportsView.swift @@ -40,8 +40,8 @@ struct UnitReportsView: View { private var eventsGridItems: [GridItem] = [ GridItem(.flexible(minimum: 100), alignment: .leading), GridItem(.flexible(minimum: 100), alignment: .leading), - GridItem(.flexible(minimum: 100), alignment: .leading), - GridItem(.flexible(minimum: 100), alignment: .leading), + GridItem(.flexible(minimum: 100, maximum: 150), alignment: .leading), + GridItem(.flexible(minimum: 150, maximum: 250), alignment: .leading), ] @ViewBuilder @@ -94,7 +94,7 @@ struct UnitReportsView: View { VStack { if unitReportsViewModel.reportType == .events { if let report = unitReportsViewModel.report as? ReportController.ReportEventsReport { - SidewaysScroller(minWidth: 400) { + SidewaysScroller(minWidth: 1000) { TablerList(eventsConfig, headerContent: eventsHeader, rowContent: eventsRow, diff --git a/iosApp/iosApp/Info.plist b/iosApp/iosApp/Info.plist index 99c8b7b..da4a45d 100644 --- a/iosApp/iosApp/Info.plist +++ b/iosApp/iosApp/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.0 + $(MARKETING_VERSION) CFBundleVersion 1 LSRequiresIPhoneOS -- cgit v1.2.3