Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
memri
iOS client for Memri
Commits
537eca54
Commit
537eca54
authored
Aug 09, 2021
by
Chaitanya Pandit
Committed by
Amirjanyan
Aug 09, 2021
Browse files
Render cvu storeddefinition
parent
a44dd1a8
Changes
9
Hide whitespace changes
Inline
Side-by-side
MemriApp/Assets/demo_database.json
View file @
537eca54
...
...
@@ -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"
,
...
...
MemriApp/Assets/schema.json
View file @
537eca54
...
...
@@ -3132,6 +3132,12 @@
"target_type"
:
"Location"
},
{
"source_type"
:
"Plugin"
,
"edge"
:
"view"
,
"target_type"
:
"CVUStoredDefinition"
},
{
"source_type"
:
"Product"
,
"edge"
:
"material"
,
...
...
MemriApp/CVU/CVUController.swift
View file @
537eca54
...
...
@@ -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
)
...
...
MemriApp/CVU/actions/CVUAction.swift
View file @
537eca54
...
...
@@ -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
)
}
...
...
MemriApp/Controllers/Database/DatabaseQuery.swift
View file @
537eca54
...
...
@@ -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
}
}
MemriApp/Controllers/Plugins/PluginHandler.swift
View file @
537eca54
...
...
@@ -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
)
}
}
MemriApp/Controllers/SceneController.swift
View file @
537eca54
...
...
@@ -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
:
new
Context
,
lookup
:
CVULookupController
(),
db
:
appController
.
databaseController
)
.
string
(
"defaultRenderer"
)
??
defaultRenderer
return
viewDefinition
.
propertyResolver
(
context
:
cvu
Context
,
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
)
...
...
MemriApp/UI/CVUComponents/CVUElements/CVU_SubView.swift
View file @
537eca54
...
...
@@ -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
)
...
...
MemriApp/UI/Renderers/CustomRenderer.swift
View file @
537eca54
...
...
@@ -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
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment