Skip to content

Commit

Permalink
Merge branch 'modelexport' into hh-megamerge
Browse files Browse the repository at this point in the history
# Conflicts:
#	test/runtests.jl
  • Loading branch information
essenciary committed Dec 11, 2024
2 parents b35c1e5 + 13814b0 commit 84f05b3
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 14 deletions.
66 changes: 65 additions & 1 deletion src/ModelStorage.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,68 @@
module ModelStorage
using JSON3
using Stipple
import Stipple: INTERNALFIELDS, AUTOFIELDS, Reactive

const DEFAULT_EXCLUDE = vcat(INTERNALFIELDS, AUTOFIELDS)

"""
model_values(model::M; fields::Vector{Symbol} = Symbol[], exclude::Vector{Symbol} = Symbol[], json::Bool = false) where M
Exports the values of reactive fields from a Stipple model. Returns either a Dict of field-value pairs or a JSON string
if json=true.
### Example
@app TestApp2 begin
@in i = 100
@out s = "Hello"
@private x = 4
end
model = @init TestApp2
exported_values = Stipple.ModelStorage.model_values(model)
"""
function model_values(model::M; fields::Vector{Symbol} = Symbol[], exclude::Vector{Symbol} = Symbol[], json::Bool = false) where M
field_list = isempty(fields) ? fieldnames(M) : fields
excluded_fields = vcat(DEFAULT_EXCLUDE, exclude)

field_dict = Dict(field => getfield(model, field)[] for field in field_list
if field excluded_fields && getfield(model, field) isa Stipple.Reactive)

json ? JSON3.write(field_dict) : field_dict
end

"""
load_model_values!(model::M, values::Dict{Symbol, Any}) where M
load_model_values!(model::M, values::String) where M
Loads values into the fields of a ReactiveModel. Accepts either a Dict of field-value pairs or a JSON string.
### Example
values_dict = Dict(:i => 20, :s => "world", :x => 5)
Stipple.ModelStorage.load_model_values!(model, values_dict)
"""
function load_model_values!(model::M, values::Dict{Symbol, Any}) where M
model_field_list = fieldnames(M)
excluded_fields = DEFAULT_EXCLUDE

for (field, value) in values
if field excluded_fields && field model_field_list
model_field = getfield(model, field)

if model_field isa Reactive
model_field[] = value
end
end
end

return model
end

function load_model_values!(model::M, values::String) where M
load_model_values!(model, Dict(JSON3.read(values)))
end

module Sessions

Expand Down Expand Up @@ -61,4 +125,4 @@ end

end # module Sessions

end # module ModelStorage
end # module ModelStorage
3 changes: 1 addition & 2 deletions src/Stipple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,9 @@ export setchannel, getchannel
isempty(methods(notify, Observables)) && (Base.notify(observable::AbstractObservable) = Observables.notify!(observable))

include("ParsingTools.jl")
use_model_storage() && include("ModelStorage.jl")
include("NamedTuples.jl")

include("stipple/reactivity.jl")
use_model_storage() && include("ModelStorage.jl")
include("stipple/json.jl")
include("stipple/undefined.jl")
include("stipple/assets.jl")
Expand Down
54 changes: 43 additions & 11 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ end
@eval @debounce TestApp i 101
@eval @debounce TestApp (a, b, c) 101
@test Stipple.DEBOUNCE[TestApp][:i] == 101

@eval @clear_debounce TestApp
@test haskey(Stipple.DEBOUNCE, TestApp) == false
end
Expand Down Expand Up @@ -154,7 +154,7 @@ end
@eval @debounce i3 101
@eval @debounce (a, b, c) 101
@test Stipple.DEBOUNCE[Stipple.@type()][:i3] == 101

@eval @clear_debounce
@test haskey(Stipple.DEBOUNCE, Stipple.@type()) == false
end
Expand Down Expand Up @@ -195,7 +195,7 @@ end

module App2
using Stipple, Stipple.ReactiveTools

@app begin
@in i2 = 102
end
Expand All @@ -205,7 +205,7 @@ end
end

end

@testset "Multipage Reactive API (implicit)" begin
@eval p1 = @page("/app1", "hello", model = App1)
@eval p2 = @page("/app2", "world", model = App2)
Expand Down Expand Up @@ -435,7 +435,7 @@ end
@test row(@gutter :sm [
cell("Hello", sm = 2, md = 8)
cell("World", sm = 10, md = 4)
]).data == "<div class=\"row q-col-gutter-sm\"><div class=\"col col-sm-2 col-md-8\">" *
]).data == "<div class=\"row q-col-gutter-sm\"><div class=\"col col-sm-2 col-md-8\">" *
"<div class=\"st-col\">Hello</div></div><div class=\"col col-sm-10 col-md-4\"><div class=\"st-col\">World</div></div></div>"
end

Expand Down Expand Up @@ -572,25 +572,25 @@ end
c::Int
d::Int
end

struct T2
a::Int
b::T1
end

t2 = T2(1, T1(2, 3))
t2_dict = JSON3.read(Stipple.json(t2), Dict)

Base.@kwdef struct T3
c::Int = 1
d::Int = 3
end

Base.@kwdef struct T4
a::Int = 1
b::T3 = T3()
end

@test Stipple.stipple_parse(T2, t2_dict) == T2(1, T1(2, 3))
@test Stipple.stipple_parse(T3, Dict()) == T3(1, 3)
@test Stipple.stipple_parse(T4, Dict()) == T4(1, T3(1, 3))
Expand All @@ -605,4 +605,36 @@ end
@test Stipple.stipple_parse(Union{Nothing, SubString}, "hi") == SubString("hi")
end
@test Stipple.stipple_parse(Union{Nothing, String}, nothing) === nothing
end
end

@testset "Exporting and loading model field values" begin
@app TestApp2 begin
@in i = 100
@out s = "Hello"
@private x = 4
end

model = @init TestApp2

exported_values = Stipple.ModelStorage.model_values(model)
@test exported_values[:i] == 100
@test exported_values[:s] == "Hello"
@test exported_values[:x] == 4

values_json = JSON3.write(exported_values)
exported_values_json = Stipple.ModelStorage.model_values(model, json = true)
@test values_json == exported_values_json

values_dict = Dict(:i => 20, :s => "world", :x => 5)
Stipple.ModelStorage.load_model_values!(model, values_dict)
@test model.i[] == 20
@test model.s[] == "world"
@test model.x[] == 5

values_json = Dict(:i => 30, :s => "zero", :x => 50) |> JSON3.write |> string
Stipple.ModelStorage.load_model_values!(model, values_json)
@test model.i[] == 30
@test model.s[] == "zero"
@test model.x[] == 50

end

0 comments on commit 84f05b3

Please sign in to comment.