StatusBar

This commit is contained in:
Gerrit Linnemann 2016-12-27 14:07:15 +01:00
parent d53936101d
commit d11c45633a
8 changed files with 186 additions and 17 deletions

View File

@ -10,11 +10,11 @@
ignoreCount = "0" ignoreCount = "0"
continueAfterRunningActions = "No" continueAfterRunningActions = "No"
filePath = "OTRS-Watch/OTRS.swift" filePath = "OTRS-Watch/OTRS.swift"
timestampString = "503499740.022029" timestampString = "504524069.32379"
startingColumnNumber = "9223372036854775807" startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807"
startingLineNumber = "45" startingLineNumber = "47"
endingLineNumber = "45" endingLineNumber = "47"
landmarkName = "reload(que:)" landmarkName = "reload(que:)"
landmarkType = "7"> landmarkType = "7">
<Locations> <Locations>
@ -58,11 +58,11 @@
ignoreCount = "0" ignoreCount = "0"
continueAfterRunningActions = "No" continueAfterRunningActions = "No"
filePath = "OTRS-Watch/OTRS.swift" filePath = "OTRS-Watch/OTRS.swift"
timestampString = "503499740.022029" timestampString = "504524069.32379"
startingColumnNumber = "9223372036854775807" startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807"
startingLineNumber = "32" startingLineNumber = "34"
endingLineNumber = "32" endingLineNumber = "34"
landmarkName = "OTRS" landmarkName = "OTRS"
landmarkType = "3"> landmarkType = "3">
</BreakpointContent> </BreakpointContent>

View File

@ -659,7 +659,7 @@
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="OTRS_Watch" customModuleProvider="target"/> <customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="OTRS_Watch" customModuleProvider="target"/>
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/> <customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="64" y="-69"/> <point key="canvasLocation" x="64" y="-191"/>
</scene> </scene>
<!--Window Controller--> <!--Window Controller-->
<scene sceneID="R2V-B0-nI4"> <scene sceneID="R2V-B0-nI4">
@ -685,16 +685,60 @@
<action selector="toolbarActionSettings:" target="B8D-0N-5wS" id="3Qw-ua-kEb"/> <action selector="toolbarActionSettings:" target="B8D-0N-5wS" id="3Qw-ua-kEb"/>
</connections> </connections>
</toolbarItem> </toolbarItem>
<toolbarItem implicitItemIdentifier="E66207FF-6D83-45B2-9DF1-41DAE0971659" label="" paletteLabel="Aktivität" tag="-1" id="Dk2-xs-uLF" userLabel="StatusToolbarItem">
<nil key="toolTip"/>
<size key="minSize" width="163" height="32"/>
<size key="maxSize" width="354" height="96"/>
<customView key="view" id="INh-1k-hv0" userLabel="StatusBarView">
<rect key="frame" x="0.0" y="14" width="354" height="48"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<box fixedFrame="YES" boxType="custom" cornerRadius="4" title="StatusToolbarItemBackground" translatesAutoresizingMaskIntoConstraints="NO" id="izA-gq-Y9P">
<rect key="frame" x="0.0" y="20" width="354" height="28"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<view key="contentView" ambiguous="YES" id="uQ3-g4-Ra4">
<rect key="frame" x="1" y="1" width="352" height="26"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3vj-XJ-zzB">
<rect key="frame" x="4" y="5" width="269" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="???" id="drP-yc-DpB">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ebY-1F-cqh" userLabel="TicketCount">
<rect key="frame" x="303" y="5" width="43" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="inline" title="0" bezelStyle="inline" alignment="center" borderStyle="border" inset="2" id="cnt-Fr-Hil">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="smallSystemBold"/>
</buttonCell>
</button>
</subviews>
</view>
<color key="borderColor" name="controlShadowColor" catalog="System" colorSpace="catalog"/>
<color key="fillColor" name="windowBackgroundColor" catalog="System" colorSpace="catalog"/>
</box>
</subviews>
</customView>
</toolbarItem>
</allowedToolbarItems> </allowedToolbarItems>
<defaultToolbarItems> <defaultToolbarItems>
<toolbarItem reference="eMt-Dh-Yhp"/> <toolbarItem reference="eMt-Dh-Yhp"/>
<toolbarItem reference="31c-eE-1XB"/> <toolbarItem reference="31c-eE-1XB"/>
<toolbarItem reference="rDU-kC-B36"/> <toolbarItem reference="rDU-kC-B36"/>
<toolbarItem reference="Dk2-xs-uLF"/>
<toolbarItem reference="rDU-kC-B36"/>
<toolbarItem reference="GwS-Vr-90W"/> <toolbarItem reference="GwS-Vr-90W"/>
</defaultToolbarItems> </defaultToolbarItems>
</toolbar> </toolbar>
</window> </window>
<connections> <connections>
<outlet property="activity" destination="3vj-XJ-zzB" id="Djl-5B-UkD"/>
<outlet property="ticketCount" destination="ebY-1F-cqh" id="hhI-UN-aPV"/>
<segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/> <segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/>
</connections> </connections>
</windowController> </windowController>

