From a4efcab464f9fd06c017d8130bf057d598a11ea7 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Wed, 2 Aug 2023 14:41:48 +0200 Subject: [PATCH 1/2] move indexing from Dash.jl --- src/components.jl | 35 +++++++++++++++++++++++++++++------ test/components.jl | 24 +++++++++++++++++++----- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/components.jl b/src/components.jl index 53c6f1a..d710999 100644 --- a/src/components.jl +++ b/src/components.jl @@ -1,6 +1,6 @@ to_dash(t::Any) = t -struct Component +struct Component name ::String type ::String namespace ::String @@ -9,9 +9,9 @@ struct Component wildcard_regex ::Union{Nothing, Regex} function Component(name::String, type::String, namespace::String, props::Vector{Symbol}, wildcard_props::Vector{Symbol}; kwargs...) - + available_props = Set{Symbol}(props) - wildcard_regex::Union{Nothing, Regex} = nothing + wildcard_regex::Union{Nothing, Regex} = nothing if !isempty(wildcard_props) wildcard_regex = Regex(join(string.(wildcard_props), "|")) end @@ -30,13 +30,36 @@ get_available_props(comp::Component) = getfield(comp, :available_props) get_wildcard_regex(comp::Component) = getfield(comp, :wildcard_regex) get_props(comp::Component) = getfield(comp, :props) -function Base.getproperty(comp::Component, prop::Symbol) +const VecChildTypes = Union{NTuple{N, Component} where {N}, Vector{<:Component}} + +function Base.getindex(component::Component, id::AbstractString) + component.id == id && return component + hasproperty(component, :children) || return nothing + cc = component.children + return if cc isa Union{VecChildTypes, DashBase.Component} + cc[id] + elseif cc isa AbstractVector + fcc = identity.(filter(x->hasproperty(x, :id), cc)) + isempty(fcc) ? nothing : fcc[id] + else + nothing + end +end +function Base.getindex(children::VecChildTypes, id::AbstractString) + for element in children + element.id == id && return element + el = element[id] + el !== nothing && return el + end +end + +function Base.getproperty(comp::Component, prop::Symbol) !Base.hasproperty(comp, prop) && error("Component $(get_name(comp)) has no property $(prop)") props = get_props(comp) return haskey(props, prop) ? props[prop] : nothing end -function Base.setproperty!(comp::Component, prop::Symbol, value) +function Base.setproperty!(comp::Component, prop::Symbol, value) !Base.hasproperty(comp, prop) && error("Component $(get_name(comp)) has no property $(prop)") props = get_props(comp) push!(props, prop=>to_dash(value)) @@ -56,4 +79,4 @@ Base.propertynames(comp::Component) = collect(get_available_props(comp)) push_prop!(component::Component, prop::Symbol, value) = push!(component.props, prop=>to_dash(value)) JSON3.StructTypes.StructType(::Type{DashBase.Component}) = JSON3.StructTypes.Struct() -JSON3.StructTypes.excludes(::Type{DashBase.Component}) = (:name, :available_props, :wildcard_regex) \ No newline at end of file +JSON3.StructTypes.excludes(::Type{DashBase.Component}) = (:name, :available_props, :wildcard_regex) diff --git a/test/components.jl b/test/components.jl index 7c547ec..6cb9536 100644 --- a/test/components.jl +++ b/test/components.jl @@ -5,10 +5,10 @@ using JSON3 test_comp = Component("html_div", "Div", "dash_html_components", [:children, :id, :n_clicks], [Symbol("data-"), Symbol("aria-")]; - id = 10, + id = 10, n_clicks = 1 ) - + @test get_name(test_comp) == "html_div" @test get_type(test_comp) == "Div" @test get_namespace(test_comp) == "dash_html_components" @@ -26,7 +26,7 @@ using JSON3 @test_throws ErrorException Component("html_div", "Div", "dash_html_components", [:children, :id, :n_clicks], [Symbol("data-"), Symbol("aria-")]; - id = 10, + id = 10, key = 1 ) json = JSON3.write(test_comp) @@ -42,7 +42,7 @@ end test_comp = Component("html_div", "Div", "dash_html_components", [:children, :id, :n_clicks], Symbol[]; - id = 10, + id = 10, n_clicks = 1 ) @@ -54,4 +54,18 @@ end @test_throws ErrorException test_comp.var"data-id" = 20 @test_throws ErrorException test_comp.aaaaa -end \ No newline at end of file +end + +@testset "Index by id" begin + layout = html_div() do + dcc_input(id = "my-id", value="initial value", type = "text"), + html_div(id = "my-div", children = [ + html_div(children = []), + "string", + html_div(id = "target") + ]), + html_div(id = "my-div2") + end + @test layout["target"].id == "target" + @test layout["ups"] === nothing +end From 3a6c7fe5aa85ec77d502fe0062fc2fd4dd321f39 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Wed, 2 Aug 2023 15:15:54 +0200 Subject: [PATCH 2/2] fix tests --- test/components.jl | 52 ++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/test/components.jl b/test/components.jl index 6cb9536..ea22970 100644 --- a/test/components.jl +++ b/test/components.jl @@ -3,11 +3,11 @@ using JSON3 @testset "components creation" begin test_comp = Component("html_div", "Div", "dash_html_components", - [:children, :id, :n_clicks], - [Symbol("data-"), Symbol("aria-")]; - id = 10, - n_clicks = 1 - ) + [:children, :id, :n_clicks], + [Symbol("data-"), Symbol("aria-")]; + id=10, + n_clicks=1 + ) @test get_name(test_comp) == "html_div" @test get_type(test_comp) == "Div" @@ -24,11 +24,11 @@ using JSON3 @test_throws ErrorException test_comp.key @test_throws ErrorException test_comp.key = 20 @test_throws ErrorException Component("html_div", "Div", "dash_html_components", - [:children, :id, :n_clicks], - [Symbol("data-"), Symbol("aria-")]; - id = 10, - key = 1 - ) + [:children, :id, :n_clicks], + [Symbol("data-"), Symbol("aria-")]; + id=10, + key=1 + ) json = JSON3.write(test_comp) res = JSON3.read(json) @test all(keys(res) .== [:type, :namespace, :props]) @@ -40,11 +40,11 @@ end @testset "empty wilds" begin test_comp = Component("html_div", "Div", "dash_html_components", - [:children, :id, :n_clicks], - Symbol[]; - id = 10, - n_clicks = 1 - ) + [:children, :id, :n_clicks], + Symbol[]; + id=10, + n_clicks=1 + ) @test get_name(test_comp) == "html_div" @test get_type(test_comp) == "Div" @@ -55,17 +55,19 @@ end @test_throws ErrorException test_comp.var"data-id" = 20 @test_throws ErrorException test_comp.aaaaa end - +function test_component(; kwargs...) + Component("html_div", "Div", "dash_html_components", [:dir, :n_clicks, :key, :loading_state, :contentEditable, :contextMenu, :n_clicks_timestamp, :draggable, :accessKey, :hidden, :style, :children, :id, :title, :role, :lang, :spellCheck, :tabIndex, :disable_n_clicks, :className], Symbol[]; kwargs...) +end @testset "Index by id" begin - layout = html_div() do - dcc_input(id = "my-id", value="initial value", type = "text"), - html_div(id = "my-div", children = [ - html_div(children = []), - "string", - html_div(id = "target") - ]), - html_div(id = "my-div2") - end + layout = test_component(children=[ + test_component(id="my-id", n_clicks=0, title="text"), + test_component(id="my-div", children=[ + test_component(children=[]), + "string", + test_component(id="target") + ]), + test_component(id="my-div2") + ]) @test layout["target"].id == "target" @test layout["ups"] === nothing end