Adds SideMenu and company view

This commit is contained in:
Patrick McDonagh
2018-06-06 18:39:18 -05:00
parent 25f862e1c5
commit ec2e0b643b
40 changed files with 7393 additions and 4214 deletions

View File

@@ -0,0 +1,27 @@
//
// AdminCompanyCell.swift
// pocloud
//
// Created by Patrick McDonagh on 6/6/18.
// Copyright © 2018 patrickjmcd. All rights reserved.
//
import UIKit
class AdminCompanyCell: UITableViewCell {
@IBOutlet weak var companyNameLabel: UILabel!
@IBOutlet weak var companyCountLabel: PillUILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}

View File

@@ -0,0 +1,93 @@
//
// AdminViewController.swift
// pocloud
//
// Created by Patrick McDonagh on 6/6/18.
// Copyright © 2018 patrickjmcd. All rights reserved.
//
import UIKit
import RealmSwift
import PromiseKit
class AdminViewController: UITableViewController {
let realm = try! Realm()
let baseURL = (UIApplication.shared.delegate as! AppDelegate).baseURL
let user = (UIApplication.shared.delegate as! AppDelegate).user
let appAuth = AppAuth()
var companiesWithGateways : Results<Company>?
var companiesNoGateways : Results<Company>?
var selectedCompany : Company?
override func viewDidLoad() {
super.viewDidLoad()
// Get company data from Realm
companiesWithGateways = realm.objects(Company.self).filter("gateways.@count > 0")
companiesNoGateways = realm.objects(Company.self).filter("gateways.@count == 0")
if (companiesWithGateways!.count + companiesNoGateways!.count) == 0{
firstly {
getAllMeshifyData(baseURL: self.baseURL, authToken: self.user!.authToken)
}.done {
self.tableView.reloadData()
}.catch { error in
print("Error getting all meshify data in AdminViewController: \(error)")
}
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return companiesWithGateways?.count ?? 0
} else {
return companiesNoGateways?.count ?? 0
}
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {
return "Companies with Devices"
} else {
return "Companies with NO Devices"
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "companyCell", for: indexPath) as! AdminCompanyCell
if indexPath.section == 0 {
cell.companyNameLabel.text = companiesWithGateways![indexPath.row].name
cell.companyCountLabel.text = String(companiesWithGateways![indexPath.row].gateways.count)
} else {
cell.companyNameLabel.text = companiesNoGateways![indexPath.row].name
cell.companyCountLabel.isHidden = true
cell.accessoryType = .none
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 0 {
selectedCompany = companiesWithGateways![indexPath.row]
performSegue(withIdentifier: "openCompanyDetailView", sender: self)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "openCompanyDetailView" {
let targetVC = segue.destination as! CompanyViewController
targetVC.thisCompany = selectedCompany
}
}
}

View File

@@ -36,6 +36,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Chameleon.setGlobalThemeUsingPrimaryColor(UIColor.flatSkyBlue(), with: UIContentStyle.contrast)
// print(Realm.Configuration.defaultConfiguration.fileURL)
Migrations().checkSchema()
FirebaseApp.configure()
return true

View File

@@ -0,0 +1,102 @@
//
// CompanyViewController.swift
// pocloud
//
// Created by Patrick McDonagh on 6/6/18.
// Copyright © 2018 patrickjmcd. All rights reserved.
//
import UIKit
import MapKit
class CompanyViewController: UIViewController, MKMapViewDelegate, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var mapView: MKMapView!
@IBOutlet weak var tableView: UITableView!
var thisCompany : Company?
var selectedGateway : Gateway?
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
mapView.delegate = self
title = thisCompany?.name
addMapDot()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let company = thisCompany{
return company.gateways.count
} else {
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "companyGatewayCell", for: indexPath)
cell.textLabel?.text = thisCompany?.gateways[indexPath.row].name
return cell
}
func addMapDot(){
let coord = CLLocationCoordinate2D(latitude: (thisCompany?.address!.lat)!, longitude: (thisCompany?.address!.long)!)
let gatewayAnnotation = GatewayAnnotation(coordinate: coord, title: (thisCompany?.name)!, subtitle: (thisCompany?.address?.streetAddress)!, gateway: nil)
mapView.addAnnotation(gatewayAnnotation)
let regionRadius: CLLocationDistance = 1000
let coordinateRegion = MKCoordinateRegionMakeWithDistance(coord, regionRadius, regionRadius)
mapView.setRegion(coordinateRegion, animated: true)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "marker"
if annotation.isKind(of: GatewayAnnotation.self) {
var view: MKMarkerAnnotationView
if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKMarkerAnnotationView {
dequeuedView.annotation = annotation
view = dequeuedView
} else {
view = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.canShowCallout = true
view.calloutOffset = CGPoint(x: -5, y: 5)
view.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
}
return view
} else {
return nil
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedGateway = thisCompany?.gateways[indexPath.row]
performSegue(withIdentifier: "openGatewayDetail", sender: self)
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
let location = view.annotation as! GatewayAnnotation
let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving]
location.mapItem().openInMaps(launchOptions: launchOptions)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "openGatewayDetail" {
let destinationVC = segue.destination as! MapDetailViewController
destinationVC.gateway = selectedGateway
}
}
}

