Improve status messages
This commit is contained in:
parent
967a2518b4
commit
31962b43a3
|
@ -49,6 +49,7 @@
|
||||||
D6A7D096243541A400B46857 /* WindowStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A7D095243541A400B46857 /* WindowStatusView.swift */; };
|
D6A7D096243541A400B46857 /* WindowStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A7D095243541A400B46857 /* WindowStatusView.swift */; };
|
||||||
D6A7D09A243546B500B46857 /* WindowStatusView.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A7D099243546B500B46857 /* WindowStatusView.xib */; };
|
D6A7D09A243546B500B46857 /* WindowStatusView.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A7D099243546B500B46857 /* WindowStatusView.xib */; };
|
||||||
D6A7D0A42435885B00B46857 /* JavaScriptHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A7D0A32435885B00B46857 /* JavaScriptHighlighter.swift */; };
|
D6A7D0A42435885B00B46857 /* JavaScriptHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A7D0A32435885B00B46857 /* JavaScriptHighlighter.swift */; };
|
||||||
|
D6ABB01424B4DE7600F79DA8 /* StatusManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6ABB01324B4DE7600F79DA8 /* StatusManager.swift */; };
|
||||||
D6D13B042436C33D00493D97 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D13B032436C33D00493D97 /* main.swift */; };
|
D6D13B042436C33D00493D97 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D13B032436C33D00493D97 /* main.swift */; };
|
||||||
D6D13B082436C34200493D97 /* JavaScriptHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A7D0A32435885B00B46857 /* JavaScriptHighlighter.swift */; };
|
D6D13B082436C34200493D97 /* JavaScriptHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A7D0A32435885B00B46857 /* JavaScriptHighlighter.swift */; };
|
||||||
D6D4665323CB730C00F13B1B /* MongoEvaluator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D4665223CB730C00F13B1B /* MongoEvaluator.swift */; };
|
D6D4665323CB730C00F13B1B /* MongoEvaluator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D4665223CB730C00F13B1B /* MongoEvaluator.swift */; };
|
||||||
|
@ -122,6 +123,7 @@
|
||||||
D6A7D095243541A400B46857 /* WindowStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowStatusView.swift; sourceTree = "<group>"; };
|
D6A7D095243541A400B46857 /* WindowStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowStatusView.swift; sourceTree = "<group>"; };
|
||||||
D6A7D099243546B500B46857 /* WindowStatusView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = WindowStatusView.xib; sourceTree = "<group>"; };
|
D6A7D099243546B500B46857 /* WindowStatusView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = WindowStatusView.xib; sourceTree = "<group>"; };
|
||||||
D6A7D0A32435885B00B46857 /* JavaScriptHighlighter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JavaScriptHighlighter.swift; sourceTree = "<group>"; };
|
D6A7D0A32435885B00B46857 /* JavaScriptHighlighter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JavaScriptHighlighter.swift; sourceTree = "<group>"; };
|
||||||
|
D6ABB01324B4DE7600F79DA8 /* StatusManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusManager.swift; sourceTree = "<group>"; };
|
||||||
D6D13B012436C33D00493D97 /* jstest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jstest; sourceTree = BUILT_PRODUCTS_DIR; };
|
D6D13B012436C33D00493D97 /* jstest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jstest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
D6D13B032436C33D00493D97 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
D6D13B032436C33D00493D97 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
||||||
D6D4665223CB730C00F13B1B /* MongoEvaluator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MongoEvaluator.swift; sourceTree = "<group>"; };
|
D6D4665223CB730C00F13B1B /* MongoEvaluator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MongoEvaluator.swift; sourceTree = "<group>"; };
|
||||||
|
@ -216,6 +218,7 @@
|
||||||
children = (
|
children = (
|
||||||
D63CDEBD23C837DC0012D658 /* AppDelegate.swift */,
|
D63CDEBD23C837DC0012D658 /* AppDelegate.swift */,
|
||||||
D63CDF3423C838190012D658 /* MongoController.swift */,
|
D63CDF3423C838190012D658 /* MongoController.swift */,
|
||||||
|
D6ABB01324B4DE7600F79DA8 /* StatusManager.swift */,
|
||||||
D63CDF3323C838190012D658 /* Node.swift */,
|
D63CDF3323C838190012D658 /* Node.swift */,
|
||||||
D6D4665223CB730C00F13B1B /* MongoEvaluator.swift */,
|
D6D4665223CB730C00F13B1B /* MongoEvaluator.swift */,
|
||||||
D624090E243903E90020E09F /* ExtendedJSON.swift */,
|
D624090E243903E90020E09F /* ExtendedJSON.swift */,
|
||||||
|
@ -376,6 +379,7 @@
|
||||||
D6A7D096243541A400B46857 /* WindowStatusView.swift in Sources */,
|
D6A7D096243541A400B46857 /* WindowStatusView.swift in Sources */,
|
||||||
D626BF82243BD2EE0075117B /* EditDocumentWindowController.swift in Sources */,
|
D626BF82243BD2EE0075117B /* EditDocumentWindowController.swift in Sources */,
|
||||||
D6A7D0A42435885B00B46857 /* JavaScriptHighlighter.swift in Sources */,
|
D6A7D0A42435885B00B46857 /* JavaScriptHighlighter.swift in Sources */,
|
||||||
|
D6ABB01424B4DE7600F79DA8 /* StatusManager.swift in Sources */,
|
||||||
D62408C12438CF550020E09F /* JavaScriptEditorView.swift in Sources */,
|
D62408C12438CF550020E09F /* JavaScriptEditorView.swift in Sources */,
|
||||||
D63CDF4023C839010012D658 /* QueryViewController.swift in Sources */,
|
D63CDF4023C839010012D658 /* QueryViewController.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
@ -526,7 +530,7 @@
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 3;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
DEVELOPMENT_TEAM = V4WK9KR9U2;
|
DEVELOPMENT_TEAM = HGYVAQA9FW;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
INFOPLIST_FILE = MongoView/Info.plist;
|
INFOPLIST_FILE = MongoView/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
@ -548,7 +552,7 @@
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 3;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
DEVELOPMENT_TEAM = V4WK9KR9U2;
|
DEVELOPMENT_TEAM = HGYVAQA9FW;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
INFOPLIST_FILE = MongoView/Info.plist;
|
INFOPLIST_FILE = MongoView/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
|
|
@ -18,10 +18,17 @@ class MongoController {
|
||||||
|
|
||||||
var client: MongoClient!
|
var client: MongoClient!
|
||||||
|
|
||||||
@Published var status: ConnectionStatus = .connecting
|
@Published var statusManager = StatusManager()
|
||||||
|
@Published private(set) var status: ConnectionStatus {
|
||||||
|
didSet {
|
||||||
|
statusManager.set(messageFor(status: status), for: .connection)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
init(connectionString: String) {
|
init(connectionString: String) {
|
||||||
self.connectionString = connectionString
|
self.connectionString = connectionString
|
||||||
|
self.status = .connecting
|
||||||
|
self.statusManager.set(messageFor(status: .connecting), for: .connection)
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
@ -50,6 +57,17 @@ class MongoController {
|
||||||
func collection(_ collection: DatabaseCollection) -> MongoCollection<Document> {
|
func collection(_ collection: DatabaseCollection) -> MongoCollection<Document> {
|
||||||
return db(for: collection).collection(collection.name)
|
return db(for: collection).collection(collection.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func messageFor(status: ConnectionStatus) -> String {
|
||||||
|
switch status {
|
||||||
|
case .connecting:
|
||||||
|
return "Connecting..."
|
||||||
|
case .connected:
|
||||||
|
return "Connected to \(connectionString)"
|
||||||
|
case .failed:
|
||||||
|
return "Failed to connect"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
//
|
||||||
|
// StatusManager.swift
|
||||||
|
// MongoView
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 7/7/20.
|
||||||
|
// Copyright © 2020 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct StatusManager {
|
||||||
|
private(set) var statuses = [Category: Status]()
|
||||||
|
|
||||||
|
var mostRelevant: Status? {
|
||||||
|
for category in Category.sortedByPriority {
|
||||||
|
if let status = statuses[category] {
|
||||||
|
return status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func set(_ message: String, for category: Category, override: Bool = false) {
|
||||||
|
statuses[category] = Status(message: message, category: category)
|
||||||
|
|
||||||
|
if override {
|
||||||
|
for other in Category.allCases where other < category {
|
||||||
|
remove(for: other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func remove(for category: Category) {
|
||||||
|
statuses.removeValue(forKey: category)
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Category: Int, Comparable, CaseIterable {
|
||||||
|
case document
|
||||||
|
case query
|
||||||
|
case connection
|
||||||
|
|
||||||
|
static let sortedByPriority = allCases.sorted()
|
||||||
|
|
||||||
|
static func < (lhs: StatusManager.Category, rhs: StatusManager.Category) -> Bool {
|
||||||
|
return lhs.rawValue < rhs.rawValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Status {
|
||||||
|
let message: String
|
||||||
|
let category: Category
|
||||||
|
let timestamp = Date()
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,9 +15,13 @@ struct DatabaseCollections {
|
||||||
let collections: [String]
|
let collections: [String]
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DatabaseCollection {
|
struct DatabaseCollection: CustomStringConvertible {
|
||||||
let database: String
|
let database: String
|
||||||
let name: String
|
let name: String
|
||||||
|
|
||||||
|
var description: String {
|
||||||
|
return "\(database).\(name)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DatabaseViewController: NSViewController {
|
class DatabaseViewController: NSViewController {
|
||||||
|
|
|
@ -94,6 +94,8 @@ class QueryViewController: NSViewController {
|
||||||
if reload {
|
if reload {
|
||||||
outlineView.reloadData()
|
outlineView.reloadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mongoController.statusManager.set("Queried \(collection)", for: .query, override: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteRootNode(_ node: Node) {
|
func deleteRootNode(_ node: Node) {
|
||||||
|
@ -133,6 +135,7 @@ class QueryViewController: NSViewController {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.refresh()
|
self.refresh()
|
||||||
|
self.mongoController.statusManager.set("Deleted document", for: .document)
|
||||||
case let .failure(error):
|
case let .failure(error):
|
||||||
let alert = NSAlert(error: error)
|
let alert = NSAlert(error: error)
|
||||||
alert.beginSheetModal(for: self.view.window!, completionHandler: nil)
|
alert.beginSheetModal(for: self.view.window!, completionHandler: nil)
|
||||||
|
@ -171,6 +174,7 @@ class QueryViewController: NSViewController {
|
||||||
let wc = EditDocumentWindowController(mongoController: mongoController, collection: collection, document: document)
|
let wc = EditDocumentWindowController(mongoController: mongoController, collection: collection, document: document)
|
||||||
wc.documentEdited = {
|
wc.documentEdited = {
|
||||||
self.refresh()
|
self.refresh()
|
||||||
|
self.mongoController.statusManager.set("Updated document", for: .document)
|
||||||
}
|
}
|
||||||
wc.showWindow(nil)
|
wc.showWindow(nil)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ class WindowStatusView: NSView {
|
||||||
super.awakeFromNib()
|
super.awakeFromNib()
|
||||||
|
|
||||||
(button.cell as! NSButtonCell).imageDimsWhenDisabled = false
|
(button.cell as! NSButtonCell).imageDimsWhenDisabled = false
|
||||||
|
button.font = .monospacedDigitSystemFont(ofSize: 13, weight: .regular)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setText(_ text: String) {
|
func setText(_ text: String) {
|
||||||
|
|
|
@ -22,7 +22,8 @@ class DatabaseWindowController: NSWindowController {
|
||||||
|
|
||||||
private var databaseViewController: DatabaseViewController!
|
private var databaseViewController: DatabaseViewController!
|
||||||
|
|
||||||
private var statusDidChangeHandler: Cancellable?
|
private var statusChangeHandler: Cancellable?
|
||||||
|
private var connectionStatusChangeHandler: Cancellable?
|
||||||
|
|
||||||
convenience init() {
|
convenience init() {
|
||||||
self.init(windowNibName: "DatabaseWindowController")
|
self.init(windowNibName: "DatabaseWindowController")
|
||||||
|
@ -35,15 +36,16 @@ class DatabaseWindowController: NSWindowController {
|
||||||
if setupMongo {
|
if setupMongo {
|
||||||
mongoController = MongoController(connectionString: "mongodb://localhost:27017")
|
mongoController = MongoController(connectionString: "mongodb://localhost:27017")
|
||||||
}
|
}
|
||||||
statusDidChangeHandler = mongoController.$status
|
|
||||||
|
statusChangeHandler = mongoController.$statusManager
|
||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { (status) in
|
.sink { self.updateStatusText(manager: $0) }
|
||||||
self.updateStatusText(status)
|
|
||||||
|
connectionStatusChangeHandler = mongoController.$status
|
||||||
if status == .connected {
|
.receive(on: DispatchQueue.main)
|
||||||
self.initializeUI()
|
.filter { $0 == .connected }
|
||||||
}
|
.sink { (_) in self.initializeUI() }
|
||||||
}
|
|
||||||
if setupMongo {
|
if setupMongo {
|
||||||
mongoController.setup()
|
mongoController.setup()
|
||||||
}
|
}
|
||||||
|
@ -66,16 +68,23 @@ class DatabaseWindowController: NSWindowController {
|
||||||
window?.title = databaseViewController?.title ?? "MongoView"
|
window?.title = databaseViewController?.title ?? "MongoView"
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateStatusText(_ status: MongoController.ConnectionStatus) {
|
private func updateStatusText(manager: StatusManager) {
|
||||||
guard let statusView = self.statusView else { return }
|
guard let statusView = self.statusView,
|
||||||
switch status {
|
let mostRelevant = manager.mostRelevant else { return }
|
||||||
case .connecting:
|
|
||||||
statusView.setText("Connecting...")
|
let dayComparisonResult = Calendar.current.compare(mostRelevant.timestamp, to: Date(), toGranularity: .day)
|
||||||
case .failed:
|
|
||||||
statusView.setText("Failed to connect")
|
let formatter = DateFormatter()
|
||||||
case .connected:
|
if dayComparisonResult == .orderedSame {
|
||||||
statusView.setText("Connected to \(self.mongoController.connectionString)")
|
formatter.dateStyle = .none
|
||||||
|
} else {
|
||||||
|
formatter.dateStyle = .short
|
||||||
}
|
}
|
||||||
|
formatter.timeStyle = .medium
|
||||||
|
let timestamp = formatter.string(from: mostRelevant.timestamp)
|
||||||
|
|
||||||
|
let string = "\(mostRelevant.message) | \(timestamp)"
|
||||||
|
statusView.setText(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func initializeUI() {
|
private func initializeUI() {
|
||||||
|
|
Loading…
Reference in New Issue