View File

@ -36,6 +36,11 @@ struct Constants {
} }
static let IN = "nf::ticket::in" static let IN = "nf::ticket::in"
struct ACTION {
static let CONNECTED = "nf::ticket::action::connected"
static let ERROR = "nf::ticket::action::error"
}
} }
} }

View File

@ -65,7 +65,7 @@ extension ViewController: NSTableViewDataSource, NSTableViewDelegate {
let myTableViewFromNotification = notification.object as! NSTableView let myTableViewFromNotification = notification.object as! NSTableView
let ticket = OTRS.sharedInstance.ticketDictionary[row] as! Ticket let ticket = OTRS.sharedInstance.ticketDictionary[row] as! Ticket
print("Ticket ausgewählt: \(ticket.title)") print("🖥 Ticket ausgewählt: \(ticket.title)")
self.ticketDetailsBox.title = "Ticket#\(ticket.ticketNumber)" self.ticketDetailsBox.title = "Ticket#\(ticket.ticketNumber)"
self.txtTicketTitle.stringValue = ticket.title self.txtTicketTitle.stringValue = ticket.title

View File

@ -6,7 +6,9 @@
// Copyright © 2016 Adawim UG (haftungsbeschränkt). All rights reserved. // Copyright © 2016 Adawim UG (haftungsbeschränkt). All rights reserved.
// //
// //
// http://saeotrs01.sae.intra/otrs/nph-genericinterface.pl/Webservice/GenericTicketConnectorREST/
// http://otrs.github.io/doc/manual/admin/stable/en/html/genericinterface.html // http://otrs.github.io/doc/manual/admin/stable/en/html/genericinterface.html
// https://developer.apple.com/swift/blog/?id=37
// //
import Foundation import Foundation
@ -40,7 +42,7 @@ class OTRS {
//MARK: REST //MARK: REST
func reload(que:Int) { func reload(que:Int) {
let nc = NotificationCenter.default
let config = URLSessionConfiguration.default // Session configuration let config = URLSessionConfiguration.default // Session configuration
let session = URLSession(configuration: config) // Load configuration into session let session = URLSession(configuration: config) // Load configuration into session
let urlNew = URL(string: buildURLForGettingNew(queID: que)) let urlNew = URL(string: buildURLForGettingNew(queID: que))
@ -48,27 +50,35 @@ class OTRS {
self.ticketDictionary.removeAll() self.ticketDictionary.removeAll()
nc.post(name:Notification.Name(rawValue:Constants.NOTIFICATION.TICKET.ACTION.CONNECTED),
object: nil,
userInfo: ["message":""])
reloadByURL(session: session, url: urlNew!) reloadByURL(session: session, url: urlNew!)
reloadByURL(session: session, url: urlOpen!) reloadByURL(session: session, url: urlOpen!)
} }
private func reloadByURL(session:URLSession, url:URL) { private func reloadByURL(session:URLSession, url:URL) {
let nc = NotificationCenter.default
let task = session.dataTask(with: url, completionHandler: { let task = session.dataTask(with: url, completionHandler: {
(data, response, error) in (data, response, error) in
if error != nil { if error != nil {
print(error!.localizedDescription) print(error!.localizedDescription)
nc.post(name:Notification.Name(rawValue:Constants.NOTIFICATION.TICKET.ACTION.ERROR),
object: nil,
userInfo: ["message":error!.localizedDescription])
} else { } else {
do { do {
if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] { if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] {
// work with json ... // work with json ...
//print(json)
var cnt = 0; var cnt = 0;
for object in json { for object in json {
let ticketIDs = object.value as! Array<String> let ticketIDs = object.value as! Array<String>
print(ticketIDs) print("📑 Going to load: \(ticketIDs)")
for ticketID in ticketIDs { for ticketID in ticketIDs {
cnt += 1; cnt += 1;
@ -81,7 +91,10 @@ class OTRS {
} }
} }
} catch { } catch {
print("Error in JSONSerialization") print("📑 Error in JSONSerialization")
nc.post(name:Notification.Name(rawValue:Constants.NOTIFICATION.TICKET.ACTION.ERROR),
object: nil,
userInfo: ["message":"Fehler beim Auslesesen der übertragenen Daten."])
} }
} }
}) })
@ -91,18 +104,21 @@ class OTRS {
func fetch(ticket:Int, session:URLSession, isLast:Bool) { func fetch(ticket:Int, session:URLSession, isLast:Bool) {
let url = URL(string: buildURLForGettingTicketInfo(ticketID: ticket)) let url = URL(string: buildURLForGettingTicketInfo(ticketID: ticket))
let nc = NotificationCenter.default
let task = session.dataTask(with: url!, completionHandler: { // see: https://developer.apple.com/swift/blog/?id=37 let task = session.dataTask(with: url!, completionHandler: { // see: https://developer.apple.com/swift/blog/?id=37
(data, response, error) in (data, response, error) in
if error != nil { if error != nil {
print(error!.localizedDescription) print(error!.localizedDescription)
nc.post(name:Notification.Name(rawValue:Constants.NOTIFICATION.TICKET.ACTION.ERROR),
object: nil,
userInfo: ["message":error!.localizedDescription])
} else { } else {
do { do {
let dictionary = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String : AnyObject] let dictionary = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String : AnyObject]
let ticketData : Dictionary = dictionary["Ticket"]?.firstObject as! [String : AnyObject] let ticketData : Dictionary = dictionary["Ticket"]?.firstObject as! [String : AnyObject]
let ticket = try Ticket(source: ticketData) let ticket = try Ticket(source: ticketData)
//print(ticket)
self.ticketDictionary.append(ticket) self.ticketDictionary.append(ticket)
@ -119,9 +135,15 @@ class OTRS {
} }
} catch SerializationError.missing(let marker) { } catch SerializationError.missing(let marker) {
print("Error in JSONSerialization for ticket #\(ticket) at \"\(marker)\"") print("📑 Error in JSONSerialization for ticket #\(ticket) at \"\(marker)\"")
nc.post(name:Notification.Name(rawValue:Constants.NOTIFICATION.TICKET.ACTION.ERROR),
object: nil,
userInfo: ["message":"Fehler beim Auslesesen der übertragenen Daten zu Ticket #\(ticket)"])
} catch { } catch {
print("Error in JSONSerialization for ticket #\(ticket): \(error)") print("📑 Error in JSONSerialization for ticket #\(ticket): \(error)")
nc.post(name:Notification.Name(rawValue:Constants.NOTIFICATION.TICKET.ACTION.ERROR),
object: nil,
userInfo: ["message":"Fehler beim Auslesesen der übertragenen Daten zu Ticket #\(ticket)"])
} }
} }
}) })

View File

@ -100,7 +100,7 @@ class ViewController: NSViewController {
guard let userInfo = notification.userInfo, guard let userInfo = notification.userInfo,
let _:String = userInfo["message"] as? String, let _:String = userInfo["message"] as? String,
let _:Ticket = userInfo["ticket"] as? Ticket else { let t:Ticket = userInfo["ticket"] as? Ticket else {
return return
} }
@ -111,10 +111,12 @@ class ViewController: NSViewController {
DispatchQueue.main.async { DispatchQueue.main.async {
self.ticketTableView.reloadData() self.ticketTableView.reloadData()
} }
print("🖥 Ticket to show: \(t.id)")
} }
func catchTicketsUpdated(notification:Notification) -> Void { func catchTicketsUpdated(notification:Notification) -> Void {
print("\(OTRS.sharedInstance.ticketDictionary.count) tickets to be shown") print("🖥 \(OTRS.sharedInstance.ticketDictionary.count) tickets to be shown")
} }
} }

View File

@ -10,6 +10,10 @@ import Cocoa
class WindowController: NSWindowController { class WindowController: NSWindowController {
@IBOutlet weak var ticketCount: NSButton!
@IBOutlet weak var activity: NSTextField!
var viewController: ViewController { var viewController: ViewController {
get { get {
return self.window!.contentViewController! as! ViewController return self.window!.contentViewController! as! ViewController
@ -20,6 +24,22 @@ class WindowController: NSWindowController {
super.windowDidLoad() super.windowDidLoad()
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
self.activity.stringValue = ""
let nc = NotificationCenter.default
nc.addObserver(forName:Notification.Name(rawValue:Constants.NOTIFICATION.TICKET.ACTION.CONNECTED),
object:nil, queue:nil,
using:catchConnected)
nc.addObserver(forName:Notification.Name(rawValue:Constants.NOTIFICATION.TICKET.IN),
object:nil, queue:nil,
using:catchLoading)
nc.addObserver(forName:Notification.Name(rawValue:Constants.NOTIFICATION.TICKET.LIST.UPDATED),
object:nil, queue:nil,
using:catchUpdateFinished)
nc.addObserver(forName:Notification.Name(rawValue:Constants.NOTIFICATION.TICKET.ACTION.ERROR),
object:nil, queue:nil,
using:catchError)
} }
@IBAction func toolbarActionReload(_ sender: NSToolbarItem) { @IBAction func toolbarActionReload(_ sender: NSToolbarItem) {
@ -33,5 +53,81 @@ class WindowController: NSWindowController {
@IBAction func toolbarActionSettings(_ sender: NSToolbarItem) { @IBAction func toolbarActionSettings(_ sender: NSToolbarItem) {
self.viewController.tabView.selectTabViewItem(at: Constants.TABS.TAB.SETTINGS) self.viewController.tabView.selectTabViewItem(at: Constants.TABS.TAB.SETTINGS)
} }
// MARK: Notification
func catchConnected(notification:Notification) -> Void {
guard let userInfo = notification.userInfo else {
return
}
DispatchQueue.main.async(execute: {
guard let message:String = userInfo["message"] as? String else {
return
}
self.activity.stringValue = "Verbindungsaufbau ..."
})
debugStatusBarContent()
}
func catchLoading(notification:Notification) -> Void {
guard let userInfo = notification.userInfo else {
return
}
DispatchQueue.main.async(execute: {
if let ticketID:String = userInfo["message"] as? String {
self.activity.stringValue = "Ticket #\(ticketID) geladen."
}
})
debugStatusBarContent()
}
func catchUpdateFinished(notification:Notification) -> Void {
DispatchQueue.main.async(execute: {
self.activity.stringValue = ""
})
guard let userInfo = notification.userInfo else {
return
}
DispatchQueue.main.async(execute: {
if let ticketCount:Int = userInfo["count"] as? Int {
self.ticketCount.title = "\(ticketCount)"
}
})
debugStatusBarContent()
}
func catchError(notification:Notification) -> Void {
DispatchQueue.main.async(execute: {
self.activity.stringValue = "Fehler bei der Verarbeitung!"
})
guard let userInfo = notification.userInfo else {
return
}
DispatchQueue.main.async(execute: {
if let message:String = userInfo["message"] as? String {
self.activity.stringValue = "\(message)"
}
})
debugStatusBarContent()
}
// MARK: Functions
private func debugStatusBarContent() {
if self.activity.stringValue != "" {
print("🖨 \(self.activity.stringValue)")
}
}
} }