View File

@@ -13,6 +13,7 @@ import RealmSwift
import SwiftyJSON
import SVProgressHUD
import FirebaseDatabase
import ChameleonFramework
class DeviceDetailViewController: UITableViewController {
let realm = try! Realm()
@@ -28,6 +29,7 @@ class DeviceDetailViewController: UITableViewController {
var values : [String : MeshifyValue] = [:]
var updatedChannelNames : [String] = [String]()
var changedChannelNames : [String] = [String]()
let numFormatter = NumberFormatter()
override func viewDidLoad() {
super.viewDidLoad()
@@ -35,6 +37,10 @@ class DeviceDetailViewController: UITableViewController {
let macAddress = String((thisDevice?.macAddress.replacingOccurrences(of: ":", with: "").uppercased().dropLast(4))!)
let deviceTypeName = (thisDevice?.parentDeviceType.first?.name)!
numFormatter.minimumFractionDigits = 0
numFormatter.maximumFractionDigits = 3
numFormatter.minimumIntegerDigits = 1
SVProgressHUD.show()
firstly {
loadData()
@@ -138,6 +144,18 @@ class DeviceDetailViewController: UITableViewController {
print("Error fetching data in DeviceDetailViewController: \(error)")
}
}
func tryRound(value : String, places numberOfPlaces: Int) -> String {
if let doubledValue = Double(value) {
if let formattedString = numFormatter.string(from: NSNumber(value: doubledValue)) {
return formattedString
} else {
return value
}
} else {
return value
}
}
@@ -158,6 +176,7 @@ class DeviceDetailViewController: UITableViewController {
let chanName = thisDevice?.parentDeviceType.first?.channels[indexPath.row].name
let chanVal = values[chanName!]
if let i = changedChannelNames.index(of: chanName!) {
changedChannelNames.remove(at: i)
cell.backgroundColor = UIColor.flatLime()
@@ -180,8 +199,8 @@ class DeviceDetailViewController: UITableViewController {
}
}
cell.channelValueLabel?.text = tryRound(value: chanVal!.value, places: 3)
cell.accessoryType = .disclosureIndicator
cell.channelValueLabel?.text = chanVal?.value
return cell
}

View File

@@ -15,6 +15,7 @@ import SVProgressHUD
import FirebaseAuth
class DeviceListViewController: UITableViewController {
@IBOutlet weak var searchBar: UISearchBar!
let realm = try! Realm()
let user = (UIApplication.shared.delegate as! AppDelegate).user
@@ -37,6 +38,8 @@ class DeviceListViewController: UITableViewController {
refreshControl?.attributedTitle = NSAttributedString(string: "Pull to refresh")
refreshControl?.addTarget(self, action: #selector(refresh), for: UIControlEvents.valueChanged)
searchBar.delegate = self
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Log Out", style: .plain, target: self, action: #selector(self.logOut))
SVProgressHUD.show()
@@ -60,13 +63,15 @@ class DeviceListViewController: UITableViewController {
func loadJSONData() -> Promise<Void>{
return Promise { promise in
firstly {
getDeviceTypes(baseURL: self.baseURL, authToken: (self.user?.authToken)!)
getDeviceTypes(baseURL: self.baseURL, authToken: self.user!.authToken)
}.then { _ in
getAddresses(baseURL: self.baseURL, authToken: (self.user?.authToken)!)
getCompanies(baseURL: self.baseURL, authToken: self.user!.authToken)
}.then { _ in
getAddresses(baseURL: self.baseURL, authToken: self.user!.authToken)
}.then { _ in
getGateways(baseURL: self.baseURL, authToken: (self.user?.authToken)!)
getGateways(baseURL: self.baseURL, authToken: self.user!.authToken)
}.then { _ in
getDevices(baseURL: self.baseURL, authToken: (self.user?.authToken)!)
getDevices(baseURL: self.baseURL, authToken: self.user!.authToken)
}.done{ _ in
promise.fulfill(())
}.catch { error in
@@ -150,3 +155,29 @@ class DeviceListViewController: UITableViewController {
}
}
extension DeviceListViewController : UISearchBarDelegate {
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
devices = devices?.filter("vanityName CONTAINS[cd] %@", searchBar.text!).sorted(byKeyPath: "vanityName", ascending: true)
tableView.reloadData()
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchBar.text?.count == 0 {
firstly {
self.loadRealmData()
}.then{ _ in
self.loadJSONData()
}.done { _ in
self.tableView.reloadData()
DispatchQueue.main.async {
searchBar.resignFirstResponder()
}
}.catch { error in
print("Error in getting data in DeviceListViewController: \(error)")
}
}
}
}

View File

@@ -0,0 +1,35 @@
//
// MainNavController.swift
// pocloud
//
// Created by Patrick McDonagh on 6/6/18.
// Copyright © 2018 patrickjmcd. All rights reserved.
//
import UIKit
class MainNavController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}

View File

@@ -56,7 +56,8 @@ class MapViewController: UIViewController, MKMapViewDelegate {
}
let buttonItem = MKUserTrackingBarButtonItem(mapView: mapView)
self.navigationItem.rightBarButtonItem = buttonItem
self.navigationItem.rightBarButtonItems?.append(buttonItem)
// self.navigationItem.rightBarButtonItem = buttonItem
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Log Out", style: .plain, target: self, action: #selector(self.logOut))

View File

@@ -129,9 +129,11 @@ func getGateways(baseURL : String, authToken : String) -> Promise<Any> {
gtw.userId = json["userId"].intValue
let associatedAddress = realm.objects(Address.self).filter("id == %d", gtw.addressId).first
let parentCompany = realm.objects(Company.self).filter("id == %d", gtw.companyId).first
gtw.address = associatedAddress
realm.add(gtw, update: true)
parentCompany?.gateways.append(gtw)
}
} catch {
seal.reject(error)
@@ -262,20 +264,6 @@ func getChannelValues(deviceId: Int, baseURL : String, authToken : String) -> Pr
let channelValJSON : JSON = JSON(response.result.value!)
var valueDict : [String : MeshifyValue] = [:]
for(chName, json) : (String, JSON) in channelValJSON {
// do {
// try realm.write {
// let chv = ChanValue()
// chv.uid = "\(deviceId).\(chName)"
// chv.name = chName
// chv.value = json["value"].stringValue
// chv.timestamp = json["timestamp"].intValue
//
// realm.add(chv, update: true)
// realm.objects(Device.self).filter("id == %d", deviceId).first?.values.append(chv)
// }
// } catch {
// prom.reject(error)
// }
let chv = MeshifyValue()
chv.name = chName
chv.value = json["value"].stringValue
@@ -320,6 +308,69 @@ func getChannelHistory(deviceId: Int, channelId : Int, baseURL : String, authTok
}
}
func getCompanies(baseURL : String, authToken : String) -> Promise<Any> {
let realm = try! Realm()
let url = "\(baseURL)/companies"
let headers : HTTPHeaders = [
"Authorization": authToken
]
return Promise { seal in
Alamofire.request(url, method: .get, headers: headers)
.responseJSON { response in
switch response.result {
case .success:
let gatewaysJSON : JSON = JSON(response.result.value!)
for(_, json) : (String, JSON) in gatewaysJSON {
do {
try realm.write {
let company = Company()
company.id = json["id"].intValue
company.name = json["name"].stringValue
company.tenantId = json["tenantId"].intValue
company.addressId = json["addressId"].intValue
company.address = realm.objects(Address.self).filter("id == %d", company.addressId).first
realm.add(company, update: true)
}
} catch {
seal.reject(error)
}
}
seal.fulfill(true)
case .failure(let error):
seal.reject(error)
}
}
}
}
func getAllMeshifyData(baseURL : String, authToken : String) -> Promise<Void>{
return Promise { promise in
firstly {
getDeviceTypes(baseURL: baseURL, authToken: authToken)
}.then { _ in
getCompanies(baseURL: baseURL, authToken: authToken)
}.then { _ in
getAddresses(baseURL: baseURL, authToken: authToken)
}.then { _ in
getGateways(baseURL: baseURL, authToken: authToken)
}.then { _ in
getDevices(baseURL: baseURL, authToken: authToken)
}.done{ _ in
promise.fulfill(())
}.catch { error in
promise.reject(error)
}
}
}
func writeChannelValue(deviceId: Int, channelName: String, value : String, baseURL : String, authToken : String) -> Promise<Any> {
let timestamp: Int = Int(Date().timeIntervalSince1970)
var channelJson : JSON = JSON()

View File

@@ -1,21 +0,0 @@
//
// NavigationController.swift
// pocloud
//
// Created by Patrick McDonagh on 5/29/18.
// Copyright © 2018 patrickjmcd. All rights reserved.
//
import UIKit
import ChameleonFramework
class NavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.navigationBar.tintColor = UIColor.flatSkyBlue()
}
}

View File

@@ -0,0 +1,37 @@
//
// NavigationMenuController.swift
// pocloud
//
// Created by Patrick McDonagh on 6/6/18.
// Copyright © 2018 patrickjmcd. All rights reserved.
//
import UIKit
class NavigationMenuController: UITableViewController {
let appAuth = AppAuth()
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func logOutButtonPressed(_ sender: Any) {
print("SHOULD LOG OUT")
// appAuth.logOut()
self.navigationController!.popToRootViewController(animated: true)
// self.dismiss(animated: false) {
// let mainVC = (UIApplication.shared.delegate!.window!?.rootViewController!)!
// if let navController = mainVC.navigationController {
// navController.popToRootViewController(animated: true)
// } else {
// print("NO NAV CONTROLLER")
// }
// }
}
}

View File

@@ -17,7 +17,7 @@
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>5</string>
<string>7</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSLocationUsageDescription</key>

View File

@@ -44,6 +44,10 @@ class Address : Object {
// return mapItem
// }
//
public var streetAddress : String {
return "\(street1)\n\(street2)\n\(city), \(state) \(zip)\n\(country)"
}
override static func primaryKey() -> String? {
return "id"
}

View File

@@ -0,0 +1,24 @@
//
// Company.swift
// pocloud
//
// Created by Patrick McDonagh on 6/6/18.
// Copyright © 2018 patrickjmcd. All rights reserved.
//
import Foundation
import RealmSwift
class Company : Object {
@objc dynamic var id : Int = 0
@objc dynamic var name : String = ""
@objc dynamic var tenantId : Int = 0
@objc dynamic var addressId : Int = 0
@objc dynamic var address : Address?
override static func primaryKey() -> String? {
return "id"
}
let gateways = List<Gateway>()
}

View File

@@ -23,7 +23,9 @@ class Gateway : Object {
@objc dynamic var userId : Int = 0
@objc dynamic var address : Address?
var devices = List<Device>()
var parentCompany = LinkingObjects(fromType: Company.self, property: "gateways")
override static func primaryKey() -> String? {
return "id"

View File

@@ -0,0 +1,44 @@
//
// Migrations.swift
// pocloud
//
// Created by Patrick McDonagh on 6/6/18.
// Copyright © 2018 patrickjmcd. All rights reserved.
//
import Foundation
import RealmSwift
class Migrations {
func checkSchema() {
let config = Realm.Configuration(
// Set the new schema version. This must be greater than the previously used
// version (if you've never set a schema version before, the version is 0).
schemaVersion: 1,
// Set the block which will be called automatically when opening a Realm with
// a schema version lower than the one set above
migrationBlock: { migration, oldSchemaVersion in
// We havent migrated anything yet, so oldSchemaVersion == 0
print(oldSchemaVersion)
switch oldSchemaVersion {
case 1:
break
default:
// Nothing to do!
self.zeroToOne(migration: migration)
}
})
Realm.Configuration.defaultConfiguration = config
print("Migration done")
}
func zeroToOne(migration : Migration) {
print("Performing migration from 0 to 1")
migration.enumerateObjects(ofType: Company.className(), { (oldObject, newObject) in
migration.delete(oldObject!)
})
}
}

View File

@@ -22,13 +22,13 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="POCloud" translatesAutoresizingMaskIntoConstraints="NO" id="1S2-PY-AeP">
<rect key="frame" x="16" y="78" width="343" height="128"/>
<rect key="frame" x="16" y="130" width="343" height="128"/>
<constraints>
<constraint firstAttribute="height" constant="128" id="kdi-J3-yap"/>
</constraints>
</imageView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Nk0-L4-BTc">
<rect key="frame" x="16" y="216" width="343" height="110"/>
<rect key="frame" x="16" y="268" width="343" height="110"/>
<subviews>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="xGD-1W-wfk" userLabel="passwordField">
<rect key="frame" x="0.0" y="40" width="343" height="30"/>
@@ -89,7 +89,7 @@
</constraints>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
<navigationItem key="navigationItem" title="Login" id="Vcq-WU-7nG"/>
<navigationItem key="navigationItem" title="Login" largeTitleDisplayMode="always" id="Vcq-WU-7nG"/>
<connections>
<outlet property="emailField" destination="ktz-LF-BMG" id="YD6-kd-Y0H"/>
<outlet property="passwordField" destination="xGD-1W-wfk" id="grX-b5-xhC"/>
@@ -98,7 +98,271 @@
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="193" y="127"/>
<point key="canvasLocation" x="-940" y="84"/>
</scene>
<!-- -->
<scene sceneID="zqR-cL-CY1">
<objects>
<tableViewController id="IRa-Tu-z8L" customClass="NavigationMenuController" customModule="pocloud" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="rZD-k6-vfI">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<sections>
<tableViewSection id="BZs-uI-hiP">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="MOW-uN-hVD">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="MOW-uN-hVD" id="Zft-87-4vv">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Map View" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="K2m-on-u83">
<rect key="frame" x="16" y="0.0" width="343" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="WkR-Ec-bck"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="K2m-on-u83" secondAttribute="trailing" constant="16" id="itX-5w-OBv"/>
<constraint firstItem="K2m-on-u83" firstAttribute="leading" secondItem="Zft-87-4vv" secondAttribute="leading" constant="16" id="ov7-hP-RzB"/>
<constraint firstAttribute="bottom" secondItem="K2m-on-u83" secondAttribute="bottom" id="uWk-am-QXU"/>
<constraint firstItem="K2m-on-u83" firstAttribute="top" secondItem="Zft-87-4vv" secondAttribute="top" id="v3E-fu-Z3h"/>
</constraints>
</tableViewCellContentView>
<connections>
<segue destination="yV3-Bs-nOb" kind="show" identifier="openMapView" id="vHY-2V-RrB"/>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="tgi-Lg-OUk">
<rect key="frame" x="0.0" y="44" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="tgi-Lg-OUk" id="cHZ-P5-57P">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="List View" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="O2Q-ia-Znc">
<rect key="frame" x="16" y="0.0" width="343" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="OUu-Sl-qO8"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="O2Q-ia-Znc" firstAttribute="top" secondItem="cHZ-P5-57P" secondAttribute="top" id="6b0-uT-Dyz"/>
<constraint firstAttribute="trailing" secondItem="O2Q-ia-Znc" secondAttribute="trailing" constant="16" id="X35-2D-Vmj"/>
<constraint firstAttribute="bottom" secondItem="O2Q-ia-Znc" secondAttribute="bottom" id="gii-t8-r0I"/>
<constraint firstItem="O2Q-ia-Znc" firstAttribute="leading" secondItem="cHZ-P5-57P" secondAttribute="leading" constant="16" id="tNz-Jj-6c9"/>
</constraints>
</tableViewCellContentView>
<connections>
<segue destination="2zN-e5-x2c" kind="show" identifier="openListView" id="9Om-lw-Jgn"/>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="MFi-Ch-dpb">
<rect key="frame" x="0.0" y="88" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="MFi-Ch-dpb" id="uOu-qn-Bsk">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Company View" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PBz-lV-jm5">
<rect key="frame" x="16" y="0.0" width="343" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="W4g-rH-3kB"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="PBz-lV-jm5" firstAttribute="top" secondItem="uOu-qn-Bsk" secondAttribute="top" id="eFS-1d-xye"/>
<constraint firstItem="PBz-lV-jm5" firstAttribute="leading" secondItem="uOu-qn-Bsk" secondAttribute="leading" constant="16" id="uJV-EL-4pQ"/>
<constraint firstAttribute="bottom" secondItem="PBz-lV-jm5" secondAttribute="bottom" id="y0g-od-TRr"/>
<constraint firstAttribute="trailing" secondItem="PBz-lV-jm5" secondAttribute="trailing" constant="16" id="y7M-Vh-JFu"/>
</constraints>
</tableViewCellContentView>
<connections>
<segue destination="gRf-OH-LM3" kind="show" identifier="openAdminView" id="gSm-yD-AQS"/>
</connections>
</tableViewCell>
</cells>
</tableViewSection>
</sections>
<connections>
<outlet property="dataSource" destination="IRa-Tu-z8L" id="x7M-5j-lGC"/>
<outlet property="delegate" destination="IRa-Tu-z8L" id="hPj-B4-IPb"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title=" " id="jEZ-M0-fct">
<barButtonItem key="rightBarButtonItem" enabled="NO" title="Log Out" id="Efy-Wb-N0o">
<connections>
<action selector="logOutButtonPressed:" destination="IRa-Tu-z8L" id="fC3-XJ-dWk"/>
</connections>
</barButtonItem>
</navigationItem>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="BGw-nQ-anY" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1522" y="-1304"/>
</scene>
<!--Admin View-->
<scene sceneID="luK-QG-5Bk">
<objects>
<tableViewController title="Admin View" id="gRf-OH-LM3" customClass="AdminViewController" customModule="pocloud" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="pRZ-8h-aCt">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="companyCell" id="DRr-fl-mHP" customClass="AdminCompanyCell" customModule="pocloud" customModuleProvider="target">
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="DRr-fl-mHP" id="P5X-PW-Uxh">
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillProportionally" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="EhU-GL-Npw">
<rect key="frame" x="16" y="0.0" width="325" height="43.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Company Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="X2f-5T-wWU">
<rect key="frame" x="0.0" y="11.5" width="278.5" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="cnt" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="16b-fu-GPA" customClass="PillUILabel" customModule="pocloud" customModuleProvider="target">
<rect key="frame" x="278.5" y="8.5" width="46.5" height="26.5"/>
<color key="backgroundColor" red="0.0" green="0.32852089410000002" blue="0.57488495110000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="horizontalPad">
<real key="value" value="3"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="verticalPad">
<real key="value" value="3"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</label>
</subviews>
<constraints>
<constraint firstItem="16b-fu-GPA" firstAttribute="width" secondItem="X2f-5T-wWU" secondAttribute="width" multiplier="1:6" id="Thj-dG-e0H"/>
</constraints>
</stackView>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="EhU-GL-Npw" secondAttribute="trailing" id="SSP-KX-dUn"/>
<constraint firstAttribute="bottom" secondItem="EhU-GL-Npw" secondAttribute="bottom" id="gWW-wI-VKJ"/>
<constraint firstItem="EhU-GL-Npw" firstAttribute="top" secondItem="P5X-PW-Uxh" secondAttribute="top" id="rlm-TY-nIF"/>
<constraint firstItem="EhU-GL-Npw" firstAttribute="leading" secondItem="P5X-PW-Uxh" secondAttribute="leading" constant="16" id="shl-Ek-QFo"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="companyCountLabel" destination="16b-fu-GPA" id="ycu-fG-ojM"/>
<outlet property="companyNameLabel" destination="X2f-5T-wWU" id="wnq-TY-OZG"/>
</connections>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="gRf-OH-LM3" id="0ea-wk-hcW"/>
<outlet property="delegate" destination="gRf-OH-LM3" id="stD-ti-ZKX"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Company View" id="mC8-zn-oFH">
<barButtonItem key="rightBarButtonItem" title="Menu" id="3os-hB-xsh">
<connections>
<segue destination="Xem-jg-Xlm" kind="presentation" identifier="openMenu" id="LUR-lb-5qK"/>
</connections>
</barButtonItem>
</navigationItem>
<connections>
<segue destination="1Oj-LF-SeF" kind="show" identifier="openCompanyDetailView" id="fe4-55-2K0"/>
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="DB1-BB-Mof" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2492" y="-1305"/>
</scene>
<!--Title-->
<scene sceneID="zaO-o6-5qR">
<objects>
<viewController id="1Oj-LF-SeF" customClass="CompanyViewController" customModule="pocloud" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="GRC-ek-5fe">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="TeN-MF-HxZ">
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
<subviews>
<mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="UFa-F1-ny6">
<rect key="frame" x="0.0" y="0.0" width="375" height="215.5"/>
</mapView>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="tuB-TB-6oT">
<rect key="frame" x="0.0" y="215.5" width="375" height="431.5"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="companyGatewayCell" id="vCb-SM-3BC">
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="vCb-SM-3BC" id="jo4-sq-noy">
<rect key="frame" x="0.0" y="0.0" width="342" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
</tableView>
</subviews>
<constraints>
<constraint firstItem="tuB-TB-6oT" firstAttribute="height" secondItem="UFa-F1-ny6" secondAttribute="height" multiplier="2:1" id="8yd-Ai-MxK"/>
</constraints>
</stackView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="TeN-MF-HxZ" firstAttribute="trailing" secondItem="VXe-is-TrW" secondAttribute="trailing" id="Yqg-gC-eg1"/>
<constraint firstItem="TeN-MF-HxZ" firstAttribute="leading" secondItem="VXe-is-TrW" secondAttribute="leading" id="cxy-jx-iWN"/>
<constraint firstItem="VXe-is-TrW" firstAttribute="bottom" secondItem="TeN-MF-HxZ" secondAttribute="bottom" id="jjA-XJ-LOb"/>
<constraint firstItem="TeN-MF-HxZ" firstAttribute="top" secondItem="VXe-is-TrW" secondAttribute="top" id="u4f-bI-9xa"/>
</constraints>
<viewLayoutGuide key="safeArea" id="VXe-is-TrW"/>
</view>
<navigationItem key="navigationItem" title="Title" id="Ja7-Gn-Q1G"/>
<connections>
<outlet property="mapView" destination="UFa-F1-ny6" id="q6c-IG-QE3"/>
<outlet property="tableView" destination="tuB-TB-6oT" id="Vtm-TF-70f"/>
<segue destination="T4w-Nz-H9R" kind="show" identifier="openGatewayDetail" id="DQm-0d-brY"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="7wS-xR-ms3" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="3449" y="-1306"/>
</scene>
<!--Side Menu Navigation Controller-->
<scene sceneID="gOX-yi-sFP">
<objects>
<navigationController id="Xem-jg-Xlm" customClass="UISideMenuNavigationController" customModule="SideMenu" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="kQ0-0P-nCC">
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="IRa-Tu-z8L" kind="relationship" relationship="rootViewController" id="rm7-9q-AsM"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="2za-Iu-Z6p" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="580" y="-1305"/>
</scene>
<!--Map View-->
<scene sceneID="pGu-9T-qKp">
@@ -123,9 +387,9 @@
</view>
<toolbarItems/>
<navigationItem key="navigationItem" title="Map" id="Qgs-vF-MTh">
<barButtonItem key="rightBarButtonItem" title="List View" id="5K7-Fn-pYV">
<barButtonItem key="rightBarButtonItem" title="Menu" id="5K7-Fn-pYV">
<connections>
<segue destination="2zN-e5-x2c" kind="show" identifier="openListView" id="23K-gs-PXS"/>
<segue destination="Xem-jg-Xlm" kind="show" identifier="openMenu" id="Whl-9k-Yj2"/>
</connections>
</barButtonItem>
</navigationItem>
@@ -137,24 +401,24 @@
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="ZSI-bq-lES" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1137" y="-305"/>
<point key="canvasLocation" x="978" y="-227"/>
</scene>
<!--Detail View-->
<!--Location Detail View-->
<scene sceneID="LQ9-aX-3sA">
<objects>
<viewController title="Detail View" id="T4w-Nz-H9R" customClass="MapDetailViewController" customModule="pocloud" customModuleProvider="target" sceneMemberID="viewController">
<viewController title="Location Detail View" id="T4w-Nz-H9R" customClass="MapDetailViewController" customModule="pocloud" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="ecT-Qg-rFR">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="xug-gE-FQz">
<rect key="frame" x="0.0" y="109" width="375" height="200"/>
<rect key="frame" x="0.0" y="65" width="375" height="200"/>
<constraints>
<constraint firstAttribute="height" constant="200" id="tu9-2Y-yHN"/>
</constraints>
</mapView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="GatewayName" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="izu-lT-xWY">
<rect key="frame" x="8" y="64" width="359" height="45"/>
<rect key="frame" x="8" y="20" width="359" height="45"/>
<constraints>
<constraint firstAttribute="height" constant="45" id="jbO-lj-xVg"/>
</constraints>
@@ -163,7 +427,7 @@
<nil key="highlightedColor"/>
</label>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="tRH-fh-elp">
<rect key="frame" x="0.0" y="319" width="375" height="304"/>
<rect key="frame" x="0.0" y="275" width="375" height="392"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="dataViewCell" rowHeight="60" id="5Sz-TR-mVj" customClass="MapDetailDeviceCell" customModule="pocloud" customModuleProvider="target">
@@ -237,9 +501,9 @@
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Rio-1u-3O1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1984.8" y="126.38680659670166"/>
<point key="canvasLocation" x="2001" y="-325"/>
</scene>
<!--Title-->
<!--Device Detail-->
<scene sceneID="q7c-Eh-Thg">
<objects>
<tableViewController id="eOb-fR-aFg" customClass="DeviceDetailViewController" customModule="pocloud" customModuleProvider="target" sceneMemberID="viewController">
@@ -301,7 +565,7 @@
</connections>
</tableView>
<toolbarItems/>
<navigationItem key="navigationItem" title="Title" id="sUT-g4-ZVO"/>
<navigationItem key="navigationItem" title="Device Detail" id="sUT-g4-ZVO"/>
<nil key="simulatedBottomBarMetrics"/>
<refreshControl key="refreshControl" opaque="NO" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" id="4fv-Lb-C8k">
<rect key="frame" x="0.0" y="0.0" width="1000" height="1000"/>
@@ -313,7 +577,7 @@
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="AE9-Tt-eth" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2780" y="456.52173913043481"/>
<point key="canvasLocation" x="2001" y="532"/>
</scene>
<!--Channel Detail View Controller-->
<scene sceneID="fDD-ow-Xi3">
@@ -548,7 +812,7 @@
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="qLG-JD-OG3" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="3600.8000000000002" y="456.52173913043481"/>
<point key="canvasLocation" x="3004" y="531"/>
</scene>
<!--History Graph View Controller-->
<scene sceneID="WkV-VI-zTb">
@@ -606,7 +870,7 @@
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Add-tM-hJL" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="4352.8000000000002" y="456.52173913043481"/>
<point key="canvasLocation" x="3972" y="530"/>
</scene>
<!--POCloud Data-->
<scene sceneID="CNC-dV-jZs">
@@ -616,9 +880,14 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<searchBar key="tableHeaderView" contentMode="redraw" id="z2g-Ak-4Pp">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<textInputTraits key="textInputTraits"/>
</searchBar>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="deviceListCell" id="rJT-U8-JVI">
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
<rect key="frame" x="0.0" y="72" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="rJT-U8-JVI" id="f7t-a1-NDN">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
@@ -632,9 +901,9 @@
</connections>
</tableView>
<navigationItem key="navigationItem" title="POCloud Data" id="u6I-Ca-wA2">
<barButtonItem key="rightBarButtonItem" title="Map View" id="yA7-No-AKb">
<barButtonItem key="rightBarButtonItem" title="Menu" id="yA7-No-AKb">
<connections>
<segue destination="yV3-Bs-nOb" kind="show" identifier="openMapView" id="HF3-JU-BOm"/>
<segue destination="Xem-jg-Xlm" kind="show" identifier="openMenu" id="qTd-vu-ryN"/>
</connections>
</barButtonItem>
</navigationItem>
@@ -643,19 +912,20 @@
<autoresizingMask key="autoresizingMask"/>
</refreshControl>
<connections>
<outlet property="searchBar" destination="z2g-Ak-4Pp" id="XeB-mp-w39"/>
<segue destination="eOb-fR-aFg" kind="show" identifier="openDeviceDetailView" id="wUb-ND-zk7"/>
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="uhB-7k-gae" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1136.8" y="456.52173913043481"/>
<point key="canvasLocation" x="-212" y="84"/>
</scene>
<!--Navigation Controller-->
<!--Main Nav Controller-->
<scene sceneID="zCd-ds-i4W">
<objects>
<navigationController id="iJg-Zc-arO" customClass="NavigationController" customModule="pocloud" customModuleProvider="target" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="eWM-wh-jgG">
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
<navigationController id="iJg-Zc-arO" customClass="MainNavController" customModule="pocloud" customModuleProvider="target" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="eWM-wh-jgG">
<rect key="frame" x="0.0" y="20" width="375" height="96"/>
<autoresizingMask key="autoresizingMask"/>
<color key="barTintColor" red="0.90823972225189209" green="0.92638683319091797" blue="0.9317171573638916" alpha="1" colorSpace="calibratedRGB"/>
</navigationBar>
@@ -665,14 +935,16 @@
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="8gs-d8-KhR" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-774" y="128"/>
<point key="canvasLocation" x="-1713" y="85"/>
</scene>
</scenes>
<resources>
<image name="POCloud" width="2100" height="512"/>
</resources>
<inferredMetricsTieBreakers>
<segue reference="CI7-x2-asH"/>
<segue reference="9Om-lw-Jgn"/>
<segue reference="wUb-ND-zk7"/>
<segue reference="DQm-0d-brY"/>
<segue reference="LUR-lb-5qK"/>
</inferredMetricsTieBreakers>
</document>

View File

@@ -0,0 +1,45 @@
//
// PillUILabel.swift
// pocloud
//
// Created by Patrick McDonagh on 6/6/18.
// Copyright © 2018 patrickjmcd. All rights reserved.
//
import UIKit
@IBDesignable class PillUILabel : UILabel {
@IBInspectable var verticalPad: CGFloat = 0
@IBInspectable var horizontalPad: CGFloat = 0
func setup() {
layer.cornerRadius = frame.height / 2
clipsToBounds = true
textAlignment = .center
}
override func awakeFromNib() {
super.awakeFromNib()
setup()
}
override func layoutSubviews() {
super.layoutSubviews()
setup()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
setup()
}
override var intrinsicContentSize: CGSize {
let superSize = super.intrinsicContentSize
let newWidth = superSize.width + superSize.height + (2 * horizontalPad)
let newHeight = superSize.height + (2 * verticalPad)
let newSize = CGSize(width: newWidth, height: newHeight)
return newSize
}
}