diff --git a/MongoView.xcodeproj/project.pbxproj b/MongoView.xcodeproj/project.pbxproj index 40e04a7..a6ac141 100644 --- a/MongoView.xcodeproj/project.pbxproj +++ b/MongoView.xcodeproj/project.pbxproj @@ -13,6 +13,10 @@ D60C864023CA2E2100C9DB8E /* ServerConnectViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D60C863E23CA2E2100C9DB8E /* ServerConnectViewController.xib */; }; D62408C12438CF550020E09F /* JavaScriptEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62408C02438CF550020E09F /* JavaScriptEditorView.swift */; }; D624090F243903E90020E09F /* ExtendedJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = D624090E243903E90020E09F /* ExtendedJSON.swift */; }; + D626BF82243BD2EE0075117B /* EditDocumentWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D626BF80243BD2EE0075117B /* EditDocumentWindowController.swift */; }; + D626BF83243BD2EE0075117B /* EditDocumentWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D626BF81243BD2EE0075117B /* EditDocumentWindowController.xib */; }; + D626BF86243BE19A0075117B /* EditDocumentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D626BF84243BE19A0075117B /* EditDocumentViewController.swift */; }; + D626BF87243BE19A0075117B /* EditDocumentViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D626BF85243BE19A0075117B /* EditDocumentViewController.xib */; }; D63CDEBE23C837DC0012D658 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63CDEBD23C837DC0012D658 /* AppDelegate.swift */; }; D63CDEC023C837DD0012D658 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D63CDEBF23C837DD0012D658 /* Assets.xcassets */; }; D63CDEC323C837DD0012D658 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D63CDEC123C837DD0012D658 /* MainMenu.xib */; }; @@ -88,6 +92,10 @@ D60C863E23CA2E2100C9DB8E /* ServerConnectViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ServerConnectViewController.xib; sourceTree = ""; }; D62408C02438CF550020E09F /* JavaScriptEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JavaScriptEditorView.swift; sourceTree = ""; }; D624090E243903E90020E09F /* ExtendedJSON.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtendedJSON.swift; sourceTree = ""; }; + D626BF80243BD2EE0075117B /* EditDocumentWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditDocumentWindowController.swift; sourceTree = ""; }; + D626BF81243BD2EE0075117B /* EditDocumentWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = EditDocumentWindowController.xib; sourceTree = ""; }; + D626BF84243BE19A0075117B /* EditDocumentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditDocumentViewController.swift; sourceTree = ""; }; + D626BF85243BE19A0075117B /* EditDocumentViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = EditDocumentViewController.xib; sourceTree = ""; }; D63CDEBA23C837DC0012D658 /* MongoView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MongoView.app; sourceTree = BUILT_PRODUCTS_DIR; }; D63CDEBD23C837DC0012D658 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; D63CDEBF23C837DD0012D658 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -153,6 +161,8 @@ D60C863823CA2DD100C9DB8E /* ServerConnectWindowController.xib */, D63CDF3A23C838470012D658 /* DatabaseWindowController.swift */, D63CDF3B23C838470012D658 /* DatabaseWindowController.xib */, + D626BF80243BD2EE0075117B /* EditDocumentWindowController.swift */, + D626BF81243BD2EE0075117B /* EditDocumentWindowController.xib */, ); path = Windows; sourceTree = ""; @@ -166,6 +176,8 @@ D63CDF4323C970C50012D658 /* DatabaseViewController.xib */, D63CDF3E23C839010012D658 /* QueryViewController.swift */, D63CDF3F23C839010012D658 /* QueryViewController.xib */, + D626BF84243BE19A0075117B /* EditDocumentViewController.swift */, + D626BF85243BE19A0075117B /* EditDocumentViewController.xib */, ); path = "View Controllers"; sourceTree = ""; @@ -334,10 +346,12 @@ D60C864023CA2E2100C9DB8E /* ServerConnectViewController.xib in Resources */, D63CDEC023C837DD0012D658 /* Assets.xcassets in Resources */, D60C863A23CA2DD100C9DB8E /* ServerConnectWindowController.xib in Resources */, + D626BF87243BE19A0075117B /* EditDocumentViewController.xib in Resources */, D63CDF4523C970C50012D658 /* DatabaseViewController.xib in Resources */, D6A7D09A243546B500B46857 /* WindowStatusView.xib in Resources */, D63CDF3D23C838470012D658 /* DatabaseWindowController.xib in Resources */, D63CDEC323C837DD0012D658 /* MainMenu.xib in Resources */, + D626BF83243BD2EE0075117B /* EditDocumentWindowController.xib in Resources */, D63CDF4123C839010012D658 /* QueryViewController.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -355,10 +369,12 @@ D63CDF3823C8381A0012D658 /* MongoController.swift in Sources */, D60C863923CA2DD100C9DB8E /* ServerConnectWindowController.swift in Sources */, D63CDF3723C8381A0012D658 /* Node.swift in Sources */, + D626BF86243BE19A0075117B /* EditDocumentViewController.swift in Sources */, D60C863F23CA2E2100C9DB8E /* ServerConnectViewController.swift in Sources */, D63CDF4423C970C50012D658 /* DatabaseViewController.swift in Sources */, D63CDF3C23C838470012D658 /* DatabaseWindowController.swift in Sources */, D6A7D096243541A400B46857 /* WindowStatusView.swift in Sources */, + D626BF82243BD2EE0075117B /* EditDocumentWindowController.swift in Sources */, D6A7D0A42435885B00B46857 /* JavaScriptHighlighter.swift in Sources */, D62408C12438CF550020E09F /* JavaScriptEditorView.swift in Sources */, D63CDF4023C839010012D658 /* QueryViewController.swift in Sources */, diff --git a/MongoView/ExtendedJSON.swift b/MongoView/ExtendedJSON.swift index 7a3092a..4fbb034 100644 --- a/MongoView/ExtendedJSON.swift +++ b/MongoView/ExtendedJSON.swift @@ -8,6 +8,7 @@ import Foundation import JavaScriptCore +import MongoSwift struct ExtendedJSON { private init() {} @@ -25,4 +26,27 @@ struct ExtendedJSON { return context.evaluateScript("JSON.stringify(\(string))")?.toString() } + private static func fromExtJSON(_ string: String) -> Document? { + do { + let doc = try Document(fromJSON: string) + return doc + } catch { + print("Unable to create document from extended JSON: \(error)") + return nil + } + } + + static func toDocument(_ string: String) -> Document? { + guard let normalized = normalize(string), + let doc = fromExtJSON(normalized) else { + return nil + } + return doc + } + + static func prettify(_ string: String) -> String? { + let command = "JSON.stringify(JSON.parse(`\(string)`), null, 4)" + return context.evaluateScript(command)?.toString() + } + } diff --git a/MongoView/View Controllers/EditDocumentViewController.swift b/MongoView/View Controllers/EditDocumentViewController.swift new file mode 100644 index 0000000..1853a87 --- /dev/null +++ b/MongoView/View Controllers/EditDocumentViewController.swift @@ -0,0 +1,70 @@ +// +// EditDocumentViewController.swift +// MongoView +// +// Created by Shadowfacts on 4/6/20. +// Copyright © 2020 Shadowfacts. All rights reserved. +// + +import Cocoa +import MongoSwift + +class EditDocumentViewController: NSViewController { + + private(set) var mongoController: MongoController! + private(set) var collection: DatabaseCollection! + private(set) var document: Document! + + var documentEdited: (() -> Void)? + + @IBOutlet var editorTextView: JavaScriptEditorView! + @IBOutlet weak var saveButton: NSButton! + @IBOutlet weak var cancelButton: NSButton! + @IBOutlet weak var validateButton: NSButton! + + init(mongoController: MongoController, collection: DatabaseCollection, document: Document) { + self.mongoController = mongoController + self.collection = collection + self.document = document + + super.init(nibName: "EditDocumentViewController", bundle: .main) + } + + required init?(coder: NSCoder) { + fatalError() + } + + override func viewDidLoad() { + super.viewDidLoad() + + editorTextView.string = ExtendedJSON.prettify(document.extendedJSON) ?? document.extendedJSON + editorTextView.isAutomaticQuoteSubstitutionEnabled = false + } + + @IBAction func savePressed(_ sender: Any) { + guard let id = document["_id"], + let newDoc = ExtendedJSON.toDocument(editorTextView.string) else { + // todo: error + return + } + let collection = mongoController.collection(self.collection) + collection.replaceOne(filter: ["_id": id], replacement: newDoc).whenComplete { (result) in + DispatchQueue.main.async { + switch result { + case .success(_): + self.documentEdited?() + case let .failure(error): + print("Unable to replace document: \(error)") + } + self.view.window!.close() + } + } + } + + @IBAction func cancelPressed(_ sender: Any) { + view.window!.close() + } + + @IBAction func validatePressed(_ sender: Any) { + } +} diff --git a/MongoView/View Controllers/EditDocumentViewController.xib b/MongoView/View Controllers/EditDocumentViewController.xib new file mode 100644 index 0000000..72e2843 --- /dev/null +++ b/MongoView/View Controllers/EditDocumentViewController.xib @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MongoView/View Controllers/QueryViewController.swift b/MongoView/View Controllers/QueryViewController.swift index db84dcb..86c9d04 100644 --- a/MongoView/View Controllers/QueryViewController.swift +++ b/MongoView/View Controllers/QueryViewController.swift @@ -79,8 +79,7 @@ class QueryViewController: NSViewController { let filterText = filterTextView.string.trimmingCharacters(in: .whitespacesAndNewlines) let filter: Document if !filterText.isEmpty, - let normalized = ExtendedJSON.normalize(filterText), - let doc = try? Document(fromJSON: normalized) { + let doc = ExtendedJSON.toDocument(filterText) { filter = doc } else { filter = [:] @@ -162,11 +161,24 @@ class QueryViewController: NSViewController { } } + @IBAction func editDocument(_ sender: Any) { + guard let node = outlineView.item(atRow: outlineView.clickedRow) as? Node, + node.parent == nil, + case let .document(document) = node.value else { + return + } + + let wc = EditDocumentWindowController(mongoController: mongoController, collection: collection, document: document) + wc.documentEdited = { + self.refresh() + } + wc.showWindow(nil) + } } extension QueryViewController: NSMenuItemValidation { func validateMenuItem(_ menuItem: NSMenuItem) -> Bool { - if menuItem.action == #selector(deleteNode(_:)) { + if menuItem.action == #selector(deleteNode(_:)) || menuItem.action == #selector(editDocument(_:)) { if outlineView.clickedRow != -1, let node = outlineView.item(atRow: outlineView.clickedRow) as? Node, node.parent == nil { return true } else { diff --git a/MongoView/View Controllers/QueryViewController.xib b/MongoView/View Controllers/QueryViewController.xib index d464264..28b4b11 100644 --- a/MongoView/View Controllers/QueryViewController.xib +++ b/MongoView/View Controllers/QueryViewController.xib @@ -1139,6 +1139,12 @@ + + + + + + diff --git a/MongoView/Windows/EditDocumentWindowController.swift b/MongoView/Windows/EditDocumentWindowController.swift new file mode 100644 index 0000000..06da4d5 --- /dev/null +++ b/MongoView/Windows/EditDocumentWindowController.swift @@ -0,0 +1,38 @@ +// +// EditDocumentWindowController.swift +// MongoView +// +// Created by Shadowfacts on 4/6/20. +// Copyright © 2020 Shadowfacts. All rights reserved. +// + +import Cocoa +import MongoSwift + +class EditDocumentWindowController: NSWindowController { + + private(set) var mongoController: MongoController! + private(set) var collection: DatabaseCollection! + private(set) var mongoDocument: Document! + + var documentEdited: (() -> Void)? + + convenience init(mongoController: MongoController, collection: DatabaseCollection, document: Document) { + self.init(windowNibName: "EditDocumentWindowController") + + self.mongoController = mongoController + self.collection = collection + self.mongoDocument = document + } + + override func windowDidLoad() { + super.windowDidLoad() + + window!.title = "Edit \(collection.database).\(collection.name) Document" + + let vc = EditDocumentViewController(mongoController: mongoController, collection: collection, document: mongoDocument) + vc.documentEdited = documentEdited + contentViewController = vc + } + +} diff --git a/MongoView/Windows/EditDocumentWindowController.xib b/MongoView/Windows/EditDocumentWindowController.xib new file mode 100644 index 0000000..7f6a5ea --- /dev/null +++ b/MongoView/Windows/EditDocumentWindowController.xib @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +