Commit 537eca54 authored by Chaitanya Pandit's avatar Chaitanya Pandit Committed by Amirjanyan
Browse files

Render cvu storeddefinition

parent a44dd1a8
......@@ -3215,7 +3215,28 @@
"_type":"CVUStoredDefinition",
"id":202106162000,
"definition":"auth-view"
},
{
"_type":"Plugin",
"name":"Demo CVU",
"container":"cvu",
"icon":"doc",
"itemDescription":"Render CVU from Stored Definition",
"allEdges":[
{
"_type":"view",
"targetType":"CVUStoredDefinition",
"id":202108041600
}
]
},
{
"_type":"CVUStoredDefinition",
"id":202108041600,
"definition": "* {\n title: \"TEST CVU\"\n defaultRenderer: custom\n showContextualBottomBar: false\n showBottomBar: false\n showDefaultLayout: false\n\n [renderer = custom] {\n HStack {\n Text {\n text: \"Demo View Rendered from CVUStoredDefinition\"\n font: 16 semibold\n color: #000\n padding: 5 8 5 8\n }\n }\n }\n}\n"
},
{
"_type": "Post",
"message": "OMG. I love @TheSuffers so much! When I need some inspiration I just listen. https://www.youtube.com/watch?v=RM3hj-6F1pk",
......
......@@ -3132,6 +3132,12 @@
"target_type": "Location"
},
{
"source_type": "Plugin",
"edge": "view",
"target_type": "CVUStoredDefinition"
},
{
"source_type": "Product",
"edge": "material",
......
......@@ -21,6 +21,10 @@ class CVUController {
static func parseCVU() throws -> [CVUParsedDefinition] {
let string = CVUController.readCVUString()
return try parseCVU(string: string)
}
static func parseCVU(string: String) throws -> [CVUParsedDefinition] {
let lexer = CVULexer(input: string)
let tokens = try lexer.tokenize()
let parser = CVUParser(tokens)
......
......@@ -417,7 +417,14 @@ struct CVUAction_StartPlugin: CVUAction {
try startPluginItem.setPropertyValue(name: "container", value: .string(container))
try startPluginItem.setPropertyValue(name: "state", value: .string("idle"))
PluginHandler.start(plugin: plugin, runner: startPluginItem, sceneController: sceneController, context: context)
// This is test code to render cvu for a plugin locally without connecting to pod
// Ideally plugins will contain more detailed container name
// We can remove this once plugins are able to send CVUs in stored definition
if (container == "cvu") {
PluginHandler.presentCVUforPlugin(plugin: plugin, runner: startPluginItem, sceneController: sceneController, context: context)
} else {
PluginHandler.start(plugin: plugin, runner: startPluginItem, sceneController: sceneController, context: context)
}
} catch let error {
print("Error starting plugin: ", error)
}
......
......@@ -311,3 +311,74 @@ enum DatabaseQueryCondition: Codable, Equatable {
}
}
}
extension DatabaseQueryConfig {
static func queryConfigWith(context: CVUContext,
datasource: CVUParsedDefinition? = nil,
inheritQuery: DatabaseQueryConfig? = nil,
overrideUIDs: Set<Int64>? = nil,
targetItem: ItemRecord? = nil,
dateRange: DateInterval? = nil) -> DatabaseQueryConfig {
let datasourceResolver = datasource?.parsed.propertyResolver(context: context, lookup: CVULookupController(), db: AppController.shared.databaseController)
let uidList = overrideUIDs ?? datasourceResolver.map {
Set($0.intArray("uids").map { Int64($0) })
}
let filterDef = datasourceResolver?.subdefinition("filter")
let edgeTargets = filterDef?.subdefinition("edgeTargets")
let edgeTargetConditions = edgeTargets?.properties.keys.compactMap { key -> DatabaseQueryCondition? in
guard let target = edgeTargets?.int(key) else { return nil }
return .edgeHasTarget(DatabaseQueryCondition.EdgeHasTarget(edgeName: key, target: Int64(target)))
} ?? []
let edgeSources = filterDef?.subdefinition("edgeSources")
let edgeSourceConditions = edgeSources?.properties.keys.compactMap { key -> DatabaseQueryCondition? in
guard let source = edgeSources?.int(key) else { return nil }
return .edgeHasSource(DatabaseQueryCondition.EdgeHasSource(edgeName: key, source: Int64(source)))
} ?? []
let properties = filterDef?.subdefinition("properties")
let propertyConditions = properties?.properties.keys.compactMap { key -> DatabaseQueryCondition? in
if let value = properties?.bool(key) {
return .propertyEquals(DatabaseQueryCondition.PropertyEquals(name: key, value: .bool(value)))
} else if let value = properties?.string(key) {
return .propertyEquals(DatabaseQueryCondition.PropertyEquals(name: key, value: .string(value)))
}
return nil
} ?? []
var queryConfig = inheritQuery ?? DatabaseQueryConfig()
if let itemTypes = datasourceResolver?.stringArray("query") ?? targetItem.map({ [$0.type] }) {
queryConfig.itemTypes = itemTypes
}
if let itemUIDs = uidList {
queryConfig.itemIDs = itemUIDs
}
if case let .constant(.string(edgeTargetsOperator)) = datasourceResolver?.properties["edgeTargetsOperator"] {
queryConfig.edgeTargetsOperator = edgeTargetsOperator == ConditionOperator.or.rawValue ? .or : .and
}
if let sortProperty = datasourceResolver?.string("sortProperty") {
queryConfig.sortProperty = sortProperty
}
if let sortAscending = datasourceResolver?.bool("sortAscending") {
queryConfig.sortAscending = sortAscending
}
if let dateModifiedRange = dateRange {
queryConfig.dateModifiedAfter = dateModifiedRange.start
queryConfig.dateModifiedBefore = dateModifiedRange.end
}
if !edgeTargetConditions.isEmpty || !edgeSourceConditions.isEmpty || !propertyConditions.isEmpty {
queryConfig.conditions = edgeTargetConditions + edgeSourceConditions + propertyConditions
}
if let count = datasourceResolver?.int("count") {
queryConfig.count = count
}
return queryConfig
}
}
......@@ -25,7 +25,8 @@ class PluginHandler {
static func presentCVUforPlugin(plugin: ItemRecord, runner: ItemRecord, sceneController: SceneController, context: CVUContext) {
guard let runnerRowId = runner.rowId,
let view = plugin.edgeItem("view"),
case let .string(viewName) = view.propertyValue("definition") else {
case let .string(cvuContent) = view.propertyValue("definition"),
let cvuDefinition = try? CVUController.parseCVU(string: cvuContent).first?.parsed else {
AppController.shared.pubsubController.stopObservingItemProperty(runner, property: "state")
return
}
......@@ -41,9 +42,6 @@ class PluginHandler {
edge.syncState = .skip // Don't sync it yet
try? edge.save()
var newVars: [String: CVUValue] = [:]
newVars["viewArguments"] = .subdefinition(CVUDefinitionContent(properties: ["readOnly": .constant(.bool(false))]))
CVUAction_OpenView(viewName: viewName, renderer: "generalEditor").execute(sceneController: sceneController, context: context.replacingItem(item), completion: nil)
sceneController.isInEditMode = true
sceneController.navigateToNewContext(defaultDefinition: cvuDefinition)
}
}
......@@ -188,75 +188,34 @@ class SceneController: ObservableObject {
navigationController.popToViewController(vc, animated: true)
}
func navigateToNewContext(clearStack: Bool = false, animated: Bool = true, viewName: String, inheritDatasource: Bool = false, overrideRenderer: String? = nil, defaultRenderer: String = "list", targetItem: ItemRecord? = nil, overrideUIDs: Set<Int64>? = nil, dateRange: DateInterval? = nil, customDefinition: CVUDefinitionContent? = nil, viewArguments: CVUViewArguments? = nil) {
let viewDefinition = appController.cvuController.viewDefinitionFor(viewName: viewName, customDefinition: customDefinition) ?? CVUDefinitionContent()
let newContext = CVUContext(currentItem: targetItem, selector: nil, viewName: viewName, viewDefinition: viewDefinition, viewArguments: viewArguments)
func navigateToNewContext(defaultDefinition: CVUDefinitionContent? = nil,
defaultContext: CVUContext? = nil,
clearStack: Bool = false,
animated: Bool = true,
viewName: String? = nil,
inheritDatasource: Bool = false,
overrideRenderer: String? = nil,
defaultRenderer: String = "list",
targetItem: ItemRecord? = nil,
overrideUIDs: Set<Int64>? = nil,
dateRange: DateInterval? = nil,
customDefinition: CVUDefinitionContent? = nil,
viewArguments: CVUViewArguments? = nil) {
let viewDefinition = defaultDefinition ?? appController.cvuController.viewDefinitionFor(viewName: viewName ?? "", customDefinition: customDefinition) ?? CVUDefinitionContent()
let cvuContext = CVUContext(currentItem: targetItem, selector: nil, viewName: viewName, viewDefinition: viewDefinition, viewArguments: viewArguments)
let rendererName = overrideRenderer ?? { () -> String in
return viewDefinition.propertyResolver(context: newContext, lookup: CVULookupController(), db: appController.databaseController).string("defaultRenderer") ?? defaultRenderer
return viewDefinition.propertyResolver(context: cvuContext, lookup: CVULookupController(), db: appController.databaseController).string("defaultRenderer") ?? defaultRenderer
}()
let datasource = viewDefinition.definitions.first(where: { $0.type == .datasource })
let datasourceResolver = datasource?.parsed.propertyResolver(context: newContext, lookup: CVULookupController(), db: appController.databaseController)
let uidList = overrideUIDs ?? datasourceResolver.map {
Set($0.intArray("uids").map { Int64($0) })
}
let filterDef = datasourceResolver?.subdefinition("filter")
let edgeTargets = filterDef?.subdefinition("edgeTargets")
let edgeTargetConditions = edgeTargets?.properties.keys.compactMap { key -> DatabaseQueryCondition? in
guard let target = edgeTargets?.int(key) else { return nil }
return .edgeHasTarget(DatabaseQueryCondition.EdgeHasTarget(edgeName: key, target: Int64(target)))
} ?? []
let edgeSources = filterDef?.subdefinition("edgeSources")
let edgeSourceConditions = edgeSources?.properties.keys.compactMap { key -> DatabaseQueryCondition? in
guard let source = edgeSources?.int(key) else { return nil }
return .edgeHasSource(DatabaseQueryCondition.EdgeHasSource(edgeName: key, source: Int64(source)))
} ?? []
let properties = filterDef?.subdefinition("properties")
let propertyConditions = properties?.properties.keys.compactMap { key -> DatabaseQueryCondition? in
if let value = properties?.bool(key) {
return .propertyEquals(DatabaseQueryCondition.PropertyEquals(name: key, value: .bool(value)))
} else if let value = properties?.string(key) {
return .propertyEquals(DatabaseQueryCondition.PropertyEquals(name: key, value: .string(value)))
}
return nil
} ?? []
var queryConfig = inheritDatasource ? (topMostContext?.config.query ?? DatabaseQueryConfig()) : DatabaseQueryConfig()
if let itemTypes = datasourceResolver?.stringArray("query") ?? targetItem.map({ [$0.type] }) {
queryConfig.itemTypes = itemTypes
}
if let itemUIDs = uidList {
queryConfig.itemIDs = itemUIDs
}
if case let .constant(.string(edgeTargetsOperator)) = datasourceResolver?.properties["edgeTargetsOperator"] {
queryConfig.edgeTargetsOperator = edgeTargetsOperator == ConditionOperator.or.rawValue ? .or : .and
}
if let sortProperty = datasourceResolver?.string("sortProperty") {
queryConfig.sortProperty = sortProperty
}
if let sortAscending = datasourceResolver?.bool("sortAscending") {
queryConfig.sortAscending = sortAscending
}
if let dateModifiedRange = dateRange {
queryConfig.dateModifiedAfter = dateModifiedRange.start
queryConfig.dateModifiedBefore = dateModifiedRange.end
}
if !edgeTargetConditions.isEmpty || !edgeSourceConditions.isEmpty || !propertyConditions.isEmpty {
queryConfig.conditions = edgeTargetConditions + edgeSourceConditions + propertyConditions
}
if let count = datasourceResolver?.int("count") {
queryConfig.count = count
}
let queryConfig = DatabaseQueryConfig.queryConfigWith(context: cvuContext,
datasource: datasource,
inheritQuery: inheritDatasource ? topMostContext?.config.query : nil,
overrideUIDs: overrideUIDs,
targetItem: targetItem,
dateRange: dateRange)
let config = ViewContext(viewName: viewName, rendererName: rendererName, viewDefinition: viewDefinition, query: queryConfig, viewArguments: viewArguments, focusedItem: targetItem)
let holder = ViewContextHolder(config)
......
......@@ -30,53 +30,9 @@ struct CVU_SubView: View {
let initialItem: ItemRecord? = nodeResolver.propertyResolver.item("initialItem")
let nodeItem = initialItem ?? nodeResolver.context.currentItem
let newContext = CVUContext(currentItem: nodeItem, selector: nil, viewName: viewName, viewDefinition: viewDefinition)
let datasourceResolver = datasource.parsed.propertyResolver(context: newContext, lookup: CVULookupController(), db: AppController.shared.databaseController)
let filterDef = datasourceResolver.subdefinition("filter")
let edgeTargets = filterDef?.subdefinition("edgeTargets")
let edgeTargetConditions = edgeTargets?.properties.keys.compactMap { key -> DatabaseQueryCondition? in
guard let target = edgeTargets?.int(key) else { return nil }
return .edgeHasTarget(DatabaseQueryCondition.EdgeHasTarget(edgeName: key, target: Int64(target)))
} ?? []
let edgeSources = filterDef?.subdefinition("edgeSources")
let edgeSourceConditions = edgeSources?.properties.keys.compactMap { key -> DatabaseQueryCondition? in
guard let source = edgeSources?.int(key) else { return nil }
return .edgeHasSource(DatabaseQueryCondition.EdgeHasSource(edgeName: key, source: Int64(source)))
} ?? []
let properties = filterDef?.subdefinition("properties")
let propertyConditions = properties?.properties.keys.compactMap { key -> DatabaseQueryCondition? in
if let value = properties?.bool(key) {
return .propertyEquals(DatabaseQueryCondition.PropertyEquals(name: key, value: .bool(value)))
} else if let value = properties?.string(key) {
return .propertyEquals(DatabaseQueryCondition.PropertyEquals(name: key, value: .string(value)))
}
return nil
} ?? []
var queryConfig = DatabaseQueryConfig()
queryConfig.itemTypes = datasourceResolver.stringArray("query")
if case let .constant(.string(edgeTargetsOperator)) = datasourceResolver.properties["edgeTargetsOperator"] {
queryConfig.edgeTargetsOperator = edgeTargetsOperator == ConditionOperator.or.rawValue ? .or : .and
}
if let sortProperty = datasourceResolver.string("sortProperty") {
queryConfig.sortProperty = sortProperty
}
if let sortAscending = datasourceResolver.bool("sortAscending") {
queryConfig.sortAscending = sortAscending
}
if !edgeTargetConditions.isEmpty || !edgeSourceConditions.isEmpty || !propertyConditions.isEmpty {
queryConfig.conditions = edgeTargetConditions + edgeSourceConditions + propertyConditions
}
if let count = datasourceResolver.int("count") {
queryConfig.count = count
}
let cvuContext = CVUContext(currentItem: nodeItem, selector: nil, viewName: viewName, viewDefinition: viewDefinition)
let queryConfig = DatabaseQueryConfig.queryConfigWith(context: cvuContext,
datasource: datasource)
let config = ViewContext(viewName: viewName, rendererName: rendererName, viewDefinition: viewDefinition, query: queryConfig)
let holder = ViewContextHolder(config)
let viewControllerContext = ViewContextController(config: holder, databaseController: AppController.shared.databaseController, cvuController: AppController.shared.cvuController)
......
......@@ -11,7 +11,7 @@ struct CustomRendererView: View {
var nodeDefinition: CVUDefinitionContent? {
guard let viewName = viewContext.config.viewName else {
return nil
return viewContext.config.viewDefinition.definitions.first?.parsed
}
return viewContext.cvuController.viewDefinitionFor(viewName: viewName)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment