// // DatabaseCollectionListViewController.swift // MongoView // // Created by Shadowfacts on 8/11/20. // Copyright © 2020 Shadowfacts. All rights reserved. // import Cocoa import NIO import Combine class DatabaseCollectionListViewController: NSViewController { @IBOutlet weak var outlineView: NSOutlineView! let mongoController: MongoController let selectedCollection = PassthroughSubject() private var databaseCollections: [DatabaseCollections] = [] init(mongoController: MongoController) { self.mongoController = mongoController super.init(nibName: "DatabaseCollectionListViewController", bundle: .main) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() mongoController.client.listDatabaseNames().flatMap { (databaseNames) -> EventLoopFuture<[DatabaseCollections]> in let futures = databaseNames.map { (name: String) -> EventLoopFuture in let db = self.mongoController.client.db(name) return db.listCollectionNames().map { (collectionNames: [String]) -> DatabaseCollections in let sortedNames = collectionNames.sorted() return DatabaseCollections(database: name, collections: sortedNames) } } return EventLoopFuture.whenAllSucceed(futures, on: futures.first!.eventLoop) }.whenComplete { [weak self] (res) in guard let self = self else { return } switch res { case let .success(databaseCollections): let sortedCollections = databaseCollections.sorted(by: { $0.database < $1.database }) self.databaseCollections = sortedCollections DispatchQueue.main.async { self.outlineView.reloadData() } case let .failure(error): fatalError("error getting database names: \(error)") } } outlineView.dataSource = self outlineView.delegate = self } @IBAction func outlineCellDoubleClicked(_ sender: Any) { let item = outlineView.item(atRow: outlineView.clickedRow)! if item is DatabaseCollections { if outlineView.isItemExpanded(item) { outlineView.collapseItem(item) } else { outlineView.expandItem(item) } } else if let collection = item as? DatabaseCollection { selectedCollection.send(collection) } } } extension DatabaseCollectionListViewController: NSOutlineViewDataSource { func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int { if item == nil { return databaseCollections.count } else if let database = item as? DatabaseCollections { return database.collections.count } else { return 0 } } func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool { return item is DatabaseCollections } func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any { if item == nil { return databaseCollections[index] } else if let databaseCollections = item as? DatabaseCollections { let collection = databaseCollections.collections[index] return DatabaseCollection(database: databaseCollections.database, name: collection) } else { fatalError() } } } extension DatabaseCollectionListViewController: NSOutlineViewDelegate { func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? { if let database = item as? DatabaseCollections { let cell = outlineView.makeView(withIdentifier: .databaseNameCell, owner: nil) as! NSTableCellView cell.textField!.stringValue = database.database cell.textField!.isEditable = false return cell } else if let collection = item as? DatabaseCollection { let cell = outlineView.makeView(withIdentifier: .collectionNameCell, owner: nil) as! NSTableCellView cell.textField!.stringValue = collection.name cell.textField!.isEditable = false return cell } else { fatalError() } } } extension NSUserInterfaceItemIdentifier { static let databaseNameCell = NSUserInterfaceItemIdentifier(rawValue: "DatabaseNameCell") static let collectionNameCell = NSUserInterfaceItemIdentifier(rawValue: "CollectionNameCell") }